<commit_before>// ==UserScript==
// @id             iitc-plugin-cross-links@mcben
// @name           IITC plugin: cross links
// @category       Layer
// @version        1.1.0.@@DATETIMEVERSION@@
// @namespace      https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL      @@UPDATEURL@@
// @downloadURL    @@DOWNLOADURL@@
// @description    [@@BUILDNAME@@-@@BUILDDATE@@] EXPERIMENTAL: Checks for existing links that cross planned links. Requires draw-tools plugin.
// @include        https://www.ingress.com/intel*
// @include        http://www.ingress.com/intel*
// @match          https://www.ingress.com/intel*
// @match          http://www.ingress.com/intel*
// @grant          none
// ==/UserScript==

@@PLUGINSTART@@

// PLUGIN START ////////////////////////////////////////////////////////

window.plugin.crossLinks = function() {};

window.plugin.crossLinks.greatCircleArcIntersect = function(a0,a1,b0,b1) {
  // based on the formula at http://williams.best.vwh.net/avform.htm#Int

  // method:
  // check to ensure no line segment is zero length - if so, cannot cross
  // check to see if either of the lines start/end at the same point. if so, then they cannot cross
  // check to see if the line segments overlap in longitude. if not, no crossing
  // if overlap, clip each line to the overlapping longitudes, then see if latitudes cross

  // anti-meridian handling. this code will not sensibly handle a case where one point is
  // close to -180 degrees and the other +180 degrees. unwrap coordinates in this case, so one point
  // is beyond +-180 degrees. this is already true in IITC
  // FIXME? if the two lines have been 'unwrapped' differently - one positive, one negative - it will fail

  // zero length line tests
  if (a0.equals(a1)) return false;
  if (b0.equals(b1)) return false;

  // lines have a common point
  if (a0.equals(b0) || a0.equals(b1)) return false;
  if (a1.equals(b0) || a1.equals(b1)) return false;

  // check for 'horizontal' overlap in lngitude
  if (Math.min(a0.lng,a1.lng) > Math.max(b0.lng,b1.lng)) return false;
  if (Math.max(a0.lng,a1.lng) < Math.min(b0.lng,b1.lng)) return false;

  // ok, our two lines have some horizontal overlap in longitude
  // 1. calculate the overlapping min/max longitude
  // 2. calculate each line latitude at each point
  // 3. if latitudes change place between overlapping range, the lines cross

  // class to hold the pre-calculated maths for a geodesic line
  // TODO: move this outside this function, so it can be pre-calculated once for each line we test
  var GeodesicLine = function(start,end) {
    var d2r = Math.PI/180.0;
    var r2d = 180.0/Math.PI;

    // maths based on http://williams.best.vwh.net/avform.htm#Int

    if (start.lng == end.lng) {
      throw 'Error: cannot calculate latitude for meridians';
    }

    // only the variables needed to calculate a latitude for a given longitude are stored in 'this'
    this.lat1 = start.lat * d2r;
    this.lat2 = end.lat * d2r;
    this.lng1 = start.lng * d2r;
    this.lng2 = end.lng * d2r;

    var dLng = this.lng1-this.lng2;

    var sinLat1 = Math.sin(this.lat1);
    var sinLat2 = Math.sin(this.lat2);
    var cosLat1 = Math.cos(this.lat1);
    var cosLat2 = Math.cos(this.lat2);

    this.sinLat1CosLat2 = sinLat1*cosLat2;
    this.sinLat2CosLat1 = sinLat2*cosLat1;

    this.cosLat1CosLat2SinDLng = cosLat1*cosLat2*Math.sin(dLng);
  }

  GeodesicLine.prototype.isMeridian = function() {
    return this.lng1 == this.lng2;
  }

  GeodesicLine.prototype.latAtLng = function(lng) {
    lng = lng * Math.PI / 180; //to radians

    var lat;
    // if we're testing the start/end point, return that directly rather than calculating
    // 1. this may be fractionally faster, no complex maths
    // 2. there's odd rounding issues that occur on some browsers (noticed on IITC MObile) for very short links - this may help
    if (lng == this.lng1) {
      lat = this.lat1;
    } else if (lng == this.lng2) {
      lat = this.lat2;
    } else {
      lat = Math.atan ( (this.sinLat1CosLat2*Math.sin(lng-this.lng2) - this.sinLat2CosLat1*Math.sin(lng-this.lng1))
                       / this.cosLat1CosLat2SinDLng);
    }
    return lat * 180 / Math.PI; // return value in degrees
  }

  // calculate the longitude of the overlapping region
  var leftLng = Math.max( Math.min(a0.lng,a1.lng), Math.min(b0.lng,b1.lng) );
  var rightLng = Math.min( Math.max(a0.lng,a1.lng), Math.max(b0.lng,b1.lng) );

  // calculate the latitudes for each line at left + right longitudes
  // NOTE: need a special case for meridians - as GeodesicLine.latAtLng method is invalid in that case
  var aLeftLat, aRightLat;
  if (a0.lng == a1.lng) {
    // 'left' and 'right' now become 'top' and 'bottom' (in some order) - which is fine for the below intersection code
    aLeftLat = a0.lat;
    aRightLat = a1.lat;
  } else {
    var aGeo = new GeodesicLine(a0,a1);
    aLeftLat = aGeo.latAtLng(leftLng);
    aRightLat = aGeo.latAtLng(rightLng);
  }

  var bLeftLat, bRightLat;
  if (b0.lng == b1.lng) {
    // 'left' and 'right' now become 'top' and 'bottom' (in some order) - which is fine for the below intersection code
    bLeftLat = b0.lat;
    bRightLat = b1.lat;
  } else {
    var bGeo = new GeodesicLine(b0,b1);
    bLeftLat = bGeo.latAtLng(leftLng);
    bRightLat = bGeo.latAtLng(rightLng);
  }

  // if both a are less or greater than both b, then lines do not cross

  if (aLeftLat < bLeftLat && aRightLat < bRightLat) return false;
  if (aLeftLat > bLeftLat && aRightLat > bRightLat) return false;

  // latitudes cross between left and right - so geodesic lines cross
  return true;
}

window.plugin.crossLinks.testPolyLine = function (polyline, link,closed) {

    var a = link.getLatLngs();
    var b = polyline.getLatLngs();

    for (var i=0;i<b.length-1;++i) {
        if (window.plugin.crossLinks.greatCircleArcIntersect(a[0],a[1],b[i],b[i+1])) return true;
    }

    if (closed) {
        if (window.plugin.crossLinks.greatCircleArcIntersect(a[0],a[1],b[b.length-1],b[0])) return true;
    }

    return false;
}

window.plugin.crossLinks.onLinkAdded = function (data) {
    if (window.plugin.crossLinks.disabled) return;

    plugin.crossLinks.testLink(data.link);
}

window.plugin.crossLinks.checkAllLinks = function() {
    if (window.plugin.crossLinks.disabled) return;

    console.debug("Cross-Links: checking all links");
    plugin.crossLinks.linkLayer.clearLayers();
    plugin.crossLinks.linkLayerGuids = {};

    $.each(window.links, function(guid, link) {
        plugin.crossLinks.testLink(link);
    });
}

window.plugin.crossLinks.testLink = function (link) {
    if (plugin.crossLinks.linkLayerGuids[link.options.guid]) return;

    for (var i in plugin.drawTools.drawnItems._layers) { // leaflet don't support breaking out of the loop
       var layer = plugin.drawTools.drawnItems._layers[i];
       if (layer instanceof L.GeodesicPolygon) {
           if (plugin.crossLinks.testPolyLine(layer, link,true)) {
               plugin.crossLinks.showLink(link);
               break;
           }
        } else if (layer instanceof L.GeodesicPolyline) {
            if (plugin.crossLinks.testPolyLine(layer, link)) {
                plugin.crossLinks.showLink(link);
                break;
            }
        }
    };
}

window.plugin.crossLinks.showLink = function(link) {

    var poly = L.geodesicPolyline(link.getLatLngs(), {
       color: '#d22',
       opacity: 0.7,
       weight: 5,
       clickable: false,
       dashArray: [8,8],

       guid: link.options.guid
    });

    poly.addTo(plugin.crossLinks.linkLayer);
    plugin.crossLinks.linkLayerGuids[link.options.guid]=poly;
}

window.plugin.crossLinks.onMapDataRefreshEnd = function () {
    if (window.plugin.crossLinks.disabled) return;

    window.plugin.crossLinks.linkLayer.bringToFront();

    window.plugin.crossLinks.testForDeletedLinks();
}

window.plugin.crossLinks.testAllLinksAgainstLayer = function (layer) {
    if (window.plugin.crossLinks.disabled) return;

    $.each(window.links, function(guid, link) {
        if (!plugin.crossLinks.linkLayerGuids[link.options.guid])
        {
            if (layer instanceof L.GeodesicPolygon) {
                if (plugin.crossLinks.testPolyLine(layer, link,true)) {
                    plugin.crossLinks.showLink(link);
                }
            } else if (layer instanceof L.GeodesicPolyline) {
                if (plugin.crossLinks.testPolyLine(layer, link)) {
                    plugin.crossLinks.showLink(link);
                }
            }
        }
    });
}

window.plugin.crossLinks.testForDeletedLinks = function () {
    window.plugin.crossLinks.linkLayer.eachLayer( function(layer) {
        var guid = layer.options.guid;
        if (!window.mapDataRequest.render.seenLinksGuid[guid]) {
            console.log("link removed");
            plugin.crossLinks.linkLayer.removeLayer(layer);
            delete plugin.crossLinks.linkLayerGuids[guid];
        }
    });
}

window.plugin.crossLinks.createLayer = function() {
    window.plugin.crossLinks.linkLayer = new L.FeatureGroup();
    window.plugin.crossLinks.linkLayerGuids={};
    window.addLayerGroup('Cross Links', window.plugin.crossLinks.linkLayer, true);

    map.on('layeradd', function(obj) {
      if(obj.layer === window.plugin.crossLinks.linkLayer) {
        delete window.plugin.crossLinks.disabled;
        window.plugin.crossLinks.checkAllLinks();
      }
    });
    map.on('layerremove', function(obj) {
      if(obj.layer === window.plugin.crossLinks.linkLayer) {
        window.plugin.crossLinks.disabled = true;
        window.plugin.crossLinks.linkLayer.clearLayers();
        plugin.crossLinks.linkLayerGuids = {};
      }
    });
}

