<commit_before>/*ngInject*/
export function setupRoutes($stateProvider, $urlRouterProvider) {
    $stateProvider
        .state('login', {
            url: '/login',
            template: '<mc-login></mc-login>'
        })
        .state('join', {
            url: '/join',
            template: '<mc-join></mc-join>'
        })
        .state('validate', {
            url: '/validate/:validation_uuid',
            template: '<mc-join-validate></mc-join-validate>'
        })
        .state('reset', {
            url: '/reset',
            template: '<mc-reset-password></mc-reset-password>'
        })
        .state('rvalidate', {
            url: '/rvalidate/:validation_uuid',
            template: '<mc-reset-validate></mc-reset-validate>'
        })
        .state('projects', {
            url: '/projects',
            abstract: true,
            template: '

'
        })
        .state('projects.list', {
            url: '/list',
            template: '<mc-projects></mc-projects>'
        })
        .state('account', {
            url: '/account',
            abstract: true,
            template: '

'
        })
        .state('account.settings', {
            url: '/settings',
            template: '<mc-account-settings></mc-account-settings>'
        })
        .state('account.settings.profile', {
            url: '/profile',
            template: '<mc-account-settings-profile></mc-account-settings-profile>'
        })
        .state('account.settings.projects', {
            url: '/projects',
            template: '<mc-account-settings-projects></mc-account-settings-projects>'
        })
        .state('templates', {
            url: '/templates',
            abstract: true,
            template: '

'
        })
        .state('templates.builder', {
            url: '/builder',
            template: '<mc-template-builder></mc-template-builder>'
        })
        .state('project', {
            url: '/project/:project_id',
            abstract: true,
            template: '<ui-view flex="100" layout="column"></ui-view>',
            resolve: {
                /* inject _projects to force next resolve to wait */
                _project: ["mcprojstore", "$stateParams", "experimentsAPI", function (mcprojstore, $stateParams, experimentsAPI) {
                    let p = mcprojstore.getProject($stateParams.project_id);
                    if (p.experimentsFullyLoaded) {
                        return p;
                    }

                    return experimentsAPI.getAllForProject($stateParams.project_id).then(
                        (experiments) => {
                            mcprojstore.updateCurrentProject((project) => {
                                project.experiments = _.indexBy(experiments.plain(), 'id');
                                project.experimentsFullyLoaded = true;
                            });
                            return p;
                        }
                    );
                }]
            }
        })
        .state('project.home', {
            url: '/home',
            template: '<mc-project-home></mc-project-home>'
        })
        .state('project.search', {
            url: '/search/:query',
            template: '<mc-project-search></mc-project-search>'
        })
        .state('project.create', {
            url: '/create',
            abstract: true,
            template: '<ui-view flex layout="column"></ui-view>'
        })
        .state('project.experiment', {
            url: '/experiment/:experiment_id',
            template: `<mc-experiment></mc-experiment>`
            //,
            // resolve: {
            //     experiment: ['experimentsAPI', 'toast', 'toUITask', '$stateParams', 'mcstate',
            //         function (experimentsAPI, toast, toUITask, $stateParams, mcstate) {
            //             return experimentsAPI.getForProject($stateParams.project_id, $stateParams.experiment_id)
            //                 .then(
            //                     (e) => {
            //                         e.tasks.forEach((task) => toUITask(task));
            //                         mcstate.set(mcstate.CURRENT$EXPERIMENT, e);
            //                         return e;
            //                     },
            //                     () => toast.error('Failed to retrieve experiment')
            //                 );
            //         }
            //     ]
            // }
        })
        .state('project.experiment.details', {
            url: '/details',
            template: '<mc-experiment-details experiment="$resolve.experiment" show-note="true"></mc-experiment-details>'
        })
        .state('project.experiment.tasks', {
            url: '/tasks',
            template: '<mc-experiment-tasks></mc-experiment-tasks>'
        })
        .state('project.experiment.forecast', {
            url: '/forecast',
            template: '<mc-experiment-forecast experiment="$resolve.experiment"></mc-experiment-forecast>'
        })
        .state('project.experiment.workflow', {
            url: '/processes',
            template: '<mc-processes-workflow processes="$resolve.processes"></mc-processes-workflow>',
            resolve: {
                processes: ['mcprojstore', '$stateParams',
                    (mcprojstore, $stateParams) => {
                        let e = mcprojstore.getExperiment($stateParams.experiment_id);
                        return e.processes;
                    }
                    // experimentsAPI.getProcessesForExperiment($stateParams.project_id, $stateParams.experiment_id)
                ]
            }
        })
        .state('project.experiment.samples', {
            url: '/samples',
            template: '<mc-project-samples samples="$resolve.samples"></mc-project-samples>',
            resolve: {
                samples: ['experimentsAPI', '$stateParams',
                    (experimentsAPI, $stateParams) =>
                        experimentsAPI.getSamplesForExperiment($stateParams.project_id, $stateParams.experiment_id)
                ]
            }
        })
        .state('project.experiment.files', {
            url: '/files',
            template: '<mc-experiment-files files="$resolve.files"></mc-experiment-files>',
            resolve: {
                files: ['experimentsAPI', '$stateParams',
                    (experimentsAPI, $stateParams) =>
                        experimentsAPI.getFilesForExperiment($stateParams.project_id, $stateParams.experiment_id)
                ]
            }
        })
        .state('project.experiment.notes', {
            url: '/notes',
            template: '<mc-experiment-notes experiment="$resolve.experiment"></mc-experiment-notes>'
        })
        .state('project.experiment.publish', {
            url: '/publish',
            template: '<mc-experiment-publish></mc-experiment-publish>'
        })
        .state('project.experiment.datasets', {
            url: '/datasets',
            template: '

',
            abstract: true
        })
        .state('project.experiment.datasets.list', {
            url: '/list',
            template: '<mc-experiment-datasets></mc-experiment-datasets>'
        })
        .state('project.experiment.datasets.dataset', {
            url: '/dataset/:dataset_id',
            template: '<mc-experiment-dataset></mc-experiment-dataset>'
        })
        .state('project.experiment.sample', {
            url: '/sample/:sample_id',
            template: '<mc-show-sample sample-id="ctrl.sampleId"></mc-show-sample>',
            controllerAs: 'ctrl',
            controller: ['$stateParams', function ($stateParams) {
                this.sampleId = $stateParams.sample_id;
            }]
        })
        .state('project.experiments', {
            url: '/experiments',
            template: '<mc-project-experiments experiments="$resolve.experiments"></mc-project-experiments>',
            resolve: {
                experiments: ['experimentsAPI', '$stateParams',
                    (experimentsAPI, $stateParams) =>
                        experimentsAPI.getAllForProject($stateParams.project_id)
                ]
            }
        })
        .state('project.processes', {
            url: '/processes',
            template: '<mc-project-processes processes="$resolve.processes"></mc-project-processes>',
            resolve: {
                processes: ['projectsAPI', '$stateParams',
                    (projectsAPI, $stateParams) =>
                        projectsAPI.getProjectProcesses($stateParams.project_id)
                ]
            }
        })
        .state('project.samples', {
            url: '/samples',
            template: '<mc-project-samples samples="$resolve.samples"></mc-project-samples>',
            resolve: {
                samples: ['samplesAPI', '$stateParams',
                    (samplesAPI, $stateParams) =>
                        samplesAPI.getProjectSamples($stateParams.project_id)
                ]
            }
        })
        .state('project.samples.sample', {
            url: '/sample/:sample_id',
            template: '<mc-sample></mc-sample>'
        })
        .state('project.files', {
            url: '/files',
            template: '<mc-file-tree flex layout-fill></mc-file-tree>'
        })
        .state('project.files.uploads', {
            url: '/uploads',
            template: '<mc-file-uploads reset-files="true"></mc-file-uploads>'
        })
        .state('project.files.file', {
            url: '/file/:file_id',
            template: '<mc-file></mc-file>'
        })
        .state('project.file', {
            url: '/file/:file_id',
            template: '<mc-file></mc-file>'
        })
        .state('project.files.dir', {
            url: '/dir/:dir_id',
            template: '<mc-dir></mc-dir>'
        })
        .state('project.sample', {
            url: '/sample/:sample_id',
            template: '<mc-sample></mc-sample>'
        })
        .state('project.datasets', {
            url: '/datasets',
            abstract: true,
            template: '

'
        })
        .state('project.datasets.list', {
            url: '/list',
            template: '<mc-project-datasets></mc-project-datasets>'
        })
        .state('project.datasets.dataset', {
            url: '/dataset/:dataset_id',
            template: '<mc-dataset-overview dataset="$resolve.dataset"></mc-dataset-overview>',
            resolve: {
                dataset: ['$stateParams', 'datasetsAPI',
                    ($stateParams, datasetsAPI) => datasetsAPI.getDataset('e634ee47-b217-4547-a345-5007cd146dbd', '511930bd-96a5-4678-9626-ef79aceb75b5', '57490e70-df32-4592-8a6f-8a6cfbd36174')
                ]
            }
        })
        .state('project.settings', {
            url: '/settings',
            template: '<mc-project-settings></mc-project-settings>'
        })
        .state('data', {
            url: '/data',
            abstract: true,
            template: '

'
        })
        .state('data.dataset', {
            url: '/dataset/:dataset_id',
            template: '<mc-dataset-overview dataset="$resolve.dataset"></mc-dataset-overview>',
            resolve: {
                dataset: ['publicDatasetsAPI', '$stateParams',
                    (publicDatasetsAPI, $stateParams) => publicDatasetsAPI.getDataset($stateParams.dataset_id)
                ]
            }
        })
        .state('data.home', {
            url: '/home',
            template: '<mc-data-home tags="$resolve.tags"></mc-data-home>',
            resolve: {
                tags: ['publicTagsAPI',
                    (publicTagsAPI) => publicTagsAPI.getPopularTags().then(
                        (tags) => tags.map(t => t.tag)
                    )
                ]
            }
        })
        .state('data.home.recent', {
            url: '/recent',
            template: '<mc-dataset-list datasets="$resolve.datasets" details-route="data.dataset"></mc-dataset-list>',
            resolve: {
                datasets: ['publicDatasetsAPI',
                    (publicDatasetsAPI) => publicDatasetsAPI.getRecent()
                ]
            }
        })
        .state('data.home.top', {
            url: '/top',
            template: '<mc-dataset-list datasets="$resolve.datasets" details-route="data.dataset"></mc-dataset-list>',
            resolve: {
                datasets: ['publicDatasetsAPI',
                    (publicDatasetsAPI) => publicDatasetsAPI.getTopViewed()
                ]
            }
        });

    // $urlRouterProvider.otherwise('/login');
    $urlRouterProvider.otherwise('/data/home/top');
}
<commit_msg>Wait on store ready before retrieving information<commit_after>/*ngInject*/
export function setupRoutes($stateProvider, $urlRouterProvider) {
    $stateProvider
        .state('login', {
            url: '/login',
            template: '<mc-login></mc-login>'
        })
        .state('join', {
            url: '/join',
            template: '<mc-join></mc-join>'
        })
        .state('validate', {
            url: '/validate/:validation_uuid',
            template: '<mc-join-validate></mc-join-validate>'
        })
        .state('reset', {
            url: '/reset',
            template: '<mc-reset-password></mc-reset-password>'
        })
        .state('rvalidate', {
            url: '/rvalidate/:validation_uuid',
            template: '<mc-reset-validate></mc-reset-validate>'
        })
        .state('projects', {
            url: '/projects',
            abstract: true,
            template: '

',
            resolve: {
                _db: ["mcprojstore", function (mcprojstore) {
                    return mcprojstore.ready();
                }],
                _projects: ["mcprojstore", "ProjectModel", "_db", function (mcprojstore, ProjectModel) {
                    let projects = mcprojstore.projects;
                    if (projects.length) {
                        return projects;
                    }

                    return ProjectModel.getProjectsForCurrentUser().then(
                        (projects) => {
                            mcprojstore.addProjects(...projects);
                            return mcprojstore.projects;
                        }
                    );
                }]
            }
        })
        .state('projects.list', {
            url: '/list',
            template: '<mc-projects></mc-projects>'
        })
        .state('account', {
            url: '/account',
            abstract: true,
            template: '

'
        })
        .state('account.settings', {
            url: '/settings',
            template: '<mc-account-settings></mc-account-settings>'
        })
        .state('account.settings.profile', {
            url: '/profile',
            template: '<mc-account-settings-profile></mc-account-settings-profile>'
        })
        .state('account.settings.projects', {
            url: '/projects',
            template: '<mc-account-settings-projects></mc-account-settings-projects>'
        })
        .state('templates', {
            url: '/templates',
            abstract: true,
            template: '

'
        })
        .state('templates.builder', {
            url: '/builder',
            template: '<mc-template-builder></mc-template-builder>'
        })
        .state('project', {
            url: '/project/:project_id',
            abstract: true,
            template: '<ui-view flex="100" layout="column"></ui-view>',
            resolve: {
                _db: ["mcprojstore", function (mcprojstore) {
                    return mcprojstore.ready();
                }],
                /* inject _db to force next resolve to wait for store to ready ready*/
                _project: ["mcprojstore", "$stateParams", "experimentsAPI", "_db", function (mcprojstore, $stateParams, experimentsAPI) {
                    let p = mcprojstore.getProject($stateParams.project_id);
                    if (p.experimentsFullyLoaded) {
                        return p;
                    }

                    return experimentsAPI.getAllForProject($stateParams.project_id).then(
                        (experiments) => {
                            mcprojstore.updateCurrentProject((project) => {
                                project.experiments = _.indexBy(experiments.plain(), 'id');
                                project.experimentsFullyLoaded = true;
                            });
                            return p;
                        }
                    );
                }]
            }
        })
        .state('project.home', {
            url: '/home',
            template: '<mc-project-home></mc-project-home>'
        })
        .state('project.search', {
            url: '/search/:query',
            template: '<mc-project-search></mc-project-search>'
        })
        .state('project.create', {
            url: '/create',
            abstract: true,
            template: '<ui-view flex layout="column"></ui-view>'
        })
        .state('project.experiment', {
            url: '/experiment/:experiment_id',
            template: `<mc-experiment></mc-experiment>`
            //,
            // resolve: {
            //     experiment: ['experimentsAPI', 'toast', 'toUITask', '$stateParams', 'mcstate',
            //         function (experimentsAPI, toast, toUITask, $stateParams, mcstate) {
            //             return experimentsAPI.getForProject($stateParams.project_id, $stateParams.experiment_id)
            //                 .then(
            //                     (e) => {
            //                         e.tasks.forEach((task) => toUITask(task));
            //                         mcstate.set(mcstate.CURRENT$EXPERIMENT, e);
            //                         return e;
            //                     },
            //                     () => toast.error('Failed to retrieve experiment')
            //                 );
            //         }
            //     ]
            // }
        })
        .state('project.experiment.details', {
            url: '/details',
            template: '<mc-experiment-details experiment="$resolve.experiment" show-note="true"></mc-experiment-details>'
        })
        .state('project.experiment.tasks', {
            url: '/tasks',
            template: '<mc-experiment-tasks></mc-experiment-tasks>'
        })
        .state('project.experiment.forecast', {
            url: '/forecast',
            template: '<mc-experiment-forecast experiment="$resolve.experiment"></mc-experiment-forecast>'
        })
        .state('project.experiment.workflow', {
            url: '/processes',
            template: '<mc-processes-workflow processes="$resolve.processes"></mc-processes-workflow>',
            resolve: {
                processes: ['mcprojstore', '$stateParams',
                    (mcprojstore, $stateParams) => {
                        let e = mcprojstore.getExperiment($stateParams.experiment_id);
                        return e.processes;
                    }
                    // experimentsAPI.getProcessesForExperiment($stateParams.project_id, $stateParams.experiment_id)
                ]
            }
        })
        .state('project.experiment.samples', {
            url: '/samples',
            template: '<mc-project-samples samples="$resolve.samples"></mc-project-samples>',
            resolve: {
                samples: ['experimentsAPI', '$stateParams',
                    (experimentsAPI, $stateParams) =>
                        experimentsAPI.getSamplesForExperiment($stateParams.project_id, $stateParams.experiment_id)
                ]
            }
        })
        .state('project.experiment.files', {
            url: '/files',
            template: '<mc-experiment-files files="$resolve.files"></mc-experiment-files>',
            resolve: {
                files: ['experimentsAPI', '$stateParams',
                    (experimentsAPI, $stateParams) =>
                        experimentsAPI.getFilesForExperiment($stateParams.project_id, $stateParams.experiment_id)
                ]
            }
        })
        .state('project.experiment.notes', {
            url: '/notes',
            template: '<mc-experiment-notes experiment="$resolve.experiment"></mc-experiment-notes>'
        })
        .state('project.experiment.publish', {
            url: '/publish',
            template: '<mc-experiment-publish></mc-experiment-publish>'
        })
        .state('project.experiment.datasets', {
            url: '/datasets',
            template: '

',
            abstract: true
        })
        .state('project.experiment.datasets.list', {
            url: '/list',
            template: '<mc-experiment-datasets></mc-experiment-datasets>'
        })
        .state('project.experiment.datasets.dataset', {
            url: '/dataset/:dataset_id',
            template: '<mc-experiment-dataset></mc-experiment-dataset>'
        })
        .state('project.experiment.sample', {
            url: '/sample/:sample_id',
            template: '<mc-show-sample sample-id="ctrl.sampleId"></mc-show-sample>',
            controllerAs: 'ctrl',
            controller: ['$stateParams', function ($stateParams) {
                this.sampleId = $stateParams.sample_id;
            }]
        })
        .state('project.experiments', {
            url: '/experiments',
            template: '<mc-project-experiments experiments="$resolve.experiments"></mc-project-experiments>',
            resolve: {
                experiments: ['experimentsAPI', '$stateParams',
                    (experimentsAPI, $stateParams) =>
                        experimentsAPI.getAllForProject($stateParams.project_id)
                ]
            }
        })
        .state('project.processes', {
            url: '/processes',
            template: '<mc-project-processes processes="$resolve.processes"></mc-project-processes>',
            resolve: {
                processes: ['projectsAPI', '$stateParams',
                    (projectsAPI, $stateParams) =>
                        projectsAPI.getProjectProcesses($stateParams.project_id)
                ]
            }
        })
        .state('project.samples', {
            url: '/samples',
            template: '<mc-project-samples samples="$resolve.samples"></mc-project-samples>',
            resolve: {
                samples: ['samplesAPI', '$stateParams',
                    (samplesAPI, $stateParams) =>
                        samplesAPI.getProjectSamples($stateParams.project_id)
                ]
            }
        })
        .state('project.samples.sample', {
            url: '/sample/:sample_id',
            template: '<mc-sample></mc-sample>'
        })
        .state('project.files', {
            url: '/files',
            template: '<mc-file-tree flex layout-fill></mc-file-tree>'
        })
        .state('project.files.uploads', {
            url: '/uploads',
            template: '<mc-file-uploads reset-files="true"></mc-file-uploads>'
        })
        .state('project.files.file', {
            url: '/file/:file_id',
            template: '<mc-file></mc-file>'
        })
        .state('project.file', {
            url: '/file/:file_id',
            template: '<mc-file></mc-file>'
        })
        .state('project.files.dir', {
            url: '/dir/:dir_id',
            template: '<mc-dir></mc-dir>'
        })
        .state('project.sample', {
            url: '/sample/:sample_id',
            template: '<mc-sample></mc-sample>'
        })
        .state('project.datasets', {
            url: '/datasets',
            abstract: true,
            template: '

'
        })
        .state('project.datasets.list', {
            url: '/list',
            template: '<mc-project-datasets></mc-project-datasets>'
        })
        .state('project.datasets.dataset', {
            url: '/dataset/:dataset_id',
            template: '<mc-dataset-overview dataset="$resolve.dataset"></mc-dataset-overview>',
            resolve: {
                dataset: ['$stateParams', 'datasetsAPI',
                    ($stateParams, datasetsAPI) => datasetsAPI.getDataset('e634ee47-b217-4547-a345-5007cd146dbd', '511930bd-96a5-4678-9626-ef79aceb75b5', '57490e70-df32-4592-8a6f-8a6cfbd36174')
                ]
            }
        })
        .state('project.settings', {
            url: '/settings',
            template: '<mc-project-settings></mc-project-settings>'
        })
        .state('data', {
            url: '/data',
            abstract: true,
            template: '

'
        })
        .state('data.dataset', {
            url: '/dataset/:dataset_id',
            template: '<mc-dataset-overview dataset="$resolve.dataset"></mc-dataset-overview>',
            resolve: {
                dataset: ['publicDatasetsAPI', '$stateParams',
                    (publicDatasetsAPI, $stateParams) => publicDatasetsAPI.getDataset($stateParams.dataset_id)
                ]
            }
        })
        .state('data.home', {
            url: '/home',
            template: '<mc-data-home tags="$resolve.tags"></mc-data-home>',
            resolve: {
                tags: ['publicTagsAPI',
                    (publicTagsAPI) => publicTagsAPI.getPopularTags().then(
                        (tags) => tags.map(t => t.tag)
                    )
                ]
            }
        })
        .state('data.home.recent', {
            url: '/recent',
            template: '<mc-dataset-list datasets="$resolve.datasets" details-route="data.dataset"></mc-dataset-list>',
            resolve: {
                datasets: ['publicDatasetsAPI',
                    (publicDatasetsAPI) => publicDatasetsAPI.getRecent()
                ]
            }
        })
        .state('data.home.top', {
            url: '/top',
            template: '<mc-dataset-list datasets="$resolve.datasets" details-route="data.dataset"></mc-dataset-list>',
            resolve: {
                datasets: ['publicDatasetsAPI',
                    (publicDatasetsAPI) => publicDatasetsAPI.getTopViewed()
                ]
            }
        });

    // $urlRouterProvider.otherwise('/login');
    $urlRouterProvider.otherwise('/data/home/top');
}
<|endoftext|>


