Como Filtrar por Categoria através de checkbox Modal usando Ionic / Angularjs?

Question: EDITADO PARA MELHOR EXPLICAÇÃO
Tenho 3 tipos de filtros:
Um de pesquisa:

            <input ng-model="q" placeholder="Procurar" aria-label="filter restaurantess" />

Onde o filtro de ng-model é: filter:q
Um por ordenação:

                <button class="button button-stable button-block  icon-left ion-android-restaurant" modal-select="" ng-model="someModel" options="selectableNames" option-property="role" modal-title="Ordenar por..." has-search="true">Ordenar

{{option.name}}

                </button>

Onde o filtro é: orderBy:someModel
E Preciso de um filtro por Categoria, que abre um modal listando todas as categorias, mas mostrando somente as categorias que existem listadas (para o usuário não perder tempo selecionando uma categoria que não exista na listagem), onde a View desta modal é:
 <ion-modal view-title="cadastrar" hide-nav-bar="false">
    <ion-header-bar>

Escolha as Categorias

    </ion-header-bar>
    <ion-content>

                Estão sendo listadas apenas as categorias existentes em sua localização.

            <button class="button button-stable button-block  icon-left ion-android-funnel" ng-click="closeModal()">Aplicar Filtro</button>

        <ion-list>
            <ion-checkbox ng-repeat="item in ofertass | unique:'categoria_comida_nome' track by $index" ng-model="filtro[$index]" ng-true-value="{{item}}" ng-false-value="" ng-checked="check">{{item.categoria_comida_nome}}</ion-checkbox>
        </ion-list>

            <button class="button button-stable button-block  icon-left ion-android-funnel" ng-click="closeModal()">Aplicar Filtro</button>

    </ion-content>
</ion-modal>

Como na imagem a seguir, o resultado da modal do código:

Os de ordenação e pesquisa, estão funcionando bem.
Mas não estou conseguindo uma forma de filtrar as categorias selecionadas pelo usuário.
Para ilustrar melhor, segue a View completa da minha listagem principal a qual quero filtrar as categorias:
    <ion-view side="center" view-title="vovócooks">

    <ion-nav-buttons side="right" class="has-header">
         {{total}}

        <button class="button button-icon button-clear ion-ios-color-filter-outline" id="menu-popover" ng-click="popover.show($event)"></button>

    </ion-nav-buttons>

                <input ng-model="q" placeholder="Procurar" aria-label="filter restaurantess" />

                 DELÍCIAS CASEIRAS

                 VOVÓS ONLINE

                 Atualizar

                 Meu Perfil

    <ion-content delegate-handle="top" lazy-scroll id="page-promocoes" class="has-header page-promocoes">

        <ion-refresher pulling-text="Puxe para atualizar..." on-refresh="doRefresh()"></ion-refresher>

                          Sua localização atual é:  {{endereco_atual}}

                              <button class="button button-clear button-assertive" style="font-size:12px" ui-sref="nhaac.localiza">
                                  Mudar Localização
                              </button>

                <button class="button button-stable button-block  icon-left ion-android-funnel" ng-click="abreModal()">
                    Filtrar
                </button>

                <button class="button button-stable button-block  icon-left ion-android-restaurant" modal-select="" ng-model="someModel" options="selectableNames" option-property="role" modal-title="Ordenar por..." has-search="true">Ordenar

{{option.name}}

                </button>

{{item.cadastra_oferta_desconto}}% Off

{{item.cadastra_oferta_valor_com_desconto | currency}}

{{item.cadastra_oferta_titulo_promocao}}

Vovó Cozinheira: {{item.fornecedores_fantasia}}

Avaliação Média

Categoria: {{item.categoria_comida_nome}}

Descrição: {{item.cadastra_oferta_descricao}}

                                Preço Normal: <s style="color:red;"> {{item.cadastra_oferta_valor_sem_desconto | currency}}</s>
 Preço Promocional:  {{item.cadastra_oferta_valor_com_desconto | currency}}
 Preço do Frete:  {{item.fornecedor_configura_frete_custo_padrao | currency}}

                PEDIR

        <ion-list class="list">
            <ion-infinite-scroll ng-if="!noMoreItemsAvailable" on-infinite="onInfinite()" distance="5px" ng-if="hasMoreData"></ion-infinite-scroll>
        </ion-list>

        <ion-list class="list">

Nenhum resultado encontrado...

        </ion-list>

    </ion-content>

</ion-view>

Em meu Controller, o que tento filtrar pelo ng-clik o trecho é este:
// PEGA OS ITENS SELECIONADOS NA MODAL E COLOCA NUM ARRAY
    $scope.checkItems = {};

    $scope.print = function () {
        console.log($scope.checkItems);

    }

    // APLICANDO FILTRO CATEGORIA
//    $scope.userCategoria = function (checkItems) {
//        console.log("entra na chamada");
        //          $scope.userCategoria = $scope.checkItems(function(element) {
//        $scope.checkItems;

//        console.log("Imprime array");
//        console.log($scope.checkItems);
        //          };
        //            console.log("Imprime array");
        //          console.log($scope.userCategoria);
//        $scope.modal.hide();
//        var role = array
//        $state.go("nhaac.promocoes");
//    };

    $scope.save = function () {
        console.log("Chamou o save");
        var array = [];
        for (i in $scope.checkItems) {
            console.log($scope.checkItems[i]);
            if ($scope.checkItems[i] == true) {
                array.push(i);

            }
        }
        console.log(array);

        $state.go("nhaac.promocoes");
    }

    // INICIA FILTRO POR CATEGORIA
    $ionicModal.fromTemplateUrl('/templates/filters/side-filter.html', {
        scope: $scope,
        animation: 'slide-in-up'
    }).then(function (modal) {
        $scope.modal = modal;
    });
    $scope.abreModal = function () {
        $scope.modal.show();
    };
    $scope.closeModal = function () {
        $scope.modal.hide();

    };

    // FIM FILTRO POR CATEGORIA

Este está bem bagunçado de tantos testes que fiz...
Mas pode ver que pego os dados, e armazeno localmente separados por virgula:

