<commit_before>/*
 * magna-charta
 * https://github.com/alphagov/magna-charta
 *
 * Copyright (c) 2012 Jack Franklin
 * Licensed under the MIT license.
 */

(function($) {

  // detecting IE
  /*
   * taken from James Padolsey: https://gist.github.com/527683
   */
   var ie = (function(){
    var undef,
        v = 3,
        div = document.createElement('div'),
        all = div.getElementsByTagName('i');
    while (div.innerHTML = '', all[0])
    return v > 4 ? v : undef;
  }());

  var MagnaCharta = function() {
    this.init = function(table, options) {
      var defaults = {
        outOf: 65,
        applyOnInit: true
      };
      this.options = $.extend({}, defaults, options);

      // if it's IE8 or less, we just show the plain tables
      // the CSS used to turn them into charts is too much for poor IE to handle
      // detection of <IE9 is done via HTML conditional comment to add a class to the html element
      this.DISABLED = (ie && ie < 8);

      this.$table = table;

      // set the stacked option based on giving the table a class of mc-stacked
      this.options.stacked = this.$table.hasClass("mc-stacked");

      // set the negative option based on giving the table a class of mc-negative
      this.options.negative = this.$table.hasClass("mc-negative");
      this.$bodyRows = this.$table.find("tr");

      if(!this.DISABLED && this.options.applyOnInit) {
        this.apply();
      }

      return this;
    };

    this.apply = function() {
      if(!this.DISABLED) {
        this.addClasses();
        this.applyWidths();
      }
    };

    this.revert = function() {
      if(!this.DISABLED) {
        this.restoreText();
        this.removeWidths();
        this.removeClasses();
      }
    };

    this.removeClasses = function() {
      this.$table.removeClass("mc-table").find(".mc-key-cell, .mc-row, .mc-bar-cell, .mc-bar-negative, .mc-bar-positive").removeClass("mc-key-cell mc-row mc-bar-cell .mc-bar-negative .mc-bar-positive");
    };

    this.removeWidths = function() {
      this.$table.find(".mc-bar-cell").css("width", "").css("margin-left", "");
    };

    this.utils = {
      isFloat: function(val) {
        return !isNaN(parseFloat(val));
      },
      stripValue: function(val) {
        return val.replace('%', '').replace("£", '').replace("m", "");
      },
      returnMax: function(values) {
        var max = 0;
        for(var i = 0; i < values.length; i++) {
          if(values[i] > max) { max = values[i]; }
        }
        return max;
      },
      isNegative: function(value) {
        return (value < 0);
      }
    };

    this.addClasses = function() {
      this.$table.addClass("mc-table");
    };

    this.calculateMaxWidth = function() {

      // JS scoping sucks
      var that = this;

      // store the cell values in here so later
      // so we can figure out the maximum value later
      var values = [];

      // var to store the maximum negative value, (used only for negative charts)
      var maxNegativeValue = 0;

      // loop through every tr in the table
      this.$bodyRows.each(function(i, item) {
        var $this = $(item);

        // the first td is going to be the key, so ignore it
        var $bodyCells = $this.find("td:not(:first)");

        // if it's stacked, the last column is a totals, so we don't want that in our calculations
        if(that.options.stacked) {
          var $stackedTotal = $bodyCells.last().addClass("mc-stacked-total");
          $bodyCells = $bodyCells.filter(":not(:last)");
        }

        // find all the header ccells and give them the right classes
        var $headCells = $this.find("th:not(:first, .total)").addClass("mc-key-cell");
        // do the same with the first td in each row
        $this.find("td:first").addClass("mc-key-cell");

        // store the total value of the bar cells in a row
        // for anything but stacked, this is just the value of one
        var cellsTotalValue = 0;

        $bodyCells.each(function(j, cell) {

          var $cell = $(cell).addClass("mc-bar-cell");

          var cellVal = that.utils.stripValue($cell.text());

          if(that.utils.isFloat(cellVal)) {

            var parsedVal = parseFloat(cellVal, 10);
            var absParsedVal = Math.abs(parsedVal);

            if(that.options.negative) {

              if(that.utils.isNegative(parsedVal)) {

                $cell.addClass("mc-bar-negative");

                if(absParsedVal > maxNegativeValue) {
                  maxNegativeValue = absParsedVal;
                }

              } else {

                $cell.addClass("mc-bar-positive");
              }

            }
            // now we are done with our negative calculations
            // set parsedVal to absParsedVal
            parsedVal = absParsedVal;

            if(!that.options.stacked) {
              cellsTotalValue = parsedVal;
              values.push(parsedVal);
            } else {
              cellsTotalValue += parsedVal;
            }
          }
        });

        // if stacked, we need to push the total value of the row to the values array
        if(that.options.stacked) { values.push(cellsTotalValue); }

      });

      var resp = {};

      resp.max = parseFloat(that.utils.returnMax(values), 10);
      resp.single = parseFloat(this.options.outOf/resp.max, 10);

      if(this.options.negative) {
        resp.marginLeft = parseFloat(maxNegativeValue, 10) * resp.single;
        resp.maxNegative = parseFloat(maxNegativeValue, 10);
      }

      return resp;
    };

    this.restoreText = function() {
      this.$table.find(".mc-bar-cell").each(function(i, item) {
        var $cell = $(item);
        var oldText = $cell.data("oldText");
        if(oldText) {
          $cell.text(oldText);
        }
      });
    };

    this.applyWidths = function() {
      this.restoreText();
      this.dimensions = this.calculateMaxWidth();

      var that = this;

      this.$bodyRows.each(function(i, row) {

        var $this = $(row);

        $this.find(".mc-bar-cell").each(function(j, cell) {

          var $cell = $(cell);

          var parsedCellVal = parseFloat(that.utils.stripValue($cell.text()), 10);
          var parsedVal = parsedCellVal * that.dimensions.single;

          var absParsedCellVal = Math.abs(parsedCellVal);
          var absParsedVal = Math.abs(parsedVal);

          // apply the left margin to the positive bars
          if(that.options.negative) {
            if($cell.hasClass("mc-bar-positive")) {
              $(cell).css("margin-left", that.dimensions.marginLeft + "%");
            } else {
              // if its negative but not the maximum negative
              // we need to give it enough margin to push it further right to align
              if(absParsedCellVal < that.dimensions.maxNegative ) {
                // left margin needs to be
                // (largestNegVal - thisNegVal)*single
                var leftMarg = (that.dimensions.maxNegative - absParsedCellVal) * that.dimensions.single;
                $cell.css("margin-left", leftMarg + "%");
              }
            }

          }

          $cell.css("width", absParsedVal + "%");

          // set the text to be the absolute value
          // but first save the old value
          $cell.data("oldText", $cell.text());
          $cell.text(absParsedCellVal);
        });
      });
    };

  };

  $.magnaCharta = function(table, options) {
    return new MagnaCharta().init(table, options);
  };

}(jQuery));
<commit_msg>add alert debug<commit_after>/*
 * magna-charta
 * https://github.com/alphagov/magna-charta
 *
 * Copyright (c) 2012 Jack Franklin
 * Licensed under the MIT license.
 */

(function($) {

  // detecting IE
  /*
   * taken from James Padolsey: https://gist.github.com/527683
   */
   var ie = (function(){
    var undef,
        v = 3,
        div = document.createElement('div'),
        all = div.getElementsByTagName('i');
    while (div.innerHTML = '', all[0])
    return v > 4 ? v : undef;
  }());

  var MagnaCharta = function() {
    this.init = function(table, options) {
      var defaults = {
        outOf: 65,
        applyOnInit: true
      };
      this.options = $.extend({}, defaults, options);

      // if it's IE8 or less, we just show the plain tables
      // the CSS used to turn them into charts is too much for poor IE to handle
      // detection of <IE9 is done via HTML conditional comment to add a class to the html element
      this.DISABLED = (ie && ie < 8);
      alert(ie);

      this.$table = table;

      // set the stacked option based on giving the table a class of mc-stacked
      this.options.stacked = this.$table.hasClass("mc-stacked");

      // set the negative option based on giving the table a class of mc-negative
      this.options.negative = this.$table.hasClass("mc-negative");
      this.$bodyRows = this.$table.find("tr");

      if(!this.DISABLED && this.options.applyOnInit) {
        this.apply();
      }

      return this;
    };

    this.apply = function() {
      if(!this.DISABLED) {
        this.addClasses();
        this.applyWidths();
      }
    };

    this.revert = function() {
      if(!this.DISABLED) {
        this.restoreText();
        this.removeWidths();
        this.removeClasses();
      }
    };

    this.removeClasses = function() {
      this.$table.removeClass("mc-table").find(".mc-key-cell, .mc-row, .mc-bar-cell, .mc-bar-negative, .mc-bar-positive").removeClass("mc-key-cell mc-row mc-bar-cell .mc-bar-negative .mc-bar-positive");
    };

    this.removeWidths = function() {
      this.$table.find(".mc-bar-cell").css("width", "").css("margin-left", "");
    };

    this.utils = {
      isFloat: function(val) {
        return !isNaN(parseFloat(val));
      },
      stripValue: function(val) {
        return val.replace('%', '').replace("£", '').replace("m", "");
      },
      returnMax: function(values) {
        var max = 0;
        for(var i = 0; i < values.length; i++) {
          if(values[i] > max) { max = values[i]; }
        }
        return max;
      },
      isNegative: function(value) {
        return (value < 0);
      }
    };

    this.addClasses = function() {
      this.$table.addClass("mc-table");
    };

    this.calculateMaxWidth = function() {

      // JS scoping sucks
      var that = this;

      // store the cell values in here so later
      // so we can figure out the maximum value later
      var values = [];

      // var to store the maximum negative value, (used only for negative charts)
      var maxNegativeValue = 0;

      // loop through every tr in the table
      this.$bodyRows.each(function(i, item) {
        var $this = $(item);

        // the first td is going to be the key, so ignore it
        var $bodyCells = $this.find("td:not(:first)");

        // if it's stacked, the last column is a totals, so we don't want that in our calculations
        if(that.options.stacked) {
          var $stackedTotal = $bodyCells.last().addClass("mc-stacked-total");
          $bodyCells = $bodyCells.filter(":not(:last)");
        }

        // find all the header ccells and give them the right classes
        var $headCells = $this.find("th:not(:first, .total)").addClass("mc-key-cell");
        // do the same with the first td in each row
        $this.find("td:first").addClass("mc-key-cell");

        // store the total value of the bar cells in a row
        // for anything but stacked, this is just the value of one
        var cellsTotalValue = 0;

        $bodyCells.each(function(j, cell) {

          var $cell = $(cell).addClass("mc-bar-cell");

          var cellVal = that.utils.stripValue($cell.text());

          if(that.utils.isFloat(cellVal)) {

            var parsedVal = parseFloat(cellVal, 10);
            var absParsedVal = Math.abs(parsedVal);

            if(that.options.negative) {

              if(that.utils.isNegative(parsedVal)) {

                $cell.addClass("mc-bar-negative");

                if(absParsedVal > maxNegativeValue) {
                  maxNegativeValue = absParsedVal;
                }

              } else {

                $cell.addClass("mc-bar-positive");
              }

            }
            // now we are done with our negative calculations
            // set parsedVal to absParsedVal
            parsedVal = absParsedVal;

            if(!that.options.stacked) {
              cellsTotalValue = parsedVal;
              values.push(parsedVal);
            } else {
              cellsTotalValue += parsedVal;
            }
          }
        });

        // if stacked, we need to push the total value of the row to the values array
        if(that.options.stacked) { values.push(cellsTotalValue); }

      });

      var resp = {};

      resp.max = parseFloat(that.utils.returnMax(values), 10);
      resp.single = parseFloat(this.options.outOf/resp.max, 10);

      if(this.options.negative) {
        resp.marginLeft = parseFloat(maxNegativeValue, 10) * resp.single;
        resp.maxNegative = parseFloat(maxNegativeValue, 10);
      }

      return resp;
    };

    this.restoreText = function() {
      this.$table.find(".mc-bar-cell").each(function(i, item) {
        var $cell = $(item);
        var oldText = $cell.data("oldText");
        if(oldText) {
          $cell.text(oldText);
        }
      });
    };

    this.applyWidths = function() {
      this.restoreText();
      this.dimensions = this.calculateMaxWidth();

      var that = this;

      this.$bodyRows.each(function(i, row) {

        var $this = $(row);

        $this.find(".mc-bar-cell").each(function(j, cell) {

          var $cell = $(cell);

          var parsedCellVal = parseFloat(that.utils.stripValue($cell.text()), 10);
          var parsedVal = parsedCellVal * that.dimensions.single;

          var absParsedCellVal = Math.abs(parsedCellVal);
          var absParsedVal = Math.abs(parsedVal);

          // apply the left margin to the positive bars
          if(that.options.negative) {
            if($cell.hasClass("mc-bar-positive")) {
              $(cell).css("margin-left", that.dimensions.marginLeft + "%");
            } else {
              // if its negative but not the maximum negative
              // we need to give it enough margin to push it further right to align
              if(absParsedCellVal < that.dimensions.maxNegative ) {
                // left margin needs to be
                // (largestNegVal - thisNegVal)*single
                var leftMarg = (that.dimensions.maxNegative - absParsedCellVal) * that.dimensions.single;
                $cell.css("margin-left", leftMarg + "%");
              }
            }

          }

          $cell.css("width", absParsedVal + "%");

          // set the text to be the absolute value
          // but first save the old value
          $cell.data("oldText", $cell.text());
          $cell.text(absParsedCellVal);
        });
      });
    };

  };

  $.magnaCharta = function(table, options) {
    return new MagnaCharta().init(table, options);
  };

}(jQuery));
<|endoftext|>


