<commit_before>/**
 * Builds document-embedded map using c2corg maps API.
 */

Ext.namespace("c2corg");

c2corg.embeddedMap = (function() {

    if (!objectsToShow) return;

    var wkt_parser = new OpenLayers.Format.WKT();
    var features = [];
    for (var i = 0, len = objectsToShow.length; i < len; i++) {
        var obj = objectsToShow[i];
        // TODO: use simplified WKT?
        var f = wkt_parser.read(obj.wkt);
        f.fid = obj.id;
        f.attributes = {type: obj.type};
        if (obj.type == "routes" || obj.type == "outings" || obj.type == "areas" || obj.type == "maps") {
            f.style = {
                strokeColor: "yellow",
                strokeWidth: 1,
                fillColor: "yellow",
                fillOpacity: 0.1
            };
        } else {
            f.style = {
                pointRadius: 10,
                externalGraphic: '/static/images/modules/' + obj.type + '_mini.png'
                // FIXME: ${type} syntax seems not to work
            };
        }
        features.push(f);
    }

    var api = new c2corg.API({lang: mapLang}); // mapLang is defined in HTML document
    api.createMap();

    var drawingLayer = api.getDrawingLayer();
    drawingLayer.addFeatures(features);

    if (features.length == 1 && features[0].geometry instanceof OpenLayers.Geometry.Point) {
        var center = features[0].geometry;
        api.map.setCenter(new OpenLayers.LonLat(center.x, center.y), 12);
    } else {
        api.map.zoomToExtent(drawingLayer.getDataExtent());
        var extent = api.map.getExtent();
    }

    var initialCenter = api.map.getCenter();
    var initialZoom = api.map.getZoom();

    var bbar = api.createBbar();

    var addPermalinkButton = function() {
        var permalinkDiv = document.createElement("div");
        permalinkDiv.id = 'permalink' + api.apiId;
        Ext.getBody().appendChild(permalinkDiv);
        api.addPermalinkControl();
        bbar.add(new Ext.Action({
            text: OpenLayers.i18n('Expand map'),
            handler: function() {
                window.open(Ext.get('permalink' + api.apiId).dom.value);
            }
        }));
    };

    var addResetButton = function() {
        bbar.add(new Ext.Action({
            text: OpenLayers.i18n('Reset'),
            handler: function() {
                var center = initialCenter.clone();
                api.map.setCenter(center.transform(api.epsg900913, api.map.getProjectionObject()),
                                  initialZoom); // FIXME: zoom changes depending on base layer resolutions nb
            }
        }));
    };

    var mappanel = Ext.apply(api.createMapPanel(), {
        id: 'mappanel',
        margins: '0 0 0 0',
        region: 'center',
        border: false,
        bbar: bbar
    });

    var layertree = Ext.apply(api.createLayerTree(), {
        region: 'west',
        width: 250,
        border: false,
        collapsible: true,
        collapseMode: 'mini',
        split: true
    });

    return {
        init: function() {
            // hide loading message
            Ext.removeNode(Ext.getDom('mapLoading'));

            new Ext.Panel({
                applyTo: 'map',
                layout: 'border',
                border: false,
                cls: 'embeddedMap',
                items: [ mappanel, layertree ]
            });

            // FIXME: done here else the zoom level is incorrect (changed when creating panel?)
            if (extent) {
                api.map.zoomToExtent(extent);
                initialZoom = api.map.getZoom();
            }

            addResetButton();
            addPermalinkButton();
        }
    };
})();

Ext.onReady(c2corg.embeddedMap.init);
<commit_msg>fix map creation bug with IE8<commit_after>/**
 * Builds document-embedded map using c2corg maps API.
 */

Ext.namespace("c2corg");

c2corg.embeddedMap = (function() {

    // mapLang and objectsToShow are global variables retrieved from template

    if (!objectsToShow) return;

    var wkt_parser = new OpenLayers.Format.WKT();
    var features = [];
    for (var i = 0, len = objectsToShow.length; i < len; i++) {
        var obj = objectsToShow[i];
        // TODO: use simplified WKT?
        var f = wkt_parser.read(obj.wkt);
        f.fid = obj.id;
        f.attributes = {type: obj.type};
        if (obj.type == "routes" || obj.type == "outings" || obj.type == "areas" || obj.type == "maps") {
            f.style = {
                strokeColor: "yellow",
                strokeWidth: 1,
                fillColor: "yellow",
                fillOpacity: 0.1
            };
        } else {
            f.style = {
                pointRadius: 10,
                externalGraphic: '/static/images/modules/' + obj.type + '_mini.png'
                // FIXME: ${type} syntax seems not to work
            };
        }
        features.push(f);
    }

    var api = new c2corg.API({lang: mapLang});

    // Creating map fails with IE if no coords is submitted,
    // so we use first object center coords
    // even if map is then recentered using features extent.
    mapCenter = features[0].geometry.getBounds().getCenterLonLat();
    mapCenter.transform(api.epsg900913, api.epsg4326);
    api.createMap({
        easting: mapCenter.lon,
        northing: mapCenter.lat,
        zoom: 12
    });

    var drawingLayer = api.getDrawingLayer();
    drawingLayer.addFeatures(features);

    var extent;
    if (features.length > 1 || !features[0].geometry instanceof OpenLayers.Geometry.Point) {
        api.map.zoomToExtent(drawingLayer.getDataExtent());
        extent = api.map.getExtent();
        // see init() function below
    }

    var initialCenter = api.map.getCenter();
    var initialZoom = api.map.getZoom();

    var bbar = api.createBbar();

    var addPermalinkButton = function() {
        var permalinkDiv = document.createElement("div");
        permalinkDiv.id = 'permalink' + api.apiId;
        Ext.getBody().appendChild(permalinkDiv);
        api.addPermalinkControl();
        bbar.add(new Ext.Action({
            text: OpenLayers.i18n('Expand map'),
            handler: function() {
                window.open(Ext.get('permalink' + api.apiId).dom.value);
            }
        }));
    };

    var addResetButton = function() {
        bbar.add(new Ext.Action({
            text: OpenLayers.i18n('Reset'),
            handler: function() {
                var center = initialCenter.clone();
                api.map.setCenter(center.transform(api.epsg900913, api.map.getProjectionObject()),
                                  initialZoom); // FIXME: zoom changes depending on base layer resolutions nb
            }
        }));
    };

    var mappanel = Ext.apply(api.createMapPanel(), {
        id: 'mappanel',
        margins: '0 0 0 0',
        region: 'center',
        border: false,
        bbar: bbar
    });

    var layertree = Ext.apply(api.createLayerTree(), {
        region: 'west',
        width: 250,
        border: false,
        collapsible: true,
        collapseMode: 'mini',
        split: true
    });

    return {
        init: function() {
            // hide loading message
            Ext.removeNode(Ext.getDom('mapLoading'));

            new Ext.Panel({
                applyTo: 'map',
                layout: 'border',
                border: false,
                cls: 'embeddedMap',
                items: [ mappanel, layertree ]
            });

            // FIXME: done here else the zoom level is incorrect (changed when creating panel?)
            if (extent) {
                api.map.zoomToExtent(extent);
                initialZoom = api.map.getZoom();
            }

            addResetButton();
            addPermalinkButton();
        }
    };
})();

Ext.onReady(c2corg.embeddedMap.init);
<|endoftext|>


<commit_before>var dateManipulations = (function() {
  function firstDayOfYear(date) {
    return moment(date).dayOfYear(1);
  }

  function lastDayOfYear(date) {
    return firstDayOfYear(date).add(1, "years").add(-1, "days");
  }

  function firstDayOfWeek(date) {
    return moment(date).day("Monday");
  }

  function lastDayOfWeek(date) {
    return firstDayOfWeek(date).add(6, "days");
  }

  function firstDayOfMonth(date) {
    return moment(date).date(1);
  }

  function lastDayOfMonth(date) {
    var daysInMonth = moment(date).daysInMonth();
    return firstDayOfMonth(date).add(daysInMonth - 1, "days");
  }

  function oneWeekAhead(date) {
    return moment(date).add("weeks", 1);
  }

  function oneMonthAhead(date) {
    return moment(date).add("months", 1);
  }

  function oneYearAhead(date) {
    return moment(date).add("years", 1);
  }

  function oneWeekBack(date) {
    return moment(date).add("weeks", -1);
  }

  function oneMonthBack(date) {
    return moment(date).add("months", -1);
  }

  function oneYearBack(date) {
    return moment(date).add("years", -1);
  }

  function dateOf(fn) {
    return function(date) {
      return fn(date).toDate();
    };
  }

  function monthPeriodContaining(date) {
    return {
      startDate: firstDayOfMonth(date).toDate(),
      endDate: lastDayOfMonth(date).toDate()
    };
  }

  function yearPeriodContaining(date) {
    return {
      startDate: firstDayOfYear(date).toDate(),
      endDate: lastDayOfYear(date).toDate()
    };
  }

  function weekPeriodContaining(date) {
    return {
      startDate: firstDayOfWeek(date).toDate(),
      endDate: lastDayOfWeek(date).toDate()
    };
  }

  return {
    oneWeekAheadOf: dateOf(oneWeekAhead),
    oneMonthAheadOf: dateOf(oneMonthAhead),
    oneYearAheadOf: dateOf(oneYearAhead),
    oneWeekBackFrom: dateOf(oneWeekBack),
    oneMonthBackFrom: dateOf(oneMonthBack),
    oneYearBackFrom: dateOf(oneYearBack),
    monthPeriodContaining: monthPeriodContaining,
    yearPeriodContaining: yearPeriodContaining,
    weekPeriodContaining: weekPeriodContaining
  };
})();<commit_msg>Fixed moment.js deprecation warning for add function<commit_after>var dateManipulations = (function() {
  function firstDayOfYear(date) {
    return moment(date).dayOfYear(1);
  }

  function lastDayOfYear(date) {
    return firstDayOfYear(date).add(1, "years").add(-1, "days");
  }

  function firstDayOfWeek(date) {
    return moment(date).day("Monday");
  }

  function lastDayOfWeek(date) {
    return firstDayOfWeek(date).add(6, "days");
  }

  function firstDayOfMonth(date) {
    return moment(date).date(1);
  }

  function lastDayOfMonth(date) {
    var daysInMonth = moment(date).daysInMonth();
    return firstDayOfMonth(date).add(daysInMonth - 1, "days");
  }

  function oneWeekAhead(date) {
    return moment(date).add(1, "weeks");
  }

  function oneMonthAhead(date) {
    return moment(date).add(1, "months");
  }

  function oneYearAhead(date) {
    return moment(date).add(1, "years");
  }

  function oneWeekBack(date) {
    return moment(date).add(-1, "weeks");
  }

  function oneMonthBack(date) {
    return moment(date).add(-1, "months");
  }

  function oneYearBack(date) {
    return moment(date).add(-1, "years");
  }

  function dateOf(fn) {
    return function(date) {
      return fn(date).toDate();
    };
  }

  function monthPeriodContaining(date) {
    return {
      startDate: firstDayOfMonth(date).toDate(),
      endDate: lastDayOfMonth(date).toDate()
    };
  }

  function yearPeriodContaining(date) {
    return {
      startDate: firstDayOfYear(date).toDate(),
      endDate: lastDayOfYear(date).toDate()
    };
  }

  function weekPeriodContaining(date) {
    return {
      startDate: firstDayOfWeek(date).toDate(),
      endDate: lastDayOfWeek(date).toDate()
    };
  }

  return {
    oneWeekAheadOf: dateOf(oneWeekAhead),
    oneMonthAheadOf: dateOf(oneMonthAhead),
    oneYearAheadOf: dateOf(oneYearAhead),
    oneWeekBackFrom: dateOf(oneWeekBack),
    oneMonthBackFrom: dateOf(oneMonthBack),
    oneYearBackFrom: dateOf(oneYearBack),
    monthPeriodContaining: monthPeriodContaining,
    yearPeriodContaining: yearPeriodContaining,
    weekPeriodContaining: weekPeriodContaining
  };
})();<|endoftext|>