<commit_before> angular.module('emission.main.diary.current', ['ui-leaflet',
                                                'ngCordova',
                                                'emission.services',
                                                'ionic',
                                                'emission.incident.posttrip.manual',
                                                'rzModule',
                                                'angularLocalStorage',
                                                'emission.plugin.logger'])

.controller('CurrMapCtrl', function($scope, Config, $state, $timeout, $ionicActionSheet,leafletData,
                                    Logger, $window, PostTripManualMarker, CommHelper, $http, storage, $ionicPlatform) {

  Logger.log("controller CurrMapCtrl called from current.js");
  var _map;
  var _localIncidentMarkers = [];
  var _serverIncidentMarkers = [];
  var db = window.cordova.plugins.BEMUserCache;
  MANUAL_INCIDENT = "manual/incident";
  BACKGROUND_LOCATION = "background/location";
  INCIDENT_CONFIG = 'incident_config';
  $scope.mapCtrl = {};
  var directions = ["N", "NE", "E", "SE", "S", "SW", "W", "NW"];

  $scope.diary = function() {
    console.log('diary', "in diary");
    $state.go("root.main.diary");
  };

  angular.extend($scope.mapCtrl, {
    defaults: {
    }
  });

  angular.extend($scope.mapCtrl.defaults, Config.getMapTiles());
  Logger.log("mapCtrl", $scope.mapCtrl);

  $scope.verticalSlider = {
    options: {
      floor:0,
      ceil: 7,
      vertical: true,
      showTicks: true,
      showSelectionBar: true,
      hideLimitLabels: true,
      translate: function(value) {
          if (value === 1) {
            return "Yesterday";
          } else if (value === 7) {
            return "Week ago";
          }
        return "";
      }
    }
  };

  var incident_value = storage.get(INCIDENT_CONFIG);
  if(incident_value != null) {
    $scope.verticalSlider.value = incident_value;
  } else {
    $scope.verticalSlider.value = 1;
  }

  var fromIncidentDate = moment().subtract($scope.verticalSlider.value, 'd');

  $scope.$watch('verticalSlider.value', function(newVal, oldVal){
    storage.set(INCIDENT_CONFIG, newVal);
    incidentServerCalldata.start_time = CommHelper.moment2Timestamp(moment().subtract(newVal, 'd'));
  }, true);

  var incidentServerCalldata = {
      start_time: CommHelper.moment2Timestamp(fromIncidentDate),
      end_time: CommHelper.moment2Timestamp(moment()),
      sel_region: null
  };

  var startTimeFn = function(ts) {
    var date = new Date(ts*1000);
    var hours = date.getHours();
    var minutes = date.getMinutes();
    var amOrPm = hours < 12 ? 'AM' : 'PM';
    hours = hours % 12;
    hours = hours ? hours : 12;
    minutes = minutes < 10 ? '0'+ minutes : minutes;
    return hours + ':' + minutes + ' ' + amOrPm;
  };

  var getSpeed = function(curr_lglat, last_lglat, curr_ts, last_ts) {
    var curr_latlng = L.latLng(curr_lglat[1],curr_lglat[0]);
    var last_latlng = L.latLng(last_lglat[1],last_lglat[0]);
    var meters = curr_latlng.distanceTo(last_latlng);
    time = moment(curr_ts).diff(moment(last_ts));
    var speed = Math.round(meters / time * 3.6); // mps to kmph
    Logger.log("Current Speed: " + speed);
    return speed;
  };

  var degreeToDirection = function(degree) {
    var index = Math.floor((degree / 45) + 0.5) % 8;
    return directions[index];
  };

  leafletData.getMap('current').then(function(map) {
    _map = map;
    _map.removeControl(_map.zoomControl);
  });

  var refreshTrip = function() {
    db.getAllSensorData(BACKGROUND_LOCATION, true).then(function(result) {
      $scope.$apply(function() {
        Logger.log("current location data" + JSON.stringify(result[0].data));
        var coordinates = result.map(function(locWrapper, index, locList) {
          return [locWrapper.data.longitude, locWrapper.data.latitude];
        });
        var both = [result[0].data.longitude, result[0].data.latitude];
        $scope.startTime = startTimeFn(result[result.length - 1].data.ts);
        var bearing = Math.round(result[0].data.bearing);

        Logger.log("last location data " + JSON.stringify(result[1]));
        if (angular.isDefined(result[1])) {
            var last_both = [result[1].data.longitude, result[1].data.latitude];
            var curr_ts = result[0].data.ts;
            var last_ts = result[1].data.ts;
            if(angular.isDefined(result[0].data.sensed_speed)) {
              $scope.currSpeedInKmh = Math.round(result[0].data.sensed_speed * 3.6);
            } else {
              if(curr_ts !== last_ts){
                $scope.currSpeedInKmh = getSpeed(both, last_both, curr_ts, last_ts);
              }
            }
            $scope.currentDirection = degreeToDirection(bearing);
        } else {
            Logger.log("last location is not defined, returning defaults");
            $scope.currSpeedInKmh = 0;
        }
        angular.extend($scope.mapCtrl, {
          defaults : {
            center: {
              lat: both[1],
              lng: both[0],
              zoom: 15
            }
          },
          markers: {
            hereMarker: {
              lat: both[1],
              lng: both[0],
              icon: {
                iconUrl: 'img/ic_navigation_black_24dp.png',
                iconSize: [40, 40],
                iconAnchor: [20, 20],
                popupAnchor: [0, 0],
                shadowSize: [0, 0],
                shadowAnchor: [0, 0]
              },
              iconAngle: bearing,
            }
          },
          geojson: {
            data: [
              {
                type: "LineString",
                coordinates: coordinates
              },
            ],
          },
        });
      });
    }).catch(function(error) {
        Logger.log("While loading location data, error "+JSON.stringify(error));
        $ionicPopup.alert({"template": "While loading location data, error = "+ JSON.stringify(error)})
    });
    console.log($scope.mapCtrl);
  };

  $scope.$on('leafletDirectiveMap.current.resize', function(event, data) {
        Logger.log("current/map received resize event, invalidating map size");
        data.leafletObject.invalidateSize();
  });

  var addIncidentLayer = function(stress, marker, map) {
    if(stress === 0) {
      marker.setStyle({color: 'green'});
    } else if (stress === 100) {
      marker.setStyle({color: 'red'});
    }
    map.addLayer(marker);
  };

  var addIncidents = function(incidents, map, markerList) {
    incidents.forEach(function(incident) {
        Logger.log("Processing incident "+JSON.stringify(incident));
        if (angular.isDefined(incident) && angular.isDefined(incident.loc)) {
            latlng = {
                lat: incident.loc.coordinates[1],
                lng: incident.loc.coordinates[0]
            };
            Logger.log("Displaying incident report at "+JSON.stringify(latlng)+" on map");
            var marker = L.circleMarker(latlng);
            markerList.push(marker);
            addIncidentLayer(incident.stress, marker, map);
        }
      });
  };

  var removeExistingIncidentMarkers = function(map, markerList) {
    markerList.forEach(function(marker) {
        map.removeLayer(marker);
        var remainingLayers = [];
        map.eachLayer(function(layer) {
            remainingLayers.push(layer);
        });
        Logger.log("After removing marker "+JSON.stringify(marker)+" new list size = "+remainingLayers.length);
    });
  };

  var getLocalIncidents = function() {
    // No metadata, to make it consistent with the server incidents
    db.getAllMessages(MANUAL_INCIDENT, false).then(function(incidents) {
      Logger.log("Incidents stored locally" + JSON.stringify(incidents));
      if(incidents.length > 0) {
        addIncidents(incidents, _map, _localIncidentMarkers);
      }
    });
  };

  var getServerIncidents = function() {
      Logger.log("Getting server incidents with call "+JSON.stringify(incidentServerCalldata));
      $http.post("https://e-mission.eecs.berkeley.edu/result/heatmap/incidents/timestamp", incidentServerCalldata).then(function(res){
          Logger.log("Server incidents result is "+JSON.stringify(res));
          // Need to remove existing markers before adding new ones
          // https://github.com/e-mission/e-mission-phone/pull/263#issuecomment-322669042
          removeExistingIncidentMarkers(_map, _serverIncidentMarkers);
          if(res.data.incidents.length > 0) {
            addIncidents(res.data.incidents, _map, _serverIncidentMarkers);
          }
      }, function(error){
          Logger.log("Error when getting incidents");
          Logger.log(error);
    });
  };

  var marker;
  $scope.showIncidentSheet = function() {
    db.getAllSensorData(BACKGROUND_LOCATION, true).then(function(result) {
            both = [result[0].data.latitude, result[0].data.longitude];
            var ts = result[0].data.ts;
            var latlng = L.latLng(both);
            $scope.features = [];
            marker = L.circleMarker(latlng);
            Logger.log(marker);
            PostTripManualMarker.showSheet($scope.features, latlng, ts, marker, _map);
    })
    .catch(function(error) {
      Logger.log("error while getting map current from leafletData");
    });
  };

  $scope.$watch('features', function(newVal, oldVal){
    if(angular.isDefined(newVal)) {
      if(newVal.length === 1) {
        addIncidentLayer(newVal[0].properties.stress, marker, _map);
      }
    }
  }, true);

  var mapRunning;
  var gettingIncidents;
  var refreshTripLoop = function() {
    refreshTrip();
    mapRunning = setTimeout(refreshTripLoop, 30 * 1000); //refresh every 30 secs
    // on android, we read the location points every 30 secs by default
  };

  var getIncidentsLoop = function() {
    getServerIncidents();
    gettingIncidents = setTimeout(getIncidentsLoop, 5 * 60 * 1000); //refresh 5 minutes
    // refreshing more frequently would put a big load on the server
  };

  $scope.$on('$ionicView.enter', function() {
    Logger.log("entered current screen, starting incident refresh");
    refreshTripLoop();
    getIncidentsLoop();
  });

  $scope.$on('$ionicView.leave', function() {
    Logger.log("exited current screen, stopping incident refresh");
    clearTimeout(mapRunning);
    clearTimeout(gettingIncidents);
  });

  $ionicPlatform.on("resume", function(event) {
    Logger.log("resumed current screen, starting incident refresh");
    refreshTripLoop();
    getIncidentsLoop();
  });

  $ionicPlatform.on("pause", function(event) {
    Logger.log("paused current screen, stopping incident refresh");
    clearTimeout(mapRunning);
    clearTimeout(gettingIncidents);
  });
  getLocalIncidents();

});
<commit_msg>Calculate the speed even if the sensed_speed is zero<commit_after> angular.module('emission.main.diary.current', ['ui-leaflet',
                                                'ngCordova',
                                                'emission.services',
                                                'ionic',
                                                'emission.incident.posttrip.manual',
                                                'rzModule',
                                                'angularLocalStorage',
                                                'emission.plugin.logger'])