<commit_before>var Client = function(opts) {
  this.opts = opts || {};
  this.http = this.opts.ssl ? require('https') : require('http');
};

Client.prototype.call = function(method, params, callback, errback, path) {
  var time = Date.now();
  var requestJSON;

  if (Array.isArray(method)) {
    // multiple rpc batch call
    requestJSON = [];
    method.forEach(function(batchCall, i) {
      requestJSON.push({
        id: time + '-' + i,
        method: batchCall.method,
        params: batchCall.params
      });
    });
  } else {
    // single rpc call
    requestJSON = {
      id: time,
      method: method,
      params: params
    };
  }

  // First we encode the request into JSON
  var requestJSON = JSON.stringify(requestJSON);

  // prepare request options
  var requestOptions = {
    host: this.opts.host || 'localhost',
    port: this.opts.port || 8332,
    method: 'POST',
    path: path || '/',
    headers: {
      'Host': this.opts.host || 'localhost',
      'Content-Length': requestJSON.length
    },
    agent: false,
    rejectUnauthorized: this.opts.ssl && this.opts.sslStrict !== false
  };

  if (this.opts.ssl && this.opts.sslCa) {
    requestOptions.ca = this.opts.sslCa;
  }

  // use HTTP auth if user and password set
  if (this.opts.user && this.opts.pass) {
    requestOptions.auth = this.opts.user + ':' + this.opts.pass;
  }

  // Now we'll make a request to the server
  var cbCalled = false;
  var request = this.http.request(requestOptions);

  // start request timeout timer
  var reqTimeout = setTimeout(function() {
    if (cbCalled) return;
    cbCalled = true;
    request.abort();
    var err = new Error('ETIMEDOUT');
    err.code = 'ETIMEDOUT';
    errback(err);
  }, this.opts.timeout || 30000);

  // set additional timeout on socket in case of remote freeze after sending headers
  request.setTimeout(this.opts.timeout || 30000, function() {
    if (cbCalled) return;
    cbCalled = true;
    request.abort();
    var err = new Error('ESOCKETTIMEDOUT')
    err.code = 'ESOCKETTIMEDOUT'
    errback(err);
  });

  request.on('error', function(err) {
    if (cbCalled) return;
    cbCalled = true;
    clearTimeout(reqTimeout);
    errback(err);
  });

  request.on('response', function(response) {
    clearTimeout(reqTimeout);

    // We need to buffer the response chunks in a nonblocking way.
    var buffer = '';
    response.on('data', function(chunk) {
      buffer = buffer + chunk;
    });
    // When all the responses are finished, we decode the JSON and
    // depending on whether it's got a result or an error, we call
    // emitSuccess or emitError on the promise.
    response.on('end', function() {
      var err;

      if (cbCalled) return;
      cbCalled = true;

      try {
        var decoded = JSON.parse(buffer);
      } catch (e) {
        if (response.statusCode !== 200) {
          err = new Error('Invalid params, response status code: ' + response.statusCode);
          err.code = -32602;
          errback(err);
        } else {
          err = new Error('Problem parsing JSON response from server');
          err.code = -32603;
          errback(err);
        }
        return;
      }

      if (!Array.isArray(decoded)) {
        decoded = [decoded];
      }

      // iterate over each response, normally there will be just one
      // unless a batch rpc call response is being processed
      decoded.forEach(function(decodedResponse, i) {
        if (decodedResponse.hasOwnProperty('error') && decodedResponse.error != null) {
          if (errback) {
            err = new Error(decodedResponse.error.message || '');
            if (decodedResponse.error.code) {
              err.code = decodedResponse.error.code;
            }
            errback(err);
          }
        } else if (decodedResponse.hasOwnProperty('result')) {
          if (callback) {
            callback(decodedResponse.result, response.headers);
          }
        } else {
          if (errback) {
            err = new Error(decodedResponse.error.message || '');
            if (decodedResponse.error.code) {
              err.code = decodedResponse.error.code;
            }
            errback(err);
          }
        }
      });

    });
  });
  request.end(requestJSON);
};

module.exports.Client = Client;
<commit_msg>don't lazy-load http/https modules<commit_after>var http = require('http'),
    https = require('https');

var Client = function(opts) {
  this.opts = opts || {};
  this.http = this.opts.ssl ? https : http;
};

Client.prototype.call = function(method, params, callback, errback, path) {
  var time = Date.now();
  var requestJSON;

  if (Array.isArray(method)) {
    // multiple rpc batch call
    requestJSON = [];
    method.forEach(function(batchCall, i) {
      requestJSON.push({
        id: time + '-' + i,
        method: batchCall.method,
        params: batchCall.params
      });
    });
  } else {
    // single rpc call
    requestJSON = {
      id: time,
      method: method,
      params: params
    };
  }

  // First we encode the request into JSON
  var requestJSON = JSON.stringify(requestJSON);

  // prepare request options
  var requestOptions = {
    host: this.opts.host || 'localhost',
    port: this.opts.port || 8332,
    method: 'POST',
    path: path || '/',
    headers: {
      'Host': this.opts.host || 'localhost',
      'Content-Length': requestJSON.length
    },
    agent: false,
    rejectUnauthorized: this.opts.ssl && this.opts.sslStrict !== false
  };

  if (this.opts.ssl && this.opts.sslCa) {
    requestOptions.ca = this.opts.sslCa;
  }

  // use HTTP auth if user and password set
  if (this.opts.user && this.opts.pass) {
    requestOptions.auth = this.opts.user + ':' + this.opts.pass;
  }

  // Now we'll make a request to the server
  var cbCalled = false;
  var request = this.http.request(requestOptions);

  // start request timeout timer
  var reqTimeout = setTimeout(function() {
    if (cbCalled) return;
    cbCalled = true;
    request.abort();
    var err = new Error('ETIMEDOUT');
    err.code = 'ETIMEDOUT';
    errback(err);
  }, this.opts.timeout || 30000);

  // set additional timeout on socket in case of remote freeze after sending headers
  request.setTimeout(this.opts.timeout || 30000, function() {
    if (cbCalled) return;
    cbCalled = true;
    request.abort();
    var err = new Error('ESOCKETTIMEDOUT')
    err.code = 'ESOCKETTIMEDOUT'
    errback(err);
  });

  request.on('error', function(err) {
    if (cbCalled) return;
    cbCalled = true;
    clearTimeout(reqTimeout);
    errback(err);
  });

  request.on('response', function(response) {
    clearTimeout(reqTimeout);

    // We need to buffer the response chunks in a nonblocking way.
    var buffer = '';
    response.on('data', function(chunk) {
      buffer = buffer + chunk;
    });
    // When all the responses are finished, we decode the JSON and
    // depending on whether it's got a result or an error, we call
    // emitSuccess or emitError on the promise.
    response.on('end', function() {
      var err;

      if (cbCalled) return;
      cbCalled = true;

      try {
        var decoded = JSON.parse(buffer);
      } catch (e) {
        if (response.statusCode !== 200) {
          err = new Error('Invalid params, response status code: ' + response.statusCode);
          err.code = -32602;
          errback(err);
        } else {
          err = new Error('Problem parsing JSON response from server');
          err.code = -32603;
          errback(err);
        }
        return;
      }

      if (!Array.isArray(decoded)) {
        decoded = [decoded];
      }

      // iterate over each response, normally there will be just one
      // unless a batch rpc call response is being processed
      decoded.forEach(function(decodedResponse, i) {
        if (decodedResponse.hasOwnProperty('error') && decodedResponse.error != null) {
          if (errback) {
            err = new Error(decodedResponse.error.message || '');
            if (decodedResponse.error.code) {
              err.code = decodedResponse.error.code;
            }
            errback(err);
          }
        } else if (decodedResponse.hasOwnProperty('result')) {
          if (callback) {
            callback(decodedResponse.result, response.headers);
          }
        } else {
          if (errback) {
            err = new Error(decodedResponse.error.message || '');
            if (decodedResponse.error.code) {
              err.code = decodedResponse.error.code;
            }
            errback(err);
          }
        }
      });

    });
  });
  request.end(requestJSON);
};