<commit_before>/* eslint-disable  no-console */
const markdownlint = require('markdownlint');

const options = {
  files: process.argv.slice(2),
  config: {
    default: false,
    // resultVersion: 1,
    MD001: true,
    MD002: true,
    MD003: true,
    MD024: true,
    MD025: true
  }
};

console.log('🗒  Linted files:');
process.argv.slice(2).forEach(filePath => console.log(`    📁  ${filePath}`));

markdownlint(options, (err, result) => {
  if (err) {
    console.log('❌ Error running markdownlint');
    process.exit(1);
  }

  if (result.toString() === '') {
    process.exit(0);
  }

  console.log('\n❌  Errors:');
  result
    .toString(true)
    .split('\n')
    .forEach(error => console.log(`    ${error}`));
  process.exit(1);
});
<commit_msg>Add rules to markdownlint<commit_after>/* eslint-disable  no-console */
const markdownlint = require('markdownlint');

const options = {
  files: process.argv.slice(2),
  config: {
    default: false,
    resultVersion: 1,
    MD001: true,
    MD002: true,
    MD003: true,
    MD005: true,
    MD006: true,
    MD011: true,
    MD012: true,
    MD018: true,
    MD019: true,
    MD023: true,
    MD024: true,
    MD025: true,
    MD026: true,
    MD027: true,
    MD031: true,
    MD034: true,
    MD035: true,
    MD037: true,
    MD038: true,
    MD039: true,
    MD040: true,
    MD041: true,
    MD042: true
  }
};

console.log('🗒  Linted files:');
process.argv.slice(2).forEach(filePath => console.log(`    📁  ${filePath}`));

markdownlint(options, (err, result) => {
  if (err) {
    console.log('❌ Error running markdownlint');
    process.exit(1);
  }

  if (result.toString() === '') {
    process.exit(0);
  }

  console.log('\n❌  Errors:');
  result
    .toString(true)
    .split('\n')
    .forEach(error => console.log(`    ${error}`));
  process.exit(1);
});
<|endoftext|>


<commit_before>// Underscore-contrib (underscore.object.builders.js 0.0.1)
// (c) 2013 Michael Fogus and DocumentCloud Inc.
// Underscore-contrib may be freely distributed under the MIT license.

(function(root) {

  // Baseline setup
  // --------------

  // Establish the root object, `window` in the browser, or `global` on the server.
  var _ = root._ || require('underscore');

  // Helpers
  // -------

  // Create quick reference variables for speed access to core prototypes.
  var slice   = Array.prototype.slice,
      concat  = Array.prototype.concat;

  var existy = function(x) { return x != null; };
  var truthy = function(x) { return (x !== false) && existy(x); };
  var isAssociative = function(x) { return _.isArray(x) || _.isObject(x); };

  // Mixing in the object builders
  // ----------------------------

  _.mixin({
    // Merges two or more objects starting with the left-most and
    // applying the keys right-word
    // {any:any}* -> {any:any}
    merge: function(/* objs */){
      var dest = _.some(arguments) ? {} : null;

      if (truthy(dest)) {
        _.extend.apply(null, concat.call([dest], _.toArray(arguments)));
      }

      return dest;
    },

    // Takes an object and another object of strings to strings where the second
    // object describes the key renaming to occur in the first object.
    renameKeys: function(obj, kobj) {
      return _.reduce(kobj, function(o, nu, old) {
        if (existy(obj[old])) {
          o[nu] = obj[old];
          return o;
        }
        else
          return o;
      },
      _.omit.apply(null, concat.call([obj], _.keys(kobj))));
    },

    // Snapshots an object deeply. Based on the version by
    // [Keith Devens](http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone)
    // until we can find a more efficient and robust way to do it.
    snapshot: function(obj) {
      if(obj == null || typeof(obj) != 'object') {
        return obj;
      }

      var temp = new obj.constructor();

      for(var key in obj) {
        temp[key] = _.snapshot(obj[key]);
      }

      return temp;
    },

    // Updates the value at any depth in a nested object based on the
    // path described by the keys given.  The function provided is supplied
    // the current value and is expected to return a value for use as the
    // new value.  If no keys are provided, then the object itself is presented
    // to the given function.
    updatePath: function(obj, fun, ks) {
      if (!isAssociative(obj)) throw new TypeError("Attempted to update a non-associative object.");
      if (!existy(ks)) return fun(obj);

      var deepness = _.isArray(ks);
      var keys     = deepness ? ks : [ks];
      var ret      = deepness ? _.snapshot(obj) : _.clone(obj);
      var lastKey  = _.last(keys);
      var target   = ret;

      _.each(_.initial(keys), function(key) {
        target = target[key];
      });

      target[lastKey] = fun(target[lastKey]);
      return ret;
    }
  });

})(this);
<commit_msg>Added setPath function.  It's debateable if this should be side-effecting or not, but for now I chose to snapshot the given object instead of modifying the original<commit_after>// Underscore-contrib (underscore.object.builders.js 0.0.1)
// (c) 2013 Michael Fogus and DocumentCloud Inc.
// Underscore-contrib may be freely distributed under the MIT license.

(function(root) {

  // Baseline setup
  // --------------

  // Establish the root object, `window` in the browser, or `global` on the server.
  var _ = root._ || require('underscore');

  // Helpers
  // -------

  // Create quick reference variables for speed access to core prototypes.
  var slice   = Array.prototype.slice,
      concat  = Array.prototype.concat;

  var existy = function(x) { return x != null; };
  var truthy = function(x) { return (x !== false) && existy(x); };
  var isAssociative = function(x) { return _.isArray(x) || _.isObject(x); };

  // Mixing in the object builders
  // ----------------------------

  _.mixin({
    // Merges two or more objects starting with the left-most and
    // applying the keys right-word
    // {any:any}* -> {any:any}
    merge: function(/* objs */){
      var dest = _.some(arguments) ? {} : null;

      if (truthy(dest)) {
        _.extend.apply(null, concat.call([dest], _.toArray(arguments)));
      }

      return dest;
    },

    // Takes an object and another object of strings to strings where the second
    // object describes the key renaming to occur in the first object.
    renameKeys: function(obj, kobj) {
      return _.reduce(kobj, function(o, nu, old) {
        if (existy(obj[old])) {
          o[nu] = obj[old];
          return o;
        }
        else
          return o;
      },
      _.omit.apply(null, concat.call([obj], _.keys(kobj))));
    },

    // Snapshots an object deeply. Based on the version by
    // [Keith Devens](http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone)
    // until we can find a more efficient and robust way to do it.
    snapshot: function(obj) {
      if(obj == null || typeof(obj) != 'object') {
        return obj;
      }

      var temp = new obj.constructor();

      for(var key in obj) {
        temp[key] = _.snapshot(obj[key]);
      }

      return temp;
    },

    // Updates the value at any depth in a nested object based on the
    // path described by the keys given.  The function provided is supplied
    // the current value and is expected to return a value for use as the
    // new value.  If no keys are provided, then the object itself is presented
    // to the given function.
    updatePath: function(obj, fun, ks) {
      if (!isAssociative(obj)) throw new TypeError("Attempted to update a non-associative object.");
      if (!existy(ks)) return fun(obj);

      var deepness = _.isArray(ks);
      var keys     = deepness ? ks : [ks];
      var ret      = deepness ? _.snapshot(obj) : _.clone(obj);
      var lastKey  = _.last(keys);
      var target   = ret;

      _.each(_.initial(keys), function(key) {
        target = target[key];
      });

      target[lastKey] = fun(target[lastKey]);
      return ret;
    },

    // Sets the value at any depth in a nested object based on the
    // path described by the keys given.
    setPath: function(obj, value, ks) {
      if (!existy(ks)) throw new TypeError("Attempted to set a property at a null path.");

      return _.updatePath(obj, function() { return value; }, ks);
    }
  });

})(this);
<|endoftext|>