var setup = function() {
    if (window.plugin.drawTools === undefined) {
       alert("'Cross-Links' requires 'draw-tools'");
       return;
    }

    // this plugin also needs to create the draw-tools hook, in case it is initialised before draw-tools
    window.pluginCreateHook('pluginDrawTools');

    window.plugin.crossLinks.createLayer();

    // events
    window.addHook('pluginDrawTools',function(e) {
        if (e.event == 'layerCreated') {
            // we can just test the new layer in this case
            window.plugin.crossLinks.testAllLinksAgainstLayer(e.layer);
        } else {
            // all other event types - assume anything could have been modified and re-check all links
            window.plugin.crossLinks.checkAllLinks();
        }
    });

    window.addHook('linkAdded', window.plugin.crossLinks.onLinkAdded);
    window.addHook('mapDataRefreshEnd', window.plugin.crossLinks.onMapDataRefreshEnd);
}

// PLUGIN END //////////////////////////////////////////////////////////

@@PLUGINEND@@
<commit_msg>fix cross-links plugin to correctly remove links that have gone<commit_after>// ==UserScript==
// @id             iitc-plugin-cross-links@mcben
// @name           IITC plugin: cross links
// @category       Layer
// @version        1.1.1.@@DATETIMEVERSION@@
// @namespace      https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL      @@UPDATEURL@@
// @downloadURL    @@DOWNLOADURL@@
// @description    [@@BUILDNAME@@-@@BUILDDATE@@] EXPERIMENTAL: Checks for existing links that cross planned links. Requires draw-tools plugin.
// @include        https://www.ingress.com/intel*
// @include        http://www.ingress.com/intel*
// @match          https://www.ingress.com/intel*
// @match          http://www.ingress.com/intel*
// @grant          none
// ==/UserScript==

@@PLUGINSTART@@

// PLUGIN START ////////////////////////////////////////////////////////

window.plugin.crossLinks = function() {};

window.plugin.crossLinks.greatCircleArcIntersect = function(a0,a1,b0,b1) {
  // based on the formula at http://williams.best.vwh.net/avform.htm#Int

  // method:
  // check to ensure no line segment is zero length - if so, cannot cross
  // check to see if either of the lines start/end at the same point. if so, then they cannot cross
  // check to see if the line segments overlap in longitude. if not, no crossing
  // if overlap, clip each line to the overlapping longitudes, then see if latitudes cross

  // anti-meridian handling. this code will not sensibly handle a case where one point is
  // close to -180 degrees and the other +180 degrees. unwrap coordinates in this case, so one point
  // is beyond +-180 degrees. this is already true in IITC
  // FIXME? if the two lines have been 'unwrapped' differently - one positive, one negative - it will fail

  // zero length line tests
  if (a0.equals(a1)) return false;
  if (b0.equals(b1)) return false;

  // lines have a common point
  if (a0.equals(b0) || a0.equals(b1)) return false;
  if (a1.equals(b0) || a1.equals(b1)) return false;

  // check for 'horizontal' overlap in lngitude
  if (Math.min(a0.lng,a1.lng) > Math.max(b0.lng,b1.lng)) return false;
  if (Math.max(a0.lng,a1.lng) < Math.min(b0.lng,b1.lng)) return false;

  // ok, our two lines have some horizontal overlap in longitude
  // 1. calculate the overlapping min/max longitude
  // 2. calculate each line latitude at each point
  // 3. if latitudes change place between overlapping range, the lines cross

  // class to hold the pre-calculated maths for a geodesic line
  // TODO: move this outside this function, so it can be pre-calculated once for each line we test
  var GeodesicLine = function(start,end) {
    var d2r = Math.PI/180.0;
    var r2d = 180.0/Math.PI;

    // maths based on http://williams.best.vwh.net/avform.htm#Int

    if (start.lng == end.lng) {
      throw 'Error: cannot calculate latitude for meridians';
    }

    // only the variables needed to calculate a latitude for a given longitude are stored in 'this'
    this.lat1 = start.lat * d2r;
    this.lat2 = end.lat * d2r;
    this.lng1 = start.lng * d2r;
    this.lng2 = end.lng * d2r;

    var dLng = this.lng1-this.lng2;

    var sinLat1 = Math.sin(this.lat1);
    var sinLat2 = Math.sin(this.lat2);
    var cosLat1 = Math.cos(this.lat1);
    var cosLat2 = Math.cos(this.lat2);

    this.sinLat1CosLat2 = sinLat1*cosLat2;
    this.sinLat2CosLat1 = sinLat2*cosLat1;

    this.cosLat1CosLat2SinDLng = cosLat1*cosLat2*Math.sin(dLng);
  }

  GeodesicLine.prototype.isMeridian = function() {
    return this.lng1 == this.lng2;
  }

  GeodesicLine.prototype.latAtLng = function(lng) {
    lng = lng * Math.PI / 180; //to radians

    var lat;
    // if we're testing the start/end point, return that directly rather than calculating
    // 1. this may be fractionally faster, no complex maths
    // 2. there's odd rounding issues that occur on some browsers (noticed on IITC MObile) for very short links - this may help
    if (lng == this.lng1) {
      lat = this.lat1;
    } else if (lng == this.lng2) {
      lat = this.lat2;
    } else {
      lat = Math.atan ( (this.sinLat1CosLat2*Math.sin(lng-this.lng2) - this.sinLat2CosLat1*Math.sin(lng-this.lng1))
                       / this.cosLat1CosLat2SinDLng);
    }
    return lat * 180 / Math.PI; // return value in degrees
  }

  // calculate the longitude of the overlapping region
  var leftLng = Math.max( Math.min(a0.lng,a1.lng), Math.min(b0.lng,b1.lng) );
  var rightLng = Math.min( Math.max(a0.lng,a1.lng), Math.max(b0.lng,b1.lng) );

  // calculate the latitudes for each line at left + right longitudes
  // NOTE: need a special case for meridians - as GeodesicLine.latAtLng method is invalid in that case
  var aLeftLat, aRightLat;
  if (a0.lng == a1.lng) {
    // 'left' and 'right' now become 'top' and 'bottom' (in some order) - which is fine for the below intersection code
    aLeftLat = a0.lat;
    aRightLat = a1.lat;
  } else {
    var aGeo = new GeodesicLine(a0,a1);
    aLeftLat = aGeo.latAtLng(leftLng);
    aRightLat = aGeo.latAtLng(rightLng);
  }

  var bLeftLat, bRightLat;
  if (b0.lng == b1.lng) {
    // 'left' and 'right' now become 'top' and 'bottom' (in some order) - which is fine for the below intersection code
    bLeftLat = b0.lat;
    bRightLat = b1.lat;
  } else {
    var bGeo = new GeodesicLine(b0,b1);
    bLeftLat = bGeo.latAtLng(leftLng);
    bRightLat = bGeo.latAtLng(rightLng);
  }

  // if both a are less or greater than both b, then lines do not cross

  if (aLeftLat < bLeftLat && aRightLat < bRightLat) return false;
  if (aLeftLat > bLeftLat && aRightLat > bRightLat) return false;

  // latitudes cross between left and right - so geodesic lines cross
  return true;
}

window.plugin.crossLinks.testPolyLine = function (polyline, link,closed) {

    var a = link.getLatLngs();
    var b = polyline.getLatLngs();

    for (var i=0;i<b.length-1;++i) {
        if (window.plugin.crossLinks.greatCircleArcIntersect(a[0],a[1],b[i],b[i+1])) return true;
    }

    if (closed) {
        if (window.plugin.crossLinks.greatCircleArcIntersect(a[0],a[1],b[b.length-1],b[0])) return true;
    }

    return false;
}

window.plugin.crossLinks.onLinkAdded = function (data) {
    if (window.plugin.crossLinks.disabled) return;

    plugin.crossLinks.testLink(data.link);
}

window.plugin.crossLinks.checkAllLinks = function() {
    if (window.plugin.crossLinks.disabled) return;

    console.debug("Cross-Links: checking all links");
    plugin.crossLinks.linkLayer.clearLayers();
    plugin.crossLinks.linkLayerGuids = {};

    $.each(window.links, function(guid, link) {
        plugin.crossLinks.testLink(link);
    });
}

window.plugin.crossLinks.testLink = function (link) {
    if (plugin.crossLinks.linkLayerGuids[link.options.guid]) return;

    for (var i in plugin.drawTools.drawnItems._layers) { // leaflet don't support breaking out of the loop
       var layer = plugin.drawTools.drawnItems._layers[i];
       if (layer instanceof L.GeodesicPolygon) {
           if (plugin.crossLinks.testPolyLine(layer, link,true)) {
               plugin.crossLinks.showLink(link);
               break;
           }
        } else if (layer instanceof L.GeodesicPolyline) {
            if (plugin.crossLinks.testPolyLine(layer, link)) {
                plugin.crossLinks.showLink(link);
                break;
            }
        }
    };
}

window.plugin.crossLinks.showLink = function(link) {

    var poly = L.geodesicPolyline(link.getLatLngs(), {
       color: '#d22',
       opacity: 0.7,
       weight: 5,
       clickable: false,
       dashArray: [8,8],

       guid: link.options.guid
    });

    poly.addTo(plugin.crossLinks.linkLayer);
    plugin.crossLinks.linkLayerGuids[link.options.guid]=poly;
}

window.plugin.crossLinks.onMapDataRefreshEnd = function () {
    if (window.plugin.crossLinks.disabled) return;

    window.plugin.crossLinks.linkLayer.bringToFront();

    window.plugin.crossLinks.testForDeletedLinks();
}

window.plugin.crossLinks.testAllLinksAgainstLayer = function (layer) {
    if (window.plugin.crossLinks.disabled) return;

    $.each(window.links, function(guid, link) {
        if (!plugin.crossLinks.linkLayerGuids[link.options.guid])
        {
            if (layer instanceof L.GeodesicPolygon) {
                if (plugin.crossLinks.testPolyLine(layer, link,true)) {
                    plugin.crossLinks.showLink(link);
                }
            } else if (layer instanceof L.GeodesicPolyline) {
                if (plugin.crossLinks.testPolyLine(layer, link)) {
                    plugin.crossLinks.showLink(link);
                }
            }
        }
    });
}

