<commit_before>(function () {
    'use strict';

    function TourDirective($timeout, $http, tourService, backdropService) {

        function link(scope, el, attr, ctrl) {

            var popover;

            scope.totalSteps;
            scope.currentStepIndex;
            scope.currentStep;
            scope.loadingStep = false;

            scope.nextStep = function() {
                nextStep();
            };

            scope.endTour = function() {
                unbindEvent();
                tourService.endTour();
                backdropService.close();
            };

            scope.completeTour = function() {
                unbindEvent();
                tourService.completeTour();
                backdropService.close();
            };

            function onInit() {
                popover = el.find(".umb-tour__popover");
                scope.totalSteps = scope.steps.length;
                scope.currentStepIndex = 0;
                startStep();
            }

            function setView() {
                if (scope.currentStep.view && scope.options.alias) {
                    //we do this to avoid a hidden dialog to start loading unconfigured views before the first activation
                    var configuredView = scope.currentStep.view;
                    if (scope.currentStep.view.indexOf(".html") === -1) {
                        var viewAlias = scope.currentStep.view.toLowerCase();
                        var tourAlias = scope.options.alias.toLowerCase();
                        configuredView = "views/common/tours/" + tourAlias + "/" + viewAlias + "/" + viewAlias + ".html";
                    }
                    if (configuredView !== scope.configuredView) {
                        scope.configuredView = configuredView;
                    }
                }
            }

            function nextStep() {
                scope.currentStepIndex++;
                if(scope.currentStepIndex !== scope.steps.length) {
                    startStep();
                }
            }

            function startStep() {

                backdropService.open();

                // we need to make sure that all requests are done
                var timer = window.setInterval(function(){

                    console.log("pending", $http.pendingRequests.length);
                    console.log("document ready", document.readyState);

                    scope.loadingStep = true;

                    backdropService.setHighlight(null);

                    // check for pending requests both in angular and on the document
                    if($http.pendingRequests.length === 0 && document.readyState === "complete") {
                        console.log("Everything is DONE JOHN");

                        scope.currentStep = scope.steps[scope.currentStepIndex];

                        clearInterval(timer);

                        setView();

                        positionPopover();

                        // if a custom event needs to be bound we do it now
                        if(scope.currentStep.event) {
                            bindEvent();
                        }

                        scope.loadingStep = false;

                    }

                }, 100);

            }

            function positionPopover() {

                $timeout(function () {

                    var element = $(scope.currentStep.element);
                    var scrollParent = element.scrollParent();

                    console.log("scrollParent", scrollParent);

                    // Detect if scroll is needed
                    if (element[0].offsetTop > scrollParent[0].clientHeight) {
                        console.log("SCROOOOOOOL");
                        scrollParent.animate({
                            scrollTop: element[0].offsetTop
                        }, function () {
                            // Animation complete.
                            console.log("ANIMATION COMPLETE");
                            _position();
                            backdropService.setHighlight(scope.currentStep.element);
                        });
                    } else {
                        _position();
                        backdropService.setHighlight(scope.currentStep.element);
                    }

                });

                function _position() {

                    var element = $(scope.currentStep.element);
                    var offset = element.offset();
                    var width = element.outerWidth(true);
                    var height = element.outerHeight(true);

                    $timeout(function () {

                        var popoverWidth = popover.outerWidth(true);
                        var popoverHeight = popover.outerHeight(true);
                        var popoverOffset = popover.offset();
                        var documentWidth = $(document).width();
                        var documentHeight = $(document).height();
                        var position;
                        var css = {};

                        console.log("SPACE", space);
                        console.log("document width", documentWidth);
                        console.log("document height", documentHeight);

                        // If no specific position is set - find the position with most available space
                        if(scope.currentStep.placement) {

                            position = scope.currentStep.placement;

                        } else {

                            var space = {
                                "top": offset.top,
                                "right": documentWidth - (offset.left + width),
                                "bottom": documentHeight - (offset.top + height),
                                "left": offset.left
                            };

                            position = findMax(space);
                        }

                        if(position === "top") {

                            if (offset.left < documentWidth/2) {
                                css = {top: offset.top - popoverHeight, left: offset.left};

                            } else {
                                css = {top: offset.top - popoverHeight, left: offset.left - popoverWidth + width};
                            }
                        }

                        if(position === "right") {

                            if (offset.top < documentHeight/2) {
                                css = {top: offset.top, left: offset.left + width};

                            } else {
                                css = {top: offset.top + height - popoverHeight, left: offset.left + width};
                            }
                        }

                        if(position === "bottom") {

                            if (offset.left < documentWidth/2) {
                                css = {top: offset.top + height, left: offset.left};

                            } else {
                                css = {top: offset.top + height, left: offset.left - popoverWidth + width};
                            }
                        }

                        if(position === "left") {

                            if (offset.top < documentHeight/2) {
                                css = {top: offset.top, left: offset.left - popoverWidth};

                            } else {
                                css = {top: offset.top + height - popoverHeight, left: offset.left - popoverWidth};
                            }
                        }

                        popover.css(css);

                        scope.position = position;

                    });

                }

            }

            function findMax(obj) {
                var keys = Object.keys(obj);
                var max = keys[0];
                for (var i = 1, n = keys.length; i < n; ++i) {
                    var k = keys[i];
                    if (obj[k] > obj[max]) {
                        max = k;
                    }
                }
                return max;
            }

            function bindEvent() {
                if(scope.currentStep.clickElement) {
                    $(scope.currentStep.clickElement).on(scope.currentStep.event, handleEvent);
                } else {
                    $(scope.currentStep.element).on(scope.currentStep.event, handleEvent);
                }
            }

            function unbindEvent() {
                if(scope.currentStep.clickElement) {
                    $(scope.currentStep.clickElement).off(scope.currentStep.event);
                } else {
                    $(scope.currentStep.element).off(scope.currentStep.event);
                }
            }

            function handleEvent() {
                alert("event happened");
                unbindEvent();
                nextStep();
            }

            function resize() {
                positionPopover();
            }

            onInit();

            $(window).on('resize.umbTour', resize);

            scope.$on('$destroy', function () {
                $(window).off('resize.umbTour');
            });

        }

        var directive = {
            transclude: true,
            restrict: 'E',
            replace: true,
            templateUrl: 'views/components/application/umb-tour.html',
            link: link,
            scope: {
                options: "=",
                steps: "="
            }
        };

        return directive;

    }

    angular.module('umbraco.directives').directive('umbTour', TourDirective);

})();
<commit_msg>Clear step custom view if none is set<commit_after>(function () {
    'use strict';

    function TourDirective($timeout, $http, tourService, backdropService) {

        function link(scope, el, attr, ctrl) {

            var popover;

            scope.totalSteps;
            scope.currentStepIndex;
            scope.currentStep;
            scope.loadingStep = false;

            scope.nextStep = function() {
                nextStep();
            };

            scope.endTour = function() {
                unbindEvent();
                tourService.endTour();
                backdropService.close();
            };

            scope.completeTour = function() {
                unbindEvent();
                tourService.completeTour();
                backdropService.close();
            };

            function onInit() {
                popover = el.find(".umb-tour__popover");
                scope.totalSteps = scope.steps.length;
                scope.currentStepIndex = 0;
                startStep();
            }

            function setView() {
                if (scope.currentStep.view && scope.options.alias) {
                    //we do this to avoid a hidden dialog to start loading unconfigured views before the first activation
                    var configuredView = scope.currentStep.view;
                    if (scope.currentStep.view.indexOf(".html") === -1) {
                        var viewAlias = scope.currentStep.view.toLowerCase();
                        var tourAlias = scope.options.alias.toLowerCase();
                        configuredView = "views/common/tours/" + tourAlias + "/" + viewAlias + "/" + viewAlias + ".html";
                    }
                    if (configuredView !== scope.configuredView) {
                        scope.configuredView = configuredView;
                    }
                } else {
                    scope.configuredView = null;
                }
            }

            function nextStep() {
                scope.currentStepIndex++;
                if(scope.currentStepIndex !== scope.steps.length) {
                    startStep();
                }
            }

            function startStep() {

                backdropService.open();

                // we need to make sure that all requests are done
                var timer = window.setInterval(function(){

                    console.log("pending", $http.pendingRequests.length);
                    console.log("document ready", document.readyState);

                    scope.loadingStep = true;

                    backdropService.setHighlight(null);

                    // check for pending requests both in angular and on the document
                    if($http.pendingRequests.length === 0 && document.readyState === "complete") {
                        console.log("Everything is DONE JOHN");

                        scope.currentStep = scope.steps[scope.currentStepIndex];

                        clearInterval(timer);

                        setView();

                        positionPopover();

                        // if a custom event needs to be bound we do it now
                        if(scope.currentStep.event) {
                            bindEvent();
                        }

                        scope.loadingStep = false;

                    }

                }, 100);

            }

            function positionPopover() {

                $timeout(function () {

                    var element = $(scope.currentStep.element);
                    var scrollParent = element.scrollParent();

                    console.log("scrollParent", scrollParent);

                    // Detect if scroll is needed
                    if (element[0].offsetTop > scrollParent[0].clientHeight) {
                        console.log("SCROOOOOOOL");
                        scrollParent.animate({
                            scrollTop: element[0].offsetTop
                        }, function () {
                            // Animation complete.
                            console.log("ANIMATION COMPLETE");
                            _position();
                            backdropService.setHighlight(scope.currentStep.element);
                        });
                    } else {
                        _position();
                        backdropService.setHighlight(scope.currentStep.element);
                    }

                });

                function _position() {

                    var element = $(scope.currentStep.element);
                    var offset = element.offset();
                    var width = element.outerWidth(true);
                    var height = element.outerHeight(true);

                    $timeout(function () {

                        var popoverWidth = popover.outerWidth(true);
                        var popoverHeight = popover.outerHeight(true);
                        var popoverOffset = popover.offset();
                        var documentWidth = $(document).width();
                        var documentHeight = $(document).height();
                        var position;
                        var css = {};

                        console.log("SPACE", space);
                        console.log("document width", documentWidth);
                        console.log("document height", documentHeight);

                        // If no specific position is set - find the position with most available space
                        if(scope.currentStep.placement) {

                            position = scope.currentStep.placement;

                        } else {

                            var space = {
                                "top": offset.top,
                                "right": documentWidth - (offset.left + width),
                                "bottom": documentHeight - (offset.top + height),
                                "left": offset.left
                            };

                            position = findMax(space);
                        }

                        if(position === "top") {

                            if (offset.left < documentWidth/2) {
                                css = {top: offset.top - popoverHeight, left: offset.left};

                            } else {
                                css = {top: offset.top - popoverHeight, left: offset.left - popoverWidth + width};
                            }
                        }

                        if(position === "right") {

                            if (offset.top < documentHeight/2) {
                                css = {top: offset.top, left: offset.left + width};

                            } else {
                                css = {top: offset.top + height - popoverHeight, left: offset.left + width};
                            }
                        }

                        if(position === "bottom") {

                            if (offset.left < documentWidth/2) {
                                css = {top: offset.top + height, left: offset.left};

                            } else {
                                css = {top: offset.top + height, left: offset.left - popoverWidth + width};
                            }
                        }

                        if(position === "left") {

                            if (offset.top < documentHeight/2) {
                                css = {top: offset.top, left: offset.left - popoverWidth};

                            } else {
                                css = {top: offset.top + height - popoverHeight, left: offset.left - popoverWidth};
                            }
                        }

                        popover.css(css);

                        scope.position = position;

                    });

                }

            }

            function findMax(obj) {
                var keys = Object.keys(obj);
                var max = keys[0];
                for (var i = 1, n = keys.length; i < n; ++i) {
                    var k = keys[i];
                    if (obj[k] > obj[max]) {
                        max = k;
                    }
                }
                return max;
            }

            function bindEvent() {
                if(scope.currentStep.clickElement) {
                    $(scope.currentStep.clickElement).on(scope.currentStep.event, handleEvent);
                } else {
                    $(scope.currentStep.element).on(scope.currentStep.event, handleEvent);
                }
            }

            function unbindEvent() {
                if(scope.currentStep.clickElement) {
                    $(scope.currentStep.clickElement).off(scope.currentStep.event);
                } else {
                    $(scope.currentStep.element).off(scope.currentStep.event);
                }
            }

            function handleEvent() {
                alert("event happened");
                unbindEvent();
                nextStep();
            }

            function resize() {
                positionPopover();
            }

            onInit();

            $(window).on('resize.umbTour', resize);

            scope.$on('$destroy', function () {
                $(window).off('resize.umbTour');
            });

        }

        var directive = {
            transclude: true,
            restrict: 'E',
            replace: true,
            templateUrl: 'views/components/application/umb-tour.html',
            link: link,
            scope: {
                options: "=",
                steps: "="
            }
        };

        return directive;

    }

    angular.module('umbraco.directives').directive('umbTour', TourDirective);

})();
<|endoftext|>


