<commit_before>'use strict';

// execute with `mocha test.js`

(function() {

  let expect = require(`chai`).expect,
      Listifier = require(`../lib/listify`),
      newlistifier = new Listifier();

// for functional tests
  let getText = function() {

    let Corpora = require(`common-corpus`),
        corpora = new Corpora(),
        source = corpora.texts,
        textObj = source[2], // eh.....
        blob = textObj.text();

    return {
      text: blob,
      source: textObj.name
    };

  };

  describe(`listifier`, function() {

    describe(`API`, function() {
      it(`should return a new instance with new`, function() {
        expect(newlistifier).to.be.a(`object`);
        expect(newlistifier).to.be.an.instanceof(Listifier);
      });

      it(`should return a new instance even without new`, function() {
        var listifier = Listifier();
        expect(listifier).to.be.a(`object`);
        expect(listifier).to.be.an.instanceof(Listifier);
      });

      it(`should expose a getList method`, function() {
        expect(newlistifier.getList).to.be.a(`function`);
      });
    });

    describe(`functional tests`, function() {
      let list = newlistifier.getList({text: getText()});
      it(`should return an object`, function() {
        expect(list).to.be.an(`object`);
      });
      it(`object should have a list array`, function() {
        expect(list.list).to.be.an(`array`);
        expect(list.list).to.have.length.above(0);
        expect(list.list[0]).to.be.a(`string`);
      });
      it(`object should have metadata`, function() {
        expect(list.metadata).to.be.an(`object`);
      });
    });

  });

}());
<commit_msg>minor test additions<commit_after>'use strict';

// execute with `mocha test.js`

(function() {

  let expect = require(`chai`).expect,
      Listifier = require(`../lib/listify`),
      newlistifier = new Listifier();

  // for functional tests
  let getText = function() {

    let Corpora = require(`common-corpus`),
        corpora = new Corpora(),
        source = corpora.texts,
        textObj = source[2], // eh.....
        blob = textObj.text();

    return {
      text: blob,
      source: textObj.name
    };

  };

  describe(`listifier`, function() {

    describe(`API`, function() {
      it(`should return a new instance with new`, function() {
        expect(newlistifier).to.be.a(`object`);
        expect(newlistifier).to.be.an.instanceof(Listifier);
      });

      it(`should return a new instance even without new`, function() {
        var listifier = Listifier();
        expect(listifier).to.be.a(`object`);
        expect(listifier).to.be.an.instanceof(Listifier);
      });

      it(`should expose a getList method`, function() {
        expect(newlistifier.getList).to.be.a(`function`);
      });
    });

    describe(`functional tests`, function() {
      let list = newlistifier.getList({text: getText()});
      it(`should return an object`, function() {
        expect(list).to.be.an(`object`);
      });
      describe(`object should have a list`, function() {
        it(`that is an array`, function() {
          expect(list.list).to.be.an(`array`);
        });
        // NOTE: as it currently stands, the lib will sometimes return an empty list
        // if the match is not found, for example
        // so... need some better way of testing/noting this
        // since it's a valid return case
        it(`having zero or non-zero length`, function() {
          expect(list.list).to.have.length.above(-1);
        });
        it(`and contain strings (or nothing`, function() {
          // if list.list has elements, they are all strings
          // OR it does not have elements
          expect(list.list.filter(e => typeof e === `string`)).to.have.length(list.list.length);
        });
      });
      it(`object should have metadata`, function() {
        expect(list.metadata).to.be.an(`object`);
      });
    });

  });

}());
<|endoftext|>


<commit_before>window.mwUI.Utils.Scheduler = {};

window.mwUI.Utils.Scheduler.Task = window.mwUI.Backbone.Model.extend({
  _updateOriginalSleep: function () {
    if (_.isNumber(this.get('executeInMs'))) {
      this.set('originalSleepTime', this.get('executeInMs'));
    }
  },
  decrementTime: function (time) {
    time = time || 1;
    var currentSleepTime = this.get('executeInMs');
    this.set({executeInMs: currentSleepTime - time}, {silent: true});
  },
  canBeExecuted: function () {
    return this.get('executeInMs') <= 0;
  },
  execute: function () {
    this.get('callback').apply(this.get('scope'));
    if (this.collection) {
      this.collection.remove(this);
    }
  },
  resetTime: function () {
    this.set('executeInMs', this.get('originalSleepTime'));
  },
  initialize: function () {
    this.on('change:executeInMs', this._updateOriginalSleep, this);
    this._updateOriginalSleep();
  }
});

window.mwUI.Utils.Scheduler.TaskRunner = window.mwUI.Backbone.Collection.extend({
  _timer: false,
  _stopped: false,
  _startTime: null,
  _prevValue: null,
  model: window.mwUI.Utils.Scheduler.Task,
  _step: function (timestamp) {
    var progress, delta;

    if (this.isStopped()) {
      return;
    }

    if (!this._startTime) {
      this._startTime = timestamp;
    }

    progress = timestamp - this._startTime;
    delta = this._prevValue ? progress - this._prevValue : progress;

    if (this.length > 0) {
      this.secureEach(function (task) {
        if (task.canBeExecuted()) {
          task.execute();
        } else {
          task.decrementTime(delta);
        }
      });

      this._prevValue = progress;
      window.requestAnimationFrame(this._step.bind(this));
    }
  },
  start: function () {
    this._stopped = false;
    this._startTime = null;
    this._prevValue = null;
    if (this.length > 0) {
      window.requestAnimationFrame(this._step.bind(this));
    }
  },
  isRunning: function () {
    return this.length > 0 && !this._stopped;
  },
  isStopped: function () {
    return this._stopped;
  },
  stop: function () {
    this._stopped = true;
  },
  add: function (task, executeInMs, id, scope) {
    if (typeof task === 'function') {
      task = new window.mwUI.Utils.Scheduler.Task({
        id: id || _.uniqueId('task'),
        callback: task,
        executeInMs: executeInMs,
        scope: scope || window
      });
    }

    mwUI.Backbone.Collection.prototype.add.call(this, task);

    if (task && !_.isFunction(task.get('callback'))) {
      throw new Error('[mwScheduler] Task has to be a function');
    }

    if (!this.isStopped()) {
      this.start();
    }

    return task;
  },
  remove: function (task) {
    var existingTask = this.findWhere({callback: task});
    return mwUI.Backbone.Collection.prototype.remove.call(this, existingTask || task);
  },
  get: function (task) {
    if (typeof task === 'function') {
      return this.findWhere({callback: task});
    } else {
      return mwUI.Backbone.Collection.prototype.get.apply(this, arguments);
    }
  },
  initialize: function () {
    document.addEventListener('visibilitychange', function () {
      if (document.hidden) {
        this.stop();
      } else {
        this.start();
      }
    }.bind(this));

    window.onfocus = this.start.bind(this);
    window.onblur = this.stop.bind(this);
  }
});

angular.module('mwUI.Utils')

  .service('mwScheduler', function () {
    return new window.mwUI.Utils.Scheduler.TaskRunner();
  });<commit_msg>move pause on inactive window functionality into service<commit_after>window.mwUI.Utils.Scheduler = {};

window.mwUI.Utils.Scheduler.Task = window.mwUI.Backbone.Model.extend({
  _updateOriginalSleep: function () {
    if (_.isNumber(this.get('executeInMs'))) {
      this.set('originalSleepTime', this.get('executeInMs'));
    }
  },
  decrementTime: function (time) {
    time = time || 1;
    var currentSleepTime = this.get('executeInMs');
    this.set({executeInMs: currentSleepTime - time}, {silent: true});
  },
  canBeExecuted: function () {
    return this.get('executeInMs') <= 0;
  },
  execute: function () {
    this.get('callback').apply(this.get('scope'));
    if (this.collection) {
      this.collection.remove(this);
    }
  },
  resetTime: function () {
    this.set('executeInMs', this.get('originalSleepTime'));
  },
  initialize: function () {
    this.on('change:executeInMs', this._updateOriginalSleep, this);
    this._updateOriginalSleep();
  }
});

window.mwUI.Utils.Scheduler.TaskRunner = window.mwUI.Backbone.Collection.extend({
  _timer: false,
  _stopped: false,
  _startTime: null,
  _prevValue: null,
  model: window.mwUI.Utils.Scheduler.Task,
  _step: function (timestamp) {
    var progress, delta;

    if (this.isStopped()) {
      return;
    }

    if (!this._startTime) {
      this._startTime = timestamp;
    }

    progress = timestamp - this._startTime;
    delta = this._prevValue ? progress - this._prevValue : progress;

    if (this.length > 0) {
      this.secureEach(function (task) {
        if (task.canBeExecuted()) {
          task.execute();
        } else {
          task.decrementTime(delta);
        }
      });

      this._prevValue = progress;
      window.requestAnimationFrame(this._step.bind(this));
    }
  },
  start: function () {
    this._stopped = false;
    this._startTime = null;
    this._prevValue = null;
    if (this.length > 0) {
      window.requestAnimationFrame(this._step.bind(this));
    }
  },
  isRunning: function () {
    return this.length > 0 && !this._stopped;
  },
  isStopped: function () {
    return this._stopped;
  },
  stop: function () {
    this._stopped = true;
  },
  add: function (task, executeInMs, id, scope) {
    if (typeof task === 'function') {
      task = new window.mwUI.Utils.Scheduler.Task({
        id: id || _.uniqueId('task'),
        callback: task,
        executeInMs: executeInMs,
        scope: scope || window
      });
    }

    mwUI.Backbone.Collection.prototype.add.call(this, task);

    if (task && !_.isFunction(task.get('callback'))) {
      throw new Error('[mwScheduler] Task has to be a function');
    }

    if (!this.isStopped()) {
      this.start();
    }

    return task;
  },
  remove: function (task) {
    var existingTask = this.findWhere({callback: task});
    return mwUI.Backbone.Collection.prototype.remove.call(this, existingTask || task);
  },
  get: function (task) {
    if (typeof task === 'function') {
      return this.findWhere({callback: task});
    } else {
      return mwUI.Backbone.Collection.prototype.get.apply(this, arguments);
    }
  }
});

angular.module('mwUI.Utils')

  .service('mwScheduler', function () {
    var scheduler = new window.mwUI.Utils.Scheduler.TaskRunner();

    angular.element(document).on('visibilitychange', function () {
      if (document.hidden) {
        scheduler.stop();
      } else {
        scheduler.start();
      }
    }.bind(this));

    angular.element(window).on('blur', scheduler.stop);
    angular.element(window).on('focus', scheduler.start);

    return scheduler;
  });<|endoftext|>


