<commit_before>/* WePay API for Node.js
 * (c)2012 Matt Farmer
 * Release without warranty under the terms of the
 * Apache License. For more details, see the LICENSE
 * file at the root of this project.
*/
var WePay = (function() {
  /**
   * The release number of wepay-node, for internal use.
  **/
  var release = "0.1.0";

  /**
   * The Client ID that uniquely identifies our application.
  **/
  var client_id = null;

  /**
   * The Client Secret we can use to request OAuth access tokens.
  **/
  var client_secret = null;

  /**
   * The current environment that we're using.
  **/
  var environment = null;

  /**
   * The OAuth redirect URI
  **/
  var oauth_redirect_uri = "";

  /**
   * The User Agent that will be displayed for requests to WePay.
  **/
  var user_agent = "wepay-node " + release;

  /**
   * API endpoints bases
  **/
  var endpoints = {
    stage: {
      oauth: "https://stage.wepay.com",
      api: "https://stage.wepayapi.com"
    },
    prod: {
      oauth: "https://wepay.com",
      api: "https://stage.wepayapi.com"
    }
  };

  /**
   * The current API version indicator we're using.
  **/
  var api_version = "v2";

  /**
   * Generate a resource URL based on the desired action.
  **/
  function resourceUrlFor(resource, oauth) {
    if (! environment)
      throw "The environment hasn't been properly specified.";

    var callType = (oauth) ? "oauth" : "api",
        baseUrl = endpoints[environment][callType];

    return baseUrl + "/" + api_version + resource;
  }

  return {
    /**
     * Initilize the WePay connection with all the required
     * parameters to start an OAuth sequence.
    **/
    init: function(init_environment, init_client_id, init_client_secret, init_oauth_redirect_uri) {
      environment = init_environment;
      client_id = init_client_id;
      client_secret = init_client_secret;
      oauth_redirect_uri = init_oauth_redirect_uri;
    },

    /**
     * Generate and return the authorize URL for the user
     * to hit to grant access to the application for the
     * requested permissions.
    **/
    authorizeUrl: function(scope) {
      return resourceUrlFor("/oauth2/authorize", true) + "?client_id=" + client_id
        + "&redirect_uri=" + encodeURIComponent(oauth_redirect_uri)
        + "&scope=" + encodeURIComponent(scope);
    },

    /**
     * Retrieve the access token for the user based on
     * the code provided.
    **/
    retrieveToken: function(code, callback) {
      //TODO
    },

    /**
     * Execute an action against the WePay API.
    **/
    execute: function(action, request_json, access_token) {
      //TODO
    }
  }
})();

modules.exports = WePay
<commit_msg>First pass at WePay API complete with authorizeUrl generation.<commit_after>/* WePay API for Node.js
 * (c)2012 Matt Farmer
 * Release without warranty under the terms of the
 * Apache License. For more details, see the LICENSE
 * file at the root of this project.
*/
var WePay = (function() {
  /**
   * The release number of wepay-node, for internal use.
  **/
  var release = "0.1.0";

  /**
   * The Client ID that uniquely identifies our application.
  **/
  var client_id = null;

  /**
   * The Client Secret we can use to request OAuth access tokens.
  **/
  var client_secret = null;

  /**
   * The current environment that we're using.
  **/
  var environment = null;

  /**
   * The OAuth redirect URI
  **/
  var oauth_redirect_uri = "";

  /**
   * The User Agent that will be displayed for requests to WePay.
  **/
  var user_agent = "wepay-node " + release;

  /**
   * API endpoints bases
  **/
  var endpoints = {
    stage: {
      oauth: "https://stage.wepay.com",
      api: "https://stage.wepayapi.com"
    },
    prod: {
      oauth: "https://wepay.com",
      api: "https://stage.wepayapi.com"
    }
  };

  /**
   * The current API version indicator we're using.
  **/
  var api_version = "v2";

  /**
   * Generate a resource URL based on the desired action.
  **/
  function resourceUrlFor(resource, oauth) {
    if (! environment)
      throw "The environment hasn't been properly specified.";

    var callType = (oauth) ? "oauth" : "api",
        baseUrl = endpoints[environment][callType];

    return baseUrl + "/" + api_version + resource;
  }

  return {
    /**
     * Initilize the WePay connection with all the required
     * parameters to start an OAuth sequence.
    **/
    init: function(init_environment, init_client_id, init_client_secret, init_oauth_redirect_uri) {
      environment = init_environment;
      client_id = init_client_id;
      client_secret = init_client_secret;
      oauth_redirect_uri = init_oauth_redirect_uri;
    },

    /**
     * Generate and return the authorize URL for the user
     * to hit to grant access to the application for the
     * requested permissions.
    **/
    authorizeUrl: function(scope) {
      return resourceUrlFor("/oauth2/authorize", true) + "?client_id=" + client_id
        + "&redirect_uri=" + encodeURIComponent(oauth_redirect_uri)
        + "&scope=" + encodeURIComponent(scope);
    },

    /**
     * Retrieve the access token for the user based on
     * the code provided.
    **/
    retrieveToken: function(code, callback) {
      //TODO
    },

    /**
     * Execute an action against the WePay API.
    **/
    execute: function(action, request_json, access_token) {
      //TODO
    }
  }
})();

module.exports = WePay
<|endoftext|>


<commit_before>var util = require('util');
var events = require('events');
var Bluebird = require('bluebird');

var Reply = require('./reply');
var errors = require('../errors');
var factory = require('./factory');

/**
 * Manages a connect to Beam's chat servers.
 * @access public
 * @param {Array} addresses
 */
function BeamSocket (addresses) {
    events.EventEmitter.call(this);

    // Which connection we use in our load balancing.
    this.addressOffset = Math.floor(Math.random() * addresses.length) - 1;

    // List of addresses we can connect to.
    this.addresses = addresses;

    // Spool to store events queued when the connection is lost.
    this.spool = [];

    // The WebSocket instance we're currently connected with.
    this.ws = null;

    // The status of the socket connection.
    this.status = BeamSocket.IDLE;

    // Number of retries to do before we give up connecting.
    this.retries = 0;
    // Max number of retries to do.
    this.maxRetries = 5;
    // Wait duration between retries.
    this.retryDelay = 500;

    // Map of call IDs to promises that should be resolved on
    // method responses.
    this.replies = {};

    // Authentication packet store that we'll resend if we have to reconnect.
    this.authpacket = null;

    // Counter for method calls.
    this.callNo = 0;
}

util.inherits(BeamSocket, events.EventEmitter);

/**
 * Gets the status of the socket connection.
 * @return {status} Should be compared against BeamSocket.status
 */
BeamSocket.prototype.getStatus = function () {
    return this.status;
};

/**
 * Returns whether the socket is currently connected.
 * @return {Boolean}
 */
BeamSocket.prototype.isConnected = function () {
    return this.status === BeamSocket.CONNECTED;
};

/**
 * Retrieves a chat endpoint to connect to. We use round-robin balancing.
 * @access protected
 * @return {String}
 */
BeamSocket.prototype.getAddress = function () {
    if (++this.addressOffset >= this.addresses.length) {
        this.addressOffset = 0;
    }

    return this.addresses[this.addressOffset];
};

/**
 * Starts a socket client. Attaches events and tries to connect to a
 * chat server.
 * @access public
 * @fires BeamSocket#connected
 * @fires BeamSocket#closed
 * @fires BeamSocket#error
 */
BeamSocket.prototype.boot = function () {
    var self = this;
    var ws = this.ws = factory.create(this.getAddress());

    // Websocket connection has been established.
    ws.on('open', this.unspool.bind(this));

    // We got an incoming data packet.
    ws.on('message', this.parsePacket.bind(this));

    // Websocket connection closed
    ws.on('close', function () {
        self.emit('closed');

        // If we errored, we are already trying to reconnect, don't
        // change the BeamSocket.
        if (self.status !== BeamSocket.CONNECTING) {
            self.status = BeamSocket.CLOSED;
        }

        // Let v8 clean up after itself.
        ws = null;
        self = null;
    });

    // Websocket hit an error and is about to close.
    ws.on('error', function (err) {
        self.emit('error', err);

        // Check to see if we should reconnect.
        if (self.retries++ < self.maxRetries) {
            // Set the status and retry booting after a bit.
            self.status = BeamSocket.CONNECTING;
            setTimeout(self.boot.bind(self), 500);

            // Terminate the socket to make sure it closes.
            ws.terminate();
        } else {
            self.status = ABORTED;
        }
    });

    return this;
};

/**
 * Should be called on reconnection. Authenticates and sends follow-up
 * packets if we have any. After we get re-established with auth
 * we'll formally say this socket is connected. This is to prevent
 * race conditions where packets could get send before authentication
 * is reestablished.
 * @access protected
 */
BeamSocket.prototype.unspool = function () {
    var self = this;

    // If we already authed, it means we're reconnecting and should
    // establish authentication again.
    if (this.authpacket) {
        this.call('auth', this.authpacket, { force: true })
            .then(bang)
            .catch(function () {
                self.emit('error', new errors.AuthenticationFailedError());
                self.close();
            });
    }
    // Otherwise, we can reestablish immedately
    else {
        bang();
    }

    // Helper function that's called when we're fully reestablished and
    // ready to take direct calls again.
    function bang () {
        // Send any spooled events that we have.
        for (var i = 0; i < self.spool.length; i++) {
            self.send(self.spool[i], { force: true });
        }
        self.spool = [];

        // Finally, tell the world we're connected.
        self.status = BeamSocket.CONNECTED;
        self.emit('connected');

        // Clean up for gc
        self = null;
    }
};

/**
 * Parses an incoming packet from the websocket.
 * @access protected
 * @param  {String} data
 * @param  {Object} flags
 * @fires BeamSocket#error
 * @fires BeamSocket#packet
 */
BeamSocket.prototype.parsePacket = function (data, flags) {
    if (flags && flags.binary) {
        // We can't handle binary packets. Why the fudge are we here?
        return this.emit('error', new errors.BadMessageError('Cannot parse binary packets. Wat.'));
    }

    // Unpack the packet data.
    var packet;
    try {
        packet = JSON.parse(data);
    } catch (e) {
        return this.emit('error', new errors.BadMessageError('Unable to parse packet as json'));
    }

    this.emit('packet', packet);

    switch (packet.type) {

        case 'reply':
            // Try to look up the packet reply handler, and call it if we can.
            var reply = this.replies[packet.id];
            if (typeof reply !== 'undefined') {
                reply.handle(packet);
                delete this.replies[packet.id];
            }
            // Otherwise emit an error. This might happen occasionally,
            // but failing silently is lame.
            else {
                this.emit('error', new errors.NoMethodHandlerError('No handler for reply ID.'));
            }

        break;
        case 'event':
            // Just emit events out on this emitter.
            this.emit(packet.event, packet.data);

        break;
        default:
            this.emit('error', new errors.BadMessageError('Unknown packet type ' + packet.type));
    }
};

/**
 * Sends raw packet data to the server. It may not send immediately;
 * if we aren't connected, it'll just be spooled up.
 *
 * @access protected
 * @param  {Object} data
 * @param  {Object} options_
 * @fires BeamSocket#sent
 * @fires BeamSocket#spooled
 */
BeamSocket.prototype.send = function (data, options_) {
    var options = options_ || {};

    if (this.isConnected() || options.force) {
        this.ws.send(JSON.stringify(data));
        this.emit('sent', data);
    } else {
        this.spool.push(data);
        this.emit('spooled', data);
    }
};

/**
 * Runs a method on the socket. Returns a promise that is rejected or
 * resolved upon reply.
 * @access public
 * @param  {String} method
 * @param  {Array=[]} args_ Additional arguments to pass to the method.
 * @param  {Options={}} options_
 * @return {Promise}
 */