<commit_before>'use strict';

/*jslint latedef:false*/

(function() {
  angular.module('o19s.splainer-search')
    .factory('SolrSearcherFactory', [
      '$http',
      '$q',
      '$sce',
      '$log',
      'SolrDocFactory',
      'SearcherFactory',
      'activeQueries',
      'defaultSolrConfig',
      'solrSearcherPreprocessorSvc',
      SolrSearcherFactory
    ]);

  function SolrSearcherFactory(
    $http, $q, $sce, $log,
    SolrDocFactory, SearcherFactory,
    activeQueries, defaultSolrConfig,
    solrSearcherPreprocessorSvc
  ) {
    var Searcher = function(options) {
      SearcherFactory.call(this, options, solrSearcherPreprocessorSvc);
    };

    Searcher.prototype = Object.create(SearcherFactory.prototype);
    Searcher.prototype.constructor = Searcher; // Reset the constructor

    Searcher.prototype.addDocToGroup    = addDocToGroup;
    Searcher.prototype.pager            = pager;
    Searcher.prototype.search           = search;
    Searcher.prototype.explainOther     = explainOther;

    function addDocToGroup (groupedBy, group, solrDoc) {
      /*jslint validthis:true*/
      var self = this;

      if (!self.grouped.hasOwnProperty(groupedBy)) {
        self.grouped[groupedBy] = [];
      }

      var found = null;
      angular.forEach(self.grouped[groupedBy], function(groupedDocs) {
        if (groupedDocs.value === group && !found) {
          found = groupedDocs;
        }
      });

      if (!found) {
        found = {docs:[], value:group};
        self.grouped[groupedBy].push(found);
      }

      found.docs.push(solrDoc);
    }

    // return a new searcher that will give you
    // the next page upon search(). To get the subsequent
    // page, call pager on that searcher ad infinidum
    function pager () {
      /*jslint validthis:true*/
      var self      = this;
      var start     = 0;
      var rows      = self.config.numberOfRows;
      var nextArgs  = angular.copy(self.args);

      if (nextArgs.hasOwnProperty('rows')) {
        rows = parseInt(nextArgs.rows);
      }

      if (nextArgs.hasOwnProperty('start')) {
        start = parseInt(nextArgs.start) + rows;

        if (start >= self.numFound) {
          return null; // no more results
        }
      } else {
        start = rows;
      }

      nextArgs.rows       = ['' + rows];
      nextArgs.start      = ['' + start];
      var pageConfig      = defaultSolrConfig;
      pageConfig.sanitize = false;
      pageConfig.escapeQuery = self.config.escapeQuery;

      var options = {
        fieldList:          self.fieldList,
        hlFieldList:        self.hlFieldList,
        url:                self.url,
        args:               nextArgs,
        queryText:          self.queryText,
        config:             pageConfig,
        type:               self.type,
        HIGHLIGHTING_PRE:   self.HIGHLIGHTING_PRE,
        HIGHLIGHTING_POST:  self.HIGHLIGHTING_POST,
      };

      var nextSearcher = new Searcher(options);

      return nextSearcher;
    }

    // search (execute the query) and produce results
    // to the returned future
    function search () {
      /*jslint validthis:true*/
      var self      = this;
      var url       = self.callUrl;
      self.inError  = false;

      var thisSearcher = self;

      var getExplData = function(solrResp) {
        if (solrResp.hasOwnProperty('debug')) {
          var dbg = solrResp.debug;
          if (dbg.hasOwnProperty('explain')) {
            return dbg.explain;
          }
        }
        return {};
      };

      var getOthersExplained = function(solrResp) {
        if (solrResp.hasOwnProperty('debug')) {
          var dbg = solrResp.debug;
          if (dbg.hasOwnProperty('explainOther')) {
            return dbg.explainOther;
          }
        }
      };

      var getHlData = function(solrResp) {
        if (solrResp.hasOwnProperty('highlighting')) {
          return solrResp.highlighting;
        }
        return {};
      };

      activeQueries.count++;
      return $q(function(resolve, reject) {
        var trustedUrl = $sce.trustAsResourceUrl(url);

        $http.jsonp(trustedUrl, { jsonpCallbackParam: 'json.wrf' })
          .then(function success(resp) {
            var solrResp = resp.data;
            activeQueries.count--;

            var explDict  = getExplData(solrResp);
            var hlDict    = getHlData(solrResp);
            thisSearcher.othersExplained = getOthersExplained(solrResp);

            var parseSolrDoc = function(solrDoc, groupedBy, group) {
              var options = {
                groupedBy:          groupedBy,
                group:              group,
                fieldList:          self.fieldList,
                hlFieldList:        self.hlFieldList,
                url:                self.url,
                explDict:           explDict,
                hlDict:             hlDict,
                highlightingPre:    self.HIGHLIGHTING_PRE,
                highlightingPost:   self.HIGHLIGHTING_POST,
              };

              return new SolrDocFactory(solrDoc, options);
            };

            if (solrResp.hasOwnProperty('response')) {
              angular.forEach(solrResp.response.docs, function(solrDoc) {
                var doc = parseSolrDoc(solrDoc);
                thisSearcher.numFound = solrResp.response.numFound;
                thisSearcher.docs.push(doc);
              });
            } else if (solrResp.hasOwnProperty('grouped')) {
              angular.forEach(solrResp.grouped, function(groupedBy, groupedByName) {

                thisSearcher.numFound = groupedBy.matches;
                // add docs for a top level group
                //console.log(groupedBy.doclist.docs);
                if (groupedBy.hasOwnProperty('doclist')) {
                  angular.forEach(groupedBy.doclist.docs, function (solrDoc) {
                    var doc = parseSolrDoc(solrDoc, groupedByName, solrDoc[groupedByName]);
                    thisSearcher.docs.push(doc);
                    thisSearcher.addDocToGroup(groupedByName, solrDoc[groupedByName], doc);
                  });
                }

                // add docs for Field Collapsing results
                angular.forEach(groupedBy.groups, function(groupResp) {
                  var groupValue = groupResp.groupValue;
                  angular.forEach(groupResp.doclist.docs, function(solrDoc) {
                    var doc = parseSolrDoc(solrDoc, groupedByName, groupValue);
                    thisSearcher.docs.push(doc);
                    thisSearcher.addDocToGroup(groupedByName, groupValue, doc);
                  });
                });
              });
            }
            resolve();
          }, function error(msg) {
            activeQueries.count--;
            thisSearcher.inError = true;
            msg.searchError = 'Error with Solr query or server. Contact Solr directly to inspect the error';
            reject(msg);
          }).catch(function(response) {
            $log.debug('Failed to run search');
            return response;
          });
      });
    } // end of search()

    function explainOther (otherQuery, fieldSpec) {
      /*jslint validthis:true*/
      var self = this;

      // var args = angular.copy(self.args);
      self.args.explainOther = [otherQuery];
      solrSearcherPreprocessorSvc.prepare(self);

      // TODO: revisit why we perform the first search, doesn't seem to have
      // any use!
      return self.search()
        .then(function() {
          var start = 0;
          var rows  = self.config.numberOfRows;

          if ( angular.isDefined(self.args.rows) && self.args.rows !== null ) {
            rows = self.args.rows;
          }

          if ( angular.isDefined(self.args.start) && self.args.start !== null ) {
            start = self.args.start;
          }
          var solrParams = {
            qf:     [fieldSpec.title + ' ' + fieldSpec.id],
            rows:   [rows],
            start:  [start],
            q:      [otherQuery]
          };

          var otherSearcherOptions = {
            fieldList:          self.fieldList,
            hlFieldList:        self.hlFieldList,
            url:                self.url,
            args:               solrParams,
            queryText:          otherQuery,
            config:             {
              numberOfRows: self.config.numberOfRows
            },
            type:               self.type,
            HIGHLIGHTING_PRE:   self.HIGHLIGHTING_PRE,
            HIGHLIGHTING_POST:  self.HIGHLIGHTING_POST,
          };

          var otherSearcher = new Searcher(otherSearcherOptions);

          return otherSearcher.search()
            .then(function() {
              self.numFound        = otherSearcher.numFound;
              self.docs            = otherSearcher.docs;
            });
        }).catch(function(response) {
          $log.debug('Failed to run explainOther');
          return response;
        });
    }

    // Return factory object
    return Searcher;
  }
})();
<commit_msg>Allow defType override for solr explainOther<commit_after>'use strict';

