<commit_before>'use strict';

var APP_SCHEMA;

// Load the application schema synchronously, before creating app module
//TODO(pjm): deprecated, change this to a requires/callback
$.ajax({
    url: typeof KARMA_TEST_MODE == 'undefined'
        ? ('/simulation-schema?' + SIREPO_APP_VERSION)
        : '/static/json/schema.json',
    data: {
        simulationType: SIREPO_APP_NAME,
    },
    success: function(result) {
        APP_SCHEMA = result;
    },
    error: function(xhr, status, err) {
        console.log("schema load failed: ", err);
    },
    async: false,
    method: typeof KARMA_TEST_MODE == 'undefined' ? 'POST' : 'GET',
    dataType: 'json',
});

var app = angular.module('SirepoApp', ['ngAnimate', 'ngDraggable', 'ngRoute', 'd3']);

var APP_LOCAL_ROUTES = {
    simulations: '/simulations',
    source: '/source/:simulationId',
};

app.value('localRoutes', APP_LOCAL_ROUTES);

app.config(function($routeProvider, localRoutesProvider) {
    var localRoutes = localRoutesProvider.$get();
    $routeProvider
        .when(localRoutes.simulations, {
            controller: 'SimulationsController as simulations',
            templateUrl: '/static/html/simulations.html?' + SIREPO_APP_VERSION,
        })
        .otherwise({
            redirectTo: localRoutes.simulations,
        });
});

app.factory('activeSection', function($route, appState) {
    var self = this;
    var activeSection = null;

    self.getActiveSection = function() {
        return activeSection;
    };

    self.setActiveSection = function(name) {
        activeSection = name;
        if ($route.current.params.simulationId)
            appState.loadModels($route.current.params.simulationId);
    };

    return self;
});

app.factory('appState', function($rootScope, requestSender) {
    var self = {};
    self.models = {};
    var savedModelValues = {};

    function broadcastClear() {
        $rootScope.$broadcast('clearCache');
    }

    function broadcastChanged(name) {
        $rootScope.$broadcast(name + '.changed');
    }

    function broadcastLoaded() {
        $rootScope.$broadcast('modelsLoaded');
    }

    function isPropagationModelName(name) {
        return name.toLowerCase().indexOf('propagation') >= 0;
    }

    function isWatchpointReportModelName(name) {
        return name.indexOf('watchpointReport') >= 0;
    }

    function updateReports() {
        broadcastClear();
        for (var key in self.models) {
            if (self.isReportModelName(key))
                broadcastChanged(key);
        }
    }

    self.addNewElectronBeam = function() {
        var newBeam = self.clone(self.models.electronBeam);
        delete newBeam.isReadOnly;
        newBeam.name = 'Beam Name';
        newBeam.id = self.maxId(self.models.electronBeams) + 1;
        self.models.electronBeams.push(newBeam);
        self.models.electronBeam = newBeam;
    };

    self.applicationState = function() {
        return savedModelValues;
    };

    self.cancelChanges = function(name) {
        if (savedModelValues[name])
            self.models[name] = self.clone(savedModelValues[name]);
        if (name == 'undulator' || name == 'multipole')
            self.cancelChanges('simulation');
    };

    self.clearModels = function(emptyValues) {
        broadcastClear();
        self.models = emptyValues || {};
        savedModelValues = {};
    };

    self.clone = function(obj) {
        return JSON.parse(JSON.stringify(obj));
    };

    self.cloneModel = function(name) {
        var val = name ? self.models[name] : self.models;
        return self.clone(val);
    };

    self.getWatchItems = function() {
        if (self.isLoaded()) {
            var beamline = savedModelValues.beamline;
            var res = [];
            for (var i = 0; i < beamline.length; i++) {
                if (beamline[i].type == 'watch')
                    res.push(beamline[i]);
            }
            return res;
        }
        return [];
    };

    self.getReportTitle = function(name) {
        //TODO(pjm): generalize this
        var match = name.match(/.*?(\d+)/);
        if (match) {
            var id = match[1];
            for (var i = 0; i < savedModelValues.beamline.length; i += 1) {
                if (savedModelValues.beamline[i].id == id)
                    return 'Intensity at ' + savedModelValues.beamline[i].title + ' Report';
            }
        }
        return self.viewInfo(name).title;
    };

    self.isLoaded = function() {
        return self.models.simulation && self.models.simulation.simulationId ? true: false;
    };

    self.isReportModelName = function(name) {
        return name.indexOf('Report') >= 0;
    };

    self.isUndulator = function() {
        return savedModelValues.simulation && savedModelValues.simulation.sourceType == 'u' ? true : false;
    };

    self.loadModels = function(simulationId) {
        if (self.isLoaded() && self.models.simulation.simulationId == simulationId)
            return;
        self.clearModels();
        requestSender.sendRequest(
            requestSender.formatUrl(
                'simulationData',
                {
                    '<simulation_id>': simulationId,
                    '<simulation_type>': APP_SCHEMA.simulationType,
                }),
            function(data, status) {
                self.models = data.models;
                savedModelValues = self.cloneModel();
                updateReports();
                broadcastLoaded();
            });
    };

    self.maxId = function(items) {
        var max = 1;
        for (var i = 0; i < items.length; i++) {
            if (items[i].id > max)
                max = items[i].id;
        }
        return max;
    };

    self.modelInfo = function(name) {
        return APP_SCHEMA.model[name];
    };

    self.saveBeamline = function() {
        // culls and saves propagation and watchpoint models
        var propagations = {}
        var watchpoints = {};
        for (var i = 0; i < self.models.beamline.length; i++) {
            var item = self.models.beamline[i];
            propagations[item.id] = self.models.propagation[item.id];
            if (item.type == 'watch')
                watchpoints[self.watchpointReportName(item.id)] = true;
        }
        self.models.propagation = propagations;

        // need to save all watchpointReports and propagations for beamline changes
        for (var modelName in self.models) {
            if (isWatchpointReportModelName(modelName) && ! watchpoints[modelName]) {
                // deleted watchpoint, remove the report model
                delete self.models[modelName];
                delete savedModelValues[modelName];
                continue;
            }
            if (isWatchpointReportModelName(modelName) || isPropagationModelName(modelName))
                savedModelValues[modelName] = self.cloneModel(modelName);
        }
        self.saveChanges('beamline');
    };

    self.saveChanges = function(name) {
        if (name == 'electronBeam') {
            // keep beamSelector in sync with name, sort beams by name
            self.models.electronBeam.beamSelector = self.models.electronBeam.name;
            if (! self.models.electronBeam.isReadOnly) {
                // update the user defined beam in the electronBeams list
                for (var i = 0; i < self.models.electronBeams.length; i++) {
                    var beam = self.models.electronBeams[i];
                    if (beam.id == self.models.electronBeam.id) {
                        self.models.electronBeams.splice(i, 1, self.models.electronBeam);
                        break;
                    }
                }
            }
            self.models.electronBeams.sort(function(a, b) {
                return a.name.localeCompare(b.name);
            });
        }
        savedModelValues[name] = self.cloneModel(name);

        if (name == 'electronBeam') {
            broadcastChanged(name);
            self.saveChanges('electronBeams');
            // save electronBeam and electronBeams, but only repolot reports once
            return;
        }
        if (name == 'multipole' || name == 'undulator') {
            broadcastChanged(name);
            self.saveChanges('simulation');
            return;
        }
        if (! self.isReportModelName(name))
            updateReports();
        broadcastChanged(name);
    };

    self.viewInfo = function(name) {
        return APP_SCHEMA.view[name];
    };

    self.watchpointReportName = function(id) {
        return 'watchpointReport' + id;
    }

    return self;
});

app.factory('panelState', function($window, $rootScope, appState, requestQueue) {
    // Tracks the data, error, hidden and loading values
    var self = {};
    var panels = {};
    $rootScope.$on('clearCache', function() {
        self.clear();
    });

    function getPanelValue(name, key) {
        if (panels[name] && panels[name][key])
            return panels[name][key];
        return null;
    }

    function setPanelValue(name, key, value) {
        if (! (name || key))
            throw 'missing name or key';
        if (! panels[name])
            panels[name] = {};
        panels[name][key] = value;
    }

    self.clear = function(name) {
        if (name)
            panels[name] = {}
        else
            panels = {};
    };

    self.getError = function(name) {
        return getPanelValue(name, 'error');
    };

    self.isHidden = function(name) {
        return getPanelValue(name, 'hidden') ? true : false;
    };

    self.isLoading = function(name) {
        return getPanelValue(name, 'loading') ? true : false;
    };

    self.isReportValid = function(name) {
        if (name == 'fluxReport' && ! appState.isUndulator())
            return false;
        return true;
    };

    self.requestData = function(name, callback) {
        if (! appState.isLoaded())
            return;
        var data = getPanelValue(name, 'data');
        if (data) {
            callback(data);
            return;
        }
        setPanelValue(name, 'loading', true);
        setPanelValue(name, 'error', null);
        var responseHandler = function(data, error) {
            setPanelValue(name, 'loading', false);
            if (error) {
                setPanelValue(name, 'error', error);
            }
            else {
                setPanelValue(name, 'data', data);
                setPanelValue(name, 'error', null);
                callback(data);
            }
        };
        requestQueue.addItem([name, appState.applicationState(), responseHandler]);
    };

    self.toggleHidden = function(name) {
        setPanelValue(name, 'hidden', ! self.isHidden(name));
        if (! self.isHidden(name) && appState.isReportModelName(name)) {
            // needed to resize a hidden report
            $($window).trigger('resize');
        }
    };

    return self;
});