window.plugin.crossLinks.testForDeletedLinks = function () {
    window.plugin.crossLinks.linkLayer.eachLayer( function(layer) {
        var guid = layer.options.guid;
        if (!window.links[guid]) {
            console.log("link removed");
            plugin.crossLinks.linkLayer.removeLayer(layer);
            delete plugin.crossLinks.linkLayerGuids[guid];
        }
    });
}

window.plugin.crossLinks.createLayer = function() {
    window.plugin.crossLinks.linkLayer = new L.FeatureGroup();
    window.plugin.crossLinks.linkLayerGuids={};
    window.addLayerGroup('Cross Links', window.plugin.crossLinks.linkLayer, true);

    map.on('layeradd', function(obj) {
      if(obj.layer === window.plugin.crossLinks.linkLayer) {
        delete window.plugin.crossLinks.disabled;
        window.plugin.crossLinks.checkAllLinks();
      }
    });
    map.on('layerremove', function(obj) {
      if(obj.layer === window.plugin.crossLinks.linkLayer) {
        window.plugin.crossLinks.disabled = true;
        window.plugin.crossLinks.linkLayer.clearLayers();
        plugin.crossLinks.linkLayerGuids = {};
      }
    });
}

var setup = function() {
    if (window.plugin.drawTools === undefined) {
       alert("'Cross-Links' requires 'draw-tools'");
       return;
    }

    // this plugin also needs to create the draw-tools hook, in case it is initialised before draw-tools
    window.pluginCreateHook('pluginDrawTools');

    window.plugin.crossLinks.createLayer();

    // events
    window.addHook('pluginDrawTools',function(e) {
        if (e.event == 'layerCreated') {
            // we can just test the new layer in this case
            window.plugin.crossLinks.testAllLinksAgainstLayer(e.layer);
        } else {
            // all other event types - assume anything could have been modified and re-check all links
            window.plugin.crossLinks.checkAllLinks();
        }
    });

    window.addHook('linkAdded', window.plugin.crossLinks.onLinkAdded);
    window.addHook('mapDataRefreshEnd', window.plugin.crossLinks.onMapDataRefreshEnd);
}

// PLUGIN END //////////////////////////////////////////////////////////

@@PLUGINEND@@
<|endoftext|>


<commit_before>/*!
 * msgpack-response
 * Copyright(c) 2017 Mobiltron Inc
 * MIT Licensed
 */

/**
 * Module dependencies.
 */
const _ = require('lodash');
const mung = require('express-mung');
const msgpackLite = require('msgpack-lite');

/**
 * Module variables.
 * @private
 */
var cacheControlNoTransformRegExp = /(?:^|,)\s*?no-transform\s*?(?:,|$)/;

/**
 * Transform response data using msgpack.
 *
 * @param {Object} [options]
 * @return {Function} middleware
 * @public
 */
function msgpack (options) {

  return function compression (req, res, next) {

    next()
  }
}

/**
 * Determine if the response body is JSON.
 * @private
 */
function isJSON(obj) {
  if(obj instanceof Array || obj instanceof Object) {
    return true
  }
  return false
}

/**
 * Determine if the request supports msgpack.
 * @private
 */
function isMgsPackSupported (req) {
  var acceptType = req.header('accept');
  return _.isNil(acceptType) === false && acceptType === 'application/x-msgpack'
}

/**
 * Determine if the entity should be transformed.
 * @private
 */
function shouldTransform (res) {
  var cacheControl = res.header['cache-control'];

  // Don't compress for Cache-Control: no-transform
  // https://tools.ietf.org/html/rfc7234#section-5.2.2.4
  return _.isNil(cacheControl) === false || !cacheControlNoTransformRegExp.test(cacheControl);
}

/**
 * Module exports.
 */

module.exports = msgpack;
<commit_msg>Refactoring index.js<commit_after>/*!
 * msgpack-response
 * Copyright(c) 2017 Mobiltron Inc
 * MIT Licensed
 */

/**
 * Module dependencies.
 */
const _ = require('lodash');
const mung = require('express-mung');
const msgpackLite = require('msgpack-lite');

/**
 * Module variables.
 * @private
 */
var cacheControlNoTransformRegExp = /(?:^|,)\s*?no-transform\s*?(?:,|$)/;

/**
 * Transform response data using msgpack.
 *
 * @param {Object} [options]
 * @return {Function} middleware
 * @public
 */
module.exports = function(options) {

  return function(req, res, next) {
    // Implement the middleware function based on the options object
    next()
  }
};

/**
 * Determine if the response body is JSON.
 * @private
 */
function isJSON(obj) {
  if(obj instanceof Array || obj instanceof Object) {
    return true
  }
  return false
}

/**
 * Determine if the request supports msgpack.
 * @private
 */
function isMgsPackSupported (req) {
  var acceptType = req.header('accept');
  return _.isNil(acceptType) === false && acceptType === 'application/x-msgpack'
}

/**
 * Determine if the entity should be transformed.
 * @private
 */
function shouldTransform (res) {
  var cacheControl = res.header['cache-control'];

  // Don't compress for Cache-Control: no-transform
  // https://tools.ietf.org/html/rfc7234#section-5.2.2.4
  return _.isNil(cacheControl) === false || !cacheControlNoTransformRegExp.test(cacheControl);
}
<|endoftext|>


<commit_before>var torrentStream = require('torrent-stream')
var http = require('http')
var fs = require('fs')
var rangeParser = require('range-parser')
var xtend = require('xtend')
var url = require('url')
var mime = require('mime')
var pump = require('pump')