/*jslint latedef:false*/

(function() {
  angular.module('o19s.splainer-search')
    .factory('SolrSearcherFactory', [
      '$http',
      '$q',
      '$sce',
      '$log',
      'SolrDocFactory',
      'SearcherFactory',
      'activeQueries',
      'defaultSolrConfig',
      'solrSearcherPreprocessorSvc',
      SolrSearcherFactory
    ]);

  function SolrSearcherFactory(
    $http, $q, $sce, $log,
    SolrDocFactory, SearcherFactory,
    activeQueries, defaultSolrConfig,
    solrSearcherPreprocessorSvc
  ) {
    var Searcher = function(options) {
      SearcherFactory.call(this, options, solrSearcherPreprocessorSvc);
    };

    Searcher.prototype = Object.create(SearcherFactory.prototype);
    Searcher.prototype.constructor = Searcher; // Reset the constructor

    Searcher.prototype.addDocToGroup    = addDocToGroup;
    Searcher.prototype.pager            = pager;
    Searcher.prototype.search           = search;
    Searcher.prototype.explainOther     = explainOther;

    function addDocToGroup (groupedBy, group, solrDoc) {
      /*jslint validthis:true*/
      var self = this;

      if (!self.grouped.hasOwnProperty(groupedBy)) {
        self.grouped[groupedBy] = [];
      }

      var found = null;
      angular.forEach(self.grouped[groupedBy], function(groupedDocs) {
        if (groupedDocs.value === group && !found) {
          found = groupedDocs;
        }
      });

      if (!found) {
        found = {docs:[], value:group};
        self.grouped[groupedBy].push(found);
      }

      found.docs.push(solrDoc);
    }

    // return a new searcher that will give you
    // the next page upon search(). To get the subsequent
    // page, call pager on that searcher ad infinidum
    function pager () {
      /*jslint validthis:true*/
      var self      = this;
      var start     = 0;
      var rows      = self.config.numberOfRows;
      var nextArgs  = angular.copy(self.args);

      if (nextArgs.hasOwnProperty('rows')) {
        rows = parseInt(nextArgs.rows);
      }

      if (nextArgs.hasOwnProperty('start')) {
        start = parseInt(nextArgs.start) + rows;

        if (start >= self.numFound) {
          return null; // no more results
        }
      } else {
        start = rows;
      }

      nextArgs.rows       = ['' + rows];
      nextArgs.start      = ['' + start];
      var pageConfig      = defaultSolrConfig;
      pageConfig.sanitize = false;
      pageConfig.escapeQuery = self.config.escapeQuery;

      var options = {
        fieldList:          self.fieldList,
        hlFieldList:        self.hlFieldList,
        url:                self.url,
        args:               nextArgs,
        queryText:          self.queryText,
        config:             pageConfig,
        type:               self.type,
        HIGHLIGHTING_PRE:   self.HIGHLIGHTING_PRE,
        HIGHLIGHTING_POST:  self.HIGHLIGHTING_POST,
      };

      var nextSearcher = new Searcher(options);

      return nextSearcher;
    }

    // search (execute the query) and produce results
    // to the returned future
    function search () {
      /*jslint validthis:true*/
      var self      = this;
      var url       = self.callUrl;
      self.inError  = false;

      var thisSearcher = self;

      var getExplData = function(solrResp) {
        if (solrResp.hasOwnProperty('debug')) {
          var dbg = solrResp.debug;
          if (dbg.hasOwnProperty('explain')) {
            return dbg.explain;
          }
        }
        return {};
      };

      var getOthersExplained = function(solrResp) {
        if (solrResp.hasOwnProperty('debug')) {
          var dbg = solrResp.debug;
          if (dbg.hasOwnProperty('explainOther')) {
            return dbg.explainOther;
          }
        }
      };

      var getHlData = function(solrResp) {
        if (solrResp.hasOwnProperty('highlighting')) {
          return solrResp.highlighting;
        }
        return {};
      };

      activeQueries.count++;
      return $q(function(resolve, reject) {
        var trustedUrl = $sce.trustAsResourceUrl(url);

        $http.jsonp(trustedUrl, { jsonpCallbackParam: 'json.wrf' })
          .then(function success(resp) {
            var solrResp = resp.data;
            activeQueries.count--;

            var explDict  = getExplData(solrResp);
            var hlDict    = getHlData(solrResp);
            thisSearcher.othersExplained = getOthersExplained(solrResp);

            var parseSolrDoc = function(solrDoc, groupedBy, group) {
              var options = {
                groupedBy:          groupedBy,
                group:              group,
                fieldList:          self.fieldList,
                hlFieldList:        self.hlFieldList,
                url:                self.url,
                explDict:           explDict,
                hlDict:             hlDict,
                highlightingPre:    self.HIGHLIGHTING_PRE,
                highlightingPost:   self.HIGHLIGHTING_POST,
              };

              return new SolrDocFactory(solrDoc, options);
            };

            if (solrResp.hasOwnProperty('response')) {
              angular.forEach(solrResp.response.docs, function(solrDoc) {
                var doc = parseSolrDoc(solrDoc);
                thisSearcher.numFound = solrResp.response.numFound;
                thisSearcher.docs.push(doc);
              });
            } else if (solrResp.hasOwnProperty('grouped')) {
              angular.forEach(solrResp.grouped, function(groupedBy, groupedByName) {

                thisSearcher.numFound = groupedBy.matches;
                // add docs for a top level group
                //console.log(groupedBy.doclist.docs);
                if (groupedBy.hasOwnProperty('doclist')) {
                  angular.forEach(groupedBy.doclist.docs, function (solrDoc) {
                    var doc = parseSolrDoc(solrDoc, groupedByName, solrDoc[groupedByName]);
                    thisSearcher.docs.push(doc);
                    thisSearcher.addDocToGroup(groupedByName, solrDoc[groupedByName], doc);
                  });
                }

                // add docs for Field Collapsing results
                angular.forEach(groupedBy.groups, function(groupResp) {
                  var groupValue = groupResp.groupValue;
                  angular.forEach(groupResp.doclist.docs, function(solrDoc) {
                    var doc = parseSolrDoc(solrDoc, groupedByName, groupValue);
                    thisSearcher.docs.push(doc);
                    thisSearcher.addDocToGroup(groupedByName, groupValue, doc);
                  });
                });
              });
            }
            resolve();
          }, function error(msg) {
            activeQueries.count--;
            thisSearcher.inError = true;
            msg.searchError = 'Error with Solr query or server. Contact Solr directly to inspect the error';
            reject(msg);
          }).catch(function(response) {
            $log.debug('Failed to run search');
            return response;
          });
      });
    } // end of search()

    function explainOther (otherQuery, fieldSpec, defType) {
      /*jslint validthis:true*/
      var self = this;

      // var args = angular.copy(self.args);
      self.args.explainOther = [otherQuery];
      solrSearcherPreprocessorSvc.prepare(self);

      // TODO: revisit why we perform the first search, doesn't seem to have
      // any use!
      return self.search()
        .then(function() {
          var start = 0;
          var rows  = self.config.numberOfRows;

          if ( angular.isDefined(self.args.rows) && self.args.rows !== null ) {
            rows = self.args.rows;
          }

          if ( angular.isDefined(self.args.start) && self.args.start !== null ) {
            start = self.args.start;
          }
          var solrParams = {
            qf:     [fieldSpec.title + ' ' + fieldSpec.id],
            rows:   [rows],
            start:  [start],
            q:      [otherQuery]
          };

          var otherSearcherOptions = {
            fieldList:          self.fieldList,
            hlFieldList:        self.hlFieldList,
            url:                self.url,
            args:               solrParams,
            queryText:          otherQuery,
            config:             {
              numberOfRows: self.config.numberOfRows
            },
            type:               self.type,
            HIGHLIGHTING_PRE:   self.HIGHLIGHTING_PRE,
            HIGHLIGHTING_POST:  self.HIGHLIGHTING_POST,
          };

          if (defType) {
            args['defType'] = defType;
          }

          var otherSearcher = new Searcher(otherSearcherOptions);

          return otherSearcher.search()
            .then(function() {
              self.numFound        = otherSearcher.numFound;
              self.docs            = otherSearcher.docs;
            });
        }).catch(function(response) {
          $log.debug('Failed to run explainOther');
          return response;
        });
    }

    // Return factory object
    return Searcher;
  }
})();
<|endoftext|>