app.factory('requestSender', function($http, $location, localRoutes) {
    var self = {};

    function logError(data) {
        console.log('request failed: ', data);
    }

    function formatUrl(map, routeName, params) {
        if (! map[routeName])
            throw 'unknown routeName: ' + routeName;
        var url = map[routeName];
        if (params) {
            for (var k in params)
                url = url.replace(k, params[k]);
        }
        return url;
    }

    self.formatLocalUrl = function(routeName, params) {
        return formatUrl(localRoutes, routeName, params);
    }

    self.formatUrl = function(routeName, params) {
        return formatUrl(APP_SCHEMA.route, routeName, params);
    };

    self.localRedirect = function(routeName, params) {
        $location.path(self.formatLocalUrl(routeName, params));
    }

    self.sendRequest = function(urlOrName, successCallback, data, errorCallback) {
        var url = urlOrName.indexOf('/') >= 0
            ? urlOrName
            : self.formatUrl(urlOrName);
        var promise = data
            ? $http.post(url, data)
            : $http.get(url);
        promise.success(successCallback);
        if (errorCallback)
            promise.error(errorCallback);
        else
            promise.error(logError);
    };

    return self;
});

app.factory('requestQueue', function($rootScope, requestSender) {
    var self = {};
    var runQueue = [];
    var queueId = 1;
    $rootScope.$on('clearCache', function() {
        runQueue = [];
        queueId++;
    });

    function executeQueue() {
        var queueItem = runQueue[0];
        if (! queueItem)
            return;

        requestSender.sendRequest(
            'runSimulation',
            function(data) {
                handleQueueResult(queueItem, data);
            },
            {
                report: queueItem.item[0],
                models: queueItem.item[1],
                simulationType: APP_SCHEMA.simulationType,
            },
            function(data, status) {
                handleQueueResult(queueItem, {
                    error: (data == null && status == 0)
                        ? 'the server is unavailable'
                        : 'a server error occurred',
                });
            });
    }

    function handleQueueResult(queueItem, data) {
        if (! runQueue.length)
            return;
        if (runQueue[0].id != queueItem.id)
            return;
        runQueue.shift();
        if (data.error)
            queueItem.item[2](null, data.error);
        else
            queueItem.item[2](data);
        executeQueue();
    }

    self.addItem = function(item) {
        var queueItem = {
            id: queueId,
            item: item,
        };
        if (runQueue.length > 0)
            // give this item priority over others
            runQueue.splice(1, 0, queueItem);
        else {
            runQueue.push(queueItem);
            executeQueue();
        }
    };

    return self;
});

app.controller('NavController', function (activeSection, appState, requestSender) {
    var self = this;

    self.activeSection = function() {
        return activeSection.getActiveSection();
    };

    self.openSection = function(name) {
        requestSender.localRedirect(name, {
            ':simulationId': appState.isLoaded()
                ? appState.models.simulation.simulationId
                : null,
        });
    };

    self.pageTitle = function() {
        return $.grep(
            [
                self.sectionTitle(),
                SIREPO_APP_NAME.toUpperCase(),
                'Radiasoft',
            ],
            function(n){ return n })
            .join(' - ');
    };

    self.sectionTitle = function() {
        if (appState.isLoaded())
            return appState.models.simulation.name;
        return null;
    };
});

app.controller('SimulationsController', function ($scope, $window, activeSection, appState, requestSender) {
    activeSection.setActiveSection('simulations');
    var self = this;
    self.list = [];
    self.selected = null;
    appState.clearModels({
        simulation: {
            sourceType: 'u',
        },
    });
    $scope.$on('simulation.changed', function() {
        newSimulation(appState.models.simulation);
    });

    function newSimulation(model) {
        requestSender.sendRequest(
            'newSimulation',
            function(data) {
                self.open(data.models.simulation);
            },
            {
                name: model.name,
                sourceType: model.sourceType,
                simulationType: APP_SCHEMA.simulationType,
            });
    }

    function loadList() {
        requestSender.sendRequest(
            'listSimulations',
            function(data) {
                self.list = data;
            },
            {
                simulationType: APP_SCHEMA.simulationType,
            });
    }

    self.copy = function(item) {
        requestSender.sendRequest(
            'copySimulation',
            function(data) {
                self.open(data.models.simulation);
            },
            {
                simulationId: self.selected.simulationId,
                simulationType: APP_SCHEMA.simulationType,
            });
    };

    self.deleteSelected = function() {
        requestSender.sendRequest(
            'deleteSimulation',
            function() {
                loadList();
            },
            {
                simulationId: self.selected.simulationId,
                simulationType: APP_SCHEMA.simulationType,
            });
        self.selected = null;
    };

    self.isSelected = function(item) {
        return self.selected && self.selected == item ? true : false;
    };

    self.open = function(item) {
        requestSender.localRedirect('source', {
            ':simulationId': item.simulationId,
        });
    };

    self.pythonSource = function(item) {
        $window.open(requestSender.formatUrl('pythonSource', {
            '<simulation_id>': self.selected.simulationId,
            '<simulation_type>': APP_SCHEMA.simulationType,
        }), '_blank');
    };

    self.selectItem = function(item) {
        self.selected = item;
    };

    loadList();
});
<commit_msg>renamed test schema file to test-schema.json<commit_after>'use strict';

var APP_SCHEMA;

// Load the application schema synchronously, before creating app module
//TODO(pjm): deprecated, change this to a requires/callback
$.ajax({
    url: typeof KARMA_TEST_MODE == 'undefined'
        ? ('/simulation-schema?' + SIREPO_APP_VERSION)
        : '/static/json/test-schema.json',
    data: {
        simulationType: SIREPO_APP_NAME,
    },
    success: function(result) {
        APP_SCHEMA = result;
    },
    error: function(xhr, status, err) {
        console.log("schema load failed: ", err);
    },
    async: false,
    method: typeof KARMA_TEST_MODE == 'undefined' ? 'POST' : 'GET',
    dataType: 'json',
});

var app = angular.module('SirepoApp', ['ngAnimate', 'ngDraggable', 'ngRoute', 'd3']);

var APP_LOCAL_ROUTES = {
    simulations: '/simulations',
    source: '/source/:simulationId',
};

app.value('localRoutes', APP_LOCAL_ROUTES);

app.config(function($routeProvider, localRoutesProvider) {
    var localRoutes = localRoutesProvider.$get();
    $routeProvider
        .when(localRoutes.simulations, {
            controller: 'SimulationsController as simulations',
            templateUrl: '/static/html/simulations.html?' + SIREPO_APP_VERSION,
        })
        .otherwise({
            redirectTo: localRoutes.simulations,
        });
});

app.factory('activeSection', function($route, appState) {
    var self = this;
    var activeSection = null;

    self.getActiveSection = function() {
        return activeSection;
    };

    self.setActiveSection = function(name) {
        activeSection = name;
        if ($route.current.params.simulationId)
            appState.loadModels($route.current.params.simulationId);
    };

    return self;
});