module.exports.Client = Client;
<|endoftext|>


<commit_before>/**
 * node-zip-stream
 *
 * Copyright (c) 2014 Chris Talkington, contributors.
 * Licensed under the MIT license.
 * https://github.com/ctalkington/node-zip-stream/blob/master/LICENSE-MIT
 */
var inherits = require('util').inherits;
var Transform = require('readable-stream').Transform;
var PassThrough = require('readable-stream').PassThrough;

var crc32 = require('buffer-crc32');
var ChecksumStream = require('crc32-stream');
var DeflateRawChecksum = require('./util/DeflateRawChecksum');
var headers = require('./headers');
var util = require('./util');

var debug = util.debug('zip-stream:instance');
var debugEntry = util.debug('zip-stream:entry');

var ZipStream = module.exports = function(options) {
  if (!(this instanceof ZipStream)) {
    return new ZipStream(options);
  }

  debug('init');

  options = this.options = util.defaults(options, {
    highWaterMark: 1024 * 1024,
    comment: '',
    forceUTC: false,
    store: false
  });

  if (typeof options.zlib !== 'object') {
    options.zlib = {};
  }

  if (typeof options.level === 'number' && options.level >= 0) {
    options.zlib.level = options.level;
    delete options.level;
  } else if (typeof options.zlib.level !== 'number') {
    options.zlib.level = 1;
  }

  if (options.zlib.level === 0) {
    options.store = true;
  }

  Transform.call(this, options);

  this.offset = 0;
  this.files = [];

  this._finalize = false;
  this._finalized = false;
  this._processing = false;

  this.once('end', function() {
    debug('end');
  });
};

inherits(ZipStream, Transform);

ZipStream.prototype._afterAppend = function(file) {
  debugEntry('%s:finish', file.name);

  this.files.push(file);
  this._processing = false;

  if (this._finalize) {
    this.finalize();
  }
};

ZipStream.prototype._appendBuffer = function(source, data, callback) {
  var self = this;

  data.offset = self.offset;

  if (source.length === 0) {
    data.store = true;
    data.compressionMethod = 0;
  }

  self.write(headers.encode('file', data));

  function onend() {
    self.write(headers.encode('fileDescriptor', data));

    self._afterAppend(data);

    callback(null, data);
  }

  if (data.store) {
    data.uncompressedSize = source.length;
    data.compressedSize = data.uncompressedSize;
    data.crc32 = crc32.unsigned(source);

    self.write(source);

    onend();
  } else {
    var processStream = self._newProcessStream(data.store);
    processStream.once('error', callback);

    processStream.once('end', function() {
      data.crc32 = processStream.digest();
      data.uncompressedSize = processStream.size();
      data.compressedSize = processStream.compressedSize || data.uncompressedSize;

      onend();
    });

    processStream.pipe(self, { end: false });

    processStream.end(source);
  }
};

ZipStream.prototype._appendStream = function(source, data, callback) {
  var self = this;

  data.offset = self.offset;

  self.write(headers.encode('file', data));

  function onend() {
    self.write(headers.encode('fileDescriptor', data));

    self._afterAppend(data);

    callback(null, data);
  }

  var processStream = self._newProcessStream(data.store);
  processStream.once('error', callback);

  processStream.once('end', function() {
    data.crc32 = processStream.digest();
    data.uncompressedSize = processStream.size();
    data.compressedSize = processStream.compressedSize || data.uncompressedSize;

    onend();
  });

  processStream.pipe(self, { end: false });

  source.pipe(processStream);
};

ZipStream.prototype._emitErrorCallback = function(err, data) {
  if (err) {
    this.emit('error', err);
  }
};

ZipStream.prototype._newProcessStream = function(store) {
  var process;

  if (store) {
    process = new ChecksumStream();
  } else {
    process = new DeflateRawChecksum(this.options.zlib);
  }

  return process;
};

ZipStream.prototype._normalizeFileData = function(data) {
  data = util.defaults(data, {
    type: 'file',
    name: null,
    date: null,
    store: this.options.store,
    comment: ''
  });

  var isDir = data.type === 'directory';

  if (data.name) {
    data.name = util.sanitizePath(data.name);

    if (data.name.slice(-1) === '/') {
      isDir = true;
      data.type = 'directory';
    } else if (isDir) {
      data.name += '/';
    }
  }

  if (isDir) {
    data.store = true;
  }

  if (typeof data.lastModifiedDate !== 'number') {
    data.lastModifiedDate = util.dosDateTime(data.date, this.options.forceUTC);
  }

  data.flags = (1 << 3);
  data.compressionMethod = data.store ? 0 : 8;
  data.uncompressedSize = 0;
  data.compressedSize = 0;

  return data;
};

ZipStream.prototype._normalizeSource = function(source) {
  if (source === null) {
    return new Buffer(0);
  } else if (typeof source === 'string') {
    return new Buffer(source);
  } else if (util.isStream(source) && !source._readableState) {
    var normalized = new PassThrough();
    source.pipe(normalized);

    return normalized;
  }

  return source;
};

ZipStream.prototype._transform = function(chunk, encoding, callback) {
  callback(null, chunk);
};

ZipStream.prototype._writeCentralDirectory = function() {
  var files = this.files;
  var comment = this.options.comment;
  var cdoffset = this.offset;
  var cdsize = 0;

  var centralDirectoryBuffer;
  for (var i = 0; i < files.length; i++) {
    var file = files[i];

    centralDirectoryBuffer = headers.encode('centralDirectory', file);
    this.write(centralDirectoryBuffer);
    cdsize += centralDirectoryBuffer.length;
  }

  var centralDirectoryFooterData = {
    directoryRecordsDisk: files.length,
    directoryRecords: files.length,
    centralDirectorySize: cdsize,
    centralDirectoryOffset: cdoffset,
    comment: comment
  };

  this.write(headers.encode('centralFooter', centralDirectoryFooterData));
};

ZipStream.prototype.entry = function(source, data, callback) {
  if (typeof callback !== 'function') {
    callback = this._emitErrorCallback.bind(this);
  }

  if (this._processing) {
    callback(new Error('already processing an entry'));
    return;
  }

  if (this._finalize || this._finalized) {
    callback(new Error('entry after finalize()'));
    return;
  }

  data = this._normalizeFileData(data);
  debugEntry('%s:start', data.name);

  if (data.type !== 'file' && data.type !== 'directory') {
    callback(new Error(data.type + ' entries not currently supported'));
    return;
  }

  if (typeof data.name !== 'string' || data.name.length === 0) {
    callback(new Error('entry name must be a non-empty string value'));
    return;
  }

  this._processing = true;
  source = this._normalizeSource(source);

  if (Buffer.isBuffer(source)) {
    debugEntry('%s:source:buffer', data.name);
    this._appendBuffer(source, data, callback);
  } else if (util.isStream(source)) {
    debugEntry('%s:source:stream', data.name);
    this._appendStream(source, data, callback);
  } else {
    this._processing = false;
    callback(new Error('input source must be valid Stream or Buffer instance'));
    return;
  }
};

ZipStream.prototype.finalize = function() {
  if (this._processing) {
    this._finalize = true;
    return;
  }

  debug('finalize');
  this._writeCentralDirectory();
  this._finalized = true;
  debug('finalized');
  this.end();
};

ZipStream.prototype.write = function(chunk, cb) {
  if (chunk) {
    this.offset += chunk.length;
  }

  return Transform.prototype.write.call(this, chunk, cb);
};<commit_msg>rename files -> entries.<commit_after>/**
 * node-zip-stream
 *
 * Copyright (c) 2014 Chris Talkington, contributors.
 * Licensed under the MIT license.
 * https://github.com/ctalkington/node-zip-stream/blob/master/LICENSE-MIT
 */
var inherits = require('util').inherits;
var Transform = require('readable-stream').Transform;
var PassThrough = require('readable-stream').PassThrough;

var crc32 = require('buffer-crc32');
var ChecksumStream = require('crc32-stream');
var DeflateRawChecksum = require('./util/DeflateRawChecksum');
var headers = require('./headers');
var util = require('./util');

var debug = util.debug('zip-stream:instance');
var debugEntry = util.debug('zip-stream:entry');

var ZipStream = module.exports = function(options) {
  if (!(this instanceof ZipStream)) {
    return new ZipStream(options);
  }

  debug('init');

  options = this.options = util.defaults(options, {
    highWaterMark: 1024 * 1024,
    comment: '',
    forceUTC: false,
    store: false
  });

  if (typeof options.zlib !== 'object') {
    options.zlib = {};
  }

  if (typeof options.level === 'number' && options.level >= 0) {
    options.zlib.level = options.level;
    delete options.level;
  } else if (typeof options.zlib.level !== 'number') {
    options.zlib.level = 1;
  }

  if (options.zlib.level === 0) {
    options.store = true;
  }

  Transform.call(this, options);

  this.offset = 0;
  this.entries = [];

  this._finalize = false;
  this._finalized = false;
  this._processing = false;

  this.once('end', function() {
    debug('end');
  });
};

inherits(ZipStream, Transform);

ZipStream.prototype._afterAppend = function(entry) {
  debugEntry('%s:finish', entry.name);

  this.entries.push(entry);
  this._processing = false;

  if (this._finalize) {
    this.finalize();
  }
};

ZipStream.prototype._appendBuffer = function(source, data, callback) {
  var self = this;

  data.offset = self.offset;

  if (source.length === 0) {
    data.store = true;
    data.compressionMethod = 0;
  }

  self.write(headers.encode('file', data));

  function onend() {
    self.write(headers.encode('fileDescriptor', data));

    self._afterAppend(data);

    callback(null, data);
  }

  if (data.store) {
    data.uncompressedSize = source.length;
    data.compressedSize = data.uncompressedSize;
    data.crc32 = crc32.unsigned(source);

    self.write(source);

    onend();
  } else {
    var processStream = self._newProcessStream(data.store);
    processStream.once('error', callback);

    processStream.once('end', function() {
      data.crc32 = processStream.digest();
      data.uncompressedSize = processStream.size();
      data.compressedSize = processStream.compressedSize || data.uncompressedSize;

      onend();
    });

    processStream.pipe(self, { end: false });

    processStream.end(source);
  }
};

ZipStream.prototype._appendStream = function(source, data, callback) {
  var self = this;

  data.offset = self.offset;

  self.write(headers.encode('file', data));

  function onend() {
    self.write(headers.encode('fileDescriptor', data));

    self._afterAppend(data);

    callback(null, data);
  }

  var processStream = self._newProcessStream(data.store);
  processStream.once('error', callback);

  processStream.once('end', function() {
    data.crc32 = processStream.digest();
    data.uncompressedSize = processStream.size();
    data.compressedSize = processStream.compressedSize || data.uncompressedSize;

    onend();
  });

  processStream.pipe(self, { end: false });

  source.pipe(processStream);
};