<commit_before>const EventBus = require('../event-bus')
const Message = require('../event-bus/message')
const _ = require("lodash")
const config = require("../config")
var awsIot = require('aws-iot-device-sdk');
var Q = [];
var retry = null;

var shadow = awsIot.thingShadow({
	keyPath: __dirname + config.keyPath,
	certPath: __dirname + config.certPath,
	caPath: __dirname + config.caPath,
	clientId: 'Alarm Master',
	region: config.iotRegion,
	host: config.iotHost
});

shadow.on('connect', function () {
	shadow.register('Alarm', {}, () => {
		console.log("Connected to Amazon IoT")
		queueUpdate({
			state:{
				reported:{
					armed:false
				}
			}
		})
	});
});

shadow.on('status',
	function (thingName, stat, clientToken, stateObject) {
		tryUpdate();
	});

shadow.on('delta',
	function (thingName, stateObject) {
		if (thingName == "Alarm" && stateObject.state) {
			if (stateObject.state.armed == true) {
				this.emit(...Message('arm', 'via Amazon'))
			} else if (stateObject.state.armed == false) {
				this.emit(...Message('disarm', 'via Amazon'))
			} else if (stateObject.state.strategy == 'bedtime'){
				this.emit(...Message('bedtime', 'via Amazon'))
			} else if (stateObject.state.strategy == 'standard'){
				this.emit(...Message('standard', 'via Amazon'))
			}
		}
	});

shadow.on('timeout',
	function (thingName, clientToken) {
		tryUpdate();
	});

shadow.on('error',
	function (error) {
		console.log("Error:", Date.now())
	});

function queueUpdate(update) {
	console.log(update)
	Q.unshift(update);
	tryUpdate();
}

function tryUpdate() {
	if (Q.length !== 0) {
		let update = Q.pop()
		let clientToken = shadow.update('Alarm', update)
		if (clientToken !== null) {
			console.log(Date.now(), clientToken)
		} else if (clientToken === null && retry !== null) {
			retry = setTimeout(() => {
				retry = null;
				tryUpdate()
			}, 100)
		} else {
			Q.push(update)
			console.log("Requeued length now", Q.length)
		}
	}
}

const updateArmedState = (event) => {
	console.log("IoT update for armed event",event)
		queueUpdate({
			state:{
				reported:{
					armed:(event.name === 'armed')
				}
			}
		})
}

const updateAlarmState = (event) => {
	console.log("IoT update for state event",event)
	queueUpdate({
		state:{
			reported:{
				state:event.detail
			}
		}
	})
}

const updateStrategyState = (event) => {
	console.log("IoT update for strategy event",event)
	queueUpdate({
		state:{
			reported:{
				strategy:event.detail
			}
		}
	})
}

EventBus.register({
	caller: shadow,
	provides: ['disarm', 'arm', 'bedtime', 'standard'],
	needs: {
		armed: updateArmedState,
		disarmed: updateArmedState,
		alarmState: updateAlarmState,
		strategyState: updateStrategyState,
	}
})
<commit_msg>state changes<commit_after>const EventBus = require('../event-bus')
const Message = require('../event-bus/message')
const _ = require("lodash")
const config = require("../config")
var awsIot = require('aws-iot-device-sdk');
var Q = [];
var retry = null;

var shadow = awsIot.thingShadow({
	keyPath: __dirname + config.keyPath,
	certPath: __dirname + config.certPath,
	caPath: __dirname + config.caPath,
	clientId: 'Alarm Master',
	region: config.iotRegion,
	host: config.iotHost
});

shadow.on('connect', function () {
	shadow.register('Alarm', {}, () => {
		console.log("Connected to Amazon IoT")
		queueUpdate({
			state:{
				reported:{
					armed:false
				}
			}
		})
	});
});

shadow.on('status',
	function (thingName, stat, clientToken, stateObject) {
		tryUpdate();
	});

shadow.on('delta',
	function (thingName, stateObject) {
		if (thingName == "Alarm" && stateObject.state) {
			if (stateObject.state.armed == true) {
				this.emit(...Message('arm', 'via Amazon'))
			} else if (stateObject.state.armed == false) {
				this.emit(...Message('disarm', 'via Amazon'))
			}
			if (stateObject.state.strategy == 'bedtime'){
				this.emit(...Message('bedtime', 'via Amazon'))
			} else if (stateObject.state.strategy == 'standard'){
				this.emit(...Message('standard', 'via Amazon'))
			}
		}
	});

shadow.on('timeout',
	function (thingName, clientToken) {
		tryUpdate();
	});

shadow.on('error',
	function (error) {
		console.log("Error:", Date.now())
	});

function queueUpdate(update) {
	console.log(update)
	Q.unshift(update);
	tryUpdate();
}

function tryUpdate() {
	if (Q.length !== 0) {
		let update = Q.pop()
		let clientToken = shadow.update('Alarm', update)
		if (clientToken !== null) {
			console.log(Date.now(), clientToken)
		} else if (clientToken === null && retry !== null) {
			retry = setTimeout(() => {
				retry = null;
				tryUpdate()
			}, 100)
		} else {
			Q.push(update)
			console.log("Requeued length now", Q.length)
		}
	}
}

const updateArmedState = (event) => {
	console.log("IoT update for armed event",event)
		queueUpdate({
			state:{
				reported:{
					armed:(event.name === 'armed')
				}
			}
		})
}

const updateAlarmState = (event) => {
	console.log("IoT update for state event",event)
	queueUpdate({
		state:{
			reported:{
				state:event.detail
			}
		}
	})
}

const updateStrategyState = (event) => {
	console.log("IoT update for strategy event",event)
	queueUpdate({
		state:{
			reported:{
				strategy:event.detail
			}
		}
	})
}

EventBus.register({
	caller: shadow,
	provides: ['disarm', 'arm', 'bedtime', 'standard'],
	needs: {
		armed: updateArmedState,
		disarmed: updateArmedState,
		alarmState: updateAlarmState,
		strategyState: updateStrategyState,
	}
})
<|endoftext|>


<commit_before>// create ESC object and sensors
var oESC = require("../lib/esc");
var oMPU6050 = require("../lib/mpu6050");
var oMS5611 = require("../lib/ms5611");
// include networking components
var oNetwork = require("../lib/HandyJS/lib/network-p");

// initialize ESC's
console.log("[QUADCOPTER] initialize");
oESC.init([9,7,23,19]); // initialize ESC's on given GPIO's

// connect to server and identify
oNetwork.oSocket.connectWebSocket("192.168.1.16", 4444, function(){
  // connected to server
  console.log("[QUADCOPTER] connected to server");
}, function(oLastConnection, lFlags){
  // message from server
  console.log("[QUADCOPTER] message from server:\nlFlag -> " + lFlags);
  console.log(oLastConnection);
}, function(oErr){
  // error
  console.log(oErr);
});
oNetwork.oSocket.serverSend(JSON.stringify({init:true,sType:"quadcopter"}));

<commit_msg>transfer push<commit_after>// create ESC object and sensors
var oESC = require("../lib/esc");
var oMPU6050 = require("../lib/mpu6050");
var oMS5611 = require("../lib/ms5611");
// include networking components
var oNetwork = require("../lib/HandyJS/lib/network-p");

function Quadcopter(){

  // initialize quadcopter
  this.initialize = function(){
    // initialize ESC's
    console.log("[QUADCOPTER] initialize");
    oESC.init([9,7,23,19]); // initialize ESC's on given GPIO's
    // connect to server and identify
    oNetwork.oSocket.connectWebSocket("192.168.1.16", 4444, function(){
      // connected to server
      console.log("[QUADCOPTER] connected to server");
      oNetwork.oSocket.serverSend(JSON.stringify({init:true,sType:"quadcopter"}));
    }, function(oLastConnection, lFlags){
      // message from server
      console.log("[QUADCOPTER] message from server:\nlFlag -> " + lFlags);
      console.log(oLastConnection);
    }, function(oErr){
      // error
      console.log(oErr);
    });
  };

}

<|endoftext|>


<commit_before>/* @flow */

import 'babel-polyfill'
import { BuildState } from '../src/main'