<commit_before>
/*    Copyright 2016 Firewalla LLC
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
'use strict'

let firewalla = require('../../net2/Firewalla.js')
let log = require("../../net2/logger.js")(__filename)

let fs = require('fs')

let spawn = require('child_process').spawn
let Promise = require('bluebird');

let instance = null

function delay(t) {
  return new Promise(function(resolve) {
    setTimeout(resolve, t)
  });
}

class BitBridge {
  static getInstance() {
    return instance
  }

  constructor(intf, routerIP, selfIP, selfMac, selfIP6, routerIP6) {
    if(!instance) {
      this.intf = intf
      this.routerIP = routerIP
      this.selfIP = selfIP
      this.spawnProcess = null
      this.started = false
      this.subscribeOnProcessExit()
      this.selfMac = selfMac
      this.selfIP6 = selfIP6
      this.routerIP6 = routerIP6
      instance = this
    }

    return instance
  }

  subscribeOnProcessExit() {
    process.on('exit', () => {
      if(this.started) {
        log.info("Terminating bitbridge on exit")
        this.stop()
      }
    });
  }

  start() {
    log.info("Starting BitBridge...")

    let binary = null, args = null;

    if(firewalla.isDocker() || firewalla.isTravis()) {

      // always stop before start
      this.stop()

      binary = "sudo";
      args = [this.getBinary(), this.intf, this.routerIP, this.selfIP,'-m','-q','-n'];

      let logStream = fs.createWriteStream("/dev/null", {flags: 'a'});

      this.spawnProcess = spawn(binary, args);
      log.info("starting new spoofing: ", binary, args, {});

      this.spawnProcess.stdout.pipe(logStream);
      this.spawnProcess.stderr.pipe(logStream);

      this.spawnProcess.on('exit', (code) => {
        log.info("spoofing binary exited with code " + code);
      });

    } else {
      binary = this.getBinary()
      args = [this.intf, this.routerIP, this.selfIP, '-m','-n','-q','-d 0'];

      let cmd = binary+" "+args.join(" ")
      log.info("Lanching Bitbridge4 ", cmd);
      require('child_process').execSync("echo 'cp /home/pi/firewalla/bin/real/bitbridge7 /home/pi/firewalla/bin/. ; sudo setcap cap_net_admin,cap_net_raw=eip /home/pi/firewalla/bin/bitbridge7 ; "+cmd +" ' > /home/pi/firewalla/bin/bitbridge4.sh");
      require('child_process').execSync("sudo service bitbridge4 restart"); // legacy issue to use bitbridge4

      binary = this.getBinary6()
      args = [this.intf, this.routerIP6, this.selfIP, this.selfMac,'-m','-q','-n'];

      cmd = binary+" "+args.join(" ")
      log.info("Lanching bitbridge6", cmd);
      require('child_process').execSync("echo 'cp /home/pi/firewalla/bin/real/bitbridge6 /home/pi/firewalla/bin/. ; sudo setcap cap_net_admin,cap_net_raw=eip /home/pi/firewalla/bin/bitbridge6 ; "+cmd +" ' > /home/pi/firewalla/bin/bitbridge6.sh");
      require('child_process').execSync("sudo service bitbridge6 restart"); // legacy issue to use bitbridge4
    }

    this.started = true
  }

  stop() {
    log.info("Stopping BitBridge...")

    try {
      if(firewalla.isDocker() || firewalla.isTravis()) {
        require('child_process').execSync("sudo pkill bitbridge7")
        require('child_process').execSync("sudo pkill bitbridge6")
      } else {
        require('child_process').execSync("sudo service bitbridge4 stop") // legacy issue to use bitbridge4
        require('child_process').execSync("sudo service bitbridge6 stop") // legacy issue to use bitbridge4
      }
    } catch(err) {
      // ignore error
    }

    this.started = false

    return delay(1000) // delay for 1 second before return to ensure bitbridge is stopped
  }

  getBinary() {
    if(firewalla.getPlatform() === "x86_64") {
      return firewalla.getFirewallaHome() + "/bin/real.x86_64/bitbridge7";
    }

    return firewalla.getFirewallaHome() + "/bin/bitbridge7";
  }

  getBinary6() {
    if(firewalla.getPlatform() === "x86_64") {
      return firewalla.getFirewallaHome() + "/bin/real.x86_64/bitbridge6";
    }

    return firewalla.getFirewallaHome() + "/bin/bitbridge6";
  }

}

module.exports = BitBridge
<commit_msg>use a better way to start bitbridge<commit_after>
/*    Copyright 2016 Firewalla LLC
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
'use strict'

let firewalla = require('../../net2/Firewalla.js')
let log = require("../../net2/logger.js")(__filename)

let fs = require('fs')

let spawn = require('child_process').spawn
let Promise = require('bluebird');

let instance = null

function delay(t) {
  return new Promise(function(resolve) {
    setTimeout(resolve, t)
  });
}

class BitBridge {
  static getInstance() {
    return instance
  }

  constructor(intf, routerIP, selfIP, selfMac, selfIP6, routerIP6) {
    if(!instance) {
      this.intf = intf
      this.routerIP = routerIP
      this.selfIP = selfIP
      this.spawnProcess = null
      this.started = false
      this.subscribeOnProcessExit()
      this.selfMac = selfMac
      this.selfIP6 = selfIP6
      this.routerIP6 = routerIP6
      instance = this
    }

    return instance
  }

  subscribeOnProcessExit() {
    process.on('exit', () => {
      if(this.started) {
        log.info("Terminating bitbridge on exit")
        this.stop()
      }
    });
  }

  start() {
    log.info("Starting BitBridge...")

    let binary = null, args = null;

    if(firewalla.isDocker() || firewalla.isTravis()) {

      // always stop before start
      this.stop()

      binary = "sudo";
      args = [this.getBinary(), this.intf, this.routerIP, this.selfIP,'-m','-q','-n'];

      let logStream = fs.createWriteStream("/dev/null", {flags: 'a'});

      this.spawnProcess = spawn(binary, args);
      log.info("starting new spoofing: ", binary, args, {});

      this.spawnProcess.stdout.pipe(logStream);
      this.spawnProcess.stderr.pipe(logStream);

      this.spawnProcess.on('exit', (code) => {
        log.info("spoofing binary exited with code " + code);
      });

    } else {
      binary = this.getBinary()
      args = [this.intf, this.routerIP, this.selfIP, '-m','-n','-q','-d 0'];

      let cmd = binary+" "+args.join(" ")
      log.info("Lanching Bitbridge4 ", cmd);

      // update arguments
      require('child_process').execSync(`echo "export BINARY_ARGUMENTS=${args}" > ${firewalla.getFirewallaHome()}/bin/bitbridge7.rc`)

      // restart ipv4
      require('child_process').execSync("sudo service bitbridge4 restart"); // legacy issue to use bitbridge4

      binary = this.getBinary6()
      args = [this.intf, this.routerIP6, this.selfIP, this.selfMac,'-m','-q','-n'];

      cmd = binary+" "+args.join(" ")

      log.info("Lanching bitbridge6", cmd);

      // update arguments
      require('child_process').execSync(`echo "export BINARY_ARGUMENTS=${args}" > ${firewalla.getFirewallaHome()}/bin/bitbridge6.rc`)

      // restart ipv6
      require('child_process').execSync("sudo service bitbridge6 restart"); // legacy issue to use bitbridge4
    }

    this.started = true
  }

  stop() {
    log.info("Stopping BitBridge...")

    try {
      if(firewalla.isDocker() || firewalla.isTravis()) {
        require('child_process').execSync("sudo pkill bitbridge7")
        require('child_process').execSync("sudo pkill bitbridge6")
      } else {
        require('child_process').execSync("sudo service bitbridge4 stop") // legacy issue to use bitbridge4
        require('child_process').execSync("sudo service bitbridge6 stop") // legacy issue to use bitbridge4
      }
    } catch(err) {
      // ignore error
    }

    this.started = false

    return delay(1000) // delay for 1 second before return to ensure bitbridge is stopped
  }

  getBinary() {
    if(firewalla.getPlatform() === "x86_64") {
      return firewalla.getFirewallaHome() + "/bin/real.x86_64/bitbridge7";
    }

    return firewalla.getFirewallaHome() + "/bin/bitbridge7";
  }

  getBinary6() {
    if(firewalla.getPlatform() === "x86_64") {
      return firewalla.getFirewallaHome() + "/bin/real.x86_64/bitbridge6";
    }

    return firewalla.getFirewallaHome() + "/bin/bitbridge6";
  }

}

module.exports = BitBridge
<|endoftext|>


<commit_before>
function isFeed (id) {
  return 'string' === typeof id
}

function isPositiveInteger (int) {
  return int >= 0 && Number.isInteger(int)
}

var isInteger = Number.isInteger

function isObject(o) {
  return o && 'object' === typeof o
}

function assertKeys(obj, keyAssert, valueAssert) {
  for(var k in obj) {
    keyAssert(k); valueAssert(obj[k])
  }
}

function _assert(fn, msg) {
  return function (value) {
    assert.ok(fn(value), msg)
  }
}

exports.validate = function (state) {
  assert.ok(isObject(state.clock), 'state has clock object')
  assert.ok(isObject(state.connections), 'state has connections object')
  assertKeys(state.clock,
    _assert(isFeed, 'clock key is feed id'),
    _assert(isPositiveInteger, 'clock value is positive integer')
  )
  assertKeys(state.connections,
    _assert(isFeed, 'clock key is feed id'),
    _assert(function (con) {
      assertKeys(con.clock,
        _assert(isFeed, 'connection.clock key is feed id'),
        _assert(isInteger, 'connection.clock value is integer')
      )
      assert.ok(Array.isArray(con.msgs), 'connection.msgs is array')
      assertKeys(con.notes,
        _assert(ref.isFeed, 'connection.notes key is feed id'),
        _assert(isInteger, 'connection.notes value is integer')
      )

      //TODO check that notes are in sync with other data structures.

      for(var id in con.notes) {
        var c = state.clock[id], n = con.notes[id], f = state.following[id]
        if(!(n == f ? ( c == null ? 0 : state.replicating[id].rx ? c : ~c ) : -1)) {
          throw new Error('incorrect notes: '+id+':'+n+', clock:'+c+', following:'+f, ', receive:'+state.replicating[id].rx)
        }
      }

      return true
    }, 'connection value is correct')
  )
}

exports.events = {}

exports.events.initialize = function (id) {
  return {
    id: id,
    clock: null,
    follows: {},
    peers: {},
    receive: []
  }
}

exports.events.clock = function (state, clock) {
  state.clock = clock

  return state
}

exports.events.connect = function (state, ev) {
  if(state.peers[ev.id]) throw new Error('already connected to peer:'+ev.id)
  state.peers[ev.id] = {
    clock: null,
    msgs: [],
    receive: [], retrive: [],
    notes: null,
    replicating: {}
  }

  return state
}

exports.events.peerClock = function (state, ev) {
  if(!state.peers[ev.id])
    throw new Error('peerClock called for:'+ev.id + ' but only connected to:'+ Object.keys(state.peers))
  var peer = state.peers[ev.id]
  var clock = peer.clock = ev.value

  //iterate over following and create replications.

  //if we want to replicate a peer that has changed since their clock,
  //create a replication for that peer.

  for(var id in state.follows) {
    if(clock[id] == null || clock[id] != state.clock[id]) {
      peer.notes = peer.notes || {}
      peer.notes[id] = state.clock[id] || 0
      peer.replicating = peer.replicating || {}
      peer.replicating[id] = {
        tx: false, rx: true, sent: null
      }
    }
  }

  return state
}

exports.events.follow = function (state, ev) {
  if(state.follows[ev.id] !== ev.value) {
    state.follows[ev.id] = ev.value
    for(var id in state.peers) {
      var peer = state.peers[id]
      //cases:
      //  don't have feed
      //  do have feed
      //  peer has feed
      //  peer rejects feed
      if(peer.clock) {
        if(peer.clock[ev.id] === -1) {
          //peer explicitly does not replicate this feed, don't ask for it.
        }
        else if(ev.value === false) { //unfollow
          peer.notes = peer.notes || {}
          peer.notes[ev.id] = -1
          if(peer.replicating[ev.id])
            peer.replicating[ev.id].rx = false
        }
        else if(ev.value === true) {
          peer.replicating[ev.id] = {
            rx: true, tx: null,
            sent: -1
          }
          peer.notes = peer.notes || {}
          peer.notes[ev.id] = state.clock[ev.id] || 0
        }
      }
    }
  }
  return state
}

exports.events.retrive = function (state, msg) {
  //check if any peer requires this msg
  for(var id in state.peers) {
    var rep = state.peers[id].replicating[msg.author]
    if(rep && rep.tx && rep.sent === msg.sequence - 1) {
      rep.sent ++
      state.peers[id].msgs.push(msg)
      if(rep.sent < state.clock[msg.author])
        state.peers[id].retrive.push(msg.author)
    }
  }
  return state
}

exports.events.append = function (state, msg) {
  //check if any peer requires this msg
  if(state.clock[msg.author] != null && state.clock[msg.author] !== msg.sequence - 1) return state //ignore

  state.clock[msg.author] = msg.sequence

  for(var id in state.peers) {
    var peer = state.peers[id]
    var rep = peer.replicating[msg.author]
    if(rep.tx && rep.sent == msg.sequence - 1) {
      peer.msgs.push(msg)
      rep.sent++
    }
    //if we are ahead of this peer, and not in tx mode, let them know that.
    else if(!rep.tx && msg.sequence > peer.clock[msg.author]) {
      peer.notes = peer.notes || {}
      peer.notes[msg.author] = ~msg.sequence
    }
  }

  return state
}

exports.events.receive = function (state, ev) {
  var msg = ev.value
  //receive a message, validate and append.
  //if this message is forked, disable this feed

  //if this message has already been seen, ignore.
  if(state.clock[msg.author] > msg.sequence) {
    var peer = state.peers[ev.id]
    if(peer.replicating[msg.author] && peer.replicating[msg.author].rx) {
      peer.notes = peer.notes || {}
      peer.notes[msg.author] = -state.clock[msg.author]
      peer.replicating[msg.author].rx = false
    }
    return state
  }

  //we _know_ that this peer is upto at least this message now.
  //(but maybe they already told us they where ahead further)
  state.peers[ev.id].clock[msg.author] = Math.max(state.peers[ev.id].clock[msg.author], msg.sequence)

  state.receive.push(msg)

  //Q: possibly update the receiving mode?

  return state
}

exports.events.notes = function (state, ev) {
  //update replicating modes
  var clock = ev.value
  var peer = state.peers[ev.id]
  for(var id in clock) {
    var seq = clock[id]
    peer.clock[id] = seq
    //check if we are not following this feed.
    if(!state.follows[id]) {
      peer.notes = peer.notes || {}
      peer.notes[id] = -1
    }
    else {
      if(!peer.replicating[id])
        peer.replicating[id] = {tx: true, rx: true, sent: seq}

      //positive seq means "send this to me please"
      peer.replicating[id].tx = seq >= 0
      //console.log('REP', id, peer.replicating[id])
      //in the case we are already ahead, get ready to send them messages.
      if(seq >= 0 && state.clock[id] > seq) {
        peer.replicating[id].sent = seq
        peer.retrive.push(id)
      }

    }
  }
  return state
}

<commit_msg>continue instead of return, and always set sent (incase we are along a broadcast path)<commit_after>
function isFeed (id) {
  return 'string' === typeof id
}

function isPositiveInteger (int) {
  return int >= 0 && Number.isInteger(int)
}

var isInteger = Number.isInteger

function isObject(o) {
  return o && 'object' === typeof o
}

function assertKeys(obj, keyAssert, valueAssert) {
  for(var k in obj) {
    keyAssert(k); valueAssert(obj[k])
  }
}

function _assert(fn, msg) {
  return function (value) {
    assert.ok(fn(value), msg)
  }
}

exports.validate = function (state) {
  assert.ok(isObject(state.clock), 'state has clock object')
  assert.ok(isObject(state.connections), 'state has connections object')
  assertKeys(state.clock,
    _assert(isFeed, 'clock key is feed id'),
    _assert(isPositiveInteger, 'clock value is positive integer')
  )
  assertKeys(state.connections,
    _assert(isFeed, 'clock key is feed id'),
    _assert(function (con) {
      assertKeys(con.clock,
        _assert(isFeed, 'connection.clock key is feed id'),
        _assert(isInteger, 'connection.clock value is integer')
      )
      assert.ok(Array.isArray(con.msgs), 'connection.msgs is array')
      assertKeys(con.notes,
        _assert(ref.isFeed, 'connection.notes key is feed id'),
        _assert(isInteger, 'connection.notes value is integer')
      )

      //TODO check that notes are in sync with other data structures.

      for(var id in con.notes) {
        var c = state.clock[id], n = con.notes[id], f = state.following[id]
        if(!(n == f ? ( c == null ? 0 : state.replicating[id].rx ? c : ~c ) : -1)) {
          throw new Error('incorrect notes: '+id+':'+n+', clock:'+c+', following:'+f, ', receive:'+state.replicating[id].rx)
        }
      }

      return true
    }, 'connection value is correct')
  )
}

exports.events = {}

exports.events.initialize = function (id) {
  return {
    id: id,
    clock: null,
    follows: {},
    peers: {},
    receive: []
  }
}

exports.events.clock = function (state, clock) {
  state.clock = clock

  return state
}

exports.events.connect = function (state, ev) {
  if(state.peers[ev.id]) throw new Error('already connected to peer:'+ev.id)
  state.peers[ev.id] = {
    clock: null,
    msgs: [],
    receive: [], retrive: [],
    notes: null,
    replicating: {}
  }

  return state
}

exports.events.peerClock = function (state, ev) {
  if(!state.peers[ev.id])
    throw new Error('peerClock called for:'+ev.id + ' but only connected to:'+ Object.keys(state.peers))
  var peer = state.peers[ev.id]
  var clock = peer.clock = ev.value

  //iterate over following and create replications.

  //if we want to replicate a peer that has changed since their clock,
  //create a replication for that peer.

  for(var id in state.follows) {
    if(clock[id] == null || clock[id] != state.clock[id]) {
      peer.notes = peer.notes || {}
      peer.notes[id] = state.clock[id] || 0
      peer.replicating = peer.replicating || {}
      peer.replicating[id] = {
        tx: false, rx: true, sent: null
      }
    }
  }

  return state
}

exports.events.follow = function (state, ev) {
  if(state.follows[ev.id] !== ev.value) {
    state.follows[ev.id] = ev.value
    for(var id in state.peers) {
      var peer = state.peers[id]
      //cases:
      //  don't have feed
      //  do have feed
      //  peer has feed
      //  peer rejects feed
      if(peer.clock) {
        if(peer.clock[ev.id] === -1) {
          //peer explicitly does not replicate this feed, don't ask for it.
        }
        else if(ev.value === false) { //unfollow
          peer.notes = peer.notes || {}
          peer.notes[ev.id] = -1
          if(peer.replicating[ev.id])
            peer.replicating[ev.id].rx = false
        }
        else if(ev.value === true) {
          peer.replicating[ev.id] = {
            rx: true, tx: null,
            sent: -1
          }
          peer.notes = peer.notes || {}
          peer.notes[ev.id] = state.clock[ev.id] || 0
        }
      }
    }
  }
  return state
}

exports.events.retrive = function (state, msg) {
  //check if any peer requires this msg
  for(var id in state.peers) {
    var rep = state.peers[id].replicating[msg.author]
    if(rep && rep.tx && rep.sent === msg.sequence - 1) {
      rep.sent ++
      state.peers[id].msgs.push(msg)
      if(rep.sent < state.clock[msg.author]) {
        //use continue, not return because we still need to loop through other peers.
        if(~state.peers[id].retrive.indexOf(msg.author)) continue
        state.peers[id].retrive.push(msg.author)
      }
    }
  }
  return state
}

exports.events.append = function (state, msg) {
  //check if any peer requires this msg
  if(state.clock[msg.author] != null && state.clock[msg.author] !== msg.sequence - 1) return state //ignore

  state.clock[msg.author] = msg.sequence

  console.log('APPEND_PEERS', state.id, Object.keys(state.peers))

  for(var id in state.peers) {
    var peer = state.peers[id]
    var rep = peer.replicating[msg.author]
    console.log('REP', state.id+'->'+id, rep, msg)
    if(rep && rep.tx && rep.sent == msg.sequence - 1) {
      peer.msgs.push(msg)
      rep.sent++
    }
    //if we are ahead of this peer, and not in tx mode, let them know that.
    else if(!rep.tx && msg.sequence > peer.clock[msg.author]) {
      peer.notes = peer.notes || {}
      peer.notes[msg.author] = ~msg.sequence
    }
  }

  return state
}

exports.events.receive = function (state, ev) {
  var msg = ev.value
  //receive a message, validate and append.
  //if this message is forked, disable this feed

  //if this message has already been seen, ignore.
  if(state.clock[msg.author] > msg.sequence) {
    var peer = state.peers[ev.id]
    if(peer.replicating[msg.author] && peer.replicating[msg.author].rx) {
      peer.notes = peer.notes || {}
      peer.notes[msg.author] = -state.clock[msg.author]
      peer.replicating[msg.author].rx = false
    }
    return state
  }

  //we _know_ that this peer is upto at least this message now.
  //(but maybe they already told us they where ahead further)
  state.peers[ev.id].clock[msg.author] = Math.max(state.peers[ev.id].clock[msg.author], msg.sequence)

  state.receive.push(msg)

  //Q: possibly update the receiving mode?

  return state
}

exports.events.notes = function (state, ev) {
  //update replicating modes
  var clock = ev.value
  var peer = state.peers[ev.id]
  for(var id in clock) {
    var seq = clock[id]
    peer.clock[id] = seq
    //check if we are not following this feed.
    if(!state.follows[id]) {
      peer.notes = peer.notes || {}
      peer.notes[id] = -1
    }
    else {
      if(!peer.replicating[id])
        peer.replicating[id] = {tx: true, rx: true, sent: seq}

      //positive seq means "send this to me please"
      peer.replicating[id].tx = seq >= 0
      //in the case we are already ahead, get ready to send them messages.
      peer.replicating[id].sent = seq
      if(seq >= 0 && state.clock[id] > seq) {
//        peer.replicating[id].sent = seq
        peer.retrive.push(id)
      }

    }
  }
  return state
}

<|endoftext|>


<commit_before>'use strict';

module.exports = uri => {
	let arr = uri.split('');
	let last = arr.length-1;
	return arr[last]!='/'? arr.concat(['/']).join(''):uri;
}<commit_msg>fix '\' at beginning bug<commit_after>'use strict';

module.exports = uri => {
	let arr = uri.split('');
	let last = arr.length-1;
	arr[last]!='/'&&(arr = arr.concat(['/']));
	arr[0]!='/'&&arr.unshift('/');
	return arr.join('');
}<|endoftext|>


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

  /**
   * Constructor for the Naive Bayes learner.
   * It takes a list of strings, which represent the different
   * groups of strings to train on, followed by an array of possible
   * classes.
   *
   * @param options: object of options that set up the naive bayes model.
   * It *must* have a `label` property that is an array of possible labels to assign
   * to things we are classifying.
   * It can optionally have a `dataLength` that specifies how many groups of strings
   * we are classifying. This is useful if we are classifying things that have several
   * separate attributes that we want to compute probabilities for separately. For
   * example, when calssifying an email, we might have three separate things to classify
   * on: the text of the email, the text of the subject, and the country of origin in
   * the sender's address. In this case, we would set `dataLength` to 3, and pass these
   * in as three separate arguments to the `train()` method.
   */
  function Credulous(options) {
    var i
      ;
    if (!this) {
      return new Credulous(options);
    }

    options = validateOptions(options);

    this.labels = options.labels;
    this.dataLength = options.dataLength;
    // For the label
    this.trainArgumentsLength = this.dataLength + 1;

    // TODO: make the data store more modular
    this.dataStore = [];
    setUpDataStore(this.dataStore, this.labels, this.dataLength);
    this.instancesTrained = 0;
  }

  /**
   * Set up structure of the datastore.
   */
  function setUpDataStore(dataStore, labels, dataLength) {
    var i
      ;
    for (i = 0; i < dataLength; i++) {
      dataStore[i] = {
          words: {}
        , labels: {}
      };
      labels.forEach(function (label) {
        dataStore[i].labels[label] = 0;
      });
    }
  }

  /**
   * Train the model with the given parameters.
   * @parameters - a list of strings that represents the attributes of the instance to classify.
   * The last parameter in the list is the label of the instance (ie 'spam', 'not spam', etc.
   */
  // TODO: handle laplacian correction
  Credulous.prototype.train = function () {
    // TODO: fix this awfulness
    var args = argsToArray(arguments)
      , length = args.length
      , label = popOffLabel(args)
      , self = this
      ;
    if (length != this.trainArgumentsLength) {
      throw new Error('Wrong number of training arguments! Did you forget the class?')
    }

    if (!labelIsInPossibleLabels(label, this.labels)) {
      throw new Error('Trained label not in possible labels!');
    }

    args.forEach(function (element, i, collection) {
      var elements = processString(element);
      // have a section for each word.
      // have a label as well
      // for this word, when the label was this, the count was this
      elements.forEach(function (word) {
        if (!self.dataStore[i].words[word]) {
          initializeWordInDatastore(self.dataStore[i], word, self.labels);
        }

        self.dataStore[i].words[word][label]++
        self.dataStore[i].labels[label]++;
      });
    });

    this.instancesTrained++;
  };

  Credulous.prototype.classify = function () {
    var args = argsToArray(arguments)
      , processedDataItems
      , labelScores = []
      , self = this
      ;

    if (args.length != this.dataLength) {
      throw new Error('Wrong number of classifying arguments!');
    }

    processedDataItems = processDataItems(args);

    // For each possible label:
    //   For each data item:
    //     For each word in the data item:
    //       Look up the probability of a class give this word appears
    this.labels.forEach(function (label, i) {
      labelScores[i] = getProbabilityForLabel(label, self.dataStore, processedDataItems);
    });

    return this.labels[argMax(labelScores)];
  };

  /**
   * Render the model as JSON, so it can be written out and
   * read back in by fromJSON.
   * @return - JSON representing the parameters and data of the model.
   */
  Credulous.prototype.toJSON = function () {
    var json = {}
      ;
    json.instancesTrained = this.instancesTrained;
    json.labels = this.labels;
    json.dataLength = this.dataLength;
    json.trainArgumentsLength = this.trainArgumentsLength;
    json.dataStore = this.dataStore;
    return json;
  }

  /**
   * Takes a JSON string and sets the properties of this
   * model to those of the saved model.
   */
  Credulous.prototype.fromJSON = function (json) {
    this.instancesTrained = json.instancesTrained;
    this.labels = json.labels;
    this.dataLength = json.dataLength;
    this.trainArgumentsLength = this.trainArgumentsLength;
    this.dataStore = json.dataStore;
  }

  function validateOptions(opts) {
    if (!opts || !opts.labels) {
      throw new Error('Constructor needs options object with "labels" and "dataLength" attributes.');
    }
    if (!opts.dataLength) {
      opts.dataLength = 1;
    }
    return opts;
  }

  function initializeWordInDatastore(datastore, word, labels) {
    datastore.words[word] = {};
    labels.forEach(function (label) {
      datastore.words[word][label] = 0;
    });
  }

  function labelIsInPossibleLabels(label, labels) {
    return labels.indexOf(label) !== -1;
  }

  /**
   * Return the index of the maximum value in the array.
   * @param array - an array of numerical values
   * @return the index of the largest value in the array.
   */
  function argMax(array) {
    var maxIndex = 0
     , i
     ;
    for (i = 0; i < array.length; i++) {
      if (array[i] > array[maxIndex]) {
        maxIndex = i;
      }
    }
    return maxIndex;
  }

  function getProbabilityForLabel(label, dataStore, processedDataItems) {
    var processedProbabilities = []
      , n
      ;
    dataStore.forEach(function (dataItem, dataItemIndex) {
      processedDataItems[dataItemIndex].forEach(function (word, j) {
        processedProbabilities.push(getProbabilityOfWordGivenLabel(word, label, dataItem));
      });
    });

    return combineProbabilitiesIntoMAP(processedProbabilities);
  }

  function combineProbabilitiesIntoMAP(probabilities) {
    // calculate probability in log space to avoid underflow
    // see http://en.wikipedia.org/wiki/Bayesian_spam_filtering#Other_expression_of_the_formula_for_combining_individual_probabilities
    var n = probabilities.reduce(function (runningSum, probability) {
      return runningSum + (Math.log(1 - probability) - Math.log(probability))
    }, 0.0);

    return (1 / (1 + Math.exp(n)));
  }

  function getProbabilityOfWordGivenLabel(word, label, dataStore) {
    // the probability of this word given the given class is the count of the word
    // for that class / the count of all words of the given class
    // TODO: where to do laplacian correction?
    var count
      , totalOfGivenClass = dataStore.labels[label]
      ;

    // Handle classifying with words that we have never seen.
    if (dataStore.words[word] === undefined) {
      count = 0;
    }
    else {
      count = dataStore.words[word][label];
    }

    return count / totalOfGivenClass;
  }

  /**
   * This is terribly named. Process the array of strings into an
   * array of arrays of words, with them stemmed, etc.
   */
  function processDataItems(items) {
    var processedItems = []
      ;

    // TODO: do stemming here
    items.forEach(function (item, i) {
      processedItems[i] = processString(item);
    });
    return processedItems;
  }

  /**
   * Convert the arguments object into an
   * actual array.
   */
  function argsToArray(args) {
    return Array.prototype.slice.call(args);
  }

  /**
   * Split the string and return the array of words.
   * This is a turrible name.
   */
  function processString(str) {
    // TODO: add stemming
    var words = str.split(/\s+/)
      ;
    return words;
  }

  /**
   * Add to the count of classes seen. Instantiate a new object to hold the
   * classes and counts if it has not been seen yet.
   */
  function addLabel(label, self) {
    if (!(label in self.labels)) {
      self.labels[label] = 1;
    }
    else {
      self.labels[label]++;
    }
  }

  function popOffLabel(args) {
    return args.pop();
  }

  module.exports = Credulous;
}());
<commit_msg>poor mans laplace correction<commit_after>(function () {
  "use strict";

  /**
   * Constructor for the Naive Bayes learner.
   * It takes a list of strings, which represent the different
   * groups of strings to train on, followed by an array of possible
   * classes.
   *
   * @param options: object of options that set up the naive bayes model.
   * It *must* have a `label` property that is an array of possible labels to assign
   * to things we are classifying.
   * It can optionally have a `dataLength` that specifies how many groups of strings
   * we are classifying. This is useful if we are classifying things that have several
   * separate attributes that we want to compute probabilities for separately. For
   * example, when calssifying an email, we might have three separate things to classify
   * on: the text of the email, the text of the subject, and the country of origin in
   * the sender's address. In this case, we would set `dataLength` to 3, and pass these
   * in as three separate arguments to the `train()` method.
   */
  function Credulous(options) {
    var i
      ;
    if (!this) {
      return new Credulous(options);
    }

    options = validateOptions(options);

    this.labels = options.labels;
    this.dataLength = options.dataLength;
    // For the label
    this.trainArgumentsLength = this.dataLength + 1;

    // TODO: make the data store more modular
    this.dataStore = [];
    setUpDataStore(this.dataStore, this.labels, this.dataLength);
    this.instancesTrained = 0;
  }

  /**
   * Set up structure of the datastore.
   */
  function setUpDataStore(dataStore, labels, dataLength) {
    var i
      ;
    for (i = 0; i < dataLength; i++) {
      dataStore[i] = {
          words: {}
        , labels: {}
      };
      labels.forEach(function (label) {
        dataStore[i].labels[label] = 0;
      });
    }
  }

  /**
   * Train the model with the given parameters.
   * @parameters - a list of strings that represents the attributes of the instance to classify.
   * The last parameter in the list is the label of the instance (ie 'spam', 'not spam', etc.
   */
  // TODO: handle laplacian correction
  Credulous.prototype.train = function () {
    // TODO: fix this awfulness
    var args = argsToArray(arguments)
      , length = args.length
      , label = popOffLabel(args)
      , self = this
      ;
    if (length != this.trainArgumentsLength) {
      throw new Error('Wrong number of training arguments! Did you forget the class?')
    }

    if (!labelIsInPossibleLabels(label, this.labels)) {
      throw new Error('Trained label not in possible labels!');
    }

    args.forEach(function (element, i, collection) {
      var elements = processString(element);
      // have a section for each word.
      // have a label as well
      // for this word, when the label was this, the count was this
      elements.forEach(function (word) {
        if (!self.dataStore[i].words[word]) {
          initializeWordInDatastore(self.dataStore[i], word, self.labels);
        }

        self.dataStore[i].words[word][label]++
        self.dataStore[i].labels[label]++;
      });
    });

    this.instancesTrained++;
  };

  Credulous.prototype.classify = function () {
    var args = argsToArray(arguments)
      , processedDataItems
      , labelScores = []
      , self = this
      ;

    if (args.length != this.dataLength) {
      throw new Error('Wrong number of classifying arguments!');
    }

    processedDataItems = processDataItems(args);

    // For each possible label:
    //   For each data item:
    //     For each word in the data item:
    //       Look up the probability of a class give this word appears
    this.labels.forEach(function (label, i) {
      labelScores[i] = getProbabilityForLabel(label, self.dataStore, processedDataItems);
    });

    return this.labels[argMax(labelScores)];
  };

  /**
   * Render the model as JSON, so it can be written out and
   * read back in by fromJSON.
   * @return - JSON representing the parameters and data of the model.
   */
  Credulous.prototype.toJSON = function () {
    var json = {}
      ;
    json.instancesTrained = this.instancesTrained;
    json.labels = this.labels;
    json.dataLength = this.dataLength;
    json.trainArgumentsLength = this.trainArgumentsLength;
    json.dataStore = this.dataStore;
    return json;
  }

  /**
   * Takes a JSON string and sets the properties of this
   * model to those of the saved model.
   */
  Credulous.prototype.fromJSON = function (json) {
    this.instancesTrained = json.instancesTrained;
    this.labels = json.labels;
    this.dataLength = json.dataLength;
    this.trainArgumentsLength = this.trainArgumentsLength;
    this.dataStore = json.dataStore;
  }

  function validateOptions(opts) {
    if (!opts || !opts.labels) {
      throw new Error('Constructor needs options object with "labels" and "dataLength" attributes.');
    }
    if (!opts.dataLength) {
      opts.dataLength = 1;
    }
    return opts;
  }

  function initializeWordInDatastore(datastore, word, labels) {
    datastore.words[word] = {};
    labels.forEach(function (label) {
      datastore.words[word][label] = 0;
    });
  }

  function labelIsInPossibleLabels(label, labels) {
    return labels.indexOf(label) !== -1;
  }

  /**
   * Return the index of the maximum value in the array.
   * @param array - an array of numerical values
   * @return the index of the largest value in the array.
   */
  function argMax(array) {
    var maxIndex = 0
     , i
     ;
    for (i = 0; i < array.length; i++) {
      if (array[i] > array[maxIndex]) {
        maxIndex = i;
      }
    }
    return maxIndex;
  }

  function getProbabilityForLabel(label, dataStore, processedDataItems) {
    var processedProbabilities = []
      , n
      ;
    dataStore.forEach(function (dataItem, dataItemIndex) {
      processedDataItems[dataItemIndex].forEach(function (word, j) {
        processedProbabilities.push(getProbabilityOfWordGivenLabel(word, label, dataItem));
      });
    });

    return combineProbabilitiesIntoMAP(processedProbabilities);
  }

  function combineProbabilitiesIntoMAP(probabilities) {
    // calculate probability in log space to avoid underflow
    // see http://en.wikipedia.org/wiki/Bayesian_spam_filtering#Other_expression_of_the_formula_for_combining_individual_probabilities
    var n = probabilities.reduce(function (runningSum, probability) {
      return runningSum + (Math.log(1 - probability) - Math.log(probability))
    }, 0.0);

    return (1 / (1 + Math.exp(n)));
  }

  function getProbabilityOfWordGivenLabel(word, label, dataStore) {
    // the probability of this word given the given class is the count of the word
    // for that class / the count of all words of the given class
    // TODO: where to do laplacian correction?
    var count
      , totalOfGivenClass = dataStore.labels[label]
      ;

    // Handle classifying with words that we have never seen.
    if (dataStore.words[word] === undefined) {
      // Poor mans laplace correction
      count = 1;
    }
    else {
      count = dataStore.words[word][label];
    }

    if (count === 0) {
      count = 1;
    }

    return count / totalOfGivenClass;
  }

  /**
   * This is terribly named. Process the array of strings into an
   * array of arrays of words, with them stemmed, etc.
   */
  function processDataItems(items) {
    var processedItems = []
      ;

    // TODO: do stemming here
    items.forEach(function (item, i) {
      processedItems[i] = processString(item);
    });
    return processedItems;
  }

  /**
   * Convert the arguments object into an
   * actual array.
   */
  function argsToArray(args) {
    return Array.prototype.slice.call(args);
  }

  /**
   * Split the string and return the array of words.
   * This is a turrible name.
   */
  function processString(str) {
    // TODO: add stemming
    var words = str.split(/\s+/)
      ;
    return words;
  }

  /**
   * Add to the count of classes seen. Instantiate a new object to hold the
   * classes and counts if it has not been seen yet.
   */
  function addLabel(label, self) {
    if (!(label in self.labels)) {
      self.labels[label] = 1;
    }
    else {
      self.labels[label]++;
    }
  }

  function popOffLabel(args) {
    return args.pop();
  }

  module.exports = Credulous;
}());
<|endoftext|>


