<commit_before>var utils = require('./connection_utils'),
  inherits = require('util').inherits,
  net = require('net'),
  debug = require('util').debug,
  inspect = require('util').inspect,
  EventEmitter = require('events').EventEmitter,
  inherits = require('util').inherits,
  binaryutils = require('../bson/binary_utils'),
  tls = require('tls');

var Connection = exports.Connection = function(id, socketOptions) {
  // Set up event emitter
  EventEmitter.call(this);
  // Store all socket options
  this.socketOptions = socketOptions ? socketOptions : {host:'localhost', port:27017};
  // Id for the connection
  this.id = id;
  // State of the connection
  this.connected = false;

  //
  // Connection parsing state
  //
  this.maxBsonSize = socketOptions.maxBsonSize ? socketOptions.maxBsonSize : Connection.DEFAULT_MAX_BSON_SIZE;
  // Contains the current message bytes
  this.buffer = null;
  // Contains the current message size
  this.sizeOfMessage = 0;
  // Contains the readIndex for the messaage
  this.bytesRead = 0;
  // Contains spill over bytes from additional messages
  this.stubBuffer = 0;

  // Just keeps list of events we allow
  this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[], timeout:[], end:[]};

  // Just keeps list of events we allow
  resetHandlers(this, false);
}

// Set max bson size
Connection.DEFAULT_MAX_BSON_SIZE = 4 * 1024 * 1024 * 4 * 3;

// Inherit event emitter so we can emit stuff wohoo
// inherits(Connection, SimpleEmitter);
inherits(Connection, EventEmitter);

Connection.prototype.start = function() {
  // If we have a normal connection
  if(this.socketOptions.ssl) {
    // Create a new stream
    this.connection = new net.Stream();
    // Set options on the socket
    this.connection.setTimeout(this.socketOptions.timeout);
    this.connection.setNoDelay(this.socketOptions.noDelay);
    // Set keep alive if defined
    if(this.socketOptions.keepAlive > 0) {
      this.connection.setKeepAlive(true, this.socketOptions.keepAlive);
    } else {
      this.connection.setKeepAlive(false);
    }

    // Set up pair for tls with server, accept self-signed certificates as well
    this.pair = tls.createSecurePair(false);
    // Set up encrypted streams
    this.pair.encrypted.pipe(this.connection);
    this.connection.pipe(this.pair.encrypted);

    // Setup clearText stream
    this.writeSteam = this.pair.cleartext;
    // Add all handlers to the socket to manage it
    this.pair.on("secure", connectHandler(this));
    this.pair.cleartext.on("data", createDataHandler(this));
    // Add handlers
    this.connection.on("error", errorHandler(this));
    // Add all handlers to the socket to manage it
    this.connection.on("end", endHandler(this));
    this.connection.on("timeout", timeoutHandler(this));
    this.connection.on("drain", drainHandler(this));
    this.writeSteam.on("close", closeHandler(this));
    // Start socket
    this.connection.connect(this.socketOptions.port, this.socketOptions.host);
  } else {
    // Create a new stream
    this.connection = new net.Stream();
    // // Create new connection instance
    this.connection = new net.Socket();
    // Set options on the socket
    this.connection.setTimeout(this.socketOptions.timeout);
    this.connection.setNoDelay(this.socketOptions.noDelay);
    // Set keep alive if defined
    if(this.socketOptions.keepAlive > 0) {
      this.connection.setKeepAlive(true, this.socketOptions.keepAlive);
    } else {
      this.connection.setKeepAlive(false);
    }

    // Set up write stream
    this.writeSteam = this.connection;
    // Add handlers
    this.connection.on("error", errorHandler(this));
    // Add all handlers to the socket to manage it
    this.connection.on("connect", connectHandler(this));
    // this.connection.on("end", endHandler(this));
    this.connection.on("data", createDataHandler(this));
    this.connection.on("timeout", timeoutHandler(this));
    this.connection.on("drain", drainHandler(this));
    this.connection.on("close", closeHandler(this));
    // Start socket
    this.connection.connect(this.socketOptions.port, this.socketOptions.host);
  }
}

// Check if the sockets are live
Connection.prototype.isConnected = function() {
  return this.connected && !this.connection.destroyed && this.connection.writable && this.connection.readable;
}

// Write the data out to the socket
Connection.prototype.write = function(command, callback) {
  try {
    // If we have a list off commands to be executed on the same socket
    if(Array.isArray(command)) {
      for(var i = 0; i < command.length; i++) {
        var binaryCommand = command[i].toBinary()
        if(this.logger != null && this.logger.doDebug) this.logger.debug("writing command to mongodb", binaryCommand);
        var r = this.writeSteam.write(binaryCommand);
      }
    } else {
      var binaryCommand = command.toBinary()
      if(this.logger != null && this.logger.doDebug) this.logger.debug("writing command to mongodb", binaryCommand);
      var r = this.writeSteam.write(binaryCommand);
    }
  } catch (err) {
    if(typeof callback === 'function') callback(err);
  }
}

// Force the closure of the connection
Connection.prototype.close = function() {
  // clear out all the listeners
  resetHandlers(this, true);
  // Add a dummy error listener to catch any weird last moment errors (and ignore them)
  this.connection.on("error", function() {})
  // destroy connection
  this.connection.destroy();
}

// Reset all handlers
var resetHandlers = function(self, clearListeners) {
  self.eventHandlers = {error:[], connect:[], close:[], end:[], timeout:[], parseError:[], message:[]};

  // If we want to clear all the listeners
  if(clearListeners && self.connection != null) {
    var keys = Object.keys(self.eventHandlers);
    // Remove all listeners
    for(var i = 0; i < keys.length; i++) {
      self.connection.removeAllListeners(keys[i]);
    }
  }
}

//
// Handlers
//

// Connect handler
var connectHandler = function(self) {
  return function() {
    // Set connected
    self.connected = true;
    // Emit the connect event with no error
    self.emit("connect", null, self);
  }
}

var createDataHandler = exports.Connection.createDataHandler = function(self) {
  // We need to handle the parsing of the data
  // and emit the messages when there is a complete one
  return function(data) {
    // console.log("----------------------------------------------------------- DATA :: " + data.length)
    // console.dir(data.toString('hex'))

    // Parse until we are done with the data
    while(data.length > 0) {
      // If we still have bytes to read on the current message
      if(self.bytesRead > 0 && self.sizeOfMessage > 0) {
        // Calculate the amount of remaining bytes
        var remainingBytesToRead = self.sizeOfMessage - self.bytesRead;
        // Check if the current chunk contains the rest of the message
        if(remainingBytesToRead > data.length) {
          // Copy the new data into the exiting buffer (should have been allocated when we know the message size)
          data.copy(self.buffer, self.bytesRead);
          // Adjust the number of bytes read so it point to the correct index in the buffer
          self.bytesRead = self.bytesRead + data.length;

          // Reset state of buffer
          data = new Buffer(0);
        } else {
          // Copy the missing part of the data into our current buffer
          data.copy(self.buffer, self.bytesRead, 0, remainingBytesToRead);
          // Slice the overflow into a new buffer that we will then re-parse
          data = data.slice(remainingBytesToRead);

          // Emit current complete message
          try {
            self.emit("message", self.buffer, self);

          } catch(err) {
            var errorObject = {err:"socketHandler", trace:err, bin:buffer, parseState:{
              sizeOfMessage:self.sizeOfMessage,
              bytesRead:self.bytesRead,
              stubBuffer:self.stubBuffer}};
            if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
            // We got a parse Error fire it off then keep going
            self.emit("parseError", errorObject, self);
          }

          // Reset state of buffer
          self.buffer = null;
          self.sizeOfMessage = 0;
          self.bytesRead = 0;
          self.stubBuffer = null;
        }
      } else {
        // Stub buffer is kept in case we don't get enough bytes to determine the
        // size of the message (< 4 bytes)
        if(self.stubBuffer != null && self.stubBuffer.length > 0) {

          // If we have enough bytes to determine the message size let's do it
          if(self.stubBuffer.length + data.length > 4) {
            // Prepad the data
            var newData = new Buffer(self.stubBuffer.length + data.length);
            self.stubBuffer.copy(newData, 0);
            data.copy(newData, self.stubBuffer.length);
            // Reassign for parsing
            data = newData;

            // Reset state of buffer
            self.buffer = null;
            self.sizeOfMessage = 0;
            self.bytesRead = 0;
            self.stubBuffer = null;

          } else {

            // Add the the bytes to the stub buffer
            var newStubBuffer = new Buffer(self.stubBuffer.length + data.length);
            // Copy existing stub buffer
            self.stubBuffer.copy(newStubBuffer, 0);
            // Copy missing part of the data
            data.copy(newStubBuffer, self.stubBuffer.length);
            // Exit parsing loop
            data = new Buffer(0);
          }
        } else {
          if(data.length > 4) {
            // Retrieve the message size
            var sizeOfMessage = binaryutils.decodeUInt32(data, 0);
            // console.log("=================================================== parse sizeOfMessage")
            // console.dir(sizeOfMessage)

            // If we have a negative sizeOfMessage emit error and return
            if(sizeOfMessage < 0 || sizeOfMessage > self.maxBsonSize) {
              var errorObject = {err:"socketHandler", trace:'', bin:self.buffer, parseState:{
                sizeOfMessage:sizeOfMessage,
                bytesRead:self.bytesRead,
                stubBuffer:self.stubBuffer}};
              if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
              // We got a parse Error fire it off then keep going
              self.emit("parseError", errorObject, self);
              return;
            }

            // console.log("--------------------------------------------------------------------")
            // console.dir(sizeOfMessage)
            // console.dir(self.maxBsonSize)
            // console.dir(data.length)

            // Ensure that the size of message is larger than 0 and less than the max allowed
            if(sizeOfMessage > 4 && sizeOfMessage < self.maxBsonSize && sizeOfMessage > data.length) {
              self.buffer = new Buffer(sizeOfMessage);
              // Copy all the data into the buffer
              data.copy(self.buffer, 0);
              // Update bytes read
              self.bytesRead = data.length;
              // Update sizeOfMessage
              self.sizeOfMessage = sizeOfMessage;
              // Ensure stub buffer is null
              self.stubBuffer = null;
              // Exit parsing loop
              data = new Buffer(0);

            } else if(sizeOfMessage > 4 && sizeOfMessage < self.maxBsonSize && sizeOfMessage == data.length) {
              try {
                self.emit("message", data, self);
                // Reset state of buffer
                self.buffer = null;
                self.sizeOfMessage = 0;
                self.bytesRead = 0;
                self.stubBuffer = null;
                // Exit parsing loop
                data = new Buffer(0);

              } catch (err) {
                var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{
                  sizeOfMessage:self.sizeOfMessage,
                  bytesRead:self.bytesRead,
                  stubBuffer:self.stubBuffer}};
                if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
                // We got a parse Error fire it off then keep going
                self.emit("parseError", errorObject, self);
              }
            } else if(sizeOfMessage <= 4 || sizeOfMessage > self.maxBsonSize) {
              var errorObject = {err:"socketHandler", trace:null, bin:data, parseState:{
                sizeOfMessage:sizeOfMessage,
                bytesRead:0,
                buffer:null,
                stubBuffer:null}};
              if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
              // We got a parse Error fire it off then keep going
              self.emit("parseError", errorObject, self);

              // Clear out the state of the parser
              self.buffer = null;
              self.sizeOfMessage = 0;
              self.bytesRead = 0;
              self.stubBuffer = null;
              // Exit parsing loop
              data = new Buffer(0);

            } else {
              try {
                self.emit("message", data.slice(0, sizeOfMessage), self);
                // Reset state of buffer
                self.buffer = null;
                self.sizeOfMessage = 0;
                self.bytesRead = 0;
                self.stubBuffer = null;
                // Copy rest of message
                data = data.slice(sizeOfMessage);
              } catch (err) {
                var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{
                  sizeOfMessage:sizeOfMessage,
                  bytesRead:self.bytesRead,
                  stubBuffer:self.stubBuffer}};
                if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
                // We got a parse Error fire it off then keep going
                self.emit("parseError", errorObject, self);
              }

            }
          } else {
            // Create a buffer that contains the space for the non-complete message
            self.stubBuffer = new Buffer(data.length)
            // Copy the data to the stub buffer
            data.copy(self.stubBuffer, 0);
            // Exit parsing loop
            data = new Buffer(0);
          }
        }
      }
    }
  }
}