ZipStream.prototype._emitErrorCallback = function(err, data) {
  if (err) {
    this.emit('error', err);
  }
};

ZipStream.prototype._newProcessStream = function(store) {
  var process;

  if (store) {
    process = new ChecksumStream();
  } else {
    process = new DeflateRawChecksum(this.options.zlib);
  }

  return process;
};

ZipStream.prototype._normalizeFileData = function(data) {
  data = util.defaults(data, {
    type: 'file',
    name: null,
    date: null,
    store: this.options.store,
    comment: ''
  });

  var isDir = data.type === 'directory';

  if (data.name) {
    data.name = util.sanitizePath(data.name);

    if (data.name.slice(-1) === '/') {
      isDir = true;
      data.type = 'directory';
    } else if (isDir) {
      data.name += '/';
    }
  }

  if (isDir) {
    data.store = true;
  }

  if (typeof data.lastModifiedDate !== 'number') {
    data.lastModifiedDate = util.dosDateTime(data.date, this.options.forceUTC);
  }

  data.flags = (1 << 3);
  data.compressionMethod = data.store ? 0 : 8;
  data.uncompressedSize = 0;
  data.compressedSize = 0;

  return data;
};

ZipStream.prototype._normalizeSource = function(source) {
  if (source === null) {
    return new Buffer(0);
  } else if (typeof source === 'string') {
    return new Buffer(source);
  } else if (util.isStream(source) && !source._readableState) {
    var normalized = new PassThrough();
    source.pipe(normalized);

    return normalized;
  }

  return source;
};

ZipStream.prototype._transform = function(chunk, encoding, callback) {
  callback(null, chunk);
};

ZipStream.prototype._writeCentralDirectory = function() {
  var entries = this.entries;
  var comment = this.options.comment;
  var cdoffset = this.offset;
  var cdsize = 0;

  var centralDirectoryBuffer;
  for (var i = 0; i < entries.length; i++) {
    var entry = entries[i];

    centralDirectoryBuffer = headers.encode('centralDirectory', entry);
    this.write(centralDirectoryBuffer);
    cdsize += centralDirectoryBuffer.length;
  }

  var centralDirectoryFooterData = {
    directoryRecordsDisk: entries.length,
    directoryRecords: entries.length,
    centralDirectorySize: cdsize,
    centralDirectoryOffset: cdoffset,
    comment: comment
  };

  this.write(headers.encode('centralFooter', centralDirectoryFooterData));
};

ZipStream.prototype.entry = function(source, data, callback) {
  if (typeof callback !== 'function') {
    callback = this._emitErrorCallback.bind(this);
  }

  if (this._processing) {
    callback(new Error('already processing an entry'));
    return;
  }

  if (this._finalize || this._finalized) {
    callback(new Error('entry after finalize()'));
    return;
  }

  data = this._normalizeFileData(data);
  debugEntry('%s:start', data.name);

  if (data.type !== 'file' && data.type !== 'directory') {
    callback(new Error(data.type + ' entries not currently supported'));
    return;
  }

  if (typeof data.name !== 'string' || data.name.length === 0) {
    callback(new Error('entry name must be a non-empty string value'));
    return;
  }

  this._processing = true;
  source = this._normalizeSource(source);

  if (Buffer.isBuffer(source)) {
    debugEntry('%s:source:buffer', data.name);
    this._appendBuffer(source, data, callback);
  } else if (util.isStream(source)) {
    debugEntry('%s:source:stream', data.name);
    this._appendStream(source, data, callback);
  } else {
    this._processing = false;
    callback(new Error('input source must be valid Stream or Buffer instance'));
    return;
  }
};

ZipStream.prototype.finalize = function() {
  if (this._processing) {
    this._finalize = true;
    return;
  }

  debug('finalize');
  this._writeCentralDirectory();
  this._finalized = true;
  debug('finalized');
  this.end();
};

ZipStream.prototype.write = function(chunk, cb) {
  if (chunk) {
    this.offset += chunk.length;
  }

  return Transform.prototype.write.call(this, chunk, cb);
};<|endoftext|>


<commit_before>var nacl = (typeof window !== 'undefined') ? window.nacl : require('../../' + (process.env.NACL_SRC || 'nacl.min.js'));
var helpers = (typeof require !== 'undefined') ? require('./helpers') : window.helpers;
var log = helpers.log;

if (!nacl) throw new Error('nacl not loaded');

function decodeUTF8(s) {
  var i, d = unescape(encodeURIComponent(s)), b = new Uint8Array(d.length);
  for (i = 0; i < d.length; i++) b[i] = d.charCodeAt(i);
  return b;
}

function benchmark(fn, bytes) {
  var elapsed = 0;
  var iterations = 1;
  while (true) {
    var startTime = Date.now();
    fn();
    elapsed += Date.now() - startTime;
    if (elapsed > 500 && iterations > 2) {
        break;
    }
    iterations++;
  }
  return {
    iterations: iterations,
    msPerOp: elapsed / iterations,
    opsPerSecond: 1000 * iterations / elapsed,
    bytesPerSecond: bytes ? 1000 * (bytes * iterations) / elapsed : undefined
  };
}

function pad(s, upto, end) {
  if (end === void 0) { end = false; }
  var padlen = upto - s.length;
  if (padlen <= 0) {
    return s;
  }
  // XXX: in ES2015 we can use ' '.repeat(padlen)
  var padding = new Array(padlen + 1).join(' ');
  if (end) {
    return s + padding;
  }
  return padding + s;
}

function report(name, results) {
  var ops = results.iterations + ' ops';
  var msPerOp = results.msPerOp.toFixed(2) + ' ms/op';
  var opsPerSecond = results.opsPerSecond.toFixed(2) + ' ops/sec';
  var mibPerSecond = results.bytesPerSecond
      ? (results.bytesPerSecond / 1024 / 1024).toFixed(2) + ' MiB/s'
      : '';
  log.print(
    pad(name, 25, true) + ' ' +
    pad(ops, 20) + ' ' +
    pad(msPerOp, 20) + ' ' +
    pad(opsPerSecond, 20) + ' ' +
    pad(mibPerSecond, 15)
  );
}

function crypto_stream_xor_benchmark() {
  var m = new Uint8Array(1024),
      n = new Uint8Array(24),
      k = new Uint8Array(32),
      out = new Uint8Array(1024),
      i;
  for (i = 0; i < 1024; i++) m[i] = i & 255;
  for (i = 0; i < 24; i++) n[i] = i;
  for (i = 0; i < 32; i++) k[i] = i;
  report('crypto_stream_xor 1K', benchmark(function() {
    nacl.lowlevel.crypto_stream_xor(out, 0, m, 0, m.length, n, k);
  }, m.length));
}

function crypto_onetimeauth_benchmark() {
  var m = new Uint8Array(1024),
      out = new Uint8Array(1024),
      k = new Uint8Array([0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1]);
  for (var i = 0; i < 1024; i++) {
    m[i] = i & 255;
  }
  report('crypto_onetimeauth 1K', benchmark(function() {
    nacl.lowlevel.crypto_onetimeauth(out, 0, m, 0, m.length, k);
  }, m.length));
}

function crypto_secretbox_benchmark() {
  var i, k = new Uint8Array(32), n = new Uint8Array(24),
      m = new Uint8Array(1024), c = new Uint8Array(1024);
  for (i = 0; i < 32; i++) k[i] = 1;
  for (i = 0; i < 24; i++) n[i] = 2;
  for (i = 0; i < 1024; i++) m[i] = 3;
  report('crypto_secretbox 1K', benchmark(function() {
    nacl.lowlevel.crypto_secretbox(c, m, m.length, n, k);
  }, m.length));
}

function secretbox_seal_open_benchmark() {
  var key = new Uint8Array(32),
      nonce = new Uint8Array(24),
      msg = new Uint8Array(1024),
      box, i;
  for (i = 0; i < 32; i++) key[i] = 1;
  for (i = 0; i < 24; i++) nonce[i] = 2;
  for (i = 0; i < 1024; i++) msg[i] = 3;

  report('secretbox 1K', benchmark(function() {
    box = nacl.secretbox(msg, nonce, key);
  }, msg.length));

  report('secretbox.open 1K', benchmark(function() {
    nacl.secretbox.open(box, nonce, key);
  }, msg.length));
}

function crypto_scalarmult_base_benchmark() {
  var n = new Uint8Array(32), q = new Uint8Array(32);
  for (var i = 0; i < 32; i++) n[i] = i;
  report('crypto_scalarmult_base', benchmark(function() {
    nacl.lowlevel.crypto_scalarmult_base(q, n);
  }));
}

function box_seal_open_benchmark() {
  var pk1 = new Uint8Array(32), sk1 = new Uint8Array(32),
      pk2 = new Uint8Array(32), sk2 = new Uint8Array(32);
  nacl.lowlevel.crypto_box_keypair(pk1, sk1);
  nacl.lowlevel.crypto_box_keypair(pk2, sk2);
  var nonce = decodeUTF8('123456789012345678901234');
  var msg = decodeUTF8((new Array(1024)).join('a'));
  var box = null;

  report('box 1K', benchmark(function() {
    box = nacl.box(msg, nonce, pk1, sk2);
  }, msg.length));

  report('box.open 1K', benchmark(function() {
    nacl.box.open(box, nonce, pk2, sk1);
  }, msg.length));
}

function sign_open_benchmark() {
  var k = nacl.sign.keyPair();
  var sk = k.secretKey;
  var pk = k.publicKey;
  var msg = decodeUTF8((new Array(128)).join('a'));
  var sm;

  report('sign', benchmark(function() {
    sm = nacl.sign(msg, sk);
  }));

  report('sign.open', benchmark(function() {
    nacl.sign.open(sm, pk);
  }));
}

function crypto_hash_benchmark() {
  var m = new Uint8Array(1024), out = new Uint8Array(64);
  var i;
  for (i = 0; i < m.length; i++) m[i] = i & 255;
  report('crypto_hash 1K', benchmark(function() {
    nacl.lowlevel.crypto_hash(out, m, m.length);
  }, m.length));

  m = new Uint8Array(16*1024);
  for (i = 0; i < m.length; i++) m[i] = i & 255;
  report('crypto_hash 16K', benchmark(function() {
    nacl.lowlevel.crypto_hash(out, m, m.length);
  }, m.length));
}

crypto_stream_xor_benchmark();
crypto_onetimeauth_benchmark();
crypto_secretbox_benchmark();
crypto_hash_benchmark();
secretbox_seal_open_benchmark();
crypto_scalarmult_base_benchmark();
box_seal_open_benchmark();
sign_open_benchmark();
<commit_msg>benchmark: use best times instead of average; use more precise time when available<commit_after>var nacl = (typeof window !== 'undefined') ? window.nacl : require('../../' + (process.env.NACL_SRC || 'nacl.min.js'));
var helpers = (typeof require !== 'undefined') ? require('./helpers') : window.helpers;
var log = helpers.log;