app.factory('appState', function($rootScope, requestSender) {
    var self = {};
    self.models = {};
    var savedModelValues = {};

    function broadcastClear() {
        $rootScope.$broadcast('clearCache');
    }

    function broadcastChanged(name) {
        $rootScope.$broadcast(name + '.changed');
    }

    function broadcastLoaded() {
        $rootScope.$broadcast('modelsLoaded');
    }

    function isPropagationModelName(name) {
        return name.toLowerCase().indexOf('propagation') >= 0;
    }

    function isWatchpointReportModelName(name) {
        return name.indexOf('watchpointReport') >= 0;
    }

    function updateReports() {
        broadcastClear();
        for (var key in self.models) {
            if (self.isReportModelName(key))
                broadcastChanged(key);
        }
    }

    self.addNewElectronBeam = function() {
        var newBeam = self.clone(self.models.electronBeam);
        delete newBeam.isReadOnly;
        newBeam.name = 'Beam Name';
        newBeam.id = self.maxId(self.models.electronBeams) + 1;
        self.models.electronBeams.push(newBeam);
        self.models.electronBeam = newBeam;
    };

    self.applicationState = function() {
        return savedModelValues;
    };

    self.cancelChanges = function(name) {
        if (savedModelValues[name])
            self.models[name] = self.clone(savedModelValues[name]);
        if (name == 'undulator' || name == 'multipole')
            self.cancelChanges('simulation');
    };

    self.clearModels = function(emptyValues) {
        broadcastClear();
        self.models = emptyValues || {};
        savedModelValues = {};
    };

    self.clone = function(obj) {
        return JSON.parse(JSON.stringify(obj));
    };

    self.cloneModel = function(name) {
        var val = name ? self.models[name] : self.models;
        return self.clone(val);
    };

    self.getWatchItems = function() {
        if (self.isLoaded()) {
            var beamline = savedModelValues.beamline;
            var res = [];
            for (var i = 0; i < beamline.length; i++) {
                if (beamline[i].type == 'watch')
                    res.push(beamline[i]);
            }
            return res;
        }
        return [];
    };

    self.getReportTitle = function(name) {
        //TODO(pjm): generalize this
        var match = name.match(/.*?(\d+)/);
        if (match) {
            var id = match[1];
            for (var i = 0; i < savedModelValues.beamline.length; i += 1) {
                if (savedModelValues.beamline[i].id == id)
                    return 'Intensity at ' + savedModelValues.beamline[i].title + ' Report';
            }
        }
        return self.viewInfo(name).title;
    };

    self.isLoaded = function() {
        return self.models.simulation && self.models.simulation.simulationId ? true: false;
    };

    self.isReportModelName = function(name) {
        return name.indexOf('Report') >= 0;
    };

    self.isUndulator = function() {
        return savedModelValues.simulation && savedModelValues.simulation.sourceType == 'u' ? true : false;
    };

    self.loadModels = function(simulationId) {
        if (self.isLoaded() && self.models.simulation.simulationId == simulationId)
            return;
        self.clearModels();
        requestSender.sendRequest(
            requestSender.formatUrl(
                'simulationData',
                {
                    '<simulation_id>': simulationId,
                    '<simulation_type>': APP_SCHEMA.simulationType,
                }),
            function(data, status) {
                self.models = data.models;
                savedModelValues = self.cloneModel();
                updateReports();
                broadcastLoaded();
            });
    };

    self.maxId = function(items) {
        var max = 1;
        for (var i = 0; i < items.length; i++) {
            if (items[i].id > max)
                max = items[i].id;
        }
        return max;
    };

    self.modelInfo = function(name) {
        return APP_SCHEMA.model[name];
    };

    self.saveBeamline = function() {
        // culls and saves propagation and watchpoint models
        var propagations = {}
        var watchpoints = {};
        for (var i = 0; i < self.models.beamline.length; i++) {
            var item = self.models.beamline[i];
            propagations[item.id] = self.models.propagation[item.id];
            if (item.type == 'watch')
                watchpoints[self.watchpointReportName(item.id)] = true;
        }
        self.models.propagation = propagations;

        // need to save all watchpointReports and propagations for beamline changes
        for (var modelName in self.models) {
            if (isWatchpointReportModelName(modelName) && ! watchpoints[modelName]) {
                // deleted watchpoint, remove the report model
                delete self.models[modelName];
                delete savedModelValues[modelName];
                continue;
            }
            if (isWatchpointReportModelName(modelName) || isPropagationModelName(modelName))
                savedModelValues[modelName] = self.cloneModel(modelName);
        }
        self.saveChanges('beamline');
    };

    self.saveChanges = function(name) {
        if (name == 'electronBeam') {
            // keep beamSelector in sync with name, sort beams by name
            self.models.electronBeam.beamSelector = self.models.electronBeam.name;
            if (! self.models.electronBeam.isReadOnly) {
                // update the user defined beam in the electronBeams list
                for (var i = 0; i < self.models.electronBeams.length; i++) {
                    var beam = self.models.electronBeams[i];
                    if (beam.id == self.models.electronBeam.id) {
                        self.models.electronBeams.splice(i, 1, self.models.electronBeam);
                        break;
                    }
                }
            }
            self.models.electronBeams.sort(function(a, b) {
                return a.name.localeCompare(b.name);
            });
        }
        savedModelValues[name] = self.cloneModel(name);

        if (name == 'electronBeam') {
            broadcastChanged(name);
            self.saveChanges('electronBeams');
            // save electronBeam and electronBeams, but only repolot reports once
            return;
        }
        if (name == 'multipole' || name == 'undulator') {
            broadcastChanged(name);
            self.saveChanges('simulation');
            return;
        }
        if (! self.isReportModelName(name))
            updateReports();
        broadcastChanged(name);
    };

    self.viewInfo = function(name) {
        return APP_SCHEMA.view[name];
    };

    self.watchpointReportName = function(id) {
        return 'watchpointReport' + id;
    }

    return self;
});

app.factory('panelState', function($window, $rootScope, appState, requestQueue) {
    // Tracks the data, error, hidden and loading values
    var self = {};
    var panels = {};
    $rootScope.$on('clearCache', function() {
        self.clear();
    });

    function getPanelValue(name, key) {
        if (panels[name] && panels[name][key])
            return panels[name][key];
        return null;
    }

    function setPanelValue(name, key, value) {
        if (! (name || key))
            throw 'missing name or key';
        if (! panels[name])
            panels[name] = {};
        panels[name][key] = value;
    }

    self.clear = function(name) {
        if (name)
            panels[name] = {}
        else
            panels = {};
    };

    self.getError = function(name) {
        return getPanelValue(name, 'error');
    };

    self.isHidden = function(name) {
        return getPanelValue(name, 'hidden') ? true : false;
    };

    self.isLoading = function(name) {
        return getPanelValue(name, 'loading') ? true : false;
    };

    self.isReportValid = function(name) {
        if (name == 'fluxReport' && ! appState.isUndulator())
            return false;
        return true;
    };

    self.requestData = function(name, callback) {
        if (! appState.isLoaded())
            return;
        var data = getPanelValue(name, 'data');
        if (data) {
            callback(data);
            return;
        }
        setPanelValue(name, 'loading', true);
        setPanelValue(name, 'error', null);
        var responseHandler = function(data, error) {
            setPanelValue(name, 'loading', false);
            if (error) {
                setPanelValue(name, 'error', error);
            }
            else {
                setPanelValue(name, 'data', data);
                setPanelValue(name, 'error', null);
                callback(data);
            }
        };
        requestQueue.addItem([name, appState.applicationState(), responseHandler]);
    };

    self.toggleHidden = function(name) {
        setPanelValue(name, 'hidden', ! self.isHidden(name));
        if (! self.isHidden(name) && appState.isReportModelName(name)) {
            // needed to resize a hidden report
            $($window).trigger('resize');
        }
    };

    return self;
});

app.factory('requestSender', function($http, $location, localRoutes) {
    var self = {};

    function logError(data) {
        console.log('request failed: ', data);
    }

    function formatUrl(map, routeName, params) {
        if (! map[routeName])
            throw 'unknown routeName: ' + routeName;
        var url = map[routeName];
        if (params) {
            for (var k in params)
                url = url.replace(k, params[k]);
        }
        return url;
    }

    self.formatLocalUrl = function(routeName, params) {
        return formatUrl(localRoutes, routeName, params);
    }

    self.formatUrl = function(routeName, params) {
        return formatUrl(APP_SCHEMA.route, routeName, params);
    };

    self.localRedirect = function(routeName, params) {
        $location.path(self.formatLocalUrl(routeName, params));
    }

    self.sendRequest = function(urlOrName, successCallback, data, errorCallback) {
        var url = urlOrName.indexOf('/') >= 0
            ? urlOrName
            : self.formatUrl(urlOrName);
        var promise = data
            ? $http.post(url, data)
            : $http.get(url);
        promise.success(successCallback);
        if (errorCallback)
            promise.error(errorCallback);
        else
            promise.error(logError);
    };

    return self;
});

app.factory('requestQueue', function($rootScope, requestSender) {
    var self = {};
    var runQueue = [];
    var queueId = 1;
    $rootScope.$on('clearCache', function() {
        runQueue = [];
        queueId++;
    });

    function executeQueue() {
        var queueItem = runQueue[0];
        if (! queueItem)
            return;

        requestSender.sendRequest(
            'runSimulation',
            function(data) {
                handleQueueResult(queueItem, data);
            },
            {
                report: queueItem.item[0],
                models: queueItem.item[1],
                simulationType: APP_SCHEMA.simulationType,
            },
            function(data, status) {
                handleQueueResult(queueItem, {
                    error: (data == null && status == 0)
                        ? 'the server is unavailable'
                        : 'a server error occurred',
                });
            });
    }

    function handleQueueResult(queueItem, data) {
        if (! runQueue.length)
            return;
        if (runQueue[0].id != queueItem.id)
            return;
        runQueue.shift();
        if (data.error)
            queueItem.item[2](null, data.error);
        else
            queueItem.item[2](data);
        executeQueue();
    }

    self.addItem = function(item) {
        var queueItem = {
            id: queueId,
            item: item,
        };
        if (runQueue.length > 0)
            // give this item priority over others
            runQueue.splice(1, 0, queueItem);
        else {
            runQueue.push(queueItem);
            executeQueue();
        }
    };

    return self;
});

app.controller('NavController', function (activeSection, appState, requestSender) {
    var self = this;

    self.activeSection = function() {
        return activeSection.getActiveSection();
    };

    self.openSection = function(name) {
        requestSender.localRedirect(name, {
            ':simulationId': appState.isLoaded()
                ? appState.models.simulation.simulationId
                : null,
        });
    };

    self.pageTitle = function() {
        return $.grep(
            [
                self.sectionTitle(),
                SIREPO_APP_NAME.toUpperCase(),
                'Radiasoft',
            ],
            function(n){ return n })
            .join(' - ');
    };

    self.sectionTitle = function() {
        if (appState.isLoaded())
            return appState.models.simulation.name;
        return null;
    };
});