var parseBlocklist = function (filename) {
  // TODO: support gzipped files
  var blocklistData = fs.readFileSync(filename, { encoding: 'utf8' })
  var blocklist = []
  blocklistData.split('\n').forEach(function (line) {
    var match = null
    if ((match = /^\s*[^#].*?\s*:\s*([a-f0-9.:]+?)\s*-\s*([a-f0-9.:]+?)\s*$/.exec(line))) {
      blocklist.push({
        start: match[1],
        end: match[2]
      })
    }
  })
  return blocklist
}

var truthy = function () {
  return true
}

var createServer = function (e, opts) {
  var server = http.createServer()
  var index = opts.index
  var getType = opts.type || mime.lookup.bind(mime)
  var filter = opts.filter || truthy

  var onready = function () {
    if (typeof index !== 'number') {
      index = e.files.reduce(function (a, b) {
        return a.length > b.length ? a : b
      })
      index = e.files.indexOf(index)
    }

    e.files[index].select()
    server.index = e.files[index]

    if (opts.sort) e.files.sort(opts.sort)
  }

  if (e.torrent) onready()
  else e.on('ready', onready)

  server.on('request', function (request, response) {
    var u = url.parse(request.url)
    var host = request.headers.host || 'localhost'

    var toPlaylist = function () {
      var toEntry = function (file, i) {
        return '#EXTINF:-1,' + file.path + '\n' + 'http://' + host + '/' + i
      }

      return '#EXTM3U\n' + e.files.filter(filter).map(toEntry).join('\n')
    }

    var toJSON = function () {
      var totalPeers = e.swarm.wires
      var activePeers = totalPeers.filter(function (wire) {
        return !wire.peerChoking
      })
      var totalLength = e.files.reduce(function(prevFileLength, currFile) {
        return prevFileLength + currFile.length
      }, 0)

      var swarmStats = {
        totalLength: totalLength,
        downloaded: e.swarm.downloaded,
        uploaded: e.swarm.uploaded,
        downloadSpeed: parseInt(e.swarm.downloadSpeed()),
        uploadSpeed: parseInt(e.swarm.uploadSpeed()),
        totalPeers: totalPeers.length,
        activePeers: activePeers.length
      }

      var toEntry = function (file, i) {
        return {
          name: file.name,
          url: 'http://' + host + '/' + i,
          length: file.length
        }
      }

      swarmStats.files = e.files.filter(filter).map(toEntry)

      return JSON.stringify(swarmStats, null, '  ')
    }

    // Allow CORS requests to specify arbitrary headers, e.g. 'Range',
    // by responding to the OPTIONS preflight request with the specified
    // origin and requested headers.
    if (request.method === 'OPTIONS' && request.headers['access-control-request-headers']) {
      response.setHeader('Access-Control-Allow-Origin', request.headers.origin)
      response.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
      response.setHeader(
          'Access-Control-Allow-Headers',
          request.headers['access-control-request-headers'])
      response.setHeader('Access-Control-Max-Age', '1728000')

      response.end()
      return
    }

    if (request.headers.origin) response.setHeader('Access-Control-Allow-Origin', request.headers.origin)
    if (u.pathname === '/') u.pathname = '/' + index

    if (u.pathname === '/favicon.ico') {
      response.statusCode = 404
      response.end()
      return
    }

    if (u.pathname === '/.json') {
      var json = toJSON()
      response.setHeader('Content-Type', 'application/json; charset=utf-8')
      response.setHeader('Content-Length', Buffer.byteLength(json))
      response.end(json)
      return
    }

    if (u.pathname === '/.m3u') {
      var playlist = toPlaylist()
      response.setHeader('Content-Type', 'application/x-mpegurl; charset=utf-8')
      response.setHeader('Content-Length', Buffer.byteLength(playlist))
      response.end(playlist)
      return
    }

    e.files.forEach(function (file, i) {
      if (u.pathname.slice(1) === file.name) u.pathname = '/' + i
    })

    var i = Number(u.pathname.slice(1))

    if (isNaN(i) || i >= e.files.length) {
      response.statusCode = 404
      response.end()
      return
    }

    var file = e.files[i]
    var range = request.headers.range
    range = range && rangeParser(file.length, range)[0]
    response.setHeader('Accept-Ranges', 'bytes')
    response.setHeader('Content-Type', getType(file.name))
    response.setHeader('transferMode.dlna.org', 'Streaming')
    response.setHeader('contentFeatures.dlna.org', 'DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=017000 00000000000000000000000000')
    if (!range) {
      response.setHeader('Content-Length', file.length)
      if (request.method === 'HEAD') return response.end()
      pump(file.createReadStream(), response)
      return
    }

    response.statusCode = 206
    response.setHeader('Content-Length', range.end - range.start + 1)
    response.setHeader('Content-Range', 'bytes ' + range.start + '-' + range.end + '/' + file.length)
    response.setHeader('transferMode.dlna.org', 'Streaming')
    response.setHeader('contentFeatures.dlna.org', 'DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=017000 00000000000000000000000000')
    if (request.method === 'HEAD') return response.end()
    pump(file.createReadStream(range), response)
  })

  server.on('connection', function (socket) {
    socket.setTimeout(36000000)
  })

  return server
}

module.exports = function (torrent, opts) {
  if (!opts) opts = {}

  // Parse blocklist
  if (opts.blocklist) opts.blocklist = parseBlocklist(opts.blocklist)

  var engine = torrentStream(torrent, xtend(opts, {port: opts.peerPort}))

  // Just want torrent-stream to list files.
  if (opts.list) return engine

  // Pause/Resume downloading as needed
  engine.on('uninterested', function () {
    engine.swarm.pause()
  })

  engine.on('interested', function () {
    engine.swarm.resume()
  })

  engine.server = createServer(engine, opts)

  // Listen when torrent-stream is ready, by default a random port.
  engine.on('ready', function () {
    engine.server.listen(opts.port || 0, opts.hostname)
  })

  engine.listen()

  return engine
}
<commit_msg>Compliance with JavaScript Standard Style.<commit_after>var torrentStream = require('torrent-stream')
var http = require('http')
var fs = require('fs')
var rangeParser = require('range-parser')
var xtend = require('xtend')
var url = require('url')
var mime = require('mime')
var pump = require('pump')

var parseBlocklist = function (filename) {
  // TODO: support gzipped files
  var blocklistData = fs.readFileSync(filename, { encoding: 'utf8' })
  var blocklist = []
  blocklistData.split('\n').forEach(function (line) {
    var match = null
    if ((match = /^\s*[^#].*?\s*:\s*([a-f0-9.:]+?)\s*-\s*([a-f0-9.:]+?)\s*$/.exec(line))) {
      blocklist.push({
        start: match[1],
        end: match[2]
      })
    }
  })
  return blocklist
}

var truthy = function () {
  return true
}

var createServer = function (e, opts) {
  var server = http.createServer()
  var index = opts.index
  var getType = opts.type || mime.lookup.bind(mime)
  var filter = opts.filter || truthy

  var onready = function () {
    if (typeof index !== 'number') {
      index = e.files.reduce(function (a, b) {
        return a.length > b.length ? a : b
      })
      index = e.files.indexOf(index)
    }

    e.files[index].select()
    server.index = e.files[index]

    if (opts.sort) e.files.sort(opts.sort)
  }

  if (e.torrent) onready()
  else e.on('ready', onready)

  server.on('request', function (request, response) {
    var u = url.parse(request.url)
    var host = request.headers.host || 'localhost'

    var toPlaylist = function () {
      var toEntry = function (file, i) {
        return '#EXTINF:-1,' + file.path + '\n' + 'http://' + host + '/' + i
      }

      return '#EXTM3U\n' + e.files.filter(filter).map(toEntry).join('\n')
    }

    var toJSON = function () {
      var totalPeers = e.swarm.wires
      var activePeers = totalPeers.filter(function (wire) {
        return !wire.peerChoking
      })
      var totalLength = e.files.reduce(function (prevFileLength, currFile) {
        return prevFileLength + currFile.length
      }, 0)

      var swarmStats = {
        totalLength: totalLength,
        downloaded: e.swarm.downloaded,
        uploaded: e.swarm.uploaded,
        downloadSpeed: parseInt(e.swarm.downloadSpeed(), 10),
        uploadSpeed: parseInt(e.swarm.uploadSpeed(), 10),
        totalPeers: totalPeers.length,
        activePeers: activePeers.length
      }

      var toEntry = function (file, i) {
        return {
          name: file.name,
          url: 'http://' + host + '/' + i,
          length: file.length
        }
      }

      swarmStats.files = e.files.filter(filter).map(toEntry)

      return JSON.stringify(swarmStats, null, '  ')
    }

    // Allow CORS requests to specify arbitrary headers, e.g. 'Range',
    // by responding to the OPTIONS preflight request with the specified
    // origin and requested headers.
    if (request.method === 'OPTIONS' && request.headers['access-control-request-headers']) {
      response.setHeader('Access-Control-Allow-Origin', request.headers.origin)
      response.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
      response.setHeader(
          'Access-Control-Allow-Headers',
          request.headers['access-control-request-headers'])
      response.setHeader('Access-Control-Max-Age', '1728000')

      response.end()
      return
    }

    if (request.headers.origin) response.setHeader('Access-Control-Allow-Origin', request.headers.origin)
    if (u.pathname === '/') u.pathname = '/' + index

    if (u.pathname === '/favicon.ico') {
      response.statusCode = 404
      response.end()
      return
    }

    if (u.pathname === '/.json') {
      var json = toJSON()
      response.setHeader('Content-Type', 'application/json; charset=utf-8')
      response.setHeader('Content-Length', Buffer.byteLength(json))
      response.end(json)
      return
    }

    if (u.pathname === '/.m3u') {
      var playlist = toPlaylist()
      response.setHeader('Content-Type', 'application/x-mpegurl; charset=utf-8')
      response.setHeader('Content-Length', Buffer.byteLength(playlist))
      response.end(playlist)
      return
    }

    e.files.forEach(function (file, i) {
      if (u.pathname.slice(1) === file.name) u.pathname = '/' + i
    })

    var i = Number(u.pathname.slice(1))

    if (isNaN(i) || i >= e.files.length) {
      response.statusCode = 404
      response.end()
      return
    }

    var file = e.files[i]
    var range = request.headers.range
    range = range && rangeParser(file.length, range)[0]
    response.setHeader('Accept-Ranges', 'bytes')
    response.setHeader('Content-Type', getType(file.name))
    response.setHeader('transferMode.dlna.org', 'Streaming')
    response.setHeader('contentFeatures.dlna.org', 'DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=017000 00000000000000000000000000')
    if (!range) {
      response.setHeader('Content-Length', file.length)
      if (request.method === 'HEAD') return response.end()
      pump(file.createReadStream(), response)
      return
    }

    response.statusCode = 206
    response.setHeader('Content-Length', range.end - range.start + 1)
    response.setHeader('Content-Range', 'bytes ' + range.start + '-' + range.end + '/' + file.length)
    response.setHeader('transferMode.dlna.org', 'Streaming')
    response.setHeader('contentFeatures.dlna.org', 'DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=017000 00000000000000000000000000')
    if (request.method === 'HEAD') return response.end()
    pump(file.createReadStream(range), response)
  })

  server.on('connection', function (socket) {
    socket.setTimeout(36000000)
  })

  return server
}

module.exports = function (torrent, opts) {
  if (!opts) opts = {}

  // Parse blocklist
  if (opts.blocklist) opts.blocklist = parseBlocklist(opts.blocklist)

  var engine = torrentStream(torrent, xtend(opts, {port: opts.peerPort}))

  // Just want torrent-stream to list files.
  if (opts.list) return engine

  // Pause/Resume downloading as needed
  engine.on('uninterested', function () {
    engine.swarm.pause()
  })

  engine.on('interested', function () {
    engine.swarm.resume()
  })

  engine.server = createServer(engine, opts)

  // Listen when torrent-stream is ready, by default a random port.
  engine.on('ready', function () {
    engine.server.listen(opts.port || 0, opts.hostname)
  })

  engine.listen()

  return engine
}
<|endoftext|>


<commit_before>import {run, Rx} from '@cycle/core';
import {makeDOMDriver, h} from '@cycle/dom';
import CycleTimeTravel from 'cycle-time-travel';
import $ from 'jquery';
import _ from 'lodash';
import rhyme from 'rhyme';

Rx.config.longStackSupport = true;

function log (label) {
  return console.log.bind(console, label);
}

function keyPressed (key, number) {
  return ev => {
    return ev.key === key || ev.keyIdentifier === key || ev.keyCode === number;
  };
}

function addRhyme (wordToRhyme, rhyme) {
  return text => {
    let availableRhymes = rhyme.rhyme(wordToRhyme);

    if (availableRhymes === undefined) {
      availableRhymes = [];
    }

    const madeRhyme = _.sample(availableRhymes) || '';

    return text + madeRhyme.toLowerCase();
  };
}

function updateText (text) {
  return oldText => text;
}

function main ({DOM}) {
  const textUpdate$ = DOM.select('.text').events('input')
    .map(event => event.target.value)
    .startWith('');

  const keyPress$ = DOM.select('.container').events('keydown');

  const tabPress$ = keyPress$.filter(keyPressed('Tab', 9));

  const rhymePress$ = Rx.Observable.merge(
    tabPress$,
    DOM.select('.rhyme').events('click')
  );

  const wordToRhyme$ = textUpdate$.map(
    text => _.chain(text.split('\n'))
      .map(_.trim)
      .select(line => line !== '')
      .map(line => line.split(' '))
      .thru(lines => {
        if (lines.length > 1) {
          return lines[lines.length - 2];
        }

        return _.last(lines);
      })
      .last().value()
  );

  const rhyme$ = Rx.Observable.fromCallback(rhyme)();

  rhymePress$.forEach(ev => ev.preventDefault());

  const editorText$ = Rx.Observable.merge(
    rhymePress$.withLatestFrom(wordToRhyme$, rhyme$, (ev, wordToRhyme, rhyme) => addRhyme(wordToRhyme, rhyme)),
    textUpdate$.map(text => updateText(text))
  ).scan((text, modifier) => modifier(text), '');

  return {
    DOM: Rx.Observable.combineLatest(
      editorText$,
      wordToRhyme$,
      (text, timeTravelBar, wordToRhyme) => (
        h('.container', [
          h('h1', 'Ghostwriter'),
          h('.app-inner', [
            h('button.rhyme', 'RHYME'),
            h('textarea.text', {rows: 18, value: text})
          ])
        ])
      ))
  };
}

const drivers = {
  DOM: makeDOMDriver('.app')
};

$(() => run(main, drivers));
<commit_msg>Refactor main to have explicit action$<commit_after>import {run, Rx} from '@cycle/core';
import {makeDOMDriver, h} from '@cycle/dom';
import CycleTimeTravel from 'cycle-time-travel';
import $ from 'jquery';
import _ from 'lodash';
import rhyme from 'rhyme';

Rx.config.longStackSupport = true;

function log (label) {
  return console.log.bind(console, label);
}

function keyPressed (key, number) {
  return ev => {
    return ev.key === key || ev.keyIdentifier === key || ev.keyCode === number;
  };
}

function addRhyme (wordToRhyme, rhyme) {
  return text => {
    let availableRhymes = rhyme.rhyme(wordToRhyme);

    if (availableRhymes === undefined) {
      availableRhymes = [];
    }

    const madeRhyme = _.sample(availableRhymes) || '';

    return text + madeRhyme.toLowerCase();
  };
}

function updateText (text) {
  return oldText => text;
}

function main ({DOM}) {
  const textUpdate$ = DOM.select('.text').events('input')
    .map(event => event.target.value)
    .startWith('');

  const keyPress$ = DOM.select('.container').events('keydown');

  const tabPress$ = keyPress$.filter(keyPressed('Tab', 9));

  const rhymePress$ = Rx.Observable.merge(
    tabPress$,
    DOM.select('.rhyme').events('click')
  );

  const wordToRhyme$ = textUpdate$.map(
    text => _.chain(text.split('\n'))
      .map(_.trim)
      .select(line => line !== '')
      .map(line => line.split(' '))
      .thru(lines => {
        if (lines.length > 1) {
          return lines[lines.length - 2];
        }

        return _.last(lines);
      })
      .last().value()
  );

  const rhyme$ = Rx.Observable.fromCallback(rhyme)();

  rhymePress$.forEach(ev => ev.preventDefault());

  const action$ = Rx.Observable.merge(
    rhymePress$.withLatestFrom(wordToRhyme$, rhyme$, (ev, wordToRhyme, rhyme) => addRhyme(wordToRhyme, rhyme)),
    textUpdate$.map(text => updateText(text))
  );

  const editorText$ = action$.scan((text, action) => action(text), '');

  return {
    DOM: Rx.Observable.combineLatest(
      editorText$,
      wordToRhyme$,
      (text, timeTravelBar, wordToRhyme) => (
        h('.container', [
          h('h1', 'Ghostwriter'),
          h('.app-inner', [
            h('button.rhyme', 'RHYME'),
            h('textarea.text', {rows: 18, value: text})
          ])
        ])
      ))
  };
}

const drivers = {
  DOM: makeDOMDriver('.app')
};

$(() => run(main, drivers));
<|endoftext|>


<commit_before>'use strict';

global.Promise = require('bluebird');
global.ROOT = __dirname;

const http = require('http');
const bodyParser = require('body-parser');
const express = require('express');
const logger = require('morgan');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');

const env = process.env.NODE_ENV || 'development';
const port = process.env.PORT || 3000;

const app = express();

app.locals.ENV = env;
app.locals.ENV_DEVELOPMENT = (env === 'development');

app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.use(express.static(`${ROOT}/public`));
if (env === 'development') {
    const compiler = webpack(require('./webpack.config.dev'));
    app.use(webpackDevMiddleware(compiler, {
        noInfo: true,
        stats: {
            colors: true
        }
    }));
    app.use(webpackHotMiddleware(compiler));
}

app.use((err, req, res) => {
    res.status(500).send(err.stack);
    console.error(err);
});

const server = http.createServer(app);

server.listen(port, () => console.log(`==> Listening on port ${server.address().port}`));
<commit_msg>Use builtin promise.<commit_after>'use strict';

global.ROOT = __dirname;

const http = require('http');
const bodyParser = require('body-parser');
const express = require('express');
const logger = require('morgan');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');

const env = process.env.NODE_ENV || 'development';
const port = process.env.PORT || 3000;

const app = express();

app.locals.ENV = env;
app.locals.ENV_DEVELOPMENT = (env === 'development');

app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.use(express.static(`${ROOT}/public`));
if (env === 'development') {
    const compiler = webpack(require('./webpack.config.dev'));
    app.use(webpackDevMiddleware(compiler, {
        noInfo: true,
        stats: {
            colors: true
        }
    }));
    app.use(webpackHotMiddleware(compiler));
}

app.use((err, req, res) => {
    res.status(500).send(err.stack);
    console.error(err);
});

const server = http.createServer(app);

server.listen(port, () => console.log(`==> Listening on port ${server.address().port}`));
<|endoftext|>


<commit_before>var BufferGroup = require('buffer-group'),
    OffsetBuffer = require('offset-buffer'),
    debug = false,
    events = require('events'),
    util = require('util');

module.exports = require('./framing-buffer.js')(
    OffsetBuffer,
    BufferGroup,
    debug,
    events,
    util,
    console
);<commit_msg>Modifying for Travis CI<commit_after>var BufferGroup = require('buffer-group'),
    OffsetBuffer = require('offset-buffer'),
    debug = false,
    events = require('events'),
    util = require('util');

module.exports = require('./framing-buffer.js')(
    OffsetBuffer,
    BufferGroup,
    debug,
    events,
    util,
    console
);

<|endoftext|>


<commit_before>var _kanaTrainer;
var _controller;
var _playMultipleChoice;

var area = JSON.parse(sessionStorage.getItem('area'));
var levels = [];
if (area) {
  levels = JSON.parse(sessionStorage.getItem(area+'_levels'));
}

if (levels && area) {
  initiate(area, levels);
} else {
  alert('Please first choose your symbols!');
  window.location.replace(ROOT_DIR+"home");
}

function initiate (area, levels) {
  // add button event handlers
  $("#kanaSwitchModeButton").click(switchMode);

  var kanaHandler;
  switch (area) {
    case 'hiragana':
    kanaHandler = new HiraganaHandler();
    break;
    case 'katakana':
    kanaHandler = new KatakanaHandler();
    default:
    break;

  }

  _kanaTrainer = new KanaTrainer (levels, kanaHandler);

  // display first question
  displayNewQuestion();

  // check if start with multipleChoice
  if (sessionStorage.getItem('multipleChoice')) {
    _playMultipleChoice = true;
    _controller = new MultipleChoiceController();
    sessionStorage.removeItem('multipleChoice');
  } else {
    _playMultipleChoice = false;
    _controller = new TextInputController();
  }

}

function displayNewQuestion () {
  var question = _kanaTrainer.nextQuestion();
  $("#kanaQuestionText").text(question);
  updateTryNumber();
  updateTotalNumber();
}

function updateTryNumber () {
  var tryNr = _kanaTrainer.getCurrentQuestionTryNumber();
  $("#kanaStatisticsTryNr").text("Try "+tryNr+" / 2");
}

function updateTotalNumber () {
  var totalNr = _kanaTrainer.getCurrentQuestionTotalNumber();
  $("#kanaStatisticsTotalNr").text("Prompt "+totalNr);
}

function handleNegativeFeedback () {
  updateTryNumber();

  $("#kanaFeedbackText").addClass("alert-danger");
  $("#kanaFeedbackText").removeClass("alert-success");
  $("#kanaFeedbackText").text("FALSE");

  $("#kanaFeedbackLastAnswer").text('');
  $("#kanaFeedbackLastQuestion").text('');
}

function handlePositiveFeedback () {
  displayNewQuestion();

  $("#kanaFeedbackText").removeClass("alert-danger");
  $("#kanaFeedbackText").addClass("alert-success");
  $("#kanaFeedbackText").text("CORRECT");

  $("#kanaFeedbackLastAnswer").text(_kanaTrainer.previousAnswer());
  $("#kanaFeedbackLastQuestion").text(_kanaTrainer.previousQuestion());
}

function switchMode () {
  _playMultipleChoice = !_playMultipleChoice;

  if (_playMultipleChoice) {
    _controller = new MultipleChoiceController();
  } else {
    _controller = new TextInputController();
  }
}

var TextInputController = function () {

  // constructor
  // remove multiple choice, add text input field and large button
  $("#kanaMultipleChoiceArea").remove();
  initializeTextInput();

  function initializeTextInput() {
    var ele = '<form role="form" method="post" action="javascript:void(0);" id="kanaAnswerForm" autocomplete="off">';
    ele += '<input type="text" id="kanaAnswerTextfield" class="form-control text-center input-lg" name="answerInput" maxlength="4" autofocus="autofocus">';
    ele += '<input type="submit" id="kanaAnswerSubmitButton" class="btn btn-primary btn-lg btn-block" value="Check">';
    ele += '</form>';

    $("#kana-prompt-box").append(ele);
    $("#kanaAnswerTextfield").focus();
  }

  // allow only letters [A-Za-z] in input field
  $("#kanaAnswerTextfield").keypress(function(event){
    var inputValue = event.which;
    if ( (inputValue < 65 || inputValue > 90) && (inputValue < 97 || inputValue > 122) && inputValue != 13){
      event.preventDefault();
    }
  });

  // user clicked submit button below input field
  $("#kanaAnswerSubmitButton").click(function () {
    var answer = $("#kanaAnswerTextfield").val();

    if (typeof answer === undefined || answer === "") { // user did not enter anything
      return;
    }

    $("#kanaAnswerTextfield").val('');
    answer = answer.toLowerCase();

    if (_kanaTrainer.validate(answer)) {  //answer is correct
      handlePositiveFeedback();
    } else {  // answer was false
      handleNegativeFeedback();
    }
  });

};

var MultipleChoiceController = function () {

  // constructor
  // remove text input field and large button, add multiple choice
  $("#kanaAnswerForm").remove();
  initializeMultipleChoice();

  function initializeMultipleChoice () {
    var ele = '
';
    ele += '
';
    ele += '
<button type="button" class="btn btn-default btn-lg btn-block">0</button>
';
    ele += '
<button type="button" class="btn btn-default btn-lg btn-block">1</button>
';
    ele += '
';
    ele += '
';
    ele += '
<button type="button" class="btn btn-default btn-lg btn-block">2</button>
';
    ele += '
<button type="button" class="btn btn-default btn-lg btn-block">3</button>
';
    ele += '
';
    ele += '
';

    $("#kana-prompt-box").append(ele);
    updateMultipleChoice();
  }

  function updateMultipleChoice () {
    var multipleChoice = _kanaTrainer.getMultipleChoiceOptions();
    var buttons = $("button.btn-block");
    var i = 0;
    $.each(buttons, function() {
      $(this).attr('value', multipleChoice[i]);
      $(this).html(multipleChoice[i++]);
    });
  }

  // user clicked a multiple choice button
  $('button.btn-block').click(function(){
    var answer = $(this).attr('value');
    if (_kanaTrainer.validate(answer)) {  //answer is correct
      handlePositiveFeedback();
      updateMultipleChoice();
    } else {  // answer was false
      handleNegativeFeedback();
    }
  });

};
<commit_msg>fixed error<commit_after>var _kanaTrainer;
var _controller;
var _playMultipleChoice;

var TextInputController = function () {

  // constructor
  // remove multiple choice, add text input field and large button
  $("#kanaMultipleChoiceArea").remove();
  initializeTextInput();

  function initializeTextInput() {
    var ele = '<form role="form" method="post" action="javascript:void(0);" id="kanaAnswerForm" autocomplete="off">';
    ele += '<input type="text" id="kanaAnswerTextfield" class="form-control text-center input-lg" name="answerInput" maxlength="4" autofocus="autofocus">';
    ele += '<input type="submit" id="kanaAnswerSubmitButton" class="btn btn-primary btn-lg btn-block" value="Check">';
    ele += '</form>';

    $("#kana-prompt-box").append(ele);
    $("#kanaAnswerTextfield").focus();
  }

  // allow only letters [A-Za-z] in input field
  $("#kanaAnswerTextfield").keypress(function(event){
    var inputValue = event.which;
    if ( (inputValue < 65 || inputValue > 90) && (inputValue < 97 || inputValue > 122) && inputValue != 13){
      event.preventDefault();
    }
  });

  // user clicked submit button below input field
  $("#kanaAnswerSubmitButton").click(function () {
    var answer = $("#kanaAnswerTextfield").val();

    if (typeof answer === undefined || answer === "") { // user did not enter anything
      return;
    }

    $("#kanaAnswerTextfield").val('');
    answer = answer.toLowerCase();

    if (_kanaTrainer.validate(answer)) {  //answer is correct
      handlePositiveFeedback();
    } else {  // answer was false
      handleNegativeFeedback();
    }
  });

};

var MultipleChoiceController = function () {

  // constructor
  // remove text input field and large button, add multiple choice
  $("#kanaAnswerForm").remove();
  initializeMultipleChoice();

  function initializeMultipleChoice () {
    var ele = '
';
    ele += '
';
    ele += '
<button type="button" class="btn btn-default btn-lg btn-block">0</button>
';
    ele += '
<button type="button" class="btn btn-default btn-lg btn-block">1</button>
';
    ele += '
';
    ele += '
';
    ele += '
<button type="button" class="btn btn-default btn-lg btn-block">2</button>
';
    ele += '
<button type="button" class="btn btn-default btn-lg btn-block">3</button>
';
    ele += '
';
    ele += '
';

    $("#kana-prompt-box").append(ele);
    updateMultipleChoice();
  }

  function updateMultipleChoice () {
    var multipleChoice = _kanaTrainer.getMultipleChoiceOptions();
    var buttons = $("button.btn-block");
    var i = 0;
    $.each(buttons, function() {
      $(this).attr('value', multipleChoice[i]);
      $(this).html(multipleChoice[i++]);
    });
  }

  // user clicked a multiple choice button
  $('button.btn-block').click(function(){
    var answer = $(this).attr('value');
    if (_kanaTrainer.validate(answer)) {  //answer is correct
      handlePositiveFeedback();
      updateMultipleChoice();
    } else {  // answer was false
      handleNegativeFeedback();
    }
  });

};

var area = JSON.parse(sessionStorage.getItem('area'));
var levels = [];
if (area) {
  levels = JSON.parse(sessionStorage.getItem(area+'_levels'));
}

if (levels && area) {
  initiate(area, levels);
} else {
  alert('Please first choose your symbols!');
  window.location.replace(ROOT_DIR+"home");
}

function initiate (area, levels) {
  // add button event handlers
  $("#kanaSwitchModeButton").click(switchMode);

  var kanaHandler;
  switch (area) {
    case 'hiragana':
    kanaHandler = new HiraganaHandler();
    break;
    case 'katakana':
    kanaHandler = new KatakanaHandler();
    default:
    break;

  }

  _kanaTrainer = new KanaTrainer (levels, kanaHandler);

  // display first question
  displayNewQuestion();

  // check if start with multipleChoice
  if (sessionStorage.getItem('multipleChoice')) {
    _playMultipleChoice = true;
    _controller = new MultipleChoiceController();
    sessionStorage.removeItem('multipleChoice');
  } else {
    _playMultipleChoice = false;
    _controller = new TextInputController();
  }

}

function displayNewQuestion () {
  var question = _kanaTrainer.nextQuestion();
  $("#kanaQuestionText").text(question);
  updateTryNumber();
  updateTotalNumber();
}

function updateTryNumber () {
  var tryNr = _kanaTrainer.getCurrentQuestionTryNumber();
  $("#kanaStatisticsTryNr").text("Try "+tryNr+" / 2");
}

function updateTotalNumber () {
  var totalNr = _kanaTrainer.getCurrentQuestionTotalNumber();
  $("#kanaStatisticsTotalNr").text("Prompt "+totalNr);
}

function handleNegativeFeedback () {
  updateTryNumber();

  $("#kanaFeedbackText").addClass("alert-danger");
  $("#kanaFeedbackText").removeClass("alert-success");
  $("#kanaFeedbackText").text("FALSE");

  $("#kanaFeedbackLastAnswer").text('');
  $("#kanaFeedbackLastQuestion").text('');
}

function handlePositiveFeedback () {
  displayNewQuestion();

  $("#kanaFeedbackText").removeClass("alert-danger");
  $("#kanaFeedbackText").addClass("alert-success");
  $("#kanaFeedbackText").text("CORRECT");

  $("#kanaFeedbackLastAnswer").text(_kanaTrainer.previousAnswer());
  $("#kanaFeedbackLastQuestion").text(_kanaTrainer.previousQuestion());
}

function switchMode () {
  _playMultipleChoice = !_playMultipleChoice;

  if (_playMultipleChoice) {
    _controller = new MultipleChoiceController();
  } else {
    _controller = new TextInputController();
  }
}
<|endoftext|>


<commit_before>'use strict';

const isFirefoxAndroid = require('./lib/is-firefox-android')();
const tabs = require('sdk/tabs');

function handleClick() {
  const worker = tabs.activeTab.attach({
    contentScriptFile: './content-script.js',
  });
  worker.port.on('copyToClipboard', (request) => {
    if (!isFirefoxAndroid) {
      const clipboard = require('sdk/clipboard');
      clipboard.set(request);
    }
  });
  worker.port.emit('buildLinkPlain');
}

if (isFirefoxAndroid) {
  const { Cu } = require('chrome');
  const getWindow = () => {
    Cu.import('resource://gre/modules/Services.jsm');
    return Services.wm.getMostRecentWindow('navigator:browser');// eslint-disable-line no-undef
  };
  const nativeWindow = getWindow().NativeWindow;
  let menuId = 0;
  exports.main = (options, callback) => {// eslint-disable-line no-unused-vars
    menuId = nativeWindow.menu.add('Link Plain', null, () => void 0);
  };
  exports.onUnload = (reason) => {// eslint-disable-line no-unused-vars
    nativeWindow.menu.remove(menuId);
  };
} else {
  const { ActionButton } = require('sdk/ui/button/action');
  ActionButton({ // eslint-disable-line new-cap
    id: 'build-link-plain',
    label: 'Plain',
    icon: {
      16: './filter3-16.png',
      32: './filter3-32.png',
      64: './filter3-64.png',
    },
    onClick: handleClick,
  });
}

// tabs.on("ready", (tab) => {
//   tab.attach({
//     contentScript: "console.log(document.body.innerHTML);"
//   });
// });
<commit_msg>feat(link): support android prompt<commit_after>'use strict';

const isFirefoxAndroid = require('./lib/is-firefox-android')();
const tabs = require('sdk/tabs');

function handleClick() {
  const worker = tabs.activeTab.attach({
    contentScriptFile: './content-script.js',
  });
  worker.port.on('copyToClipboard', (request) => {
    if (isFirefoxAndroid) {
      const { Cc, Ci } = require('chrome');
      const prompts = Cc['@mozilla.org/embedcomp/prompt-service;1']
        .getService(Ci.nsIPromptService);
      prompts.prompt(null, 'Build Link Plain', 'Built link', { value: request }, null, { value: false });
    } else {
      const clipboard = require('sdk/clipboard');
      clipboard.set(request);
    }
  });
  worker.port.emit('buildLinkPlain');
}

if (isFirefoxAndroid) {
  const { Cu } = require('chrome');
  const getWindow = () => {
    Cu.import('resource://gre/modules/Services.jsm');
    return Services.wm.getMostRecentWindow('navigator:browser');// eslint-disable-line no-undef
  };
  const nativeWindow = getWindow().NativeWindow;
  let menuId = 0;
  exports.main = (options, callback) => {// eslint-disable-line no-unused-vars
    menuId = nativeWindow.menu.add({
      name: 'Link Plain',
      callback: handleClick,
    });
  };
  exports.onUnload = (reason) => {// eslint-disable-line no-unused-vars
    nativeWindow.menu.remove(menuId);
  };
} else {
  const { ActionButton } = require('sdk/ui/button/action');
  ActionButton({ // eslint-disable-line new-cap
    id: 'build-link-plain',
    label: 'Plain',
    icon: {
      16: './filter3-16.png',
      32: './filter3-32.png',
      64: './filter3-64.png',
    },
    onClick: handleClick,
  });
}

// tabs.on("ready", (tab) => {
//   tab.attach({
//     contentScript: "console.log(document.body.innerHTML);"
//   });
// });
<|endoftext|>


<commit_before>var buttons = require('sdk/ui/button/action');
var tabs = require("sdk/tabs");

var button = buttons.ActionButton({
  id: "donatal-link",
  label: "Acessar Diário Oficial de Natal",
  icon: {
    "16": "./icon-16.png",
    "32": "./icon-32.png",
    "64": "./icon-64.png"
  },
  onClick: handleClick
});

function handleClick(state) {
  tabs.open({
    url: "http://portal.natal.rn.gov.br/dom/index.php?p=c",
    onReady: function(tab) {
      tab.attach({
        contentScriptFile: "./content-script.js",
        contentScriptOptions: {
          chave: "cuidador",
          dtini: "01/08/2016",
          dtfim: "21/08/2016"
        }
      });
    }
  });
}

var { Hotkey } = require("sdk/hotkeys");

var donatalHotKey = Hotkey({
  combo: "control-shift-d",
  onPress: function() {
    handleClick();  // state?
  }
});
<commit_msg>Carregamento com POST<commit_after>var buttons = require('sdk/ui/button/action');

var button = buttons.ActionButton({
  id: "donatal-link",
  label: "Acessar Diário Oficial de Natal",
  icon: {
    "16": "./icon-16.png",
    "32": "./icon-32.png",
    "64": "./icon-64.png"
  },
  onClick: handleClick
});

var { Cc, Ci } = require("chrome");

function aPostDataFor(dataString) {

  var stringStream = Cc["@mozilla.org/io/string-input-stream;1"].
                     createInstance(Ci.nsIStringInputStream);
  if ("data" in stringStream) // Gecko 1.9 or newer
    stringStream.data = dataString;
  else // 1.8 or older
    stringStream.setData(dataString, dataString.length);

  var postData = Cc["@mozilla.org/network/mime-input-stream;1"].
                 createInstance(Ci.nsIMIMEInputStream);
  postData.addHeader("Content-Type", "application/x-www-form-urlencoded");
  postData.addContentLength = true;
  postData.setData(stringStream);
  return postData;
}

var { modelFor } = require("sdk/model/core");
var { viewFor } = require("sdk/view/core");

var tabs = require("sdk/tabs");
var utils = require("sdk/tabs/utils");

function handleClick(state) {
  var xulActiveTab = viewFor(tabs.activeTab);
  var tabBrowser = utils.getTabBrowserForTab(xulActiveTab);
  var postData = aPostDataFor("chave=cuidador&dtini=01/08/2016&dtfim=21/08/2016&list=Listar");
  var xulTab = tabBrowser.addTab(
      "http://portal.natal.rn.gov.br/dom/index.php?p=c",
      null,
      null,
      postData
  );
  // fast enough it goes to next step, or not?
  tabs.on("ready", function(tab) {
    tab.attach({
      contentScriptFile: "./content-script.js",
      contentScriptOptions: {
      chave: "cuidador",
      dtini: "01/08/2016",
      dtfim: "21/08/2016"
      }
    });
  });
}

var { Hotkey } = require("sdk/hotkeys");

var donatalHotKey = Hotkey({
  combo: "control-shift-d",
  onPress: function() {
    handleClick();  // state?
  }
});
<|endoftext|>


<commit_before>'use strict';

var c = require('../constants');

function convertToBase(manifestInfo, callback) {
  if (!manifestInfo || !manifestInfo.content) {
    return callback(new Error('Manifest content is empty or not initialized.'));
  }

  var originalManifest = manifestInfo.content;
  var manifest = {
    'start_url': originalManifest.app.launch.web_url,
    'name': originalManifest.name
  };

  var icons = [];

  for (var size in originalManifest.icons) {
    if (originalManifest.icons.hasOwnProperty(size)) {
      icons.push({
        'sizes' : size + 'x' + size,
        'src': originalManifest.icons[size]
      });
    }
  }

  manifest.icons = icons;

  var convertedManifestInfo = {
    'content': manifest,
    'format': c.BASE_MANIFEST_FORMAT
  };

  return callback(undefined, convertedManifestInfo);
}

function convertFromBase(manifestInfo, callback) {
  if (!manifestInfo || !manifestInfo.content) {
    return callback(new Error('Manifest content is empty or not initialized.'));
  }

  var originalManifest = manifestInfo.content;

  if (!originalManifest.start_url) {
    return callback(new Error('Start url is required.'));
  }

  var manifest = {
    'manifest_version': 2,
    'name': originalManifest.name || originalManifest.start_url,
    'version': '0.0.1',
    'app': {
      'launch': {
        'web_url': originalManifest.start_url
      }
    }
  };

  if (originalManifest.icons && originalManifest.icons.length) {
    var icons = {};

    for (var i = 0; i < originalManifest.icons.length; i++) {
      var icon = originalManifest.icons[i];
      var iconDimensions = icon.sizes.split('x');
      if (iconDimensions[0] === iconDimensions[1]) {
        icons[iconDimensions[0]] = icon.src;
      }
    }

    manifest.icons = icons;
  }

  var convertedManifestInfo = {
    'content': manifest,
    'format': c.CHROME_MANIFEST_FORMAT
  };

  return callback(undefined, convertedManifestInfo);
}

// see https://developer.chrome.com/webstore/hosted_apps
var requiredRootProperties = ['name', 'version', 'manifest_version', 'app'];

var validRootProperties = ['name', 'description', 'version', 'manifest_version', 'app',
                           'background_page', 'icons', 'key',
                           'minimum_chrome_version', 'offline_enabled',
                           'permissions', 'update_url', 'default_locale'];

var validAppProperties = ['urls', 'launch'];
var validAppLaunchProperties = ['web_url', 'container', 'height', 'width'];

function matchFormat(manifestObj) {
  var lowercasePropName;

  // check required fields
  for (var i = 0; i < requiredRootProperties.length; i++) {
    if (!manifestObj.hasOwnProperty(requiredRootProperties[i])) {
      return false;
    }
  }

  if (!manifestObj.app.hasOwnProperty('launch') ||
    !manifestObj.app.launch.hasOwnProperty('web_url')) {
    return false;
  }

  for (var prop in manifestObj) {
    if (manifestObj.hasOwnProperty(prop)) {
      lowercasePropName = prop.toLowerCase();
      if (validRootProperties.indexOf(lowercasePropName) === -1) {
        return false;
      }
    }

    if (lowercasePropName === 'app') {
      for (var appProp in manifestObj.app) {
        if (manifestObj.app.hasOwnProperty(appProp)) {
          if (validAppProperties.indexOf(appProp) === -1) {
            return false;
          }

          if (appProp === 'launch') {
            for (var appLaunchProp in manifestObj.app.launch) {
              if (manifestObj.app.launch.hasOwnProperty(appLaunchProp)) {
                if (validAppLaunchProperties.indexOf(appLaunchProp) === -1) {
                  return false;
                }
              }
            }
          }
        }
      }
    }
  }

  return true;
}

module.exports = {
  convertToBase: convertToBase,
  convertFromBase: convertFromBase,
  matchFormat: matchFormat
};
<commit_msg>Updated generation of Chrome output manifest to include app URLs and permissions<commit_after>'use strict';

var url = require('url'),
    utils = require('../../common/utils'),
    c = require('../constants');

function convertToBase(manifestInfo, callback) {
  if (!manifestInfo || !manifestInfo.content) {
    return callback(new Error('Manifest content is empty or not initialized.'));
  }

  var originalManifest = manifestInfo.content;
  var manifest = {
    'start_url': originalManifest.app.launch.web_url,
    'name': originalManifest.name
  };

  var icons = [];

  for (var size in originalManifest.icons) {
    if (originalManifest.icons.hasOwnProperty(size)) {
      icons.push({
        'sizes' : size + 'x' + size,
        'src': originalManifest.icons[size]
      });
    }
  }

  manifest.icons = icons;

  var convertedManifestInfo = {
    'content': manifest,
    'format': c.BASE_MANIFEST_FORMAT
  };

  return callback(undefined, convertedManifestInfo);
}

function convertFromBase(manifestInfo, callback) {
  if (!manifestInfo || !manifestInfo.content) {
    return callback(new Error('Manifest content is empty or not initialized.'));
  }

  var originalManifest = manifestInfo.content;

  if (!originalManifest.start_url) {
    return callback(new Error('Start url is required.'));
  }

  var manifest = {
    'manifest_version': 2,
    'name': originalManifest.name
            || originalManifest.short_name
            || utils.sanitizeName(url.parse(originalManifest.start_url).hostname),
    'version': '0.0.1',
    'app': {
      'launch': {
        'web_url': originalManifest.start_url
      }
    }
  };

  // map icons
  if (originalManifest.icons && originalManifest.icons.length) {
    var icons = {};

    for (var i = 0; i < originalManifest.icons.length; i++) {
      var icon = originalManifest.icons[i];
      var iconDimensions = icon.sizes.split('x');
      if (iconDimensions[0] === iconDimensions[1]) {
        icons[iconDimensions[0]] = icon.src;
      }
    }

    manifest.icons = icons;
  }

  // map extended scope
  if (originalManifest.mjs_extended_scope && originalManifest.mjs_extended_scope.length) {
    manifest.app.urls = originalManifest.mjs_extended_scope;
  }

  // map permissions
  // NOTE: Chrome manifest does not support assigning different permissions based on URL.
  // Mapping calculates union of all permissions found for the 'Chrome' platform and grants
  // the same set of permissions for all URLs.
  if (originalManifest.mjs_api_access && originalManifest.mjs_api_access.length) {
    var permissionSet = {};
    originalManifest.mjs_api_access.forEach(function(rule) {
      if (rule.platform && rule.platform.split(';')
        .map(function (item) { return item.trim(); })
        .indexOf('chrome') >= 0) {
          rule.access.split(';').forEach(function (p) {
            permissionSet[p.trim()] = undefined;
          });
        }
    });

    var permissions = Object.keys(permissionSet);
    if (permissions.length) {
      manifest.permissions = permissions;
    }
  }

  var convertedManifestInfo = {
    'content': manifest,
    'format': c.CHROME_MANIFEST_FORMAT
  };

  return callback(undefined, convertedManifestInfo);
}

// see https://developer.chrome.com/webstore/hosted_apps
var requiredRootProperties = ['name', 'version', 'manifest_version', 'app'];

var validRootProperties = ['name', 'description', 'version', 'manifest_version', 'app',
                           'background_page', 'icons', 'key',
                           'minimum_chrome_version', 'offline_enabled',
                           'permissions', 'update_url', 'default_locale'];

var validAppProperties = ['urls', 'launch'];
var validAppLaunchProperties = ['web_url', 'container', 'height', 'width'];

function matchFormat(manifestObj) {
  var lowercasePropName;

  // check required fields
  for (var i = 0; i < requiredRootProperties.length; i++) {
    if (!manifestObj.hasOwnProperty(requiredRootProperties[i])) {
      return false;
    }
  }

  if (!manifestObj.app.hasOwnProperty('launch') ||
    !manifestObj.app.launch.hasOwnProperty('web_url')) {
    return false;
  }

  for (var prop in manifestObj) {
    if (manifestObj.hasOwnProperty(prop)) {
      lowercasePropName = prop.toLowerCase();
      if (validRootProperties.indexOf(lowercasePropName) === -1) {
        return false;
      }
    }

    if (lowercasePropName === 'app') {
      for (var appProp in manifestObj.app) {
        if (manifestObj.app.hasOwnProperty(appProp)) {
          if (validAppProperties.indexOf(appProp) === -1) {
            return false;
          }

          if (appProp === 'launch') {
            for (var appLaunchProp in manifestObj.app.launch) {
              if (manifestObj.app.launch.hasOwnProperty(appLaunchProp)) {
                if (validAppLaunchProperties.indexOf(appLaunchProp) === -1) {
                  return false;
                }
              }
            }
          }
        }
      }
    }
  }

  return true;
}

module.exports = {
  convertToBase: convertToBase,
  convertFromBase: convertFromBase,
  matchFormat: matchFormat
};
<|endoftext|>


<commit_before>const context = require('./context')
const modules = require('./lib/modules')
const log = require('./lib/log')

const {
  start,
  version,
  team,
  channels,
  users,
  posts,
  directChannels,
  directPosts,
  end
} = modules

//
// Common function log errors and
// terminate the process
//
const abort = function(err) {
  log.error(err)
  //
  // We set a timeout here to
  // allow the log streams to finish
  // writing.
  //
  setTimeout(function() {
    process.exit(1)
  }, 3000)
}

//
// Ensure we trap uncaught exceptions
// and properly abort
//
process.on('uncaughtException', abort)

//
// Let's do it
//
start(context)
  .then(version)
  .then(team)
  .then(channels)
  .then(users)
  .then(posts)
  .then(directChannels)
  .then(directPosts)
  .then(end)
  .catch(abort)
<commit_msg>Fix codeclimate issue<commit_after>const context = require('./context')
const log = require('./lib/log')
const {
  start,
  version,
  team,
  channels,
  users,
  posts,
  directChannels,
  directPosts,
  end
} = require('./lib/modules')

//
// Common function log errors and
// terminate the process
//
const abort = function(err) {
  log.error(err)
  //
  // We set a timeout here to
  // allow the log streams to finish
  // writing.
  //
  setTimeout(function() {
    process.exit(1)
  }, 3000)
}

//
// Ensure we trap uncaught exceptions
// and properly abort
//
process.on('uncaughtException', abort)

//
// Let's do it
//
start(context)
  .then(version)
  .then(team)
  .then(channels)
  .then(users)
  .then(posts)
  .then(directChannels)
  .then(directPosts)
  .then(end)
  .catch(abort)
<|endoftext|>


<commit_before>const smash = require("../../../../smash.js");
const logger = smash.logger("EventType");
const errorUtil = new smash.SmashError(logger);
const ENV = "{$ENV}";

class EventType {
    constructor(route, callback) {
        if (typeof route !== 'object') {
            throw new Error("First parameter of EventType() must be an object, " + errorUtil.typeOf(route));
        }
        if (typeof route.type !== 'string') {
            throw new Error("First parameter of EventType() must have a string property called type, " + errorUtil.typeOf(route.source));
        }
        this._type = route.type;
        if (typeof route.table !== 'string') {
            throw new Error("First parameter of EventType() must have a string property called table, " + errorUtil.typeOf(route.version));
        }
        this._table = route.table;
        if (this._table.indexOf(ENV) !== -1) {
            this._table.split(ENV).join(smash.getEnv("ENV"));
        }
        if (typeof callback !== 'function') {
            throw new Error("Third parameter of EventType() must be a function, " + errorUtil.typeOf(callback));
        }
        if (callback.length !== 1) {
            throw new Error("Third parameter of EventType() must be a function witch takes 1 parameter: Event, " + callback.length + " given");
        }
        this._callback = callback;
    }

    get type() {
        return this._type;
    }

    get table() {
        return this._table;
    }

    get callback() {
        return this._callback;
    }

    match(event) {
        if (event.type !== this.type) {
            return false;
        }
        if (event.table !== this.table) {
            return false;
        }
        return true;
    }
}

module.exports = EventType;
<commit_msg>fix table<commit_after>const smash = require("../../../../smash.js");
const logger = smash.logger("EventType");
const errorUtil = new smash.SmashError(logger);
const ENV = "{$ENV}";

class EventType {
    constructor(route, callback) {
        if (typeof route !== 'object') {
            throw new Error("First parameter of EventType() must be an object, " + errorUtil.typeOf(route));
        }
        if (typeof route.type !== 'string') {
            throw new Error("First parameter of EventType() must have a string property called type, " + errorUtil.typeOf(route.source));
        }
        this._type = route.type;
        if (typeof route.table !== 'string') {
            throw new Error("First parameter of EventType() must have a string property called table, " + errorUtil.typeOf(route.version));
        }
        let table = route.table;
        if (table.indexOf(ENV) !== -1) {
            table = table.split(ENV).join(smash.getEnv("ENV"));
        }
        this._table = table;
        if (typeof callback !== 'function') {
            throw new Error("Third parameter of EventType() must be a function, " + errorUtil.typeOf(callback));
        }
        if (callback.length !== 1) {
            throw new Error("Third parameter of EventType() must be a function witch takes 1 parameter: Event, " + callback.length + " given");
        }
        this._callback = callback;
    }

    get type() {
        return this._type;
    }

    get table() {
        return this._table;
    }

    get callback() {
        return this._callback;
    }

    match(event) {
        if (event.type !== this.type) {
            return false;
        }
        if (event.table !== this.table) {
            return false;
        }
        return true;
    }
}

module.exports = EventType;
<|endoftext|>


<commit_before>var stream = require("stream");
var teoria = require("teoria");
var xml2js = require("xml2js");

var xmlParser = new xml2js.Parser({
  tagNameProcessors: [
    xml2js.processors.stripPrefix,
    xml2js.processors.firstCharLowerCase
  ]
});

var readScore = function(xml) {
  var score = {
    notes: [],
    beatsPerMinute: 120,
    beatUnit: 4
  };

  xmlParser.parseString(xml, function(err, result) {
    var part = result["score-partwise"]["part"][0];

    part["measure"].forEach(function(measure) {
      measure["note"].forEach(function(note) {
        var pitch = note["pitch"][0];
        var step = pitch["step"][0];
        var octave = pitch["octave"][0];
        score.notes.push(teoria.note(step + octave, { value: 4 }));
      });
    });
  });

  return score;
};

module.exports.newStream = function(xml, bitsPerSample, samplesPerSecond) {
  var score = readScore(xml);
  var bytesPerSample = bitsPerSample / 8;
  var amplitude = (Math.pow(2, bitsPerSample) / 2) - 1;
  var noteIndex = 0;
  var pcmStream = new stream.Readable();

  pcmStream._read = function() {
    var note = score.notes[noteIndex];
    var frequency = note.fq();
    var durationInSeconds = note.durationInSeconds(score.beatsPerMinute, score.beatUnit);
    var totalSamples = samplesPerSecond * durationInSeconds;

    // Fill a buffer with all of the PCM audio data samples for this note. Since the
    // buffer holds 1 byte per slot, and each sample is 2 bytes (a 16-bit integer),
    // the buffer's capacity needs to be twice the number of samples.
    var buffer = new Buffer(totalSamples * bytesPerSample);
    for (var sampleIndex = 0; sampleIndex < totalSamples; sampleIndex++) {
      var sample = Math.floor(amplitude * Math.sin((2 * Math.PI * frequency * sampleIndex) / samplesPerSecond));
      buffer.writeInt16LE(sample, sampleIndex * bytesPerSample);
    }
    this.push(buffer);

    noteIndex++;
    if (noteIndex >= score.notes.length) {
      this.push(null); // We're all out of notes! Finish streaming.
    }
  };

  return pcmStream;
};
<commit_msg>Sample all parts in the score<commit_after>var stream = require("stream");
var teoria = require("teoria");
var xml2js = require("xml2js");

var xmlParser = new xml2js.Parser({
  tagNameProcessors: [
    xml2js.processors.stripPrefix,
    xml2js.processors.firstCharLowerCase
  ]
});

var readScore = function(xml) {
  var score = {
    parts: [],
    beatsPerMinute: 120,
    beatUnit: 4
  };

  xmlParser.parseString(xml, function(err, result) {
    var scoreEl = result["score-partwise"];

    scoreEl["part"].forEach(function(partEl) {
      var part = { measures: [] }

      partEl["measure"].forEach(function(measureEl) {
        var measure = { notes: [] };

        measureEl["note"].forEach(function(noteEl) {
          var pitchEl = noteEl["pitch"][0];
          var stepEl = pitchEl["step"][0];
          var octaveEl = pitchEl["octave"][0];
          measure.notes.push(teoria.note(stepEl + octaveEl, { value: 4 }));
        });

        part.measures.push(measure);
      });

      score.parts.push(part);
    });
  });

  return score;
};

module.exports.newStream = function(xml, bitsPerSample, samplesPerSecond) {
  var score = readScore(xml);
  var bytesPerSample = bitsPerSample / 8;
  var amplitude = (Math.pow(2, bitsPerSample) / 2) - 1;
  var partIndex = 0;
  var measureIndex = 0;
  var noteIndex = 0;
  var pcmStream = new stream.Readable();

  pcmStream._read = function() {
    var part = score.parts[partIndex];
    if (part) {
      var measure = part.measures[measureIndex];
      if (measure) {
        var note = measure.notes[noteIndex];
        if (note) {
          var frequency = note.fq();
          var durationInSeconds = note.durationInSeconds(score.beatsPerMinute, score.beatUnit);
          var totalSamples = samplesPerSecond * durationInSeconds;

          // Fill a buffer with all of the PCM audio data samples for this note. Since the
          // buffer holds 1 byte per slot, and each sample is 2 bytes (a 16-bit integer),
          // the buffer's capacity needs to be twice the number of samples.
          var buffer = new Buffer(totalSamples * bytesPerSample);
          for (var sampleIndex = 0; sampleIndex < totalSamples; sampleIndex++) {
            var sample = Math.floor(amplitude * Math.sin((2 * Math.PI * frequency * sampleIndex) / samplesPerSecond));
            buffer.writeInt16LE(sample, sampleIndex * bytesPerSample);
          }

          this.push(buffer);
          noteIndex++;
        }

        if (noteIndex >= measure.notes.length) {
          measureIndex++;
          noteIndex = 0;
        }
      }

      if (measureIndex >= part.measures.length) {
        partIndex++;
        measureIndex = 0;
      }
    }

    if (partIndex >= score.parts.length) {
      this.push(null); // We're all out of notes! Finish streaming.
    }
  };

  return pcmStream;
};
<|endoftext|>