.controller('CurrMapCtrl', function($scope, Config, $state, $timeout, $ionicActionSheet,leafletData,
                                    Logger, $window, PostTripManualMarker, CommHelper, $http, storage, $ionicPlatform) {

  Logger.log("controller CurrMapCtrl called from current.js");
  var _map;
  var _localIncidentMarkers = [];
  var _serverIncidentMarkers = [];
  var db = window.cordova.plugins.BEMUserCache;
  MANUAL_INCIDENT = "manual/incident";
  BACKGROUND_LOCATION = "background/location";
  INCIDENT_CONFIG = 'incident_config';
  $scope.mapCtrl = {};
  var directions = ["N", "NE", "E", "SE", "S", "SW", "W", "NW"];

  $scope.diary = function() {
    console.log('diary', "in diary");
    $state.go("root.main.diary");
  };

  angular.extend($scope.mapCtrl, {
    defaults: {
    }
  });

  angular.extend($scope.mapCtrl.defaults, Config.getMapTiles());
  Logger.log("mapCtrl", $scope.mapCtrl);

  $scope.verticalSlider = {
    options: {
      floor:0,
      ceil: 7,
      vertical: true,
      showTicks: true,
      showSelectionBar: true,
      hideLimitLabels: true,
      translate: function(value) {
          if (value === 1) {
            return "Yesterday";
          } else if (value === 7) {
            return "Week ago";
          }
        return "";
      }
    }
  };

  var incident_value = storage.get(INCIDENT_CONFIG);
  if(incident_value != null) {
    $scope.verticalSlider.value = incident_value;
  } else {
    $scope.verticalSlider.value = 1;
  }

  var fromIncidentDate = moment().subtract($scope.verticalSlider.value, 'd');

  $scope.$watch('verticalSlider.value', function(newVal, oldVal){
    storage.set(INCIDENT_CONFIG, newVal);
    incidentServerCalldata.start_time = CommHelper.moment2Timestamp(moment().subtract(newVal, 'd'));
  }, true);

  var incidentServerCalldata = {
      start_time: CommHelper.moment2Timestamp(fromIncidentDate),
      end_time: CommHelper.moment2Timestamp(moment()),
      sel_region: null
  };

  var startTimeFn = function(ts) {
    var date = new Date(ts*1000);
    var hours = date.getHours();
    var minutes = date.getMinutes();
    var amOrPm = hours < 12 ? 'AM' : 'PM';
    hours = hours % 12;
    hours = hours ? hours : 12;
    minutes = minutes < 10 ? '0'+ minutes : minutes;
    return hours + ':' + minutes + ' ' + amOrPm;
  };

  var getSpeed = function(curr_lglat, last_lglat, curr_ts, last_ts) {
    var curr_latlng = L.latLng(curr_lglat[1],curr_lglat[0]);
    var last_latlng = L.latLng(last_lglat[1],last_lglat[0]);
    var meters = curr_latlng.distanceTo(last_latlng);
    time = moment(curr_ts).diff(moment(last_ts));
    var speed = Math.round(meters / time * 3.6); // mps to kmph
    Logger.log("Current Speed: " + speed);
    return speed;
  };

  var degreeToDirection = function(degree) {
    var index = Math.floor((degree / 45) + 0.5) % 8;
    return directions[index];
  };

  leafletData.getMap('current').then(function(map) {
    _map = map;
    _map.removeControl(_map.zoomControl);
  });

  var refreshTrip = function() {
    db.getAllSensorData(BACKGROUND_LOCATION, true).then(function(result) {
      $scope.$apply(function() {
        Logger.log("current location data" + JSON.stringify(result[0].data));
        var coordinates = result.map(function(locWrapper, index, locList) {
          return [locWrapper.data.longitude, locWrapper.data.latitude];
        });
        var both = [result[0].data.longitude, result[0].data.latitude];
        $scope.startTime = startTimeFn(result[result.length - 1].data.ts);
        var bearing = Math.round(result[0].data.bearing);

        Logger.log("last location data " + JSON.stringify(result[1]));
        if (angular.isDefined(result[1])) {
            var last_both = [result[1].data.longitude, result[1].data.latitude];
            var curr_ts = result[0].data.ts;
            var last_ts = result[1].data.ts;
            var last_sensed_speed = result[0].data.sensed_speed;
            if(angular.isDefined(last_sensed_speed) && last_sensed_speed != 0) {
              $scope.currSpeedInKmh = Math.round(result[0].data.sensed_speed * 3.6);
            } else {
              if(curr_ts !== last_ts){
                $scope.currSpeedInKmh = getSpeed(both, last_both, curr_ts, last_ts);
              }
            }
            $scope.currentDirection = degreeToDirection(bearing);
        } else {
            Logger.log("last location is not defined, returning defaults");
            $scope.currSpeedInKmh = 0;
        }
        angular.extend($scope.mapCtrl, {
          defaults : {
            center: {
              lat: both[1],
              lng: both[0],
              zoom: 15
            }
          },
          markers: {
            hereMarker: {
              lat: both[1],
              lng: both[0],
              icon: {
                iconUrl: 'img/ic_navigation_black_24dp.png',
                iconSize: [40, 40],
                iconAnchor: [20, 20],
                popupAnchor: [0, 0],
                shadowSize: [0, 0],
                shadowAnchor: [0, 0]
              },
              iconAngle: bearing,
            }
          },
          geojson: {
            data: [
              {
                type: "LineString",
                coordinates: coordinates
              },
            ],
          },
        });
      });
    }).catch(function(error) {
        Logger.log("While loading location data, error "+JSON.stringify(error));
        $ionicPopup.alert({"template": "While loading location data, error = "+ JSON.stringify(error)})
    });
    console.log($scope.mapCtrl);
  };

  $scope.$on('leafletDirectiveMap.current.resize', function(event, data) {
        Logger.log("current/map received resize event, invalidating map size");
        data.leafletObject.invalidateSize();
  });

  var addIncidentLayer = function(stress, marker, map) {
    if(stress === 0) {
      marker.setStyle({color: 'green'});
    } else if (stress === 100) {
      marker.setStyle({color: 'red'});
    }
    map.addLayer(marker);
  };

  var addIncidents = function(incidents, map, markerList) {
    incidents.forEach(function(incident) {
        Logger.log("Processing incident "+JSON.stringify(incident));
        if (angular.isDefined(incident) && angular.isDefined(incident.loc)) {
            latlng = {
                lat: incident.loc.coordinates[1],
                lng: incident.loc.coordinates[0]
            };
            Logger.log("Displaying incident report at "+JSON.stringify(latlng)+" on map");
            var marker = L.circleMarker(latlng);
            markerList.push(marker);
            addIncidentLayer(incident.stress, marker, map);
        }
      });
  };

  var removeExistingIncidentMarkers = function(map, markerList) {
    markerList.forEach(function(marker) {
        map.removeLayer(marker);
        var remainingLayers = [];
        map.eachLayer(function(layer) {
            remainingLayers.push(layer);
        });
        Logger.log("After removing marker "+JSON.stringify(marker)+" new list size = "+remainingLayers.length);
    });
  };

  var getLocalIncidents = function() {
    // No metadata, to make it consistent with the server incidents
    db.getAllMessages(MANUAL_INCIDENT, false).then(function(incidents) {
      Logger.log("Incidents stored locally" + JSON.stringify(incidents));
      if(incidents.length > 0) {
        addIncidents(incidents, _map, _localIncidentMarkers);
      }
    });
  };

  var getServerIncidents = function() {
      Logger.log("Getting server incidents with call "+JSON.stringify(incidentServerCalldata));
      $http.post("https://e-mission.eecs.berkeley.edu/result/heatmap/incidents/timestamp", incidentServerCalldata).then(function(res){
          Logger.log("Server incidents result is "+JSON.stringify(res));
          // Need to remove existing markers before adding new ones
          // https://github.com/e-mission/e-mission-phone/pull/263#issuecomment-322669042
          removeExistingIncidentMarkers(_map, _serverIncidentMarkers);
          _serverIncidentMarkers = [];
          if(res.data.incidents.length > 0) {
            addIncidents(res.data.incidents, _map, _serverIncidentMarkers);
          }
      }, function(error){
          Logger.log("Error when getting incidents");
          Logger.log(error);
    });
  };

  var marker;
  $scope.showIncidentSheet = function() {
    db.getAllSensorData(BACKGROUND_LOCATION, true).then(function(result) {
            both = [result[0].data.latitude, result[0].data.longitude];
            var ts = result[0].data.ts;
            var latlng = L.latLng(both);
            $scope.features = [];
            marker = L.circleMarker(latlng);
            Logger.log(marker);
            PostTripManualMarker.showSheet($scope.features, latlng, ts, marker, _map);
    })
    .catch(function(error) {
      Logger.log("error while getting map current from leafletData");
    });
  };

  $scope.$watch('features', function(newVal, oldVal){
    if(angular.isDefined(newVal)) {
      if(newVal.length === 1) {
        addIncidentLayer(newVal[0].properties.stress, marker, _map);
      }
    }
  }, true);

  var mapRunning;
  var gettingIncidents;
  var refreshTripLoop = function() {
    refreshTrip();
    mapRunning = setTimeout(refreshTripLoop, 30 * 1000); //refresh every 30 secs
    // on android, we read the location points every 30 secs by default
  };

  var getIncidentsLoop = function() {
    getServerIncidents();
    gettingIncidents = setTimeout(getIncidentsLoop, 5 * 60 * 1000); //refresh 5 minutes
    // refreshing more frequently would put a big load on the server
  };

  $scope.$on('$ionicView.enter', function() {
    Logger.log("entered current screen, starting incident refresh");
    refreshTripLoop();
    getIncidentsLoop();
  });

  $scope.$on('$ionicView.leave', function() {
    Logger.log("exited current screen, stopping incident refresh");
    clearTimeout(mapRunning);
    clearTimeout(gettingIncidents);
  });

  $ionicPlatform.on("resume", function(event) {
    Logger.log("resumed current screen, starting incident refresh");
    refreshTripLoop();
    getIncidentsLoop();
  });

  $ionicPlatform.on("pause", function(event) {
    Logger.log("paused current screen, stopping incident refresh");
    clearTimeout(mapRunning);
    clearTimeout(gettingIncidents);
  });
  getLocalIncidents();

});
<|endoftext|>