describe('BuildState', () => {
  let buildState: BuildState

  beforeEach(() => {
    buildState = new BuildState('foo.tex')
  })

  it('verifies that getRuleId returns expected id', () => {
    buildState.phase = 'initialize'
    expect(buildState.getRuleId('quux', 'bar', 'foo.tex')).toEqual('quux(initialize;bar;foo.tex)')
  })
})
<commit_msg>Test CI output<commit_after>/* @flow */

import 'babel-polyfill'
import { BuildState } from '../src/main'

describe('BuildState', () => {
  let buildState: BuildState

  beforeEach(() => {
    buildState = new BuildState('foo.tex')
  })

  it('verifies that getRuleId returns expected id', () => {
    buildState.phase = 'initialize'
    console.log(buildState.getRuleId('quux', 'bar', 'foo.tex'))
    expect(buildState.getRuleId('quux', 'bar', 'foo.tex')).toEqual('quux(initialize;bar;foo.tex)')
  })
})
<|endoftext|>


<commit_before>describe("Calculator",function() {
  var calculator;

  beforeEach(function(){
    calculator = new Calculator();
  });
  it("should set a number of people", function() {
    calculator.people(1);
    expect(calculator.people_count).toEqual(1);
    calculator.people(4);
    expect(calculator.people_count).toEqual(4);
  });
  it("should return markup for each person", function(){
    calculator.people(1);
    calculator.price = 100;
    //5% + 1.2$ * people(1)
    var cost = calculator.flatMarkup();
    expect(cost).toEqual(6.2);

    calculator.people(2);
    //5% + 1.2$ * people(2)
    cost = calculator.flatMarkup();
    expect(cost).toEqual(7.4);

    calculator.people(3);
    //5% + 1.2% * people(3)
    cost = calculator.flatMarkup();
    expect(cost).toEqual(8.6);
  });
  it("should return markup for type", function(){
    // drugs have a 7.5% markup
    var cost = 100 * calculator.setMarkup('drugs');
    expect(cost).toEqual(7.5);

    // food have a 13% markup
    cost = 101 * calculator.setMarkup('food');
    expect(cost).toEqual(13.13);

    // electronics have a 2% markup
    cost = 100 * calculator.setMarkup('electronics');
    expect(cost).toEqual(2);

    // other types have a 0% markup
    cost = 101 * calculator.setMarkup('books');
    expect(cost).toEqual(0);
  });
  it("should return electronics cost on price", function(){
    var electronics_cost=calculator.execute({
      people:3,
      type:'electronics',
      price:1299.99
    });
    expect(electronics_cost).toEqual(1440.03);
  });

  // The following tests are directly from the exercise
  //  NOTE: THEY FAIL!
  //    could it be that the numbers are wrong on the exercise? that would be evil.
  //    it is more likely that it is my magical calculation..
  //    cost = price + flat_markup + additionalMarkup((flat_markup + price),options.type));
  it("should return food cost on price", function(){
    var food_cost=calculator.execute({
      people:3,
      type:'food',
      price:1299.99
    });
    expect(food_cost).toEqual(1591.58);
  });
  it("should return drugs cost on price", function(){
    var drugs_cost=calculator.execute({
      people:1,
      type:'drugs',
      price:5432.00
    });
    expect(drugs_cost).toEqual(6199.81);
  });
  it("should return other cost on price", function(){
    var books_cost=calculator.execute({
      people:4,
      type:'books',
      price:12456.95
    });
    expect(books_cost).toEqual(13707.63);
  });
});
<commit_msg>test additionalMarkup method as well as setMarkup<commit_after>describe("Calculator",function() {
  var calculator;

  beforeEach(function(){
    calculator = new Calculator();
  });
  it("should set a number of people", function() {
    calculator.people(1);
    expect(calculator.people_count).toEqual(1);
    calculator.people(4);
    expect(calculator.people_count).toEqual(4);
  });
  it("should return markup for each person", function(){
    calculator.people(1);
    calculator.price = 100;
    //5% + 1.2$ * people(1)
    var cost = calculator.flatMarkup();
    expect(cost).toEqual(6.2);

    calculator.people(2);
    //5% + 1.2$ * people(2)
    cost = calculator.flatMarkup();
    expect(cost).toEqual(7.4);

    calculator.people(3);
    //5% + 1.2% * people(3)
    cost = calculator.flatMarkup();
    expect(cost).toEqual(8.6);
  });
  it("should return markup for type", function(){
    // drugs have a 7.5% markup
    var cost = 100 * calculator.setMarkup('drugs');
    expect(cost).toEqual(7.5);
    cost = calculator.additionalMarkup(100,'drugs');
    expect(cost).toEqual(7.5);

    // food have a 13% markup
    cost = 101 * calculator.setMarkup('food');
    expect(cost).toEqual(13.13);
    cost = calculator.additionalMarkup(101,'food');
    expect(cost).toEqual(13.13);

    // electronics have a 2% markup
    cost = 100 * calculator.setMarkup('electronics');
    expect(cost).toEqual(2);
    cost = calculator.additionalMarkup(100,'electronics');
    expect(cost).toEqual(2);

    // other types have a 0% markup
    cost = 101 * calculator.setMarkup('books');
    expect(cost).toEqual(0);
    cost = calculator.additionalMarkup(101,'books');
    expect(cost).toEqual(0);
  });
  it("should return electronics cost on price", function(){
    var electronics_cost=calculator.execute({
      people:3,
      type:'electronics',
      price:1299.99
    });
    expect(electronics_cost).toEqual(1440.03);
  });

  // The following tests are directly from the exercise
  //  NOTE: THEY FAIL!
  //    could it be that the numbers are wrong on the exercise? that would be evil.
  //    it is more likely that it is my magical calculation..
  //    cost = price + flat_markup + additionalMarkup((flat_markup + price),options.type));
  it("should return food cost on price", function(){
    var food_cost=calculator.execute({
      people:3,
      type:'food',
      price:1299.99
    });
    expect(food_cost).toEqual(1591.58);
  });
  it("should return drugs cost on price", function(){
    var drugs_cost=calculator.execute({
      people:1,
      type:'drugs',
      price:5432.00
    });
    expect(drugs_cost).toEqual(6199.81);
  });
  it("should return other cost on price", function(){
    var books_cost=calculator.execute({
      people:4,
      type:'books',
      price:12456.95
    });
    expect(books_cost).toEqual(13707.63);
  });
});
<|endoftext|>