if (!nacl) throw new Error('nacl not loaded');

function decodeUTF8(s) {
  var i, d = unescape(encodeURIComponent(s)), b = new Uint8Array(d.length);
  for (i = 0; i < d.length; i++) b[i] = d.charCodeAt(i);
  return b;
}

var getTime = (function () {
  if (typeof performance !== "undefined") {
    return performance.now.bind(performance);
  }
  if (typeof process !== "undefined" && process.hrtime) {
    return function () {
      var _a = process.hrtime(), sec = _a[0], nanosec = _a[1];
      return (sec * 1e9 + nanosec) / 1e6;
    };
  }
  return Date.now.bind(Date);
})();

function benchmark(fn, bytes) {
  var best = Number.MAX_VALUE;
  var elapsed = 0;
  var iterations = 1;
  while (true) {
    var startTime = getTime();
    fn();
    var diff = getTime() - startTime;
    if (diff > 0 && diff < best) {
      best = diff;
    }
    elapsed += diff;
    if (elapsed > 500 && iterations > 2) {
      break;
    }
    iterations++;
  }
  return {
    iterations: iterations,
    msPerOp: best,
    opsPerSecond: 1 / (best / 1000),
    bytesPerSecond: bytes ? 1000 * (bytes * iterations) / (best * iterations) : undefined
  };
}

function pad(s, upto, end) {
  if (end === void 0) { end = false; }
  var padlen = upto - s.length;
  if (padlen <= 0) {
    return s;
  }
  // XXX: in ES2015 we can use ' '.repeat(padlen)
  var padding = new Array(padlen + 1).join(' ');
  if (end) {
    return s + padding;
  }
  return padding + s;
}

function report(name, results) {
  var ops = results.iterations + ' ops';
  var msPerOp = results.msPerOp.toFixed(2) + ' ms/op';
  var opsPerSecond = results.opsPerSecond.toFixed(2) + ' ops/sec';
  var mibPerSecond = results.bytesPerSecond
      ? (results.bytesPerSecond / 1024 / 1024).toFixed(2) + ' MiB/s'
      : '';
  log.print(
    pad(name, 25, true) + ' ' +
    pad(ops, 20) + ' ' +
    pad(msPerOp, 20) + ' ' +
    pad(opsPerSecond, 20) + ' ' +
    pad(mibPerSecond, 15)
  );
}

function crypto_stream_xor_benchmark() {
  var m = new Uint8Array(1024),
      n = new Uint8Array(24),
      k = new Uint8Array(32),
      out = new Uint8Array(1024),
      i;
  for (i = 0; i < 1024; i++) m[i] = i & 255;
  for (i = 0; i < 24; i++) n[i] = i;
  for (i = 0; i < 32; i++) k[i] = i;
  report('crypto_stream_xor 1K', benchmark(function() {
    nacl.lowlevel.crypto_stream_xor(out, 0, m, 0, m.length, n, k);
  }, m.length));
}

function crypto_onetimeauth_benchmark() {
  var m = new Uint8Array(1024),
      out = new Uint8Array(1024),
      k = new Uint8Array([0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1]);
  for (var i = 0; i < 1024; i++) {
    m[i] = i & 255;
  }
  report('crypto_onetimeauth 1K', benchmark(function() {
    nacl.lowlevel.crypto_onetimeauth(out, 0, m, 0, m.length, k);
  }, m.length));
}

function crypto_secretbox_benchmark() {
  var i, k = new Uint8Array(32), n = new Uint8Array(24),
      m = new Uint8Array(1024), c = new Uint8Array(1024);
  for (i = 0; i < 32; i++) k[i] = 1;
  for (i = 0; i < 24; i++) n[i] = 2;
  for (i = 0; i < 1024; i++) m[i] = 3;
  report('crypto_secretbox 1K', benchmark(function() {
    nacl.lowlevel.crypto_secretbox(c, m, m.length, n, k);
  }, m.length));
}

function secretbox_seal_open_benchmark() {
  var key = new Uint8Array(32),
      nonce = new Uint8Array(24),
      msg = new Uint8Array(1024),
      box, i;
  for (i = 0; i < 32; i++) key[i] = 1;
  for (i = 0; i < 24; i++) nonce[i] = 2;
  for (i = 0; i < 1024; i++) msg[i] = 3;

  report('secretbox 1K', benchmark(function() {
    box = nacl.secretbox(msg, nonce, key);
  }, msg.length));

  report('secretbox.open 1K', benchmark(function() {
    nacl.secretbox.open(box, nonce, key);
  }, msg.length));
}

function crypto_scalarmult_base_benchmark() {
  var n = new Uint8Array(32), q = new Uint8Array(32);
  for (var i = 0; i < 32; i++) n[i] = i;
  report('crypto_scalarmult_base', benchmark(function() {
    nacl.lowlevel.crypto_scalarmult_base(q, n);
  }));
}

function box_seal_open_benchmark() {
  var pk1 = new Uint8Array(32), sk1 = new Uint8Array(32),
      pk2 = new Uint8Array(32), sk2 = new Uint8Array(32);
  nacl.lowlevel.crypto_box_keypair(pk1, sk1);
  nacl.lowlevel.crypto_box_keypair(pk2, sk2);
  var nonce = decodeUTF8('123456789012345678901234');
  var msg = decodeUTF8((new Array(1024)).join('a'));
  var box = null;

  report('box 1K', benchmark(function() {
    box = nacl.box(msg, nonce, pk1, sk2);
  }, msg.length));

  report('box.open 1K', benchmark(function() {
    nacl.box.open(box, nonce, pk2, sk1);
  }, msg.length));
}

function sign_open_benchmark() {
  var k = nacl.sign.keyPair();
  var sk = k.secretKey;
  var pk = k.publicKey;
  var msg = decodeUTF8((new Array(128)).join('a'));
  var sm;

  report('sign', benchmark(function() {
    sm = nacl.sign(msg, sk);
  }));

  report('sign.open', benchmark(function() {
    nacl.sign.open(sm, pk);
  }));
}

function crypto_hash_benchmark() {
  var m = new Uint8Array(1024), out = new Uint8Array(64);
  var i;
  for (i = 0; i < m.length; i++) m[i] = i & 255;
  report('crypto_hash 1K', benchmark(function() {
    nacl.lowlevel.crypto_hash(out, m, m.length);
  }, m.length));

  m = new Uint8Array(16*1024);
  for (i = 0; i < m.length; i++) m[i] = i & 255;
  report('crypto_hash 16K', benchmark(function() {
    nacl.lowlevel.crypto_hash(out, m, m.length);
  }, m.length));
}

crypto_stream_xor_benchmark();
crypto_onetimeauth_benchmark();
crypto_secretbox_benchmark();
crypto_hash_benchmark();
secretbox_seal_open_benchmark();
crypto_scalarmult_base_benchmark();
box_seal_open_benchmark();
sign_open_benchmark();
<|endoftext|>


<commit_before>var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var cw = canvas.width = window.innerWidth,
  cx = cw / 2;
var ch = canvas.height = window.innerHeight,
  cy = ch / 2;

ctx.fillStyle = "#000";
var linesNum = 16;
var linesRy = [];
var requestId = null;

function Line(flag) {
  this.flag = flag;
  this.a = {};
  this.b = {};
  if (flag == "v") {
    this.a.y = 0;
    this.b.y = ch;
    this.a.x = randomIntFromInterval(0, ch);
    this.b.x = randomIntFromInterval(0, ch);
  } else if (flag == "h") {
    this.a.x = 0;
    this.b.x = cw;
    this.a.y = randomIntFromInterval(0, cw);
    this.b.y = randomIntFromInterval(0, cw);
  }
  this.va = randomIntFromInterval(25, 100) / 100;
  this.vb = randomIntFromInterval(25, 100) / 100;

  this.draw = function() {
    ctx.strokeStyle = "#ccc";
    ctx.beginPath();
    ctx.moveTo(this.a.x, this.a.y);
    ctx.lineTo(this.b.x, this.b.y);
    ctx.stroke();
  }

  this.update = function() {
    if (this.flag == "v") {
      this.a.x += this.va;
      this.b.x += this.vb;
    } else if (flag == "h") {
      this.a.y += this.va;
      this.b.y += this.vb;
    }

    this.edges();
  }

  this.edges = function() {
    if (this.flag == "v") {
      if (this.a.x < 0 || this.a.x > cw) {
        this.va *= -1;
      }
      if (this.b.x < 0 || this.b.x > cw) {
        this.vb *= -1;
      }
    } else if (flag == "h") {
      if (this.a.y < 0 || this.a.y > ch) {
        this.va *= -1;
      }
      if (this.b.y < 0 || this.b.y > ch) {
        this.vb *= -1;
      }
    }
  }

}

for (var i = 0; i < linesNum; i++) {
  var flag = i % 2 == 0 ? "h" : "v";
  var l = new Line(flag);
  linesRy.push(l);
}

function Draw() {
  requestId = window.requestAnimationFrame(Draw);
  ctx.clearRect(0, 0, cw, ch);

  for (var i = 0; i < linesRy.length; i++) {
    var l = linesRy[i];
    l.draw();
    l.update();
  }
  for (var i = 0; i < linesRy.length; i++) {
    var l = linesRy[i];
    for (var j = i + 1; j < linesRy.length; j++) {
      var l1 = linesRy[j]
      Intersect2lines(l, l1);
    }
  }
}

function Init() {
  linesRy.length = 0;
  for (var i = 0; i < linesNum; i++) {
    var flag = i % 2 == 0 ? "h" : "v";
    var l = new Line(flag);
    linesRy.push(l);
  }

  if (requestId) {
    window.cancelAnimationFrame(requestId);
    requestId = null;
  }

  cw = canvas.width = window.innerWidth,
    cx = cw / 2;
  ch = canvas.height = window.innerHeight,
    cy = ch / 2;

  Draw();
};

setTimeout(function() {
  Init();

  addEventListener('resize', Init, false);
}, 15);

function Intersect2lines(l1, l2) {
  var p1 = l1.a,
    p2 = l1.b,
    p3 = l2.a,
    p4 = l2.b;
  var denominator = (p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y);
  var ua = ((p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x)) / denominator;
  var ub = ((p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x)) / denominator;
  var x = p1.x + ua * (p2.x - p1.x);
  var y = p1.y + ua * (p2.y - p1.y);
  if (ua > 0 && ub > 0) {
    markPoint({
      x: x,
      y: y
    })
  }
}

function markPoint(p) {
  ctx.beginPath();
  ctx.arc(p.x, p.y, 2, 0, 2 * Math.PI);
  ctx.fill();
}