<commit_before>function(args) {
/*
is_app(true)
control_type("VB")
display_name("REST API call control")
description("This will return the REST APIn call control")
base_component_id("rest_control")
load_once_from_file(true)
visibility("PRIVATE")
read_only(true)
properties(
    [
        {
            id:         "text",
            name:       "Dev text",
            default:    "REST API Call",
            type:       "String"
        }
        ,
        {
            id:         "width",
            name:       "Width",
            default:    140,
            type:       "Number"
        }
        ,
        {
            id:         "height",
            name:       "Height",
            default:    40,
            type:       "Number"
        }
        ,
        {
            id:         "callRestApi",
            pre_snippet:    `await `,
            snippet:    `callRestApi("http://INSERT_URL_HERE")`,
            name:       "Execute Command",
            type:       "Action"
        }
        ,
        {
            id:         "URL",
            name:       "URL",
            default:    "https://raw.githubusercontent.com/typicode/demo/master/db.json",
            type:       "String"
        }

    ]
)//properties
logo_url("/driver_icons/rest.png")
*/

    Vue.component("rest_control",{

        props: ["meta", "args","design_mode","refresh"]

        ,

        template:

`

        {{args.text}}

            <slot v-bind:refresh='refresh'>
            </slot>

`

        ,

        data: function() {
            return {
            }
        }

        ,

        mounted: async function() {
            registerComponent(this)

        }
        ,

        methods: {
            callRestApiInternal: async function() {
                var mm = this

                var result = await callFunction(
                {
                    driver_name: "rest_call_service",
                    method_name: "rest_call_service"
                }
                ,
                {
                    URL:    mm.args.URL
                })

                if (result) {
                    return result
                }
                return null
            }
            ,

            callRestApi: async function(urlToCall) {

                var mm = this
                if (urlToCall) {
                    mm.args.URL = urlToCall
                }
                var qwe = await this.callRestApiInternal()
                return qwe
            }

        }

    })
}
<commit_msg>Can call the default API on a REST control<commit_after>function(args) {
/*
is_app(true)
control_type("VB")
display_name("REST API call control")
description("This will return the REST APIn call control")
base_component_id("rest_control")
load_once_from_file(true)
visibility("PRIVATE")
read_only(true)
properties(
    [
        {
            id:         "text",
            name:       "Dev text",
            default:    "REST API Call",
            type:       "String"
        }
        ,
        {
            id:         "width",
            name:       "Width",
            default:    140,
            type:       "Number"
        }
        ,
        {
            id:         "height",
            name:       "Height",
            default:    40,
            type:       "Number"
        }
        ,
        {
            id:             "callDefaultRestApi",
            pre_snippet:    `await `,
            snippet:        `callDefaultRestApi()`,
            name:           "Execute Command",
            type:           "Action"
        }
        ,
        {
            id:         "callRestApi",
            pre_snippet:    `await `,
            snippet:    `callRestApi("http://INSERT_URL_HERE")`,
            name:       "Execute Command",
            type:       "Action"
        }
        ,
        {
            id:         "URL",
            name:       "URL",
            default:    "https://raw.githubusercontent.com/typicode/demo/master/db.json",
            type:       "String"
        }

    ]
)//properties
logo_url("/driver_icons/rest.png")
*/

    Vue.component("rest_control",{

        props: ["meta", "args","design_mode","refresh"]

        ,

        template:

`

        {{args.text}}

            <slot v-bind:refresh='refresh'>
            </slot>

`

        ,

        data: function() {
            return {
            }
        }

        ,

        mounted: async function() {
            registerComponent(this)

        }
        ,

        methods: {
            callRestApiInternal: async function() {
                var mm = this

                var result = await callFunction(
                {
                    driver_name: "rest_call_service",
                    method_name: "rest_call_service"
                }
                ,
                {
                    URL:    mm.args.URL
                })

                if (result) {
                    return result
                }
                return null
            }
            ,

            callDefaultRestApi: async function() {

                var qwe = await this.callRestApiInternal()
                return qwe
            }
            ,

            callRestApi: async function(urlToCall) {

                var mm = this
                if (urlToCall) {
                    mm.args.URL = urlToCall
                }
                var qwe = await this.callRestApiInternal()
                return qwe
            }

        }

    })
}
<|endoftext|>