<commit_before>var Drone = require('/drone/drone').Drone
var foreach = require('utils').foreach

var JavaString = java.lang.String;
var http = require('http');
var utils = require('utils');
var sounds = require('sounds');

var scratchReturnAddress = 'http://127.0.0.1:8089/';

scratchClients=[];

function scratch(command,ip){
	var players = utils.players();
    var cmd=command.split("/");
    var index=-1;
	var drona='';

	for(i=0;i<scratchClients.length;i++){
		if (scratchClients[i].ip==ip){
			console.log("target player: "+scratchClients[i].playerName);
			index=i;
			drona=scratchClients[i].drone;
			targetPlayer=scratchClients[i].targetPlayer;
			}
		}

	if(cmd[0]=='connect'){
    		console.log('trying to connect to player ' + cmd[1]);
    		playerName=cmd[1];
    		for (pl in players){  //use server.getPlayer(playerName)
    			if (players[pl].name.toLowerCase()==playerName.toLowerCase()){
    				targetPlayer=players[pl];
    				drona=new Drone (targetPlayer.location);
    				if (index==-1){ //new player
    					scratchClients.push({playerName:playerName, targetPlayer:targetPlayer,drone:drona, ip:ip});
    					index=scratchClients.length-1;
    					echo(targetPlayer, "Connected to Scratch client on IP "+ip);
    					}
    				else { //update existing player
    					scratchClients[index].playerName=playerName;
    					scratchClients[index].targetPlayer=targetPlayer;
    					scratchClients[index].drone=drona;
    					}
    				}
    			}
    		if (index==-1) { //use of other command before connecting to any player
				console.log('Player not found');
				scratchReturn(-1, -1, 'player_not_found', ip);
				return
				}
			else { //return to Scratch current block
				bl=drona.getBlock();
				scratchReturn(bl.typeId, bl.data, 'connected', ip); //updates values for current block to be read by Scratch
				}
    		}

	if (index==-1) { //use of other command before connecting to any player
		console.log('No target player defined');
		scratchReturn(-1, -1, 'no_target_player', ip);
		return
		}
	console.log("command received -" + cmd[0]+";");
	    switch(cmd[0]){
		case 'boxCommand':
		case 'box':
     			if(cmd[1]==64){
				drona.door(cmd[1]);
				}
			else
    				drona.box(''+cmd[1]+':'+parseInt(cmd[2]),parseInt(cmd[3]),parseInt(cmd[4]),parseInt(cmd[5]));
    		break;
		case 'box0':
		case 'box0Command':
    			drona.box0(''+cmd[1]+':'+parseInt(cmd[2]),parseInt(cmd[3]),parseInt(cmd[4]),parseInt(cmd[5]));
    		break;

		case 'cylinder':
    			drona.cylinder(''+cmd[1]+':'+parseInt(cmd[2]),parseInt(cmd[3]),parseInt(cmd[4]));
    		break;
		case 'cylinder0':
    			drona.cylinder0(''+cmd[1]+':'+parseInt(cmd[2]),parseInt(cmd[3]),parseInt(cmd[4]));
    		break;

		case 'prism':
    			drona.prism(''+cmd[1]+':'+parseInt(cmd[2]),parseInt(cmd[3]),parseInt(cmd[4]));
    		break;
		case 'prism':
    			drona.prism(''+cmd[1]+':'+parseInt(cmd[2]),parseInt(cmd[3]),parseInt(cmd[4]));
    		break;

		case 'rainbow':
    			drona.rainbow(parseInt(cmd[1]));
    		break;

		case 'bed':
    			drona.bed();
    		break;

		case 'torch':
    			drona.hangtorch();
    		break;

		case 'stairs':
    			drona.stairs(parseInt(cmd[1]),parseInt(cmd[3]),parseInt(cmd[4]));
    		break;

		case 'wallsign':
			textArray=[];
			for (i=1; i<5; i++)
				textArray.push(cmd[i]);
    		drona.wallsign(textArray);
    		break;

    		case 'summon':   //summons mobs using Scriptcraft predefined drone's summon method
    			console.log("summon "+cmd[1]);
			drona.spawn(cmd[1]) ;
    		break ;

    		case 'sound':   //plays randonmly one of the basic sounds of the specified entity on each connected player MC session
    			utils.foreach( players, function( player ) {
				sounds['entity' + cmd[1] + 'Ambient']( player ); // spigot 1.10
			} );
    		break ;
    		case 'moveDrone':
			console.log("before moveDrone: " + parseInt(10*drona.x)/10 + ":" + parseInt(10*drona.y)/10 + ":" + parseInt(10*drona.z)/10);
			switch(cmd[1]){
				case 'reset':
    				drona=new Drone (targetPlayer.location);
    				scratchClients[index].drone=drona;
    				break;
				case 'up':
					drona.up(parseInt(cmd[2]));
					break;
				case 'down':
					drona.down(parseInt(cmd[2]));
					break;
				case 'left':
					drona.left(parseInt(cmd[2]));
					break;
				case 'right':
					drona.right(parseInt(cmd[2]));
					break;
				case 'fwd':
					drona.fwd(parseInt(cmd[2]));
					break;
				case 'back':
					drona.back(parseInt(cmd[2]));
					break;
				case 'turn':
					drona.turn(parseInt(cmd[2]));
					break;
				case 'save_chkpt':
					drona.chkpt(cmd[2]);
					break;
				case 'goto_chkpt':
					drona.move(cmd[2]);
					break;
    			}
			//console.log("after moveDrone: " + parseInt(100*drona.x)/100 + ":" + parseInt(100*drona.y)/100 + ":" + parseInt(100*drona.z)/100);
    		bl=drona.getBlock();
		scratchReturn(bl.typeId, bl.data, 'ok', ip); //updates values for current block to be read by Scratch
		break;
    }
};