BeamSocket.prototype.call = function (method, args_, options_) {
    // Unpack arguments, so that the client can pass both, one, or
    // neither args or options.
    var options = options_, args = args_;
    if (!Array.isArray(args)) {
        options = args;
        args = [];
    }
    options = options || {};

    // Save the arguments to any auth call we get.
    if (method === 'auth') {
        this.authpacket = args;
    }

    // Send out the data
    var id = this.callNo++, self = this;
    this.send({ type: 'method', method: method, arguments: args, id: id }, options);

    // Then create and return a promise that's resolved when we get
    // a reply, if we expect one to be given.
    if (!options.noReply) {
        return new Bluebird(function (resolve, reject) {
            self.replies[id] = new Reply(resolve, reject);
        }).timeout(5000)
          .catch(Bluebird.TimeoutError, function () {
            // After five seconds, if we haven't gotten a reply, remove
            // the method reply. Keeps memory leaks down.
            delete self.replies[id];
          })
          .finally(function () {
            // null to prevent memory leaks
            id = null;
            self = null;
          });
    }
};

/**
 * Closes the existing websocket.
 * @access public
 */
BeamSocket.prototype.close = function () {
    if (this.ws) {
        this.ws.close();
    }
};

/**
 * List of available statuses.
 * @readonly
 * @enum {Number}
 */
[
    /** We've not tried connecting yet */
    'IDLE',
    /** We successfully connected */
    'CONNECTED',
    /** The socket was closed gracefully. */
    'CLOSED',
    /** We're currently trying to connect */
    'CONNECTING',
    /** We tried several times to connect, but were unable to do so. */
    'ABORTED',
].forEach(function (status, i) {
    BeamSocket[status] = i;
});

module.exports = BeamSocket;
<commit_msg>Retries must be reset on successful connection.<commit_after>var util = require('util');
var events = require('events');
var Bluebird = require('bluebird');

var Reply = require('./reply');
var errors = require('../errors');
var factory = require('./factory');

/**
 * Manages a connect to Beam's chat servers.
 * @access public
 * @param {Array} addresses
 */
function BeamSocket (addresses) {
    events.EventEmitter.call(this);

    // Which connection we use in our load balancing.
    this.addressOffset = Math.floor(Math.random() * addresses.length) - 1;

    // List of addresses we can connect to.
    this.addresses = addresses;

    // Spool to store events queued when the connection is lost.
    this.spool = [];

    // The WebSocket instance we're currently connected with.
    this.ws = null;

    // The status of the socket connection.
    this.status = BeamSocket.IDLE;

    // Number of retries to do before we give up connecting.
    this.retries = 0;
    // Max number of retries to do.
    this.maxRetries = 5;
    // Wait duration between retries.
    this.retryDelay = 500;

    // Map of call IDs to promises that should be resolved on
    // method responses.
    this.replies = {};

    // Authentication packet store that we'll resend if we have to reconnect.
    this.authpacket = null;

    // Counter for method calls.
    this.callNo = 0;
}

util.inherits(BeamSocket, events.EventEmitter);

/**
 * Gets the status of the socket connection.
 * @return {status} Should be compared against BeamSocket.status
 */
BeamSocket.prototype.getStatus = function () {
    return this.status;
};

/**
 * Returns whether the socket is currently connected.
 * @return {Boolean}
 */
BeamSocket.prototype.isConnected = function () {
    return this.status === BeamSocket.CONNECTED;
};

/**
 * Retrieves a chat endpoint to connect to. We use round-robin balancing.
 * @access protected
 * @return {String}
 */
BeamSocket.prototype.getAddress = function () {
    if (++this.addressOffset >= this.addresses.length) {
        this.addressOffset = 0;
    }

    return this.addresses[this.addressOffset];
};

/**
 * Starts a socket client. Attaches events and tries to connect to a
 * chat server.
 * @access public
 * @fires BeamSocket#connected
 * @fires BeamSocket#closed
 * @fires BeamSocket#error
 */
BeamSocket.prototype.boot = function () {
    var self = this;
    var ws = this.ws = factory.create(this.getAddress());

    // Websocket connection has been established.
    ws.on('open', this.unspool.bind(this));

    // We got an incoming data packet.
    ws.on('message', this.parsePacket.bind(this));

    // Websocket connection closed
    ws.on('close', function () {
        self.emit('closed');

        // If we errored, we are already trying to reconnect, don't
        // change the BeamSocket.
        if (self.status !== BeamSocket.CONNECTING) {
            self.status = BeamSocket.CLOSED;
        }

        // Let v8 clean up after itself.
        ws = null;
        self = null;
    });

    // Websocket hit an error and is about to close.
    ws.on('error', function (err) {
        self.emit('error', err);

        // Check to see if we should reconnect.
        if (self.retries++ < self.maxRetries) {
            // Set the status and retry booting after a bit.
            self.status = BeamSocket.CONNECTING;
            setTimeout(self.boot.bind(self), 500);

            // Terminate the socket to make sure it closes.
            ws.terminate();
        } else {
            self.status = ABORTED;
        }
    });

    return this;
};

/**
 * Should be called on reconnection. Authenticates and sends follow-up
 * packets if we have any. After we get re-established with auth
 * we'll formally say this socket is connected. This is to prevent
 * race conditions where packets could get send before authentication
 * is reestablished.
 * @access protected
 */
BeamSocket.prototype.unspool = function () {
    var self = this;

    // If we already authed, it means we're reconnecting and should
    // establish authentication again.
    if (this.authpacket) {
        this.call('auth', this.authpacket, { force: true })
            .then(bang)
            .catch(function () {
                self.emit('error', new errors.AuthenticationFailedError());
                self.close();
            });
    }
    // Otherwise, we can reestablish immedately
    else {
        bang();
    }

    // Helper function that's called when we're fully reestablished and
    // ready to take direct calls again.
    function bang () {
        // Send any spooled events that we have.
        for (var i = 0; i < self.spool.length; i++) {
            self.send(self.spool[i], { force: true });
        }
        self.spool = [];

        // Finally, tell the world we're connected.
        self.retries = 0;
        self.status = BeamSocket.CONNECTED;
        self.emit('connected');

        // Clean up for gc
        self = null;
    }
};

/**
 * Parses an incoming packet from the websocket.
 * @access protected
 * @param  {String} data
 * @param  {Object} flags
 * @fires BeamSocket#error
 * @fires BeamSocket#packet
 */
BeamSocket.prototype.parsePacket = function (data, flags) {
    if (flags && flags.binary) {
        // We can't handle binary packets. Why the fudge are we here?
        return this.emit('error', new errors.BadMessageError('Cannot parse binary packets. Wat.'));
    }

    // Unpack the packet data.
    var packet;
    try {
        packet = JSON.parse(data);
    } catch (e) {
        return this.emit('error', new errors.BadMessageError('Unable to parse packet as json'));
    }

    this.emit('packet', packet);

    switch (packet.type) {

        case 'reply':
            // Try to look up the packet reply handler, and call it if we can.
            var reply = this.replies[packet.id];
            if (typeof reply !== 'undefined') {
                reply.handle(packet);
                delete this.replies[packet.id];
            }
            // Otherwise emit an error. This might happen occasionally,
            // but failing silently is lame.
            else {
                this.emit('error', new errors.NoMethodHandlerError('No handler for reply ID.'));
            }

        break;
        case 'event':
            // Just emit events out on this emitter.
            this.emit(packet.event, packet.data);

        break;
        default:
            this.emit('error', new errors.BadMessageError('Unknown packet type ' + packet.type));
    }
};

/**
 * Sends raw packet data to the server. It may not send immediately;
 * if we aren't connected, it'll just be spooled up.
 *
 * @access protected
 * @param  {Object} data
 * @param  {Object} options_
 * @fires BeamSocket#sent
 * @fires BeamSocket#spooled
 */
BeamSocket.prototype.send = function (data, options_) {
    var options = options_ || {};

    if (this.isConnected() || options.force) {
        this.ws.send(JSON.stringify(data));
        this.emit('sent', data);
    } else {
        this.spool.push(data);
        this.emit('spooled', data);
    }
};

/**
 * Runs a method on the socket. Returns a promise that is rejected or
 * resolved upon reply.
 * @access public
 * @param  {String} method
 * @param  {Array=[]} args_ Additional arguments to pass to the method.
 * @param  {Options={}} options_
 * @return {Promise}
 */
BeamSocket.prototype.call = function (method, args_, options_) {
    // Unpack arguments, so that the client can pass both, one, or
    // neither args or options.
    var options = options_, args = args_;
    if (!Array.isArray(args)) {
        options = args;
        args = [];
    }
    options = options || {};

    // Save the arguments to any auth call we get.
    if (method === 'auth') {
        this.authpacket = args;
    }

    // Send out the data
    var id = this.callNo++, self = this;
    this.send({ type: 'method', method: method, arguments: args, id: id }, options);

    // Then create and return a promise that's resolved when we get
    // a reply, if we expect one to be given.
    if (!options.noReply) {
        return new Bluebird(function (resolve, reject) {
            self.replies[id] = new Reply(resolve, reject);
        }).timeout(5000)
          .catch(Bluebird.TimeoutError, function () {
            // After five seconds, if we haven't gotten a reply, remove
            // the method reply. Keeps memory leaks down.
            delete self.replies[id];
          })
          .finally(function () {
            // null to prevent memory leaks
            id = null;
            self = null;
          });
    }
};

/**
 * Closes the existing websocket.
 * @access public
 */
BeamSocket.prototype.close = function () {
    if (this.ws) {
        this.ws.close();
    }
};

/**
 * List of available statuses.
 * @readonly
 * @enum {Number}
 */
[
    /** We've not tried connecting yet */
    'IDLE',
    /** We successfully connected */
    'CONNECTED',
    /** The socket was closed gracefully. */
    'CLOSED',
    /** We're currently trying to connect */
    'CONNECTING',
    /** We tried several times to connect, but were unable to do so. */
    'ABORTED',
].forEach(function (status, i) {
    BeamSocket[status] = i;
});

module.exports = BeamSocket;
<|endoftext|>


<commit_before>//
// Factor related code.
//

var unique = function(x) {
  var set = {}, hasNull = false;
  for (var i = 0; i < x.length; i++) {
    if (x[i] === null) hasNull = true;
    else if (set[x[i]] == null) set[x[i]] = true;
  }
  return hasNull ? Object.keys(set).concat(null) : Object.keys(set);
};

var match = function(x, table, useNull) {
  // Construct map.
  var map = {};
  for (var i = 0; i < table.length; i++) {
    if (table[i] !== null) map[table[i]] = i;
  }
  // Construct results.
  var res = new Array(x.length);
  var nullValue = (useNull ? table.length - 1 : null);
  for (var i = 0; i < x.length; i++) {
    res[i] = (x[i] !== null ? map[x[i]] : nullValue);
  }
  return res;
};

var factor = function(x, useNull) {
  if (isFactor(x)) {
    if (useNull && x.levels[x.levels.length - 1] !== null) {
      var tmp = x.slice(0, x.length);
      tmp.levels = x.levels;
      x = tmp;
      x.levels.push(null);
      for (var i = 0; i < x.length; i++) {
        if (x[i] === null) x[i] = x.levels.length - 1;
      }
    } else if (!useNull && x.levels[x.levels.length - 1] === null) {
      var tmp = x.slice(0, x.length);
      tmp.levels = x.levels;
      x = tmp;
      for (var i = 0; i < x.length; i++) {
        if (x[i] === x.levels.length - 1) x[i] = null;
      }
      x.levels.length - 1;
    }
    return x;
  }
  x = Array.isArray(x) ? x : [x];
  var levels = unique(x);
  if (!useNull && levels[levels.length - 1] === null) levels.length--;
  var f = match(x, levels, useNull);
  f.levels = levels;
  return f;
};

var isFactor = function(o) {
  return (Array.isArray(o) && o.levels != null);
};

var asString = function(f) {
  if (!isFactor(f)) return String(f);

  // Construct map.
  var map = {};
  for (var i = 0; i < f.levels.length; i++) {
    map[i] = f.levels[i];
  }
  // Construct results.
  var res = new Array(f.length);
  for (var i = 0; i < f.length; i++) {
    res[i] = (f[i] !== null ? map[f[i]] : null);
  }
  return res;
};

exports.factor = factor;
exports.isFactor = isFactor;
exports.asString = asString;