Ou seja, estou sofrendo com a volta (desconhecimento)...
Se coloco | groupBy: 'mais_campo' dá erro.
Não estou conseguindo fazer este filtro por categorias, e preciso de ajuda.
Ou preciso mudar a lógica? Não sei se por falta de uma lógica melhor (ou conhecimento). Agradeceria muito...
Bem, para finalizar, disponibilizo todo o meu Controller da View Principal:
    .controller("promocoesCtrl", function ($scope, $rootScope, $state, $ionicScrollDelegate, $http, $httpParamSerializer, $stateParams, $timeout, $ionicLoading, $ionicPopup, $ionicPopover, $ionicSlideBoxDelegate, $ionicHistory, ionicMaterialInk, ionicMaterialMotion, $ionicModal, sharedCartService, sharedFilterService) {

         $ionicHistory.nextViewOptions({
                disableBack: false,
                historyRoot: true
            });

//            $ionicHistory.clearCache();
//            $ionicHistory.clearHistory();

        //put cart after menu
        var cart = sharedCartService.cart;

        $scope.endereco_atual = window.localStorage.getItem("endereco_atual");

        if (window.localStorage.getItem("user_des") === undefined) {
            console.log("Usuário logado, setar como logado");

        } else {

            console.log("Usuário deslogado, setar como deslogado");
            var setar = "user_des";
            window.localStorage.setItem("user_des", setar)
        };

        $scope.getStars = function (avalia) {
            // Get the value
            var val = parseFloat(avalia);
            // Turn value into number/100
            var size = val / 6 * 100;
            return size + '%';
        }

        $scope.cadastra_oferta_cod_fornecedor = $stateParams.cadastra_oferta_cod_fornecedor;

        $scope.endereco_atual = window.localStorage.getItem("endereco_atual");

        // ORDENA POR...
        $scope.selectableNames = [

            {
                name: "Por preço: Do Menor para o Maior",
                role: "+cadastra_oferta_valor_com_desconto"
        },

            {
                name: "Por preço: Do Maior para o Menor",
                role: "-cadastra_oferta_valor_com_desconto"
        },

            {
                name: "Por Maior Desconto (%)",
                role: "-cadastra_oferta_desconto"
        },

            {
                name: "Menor Prazo de Entrega",
                role: "+fornecedor_configura_frete_prazo_entrega_min"
        },

            {
                name: "Maior Prazo de Entrega",
                role: "-fornecedor_configura_frete_prazo_entrega_min"
        },

            {
                name: "Oferta em Ordem Alfabética",
                role: "+cadastra_oferta_titulo_promocao"
        },

            {
                name: "Por Categoria",
                role: "+categoria_comida_nome"
        },

//        {
//            name: "Por Menor valor de Frete",
//            role: "+fornecedor_configura_frete_custo_padrao"
//        },

    ];

        $scope.getOpt = function (option) {
            return option.name + ":" + option.role;
            console.log(option);
            window.localstorage.setItem("OrdenaPor", option.role);
        };
        // FIM DE ORDENA POR

        $scope.filtro = [];

        //função utilizada no filter do ng-repeat
        $scope.devListFilter = function () {
            return $scope.devList.filter(function (item) {
                return $scope.filtro.indexOf(item.categoria_comida_nome) !== -1;
            });
        };
        $scope.pushNotificationChange = function () {
            console.log('Push Notification Change', $scope.pushNotification.checked);
        };

        $scope.pushNotification = {
            checked: true
        };
        $scope.emailNotification = 'Subscribed';

        $scope.save = function () {
            console.log("clicado");
            $state.go("nhaac.promocoes");
        };

        // PEGA OS ITENS SELECIONADOS NA MODAL E COLOCA NUM ARRAY
        $scope.checkItems = {};

        $scope.print = function () {
            console.log($scope.checkItems);
        }

        // APLICANDO FILTRO CATEGORIA
        //    $scope.userCategoria = function (checkItems) {
        //        console.log("entra na chamada");
        //          $scope.userCategoria = $scope.checkItems(function(element) {
        //        $scope.checkItems;

        //        console.log("Imprime array");
        //        console.log($scope.checkItems);
        //          };
        //            console.log("Imprime array");
        //          console.log($scope.userCategoria);
        //        $scope.modal.hide();
        //        var role = array
        //        $state.go("nhaac.promocoes");
        //    };

        //    $scope.save = function (item) {
        //        console.log("Chamou o save");
        //        var array = [];
        //        for (i in $scope.checkItems) {
        //            console.log($scope.checkItems[i]);
        //            if ($scope.checkItems[i] == true) {
        //                array.push(i);

        //            }
        //        }
        //        console.log(array);
        //        window.localStorage.setItem("q", array);
        //
        //        $scope.q = window.localStorage.getItem("q");
        //
        //        $scope.modal.hide();
        //    }

        // INICIA FILTRO POR CATEGORIA
        $ionicModal.fromTemplateUrl('/templates/filters/side-filter.html', {
            scope: $scope,
            animation: 'slide-in-up'
        }).then(function (modal) {
            $scope.modal = modal;
        });
        $scope.abreModal = function () {
            $scope.modal.show();
        };
        $scope.closeModal = function () {
            $scope.modal.hide();

        };

        // FIM FILTRO POR CATEGORIA

        $rootScope.page_id = "promocoes";

        $scope.endereco_atual = window.localStorage.getItem("endereco_atual");

        $scope.scrollTop = function () {
            $ionicScrollDelegate.$getByHandle("top").scrollTop();
        };
        // open external browser
        $scope.openURL = function ($url) {
            window.open($url, "_system", "location=yes");
        };
        // open AppBrowser
        $scope.openAppBrowser = function ($url) {
            window.open($url, "_blank", "closebuttoncaption=Done");
        };
        // open WebView
        $scope.openWebView = function ($url) {
            window.open($url, "_self");
        };

        // Set Motion
        $timeout(function () {
            ionicMaterialMotion.slideUp({
                selector: ".slide-up"
            });
        }, 300);

        var targetQuery = ""; //default param
        var raplaceWithQuery = "";
        // TODO: Dinamics Promoções

        $scope.endereco_atual = window.localStorage.getItem("endereco_atual");

        targetQuery = "json=promocao"; //default param
        raplaceWithQuery = "json=promocao";

        var fetch_per_scroll = 1;
        // animation loading
        $ionicLoading.show({
            template: '
<svg class="circular"><circle class="path" cx="50" cy="50" r="20" fill="none" stroke-width="2" stroke-miterlimit="10"/></svg>
'
        });

        $scope.noMoreItemsAvailable = false; //readmore status
        var lastPush = 0;
        var data_ofertass = [];

        if (window.localStorage.getItem("data_ofertass") !== "undefined") {
            data_ofertass = JSON.parse(window.localStorage.getItem("data_ofertass"));
            if (data_ofertass !== null) {
                $scope.ofertass = [];
                for (lastPush = 0; lastPush < 10; lastPush++) {
                    if (angular.isObject(data_ofertass[lastPush])) {
                        $scope.ofertass.push(data_ofertass[lastPush]);
                    };
                }

                $timeout(function () {
                    $ionicLoading.hide();
                }, 500);

            }
        }
        if (!angular.isObject(data_ofertass)) {
            $timeout(function () {
                // retry retrieving data
                $http.get("http://vovocooks.com.br/admin/apis/api_listagem/lista_oferta_api.php?json=promocao".replace(targetQuery, raplaceWithQuery)).then(function (response) {
                    data_ofertass = response.data;
                    if (typeof (Storage) != "undefined") {
                        try {
                            window.localStorage.setItem("data_ofertass", JSON.stringify(data_ofertass));
                        } catch (e) {
                            window.localStorage.clear();
                            window.localStorage.setItem("data_ofertass", JSON.stringify(data_ofertass));
                            //         $ionicHistory.removeBackView();
                            //            $ionicHistory.clearCache();
                            //            $ionicHistory.clearHistory();

                            $state.reload();
                            $scope.$state = $state;
                        }
                    }
                    $scope.ofertass = [];
                    for (lastPush = 0; lastPush < 100; lastPush++) {
                        if (angular.isObject(data_ofertass[lastPush])) {
                            $scope.ofertass.push(data_ofertass[lastPush]);
                        };
                    }
                }, function (response) {
                    // error message
                    var alertPopup = $ionicPopup.alert({
                        title: "error " + response.status,
                        template: response.statusText + "
problem: table ofertas",
                    });
                }).finally(function () {
                    $scope.$broadcast("scroll.refreshComplete");
                    // event done, hidden animation loading
                    $timeout(function () {
                        $ionicLoading.hide();
                    }, 1000);
                });

            }, 1000);
        }

        $scope.doRefresh = function () {
            // retry retrieving data
            //  window.localStorage.clear();
            $http.get("http://vovocooks.com.br/admin/apis/api_listagem/lista_oferta_api.php?json=promocao".replace(targetQuery, raplaceWithQuery)).then(function (response) {
                data_ofertass = response.data;
                if (typeof (Storage) != "undefined") {
                    try {
                        window.localStorage.setItem("data_ofertass", JSON.stringify(data_ofertass));
                    } catch (e) {
                        window.localStorage.clear();
                        window.localStorage.setItem("data_ofertass", JSON.stringify(data_ofertass));
                        //   $ionicHistory.removeBackView();
                        $ionicHistory.clearCache();
                        //    $ionicHistory.clearHistory();
                        $state.reload();
                        $scope.$state = $state;

                    }
                }
                $scope.ofertass = [];
                for (lastPush = 0; lastPush < 100; lastPush++) {
                    if (angular.isObject(data_ofertass[lastPush])) {
                        $scope.ofertass.push(data_ofertass[lastPush]);
                    };
                }
            }, function (response) {
                // error message
                var alertPopup = $ionicPopup.alert({
                    title: "error " + response.status,
                    template: response.statusText + "
Problema: com a tabela de ofertas",
                });
            }).finally(function () {
                $scope.$broadcast("scroll.refreshComplete");
                // event done, hidden animation loading
                $timeout(function () {
                    $ionicLoading.hide();
                }, 500);
            });

        };

        if (data_ofertass === null) {
            data_ofertass = [];
        };

        //Coloca produto em destaque
        $scope.addToStar = function (id, image, name, price, supply_id, deliver) {

            console.log(id);
            console.log(name);
            console.log(price);
            console.log(supply_id);

        };

        //add to cart function
        $scope.addToCart = function (id, image, name, price, supply_id, deliver, entrega) {
            // CHAMA CART.ADD DE SERVICES
            window.localStorage.setItem("fonecedor_carrinho", supply_id);
            window.localStorage.setItem("tipos_pagamentos", tipopag);
            window.localStorage.setItem("frete", deliver);
            window.localStorage.setItem("faz_entrega", entrega);
            cart.add(id, image, name, price, 1, supply_id, deliver);
            $state.go('nhaac.carrinho');

        };

        // animation readmore
        var fetchItems = function () {
            for (var z = 0; z < fetch_per_scroll; z++) {
                if (angular.isObject(data_ofertass[lastPush])) {
                    $scope.ofertass.push(data_ofertass[lastPush]);
                    lastPush++;
                } else {;
                    $scope.noMoreItemsAvailable = true;
                }
            }
            $scope.$broadcast("scroll.infiniteScrollComplete");
        };

        var tipo = '';

        // $scope.checarPermissoes();

        $scope.checarPermissoes = function (tipo) {
            var permitido;

            if (tipo === 'logado_usuario' && window.localStorage.getItem("user_log") !== null) {
                permitido = true;
            } else {
                permitido = false;
            }

            return permitido;
        };

        // event readmore
        $scope.onInfinite = function () {
            $timeout(fetchItems, 500);
        };

        // create animation fade slide in right (ionic-material)
        $scope.fireEvent = function () {
            ionicMaterialMotion.fadeSlideInRight();
            ionicMaterialInk.displayEffect();
        };

        // animation ink (ionic-material)
        ionicMaterialInk.displayEffect();
        $scope.rating = {};
        $scope.rating.max = 5;
    })

Comment: Para oferecer gratificação você precisa alcançar os 75 pontos de reputação, daí aparecerá uma opção aqui embaixo para você vvvvvv
Comment: Só para ilustrar: https://i.stack.imgur.com/IHvtF.png
Comment: Obrigado @Math que esta solução minha não é o que quero.
Answer: Fiz uma solução BEM TABAJARA.
A aproveitei o | filter:q do resultado.
Mudei minha modal de Checkbox (Não é o ideal, nem o que queria. O ideal era selecionar mais de uma categoria) para um Radio:
 <ion-modal-view  view-title="cadastrar" hide-nav-bar="false">
    <ion-header-bar>

Escolha as Categorias

    </ion-header-bar>
    <ion-content>

                Estão sendo listadas apenas as categorias existentes em sua localização.

            <button id="home-button72" class="button button-assertive  button-block" ng-click="save()">Filtrar</button>

            <button id="home-button73" class="button button-balanced  button-block" ng-click="limpaFiltro()">Limpar</button>

            <button id="home-button74" class="button button-dark  button-block" ng-click="limpaFiltro()">Cancelar</button>

        <ion-list>
            <ion-radio ng-repeat="item in ofertass | unique:'categoria_comida_nome'" ng-model="checkItems[item.categoria_comida_nome]" ng-change="print()" ng-value="item.categoria_comida_nome">{{item.categoria_comida_nome}}</ion-radio>

        </ion-list>

            <button id="home-button72" class="button button-assertive  button-block" ng-click="save()">Filtrar</button>

            <button id="home-button73" class="button button-balanced  button-block" ng-click="limpaFiltro()">Limpar</button>

            <button id="home-button74" class="button button-dark  button-block" ng-click="limpaFiltro()">Cancelar</button>

    </ion-content>
</ion-modal-view>

E no Controller diz essas chamadas:
// APLICANDO FILTRO CATEGORIA
        $scope.userCategoria = function (checkItems) {
            console.log("entra na chamada");

            $scope.modal.hide();

        };

        $scope.save = function (checkItems) {
            console.log("Chamou o save");
            var array = [];
            for (i in $scope.checkItems) {
                console.log($scope.checkItems[i]);
                if ($scope.checkItems[i] == true) {
                    array.push(i);

                }
            }
            console.log(array);

            window.localStorage.setItem("q",$scope.checkItems[i]);

            $scope.q = window.localStorage.getItem("q");

            $scope.modal.hide();
        }

        $scope.limpaFiltro = function(){

            var limpa = '';

            window.localStorage.setItem("q",limpa);

            $scope.q = window.localStorage.getItem("q");

            $scope.modal.hide();

            $scope.doRefresh();

        };

Pronto! Tabajara pro MVP. Quem sabe no futuro consigo a solução ideal.
Mas e ai? Me dá alguma solução para o verdadeiro objetivo?


Dynamic network interface for Compute Instance module

Question: We've Terraform module that creates compute_instance.
Some instances should get public IP.
Public IP created when you define "access_config {}" property under network_interface:
network_interface {
  network = "default"
  access_config {

  }
}

We try to inject dynamically the network interface and the access_config from
"production/Main.tf" that called to this module:
module "arbiter" {
  source                = "../modules/compute"
  name                  = "arbiter"
  machine_type          = "custom-1-2048"
  zones                 = ["europe-west2-a"]
  tags                  = ["mongo-db"]
  metadata              = {
    sshKeys             = "${var.ssh_user}:${file("ssh-keys/main.rsa.pub")}"
  }
  network_interface = { -> this line is worng
    network = "default"
  }
}

How can we inject a dynamic object to network_interface property?
Is it possible with Terraform if not, What are the alternatives?
Answer: In your arbiter module do this:
variable "external_ip" {
  description = "Controls if VM gets external IP"
  default     = false
}

locals {
  access_config = {
    "0" = []
    "1" = [{}]
  }
}

resource "google_compute_instance" "arbiter" {
  name         = "${var.name}"
  machine_type = "${var.type}"
  zone         = "${var.zones}"
  tags         = "${var.tags}"
  metadata     = "${var.metadata}"

  boot_disk {
    initialize_params {
      image = "some/image"
    }
  }

  network_interface {
    network = "default"

    access_config = "${local.access_config[var.external_ip]}"
  }
}

Then, when using the module, you can specify external_ip variable to indicate that VM should be accessible from the internet.
module "arbiter" {
  source       = "../modules/compute"
  name         = "arbiter"