function scratchReturn(bltype, bldata, result, ip){ //updates values for current block to be read by Scratch
	var http = require('http');
	http.request( scratchReturnAddress + bltype + '/' + bldata + '/' + result + '/' +ip,function(responseCode, responseBody){console.log(  responseBody );});
}

exports.scratch=scratch
<commit_msg>Update scratch.js<commit_after>var Drone = require('/drone/drone').Drone
var foreach = require('utils').foreach

var JavaString = java.lang.String;
var http = require('http');
var utils = require('utils');
var sounds = require('sounds');

var scratchReturnAddress = 'http://127.0.0.1:8089/';

scratchClients=[];

function scratch(command,ip){
	var players = utils.players();
    var cmd=command.split("/");
    var index=-1;
	var drona='';

	for(i=0;i<scratchClients.length;i++){
		if (scratchClients[i].ip==ip){
			console.log("target player: "+scratchClients[i].playerName);
			index=i;
			drona=scratchClients[i].drone;
			targetPlayer=scratchClients[i].targetPlayer;
			}
		}

	if(cmd[0]=='connect'){
    		console.log('trying to connect to player ' + cmd[1]);
    		playerName=cmd[1];
    		for (pl in players){  //use server.getPlayer(playerName)
    			if (players[pl].name.toLowerCase()==playerName.toLowerCase()){
    				targetPlayer=players[pl];
    				drona=new Drone (targetPlayer.location);
    				if (index==-1){ //new player
    					scratchClients.push({playerName:playerName, targetPlayer:targetPlayer,drone:drona, ip:ip});
    					index=scratchClients.length-1;
    					echo(targetPlayer, "Connected to Scratch client on IP "+ip);
    					}
    				else { //update existing player
    					scratchClients[index].playerName=playerName;
    					scratchClients[index].targetPlayer=targetPlayer;
    					scratchClients[index].drone=drona;
    					}
    				}
    			}
    		if (index==-1) { //use of other command before connecting to any player
				console.log('Player not found');
				scratchReturn(-1, -1, 'player_not_found', ip);
				return
				}
			else { //return to Scratch current block
				bl=drona.getBlock();
				scratchReturn(bl.typeId, bl.data, 'connected', ip); //updates values for current block to be read by Scratch
				}
    		}

	if (index==-1) { //use of other command before connecting to any player
		console.log('No target player defined');
		scratchReturn(-1, -1, 'no_target_player', ip);
		return
		}
	console.log("command received -" + cmd[0]+";");
	    switch(cmd[0]){
		case 'boxCommand':
		case 'box':
     			if(cmd[1]==64){
				drona.door(cmd[1]);
				}
			else
    				drona.box(''+cmd[1]+':'+parseInt(cmd[2]),parseInt(cmd[3]),parseInt(cmd[4]),parseInt(cmd[5]));
    		break;
		case 'box0':
		case 'box0Command':
    			drona.box0(''+cmd[1]+':'+parseInt(cmd[2]),parseInt(cmd[3]),parseInt(cmd[4]),parseInt(cmd[5]));
    		break;

		case 'cylinder':
    			drona.cylinder(''+cmd[1]+':'+parseInt(cmd[2]),parseInt(cmd[3]),parseInt(cmd[4]));
    		break;
		case 'cylinder0':
    			drona.cylinder0(''+cmd[1]+':'+parseInt(cmd[2]),parseInt(cmd[3]),parseInt(cmd[4]));
    		break;

		case 'prism':
    			drona.prism(''+cmd[1]+':'+parseInt(cmd[2]),parseInt(cmd[3]),parseInt(cmd[4]));
    		break;
		case 'prism':
    			drona.prism(''+cmd[1]+':'+parseInt(cmd[2]),parseInt(cmd[3]),parseInt(cmd[4]));
    		break;

		case 'rainbow':
    			drona.rainbow(parseInt(cmd[1]));
    		break;

		case 'bed':
    			drona.bed();
    		break;

		case 'torch':
    			drona.hangtorch();
    		break;

		case 'stairs':
    			drona.stairs(parseInt(cmd[1]),parseInt(cmd[3]),parseInt(cmd[4]));
    		break;

		case 'wallsign':
			textArray=[];
			for (i=1; i<5; i++)
				textArray.push(decodeURIComponent(cmd[i]));
    			drona.wallsign(textArray);
    		break;

    		case 'summon':   //summons mobs using Scriptcraft predefined drone's summon method
    			console.log("summon "+cmd[1]);
			drona.spawn(cmd[1]) ;
    		break ;

    		case 'sound':   //plays randonmly one of the basic sounds of the specified entity on each connected player MC session
    			utils.foreach( players, function( player ) {
				sounds['entity' + cmd[1] + 'Ambient']( player ); // spigot 1.10
			} );
    		break ;
    		case 'moveDrone':
			console.log("before moveDrone: " + parseInt(10*drona.x)/10 + ":" + parseInt(10*drona.y)/10 + ":" + parseInt(10*drona.z)/10);
			switch(cmd[1]){
				case 'reset':
    				drona=new Drone (targetPlayer.location);
    				scratchClients[index].drone=drona;
    				break;
				case 'up':
					drona.up(parseInt(cmd[2]));
					break;
				case 'down':
					drona.down(parseInt(cmd[2]));
					break;
				case 'left':
					drona.left(parseInt(cmd[2]));
					break;
				case 'right':
					drona.right(parseInt(cmd[2]));
					break;
				case 'fwd':
					drona.fwd(parseInt(cmd[2]));
					break;
				case 'back':
					drona.back(parseInt(cmd[2]));
					break;
				case 'turn':
					drona.turn(parseInt(cmd[2]));
					break;
				case 'save_chkpt':
					drona.chkpt(cmd[2]);
					break;
				case 'goto_chkpt':
					drona.move(cmd[2]);
					break;
    			}
			//console.log("after moveDrone: " + parseInt(100*drona.x)/100 + ":" + parseInt(100*drona.y)/100 + ":" + parseInt(100*drona.z)/100);
    		bl=drona.getBlock();
		scratchReturn(bl.typeId, bl.data, 'ok', ip); //updates values for current block to be read by Scratch
		break;
    }
};