//
// Cross tabulation related code.
//

var Table = function(dim, dimnames, array) {
  this.dim = dim;
  this.dimnames = dimnames;
  this.array = array;

  // Indices for level names
  this._levelIndices = new Array(this.dim.length);
  this._levelNullsIndex = new Array(this.dim.length);
  for (var i = 0; i < this.dim.length; i++) {
    this._levelIndices[i] = {};
    this._levelNullsIndex[i] = undefined;
    for (var j = 0; j < this.dimnames[i].names.length; j++) {
      if (this.dimnames[i].names[j] === null) {
        this._levelNullsIndex[i] = j;
      } else {
        this._levelIndices[i][this.dimnames[i].names[j]] = j;
      }
    }
  }

  // Used for calculate offset of indices.
  this._multipliers = new Array(this.dim.length);
  this._multipliers[this._multipliers.length - 1] = 1;
  for (var i = this._multipliers.length - 2; i >= 0; i--) {
    this._multipliers[i] = this._multipliers[i + 1] * this.dim[i + 1];
  }

  Object.defineProperties(this, {
    _levelIndices: {enumerable: false},
    _levelNullsIndex: {enumerable: false},
    _multipliers: {enumerable: false}
  });
};

Table.prototype._offset = function(ind) {
  var val = 0;
  for (var i = 0; i < ind.length; i++) {
    val += ind[i] * this._multipliers[i];
  }
  return val;
};
Object.defineProperty(Table.prototype, "_offset", {enumerable: false});

Table.prototype.get = function() {
  var indices = Array.prototype.slice.call(arguments);
  if (indices.length === 0) return this;

  // Normalize indices.
  for (var i = 0; i < this.dim.length; i++) {
    if (Array.isArray(indices[i])) {
      for (var j = 0; j < indices[i].length; j++) {
        if (typeof indices[i][j] !== "number") {
          // Normalize index to number.
          var ind = (indices[i][j] === null ? this._levelNullsIndex[i] : this._levelIndices[i][indices[i][j]]);
          if (ind === undefined)
            throw new Error("Variable '" + indices[i][j] + "' does not exist.");
          indices[i][j] = ind;
        }
      }
    } else if (indices[i] === undefined) {
      // Normalize undefined to the respective dim indices.
      indices[i] = new Array(this.dim[i]);
      for (var j = 0; j < indices[i].length; j++) {
        indices[i][j] = j;
      }
    } else if (typeof indices[i] !== "number") {
      // Normalize index to number.
      var ind = (indices[i] === null ? this._levelNullsIndex[i] : this._levelIndices[i][indices[i]]);
      if (ind === undefined)
        throw new Error("Variable '" + indices[i] + "' does not exist.");
      indices[i] = [ind];
    } else {
      indices[i] = [indices[i]];
    }
  }

  if (indices.every(function(ind) { return ind.length === 1 })) {
    // Retrieve a singular data.
    return this.array[this._offset(indices)];
  } else {
    // Retrieve as new Table instance.
    var dim = indices
      .map(function(ind) { return ind.length })
      .filter(function(len) { return len > 1 });
    var dimnames = this.dimnames
      .map(function(d, i) {
        return {
          dim: d.dim,
          names: indices[i].map(function(ind) { return d.names[ind] })
        };
      })
      .filter(function(d, i) { return indices[i].length > 1 });
    var array = new Array(dim.reduce(function(x, y) { return x * y }));

    var nextIndex = (function() {
      // Index initialization.
      var pos = new Array(indices.length);
      for (var i = 0; i < pos.length; i++) {
        pos[i] = 0;
      }

      return function(index) {
        var p, ind;

        // Set indices according pos position.
        for (var i = 0; i < index.length; i++) {
          index[i] = indices[i][pos[i]];
        }

        // Increase position.
        for (var i = pos.length - 1; i >= 0; i--) {
          p = pos[i];
          ind = indices[i];
          if (p + 1 < ind.length) {
            pos[i] = p + 1;
            break;
          } else {
            pos[i] = 0;
          }
        }

        return index;
      };
    }());

    var ind = new Array(indices.length);
    for (var i = 0; i < array.length; i++) {
      ind = nextIndex(ind);
      array[i] = this.array[this._offset(ind)];
    }

    return Object.freeze(new Table(dim, dimnames, array));
  }
};

var table = function(x) {
  var useNull, varNames, vars;

  if (typeof arguments[arguments.length - 1] === "boolean") {
    useNull = arguments[arguments.length - 1];
    arguments.length--;
  }

  if (arguments.length <= 1) {
    varNames = [""];
    vars = [factor(x, useNull)];
  } else {
    varNames = Array.prototype.slice.call(arguments, 1, arguments.length);
    vars = new Array(varNames.length);
    for (var i = 0; i < varNames.length; i++) {
      vars[i] = x[varNames[i]];
    }
    if (!vars.every(function(v) { return v.length === vars[0].length }))
      throw new Error("variables must have the same length.");
    for (var i = 0; i < varNames.length; i++) {
      vars[i] = factor(vars[i], useNull);
    }
  }

  var dimnames = new Array(vars.length);
  var dim = new Array(vars.length);
  var index = new Array(vars.length);

  // Assign dimnames and dim according to factor levels.
  for (var i = 0; i < vars.length; i++) {
    dimnames[i] = {
      dim: varNames[i],
      names: vars[i].levels
    };
    dim[i] = vars[i].levels.length;
  }

  var array = new Array(dim.reduce(function(x, y) { return x * y; }));
  // Initialize all counts to zero.
  for (var i = 0; i < array.length; i++) {
    array[i] = 0;
  }

  var t = new Table(dim, dimnames, array);

  // Counts
  next: for (var i = 0; i < vars[0].length; i++) {
    for (var j = 0; j < vars.length; j++) {
      if (vars[j][i] == null) continue next;
      index[j] = vars[j][i];
    }
    array[t._offset(index)]++;
  }

  return Object.freeze(t);
};

exports.table = table;
<commit_msg>Fixed a bug related to factor.<commit_after>//
// Factor related code.
//

var unique = function(x) {
  var set = {}, hasNull = false;
  for (var i = 0; i < x.length; i++) {
    if (x[i] === null) hasNull = true;
    else if (set[x[i]] == null) set[x[i]] = true;
  }
  return hasNull ? Object.keys(set).concat(null) : Object.keys(set);
};

var match = function(x, table, useNull) {
  // Construct map.
  var map = {};
  for (var i = 0; i < table.length; i++) {
    if (table[i] !== null) map[table[i]] = i;
  }
  // Construct results.
  var res = new Array(x.length);
  var nullValue = (useNull ? table.length - 1 : null);
  for (var i = 0; i < x.length; i++) {
    res[i] = (x[i] !== null ? map[x[i]] : nullValue);
  }
  return res;
};

var isFactor = function(o) {
  return (Array.isArray(o) && o.levels != null);
};

var factor = function(x, useNull) {
  if (isFactor(x)) {
    if (useNull && x.levels[x.levels.length - 1] !== null) {
      var tmp = x.slice(0, x.length);
      tmp.levels = x.levels;
      x = tmp;
      x.levels.push(null);
      for (var i = 0; i < x.length; i++) {
        if (x[i] === null) x[i] = x.levels.length - 1;
      }
    } else if (!useNull && x.levels[x.levels.length - 1] === null) {
      var tmp = x.slice(0, x.length);
      tmp.levels = x.levels;
      x = tmp;
      for (var i = 0; i < x.length; i++) {
        if (x[i] === x.levels.length - 1) x[i] = null;
      }
      x.levels.length--;
    }
    return x;
  }
  x = Array.isArray(x) ? x : [x];
  var levels = unique(x);
  if (!useNull && levels[levels.length - 1] === null) levels.length--;
  var f = match(x, levels, useNull);
  f.levels = levels;
  return f;
};

var asString = function(f) {
  if (!isFactor(f)) return String(f);

  // Construct map.
  var map = {};
  for (var i = 0; i < f.levels.length; i++) {
    map[i] = f.levels[i];
  }
  // Construct results.
  var res = new Array(f.length);
  for (var i = 0; i < f.length; i++) {
    res[i] = (f[i] !== null ? map[f[i]] : null);
  }
  return res;
};

exports.factor = factor;
exports.isFactor = isFactor;
exports.asString = asString;

//
// Cross tabulation related code.
//

var Table = function(dim, dimnames, array) {
  this.dim = dim;
  this.dimnames = dimnames;
  this.array = array;

  // Indices for level names
  this._levelIndices = new Array(this.dim.length);
  this._levelNullsIndex = new Array(this.dim.length);
  for (var i = 0; i < this.dim.length; i++) {
    this._levelIndices[i] = {};
    this._levelNullsIndex[i] = undefined;
    for (var j = 0; j < this.dimnames[i].names.length; j++) {
      if (this.dimnames[i].names[j] === null) {
        this._levelNullsIndex[i] = j;
      } else {
        this._levelIndices[i][this.dimnames[i].names[j]] = j;
      }
    }
  }

  // Used for calculate offset of indices.
  this._multipliers = new Array(this.dim.length);
  this._multipliers[this._multipliers.length - 1] = 1;
  for (var i = this._multipliers.length - 2; i >= 0; i--) {
    this._multipliers[i] = this._multipliers[i + 1] * this.dim[i + 1];
  }

  Object.defineProperties(this, {
    _levelIndices: {enumerable: false},
    _levelNullsIndex: {enumerable: false},
    _multipliers: {enumerable: false}
  });
};

Table.prototype._offset = function(ind) {
  var val = 0;
  for (var i = 0; i < ind.length; i++) {
    val += ind[i] * this._multipliers[i];
  }
  return val;
};
Object.defineProperty(Table.prototype, "_offset", {enumerable: false});

Table.prototype.get = function() {
  var indices = Array.prototype.slice.call(arguments);
  if (indices.length === 0) return this;

  // Normalize indices.
  for (var i = 0; i < this.dim.length; i++) {
    if (Array.isArray(indices[i])) {
      for (var j = 0; j < indices[i].length; j++) {
        if (typeof indices[i][j] !== "number") {
          // Normalize index to number.
          var ind = (indices[i][j] === null ? this._levelNullsIndex[i] : this._levelIndices[i][indices[i][j]]);
          if (ind === undefined)
            throw new Error("Variable '" + indices[i][j] + "' does not exist.");
          indices[i][j] = ind;
        }
      }
    } else if (indices[i] === undefined) {
      // Normalize undefined to the respective dim indices.
      indices[i] = new Array(this.dim[i]);
      for (var j = 0; j < indices[i].length; j++) {
        indices[i][j] = j;
      }
    } else if (typeof indices[i] !== "number") {
      // Normalize index to number.
      var ind = (indices[i] === null ? this._levelNullsIndex[i] : this._levelIndices[i][indices[i]]);
      if (ind === undefined)
        throw new Error("Variable '" + indices[i] + "' does not exist.");
      indices[i] = [ind];
    } else {
      indices[i] = [indices[i]];
    }
  }

  if (indices.every(function(ind) { return ind.length === 1 })) {
    // Retrieve a singular data.
    return this.array[this._offset(indices)];
  } else {
    // Retrieve as new Table instance.
    var dim = indices
      .map(function(ind) { return ind.length })
      .filter(function(len) { return len > 1 });
    var dimnames = this.dimnames
      .map(function(d, i) {
        return {
          dim: d.dim,
          names: indices[i].map(function(ind) { return d.names[ind] })
        };
      })
      .filter(function(d, i) { return indices[i].length > 1 });
    var array = new Array(dim.reduce(function(x, y) { return x * y }));

    var nextIndex = (function() {
      // Index initialization.
      var pos = new Array(indices.length);
      for (var i = 0; i < pos.length; i++) {
        pos[i] = 0;
      }

      return function(index) {
        var p, ind;

        // Set indices according pos position.
        for (var i = 0; i < index.length; i++) {
          index[i] = indices[i][pos[i]];
        }

        // Increase position.
        for (var i = pos.length - 1; i >= 0; i--) {
          p = pos[i];
          ind = indices[i];
          if (p + 1 < ind.length) {
            pos[i] = p + 1;
            break;
          } else {
            pos[i] = 0;
          }
        }

        return index;
      };
    }());

    var ind = new Array(indices.length);
    for (var i = 0; i < array.length; i++) {
      ind = nextIndex(ind);
      array[i] = this.array[this._offset(ind)];
    }

    return Object.freeze(new Table(dim, dimnames, array));
  }
};