app.controller('SimulationsController', function ($scope, $window, activeSection, appState, requestSender) {
    activeSection.setActiveSection('simulations');
    var self = this;
    self.list = [];
    self.selected = null;
    appState.clearModels({
        simulation: {
            sourceType: 'u',
        },
    });
    $scope.$on('simulation.changed', function() {
        newSimulation(appState.models.simulation);
    });

    function newSimulation(model) {
        requestSender.sendRequest(
            'newSimulation',
            function(data) {
                self.open(data.models.simulation);
            },
            {
                name: model.name,
                sourceType: model.sourceType,
                simulationType: APP_SCHEMA.simulationType,
            });
    }

    function loadList() {
        requestSender.sendRequest(
            'listSimulations',
            function(data) {
                self.list = data;
            },
            {
                simulationType: APP_SCHEMA.simulationType,
            });
    }

    self.copy = function(item) {
        requestSender.sendRequest(
            'copySimulation',
            function(data) {
                self.open(data.models.simulation);
            },
            {
                simulationId: self.selected.simulationId,
                simulationType: APP_SCHEMA.simulationType,
            });
    };

    self.deleteSelected = function() {
        requestSender.sendRequest(
            'deleteSimulation',
            function() {
                loadList();
            },
            {
                simulationId: self.selected.simulationId,
                simulationType: APP_SCHEMA.simulationType,
            });
        self.selected = null;
    };

    self.isSelected = function(item) {
        return self.selected && self.selected == item ? true : false;
    };

    self.open = function(item) {
        requestSender.localRedirect('source', {
            ':simulationId': item.simulationId,
        });
    };

    self.pythonSource = function(item) {
        $window.open(requestSender.formatUrl('pythonSource', {
            '<simulation_id>': self.selected.simulationId,
            '<simulation_type>': APP_SCHEMA.simulationType,
        }), '_blank');
    };

    self.selectItem = function(item) {
        self.selected = item;
    };

    loadList();
});
<|endoftext|>


<commit_before>'use strict';
angular.module('com.module.core')
  /**
   * @ngdoc function
   * @name com.module.core.controller:LayoutCtrl
   * @description Layout controller
   * @requires $scope
   * @requires $rootScope
   * @requires CoreService
   * @requires gettextCatalog
   **/
  .controller('LayoutCtrl', function($state, $scope, $rootScope, $timeout, $cookies, CoreService,
    gettextCatalog, $location, $window) {

    $scope.goToExplore = function(){
      $location.path('/explore');
      $window.location.reload();
    };

    $scope.goToHome = function(){
      $location.path('/app');
    };

    // angular translate
    $scope.locale = {
      isopen: false
    };

    $scope.locales = $rootScope.locales;
    $scope.selectLocale = $rootScope.locale;

    $scope.setLocale = function(locale) {
      // set the current lang
      $scope.locale = $scope.locales[locale];
      $scope.selectLocale = $scope.locale;
      $rootScope.locale = $scope.locale;
      $cookies.lang = $scope.locale.lang;

      // You can change the language during runtime
      $scope.locale.isopen = !$scope.locale.isopen;

      gettextCatalog.setCurrentLanguage($scope.locale.lang);
    };

    $scope.appName = 'LB-NG-BS';
    $scope.apiUrl = CoreService.env.apiUrl;
    $scope.appTheme = 'skin-blue';
    $scope.appThemes = [{
      'name': 'Black',
      'class': 'skin-black'
    }, {
      'name': 'Blue',
      'class': 'skin-blue'
    }];
    $scope.appLayout = '';
    $scope.appLayouts = [{
      'name': 'Fixed',
      'class': 'fixed'
    }, {
      'name': 'Scrolling',
      'class': 'not-fixed'
    }];

    $scope.toggleSidebar = function() {
      var $ = angular.element;
      if ($(window).width() <= 992) {
        $('.row-offcanvas').toggleClass('active');
        $('.left-side').toggleClass('collapse-left');
        $('body').toggleClass('sidebar-collapse');
        $('.row-offcanvas').toggleClass('relative');
      } else {
        // Else, enable content streching
        $('.left-side').toggleClass('collapse-left');
        $('body').toggleClass('sidebar-collapse');
      }
    };
    $scope.toggleSidebar1 = function() {
      var $ = angular.element;
      $('body').removeClass('sidebar-collapse');
      $('.left-side').removeClass('collapse-left');
    };

    $scope.additional = function() {
      var $ = angular.element;
      $('.wrapper').toggleClass('additional');
    };

    $scope.addAlerts =[];
    var i=-1;
    $scope.notification = function() {
      i++;
      var $ = angular.element;
      $scope.namepage = ['alert-warning','alert-info','alert-mint','alert-pink','alert-dark','alert-danger','alert-primary','alert-purple','alert-success'];
      $scope.addAlerts.push($scope.namepage[i]);
      $timeout($scope.removeAdd(addAlerts[i]), 3000);
      $timeout($('.alert-wrap').removeClass('in'),5000);
    };

    $scope.removeAdd = function(index){
      $scope.addAlerts.splice(index, 1);
      $('.alert-wrap').removeClass('in');
    };
    $scope.settings = $rootScope.settings;

    $rootScope.loadSettings();

  });
<commit_msg>article display 18/7<commit_after>'use strict';
angular.module('com.module.core')
  /**
   * @ngdoc function
   * @name com.module.core.controller:LayoutCtrl
   * @description Layout controller
   * @requires $scope
   * @requires $rootScope
   * @requires CoreService
   * @requires gettextCatalog
   **/
  .controller('LayoutCtrl', function($state, $scope, $rootScope, $timeout, $cookies, CoreService,
    gettextCatalog, $location) {

    $scope.goToExplore = function(){
      $location.path('/explore');
    };

    $scope.goToHome = function(){
      $location.path('/app');
    };

    // angular translate
    $scope.locale = {
      isopen: false
    };

    $scope.locales = $rootScope.locales;
    $scope.selectLocale = $rootScope.locale;

    $scope.setLocale = function(locale) {
      // set the current lang
      $scope.locale = $scope.locales[locale];
      $scope.selectLocale = $scope.locale;
      $rootScope.locale = $scope.locale;
      $cookies.lang = $scope.locale.lang;

      // You can change the language during runtime
      $scope.locale.isopen = !$scope.locale.isopen;

      gettextCatalog.setCurrentLanguage($scope.locale.lang);
    };

    $scope.appName = 'LB-NG-BS';
    $scope.apiUrl = CoreService.env.apiUrl;
    $scope.appTheme = 'skin-blue';
    $scope.appThemes = [{
      'name': 'Black',
      'class': 'skin-black'
    }, {
      'name': 'Blue',
      'class': 'skin-blue'
    }];
    $scope.appLayout = '';
    $scope.appLayouts = [{
      'name': 'Fixed',
      'class': 'fixed'
    }, {
      'name': 'Scrolling',
      'class': 'not-fixed'
    }];

    $scope.toggleSidebar = function() {
      var $ = angular.element;
      if ($(window).width() <= 992) {
        $('.row-offcanvas').toggleClass('active');
        $('.left-side').toggleClass('collapse-left');
        $('body').toggleClass('sidebar-collapse');
        $('.row-offcanvas').toggleClass('relative');
      } else {
        // Else, enable content streching
        $('.left-side').toggleClass('collapse-left');
        $('body').toggleClass('sidebar-collapse');
      }
    };
    $scope.toggleSidebar1 = function() {
      var $ = angular.element;
      $('body').removeClass('sidebar-collapse');
      $('.left-side').removeClass('collapse-left');
    };

    $scope.additional = function() {
      var $ = angular.element;
      $('.wrapper').toggleClass('additional');
    };

    $scope.addAlerts =[];
    var i=-1;
    $scope.notification = function() {
      i++;
      var $ = angular.element;
      $scope.namepage = ['alert-warning','alert-info','alert-mint','alert-pink','alert-dark','alert-danger','alert-primary','alert-purple','alert-success'];
      $scope.addAlerts.push($scope.namepage[i]);
      $timeout($scope.removeAdd(addAlerts[i]), 3000);
      $timeout($('.alert-wrap').removeClass('in'),5000);
    };

    $scope.removeAdd = function(index){
      $scope.addAlerts.splice(index, 1);
      $('.alert-wrap').removeClass('in');
    };
    $scope.settings = $rootScope.settings;

    $rootScope.loadSettings();

  });
<|endoftext|>


<commit_before>'use strict';

var app = angular.module('myApp.google.maps.directives', []);