  machine_type = "custom-1-2048"
  zones        = ["europe-west2-a"]
  tags         = ["mongo-db"]

  metadata = {
    sshKeys = "${var.ssh_user}:${file("ssh-keys/main.rsa.pub")}"
  }

  external_ip = true
}

More details about Terraform and null values tricks: Null values in Terraform v0.11.x


How to check if string is valid URL to image?

Question: I have the following class:
require 'uri'

class Images

  IMAGE_NOT_FOUND = '/images/no_image.gif'

  attr_accessor :url

  def initialize(parameters = {})
    @url = parameters.fetch(:url, IMAGE_NOT_FOUND)
    @url = IMAGE_NOT_FOUND unless @url =~/^#{URI::regexp}$/
  end

end

holding URL to image. I have checked some questions and add URL validation, but I need to improve it validating URLs pointing to images only.If validation fails, I want to use default image showing there is some issue.
Note, the current validation of the URL is not working with relative paths. For example, the following url is valid as image source /images/image1.png but the current validation is not recognizing it.
Could anyone tell if this is possible using URI?
Answer: Assuming that you want to only validate the URLs pointing to image type of files.
For eg: http://www.xyz.com/logo.png or http://www.xyz.com/logo.gif or http://www.xyz.com/logo.jpg
Here's the solution:
require 'uri'