var table = function(x) {
  var useNull, varNames, vars;

  if (typeof arguments[arguments.length - 1] === "boolean") {
    useNull = arguments[arguments.length - 1];
    arguments.length--;
  }

  if (arguments.length <= 1) {
    varNames = [""];
    vars = [factor(x, useNull)];
  } else {
    varNames = Array.prototype.slice.call(arguments, 1, arguments.length);
    vars = new Array(varNames.length);
    for (var i = 0; i < varNames.length; i++) {
      vars[i] = x[varNames[i]];
    }
    if (!vars.every(function(v) { return v.length === vars[0].length }))
      throw new Error("variables must have the same length.");
    for (var i = 0; i < varNames.length; i++) {
      vars[i] = factor(vars[i], useNull);
    }
  }

  var dimnames = new Array(vars.length);
  var dim = new Array(vars.length);
  var index = new Array(vars.length);

  // Assign dimnames and dim according to factor levels.
  for (var i = 0; i < vars.length; i++) {
    dimnames[i] = {
      dim: varNames[i],
      names: vars[i].levels
    };
    dim[i] = vars[i].levels.length;
  }

  var array = new Array(dim.reduce(function(x, y) { return x * y; }));
  // Initialize all counts to zero.
  for (var i = 0; i < array.length; i++) {
    array[i] = 0;
  }

  var t = new Table(dim, dimnames, array);

  // Counts
  next: for (var i = 0; i < vars[0].length; i++) {
    for (var j = 0; j < vars.length; j++) {
      if (vars[j][i] == null) continue next;
      index[j] = vars[j][i];
    }
    array[t._offset(index)]++;
  }

  return Object.freeze(t);
};

exports.table = table;
<|endoftext|>


<commit_before>import { Model, initModel } from "./model"
import { cast, checkDefinition, checkAssertions } from "./definition"
import { is, isString, isFunction, isObject, isPlainObject, merge, setConstructorProto, toString } from "./helpers"

export default function ObjectModel(def){
	const model = function(obj = model.default) {
		if(!is(model, this)) return new model(obj)
		if(is(model, obj)) return obj
		merge(this, obj, true)
		if(model.hasOwnProperty("constructor")){
			model.constructor.call(this, obj)
		}
		model.validate(this)
		return getProxy(model, this, model.definition)
	}

	setConstructorProto(model, Object.prototype)
	initModel(model, arguments, ObjectModel)
	return model
}

setConstructorProto(ObjectModel, Model.prototype)

Object.assign(ObjectModel.prototype, {

	defaults(p){
		Object.assign(this.prototype, p)
		return this
	},

	toString(stack){
		return toString(this.definition, stack)
	},

	extend(){
		const def = {}
		const proto = {}
		const args = [...arguments]

		Object.assign(def, this.definition)
		merge(proto, this.prototype, false, true)
		args.forEach(arg => {
			if(is(Model, arg)) merge(def, arg.definition, true)
			if(isFunction(arg)) merge(proto, arg.prototype, true, true)
			if(isObject(arg)) merge(def, arg, true, true)
		})
		delete proto.constructor;

		let assertions = [...this.assertions]
		args.forEach(arg => {
			if(is(Model, arg)) assertions = assertions.concat(arg.assertions)
		})

		const submodel = new this.constructor(def)
		setConstructorProto(submodel, this.prototype)
		Object.assign(submodel.prototype, proto)
		submodel.assertions = assertions
		submodel.errorCollector = this.errorCollector
		return submodel
	},

	_validate(obj, path, errorStack, callStack){
		if(!isObject(obj)){
			errorStack.push({
				expected: this,
				received: obj,
				path
			})
		} else {
			checkDefinition(obj, this.definition, path, errorStack, callStack)
		}
		checkAssertions(obj, this, path, errorStack)
	}
})

function getProxy(model, obj, def, path) {
	if(!isPlainObject(def)) {
		return cast(obj, def)
	}

	return new Proxy(obj || {}, {
		getPrototypeOf(){
			if (def === model.definition)
				return model.prototype

			return Object.prototype
		},

		get(o, key) {
			if(!isString(key)) return Reflect.get(o, key)

			const newPath = (path ? path + '.' + key : key),
			      defPart = def[key];

			if(key in def && model.conventionForPrivate(key)){
				model.errorStack.push({
					message: `cannot access to private property ${newPath}`
				})
				model.unstackErrors()
				return
			}

			if(o[key] && o.hasOwnProperty(key) && !isPlainObject(defPart) && !is(Model, o[key].constructor)){
				o[key] = cast(o[key], defPart) // cast nested models
			}

			if (isFunction(o[key]) && o[key].bind) {
				return o[key].bind(o); // auto-bind methods to original object, so they can access private props
			}

			return getProxy(model, o[key], defPart, newPath)
		},

		set(o, key, val) {
			return controlMutation(model, def, path, o, key, (newPath) => {
				Reflect.set(o, key, getProxy(model, val, def[key], newPath))
			})
		},

		deleteProperty(o, key) {
			return controlMutation(model, def, path, o, key, () => Reflect.deleteProperty(o, key))
		},

		defineProperty(o, key, args){
			return controlMutation(model, def, path, o, key, () => Reflect.defineProperty(o, key, args))
		},

		has(o, key){
			return Reflect.has(o, key) && Reflect.has(def, key) && !model.conventionForPrivate(key)
		},

		ownKeys(){
			return Reflect.ownKeys(def).filter(key => !model.conventionForPrivate(key))
		},

		getOwnPropertyDescriptor(o, key){
			let descriptor;
			if(!model.conventionForPrivate(key)){
				descriptor = Object.getOwnPropertyDescriptor(def, key);
				if(descriptor !== undefined) descriptor.value = o[key];
			}

			return descriptor
		}
	})
}

function controlMutation(model, def, path, o, key, applyMutation){
	const newPath = (path ? path + '.' + key : key),
	      isPrivate = model.conventionForPrivate(key),
	      isConstant = model.conventionForConstant(key),
	      isOwnProperty = o.hasOwnProperty(key),
	      initialPropDescriptor = isOwnProperty && Object.getOwnPropertyDescriptor(o, key)

	if(key in def && (isPrivate || (isConstant && o[key] !== undefined))){
		model.errorStack.push({
			message: `cannot modify ${isPrivate ? "private" : "constant"} ${key}`
		})
	}

	if(def.hasOwnProperty(key)){
		applyMutation(newPath)
		checkDefinition(o[key], def[key], newPath, model.errorStack, [])
		checkAssertions(o, model, newPath)
	} else {
		model.errorStack.push({
			message: `cannot find property ${newPath} in the model definition`
		})
	}

	if(model.errorStack.length){
		if(isOwnProperty) Object.defineProperty(o, key, initialPropDescriptor)
		else delete o[key] // back to the initial property defined in prototype chain

		model.unstackErrors()
		return false
	}

	return true
}<commit_msg>simplify getProto test for object models<commit_after>import { Model, initModel } from "./model"
import { cast, checkDefinition, checkAssertions } from "./definition"
import { is, isString, isFunction, isObject, isPlainObject, merge, setConstructorProto, toString } from "./helpers"

export default function ObjectModel(def){
	const model = function(obj = model.default) {
		if(!is(model, this)) return new model(obj)
		if(is(model, obj)) return obj
		merge(this, obj, true)
		if(model.hasOwnProperty("constructor")){
			model.constructor.call(this, obj)
		}
		model.validate(this)
		return getProxy(model, this, model.definition)
	}

	setConstructorProto(model, Object.prototype)
	initModel(model, arguments, ObjectModel)
	return model
}

setConstructorProto(ObjectModel, Model.prototype)

Object.assign(ObjectModel.prototype, {

	defaults(p){
		Object.assign(this.prototype, p)
		return this
	},

	toString(stack){
		return toString(this.definition, stack)
	},

	extend(){
		const def = {}
		const proto = {}
		const args = [...arguments]

		Object.assign(def, this.definition)
		merge(proto, this.prototype, false, true)
		args.forEach(arg => {
			if(is(Model, arg)) merge(def, arg.definition, true)
			if(isFunction(arg)) merge(proto, arg.prototype, true, true)
			if(isObject(arg)) merge(def, arg, true, true)
		})
		delete proto.constructor;

		let assertions = [...this.assertions]
		args.forEach(arg => {
			if(is(Model, arg)) assertions = assertions.concat(arg.assertions)
		})

		const submodel = new this.constructor(def)
		setConstructorProto(submodel, this.prototype)
		Object.assign(submodel.prototype, proto)
		submodel.assertions = assertions
		submodel.errorCollector = this.errorCollector
		return submodel
	},

	_validate(obj, path, errorStack, callStack){
		if(!isObject(obj)){
			errorStack.push({
				expected: this,
				received: obj,
				path
			})
		} else {
			checkDefinition(obj, this.definition, path, errorStack, callStack)
		}
		checkAssertions(obj, this, path, errorStack)
	}
})

function getProxy(model, obj, def, path) {
	if(!isPlainObject(def)) {
		return cast(obj, def)
	}

	return new Proxy(obj || {}, {
		getPrototypeOf(){
			return path ? Object.prototype : model.prototype
		},

		get(o, key) {
			if(!isString(key)) return Reflect.get(o, key)

			const newPath = (path ? path + '.' + key : key),
			      defPart = def[key];

			if(key in def && model.conventionForPrivate(key)){
				model.errorStack.push({
					message: `cannot access to private property ${newPath}`
				})
				model.unstackErrors()
				return
			}

			if(o[key] && o.hasOwnProperty(key) && !isPlainObject(defPart) && !is(Model, o[key].constructor)){
				o[key] = cast(o[key], defPart) // cast nested models
			}

			if (isFunction(o[key]) && o[key].bind) {
				return o[key].bind(o); // auto-bind methods to original object, so they can access private props
			}

			return getProxy(model, o[key], defPart, newPath)
		},

		set(o, key, val) {
			return controlMutation(model, def, path, o, key, (newPath) => {
				Reflect.set(o, key, getProxy(model, val, def[key], newPath))
			})
		},

		deleteProperty(o, key) {
			return controlMutation(model, def, path, o, key, () => Reflect.deleteProperty(o, key))
		},

		defineProperty(o, key, args){
			return controlMutation(model, def, path, o, key, () => Reflect.defineProperty(o, key, args))
		},

		has(o, key){
			return Reflect.has(o, key) && Reflect.has(def, key) && !model.conventionForPrivate(key)
		},

		ownKeys(){
			return Reflect.ownKeys(def).filter(key => !model.conventionForPrivate(key))
		},

		getOwnPropertyDescriptor(o, key){
			let descriptor;
			if(!model.conventionForPrivate(key)){
				descriptor = Object.getOwnPropertyDescriptor(def, key);
				if(descriptor !== undefined) descriptor.value = o[key];
			}

			return descriptor
		}
	})
}

function controlMutation(model, def, path, o, key, applyMutation){
	const newPath = (path ? path + '.' + key : key),
	      isPrivate = model.conventionForPrivate(key),
	      isConstant = model.conventionForConstant(key),
	      isOwnProperty = o.hasOwnProperty(key),
	      initialPropDescriptor = isOwnProperty && Object.getOwnPropertyDescriptor(o, key)

	if(key in def && (isPrivate || (isConstant && o[key] !== undefined))){
		model.errorStack.push({
			message: `cannot modify ${isPrivate ? "private" : "constant"} ${key}`
		})
	}

	if(def.hasOwnProperty(key)){
		applyMutation(newPath)
		checkDefinition(o[key], def[key], newPath, model.errorStack, [])
		checkAssertions(o, model, newPath)
	} else {
		model.errorStack.push({
			message: `cannot find property ${newPath} in the model definition`
		})
	}

	if(model.errorStack.length){
		if(isOwnProperty) Object.defineProperty(o, key, initialPropDescriptor)
		else delete o[key] // back to the initial property defined in prototype chain

		model.unstackErrors()
		return false
	}

	return true
}<|endoftext|>