app.directive('googleMaps', function ($q,$compile,$timeout) {

  var _map;

  var link = function(scope,element,attrs) {

    var el = document.createElement('div');
    var lat = attrs.lat || 51.50889335149151;
    var lng = attrs.lng || -0.12989097040133;

    var zoom = 12;

    el.style.width = '100%';
    el.style.height = '100%';
    element.prepend(el);

    var myLatlng = new window.google.maps.LatLng(lat,lng);

    var createMap = function() {

      var mapOptions = {
        center: myLatlng,
        zoom: zoom,
        panControl: false,
        zoomControl: true,
        streetViewControl: false,
        zoomControlOptions: {
          style: window.google.maps.ZoomControlStyle.SMALL,
          position: window.google.maps.ControlPosition.LEFT_TOP
        }
      };
      scope.map = new window.google.maps.Map(el, mapOptions);
      scope.map.setOptions({styles: styles});

      _map.resolve(scope.map);

      // zoomListener();
    };

    $(window).resize(function() {
      if (this.resizeTO) {
        clearTimeout(this.resizeTO);
      }
      this.resizeTO = setTimeout(function() {
        $(this).trigger('resizeEnd');
      }, 500);
    });

    $(window).on('resizeEnd', function() {
      var center = scope.map.getCenter();
      window.google.maps.event.trigger(scope.map, 'resize');
      scope.map.setCenter(center);
    });

    var zoomListener = function() {
      window.google.maps.event.addListener(scope.map, 'zoom_changed', function() {
      });
    };

    var styles = [{
      'featureType': 'administrative',
      'elementType': 'labels.text.fill',
      'stylers': [{
        'color': '#444444'
      }]
    }, {
      'featureType': 'administrative.locality',
      'elementType': 'labels',
      'stylers': [{
        'visibility': 'on'
      }]
    }, {
      'featureType': 'landscape',
      'elementType': 'all',
      'stylers': [{
        'color': '#f2f2f2'
      }, {
        'visibility': 'simplified'
      }]
    }, {
      'featureType': 'poi',
      'elementType': 'all',
      'stylers': [{
        'visibility': 'on'
      }]
    }, {
      'featureType': 'poi',
      'elementType': 'geometry',
      'stylers': [{
        'visibility': 'simplified'
      }, {
        'saturation': '-65'
      }, {
        'lightness': '45'
      }, {
        'gamma': '1.78'
      }]
    }, {
      'featureType': 'poi',
      'elementType': 'labels',
      'stylers': [{
        'visibility': 'off'
      }]
    }, {
      'featureType': 'poi',
      'elementType': 'labels.icon',
      'stylers': [{
        'visibility': 'off'
      }]
    }, {
      'featureType': 'road',
      'elementType': 'all',
      'stylers': [{
        'saturation': -100
      }, {
        'lightness': 45
      }]
    }, {
      'featureType': 'road',
      'elementType': 'labels',
      'stylers': [{
        'visibility': 'on'
      }]
    }, {
      'featureType': 'road',
      'elementType': 'labels.icon',
      'stylers': [{
        'visibility': 'off'
      }]
    }, {
      'featureType': 'road.highway',
      'elementType': 'all',
      'stylers': [{
        'visibility': 'simplified'
      }]
    }, {
      'featureType': 'road.highway',
      'elementType': 'labels.icon',
      'stylers': [{
        'visibility': 'off'
      }]
    }, {
      'featureType': 'road.arterial',
      'elementType': 'labels.icon',
      'stylers': [{
        'visibility': 'off'
      }]
    }, {
      'featureType': 'transit.line',
      'elementType': 'geometry',
      'stylers': [{
        'saturation': '-33'
      }, {
        'lightness': '22'
      }, {
        'gamma': '2.08'
      }]
    }, {
      'featureType': 'transit.station.airport',
      'elementType': 'geometry',
      'stylers': [{
        'gamma': '2.08'
      }, {
        'hue': '#ffa200'
      }]
    }, {
      'featureType': 'transit.station.airport',
      'elementType': 'labels',
      'stylers': [{
        'visibility': 'off'
      }]
    }, {
      'featureType': 'transit.station.rail',
      'elementType': 'labels.text',
      'stylers': [{
        'visibility': 'off'
      }]
    }, {
      'featureType': 'transit.station.rail',
      'elementType': 'labels.icon',
      'stylers': [{
        'visibility': 'simplified'
      }, {
        'saturation': '-55'
      }, {
        'lightness': '-2'
      }, {
        'gamma': '1.88'
      }, {
        'hue': '#ffab00'
      }]
    }, {
      'featureType': 'water',
      'elementType': 'all',
      'stylers': [{
        'color': '#bbd9e5'
      }, {
        'visibility': 'simplified'
      }]
    }];

    $timeout(function() {
      createMap();
    },250);

  };

  return {
    link: link,
    scope: {
      update: '&'
    },
    transclude: true,
    replace: true,
    template: '

',
    controller: function($scope) {

      this.infoWindow = [];

      $scope.bounds = new window.google.maps.LatLngBounds();
      $scope.markers = [];
      _map = $q.defer();

      $scope.getMap = this.getMap = function() {
        return _map.promise;
      };

      this.deleteObject = function(group, obj) {
        var objs = obj.map[group];
        for (var name in objs) {
          objs[name] === obj && (delete objs[name]);
        }
        obj.map && obj.setMap && obj.setMap(null);
      };

      this.$scope = $scope;
    }

  };

});