<commit_before>const Molotov = require('../../lib/molotov');
const { MolotovError } = require('../../lib/molotovError');

const molotovConfig = {
  testMolotovImplementer: {
    supersNameSpace: {
      testSuper: 'testSuper'
    },
    molotovPlugins: {
      testSuper: {
        onlyPluginOne: [
          'pluginOne',
        ],
        pluginAll: [
          'pluginOne',
          'pluginTwo',
          'pluginThree',
        ],
        pluginOneTwo: [
          'pluginOne',
          'pluginTwo',
        ],
      },
    },
  },
};

const configOverrides = {
  testMolotovImplementer: {
    molotovPlugins: {
      testSuper: {
        pluginAll: [
          'pluginOne',
          'pluginTwo',
        ],
        pluginOneThree: [
          'pluginOne',
          'pluginThree',
        ],
      },
    },
  },
};

const mixins = require('./../helpers/mixins');
const supers = require('./../helpers/supers');
const cocktailClass = require('./../helpers/cocktailHelper');

let tmpMocks = [];

describe('Molotov Basic tests', () => {
  beforeEach(() => {
    tmpMocks.forEach(mock => mock.mockRestore());
    tmpMocks = [];
    jest.resetAllMocks();
  });

  afterAll(() => {
    jest.restoreAllMocks();
  });

  test('Molotov constructor', () => {
    expect.assertions(7);
    const molotov = new Molotov(molotovConfig, 'testMolotovImplementer', supers, mixins, configOverrides, [cocktailClass]);
    molotov.setPlugins({ plugins: 'yay' });
    expect(molotov.getNameSpace()).toEqual('testMolotovImplementer');
    expect(molotov.getMixins()).toMatchSnapshot();
    expect(molotov.getMolotovConfig()).toMatchSnapshot();
    expect(molotov.getPlugins()).toEqual({ plugins: 'yay' });
    expect(molotov.getSupers()).toMatchSnapshot();
    expect(molotov.getConfigOverrides()).toMatchSnapshot();
    expect(molotov.getCocktails()).toMatchSnapshot();
  });
});

describe('Molotov Constructor Errors', () => {
  beforeEach(() => {
    tmpMocks.forEach(mock => mock.mockRestore());
    tmpMocks = [];
    jest.resetAllMocks();
  });

  afterAll(() => {
    jest.restoreAllMocks();
  });

  test('Bad config', () => {
    expect.assertions(1);
    expect(() => new Molotov(null, 'testMolotovImplementer', supers, mixins, configOverrides, [cocktailClass])).toThrowError(MolotovError);
  });
  test('Config must not be string', () => {
    expect.assertions(1);
    expect(() => new Molotov('string', 'testMolotovImplementer', supers, mixins, configOverrides, [cocktailClass])).toThrowError(MolotovError);
  });
  test('Supers must be an object', () => {
    expect.assertions(1);
    expect(() => new Molotov(molotovConfig, 'testMolotovImplementer', 'supers', mixins, configOverrides, [cocktailClass])).toThrowError(MolotovError);
  });
  test('Mixins must have super keys', () => {
    expect.assertions(1);
    expect(() => new Molotov(molotovConfig, 'testMolotovImplementer', supers, {}, configOverrides, [cocktailClass])).toThrowError(MolotovError);
  });
  test('Mixins must be objects', () => {
    expect.assertions(1);
    expect(() => new Molotov(molotovConfig, 'testMolotovImplementer', supers, 'mixins', configOverrides, [cocktailClass])).toThrowError(MolotovError);
  });
  test('ConfigOverrides must be objects', () => {
    expect.assertions(1);
    expect(() => new Molotov(molotovConfig, 'testMolotovImplementer', supers, mixins, 'configOverrides', [cocktailClass])).toThrowError(MolotovError);
  });
  test('CocktailArray must be array', () => {
    expect.assertions(1);
    expect(() => new Molotov(molotovConfig, 'testMolotovImplementer', supers, mixins, configOverrides, 'cocktail')).toThrowError(MolotovError);
  });
  test('Bad Molotov config throws an error', () => {
    expect.assertions(1);
    expect(() => new Molotov({nob: 'nope'}, 'testMolotovImplementer', supers, mixins, configOverrides, 'cocktail')).toThrowError(MolotovError);
  });
});

describe('Molotov advanced', () => {
  beforeEach(() => {
    tmpMocks.forEach(mock => mock.mockRestore());
    tmpMocks = [];
    jest.resetAllMocks();
  });

  afterAll(() => {
    jest.restoreAllMocks();
  });

  test('Molotov Mix Supers', () => {
    expect.assertions(1);
    const molotov = new Molotov(molotovConfig, 'testMolotovImplementer', supers, mixins, configOverrides, [cocktailClass]);
    expect(molotov.mixSupers()).toMatchSnapshot();
  });

  test('Molotov Mix Supers', () => {
    expect.assertions(1);
    const molotov = new Molotov(molotovConfig, 'testMolotovImplementer', supers, mixins, configOverrides, [cocktailClass]);
    expect(molotov.getMolotov()).toMatchSnapshot();
  });
});

describe('Molotov no overrides no cocktails', () => {
  beforeEach(() => {
    tmpMocks.forEach(mock => mock.mockRestore());
    tmpMocks = [];
    jest.resetAllMocks();
  });

  afterAll(() => {
    jest.restoreAllMocks();
  });

  test('Molotov constructor', () => {
    expect.assertions(7);
    const molotov = new Molotov(molotovConfig, 'testMolotovImplementer', supers, mixins);
    molotov.setPlugins({ plugins: 'yay' });
    expect(molotov.getNameSpace()).toEqual('testMolotovImplementer');
    expect(molotov.getMixins()).toMatchSnapshot();
    expect(molotov.getSupers()).toMatchSnapshot();
    expect(molotov.getMolotov()).toMatchSnapshot();
  });
});
<commit_msg>fix(tests): Set correct number of assertions on no overrides no config test.<commit_after>const Molotov = require('../../lib/molotov');
const { MolotovError } = require('../../lib/molotovError');

const molotovConfig = {
  testMolotovImplementer: {
    supersNameSpace: {
      testSuper: 'testSuper'
    },
    molotovPlugins: {
      testSuper: {
        onlyPluginOne: [
          'pluginOne',
        ],
        pluginAll: [
          'pluginOne',
          'pluginTwo',
          'pluginThree',
        ],
        pluginOneTwo: [
          'pluginOne',
          'pluginTwo',
        ],
      },
    },
  },
};

const configOverrides = {
  testMolotovImplementer: {
    molotovPlugins: {
      testSuper: {
        pluginAll: [
          'pluginOne',
          'pluginTwo',
        ],
        pluginOneThree: [
          'pluginOne',
          'pluginThree',
        ],
      },
    },
  },
};

const mixins = require('./../helpers/mixins');
const supers = require('./../helpers/supers');
const cocktailClass = require('./../helpers/cocktailHelper');

let tmpMocks = [];

describe('Molotov Basic tests', () => {
  beforeEach(() => {
    tmpMocks.forEach(mock => mock.mockRestore());
    tmpMocks = [];
    jest.resetAllMocks();
  });

  afterAll(() => {
    jest.restoreAllMocks();
  });

  test('Molotov constructor', () => {
    expect.assertions(7);
    const molotov = new Molotov(molotovConfig, 'testMolotovImplementer', supers, mixins, configOverrides, [cocktailClass]);
    molotov.setPlugins({ plugins: 'yay' });
    expect(molotov.getNameSpace()).toEqual('testMolotovImplementer');
    expect(molotov.getMixins()).toMatchSnapshot();
    expect(molotov.getMolotovConfig()).toMatchSnapshot();
    expect(molotov.getPlugins()).toEqual({ plugins: 'yay' });
    expect(molotov.getSupers()).toMatchSnapshot();
    expect(molotov.getConfigOverrides()).toMatchSnapshot();
    expect(molotov.getCocktails()).toMatchSnapshot();
  });
});