<commit_before>// FIXME works for View2D only

goog.provide('ol.animation');

goog.require('ol.PreRenderFunction');
goog.require('ol.ViewHint');
goog.require('ol.easing');

/**
 * @param {ol.animation.BounceOptions} options Options.
 * @return {ol.PreRenderFunction} Pre-render function.
 */
ol.animation.bounce = function(options) {
  var resolution = options.resolution;
  var start = goog.isDef(options.start) ? options.start : goog.now();
  var duration = goog.isDef(options.duration) ? options.duration : 1000;
  var easing = goog.isDef(options.easing) ?
      options.easing : ol.easing.upAndDown;
  return function(map, frameState) {
    if (frameState.time < start) {
      frameState.animate = true;
      frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
      return true;
    } else if (frameState.time < start + duration) {
      var delta = easing((frameState.time - start) / duration);
      var deltaResolution = resolution - frameState.view2DState.resolution;
      frameState.animate = true;
      frameState.view2DState.resolution += delta * deltaResolution;
      frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
      return true;
    } else {
      return false;
    }
  };
};

/**
 * @param {ol.animation.PanOptions} options Options.
 * @return {ol.PreRenderFunction} Pre-render function.
 */
ol.animation.pan = function(options) {
  var source = options.source;
  var start = goog.isDef(options.start) ? options.start : goog.now();
  var sourceX = source.x;
  var sourceY = source.y;
  var duration = goog.isDef(options.duration) ? options.duration : 1000;
  var easing = goog.isDef(options.easing) ?
      options.easing : ol.easing.inAndOut;
  return function(map, frameState) {
    if (frameState.time < start) {
      frameState.animate = true;
      frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
      return true;
    } else if (frameState.time < start + duration) {
      var delta = 1 - easing((frameState.time - start) / duration);
      var deltaX = sourceX - frameState.view2DState.center.x;
      var deltaY = sourceY - frameState.view2DState.center.y;
      frameState.animate = true;
      frameState.view2DState.center.x += delta * deltaX;
      frameState.view2DState.center.y += delta * deltaY;
      frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
      return true;
    } else {
      return false;
    }
  };
};

/**
 * @param {ol.animation.RotateOptions} options Options.
 * @return {ol.PreRenderFunction} Pre-render function.
 */
ol.animation.rotate = function(options) {
  var sourceRotation = options.rotation;
  var start = goog.isDef(options.start) ? options.start : goog.now();
  var duration = goog.isDef(options.duration) ? options.duration : 1000;
  var easing = goog.isDef(options.easing) ?
      options.easing : ol.easing.inAndOut;

  return function(map, frameState) {
    if (frameState.time < start) {
      frameState.animate = true;
      frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
      return true;
    } else if (frameState.time < start + duration) {
      var delta = 1 - easing((frameState.time - start) / duration);
      var deltaRotation =
          sourceRotation - frameState.view2DState.rotation;
      frameState.animate = true;
      frameState.view2DState.rotation += delta * deltaRotation;
      frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
      return true;
    } else {
      return false;
    }
  };
};

/**
 * @param {ol.animation.ZoomOptions} options Options.
 * @return {ol.PreRenderFunction} Pre-render function.
 */
ol.animation.zoom = function(options) {
  var sourceResolution = options.resolution;
  var start = goog.isDef(options.start) ? options.start : goog.now();
  var duration = goog.isDef(options.duration) ? options.duration : 1000;
  var easing = goog.isDef(options.easing) ?
      options.easing : ol.easing.linear;
  return function(map, frameState) {
    if (frameState.time < start) {
      frameState.animate = true;
      frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
      return true;
    } else if (frameState.time < start + duration) {
      var delta = 1 - easing((frameState.time - start) / duration);
      var deltaResolution =
          sourceResolution - frameState.view2DState.resolution;
      frameState.animate = true;
      frameState.view2DState.resolution += delta * deltaResolution;
      frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
      return true;
    } else {
      return false;
    }
  };
};
<commit_msg>Default to easing inAndOut for all animations<commit_after>// FIXME works for View2D only

goog.provide('ol.animation');

goog.require('ol.PreRenderFunction');
goog.require('ol.ViewHint');
goog.require('ol.easing');

/**
 * @param {ol.animation.BounceOptions} options Options.
 * @return {ol.PreRenderFunction} Pre-render function.
 */
ol.animation.bounce = function(options) {
  var resolution = options.resolution;
  var start = goog.isDef(options.start) ? options.start : goog.now();
  var duration = goog.isDef(options.duration) ? options.duration : 1000;
  var easing = goog.isDef(options.easing) ?
      options.easing : ol.easing.upAndDown;
  return function(map, frameState) {
    if (frameState.time < start) {
      frameState.animate = true;
      frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
      return true;
    } else if (frameState.time < start + duration) {
      var delta = easing((frameState.time - start) / duration);
      var deltaResolution = resolution - frameState.view2DState.resolution;
      frameState.animate = true;
      frameState.view2DState.resolution += delta * deltaResolution;
      frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
      return true;
    } else {
      return false;
    }
  };
};

/**
 * @param {ol.animation.PanOptions} options Options.
 * @return {ol.PreRenderFunction} Pre-render function.
 */
ol.animation.pan = function(options) {
  var source = options.source;
  var start = goog.isDef(options.start) ? options.start : goog.now();
  var sourceX = source.x;
  var sourceY = source.y;
  var duration = goog.isDef(options.duration) ? options.duration : 1000;
  var easing = goog.isDef(options.easing) ?
      options.easing : ol.easing.inAndOut;
  return function(map, frameState) {
    if (frameState.time < start) {
      frameState.animate = true;
      frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
      return true;
    } else if (frameState.time < start + duration) {
      var delta = 1 - easing((frameState.time - start) / duration);
      var deltaX = sourceX - frameState.view2DState.center.x;
      var deltaY = sourceY - frameState.view2DState.center.y;
      frameState.animate = true;
      frameState.view2DState.center.x += delta * deltaX;
      frameState.view2DState.center.y += delta * deltaY;
      frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
      return true;
    } else {
      return false;
    }
  };
};

/**
 * @param {ol.animation.RotateOptions} options Options.
 * @return {ol.PreRenderFunction} Pre-render function.
 */
ol.animation.rotate = function(options) {
  var sourceRotation = options.rotation;
  var start = goog.isDef(options.start) ? options.start : goog.now();
  var duration = goog.isDef(options.duration) ? options.duration : 1000;
  var easing = goog.isDef(options.easing) ?
      options.easing : ol.easing.inAndOut;

  return function(map, frameState) {
    if (frameState.time < start) {
      frameState.animate = true;
      frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
      return true;
    } else if (frameState.time < start + duration) {
      var delta = 1 - easing((frameState.time - start) / duration);
      var deltaRotation =
          sourceRotation - frameState.view2DState.rotation;
      frameState.animate = true;
      frameState.view2DState.rotation += delta * deltaRotation;
      frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
      return true;
    } else {
      return false;
    }
  };
};

/**
 * @param {ol.animation.ZoomOptions} options Options.
 * @return {ol.PreRenderFunction} Pre-render function.
 */
ol.animation.zoom = function(options) {
  var sourceResolution = options.resolution;
  var start = goog.isDef(options.start) ? options.start : goog.now();
  var duration = goog.isDef(options.duration) ? options.duration : 1000;
  var easing = goog.isDef(options.easing) ?
      options.easing : ol.easing.inAndOut;
  return function(map, frameState) {
    if (frameState.time < start) {
      frameState.animate = true;
      frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
      return true;
    } else if (frameState.time < start + duration) {
      var delta = 1 - easing((frameState.time - start) / duration);
      var deltaResolution =
          sourceResolution - frameState.view2DState.resolution;
      frameState.animate = true;
      frameState.view2DState.resolution += delta * deltaResolution;
      frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
      return true;
    } else {
      return false;
    }
  };
};
<|endoftext|>


<commit_before>goog.provide('ol.dom.Input');
goog.provide('ol.dom.InputProperty');

goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('ol.Object');

/**
 * @enum {string}
 */
ol.dom.InputProperty = {
  VALUE: 'value',
  CHECKED: 'checked'
};

/**
 * Helper class for binding HTML input to an {@link ol.Object}.
 *
 * Example:
 *
 *     // bind a checkbox with id 'visible' to a layer's visibility
 *     var visible = new ol.dom.Input(document.getElementById('visible'));
 *     visible.bindTo('checked', layer, 'visible');
 *
 * @constructor
 * @extends {ol.Object}
 * @param {Element} target Target element.
 * @todo stability experimental
 * @todo observable value {string} the value of the Input
 * @todo observable checked {boolean} the checked state of the Input
 */
ol.dom.Input = function(target) {
  goog.base(this);

  /**
   * @private
   * @type {Element}
   */
  this.target_ = target;

  goog.events.listen(this.target_, goog.events.EventType.CHANGE,
      this.handleInputChanged_, false, this);

  goog.events.listen(this,
      ol.Object.getChangeEventType(ol.dom.InputProperty.VALUE),
      this.handleValueChanged_, false, this);
  goog.events.listen(this,
      ol.Object.getChangeEventType(ol.dom.InputProperty.CHECKED),
      this.handleCheckedChanged_, false, this);
};
goog.inherits(ol.dom.Input, ol.Object);

/**
 * If the input is a checkbox, return whether or not the checbox is checked.
 * @return {boolean|undefined} checked.
 * @todo stability experimental
 */
ol.dom.Input.prototype.getChecked = function() {
  return /** @type {boolean} */ (this.get(ol.dom.InputProperty.CHECKED));
};
goog.exportProperty(
    ol.dom.Input.prototype,
    'getChecked',
    ol.dom.Input.prototype.getChecked);

/**
 * Get the value of the input.
 * @return {string|undefined} input value.
 * @todo stability experimental
 */
ol.dom.Input.prototype.getValue = function() {
  return /** @type {string} */ (this.get(ol.dom.InputProperty.VALUE));
};
goog.exportProperty(
    ol.dom.Input.prototype,
    'getValue',
    ol.dom.Input.prototype.getValue);

/**
 * Sets the value of the input.
 * @param {string} value Value.
 * @todo stability experimental
 */
ol.dom.Input.prototype.setValue = function(value) {
  this.set(ol.dom.InputProperty.VALUE, value);
};
goog.exportProperty(
    ol.dom.Input.prototype,
    'setValue',
    ol.dom.Input.prototype.setValue);

/**
 * Set whether or not a checkbox is checked.
 * @param {boolean} checked Checked.
 * @todo stability experimental
 */
ol.dom.Input.prototype.setChecked = function(checked) {
  this.set(ol.dom.InputProperty.CHECKED, checked);
};
goog.exportProperty(
    ol.dom.Input.prototype,
    'setChecked',
    ol.dom.Input.prototype.setChecked);

/**
 * @private
 */
ol.dom.Input.prototype.handleInputChanged_ = function() {
  var target = this.target_;
  if (target.type === 'checkbox' || target.type === 'radio') {
    this.setChecked(target.checked);
  } else {
    this.setValue(target.value);
  }
};

/**
 * @private
 */
ol.dom.Input.prototype.handleCheckedChanged_ = function() {
  this.target_.checked = this.getChecked();
};

/**
 * @private
 */
ol.dom.Input.prototype.handleValueChanged_ = function() {
  this.target_.value = this.getValue();
};
<commit_msg>Change ol.dom.Input target param from Element to HTMLInputElement<commit_after>goog.provide('ol.dom.Input');
goog.provide('ol.dom.InputProperty');

goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('ol.Object');

/**
 * @enum {string}
 */
ol.dom.InputProperty = {
  VALUE: 'value',
  CHECKED: 'checked'
};