app.directive('googleMarker', function ($timeout,$compile) {

  var link = function(scope,element,attrs,controller,transclude) {

    var infoWindow = new window.google.maps.InfoWindow();
    var contentString = '';
    var markers = controller.$scope.markers;
    var bounds = controller.$scope.bounds;
    var image;
    var marker;

    attrs.$observe('slug', function(val){

      if (val !== '') {

        controller.getMap().then(function(map) {

          var template = element.html().trim();
          var myLatLng = new window.google.maps.LatLng(attrs.lat,attrs.lng);

          infoWindow.__template = template.replace(/\s?ng-non-bindable[='"]+/,"");

          infoWindow.__compile = function() {
            marker && (scope['this'] = marker);
            var el = $compile(infoWindow.__template)(scope);
            infoWindow.setContent(template);
            scope.$apply();
          };

          infoWindow.__open = function() {
            infoWindow.__compile();
            infoWindow.open(map, marker);
          };

          var color = attrs.state === 'online' ? 'green' : 'red';

          if (attrs.spot === 'true') {
            var spot = attrs.state === 'online' ? 'online' : 'orange';
            image = {
              url: 'https://d3e9l1phmgx8f2.cloudfront.net/images/icons/'+ spot +'.png',
              size: new google.maps.Size(32,32),
              scaledSize: new google.maps.Size(10,10),
              origin: new google.maps.Point(0,0),
              anchor: new google.maps.Point(0, 0)
            };
          } else if (attrs.icon !== '') {
            image = {
              url: 'https://d3e9l1phmgx8f2.cloudfront.net/images/manufacturer-images/'+ attrs.icon + '',
              size: new google.maps.Size(44,44),
              scaledSize: new google.maps.Size(22,22),
              // strokeColor: 'green',
              // labelClass: c,
              origin: new google.maps.Point(0,0),
              anchor: new google.maps.Point(10, 40)
            };
          } else if (attrs.circle === '') {
            image = {
              url: 'https://d3e9l1phmgx8f2.cloudfront.net/images/maps/spotlight-poi_hdpi_'+ color +'.png',
              size: new google.maps.Size(44,80),
              scaledSize: new google.maps.Size(22,40),
              origin: new google.maps.Point(0,0),
              anchor: new google.maps.Point(10, 40)
            };
          }

          var c = attrs.state === 'online' ? 'online' : 'orange';
          marker = new window.google.maps.Marker({
            position: myLatLng,
            map: map,
            draggable: attrs.draggable === 'true',
            icon: image
          });

          if (attrs.circle === 'true') {
            if (attrs.norm) {
              var scale = (attrs.norm / 100);
              marker.setIcon(getIcon(scale)); //getIcon returns a circle symbol
            }
          }

          controller.infoWindow.push(infoWindow);

          markers.push(marker);
          if (attrs.zoom) {
            map.setZoom(3);
          } else {
            bounds.extend(myLatLng);
            map.fitBounds(bounds);
          }

          window.google.maps.event.addListener(marker, 'dragend', function(event) {
            var options = {};
            options.lat = event.latLng.lat();
            options.lng = event.latLng.lng();
            options.zoom = map.getZoom();
            options.slug = attrs.slug;
            controller.$scope.update({options: options});
          });

          var showInfoWindow = function() {
            var win = controller.infoWindow;
            for (var i=0; i<controller.infoWindow.length; i++) {
              controller.infoWindow[i].close();
            }
            infoWindow.__open();
          };

          window.google.maps.event.addListener(marker, 'click', function() {
            showInfoWindow();
          });

          scope.$on('$destroy', function(event, map) {
            controller.deleteObject('markers', marker);
          });

          function getIcon(scale) {
            return {
              path: window.google.maps.SymbolPath.CIRCLE,
              fillColor: attrs.colour || 'green',
              fillOpacity: .6,
              strokeColor: 'white',
              strokeWeight: 0.5,
              scale: scale * Math.pow(1.4, map.getZoom()) // Bigger circles as you zoom in
            };
          }

        });

      }

    });

  };

  return {
    link: link,
    require: '^googleMaps',
    restrict: 'E',
    scope: true
  };

});

app.directive('googleMarkerMovable', function ($timeout,$compile) {

  var link = function(scope,element,attrs,controller,transclude) {

    function setMarkers(obj, map) {

      console.log('Starting the magic');

      if (markers && markers.length) {
        for (var aa in markers) {
          markers[aa].setMap(null);
          markers[aa] = undefined;
        }
      }

      var aps = {};
      var cc = 0;
      var markers = [];
      var array = [];
      var position;
      var key;
      var bounds = new window.google.maps.LatLngBounds();

      for (var i = 0; i < obj.length; i++) {
        var a = obj[i];
        array.push(a.slug);
      }

      var noiseFactor = 0.00003;
      var noiseFactorS = 0.000001;
      var randomGaussian = function() {
        var u1 = Math.random();
        var u2 = Math.random();
        return Math.sqrt(-2*Math.log(u1))*Math.sin(2 * Math.PI * u2);
      };

      for (var k in aps) {
        if (array.indexOf(k) === -1 ) {
          aps[k].marker.setMap(null);
          delete aps[k];
        }
      }

      var deleteMarkers = function (key, count) {
        if (markers.length) {
          console.log('Deleting', count, 'markers');
          for (var i = 0; i < markers.length; i++) {
            if (markers[i].ap === key) {
              if ( parseInt(i) < (count) ) {
                markers[i].setMap(null);
                markers.splice(i, 1);
              } else { break; }
            }
          }
          console.log('Length after trim', markers.length);
        }
      };

      if ( attrs.moving !== 'true' ) {

        for (var i = 0; i < obj.length; i++) {

          var ap  = obj[i];
          key = ap.slug;
          if (!aps[key]) {

            position = new window.google.maps.LatLng(ap.latitude, ap.longitude);

            ap.marker = new window.google.maps.Marker({
              position: new google.maps.LatLng(ap.latitude, ap.longitude),
              map: map
            });
            var scale = (ap.norm / 100) * Math.pow(1.25, 15);
            ap.marker.setIcon(getIcon(scale));
            aps[key] = obj[i];
          } else  {
            aps[key].val = ap.val;
            position = new window.google.maps.LatLng(aps[key].latitude, aps[key].longitude);
          }

          bounds.extend(position);
          map.fitBounds(bounds);

        }

      } else if ( attrs.moving === 'true' ) {

        // var ap;
        var loop = function () {
          cc++;
          console.log('In array: ', markers.length)

          for (var i = 0; i < obj.length; i++) {

            var old_val = 0;
            key = obj[i].slug;

            if ( aps[key] ) {
              old_val = aps[key].old_val;
            }

            var ap = obj[i];
            // ap.val = Math.floor(Math.random() * 10 ) + 1  //ap.val;

            ap.old_val = ap.norm;

            var clients = ap.norm - old_val;

            if (clients > 0 ) {

              position = new window.google.maps.LatLng(ap.latitude, ap.longitude);

              for ( var j = 0; j < (clients); j++ ) {

                var lat = parseFloat(ap.latitude) + (noiseFactor * randomGaussian());
                var lng = parseFloat(ap.longitude) + (noiseFactor * randomGaussian());

                var m = new window.google.maps.Marker({
                  ap: key,
                  position: new google.maps.LatLng(lat, lng),
                  map: map
                });

                m.setIcon(getIcon(4));

                aps[key] = obj[i];
                markers.push(m);

              }
            } else if (clients < 0 ) {
              deleteMarkers(key, Math.abs(clients));
            }

            if (cc > 1) {
              for (var n in markers) {
                var marker = markers[n];
                var lt = parseFloat(marker.position.G) + (noiseFactorS * randomGaussian());
                var ln = parseFloat(marker.position.K) + (noiseFactorS * randomGaussian());
                marker.setPosition( new google.maps.LatLng( lt, ln ) );
              }

            }

            bounds.extend(position);
            map.fitBounds(bounds);

          }

          loopMarkers();

        };

        var t;
        var loopMarkers = function() {
          $timeout(function() {
            loop();
          }, 35000);
        };

        loop();

      }

    }

    function getIcon(scale) {
      return {
        path: window.google.maps.SymbolPath.CIRCLE,
        // fillColor: attrs.colour || '#12944E',
        fillColor: attrs.colour || '#017fdd',
        fillOpacity: 0.5,
        strokeColor: 'transparent',
        strokeWeight: 0.5,
        scale: scale,
      };
    }

    var running;
    attrs.$observe('markers', function(val){

      if (val !== '' && !running) {
        running = true;
        var newMarker = JSON.parse(attrs.markers)[0];
        controller.getMap().then(function(map) {
          setMarkers(newMarker, map);
        });

      }

    });

  };

  return {
    link: link,
    require: '^googleMaps',
    restrict: 'E',
    scope: true
  };

});

<commit_msg>zoom overrides close bounds<commit_after>'use strict';

var app = angular.module('myApp.google.maps.directives', []);

app.directive('googleMaps', function ($q,$compile,$timeout) {

  var _map;

  var link = function(scope,element,attrs) {

    var el = document.createElement('div');
    var lat = attrs.lat || 51.50889335149151;
    var lng = attrs.lng || -0.12989097040133;

    var zoom = 12;

    el.style.width = '100%';
    el.style.height = '100%';
    element.prepend(el);

    var myLatlng = new window.google.maps.LatLng(lat,lng);

    var createMap = function() {

      var mapOptions = {
        center: myLatlng,
        zoom: zoom,
        panControl: false,
        zoomControl: true,
        streetViewControl: false,
        zoomControlOptions: {
          style: window.google.maps.ZoomControlStyle.SMALL,
          position: window.google.maps.ControlPosition.LEFT_TOP
        }
      };
      scope.map = new window.google.maps.Map(el, mapOptions);
      scope.map.setOptions({styles: styles});

      _map.resolve(scope.map);

      // zoomListener();
    };

    $(window).resize(function() {
      if (this.resizeTO) {
        clearTimeout(this.resizeTO);
      }
      this.resizeTO = setTimeout(function() {
        $(this).trigger('resizeEnd');
      }, 500);
    });

    $(window).on('resizeEnd', function() {
      var center = scope.map.getCenter();
      window.google.maps.event.trigger(scope.map, 'resize');
      scope.map.setCenter(center);
    });

    var zoomListener = function() {
      window.google.maps.event.addListener(scope.map, 'zoom_changed', function() {
      });
    };

    var styles = [{
      'featureType': 'administrative',
      'elementType': 'labels.text.fill',
      'stylers': [{
        'color': '#444444'
      }]
    }, {
      'featureType': 'administrative.locality',
      'elementType': 'labels',
      'stylers': [{
        'visibility': 'on'
      }]
    }, {
      'featureType': 'landscape',
      'elementType': 'all',
      'stylers': [{
        'color': '#f2f2f2'
      }, {
        'visibility': 'simplified'
      }]
    }, {
      'featureType': 'poi',
      'elementType': 'all',
      'stylers': [{
        'visibility': 'on'
      }]
    }, {
      'featureType': 'poi',
      'elementType': 'geometry',
      'stylers': [{
        'visibility': 'simplified'
      }, {
        'saturation': '-65'
      }, {
        'lightness': '45'
      }, {
        'gamma': '1.78'
      }]
    }, {
      'featureType': 'poi',
      'elementType': 'labels',
      'stylers': [{
        'visibility': 'off'
      }]
    }, {
      'featureType': 'poi',
      'elementType': 'labels.icon',
      'stylers': [{
        'visibility': 'off'
      }]
    }, {
      'featureType': 'road',
      'elementType': 'all',
      'stylers': [{
        'saturation': -100
      }, {
        'lightness': 45
      }]
    }, {
      'featureType': 'road',
      'elementType': 'labels',
      'stylers': [{
        'visibility': 'on'
      }]
    }, {
      'featureType': 'road',
      'elementType': 'labels.icon',
      'stylers': [{
        'visibility': 'off'
      }]
    }, {
      'featureType': 'road.highway',
      'elementType': 'all',
      'stylers': [{
        'visibility': 'simplified'
      }]
    }, {
      'featureType': 'road.highway',
      'elementType': 'labels.icon',
      'stylers': [{
        'visibility': 'off'
      }]
    }, {
      'featureType': 'road.arterial',
      'elementType': 'labels.icon',
      'stylers': [{
        'visibility': 'off'
      }]
    }, {
      'featureType': 'transit.line',
      'elementType': 'geometry',
      'stylers': [{
        'saturation': '-33'
      }, {
        'lightness': '22'
      }, {
        'gamma': '2.08'
      }]
    }, {
      'featureType': 'transit.station.airport',
      'elementType': 'geometry',
      'stylers': [{
        'gamma': '2.08'
      }, {
        'hue': '#ffa200'
      }]
    }, {
      'featureType': 'transit.station.airport',
      'elementType': 'labels',
      'stylers': [{
        'visibility': 'off'
      }]
    }, {
      'featureType': 'transit.station.rail',
      'elementType': 'labels.text',
      'stylers': [{
        'visibility': 'off'
      }]
    }, {
      'featureType': 'transit.station.rail',
      'elementType': 'labels.icon',
      'stylers': [{
        'visibility': 'simplified'
      }, {
        'saturation': '-55'
      }, {
        'lightness': '-2'
      }, {
        'gamma': '1.88'
      }, {
        'hue': '#ffab00'
      }]
    }, {
      'featureType': 'water',
      'elementType': 'all',
      'stylers': [{
        'color': '#bbd9e5'
      }, {
        'visibility': 'simplified'
      }]
    }];

    $timeout(function() {
      createMap();
    },250);

  };

  return {
    link: link,
    scope: {
      update: '&'
    },
    transclude: true,
    replace: true,
    template: '

',
    controller: function($scope) {

      this.infoWindow = [];

      $scope.bounds = new window.google.maps.LatLngBounds();
      $scope.markers = [];
      _map = $q.defer();

      $scope.getMap = this.getMap = function() {
        return _map.promise;
      };

      this.deleteObject = function(group, obj) {
        var objs = obj.map[group];
        for (var name in objs) {
          objs[name] === obj && (delete objs[name]);
        }
        obj.map && obj.setMap && obj.setMap(null);
      };

      this.$scope = $scope;
    }

  };

});

app.directive('googleMarker', function ($timeout,$compile) {

  var link = function(scope,element,attrs,controller,transclude) {

    var infoWindow = new window.google.maps.InfoWindow();
    var contentString = '';
    var markers = controller.$scope.markers;
    var bounds = controller.$scope.bounds;
    var image;
    var marker;

    attrs.$observe('slug', function(val){

      if (val !== '') {

        controller.getMap().then(function(map) {

          var template = element.html().trim();
          var myLatLng = new window.google.maps.LatLng(attrs.lat,attrs.lng);

          infoWindow.__template = template.replace(/\s?ng-non-bindable[='"]+/,"");

          infoWindow.__compile = function() {
            marker && (scope['this'] = marker);
            var el = $compile(infoWindow.__template)(scope);
            infoWindow.setContent(template);
            scope.$apply();
          };

          infoWindow.__open = function() {
            infoWindow.__compile();
            infoWindow.open(map, marker);
          };

          var color = attrs.state === 'online' ? 'green' : 'red';

          if (attrs.spot === 'true') {
            var spot = attrs.state === 'online' ? 'online' : 'orange';
            image = {
              url: 'https://d3e9l1phmgx8f2.cloudfront.net/images/icons/'+ spot +'.png',
              size: new google.maps.Size(32,32),
              scaledSize: new google.maps.Size(10,10),
              origin: new google.maps.Point(0,0),
              anchor: new google.maps.Point(0, 0)
            };
          } else if (attrs.icon !== '') {
            image = {
              url: 'https://d3e9l1phmgx8f2.cloudfront.net/images/manufacturer-images/'+ attrs.icon + '',
              size: new google.maps.Size(44,44),
              scaledSize: new google.maps.Size(22,22),
              // strokeColor: 'green',
              // labelClass: c,
              origin: new google.maps.Point(0,0),
              anchor: new google.maps.Point(10, 40)
            };
          } else if (attrs.circle === '') {
            image = {
              url: 'https://d3e9l1phmgx8f2.cloudfront.net/images/maps/spotlight-poi_hdpi_'+ color +'.png',
              size: new google.maps.Size(44,80),
              scaledSize: new google.maps.Size(22,40),
              origin: new google.maps.Point(0,0),
              anchor: new google.maps.Point(10, 40)
            };
          }

          var c = attrs.state === 'online' ? 'online' : 'orange';
          marker = new window.google.maps.Marker({
            position: myLatLng,
            map: map,
            draggable: attrs.draggable === 'true',
            icon: image
          });

          if (attrs.circle === 'true') {
            if (attrs.norm) {
              var scale = (attrs.norm / 100);
              marker.setIcon(getIcon(scale)); //getIcon returns a circle symbol
            }
          }

          controller.infoWindow.push(infoWindow);

          markers.push(marker);
          if (attrs.zoom) {
            map.setZoom(3);
          } else {
            bounds.extend(myLatLng);
            map.fitBounds(bounds);
            overrideCloseBounds();
          }

          window.google.maps.event.addListener(marker, 'dragend', function(event) {
            var options = {};
            options.lat = event.latLng.lat();
            options.lng = event.latLng.lng();
            options.zoom = map.getZoom();
            options.slug = attrs.slug;
            controller.$scope.update({options: options});
          });

          var showInfoWindow = function() {
            var win = controller.infoWindow;
            for (var i=0; i<controller.infoWindow.length; i++) {
              controller.infoWindow[i].close();
            }
            infoWindow.__open();
          };

          window.google.maps.event.addListener(marker, 'click', function() {
            showInfoWindow();
          });

          scope.$on('$destroy', function(event, map) {
            controller.deleteObject('markers', marker);
          });

          function getIcon(scale) {
            return {
              path: window.google.maps.SymbolPath.CIRCLE,
              fillColor: attrs.colour || 'green',
              fillOpacity: .6,
              strokeColor: 'white',
              strokeWeight: 0.5,
              scale: scale * Math.pow(1.4, map.getZoom()) // Bigger circles as you zoom in
            };
          }

          function overrideCloseBounds() {
            var listener = window.google.maps.event.addListener(map, "idle", function() {
              var zoom = map.getZoom();
              map.setZoom(zoom > 12 ? 12 : zoom)
              google.maps.event.removeListener(listener);
            });
          }

        });

      }

    });

  };

  return {
    link: link,
    require: '^googleMaps',
    restrict: 'E',
    scope: true
  };

});

app.directive('googleMarkerMovable', function ($timeout,$compile) {

  var link = function(scope,element,attrs,controller,transclude) {

    function setMarkers(obj, map) {

      console.log('Starting the magic');

      if (markers && markers.length) {
        for (var aa in markers) {
          markers[aa].setMap(null);
          markers[aa] = undefined;
        }
      }

      var aps = {};
      var cc = 0;
      var markers = [];
      var array = [];
      var position;
      var key;
      var bounds = new window.google.maps.LatLngBounds();

      for (var i = 0; i < obj.length; i++) {
        var a = obj[i];
        array.push(a.slug);
      }

      var noiseFactor = 0.00003;
      var noiseFactorS = 0.000001;
      var randomGaussian = function() {
        var u1 = Math.random();
        var u2 = Math.random();
        return Math.sqrt(-2*Math.log(u1))*Math.sin(2 * Math.PI * u2);
      };

      for (var k in aps) {
        if (array.indexOf(k) === -1 ) {
          aps[k].marker.setMap(null);
          delete aps[k];
        }
      }

      var deleteMarkers = function (key, count) {
        if (markers.length) {
          console.log('Deleting', count, 'markers');
          for (var i = 0; i < markers.length; i++) {
            if (markers[i].ap === key) {
              if ( parseInt(i) < (count) ) {
                markers[i].setMap(null);
                markers.splice(i, 1);
              } else { break; }
            }
          }
          console.log('Length after trim', markers.length);
        }
      };

      if ( attrs.moving !== 'true' ) {

        for (var i = 0; i < obj.length; i++) {

          var ap  = obj[i];
          key = ap.slug;
          if (!aps[key]) {

            position = new window.google.maps.LatLng(ap.latitude, ap.longitude);

            ap.marker = new window.google.maps.Marker({
              position: new google.maps.LatLng(ap.latitude, ap.longitude),
              map: map
            });
            var scale = (ap.norm / 100) * Math.pow(1.25, 15);
            ap.marker.setIcon(getIcon(scale));
            aps[key] = obj[i];
          } else  {
            aps[key].val = ap.val;
            position = new window.google.maps.LatLng(aps[key].latitude, aps[key].longitude);
          }

          bounds.extend(position);
          map.fitBounds(bounds);

        }

      } else if ( attrs.moving === 'true' ) {

        // var ap;
        var loop = function () {
          cc++;
          console.log('In array: ', markers.length)

          for (var i = 0; i < obj.length; i++) {

            var old_val = 0;
            key = obj[i].slug;

            if ( aps[key] ) {
              old_val = aps[key].old_val;
            }

            var ap = obj[i];
            // ap.val = Math.floor(Math.random() * 10 ) + 1  //ap.val;

            ap.old_val = ap.norm;

            var clients = ap.norm - old_val;

            if (clients > 0 ) {

              position = new window.google.maps.LatLng(ap.latitude, ap.longitude);

              for ( var j = 0; j < (clients); j++ ) {

                var lat = parseFloat(ap.latitude) + (noiseFactor * randomGaussian());
                var lng = parseFloat(ap.longitude) + (noiseFactor * randomGaussian());

                var m = new window.google.maps.Marker({
                  ap: key,
                  position: new google.maps.LatLng(lat, lng),
                  map: map
                });

                m.setIcon(getIcon(4));

                aps[key] = obj[i];
                markers.push(m);

              }
            } else if (clients < 0 ) {
              deleteMarkers(key, Math.abs(clients));
            }

            if (cc > 1) {
              for (var n in markers) {
                var marker = markers[n];
                var lt = parseFloat(marker.position.G) + (noiseFactorS * randomGaussian());
                var ln = parseFloat(marker.position.K) + (noiseFactorS * randomGaussian());
                marker.setPosition( new google.maps.LatLng( lt, ln ) );
              }

            }

            bounds.extend(position);
            map.fitBounds(bounds);

          }

          loopMarkers();

        };

        var t;
        var loopMarkers = function() {
          $timeout(function() {
            loop();
          }, 35000);
        };

        loop();

      }

    }

    function getIcon(scale) {
      return {
        path: window.google.maps.SymbolPath.CIRCLE,
        // fillColor: attrs.colour || '#12944E',
        fillColor: attrs.colour || '#017fdd',
        fillOpacity: 0.5,
        strokeColor: 'transparent',
        strokeWeight: 0.5,
        scale: scale,
      };
    }

    var running;
    attrs.$observe('markers', function(val){

      if (val !== '' && !running) {
        running = true;
        var newMarker = JSON.parse(attrs.markers)[0];
        controller.getMap().then(function(map) {
          setMarkers(newMarker, map);
        });

      }

    });

  };

  return {
    link: link,
    require: '^googleMaps',
    restrict: 'E',
    scope: true
  };

});

<|endoftext|>


<commit_before>
'use strict';

import Immutable from 'immutable';

import {
  TESTS_STARTED
} from '../actions/test';

import {
  GAME_DIFFICULTY_CHANGE
} from '../actions/gamesetting';

import {
  PLAYER_PASSED
} from '../actions/playerstatus';

const initialState = Immutable.Map({
  lives: 5,
  passOption: true
});

// currently difficulty settings pertain to lives and timeleft only,
// as challenges still need to be sorted by difficulty.
const difficultySettings = {
  Easy: { lives: 10 },
  Medium: { lives: 5 },
  Hard: { lives: 3 }
  // Random - for random, can randomly generate lives and time and hide until game start
};

export default function playerstatus (state = initialState, action) {
  switch (action.type) {
    case TESTS_STARTED:
      return state.update('lives', lives => lives - 1);
    case GAME_DIFFICULTY_CHANGE:
      return state.set('lives', difficultySettings[action.difficulty].lives);
    case PLAYER_PASSED:
      return state.set('passOption', false);
    default:
      return state;
  }
}
<commit_msg>Reduces lives only on TESTS_FAILED now.<commit_after>
'use strict';

import Immutable from 'immutable';

import {
  CHALLENGE_START
} from '../actions/challenge';

import {
  TESTS_FAILED
} from '../actions/test';

import {
  GAME_DIFFICULTY_CHANGE
} from '../actions/gamesetting';

import {
  PLAYER_PASSED
} from '../actions/playerstatus';

const initialState = Immutable.Map({
  lives: 5,
  passOption: true
});

// currently difficulty settings pertain to lives and timeleft only,
// as challenges still need to be sorted by difficulty.
const difficultySettings = {
  Easy: { lives: 10 },
  Medium: { lives: 5 },
  Hard: { lives: 3 }
  // Random - for random, can randomly generate lives and time and hide until game start
};

export default function playerstatus (state = initialState, action) {
  switch (action.type) {
    case CHALLENGE_START:
      return state
        .set('lives', initialState.get('lives'))
        .set('passOption', true);
    case TESTS_FAILED:
      return state.update('lives', lives => lives - 1);
    case GAME_DIFFICULTY_CHANGE:
      return state.set('lives', difficultySettings[action.difficulty].lives);
    case PLAYER_PASSED:
      return state.set('passOption', false);
    default:
      return state;
  }
}
<|endoftext|>


<commit_before>'use strict'
const slapp = require('../../slackSetup.js').slapp
const getRadius = require('../../radius.js').getRadius
const tinyurl = require('tinyurl');
const routeFuncs = require('./routesIndex.js')

//db imports
const firebase    = require('../../firebaseSetup.js'),
      db = firebase.db,
      snaps = firebase.snaps,
      tags = firebase.tags,
      users = firebase.users

function snapsByGeo (lat,lng, msg, state){
    //firebase search by snap lat (start at bottom of circle, end at top)
    let radius = getRadius(lat,lng)
    let resultArr = []
    let snapLat = snaps
      .orderByChild('lat')
      .startAt(radius[5].lat + "-") // "-"makes a string: required for query
      .endAt(radius[1].lat + "-")
      .once('value')
      .then(function(snapObj) {
        let count = 0
        snapObj.forEach(function(data) {
          let snap = data.val()
          //if returns lng within radius (east/west)
          if (snap.lng <= radius[0].lng && snap.lng >= radius[3].lng) {
            count ++
            resultArr.push(snap)
          } //end if (lng checker)
        }) //end foreach
        let len = (resultArr.length-1)
        for(let i=len;i>(len-4);i--){ //last four
          let snap = resultArr[i]

          console.log(snap)
          let callback = function(picUrl){
            msg.say({
                text: '',
                attachments:[{
                  title: `${snap.description}`,
                  color: 'warning',
                  image_url: `${picUrl}`,
                  text: `${snap.address}`,
                  footer:`Jaywalk`,
                  callback_id: "snap_callback",
                  actions:[{
                    name: 'answer',
                    text: 'Directions',
                    type: 'button',
                    value: `directions`
                  }]
                }]
            }) //end msg.say
          }
          tinyurl.shorten(snap.picture, function(res) {
            callback(res)
          })
        } //end for
      }) //end .then(snap)
} // end snapsByGeo()

slapp.action('snap_callback', 'answer', (msg, value) => {
  var start = `39.733543, -104.992554`
  var mapsize = "500x400"
  var maptype = "roadmap"
  var markerParam = "&markers=color%3Ared%7Clabel%3Aa%7Cshadow%3Atrue%7C" + start

  msg.say({
    text: 'directions api here',
    "attachments": [
      {
        "fallback": "Required plain-text summary of the attachment.",
        "color": "#36a64f",
        "title_link": "https://www.google.com/maps/place/" + start,
        "image_url": "https://maps.googleapis.com/maps/api/staticmap?" +
               "size=" + mapsize +
               "&maptype=" + maptype +
               markerParam,
        //"thumb_url": "http://example.com/path/to/thumb.png"
         // "fields":[
         //  {
         //     "title": "Update your own location",
         //     "value": host_app_url + "",
         //     "short":false
         //  }
         // ]
      }
    ]
  })
})

module.exports = {
  snapsByGeo: snapsByGeo
}<commit_msg>testing map<commit_after>'use strict'
const slapp = require('../../slackSetup.js').slapp
const getRadius = require('../../radius.js').getRadius
const tinyurl = require('tinyurl');
const routeFuncs = require('./routesIndex.js')

//db imports
const firebase    = require('../../firebaseSetup.js'),
      db = firebase.db,
      snaps = firebase.snaps,
      tags = firebase.tags,
      users = firebase.users

function snapsByGeo (lat,lng, msg, state){
    //firebase search by snap lat (start at bottom of circle, end at top)
    let radius = getRadius(lat,lng)
    let resultArr = []
    let snapLat = snaps
      .orderByChild('lat')
      .startAt(radius[5].lat + "-") // "-"makes a string: required for query
      .endAt(radius[1].lat + "-")
      .once('value')
      .then(function(snapObj) {
        let count = 0
        snapObj.forEach(function(data) {
          let snap = data.val()
          //if returns lng within radius (east/west)
          if (snap.lng <= radius[0].lng && snap.lng >= radius[3].lng) {
            count ++
            resultArr.push(snap)
          } //end if (lng checker)
        }) //end foreach
        let len = (resultArr.length-1)
        for(let i=len;i>(len-4);i--){ //last four
          let snap = resultArr[i]

          console.log(snap)
          let callback = function(picUrl){
            msg.say({
                text: '',
                attachments:[{
                  title: `${snap.description}`,
                  color: 'warning',
                  image_url: `${picUrl}`,
                  text: `${snap.address}`,
                  footer:`Jaywalk`,
                  callback_id: "snap_callback",
                  actions:[{
                    name: 'answer',
                    text: 'Directions',
                    type: 'button',
                    value: `directions`
                  }]
                }]
            }) //end msg.say
          }
          tinyurl.shorten(snap.picture, function(res) {
            callback(res)
          })
        } //end for
      }) //end .then(snap)
} // end snapsByGeo()

slapp.action('snap_callback', 'answer', (msg, value) => {
  var start = `39.733543, -104.992554`
  var mapsize = "500x400"
  var maptype = "roadmap"
  var markerParam = "&markers=color%3Ared%7Clabel%3Aa%7Cshadow%3Atrue%7C" + start

  msg.say({
    text: 'directions api here',
    "attachments": [
      {
        "fallback": "Required plain-text summary of the attachment.",
        "color": "#36a64f",
        "title_link": "https://www.google.com/maps/place/" + start,
        "image_url": "https://maps.googleapis.com/maps/api/staticmap?size=500x400&maptype=roadmap&markers=color%3Ared%7Clabel%3Aa%7Cshadow%3Atrue%7C39.733543,%20-104.992554"
        //"thumb_url": "http://example.com/path/to/thumb.png"
         // "fields":[
         //  {
         //     "title": "Update your own location",
         //     "value": host_app_url + "",
         //     "short":false
         //  }
         // ]
      }
    ]
  })
})

module.exports = {
  snapsByGeo: snapsByGeo
}

// "https://maps.googleapis.com/maps/api/staticmap?size=500x400&maptype=roadmap&markers=color%3Ared%7Clabel%3Aa%7Cshadow%3Atrue%7C39.733543,-104.992554"

<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { connect } from 'react-redux';

class DriverContainer extends Component {
  render(){
    return (

Drivers

    )
  }
}

export default DriverContainer;
<commit_msg>show all the drivers and wire up all the buttons<commit_after>import React, { Component } from 'react';
import { connect } from 'react-redux';
// Actions
import { showModal, getUsers, deleteUser } from '../../actions/driver';
// Components
import Driver from '../../components/drivers/Driver';
import DriverModal from '../../components/drivers/DriverModal';
import { Button } from 'react-bootstrap';
import FontAwesome from 'react-fontawesome';

class DriverContainer extends Component {
  componentWillMount(){
    this.props.getUsers();
  }

  show = (event, driver = {}) => {this.props.showModal(driver);}
  destroy = id => {this.props.deleteUser(id)}

  render(){
    const drivers = this.props.drivers.map((driver, index) => <Driver driver={driver} key={index} onEdit={this.show} onDestroy={this.destroy}/>)
    return (

Drivers

        <Button className="create-route-btn" onClick={this.show} >
          Create Driver <FontAwesome name="plus"/>
        </Button>

{drivers}

        {this.props.showDriverModal && <DriverModal /> /* re render the route so that it updates*/}

    )
  }
}

function mapStateToProps(state, ownProps){
  return {
    drivers: state.drivers.drivers,
    showDriverModal: state.drivers.showModal
  }
}

export default connect(mapStateToProps, { showModal, getUsers, deleteUser })(DriverContainer);
<|endoftext|>