function scratchReturn(bltype, bldata, result, ip){ //updates values for current block to be read by Scratch
	var http = require('http');
	http.request( scratchReturnAddress + bltype + '/' + bldata + '/' + result + '/' +ip,function(responseCode, responseBody){console.log(  responseBody );});
}

exports.scratch=scratch
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import FontAwesome from 'react-fontawesome';
import _ from 'lodash';
import { Dropdown, Popup } from 'semantic-ui-react';
import Img from 'react-image';

import artPlaceholder from '../../../resources/media/art_placeholder.png';
import { getSelectedStream } from '../../utils';

import styles from './styles.scss';
import { withTranslation } from 'react-i18next';

@withTranslation('queue')
class QueuePopup extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      isOpen: false
    };
  }

  toggleOpen() {
    this.setState({
      isOpen: !this.state.isOpen
    });
    this.container.click();
  }

  handleClose() {
    this.setState({ isOpen: false });
  }

  rerollTrack(track) {
    let selectedStream = getSelectedStream(
      track.streams,
      this.props.defaultMusicSource
    );
    let musicSource = _.find(
      this.props.musicSources,
      s => s.sourceName === selectedStream.source
    );
    this.props.rerollTrack(musicSource, selectedStream, track);
  }

  renderStreamSourceDropdown() {
    let { track, musicSources, defaultMusicSource } = this.props;

    let dropdownOptions = _.map(musicSources, s => {
      return {
        key: s.sourceName,
        text: s.sourceName,
        value: s.sourceName,
        content: s.sourceName
      };
    });

    let selectedStream = getSelectedStream(track.streams, defaultMusicSource);
    return (

        Source:{' '}
        <Dropdown
          inline
          options={dropdownOptions}
          defaultValue={
            _.find(dropdownOptions, o => o.value === selectedStream.source)
              .value
          }
        />

    );
  }

  renderStreamRefreshButton() {
    let { track } = this.props;
    return (

         this.rerollTrack.bind(this)(track)}>
          <FontAwesome name='refresh' />

    );
  }

  renderStreamInfo() {
    const { track, defaultMusicSource, t } = this.props;
    const selectedStream = getSelectedStream(track.streams, defaultMusicSource);

    return (

          <Img
            alt=''
            src={selectedStream.thumbnail}
            unloader={}
          />

          {this.renderStreamSourceDropdown()}

            {t('title')}
            {selectedStream.title}

            {t('id')}
            {selectedStream.id}

        {this.renderStreamRefreshButton()}

    );
  }

  renderPopupTrigger() {
    let { trigger } = this.props;
    return (

 {
          this.container = element;
        }}
      >
        {trigger}

    );
  }

  render() {
    const { track, defaultMusicSource, t } = this.props;
    const selectedStream = getSelectedStream(track.streams, defaultMusicSource);

    return (

        <Popup
          className={styles.queue_popup}
          trigger={this.renderPopupTrigger()}
          open={this.state.isOpen}
          onClose={this.handleClose.bind(this)}
          onOpen={this.toggleOpen.bind(this)}
          hideOnScroll
          position='left center'
          // Do not touch - has to be null
          on={null}
        >
          {track.streams && selectedStream ? (
            this.renderStreamInfo()
          ) : (

{t('loading')}

          )}
        </Popup>

    );
  }
}