/**
 * Helper class for binding HTML input to an {@link ol.Object}.
 *
 * Example:
 *
 *     // bind a checkbox with id 'visible' to a layer's visibility
 *     var visible = new ol.dom.Input(document.getElementById('visible'));
 *     visible.bindTo('checked', layer, 'visible');
 *
 * @constructor
 * @extends {ol.Object}
 * @param {Element} target Target element.
 * @todo stability experimental
 * @todo observable value {string} the value of the Input
 * @todo observable checked {boolean} the checked state of the Input
 */
ol.dom.Input = function(target) {
  goog.base(this);

  /**
   * @private
   * @type {HTMLInputElement}
   */
  this.target_ = /** @type {HTMLInputElement} */ (target);

  goog.events.listen(this.target_, goog.events.EventType.CHANGE,
      this.handleInputChanged_, false, this);

  goog.events.listen(this,
      ol.Object.getChangeEventType(ol.dom.InputProperty.VALUE),
      this.handleValueChanged_, false, this);
  goog.events.listen(this,
      ol.Object.getChangeEventType(ol.dom.InputProperty.CHECKED),
      this.handleCheckedChanged_, false, this);
};
goog.inherits(ol.dom.Input, ol.Object);

/**
 * If the input is a checkbox, return whether or not the checbox is checked.
 * @return {boolean|undefined} checked.
 * @todo stability experimental
 */
ol.dom.Input.prototype.getChecked = function() {
  return /** @type {boolean} */ (this.get(ol.dom.InputProperty.CHECKED));
};
goog.exportProperty(
    ol.dom.Input.prototype,
    'getChecked',
    ol.dom.Input.prototype.getChecked);

/**
 * Get the value of the input.
 * @return {string|undefined} input value.
 * @todo stability experimental
 */
ol.dom.Input.prototype.getValue = function() {
  return /** @type {string} */ (this.get(ol.dom.InputProperty.VALUE));
};
goog.exportProperty(
    ol.dom.Input.prototype,
    'getValue',
    ol.dom.Input.prototype.getValue);

/**
 * Sets the value of the input.
 * @param {string} value Value.
 * @todo stability experimental
 */
ol.dom.Input.prototype.setValue = function(value) {
  this.set(ol.dom.InputProperty.VALUE, value);
};
goog.exportProperty(
    ol.dom.Input.prototype,
    'setValue',
    ol.dom.Input.prototype.setValue);

/**
 * Set whether or not a checkbox is checked.
 * @param {boolean} checked Checked.
 * @todo stability experimental
 */
ol.dom.Input.prototype.setChecked = function(checked) {
  this.set(ol.dom.InputProperty.CHECKED, checked);
};
goog.exportProperty(
    ol.dom.Input.prototype,
    'setChecked',
    ol.dom.Input.prototype.setChecked);

/**
 * @private
 */
ol.dom.Input.prototype.handleInputChanged_ = function() {
  var target = this.target_;
  if (target.type === 'checkbox' || target.type === 'radio') {
    this.setChecked(target.checked);
  } else {
    this.setValue(target.value);
  }
};

/**
 * @private
 */
ol.dom.Input.prototype.handleCheckedChanged_ = function() {
  this.target_.checked = /** @type {boolean} */ (this.getChecked());
};

/**
 * @private
 */
ol.dom.Input.prototype.handleValueChanged_ = function() {
  this.target_.value =  /** @type {string} */ (this.getValue());
};
<|endoftext|>


<commit_before>/**
 * Set up imports that are required at this level for the application
 */
const restify = require("restify");
const corsMiddleware = require("restify-cors-middleware");
const fs = require("fs");
const os = require("os");
const path = require("path");

/**
 * Set up imports from local files
 */
const log = require("./utils/logger.js");
const logName = "Lifeforce";

// Set the app name and some other helpful variables
const tempdir = os.tmpdir();
const pluginpath = "./plugins/";

// This variable will contain settings and api keys that are not public
log.info("Loading settings from config.json...", logName);
const settings = require("./config.json");

log.info("loading enabled list from enabled.json", logName);
const enabledPlugins = require("./enabled.json");

log.info("Creating Restify Server...", logName);
const server = restify.createServer({
  name: "api.repkam09.com",
  version: "1.1.0"
});

const cors = corsMiddleware({
  origins: [
    "https://repkam09.com",
    "http://localhost:8080",
    "http://localhost:8000",
    "http://localhost",
    "https://demo.kaspe.net",
    "http://localhost:3000"
  ],
  allowHeaders: ["cache-control", "repka-repcast-token", "repka-verify"]
});

server.pre(cors.preflight);
server.use(cors.actual);
server.use(restify.plugins.authorizationParser());
server.use(
  restify.plugins.bodyParser({
    mapParams: true,
    mapFiles: true,
    overrideParams: true,
    keepExtensions: true,
    uploadDir: tempdir,
    multiples: true,
    hash: "md5"
  })
);

/**
 * Quick function to log incoming requests
 */
server.use(function logging(req, res, next) {
  let clientip = "unknown";
  if (req.headers["x-forwarded-for"]) {
    clientip = req.headers["x-forwarded-for"];
  } else if (req.connection.remoteAddress) {
    clientip = req.connection.remoteAddress;
  }

  const user = { method: req.method, endpoint: req.url, ip: clientip };
  log.info(">>> " + JSON.stringify(user) + " <<<", logName);
  return next();
});

const endpoints = [];
server.updateAbout = (entry) => {
  endpoints.push(entry);
}

server.getAbout = () => {
  return endpoints;
}

// Go out and check the plugins list for endpoints to listen on
const pluginList = [];
fs.readdir(pluginpath, (err, files) => {
  files.forEach(file => {
    fs.stat(pluginpath + "/" + file, (err, stats) => {
      if (!stats.isDirectory()) {
        let type = path.extname(file);
        if (type === ".js") {
          // Load the plugin and check if it is enabled
          const plugin = require(pluginpath + "/" + file);
          let status = enabledPlugins[plugin.name];
          if (!status) {
            log.debug(
              "Skipping " +
              plugin.name +
              " plugin because it does not have an entry in config",
              logName
            );
          } else {
            if (status && status.enabled) {
              // Call the plugins start method to attach the various get/post/etc
              let temp = new plugin(server, log, plugin.name);

              // Attach the handlers to restify
              temp.addHandlers();

              // Add this plugin to the list of plugins
              pluginList.push(temp);
            } else {
              log.debug(
                "Skipping " + plugin.name + " plugin because it is disabled",
                logName
              );
            }
          }
        }
      }
    });
  });
});

// Startup the server
log.info("Starting Restify Server...", logName);
server.listen(16001, () => {
  log.info(server.name + " listening at " + server.url, logName);
});
<commit_msg>Fix the max parameter length<commit_after>/**
 * Set up imports that are required at this level for the application
 */
const restify = require("restify");
const corsMiddleware = require("restify-cors-middleware");
const fs = require("fs");
const os = require("os");
const path = require("path");

/**
 * Set up imports from local files
 */
const log = require("./utils/logger.js");
const logName = "Lifeforce";

// Set the app name and some other helpful variables
const tempdir = os.tmpdir();
const pluginpath = "./plugins/";

// This variable will contain settings and api keys that are not public
log.info("Loading settings from config.json...", logName);
const settings = require("./config.json");

log.info("loading enabled list from enabled.json", logName);
const enabledPlugins = require("./enabled.json");

log.info("Creating Restify Server...", logName);
const server = restify.createServer({
  name: "api.repkam09.com",
  version: "1.1.0",
  maxParamLength: 1000
});

const cors = corsMiddleware({
  origins: [
    "https://repkam09.com",
    "http://localhost:8080",
    "http://localhost:8000",
    "http://localhost",
    "https://demo.kaspe.net",
    "http://localhost:3000"
  ],
  allowHeaders: ["cache-control", "repka-repcast-token", "repka-verify"]
});

server.pre(cors.preflight);
server.use(cors.actual);
server.use(restify.plugins.authorizationParser());
server.use(
  restify.plugins.bodyParser({
    mapParams: true,
    mapFiles: true,
    overrideParams: true,
    keepExtensions: true,
    uploadDir: tempdir,
    multiples: true,
    hash: "md5"
  })
);

/**
 * Quick function to log incoming requests
 */
server.pre(function logging(req, res, next) {
  let clientip = "unknown";
  if (req.headers["x-forwarded-for"]) {
    clientip = req.headers["x-forwarded-for"];
  } else if (req.connection.remoteAddress) {
    clientip = req.connection.remoteAddress;
  }

  const user = { method: req.method, endpoint: req.url, ip: clientip };
  log.info(">>> " + JSON.stringify(user) + " <<<", logName);
  return next();
});

const endpoints = [];
server.updateAbout = (entry) => {
  endpoints.push(entry);
}

server.getAbout = () => {
  return endpoints;
}

// Go out and check the plugins list for endpoints to listen on
const pluginList = [];
fs.readdir(pluginpath, (err, files) => {
  files.forEach(file => {
    fs.stat(pluginpath + "/" + file, (err, stats) => {
      if (!stats.isDirectory()) {
        let type = path.extname(file);
        if (type === ".js") {
          // Load the plugin and check if it is enabled
          const plugin = require(pluginpath + "/" + file);
          let status = enabledPlugins[plugin.name];
          if (!status) {
            log.debug(
              "Skipping " +
              plugin.name +
              " plugin because it does not have an entry in config",
              logName
            );
          } else {
            if (status && status.enabled) {
              // Call the plugins start method to attach the various get/post/etc
              let temp = new plugin(server, log, plugin.name);

              // Attach the handlers to restify
              temp.addHandlers();

              // Add this plugin to the list of plugins
              pluginList.push(temp);
            } else {
              log.debug(
                "Skipping " + plugin.name + " plugin because it is disabled",
                logName
              );
            }
          }
        }
      }
    });
  });
});

// Startup the server
log.info("Starting Restify Server...", logName);
server.listen(16001, () => {
  log.info(server.name + " listening at " + server.url, logName);
});
<|endoftext|>


<commit_before>import Client from '../../client.js';
import { enterJob } from '../../../utils/buildmessage.js';
import { ensureDependencies } from '../../../cli/dev-bundle-helpers.js';

const NPM_DEPENDENCIES = {
  puppeteer: '1.3.0'
};

export default class PuppeteerClient extends Client {
  constructor(options) {
    super(options);

    enterJob(
      {
        title: 'Installing Puppeteer in Meteor tool'
      },
      () => {
        ensureDependencies(NPM_DEPENDENCIES);
      }
    );

    this.npmPackageExports = require('puppeteer');

    this.name = 'Puppeteer';
  }

  async connect() {
    // Note for Travis and CircleCI to run sandbox must be turned off.
    // From a security perspective this is not ideal, in the future would be worthwhile
    // to configure to include only for CI based setups
    this.browser = await this.npmPackageExports.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] });
    this.page = await this.browser.newPage();
    this.page.goto(`http://${this.host}:${this.port}`);
  }

  async stop() {
    this.page && await this.page.close();
    this.page = null;

    this.browser && await this.browser.close();
    this.browser = null;
  }

  static pushClients(clients, appConfig) {
    clients.push(new PuppeteerClient(appConfig));
  }
}<commit_msg>Fix browserstack test failures. Old puppeteer is not supported anymore.<commit_after>import Client from '../../client.js';
import { enterJob } from '../../../utils/buildmessage.js';
import { ensureDependencies } from '../../../cli/dev-bundle-helpers.js';

const NPM_DEPENDENCIES = {
  puppeteer: '8.0.0'
};

export default class PuppeteerClient extends Client {
  constructor(options) {
    super(options);

    enterJob(
      {
        title: 'Installing Puppeteer in Meteor tool'
      },
      () => {
        ensureDependencies(NPM_DEPENDENCIES);
      }
    );

    this.npmPackageExports = require('puppeteer');

    this.name = 'Puppeteer';
  }