describe('Molotov Constructor Errors', () => {
  beforeEach(() => {
    tmpMocks.forEach(mock => mock.mockRestore());
    tmpMocks = [];
    jest.resetAllMocks();
  });

  afterAll(() => {
    jest.restoreAllMocks();
  });

  test('Bad config', () => {
    expect.assertions(1);
    expect(() => new Molotov(null, 'testMolotovImplementer', supers, mixins, configOverrides, [cocktailClass])).toThrowError(MolotovError);
  });
  test('Config must not be string', () => {
    expect.assertions(1);
    expect(() => new Molotov('string', 'testMolotovImplementer', supers, mixins, configOverrides, [cocktailClass])).toThrowError(MolotovError);
  });
  test('Supers must be an object', () => {
    expect.assertions(1);
    expect(() => new Molotov(molotovConfig, 'testMolotovImplementer', 'supers', mixins, configOverrides, [cocktailClass])).toThrowError(MolotovError);
  });
  test('Mixins must have super keys', () => {
    expect.assertions(1);
    expect(() => new Molotov(molotovConfig, 'testMolotovImplementer', supers, {}, configOverrides, [cocktailClass])).toThrowError(MolotovError);
  });
  test('Mixins must be objects', () => {
    expect.assertions(1);
    expect(() => new Molotov(molotovConfig, 'testMolotovImplementer', supers, 'mixins', configOverrides, [cocktailClass])).toThrowError(MolotovError);
  });
  test('ConfigOverrides must be objects', () => {
    expect.assertions(1);
    expect(() => new Molotov(molotovConfig, 'testMolotovImplementer', supers, mixins, 'configOverrides', [cocktailClass])).toThrowError(MolotovError);
  });
  test('CocktailArray must be array', () => {
    expect.assertions(1);
    expect(() => new Molotov(molotovConfig, 'testMolotovImplementer', supers, mixins, configOverrides, 'cocktail')).toThrowError(MolotovError);
  });
  test('Bad Molotov config throws an error', () => {
    expect.assertions(1);
    expect(() => new Molotov({nob: 'nope'}, 'testMolotovImplementer', supers, mixins, configOverrides, 'cocktail')).toThrowError(MolotovError);
  });
});

describe('Molotov advanced', () => {
  beforeEach(() => {
    tmpMocks.forEach(mock => mock.mockRestore());
    tmpMocks = [];
    jest.resetAllMocks();
  });

  afterAll(() => {
    jest.restoreAllMocks();
  });

  test('Molotov Mix Supers', () => {
    expect.assertions(1);
    const molotov = new Molotov(molotovConfig, 'testMolotovImplementer', supers, mixins, configOverrides, [cocktailClass]);
    expect(molotov.mixSupers()).toMatchSnapshot();
  });

  test('Molotov Mix Supers', () => {
    expect.assertions(1);
    const molotov = new Molotov(molotovConfig, 'testMolotovImplementer', supers, mixins, configOverrides, [cocktailClass]);
    expect(molotov.getMolotov()).toMatchSnapshot();
  });
});

describe('Molotov no overrides no cocktails', () => {
  beforeEach(() => {
    tmpMocks.forEach(mock => mock.mockRestore());
    tmpMocks = [];
    jest.resetAllMocks();
  });

  afterAll(() => {
    jest.restoreAllMocks();
  });

  test('Molotov constructor', () => {
    expect.assertions(4);
    const molotov = new Molotov(molotovConfig, 'testMolotovImplementer', supers, mixins);
    molotov.setPlugins({ plugins: 'yay' });
    expect(molotov.getNameSpace()).toEqual('testMolotovImplementer');
    expect(molotov.getMixins()).toMatchSnapshot();
    expect(molotov.getSupers()).toMatchSnapshot();
    expect(molotov.getMolotov()).toMatchSnapshot();
  });
});
<|endoftext|>


<commit_before>/**
 * Parted (https://github.com/chjj/parted)
 * A streaming multipart state parser.
 * Copyright (c) 2011, Christopher Jeffrey. (MIT Licensed)
 */

var fs = require('fs')
  , path = require('path')
  , EventEmitter = require('events').EventEmitter
  , StringDecoder = require('string_decoder').StringDecoder;

var DASH = '-'.charCodeAt(0)
  , CR = '\r'.charCodeAt(0)
  , LF = '\n'.charCodeAt(0)
  , COLON = ':'.charCodeAt(0)
  , SPACE = ' '.charCodeAt(0);

/**
 * Parted
 */

var parted = function(type, options) {
  if (!(this instanceof parted)) {
    return new parted(type, options);
  }

  EventEmitter.call(this);

  this.writable = true;
  this.readable = true;

  this.options = options || {};

  var key = grab(type, 'boundary');
  if (!key) {
    return this._error('No boundary key found.');
  }

  this.key = new Buffer('\r\n--' + key);

  this.state = 'start';
  this.pending = 0;
  this.written = 0;
  this.buff = new Buffer(200);

  this.preamble = true;
  this.epilogue = false;

  this._reset();

  this.on('header', this._handleDisposition);
};

parted.prototype.__proto__ = EventEmitter.prototype;

/**
 * Parsing
 */

parted.prototype.write = function(data) {
  if (!this.writable
      || this.epilogue) return;

  try {
    this._parse(data);
  } catch(e) {
    this._error(e);
  }

  return true;
};

parted.prototype.end = function(data) {
  if (!this.writable) return;

  this.writable = false;
  this.readable = false;

  if (data) this.write(data);

  if (!this.epilogue) {
    return this._error('Message underflow.');
  }

  if (!this.pending) this.emit('end');

  return true;
};

parted.prototype._parse = function(data) {
  var i = 0
    , len = data.length
    , buff = this.buff
    , key = this.key
    , ch
    , val;

  for (; i < len; i++) {
    if (this.pos >= 200) {
      return this._error('Potential buffer overflow.');
    }

    ch = data[i];

    switch (this.state) {
      case 'start':
        switch (ch) {
          case DASH:
            this.pos = 3;
            this.state = 'key';
            break;
          default:
            break;
        }
        break;
      case 'key':
        if (this.pos === key.length) {
          this.state = 'key_end';
          i--;
        } else if (ch !== key[this.pos]) {
          if (this.preamble) {
            this.state = 'start';
          } else {
            this.state = 'body';
            val = this.pos - i;
            if (val > 0) {
              this._write(key.slice(0, val));
            }
            i--;
          }
        } else {
          this.pos++;
        }
        break;
      case 'key_end':
        switch (ch) {
          case CR:
            this.state = 'key_line_end';
            break;
          case DASH:
            this.state = 'key_dash_end';
            break;
          default:
            return this._error('Parse error 1.');
        }
        break;
      case 'key_line_end':
        switch (ch) {
          case LF:
            if (this.preamble) {
              this.preamble = false;
            } else {
              this._finish();
            }
            this.state = 'header_name';
            this.pos = 0;
            break;
          default:
            return this._error('Parse error 2.');
        }
        break;
      case 'key_dash_end':
        switch (ch) {
          case DASH:
            this._finish();
            this.epilogue = true;
            return;
          default:
            return this._error('Parse error 3.');
        }
        break;
      case 'header_name':
        switch (ch) {
          case COLON:
            val = buff.slice(0, this.pos);
            this.header = val.toString('ascii');
            this.pos = 0;
            this.state = 'header_val';
            break;
          default:
            buff[this.pos++] = ch | 32;
            break;
        }
        break;
      case 'header_val':
        switch (ch) {
          case CR:
            this.state = 'header_val_end';
            break;
          case SPACE:
            if (this.pos === 0) {
              break;
            }
            ; // FALL-THROUGH
          default:
            buff[this.pos++] = ch;
            break;
        }
        break;
      case 'header_val_end':
        switch (ch) {
          case LF:
            val = buff.slice(0, this.pos).toString('ascii');
            this.emit('header', this.header, val);
            this.pos = 0;
            this.state = 'header_end';
            break;
          default:
            return this._error('Parse error 4.');
        }
        break;
      case 'header_end':
        switch (ch) {
          case CR:
            this.state = 'head_end';
            break;
          default:
            this.state = 'header_name';
            i--;
            break;
        }
        break;
      case 'head_end':
        switch (ch) {
          case LF:
            this.state = 'body';
            i++;
            if (i >= len) return;
            data = data.slice(i);
            i = 0;
            len = data.length;
            break;
          default:
            return this._error('Parse error 5.');
        }
        break;
      case 'body':
        switch (ch) {
          case CR:
            if (i > 0) {
              this._write(data.slice(0, i));
            }
            this.pos = 1;
            this.state = 'key';
            data = data.slice(i);
            i = 0;
            len = data.length;
            break;
          default:
            break;
        }
        break;
    }
  }

  if (this.state === 'body') {
    this._write(data);
  }
};

parted.prototype._handleDisposition = function(name, val) {
  if (name !== 'content-disposition') return;

  this.field = grab(val, 'name');
  this.file = grab(val, 'filename');

  if (this.file) {
    this.data = stream(this.file, this.options.path);
  } else {
    this.data = '';
  }
};

parted.prototype._write = function(data) {
  if (this.data == null) {
    return this._error('No disposition.');
  }

  if (this.file) {
    this.data.write(data);
  } else {
    this.data += this.decode.write(data);
  }

  this.written += data.length;
  this.emit('data', data.length);
};

parted.prototype._reset = function() {
  this.decode = new StringDecoder('utf8');
  this.pos = 0;
  this.field = null;
  this.data = null;
  this.file = null;
  this.header = null;
};

parted.prototype._error = function(err) {
  this.destroy();
  this.emit('error', new Error(err + ''));
};

parted.prototype.destroy = function(err) {
  this.writable = false;
  this.readable = false;
  this._reset();
};

parted.prototype._finish = function() {
  var self = this
    , field = this.field
    , data = this.data
    , part;

  this.pending++;

  if (data.path) {
    part = data.path;
    data.end(next);
  } else {
    part = data;
    next();
  }

  this._reset();

  function next() {
    self.pending--;

    self.emit('part', field, part);

    if (self.epilogue && !self.pending) {
      self.emit('end');
    }
  }
};

/**
 * Uploads
 */

parted.root = '/tmp';

/**
 * Middleware
 */

parted.middleware = function(options) {
  options = options || {};
  options.limit = options.limit || Infinity;
  return function(req, res, next) {
    if (req.method === 'GET'
        || req.method === 'HEAD'
        || req.body) return next();

    var type = req.headers['content-type'];

    if (type && type.indexOf('multipart/form-data') === 0) {
      var parser = new parted(type, options)
        , parts = {};

      parser.on('error', function(err) {
        req.destroy();
        next(err);
      });

      parser.on('part', function(field, part) {
        parts[field] = part;
      });

      parser.on('data', function(bytes) {
        if (this.written > options.limit) {
          this.emit('error', new Error('Overflow.'));
          this.destroy();
        }
      });

      parser.on('end', next);

      req.body = parts;
      req.pipe(parser);
    } else {
      next();
    }
  };
};

/**
 * Helpers
 */

var stream = function(name, dir) {
  var ext = path.extname(name) || ''
    , name = path.basename(name, ext) || ''
    , dir = dir || parted.root;

  name = Date.now() + '_' + name.substring(0, 10);
  name = path.join(dir, name) + ext.substring(0, 6);
  name = name.replace(/\0/g, '');

  return fs.createWriteStream(name);
};