<commit_before>define(['jquery',
        'net/meisen/general/date/DateLibrary',
        'net/meisen/ui/gantt/svg/SvgIllustrator',
        'net/meisen/ui/svglibrary/SvgLibrary',
        'net/meisen/ui/svglibrary/LoadingCircles'], function (
        $,
        datelib,
        SvgIllustrator,
        svglib,
        loadingImage) {

  /*
   * Hidden utilities, only used within the GanttChart.
   */
  var utilities = {
    generateMap: function(mapper, names) {
      var group = this.validateArray(mapper.group);
      var label = this.validateArray(mapper.label);
      var tooltip = this.validateArray(mapper.tooltip);

      var mappedGroup = this.createArray(group.length, -1);
      var mappedLabel = this.createArray(label.length, -1);
      var mappedTooltip = this.createArray(tooltip.length, -1);

      // create the initial map
      var map = {
        start: -1,
        end: -1,
        group: mappedGroup,
        label: mappedLabel,
        tooltip: mappedTooltip,

        get: function(type, record) {

          // get the array
          var arr = null;
          if (type == 'group') {
            arr = this.group;
          } else if (type == 'label') {
            arr = this.label;
          } else if (type == 'tooltip') {
            arr = this.tooltip;
          } else {
            arr = null;
          }

          // make sure we have something
          var len = arr.length;
          if (arr == null || len == 0) {
            return [];
          } else {
            var vals = [];
            for (var i = 0; i < len; i++) {
              var val = record[arr[i]];
              vals.push(val);
            }
            return vals;
          }
        }
      };

      // get the arrays to look through
      var arrays = [
        [group, mappedGroup],
        [label, mappedLabel],
        [tooltip, mappedTooltip]
      ];

      // look-up the names and the defined maps
      $.each(names, function(idx, val) {
        if (val == mapper.startname) {
          map.start = idx;
        } else if (val == mapper.endname) {
          map.end = idx;
        }

        $.each(arrays, function(nr, pair) {
          var arrayIdx = $.inArray(val, pair[0]);
          if (arrayIdx != -1) {
            pair[1][arrayIdx] = idx;
          }
        });
      });

      // validate the result, no -1 present anymore
      var validateValue = function(value) {
        if (!$.isNumeric(value) || parseInt(value) !== value || value < 0) {
          throw Error('Mapping failed (reason: value="' + value + '", map="' + JSON.stringify(map) + '", names="' + JSON.stringify(names) + '")');
        }
      }
      $.each(map, function(key, value) {

        if ($.isFunction(value)) {
          // nothing to do
        } else if ($.isArray(value)) {
          $.each(value, function(idx, val) {
            validateValue(val);
          });
        } else {
          validateValue(value);
        }
      });

      return map;
    },

    createArray: function(length, value) {
      var res = [];

      for (var i = 0; i < length; i++) {
        res[i] = value;
      }

      return res;
    },

    validateArray: function(array) {
      var res;

      if (!$.isArray(array)) {
        res = [];
        res.push(array);
      } else {
        res = array;
      }

      return res;
    },

    initTimeaxis: function(timeaxis, map, records) {
      var start = timeaxis.start;
      var end = timeaxis.end;

      var needStart = start == null || typeof(start) == 'undefined';
      var needEnd = end == null || typeof(end) == 'undefined';

      if (needStart || needEnd) {

        // TODO! What if we have numbers
        // get the needed values
        if (records == null || typeof(records) == 'undefined' || !$.isArray(records) || records.length == 0 ||
            map == null || typeof(map) == 'undefined' || map.start == -1 || map.end == -1) {
          start = needStart ? datelib.createUTC() : start;
          end = needEnd ? datelib.createUTC(null, null, null, 23, 59, 0) : end;
        } else {
          var max = -1;
          var min = -1;

          $.each(records, function(idx, val) {
            var s = val[map.start].getTime();
            var e = val[map.end].getTime();

            if (needStart && $.isNumeric(s)) {
              min = min == -1 || min > s ? s : min;
            }

            if (needEnd && $.isNumeric(e)) {
              max = max == -1 || max < e ? e : max;
            }
          });

          // get the start if needed
          if (needStart) {
            if (min == -1 && max == -1) {
              start = datelib.createUTC();
            } else if (min == -1) {
              start = new Date(max);
              start = datelib.createUTC(start.getUTCFullYear(), start.getUTCMonth() + 1, start.getUTCDate());
            } else {
              start = new Date(min);
              start = datelib.createUTC(start.getUTCFullYear(), start.getUTCMonth() + 1, start.getUTCDate());
            }
          }

          // get the end if needed
          if (needEnd) {
            if (min == -1 && max == -1) {
              end = datelib.createUTC(null, null, null, 23, 59, 0);
            } else if (max == -1) {
              end = new Date(min);
              end = datelib.createUTC(end.getUTCFullYear(), end.getUTCMonth() + 1, end.getUTCDate(), 23, 59, 0);
            } else {
              end = new Date(max);
              end = datelib.createUTC(end.getUTCFullYear(), end.getUTCMonth() + 1, end.getUTCDate(), 23, 59, 0);
            }
          }
        }

        // set the new values
        return $.extend(true, timeaxis, { start: start, end: end });
      } else {
        return timeaxis;
      }
    }
  };

  /*
   * Default constructor...
   */
  GanttChart = function() {
  };

  /*
   * Extended prototype
   */
  GanttChart.prototype = {
    defaultCfg: {

      theme: {
        loadingBackgroundColor: '#CCCCCC',
        loadingBackgroundPosition: 'center center',
        loadingBackgroundRepeat: 'no-repeat',

        errorBackgroundColor: '#A30B1D'
      },

      illustrator: {
        factory: function() { return new SvgIllustrator() },
        config: {}
      },

      position: 'center',

      throwException: false,

      data: {
        url: null,
        postProcessor: function(data) {
          if (!$.isArray(data.names) || !$.isArray(data.records)) {
            return null;
          } else {
            return data;
          }
        },
        mapper: {
          startname: 'start',
          endname: 'end',
          group: [],
          label: [],
          tooltip: []
        },
        names: [],
        records: [],
        timeaxis: {
          start: null,
          end: null,
          granularity: 'days'
        }
      }
    },

    init: function(selector, cfg) {
      this.opts = $.extend(true, {}, this.defaultCfg, cfg);

      var selector = selector instanceof jQuery ? selector : $(selector);
      selector.children('.ganttchart').remove();

      this.container = $('

');
      this.container.addClass('ganttchart');
      this.container.css('overflow', 'hidden');
      this.container.css('position', 'relative');

      // set the positioning
      if (this.opts.position == 'center' || this.opts.position == 'left') {
        this.container.css('margin-right', 'auto');
      }
      if (this.opts.position == 'center' || this.opts.position == 'right') {
        this.container.css('margin-left', 'auto');
      }
      this.container.appendTo(selector);

      this.view = $('

');
      this.view.addClass('ganttview');
      this.view.css('position', 'absolute');
      this.view.css('overflow', 'hidden');
      this.view.css('zIndex', 0);
      this.view.appendTo(this.container);

      this.indicator = $('

');
      this.indicator.addClass('ganttloading');
      this.indicator.css('backgroundRepeat', this.opts.theme.loadingBackgroundRepeat);
      this.indicator.css('backgroundPosition', this.opts.theme.loadingBackgroundPosition);
      this.indicator.css('backgroundColor', this.opts.theme.loadingBackgroundColor);
      this.indicator.css('position', 'absolute');
      this.indicator.css('zIndex', 1000);
      svglib.setBackgroundImage(this.indicator, loadingImage);
      this.indicator.appendTo(this.container);

      this.error = $('

');
      this.error.addClass('gantterror');
      this.error.css('backgroundColor', this.opts.theme.errorBackgroundColor);
      this.error.css('position', 'absolute');
      this.error.css('zIndex', '500');
      this.error.appendTo(this.container);

      var _ref = this;
      $(this.view).on('load', function() {
        _ref.mask();
      }).on('renderStart', function() {
        _ref.mask();
      }).on('renderEnd', function() {
        _ref.unmask();
      }).on('error', function(event, data) {
        _ref.showError(data);
      }).on('changeTimeaxis', function(event, data) {
        _ref.changeTimeaxis(data.start, data.end, data.granularity, data.force);
      });

      // initialize the illustrator
      this.illustrator = this.opts.illustrator.factory();
      this.illustrator.init(this.view, this.opts.illustrator.config);
      this.illustrator.on('finishedLayouting', function() {
        _ref.view.trigger('renderEnd');
      });

      this.load();
    },

    mask: function() {
      if (this.masking != 'loading') {
        this.masking = 'loading';

        this.error.hide();
        this.indicator.show();
      }
    },

    unmask: function() {
      if (this.masking != null) {
        this.indicator.hide();
        this.error.hide();

        this.masking = null;
      }
    },

    resize: function(width, height) {
      this.container.css('width', width);
      this.container.css('height', height);

      var innerWidth = this.container.width();
      var innerHeight = this.container.height();
      this.indicator.css('width', innerWidth);
      this.indicator.css('height', innerHeight);
      this.error.css('width', innerWidth);
      this.error.css('height', innerHeight);

      // fire the resize event
      this.view.trigger('sizechanged', { width: innerWidth, height: innerHeight });
    },

    changeTimeaxis: function(start, end, granularity, force) {
      if (force || (typeof(granularity) != 'undefined' && this.opts.timeaxis.granularity != granularity)
                || (typeof(start) != 'undefined' && this.opts.timeaxis.start != start)
                || (typeof(end) != 'undefined' && this.opts.timeaxis.end != end)) {

        this.opts.timeaxis.start = typeof(start) != 'undefined' ? start : this.opts.timeaxis.start;
        this.opts.timeaxis.end = typeof(end) != 'undefined' ? end : this.opts.timeaxis.end;
        this.opts.timeaxis.granularity = typeof(granularity) != 'undefined' ? granularity : this.opts.timeaxis.granularity;

        this.render();
      }
    },

    load: function() {
      this.view.trigger('load');

      if (typeof(this.opts.data.url) == 'undefined' || this.opts.data.url == null) {
        this.render();
      } else {
        var _ref = this;
        $.getJSON(this.opts.data.url).done(function(data) {
          var postProcessedData = $.isFunction(_ref.opts.data.postProcessor) ? _ref.opts.data.postProcessor(data) : data;
          if (postProcessedData == null) {
            _ref.view.trigger('error', { error: null, message: 'Postprocessing of data failed', nr: '1001'});
          } else {
            _ref.render(postProcessedData);
          }
        }).fail(function(error) {
          _ref.view.trigger('error', { error: error, message: 'Unable to load data', nr: '1000'});
        });
      }
    },

    render: function(loaded) {

      // rendering will be started
      this.view.trigger('renderStart');

      // combine the loaded data and the data
      var data = $.extend(true, {}, this.opts.data, loaded);

      // make sure we have a valid time-axis
      var map;
      try {
        map = utilities.generateMap(data.mapper, data.names);
        utilities.initTimeaxis(data.timeaxis, map, data.records);
      } catch (error) {
        this.view.trigger('error', { error: error, message: 'Failed to initialize rendering', nr: '1002'});
        return;
      }

      // use a time-out to make sure that the mask is shown
      var _ref = this;
      window.setTimeout(function () {

        try {
          _ref.illustrator.draw(data.timeaxis, data.records, map);
        } catch (error) {
          _ref.view.trigger('error', { error: error, message: 'Failed to draw', nr: '1003'});
        }
      }, 50);
    },

    showError: function(data) {
      if (this.opts.throwException === true) {
        throw data.error;
      } else if (console && $.isFunction(console.error)) {
        console.error(data);
      }

      if (this.masking != 'error') {
        this.masking = 'error';

        this.indicator.hide();
        this.error.show();
      }
    }
  };

  /*
   * Add the plug-in functionality for jQuery
   */
  $.fn.ganttChart = function () {
    var charts = [];

    // get the arguments
    var args = Array.prototype.slice.call(arguments);

    // get the arguments
    var config = args.length == 1 && typeof(args[0]) == 'object' ? args[0] : null;

    // create a chart for each element, if we have a configuration defined

    this.each(function () {
      var el = $(this);
      var chart = el.data('ganttchart');

      if (config != null && (typeof(chart) == 'undefined' || chart == null)) {
        var chart = new GanttChart();
        chart.init(el, config);
        el.data('ganttchart', chart);
        charts.push(chart);
      } else if (config == null && typeof(chart) != 'undefined' && chart != null) {
        charts.push(chart);
      } else if (config == null && typeof(chart) != 'undefined' && chart != null) {
        chart.init(el, config);
        charts.push(chart);
      }
    });

    // make the resize function available
    this.resize = function(width, height) {
      $.each(charts, function() {
        this.resize(width, height);
      });
    };

    // make the changeGranularity function available
    this.changeTimeaxis = function(start, end, granularity, force) {
      $.each(charts, function() {
        this.changeTimeaxis(start, end, granularity, force);
      });
    };

    return this;
  };

  return GanttChart;
});<commit_msg>- removed empty line<commit_after>define(['jquery',
        'net/meisen/general/date/DateLibrary',
        'net/meisen/ui/gantt/svg/SvgIllustrator',
        'net/meisen/ui/svglibrary/SvgLibrary',
        'net/meisen/ui/svglibrary/LoadingCircles'], function (
        $,
        datelib,
        SvgIllustrator,
        svglib,
        loadingImage) {

  /*
   * Hidden utilities, only used within the GanttChart.
   */
  var utilities = {
    generateMap: function(mapper, names) {
      var group = this.validateArray(mapper.group);
      var label = this.validateArray(mapper.label);
      var tooltip = this.validateArray(mapper.tooltip);

      var mappedGroup = this.createArray(group.length, -1);
      var mappedLabel = this.createArray(label.length, -1);
      var mappedTooltip = this.createArray(tooltip.length, -1);

      // create the initial map
      var map = {
        start: -1,
        end: -1,
        group: mappedGroup,
        label: mappedLabel,
        tooltip: mappedTooltip,

        get: function(type, record) {

          // get the array
          var arr = null;
          if (type == 'group') {
            arr = this.group;
          } else if (type == 'label') {
            arr = this.label;
          } else if (type == 'tooltip') {
            arr = this.tooltip;
          } else {
            arr = null;
          }

          // make sure we have something
          var len = arr.length;
          if (arr == null || len == 0) {
            return [];
          } else {
            var vals = [];
            for (var i = 0; i < len; i++) {
              var val = record[arr[i]];
              vals.push(val);
            }
            return vals;
          }
        }
      };

      // get the arrays to look through
      var arrays = [
        [group, mappedGroup],
        [label, mappedLabel],
        [tooltip, mappedTooltip]
      ];

      // look-up the names and the defined maps
      $.each(names, function(idx, val) {
        if (val == mapper.startname) {
          map.start = idx;
        } else if (val == mapper.endname) {
          map.end = idx;
        }

        $.each(arrays, function(nr, pair) {
          var arrayIdx = $.inArray(val, pair[0]);
          if (arrayIdx != -1) {
            pair[1][arrayIdx] = idx;
          }
        });
      });

      // validate the result, no -1 present anymore
      var validateValue = function(value) {
        if (!$.isNumeric(value) || parseInt(value) !== value || value < 0) {
          throw Error('Mapping failed (reason: value="' + value + '", map="' + JSON.stringify(map) + '", names="' + JSON.stringify(names) + '")');
        }
      }
      $.each(map, function(key, value) {

        if ($.isFunction(value)) {
          // nothing to do
        } else if ($.isArray(value)) {
          $.each(value, function(idx, val) {
            validateValue(val);
          });
        } else {
          validateValue(value);
        }
      });

      return map;
    },

    createArray: function(length, value) {
      var res = [];

      for (var i = 0; i < length; i++) {
        res[i] = value;
      }

      return res;
    },

    validateArray: function(array) {
      var res;

      if (!$.isArray(array)) {
        res = [];
        res.push(array);
      } else {
        res = array;
      }

      return res;
    },

    initTimeaxis: function(timeaxis, map, records) {
      var start = timeaxis.start;
      var end = timeaxis.end;

      var needStart = start == null || typeof(start) == 'undefined';
      var needEnd = end == null || typeof(end) == 'undefined';

      if (needStart || needEnd) {

        // TODO! What if we have numbers
        // get the needed values
        if (records == null || typeof(records) == 'undefined' || !$.isArray(records) || records.length == 0 ||
            map == null || typeof(map) == 'undefined' || map.start == -1 || map.end == -1) {
          start = needStart ? datelib.createUTC() : start;
          end = needEnd ? datelib.createUTC(null, null, null, 23, 59, 0) : end;
        } else {
          var max = -1;
          var min = -1;

          $.each(records, function(idx, val) {
            var s = val[map.start].getTime();
            var e = val[map.end].getTime();

            if (needStart && $.isNumeric(s)) {
              min = min == -1 || min > s ? s : min;
            }

            if (needEnd && $.isNumeric(e)) {
              max = max == -1 || max < e ? e : max;
            }
          });

          // get the start if needed
          if (needStart) {
            if (min == -1 && max == -1) {
              start = datelib.createUTC();
            } else if (min == -1) {
              start = new Date(max);
              start = datelib.createUTC(start.getUTCFullYear(), start.getUTCMonth() + 1, start.getUTCDate());
            } else {
              start = new Date(min);
              start = datelib.createUTC(start.getUTCFullYear(), start.getUTCMonth() + 1, start.getUTCDate());
            }
          }

          // get the end if needed
          if (needEnd) {
            if (min == -1 && max == -1) {
              end = datelib.createUTC(null, null, null, 23, 59, 0);
            } else if (max == -1) {
              end = new Date(min);
              end = datelib.createUTC(end.getUTCFullYear(), end.getUTCMonth() + 1, end.getUTCDate(), 23, 59, 0);
            } else {
              end = new Date(max);
              end = datelib.createUTC(end.getUTCFullYear(), end.getUTCMonth() + 1, end.getUTCDate(), 23, 59, 0);
            }
          }
        }

        // set the new values
        return $.extend(true, timeaxis, { start: start, end: end });
      } else {
        return timeaxis;
      }
    }
  };

  /*
   * Default constructor...
   */
  GanttChart = function() {
  };

  /*
   * Extended prototype
   */
  GanttChart.prototype = {
    defaultCfg: {

      theme: {
        loadingBackgroundColor: '#CCCCCC',
        loadingBackgroundPosition: 'center center',
        loadingBackgroundRepeat: 'no-repeat',

        errorBackgroundColor: '#A30B1D'
      },

      illustrator: {
        factory: function() { return new SvgIllustrator() },
        config: {}
      },

      position: 'center',

      throwException: false,

      data: {
        url: null,
        postProcessor: function(data) {
          if (!$.isArray(data.names) || !$.isArray(data.records)) {
            return null;
          } else {
            return data;
          }
        },
        mapper: {
          startname: 'start',
          endname: 'end',
          group: [],
          label: [],
          tooltip: []
        },
        names: [],
        records: [],
        timeaxis: {
          start: null,
          end: null,
          granularity: 'days'
        }
      }
    },

    init: function(selector, cfg) {
      this.opts = $.extend(true, {}, this.defaultCfg, cfg);

      var selector = selector instanceof jQuery ? selector : $(selector);
      selector.children('.ganttchart').remove();

      this.container = $('

');
      this.container.addClass('ganttchart');
      this.container.css('overflow', 'hidden');
      this.container.css('position', 'relative');

      // set the positioning
      if (this.opts.position == 'center' || this.opts.position == 'left') {
        this.container.css('margin-right', 'auto');
      }
      if (this.opts.position == 'center' || this.opts.position == 'right') {
        this.container.css('margin-left', 'auto');
      }
      this.container.appendTo(selector);

      this.view = $('

');
      this.view.addClass('ganttview');
      this.view.css('position', 'absolute');
      this.view.css('overflow', 'hidden');
      this.view.css('zIndex', 0);
      this.view.appendTo(this.container);

      this.indicator = $('

');
      this.indicator.addClass('ganttloading');
      this.indicator.css('backgroundRepeat', this.opts.theme.loadingBackgroundRepeat);
      this.indicator.css('backgroundPosition', this.opts.theme.loadingBackgroundPosition);
      this.indicator.css('backgroundColor', this.opts.theme.loadingBackgroundColor);
      this.indicator.css('position', 'absolute');
      this.indicator.css('zIndex', 1000);
      svglib.setBackgroundImage(this.indicator, loadingImage);
      this.indicator.appendTo(this.container);

      this.error = $('

');
      this.error.addClass('gantterror');
      this.error.css('backgroundColor', this.opts.theme.errorBackgroundColor);
      this.error.css('position', 'absolute');
      this.error.css('zIndex', '500');
      this.error.appendTo(this.container);

      var _ref = this;
      $(this.view).on('load', function() {
        _ref.mask();
      }).on('renderStart', function() {
        _ref.mask();
      }).on('renderEnd', function() {
        _ref.unmask();
      }).on('error', function(event, data) {
        _ref.showError(data);
      }).on('changeTimeaxis', function(event, data) {
        _ref.changeTimeaxis(data.start, data.end, data.granularity, data.force);
      });

      // initialize the illustrator
      this.illustrator = this.opts.illustrator.factory();
      this.illustrator.init(this.view, this.opts.illustrator.config);
      this.illustrator.on('finishedLayouting', function() {
        _ref.view.trigger('renderEnd');
      });

      this.load();
    },

    mask: function() {
      if (this.masking != 'loading') {
        this.masking = 'loading';

        this.error.hide();
        this.indicator.show();
      }
    },

    unmask: function() {
      if (this.masking != null) {
        this.indicator.hide();
        this.error.hide();

        this.masking = null;
      }
    },

    resize: function(width, height) {
      this.container.css('width', width);
      this.container.css('height', height);

      var innerWidth = this.container.width();
      var innerHeight = this.container.height();
      this.indicator.css('width', innerWidth);
      this.indicator.css('height', innerHeight);
      this.error.css('width', innerWidth);
      this.error.css('height', innerHeight);

      // fire the resize event
      this.view.trigger('sizechanged', { width: innerWidth, height: innerHeight });
    },

    changeTimeaxis: function(start, end, granularity, force) {
      if (force || (typeof(granularity) != 'undefined' && this.opts.timeaxis.granularity != granularity)
                || (typeof(start) != 'undefined' && this.opts.timeaxis.start != start)
                || (typeof(end) != 'undefined' && this.opts.timeaxis.end != end)) {

        this.opts.timeaxis.start = typeof(start) != 'undefined' ? start : this.opts.timeaxis.start;
        this.opts.timeaxis.end = typeof(end) != 'undefined' ? end : this.opts.timeaxis.end;
        this.opts.timeaxis.granularity = typeof(granularity) != 'undefined' ? granularity : this.opts.timeaxis.granularity;

        this.render();
      }
    },

    load: function() {
      this.view.trigger('load');

      if (typeof(this.opts.data.url) == 'undefined' || this.opts.data.url == null) {
        this.render();
      } else {
        var _ref = this;
        $.getJSON(this.opts.data.url).done(function(data) {
          var postProcessedData = $.isFunction(_ref.opts.data.postProcessor) ? _ref.opts.data.postProcessor(data) : data;
          if (postProcessedData == null) {
            _ref.view.trigger('error', { error: null, message: 'Postprocessing of data failed', nr: '1001'});
          } else {
            _ref.render(postProcessedData);
          }
        }).fail(function(error) {
          _ref.view.trigger('error', { error: error, message: 'Unable to load data', nr: '1000'});
        });
      }
    },

    render: function(loaded) {

      // rendering will be started
      this.view.trigger('renderStart');

      // combine the loaded data and the data
      var data = $.extend(true, {}, this.opts.data, loaded);

      // make sure we have a valid time-axis
      var map;
      try {
        map = utilities.generateMap(data.mapper, data.names);
        utilities.initTimeaxis(data.timeaxis, map, data.records);
      } catch (error) {
        this.view.trigger('error', { error: error, message: 'Failed to initialize rendering', nr: '1002'});
        return;
      }

      // use a time-out to make sure that the mask is shown
      var _ref = this;
      window.setTimeout(function () {

        try {
          _ref.illustrator.draw(data.timeaxis, data.records, map);
        } catch (error) {
          _ref.view.trigger('error', { error: error, message: 'Failed to draw', nr: '1003'});
        }
      }, 50);
    },

    showError: function(data) {
      if (this.opts.throwException === true) {
        throw data.error;
      } else if (console && $.isFunction(console.error)) {
        console.error(data);
      }

      if (this.masking != 'error') {
        this.masking = 'error';

        this.indicator.hide();
        this.error.show();
      }
    }
  };

  /*
   * Add the plug-in functionality for jQuery
   */
  $.fn.ganttChart = function () {
    var charts = [];

    // get the arguments
    var args = Array.prototype.slice.call(arguments);

    // get the arguments
    var config = args.length == 1 && typeof(args[0]) == 'object' ? args[0] : null;

    // create a chart for each element, if we have a configuration defined
    this.each(function () {
      var el = $(this);
      var chart = el.data('ganttchart');

      if (config != null && (typeof(chart) == 'undefined' || chart == null)) {
        var chart = new GanttChart();
        chart.init(el, config);
        el.data('ganttchart', chart);
        charts.push(chart);
      } else if (config == null && typeof(chart) != 'undefined' && chart != null) {
        charts.push(chart);
      } else if (config == null && typeof(chart) != 'undefined' && chart != null) {
        chart.init(el, config);
        charts.push(chart);
      }
    });

    // make the resize function available
    this.resize = function(width, height) {
      $.each(charts, function() {
        this.resize(width, height);
      });
    };

    // make the changeGranularity function available
    this.changeTimeaxis = function(start, end, granularity, force) {
      $.each(charts, function() {
        this.changeTimeaxis(start, end, granularity, force);
      });
    };

    return this;
  };

  return GanttChart;
});<|endoftext|>


<commit_before>/* global describe, it, before, beforeEach, after, afterEach */

'use strict';

var chai = require('chai');
chai.use(require('chai-string'));

var should = chai.should();

var metrics = require('../lib/metrics');

describe('Metric', function() {
    it('should set its initial state correctly', function() {
        var m = new metrics.Metric('the.key', ['tag1'], 'myhost');
        m.key.should.equal('the.key');
        m.tags.should.deep.equal(['tag1']);
        m.host.should.equal('myhost');
    });

    it('should update the timestamp with Date.now when a data point is added', function() {
        var m = new metrics.Metric();
        var now = Date.now();
        m.updateTimestamp();
        var diff = (m.timestamp * 1000) - now;
        Math.abs(diff).should.lessThan(1000); // within one second
    });
    it('should update the timestamp when a data point is added with a timestamp in ms', function() {
        var m = new metrics.Metric();
        m.updateTimestamp(123000);
        m.timestamp.should.equal(123);
    });
});

describe('Gauge', function() {
    it('should extend Metric', function() {
        var g = new metrics.Gauge();
        g.updateTimestamp.should.be.a('function');
    });

    it('should flush correctly', function() {
        var g = new metrics.Gauge('the.key', ['mytag'], 'myhost');
        g.addPoint(1);
        var f = g.flush();
        f.should.have.length(1);
        f[0].should.have.deep.property('metric', 'the.key');
        f[0].should.have.deep.property('tags[0]', 'mytag');
        f[0].should.have.deep.property('host', 'myhost');
        f[0].should.have.deep.property('type', 'gauge');
        f[0].should.have.deep.property('points[0][0]', g.timestamp);
        f[0].should.have.deep.property('points[0][1]', 1);
    });

    it('should flush correctly when given timestamp', function() {
        var g = new metrics.Gauge('the.key', ['mytag'], 'myhost');
        g.addPoint(1, 123000);
        var f = g.flush();
        f.should.have.length(1);
        f[0].should.have.deep.property('metric', 'the.key');
        f[0].should.have.deep.property('tags[0]', 'mytag');
        f[0].should.have.deep.property('host', 'myhost');
        f[0].should.have.deep.property('type', 'gauge');
        f[0].should.have.deep.property('points[0][0]', 123);
        f[0].should.have.deep.property('points[0][1]', 1);
    });
});

describe('Counter', function() {
    it('should extend Metric', function() {
        var g = new metrics.Counter();
        g.updateTimestamp.should.be.a('function');
    });

    it('should flush correctly', function() {
        var g = new metrics.Counter('the.key', ['mytag'], 'myhost');
        g.addPoint(1);
        var f = g.flush();
        f.should.have.length(1);
        f[0].should.have.deep.property('metric', 'the.key');
        f[0].should.have.deep.property('tags[0]', 'mytag');
        f[0].should.have.deep.property('host', 'myhost');
        f[0].should.have.deep.property('type', 'counter');
        f[0].should.have.deep.property('points[0][0]', g.timestamp);
        f[0].should.have.deep.property('points[0][1]', 1);
    });

    it('should flush correctly', function() {
        var g = new metrics.Counter('the.key', ['mytag'], 'myhost');
        g.addPoint(1, 123000);
        var f = g.flush();
        f.should.have.length(1);
        f[0].should.have.deep.property('metric', 'the.key');
        f[0].should.have.deep.property('tags[0]', 'mytag');
        f[0].should.have.deep.property('host', 'myhost');
        f[0].should.have.deep.property('type', 'counter');
        f[0].should.have.deep.property('points[0][0]', 123);
        f[0].should.have.deep.property('points[0][1]', 1);
    });
});

describe('Histogram', function() {
    it('should extend Metric', function() {
        var h = new metrics.Histogram();
        h.updateTimestamp.should.be.a('function');
    });

    it('should report the min and max of all values', function() {
        var h = new metrics.Histogram('hist');
        var f = h.flush();

        f.should.have.deep.property('[0].metric', 'hist.min');
        f.should.have.deep.property('[0].points[0][1]', Infinity);
        f.should.have.deep.property('[1].metric', 'hist.max');
        f.should.have.deep.property('[1].points[0][1]', -Infinity);

        h.addPoint(23);

        f = h.flush();
        f.should.have.deep.property('[0].metric', 'hist.min');
        f.should.have.deep.property('[0].points[0][1]', 23);
        f.should.have.deep.property('[1].metric', 'hist.max');
        f.should.have.deep.property('[1].points[0][1]', 23);
    });

    it('should report a sum of all values', function() {
        var h = new metrics.Histogram('hist');
        var f = h.flush();

        f.should.have.deep.property('[2].metric', 'hist.sum');
        f.should.have.deep.property('[2].points[0][1]', 0);

        h.addPoint(2);
        h.addPoint(3);

        f = h.flush();
        f.should.have.deep.property('[2].metric', 'hist.sum');
        f.should.have.deep.property('[2].points[0][1]', 5);
    });

    it('should report the number of samples (count)', function() {
        var h = new metrics.Histogram('hist');
        var f = h.flush();

        f.should.have.deep.property('[3].metric', 'hist.count');
        f.should.have.deep.property('[3].points[0][1]', 0);

        h.addPoint(2);
        h.addPoint(3);

        f = h.flush();
        f.should.have.deep.property('[3].metric', 'hist.count');
        f.should.have.deep.property('[3].points[0][1]', 2);
    });

    it('should report the average', function() {
        var h = new metrics.Histogram('hist');
        var f = h.flush();

        f.should.have.deep.property('[4].metric', 'hist.avg');
        f.should.have.deep.property('[4].points[0][1]', 0);

        h.addPoint(2);
        h.addPoint(3);

        f = h.flush();
        f.should.have.deep.property('[4].metric', 'hist.avg');
        f.should.have.deep.property('[4].points[0][1]', 2.5);
    });

    it('should report the correct percentiles', function() {
        var h = new metrics.Histogram('hist');
        h.addPoint(1);
        var f = h.flush();

        f.should.have.deep.property('[5].metric', 'hist.75percentile');
        f.should.have.deep.property('[5].points[0][1]', 1);
        f.should.have.deep.property('[6].metric', 'hist.85percentile');
        f.should.have.deep.property('[6].points[0][1]', 1);
        f.should.have.deep.property('[7].metric', 'hist.95percentile');
        f.should.have.deep.property('[7].points[0][1]', 1);
        f.should.have.deep.property('[8].metric', 'hist.99percentile');
        f.should.have.deep.property('[8].points[0][1]', 1);

        // Create 100 samples from [1..100] so we can
        // verify the calculated percentiles.
        for (var i = 2; i <= 100; i++) {
            h.addPoint(i);
        }
        f = h.flush();

        f.should.have.deep.property('[5].metric', 'hist.75percentile');
        f.should.have.deep.property('[5].points[0][1]', 75);
        f.should.have.deep.property('[6].metric', 'hist.85percentile');
        f.should.have.deep.property('[6].points[0][1]', 85);
        f.should.have.deep.property('[7].metric', 'hist.95percentile');
        f.should.have.deep.property('[7].points[0][1]', 95);
        f.should.have.deep.property('[8].metric', 'hist.99percentile');
        f.should.have.deep.property('[8].points[0][1]', 99);
    });
});
<commit_msg>fix tests for [f6eea7f]<commit_after>/* global describe, it, before, beforeEach, after, afterEach */

'use strict';

var chai = require('chai');
chai.use(require('chai-string'));

var should = chai.should();

var metrics = require('../lib/metrics');

describe('Metric', function() {
    it('should set its initial state correctly', function() {
        var m = new metrics.Metric('the.key', ['tag1'], 'myhost');
        m.key.should.equal('the.key');
        m.tags.should.deep.equal(['tag1']);
        m.host.should.equal('myhost');
    });

    it('should update the timestamp with Date.now when a data point is added', function() {
        var m = new metrics.Metric();
        var now = Date.now();
        m.updateTimestamp();
        var diff = (m.timestamp * 1000) - now;
        Math.abs(diff).should.lessThan(1000); // within one second
    });
    it('should update the timestamp when a data point is added with a timestamp in ms', function() {
        var m = new metrics.Metric();
        m.updateTimestamp(123000);
        m.timestamp.should.equal(123);
    });
});

describe('Gauge', function() {
    it('should extend Metric', function() {
        var g = new metrics.Gauge();
        g.updateTimestamp.should.be.a('function');
    });

    it('should flush correctly', function() {
        var g = new metrics.Gauge('the.key', ['mytag'], 'myhost');
        g.addPoint(1);
        var f = g.flush();
        f.should.have.length(1);
        f[0].should.have.deep.property('metric', 'the.key');
        f[0].should.have.deep.property('tags[0]', 'mytag');
        f[0].should.have.deep.property('host', 'myhost');
        f[0].should.have.deep.property('type', 'gauge');
        f[0].should.have.deep.property('points[0][0]', g.timestamp);
        f[0].should.have.deep.property('points[0][1]', 1);
    });

    it('should flush correctly when given timestamp', function() {
        var g = new metrics.Gauge('the.key', ['mytag'], 'myhost');
        g.addPoint(1, 123000);
        var f = g.flush();
        f.should.have.length(1);
        f[0].should.have.deep.property('metric', 'the.key');
        f[0].should.have.deep.property('tags[0]', 'mytag');
        f[0].should.have.deep.property('host', 'myhost');
        f[0].should.have.deep.property('type', 'gauge');
        f[0].should.have.deep.property('points[0][0]', 123);
        f[0].should.have.deep.property('points[0][1]', 1);
    });
});

describe('Counter', function() {
    it('should extend Metric', function() {
        var g = new metrics.Counter();
        g.updateTimestamp.should.be.a('function');
    });

    it('should flush correctly', function() {
        var g = new metrics.Counter('the.key', ['mytag'], 'myhost');
        g.addPoint(1);
        var f = g.flush();
        f.should.have.length(1);
        f[0].should.have.deep.property('metric', 'the.key');
        f[0].should.have.deep.property('tags[0]', 'mytag');
        f[0].should.have.deep.property('host', 'myhost');
        f[0].should.have.deep.property('type', 'count');
        f[0].should.have.deep.property('points[0][0]', g.timestamp);
        f[0].should.have.deep.property('points[0][1]', 1);
    });

    it('should flush correctly', function() {
        var g = new metrics.Counter('the.key', ['mytag'], 'myhost');
        g.addPoint(1, 123000);
        var f = g.flush();
        f.should.have.length(1);
        f[0].should.have.deep.property('metric', 'the.key');
        f[0].should.have.deep.property('tags[0]', 'mytag');
        f[0].should.have.deep.property('host', 'myhost');
        f[0].should.have.deep.property('type', 'count');
        f[0].should.have.deep.property('points[0][0]', 123);
        f[0].should.have.deep.property('points[0][1]', 1);
    });
});

describe('Histogram', function() {
    it('should extend Metric', function() {
        var h = new metrics.Histogram();
        h.updateTimestamp.should.be.a('function');
    });

    it('should report the min and max of all values', function() {
        var h = new metrics.Histogram('hist');
        var f = h.flush();

        f.should.have.deep.property('[0].metric', 'hist.min');
        f.should.have.deep.property('[0].points[0][1]', Infinity);
        f.should.have.deep.property('[1].metric', 'hist.max');
        f.should.have.deep.property('[1].points[0][1]', -Infinity);

        h.addPoint(23);

        f = h.flush();
        f.should.have.deep.property('[0].metric', 'hist.min');
        f.should.have.deep.property('[0].points[0][1]', 23);
        f.should.have.deep.property('[1].metric', 'hist.max');
        f.should.have.deep.property('[1].points[0][1]', 23);
    });

    it('should report a sum of all values', function() {
        var h = new metrics.Histogram('hist');
        var f = h.flush();

        f.should.have.deep.property('[2].metric', 'hist.sum');
        f.should.have.deep.property('[2].points[0][1]', 0);

        h.addPoint(2);
        h.addPoint(3);

        f = h.flush();
        f.should.have.deep.property('[2].metric', 'hist.sum');
        f.should.have.deep.property('[2].points[0][1]', 5);
    });

    it('should report the number of samples (count)', function() {
        var h = new metrics.Histogram('hist');
        var f = h.flush();

        f.should.have.deep.property('[3].metric', 'hist.count');
        f.should.have.deep.property('[3].points[0][1]', 0);

        h.addPoint(2);
        h.addPoint(3);

        f = h.flush();
        f.should.have.deep.property('[3].metric', 'hist.count');
        f.should.have.deep.property('[3].points[0][1]', 2);
    });

    it('should report the average', function() {
        var h = new metrics.Histogram('hist');
        var f = h.flush();

        f.should.have.deep.property('[4].metric', 'hist.avg');
        f.should.have.deep.property('[4].points[0][1]', 0);

        h.addPoint(2);
        h.addPoint(3);

        f = h.flush();
        f.should.have.deep.property('[4].metric', 'hist.avg');
        f.should.have.deep.property('[4].points[0][1]', 2.5);
    });

    it('should report the correct percentiles', function() {
        var h = new metrics.Histogram('hist');
        h.addPoint(1);
        var f = h.flush();

        f.should.have.deep.property('[5].metric', 'hist.75percentile');
        f.should.have.deep.property('[5].points[0][1]', 1);
        f.should.have.deep.property('[6].metric', 'hist.85percentile');
        f.should.have.deep.property('[6].points[0][1]', 1);
        f.should.have.deep.property('[7].metric', 'hist.95percentile');
        f.should.have.deep.property('[7].points[0][1]', 1);
        f.should.have.deep.property('[8].metric', 'hist.99percentile');
        f.should.have.deep.property('[8].points[0][1]', 1);

        // Create 100 samples from [1..100] so we can
        // verify the calculated percentiles.
        for (var i = 2; i <= 100; i++) {
            h.addPoint(i);
        }
        f = h.flush();

        f.should.have.deep.property('[5].metric', 'hist.75percentile');
        f.should.have.deep.property('[5].points[0][1]', 75);
        f.should.have.deep.property('[6].metric', 'hist.85percentile');
        f.should.have.deep.property('[6].points[0][1]', 85);
        f.should.have.deep.property('[7].metric', 'hist.95percentile');
        f.should.have.deep.property('[7].points[0][1]', 95);
        f.should.have.deep.property('[8].metric', 'hist.99percentile');
        f.should.have.deep.property('[8].points[0][1]', 99);
    });
});
<|endoftext|>


<commit_before>'use strict';
var _ = require('underscore');
var fs = require('fs');
var path = require('path');

var pluginUtils = require('ep_etherpad-lite/static/js/pluginfw/shared');

var PACKAGE_ROOT = path.dirname(require.resolve('ep_etherpad-lite/ep.json'));
var SRC_ROOT = path.normalize(PACKAGE_ROOT + '/static');
console.log('SRC_ROOT', SRC_ROOT);
console.log('PACKAGE_ROOT', PACKAGE_ROOT);

// var TMP_ROOT = SRC_ROOT+'/build';

/******* plugin definitions   ************/
var _s = JSON.stringify;
function writePluginsFile(plugins) {

  var filePaths = [];

  var clientParts = _(plugins.parts)
    .filter(function(part) {
      return _(part).has('client_hooks')
    });

  var clientPlugins = {};

  _(clientParts).chain()
    .map(function(part) {
      return part.plugin
    })
    .uniq()
    .each(function(name) {
      clientPlugins[name] = _(plugins.plugins[name]).clone();
      delete clientPlugins[name]['package'];
    });

  _.each(clientPlugins, function(conf, name) {
    console.log('\n *** ' + name);

    _.each(conf.parts, function(part) {
      if (part.client_hooks) {
        _.each(part.client_hooks, function(fnPath, evName) {
          var pathAndFn = fnPath.split(':');
          var includePath = pathAndFn[0];
          var absPath = PACKAGE_ROOT + '/../node_modules/' + includePath;
          var relPath = path.relative(SRC_ROOT, absPath);

          if (filePaths.indexOf(relPath) !== -1) {
            debugger;
            return;
          }
          filePaths.push(relPath);
          // require();

          var fnName = pathAndFn.length == 2 ? pathAndFn[1] : evName;
          console.log('hook: ' + evName, relPath, '@fn: ' + fnName);
        });
      }

    });

  });

  var buf = '/*** AUTO GENERATED CLIENT SIDE INCLUDES ***/\n\n';
  var lines = _.map(filePaths, function(p) {
    return "require ('" + p + "');";
  });
  buf += lines.join('\n') + '\n';

  console.log(buf);

  return;

// var definitions = JSON.stringify({
//   "plugins": clientPlugins,
//   "parts": clientParts
// }, 2, 2);
// console.log(definitions);
}

var pluginDefsPath = path.normalize(PACKAGE_ROOT + '/../var/plugin-definitions.json');
var pluginsDefs = fs.readFileSync(pluginDefsPath, {
  encoding: 'utf8'
});
pluginsDefs = JSON.parse(pluginsDefs);
writePluginsFile(pluginsDefs);

/*** mangle ace to include CSS and JS ***/

//get abs path by module resolver
var aceSrc = require.resolve('ep_etherpad-lite/static/js/ace');

// replacement for Minify.js
var data = fs.readFileSync(aceSrc, {
  encoding: 'utf8'
});

// Find all includes in ace.js and embed them
var founds = data.match(/\$\$INCLUDE_[a-zA-Z_]+\("[^"]*"\)/gi);

data += '\n\n\n\n';
data += '/*----------- AUTO_GENERATED CODE BELOW -----------*/;\n';
data += '\n\n\n\n';
data += 'Ace2Editor.EMBEDED = Ace2Editor.EMBEDED || {};\n';
data += '\n\n\n\n';

// Always include the require kernel.
// founds.push('$$INCLUDE_JS("../static/js/require-kernel.js")');
var RequireKernel = require('etherpad-require-kernel');

// data += 'Ace2Editor.EMBEDED[' + JSON.stringify('../static/js/require-kernel.js') + '] = '
//   + JSON.stringify(RequireKernel.kernelSource) + ';\n';
data += 'Ace2Editor.EMBEDED[' + JSON.stringify('../static/js/require-kernel.js') + '] = '
  + JSON.stringify(' ') + ';\n';

// Request the contents of the included file on the server-side and write
// them into the file.
_.each(founds, function(item) {
  var filename = item.match(/"([^"]*)"/)[1];
  var filePath = path.normalize(SRC_ROOT + '/' + filename);
  var contents = fs.readFileSync(filePath, {
    encoding: 'utf8'
  });
  // console.log(filePath, contents);

  data += 'Ace2Editor.EMBEDED[' + JSON.stringify(filename) + '] = '
    + JSON.stringify(contents) + ';\n';
});

//console.log(data);
var destPath = SRC_ROOT + '/js/__ace_build.js';
fs.writeFileSync(destPath, data, {
  encoding: 'utf8'
});
console.log(aceSrc + ' transformed to ' + destPath);<commit_msg>including in boot makes it work<commit_after>'use strict';
var _ = require('underscore');
var fs = require('fs');
var path = require('path');

var pluginUtils = require('ep_etherpad-lite/static/js/pluginfw/shared');

var PACKAGE_ROOT = path.dirname(require.resolve('ep_etherpad-lite/ep.json'));
var SRC_ROOT = path.normalize(PACKAGE_ROOT + '/static');
console.log('SRC_ROOT', SRC_ROOT);
console.log('PACKAGE_ROOT', PACKAGE_ROOT);

// var TMP_ROOT = SRC_ROOT+'/build';

/******* plugin definitions   ************/
var _s = JSON.stringify;
function writePluginsFile(plugins) {

  var filePaths = [];

  var clientParts = _(plugins.parts)
    .filter(function(part) {
      return _(part).has('client_hooks')
    });

  var clientPlugins = {};

  _(clientParts).chain()
    .map(function(part) {
      return part.plugin
    })
    .uniq()
    .each(function(name) {
      clientPlugins[name] = _(plugins.plugins[name]).clone();
      delete clientPlugins[name]['package'];
    });

  _.each(clientPlugins, function(conf, name) {
    console.log('\n *** ' + name);

    _.each(conf.parts, function(part) {
      if (part.client_hooks) {
        _.each(part.client_hooks, function(fnPath, evName) {
          var pathAndFn = fnPath.split(':');
          var includePath = pathAndFn[0];
          var absPath = PACKAGE_ROOT + '/../node_modules/' + includePath;
          var relPath = path.relative(SRC_ROOT + '/js', absPath);

          if (filePaths.indexOf(relPath) !== -1) {
            debugger;
            return;
          }
          filePaths.push(relPath);
          // require();

          var fnName = pathAndFn.length == 2 ? pathAndFn[1] : evName;
          console.log('hook: ' + evName, relPath, '@fn: ' + fnName);
        });
      }

    });

  });

  var buf = '/*** AUTO GENERATED CLIENT SIDE INCLUDES ***/\n\n';
  var lines = _.map(filePaths, function(p) {
    return "require ('" + p + "');";
  });
  buf += lines.join('\n') + '\n';

  console.log(buf);

  var destPath = SRC_ROOT + '/js/__client_hooks.js';
  fs.writeFileSync(destPath, buf, {
    encoding: 'utf8'
  });

  return;

// var definitions = JSON.stringify({
//   "plugins": clientPlugins,
//   "parts": clientParts
// }, 2, 2);
// console.log(definitions);
}

var pluginDefsPath = path.normalize(PACKAGE_ROOT + '/../var/plugin-definitions.json');
var pluginsDefs = fs.readFileSync(pluginDefsPath, {
  encoding: 'utf8'
});
pluginsDefs = JSON.parse(pluginsDefs);
writePluginsFile(pluginsDefs);

/*** mangle ace to include CSS and JS ***/

//get abs path by module resolver
var aceSrc = require.resolve('ep_etherpad-lite/static/js/ace');

// replacement for Minify.js
var data = fs.readFileSync(aceSrc, {
  encoding: 'utf8'
});

// Find all includes in ace.js and embed them
var founds = data.match(/\$\$INCLUDE_[a-zA-Z_]+\("[^"]*"\)/gi);

data += '\n\n\n\n';
data += '/*----------- AUTO_GENERATED CODE BELOW -----------*/;\n';
data += '\n\n\n\n';
data += 'Ace2Editor.EMBEDED = Ace2Editor.EMBEDED || {};\n';
data += '\n\n\n\n';

// Always include the require kernel.
// founds.push('$$INCLUDE_JS("../static/js/require-kernel.js")');
var RequireKernel = require('etherpad-require-kernel');

// data += 'Ace2Editor.EMBEDED[' + JSON.stringify('../static/js/require-kernel.js') + '] = '
//   + JSON.stringify(RequireKernel.kernelSource) + ';\n';
data += 'Ace2Editor.EMBEDED[' + JSON.stringify('../static/js/require-kernel.js') + '] = '
  + JSON.stringify(' ') + ';\n';

// Request the contents of the included file on the server-side and write
// them into the file.
_.each(founds, function(item) {
  var filename = item.match(/"([^"]*)"/)[1];
  var filePath = path.normalize(SRC_ROOT + '/' + filename);
  var contents = fs.readFileSync(filePath, {
    encoding: 'utf8'
  });
  // console.log(filePath, contents);

  data += 'Ace2Editor.EMBEDED[' + JSON.stringify(filename) + '] = '
    + JSON.stringify(contents) + ';\n';
});

//console.log(data);
var destPath = SRC_ROOT + '/js/__ace_build.js';
fs.writeFileSync(destPath, data, {
  encoding: 'utf8'
});
console.log(aceSrc + ' transformed to ' + destPath);<|endoftext|>


<commit_before>EkloreQuestions = new Mongo.Collection('ekloreQuestions');

var Schemas = {};

UniverseSchema = new SimpleSchema({
	universeId: {
		type: String,
		label: 'Univers ID'
	},
	matchingPower: {
		type: Number,
		decimal: true,
		label: 'Matching power or the universe against the question or choice'
	}
});

WorkshopSchema = new SimpleSchema({
	workshopId: {
		type: String,
		label: 'Workshop ID'
	},
	matchingPower: {
		type: Number,
		decimal: true,
		label: 'Matching power or the workshop against the question or choice'
	}
});

ChoiceSchema = new SimpleSchema({
	choiceId: {
		type: String,
		label: 'Choice ID'
	},
	label: {
		type: String,
		label: 'tradID via i18n'
	},
	pictureSource: {
		type: String,
		label: 'Url or image path',
		optional: true
	},
	universesLinked: {
		type: [UniverseSchema],
		label: 'List of the linked universes to the choice'
	},
	workshopsLinked: {
		type: [WorkshopSchema],
		label: 'List of the linked workshops to the choice'
	}
});

Schemas.EkloreQuestions = new SimpleSchema({
	level: {
		type: Number,
		label: 'Question level'
	},
	version: {
		type: Number,
		label: 'Question version'
	},
	choices: {
		type: [ChoiceSchema],
		label: 'Choices list',
		optional: true
	},
	deprecated: {
		type: Boolean,
		label: 'Is the question deprecated or not'
	},
	universesLinked: {
		type: [UniverseSchema],
		label: 'List of the linked universe to the question',
		optional: true
	},
	workshopsLinked: {
		type: [WorkshopSchema],
		label: 'List of the linked workshops to the question',
		optional: true
	},
	questionGroupId: {
		type: String,
		label: 'Question group ID',
		optional: true
	},
	displayType: {
		type: String,
		label: 'Question display',
		allowedValues: ['text', 'picture']
	},
	title: {
		type: String,
		label: 'Question title'
	},
	createdAt: {
		type: Date,
		label: 'Question creation date'
	}
});

EkloreQuestions.attachSchema(Schemas.EkloreQuestions);

Meteor.methods({
	addAnEkloreQuestion(data) {
		check(data.title, String);
		check(data.level, Number);
		check(data.displayType, String);
		data.version = 1;
		data.deprecated = false;
		data.createdAt = new Date();
		return EkloreQuestions.insert(data);
	},
	linkQuestionGroupToAnEkloreQuestion(data) {
		check(data, Object);
		check(data.questionGroupId, String);
		check(data.ekloreQuestionId, String);
		return EkloreQuestions.update({ _id: data.ekloreQuestionId }, {
			$set: {
				questionGroupId: data.questionGroupId
			}
		});
	},
	unlikQuestionGroupFromEkloreQuestion(data) {
		check(data, Object);
		check(data.ekloreQuestionId, String);
		return EkloreQuestions.update({ _id: data.ekloreQuestionId }, {
			$unset: {
				questionGroupId: ''
			}
		});
	},
	addWorkshopToEkloreQuestion(data) {
		check(data, Object);
		check(data.ekloreQuestionId, String);
		check(data.workshopId, String);
		check(data.matchingPower, Number);
		return EkloreQuestions.update({ _id: data.ekloreQuestionId }, {
			$push: {
				workshopsLinked: {
					workshopId: data.workshopId,
					matchingPower: data.matchingPower
				}
			}
		});
	},
	removeWorkshopFromEkloreQuestion(data) {
		check(data, Object);
		check(data.ekloreQuestionId, String);
		check(data.workshopId, String);
		return EkloreQuestions.update({ _id: data.ekloreQuestionId }, {
			$pull: {
				workshopsLinked: {
					workshopId: data.workshopId
				}
			}
		});
	},
	addUniverseToEkloreQuestion(data) {
		check(data, Object);
		check(data.ekloreQuestionId, String);
		check(data.universeId, String);
		check(data.matchingPower, Number);
		return EkloreQuestions.update({ _id: data.ekloreQuestionId }, {
			$push: {
				universesLinked: {
					universeId: data.universeId,
					matchingPower: data.matchingPower
				}
			}
		});
	},
	removeUniverseFromEkloreQuestion(data) {
		check(data, Object);
		check(data.ekloreQuestionId, String);
		check(data.universeId, String);
		return EkloreQuestions.update({ _id: data.ekloreQuestionId }, {
			$pull: {
				universesLinked: {
					universeId: data.workshopId
				}
			}
		});
	}
});
<commit_msg>Add methods and fix bugs<commit_after>EkloreQuestions = new Mongo.Collection('ekloreQuestions');

var Schemas = {};

UniverseSchema = new SimpleSchema({
	universeId: {
		type: String,
		label: 'Univers ID'
	},
	matchingPower: {
		type: Number,
		decimal: true,
		label: 'Matching power or the universe against the question or choice'
	}
});

WorkshopSchema = new SimpleSchema({
	workshopId: {
		type: String,
		label: 'Workshop ID'
	},
	matchingPower: {
		type: Number,
		decimal: true,
		label: 'Matching power or the workshop against the question or choice'
	}
});

ChoiceSchema = new SimpleSchema({
	choiceId: {
		type: String,
		label: 'Choice ID'
	},
	label: {
		type: String,
		label: 'tradID via i18n',
		optional: true
	},
	pictureSource: {
		type: String,
		label: 'Url or image path',
		optional: true
	},
	universesLinked: {
		type: [UniverseSchema],
		label: 'List of the linked universes to the choice',
		optional: true
	},
	workshopsLinked: {
		type: [WorkshopSchema],
		label: 'List of the linked workshops to the choice',
		optional: true
	}
});

Schemas.EkloreQuestions = new SimpleSchema({
	level: {
		type: Number,
		label: 'Question level'
	},
	version: {
		type: Number,
		label: 'Question version'
	},
	choices: {
		type: [ChoiceSchema],
		label: 'Choices list',
		optional: true
	},
	deprecated: {
		type: Boolean,
		label: 'Is the question deprecated or not'
	},
	universesLinked: {
		type: [UniverseSchema],
		label: 'List of the linked universe to the question',
		optional: true
	},
	workshopsLinked: {
		type: [WorkshopSchema],
		label: 'List of the linked workshops to the question',
		optional: true
	},
	questionGroupId: {
		type: String,
		label: 'Question group ID',
		optional: true
	},
	displayType: {
		type: String,
		label: 'Question display',
		allowedValues: ['text', 'picture']
	},
	title: {
		type: String,
		label: 'Question title'
	},
	createdAt: {
		type: Date,
		label: 'Question creation date'
	}
});

EkloreQuestions.attachSchema(Schemas.EkloreQuestions);

Meteor.methods({
	addAnEkloreQuestion(data) {
		check(data, Object);
		check(data.title, String);
		check(data.level, Number);
		check(data.displayType, String);
		data.version = 1;
		data.deprecated = false;
		data.createdAt = new Date();
		data.choices = [];
		for (let i = 0; i < 4; i++) {
			let choice = {
				choiceId: Random.id()
			};
			data.choices.push(choice);
		}
		return EkloreQuestions.insert(data);
	},
	updateAnEkloreQuestion(data) {
		check(data, Object);
		check(data.ekloreQuestionId, String);
		check(data.title, String);
		check(data.level, Number);
		check(data.displayType, String);
		check(data.deprecated, Boolean);
		return EkloreQuestions.update({ _id: data.ekloreQuestionId }, {
			$set: {
				title: data.title,
				level: data.level,
				deprecated: data.deprecated,
				displayType: data.displayType
			},
			$inc: {
				version: 1
			}
		});
	},
	linkQuestionGroupToAnEkloreQuestion(data) {
		check(data, Object);
		check(data.questionGroupId, String);
		check(data.ekloreQuestionId, String);
		return EkloreQuestions.update({ _id: data.ekloreQuestionId }, {
			$set: {
				questionGroupId: data.questionGroupId
			}
		});
	},
	unlikQuestionGroupFromEkloreQuestion(data) {
		check(data, Object);
		check(data.ekloreQuestionId, String);
		return EkloreQuestions.update({ _id: data.ekloreQuestionId }, {
			$unset: {
				questionGroupId: ''
			}
		});
	},
	addWorkshopToEkloreQuestion(data) {
		check(data, Object);
		check(data.ekloreQuestionId, String);
		check(data.workshopId, String);
		check(data.matchingPower, Number);
		return EkloreQuestions.update({ _id: data.ekloreQuestionId }, {
			$push: {
				workshopsLinked: {
					workshopId: data.workshopId,
					matchingPower: data.matchingPower
				}
			}
		});
	},
	removeWorkshopFromEkloreQuestion(data) {
		check(data, Object);
		check(data.ekloreQuestionId, String);
		check(data.workshopId, String);
		return EkloreQuestions.update({ _id: data.ekloreQuestionId }, {
			$pull: {
				workshopsLinked: {
					workshopId: data.workshopId
				}
			}
		});
	},
	addUniverseToEkloreQuestion(data) {
		check(data, Object);
		check(data.ekloreQuestionId, String);
		check(data.universeId, String);
		check(data.matchingPower, Number);
		return EkloreQuestions.update({ _id: data.ekloreQuestionId }, {
			$push: {
				universesLinked: {
					universeId: data.universeId,
					matchingPower: data.matchingPower
				}
			}
		});
	},
	removeUniverseFromEkloreQuestion(data) {
		check(data, Object);
		check(data.ekloreQuestionId, String);
		check(data.universeId, String);
		return EkloreQuestions.update({ _id: data.ekloreQuestionId }, {
			$pull: {
				universesLinked: {
					universeId: data.universeId
				}
			}
		});
	}
});
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015, Jozef Stefan Institute, Quintelligence d.o.o. and contributors
 * All rights reserved.
 *
 * This source code is licensed under the FreeBSD license found in the
 * LICENSE file in the root directory of this source tree.
 */

// console.log(__filename)
var la = require('qminer').la;
var assert = require('assert');
var spmat = new la.SparseMatrix([[[0,2.2]],[[2,3.3]]]);
assert(Math.abs(spmat.frob() * spmat.frob() - spmat.frob2()) < 1e-8, 'native + JS implementation test');
<commit_msg>deleted a test that didn't use mocha<commit_after><|endoftext|>


<commit_before>#!/usr/bin/env node

var argv = require('optimist').argv
var dns = require('dns')
var node_http = require('http')
var node_url = require('url')
var pcap = require("pcap")
var server = require('htracr/server')
var util = require('util')

var htracr = {
  packets: [],
  conns: {},
  msgs: {},
  server_names: {},
  pcap_session: undefined,
  drop_watcher: undefined,
  device: '',

  start_capture: function() {
    var self = this
    self.clear()
    var f = "tcp port 80"
    var b = 10
    self.pcap_session = pcap.createSession(self.device, f, (b * 1024 * 1024))
    this.setup_listeners()
    console.log("Sniffing on " + self.pcap_session.device_name)

    // Check for pcap dropped packets on an interval
    self.drop_watcher = setInterval(function () {
      var stats = self.pcap_session.stats()
      if (stats.ps_drop > 0) {
        console.log(
          "dropped packets, need larger buffer or less work to do: "
          + util.inspect(stats)
        )
      }
    }, 2000)
  },

  stop_capture: function () {
    var self = this
    if (self.pcap_session == undefined)
      return
    clearInterval(self.drop_watcher)
    self.pcap_session.close()
    self.pcap_session = undefined
    console.log("Stopped sniffing")
  },

  clear: function () {
    var self = this
    self.packets = []
    self.conns = {}
    self.msgs = {}
  },

  get_conns: function () {
    var self = this
    var got_something = false;
    var o = {}
    for (server in self.conns) {
      for (conn in self.conns[server]) {
        // weed out servers without HTTP requests in them
        item_loop:
        for (var i = 0; i < self.conns[server][conn].length; i++) {
          var item = self.conns[server][conn][i]
          if (item.what == 'http-req-start') {
            if (o[server] == undefined) {
              got_something = true
              o[server] = {}
            }
            o[server][conn] = self.conns[server][conn]
            break item_loop
          }
        }
      }
    }
    if (! got_something) {
      return null
    } else {
      return o
    }
  },

  setup_listeners: function () {
    var self = this
    var tcp_tracker = new pcap.TCP_tracker()

    // listen for packets, decode them, and feed TCP to the tracker
    self.pcap_session.on('packet', function (raw_packet) {
      var packet = pcap.decode.packet(raw_packet)
      // NOTE: ordering is important here!
      self.note_packet(packet)
      tcp_tracker.track_packet(packet)
    })

    tcp_tracker.on("start", function (session) {
      self.note_session(session, 'tcp-start')
    })

    tcp_tracker.on("retransmit", function (session, direction, seqno) {
      self.note_session(session, 'tcp-retransmit',
        {'direction': direction, 'seqno': seqno}
      )
    })

    tcp_tracker.on("end", function (session) {
      self.note_session(session, 'tcp-end')
    })

    tcp_tracker.on("reset", function (session) {
      // Right now, it's only from dst.
      self.note_session(session, 'tcp-reset')
    })

    tcp_tracker.on("syn retry", function (session) {
      self.note_session(session, 'tcp-retry')
    })

    tcp_tracker.on('http error', function (session, direction, error) {
      console.log(" HTTP parser error: " + error)
      // TODO - probably need to force this transaction to be over at this point
    })

    tcp_tracker.on('http request', function (session, http) {
      self.note_session(session, 'http-req-start', http.request)
    })

    tcp_tracker.on('http request body', function (session, http, data) {
      self.note_session(session, 'http-req-data', {length: data.length})
    })

    tcp_tracker.on('http request complete', function (session, http) {
      self.note_session(session, 'http-req-end')
    })

    tcp_tracker.on('http response', function (session, http) {
      self.note_session(session, 'http-res-start', http.response)
    })

    tcp_tracker.on('http response body', function (session, http, data) {
      self.note_session(session, 'http-res-data', {length: data.length})
    })

    tcp_tracker.on('http response complete', function (session, http) {
      self.note_session(session, 'http-res-end')
    })

  },

  note_session: function (session, what, details) {
    var self = this;
    if (! details) {
      details = {}
    }
    if (session.dst.split(":")[1] == 80) {
      var server = session.dst
      var local_port = session.src.split(":")[1]
    } else {
      var server = session.src
      var local_port = session.dst.split(":")[1]
    }
    details.time = session.current_cap_time
    details.what = what
    self.note(server, local_port, details)
  },

  note_packet: function (packet) {
    var self = this;
    var what;
    if (packet.link.ip.tcp.dport == 80) {
      var server_ip = packet.link.ip.daddr
      var server = server_ip + ":" + packet.link.ip.tcp.dport
      var local_port = packet.link.ip.tcp.sport
      what = "packet-out"
    } else {
      var server_ip = packet.link.ip.saddr
      var server = server_ip + ":" + packet.link.ip.tcp.sport
      var local_port = packet.link.ip.tcp.dport
      what = "packet-in"
    }
    if (self.server_names[server_ip] == undefined) {
      self.server_names[server_ip] = ""
      dns.reverse(server_ip, function(err, domains) {
        if (! err) {
          self.server_names[server_ip] = domains[0]
        } else {
          delete self.server_names[server_ip]
        }
      })
    }
    var detail = {
      time: packet.pcap_header.time_ms,
      what: what,
      ws: packet.link.ip.tcp.window_size,
      flags: packet.link.ip.tcp.flags,
      options: packet.link.ip.tcp.options,
      data_sz: packet.link.ip.tcp.data_bytes,
      packet_id: self.packets.length,
    }
    self.note(server, local_port, detail)
    // FIXME - encoding
    self.packets.push((packet.link.ip.tcp.data || "").toString('utf8'))
  },

  note: function (server, local_port, details) {
    if (this.conns[server] == undefined) {
      this.conns[server] = {}
    }
    var server_conn = this.conns[server]
    if (server_conn[local_port] == undefined)
      server_conn[local_port] = []
    server_conn[local_port].push(details)
  },

}

// port to listen to
var port = parseInt(argv._[2])
if (! port || port == NaN) {
  console.log("Usage: test-browser.js listen-port [device]")
  process.exit(1)
}

// device to snoop on
var device = argv._[3]
if (device) {
  htracr.device = device
}

server.start(port, htracr)
<commit_msg>update argv for newer npm<commit_after>#!/usr/bin/env node

var argv = require('optimist').argv
var dns = require('dns')
var node_http = require('http')
var node_url = require('url')
var pcap = require("pcap")
var server = require('htracr/server')
var util = require('util')

var htracr = {
  packets: [],
  conns: {},
  msgs: {},
  server_names: {},
  pcap_session: undefined,
  drop_watcher: undefined,
  device: '',

  start_capture: function() {
    var self = this
    self.clear()
    var f = "tcp port 80"
    var b = 10
    self.pcap_session = pcap.createSession(self.device, f, (b * 1024 * 1024))
    this.setup_listeners()
    console.log("Sniffing on " + self.pcap_session.device_name)

    // Check for pcap dropped packets on an interval
    self.drop_watcher = setInterval(function () {
      var stats = self.pcap_session.stats()
      if (stats.ps_drop > 0) {
        console.log(
          "dropped packets, need larger buffer or less work to do: "
          + util.inspect(stats)
        )
      }
    }, 2000)
  },

  stop_capture: function () {
    var self = this
    if (self.pcap_session == undefined)
      return
    clearInterval(self.drop_watcher)
    self.pcap_session.close()
    self.pcap_session = undefined
    console.log("Stopped sniffing")
  },

  clear: function () {
    var self = this
    self.packets = []
    self.conns = {}
    self.msgs = {}
  },

  get_conns: function () {
    var self = this
    var got_something = false;
    var o = {}
    for (server in self.conns) {
      for (conn in self.conns[server]) {
        // weed out servers without HTTP requests in them
        item_loop:
        for (var i = 0; i < self.conns[server][conn].length; i++) {
          var item = self.conns[server][conn][i]
          if (item.what == 'http-req-start') {
            if (o[server] == undefined) {
              got_something = true
              o[server] = {}
            }
            o[server][conn] = self.conns[server][conn]
            break item_loop
          }
        }
      }
    }
    if (! got_something) {
      return null
    } else {
      return o
    }
  },

  setup_listeners: function () {
    var self = this
    var tcp_tracker = new pcap.TCP_tracker()

    // listen for packets, decode them, and feed TCP to the tracker
    self.pcap_session.on('packet', function (raw_packet) {
      var packet = pcap.decode.packet(raw_packet)
      // NOTE: ordering is important here!
      self.note_packet(packet)
      tcp_tracker.track_packet(packet)
    })

    tcp_tracker.on("start", function (session) {
      self.note_session(session, 'tcp-start')
    })

    tcp_tracker.on("retransmit", function (session, direction, seqno) {
      self.note_session(session, 'tcp-retransmit',
        {'direction': direction, 'seqno': seqno}
      )
    })

    tcp_tracker.on("end", function (session) {
      self.note_session(session, 'tcp-end')
    })

    tcp_tracker.on("reset", function (session) {
      // Right now, it's only from dst.
      self.note_session(session, 'tcp-reset')
    })

    tcp_tracker.on("syn retry", function (session) {
      self.note_session(session, 'tcp-retry')
    })

    tcp_tracker.on('http error', function (session, direction, error) {
      console.log(" HTTP parser error: " + error)
      // TODO - probably need to force this transaction to be over at this point
    })

    tcp_tracker.on('http request', function (session, http) {
      self.note_session(session, 'http-req-start', http.request)
    })

    tcp_tracker.on('http request body', function (session, http, data) {
      self.note_session(session, 'http-req-data', {length: data.length})
    })

    tcp_tracker.on('http request complete', function (session, http) {
      self.note_session(session, 'http-req-end')
    })

    tcp_tracker.on('http response', function (session, http) {
      self.note_session(session, 'http-res-start', http.response)
    })

    tcp_tracker.on('http response body', function (session, http, data) {
      self.note_session(session, 'http-res-data', {length: data.length})
    })

    tcp_tracker.on('http response complete', function (session, http) {
      self.note_session(session, 'http-res-end')
    })

  },

  note_session: function (session, what, details) {
    var self = this;
    if (! details) {
      details = {}
    }
    if (session.dst.split(":")[1] == 80) {
      var server = session.dst
      var local_port = session.src.split(":")[1]
    } else {
      var server = session.src
      var local_port = session.dst.split(":")[1]
    }
    details.time = session.current_cap_time
    details.what = what
    self.note(server, local_port, details)
  },

  note_packet: function (packet) {
    var self = this;
    var what;
    if (packet.link.ip.tcp.dport == 80) {
      var server_ip = packet.link.ip.daddr
      var server = server_ip + ":" + packet.link.ip.tcp.dport
      var local_port = packet.link.ip.tcp.sport
      what = "packet-out"
    } else {
      var server_ip = packet.link.ip.saddr
      var server = server_ip + ":" + packet.link.ip.tcp.sport
      var local_port = packet.link.ip.tcp.dport
      what = "packet-in"
    }
    if (self.server_names[server_ip] == undefined) {
      self.server_names[server_ip] = ""
      dns.reverse(server_ip, function(err, domains) {
        if (! err) {
          self.server_names[server_ip] = domains[0]
        } else {
          delete self.server_names[server_ip]
        }
      })
    }
    var detail = {
      time: packet.pcap_header.time_ms,
      what: what,
      ws: packet.link.ip.tcp.window_size,
      flags: packet.link.ip.tcp.flags,
      options: packet.link.ip.tcp.options,
      data_sz: packet.link.ip.tcp.data_bytes,
      packet_id: self.packets.length,
    }
    self.note(server, local_port, detail)
    // FIXME - encoding
    self.packets.push((packet.link.ip.tcp.data || "").toString('utf8'))
  },

  note: function (server, local_port, details) {
    if (this.conns[server] == undefined) {
      this.conns[server] = {}
    }
    var server_conn = this.conns[server]
    if (server_conn[local_port] == undefined)
      server_conn[local_port] = []
    server_conn[local_port].push(details)
  },

}

// port to listen to
var port = parseInt(argv._[0])
if (! port || port == NaN) {
  console.log("Usage: test-browser.js listen-port [device]")
  process.exit(1)
}

// device to snoop on
var device = argv._[1]
if (device) {
  htracr.device = device
}

server.start(port, htracr)
<|endoftext|>


<commit_before>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const ContextDependencyHelpers = exports;

/**
 * Escapes regular expression metacharacters
 * @param {string} str String to quote
 * @returns {string} Escaped string
 */
const quotemeta = str => {
	return str.replace(/[-[\]\\/{}()*+?.^$|]/g, "\\$&");
};

const splitContextFromPrefix = prefix => {
	const idx = prefix.lastIndexOf("/");
	let context = ".";
	if (idx >= 0) {
		context = prefix.substr(0, idx);
		prefix = `.${prefix.substr(idx)}`;
	}
	return {
		context,
		prefix
	};
};

const splitQueryFromPostfix = postfix => {
	const idx = postfix.indexOf("?");
	let query = "";
	if (idx >= 0) {
		query = postfix.substr(idx);
		postfix = postfix.substr(0, idx);
	}
	return {
		postfix,
		query
	};
};

ContextDependencyHelpers.create = (
	Dep,
	range,
	param,
	expr,
	options,
	contextOptions,
	// when parser is not passed in, expressions won't be walked
	parser = null
) => {
	if (param.isTemplateString()) {
		let prefixRaw = param.quasis[0].string;
		let postfixRaw =
			param.quasis.length > 1
				? param.quasis[param.quasis.length - 1].string
				: "";

		const valueRange = param.range;
		const { context, prefix } = splitContextFromPrefix(prefixRaw);
		const { postfix, query } = splitQueryFromPostfix(postfixRaw);

		// When there are more than two quasis, the generated RegExp can be more precise
		// We join the quasis with the expression regexp
		const innerQuasis = param.quasis.slice(1, param.quasis.length - 1);
		const innerRegExp =
			options.wrappedContextRegExp.source +
			innerQuasis
				.map(q => quotemeta(q.string) + options.wrappedContextRegExp.source)
				.join("");

		// Example: `./context/pre${e}inner${e}inner2${e}post?query`
		// context: "./context"
		// prefix: "./pre"
		// innerQuasis: [BEE("inner"), BEE("inner2")]
		// (BEE = BasicEvaluatedExpression)
		// postfix: "post"
		// query: "?query"
		// regExp: /^\.\/pre.*inner.*inner2.*post$/
		const regExp = new RegExp(
			`^${quotemeta(prefix)}${innerRegExp}${quotemeta(postfix)}$`
		);
		const dep = new Dep(
			Object.assign(
				{
					request: context + query,
					recursive: options.wrappedContextRecursive,
					regExp,
					mode: "sync"
				},
				contextOptions
			),
			range,
			valueRange
		);
		dep.loc = expr.loc;
		const replaces = [];

		param.parts.forEach((part, i) => {
			if (i % 2 === 0) {
				// Quasis or merged quasi
				let range = part.range;
				let value = part.string;
				if (param.templateStringKind === "cooked") {
					value = JSON.stringify(value);
					value = value.slice(1, value.length - 1);
				}
				if (i === 0) {
					// prefix
					value = prefix;
					range = [param.range[0], part.range[1]];
					value =
						(param.templateStringKind === "cooked" ? "`" : "String.raw`") +
						value;
				} else if (i === param.parts.length - 1) {
					// postfix
					value = postfix;
					range = [part.range[0], param.range[1]];
					value = value + "`";
				} else if (
					part.expression &&
					part.expression.type === "TemplateElement" &&
					part.expression.value.raw === value
				) {
					// Shortcut when it's a single quasi and doesn't need to be replaced
					return;
				}
				replaces.push({
					range,
					value
				});
			} else {
				// Expression
				if (parser) {
					parser.walkExpression(part.expression);
				}
			}
		});

		dep.replaces = replaces;
		dep.critical =
			options.wrappedContextCritical &&
			"a part of the request of a dependency is an expression";
		return dep;
	} else if (
		param.isWrapped() &&
		((param.prefix && param.prefix.isString()) ||
			(param.postfix && param.postfix.isString()))
	) {
		let prefixRaw =
			param.prefix && param.prefix.isString() ? param.prefix.string : "";
		let postfixRaw =
			param.postfix && param.postfix.isString() ? param.postfix.string : "";
		const prefixRange =
			param.prefix && param.prefix.isString() ? param.prefix.range : null;
		const postfixRange =
			param.postfix && param.postfix.isString() ? param.postfix.range : null;
		const valueRange = param.range;
		const { context, prefix } = splitContextFromPrefix(prefixRaw);
		const { postfix, query } = splitQueryFromPostfix(postfixRaw);
		const regExp = new RegExp(
			`^${quotemeta(prefix)}${options.wrappedContextRegExp.source}${quotemeta(
				postfix
			)}$`
		);
		const dep = new Dep(
			Object.assign(
				{
					request: context + query,
					recursive: options.wrappedContextRecursive,
					regExp,
					mode: "sync"
				},
				contextOptions
			),
			range,
			valueRange
		);
		dep.loc = expr.loc;
		const replaces = [];
		if (prefixRange && prefix !== prefixRaw) {
			replaces.push({
				range: prefixRange,
				value: JSON.stringify(prefix)
			});
		}
		if (postfixRange && postfix !== postfixRaw) {
			replaces.push({
				range: postfixRange,
				value: JSON.stringify(postfix)
			});
		}
		dep.replaces = replaces;
		dep.critical =
			options.wrappedContextCritical &&
			"a part of the request of a dependency is an expression";
		return dep;
	} else {
		const dep = new Dep(
			Object.assign(
				{
					request: options.exprContextRequest,
					recursive: options.exprContextRecursive,
					regExp: options.exprContextRegExp,
					mode: "sync"
				},
				contextOptions
			),
			range,
			param.range
		);
		dep.loc = expr.loc;
		dep.critical =
			options.exprContextCritical &&
			"the request of a dependency is an expression";

		if (parser) {
			parser.walkExpression(param.expression);
		}

		return dep;
	}
};
<commit_msg>Partial update of #8294, compat layer is no longer needed<commit_after>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const ContextDependencyHelpers = exports;

/**
 * Escapes regular expression metacharacters
 * @param {string} str String to quote
 * @returns {string} Escaped string
 */
const quotemeta = str => {
	return str.replace(/[-[\]\\/{}()*+?.^$|]/g, "\\$&");
};

const splitContextFromPrefix = prefix => {
	const idx = prefix.lastIndexOf("/");
	let context = ".";
	if (idx >= 0) {
		context = prefix.substr(0, idx);
		prefix = `.${prefix.substr(idx)}`;
	}
	return {
		context,
		prefix
	};
};

const splitQueryFromPostfix = postfix => {
	const idx = postfix.indexOf("?");
	let query = "";
	if (idx >= 0) {
		query = postfix.substr(idx);
		postfix = postfix.substr(0, idx);
	}
	return {
		postfix,
		query
	};
};

ContextDependencyHelpers.create = (
	Dep,
	range,
	param,
	expr,
	options,
	contextOptions,
	parser
) => {
	if (param.isTemplateString()) {
		let prefixRaw = param.quasis[0].string;
		let postfixRaw =
			param.quasis.length > 1
				? param.quasis[param.quasis.length - 1].string
				: "";

		const valueRange = param.range;
		const { context, prefix } = splitContextFromPrefix(prefixRaw);
		const { postfix, query } = splitQueryFromPostfix(postfixRaw);

		// When there are more than two quasis, the generated RegExp can be more precise
		// We join the quasis with the expression regexp
		const innerQuasis = param.quasis.slice(1, param.quasis.length - 1);
		const innerRegExp =
			options.wrappedContextRegExp.source +
			innerQuasis
				.map(q => quotemeta(q.string) + options.wrappedContextRegExp.source)
				.join("");

		// Example: `./context/pre${e}inner${e}inner2${e}post?query`
		// context: "./context"
		// prefix: "./pre"
		// innerQuasis: [BEE("inner"), BEE("inner2")]
		// (BEE = BasicEvaluatedExpression)
		// postfix: "post"
		// query: "?query"
		// regExp: /^\.\/pre.*inner.*inner2.*post$/
		const regExp = new RegExp(
			`^${quotemeta(prefix)}${innerRegExp}${quotemeta(postfix)}$`
		);
		const dep = new Dep(
			Object.assign(
				{
					request: context + query,
					recursive: options.wrappedContextRecursive,
					regExp,
					mode: "sync"
				},
				contextOptions
			),
			range,
			valueRange
		);
		dep.loc = expr.loc;
		const replaces = [];

		param.parts.forEach((part, i) => {
			if (i % 2 === 0) {
				// Quasis or merged quasi
				let range = part.range;
				let value = part.string;
				if (param.templateStringKind === "cooked") {
					value = JSON.stringify(value);
					value = value.slice(1, value.length - 1);
				}
				if (i === 0) {
					// prefix
					value = prefix;
					range = [param.range[0], part.range[1]];
					value =
						(param.templateStringKind === "cooked" ? "`" : "String.raw`") +
						value;
				} else if (i === param.parts.length - 1) {
					// postfix
					value = postfix;
					range = [part.range[0], param.range[1]];
					value = value + "`";
				} else if (
					part.expression &&
					part.expression.type === "TemplateElement" &&
					part.expression.value.raw === value
				) {
					// Shortcut when it's a single quasi and doesn't need to be replaced
					return;
				}
				replaces.push({
					range,
					value
				});
			} else {
				// Expression
				parser.walkExpression(part.expression);
			}
		});

		dep.replaces = replaces;
		dep.critical =
			options.wrappedContextCritical &&
			"a part of the request of a dependency is an expression";
		return dep;
	} else if (
		param.isWrapped() &&
		((param.prefix && param.prefix.isString()) ||
			(param.postfix && param.postfix.isString()))
	) {
		let prefixRaw =
			param.prefix && param.prefix.isString() ? param.prefix.string : "";
		let postfixRaw =
			param.postfix && param.postfix.isString() ? param.postfix.string : "";
		const prefixRange =
			param.prefix && param.prefix.isString() ? param.prefix.range : null;
		const postfixRange =
			param.postfix && param.postfix.isString() ? param.postfix.range : null;
		const valueRange = param.range;
		const { context, prefix } = splitContextFromPrefix(prefixRaw);
		const { postfix, query } = splitQueryFromPostfix(postfixRaw);
		const regExp = new RegExp(
			`^${quotemeta(prefix)}${options.wrappedContextRegExp.source}${quotemeta(
				postfix
			)}$`
		);
		const dep = new Dep(
			Object.assign(
				{
					request: context + query,
					recursive: options.wrappedContextRecursive,
					regExp,
					mode: "sync"
				},
				contextOptions
			),
			range,
			valueRange
		);
		dep.loc = expr.loc;
		const replaces = [];
		if (prefixRange && prefix !== prefixRaw) {
			replaces.push({
				range: prefixRange,
				value: JSON.stringify(prefix)
			});
		}
		if (postfixRange && postfix !== postfixRaw) {
			replaces.push({
				range: postfixRange,
				value: JSON.stringify(postfix)
			});
		}
		dep.replaces = replaces;
		dep.critical =
			options.wrappedContextCritical &&
			"a part of the request of a dependency is an expression";
		return dep;
	} else {
		const dep = new Dep(
			Object.assign(
				{
					request: options.exprContextRequest,
					recursive: options.exprContextRecursive,
					regExp: options.exprContextRegExp,
					mode: "sync"
				},
				contextOptions
			),
			range,
			param.range
		);
		dep.loc = expr.loc;
		dep.critical =
			options.exprContextCritical &&
			"the request of a dependency is an expression";

		parser.walkExpression(param.expression);

		return dep;
	}
};
<|endoftext|>


<commit_before>var express = require('express');
var test = require("tap").test
var pixelTracker = require("../") //Load the parent directory, looks for index.js
var http = require('http')

test("testing pixel tracker",function(t){

  var app = module.exports = express.createServer();

  app.configure(function(){
    app.use(express.bodyParser());
    app.use(express.cookieParser());
    app.use(express.methodOverride());
    app.use(app.router);
    app.use(express.static(__dirname + '/public'));
  });

  pixelTracker
    .use(function(e,res){
      t.type(res.decay,'number','Decay is a number')
      t.type(res.cookies._tracker,'string','_tracker should be created for all request')
      t.notOk(res.ua,'For testing, user agent browser should be false')
      t.type(res.host,'string','host should valid')
      t.type(res.domain,'string','domain should valid')
      t.type(res.geo.ip,'string','ip should valid')
    })
    .use(function(e,res){
      t.type(res.decay,'number','Decay is a number')
      t.type(res.cookies._tracker,'string','_tracker should be created for all request')
      t.notOk(res.ua,'For testing, user agent browser should be false')
      t.type(res.host,'string','host should valid')
      t.type(res.domain,'string','domain should valid')
      t.type(res.geo.ip,'string','ip should valid')
      t.end()
    })

  app.all('/pixel',pixelTracker.middleware)
  app.listen(3000);

  http.get({host:'localhost',port:3000,path:'/pixel',agent:false},function(res){
    // Stop the server
    process.exit(0)
  })
})
<commit_msg>update test for formatting, app.close<commit_after>var express = require('express')
  , test = require('tap').test
  , tracker = require('../')

test('testing pixel tracker', function (t) {

  var app = express.createServer()

  app.configure(function () {
    app.use(express.cookieParser())
  })

  tracker
    .use(function (e, res) {
      t.type(res.decay, 'number', 'Decay is a number')
      t.type(res.cookies._tracker, 'string','_tracker should be created for all request')
      t.notOk(res.ua, 'For testing, user agent browser should be false')
      t.type(res.host, 'string', 'host should valid')
      t.type(res.domain, 'string', 'domain should valid')
      t.type(res.geo.ip, 'string', 'ip should valid')
    })
    .use(function (e, res) {
      t.type(res.decay, 'number', 'Decay is a number')
      t.type(res.cookies._tracker, 'string', '_tracker should be created for all request')
      t.notOk(res.ua, 'For testing, user agent browser should be false')
      t.type(res.host, 'string', 'host should valid')
      t.type(res.domain, 'string', 'domain should valid')
      t.type(res.geo.ip, 'string', 'ip should valid')
      t.end()
    })

  app.all('/pixel', tracker.middleware)
  app.listen(3000)

  require('http').get({
      host : 'localhost'
    , port : 3000
    , path : '/pixel'
    , agent : false
  }, function (res) {
    app.close()
  })

})
<|endoftext|>