var endHandler = function(self) {
  return function() {
    // Set connected to false
    self.connected = false;
    // Emit end event
    self.emit("end", {err: 'connection received Fin packet from [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
    // Reset handlers
    resetHandlers(self, true);
  }
}

var timeoutHandler = function(self) {
  return function() {
    self.emit("timeout", {err: 'connection to [' + self.socketOptions.host + ':' + self.socketOptions.port + '] timed out'}, self);
    // Reset handlers
    resetHandlers(self, true);
  }
}

var drainHandler = function(self) {
  return function() {
  }
}

var errorHandler = function(self) {
  return function(err) {
    // Set connected to false
    self.connected = false;
    // Emit error
    self.emit("error", {err: 'failed to connect to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
    // Reset handlers
    resetHandlers(self, true);
  }
}

var closeHandler = function(self) {
  return function(hadError) {
    // If we have an error during the connection phase
    if(hadError && !self.connected) {
      // Set disconnected
      self.connected = false;
      // Emit error
      self.emit("error", {err: 'failed to connect to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
    } else {
      // Set disconnected
      self.connected = false;
      // Emit close
      self.emit("close", {err: 'connection closed to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
    }

    // Reset handlers
    resetHandlers(self, true);
  }
}

// Some basic defaults
Connection.DEFAULT_PORT = 27017;

<commit_msg>Socket is faster than Stream<commit_after>var utils = require('./connection_utils'),
  inherits = require('util').inherits,
  net = require('net'),
  debug = require('util').debug,
  inspect = require('util').inspect,
  EventEmitter = require('events').EventEmitter,
  inherits = require('util').inherits,
  binaryutils = require('../bson/binary_utils'),
  tls = require('tls');

var Connection = exports.Connection = function(id, socketOptions) {
  // Set up event emitter
  EventEmitter.call(this);
  // Store all socket options
  this.socketOptions = socketOptions ? socketOptions : {host:'localhost', port:27017};
  // Id for the connection
  this.id = id;
  // State of the connection
  this.connected = false;

  //
  // Connection parsing state
  //
  this.maxBsonSize = socketOptions.maxBsonSize ? socketOptions.maxBsonSize : Connection.DEFAULT_MAX_BSON_SIZE;
  // Contains the current message bytes
  this.buffer = null;
  // Contains the current message size
  this.sizeOfMessage = 0;
  // Contains the readIndex for the messaage
  this.bytesRead = 0;
  // Contains spill over bytes from additional messages
  this.stubBuffer = 0;

  // Just keeps list of events we allow
  this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[], timeout:[], end:[]};

  // Just keeps list of events we allow
  resetHandlers(this, false);
}

// Set max bson size
Connection.DEFAULT_MAX_BSON_SIZE = 4 * 1024 * 1024 * 4 * 3;

// Inherit event emitter so we can emit stuff wohoo
// inherits(Connection, SimpleEmitter);
inherits(Connection, EventEmitter);

Connection.prototype.start = function() {
  // If we have a normal connection
  if(this.socketOptions.ssl) {
    // Create a new stream
    this.connection = new net.Stream();
    // Set options on the socket
    this.connection.setTimeout(this.socketOptions.timeout);
    this.connection.setNoDelay(this.socketOptions.noDelay);
    // Set keep alive if defined
    if(this.socketOptions.keepAlive > 0) {
      this.connection.setKeepAlive(true, this.socketOptions.keepAlive);
    } else {
      this.connection.setKeepAlive(false);
    }

    // Set up pair for tls with server, accept self-signed certificates as well
    this.pair = tls.createSecurePair(false);
    // Set up encrypted streams
    this.pair.encrypted.pipe(this.connection);
    this.connection.pipe(this.pair.encrypted);

    // Setup clearText stream
    this.writeSteam = this.pair.cleartext;
    // Add all handlers to the socket to manage it
    this.pair.on("secure", connectHandler(this));
    this.pair.cleartext.on("data", createDataHandler(this));
    // Add handlers
    this.connection.on("error", errorHandler(this));
    // Add all handlers to the socket to manage it
    this.connection.on("end", endHandler(this));
    this.connection.on("timeout", timeoutHandler(this));
    this.connection.on("drain", drainHandler(this));
    this.writeSteam.on("close", closeHandler(this));
    // Start socket
    this.connection.connect(this.socketOptions.port, this.socketOptions.host);
  } else {
    // // Create a new stream
    // this.connection = new net.Stream();
    // // Create new connection instance
    this.connection = new net.Socket();
    // Set options on the socket
    this.connection.setTimeout(this.socketOptions.timeout);
    this.connection.setNoDelay(this.socketOptions.noDelay);
    // Set keep alive if defined
    if(this.socketOptions.keepAlive > 0) {
      this.connection.setKeepAlive(true, this.socketOptions.keepAlive);
    } else {
      this.connection.setKeepAlive(false);
    }

    // Set up write stream
    this.writeSteam = this.connection;
    // Add handlers
    this.connection.on("error", errorHandler(this));
    // Add all handlers to the socket to manage it
    this.connection.on("connect", connectHandler(this));
    // this.connection.on("end", endHandler(this));
    this.connection.on("data", createDataHandler(this));
    this.connection.on("timeout", timeoutHandler(this));
    this.connection.on("drain", drainHandler(this));
    this.connection.on("close", closeHandler(this));
    // Start socket
    this.connection.connect(this.socketOptions.port, this.socketOptions.host);
  }
}

// Check if the sockets are live
Connection.prototype.isConnected = function() {
  return this.connected && !this.connection.destroyed && this.connection.writable && this.connection.readable;
}

// Write the data out to the socket
Connection.prototype.write = function(command, callback) {
  try {
    // If we have a list off commands to be executed on the same socket
    if(Array.isArray(command)) {
      for(var i = 0; i < command.length; i++) {
        var binaryCommand = command[i].toBinary()
        if(this.logger != null && this.logger.doDebug) this.logger.debug("writing command to mongodb", binaryCommand);
        var r = this.writeSteam.write(binaryCommand);
      }
    } else {
      var binaryCommand = command.toBinary()
      if(this.logger != null && this.logger.doDebug) this.logger.debug("writing command to mongodb", binaryCommand);
      var r = this.writeSteam.write(binaryCommand);
    }
  } catch (err) {
    if(typeof callback === 'function') callback(err);
  }
}

// Force the closure of the connection
Connection.prototype.close = function() {
  // clear out all the listeners
  resetHandlers(this, true);
  // Add a dummy error listener to catch any weird last moment errors (and ignore them)
  this.connection.on("error", function() {})
  // destroy connection
  this.connection.destroy();
}

// Reset all handlers
var resetHandlers = function(self, clearListeners) {
  self.eventHandlers = {error:[], connect:[], close:[], end:[], timeout:[], parseError:[], message:[]};

  // If we want to clear all the listeners
  if(clearListeners && self.connection != null) {
    var keys = Object.keys(self.eventHandlers);
    // Remove all listeners
    for(var i = 0; i < keys.length; i++) {
      self.connection.removeAllListeners(keys[i]);
    }
  }
}

//
// Handlers
//

// Connect handler
var connectHandler = function(self) {
  return function() {
    // Set connected
    self.connected = true;
    // Emit the connect event with no error
    self.emit("connect", null, self);
  }
}

var createDataHandler = exports.Connection.createDataHandler = function(self) {
  // We need to handle the parsing of the data
  // and emit the messages when there is a complete one
  return function(data) {
    // console.log("----------------------------------------------------------- DATA :: " + data.length)
    // console.dir(data.toString('hex'))

    // Parse until we are done with the data
    while(data.length > 0) {
      // If we still have bytes to read on the current message
      if(self.bytesRead > 0 && self.sizeOfMessage > 0) {
        // Calculate the amount of remaining bytes
        var remainingBytesToRead = self.sizeOfMessage - self.bytesRead;
        // Check if the current chunk contains the rest of the message
        if(remainingBytesToRead > data.length) {
          // Copy the new data into the exiting buffer (should have been allocated when we know the message size)
          data.copy(self.buffer, self.bytesRead);
          // Adjust the number of bytes read so it point to the correct index in the buffer
          self.bytesRead = self.bytesRead + data.length;

          // Reset state of buffer
          data = new Buffer(0);
        } else {
          // Copy the missing part of the data into our current buffer
          data.copy(self.buffer, self.bytesRead, 0, remainingBytesToRead);
          // Slice the overflow into a new buffer that we will then re-parse
          data = data.slice(remainingBytesToRead);

          // Emit current complete message
          try {
            self.emit("message", self.buffer, self);

          } catch(err) {
            var errorObject = {err:"socketHandler", trace:err, bin:buffer, parseState:{
              sizeOfMessage:self.sizeOfMessage,
              bytesRead:self.bytesRead,
              stubBuffer:self.stubBuffer}};
            if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
            // We got a parse Error fire it off then keep going
            self.emit("parseError", errorObject, self);
          }

          // Reset state of buffer
          self.buffer = null;
          self.sizeOfMessage = 0;
          self.bytesRead = 0;
          self.stubBuffer = null;
        }
      } else {
        // Stub buffer is kept in case we don't get enough bytes to determine the
        // size of the message (< 4 bytes)
        if(self.stubBuffer != null && self.stubBuffer.length > 0) {

          // If we have enough bytes to determine the message size let's do it
          if(self.stubBuffer.length + data.length > 4) {
            // Prepad the data
            var newData = new Buffer(self.stubBuffer.length + data.length);
            self.stubBuffer.copy(newData, 0);
            data.copy(newData, self.stubBuffer.length);
            // Reassign for parsing
            data = newData;

            // Reset state of buffer
            self.buffer = null;
            self.sizeOfMessage = 0;
            self.bytesRead = 0;
            self.stubBuffer = null;

          } else {

            // Add the the bytes to the stub buffer
            var newStubBuffer = new Buffer(self.stubBuffer.length + data.length);
            // Copy existing stub buffer
            self.stubBuffer.copy(newStubBuffer, 0);
            // Copy missing part of the data
            data.copy(newStubBuffer, self.stubBuffer.length);
            // Exit parsing loop
            data = new Buffer(0);
          }
        } else {
          if(data.length > 4) {
            // Retrieve the message size
            var sizeOfMessage = binaryutils.decodeUInt32(data, 0);
            // console.log("=================================================== parse sizeOfMessage")
            // console.dir(sizeOfMessage)

            // If we have a negative sizeOfMessage emit error and return
            if(sizeOfMessage < 0 || sizeOfMessage > self.maxBsonSize) {
              var errorObject = {err:"socketHandler", trace:'', bin:self.buffer, parseState:{
                sizeOfMessage:sizeOfMessage,
                bytesRead:self.bytesRead,
                stubBuffer:self.stubBuffer}};
              if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
              // We got a parse Error fire it off then keep going
              self.emit("parseError", errorObject, self);
              return;
            }

            // console.log("--------------------------------------------------------------------")
            // console.dir(sizeOfMessage)
            // console.dir(self.maxBsonSize)
            // console.dir(data.length)

            // Ensure that the size of message is larger than 0 and less than the max allowed
            if(sizeOfMessage > 4 && sizeOfMessage < self.maxBsonSize && sizeOfMessage > data.length) {
              self.buffer = new Buffer(sizeOfMessage);
              // Copy all the data into the buffer
              data.copy(self.buffer, 0);
              // Update bytes read
              self.bytesRead = data.length;
              // Update sizeOfMessage
              self.sizeOfMessage = sizeOfMessage;
              // Ensure stub buffer is null
              self.stubBuffer = null;
              // Exit parsing loop
              data = new Buffer(0);

            } else if(sizeOfMessage > 4 && sizeOfMessage < self.maxBsonSize && sizeOfMessage == data.length) {
              try {
                self.emit("message", data, self);
                // Reset state of buffer
                self.buffer = null;
                self.sizeOfMessage = 0;
                self.bytesRead = 0;
                self.stubBuffer = null;
                // Exit parsing loop
                data = new Buffer(0);

              } catch (err) {
                var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{
                  sizeOfMessage:self.sizeOfMessage,
                  bytesRead:self.bytesRead,
                  stubBuffer:self.stubBuffer}};
                if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
                // We got a parse Error fire it off then keep going
                self.emit("parseError", errorObject, self);
              }
            } else if(sizeOfMessage <= 4 || sizeOfMessage > self.maxBsonSize) {
              var errorObject = {err:"socketHandler", trace:null, bin:data, parseState:{
                sizeOfMessage:sizeOfMessage,
                bytesRead:0,
                buffer:null,
                stubBuffer:null}};
              if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
              // We got a parse Error fire it off then keep going
              self.emit("parseError", errorObject, self);

              // Clear out the state of the parser
              self.buffer = null;
              self.sizeOfMessage = 0;
              self.bytesRead = 0;
              self.stubBuffer = null;
              // Exit parsing loop
              data = new Buffer(0);

            } else {
              try {
                self.emit("message", data.slice(0, sizeOfMessage), self);
                // Reset state of buffer
                self.buffer = null;
                self.sizeOfMessage = 0;
                self.bytesRead = 0;
                self.stubBuffer = null;
                // Copy rest of message
                data = data.slice(sizeOfMessage);
              } catch (err) {
                var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{
                  sizeOfMessage:sizeOfMessage,
                  bytesRead:self.bytesRead,
                  stubBuffer:self.stubBuffer}};
                if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
                // We got a parse Error fire it off then keep going
                self.emit("parseError", errorObject, self);
              }

            }
          } else {
            // Create a buffer that contains the space for the non-complete message
            self.stubBuffer = new Buffer(data.length)
            // Copy the data to the stub buffer
            data.copy(self.stubBuffer, 0);
            // Exit parsing loop
            data = new Buffer(0);
          }
        }
      }
    }
  }
}

var endHandler = function(self) {
  return function() {
    // Set connected to false
    self.connected = false;
    // Emit end event
    self.emit("end", {err: 'connection received Fin packet from [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
    // Reset handlers
    resetHandlers(self, true);
  }
}

var timeoutHandler = function(self) {
  return function() {
    self.emit("timeout", {err: 'connection to [' + self.socketOptions.host + ':' + self.socketOptions.port + '] timed out'}, self);
    // Reset handlers
    resetHandlers(self, true);
  }
}

var drainHandler = function(self) {
  return function() {
  }
}

var errorHandler = function(self) {
  return function(err) {
    // Set connected to false
    self.connected = false;
    // Emit error
    self.emit("error", {err: 'failed to connect to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
    // Reset handlers
    resetHandlers(self, true);
  }
}

var closeHandler = function(self) {
  return function(hadError) {
    // If we have an error during the connection phase
    if(hadError && !self.connected) {
      // Set disconnected
      self.connected = false;
      // Emit error
      self.emit("error", {err: 'failed to connect to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
    } else {
      // Set disconnected
      self.connected = false;
      // Emit close
      self.emit("close", {err: 'connection closed to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
    }

    // Reset handlers
    resetHandlers(self, true);
  }
}

// Some basic defaults
Connection.DEFAULT_PORT = 27017;

<|endoftext|>


<commit_before>window.__recordedEvents = window.__recordedEvents||{};

var internals = {};

/*
    Kan vi kanskje bruke denne til å trappe click events bedre?
*/
var KEYS = ['height', 'width', 'position', 'left', 'right', 'top', 'bottom', 'z-index', 'display', 'visability'];
function getCss(computedStyle){
    var res = {};
    KEYS.forEach(function (key) {
        res[key] = computedStyle.getPropertyValue(key);
    });
    return res;
}
function getStyles(el){
    return getCss(window.getComputedStyle(el));
}

internals.addHandlerToString = function (element, eventType, handler, id) {
    var str = handler && handler.toString();
    console.log('resources/wrapElement.js => toStringedHandler len:' +str.length);
    window.__recordedEvents[eventType] = window.__recordedEvents[eventType] || {};
    window.__recordedEvents[eventType][id] = {
        events: [],
        handler: str,
        elementData: {
            className: element.className,
            id: element.id,
            style: element.style,
            styles: getStyles(element)
        }
    };
};

internals.wrap = function (eventType, handler, id) {
    return function (e) {
        window.__recordedEvents[eventType][id].events.push({
            'eventType': eventType,
            'id': id,
            'time': new Date()
        });
        console.log('resources/wrapElement.js => captured ' + eventType, e.target);
        return handler.apply(this, Array.prototype.slice.call(arguments));
    };
};

internals.counter = 0;
internals.getId = function getId(event){
    internals.counter++]
    return [event,
        Date.now(), Math.round(Math.random() + Math.random() +
        Date.now() * Math.random()), internals.counter].join('-');
};

module.exports = function (/*fn*/) {
    console.log('resources/wrapElement.js => Element.prototype.addEventListener wrapped');
    internals._addEventListener = window.Element.prototype.addEventListener;
    window.Element.prototype.addEventListener = function (event, handler, capture) {
        console.log('resources/wrapElement.js => window.addEventListener init on ', event);
        var id = internals.getId(event);
        internals.addHandlerToString(this, event, handler, id);
        handler = internals.wrap(event, handler, id);
        // if (fn) {
        //     fn(this, event, handler);
        // }
        if (internals._addEventListener) {
            return internals._addEventListener.call(this, event, handler, capture);
        }
    };
};
<commit_msg>fix another typ0<commit_after>window.__recordedEvents = window.__recordedEvents||{};

var internals = {};

/*
    Kan vi kanskje bruke denne til å trappe click events bedre?
*/
var KEYS = ['height', 'width', 'position', 'left', 'right', 'top', 'bottom', 'z-index', 'display', 'visability'];
function getCss(computedStyle){
    var res = {};
    KEYS.forEach(function (key) {
        res[key] = computedStyle.getPropertyValue(key);
    });
    return res;
}
function getStyles(el){
    return getCss(window.getComputedStyle(el));
}

internals.addHandlerToString = function (element, eventType, handler, id) {
    var str = handler && handler.toString();
    console.log('resources/wrapElement.js => toStringedHandler len:' +str.length);
    window.__recordedEvents[eventType] = window.__recordedEvents[eventType] || {};
    window.__recordedEvents[eventType][id] = {
        events: [],
        handler: str,
        elementData: {
            className: element.className,
            id: element.id,
            style: element.style,
            styles: getStyles(element)
        }
    };
};

internals.wrap = function (eventType, handler, id) {
    return function (e) {
        window.__recordedEvents[eventType][id].events.push({
            'eventType': eventType,
            'id': id,
            'time': new Date()
        });
        console.log('resources/wrapElement.js => captured ' + eventType, e.target);
        return handler.apply(this, Array.prototype.slice.call(arguments));
    };
};

internals.counter = 0;
internals.getId = function getId(event){
    internals.counter++;
    return [event,
        Date.now(), Math.round(Math.random() + Math.random() +
        Date.now() * Math.random()), internals.counter].join('-');
};

module.exports = function (/*fn*/) {
    console.log('resources/wrapElement.js => Element.prototype.addEventListener wrapped');
    internals._addEventListener = window.Element.prototype.addEventListener;
    window.Element.prototype.addEventListener = function (event, handler, capture) {
        console.log('resources/wrapElement.js => window.addEventListener init on ', event);
        var id = internals.getId(event);
        internals.addHandlerToString(this, event, handler, id);
        handler = internals.wrap(event, handler, id);
        // if (fn) {
        //     fn(this, event, handler);
        // }
        if (internals._addEventListener) {
            return internals._addEventListener.call(this, event, handler, capture);
        }
    };
};
<|endoftext|>


<commit_before>/**
 * @author Pieter Colpaert <pieter.colpaert@okfn.org>
 */
var Transform = require('stream').Transform,
    util = require('util');

util.inherits(StopsTransformer, Transform);

function StopsTransformer (options) {
  this._feedbaseuri = options.baseuri;
  this._options = options;
  Transform.call(this, {objectMode : true});
}

/**
 *  Creates a gtfs:Station or gtfs:Stop with additional properties. Also creates a gtfs:Zone
 */
StopsTransformer.prototype._transform = function (data, encoding, done) {
  var subject = this._feedbaseuri + "/stops/" + data["stop_id"];
  // gtfs:locationType triple
  if (data["location_type"] && data["location_type"] === "1") {
    this.push({ subject: subject, predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", object: "http://vocab.gtfs.org/terms#Station"});
  } else {
    this.push({ subject: subject, predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", object: "http://vocab.gtfs.org/terms#Stop"});
    //Stations can't have a parent_station, only Stops can have a parent station.
    if (data["parent_station"]) {
      this.push({ subject: subject, predicate: "http://vocab.gtfs.org/terms#parentStation", object :'"' +  data["parent_station"]+'"' });
    }
    if (data["zone_id"]) {
      this.push({ subject: this._feedbaseuri + "/zones/" + data["zone_id"], predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", object : "http://vocab.gtfs.org/terms#Zone" });
      this.push({ subject: subject, predicate: "http://vocab.gtfs.org/terms#zone", object : this._feedbaseuri + "/zones/" + data["zone_id"] });
    }
  }
  // gtfs:code triple
  if (data["stop_code"]) {
    this.push({ subject: subject, predicate: "http://purl.org/dc/terms/identifier", object :'"' +  data["stop_code"]+'"' });
  }
  // foaf:name triple
  if (data["stop_name"]) {
    this.push({ subject: subject, predicate: "http://xmlns.com/foaf/0.1/name", object :'"' +  data["stop_name"]+'"' });
  }
  if (data["stop_desc"]) {
    this.push({ subject: subject, predicate: "http://purl.org/dc/terms/description", object :'"' +  data["stop_desc"]+'"' });
  }
  // geo:lat triple
  if (data["stop_lat"]) {
    this.push({ subject: subject, predicate: "http://www.w3.org/2003/01/geo/wgs84_pos#lat", object :'"' + data["stop_lat"] + '"' });
  }
  // geo:long triple
  if (data["stop_lon"]) {
    this.push({ subject: subject, predicate: "http://www.w3.org/2003/01/geo/wgs84_pos#long", object :'"' + data["stop_lon"] + '"' });
  }
  if (data["stop_url"]) {
    this.push({ subject: subject, predicate: "http://xmlns.com/foaf/0.1/page", object : data["stop_url"] });
  }
  if (data["wheelchair_boarding"]) {
    if (data["wheelchair_boarding"] === "0") {
      this.push({ subject: subject, predicate: "http://vocab.gtfs.org/terms#wheelchairAccessible", object: "http://vocab.gtfs.org/terms#CheckParentStation"});
    } else if (data["wheelchair_boarding"] === "1") {
      this.push({ subject: subject, predicate: "http://vocab.gtfs.org/terms#wheelchairAccessible", object : "http://vocab.gtfs.org/terms#WheelchairAccessible" });
    } else if (data["wheelchair_boarding"] === "2") {
      this.push({ subject: subject, predicate: "http://vocab.gtfs.org/terms#wheelchairAccessible", object : "http://vocab.gtfs.org/terms#NotWheelchairAccessible" });
    }
  }
  done();
};

module.exports = StopsTransformer;
<commit_msg>Fix #14<commit_after>/**
 * @author Pieter Colpaert <pieter.colpaert@okfn.org>
 */
var Transform = require('stream').Transform,
    util = require('util');

util.inherits(StopsTransformer, Transform);

function StopsTransformer (options) {
  this._feedbaseuri = options.baseuri;
  this._options = options;
  Transform.call(this, {objectMode : true});
}

/**
 *  Creates a gtfs:Station or gtfs:Stop with additional properties. Also creates a gtfs:Zone
 */
StopsTransformer.prototype._transform = function (data, encoding, done) {
  var subject = this._feedbaseuri + "/stops/" + data["stop_id"];
   this.push({ subject: subject, predicate: "http://purl.org/dc/terms/identifier", object :'"' +  data["stop_id"]+'"' });
  // gtfs:locationType triple
  if (data["location_type"] && data["location_type"] === "1") {
    this.push({ subject: subject, predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", object: "http://vocab.gtfs.org/terms#Station"});
  } else {
    this.push({ subject: subject, predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", object: "http://vocab.gtfs.org/terms#Stop"});
    //Stations can't have a parent_station, only Stops can have a parent station.
    if (data["parent_station"]) {
      this.push({ subject: subject, predicate: "http://vocab.gtfs.org/terms#parentStation", object :'"' +  data["parent_station"]+'"' });
    }
    if (data["zone_id"]) {
      this.push({ subject: this._feedbaseuri + "/zones/" + data["zone_id"], predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", object : "http://vocab.gtfs.org/terms#Zone" });
      this.push({ subject: subject, predicate: "http://vocab.gtfs.org/terms#zone", object : this._feedbaseuri + "/zones/" + data["zone_id"] });
    }
  }
  // gtfs:code triple
  if (data["stop_code"]) {
    this.push({ subject: subject, predicate: "http://vocab.gtfs.org/terms#code", object :'"' +  data["stop_code"]+'"' });
  }

  // foaf:name triple
  if (data["stop_name"]) {
    this.push({ subject: subject, predicate: "http://xmlns.com/foaf/0.1/name", object :'"' +  data["stop_name"]+'"' });
  }
  if (data["stop_desc"]) {
    this.push({ subject: subject, predicate: "http://purl.org/dc/terms/description", object :'"' +  data["stop_desc"]+'"' });
  }
  // geo:lat triple
  if (data["stop_lat"]) {
    this.push({ subject: subject, predicate: "http://www.w3.org/2003/01/geo/wgs84_pos#lat", object :'"' + data["stop_lat"] + '"' });
  }
  // geo:long triple
  if (data["stop_lon"]) {
    this.push({ subject: subject, predicate: "http://www.w3.org/2003/01/geo/wgs84_pos#long", object :'"' + data["stop_lon"] + '"' });
  }
  if (data["stop_url"]) {
    this.push({ subject: subject, predicate: "http://xmlns.com/foaf/0.1/page", object : data["stop_url"] });
  }
  if (data["wheelchair_boarding"]) {
    if (data["wheelchair_boarding"] === "0") {
      this.push({ subject: subject, predicate: "http://vocab.gtfs.org/terms#wheelchairAccessible", object: "http://vocab.gtfs.org/terms#CheckParentStation"});
    } else if (data["wheelchair_boarding"] === "1") {
      this.push({ subject: subject, predicate: "http://vocab.gtfs.org/terms#wheelchairAccessible", object : "http://vocab.gtfs.org/terms#WheelchairAccessible" });
    } else if (data["wheelchair_boarding"] === "2") {
      this.push({ subject: subject, predicate: "http://vocab.gtfs.org/terms#wheelchairAccessible", object : "http://vocab.gtfs.org/terms#NotWheelchairAccessible" });
    }
  }
  done();
};

module.exports = StopsTransformer;
<|endoftext|>


<commit_before>//       telegram.link
//
//       Copyright 2014 Enrico Stara 'enrico.stara@gmail.com'
//       Released under the MIT license
//       http://telegram.link

//      AbstractObject class
//
// The `AbstractObject` class is an abstraction of the `TypeLanguage Objects and Methods` providing read/write methods to serialize/de-serialize
// the TypeLanguage binary format

// Import dependencies
var logger = require('../util/logger')('type_language.AbstractObject');
var BigInt = require('bignum');

// The constructor may be called giving a `Buffer` with the binary image - eventually starting from an `offset` -
// in order to de-serialize a `TypeLanguage entity` via `read*` methods,
// otherwise you can call it without any argument and start serializing a new one via `write*` methods
function AbstractObject(buffer, offset) {
    if (buffer) {
        this._writeBuffers = null;
        this._readOffset = 0;
        buffer = Buffer.isBuffer(buffer) ? buffer : new Buffer(buffer);
        this._buffer = offset ? buffer.slice(offset) : buffer;
    } else {
        this._writeBuffers = [];
        this._writeOffset = 0;
    }
}

// The base method to de-serialize the object
AbstractObject.prototype.deserialize = function () {
    if (!this.isReadonly()) {
        logger.debug('Unable to de-serialize, the buffer is undefined');
        return false;
    }
    var id = this.readInt();
    if(this.constructor.logger && this.constructor.logger.isDebugEnabled()) {
        this.constructor.logger.debug('read ID = %s', id);
    }
    if (this.id != id) {
        logger.warn('Unable to de-serialize, (read id) %s != (this.id) %s', id, this.id);
        return false;
    }
    return this;
};

// The base method to serialize the object
AbstractObject.prototype.serialize = function () {
    if(this.constructor.logger && this.constructor.logger.isDebugEnabled()) {
        this.constructor.logger.debug('write ID = %s', this.id);
    }
    return this.writeInt(this.id);
};

// The method finalizes the serialization process and retrieves the `Buffer` image of the object,
// putting the instance in `readonly` state
AbstractObject.prototype.retrieveBuffer = function () {
    if (!this._buffer) {
        this._buffer = Buffer.concat(this._writeBuffers);
    }
    this._writeBuffers = null;
    this._writeOffset = 0;
    this._readOffset = 0;
    return this._buffer;
};

AbstractObject.prototype._addWriteBuffer = function (buffer) {
    this._writeBuffers.push(buffer);
    this._writeOffset += buffer.length;
    if(this.constructor.logger && this.constructor.logger.isDebugEnabled()) {
        this.constructor.logger.debug('Write offset %s', this._writeOffset);
    }
};

// The method writes the `int` value given as argument
AbstractObject.prototype.writeInt = function (intValue) {
    if (this.isReadonly()) {
        return false;
    }
    var buffer = new Buffer(4);
    if (intValue < 0) {
        buffer.writeInt32LE(intValue, 0);
    } else {
        buffer.writeUInt32LE(intValue, 0);
    }
    this._addWriteBuffer(buffer);
    return true;
};

// The method writes the `BigInteger` value given as argument, you have to provide the value as `String` type
// and specify a `byte length`, where `length % 4 == 0`
AbstractObject.prototype._writeBigInt = function (bigIntegerAsString, byteLength) {
    if (this.isReadonly() || (byteLength % 4) !== 0) {
        return false;
    }
    var big = ('' + bigIntegerAsString).slice(0, 2) == '0x' ? new BigInt(bigIntegerAsString.slice(2), 16) : new BigInt(bigIntegerAsString, 10);
    var buffer = big.toBuffer({endian: 'little', size: byteLength});
    this._addWriteBuffer(buffer);
    return true;
};

// The method writes the `byte[]` value given as argument,
// adding the bytes length at the beginning
// and adding padding at the end if needed
AbstractObject.prototype.writeBytes = function (bytes, useWordLength) {
    if (this.isReadonly()) {
        return false;
    }
    var bLength = useWordLength ? bytes.length / 4 : bytes.length;
    var isShort = bLength < 0x7F;
    var buffer = new Buffer(isShort ? 1 : 4);
    var offset = 0;
    if (isShort) {
        buffer.writeUInt8(bLength, offset++);
    } else {
        buffer.writeUInt8(0x7F, offset++);
        buffer.writeUInt8(bLength & 0xFF, offset++);
        buffer.writeUInt8((bLength >> 8) & 0xFF, offset++);
        buffer.writeUInt8((bLength >> 16) & 0xFF, offset++);
    }
    this._addWriteBuffer(buffer);
    this._writeBytes(bytes);
    // add padding if needed
    var padding = (offset + bytes.length) % 4;
    if (padding > 0) {
        buffer = new Buffer(4 - padding);
        buffer.fill(0);
        this._addWriteBuffer(buffer);
    }
    return true;
};

// The method writes the `string` value given as argument
AbstractObject.prototype.writeString = function (str) {
    return this.writeBytes(str);
};

// The method writes the `byte[]` value given as argument
AbstractObject.prototype._writeBytes = function (bytes) {
    if (this.isReadonly()) {
        return false;
    }
    var buffer = !Buffer.isBuffer(bytes) ? new Buffer(bytes) : bytes;
    this._addWriteBuffer(buffer);
    return true;
};

// The method writes the `long` value given as argument
AbstractObject.prototype.writeLong = function (bigInteger) {
    return (typeof bigInteger == 'string' || typeof bigInteger == 'number') ? this._writeBigInt(bigInteger, 8) :
        this._writeBytes(bigInteger);
};

// The method writes the `int128` value given as argument
AbstractObject.prototype.writeInt128 = function (bigInteger) {
    return (typeof bigInteger == 'string' || typeof bigInteger == 'number') ? this._writeBigInt(bigInteger, 16) :
        this._writeBytes(bigInteger);
};

// The method writes the `int256` value given as argument
AbstractObject.prototype.writeInt256 = function (bigInteger) {
    return (typeof bigInteger == 'string' || typeof bigInteger == 'number') ? this._writeBigInt(bigInteger, 32) :
        this._writeBytes(bigInteger);
};

// The method reads an `int` value starting from the current position, you may request the value `signed` or not
AbstractObject.prototype.readInt = function (signed) {
    if (!this.isReadonly() || (this._readOffset + 4) > this._buffer.length) {
        return undefined;
    }
    var intValue = signed ? this._buffer.readInt32LE(this._readOffset) : this._buffer.readUInt32LE(this._readOffset);
    // Reading position will be increased of 4
    this._readOffset += 4;
    return intValue;
};

// The method reads a `byte[]` value starting from the current position, using the first byte(s) to get the length
AbstractObject.prototype.readBytes = function (useWordLength) {
    var start = this._readOffset;
    var bLength = this._buffer.readUInt8(this._readOffset++);
    var isShort = bLength < 0x7F;
    if (!isShort) {
        bLength = this._buffer.readUInt8(this._readOffset++) +
            (this._buffer.readUInt8(this._readOffset++) << 8) +
            (this._buffer.readUInt8(this._readOffset++) << 16);
    }
    var buffer = this._readBytes(useWordLength ? bLength * 4 : bLength);
    // consider padding if needed
    this._readOffset += 4 - (this._readOffset - start) % 4;
    return buffer;
};

// The method reads a `string` value starting from the current position
AbstractObject.prototype.readString = function () {
    return this.readBytes().toString('utf8');
};

// The method reads a `byte[]` value starting from the current position
AbstractObject.prototype._readBytes = function (byteLength) {
    var end = this._readOffset + byteLength;
    if (!this.isReadonly() || end > this._buffer.length) {
        return undefined;
    }
    var buffer = this._buffer.slice(this._readOffset, end);
    this._readOffset = end;
    return buffer;
};

// The method reads a `BigInteger` value with a given byte length starting from the current position
AbstractObject.prototype._readBigInt = function (byteLength) {
    var buffer = this._readBytes(byteLength);
    return buffer ? '0x' + BigInt.fromBuffer(buffer, {endian: 'little', size: byteLength}).toString(16) : undefined;
};

// The method reads a `long` value with  starting from the current position
AbstractObject.prototype.readLong = function () {
    return this._readBigInt(8);
};

// The method reads a `int128` value with  starting from the current position
AbstractObject.prototype.readInt128 = function () {
    return this._readBigInt(16);
};

// The method reads a `int256` value with  starting from the current position
AbstractObject.prototype.readInt256 = function () {
    return this._readBigInt(32);
};

// The method checks if the object has been already serialized and then it's `readonly`
AbstractObject.prototype.isReadonly = function () {
    if (this._buffer) {
        return true;
    }
    return false;
};

// The method retrieves the current read position
AbstractObject.prototype.getReadOffset = function () {
    return this._readOffset;
};

// Export the class
module.exports = exports = AbstractObject;
<commit_msg>Fix AbstractObject class<commit_after>//       telegram.link
//
//       Copyright 2014 Enrico Stara 'enrico.stara@gmail.com'
//       Released under the MIT license
//       http://telegram.link

//      AbstractObject class
//
// The `AbstractObject` class is an abstraction of the `TypeLanguage Objects and Methods` providing read/write methods to serialize/de-serialize
// the TypeLanguage binary format

// Import dependencies
var logger = require('../util/logger')('type_language.AbstractObject');
var BigInt = require('bignum');

// The constructor may be called giving a `Buffer` with the binary image - eventually starting from an `offset` -
// in order to de-serialize a `TypeLanguage entity` via `read*` methods,
// otherwise you can call it without any argument and start serializing a new one via `write*` methods
function AbstractObject(buffer, offset) {
    if (buffer) {
        this._writeBuffers = null;
        this._readOffset = 0;
        buffer = Buffer.isBuffer(buffer) ? buffer : new Buffer(buffer);
        this._buffer = offset ? buffer.slice(offset) : buffer;
    } else {
        this._writeBuffers = [];
        this._writeOffset = 0;
    }
}

// The base method to de-serialize the object
AbstractObject.prototype.deserialize = function () {
    if (!this.isReadonly()) {
        logger.debug('Unable to de-serialize, the buffer is undefined');
        return false;
    }
    var id = this.readInt();
    if (this.constructor.logger && this.constructor.logger.isDebugEnabled()) {
        this.constructor.logger.debug('read ID = %s', id);
    }
    if (this.id != id) {
        logger.warn('Unable to de-serialize, (read id) %s != (this.id) %s', id, this.id);
        return false;
    }
    return this;
};

// The base method to serialize the object
AbstractObject.prototype.serialize = function () {
    if (this.constructor.logger && this.constructor.logger.isDebugEnabled()) {
        this.constructor.logger.debug('write ID = %s', this.id);
    }
    return this.writeInt(this.id);
};

// The method finalizes the serialization process and retrieves the `Buffer` image of the object,
// putting the instance in `readonly` state
AbstractObject.prototype.retrieveBuffer = function () {
    if (!this._buffer) {
        this._buffer = Buffer.concat(this._writeBuffers);
    }
    this._writeBuffers = null;
    this._writeOffset = 0;
    this._readOffset = 0;
    return this._buffer;
};

AbstractObject.prototype._addWriteBuffer = function (buffer) {
    this._writeBuffers.push(buffer);
    this._writeOffset += buffer.length;
    if (this.constructor.logger && this.constructor.logger.isDebugEnabled()) {
        this.constructor.logger.debug('Write offset %s', this._writeOffset);
    }
};

// The method writes the `int` value given as argument
AbstractObject.prototype.writeInt = function (intValue) {
    if (this.isReadonly()) {
        return false;
    }
    var buffer = new Buffer(4);
    buffer.writeUInt32LE(intValue, 0, true);
    if (this.constructor.logger && this.constructor.logger.isDebugEnabled()) {
        this.constructor.logger.debug('intValue %s, intBuffer %s', intValue, buffer.toString('hex'));
    }
    this._addWriteBuffer(buffer);
    return true;
};

// The method writes the `BigInteger` value given as argument, you have to provide the value as `String` type
// and specify a `byte length`, where `length % 4 == 0`
AbstractObject.prototype._writeBigInt = function (bigIntegerAsString, byteLength) {
    if (this.isReadonly() || (byteLength % 4) !== 0) {
        return false;
    }
    var big = ('' + bigIntegerAsString).slice(0, 2) == '0x' ? new BigInt(bigIntegerAsString.slice(2), 16) : new BigInt(bigIntegerAsString, 10);
    var buffer = big.toBuffer({endian: 'little', size: byteLength});
    this._addWriteBuffer(buffer);
    return true;
};

// The method writes the `byte[]` value given as argument,
// adding the bytes length at the beginning
// and adding padding at the end if needed
AbstractObject.prototype.writeBytes = function (bytes, useWordLength) {
    if (this.isReadonly()) {
        return false;
    }
    var bLength = useWordLength ? bytes.length / 4 : bytes.length;
    var isShort = bLength < (useWordLength ? 0x7F : 0xFE);
    var buffer = new Buffer(isShort ? 1 : 4);
    var offset = 0;
    if (isShort) {
        buffer.writeUInt8(bLength, offset++);
    } else {
        buffer.writeUInt8((useWordLength ? 0x7F : 0xFE), offset++);
        buffer.writeUInt8(bLength & 0xFF, offset++);
        buffer.writeUInt8((bLength >> 8) & 0xFF, offset++);
        buffer.writeUInt8((bLength >> 16) & 0xFF, offset++);
    }
    this._addWriteBuffer(buffer);
    this._writeBytes(bytes);
    // add padding if needed
    if (!useWordLength) {
        var padding = (offset + bytes.length) % 4;
        if (padding > 0) {
            buffer = new Buffer(4 - padding);
            buffer.fill(0);
            this._addWriteBuffer(buffer);
        }
    }
    return true;
};

// The method writes the `string` value given as argument
AbstractObject.prototype.writeString = function (str) {
    return this.writeBytes(str);
};

// The method writes the `byte[]` value given as argument
AbstractObject.prototype._writeBytes = function (bytes) {
    if (this.isReadonly()) {
        return false;
    }
    var buffer = !Buffer.isBuffer(bytes) ? new Buffer(bytes) : bytes;
    this._addWriteBuffer(buffer);
    return true;
};

// The method writes the `long` value given as argument
AbstractObject.prototype.writeLong = function (bigInteger) {
    return (typeof bigInteger == 'string' || typeof bigInteger == 'number') ? this._writeBigInt(bigInteger, 8) :
        this._writeBytes(bigInteger);
};

// The method writes the `int128` value given as argument
AbstractObject.prototype.writeInt128 = function (bigInteger) {
    return (typeof bigInteger == 'string' || typeof bigInteger == 'number') ? this._writeBigInt(bigInteger, 16) :
        this._writeBytes(bigInteger);
};

// The method writes the `int256` value given as argument
AbstractObject.prototype.writeInt256 = function (bigInteger) {
    return (typeof bigInteger == 'string' || typeof bigInteger == 'number') ? this._writeBigInt(bigInteger, 32) :
        this._writeBytes(bigInteger);
};

// The method reads an `int` value starting from the current position, you may request the value `signed` or not
AbstractObject.prototype.readInt = function (signed) {
    if (!this.isReadonly() || (this._readOffset + 4) > this._buffer.length) {
        return undefined;
    }
    var intValue = signed ? this._buffer.readInt32LE(this._readOffset) : this._buffer.readUInt32LE(this._readOffset);
    // Reading position will be increased of 4
    this._readOffset += 4;
    return intValue;
};

// The method reads a `byte[]` value starting from the current position, using the first byte(s) to get the length
AbstractObject.prototype.readBytes = function (useWordLength) {
    var start = this._readOffset;
    var bLength = this._buffer.readUInt8(this._readOffset++);
    var isShort = bLength < 0x7F;
    if (!isShort) {
        bLength = this._buffer.readUInt8(this._readOffset++) +
            (this._buffer.readUInt8(this._readOffset++) << 8) +
            (this._buffer.readUInt8(this._readOffset++) << 16);
    }
    var buffer = this._readBytes(useWordLength ? bLength * 4 : bLength);
    // consider padding if needed
    this._readOffset += 4 - (this._readOffset - start) % 4;
    return buffer;
};

// The method reads a `string` value starting from the current position
AbstractObject.prototype.readString = function () {
    return this.readBytes().toString('utf8');
};

// The method reads a `byte[]` value starting from the current position
AbstractObject.prototype._readBytes = function (byteLength) {
    var end = this._readOffset + byteLength;
    if (!this.isReadonly() || end > this._buffer.length) {
        return undefined;
    }
    var buffer = this._buffer.slice(this._readOffset, end);
    this._readOffset = end;
    return buffer;
};

// The method reads a `BigInteger` value with a given byte length starting from the current position
AbstractObject.prototype._readBigInt = function (byteLength) {
    var buffer = this._readBytes(byteLength);
    return buffer ? '0x' + BigInt.fromBuffer(buffer, {endian: 'little', size: byteLength}).toString(16) : undefined;
};

// The method reads a `long` value with  starting from the current position
AbstractObject.prototype.readLong = function () {
    return this._readBigInt(8);
};

// The method reads a `int128` value with  starting from the current position
AbstractObject.prototype.readInt128 = function () {
    return this._readBigInt(16);
};

// The method reads a `int256` value with  starting from the current position
AbstractObject.prototype.readInt256 = function () {
    return this._readBigInt(32);
};

// The method checks if the object has been already serialized and then it's `readonly`
AbstractObject.prototype.isReadonly = function () {
    if (this._buffer) {
        return true;
    }
    return false;
};

// The method retrieves the current read position
AbstractObject.prototype.getReadOffset = function () {
    return this._readOffset;
};

// Export the class
module.exports = exports = AbstractObject;
<|endoftext|>


<commit_before>/**
 * Basic Finder Queries
 */

var usageError = require('../../utils/usageError'),
    utils = require('../../utils/helpers'),
    normalize = require('../../utils/normalize'),
    Deferred = require('../deferred'),
    _ = require('underscore');

module.exports = {

  /**
   * Find a single record that meets criteria
   *
   * @param {Object} criteria to search
   * @param {Function} callback
   * @return Deferred object if no callback
   */

  findOne: function(criteria, cb) {
    var self = this;

    if(typeof criteria === 'function') {
      cb = criteria;
      criteria = null;
    }

    // Check if criteria is an integer and normalize criteria
    // to object, using the id field. If something besides
    // an id field is being used as a primary key a where criteria
    // should be used and not an integer.
    if(_.isNumber(criteria)) {
      criteria = { id: criteria };
    }

    // Return Deferred or pass to adapter
    if(typeof cb !== 'function') {
      return new Deferred(this, this.findOne, criteria);
    }

    // Transform Search Criteria
    criteria = self._transformer.serialize(criteria);

    // Pass criteria to adapter definition
    this._adapter.findOne(criteria, function(err, values) {
      if(err) return cb(err);

      // Unserialize values
      values = self._transformer.unserialize(values);

      cb(null, new self._model(values));
    });
  },

  /**
   * Find All Records that meet criteria
   *
   * @param {Object} search criteria
   * @param {Object} options
   * @param {Function} callback
   * @return Deferred object if no callback
   */

  find: function(criteria, options, cb) {
    var self = this;

    var usage = utils.capitalize(this.identity) + '.find([criteria],[options],callback)';

    if(typeof criteria === 'function') {
      cb = criteria;
      criteria = null;
      options = null;
    }

    if(typeof options === 'function') {
      cb = options;
      options = null;
    }

    // Normalize criteria and fold in options
    criteria = normalize.criteria(criteria);
    if(options === Object(options) && criteria === Object(criteria)) {
      criteria = _.extend({}, criteria, options);
    }

    // Validate Arguments
    if(typeof criteria === 'function' || typeof options === 'criteria') {
      return usageError('Invalid options specified!', usage, cb);
    }

    // Return Deferred or pass to adapter
    if(typeof cb !== 'function') {
      return new Deferred(this, this.find, criteria);
    }

    // Transform Search Criteria
    criteria = self._transformer.serialize(criteria);

    // Pass criteria to adapter definition
    this._adapter.find(criteria, function(err, values) {
      if(err) return cb(err);

      var models = [];

      // Make each result an instance of model
      values.forEach(function(value) {

        // Unserialize value
        value = self._transformer.unserialize(value);

        models.push(new self._model(value));
      });

      cb(null, models);
    });
  },

  where: function() {
    this.find.apply(this, Array.prototype.slice.call(arguments));
  },

  select: function() {
    this.find.apply(this, Array.prototype.slice.call(arguments));
  }

};
<commit_msg>allow a string to be passed in as an id to findOne, supports mongo id's<commit_after>/**
 * Basic Finder Queries
 */

var usageError = require('../../utils/usageError'),
    utils = require('../../utils/helpers'),
    normalize = require('../../utils/normalize'),
    Deferred = require('../deferred'),
    _ = require('underscore');

module.exports = {

  /**
   * Find a single record that meets criteria
   *
   * @param {Object} criteria to search
   * @param {Function} callback
   * @return Deferred object if no callback
   */

  findOne: function(criteria, cb) {
    var self = this;

    if(typeof criteria === 'function') {
      cb = criteria;
      criteria = null;
    }

    // Check if criteria is an integer or string and normalize criteria
    // to object, using the id field. If something besides
    // an id field is being used as a primary key a where criteria
    // should be used and not an integer.
    if(_.isNumber(criteria) || _.isString(criteria)) {
      criteria = { id: criteria };
    }

    // Return Deferred or pass to adapter
    if(typeof cb !== 'function') {
      return new Deferred(this, this.findOne, criteria);
    }

    // Transform Search Criteria
    criteria = self._transformer.serialize(criteria);

    // Pass criteria to adapter definition
    this._adapter.findOne(criteria, function(err, values) {
      if(err) return cb(err);

      // Unserialize values
      values = self._transformer.unserialize(values);

      cb(null, new self._model(values));
    });
  },

  /**
   * Find All Records that meet criteria
   *
   * @param {Object} search criteria
   * @param {Object} options
   * @param {Function} callback
   * @return Deferred object if no callback
   */

  find: function(criteria, options, cb) {
    var self = this;

    var usage = utils.capitalize(this.identity) + '.find([criteria],[options],callback)';

    if(typeof criteria === 'function') {
      cb = criteria;
      criteria = null;
      options = null;
    }

    if(typeof options === 'function') {
      cb = options;
      options = null;
    }

    // Normalize criteria and fold in options
    criteria = normalize.criteria(criteria);
    if(options === Object(options) && criteria === Object(criteria)) {
      criteria = _.extend({}, criteria, options);
    }

    // Validate Arguments
    if(typeof criteria === 'function' || typeof options === 'criteria') {
      return usageError('Invalid options specified!', usage, cb);
    }

    // Return Deferred or pass to adapter
    if(typeof cb !== 'function') {
      return new Deferred(this, this.find, criteria);
    }

    // Transform Search Criteria
    criteria = self._transformer.serialize(criteria);

    // Pass criteria to adapter definition
    this._adapter.find(criteria, function(err, values) {
      if(err) return cb(err);

      var models = [];

      // Make each result an instance of model
      values.forEach(function(value) {

        // Unserialize value
        value = self._transformer.unserialize(value);

        models.push(new self._model(value));
      });

      cb(null, models);
    });
  },

  where: function() {
    this.find.apply(this, Array.prototype.slice.call(arguments));
  },

  select: function() {
    this.find.apply(this, Array.prototype.slice.call(arguments));
  }

};
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react'
import Autocomplete from 'react-autocomplete'
import classNames from 'classnames'
import isEqual from 'lodash.isequal'
import PreviewTile from '../common/PreviewTile'
import i18n from '../i18n'

const ResultItem = (item, isHighlighted) => (

    {item.name}

)

const ResultMenu = items =>
{items}

const Preview = (latitude, longitude, markerIcon) => (
  <PreviewTile
    latitude={Number(latitude)}
    longitude={Number(longitude)}
    markerIcon={markerIcon}
  />
)

const formatDisplayValue = ({ address, city }) => {
  if (address && city) {
    return `${address}, ${city}`
  }
  return city || address || ''
}

class GeocoderSearch extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      value: {},
      initialValue: ''
    }
  }

  componentWillReceiveProps({ input, displayValue }) {
    if (!this.state.itemSelected) {
      this.setState({ displayValue })
    }

    if (input.value && !isEqual(input.value, this.state.value)) {
      this.setState({
        displayValue: formatDisplayValue(input.value),
        value: {
          latitude: input.value.latitude,
          longitude: input.value.longitude,
          city: input.value.city,
          address: input.value.address
        }
      })
    }
  }

  handleSelect = (event, value) => {
    this.props.onSelect(value.id)
  }

  handleChange = (event, value) => {
    this.setState({ itemSelected: false })
    this.props.onAutocomplete(value)
  }

  render() {
    const error = this.props.meta.error
    const position = this.props.geocodePosition
    const lat = position && position.lat
    const lon = position && position.lon

    const wrapperClassNames = classNames({
      'geocoder-search': true,
      'form-input-error': error
    })

    return (

          {this.props.label}

          <Autocomplete
            inputProps={{
              name: this.props.input.name,
              className: 'geocoder-search-input',
              placeholder: i18n.t('geocoder.placeholder')
            }}
            renderItem={ResultItem}
            renderMenu={ResultMenu}
            onChange={this.handleChange}
            onSelect={this.handleSelect}
            items={this.props.geocoderItems}
            getItemValue={item => item.name}
            value={this.state.displayValue}
          />
          {lat && lon && Preview(lat, lon, this.props.markerIcon)}

        {error &&
{error}
}

{i18n.t('geocoder.help')}

{i18n.t('geocoder.explanation')}

    )
  }
}

GeocoderSearch.propTypes = {
  input: PropTypes.shape({
    name: PropTypes.string,
    onChange: PropTypes.func,
    // TODO what is going on here, both object and string are set?
    value: PropTypes.any
  }).isRequired,
  meta: PropTypes.shape({
    error: PropTypes.string
  }),
  displayValue: PropTypes.string.isRequired,
  label: PropTypes.string.isRequired,
  required: PropTypes.bool,
  markerIcon: PropTypes.oneOf(['Depot', 'Farm', 'Initiative']).isRequired,
  onAutocomplete: PropTypes.func.isRequired,
  onSelect: PropTypes.func.isRequired,
  geocoderItems: PropTypes.arrayOf(PropTypes.object).isRequired,
  geocodePosition: PropTypes.shape({
    lat: PropTypes.number.isRequired,
    lon: PropTypes.number.isRequired
  })
}

GeocoderSearch.defaultProps = {
  required: false,
  meta: {}
}

export default GeocoderSearch
<commit_msg>Autocomplete: Simplify data handling in geocoder form component<commit_after>import React, { PropTypes } from 'react'
import Autocomplete from 'react-autocomplete'
import classNames from 'classnames'
import PreviewTile from '../common/PreviewTile'
import i18n from '../i18n'

const ResultItem = (item, isHighlighted) => (

    {item.name}

)

const ResultMenu = items =>
{items}

const Preview = (latitude, longitude, markerIcon) => (
  <PreviewTile
    latitude={Number(latitude)}
    longitude={Number(longitude)}
    markerIcon={markerIcon}
  />
)

class GeocoderSearch extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      value: {},
      displayValue: ''
    }
  }

  componentWillReceiveProps({ geocodePosition }) {
    if (geocodePosition) {
      this.setState({
        displayValue: geocodePosition.name,
        value: {
          name: geocodePosition.name,
          latitude: geocodePosition.lat,
          longitude: geocodePosition.lon,
          address: geocodePosition.address,
          city: geocodePosition.city,
          country: geocodePosition.country
        }
      })
    }
  }

  handleSelect = (event, value) => {
    this.props.onSelect(value.id)
  }

  handleChange = (event, value) => {
    this.setState({ displayValue: value })
    this.props.onAutocomplete(value)
  }

  render() {
    const error = this.props.meta.error
    const value = this.state.value
    const lat = value && value.latitude
    const lon = value && value.longitude

    const wrapperClassNames = classNames({
      'geocoder-search': true,
      'form-input-error': error
    })

    return (

          {this.props.label}

          <Autocomplete
            inputProps={{
              name: this.props.input.name,
              className: 'geocoder-search-input',
              placeholder: i18n.t('geocoder.placeholder')
            }}
            renderItem={ResultItem}
            renderMenu={ResultMenu}
            onChange={this.handleChange}
            onSelect={this.handleSelect}
            items={this.props.geocoderItems}
            getItemValue={item => item.name}
            value={this.state.displayValue}
          />
          {lat && lon && Preview(lat, lon, this.props.markerIcon)}

        {error &&
{error}
}

{i18n.t('geocoder.help')}

{i18n.t('geocoder.explanation')}

    )
  }
}

GeocoderSearch.propTypes = {
  input: PropTypes.shape({
    name: PropTypes.string,
    onChange: PropTypes.func,
    // TODO what is going on here, both object and string are set?
    value: PropTypes.any
  }).isRequired,
  meta: PropTypes.shape({
    error: PropTypes.string
  }),
  label: PropTypes.string.isRequired,
  required: PropTypes.bool,
  markerIcon: PropTypes.oneOf(['Depot', 'Farm', 'Initiative']).isRequired,
  onAutocomplete: PropTypes.func.isRequired,
  onSelect: PropTypes.func.isRequired,
  geocoderItems: PropTypes.arrayOf(PropTypes.object).isRequired,
  geocodePosition: PropTypes.shape({
    lat: PropTypes.number.isRequired,
    lon: PropTypes.number.isRequired
  })
}

GeocoderSearch.defaultProps = {
  required: false,
  meta: {}
}

export default GeocoderSearch
<|endoftext|>


<commit_before>Template.errors.helpers({
  errors: function() {
    return Errors.find();
  }
});<commit_msg>Clear errors after 3 seconds.<commit_after>Template.errors.helpers({
  errors: function() {
    return Errors.find();
  }
});

Template.error.onRendered(function() {
  var error = this.data;
  Meteor.setTimeout(function () {
    Errors.remove(error._id);
  }, 3000);
});<|endoftext|>


<commit_before>Template.setList.helpers({
    gameSets: function() {
      return Sets.find();
    }
});

Template.results.helpers({
  randomCards: function() {
    return roleSet.find();
  }
});

Template.results.created = function() {
  // Create local collection to store randomized result
  roleSet = new Mongo.Collection(null);
};

Array.prototype.randomElement = function () {
    var randIndex;
    randIndex = Math.floor(Math.random() * this.length);
    return this.splice(randIndex)[0];
};

Template.randomize.events({
  'click #doRandomize': function(event, template) {
    var numPlayers = parseInt($("#numPlayers").val(),10);
    var numWolves  = parseInt($("#numWolves").val(),10);
    numPlayers = numPlayers + 3;

    // Empty existing set in collection
    roleSet.remove({});

    // Get all sets that are checked
    var sets = [];
    $("input:checkbox").each(function() {
      var $this = $(this);
      if ($this.is(":checked")) {
        sets.push($this.attr("id"));
      }
    });

    // Now that we have all the sets, lets get all of the cards
    var cards = [];
    _.each(sets, function(element) {
    $.merge(cards, Sets.findOne({_id: element}).cards);
    });

    // Filter out villager and werewolf roles
    var werewolves = [];
    var villagers = [];
    werewolves = _.filter(cards, function(card) {return card.team === "werewolf";});
    villagers  = _.filter(cards, function(card) {return card.team === "villager";});

    // Get random werewolf cards
    var randomSet = [];
    $.merge(randomSet, _.sample(werewolves, numWolves));
    numPlayers -= numWolves;

    // Check to see if we have an alpha-wolf, if so add another wolf
    if (_.some(randomSet, function(elem) {return elem.name === "Alpha Wolf";})) {
      randomSet.push(_.sample(_.difference(werewolves, randomSet), 1)[0]);
    }

    // Get remaining villager cards
    $.merge(randomSet, _.sample(villagers, numPlayers));

    // Add to roleSet local collection
    _.each(randomSet, function(elem){
      roleSet.insert(elem);
    });

    console.log(numPlayers);
    console.log(randomSet);
  }
});<commit_msg>Added mason handling logic<commit_after>Template.setList.helpers({
    gameSets: function() {
      return Sets.find();
    }
});

Template.results.helpers({
  randomCards: function() {
    return roleSet.find();
  }
});

Template.results.created = function() {
  // Create local collection to store randomized result
  roleSet = new Mongo.Collection(null);
};

Array.prototype.randomElement = function () {
    var randIndex;
    randIndex = Math.floor(Math.random() * this.length);
    return this.splice(randIndex)[0];
};

Template.randomize.events({
  'click #doRandomize': function(event, template) {
    var numPlayers = parseInt($("#numPlayers").val(),10);
    var numWolves  = parseInt($("#numWolves").val(),10);
    numPlayers = numPlayers + 3;

    // Empty existing set in collection
    roleSet.remove({});

    // Get all sets that are checked
    var sets = [];
    $("input:checkbox").each(function() {
      var $this = $(this);
      if ($this.is(":checked")) {
        sets.push($this.attr("id"));
      }
    });

    // Now that we have all the sets, lets get all of the cards
    var cards = [];
    _.each(sets, function(element) {
    $.merge(cards, Sets.findOne({_id: element}).cards);
    });

    // Filter out villager and werewolf roles
    var werewolves = [];
    var villagers = [];
    werewolves = _.filter(cards, function(card) {return card.team === "werewolf";});
    villagers  = _.filter(cards, function(card) {return card.team === "villager";});

    // Get random werewolf cards
    var randomSet = [];
    $.merge(randomSet, _.sample(werewolves, numWolves));
    numPlayers -= numWolves;

    // Check to see if we have an alpha-wolf, if so add another wolf
    if (_.some(randomSet, function(elem) {return elem.name === "Alpha Wolf";})) {
      randomSet.push(_.sample(_.difference(werewolves, randomSet), 1)[0]);
    }

    // Get remaining villager cards
    $.merge(randomSet, _.sample(villagers, numPlayers));

    // Check to see if we have a single mason, if so, give him a friend
    if (_.reduce(randomSet, function(memo, card){return memo + (card.name === "Mason" ? 1 : 0);},0) === 1) {
      // Villager to replace with a mason
      var sacrificialVillager = _.find(randomSet, function(card){
        return (card.team === "villager" && card.name !== "Mason");
      });
      console.log(sacrificialVillager);

      randomSet.splice(_.indexOf(randomSet, sacrificialVillager), 1, {name: "Mason", team: "villager"});
    }

    // Add to roleSet local collection
    _.each(randomSet, function(elem){
      roleSet.insert(elem);
    });
  }
});<|endoftext|>


<commit_before>
var twitter = require('./lib/twitter');
var select_options = require('../../lib/options');

module.exports = {

    name: 'twitter',

    label: 'Twitter',

    image_url: 'assets/content/modules/twitter.png',

    config: {
        position: '',
        title: '',
        panel: '',
        opacity: 1,
        fullwidth: false,
        template: 'list',
        count: 5,
        search_term: '',
        text: {
            color: '',
            size: ''
        }
    },

    fields: {
        config: {
            'search_term': {
                type: 'text',
                label: 'Zoekterm',
                attrs: {'class': 'uk-form-width-medium'}
            },
            'count': {
                type: 'number',
                label: 'Aantal tweets',
                attrs: {'class': 'uk-form-width-small uk-text-right', min: 0, max: 30}
            },
            'text.color': {
                type: 'select',
                label: 'Tekstkleur',
                options: select_options.text_color,
                attrs: {'class': 'uk-form-width-medium'}
            },
            'text.size': {
                type: 'select',
                label: 'Tekstgrootte',
                options: select_options.text_size,
                attrs: {'class': 'uk-form-width-medium'}
            }
        },
        advanced_1: {
        }
    },

    commands: {
        getTweets(config, params, cb) {
            if (!params.search_term) {
                return cb(null,  []);
            }
            twitter.search(params.search_term, params.count)
                .then(tweets => cb(null, {tweets}))
                .catch(err => cb(err));
        }
    }
};<commit_msg>Changed getTweets commands.<commit_after>
var twitter = require('./lib/twitter');
var select_options = require('../../lib/options');

module.exports = {

    name: 'twitter',

    label: 'Twitter',

    image_url: 'assets/content/modules/twitter.png',

    config: {
        position: '',
        title: '',
        panel: '',
        opacity: 1,
        fullwidth: false,
        template: 'list',
        count: 5,
        search_term: '',
        text: {
            color: '',
            size: ''
        }
    },

    fields: {
        config: {
            'search_term': {
                type: 'text',
                label: 'Zoekterm',
                attrs: {'class': 'uk-form-width-medium'}
            },
            'count': {
                type: 'number',
                label: 'Aantal tweets',
                attrs: {'class': 'uk-form-width-small uk-text-right', min: 0, max: 30}
            },
            'text.color': {
                type: 'select',
                label: 'Tekstkleur',
                options: select_options.text_color,
                attrs: {'class': 'uk-form-width-medium'}
            },
            'text.size': {
                type: 'select',
                label: 'Tekstgrootte',
                options: select_options.text_size,
                attrs: {'class': 'uk-form-width-medium'}
            }
        },
        advanced_1: {
        }
    },

    commands: {
        getTweets(config, params, cb) {
            if (!config.search_term) {
                return cb(null, {
                    error: 'Geen search term bekend.',
                    tweets: {}
                });
            }
            twitter.search(params.search_term, params.count),
                (err, tweets) => {
                    if (err) {
                        //todo retry/return cache
                        return cb(err);
                    }
                    cb(null, {error: false, tweets});
                });
        }
    }
};<|endoftext|>


<commit_before>// Copyright 2006 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview An object that encapsulates text changed events for textareas
 * and input element of type text and password. The event occurs after the value
 * has been changed. The event does not occur if value was changed
 * programmatically.

 *

 * Note: this does not guarantee the correctness of {@code keyCode} or
 * {@code charCode}, or attempt to unify them across browsers. See
 * {@code goog.events.KeyHandler} for that functionality.

 *

 * Known issues:
 *

 *
Does not trigger for drop events on Opera due to browser bug.
 *
IE doesn't have native support for input event. WebKit before version 531
 *     doesn't have support for textareas. For those browsers an emulation mode
 *     based on key, clipboard and drop events is used. Thus this event won't
 *     trigger in emulation mode if text was modified by context menu commands
 *     such as 'Undo' and 'Delete'.
 *

 * @see ../demos/inputhandler.html
 */

goog.provide('goog.events.InputHandler');
goog.provide('goog.events.InputHandler.EventType');

goog.require('goog.Timer');
goog.require('goog.dom');
goog.require('goog.events');
goog.require('goog.events.BrowserEvent');
goog.require('goog.events.EventHandler');
goog.require('goog.events.EventTarget');
goog.require('goog.events.KeyCodes');
goog.require('goog.userAgent');

/**
 * This event handler will dispatch events when the user types into a text
 * input, password input or a textarea
 * @param {Element} element  The element that you want to listen for input
 *     events on.
 * @constructor
 * @extends {goog.events.EventTarget}
 */
goog.events.InputHandler = function(element) {
  goog.events.EventTarget.call(this);

  /**
   * The element that you want to listen for input events on.
   * @type {Element}
   * @private
   */
  this.element_ = element;

  /**
   * Whether input event is emulated.
   * IE doesn't support input events. We could use property change events but
   * they are broken in many ways:
   * - Fire even if value was changed programmatically.
   * - Aren't always delivered. For example, if you change value or even width
   *   of input programmatically, next value change made by user won't fire an
   *   event.
   * WebKit before version 531 did not support input events for textareas.
   * @type {boolean}
   * @private
   */
  this.inputEventEmulation_ =
      goog.userAgent.IE ||
      (goog.userAgent.WEBKIT && !goog.userAgent.isVersion('531') &&
          element.tagName == 'TEXTAREA');

  /**
   * @type {goog.events.EventHandler}
   * @private
   */
  this.eventHandler_ = new goog.events.EventHandler();
  this.eventHandler_.listen(
      this.element_,
      this.inputEventEmulation_ ? ['keydown', 'paste', 'cut', 'drop'] : 'input',
      this);
};
goog.inherits(goog.events.InputHandler, goog.events.EventTarget);

/**
 * Enum type for the events fired by the input handler
 * @enum {string}
 */
goog.events.InputHandler.EventType = {
  INPUT: 'input'
};

/**
 * Id of a timer used to postpone firing input event in emulation mode.
 * @type {?number}
 * @private
 */
goog.events.InputHandler.prototype.timer_ = null;

/**
 * This handles the underlying events and dispatches a new event as needed.
 * @param {goog.events.BrowserEvent} e The underlying browser event.
 */
goog.events.InputHandler.prototype.handleEvent = function(e) {
  if (this.inputEventEmulation_) {
    // Filter out key events that don't modify text.
    if (e.type == 'keydown' &&
        !goog.events.KeyCodes.isTextModifyingKeyEvent(e)) {
      return;
    }

    // It is still possible that pressed key won't modify the value of an
    // element. Storing old value will help us to detect modification but is
    // also a little bit dangerous. If value is changed programmatically in
    // another key down handler, we will detect it as user-initiated change.
    var valueBeforeKey = e.type == 'keydown' ? this.element_.value : null;

    // In IE on XP, IME the element's value has already changed when we get
    // keydown events when the user is using an IME. In this case, we can't
    // check the current value normally, so we assume that it's a modifying key
    // event. This means that ENTER when used to commit will fire a spurious
    // input event, but it's better to have a false positive than let some input
    // slip through the cracks.
    if (goog.userAgent.IE && e.keyCode == goog.events.KeyCodes.WIN_IME) {
      valueBeforeKey = null;
    }

    // Create an input event now, because when we fire it on timer, the
    // underlying event will already be disposed.
    var inputEvent = this.createInputEvent_(e);

    // Since key down, paste, cut and drop events are fired before actual value
    // of the element has changed, we need to postpone dispatching input event
    // until value is updated.
    this.cancelTimerIfSet_();
    this.timer_ = goog.Timer.callOnce(function() {
      this.timer_ = null;
      if (this.element_.value != valueBeforeKey) {
        this.dispatchAndDisposeEvent_(inputEvent);
      }
    }, 0, this);
  } else {
    // Unlike other browsers, Opera fires an extra input event when an element
    // is blurred after the user has input into it. Since Opera doesn't fire
    // input event on drop, it's enough to check whether element still has focus
    // to suppress bogus notification.
    if (!goog.userAgent.OPERA || this.element_ ==
        goog.dom.getOwnerDocument(this.element_).activeElement) {
      this.dispatchAndDisposeEvent_(this.createInputEvent_(e));
    }
  }
};

/**
 * Cancels timer if it is set, does nothing otherwise.
 * @private
 */
goog.events.InputHandler.prototype.cancelTimerIfSet_ = function() {
  if (this.timer_ != null) {
    goog.Timer.clear(this.timer_);
    this.timer_ = null;
  }
};

/**
 * Creates an input event from the browser event.
 * @param {goog.events.BrowserEvent} be A browser event.
 * @return {goog.events.BrowserEvent} An input event.
 * @private
 */
goog.events.InputHandler.prototype.createInputEvent_ = function(be) {
  var e = new goog.events.BrowserEvent(be.getBrowserEvent());
  e.type = goog.events.InputHandler.EventType.INPUT;
  return e;
};

/**
 * Dispatches and disposes an event.
 * @param {goog.events.BrowserEvent} event Event to dispatch.
 * @private
 */
goog.events.InputHandler.prototype.dispatchAndDisposeEvent_ = function(event) {
  try {
    this.dispatchEvent(event);
  } finally {
    event.dispose();
  }
};

/**
 * Disposes of the input handler.
 */
goog.events.InputHandler.prototype.disposeInternal = function() {
  goog.events.InputHandler.superClass_.disposeInternal.call(this);
  this.eventHandler_.dispose();
  this.cancelTimerIfSet_();
  delete this.element_;
};
<commit_msg><commit_after>// Copyright 2006 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview An object that encapsulates text changed events for textareas
 * and input element of type text and password. The event occurs after the value
 * has been changed. The event does not occur if value was changed
 * programmatically.

 *

 * Note: this does not guarantee the correctness of {@code keyCode} or
 * {@code charCode}, or attempt to unify them across browsers. See
 * {@code goog.events.KeyHandler} for that functionality.

 *

 * Known issues:
 *

 *
Does not trigger for drop events on Opera due to browser bug.
 *
IE doesn't have native support for input event. WebKit before version 531
 *     doesn't have support for textareas. For those browsers an emulation mode
 *     based on key, clipboard and drop events is used. Thus this event won't
 *     trigger in emulation mode if text was modified by context menu commands
 *     such as 'Undo' and 'Delete'.
 *

 * @see ../demos/inputhandler.html
 */

goog.provide('goog.events.InputHandler');
goog.provide('goog.events.InputHandler.EventType');

goog.require('goog.Timer');
goog.require('goog.dom');
goog.require('goog.events');
goog.require('goog.events.BrowserEvent');
goog.require('goog.events.EventHandler');
goog.require('goog.events.EventTarget');
goog.require('goog.events.KeyCodes');
goog.require('goog.userAgent');

/**
 * This event handler will dispatch events when the user types into a text
 * input, password input or a textarea
 * @param {Element} element  The element that you want to listen for input
 *     events on.
 * @constructor
 * @extends {goog.events.EventTarget}
 */
goog.events.InputHandler = function(element) {
  goog.events.EventTarget.call(this);

  /**
   * The element that you want to listen for input events on.
   * @type {Element}
   * @private
   */
  this.element_ = element;

  /**
   * Whether input event is emulated.
   * IE doesn't support input events. We could use property change events but
   * they are broken in many ways:
   * - Fire even if value was changed programmatically.
   * - Aren't always delivered. For example, if you change value or even width
   *   of input programmatically, next value change made by user won't fire an
   *   event.
   * WebKit before version 531 did not support input events for textareas.
   * @type {boolean}
   * @private
   */
  this.inputEventEmulation_ =
      goog.userAgent.IE ||
      (goog.userAgent.WEBKIT && !goog.userAgent.isVersion('531') &&
          element.tagName == 'TEXTAREA');

  /**
   * @type {goog.events.EventHandler}
   * @private
   */
  this.eventHandler_ = new goog.events.EventHandler(this);
  this.eventHandler_.listen(
      this.element_,
      this.inputEventEmulation_ ? ['keydown', 'paste', 'cut', 'drop'] : 'input',
      this);
};
goog.inherits(goog.events.InputHandler, goog.events.EventTarget);

/**
 * Enum type for the events fired by the input handler
 * @enum {string}
 */
goog.events.InputHandler.EventType = {
  INPUT: 'input'
};

/**
 * Id of a timer used to postpone firing input event in emulation mode.
 * @type {?number}
 * @private
 */
goog.events.InputHandler.prototype.timer_ = null;

/**
 * This handles the underlying events and dispatches a new event as needed.
 * @param {goog.events.BrowserEvent} e The underlying browser event.
 */
goog.events.InputHandler.prototype.handleEvent = function(e) {
  if (this.inputEventEmulation_) {
    // Filter out key events that don't modify text.
    if (e.type == 'keydown' &&
        !goog.events.KeyCodes.isTextModifyingKeyEvent(e)) {
      return;
    }

    // It is still possible that pressed key won't modify the value of an
    // element. Storing old value will help us to detect modification but is
    // also a little bit dangerous. If value is changed programmatically in
    // another key down handler, we will detect it as user-initiated change.
    var valueBeforeKey = e.type == 'keydown' ? this.element_.value : null;

    // In IE on XP, IME the element's value has already changed when we get
    // keydown events when the user is using an IME. In this case, we can't
    // check the current value normally, so we assume that it's a modifying key
    // event. This means that ENTER when used to commit will fire a spurious
    // input event, but it's better to have a false positive than let some input
    // slip through the cracks.
    if (goog.userAgent.IE && e.keyCode == goog.events.KeyCodes.WIN_IME) {
      valueBeforeKey = null;
    }

    // Create an input event now, because when we fire it on timer, the
    // underlying event will already be disposed.
    var inputEvent = this.createInputEvent_(e);

    // Since key down, paste, cut and drop events are fired before actual value
    // of the element has changed, we need to postpone dispatching input event
    // until value is updated.
    this.cancelTimerIfSet_();
    this.timer_ = goog.Timer.callOnce(function() {
      this.timer_ = null;
      if (this.element_.value != valueBeforeKey) {
        this.dispatchAndDisposeEvent_(inputEvent);
      }
    }, 0, this);
  } else {
    // Unlike other browsers, Opera fires an extra input event when an element
    // is blurred after the user has input into it. Since Opera doesn't fire
    // input event on drop, it's enough to check whether element still has focus
    // to suppress bogus notification.
    if (!goog.userAgent.OPERA || this.element_ ==
        goog.dom.getOwnerDocument(this.element_).activeElement) {
      this.dispatchAndDisposeEvent_(this.createInputEvent_(e));
    }
  }
};

/**
 * Cancels timer if it is set, does nothing otherwise.
 * @private
 */
goog.events.InputHandler.prototype.cancelTimerIfSet_ = function() {
  if (this.timer_ != null) {
    goog.Timer.clear(this.timer_);
    this.timer_ = null;
  }
};

/**
 * Creates an input event from the browser event.
 * @param {goog.events.BrowserEvent} be A browser event.
 * @return {goog.events.BrowserEvent} An input event.
 * @private
 */
goog.events.InputHandler.prototype.createInputEvent_ = function(be) {
  var e = new goog.events.BrowserEvent(be.getBrowserEvent());
  e.type = goog.events.InputHandler.EventType.INPUT;
  return e;
};

/**
 * Dispatches and disposes an event.
 * @param {goog.events.BrowserEvent} event Event to dispatch.
 * @private
 */
goog.events.InputHandler.prototype.dispatchAndDisposeEvent_ = function(event) {
  try {
    this.dispatchEvent(event);
  } finally {
    event.dispose();
  }
};

/**
 * Disposes of the input handler.
 */
goog.events.InputHandler.prototype.disposeInternal = function() {
  goog.events.InputHandler.superClass_.disposeInternal.call(this);
  this.eventHandler_.dispose();
  this.cancelTimerIfSet_();
  delete this.element_;
};
<|endoftext|>