QueuePopup.propTypes = {
  trigger: PropTypes.node,
  track: PropTypes.object,
  defaultMusicSource: PropTypes.object,
  musicSources: PropTypes.array,
  rerollTrack: PropTypes.func
};

export default QueuePopup;
<commit_msg>Display stream id only if exist (#512)<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import FontAwesome from 'react-fontawesome';
import _ from 'lodash';
import { Dropdown, Popup } from 'semantic-ui-react';
import Img from 'react-image';

import artPlaceholder from '../../../resources/media/art_placeholder.png';
import { getSelectedStream } from '../../utils';

import styles from './styles.scss';
import { withTranslation } from 'react-i18next';

@withTranslation('queue')
class QueuePopup extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      isOpen: false
    };
  }

  toggleOpen() {
    this.setState({
      isOpen: !this.state.isOpen
    });
    this.container.click();
  }

  handleClose() {
    this.setState({ isOpen: false });
  }

  rerollTrack(track) {
    let selectedStream = getSelectedStream(
      track.streams,
      this.props.defaultMusicSource
    );
    let musicSource = _.find(
      this.props.musicSources,
      s => s.sourceName === selectedStream.source
    );
    this.props.rerollTrack(musicSource, selectedStream, track);
  }

  renderStreamSourceDropdown() {
    let { track, musicSources, defaultMusicSource } = this.props;

    let dropdownOptions = _.map(musicSources, s => {
      return {
        key: s.sourceName,
        text: s.sourceName,
        value: s.sourceName,
        content: s.sourceName
      };
    });

    let selectedStream = getSelectedStream(track.streams, defaultMusicSource);
    return (

        Source:{' '}
        <Dropdown
          inline
          options={dropdownOptions}
          defaultValue={
            _.find(dropdownOptions, o => o.value === selectedStream.source)
              .value
          }
        />

    );
  }

  renderStreamRefreshButton() {
    let { track } = this.props;
    return (

         this.rerollTrack.bind(this)(track)}>
          <FontAwesome name='refresh' />

    );
  }

  renderStreamInfo() {
    const { track, defaultMusicSource, t } = this.props;
    const selectedStream = getSelectedStream(track.streams, defaultMusicSource);

    return (

          <Img
            alt=''
            src={selectedStream.thumbnail}
            unloader={}
          />

          {this.renderStreamSourceDropdown()}

            {t('title')}
            {selectedStream.title}

          {selectedStream.id && (

              {t('id')}
              {selectedStream.id}

          )}

        {this.renderStreamRefreshButton()}

    );
  }

  renderPopupTrigger() {
    let { trigger } = this.props;
    return (

 {
          this.container = element;
        }}
      >
        {trigger}

    );
  }

  render() {
    const { track, defaultMusicSource, t } = this.props;
    const selectedStream = getSelectedStream(track.streams, defaultMusicSource);

    return (

        <Popup
          className={styles.queue_popup}
          trigger={this.renderPopupTrigger()}
          open={this.state.isOpen}
          onClose={this.handleClose.bind(this)}
          onOpen={this.toggleOpen.bind(this)}
          hideOnScroll
          position='left center'
          // Do not touch - has to be null
          on={null}
        >
          {track.streams && selectedStream ? (
            this.renderStreamInfo()
          ) : (

{t('loading')}

          )}
        </Popup>

    );
  }
}

QueuePopup.propTypes = {
  trigger: PropTypes.node,
  track: PropTypes.object,
  defaultMusicSource: PropTypes.object,
  musicSources: PropTypes.array,
  rerollTrack: PropTypes.func
};

export default QueuePopup;
<|endoftext|>


<commit_before>const _test = require('tape-promise').default
const tape = require('tape')
const test = _test(tape)
const paramsCielo = {
  'MerchantId': 'e60c1e21cf8743d1bc1fbd760fe0aba4',
  'MerchantKey': 'LVYLUTLJYYIXXRUQMXLIMYEDLRVCRWHNGYQFIVIG',
  'sandbox': true,
  'debug': false
}
const cielo = require('./cielo')(paramsCielo)
const regexToken = new RegExp(/^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$/)
const brands = ['Visa', 'Master', 'Amex', 'Elo', 'Aura', 'JCB', 'Diners', 'Discover', 'Hipercard']

brands.forEach(brand => {
  test(brand, async (t) => {
    const tokenParams = {
      'CustomerName': 'Comprador Teste Cielo',
      'CardNumber': '4532117080573700',
      'Holder': 'Comprador T Cielo',
      'ExpirationDate': '12/2021',
      'Brand': brand
    }
    const token = await cielo.cards.createTokenizedCard(tokenParams)

    const vendaParams = {
      'MerchantOrderId': 'CieloNodeJS000003',
      'Customer': {
        'Name': 'Comprador Teste'
      },
      'Payment': {
        'Type': 'CreditCard',
        'Amount': 100,
        'Installments': 1,
        'SoftDescriptor': '123456789ABCD',
        'CreditCard': {
          'CardToken': token.CardToken,
          'SecurityCode': '262',
          'Brand': brand
        }
      }
    }
    const venda = await cielo.creditCard.simpleTransaction(vendaParams)

    const capturaParams = {
      paymentId: venda.Payment.PaymentId,
      amount: 70
    }
    const captura = await cielo.creditCard.captureSaleTransaction(capturaParams)

    const consultaParams = {
      paymentId: venda.Payment.PaymentId
    }
    const consultaPaymentId = await cielo.consulting.sale(consultaParams)

    const consultaParamsMerchantOrderId = {
      merchantOrderId: 'CieloNodeJS000003'
    }

    const consultaMerchantOrderId = await cielo.consulting.sale(consultaParamsMerchantOrderId)

    const cancelaVendaParams = {
      paymentId: venda.Payment.PaymentId
    }
    const cancelaVenda = await cielo.creditCard.cancelSale(cancelaVendaParams)

    t.assert('CardToken' in token, 'retorno cardToken correto')
    t.assert(regexToken.test(token.CardToken), 'CardToken válido')
    t.assert(venda.Payment.Status === 1, 'Status da Venda Correto')
    t.assert(regexToken.test(venda.Payment.PaymentId), 'venda.Payment.PaymentId válido')
    t.assert(consultaPaymentId.Payment.Status === 2 || consultaPaymentId.Payment.Status === 1, 'Consulta de venda correta')
    t.assert(consultaMerchantOrderId.Payments.filter(x => x.PaymentId === venda.Payment.PaymentId).length > 0, 'Consulta de MerchantOrderId correta')
    t.assert(venda.Payment.Tid === consultaPaymentId.Payment.Tid, 'Tid da Venda Correto')
    t.assert(venda.Payment.Amount === vendaParams.Payment.Amount, 'Valor da Transação de Venda correto')
    t.assert(captura.Status === 2, 'Status da Caputra correto')
    t.assert(consultaPaymentId.Payment.CapturedAmount === capturaParams.amount, 'Valor da captura parcial correto')
    t.assert(cancelaVenda.Status === 10, 'Status de cancelamento correto')

    t.end()
  })
})

test('cardBin', async (t) => {
  const cardBinParams = {
    cardBin: 402400
  }
  const cardBin = await cielo.consulting.cardBin(cardBinParams)

  t.assert(cardBin.Status === '00', 'Status do CardBin válido (cardBin)')
  t.assert(cardBin.Provider === 'VISA', 'Bandeira do CardBin correto (cardBin)')
  t.assert(cardBin.CardType === 'Multiplo', 'Tipo de cartão (cardBin)')
  t.assert(cardBin.ForeignCard === true, 'Cartão emitido no exterior (cardBin)')

  t.end()
})

test('Boleto', async (t) => {
  const boletoParams = {
    "MerchantOrderId": "20180531",
    "Customer": {
      "Name": "Comprador Teste Boleto",
      "Identity": "1234567890",
      "Address": {
        "Street": "Avenida Marechal Câmara",
        "Number": "160",
        "Complement": "Sala 934",
        "ZipCode": "22750012",
        "District": "Centro",
        "City": "Rio de Janeiro",
        "State": "RJ",
        "Country": "BRA"
      }
    },
    "Payment": {
      "Type": "Boleto",
      "Amount": 15700,
      "Provider": "Bradesco2",
      "Address": "Rua Teste",
      "BoletoNumber": "123",
      "Assignor": "Empresa Teste",
      "Demonstrative": "Desmonstrative Teste",
      "ExpirationDate": "5/1/2015",
      "Identification": "11884926754",
      "Instructions": "Aceitar somente até a data de vencimento, após essa data juros de 1% dia."
    }
  }
  const boleto = await cielo.boleto.sale(boletoParams)

  t.assert(typeof boleto.Code === 'undefined', 'Não ocorreu erro no boleto')
  t.assert(typeof boleto.Payment !== 'undefined', 'Boleto retornou Payment')
  t.assert(boleto.Payment.Url.trim() !== '', 'Retornou Url para o boleto')
})

test('Recurrency', async (t) => {
  const recurrencyParams = {
    "MerchantOrderId": "2014113245231706",
    "Customer": {
      "Name": "Comprador rec programada"
    },
    "Payment": {
      "Type": "CreditCard",
      "Amount": 1500,
      "Installments": 1,
      "SoftDescriptor": "123456789ABCD",
      "RecurrentPayment": {
        "AuthorizeNow": "true",
        "EndDate": "2019-12-01",
        "Interval": "SemiAnnual"
      },
      "CreditCard": {
        "CardNumber": "1234123412341231",
        "Holder": "Teste Holder",
        "ExpirationDate": "12/2030",
        "SecurityCode": "262",
        "SaveCard": "false",
        "Brand": "Visa"
      }
    }
  }

  const firstRecurrency = await cielo.recurrentPayments.firstScheduledRecurrence(recurrencyParams)

  const modifyRecurrencyParams =
  {
    "recurrentPaymentId": firstRecurrency.Payment.RecurrentPayment.RecurrentPaymentId,
    "Interval": 1
  }
  const modifyRecurrency = await cielo.recurrentPayments.modify.Interval(modifyRecurrencyParams)

  const updateCustomer = {
    "recurrentPaymentId": firstRecurrency.Payment.RecurrentPayment.RecurrentPaymentId,
    "Customer": {
      "Name": "Customer",
      "Email": "customer@teste.com",
      "Birthdate": "1999-12-12",
      "Identity": "22658954236",
      "IdentityType": "CPF",
      "Address": {
        "Street": "Rua Teste",
        "Number": "174",
        "Complement": "AP 201",
        "ZipCode": "21241140",
        "City": "Rio de Janeiro",
        "State": "RJ",
        "Country": "BRA"
      },
      "DeliveryAddress": {
        "Street": "Outra Rua Teste",
        "Number": "123",
        "Complement": "AP 111",
        "ZipCode": "21241111",
        "City": "Qualquer Lugar",
        "State": "QL",
        "Country": "BRA",
        "District": "Teste"
      }
    }
  }

  await cielo.recurrentPayments.modify.Customer(updateCustomer)

  const deactivateRecurrencyParams = {
    "recurrentPaymentId": firstRecurrency.Payment.RecurrentPayment.RecurrentPaymentId
  }
  const deactivateRecurrency = await cielo.recurrentPayments.modify.Deactivate(deactivateRecurrencyParams)

  const recurrencyConsultingParams = {
    "recurrentPaymentId": firstRecurrency.Payment.RecurrentPayment.RecurrentPaymentId
  }
  const recurrencyConsulting = await cielo.recurrentPayments.consulting(recurrencyConsultingParams)

  t.assert(firstRecurrency.Payment.RecurrentPayment.ReasonCode == 0, 'Pagamento recorrente criado')
  t.assert(firstRecurrency.Payment.Status === 1, 'Status transacional autorizado (1)')
  t.assert(firstRecurrency.Payment.RecurrentPayment.Interval === 6, 'Intervalo de recorrência correto (6)')
  t.assert(modifyRecurrency.statusCode === 200, 'StatusCode da modificação da recorrência para mensal correto (200)')
  t.assert(deactivateRecurrency.statusCode === 200, 'StatusCode da desativação da recorrência correto (200)')
  t.assert(recurrencyConsulting.RecurrentPayment.Status === 3, 'Status da recorrência correto (3 - desativada pelo lojista)')
  t.assert(recurrencyConsulting.RecurrentPayment.Interval === 'Monthly', 'Intervalo da recorrência correto (Monthly)')
  t.assert(recurrencyConsulting.Customer.Email === 'customer@teste.com', 'Dados do cliente alterados com sucesso')

})<commit_msg>Atualizações dos testes de recorrência<commit_after>const _test = require('tape-promise').default
const tape = require('tape')
const test = _test(tape)
const paramsCielo = {
  'MerchantId': 'e60c1e21cf8743d1bc1fbd760fe0aba4',
  'MerchantKey': 'LVYLUTLJYYIXXRUQMXLIMYEDLRVCRWHNGYQFIVIG',
  'sandbox': true,
  'debug': false
}
const cielo = require('./cielo')(paramsCielo)
const regexToken = new RegExp(/^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$/)
const brands = ['Visa', 'Master', 'Amex', 'Elo', 'Aura', 'JCB', 'Diners', 'Discover', 'Hipercard']