var grab = function(str, name) {
  if (!str) return;

  var rx = new RegExp(name + '\\s*=\\s*([^;,]+)', 'i')
    , cap = rx.exec(str);

  if (cap) {
    return cap[1].trim().replace(/^['"]|['"]$/g, '');
  }
};

/**
 * Expose
 */

module.exports = parted;
<commit_msg>error messages<commit_after>/**
 * Parted (https://github.com/chjj/parted)
 * A streaming multipart state parser.
 * Copyright (c) 2011, Christopher Jeffrey. (MIT Licensed)
 */

var fs = require('fs')
  , path = require('path')
  , EventEmitter = require('events').EventEmitter
  , StringDecoder = require('string_decoder').StringDecoder;

var DASH = '-'.charCodeAt(0)
  , CR = '\r'.charCodeAt(0)
  , LF = '\n'.charCodeAt(0)
  , COLON = ':'.charCodeAt(0)
  , SPACE = ' '.charCodeAt(0);

/**
 * Parted
 */

var parted = function(type, options) {
  if (!(this instanceof parted)) {
    return new parted(type, options);
  }

  EventEmitter.call(this);

  this.writable = true;
  this.readable = true;

  this.options = options || {};

  var key = grab(type, 'boundary');
  if (!key) {
    return this._error('No boundary key found.');
  }

  this.key = new Buffer('\r\n--' + key);

  this.state = 'start';
  this.pending = 0;
  this.written = 0;
  this.buff = new Buffer(200);

  this.preamble = true;
  this.epilogue = false;

  this._reset();

  this.on('header', this._handleDisposition);
};

parted.prototype.__proto__ = EventEmitter.prototype;

/**
 * Parsing
 */

parted.prototype.write = function(data) {
  if (!this.writable
      || this.epilogue) return;

  try {
    this._parse(data);
  } catch(e) {
    this._error(e);
  }

  return true;
};

parted.prototype.end = function(data) {
  if (!this.writable) return;

  this.writable = false;
  this.readable = false;

  if (data) this.write(data);

  if (!this.epilogue) {
    return this._error('Message underflow.');
  }

  if (!this.pending) this.emit('end');

  return true;
};

parted.prototype._parse = function(data) {
  var i = 0
    , len = data.length
    , buff = this.buff
    , key = this.key
    , ch
    , val;

  for (; i < len; i++) {
    if (this.pos >= 200) {
      return this._error('Potential buffer overflow.');
    }

    ch = data[i];

    switch (this.state) {
      case 'start':
        switch (ch) {
          case DASH:
            this.pos = 3;
            this.state = 'key';
            break;
          default:
            break;
        }
        break;
      case 'key':
        if (this.pos === key.length) {
          this.state = 'key_end';
          i--;
        } else if (ch !== key[this.pos]) {
          if (this.preamble) {
            this.state = 'start';
          } else {
            this.state = 'body';
            val = this.pos - i;
            if (val > 0) {
              this._write(key.slice(0, val));
            }
            i--;
          }
        } else {
          this.pos++;
        }
        break;
      case 'key_end':
        switch (ch) {
          case CR:
            this.state = 'key_line_end';
            break;
          case DASH:
            this.state = 'key_dash_end';
            break;
          default:
            return this._error('Expected CR or DASH.');
        }
        break;
      case 'key_line_end':
        switch (ch) {
          case LF:
            if (this.preamble) {
              this.preamble = false;
            } else {
              this._finish();
            }
            this.state = 'header_name';
            this.pos = 0;
            break;
          default:
            return this._error('Expected CR.');
        }
        break;
      case 'key_dash_end':
        switch (ch) {
          case DASH:
            this._finish();
            this.epilogue = true;
            return;
          default:
            return this._error('Expected DASH.');
        }
        break;
      case 'header_name':
        switch (ch) {
          case COLON:
            val = buff.slice(0, this.pos);
            this.header = val.toString('ascii');
            this.pos = 0;
            this.state = 'header_val';
            break;
          default:
            buff[this.pos++] = ch | 32;
            break;
        }
        break;
      case 'header_val':
        switch (ch) {
          case CR:
            this.state = 'header_val_end';
            break;
          case SPACE:
            if (this.pos === 0) {
              break;
            }
            ; // FALL-THROUGH
          default:
            buff[this.pos++] = ch;
            break;
        }
        break;
      case 'header_val_end':
        switch (ch) {
          case LF:
            val = buff.slice(0, this.pos).toString('ascii');
            this.emit('header', this.header, val);
            this.pos = 0;
            this.state = 'header_end';
            break;
          default:
            return this._error('Expected LF.');
        }
        break;
      case 'header_end':
        switch (ch) {
          case CR:
            this.state = 'head_end';
            break;
          default:
            this.state = 'header_name';
            i--;
            break;
        }
        break;
      case 'head_end':
        switch (ch) {
          case LF:
            this.state = 'body';
            i++;
            if (i >= len) return;
            data = data.slice(i);
            i = 0;
            len = data.length;
            break;
          default:
            return this._error('Expected LF.');
        }
        break;
      case 'body':
        switch (ch) {
          case CR:
            if (i > 0) {
              this._write(data.slice(0, i));
            }
            this.pos = 1;
            this.state = 'key';
            data = data.slice(i);
            i = 0;
            len = data.length;
            break;
          default:
            break;
        }
        break;
    }
  }

  if (this.state === 'body') {
    this._write(data);
  }
};

parted.prototype._handleDisposition = function(name, val) {
  if (name !== 'content-disposition') return;

  this.field = grab(val, 'name');
  this.file = grab(val, 'filename');

  if (this.file) {
    this.data = stream(this.file, this.options.path);
  } else {
    this.data = '';
  }
};

parted.prototype._write = function(data) {
  if (this.data == null) {
    return this._error('No disposition.');
  }

  if (this.file) {
    this.data.write(data);
  } else {
    this.data += this.decode.write(data);
  }

  this.written += data.length;
  this.emit('data', data.length);
};

parted.prototype._reset = function() {
  this.decode = new StringDecoder('utf8');
  this.pos = 0;
  this.field = null;
  this.data = null;
  this.file = null;
  this.header = null;
};

parted.prototype._error = function(err) {
  this.destroy();
  this.emit('error', new Error(err + ''));
};

parted.prototype.destroy = function(err) {
  this.writable = false;
  this.readable = false;
  this._reset();
};

parted.prototype._finish = function() {
  var self = this
    , field = this.field
    , data = this.data
    , part;

  this.pending++;

  if (data.path) {
    part = data.path;
    data.end(next);
  } else {
    part = data;
    next();
  }

  this._reset();

  function next() {
    self.pending--;

    self.emit('part', field, part);

    if (self.epilogue && !self.pending) {
      self.emit('end');
    }
  }
};

/**
 * Uploads
 */

parted.root = '/tmp';

/**
 * Middleware
 */

parted.middleware = function(options) {
  options = options || {};
  options.limit = options.limit || Infinity;
  return function(req, res, next) {
    if (req.method === 'GET'
        || req.method === 'HEAD'
        || req.body) return next();

    var type = req.headers['content-type'];

    if (type && type.indexOf('multipart/form-data') === 0) {
      var parser = new parted(type, options)
        , parts = {};

      parser.on('error', function(err) {
        req.destroy();
        next(err);
      });

      parser.on('part', function(field, part) {
        parts[field] = part;
      });

      parser.on('data', function(bytes) {
        if (this.written > options.limit) {
          this.emit('error', new Error('Overflow.'));
          this.destroy();
        }
      });

      parser.on('end', next);

      req.body = parts;
      req.pipe(parser);
    } else {
      next();
    }
  };
};

/**
 * Helpers
 */

var stream = function(name, dir) {
  var ext = path.extname(name) || ''
    , name = path.basename(name, ext) || ''
    , dir = dir || parted.root;

  name = Date.now() + '_' + name.substring(0, 10);
  name = path.join(dir, name) + ext.substring(0, 6);
  name = name.replace(/\0/g, '');

  return fs.createWriteStream(name);
};

var grab = function(str, name) {
  if (!str) return;

  var rx = new RegExp(name + '\\s*=\\s*([^;,]+)', 'i')
    , cap = rx.exec(str);

  if (cap) {
    return cap[1].trim().replace(/^['"]|['"]$/g, '');
  }
};

/**
 * Expose
 */

module.exports = parted;
<|endoftext|>


<commit_before>//
// weightedRandomSelector.js
//
// simple weighted random selector.
//
// Fri, 26 Jul 2013  11:14
//

function WeightedRandomSelector(a) {
  // A must be an array of arrays. Each inner array is 2 elements,
  // with the item value as the first element and the weight for
  // that value as the second. The items need not be in any
  // particular order.  eg,
  // var fish = [
  //   //["name",      weight]
  //   ["Shark",      3],
  //   ["Shrimp",     50],
  //   ["Sardine",    10],
  //   ["Herring",    20],
  //   ["Anchovies",  10],
  //   ["Mackerel",   50],
  //   ["Tuna",       8]
  // ];

  var i, L;
  this.totalWeight = 0;
  this.a = a;
  this.selectionCounts = [];
  this.weightThreshold = [];
  // initialize
  for (i = 0, L = a.length; i<L; i++) {
    this.totalWeight += a[i][1];
    this.weightThreshold[i] = this.totalWeight;
    this.selectionCounts[i] = 0;
  }
}

WeightedRandomSelector.prototype.select = function() {
  // select a random value
  var R = Math.floor(Math.random() * this.totalWeight),
      i, L;

  // now find the bucket that R value falls into.
  for (i = 0, L = this.a.length; i < L; i++) {
    if (R < this.weightThreshold[i]) {
      this.selectionCounts[i]++;
      return(this.a[i]);
    }
  }
  return this.a[L - 1];
};

module.exports = WeightedRandomSelector;
<commit_msg>update comments in weightedRandomSelector.js<commit_after>// weightedRandomSelector.js
//
// simple weighted random selector.
//
// Copyright © 2013 Dino Chiesa
// All rights reserved.
//
// created: Fri, 26 Jul 2013  11:14
// last saved: <2013-August-13 21:41:39>
//
// --------------------------------------------------------

function WeightedRandomSelector(a) {
  // A must be an array of arrays. Each inner array is 2 elements,
  // with the item value as the first element and the weight for
  // that value as the second. The items need not be in any
  // particular order.  eg,
  // var fish = [
  //   //["name",      weight]
  //   ["Shark",      3],
  //   ["Shrimp",     50],
  //   ["Sardine",    10],
  //   ["Herring",    20],
  //   ["Anchovies",  10],
  //   ["Mackerel",   50],
  //   ["Tuna",       8]
  // ];

  var i, L;
  this.totalWeight = 0;
  this.a = a;
  this.selectionCounts = [];
  this.weightThreshold = [];
  // initialize
  for (i = 0, L = a.length; i<L; i++) {
    this.totalWeight += a[i][1];
    this.weightThreshold[i] = this.totalWeight;
    this.selectionCounts[i] = 0;
  }
}

WeightedRandomSelector.prototype.select = function() {
  // select a random value
  var R = Math.floor(Math.random() * this.totalWeight),
      i, L;

  // now find the bucket that R value falls into.
  for (i = 0, L = this.a.length; i < L; i++) {
    if (R < this.weightThreshold[i]) {
      this.selectionCounts[i]++;
      return(this.a[i]);
    }
  }
  return this.a[L - 1];
};

module.exports = WeightedRandomSelector;
<|endoftext|>


<commit_before>"use strict";

window.cls || (window.cls = {});

/**
 * @constructor
 * @extends ViewBase
 */
cls.ResourceTreeView = function(id, name, container_class, html, default_handler, resource_inspector)
{
  //	const
  var THROTTLE_DELAY = 250;
  var GROUP_ORDER = [
    ui_strings.S_HTTP_LABEL_FILTER_MARKUP,
    ui_strings.S_HTTP_LABEL_FILTER_STYLESHEETS,
    ui_strings.S_HTTP_LABEL_FILTER_SCRIPTS,
    ui_strings.S_HTTP_LABEL_FILTER_IMAGES,
    ui_strings.S_HTTP_LABEL_FILTER_FONTS,
    ui_strings.S_HTTP_LABEL_FILTER_OTHER
  ];

  this._next_render_time = 0;
  this._resource_inspector = resource_inspector;
  this.required_services = ["resource-manager", "document-manager"];

  this.get_group_order = function()
  {
    return GROUP_ORDER;
  };

  this.instant_update = function()
  {
    // Reset the _next_render_time to force an immediate render
    this._next_render_time = 0;
    this.update();
  };

  this.update_bound = this.update.bind(this);

  this.createView = function(container)
  {
    var now = Date.now();
    if (now >= this._next_render_time)
    {
      if (this._bounced_update)
        this._bounced_update = clearTimeout(this._bounced_update);

      this._render_view(container);
      this._next_render_time = now + THROTTLE_DELAY;
    }
    else if (!this._bounced_update)
      this._bounced_update = setTimeout(this.update_bound, THROTTLE_DELAY);
	};

  this._render_view = function(container)
  {
    var tpl;
    var ctx = this._resource_inspector.get_resource_context();
    var target = container.firstElementChild;

    if (ctx)
    {
      ctx.search_term = this.search_term || "";
      tpl = templates.resource_tree.update(ctx);
    }
    else
    {
      tpl = (
        ["div",
         ["span",
          "class", "container-button ui-button reload-window",
          "handler", "reload-window",
          "tabindex", "1"],
         ["p", ui_strings.S_RESOURCE_CLICK_BUTTON_TO_FETCH_RESOURCES],
         "class", "info-box"
        ]
      );
    }

    //  Exit if the template has not changed since last time ( using its JSON representation as hash )
    var tpl_JSON = JSON.stringify(tpl);
    if (tpl_JSON == this.tpl_JSON)
      return;

    this.tpl_JSON = tpl_JSON;

    var scroll_top = target ? target.scrollTop : 0;
    var scroll_left = target ? target.scrollLeft : 0;

    container.clearAndRender(tpl);

    target = container.firstElementChild;
    if (target)
    {
      target.scrollTop = scroll_top;
      target.scrollLeft = scroll_left;
    }
  };

  this.ondestroy = function(container)
  {
    this.tpl_JSON = null;
  };

  this.create_disabled_view = function(container)
  {
    container.clearAndRender(window.templates.disabled_view());
  };

  this._init = function()
  {
    this.id = id;

    var messages = window.messages;
    messages.add_listener("debug-context-selected", this.update_bound);

    var doc_service = window.services["document-manager"];
    doc_service.add_listener("abouttoloaddocument", this.update_bound);
    doc_service.add_listener("documentloaded", this.update_bound);

    ActionHandlerInterface.apply(this);
    this._handlers = {
      "select-next-entry": this._resource_inspector.highlight_next_resource_bound,
      "select-previous-entry": this._resource_inspector.highlight_previous_resource_bound
    };
    ActionBroker.get_instance().register_handler(this);

    this.init(id, name, container_class, html, default_handler);
  };

  this._init(id, name, container_class, html, default_handler);
};

cls.ResourceTreeView.create_ui_widgets = function()
{
  new ToolbarConfig(
  {
    view: "resource_tree_view",
    groups:
    [
      {
        type: UI.TYPE_INPUT,
        items:
        [
          {
            handler: "resource-tree-text-search",
            shortcuts: "resource-tree-text-search",
            title: ui_strings.S_SEARCH_INPUT_TOOLTIP,
            label: ui_strings.S_INPUT_DEFAULT_TEXT_FILTER,
            type: "filter"
          }
        ]
      }
    ]
  });

  var text_search = window.views.resource_tree_view.text_search = new TextSearch();
  text_search.ignore_case = false;

  text_search.add_listener("onbeforesearch", (function(msg)
  {
    var view = window.views.resource_tree_view;
    view.search_term = msg.search_term;
    view.instant_update();
  }).bind(text_search));

  window.event_handlers.input["resource-tree-text-search"] = function(event, target)
  {
    text_search.searchDelayed(target.value);
  };

  ActionBroker.get_instance().get_global_handler().register_shortcut_listener(
    "resource-tree-text-search",
    cls.Helpers.shortcut_search_cb.bind(text_search)
  );

  var on_view_created = function(msg)
  {
    if (msg.id == "resource_tree_view" && msg.container)
    {
      text_search.setContainer(msg.container);
      text_search.set_query_selector(".resource-tree-resource-label");
    }
  };

  var on_view_destroyed = function(msg)
  {
    if (msg.id == "resource_tree_view")
    {
      text_search.cleanup();
      window.views.resource_tree_view.search_term = "";
    }
  };

  window.messages.add_listener("view-created", on_view_created);
  window.messages.add_listener("view-destroyed", on_view_destroyed);
};

cls.ResourceTreeView.prototype = ViewBase;
<commit_msg>Fix for DFL-3715, Hits aren't shown when entering search token before reloading<commit_after>"use strict";

window.cls || (window.cls = {});

/**
 * @constructor
 * @extends ViewBase
 */
cls.ResourceTreeView = function(id, name, container_class, html, default_handler, resource_inspector)
{
  //	const
  var THROTTLE_DELAY = 250;
  var GROUP_ORDER = [
    ui_strings.S_HTTP_LABEL_FILTER_MARKUP,
    ui_strings.S_HTTP_LABEL_FILTER_STYLESHEETS,
    ui_strings.S_HTTP_LABEL_FILTER_SCRIPTS,
    ui_strings.S_HTTP_LABEL_FILTER_IMAGES,
    ui_strings.S_HTTP_LABEL_FILTER_FONTS,
    ui_strings.S_HTTP_LABEL_FILTER_OTHER
  ];

  this._next_render_time = 0;
  this._resource_inspector = resource_inspector;
  this.required_services = ["resource-manager", "document-manager"];

  this.get_group_order = function()
  {
    return GROUP_ORDER;
  };

  this.instant_update = function()
  {
    // Reset the _next_render_time to force an immediate render
    this._next_render_time = 0;
    this.update();
  };

  this.update_bound = this.update.bind(this);

  this.createView = function(container)
  {
    var now = Date.now();
    if (now >= this._next_render_time)
    {
      if (this._bounced_update)
        this._bounced_update = clearTimeout(this._bounced_update);

      this._render_view(container);
      this._next_render_time = now + THROTTLE_DELAY;
    }
    else if (!this._bounced_update)
      this._bounced_update = setTimeout(this.update_bound, THROTTLE_DELAY);
	};

  this._render_view = function(container)
  {
    var tpl;
    var ctx = this._resource_inspector.get_resource_context();
    var target = container.firstElementChild;

    if (ctx)
    {
      ctx.search_term = this.search_term || "";
      tpl = templates.resource_tree.update(ctx);
    }
    else
    {
      tpl = (
        ["div",
         ["span",
          "class", "container-button ui-button reload-window",
          "handler", "reload-window",
          "tabindex", "1"],
         ["p", ui_strings.S_RESOURCE_CLICK_BUTTON_TO_FETCH_RESOURCES],
         "class", "info-box"
        ]
      );
    }

    //  Exit if the template has not changed since last time ( using its JSON representation as hash )
    var tpl_JSON = JSON.stringify(tpl);
    if (tpl_JSON == this.tpl_JSON)
      return;

    this.tpl_JSON = tpl_JSON;

    var scroll_top = target ? target.scrollTop : 0;
    var scroll_left = target ? target.scrollLeft : 0;

    container.clearAndRender(tpl);

    target = container.firstElementChild;
    if (target)
    {
      target.scrollTop = scroll_top;
      target.scrollLeft = scroll_left;
    }
  };

  this.ondestroy = function(container)
  {
    this.tpl_JSON = null;
  };

  this.create_disabled_view = function(container)
  {
    container.clearAndRender(window.templates.disabled_view());
  };

  this._init = function()
  {
    this.id = id;

    var messages = window.messages;
    messages.add_listener("debug-context-selected", this.update_bound);

    var doc_service = window.services["document-manager"];
    doc_service.add_listener("abouttoloaddocument", this.update_bound);
    doc_service.add_listener("documentloaded", this.update_bound);

    ActionHandlerInterface.apply(this);
    this._handlers = {
      "select-next-entry": this._resource_inspector.highlight_next_resource_bound,
      "select-previous-entry": this._resource_inspector.highlight_previous_resource_bound
    };
    ActionBroker.get_instance().register_handler(this);

    this.init(id, name, container_class, html, default_handler);
  };

  this._init(id, name, container_class, html, default_handler);
};

cls.ResourceTreeView.create_ui_widgets = function()
{
  new ToolbarConfig(
  {
    view: "resource_tree_view",
    groups:
    [
      {
        type: UI.TYPE_INPUT,
        items:
        [
          {
            handler: "resource-tree-text-search",
            shortcuts: "resource-tree-text-search",
            title: ui_strings.S_SEARCH_INPUT_TOOLTIP,
            label: ui_strings.S_INPUT_DEFAULT_TEXT_FILTER,
            type: "filter"
          }
        ]
      }
    ]
  });

  var view = window.views.resource_tree_view;
  var text_search = window.views.resource_tree_view.text_search = new TextSearch();
  text_search.ignore_case = false;

  text_search.add_listener("onbeforesearch", (function(msg)
  {
    view.last_view_event = "onbeforesearch";
    view.search_term = msg.search_term;
    view.instant_update();
  }).bind(text_search));

  window.event_handlers.input["resource-tree-text-search"] = function(event, target)
  {
    text_search.searchDelayed(target.value);
  };

  ActionBroker.get_instance().get_global_handler().register_shortcut_listener(
    "resource-tree-text-search",
    cls.Helpers.shortcut_search_cb.bind(text_search)
  );

  var on_view_created = function(msg)
  {
    if (msg.id == "resource_tree_view" && msg.container)
    {
      text_search.setContainer(msg.container);
      text_search.set_query_selector(".resource-tree-resource-label");

      if (view.last_view_event != "onbeforesearch")
        text_search.update();

      view.last_view_event = "view-created";
    }
  };

  var on_view_destroyed = function(msg)
  {
    if (msg.id == "resource_tree_view")
    {
      text_search.cleanup();
      window.views.resource_tree_view.search_term = "";
    }
  };

  window.messages.add_listener("view-created", on_view_created);
  window.messages.add_listener("view-destroyed", on_view_destroyed);
};

cls.ResourceTreeView.prototype = ViewBase;
<|endoftext|>