  async connect() {
    // Note for Travis and CircleCI to run sandbox must be turned off.
    // From a security perspective this is not ideal, in the future would be worthwhile
    // to configure to include only for CI based setups
    this.browser = await this.npmPackageExports.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] });
    this.page = await this.browser.newPage();
    this.page.goto(`http://${this.host}:${this.port}`);
  }

  async stop() {
    this.page && await this.page.close();
    this.page = null;

    this.browser && await this.browser.close();
    this.browser = null;
  }

  static pushClients(clients, appConfig) {
    clients.push(new PuppeteerClient(appConfig));
  }
}
<|endoftext|>


<commit_before>/**
 * Interactive Linter Copyright (c) 2015 Miguel Castillo.
 *
 * Licensed under MIT
 */

define(function (require /*, exports, module*/) {
    "use strict";

    var EditorManager    = brackets.getModule("editor/EditorManager"),
        MainViewManager  = brackets.getModule("view/MainViewManager"),
        WorkspaceManager = brackets.getModule("view/WorkspaceManager"),
        Resizer          = brackets.getModule("utils/Resizer"),
        StringUtils      = brackets.getModule("utils/StringUtils"),
        linterManager    = require("linterManager"),
        linterReporter   = require("linterReporter"),
        panelTemplate    = require("text!templates/problemsPanel.html"),
        resultsTemplate  = require("text!templates/problemsPanelTable.html"),
        collapsed        = true,
        hasErrors        = false;

    var $problemsPanel, $problemsPanelTable;

    function handleIndicatorClick() {
        if (!hasErrors) {
            hidePanel();
        }
        else {
            if (Resizer.isVisible($problemsPanel)) {
                collapsed = true;
                hidePanel();
            }
            else {
                collapsed = false;
                showPanel();
            }
        }
    }

    function showPanel() {
        if (hasErrors) {
            Resizer.show($problemsPanel);
        }
    }

    function hidePanel() {
        Resizer.hide($problemsPanel);
    }

    function createPanel() {
        var $panelHtml = $(Mustache.render(panelTemplate));
        WorkspaceManager.createBottomPanel("interactive-linter.linting.messages", $panelHtml, 100);

        $problemsPanel = $("#interactive-linter-problems-panel");
        $problemsPanel.on("click", ".close", function () {
            collapsed = true;
            hidePanel();
        });

        $problemsPanelTable = $problemsPanel.find(".table-container");
        $problemsPanelTable.on("click", "tr", function () {
            var $target = $(this);
            var line = $target.data("line"); // Convert from friendly line to actual line number
            var ch   = $target.data("character");

            // if there is no line number available, don't do anything
            if (!isNaN(line) && !isNaN(ch)) {
                line -= 1;
                ch -= 1;
                var editor    = EditorManager.getCurrentFullEditor();
                editor.setCursorPos(line, ch, true);
                MainViewManager.focusActivePane();
            }
        });
    }

    function updateTitle(numProblems) {
        var message;
        if (numProblems === 1) {
            message = 'Interactive Linter: 1 Linter Problem';
        }
        else {
            message = StringUtils.format('Interactive Linter: {0} Linter Problems', numProblems);
        }
        $problemsPanel.find(".title").text(message);
    }

    function handleMessages(messages) {
        if (messages) {
            hasErrors = true;
            var html = Mustache.render(resultsTemplate, {messages: messages});

            $problemsPanelTable
                .empty()
                .append($(html))
                .scrollTop(0);

            if (!collapsed) {
                showPanel();
            }

            updateTitle(messages.length);
        }
        else {
            hasErrors = false;
            hidePanel();
        }
    }

    $(linterReporter).on("lintMessage", function (evt, messages) {
        handleMessages(messages);
    });

    $(linterManager).on("linterNotFound", function () {
        hasErrors = false;
        hidePanel();
    });

    createPanel();

    $(document).on("click", "#interactive-linter-lint-indicator", function () {
        handleIndicatorClick();
    });
});
<commit_msg>Simplify lint panel title update logic<commit_after>/**
 * Interactive Linter Copyright (c) 2015 Miguel Castillo.
 *
 * Licensed under MIT
 */

define(function (require /*, exports, module*/) {
    "use strict";

    var EditorManager    = brackets.getModule("editor/EditorManager"),
        MainViewManager  = brackets.getModule("view/MainViewManager"),
        WorkspaceManager = brackets.getModule("view/WorkspaceManager"),
        Resizer          = brackets.getModule("utils/Resizer"),
        StringUtils      = brackets.getModule("utils/StringUtils"),
        linterManager    = require("linterManager"),
        linterReporter   = require("linterReporter"),
        panelTemplate    = require("text!templates/problemsPanel.html"),
        resultsTemplate  = require("text!templates/problemsPanelTable.html"),
        collapsed        = true,
        hasErrors        = false;

    var $problemsPanel, $problemsPanelTable;

    function handleIndicatorClick() {
        if (!hasErrors) {
            hidePanel();
        }
        else {
            if (Resizer.isVisible($problemsPanel)) {
                collapsed = true;
                hidePanel();
            }
            else {
                collapsed = false;
                showPanel();
            }
        }
    }

    function showPanel() {
        if (hasErrors) {
            Resizer.show($problemsPanel);
        }
    }

    function hidePanel() {
        Resizer.hide($problemsPanel);
    }

    function createPanel() {
        var $panelHtml = $(Mustache.render(panelTemplate));
        WorkspaceManager.createBottomPanel("interactive-linter.linting.messages", $panelHtml, 100);

        $problemsPanel = $("#interactive-linter-problems-panel");
        $problemsPanel.on("click", ".close", function () {
            collapsed = true;
            hidePanel();
        });

        $problemsPanelTable = $problemsPanel.find(".table-container");
        $problemsPanelTable.on("click", "tr", function () {
            var $target = $(this);
            var line = $target.data("line"); // Convert from friendly line to actual line number
            var ch   = $target.data("character");

            // if there is no line number available, don't do anything
            if (!isNaN(line) && !isNaN(ch)) {
                line -= 1;
                ch -= 1;
                var editor    = EditorManager.getCurrentFullEditor();
                editor.setCursorPos(line, ch, true);
                MainViewManager.focusActivePane();
            }
        });
    }

    function updateTitle(numProblems) {
        var isPlural = numProblems !== 1;
        var message = StringUtils.format("Interactive Linter: {0} Linter Problem{1}", numProblems, isPlural ? "s" : "");
        $problemsPanel.find(".title").text(message);
    }

    function handleMessages(messages) {
        if (messages) {
            hasErrors = true;
            var html = Mustache.render(resultsTemplate, {messages: messages});

            $problemsPanelTable
                .empty()
                .append($(html))
                .scrollTop(0);

            if (!collapsed) {
                showPanel();
            }

            updateTitle(messages.length);
        }
        else {
            hasErrors = false;
            hidePanel();
        }
    }

    $(linterReporter).on("lintMessage", function (evt, messages) {
        handleMessages(messages);
    });

    $(linterManager).on("linterNotFound", function () {
        hasErrors = false;
        hidePanel();
    });

    createPanel();

    $(document).on("click", "#interactive-linter-lint-indicator", function () {
        handleIndicatorClick();
    });
});
<|endoftext|>


<commit_before>/* Base64 encode / decode
 * fom http://www.webtoolkit.info/
 * modified to support more url friendly variant "base64url".
 * modified to include Base64 for decimal numbers.
 */
var Base64 = {

	// private property
	_keyStr_compat : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
        // modified keyStr to be more url friendly
	_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_~",

	// public method for encoding
	encode : function (input, compat_mode) {
                var keyStr = this._keyStr;
                if (compat_mode)
                  keyStr = this._keyStr_compat;
		var output = "";
		var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
		var i = 0;

		input = Base64._utf8_encode(input);

		while (i < input.length) {

			chr1 = input.charCodeAt(i++);
			chr2 = input.charCodeAt(i++);
			chr3 = input.charCodeAt(i++);

			enc1 = chr1 >> 2;
			enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
			enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
			enc4 = chr3 & 63;

			if (isNaN(chr2)) {
				enc3 = enc4 = 64;
			} else if (isNaN(chr3)) {
				enc4 = 64;
			}

			output = output +
			keyStr.charAt(enc1) + keyStr.charAt(enc2) +
			keyStr.charAt(enc3) + keyStr.charAt(enc4);

		}

                if (compat_mode)
                  return output;
		return output.replace(/~/g,"");
	},

	// public method for decoding
	decode : function (input) {
		var output = "";
		var chr1, chr2, chr3;
		var enc1, enc2, enc3, enc4;
		var i = 0;

		//input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
		input = input.replace(/[^A-Za-z0-9\-_]/g, "");
                //append the trimmed padding
                input = input + "~~".substring(0,(4-input.length%4)%4);

		while (i < input.length) {

			enc1 = this._keyStr.indexOf(input.charAt(i++));
			enc2 = this._keyStr.indexOf(input.charAt(i++));
			enc3 = this._keyStr.indexOf(input.charAt(i++));
			enc4 = this._keyStr.indexOf(input.charAt(i++));

			chr1 = (enc1 << 2) | (enc2 >> 4);
			chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
			chr3 = ((enc3 & 3) << 6) | enc4;

			output = output + String.fromCharCode(chr1);

			if (enc3 != 64) {
				output = output + String.fromCharCode(chr2);
			}
			if (enc4 != 64) {
				output = output + String.fromCharCode(chr3);
			}

		}

		output = Base64._utf8_decode(output);

		return output;

	},

        encodeNum : function(num) {
          var output = "";
          while (num > 0) {
            output += this._keyStr.charAt(num%64);
            num -= num%64;
            num /= 64;
          }
          return output;
        },

        decodeNum : function(input) {
          var num = 0;
          for (var i=0; i<input.length; i++) {
            num += this._keyStr.indexOf(input.charAt(i)) * Math.pow(64,i);
          }
          return num;
        },

	// private method for UTF-8 encoding
	_utf8_encode : function (string) {
		string = string.replace(/\r\n/g,"\n");
		var utftext = "";

		for (var n = 0; n < string.length; n++) {

			var c = string.charCodeAt(n);

			if (c < 128) {
				utftext += String.fromCharCode(c);
			}
			else if((c > 127) && (c < 2048)) {
				utftext += String.fromCharCode((c >> 6) | 192);
				utftext += String.fromCharCode((c & 63) | 128);
			}
			else {
				utftext += String.fromCharCode((c >> 12) | 224);
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
				utftext += String.fromCharCode((c & 63) | 128);
			}

		}

		return utftext;
	},

	// private method for UTF-8 decoding
	_utf8_decode : function (utftext) {
		var string = "";
		var i = 0;
		var c = c1 = c2 = 0;

		while ( i < utftext.length ) {

			c = utftext.charCodeAt(i);

			if (c < 128) {
				string += String.fromCharCode(c);
				i++;
			}
			else if((c > 191) && (c < 224)) {
				c2 = utftext.charCodeAt(i+1);
				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
				i += 2;
			}
			else {
				c2 = utftext.charCodeAt(i+1);
				c3 = utftext.charCodeAt(i+2);
				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 3;
			}

		}

		return string;
	}

}

// LZW-compress a string
function lzw_encode(s) {
    var dict = {};
    var data = (s + "").split("");
    var out = [];
    var currChar;
    var phrase = data[0];
    var code = 256;
    for (var i=1; i<data.length; i++) {
        currChar=data[i];
        if (dict[phrase + currChar] != null) {
            phrase += currChar;
        }
        else {
            out.push(phrase.length > 1 ? dict[phrase] : phrase.charCodeAt(0));
            dict[phrase + currChar] = code;
            code++;
            phrase=currChar;
        }
    }
    out.push(phrase.length > 1 ? dict[phrase] : phrase.charCodeAt(0));
    for (var i=0; i<out.length; i++) {
        out[i] = String.fromCharCode(out[i]);
    }
    return out.join("");
}

// Decompress an LZW-encoded string
function lzw_decode(s) {
    var dict = {};
    var data = (s + "").split("");
    var currChar = data[0];
    var oldPhrase = currChar;
    var out = [currChar];
    var code = 256;
    var phrase;
    for (var i=1; i<data.length; i++) {
        var currCode = data[i].charCodeAt(0);
        if (currCode < 256) {
            phrase = data[i];
        }
        else {
           phrase = dict[currCode] ? dict[currCode] : (oldPhrase + currChar);
        }
        out.push(phrase);
        currChar = phrase.charAt(0);
        dict[code] = oldPhrase + currChar;
        code++;
        oldPhrase = phrase;
    }
    return out.join("");
}