function randomIntFromInterval(mn, mx) {
  return ~~(Math.random() * (mx - mn + 1) + mn);
}<commit_msg>del background<commit_after><|endoftext|>


<commit_before>import { expect } from 'chai'
import { bindToSelection } from '../src'
import { init, setItems } from 'yourchoice'

describe('bindToSelection', () => {
  it('should add selectionName to payload of actions', () => {
    const boundYourchoice = bindToSelection('selectionA')
    const testAction = boundYourchoice.actions.removeAll()
    expect(testAction).to.have.deep.property('payload.selectionName', 'selectionA')
  })

  it('should make selectors act on the bound selection', () => {
    const boundYourchoice = bindToSelection('selectionA')
    const testState = {
      selectionA: setItems(['A', 'B', 'C'], init()),
      selectionB: setItems([], init()),
    }
    const testSelector = boundYourchoice.selectors.getItems

    expect(testSelector(testState)).to.deep.equal(['A', 'B', 'C'])
  })

  it('should default selectionName to to selection', () => {
    const boundYourchoice = bindToSelection()
    const testAction = boundYourchoice.actions.removeAll()

    expect(testAction).to.have.deep.property('payload.selectionName', 'selection')
  })
})
<commit_msg>Improve formatting<commit_after>import { expect } from 'chai'
import { bindToSelection } from '../src'
import { init, setItems } from 'yourchoice'

describe('bindToSelection', () => {
  it('should add selectionName to payload of actions', () => {
    const boundYourchoice = bindToSelection('selectionA')
    const testAction = boundYourchoice.actions.removeAll()

    expect(testAction).to.have.deep.property('payload.selectionName', 'selectionA')
  })

  it('should make selectors act on the bound selection', () => {
    const boundYourchoice = bindToSelection('selectionA')
    const testState = {
      selectionA: setItems(['A', 'B', 'C'], init()),
      selectionB: setItems([], init()),
    }
    const testSelector = boundYourchoice.selectors.getItems

    expect(testSelector(testState)).to.deep.equal(['A', 'B', 'C'])
  })

  it('should default selectionName to to selection', () => {
    const boundYourchoice = bindToSelection()
    const testAction = boundYourchoice.actions.removeAll()

    expect(testAction).to.have.deep.property('payload.selectionName', 'selection')
  })
})
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.movement',
  name: 'Animation',

  properties: [
    {
      class: 'Int',
      name: 'duration',
      units: 'ms',
      value: 1000
    },
    {
      name: 'f',
    },
    {
      class: 'Array',
      name: 'objs'
    },
    {
      name: 'onEnd',
      value: function() {}
    },
    {
      name: 'startTime_'
    },
    {
      class: 'Map',
      name: 'slots_'
    }
  ],

  methods: [
    function start() {
      var self    = this;
      var cleanup = foam.core.FObject.create();

      this.objs.forEach(function(o) {
        cleanup.onDetach(o.propertyChange.sub(self.propertySet));
      });

      this.f();

      cleanup.detach();

      this.startTime_ = Date.now();

      this.animateValues();
      this.tick();
    },

    function animateValues() {
      for ( var key in this.slots_ ) {
        var s = this.slots_[key];
        var slot = s[0], startValue = s[1], endValue = s[2];
        var completion = Math.min(1, (Date.now() - this.startTime_) / this.duration);
        var value = startValue + (endValue-startValue) * completion;
        slot.set(value);
      }
    }
  ],

  listeners: [
    {
      name: 'propertySet',
      code: function(_, __, __, slot) {
        if ( this.slots_[slot] ) return;

        var oldValue = slot.getPrev(), newValue = slot.get();

        this.slots_[slot] = [ slot, oldValue, newValue ];
      }
    },
    {
      name: 'tick',
      isFramed: true,
      code: function() {
        this.animateValues();

        if ( Date.now() < this.startTime_ + this.duration ) {
          this.tick();
        } else {
          this.onEnd();
        }
      }
    }
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.snake',
  name: 'Scale',
  extends: 'foam.graphics.Circle',
});