brands.forEach(brand => {
  test(brand, async (t) => {
    const tokenParams = {
      'CustomerName': 'Comprador Teste Cielo',
      'CardNumber': '4532117080573700',
      'Holder': 'Comprador T Cielo',
      'ExpirationDate': '12/2021',
      'Brand': brand
    }
    const token = await cielo.cards.createTokenizedCard(tokenParams)

    const vendaParams = {
      'MerchantOrderId': 'CieloNodeJS000003',
      'Customer': {
        'Name': 'Comprador Teste'
      },
      'Payment': {
        'Type': 'CreditCard',
        'Amount': 100,
        'Installments': 1,
        'SoftDescriptor': '123456789ABCD',
        'CreditCard': {
          'CardToken': token.CardToken,
          'SecurityCode': '262',
          'Brand': brand
        }
      }
    }
    const venda = await cielo.creditCard.simpleTransaction(vendaParams)

    const capturaParams = {
      paymentId: venda.Payment.PaymentId,
      amount: 70
    }
    const captura = await cielo.creditCard.captureSaleTransaction(capturaParams)

    const consultaParams = {
      paymentId: venda.Payment.PaymentId
    }
    const consultaPaymentId = await cielo.consulting.sale(consultaParams)

    const consultaParamsMerchantOrderId = {
      merchantOrderId: 'CieloNodeJS000003'
    }

    const consultaMerchantOrderId = await cielo.consulting.sale(consultaParamsMerchantOrderId)

    const cancelaVendaParams = {
      paymentId: venda.Payment.PaymentId
    }
    const cancelaVenda = await cielo.creditCard.cancelSale(cancelaVendaParams)

    t.assert('CardToken' in token, 'retorno cardToken correto')
    t.assert(regexToken.test(token.CardToken), 'CardToken válido')
    t.assert(venda.Payment.Status === 1, 'Status da Venda Correto')
    t.assert(regexToken.test(venda.Payment.PaymentId), 'venda.Payment.PaymentId válido')
    t.assert(consultaPaymentId.Payment.Status === 2 || consultaPaymentId.Payment.Status === 1, 'Consulta de venda correta')
    t.assert(consultaMerchantOrderId.Payments.filter(x => x.PaymentId === venda.Payment.PaymentId).length > 0, 'Consulta de MerchantOrderId correta')
    t.assert(venda.Payment.Tid === consultaPaymentId.Payment.Tid, 'Tid da Venda Correto')
    t.assert(venda.Payment.Amount === vendaParams.Payment.Amount, 'Valor da Transação de Venda correto')
    t.assert(captura.Status === 2, 'Status da Caputra correto')
    t.assert(consultaPaymentId.Payment.CapturedAmount === capturaParams.amount, 'Valor da captura parcial correto')
    t.assert(cancelaVenda.Status === 10, 'Status de cancelamento correto')

    t.end()
  })
})

test('cardBin', async (t) => {
  const cardBinParams = {
    cardBin: 402400
  }
  const cardBin = await cielo.consulting.cardBin(cardBinParams)

  t.assert(cardBin.Status === '00', 'Status do CardBin válido (cardBin)')
  t.assert(cardBin.Provider === 'VISA', 'Bandeira do CardBin correto (cardBin)')
  t.assert(cardBin.CardType === 'Multiplo', 'Tipo de cartão (cardBin)')
  t.assert(cardBin.ForeignCard === true, 'Cartão emitido no exterior (cardBin)')

  t.end()
})

test('Boleto', async (t) => {
  const boletoParams = {
    "MerchantOrderId": "20180531",
    "Customer": {
      "Name": "Comprador Teste Boleto",
      "Identity": "1234567890",
      "Address": {
        "Street": "Avenida Marechal Câmara",
        "Number": "160",
        "Complement": "Sala 934",
        "ZipCode": "22750012",
        "District": "Centro",
        "City": "Rio de Janeiro",
        "State": "RJ",
        "Country": "BRA"
      }
    },
    "Payment": {
      "Type": "Boleto",
      "Amount": 15700,
      "Provider": "Bradesco2",
      "Address": "Rua Teste",
      "BoletoNumber": "123",
      "Assignor": "Empresa Teste",
      "Demonstrative": "Desmonstrative Teste",
      "ExpirationDate": "5/1/2015",
      "Identification": "11884926754",
      "Instructions": "Aceitar somente até a data de vencimento, após essa data juros de 1% dia."
    }
  }
  const boleto = await cielo.boleto.sale(boletoParams)

  t.assert(typeof boleto.Code === 'undefined', 'Não ocorreu erro no boleto')
  t.assert(typeof boleto.Payment !== 'undefined', 'Boleto retornou Payment')
  t.assert(boleto.Payment.Url.trim() !== '', 'Retornou Url para o boleto')
})

test('Recurrency', async (t) => {
  const recurrencyParams = {
    "MerchantOrderId": "2014113245231706",
    "Customer": {
      "Name": "Comprador rec programada"
    },
    "Payment": {
      "Type": "CreditCard",
      "Amount": 1500,
      "Installments": 1,
      "SoftDescriptor": "123456789ABCD",
      "RecurrentPayment": {
        "AuthorizeNow": "true",
        "EndDate": "2019-12-01",
        "Interval": "SemiAnnual"
      },
      "CreditCard": {
        "CardNumber": "1234123412341231",
        "Holder": "Teste Holder",
        "ExpirationDate": "12/2030",
        "SecurityCode": "262",
        "SaveCard": "false",
        "Brand": "Visa"
      }
    }
  }

  const firstRecurrency = await cielo.recurrentPayments.firstScheduledRecurrence(recurrencyParams)

  const modifyRecurrencyParams = {
    "recurrentPaymentId": firstRecurrency.Payment.RecurrentPayment.RecurrentPaymentId,
    "Interval": 1
  }
  const modifyRecurrency = await cielo.recurrentPayments.modify.Interval(modifyRecurrencyParams)

  const updateCustomer = {
    "recurrentPaymentId": firstRecurrency.Payment.RecurrentPayment.RecurrentPaymentId,
    "Customer": {
      "Name": "Customer",
      "Email": "customer@teste.com",
      "Birthdate": "1999-12-12",
      "Identity": "22658954236",
      "IdentityType": "CPF",
      "Address": {
        "Street": "Rua Teste",
        "Number": "174",
        "Complement": "AP 201",
        "ZipCode": "21241140",
        "City": "Rio de Janeiro",
        "State": "RJ",
        "Country": "BRA"
      },
      "DeliveryAddress": {
        "Street": "Outra Rua Teste",
        "Number": "123",
        "Complement": "AP 111",
        "ZipCode": "21241111",
        "City": "Qualquer Lugar",
        "State": "QL",
        "Country": "BRA",
        "District": "Teste"
      }
    }
  }

  const customer = await cielo.recurrentPayments.modify.Customer(updateCustomer)

  const endDate = await cielo.recurrentPayments.modify.EndDate({
    "recurrentPaymentId": firstRecurrency.Payment.RecurrentPayment.RecurrentPaymentId,
    "EndDate": "2021-01-09"
  })

  const recurrencyDay = await cielo.recurrentPayments.modify.RecurrencyDay({
    "recurrentPaymentId": firstRecurrency.Payment.RecurrentPayment.RecurrentPaymentId,
    "RecurrencyDay": 10
  })

  const updateAmount = {
    "recurrentPaymentId": firstRecurrency.Payment.RecurrentPayment.RecurrentPaymentId,
    "Amount": 156 // Valor do Pedido em centavos: 156 equivale a R$ 1,56
  }
  const amount = await cielo.recurrentPayments.modify.Amount(updateAmount)

  const updateNextPaymentDate = {
    "recurrentPaymentId": firstRecurrency.Payment.RecurrentPayment.RecurrentPaymentId,
    "NextPaymentDate": "2018-11-29"
  }
  const nextPaymentDate = await cielo.recurrentPayments.modify.NextPaymentDate(updateNextPaymentDate)

  const deactivateRecurrencyParams = {
    "recurrentPaymentId": firstRecurrency.Payment.RecurrentPayment.RecurrentPaymentId
  }
  const deactivateRecurrency = await cielo.recurrentPayments.modify.Deactivate(deactivateRecurrencyParams)

  const recurrencyConsultingParams = {
    "recurrentPaymentId": firstRecurrency.Payment.RecurrentPayment.RecurrentPaymentId
  }
  const recurrencyConsulting = await cielo.recurrentPayments.consulting(recurrencyConsultingParams)

  t.assert(firstRecurrency.Payment.RecurrentPayment.ReasonCode == 0, 'Pagamento recorrente criado')
  t.assert(firstRecurrency.Payment.Status === 1, 'Status transacional autorizado (1)')
  t.assert(firstRecurrency.Payment.RecurrentPayment.Interval === 6, 'Intervalo de recorrência correto (6)')
  t.assert(modifyRecurrency.statusCode === 200, 'StatusCode da modificação da recorrência para mensal correto (200)')
  t.assert(customer.statusCode === 200, 'StatusCode da modificação do Customer correto (200)')
  t.assert(endDate.statusCode === 200, 'StatusCode da modificação da recorrência terminar dia 09/01/2021 correto (200)')
  t.assert(recurrencyDay.statusCode === 200, 'StatusCode da modificação da recorrência para dia 10 correto (200)')
  t.assert(amount.statusCode === 200, 'StatusCode da modificação do valor para 156 correto (200)')
  t.assert(nextPaymentDate.statusCode === 200, 'StatusCode da modificação da data do próximo pagamento para 15/06/2016 correto (200)')
  t.assert(deactivateRecurrency.statusCode === 200, 'StatusCode da desativação da recorrência correto (200)')
  t.assert(recurrencyConsulting.RecurrentPayment.Status === 3, 'Status da recorrência correto (3 - desativada pelo lojista)')
  t.assert(recurrencyConsulting.RecurrentPayment.Interval === 'Monthly', 'Intervalo da recorrência correto (Monthly)')
  t.assert(recurrencyConsulting.Customer.Email === 'customer@teste.com', 'Dados do cliente alterados com sucesso')
})<|endoftext|>