// escape strings to show them directly in the html.
function htmlentities(str) {
  return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
}

<commit_msg>modified lzw library to support utf8 unicode strings (reusing the Base64._utf8_encode/decode methods)<commit_after>/* Base64 encode / decode
 * fom http://www.webtoolkit.info/
 * modified to support more url friendly variant "base64url".
 * modified to include Base64 for decimal numbers.
 */
var Base64 = {

	// private property
	_keyStr_compat : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
        // modified keyStr to be more url friendly
	_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_~",

	// public method for encoding
	encode : function (input, compat_mode) {
                var keyStr = this._keyStr;
                if (compat_mode)
                  keyStr = this._keyStr_compat;
		var output = "";
		var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
		var i = 0;

		input = Base64._utf8_encode(input);

		while (i < input.length) {

			chr1 = input.charCodeAt(i++);
			chr2 = input.charCodeAt(i++);
			chr3 = input.charCodeAt(i++);

			enc1 = chr1 >> 2;
			enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
			enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
			enc4 = chr3 & 63;

			if (isNaN(chr2)) {
				enc3 = enc4 = 64;
			} else if (isNaN(chr3)) {
				enc4 = 64;
			}

			output = output +
			keyStr.charAt(enc1) + keyStr.charAt(enc2) +
			keyStr.charAt(enc3) + keyStr.charAt(enc4);

		}

                if (compat_mode)
                  return output;
		return output.replace(/~/g,"");
	},

	// public method for decoding
	decode : function (input) {
		var output = "";
		var chr1, chr2, chr3;
		var enc1, enc2, enc3, enc4;
		var i = 0;

		//input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
		input = input.replace(/[^A-Za-z0-9\-_]/g, "");
                //append the trimmed padding
                input = input + "~~".substring(0,(4-input.length%4)%4);

		while (i < input.length) {

			enc1 = this._keyStr.indexOf(input.charAt(i++));
			enc2 = this._keyStr.indexOf(input.charAt(i++));
			enc3 = this._keyStr.indexOf(input.charAt(i++));
			enc4 = this._keyStr.indexOf(input.charAt(i++));

			chr1 = (enc1 << 2) | (enc2 >> 4);
			chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
			chr3 = ((enc3 & 3) << 6) | enc4;

			output = output + String.fromCharCode(chr1);

			if (enc3 != 64) {
				output = output + String.fromCharCode(chr2);
			}
			if (enc4 != 64) {
				output = output + String.fromCharCode(chr3);
			}

		}

		output = Base64._utf8_decode(output);

		return output;

	},

        encodeNum : function(num) {
          var output = "";
          while (num > 0) {
            output += this._keyStr.charAt(num%64);
            num -= num%64;
            num /= 64;
          }
          return output;
        },

        decodeNum : function(input) {
          var num = 0;
          for (var i=0; i<input.length; i++) {
            num += this._keyStr.indexOf(input.charAt(i)) * Math.pow(64,i);
          }
          return num;
        },

	// private method for UTF-8 encoding
	_utf8_encode : function (string) {
		string = string.replace(/\r\n/g,"\n");
		var utftext = "";

		for (var n = 0; n < string.length; n++) {

			var c = string.charCodeAt(n);

			if (c < 128) {
				utftext += String.fromCharCode(c);
			}
			else if((c > 127) && (c < 2048)) {
				utftext += String.fromCharCode((c >> 6) | 192);
				utftext += String.fromCharCode((c & 63) | 128);
			}
			else {
				utftext += String.fromCharCode((c >> 12) | 224);
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
				utftext += String.fromCharCode((c & 63) | 128);
			}

		}

		return utftext;
	},

	// private method for UTF-8 decoding
	_utf8_decode : function (utftext) {
		var string = "";
		var i = 0;
		var c = c1 = c2 = 0;

		while ( i < utftext.length ) {

			c = utftext.charCodeAt(i);

			if (c < 128) {
				string += String.fromCharCode(c);
				i++;
			}
			else if((c > 191) && (c < 224)) {
				c2 = utftext.charCodeAt(i+1);
				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
				i += 2;
			}
			else {
				c2 = utftext.charCodeAt(i+1);
				c3 = utftext.charCodeAt(i+2);
				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 3;
			}

		}

		return string;
	}

}

// lzw_* taken from jsolait library (http://jsolait.net/), LGPL
// slightly modified to support utf8 strings.
// LZW-compress a string
function lzw_encode(s) {
    s = Base64._utf8_encode(s);
    var dict = {};
    var data = (s + "").split("");
    var out = [];
    var currChar;
    var phrase = data[0];
    var code = 256;
    for (var i=1; i<data.length; i++) {
        currChar=data[i];
        if (dict[phrase + currChar] != null) {
            phrase += currChar;
        }
        else {
            out.push(phrase.length > 1 ? dict[phrase] : phrase.charCodeAt(0));
            dict[phrase + currChar] = code;
            code++;
            phrase=currChar;
        }
    }
    out.push(phrase.length > 1 ? dict[phrase] : phrase.charCodeAt(0));
    for (var i=0; i<out.length; i++) {
        out[i] = String.fromCharCode(out[i]);
    }
    return out.join("");
}

// Decompress an LZW-encoded string
function lzw_decode(s) {
    var dict = {};
    var data = (s + "").split("");
    var currChar = data[0];
    var oldPhrase = currChar;
    var out = [currChar];
    var code = 256;
    var phrase;
    for (var i=1; i<data.length; i++) {
        var currCode = data[i].charCodeAt(0);
        if (currCode < 256) {
            phrase = data[i];
        }
        else {
           phrase = dict[currCode] ? dict[currCode] : (oldPhrase + currChar);
        }
        out.push(phrase);
        currChar = phrase.charAt(0);
        dict[code] = oldPhrase + currChar;
        code++;
        oldPhrase = phrase;
    }
    return Base64._utf8_decode(out.join(""));
}

// escape strings to show them directly in the html.
function htmlentities(str) {
  return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
}

<|endoftext|>


<commit_before>exports.format_date = function (date, friendly) {
  var year = date.getFullYear();
  var month = date.getMonth() + 1;
  var day = date.getDate();
  var hour = date.getHours();
  var minute = date.getMinutes();
  var second = date.getSeconds();

  if (friendly) {
    var now = new Date();
    var mseconds = -(date.getTime() - now.getTime());
    var time_std = [ 1000, 60 * 1000, 60 * 60 * 1000, 24 * 60 * 60 * 1000 ];
    if (mseconds < time_std[3]) {
      if (mseconds > 0 && mseconds < time_std[1]) {
        return Math.floor(mseconds / time_std[0]).toString() + ' 秒前';
      }
      if (mseconds > time_std[1] && mseconds < time_std[2]) {
        return Math.floor(mseconds / time_std[1]).toString() + ' 分钟前';
      }
      if (mseconds > time_std[2]) {
        return Math.floor(mseconds / time_std[2]).toString() + ' 小时前';
      }
    }
  }

  //month = ((month < 10) ? '0' : '') + month;
  //day = ((day < 10) ? '0' : '') + day;
  hour = ((hour < 10) ? '0' : '') + hour;
  minute = ((minute < 10) ? '0' : '') + minute;
  second = ((second < 10) ? '0': '') + second;

  thisYear = new Date().getFullYear();
  year = (thisYear === year) ? '' : (year + '-');
  return year + month + '-' + day + ' ' + hour + ':' + minute;
};

/**
 * Escape the given string of `html`.
 *
 * @param {String} html
 * @return {String}
 * @api private
 */

exports.escape = function(html){
  return String(html)
    .replace(/&(?!\w+;)/g, '&')
    .replace(/</g, '<')
    .replace(/>/g, '>');
    // .replace(/"/g, '"');
};<commit_msg>escape "<commit_after>exports.format_date = function (date, friendly) {
  var year = date.getFullYear();
  var month = date.getMonth() + 1;
  var day = date.getDate();
  var hour = date.getHours();
  var minute = date.getMinutes();
  var second = date.getSeconds();

  if (friendly) {
    var now = new Date();
    var mseconds = -(date.getTime() - now.getTime());
    var time_std = [ 1000, 60 * 1000, 60 * 60 * 1000, 24 * 60 * 60 * 1000 ];
    if (mseconds < time_std[3]) {
      if (mseconds > 0 && mseconds < time_std[1]) {
        return Math.floor(mseconds / time_std[0]).toString() + ' 秒前';
      }
      if (mseconds > time_std[1] && mseconds < time_std[2]) {
        return Math.floor(mseconds / time_std[1]).toString() + ' 分钟前';
      }
      if (mseconds > time_std[2]) {
        return Math.floor(mseconds / time_std[2]).toString() + ' 小时前';
      }
    }
  }

  //month = ((month < 10) ? '0' : '') + month;
  //day = ((day < 10) ? '0' : '') + day;
  hour = ((hour < 10) ? '0' : '') + hour;
  minute = ((minute < 10) ? '0' : '') + minute;
  second = ((second < 10) ? '0': '') + second;

  thisYear = new Date().getFullYear();
  year = (thisYear === year) ? '' : (year + '-');
  return year + month + '-' + day + ' ' + hour + ':' + minute;
};

/**
 * Escape the given string of `html`.
 *
 * @param {String} html
 * @return {String}
 * @api private
 */

exports.escape = function(html){
  return String(html)
    .replace(/&(?!\w+;)/g, '&')
    .replace(/</g, '<')
    .replace(/>/g, '>')
    .replace(/"/g, '"');
};<|endoftext|>


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

exports.currentPrice = function(priceList) {
  return priceList.map((lastPrice) => {
    const change = lastPrice.percentChange.toString().charAt(0) === '-'
    ? `- ${utils.formatDecimal(-lastPrice.percentChange * 100, 2)}%`
    : `+ ${utils.formatDecimal(lastPrice.percentChange * 100, 2)}%`

    return [lastPrice.name, lastPrice.last, change]
  })
}

exports.priceTrend = function(currentMarket, data) {
  const closePrices = []
  const labels = []

  data.map((record) => {
    closePrices.push(record.close)
    labels.push(utils.formatDate(new Date(record.date * 1000), 'MM-dd'))
  })

  return {
    currentMarket,
    closePrices,
    labels
  }
}

// YUNBI
exports.currentPriceYUNBI = function(priceList, open) {
  const market = []

  priceList.map((lastPrice) => {
    open.map((openPrice) => {
      if (lastPrice.name === openPrice.name) {
        market.push({ name: lastPrice.name, last: lastPrice.last, open: openPrice.open })
      }
    })
  })

  return market.map((item) => {
    const change = (item.last - item.open).toString().charAt(0) === '-'
    ? `- ${utils.formatDecimal(-(item.last - item.open) / item.open * 100, 2)}%`
    : `+ ${utils.formatDecimal((item.last - item.open) / item.open * 100, 2)}%`

    return [item.name, item.last, change]
  })
}

exports.priceTrendYUNBI = function(currentMarket, data) {
  const closePrices = []
  const labels = []

  data.map((record) => {
    closePrices.push(record[1])
    labels.push(utils.formatDate(new Date(record[0] * 1000), 'MM-dd'))
  })

  return {
    currentMarket,
    closePrices,
    labels
  }
}
<commit_msg>Refactor wash function<commit_after>const utils = require('./utils')
const exchangers = require('../config/exchangers')

exports.currentPrice = function(exchange, priceList) {
  return priceList.map((price) => {
    const change = price.percentChange.toString().charAt(0) === '-'
    ? `- ${utils.formatDecimal(-price.percentChange * 100, 2)}%`
    : `+ ${utils.formatDecimal(price.percentChange * 100, 2)}%`

    const last = `${exchangers[exchange].currency} ${price.last}`

    return [price.name, last, change]
  })
}
<|endoftext|>