foam.CLASS({
  package: 'com.foamdev.demos.snake',
  name: 'Snake',
  extends: 'foam.graphics.CView',

  requires: [
    'com.foamdev.demos.snake.Scale',
    'com.foamdev.demos.snake.Laser'
  ],

  imports: [
    'game',
    'timer',
    'R'
  ],

  properties: [
//    { name: 'scales', factory: function() { return []; } },
    [ 'sx', 240 ],
    [ 'sy', 240 ],
    [ 'vx', 1/5 ],
    [ 'vy', 0 ],
    [ 'length', 5 ]
  ],

  methods: [
    function init() {
      this.SUPER();

      this.timer.i$.sub(this.tick);
    },
    function up()    { this.vy = -1/5; this.vx =  0; },
    function down()  { this.vy =  1/5; this.vx =  0; },
    function left()  { this.vy =  0; this.vx = -1/5; },
    function right() { this.vy =  0; this.vx =  1/5; },
    function fire () {
      this.Laser.create({x: this.sx, y: this.sy, vx: this.vx, vy: this.vy});
    },
    function intersects(o) {
      if ( ! this.children.length ) return false;
      return this.children[this.children.length-1].intersects(o);
    }
  ],

  listeners: [
    {
      name: 'tick',
      isMerged: 150,
      code: function() {
        this.sx += this.vx * 2 * this.R;
        this.sy += this.vy * 2 * this.R;
        if ( this.children.length )
          this.children[this.children.length-1].color = 'green';
        this.add(this.Scale.create({x: this.sx, y: this.sy, radius: this.R, color: 'red'}));
        if ( this.children.length > this.length )
          this.children.shift();
      }
    }
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.snake',
  name: 'Food',
  extends: 'foam.graphics.Circle',

  requires: [ 'foam.movement.Animation' ],

  properties: [
    [ 'color', 'darkblue' ],
    [ 'radius', 10 ]
  ],

  methods: [
    function init() {
      this.SUPER();

      this.Animation.create({
        duration: 5000,
        f: ()=> this.radius = 0,
        objs: [this]
      }).start();
      /*
      this.movement.animate(15000, function() {
        // TODO:
        this.radius = 0;
      }.bind(this), this)();
      */
    }
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.snake',
  name: 'Mushroom',
  extends: 'foam.graphics.Circle',
  requires: [ 'foam.graphics.Box as Rectangle' ],

  imports: [ 'R as r', 'movement' ],

  properties: [
    [ 'radius', 20 ],
    [ 'color',    'red' ],
    [ 'start', Math.PI ],
    [ 'end', 0 ],
    'stem'
  ],

  methods: [
    function init() {
      this.SUPER();

      this.add(this.stem = this.Rectangle.create({
        x: -7.5,
        y: -0.5,
        width: 15,
        height: 20,
        color: 'gray'
      }));
    },

    function explode() {
      this.stem.background = 'red';
      this.movement.animate(200, function() {
        this.scaleX     = this.scaleY = 30;
        this.alpha      = 0;
        this.a          = Math.PI * 1.5;
        this.stem.alpha = 0;
      }.bind(this)/*, function() { this.table.removeChild(o2); }.bind(this)*/)();
    }
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.snake',
  name: 'Laser',
  extends: 'foam.graphics.Circle',
  imports: [ 'game', 'movement' ],

  properties: [
    [ 'color', 'yellow' ],
    [ 'r', 12 ],
    'vx',
    'vy'
  ],

  methods: [
    function init() {
      this.SUPER();

      this.game.add(this);
      this.movement.animate(5000, function() {
        this.x += 2000 * this.vx;
        this.y += 2000 * this.vy;
      }.bind(this))();
    }
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.snake',
  name: 'Game',
  extends: 'foam.u2.View',

  requires: [
    'foam.movement.Movement',
    'foam.util.Timer',
    'com.google.foam.demos.robot.Robot',
    'com.foamdev.demos.snake.Laser',
    'com.foamdev.demos.snake.Snake',
    'com.foamdev.demos.snake.Mushroom',
    'com.foamdev.demos.snake.Food',
    'foam.graphics.CView',
    'foam.graphics.Box as Rectangle',
    'foam.physics.Collider'
  ],

  exports: [
    'R',
    'timer',
    'as game',
    'movement'
  ],

  constants: { R: 20 },

  properties: [
    {
      name: 'movement',
      factory: function() { return this.Movement.create(); }
    },
    {
      name: 'timer',
      factory: function() { return this.Timer.create(); }
    },
    [ 'width', 1600 ],
    [ 'height', 800 ],
    {
      name: 'snake',
      factory: function() { return this.Snake.create(); }
    },
    {
      name: 'table',
      factory: function() {
        return this.Rectangle.create({
          color: 'lightblue',
          width: 800, //window.innerWidth,
          height: 500, //window.innerHeight
        }).add(this.snake);
      }
    },
    {
      name: 'collider',
      factory: function() { return this.Collider.create(); }
    }
  ],

  listeners: [
    {
      name: 'tick',
      code: function(_, __, ___, t) {
        if ( t.get() % 10 == 0 ) this.addFood();
        if ( Math.random() < 0.02 ) this.addMushroom();
      }
    }
  ],

  actions: [
    {
      name: 'up',
      keyboardShortcuts: [ 38 /* up arrow */, 'w' ],
      code: function() { this.snake.up(); }
    },
    {
      name: 'down',
      keyboardShortcuts: [ 40 /* down arrow */, 's' ],
      code: function() { this.snake.down(); }
    },
    {
      name: 'left',
      keyboardShortcuts: [ 37 /* left arrow */, 'a' ],
      code: function() { this.snake.left(); }
    },
    {
      name: 'right',
      keyboardShortcuts: [ 39 /* right arrow */, 'd' ],
      code: function() { this.snake.right(); }
    },
    {
      name: 'fire',
      keyboardShortcuts: [ ' ', 'x' ],
      code: function() { this.snake.fire(); }
    }
  ],

  methods: [
    function init() {
      this.SUPER();

//      this.addChild(this.collider);

      this.timer.i$.sub(this.tick);
      this.timer.start();

      this.table.add(this.Robot.create({x:200, y:200}));

      // Setup Physics
      this.collider.add(this.snake);
      this.collider.collide = function(o1, o2) {
        if ( this.Laser.isInstance(o2) || this.Snake.isInstance(o2) ) {
          var tmp = o1;
          o1 = o2;
          o2 = tmp;
        }
        if ( this.Laser.isInstance(o1) ) {
          if ( this.Mushroom.isInstance(o2) ) {
            o2.explode();
          } else if ( this.Food.isInstance(o2) ) {
          }
        }
        if ( this.Snake.isInstance(o1) && this.Mushroom.isInstance(o2) ) {
          if ( o2.scaleX == 1 )
            this.gameOver();
          else
            this.removeChild(o2);
        }
        if ( this.Snake.isInstance(o1) && this.Food.isInstance(o2) ) {
          this.removeChild(o2);
          this.snake.length++;
        }
//        console.log('BANG', o1, o2);
      }.bind(this);
      this.collider.start();
    },

    function initE() {
      this.SUPER();
      this.focus();
      this.add(this.table);
    },

    function gameOver() {
      this.timer.stop();
//      this.collider.stop(); // TODO: add stop() method to collider
      this.table.background='orange';
    },

    function addChild(c) {
      this.table.add(c);
      // TODO
     // if ( c.intersects ) this.collider.add(c);
    },

    function removeChild(c) {
      this.table.removeChild(c);
      if ( c.intersects ) this.collider.remove(c);
    },

    function addFood() {
      var R = this.R;
      var f = this.Food.create({
        x: Math.round(1+Math.random()*(this.table.width -4*R)/R)*2*R,
        y: Math.round(1+Math.random()*(this.table.height-4*R)/R)*2*R,
      });
      this.addChild(f);
    },

    function addMushroom() {
      var R = this.R;
      var m = this.Mushroom.create({
        x: Math.round(1+Math.random()*(this.table.width -4*R)/R)*2*R,
        y: Math.round(1+Math.random()*(this.table.height-4*R)/R)*2*R,
        scaleX: 0.1,
        scaleY: 0.1});

        /*
        TODO
      this.movement.animate(7000, function() {
        m.scaleX = m.scaleY = 1;
      })();
      */

      this.addChild(m);
    }
  ]
});
<commit_msg>Improve snake game.<commit_after>/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.movement',
  name: 'Animation',

  properties: [
    {
      class: 'Int',
      name: 'duration',
      units: 'ms',
      value: 1000
    },
    {
      name: 'f',
    },
    {
      class: 'Array',
      name: 'objs'
    },
    {
      name: 'onEnd',
      value: function() {}
    },
    {
      name: 'startTime_'
    },
    {
      class: 'Map',
      name: 'slots_'
    }
  ],

  methods: [
    function start() {
      var self    = this;
      var cleanup = foam.core.FObject.create();

      this.objs.forEach(function(o) {
        cleanup.onDetach(o.propertyChange.sub(self.propertySet));
      });

      this.f();

      cleanup.detach();

      this.startTime_ = Date.now();

      this.animateValues();
      this.tick();
    },

    function animateValues() {
      for ( var key in this.slots_ ) {
        var s = this.slots_[key];
        var slot = s[0], startValue = s[1], endValue = s[2];
        var completion = Math.min(1, (Date.now() - this.startTime_) / this.duration);
        var value = startValue + (endValue-startValue) * completion;
        slot.set(value);
      }
    }
  ],

  listeners: [
    {
      name: 'propertySet',
      code: function(_, __, __, slot) {
        if ( this.slots_[slot] ) return;

        var oldValue = slot.getPrev(), newValue = slot.get();

        this.slots_[slot] = [ slot, oldValue, newValue ];
      }
    },
    {
      name: 'tick',
      isFramed: true,
      code: function() {
        this.animateValues();

        if ( Date.now() < this.startTime_ + this.duration ) {
          this.tick();
        } else {
          this.onEnd();
        }
      }
    }
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.snake',
  name: 'Scale',
  extends: 'foam.graphics.Circle',
});

foam.CLASS({
  package: 'com.foamdev.demos.snake',
  name: 'Snake',
  extends: 'foam.graphics.CView',

  requires: [
    'com.foamdev.demos.snake.Scale',
    'com.foamdev.demos.snake.Laser'
  ],

  imports: [
    'game',
    'timer',
    'R'
  ],

  properties: [
//    { name: 'scales', factory: function() { return []; } },
    [ 'sx', 240 ],
    [ 'sy', 240 ],
    [ 'vx', 1/5 ],
    [ 'vy', 0 ],
    [ 'length', 5 ]
  ],

  methods: [
    function init() {
      this.SUPER();

      this.timer.i$.sub(this.tick);
    },
    function up()    { this.vy = -1/5; this.vx =  0; },
    function down()  { this.vy =  1/5; this.vx =  0; },
    function left()  { this.vy =  0; this.vx = -1/5; },
    function right() { this.vy =  0; this.vx =  1/5; },
    function fire () {
      this.Laser.create({x: this.sx, y: this.sy, vx: this.vx, vy: this.vy});
    },
    function intersects(o) {
      if ( ! this.children.length ) return false;
      return this.children[this.children.length-1].intersects(o);
    }
  ],

  listeners: [
    {
      name: 'tick',
      isMerged: 150,
      code: function() {
        this.sx += this.vx * 2 * this.R;
        this.sy += this.vy * 2 * this.R;
        if ( this.children.length )
          this.children[this.children.length-1].color = 'green';
        this.add(this.Scale.create({x: this.sx, y: this.sy, radius: this.R, color: 'red'}));
        if ( this.children.length > this.length )
          this.children.shift();
      }
    }
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.snake',
  name: 'Food',
  extends: 'foam.graphics.Circle',

  requires: [ 'foam.movement.Animation' ],

  properties: [
    [ 'color', 'darkblue' ],
    [ 'radius', 10 ]
  ],

  methods: [
    function init() {
      this.SUPER();

      this.Animation.create({
        duration: 5000,
        f: ()=> this.radius = 0,
        objs: [this]
      }).start();
      /*
      this.movement.animate(15000, function() {
        // TODO:
        this.radius = 0;
      }.bind(this), this)();
      */
    }
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.snake',
  name: 'Mushroom',
  extends: 'foam.graphics.Circle',
  requires: [ 'foam.graphics.Box as Rectangle' ],

  imports: [ 'R as r', 'movement' ],

  properties: [
    [ 'radius', 20 ],
    [ 'color',    'red' ],
    [ 'start', Math.PI ],
    [ 'end', 0 ],
    'stem'
  ],

  methods: [
    function init() {
      this.SUPER();

      this.add(this.stem = this.Rectangle.create({
        x: -7.5,
        y: -0.5,
        width: 15,
        height: 20,
        color: 'gray'
      }));
    },

    function explode() {
      this.stem.background = 'red';
      this.movement.animate(200, function() {
        this.scaleX     = this.scaleY = 30;
        this.alpha      = 0;
        this.a          = Math.PI * 1.5;
        this.stem.alpha = 0;
      }.bind(this)/*, function() { this.table.removeChild(o2); }.bind(this)*/)();
    }
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.snake',
  name: 'Laser',
  extends: 'foam.graphics.Circle',
  imports: [ 'game', 'movement' ],

  properties: [
    [ 'color', 'yellow' ],
    [ 'r', 12 ],
    'vx',
    'vy'
  ],

  methods: [
    function init() {
      this.SUPER();

      this.game.add(this);
      this.movement.animate(5000, function() {
        this.x += 2000 * this.vx;
        this.y += 2000 * this.vy;
      }.bind(this))();
    }
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.snake',
  name: 'Game',
  extends: 'foam.u2.View',

  requires: [
    'foam.movement.Movement',
    'foam.util.Timer',
    'com.google.foam.demos.robot.Robot',
    'com.foamdev.demos.snake.Laser',
    'com.foamdev.demos.snake.Snake',
    'com.foamdev.demos.snake.Mushroom',
    'com.foamdev.demos.snake.Food',
    'foam.graphics.CView',
    'foam.graphics.Box as Rectangle',
    'foam.physics.Collider'
  ],

  exports: [
    'R',
    'timer',
    'as game',
    'movement'
  ],

  constants: { R: 20 },

  properties: [
    {
      name: 'movement',
      factory: function() { return this.Movement.create(); }
    },
    {
      name: 'timer',
      factory: function() { return this.Timer.create(); }
    },
    [ 'width', 1600 ],
    [ 'height', 800 ],
    {
      name: 'snake',
      factory: function() { return this.Snake.create(); }
    },
    {
      name: 'table',
      factory: function() {
        return this.Rectangle.create({
          color: 'lightblue',
          width: 800, //window.innerWidth,
          height: 500, //window.innerHeight
        }).add(this.snake);
      }
    },
    {
      name: 'collider',
      factory: function() { return this.Collider.create(); }
    }
  ],

  listeners: [
    {
      name: 'tick',
      code: function(_, __, ___, t) {
        if ( t.get() % 10 == 0 ) this.addFood();
        if ( Math.random() < 0.02 ) this.addMushroom();
      }
    }
  ],

  actions: [
    {
      name: 'up',
      keyboardShortcuts: [ 38 /* up arrow */, 'w' ],
      code: function() { this.snake.up(); }
    },
    {
      name: 'down',
      keyboardShortcuts: [ 40 /* down arrow */, 's' ],
      code: function() { this.snake.down(); }
    },
    {
      name: 'left',
      keyboardShortcuts: [ 37 /* left arrow */, 'a' ],
      code: function() { this.snake.left(); }
    },
    {
      name: 'right',
      keyboardShortcuts: [ 39 /* right arrow */, 'd' ],
      code: function() { this.snake.right(); }
    },
    {
      name: 'fire',
      keyboardShortcuts: [ ' ', 'x' ],
      code: function() { this.snake.fire(); }
    }
  ],

  methods: [
    function init() {
      this.SUPER();

//      this.addChild(this.collider);

      this.timer.i$.sub(this.tick);
      this.timer.start();

      this.table.add(this.Robot.create({x:200, y:200}));

      // Setup Physics
      this.collider.add(this.snake);
      this.collider.collide = function(o1, o2) {
        if ( this.Laser.isInstance(o2) || this.Snake.isInstance(o2) ) {
          var tmp = o1;
          o1 = o2;
          o2 = tmp;
        }
        if ( this.Laser.isInstance(o1) ) {
          if ( this.Mushroom.isInstance(o2) ) {
            o2.explode();
          } else if ( this.Food.isInstance(o2) ) {
          }
        }
        if ( this.Snake.isInstance(o1) && this.Mushroom.isInstance(o2) ) {
          if ( o2.scaleX == 1 )
            this.gameOver();
          else
            this.removeChild(o2);
        }
        if ( this.Snake.isInstance(o1) && this.Food.isInstance(o2) ) {
          this.removeChild(o2);
          this.snake.length++;
        }
//        console.log('BANG', o1, o2);
      }.bind(this);
      this.collider.start();
    },

    function initE() {
      this.SUPER();
      this.focus();
      this.style({display:'inline'}).add(this.table);
    },

    function gameOver() {
      this.timer.stop();
//      this.collider.stop(); // TODO: add stop() method to collider
      this.table.background='orange';
    },

    function addChild(c) {
      this.table.add(c);
      // TODO
     // if ( c.intersects ) this.collider.add(c);
    },

    function removeChild(c) {
      this.table.removeChild(c);
      if ( c.intersects ) this.collider.remove(c);
    },

    function addFood() {
      var R = this.R;
      var f = this.Food.create({
        x: Math.round(1+Math.random()*(this.table.width -4*R)/R)*2*R,
        y: Math.round(1+Math.random()*(this.table.height-4*R)/R)*2*R,
      });
      this.addChild(f);
    },

    function addMushroom() {
      var R = this.R;
      var m = this.Mushroom.create({
        x: Math.round(1+Math.random()*(this.table.width -4*R)/R)*2*R,
        y: Math.round(1+Math.random()*(this.table.height-4*R)/R)*2*R,
        scaleX: 0.1,
        scaleY: 0.1});

        /*
        TODO
      this.movement.animate(7000, function() {
        m.scaleX = m.scaleY = 1;
      })();
      */

      this.addChild(m);
    }
  ]
});
<|endoftext|>


<commit_before>var assert = require('chai').assert;
var sinon = require('sinon');
var cart = typeof window !== 'undefined' ? window.carty : require('../lib/cart');

describe("cart().option('store')", function() {
    var store, mock;

    beforeEach(function() {
        store = {
            load: function () { return [{id: 'Existing Item'}]; },
            add: function (item, items) { },
            remove: function (item, items) { },
            clear: function () {}
        };

        mock = sinon.mock(store)
    });

    it("loads items from store", function(done) {
        mock.expects('load').once().returns([{id: 'id'}]);

        cart({store: store})
            .ready(function(instance) {
                assert.strictEqual(1, instance.size());
                assert.strictEqual(1, instance().length);

                mock.verify();

                done();
            });
    });

    it("adds items to store", function(done) {
        mock.expects('add').twice();

        cart({store: store})
            .add('Item')
            .add('Item2')
            .ready(function() {
                mock.verify();
                done();
            })
        ;
    });

    it("propagates add error", function(done) {
        mock.expects('add').once().returns(Promise.reject('error'));

        cart({store: store})
            .add('Item')
            .error(function(error) {
                assert.strictEqual(error, 'error');

                return Promise.reject(error);
            })
            .error(function(error) {
                assert.strictEqual(error, 'error');
            })
            .ready(function(error) {
                assert.notStrictEqual(error, 'error');
                mock.verify();
                done();
            })
            .error(function() {
                process.nextTick(function() {
                    assert.fail();
                    done();
                }, 10);
            })
        ;
    });

    it("removes items from store", function(done) {
        mock.expects('remove').once();

        cart({store: store})
            .remove('Existing Item')
            .ready(function() {
                mock.verify();
                done();
            })
        ;
    });

    it("propagates remove error returned as Promise", function(done) {
        mock.expects('remove').once().returns(Promise.reject('error'));

        cart({store: store})
            .remove('Existing Item')
            .error(function(error) {
                assert.strictEqual(error, 'error');

                return Promise.reject(error);
            })
            .error(function(error) {
                assert.strictEqual(error, 'error');
            })
            .ready(function(error) {
                assert.notStrictEqual(error, 'error');
                mock.verify();
                done();
            })
            .error(function() {
                process.nextTick(function() {
                    assert.fail();
                    done();
                }, 10);
            })
        ;
    });

    it("propagates thrown remove error", function(done) {
        var exception = new Error('error');
        mock.expects('remove').once().throws(exception);

        cart({store: store})
            .remove('Existing Item')
            .error(function(error) {
                assert.strictEqual(error, exception);

                return Promise.reject(error);
            })
            .error(function(error) {
                assert.strictEqual(error, exception);
            })
            .ready(function(error) {
                assert.notStrictEqual(error, exception);
                mock.verify();
                done();
            })
            .error(function() {
                process.nextTick(function() {
                    assert.fail();
                    done();
                }, 10);
            })
        ;
    });

    it("clears store", function(done) {
        mock.expects('clear').once();

        cart({store: store})
            .clear()
            .ready(function() {
                mock.verify();

                done();
            });
    });
});
<commit_msg>Add test for stores loading non-array data<commit_after>var assert = require('chai').assert;
var sinon = require('sinon');
var cart = typeof window !== 'undefined' ? window.carty : require('../lib/cart');

describe("cart().option('store')", function() {
    var store, mock;

    beforeEach(function() {
        store = {
            load: function () { return [{id: 'Existing Item'}]; },
            add: function (item, items) { },
            remove: function (item, items) { },
            clear: function () {}
        };

        mock = sinon.mock(store)
    });

    it("can load non-array data", function(done) {
        mock.expects('load').once().returns(null);

        cart({store: store})
            .ready(function(instance) {
                assert.strictEqual(0, instance.size());
                assert.strictEqual(0, instance().length);

                mock.verify();

                done();
            });
    });

    it("loads items from store", function(done) {
        mock.expects('load').once().returns([{id: 'id'}]);

        cart({store: store})
            .ready(function(instance) {
                assert.strictEqual(1, instance.size());
                assert.strictEqual(1, instance().length);

                mock.verify();

                done();
            });
    });

    it("adds items to store", function(done) {
        mock.expects('add').twice();

        cart({store: store})
            .add('Item')
            .add('Item2')
            .ready(function() {
                mock.verify();
                done();
            })
        ;
    });

    it("propagates add error", function(done) {
        mock.expects('add').once().returns(Promise.reject('error'));

        cart({store: store})
            .add('Item')
            .error(function(error) {
                assert.strictEqual(error, 'error');

                return Promise.reject(error);
            })
            .error(function(error) {
                assert.strictEqual(error, 'error');
            })
            .ready(function(error) {
                assert.notStrictEqual(error, 'error');
                mock.verify();
                done();
            })
            .error(function() {
                process.nextTick(function() {
                    assert.fail();
                    done();
                }, 10);
            })
        ;
    });

    it("removes items from store", function(done) {
        mock.expects('remove').once();

        cart({store: store})
            .remove('Existing Item')
            .ready(function() {
                mock.verify();
                done();
            })
        ;
    });

    it("propagates remove error returned as Promise", function(done) {
        mock.expects('remove').once().returns(Promise.reject('error'));

        cart({store: store})
            .remove('Existing Item')
            .error(function(error) {
                assert.strictEqual(error, 'error');

                return Promise.reject(error);
            })
            .error(function(error) {
                assert.strictEqual(error, 'error');
            })
            .ready(function(error) {
                assert.notStrictEqual(error, 'error');
                mock.verify();
                done();
            })
            .error(function() {
                process.nextTick(function() {
                    assert.fail();
                    done();
                }, 10);
            })
        ;
    });

    it("propagates thrown remove error", function(done) {
        var exception = new Error('error');
        mock.expects('remove').once().throws(exception);

        cart({store: store})
            .remove('Existing Item')
            .error(function(error) {
                assert.strictEqual(error, exception);

                return Promise.reject(error);
            })
            .error(function(error) {
                assert.strictEqual(error, exception);
            })
            .ready(function(error) {
                assert.notStrictEqual(error, exception);
                mock.verify();
                done();
            })
            .error(function() {
                process.nextTick(function() {
                    assert.fail();
                    done();
                }, 10);
            })
        ;
    });

    it("clears store", function(done) {
        mock.expects('clear').once();

        cart({store: store})
            .clear()
            .ready(function() {
                mock.verify();

                done();
            });
    });
});
<|endoftext|>


<commit_before>'use strict';

(function(module) {

  var uberObject = {};

  uberObject.dataAll = [];

  uberObject.attachEta = function() {
    var uberX = uberObject.dataAll.filter(function(car){
      return car.display_name === 'uberX';
    });
    var eta = uberX[0].estimate;
    console.log('uber eta from attachEta', eta);
    return eta;
  };

  uberObject.getInfo = function(callback, selectionObject) {
    var longitude = selectionObject.lng;
    var latitude = selectionObject.lat;
    var ajaxQuery = {
      url: 'http://localhost:3000/uber/' + latitude + '/' + longitude,
      //url: 'data/uber.json',
      type: 'GET',
      success: function(data, textStatus, jqXHR) {
        //uberObject.dataAll = data.times;

        uberObject.dataAll = data;
        var eta = uberObject.attachEta();

        var etaTransform = etaObject.etaTransform(eta);

        callback(etaObject.context, etaTransform, etaObject.canvas.clientHeight/10, 'uber-logo', etaObject.etaLogos);
      },
      error: function(jqXHR, textStatus, errorThrown) {
        // console.log('What happened?');
        // console.log(jqXHR, textStatus, errorThrown);
      }
    };
    $.ajax(ajaxQuery);
  };

  module.uberObject = uberObject;
  //uberObject.getInfo(etaObject.drawLogo);
})(window);
<commit_msg>uber api calls are working<commit_after>'use strict';

(function(module) {

  var uberObject = {};

  uberObject.dataAll = [];

  uberObject.attachEta = function() {
    var uberX = uberObject.dataAll.times.filter(function(car){
      return car.display_name === 'uberX';
    });
    var eta = uberX[0].estimate;
    console.log('uber eta from attachEta', eta);
    return eta;
  };

  uberObject.getInfo = function(callback, selectionObject) {
    var longitude = selectionObject.lng;
    var latitude = selectionObject.lat;
    var ajaxQuery = {
      url: 'http://localhost:3000/uber/' + latitude + '/' + longitude,
      //url: 'data/uber.json',
      type: 'GET',
      success: function(data, textStatus, jqXHR) {
        //uberObject.dataAll = data.times;

        uberObject.dataAll = data;
        var eta = uberObject.attachEta();

        var etaTransform = etaObject.etaTransform(eta);

        callback(etaObject.context, etaTransform, etaObject.canvas.clientHeight/10, 'uber-logo', etaObject.etaLogos);
      },
      error: function(jqXHR, textStatus, errorThrown) {
        // console.log('What happened?');
        // console.log(jqXHR, textStatus, errorThrown);
      }
    };
    $.ajax(ajaxQuery);
  };

  module.uberObject = uberObject;
  //uberObject.getInfo(etaObject.drawLogo);
})(window);
<|endoftext|>


<commit_before>const Command = require('../Command')

module.exports =
class AnnounceChannelCommand extends Command {
  constructor (client) {
    super(client, {
      name: 'support',
      aliases: ['server'],
      description: 'Posts an invite link to the Official RoVer Discord where you can easily get help.',
    })
  }

  async fn (msg) {
    msg.reply('The invite URL to the Official RoVer Discord is: discord.gg/UgrYcCS');
  }
}
<commit_msg>Fix support permission requirements<commit_after>const Command = require('../Command')

module.exports =
class AnnounceChannelCommand extends Command {
  constructor (client) {
    super(client, {
      name: 'support',
      aliases: ['server'],
      userPermissions: [],
      description: 'Posts an invite link to the Official RoVer Discord where you can easily get help.',
    })
  }

  async fn (msg) {
    msg.reply('The invite URL to the Official RoVer Discord is: discord.gg/UgrYcCS');
  }
}
<|endoftext|>