class Images

  IMAGE_NOT_FOUND = '/images/no_image.gif'

  attr_accessor :url

  def initialize(parameters = {})
    @url = parameters.fetch(:url, IMAGE_NOT_FOUND)
    @url = IMAGE_NOT_FOUND unless ((File.extname(@url) =~/^(.png|.gif|.jpg)$/ )||(@url =~ /^#{URI::regexp}$/))
  end

end

The above example will only allow url's pointing to images with extension .png or .gif or .jpg and rest would be set to IMAGE_NOT_FOUND. Add more extensions if you want to.
Comment: Just a bit tweak. You could write `if (File.extname(@url) =~/^(.png|.gif|.jpg)$/).nil?` as `unless File.extname(@url) =~/^(.png|.gif|.jpg)$/`
Comment: @KirtiThorat +1, but this is validating the image extension but it requires full url path - in most cases the path to images is relative. For exmaple: `/images/myimate.jpg`. Also I believe you should use `&&` instead of `||`


JavaFX error "Application launch must not be called more than once" while running 2 Test cases

Question: I am using JavaFX to write a sample video player. But the tests fails when run together, ( Note: individually test passes).
Error: Unexpected exception thrown: java.lang.IllegalStateException: Application launch must not be called more than once
I understand that calling launch() twice on same Application Instance is causing this issue as per this . But I am not able to understand, that after one test completes, why the app is still running ? Why new instance is not getting created for 2nd test. testUnsupportedVideoFileThrowsError() succeeds but testSupportedVideoFilePlaysSuccessfully() fails.
package media;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.stage.Stage;

import java.io.File;

public class PlayVideoSnippet extends Application {

    private static String source;
    private Media media = null;
    private MediaPlayer mediaPlayer = null;
    private MediaView mediaView = null;
    private Scene scene = null;

    public static void playVideo(String source) {
        PlayVideoSnippet.source = source;
        PlayVideoSnippet.launch();
    }

    @Override
    public void start(Stage stage) throws InterruptedException {
        try {
            media = new Media(new File(source).toURI().toString());
            //onError close the app
            media.setOnError(() -> {
                Platform.exit();
            });
            //Create MediaPlayer, with media
            mediaPlayer = new MediaPlayer(media);
            mediaPlayer.setAutoPlay(true);
            //onEnd of media, close the app
            mediaPlayer.setOnEndOfMedia(() -> {
                Platform.exit();
            });
            //Create media viewer
            mediaView = new MediaView(mediaPlayer);
            //create scene
            scene = new Scene(new Group(), media.getWidth(), media.getHeight());
            stage.setScene(scene);
            stage.setTitle("Video Player");
            //attach the mediaView to the scene root
            ((Group) scene.getRoot()).getChildren().add(mediaView);
            stage.show();
        } finally {
            System.out.println("Inside finally");
            stage.close();
        }

    }
}

package media;

import javafx.scene.media.MediaException;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class PlayVideoSnippetTest {
    /**
     * Tests for {@link PlayVideoSnippet#playVideo(String)}.
     */

    final String PATH_OF_SUPPORTED_VIDEO_FILE = "src/test/resources/file_example_MP4_480_1_5MG.mp4";
    final String PATH_OF_UNSUPPORTED_VIDEO_FILE = "src/test/resources/file_example_WMV_480_1_2MB.wmv";

    @Test
    void testSupportedVideoFilePlaysSuccessfully() {

        assertDoesNotThrow(() -> PlayVideoSnippet.playVideo(PATH_OF_SUPPORTED_VIDEO_FILE));
    }

    @Test
    void testUnsupportedVideoFileThrowsError() {
        RuntimeException exception = assertThrows(RuntimeException.class, () -> PlayVideoSnippet.playVideo(PATH_OF_UNSUPPORTED_VIDEO_FILE));
        assertTrue(exception.getCause().getClass().equals(MediaException.class));
    }
}

Comment: If you want to test JavaFX apps, look into a testing framework dedicated for that purpose: [TestFX](http://testfx.github.io/TestFX/).
Comment: The rule for `launch()` is not that it can only be called once per instance. The rule is that it can only be called once per *application*, i.e. it must only be called once in the lifecycle of the JVM. You would see the same error without the unit test, e.g. if you called `PlayVideoSnippet.playVideo(...)` twice from the `main(...)` method (or anywhere). If you want to be able to show multiple windows in JavaFX by calling a method multiple times, you should move that functionality out of `Application.start()`, make `start()` essentially a no-op, and call `launch()` once at startup.
Comment: @James_D So how to stop the JVM in between 2 test cases ? Tried calling ```Platform.exit()``` between each test case, not helpful !!  Piece of code would be helpful. Thank you !!
Comment: You can't stop the JVM in between the test cases. The test cases are running in a JVM. As I described in my previous comment, your approach is incorrect: you **must not** call `launch()` more than once and you are setting up your code to do so. Just read the answer to the question you already linked.
Comment: Just to clarify: having a method (other than `main()`) which calls `launch()` is wrong. That's the part you need to fix.
Comment: Thanks @James_D Got your point. Will look into it !!
Answer: I was able to fix the issue with help of below inputs:

Using TestFX for testing purpose as suggested by @jewelsea.
Inputs from @James_D
StackOver flow issue

ApplicationTest.launch() method internally takes care of setting up primary stage and cleaning before each test.
Solution:
import org.junit.jupiter.api.Test;
import org.testfx.framework.junit5.ApplicationTest;
class VideoTest extends ApplicationTest {

  final String pathOfSupportedFile = "video.mp4";
  final String pathOfUnsupportedFile = "video.wmv";

  @Test
  void testSupportedVideoFilePlaysSuccessfully() throws Exception {
    assertDoesNotThrow(() -> PlayVideoSnippetTest.launch(PlayVideoSnippet.class,
            new String[]{pathOfSupportedFile}));
  }

  @Test
  void testUnsupportedVideoFileThrowsError() throws Exception {
    RuntimeException exception = assertThrows(RuntimeException.class,
        () -> PlayVideoSnippetTest.launch(PlayVideoSnippet.class,
                    new String[]{pathOfUnsupportedFile}));
    assertTrue(exception.getCause().getCause().getClass().equals(MediaException.class));
  }
}


Slight design problem with Roles, Rules and Profile2 on my site

Question: I'm a little stuck with the registration flow on my site. What I have is a multi-user environment, where each user can, but does not have to, create a secondary/Profile2 "shop" profile.
Now I don't want to just expose the Profile2 shop type to everyone. So I've set up a shopkeeper role, and would like to somehow allow users to request or opt into the role.
This isn't for security or anything. It just doesn't look professional having the menu link available to users who don't want or need the profile. Also, some newbie is bound to get curious and enter random crap, which will later mess with the display of their content.
My solution was to use a flag on the user page, which triggers a rule to promote the user, but the problem is; there's no Flag option to prevent users from being able to flag other user's accounts. Unless I use a page template to hide the flag link, but that's a perhaps a little too hacky, and as far as I understand, doesn't actually disable the link.
All I really want is some sort of link or checkbox somewhere(preferably on the user-page) saying, "I have a shop, lemme create a profile". So if anyone has a suggestion for my issue, it would be greatly appreciated!
Cheers,
Matt
Answer: Here's a fairly straightforward way to do it.

Create a field (boolean) on the user account manage fields page.  Assign it useful label such as "I want to run a store" etc.
Create a rule to add the role as follows:

Event After saving user account AND After updating an existing user account
Conditions Data comparison (user account field value) == yes AND User has role (store) NOT
Actions
Add user role (store)
And create another rule to remove the role:
Event After updating an existing user account
Conditions Data comparison (user account field value) account-unchanged == yes AND data comparison (user account field value) account == yes
Actions Remove user role (store)
This should let the users check the box and then the role will automatically be toggled on or off.


PHP - Autocomplete on input tag

Question: Google has an autofill function on any website. I wonder if it is possible if you could recreate this on your own website (eg. Autofill when website is loading). I want this autofill function implemented on my website. The data it gets should be coming from a database. What would be the most efficient way to be doing this?
Comment: ``
Answer: The Value Attribute = What is physically in the input box
The Placeholder Attribute = An input hint, as soon as a user types in the input box it disapears.
Use them like:
<input type="text" value="<?=$data['username']>">

Or:
    ">
Also, disable autofill with autocomplete="off"
Source for autocomplete

PHP - Autocomplete on input tag


Is there a way to simulate multithreading in DOS, e.g., when solving the dining philosopher's problem?

Question: The dining philosophers problem is a classic computer science textbook problem for demonstrating the use of multithreading. As Wikipedia says:

Five silent philosophers sit at a round table with bowls of spaghetti. Forks are placed between each pair of adjacent philosophers.
Each philosopher must alternately think and eat. However, a philosopher can only eat spaghetti when they have both left and right forks. Each fork can be held by only one philosopher and so a philosopher can use the fork only if it is not being used by another philosopher. After an individual philosopher finishes eating, they need to put down both forks so that the forks become available to others. A philosopher can only take the fork on their right or the one on their left as they become available and they cannot start eating before getting both forks.
Eating is not limited by the remaining amounts of spaghetti or stomach space; an infinite supply and an infinite demand are assumed.
The problem is how to design a discipline of behavior (a concurrent algorithm) such that no philosopher will starve; i.e., each can forever continue to alternate between eating and thinking, assuming that no philosopher can know when others may want to eat or think.
The problem was designed to illustrate the challenges of avoiding deadlock, a system state in which no progress is possible.

In summary, then, this is a classical problem in multithreading, demonstrating the need to avoid resource starvation using mutual exclusion principles.
I want to implement such a program in real-mode DOS, but DOS clearly lacks multithreading capabilities.
I am aware of third-party software such as RTKernel, but this seems like overkill for this situation.
Is there any solution to simulate multithreading so that I can program a simulation of the dining philosophers problem in DOS, using 16-bit x86 assembly language?
Comment: FWIW: DOS doesn't offer any help to multi-threaded programming, but it also doesn't do anything to _prevent_ you from writing a multi-threaded program. A program running on a DOS box has full control of the hardware. I don't know RTKernel, but I bet its not "overkill." Providing multi-threading probably is a large part of what RTKernel does. If you want to write your own multithreading implementation, you'll probably spend a lot more time making that work than you will spend on the actual dining philosophers.
Comment: @SolomonSlow  About the time spent on writing my own multithreading implementation, you're right that it took longer than writing a *basic version* of the dining philosophers, but as it happens I went for a *deluxe version*. The multithreading module is but a tiny part of it.
Answer: Multithreading is about creating the illusion that multiple execution paths in a program run simultaneously. On today's multi-core computers this doesn't have to be an illusion anymore if the number of threads stays within limits.
A different road to multithreading
In the preemptive multitasking model the running out of a timeslice triggers a thread switch. The switch is initiated from outside the running thread.
In the multithreading module that I have written, the switch can not happen without the running thread's approval and collaboration.
It is the running thread that decides where, but not when, a switch can take place. To this end the programmer has to insert calls to a function MaybeYieldThread at strategically chosen places in the thread. Loops are good places for this.
If at the moment of such a call, the timeslice has not yet elapsed then the call will instantly return. If the timeslice has elapsed then the MaybeYieldThread momentarily acts like a true YieldThread and the switch happens.
The major advantage of this approach is that it can avoid many of the race conditions for which you would normally be using synchronization objects like mutexes, semaphores, or critical sections. You insert your call MaybeYieldThread instruction(s) where it is thread-safe and that's it!
The main characteristics
The multithreading capabilities are encoded in a single source file mtModule.INC that you include in your application anywhere you like.

small footprint. The include file has less than 600 bytes.
very fast. Thread switches are inexpensive.
wide range of allowable stacksizes. They can range from 128 to 65536 bytes in increments of 16 bytes.
optimal memory use. Very little overhead and an allocator that coalesces free blocks.
selectable timeslice. The timeslice can range from 1 to 55 msec. (55 uses standard 54.925494 msec)
round robin scheduler.
just a few, easy to use functions.
very generous parameter passing scheme. Every (integer) register that is not used as an arg by the api itself is indeed a parameter on the thread's first invocation.

The api description
The api that I propose is a small one, but I believe it delivers all the multithreading capability a DOS program could need...
At some moment I had implemented features like thread handles, thread priorities, and inter thread communication. In retrospect and bearing in mind the saying "Less is More", I am glad that I removed all of these.
It all starts with a call to BeginSessionThread. You define the borders of the session memory where all of the thread's stacks will be placed, you define the timeslice to be used, and you point to the first thread that immediately receives control if no errors were encountered.
Among the things that the first thread will do is creating additional threads using CreateThread. What you provide is the code address of the other thread and the amount of memory you wish to use for its stack.
Once threads are up and running, they can use YieldThread to give up control in favor of the next thread, use MaybeYieldThread to give up control if, and only if, the timeslice that they are running in has elapsed, and use SleepThread to give up control and remove themselves from being scheduled until the requested duration is over.
If a thread has outlived its purpose, a call (or jmp) to ExitThread or a mere ret instruction (from a balanced stack of course!) removes the thread permanently from the scheduler and returns the memory that its stack occupied, to the pool of free session memory.
When no more multithreading is needed, a call (or jmp) to EndSessionThread will return control to the instruction directly below from where the session was started (the call BeginSessionThread instruction). It is possible to pass an exitcode.
Alternatively, exiting from the last active thread will also end the session, but in this case the exitcode will be zero.
In order to suspend the multithreading session, you can call StopSessionThread. It will reset the timer frequency to the standard 18.2 Hz and freeze all pending SleepTimes. To resume the multithreading session, all it takes is a call to ContSessionThread.
Suspending the session is one way to temporarily pause the program without disturbing the SleepTimes.
And if you want to EXEC a child program or even launch a nested multithreading session, suspending the current session is mandatory for success.
The api quick reference
BeginSessionThread
 Input
  BX timeslice in milliseconds [1,55]
  CX requested stacksize for first thread
  DX near address of first thread
  SI para address begin session memory
  DI para address end session memory
  -- everything else is user defined parameter
 Output
  CF=0 Session has ended, AX is SessionExitcode
  CF=1 'Insufficient memory'
       'Invalid stacksize'
       'Invalid timeslice'
 --------------------------------------
CreateThread
 Input
  CX requested stacksize for thread
  DX near address of thread
  -- everything else is user defined parameter
 Output
  CF=0 OK
  CF=1 'Invalid stacksize'
       'Out of memory'
 --------------------------------------
SleepThread
 Input
  CX is requested duration in milliseconds
 Output
  none
 --------------------------------------
MaybeYieldThread
 Input
  none
 Output
  none
 --------------------------------------
YieldThread
 Input
  none
 Output
  none
 --------------------------------------
ExitThread
 Input
  none
 Output
  none
 --------------------------------------
EndSessionThread
 Input
  CX is SessionExitcode
 Output
  none
 --------------------------------------
StopSessionThread
 Input
  none
 Output
  none
 --------------------------------------
ContSessionThread
 Input
  none
 Output
  none
 --------------------------------------

Some points of interest
It is mandatory that a thread doesn't change the SS segment register and that it leaves about 80 bytes on the stack for use by the mtModule.INC.
For optimal 'preemptiveness', you should not use MaybeYieldThread too sparsely. On the other hand for efficiency reasons, you should perhaps not be using MaybeYieldThread in a tight loop.
; mtModule.INC Multithreading in DOS (c) 2020 Sep Roland
; ------------------------------------------------------
; assemble with FASM, compatible with CMD and DOSBox

; Functions:
;  BeginSessionThread(BX,CX,DX,SI,DI,..) -> AX CF
;  CreateThread(CX,DX,..) -> CF
;  SleepThread(CX)
;  MaybeYieldThread()
;  YieldThread()
;  ExitThread()
;  EndSessionThread(CX)
;  StopSessionThread()
;  ContSessionThread()

; Session header:
;  +0  wSessionHighMem
;  +2  wSessionNumberOfThreads
;  +4 dwSessionParentStackptr
;  +8  wSessionTickVarStep
; +10  wSessionMicroTimeslice
; +12  wSessionTickVar

; Thread header:
;  +0  wThreadLowMem
;  +2  wThreadStacksize
;  +4  wThreadStatus: DEAD/FREE (-1), AWAKE (0), ASLEEP (1+)
;  +6  wThreadStackptr
; --------------------------------------
; IN (bx=0,cx,dx,ss:si,fs) OUT (ax,CF) MOD (cx,si,di,bp,ds,es)
mtAlloc:cmp     cx, 4096                ; Max 64KB stack
        ja      .NOK
        cmp     cx, 8                   ; Min 128 bytes stack
        jb      .NOK
; Find a free alloc that is big enough
        mov     ax, fs
        inc     ax                      ; Skipping session header
.a:     mov     ds, ax
        cmp     [bx+4], bx              ; ThreadStatus
        jge     .b                      ; Is occupied
        mov     bp, [bx+2]              ; ThreadStacksize (size of free alloc)
        sub     bp, cx
        jae     .OK
.b:     add     ax, [bx+2]              ; ThreadStacksize
        cmp     ax, [fs:bx]             ; SessionHighMem
        jb      .a
.NOK:   stc
        ret
.OK:    je      .c                      ; Tight fit, no split up
; Init header of a free alloc
        add     ax, cx
        mov     ds, ax
        mov     [bx], fs                ; ThreadLowMem
        mov     [bx+2], bp              ; ThreadStacksize
        mov     word [bx+4], -1         ; ThreadStatus = FREE
        sub     ax, cx
        mov     ds, ax
; Init thread header
.c:     mov     [bx], fs                ; ThreadLowMem
        mov     [bx+2], cx              ; ThreadStacksize
        mov     [bx+4], bx              ; ThreadStatus = AWAKE
        imul    di, cx, 16              ; -> DI is total stacksize in bytes
        sub     di, (32+8+4)+2+2        ; Initial items that go on this stack
        mov     [bx+6], di              ; ThreadStackptr
; Init thread stack
        mov     es, ax
        mov     cx, (32+8+4)/2          ; GPRs, SRegs, EFlags
        cld
        rep movs word [di], [ss:si]
        mov     [di], dx                ; ThreadAddress
        mov     word [di+2], ExitThread
        inc     word [fs:bx+2]          ; SessionNumberOfThreads
        clc
        ret
; --------------------------------------
; IN (bx,cx,dx,si,di,..) OUT (ax,CF)
; BX timeslice in milliseconds [1,55] (55 uses standard 54.925494 msec)
; CX requested stacksize for first thread, DX near address of first thread
; SI para address begin session memory, DI para address end session memory
;
; CF=0  Session has ended, AX is SessionExitcode
; CF=1  'Insufficient memory' or 'Invalid stacksize' or 'Invalid timeslice'
BeginSessionThread:
        pushfd                          ; '..' Every register is considered
        push    ds es fs gs             ; parameter on the first invocation
        pushad                          ; of the thread
; Test parameters
        mov     bp, di                  ; SessionHighMem
        sub     bp, si                  ; ThreadLowMem
        jbe     mtFail
        dec     bp
        jz      mtFail
        dec     bx                      ; Timeslice in msec
        cmp     bx, 55
        jnb     mtFail
        inc     bx
; Turn MilliTimeslice BX into TickVarStep AX and MicroTimeslice CX
        mov     ax, 65535               ; Standard step is 'chain always'
        mov     cx, 54925               ; Standard slice is 54925.494 microsec
        cmp     bx, 55
        je      .a
        push    dx                      ; (1)
        mov     ax, 1193180 Mod 65536   ; TickVarStep = (1193180 * BX) / 1000
        mul     bx                      ; BX = [1,54]
        imul    cx, bx, 1193180/65536
        add     dx, cx
        mov     cx, 1000
        div     cx                      ; -> AX = {1193, 2386, ..., 64431}
        imul    cx, bx                  ; -> CX = {1000, 2000, ..., 54000}
        pop     dx                      ; (1)
; Init session header
.a:     xor     bx, bx                  ; CONST
        mov     ds, si                  ; -> DS = Session header
        mov     [bx], di                ; SessionHighMem
        mov     [bx+2], bx              ; SessionNumberOfThreads = 0
        mov     [bx+4], sp              ; SessionParentStackptr
        mov     [bx+6], ss
        mov     [bx+8], ax              ; SessionTickVarStep
        mov     [bx+10], cx             ; SessionMicroTimeslice
        ;;mov     [bx+12], bx           ; SessionTickVar = 0
; Init header of a free alloc
        mov     [bx+16], ds             ; ThreadLowMem
        mov     [bx+18], bp             ; ThreadStacksize, all of the session
        mov     word [bx+20], -1        ; ThreadStatus = FREE          memory
; Create first thread
        mov     fs, si                  ; ThreadLowMem -> FS = Session header
        mov     si, sp                  ; -> SS:SI = Initial registers
        mov     cx, [ss:si+24]          ; pushad.CX
        call    mtAlloc                 ; -> AX CF (CX SI DI BP DS ES)
        jc      mtFail
        mov     [cs:mtTick+5], fs       ; ThreadLowMem
        mov     [cs:mtChain+3], cs      ; Patch far pointer
        call    mtSwap                  ; Hook vector 08h/1Ch
        jmp     mtCont
; --------------------------------------
; IN (ss:sp)
mtFail: popad                           ; Return with all registers preserved
        pop     gs fs es ds             ; to caller
        popfd
        stc
        ret
; --------------------------------------
; IN (cx,dx,..) OUT (CF)
; CX requested stacksize for thread, DX near address of thread
;
; CF=0  OK
; CF=1  'Invalid stacksize' or 'Out of memory'
CreateThread:
        pushfd                          ; '..' Every register is considered
        push    ds es fs gs             ; parameter on the first invocation
        pushad                          ; of the thread
        xor     bx, bx                  ; CONST
        mov     fs, [ss:bx]             ; ThreadLowMem -> FS = Session header
        mov     si, sp                  ; -> SS:SI = Initial registers
; Coalescing free blocks
        mov     ax, fs
        inc     ax
.a:     mov     ds, ax                  ; -> DS = Thread header
        mov     bp, [bx+2]              ; ThreadStacksize
        cmp     [bx+4], bx              ; ThreadStatus
        jge     .c                      ; Is occupied
        mov     es, ax
.b:     add     ax, bp                  ; BP is size of a free alloc
        cmp     ax, [fs:bx]             ; SessionHighMem
        jnb     .d
        mov     ds, ax
        mov     bp, [bx+2]              ; ThreadStacksize
        cmp     [bx+4], bx              ; ThreadStatus
        jge     .c
        add     [es:bx+2], bp           ; ThreadStacksize, BP is size of
        jmp     .b                      ;    the free alloc that follows
.c:     add     ax, bp                  ; BP is size of an actual thread stack
        cmp     ax, [fs:bx]             ; SessionHighMem
        jb      .a
.d:     call    mtAlloc                 ; -> AX CF (CX SI DI BP DS ES)
        jc      mtFail
; ---   ---   ---   ---   ---   ---   --
; IN (ss:sp)
mtFine: popad                           ; Return with all registers preserved
        pop     gs fs es ds             ; to caller
        popfd
        clc
        ret
; --------------------------------------
; IN (cx) OUT ()
; CX is requested duration in msec
SleepThread:
        pushf
        pusha
        push    ds
        xor     bx, bx                  ; CONST
        mov     ds, [ss:bx]             ; ThreadLowMem -> DS = Session header
        mov     ax, 1000                ; TICKS = (CX * 1000) / MicroTimeslice
        mul     cx
        mov     cx, [bx+10]             ; SessionMicroTimeslice
        shr     cx, 1                   ; Rounding to nearest
        adc     ax, cx
        adc     dx, bx
        div     word [bx+10]            ; SessionMicroTimeslice
        mov     [ss:bx+4], ax           ; ThreadStatus = TICKS
        pop     ds
        popa
        popf
        jmp     YieldThread
; --------------------------------------
mtTick: push    ds                      ; 1. Decrement all sleep counters
        pusha
        xor     bx, bx                  ; CONST
        mov     ax, 0                   ; SMC Start of session memory
        mov     ds, ax                  ; ThreadLowMem -> DS = Session header
        mov     cx, [bx+8]              ; SessionTickVarStep
        stc
        adc     [bx+12], cx             ; SessionTickVar
        pushf                           ; (1)
        mov     dx, [bx]                ; SessionHighMem
        inc     ax
.a:     mov     ds, ax                  ; -> DS = Thread header
        mov     cx, [bx+4]              ; ThreadStatus
        dec     cx
        js      .b                      ; AX was [-1,0], ergo not ASLEEP
        mov     [bx+4], cx              ; ThreadStatus
.b:     add     ax, [bx+2]              ; ThreadStacksize -> End current stack
        cmp     ax, dx
        jb      .a
        mov     byte [cs:$+23], 90h     ; 2. Turn 'MaybeYield' into 'Yield'
        popf                            ; (1)
        popa
        pop     ds
        jc      mtChain
        push    ax
        mov     al, 20h
        out     20h, al
        pop     ax
        iret
mtChain:jmp far 0:mtTick                ; 3. Chain to original vector 08h/1Ch
; --------------------------------------
; IN () OUT ()
MaybeYieldThread:
        ret                             ; SMC {90h=nop,C3h=ret}
; ---   ---   ---   ---   ---   ---   --
; IN () OUT ()
YieldThread:
        mov     byte [cs:$-1], 0C3h     ; Back to 'MaybeYield'
        pushfd                          ; Save context current thread
        push    ds es fs gs
        pushad
        xor     bx, bx                  ; CONST
        mov     ax, ss                  ; Begin current stack
        mov     ds, ax                  ; -> DS = Thread header
        mov     [bx+6], sp              ; ThreadStackptr
        mov     fs, [bx]                ; ThreadLowMem -> FS = Session header
        sti                             ; Guard against every thread ASLEEP!
.a:     add     ax, [bx+2]              ; ThreadStacksize -> End current stack
        cmp     ax, [fs:bx]             ; SessionHighMem
        jb      .b
        mov     ax, fs                  ; Session header
        inc     ax                      ; Stack lowest thread
.b:     mov     ds, ax
        cmp     [bx+4], bx              ; ThreadStatus
        jne     .a                      ; Is DEAD/FREE (-1) or ASLEEP (1+)
; ---   ---   ---   ---   ---   ---   --
; IN (ax,bx=0)
mtCont: mov     ss, ax
        mov     sp, [ss:bx+6]           ; ThreadStackptr
        popad                           ; Restore context new current thread
        pop     gs fs es ds
        popfd
        ret
; --------------------------------------
; IN () OUT ()
ExitThread:
        xor     bx, bx                  ; CONST
        dec     word [ss:bx+4]          ; ThreadStatus = DEAD/FREE
        mov     ds, [ss:bx]             ; ThreadLowMem -> DS = Session header
        dec     word [bx+2]             ; SessionNumberOfThreads
        jnz     YieldThread             ; Not exiting from the sole thread
        xor     cx, cx                  ; SessionExitcode
; ---   ---   ---   ---   ---   ---   --
; IN (cx) OUT (ax,CF=0)
EndSessionThread:
        call    mtSwap                  ; Unhook vector 08h/1Ch
        xor     bx, bx                  ; CONST
        mov     ds, [ss:bx]             ; ThreadLowMem -> DS = Session header
        lss     sp, [bx+4]              ; SessionParentStackptr
        mov     [esp+28], cx            ; pushad.AX, SessionExitcode
        jmp     mtFine
; --------------------------------------
; IN () OUT ()
StopSessionThread:
ContSessionThread:
        push    ax
        mov     ax, [ss:0000h]          ; ThreadLowMem -> AX = Session header
        mov     [cs:mtTick+5], ax       ; ThreadLowMem (In case there's been a
        pop     ax                      ;                       nested session)
; ---   ---   ---   ---   ---   ---   --
; IN () OUT ()
mtSwap: push    ds
        pushad
        xor     bx, bx                  ; CONST
        mov     ds, bx                  ; -> DS = IVT
        mov     ax, [046Ch]             ; BIOS.Timer
.Wait:  cmp     ax, [046Ch]
        je      .Wait
        cli
        mov     ds, [cs:mtTick+5]       ; ThreadLowMem -> DS = Session header
        mov     [bx+12], bx             ; SessionTickVar = 0
        mov     dx, [bx+8]              ; SessionTickVarStep
        mov     ds, bx                  ; -> DS = IVT
        mov     bl, 1Ch*4               ; BH=0
        inc     dx                      ; SessionTickVarStep
        jz      .Swap
        dec     dx
        mov     bl, 08h*4               ; BH=0
        mov     ax, cs
        cmp     [cs:mtChain+3], ax
        je      .Hook
.Unhook:xor     dx, dx
.Hook:  mov     al, 34h
        out     43h, al
        mov     al, dl
        out     40h, al
        mov     al, dh
        out     40h, al
.Swap:  mov     eax, [bx]
        xchg    [cs:mtChain+1], eax
        mov     [bx], eax               ; Hook/Unhook vector 08h/1Ch
        sti
        popad
        pop     ds
        ret
; --------------------------------------

An example application
Next demo program uses every function available in the above api. Its sole purpose is to demonstrate how to use the api functions, nothing more.
It's easy to experiment with different timeslices because you can specify the length of the timeslice (expressed in milliseconds) on the commandline.
The program runs fine in true real address mode and under emulation (Windows CMD and DOSBox).

; mtVersus.ASM Multithreading in DOS (c) 2020 Sep Roland
; ------------------------------------------------------
; assemble with FASM, compatible with CMD and DOSBox
DefaultTimeslice=55                     ; [1,55]

        ORG     256

        mov     sp, $
        cld

; Was timeslice specified on commandline ?
        xor     cx, cx                  ; RequestedTimeslice
        mov     si, 0081h               ; Commandline
Skip:   lodsb
        cmp     al, " "
        je      Skip
        cmp     al, 9
        je      Skip
Digit:  sub     al, "0"
        jb      Other
        cmp     al, 9
        ja      Other
        cbw
        imul    cx, 10                  ; Reasonably ignoring overflow
        add     cx, ax
        lodsb
        jmp     Digit
Other:  mov     bx, DefaultTimeslice
        cmp     cx, 1
        jb      Setup
        cmp     cx, 55
        ja      Setup
        mov     bx, cx
Setup:  mov     di, [0002h]             ; PSP.NXTGRAF -> end of session memory
        lea     si, [di-128]            ; 2KB session memory (11 threads)
        mov     dx, Main
        mov     cx, 8                   ; 128 bytes stack

        mov     bp, MsgCO
        call    BeginSessionThread      ; -> AX CF
        jc      Exit
        mov     bp, MsgPE
        call    BeginSessionThread      ; -> AX CF
        ;;;jc      Exit

Exit:   mov     ax, 4C00h               ; DOS.Terminate
        int     21h
; --------------------------------------
; IN (bp)                               ; BP=ModeOfOperation
Main:   mov     dx, bp                  ; Displaying title
        mov     ah, 09h                 ; DOS.PrintString
        int     21h

        mov     di, EOF                 ; Preparing output string
        mov     cx, 79
        mov     al, " "
        rep stosb
        mov     word [di], 240Dh        ; CR and '$'

        mov     di, EOF+6               ; Creating 10 counting threads
        mov     dx, Count
        mov     cx, 8                   ; 128 bytes stack
.a:     mov     byte [di], "0"
        call    CreateThread            ; -> CF
        jc      EndSessionThread        ; CX=8
        add     di, 8
        cmp     di, EOF+79
        jb      .a

        mov     byte [Flag], 0
        mov     dx, 10                  ; Sleep while counters run (10 sec)
.b:     mov     cx, 1000
        call    SleepThread
        mov     ah, 01h                 ; BIOS.TestKey
        int     16h                     ; -> AX ZF
        jz      .c
        mov     ah, 00h                 ; BIOS.GetKey
        int     16h                     ; -> AX
        call    StopSessionThread
        mov     ah, 00h                 ; BIOS.GetKey
        int     16h                     ; -> AX
        call    ContSessionThread
.c:     dec     dx
        jnz     .b

        not     byte [Flag]             ; Forces all other threads to exit
        call    YieldThread

; Exiting from the sole thread == EndSessionThread
        mov     dl, 10
        mov     ah, 02h                 ; DOS.PrintChar
        int     21h
        ret                             ; == ExitThread
; --------------------------------------
; IN (di,bp)                            ; DI=Counter, BP=ModeOfOperation
Count:  mov     si, di                  ; Position of the ones in our counter
.a:     mov     al, [si]
        inc     al
        cmp     al, "9"
        jbe     .b
        mov     byte [si], "0"
        dec     si
        cmp     byte [si], " "
        jne     .a
        mov     al, "1"
.b:     mov     [si], al
        mov     dx, EOF
        mov     ah, 09h                 ; DOS.PrintString
        int     21h
        cmp     bp, MsgPE
        je      .PE
.CO:    call    YieldThread
        cmp     byte [Flag], 0
        je      Count
        jmp     ExitThread
.PE:    call    MaybeYieldThread
        cmp     byte [Flag], 0
        je      Count
        ret                             ; == ExitThread
; --------------------------------------
MsgCO:  db      13, 10, '10 seconds of cooperative multithreading '
        db      'using YieldThread():', 13, 10, '$'
MsgPE:  db      13, 10, '10 seconds of preemptive multithreading '
        db      'using MaybeYieldThread():', 13, 10, '$'
Flag:   db      0
; --------------------------------------
        INCLUDE 'mtModule.INC'
; --------------------------------------
EOF:
; --------------------------------------


Drupal 7 skip loading the template for ajax requests

Question: I am trying to upload an image in my template page, using jquery ajax-form submit.
And i am returning just the image name after it is uploaded in the module function.
However, i am getting the entire html as response.
In my theme's template.php, i have used the following code:
function my_theme_preprocess_page(&$vars) {
  if ( isset($_GET['ajax']) && $_GET['ajax'] == 1 ) {
        $vars['template_file'] = 'page-ajax';
  }
}

I have this code in my theme's page-ajax.tpl.php: <?php print $content; ?>
And i am passing the 'ajax=1' parameter to the module hook menu function that handles the image upload.
How can i just output the image name in ajax response, instead of the entire html.tpl.php?
Answer: How are you generating the ajax response?
If you simply want to return a string eg a file name you can just return it as plain text or as JSON using hook_menu and a callback function eg:
function mymodule_menu() {
    $items['my/custom/path'] = array(
      'page callback' => 'mymodule_callback',
    );
    return $items;
}
function mymodule_callback() {
  //Do stuff like get filename from DB.
  print 'filename.jpg';

  //to return JSON use drupal_json
  //drupal_json(array('filename' => 'filename.jpg'))
}

Comment: Sorry for being late. In my module function, i am returning just the string output, and then using exit. For example, ****
After clearing the cache, everything is working well now.


What should I change so that my arctan(x) approximation can display x=1 and x=-1 properly?

Question: One of my C assignments was it to write an approximation of arctan(x) in the language C. The equation which I should base it on is
arctan(x)=\sum {k=0}^{\infty }(-1)^{k} \tfrac{x^{2k+1}}{2k+1}

In addition x is only defined as -1<=x<=1.
Here is my code.
#include <stdio.h>
#include <math.h>

double main(void) {

    double x=1;
    double k;
    double sum;
    double sum_old;
    int count;

    double pw(double y, double n) {
        double i;
        double number = 1;

        for (i = 0; i < n; i++) {
            number *= y;
        }
        return(number);
    }

    double fc (double y) {
        double i;
        double number = 1;

        for (i = 1; i <= y; i++){
            number *= i;
        }
        return(number);
    }

    if(x >= (-1) && x <= 1) {
        for(k=0; sum!=sum_old; k++) {
            sum_old = sum;
            sum += pw((-1), k) * pw(x, (2*k) + 1)/((2*k) + 1);
            count++;

            printf("%d || %.17lf\n", count, sum);
        }

    printf("My result is: %.17lf\n",sum);
    printf("atan(%f) is: %.17f\n", x, atan(x));
    printf("My result minus atan(x) = %.17lf\n", sum - atan(x));
    } else {
        printf("x is not defined. Please choose an x in the intervall [-1, 1]\n");
        }

return 0;
}

It seemingly works fine with every value, except value 1 and -1. If x=1, then the output ends with:
...
7207 || 0.78543285189457468
7208 || 0.78536

Whereas the output should look more like this. In this case x=0.5.
25 || 0.46364760900080587
26 || 0.46364760900080587
My result is: 0.46364760900080587
atan(0.500000) is: 0.46364760900080609
My result minus atan(x) atan(x) = -0.00000000000000022

How can I improve my code so that it can run with x=1 and x=-1.
Thanks in advance.
PS: I use my own created pw() function instead of pow(), because I wanted to bybass the restriction of not using pow() as we didn't had that in our lectures yet.
PPS: I'd appreciate any advice as to how to improve my code.
Comment: @Arhama I have not seen C functions declared inside main like that, looks like java to me.  Prototype all your functions at the top of the file and define then at the bottom, thats normally how we do it.  I suppose what you have is fine assuming it works, it just makes main harder to read imo.
Comment: It is wasteful to compute `pw` from scratch every time. Instead, remember the factors in the term (-1^k and x^(2k+1)) and just update them in each iteration.
Comment: Why are you defining functions within `main`?
Comment: @Bwebb Apparently, [GCC](https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html) (for example) is a C language extension and allows nested functions.  I didn't know that it was still legal.
Comment: What is x=1 and x=-1 supposed to output?  I looked up the graph and is seems close enough, whats the problem exactly?  The number of iterations it takes?
Comment: Incidentally, you need to initialize `sum`, `sum_old`, and `count`, or rearrange the code to avoid using them before they have been assigned values.
Comment: You need to use the Taylor expansion around `x = 1` if you plan to calculate `atan` in the region of unity accurately.
Answer: In each iteration, you add (-1)k • x2k+1 / (2k+1), and you stop when there is no change to the sum.
If this were calculated with ideal arithmetic (exact, infinitely precise arithmetic), it would never stop for non-zero x, since you are always changing the sum. When calculating with fixed-precision arithmetic, it stops when the term is so small it does not change the sum because of the limited precision.
When |x| is less than one by any significant amount, this comes quickly because x2k+1 gets smaller. When |x| is one, the term becomes just 1 / (2k+1), which gets smaller very slowly. Not until k is around 253 would the sum stop changing.
You might consider changing your stopping condition to be when sum has not changed from sum_old very much rather than when it has not changed at all.
Answer: I think the cause of this is for a mathematical reason rather than a programming one.
Away from the little mistakes and adjustments that you should do to your code, putting x = 1 in the infinite series of arctan, is a boundary condition:

In this series, we add a negative value to a positive value then a negative value. This means the sum will be increasing, decreasing, increasing, ...  and this will make some difference each iteration. This difference will be smaller until the preciseness of double won't catch it, so the program will stop and give us the value.
But in the sum equation. When we set z = 1 and n goes from 0 to ∞, this will make this term (-1^n) equal to 1 in one time and -1 in the next iteration. Also,
the value of the z-term will be one and the denominator value when n approaches infinity will = ∞ .
So the sum several iterations will be like +1/∞ -1/∞ +1/∞ -1/∞ ... (where ∞ here represents a big number). That way the series will not reach a specific number. This is because z = 1 is a boundary in this equation. And that is causing infinite iterations in your solution without reaching a number.
If you need to calculate arctan(1) I think you should use this formula:
All formulas are from this Wikipedia article.
Answer: if(x >= (-1) && x <= 1) {
    for(k=0; sum!=sum_old; k++) {
        sum_old = sum;
        sum += pw((-1), k) * pw(x, (2*k) + 1)/((2*k) + 1);
        count++;

        printf("%d || %.17lf\n", count, sum);
    }

Comparing doubles can be tricky. The conventional way to compare doubles is to test within epsilon.  There should be an epsilon value defined somewhere, but for your purposes how many digits are enough to approximate?  If you only need like 3 or 4 digits you can instead have
#define EPSILON 0.0001 //make this however precise you need to approximate.

if(x >= (-1) && x <= 1) {
    for(k=0; fabs(sum - sum_old) > EPSILON; k++) {
        sum_old = sum;
        sum += pw((-1), k) * pw(x, (2*k) + 1)/((2*k) + 1);
        count++;

        printf("%d || %.17lf\n", count, sum);
    }

If the issue is that -1,1 iterate too many times either reduce the precision or increase the step per iteration.  I am not sure that is what you're asking though, please clarify.
Answer: Here is some modifications that make your code more compact and has less errors:
#include <stdio.h>
#include <math.h>

#define x 0.5               //here x is much easier to change

double pw(double, double);      //declaration of the function should be done

int main() {                    //the default return type of main is int.

    double k;
    double sum = 0 ;                //you should initiate your variables.
    double sum_old = 1 ;            //=1 only to pass the for condition first time.
                                    //you don't need to define counter here
    if(x < -1 || x > 1){
        printf("x is not defined. Please choose an x in the interval [-1, 1]\n");
        return 0;
    }
    for(k=0; sum!=sum_old; k++) {
        sum_old = sum;
        sum += pw((-1), k) * pw(x, (2*k) + 1)/((2*k) + 1);
        printf("%.0f || %.17lf\n", k, sum);
    }

    printf("My result is: %.17lf\n",sum);
    printf("atan(%f) is: %.17f\n", x, atan(x));
    printf("My result minus atan(x) = %.17lf\n", sum - atan(x));

return 0;
}

double pw(double y, double n) {         //functions should be declared out of the main function
    double i;
    double number = 1;

    for (i = 0; i < n; i++) {
        number *= y;
    }
    return(number);
}

double fc (double y) {
    double i;
    double number = 1;

    for (i = 1; i <= y; i++){
        number *= i;
    }
    return(number);
}


Add timespan to another timespan does not work

Question: I have two timespans and I want to add the second timespan to the first timespan:
TimeSpan weeklyWorkTimeHours = new TimeSpan(0,0,0);
TimeSpan? completeWorkTimeForCurrentDay =
CalculateCompleteWorktime(currentWorkTimeItem).Value; /* I debugged through
the code. This method returns a correct timespan with a correct value */
weeklyWorkTimeHours.Add(completeWorkTimeForCurrentDay.Value);

But even after the last line of code, weeklyWorkTimeHours contains 0,0,0.
Why doesn't add work in this context?
Comment: Why add when you're adding to zero? Why not just take the second term?
Comment: Show the definition of `CalculateCompleteWorktime` method and `currentWorkTimeItem` variable as well. And [`TimeSpan.Add` method](http://msdn.microsoft.com/en-us/library/system.timespan.add%28v=vs.110%29.aspx) return new `TimeSpan` if you don't want ignore the return value.
Answer: The return value is a new TimeSpan, the original TimeSpan is not modified.
Try this:
weeklyWorkTimeHours = weeklyWorkTimeHours.Add(completeWorkTimeForCurrentDay.Value);

Comment: An explanation would be useful for the OP
Comment: Thanks for your answer, now I'm less confused about this.


Adding 'Add to Cart' to 'Collection Products' view

Question: I want to add an Add to Cart button to my products when they are still in the Collection Products view (Category overview). By default, when you navigate to a category like /commerce_kickstart/product-category/sample-category-1, you will find the single products display like this:

I would like to have all of the single products be shown like this:

In the Product Display content type, the add-to-cart-form is stored in $content variable. It is pretty easy to access via field_productand I can for example add multiple forms and stuff. But how can I get the form in the Collections Product view?
I went to Structure -> Views -> Collection Products -> Field and looked through the available fields. I found field_product but when I add this, everthing that changes is that a link to the product is shown underneath the price.
So how can I add this to the Category overview?
Edit:
I have added this field (because the name appeared to be familiar scince the cart form is stored in this variable (field_product) in node--product_display
https: //i.stack.imgur.com/CaNo9.png
And that caused this to appear, wich only adds a link to the product underneath the price.
https: //i.stack.imgur.com/1vbWW.png
And this is basically all the configuration besides some more irrelevant stuff:
https: //i.stack.imgur.com/fk9BB.png
Comment: In your view's field_product, do you not see the option "add to cart" under "Formatter"? Can you add a screenshot of your view configuration page?
Comment: @longboardnode I have added the screens (Sorry for plain text links, cant post more than 2 due to lack of reputation in this community)
Comment: In your view, can you add a relationship to the product category in your cart? It should be visible as Referenced Entity or Referenced Product... basically in views you need to join your node/product to its related store/product, once you have done that you should see an available field "% to buy" with the formatter "add to cart button"
Comment: https://i.stack.imgur.com/JAE5W.jpg You are a lifesaver, I would have never been able to find it myself
Comment: Good to hear it worked! I added as answer, plz accept if was helpful.
Comment: Sure thing. Keep an eye out for me if you want to play lifesaver again, I am afraid this is not going to be my last question scince I cant really get a hold of Drupal ^^
Answer: In your view, can you add a relationship to the product category in your cart? It should be visible as Referenced Entity or Referenced Product... basically in views you need to join your node/product to its related store/product, once you have done that you should see an available field "% to buy" with the formatter "add to cart button"


Post images from the DataBase

Question: I have a DataBase called iiti which has a String called ImgName,
the Value of ImgName, which is the name of an Image in the Drawable folder.
I want to post that image on an imageView
TextView descText = (TextView) findViewById(R.id.descriptionText);
        descText.setText(iiti.getneighborhood() + "\n");

ImageView iv = (ImageView) findViewById(R.id.imageView);
    int resourceId = this.getResources().getIdentifier(iiti.getLatLat(),"drawable",this.getPackageName());
    iv.setImageResource(resourceId);

the code above well only just make the ImageView a white blank image and if i try to use this code
ImageView iv = (ImageView) findViewById(R.id.imageView);
        iv.setImageResource(R.drawable.hii);
        //hii is a png image in the drawable folder

this is my xml file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".DetailActivity">

    <TextView
        android:id="@+id/cityText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:text="London"
        android:textSize="30sp" />

    <TextView
        android:id="@+id/neighborhoodText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/cityText"
        android:gravity="center"
        android:text="West End"
        android:textSize="20sp" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_below="@+id/cityText"
        android:layout_marginTop="20dp"
        android:orientation="vertical">
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:scaleType="fitStart"
            android:src="@drawable/london_photo"/>

        <fragment xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/map"
            android:name="com.google.android.gms.maps.SupportMapFragment"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_marginTop="10dp"
            android:layout_weight="1" />

    </LinearLayout>

</RelativeLayout>

the app just crashes this is the Logcat:
03-27 15:21:10.984 9542-9542/com.example.android.mymaps E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.mymaps, PID: 9542
java.lang.RuntimeException: Canvas: trying to draw too large(110250000bytes) bitmap.
at android.view.DisplayListCanvas.throwIfCannotDraw(DisplayListCanvas.java:260)
at android.graphics.Canvas.drawBitmap(Canvas.java:1420)
at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:545)

How can I resolve this error?
Comment: Post the error stacktrace and xml file
Comment: i edited it and added the Logcat and the XML file
Answer: Try this in your Activity:
val resourceId = this.getResources().getIdentifier(iiti.getImgName(), "drawable", this.getPackageName())
iv.setImageResource(resourceId)

Or this in your Fragment:
int resourceId = getActivity().getResources().getIdentifier(iiti.getImgName(), "drawable", getActivity().getPackageName());
iv.setImageResource(resourceId);

In case of any problems check source
EDIT:
This is your crash:
Canvas: trying to draw too large(110250000bytes) bitmap.

So bitmap you are trying to draw is to large... that's it. Compress your file, change it's size or do whatever shrinks it's size. And if you are hasitating - this file is 110.25MB large.
Comment: What question? You didn't edit anything. I've edited my answer to show what I meant by 'context'
Comment: can you please have another look at the question above
Comment: i don't get it what can I do all the Images are under 150kb so i don't think that they are stressing a prolem
Comment: Crash = your bitmap is to big. What to do? Make it smaller. Search in google for tools for optimizing image size
Comment: thanks for the help the hii image is the one causing the bitmap error and i fixed the bit map error
Answer: scale down the image as:
Bitmap b = BitmapFactory.decodeResource(context.getResources(),
                                       resourceId);
iv.setImageBitmap(Bitmap.createScaledBitmap(b, b.getWidth()/2, b.getHeight/2, false));

Post images from the DataBase


Optimize innodb table

Question: When i run optimize table on a innodb table, i get this message instead. does it mean that the table has already been optimized, but in a different manner?
"table | optimize | note | Table does not support optimize, doing recreate + analyze instead |"
Answer: From the documentation:
For InnoDB tables, OPTIMIZE TABLE is mapped to ALTER TABLE, which rebuilds the table to update index statistics and free unused space in the clustered index. Beginning with MySQL 5.1.27, this is displayed in the output of OPTIMIZE TABLE  when you run it on an InnoDB table, as shown here:
<code>mysql> OPTIMIZE TABLE foo;
+----------+----------+----------+-----------------------------------------------------------
| Table    | Op       | Msg_type | Msg_text
+----------+----------+----------+-----------------------------------------------------------
| test.foo | optimize | note     | Table does not support optimize, doing recreate + analyze ...
| test.foo | optimize | status   | OK
+----------+----------+----------+-----------------------------------------------------------
</code>
You can make OPTIMIZE TABLE work on other storage engines by starting mysqld with the --skip-new or --safe-mode option. In this case, OPTIMIZE TABLE is just mapped to ALTER TABLE.
Comment: Better late than never. :)

Optimize innodb table


Is the adjunct of the comorphism for a closed immersion of ringed spaces an isomorphism?

Question: Consider a closed immersion of ringed spaces $(i, i^\sharp): (Z, \mathcal{O}_Z) \to (M, \mathcal{O}_M)$. That is, $i: Z \hookrightarrow M$ is an embedding with closed image and $i^\sharp: \mathcal{O}_M \to i_* \mathcal{O}_Z$ is surjective.
My question is: is the adjunct $i^{-1}\mathcal{O}_M \to \mathcal{O}_Z$ of the comorphism  an isomorphism? It seems to me that it should be, but I don't really "understand" how to think of the adjunct to $i^\sharp$.
If this is not true in general, is it true if $Z \to M$ is a closed embedding of smooth manifolds? In this situation $\mathcal{O}_M$ is the sheaf of smooth functions on $M$, and $\mathcal{O}_Z$ is the sheaf of smooth functions on $Z$. The comorphism $i^\sharp$ here is the usual pullback of smooth functions.
Answer: No the comorphism is not an isomorphism in general.
Here is an easy counter-example. Take $Z=M$ so that $i$ is the identity. Then $i_*$ and $i^{-1}$ are the identity functors, and $(Z,\mathcal{O}_Z)\rightarrow (M,\mathcal{O}_M)$ is a closed embedding iff $\mathcal{O}_M\rightarrow i_*\mathcal{O}_Z=\mathcal{O}_Z$ is an epimorphism. But by adjunction, this corresponds to the same morphism $i^{-1}\mathcal{O}_M=\mathcal{O}_M\rightarrow\mathcal{O}_Z$. So it is not be an isomorphism if $i^\#$ isn't.
However, the morphism $i^{-1}\mathcal{O}_M\rightarrow\mathcal{O}_Z$ is always an epimorphism as it is the composition
$$ i^{-1}\mathcal{O}_M\overset{i^{-1}i^\#}\longrightarrow i^{-1}i_*\mathcal{O}_Z\overset{\varepsilon}\longrightarrow\mathcal{O}_Z$$
where $\varepsilon$ is the counit. Indeed, the counit is an isomorphism because $i$ is a closed immersion, and $i^{-1}i^\#$ is an epimorphism because $i^\#$ is an epimorphism and $i^{-1}$, being a left adjoint, preserve the epimorphisms.
I think of $i^{-1}\mathcal{O}_M$ as the sheaf of function defined in a neighborhood of $Z$ (up to equivalence where two functions agree if they agree in a neighborhood of $Z$). And I think of $i^{-1}\mathcal{O}_M\rightarrow\mathcal{O}_Z$ as the restriction map.
This give a more concrete counter-example to your assertion, and answers the second question :
if $M$ is a manifold with $\mathcal{O}_M$ the sheaf of smooth functions on $M$, and $Z$ a closed point, then $i^{-1}\mathcal{O}_M$ is simply the germs of smooth functions at $Z$, whereas $\mathcal{O}_Z$ is simply $\mathbb{R}$. The map $i^{-1}\mathcal{O}_M\rightarrow\mathcal{O}_Z$ is then the evaluation at the point $Z$. Clearly this is onto, but this is not an isomorphism.


How can I clear specific caches?

Question: In Drupal 8, we have drush cr which is the new version of drush cc all now deprecated.
We also had drush cc menu and some more specific commands to clear cache clear. If I try to execute them, I get some weird Symfony error.
What command should I use instead of drush cc <cache name> in Drupal 8?
The documentation for drush cache-clear doesn't help much.
I tried drush cr menu, for example, and it doesn't seem to work.
Comment: What weird error? drush cc and many of its more specific cache clear commands still exist, for example drush cc render.
Answer: drush is not ready for that right now (as far as I know), so you'll need to write custom drush-scripts or do some other execution. drush cr rebuilds the whole cache, drush cc is not working with drupal8.
the method drupal_flush_all_caches shows how to flush all core caches.
$module_handler = \Drupal::moduleHandler();
  // Flush all persistent caches.
  // This is executed based on old/previously known information, which is
  // sufficient, since new extensions cannot have any primed caches yet.
  $module_handler->invokeAll('cache_flush');
  foreach (Cache::getBins() as $service_id => $cache_backend) {
    $cache_backend->deleteAll();
  }

  // Flush asset file caches.
  \Drupal::service('asset.css.collection_optimizer')->deleteAll();
  \Drupal::service('asset.js.collection_optimizer')->deleteAll();
  _drupal_flush_css_js();

  // Reset all static caches.
  drupal_static_reset();

  // Invalidate the container.
  \Drupal::service('kernel')->invalidateContainer();

  // Wipe the Twig PHP Storage cache.
  PhpStorageFactory::get('twig')->deleteAll();

  // Rebuild module and theme data.
  $module_data = system_rebuild_module_data();
  /** @var \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler */
  $theme_handler = \Drupal::service('theme_handler');
  $theme_handler->refreshInfo();
  // In case the active theme gets requested later in the same request we need
  // to reset the theme manager.
  \Drupal::theme()->resetActiveTheme();

  // Rebuild and reboot a new kernel. A simple DrupalKernel reboot is not
  // sufficient, since the list of enabled modules might have been adjusted
  // above due to changed code.
  $files = array();
  foreach ($module_data as $name => $extension) {
    if ($extension->status) {
      $files[$name] = $extension;
    }
  }
  \Drupal::service('kernel')->updateModules($module_handler->getModuleList(), $files);
  // New container, new module handler.
  $module_handler = \Drupal::moduleHandler();

  // Ensure that all modules that are currently supposed to be enabled are
  // actually loaded.
  $module_handler->loadAll();

  // Rebuild all information based on new module data.
  $module_handler->invokeAll('rebuild');

  // Clear all plugin caches.
  \Drupal::service('plugin.cache_clearer')->clearCachedDefinitions();

  // Rebuild the menu router based on all rebuilt data.
  // Important: This rebuild must happen last, so the menu router is guaranteed
  // to be based on up to date information.
  \Drupal::service('router.builder')->rebuild();

  // Re-initialize the maintenance theme, if the current request attempted to
  // use it. Unlike regular usages of this function, the installer and update
  // scripts need to flush all caches during GET requests/page building.
  if (function_exists('_drupal_maintenance_theme')) {
    \Drupal::theme()->resetActiveTheme();
    drupal_maintenance_theme();
  }

There's a module too, enable admin_toolbar's admin_toolbar_tools submodule to have it all in the toolbar:
Comment: Thanks for the answer then :) I guess we will have to wait for it. Until then we can write specific scripts.
Answer: You can use DrupalConsole cache:rebuild command and use the interactive mode to select from the list the cache to clear.
drupal cache:rebuild

You can also use the command alias cr
drupal cr

If you know the cache you are trying to clear try passing as an argument
drupal cr menu

Comment: Funny enough, even here at the end of 2019 `drush cr` does not rebuild all cache. Instead, it rebuilds most. It does not "Flush routing and links cache" as you can do from the toolbar when logged in as admin.
Answer: Drush cc still (or again?) works as it did in v7
you can do e.g.:

drush cc css-js

or

drush cc render

see the link you allready gave: https://drushcommands.com/drush-8x/cache/cache-clear/
if you simply do

drush cc

you will get a list of options. ('menu' is not one of them)
$ drush cc
Enter a number to choose which cache to clear.
 [0]  :  Cancel
 [1]  :  drush
 [2]  :  theme-registry
 [3]  :  router
 [4]  :  css-js
 [5]  :  module-list
 [6]  :  theme-list
 [7]  :  render
 [8]  :  token
 [9]  :  views

Answer: Use Clear Specific Cache(https://www.drupal.org/project/ccos) module.
The Clear Specific Cache module will help you to clear the cache of sole/specific entity type (i.e block, node, views block, view page, etc.) from contextual links, local task menu, and operations drop-button.

How can I clear specific caches?


Simplifying Boolean Function with Karnaugh Maps

Question: Given the boolean function
f(x,y,z) = xyz + xyz' + xy'z + xy'z' + x'yz + x'y'z + x'y'z' (where x' = not x)

In a three variable Karnaugh Map:
   yz   yz'  y'z'  y'z
x  1    1    1     1
x' 1         1     1

The goal is to group the adjacent units and simplifying using the distributive law since y+y' would equal one. This is all good, but when it comes to the above Karnaugh map, which one do I group together? The textbook says, it should be the biggest block but I am a bit confused in terms of what that means.
The final answer after simplification would yield:
x + y' + z

Answer: I've marked the groups on the image below. As usual, the value of each group is the variable that remains constant in the group.
Red = x
Blue = y'
Green = z
So the answer is x + y' + z
Comment: The groups should always be rectangles, and the sides should be powers of two. So, in this case, we have groups that are 1x4, 2x2 and 2x2. If the blue group included the first column, it would be 2x3, which is not permitted.
Comment: Thanks for the answer. The problem I am having is know which to include inside the circles. How come the blue circle not include the first column too? Wouldn't such grouping making it a bigger block?
Answer: K-Maps must be grouped in either 1,2,4,8 basically powers of 2.
This K map can be grouped in to 3 groups  that have 4 in each group. Then look fro the variables that don't change.
The groups would look like this:
Group 1:
y' z' x'
y' z' x
y' z  x'
y' z  x

This simplifies to y'.
Group 2:
y  z  x
y  z' x
y' z' x
y' z  x

This simplifies to x.
Group 3:
y  z  x'
y' z  x'
y' z  x
y' z  x

This simplifies to z.
So the boolean function is:
y' + x + z
This is how the final answer is resolved.


scope of a controller and a validator

Question: We are developing an application using Spring MVC. There is a page which displays list of user, a check box next to it, and a submit button at the bottom of the page.
A logged in user can select those check boxes and submit, currently a controller checks whether the selected user list is empty or not and acts accordingly. Should we just bring a validator only to do this check ? or else is it fine to do it in the controller itself ? Is there any doc which says what a controller, validator should do and should not do ?
Answer: Until Spring 3.0 is released - there is no built-in support for model validation. You'll have to handle validation on your own - like this:
<code>@RequestMapping
public String post(@ModelAttribute MyModel myModel, BindingResult result){
   myValidator.validate(myModel, result);
   if (result.hasErrors()) return "myView";
   ...
}
</code>
You can do what you like, it's your code. But by convention, the controller should just be concerned with directing things - validation should really be in a separate validator.
Comment: Thanks Daniel. I could see in your code you explicitly call validate method which is applicable for AbstractCommandController not for SimpleFormController. For SimpleFormController we can just enable the validator in the bean declaration.
Comment: Yes you're absolutely right; I've been using annotation-based controllers for so long I forgot about those who extend Spring's controller classes.

scope of a controller and a validator


Trouble Understanding general Quartic soulution from the Wiki what is $\Delta_1^2$ and $\Delta_0^3$

Question: I'm trying to implement the general quartic solution for use in a ray tracer, but I'm having some trouble. The solvers I've found do cause some strange false negatives leaving holes in the tori I'm testing with.
Most implementations use the depressed quartic solutions, I don't understand the math involved and can't figure out why I'm having false non-intersections (link to layman explanation would be great).  So I'm trying to implement the general solution at this wikipedia page.  I got the stuff up until the special cases implemented, but at that point I have an issue.
When there are 4 unique roots the term they've called Q becomes non-real, and S must be calculated with the special case trig-based equations.  The problem is the angle is calculated as $\arccos{\frac{\Delta_1}{2\sqrt{\Delta_0^3}}}$ but I cannot find where $\Delta_0^3$ is defined. It does not seem to appear anywhere else in the entire wikipedia entry. Am I missing it or does anyone know what it should be?
Comment: $\Delta_0$ and $\Delta_1$ are defined towards the end of the sub-section to which you've linked, and right above the subsection dealing with Special Cases.
Comment: So your saying the superscript on those is in fact a power and not a denotation of a separate entity? I would have expected the super script number to have a separation in that case. ie. ${\Delta_0}^3$ instead of $\Delta_0^3$
Comment: @Lucian After implementing them as such, you are quite correct, I was misunderstanding the notation. Thank you, if your comment was an answer I would gladly accept it if you would like to write one up.
Answer: $\Delta_0$ and $\Delta_1$ are defined towards the end of the subsection to which you've linked, and right above the subsection dealing with Special Cases. The $3$ is an exponent, not a superscript index.


How to remove markup from file field

Question: I have added a file field in views and when displaying it has some markup like this

 6783c11f-0b05-49e3-a494-ca68d2e6c23b-2060x1366.jpeg

Configure

  Edit

 Delete

While all I need is

How can I remove this markup. Can I use views-view-field-field_name.tpl.php. Only line this file contains is print $output. How can i use this file to remove markup. Or does any preprocess hook helps
Comment: Are you using the [File Entity](https://www.drupal.org/project/file_entity) module? Then your answer may be here: [Customize Rendered File markup?](http://drupal.stackexchange.com/questions/106177/customize-rendered-file-markup)
Comment: Yes I am using File Entity module
Answer: You can use theme layer to override the views output , if you want only theme a certain field you can use this template file :views-view-field.tpl.php
for more information check this tutorial : Theming a single field in a Views
Answer: You can use Semantic Views module, it is good module that can help you get rid of unwanted Drupal wrappers.
Here are some more details about this module(quotes from its page):

This Views plugin makes unformatted styles, field row styles and other
  output more readily configurable without needing to override template
  files. Instead of overriding row style templates for views where you
  want to specify different HTML elements (tags) and class attributes,
  you can specify these inside the Views UI and avoid overriding
  templates for each view.
Some of Semantics Views functionality can be done in Views, but Views
  is restricted to use only predefined HTML element and can only style
  each Field but not wrap rows with any HTML you like.

How to remove markup from file field


How to print info when 2 things are correct and to use the input fuction when the those two things are incorrect

Question: I am doing a controlled assessment. I have this code :
# user Qualifications
print("\nQualification Level")

print("\n""\"AP\" = Apprentice",
      "\n\"FQ\" = Fully-Qualified")
user_qual = input("Enter you Qualification Level: ")

When the user_qual is equal to AP or FQ I want to print "correct". But when the user_qual is not equal to either AP or FQ, I want to print an error message and re-ask the user_qual input question. However, I tried many different ways but couldn't do it.
Please just give a simple solution and nothing complicated. I am just a beginner and learning the basics.
Comment: *"I tried many different ways but couldn't do it."* You *should* add those, it is better to show your attempts and where you failed than expecting us to write everything.
Answer: You can try defining the qualification levels within a variable. In this simple case a tuple suffices, but if there were to be more qualification levels, a dictionary would make more sense.
qualification_levels = ('AP', 'FQ')
print("\n""\"AP\" = Apprentice",
      "\n\"FQ\" = Fully-Qualified")
user_qual = input("Enter you Qualification Level: ")
if user_qual in qualification_levels:
    print('correct!')
else:
    print('ERROR!!!')

Answer: You need to turn your code into a function so it can be called again, if the criteria are not met:
def prompt():
    # user Qualifications
    print('\nQualification Level')
    print('\n"AP" = Apprentice\n"FQ" = Fully-Qualified')

    user_qual = input('Enter you Qualification Level: ')

    if user_qual not in ('AP','FQ'):
        prompt() # Criteria not met, so ask again
    print('Correct!') # Criteria met, don't ask again

# Call the function the first time
prompt()

As @IanAuld mentions in the comments, if you want to allow users to provide the answer (ie. AP) in a case insensitive manner (so users can type 'ap' instead), you would want to convert the case before evaluating it, like so:
if user_qual.upper() not in ('AP','FQ'):
    ...rest of code...

Comment: It's often useful in cases like this to normalize the input with either `upper()` or `lower()` (in this case `upper()` would be best) so that users aren't presented with an error for entering `'ap'`. This makes for a much more pleasant UX.
Comment: @IanAuld - I agree, though I wanted to throw as little at OP as possible as they state they are a beginner, etc - so just showing the basics. I'll add your comment as a note in the answer.