<commit_before>(function(){

	// MEOW CONTAINER MODULE
	// =====================
	//
	// CONTAINS MANY CLASSES TO SAVE AND COLLECT DATA.
	//
	// LICENSE: MEOW LICENSE (SEE LICENSE FILE)
	// SINCE: 08.07.2011
	//======================================================================

    // ARRAY LIST
    //======================================================================

    /**
	 * MeowEngine implementation of the javascript Array class. This one
	 * contains some enhanced functions and is programmed against the shape
	 * of java's java.util.Array class.
	 *
	 * @example
	 * This implementation allows no shortcut syntax.
	 * var a = new meow.Array()
	 * a[0] = 10 // not works
	 * a.add( 10 ) // works
	 * a.set( 0 , 10 ) // works
	 * a.get( 0 ) // works
	 *
	 * @class
	 */
	meowEngine.Array = meowEngine.Class( /** @lends meowEngine.Array# */{

        /**
         * @param {Number} initSize initial size of the internal array
         */
		constructor : function( initSize )
		{
            /** @private holds all data from the array */
			this._data = ( initSize && initSize > 0)? new Array(initSize) :[];
		},

        /**
         * Adds an element to the array.
         *
         * @param obj object, that will be added
         */
		add : function( obj )
		{
			this._data.push( obj );
		},

        /**
         * Inserts the element at a given position.
         *
         * @param obj object, that will be inserted
         * @param {Number} index index
         */
        insertAt : function( obj, index ){

            if( index >= 0 && index <= this.length ){
                this._data.splice( index , 0, obj );
                return true;
            }
            else{
                return false;
            }
        },

        /**
         * Sets the element of a given position.
         *
         * @param obj object, that will be set
         * @param {Number} index index
         */
		set : function( obj, index )
		{
            if( index >= 0 && index < this.length ){
                this._data[ index ] = obj;
                return true;
            }
            else{
                return false;
            }
		},

        /**
         * Returns the element of a given position.
         *
         * @param {Number} index index
         * @return object at the given index
         */
		get : function( index )
		{
			if( index >= 0 && index < this.length ){
                return this._data[ index ];
            }
            else{
                return 'undefined';
            }
		},

        /**
         * @return true, if the array is empty, else false
         */
		isEmpty : function(){
			return this._data.length == 0;
		},

		/**
		 * Removes a range from the array.
		 * by John Resig (MIT Licensed)
         *
         * @param {Number} from first element
         * @param {Number} to last element (inclusive)
		 */
		removeRange : function(from, to)
		{
			var rest = this._data.slice((to||from) + 1 || this._data.length);
			this._data.length = from < 0 ? this.length + from : from;
			return this._data.push.apply(this, rest);
		},

		/**
		 * Removes an index from the array.
         *
         * @param {Number} index index, that will be removed
		 */
		removeIndex : function( index )
		{
			if( index >= 0 && index < this._data.length ){
				var o = this._data[index];
                this._data.splice(index, 1);
                return o;
            }

            return 'undefined';
		},

		/**
		 * Removes an object from the array.
         *
         * @param obj object, that will be removed
         * @return object
		 */
		remove : function( obj )
		{
			var i = this._data.indexOf( obj );

			if(i != -1){
                this._data.splice(i, 1);
                return true;
            }
            else{
                return false;
            }
		},

		/**
         * @param obj object that will be checked
		 * @return true if the array contains the object, else false.
		 */
		contains : function( obj )
		{
			return this._data.indexOf( obj ) != -1;
		},

        /**
         * @param obj object that will be checked
         * @return the index of the object, if not exist, -1
         */
		indexOf : function( obj )
		{
			return this._data.indexOf( obj );
		},

        /**
         * @param obj object that will be checked
         * @return the last index of the object, if not exist, -1
         */
        lastIndexOf : function( obj )
		{
			return this._data.lastIndexOf( obj );
		},

		/**
		 * Removes all elements from the array.
		 */
		clear : function()
		{
			this._data.splice(0,this._data.length-1);
		},

        /**
         * @return {Number} size of the array
         */
		size : function()
		{
			return this._data.length;
		}
	});

    // SET
    //======================================================================

    /**
	 * Set class.
	 *
     * Extends: {@link meowEngine.Array}
	 * @class
	 */
	meowEngine.Set =
        meowEngine.Class( meowEngine.Array, /** @lends meowEngine.Set# */ {

        /** @borrows meowEngine.Array.constructor as #constructor */
		constructor : function( initSize ){

			this.Super.call( this, initSize );
		},

        /** @borrows meowEngine.Array.add as #add */
		add : function( obj ){

			if( this.indexOf(obj) == -1 ){
                this.Super.add( obj );
                return true;
            }
            return false;
		},

        /** @borrows meowEngine.Array.insertAt as #insertAt */
        insertAt : function( obj, index ){

            if( this.indexOf(obj) == -1 ){
                return this.Super.insertAt( obj, index );
            }
            return false;
        },

        /** @borrows meowEngine.Array.set as #set */
        set : function( obj, index ){

            if( this.indexOf(obj) == -1 ){
                return this.Super.set( obj, index );
            }
            return false;
        }
	});

    // RANDOM SET
    //======================================================================

    /**
	 * RandomSet class.
	 *
	 * @class
	 */
	meowEngine.RandomSet =
        meowEngine.Class( /** @lends meowEngine.RandomSet# */ {

		constructor : function( initSize ){

			this.Super.call(this, initSize);

			this._weights = [];
			this._listWeight = 0;
		},

        /**
         * Adds an element to the array.
         *
         * @param obj object, that will be added
         * @param {Number} weight weight of the element
         */
		add : function( obj , weight ){

			var l = this._data;
			var e = l.length;
			var i = parseInt( Math.random()*l );

			if( i == e ){

				l.push( obj );
				this._weights.push( weight );
			}
			else{

				l.splice( i , 0 , obj );
				this._weights.splice( i , 0 , weight );
			}

			this._listWeight += weight;
		},

        /** @borrows meowEngine.Array.remove as #remove */
		remove : function( obj ){

			var l = this._data;
			var wl = this._weights;
			var i = l.indexOf( obj );
			var w = wl[i];

			l.splice( i , 1 );
			wl.splice( i , 1 );
			this._listWeight -= w;
		},

        /**
         * Picks a random element from the random set.
         *
         * @return random element
         */
		random : function(){

			var l = this._data;
			var wl = this._weights;
			var e = l.length;
			var n = parseInt( Math.random()*this._listWeight );

			var cW = 0;
			for( var i = 0 ; i < e ; i++ ){

				// add weight to slot runner
				cW += wl[i];

				// slot found
				if( n <= cW ) return l[i];
			}

			throw "This should not happen =("
		},

        /** @borrows meowEngine.Array.clear as #clear */
		clear : function(){

			this._data.clear();
			this._weights.clear();
			this._listWeight = 0;
		},

        /**
         * Modifies the weight of an element in the random set.
         *
         * @param obj object that will be modified
         * @param {Number} newWeight new weight of the modified weight
         */
		modifyWeight : function( obj , newWeight ){

			var l = this._data;
			var wl = this._weights;
			var i = l.indexOf( obj );
			var w = wl[i];

			this._listWeight -= w;
			this._listWeight += newWeight;

			wl[i] = newWeight;
		}
	});

})();<commit_msg>removed container module, replaced by collections/set and collections/randomSet<commit_after><|endoftext|>


<commit_before>// ==UserScript==
// @name         Quick Links for OnePlus Forum Users
// @namespace    *.oneplus.net*
// @version      1.2
// @description  enter something useful
// @author       Mikasa Ackerman aka Kallen & Kevin Pei
// @match        *.oneplus.net*
// @include        *.oneplus.net*
// @grant        none
// ==/UserScript==
//ADD JQUERY SCRIPT ADAPTED FROM https://gist.github.com/eristoddle/4440713
function addJQuery(callback) {
    var script = document.createElement("script");
    script.textContent = "(" + callback.toString() + ")();";
    document.body.appendChild(script);
}

function main() {
    function closeThread(batch) {
        function getWarningMsg(option, name, title) {
            if (option == 1) {
                return '
Hi there @' + name + '!

It has come to my attention that you have created a thread to ask for invites, however that is not allowed.

The best way to receive an invite is to hang around the forums, join in on the community discussion and create quality replies and threads.

If you have any further questions, please read the following thread https://forums.oneplus.net/threads/2-rules-revisited-and-restated.78159/, or feel free to message me via the private message feature.

Thanks for your understanding!

Thread closed.
';
            }
            if (option == 2) {
                var link = prompt("Duplicate link for " + title + "? (enter 0 to skip this)");
                return '
Hi there @' + name + '!

It appears that this has already been discussed ' + (link ? ('at ' + link + '.
') : 'before.') + '
Please search in the future prior to creating a thread, so we don\'t encounter any duplicates :).

If you have any further questions, feel free to message me via the private message feature.

Thanks for your understanding!

Thread closed.
';
            }
            if (option == 3) {
                return '
Hi there @' + name + '!

It has come to my attention that you have linked to a scalper site, however that is not allowed.

OnePlus is the one and only official retailer of the OnePlus One at the moment, and buying from other sources puts people at risk of scamming and other dangers.

If you have any further questions, please read the following thread https://forums.oneplus.net/threads/5-reasons-to-not-buy-the-oneplus-one-from-scalpers.35689/, or feel free to message me via the private message feature.

Thanks for your understanding!
';
            }
            if (option == 4) {
                return '
Congrats to the winner(s)!

Thank you @' + name + ' for sharing with the OnePlus community :)

Invites given, thread closed.
';
            }
        }

        function closePost(url, message) {
            $.get(url, function(data) {
                var token = data.match(/_csrfToken: \"(.*)\"/)[1];
                var dataObject = $(data);
                var name = dataObject.find('.message:first').attr('data-author');
                var msg = getWarningMsg(message, name, dataObject.find('.titleBar:first h1').text());
                $.post(url + '/add-reply', {
                    message_html: msg,
                    _xfRelativeResolver: url,
                    last_date: Date.now(),
                    last_known_date: Date.now(),
                    _xfToken: token,
                    _xfRequestUri: url.replace("https://forums.oneplus.net", ""),
                    _xfNoRedirect: 1,
                    _xfResponseType: "json"
                }, function(data) {
                    if (data.error) {
                        alert(data.error[0]);
                        return 0;
                    }
                    $.post(url + '/quick-update', {
                        'set[discussion_open]': 1,
                        'set[sticky]': 1,
                        _xfToken: token,
                        _xfRequestUri: url.replace("https://forums.oneplus.net", ""),
                        _xfNoRedirect: 1,
                        _xfResponseType: 'json'
                    }, function(data) {
                        if (batch) {
                            modal.find('#close-messages').append('
Closed ' + (url.replace('https://forums.oneplus.net/threads/', '').replace('/', '').replace('-', ' ')) + '. Waiting 30 seconds...
');
                        } else {
                            location.reload(1);
                        }
                    });
                });
            });
        }
        var links = [];

        function runClose() {
            window.queue = [];
            for (var i = 0; i < links.length; i++) {
                var message = 0;
                while (message < 1 || message > 4) {
                    message = Number(prompt("Warning type for \"" + (links[i].replace('https://forums.oneplus.net/threads/', '').replace('/', '').replace('-', ' ')) + "\": \n1. Begging\n2. Duplicate\n3. Scalpers\n4. Contest over"));
                    if (!message) {
                        return;
                    }
                }
                window.queue.push([links[i].replace(/page-\d+/, '').split("#")[0], message]);
            }
            var thisArgs = window.queue.shift();
            closePost(thisArgs[0], thisArgs[1]);
            if (window.queue.length != 0) {
                window.closeInterval = setInterval(function() {
                    thisArgs = window.queue.shift();
                    closePost(thisArgs[0], thisArgs[1]);
                    if (window.queue.length == 0 && modal) {
                        alert('All thread(s) successfully closed!');
                        modal.remove();
                        clearInterval(window.closeInterval);
                    }
                }, 35000);
            } else {
                if (modal) {
                    alert('All thread(s) successfully closed!');
                    modal.remove();
                }
            }
        }
        if (batch) {
            var modal = $('
<form class="formOverlay xenForm">
 Autoclose

 Links:

<textarea id="postUrls" class="textCtrl" style="height: 100px;resize: none"></textarea>

<input name="upload" class="redactor_modal_btn button primary" id="redactor_insert_urls_btn" value="Close!" type="button"> Cancel

</form>
');
            modal.appendTo('body');
            modal.find('.redactor_btn_modal_close').click(function() {
                modal.remove();
            });
            modal.find('#redactor_insert_urls_btn').click(function() {
                modal.find('.button').remove();
                links = modal.find('#postUrls').val().split("\n");
                runClose();
            });
        } else {
            links.push(location.href);
            runClose();
        }
    }

    function like(method) {
        //---------------------------- CURRENT PAGE LIKING FUNCTION -------------------------------//
        function like() {
            for (k = 0; k < document.getElementsByClassName('LikeLink item control like').length; k++) {
                document.getElementsByClassName('LikeLink item control like')[k].click();
            }
        }
        //---------------------------- THREAD LIKING FUNCTION -------------------------------//
        function likeThreadPosts() {
            var links = [];
            jQuery.ajaxSetup({
                async: false
            });
            try {
                document.getElementsByClassName('PageNav')[0].getAttribute('data-last')
                var pages = parseInt(document.getElementsByClassName('PageNav')[0].getAttribute('data-last')) + 2;
            } catch (err) {
                var pages = 1;
            }
            var url = '/' + window.location.pathname.split('/')[1] + '/' + window.location.pathname.split('/')[2] + '/'
            getLikeURLs();
            likeLinks();

            function getLikeURLs() {
                for (i = 1; i <= pages; i++) {
                    $.get(url + 'page-' + i, function(data) {
                        //gets the like links from current page
                        $(data).find('a[class="LikeLink item control like"]').each(function() {
                            links.push($(this).attr('href')); // get the normalized `href` property; fastest solution
                        });
                        async: false
                    });
                }
            }

            function likeLinks() {
                var numbLinks = links.length + 2;
                for (t = 0; t <= numbLinks; t++) {
                    var token = document.getElementsByName('_xfToken')[0].getAttribute('value')
                    jQuery.ajaxSetup({
                        async: false
                    });
                    $.post(links[t], {
                        _xfToken: token,
                        _xfNoRedirect: 1,
                        _xfResponseType: 'json'
                    }, function(data) {});
                }
                alert('done');
            }
        }
        //---------------------------- FORWARD POST LIKING FUNCTION -------------------------------//
        function likeForward() {
            var links = [];
            jQuery.ajaxSetup({
                async: false
            });
            try {
                document.getElementsByClassName('PageNav')[0].getAttribute('data-last')
                var pages = parseInt(document.getElementsByClassName('PageNav')[0].getAttribute('data-last'));
            } catch (err) {
                var pages = 1;
            }
            var url = '/' + window.location.pathname.split('/')[1] + '/' + window.location.pathname.split('/')[2] + '/'
            getForward();
            likeLinks();

            function getForward() {
                for (i = parseInt(document.getElementsByClassName('PageNav')[0].getAttribute('data-end')); i <= pages; i++) {
                    $.get(url + 'page-' + i, function(data) {
                        //gets the like links from current page
                        $(data).find('a[class="LikeLink item control like"]').each(function() {
                            links.push($(this).attr('href')); // get the normalized `href` property; fastest solution
                        });
                        async: false
                    });
                }
            }

            function likeLinks() {
                var numbLinks = links.length + 2;
                for (t = 0; t <= numbLinks; t++) {
                    var token = document.getElementsByName('_xfToken')[0].getAttribute('value')
                    jQuery.ajaxSetup({
                        async: false
                    });
                    $.post(links[t], {
                        _xfToken: token,
                        _xfNoRedirect: 1,
                        _xfResponseType: 'json'
                    }, function(data) {});
                }
                alert('done');
            }
        }
        //---------------------------- ALERT LIKING FUNCTION -------------------------------//
        function likeAlert() {
            var url = 'https://forums.oneplus.net/account/alerts'
            jQuery.ajaxSetup({
                async: false
            });
            var alertPages = 5;
            var links = []; //contains all the tagged / quoted links
            getAlertLinks();
            likeLinks();
            //Gets the links of posts you've been tagged or quoted in
            function getAlertLinks() {
                for (i = 0; i <= alertPages; i++) {
                    $.get(url + '?page=' + i, function(data) {
                        $(data).find("h3:contains('tagged')").each(function(likes) {
                            alertLinks.push($(this).find("a[class='PopupItemLink']").attr('href') + 'like')
                        });
                        async: false
                    });
                }
            }
            //Likes the links stored into the array.
            function likeLinks() {
                var numbLinks = links.length + 2;
                for (t = 0; t <= numbLinks; t++) {
                    var token = document.getElementsByName('_xfToken')[0].getAttribute('value')
                    jQuery.ajaxSetup({
                        async: false
                    });
                    $.post(links[t], {
                        _xfToken: token,
                        _xfNoRedirect: 1,
                        _xfResponseType: 'json'
                    }, function(data) {});
                }
                alert('done');
            }
        }
        //---------------------------- POST LIKING MENU -------------------------------//
        function option() {
            var menu = window.prompt("Choose an option below.\n1. Like all posts on page.\n2. like all posts in thread.\n3. Like posts from this page forward");
            if (menu == 1) {
                like();
            } else if (menu == 2) {
                likeThreadPosts();
            } else if (menu == 3) {
                likeForward();
            }
        }
        if (method == "allPosts") {
            option();
        }
        if (method == "alerts") {
            likeAlert();
        }
    }

    function sidebar(title, opts) {
        var options = {
            layout: 'oneColumn'
        };
        $.extend(options, opts);
        this.wrapper = $('

');
        this.wrapper.append('

' + title + '

');
        this.content = this.wrapper.find('.custom-inner');
        this.add = function(elem, callback) {
            this.content.append(elem);
            elem.wrap('

');
            if (typeof callback != "undefined") {
                callback(elem);
            }
        }
        $('.sidebar .section:first').after(this.wrapper);
    }
    //Quick Links
    var quickLinks = new sidebar("Quick Links", {
        layout: "twoColumns"
    });
    quickLinks.add($('Edit Signature'));
    quickLinks.add($('View Invites'));
    quickLinks.add($('Start PM'));
    quickLinks.add($('Blocked People'));
    quickLinks.add($('Following'));
    quickLinks.add($('Watched Threads'));
    quickLinks.add($('Likes Received'));
    //Misc. Tools
    var miscTools = new sidebar("Misc. Tools");
    miscTools.add($('Like All Posts'), function(elem) {
        elem.click(function() {
            like('allPosts');
        });
    });
    miscTools.add($('Like Alerts'), function(elem) {
        elem.click(function() {
            like('alerts');
        });
    });
    //Mod Tools
    var moderatorTools = new sidebar("Moderator Tools");
    moderatorTools.add($('Close Current Thread'), function(elem) {
        elem.click(function() {
            closeThread(false);
        });
    });
    moderatorTools.add($('Batch Close Threads'), function(elem) {
        elem.click(function() {
            closeThread(true);
        });
    });
}
addJQuery(main);<commit_msg>Bugfix<commit_after>// ==UserScript==
// @name         Quick Links for OnePlus Forum Users
// @namespace    *.oneplus.net*
// @version      1.2
// @description  enter something useful
// @author       Mikasa Ackerman aka Kallen & Kevin Pei
// @match        *.oneplus.net*
// @include        *.oneplus.net*
// @grant        none
// ==/UserScript==
//ADD JQUERY SCRIPT ADAPTED FROM https://gist.github.com/eristoddle/4440713
function addJQuery(callback) {
    var script = document.createElement("script");
    script.textContent = "(" + callback.toString() + ")();";
    document.body.appendChild(script);
}

function main() {
    function closeThread(batch) {
        function getWarningMsg(option, name, title) {
            if (option == 1) {
                return '
Hi there @' + name + '!

It has come to my attention that you have created a thread to ask for invites, however that is not allowed.

The best way to receive an invite is to hang around the forums, join in on the community discussion and create quality replies and threads.

If you have any further questions, please read the following thread https://forums.oneplus.net/threads/2-rules-revisited-and-restated.78159/, or feel free to message me via the private message feature.

Thanks for your understanding!

Thread closed.
';
            }
            if (option == 2) {
                var link = prompt("Duplicate link for " + title + "? (enter 0 to skip this)");
                return '
Hi there @' + name + '!

It appears that this has already been discussed ' + (link ? ('at ' + link + '.
') : 'before.') + '
Please search in the future prior to creating a thread, so we don\'t encounter any duplicates :).

If you have any further questions, feel free to message me via the private message feature.

Thanks for your understanding!

Thread closed.
';
            }
            if (option == 3) {
                return '
Hi there @' + name + '!

It has come to my attention that you have linked to a scalper site, however that is not allowed.

OnePlus is the one and only official retailer of the OnePlus One at the moment, and buying from other sources puts people at risk of scamming and other dangers.

If you have any further questions, please read the following thread https://forums.oneplus.net/threads/5-reasons-to-not-buy-the-oneplus-one-from-scalpers.35689/, or feel free to message me via the private message feature.

Thanks for your understanding!
';
            }
            if (option == 4) {
                return '
Congrats to the winner(s)!

Thank you @' + name + ' for sharing with the OnePlus community :)

Invites given, thread closed.
';
            }
        }

        function closePost(url, message) {
            $.get(url, function(data) {
                var token = data.match(/_csrfToken: \"(.*)\"/)[1];
                var dataObject = $(data);
                var name = dataObject.find('.message:first').attr('data-author');
                var msg = getWarningMsg(message, name, dataObject.find('.titleBar:first h1').text());
                $.post(url + '/add-reply', {
                    message_html: msg,
                    _xfRelativeResolver: url,
                    last_date: Date.now(),
                    last_known_date: Date.now(),
                    _xfToken: token,
                    _xfRequestUri: url.replace("https://forums.oneplus.net", ""),
                    _xfNoRedirect: 1,
                    _xfResponseType: "json"
                }, function(data) {
                    if (data.error) {
                        alert(data.error[0]);
                        return 0;
                    }
                    $.post(url + '/quick-update', {
                        'set[discussion_open]': 1,
                        'set[sticky]': 1,
                        _xfToken: token,
                        _xfRequestUri: url.replace("https://forums.oneplus.net", ""),
                        _xfNoRedirect: 1,
                        _xfResponseType: 'json'
                    }, function(data) {
                        if (batch) {
                            modal.find('#close-messages').append('
Closed ' + (url.replace('https://forums.oneplus.net/threads/', '').replace('/', '').replace('-', ' ')) + '. Waiting 30 seconds...
');
                        } else {
                            location.reload(1);
                        }
                    });
                });
            });
        }
        var links = [];

        function runClose() {
            window.queue = [];
            for (var i = 0; i < links.length; i++) {
                var message = 0;
                while (message < 1 || message > 4) {
                    message = Number(prompt("Warning type for \"" + (links[i].replace('https://forums.oneplus.net/threads/', '').replace('/', '').replace('-', ' ')) + "\": \n1. Begging\n2. Duplicate\n3. Scalpers\n4. Contest over"));
                    if (!message) {
                        return;
                    }
                }
                window.queue.push([links[i].replace(/page-\d+/, '').split("#")[0], message]);
            }
            var thisArgs = window.queue.shift();
            closePost(thisArgs[0], thisArgs[1]);
            if (window.queue.length != 0) {
                window.closeInterval = setInterval(function() {
                    thisArgs = window.queue.shift();
                    closePost(thisArgs[0], thisArgs[1]);
                    if (window.queue.length == 0 && modal) {
                        alert('All thread(s) successfully closed!');
                        modal.remove();
                        clearInterval(window.closeInterval);
                    }
                }, 35000);
            } else {
                if (modal) {
                    alert('All thread(s) successfully closed!');
                    modal.remove();
                }
            }
        }
        if (batch) {
            var modal = $('
<form class="formOverlay xenForm">
 Autoclose

 Links:

<textarea id="postUrls" class="textCtrl" style="height: 100px;resize: none"></textarea>

<input name="upload" class="redactor_modal_btn button primary" id="redactor_insert_urls_btn" value="Close!" type="button"> Cancel

</form>
');
            modal.appendTo('body');
            modal.find('.redactor_btn_modal_close').click(function() {
                modal.remove();
            });
            modal.find('#redactor_insert_urls_btn').click(function() {
                modal.find('.button').remove();
                links = modal.find('#postUrls').val().split("\n");
                runClose();
            });
        } else {
            links.push(location.href);
            runClose();
        }
    }

    function like(method) {
        //---------------------------- CURRENT PAGE LIKING FUNCTION -------------------------------//
        function like() {
            for (k = 0; k < document.getElementsByClassName('LikeLink item control like').length; k++) {
                document.getElementsByClassName('LikeLink item control like')[k].click();
            }
        }
        //---------------------------- THREAD LIKING FUNCTION -------------------------------//
        function likeThreadPosts() {
            var links = [];
            jQuery.ajaxSetup({
                async: false
            });
            try {
                document.getElementsByClassName('PageNav')[0].getAttribute('data-last')
                var pages = parseInt(document.getElementsByClassName('PageNav')[0].getAttribute('data-last')) + 2;
            } catch (err) {
                var pages = 1;
            }
            var url = '/' + window.location.pathname.split('/')[1] + '/' + window.location.pathname.split('/')[2] + '/'
            getLikeURLs();
            likeLinks();

            function getLikeURLs() {
                for (i = 1; i <= pages; i++) {
                    $.get(url + 'page-' + i, function(data) {
                        //gets the like links from current page
                        $(data).find('a[class="LikeLink item control like"]').each(function() {
                            links.push($(this).attr('href')); // get the normalized `href` property; fastest solution
                        });
                        async: false
                    });
                }
            }

            function likeLinks() {
                var numbLinks = links.length + 2;
                for (t = 0; t <= numbLinks; t++) {
                    var token = document.getElementsByName('_xfToken')[0].getAttribute('value')
                    jQuery.ajaxSetup({
                        async: false
                    });
                    $.post(links[t], {
                        _xfToken: token,
                        _xfNoRedirect: 1,
                        _xfResponseType: 'json'
                    }, function(data) {});
                }
                alert('done');
            }
        }
        //---------------------------- FORWARD POST LIKING FUNCTION -------------------------------//
        function likeForward() {
            var links = [];
            jQuery.ajaxSetup({
                async: false
            });
            try {
                document.getElementsByClassName('PageNav')[0].getAttribute('data-last')
                var pages = parseInt(document.getElementsByClassName('PageNav')[0].getAttribute('data-last'));
            } catch (err) {
                var pages = 1;
            }
            var url = '/' + window.location.pathname.split('/')[1] + '/' + window.location.pathname.split('/')[2] + '/'
            getForward();
            likeLinks();

            function getForward() {
                for (i = parseInt(document.getElementsByClassName('PageNav')[0].getAttribute('data-end')); i <= pages; i++) {
                    $.get(url + 'page-' + i, function(data) {
                        //gets the like links from current page
                        $(data).find('a[class="LikeLink item control like"]').each(function() {
                            links.push($(this).attr('href')); // get the normalized `href` property; fastest solution
                        });
                        async: false
                    });
                }
            }

            function likeLinks() {
                var numbLinks = links.length + 2;
                for (t = 0; t <= numbLinks; t++) {
                    var token = document.getElementsByName('_xfToken')[0].getAttribute('value')
                    jQuery.ajaxSetup({
                        async: false
                    });
                    $.post(links[t], {
                        _xfToken: token,
                        _xfNoRedirect: 1,
                        _xfResponseType: 'json'
                    }, function(data) {});
                }
                alert('done');
            }
        }
        //---------------------------- ALERT LIKING FUNCTION -------------------------------//
        function likeAlert() {
            var url = 'https://forums.oneplus.net/account/alerts'
            jQuery.ajaxSetup({
                async: false
            });
            var alertPages = 5;
            var links = []; //contains all the tagged / quoted links
            getAlertLinks();
            likeLinks();
            //Gets the links of posts you've been tagged or quoted in
            function getAlertLinks() {
                for (i = 0; i <= alertPages; i++) {
                    $.get(url + '?page=' + i, function(data) {
                        $(data).find("h3:contains('tagged')").each(function(likes) {
                            links.push($(this).find("a[class='PopupItemLink']").attr('href') + 'like')
                        });
                        async: false
                    });
                }
            }
            //Likes the links stored into the array.
            function likeLinks() {
                var numbLinks = links.length + 2;
                for (t = 0; t <= numbLinks; t++) {
                    var token = document.getElementsByName('_xfToken')[0].getAttribute('value')
                    jQuery.ajaxSetup({
                        async: false
                    });
                    $.post(links[t], {
                        _xfToken: token,
                        _xfNoRedirect: 1,
                        _xfResponseType: 'json'
                    }, function(data) {});
                }
                alert('done');
            }
        }
        //---------------------------- POST LIKING MENU -------------------------------//
        function option() {
            var menu = window.prompt("Choose an option below.\n1. Like all posts on page.\n2. like all posts in thread.\n3. Like posts from this page forward");
            if (menu == 1) {
                like();
            } else if (menu == 2) {
                likeThreadPosts();
            } else if (menu == 3) {
                likeForward();
            }
        }
        if (method == "allPosts") {
            option();
        }
        if (method == "alerts") {
            likeAlert();
        }
    }

    function sidebar(title, opts) {
        var options = {
            layout: 'oneColumn'
        };
        $.extend(options, opts);
        this.wrapper = $('

');
        this.wrapper.append('

' + title + '

');
        this.content = this.wrapper.find('.custom-inner');
        this.add = function(elem, callback) {
            this.content.append(elem);
            elem.wrap('

');
            if (typeof callback != "undefined") {
                callback(elem);
            }
        }
        $('.sidebar .section:first').after(this.wrapper);
    }
    //Quick Links
    var quickLinks = new sidebar("Quick Links", {
        layout: "twoColumns"
    });
    quickLinks.add($('Edit Signature'));
    quickLinks.add($('View Invites'));
    quickLinks.add($('Start PM'));
    quickLinks.add($('Blocked People'));
    quickLinks.add($('Following'));
    quickLinks.add($('Watched Threads'));
    quickLinks.add($('Likes Received'));
    //Misc. Tools
    var miscTools = new sidebar("Misc. Tools");
    miscTools.add($('Like All Posts'), function(elem) {
        elem.click(function() {
            like('allPosts');
        });
    });
    miscTools.add($('Like Alerts'), function(elem) {
        elem.click(function() {
            like('alerts');
        });
    });
    //Mod Tools
    var moderatorTools = new sidebar("Moderator Tools");
    moderatorTools.add($('Close Current Thread'), function(elem) {
        elem.click(function() {
            closeThread(false);
        });
    });
    moderatorTools.add($('Batch Close Threads'), function(elem) {
        elem.click(function() {
            closeThread(true);
        });
    });
}
addJQuery(main);<|endoftext|>