<commit_before>// Copyright 2014 Technical Machine, Inc. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

var util = require('util');
var EventEmitter = require('events').EventEmitter;
var Attiny = require('attiny-common');
var MODULE_ID = 0x08;
var TINY44_SIGNATURE = 0x9207;
var FIRMWARE_FILE = __dirname + '/firmware/src/ambient-attx4.hex';

// Max 10 (16 bit) data chunks
var AMBIENT_BUF_SIZE = 10 * 2;
var AMBIENT_SINGLE_BYTE = 1 * 2;
var MAX_AMBIENT_VALUE = 1024;

// Confirmation Signals
var PACKET_CONF = 0x55;
var ACK_CONF = 0x33;
var FIN_CONF = 0x16;

var LIGHT_CMD = 2;
var SOUND_CMD = 3;
var LIGHT_TRIGGER_CMD = 4;
var SOUND_TRIGGER_CMD = 5;
var FETCH_TRIGGER_CMD = 6;

// These should be updated with each firmware release
var FIRMWARE_VERSION = 0x03;
var CRC = 0x1eb5;

function Ambient(hardware, callback) {

  // Create a new instance of an attiny
  this.attiny = new Attiny(hardware);

  // Global connected. We may use this in the future
  this.connected = false;

  this.lightTriggerLevel = null;

  this.soundTriggerLevel = null;

  // milliSeconds between reads
  this.pollingFrequency = 500;
  this.lightPolling = false;
  this.soundPolling = false;
  this.pollInterval = undefined;

  var self = this;

  // Store our firmware checking and updating options
  var firmwareOptions = {
    firmwareFile : FIRMWARE_FILE,
    firmwareVersion : FIRMWARE_VERSION,
    moduleID : MODULE_ID,
    signature : TINY44_SIGNATURE,
    crc : CRC,
  }
  // Make sure we can communicate with the module
  self.attiny.initialize(firmwareOptions, function(err) {
    if (err) {
      // Emit the error
      self.emit('error', err);

      // Call the callback with an error
      if (callback) {
        callback(err);
      }

      return;
    }
    else {

      self.connected = true;

      // If someone starts listening
      self.on('newListener', function(event) {
        // and there weren't listeners before
        if (!self.listeners(event).length)
        {
          // start retrieving data for this type of buffer
          self._setListening(true, event);
        }
      });

      // if someone stops listening
      self.on('removeListener', function(event)
      {
        // and there are none left
        if (!self.listeners(event).length)
        {
          // stop retrieving data
          self._setListening(false, event);
        }
      });

      setImmediate(function () {
        // Emit a ready event
        self.emit('ready');
        // Start listening for IRQ interrupts
        self.irqwatcher = self._fetchTriggerValues.bind(self);
        self.attiny.setIRQCallback(self.irqwatcher);

      });

      if (callback) {
        callback(null, self);
      }
    }
  });
}

// We want the ability to emit events
util.inherits(Ambient, EventEmitter);

Ambient.prototype._fetchTriggerValues = function() {

  var self = this;

  // cmd, cmd_echo, light_val (16 bits), sound_val (16 bits)
  var packet = new Buffer([FETCH_TRIGGER_CMD, 0x00, 0x00, 0x00, 0x00, 0x00]);

  // transceive the command
  self.attiny.transceive(packet, function spiComplete(err, response) {
    if (self.attiny._validateResponse(response, [PACKET_CONF, FETCH_TRIGGER_CMD]))
    {
      // make a buffer with the cmd and cmd_echo spliced out
      var data = new Buffer(response.slice(2, response.length));
      // Read values
      var lightTriggerValue = self._normalizeValue(data.readUInt16BE(0));
      var soundTriggerValue = self._normalizeValue(data.readUInt16BE(2));

      if (lightTriggerValue && self.lightTriggerLevel)
      {
        self.emit('light-trigger', lightTriggerValue);
      }
      if (soundTriggerValue && self.soundTriggerLevel)
      {
        self.emit('sound-trigger', soundTriggerValue);
      }

      setImmediate(function() {
        self.irqwatcher = self._fetchTriggerValues.bind(self);
        self.attiny.setIRQCallback(self.irqwatcher);
      });
    }
    else
    {
      console.warn("Warning... Invalid trigger values fetched...");
    }
  });
};

Ambient.prototype._getSingleDatum = function(command, callback) {

  // Read the buffer but only 1 16-bit wordbyte
  this._readBuffer(command, AMBIENT_SINGLE_BYTE, callback);
};

Ambient.prototype._normalizeBuffer = function(buf) {
  var numUInt16 = buf.length/2;
  var ret = new Array(numUInt16);

  for (var i = 0; i < numUInt16; i++) {
    ret[i] = this._normalizeValue(buf.readUInt16BE(i*2));
  }

  return ret;
};

Ambient.prototype._normalizeValue = function(value) {
  return (value/MAX_AMBIENT_VALUE);
};

Ambient.prototype._pollBuffers = function(cb) {
  var self = this;

  if (!self.connected) {
    self._establishCommunication(5, function(err) {
      if (err) {
        self.emit('error', new Error("Can't communicate with Ambient module..."));
      }
    });
  }
  if (self.lightPolling)
  {
    self.getLightBuffer(cb);
  }
  if (self.soundPolling)
  {
    self.getSoundBuffer(cb);
  }
};

Ambient.prototype._readBuffer = function(command, readLen, callback) {

  var self = this;

  // Create a packet with header, data bytes (16 bits) and stop byte
  var header = new Buffer([command, readLen/2, 0x00]);

  var bytes = new Buffer(readLen);
  bytes.fill(0);

  var stop = new Buffer(1);
  stop.writeUInt8(FIN_CONF, 0);

  var packet = Buffer.concat([header, bytes, stop]);

  // Synchronously transceive command to read
  self.attiny.transceive(packet, function spiComplete(err, data) {
    // If the response is valid
    if (self.attiny._validateResponse(data, [PACKET_CONF, command, readLen/2]) &&
      data[data.length-1] === FIN_CONF) {

      data = self._normalizeBuffer(data.slice(header.length, data.length-1));

      if (data.length === 1) {
        data = data[0];
      }

      var event = (command == LIGHT_CMD ? "light" : "sound");

      self.emit(event, data);

      // Return data
      if (callback) {
        callback(null, data);
      }

      return data;
    }
    else {

      var err = new Error("Invalid response from Ambient module");

      if (callback) {
        callback(err);
      }
    }
  });
};

Ambient.prototype._setListening = function(enable, event) {
  var self = this;
  this._pollTimeout = null;
  if (event === "light") {
    this.lightPolling = enable;
  } else if (event === "sound") {
    this.soundPolling = enable;
  } else {
    return;
  }

  // if the other buffer is not already polling
  if (event === "light" && !this.soundPolling ||
      event === "sound" && !this.lightPolling) {

    function pollBuffers() {
      self._pollBuffers(function(){
        self._pollTimeout = setTimeout(pollBuffers, self.pollingFrequency);
      });
    }

    if (enable && self._pollTimeout == null) {
      pollBuffers();
    } else if (!enable && self._pollTimeout !== null) {
      // stop polling
      clearTimeout(self._pollTimeout);
      self._pollTimeout = null;
      if(this.irqwatcher) {
        this.attiny.irq.removeListener('high', this.irqwatcher);
      }
    }
  }
};

Ambient.prototype.disable = function () {
  this._setListening(false, 'light');
  this._setListening(false, 'sound');
};

Ambient.prototype._setTrigger = function(triggerCmd, triggerVal, callback) {

  var self = this;

  // Make the packet
  triggerVal = Math.ceil(triggerVal * MAX_AMBIENT_VALUE);

  var dataBuffer = new Buffer(2);
  dataBuffer.writeUInt16BE(triggerVal, 0);

  var packet = new Buffer([triggerCmd, dataBuffer.readUInt8(0), dataBuffer.readUInt8(1), 0x00]);

  // Send it over SPI
  self.attiny.transceive(packet, function spiComplete(err, data) {
    // If it's a valud response
    if (self.attiny._validateResponse(data, [PACKET_CONF, triggerCmd, dataBuffer.readUInt8(0), dataBuffer.readUInt8(1)]))
    {

      // Get the event title
      var event = (triggerCmd == LIGHT_TRIGGER_CMD ? "light-trigger-set" : "sound-trigger-set");

      // Store the trigger value locally
      if (triggerCmd == LIGHT_TRIGGER_CMD)
      {
        self.lightTriggerLevel = triggerVal;
      }
      else
      {
        self.soundTriggerLevel = triggerVal;
      }

      // Emit the event
      self.emit(event, triggerVal / MAX_AMBIENT_VALUE);
      // Return data
      if (callback) {
        callback(null, triggerVal / MAX_AMBIENT_VALUE);
      }
      // Return the value
      return triggerVal;
    }
    else
    {
      if (callback) {
        callback(new Error("Invalid response from Ambient module for trigger set."));
      }
    }
  });
};

// Clears trigger listener for light trigger
Ambient.prototype.clearLightTrigger = function(callback) {
  this.setLightTrigger(0, callback);
};

// Gets trigger listener for sound trigger
Ambient.prototype.clearSoundTrigger = function(callback) {
  this.setSoundTrigger(0, callback);
};

// Gets the last 20 light readings
Ambient.prototype.getLightBuffer = function(callback) {
  this._readBuffer(LIGHT_CMD, AMBIENT_BUF_SIZE, callback);
};

// Gets a single data point of light level
Ambient.prototype.getLightLevel = function(callback) {
  // Grab a single data point
  this._getSingleDatum(LIGHT_CMD, callback);
};

// Gets the last 20 sound readings
Ambient.prototype.getSoundBuffer = function(callback) {
  this._readBuffer(SOUND_CMD, AMBIENT_BUF_SIZE, callback);
};

// Gets a single data point of sound level
Ambient.prototype.getSoundLevel = function(callback) {
    // Grab a single data point
  this._getSingleDatum(SOUND_CMD, callback);
};

// Sets a trigger to emit a 'light-trigger' event when triggerVal is reached
Ambient.prototype.setLightTrigger = function(triggerVal, callback) {
  this._setTrigger(LIGHT_TRIGGER_CMD, triggerVal, callback);
};

// Sets a trigger to emit a 'sound-trigger' event when triggerVal is reached
Ambient.prototype.setSoundTrigger = function(triggerVal, callback) {
  this._setTrigger(SOUND_TRIGGER_CMD, triggerVal, callback);
};

function use (hardware, callback) {
  if(!hardware) {
    console.warn(new Error('Improperly specified Tessel port.'));
  }
  return new Ambient(hardware, callback);
}

exports.Ambient = Ambient;
exports.use = use;
<commit_msg>poll check<commit_after>// Copyright 2014 Technical Machine, Inc. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

var util = require('util');
var EventEmitter = require('events').EventEmitter;
var Attiny = require('attiny-common');
var MODULE_ID = 0x08;
var TINY44_SIGNATURE = 0x9207;
var FIRMWARE_FILE = __dirname + '/firmware/src/ambient-attx4.hex';

// Max 10 (16 bit) data chunks
var AMBIENT_BUF_SIZE = 10 * 2;
var AMBIENT_SINGLE_BYTE = 1 * 2;
var MAX_AMBIENT_VALUE = 1024;

// Confirmation Signals
var PACKET_CONF = 0x55;
var ACK_CONF = 0x33;
var FIN_CONF = 0x16;

var LIGHT_CMD = 2;
var SOUND_CMD = 3;
var LIGHT_TRIGGER_CMD = 4;
var SOUND_TRIGGER_CMD = 5;
var FETCH_TRIGGER_CMD = 6;

// These should be updated with each firmware release
var FIRMWARE_VERSION = 0x03;
var CRC = 0x1eb5;

function Ambient(hardware, callback) {

  // Create a new instance of an attiny
  this.attiny = new Attiny(hardware);

  // Global connected. We may use this in the future
  this.connected = false;

  this.lightTriggerLevel = null;

  this.soundTriggerLevel = null;

  // milliSeconds between reads
  this.pollingFrequency = 500;
  this.lightPolling = false;
  this.soundPolling = false;
  this.pollInterval = undefined;

  var self = this;

  // Store our firmware checking and updating options
  var firmwareOptions = {
    firmwareFile : FIRMWARE_FILE,
    firmwareVersion : FIRMWARE_VERSION,
    moduleID : MODULE_ID,
    signature : TINY44_SIGNATURE,
    crc : CRC,
  }
  // Make sure we can communicate with the module
  self.attiny.initialize(firmwareOptions, function(err) {
    if (err) {
      // Emit the error
      self.emit('error', err);

      // Call the callback with an error
      if (callback) {
        callback(err);
      }

      return;
    }
    else {

      self.connected = true;

      // If someone starts listening
      self.on('newListener', function(event) {
        // and there weren't listeners before
        if (!self.listeners(event).length)
        {
          // start retrieving data for this type of buffer
          self._setListening(true, event);
        }
      });

      // if someone stops listening
      self.on('removeListener', function(event)
      {
        // and there are none left
        if (!self.listeners(event).length)
        {
          // stop retrieving data
          self._setListening(false, event);
        }
      });

      setImmediate(function () {
        // Emit a ready event
        self.emit('ready');
        // Start listening for IRQ interrupts
        self.irqwatcher = self._fetchTriggerValues.bind(self);
        self.attiny.setIRQCallback(self.irqwatcher);

      });

      if (callback) {
        callback(null, self);
      }
    }
  });
}

// We want the ability to emit events
util.inherits(Ambient, EventEmitter);

Ambient.prototype._fetchTriggerValues = function() {

  var self = this;

  // cmd, cmd_echo, light_val (16 bits), sound_val (16 bits)
  var packet = new Buffer([FETCH_TRIGGER_CMD, 0x00, 0x00, 0x00, 0x00, 0x00]);

  // transceive the command
  self.attiny.transceive(packet, function spiComplete(err, response) {
    if (self.attiny._validateResponse(response, [PACKET_CONF, FETCH_TRIGGER_CMD]))
    {
      // make a buffer with the cmd and cmd_echo spliced out
      var data = new Buffer(response.slice(2, response.length));
      // Read values
      var lightTriggerValue = self._normalizeValue(data.readUInt16BE(0));
      var soundTriggerValue = self._normalizeValue(data.readUInt16BE(2));

      if (lightTriggerValue && self.lightTriggerLevel)
      {
        self.emit('light-trigger', lightTriggerValue);
      }
      if (soundTriggerValue && self.soundTriggerLevel)
      {
        self.emit('sound-trigger', soundTriggerValue);
      }

      setImmediate(function() {
        self.irqwatcher = self._fetchTriggerValues.bind(self);
        self.attiny.setIRQCallback(self.irqwatcher);
      });
    }
    else
    {
      console.warn("Warning... Invalid trigger values fetched...");
    }
  });
};

Ambient.prototype._getSingleDatum = function(command, callback) {

  // Read the buffer but only 1 16-bit wordbyte
  this._readBuffer(command, AMBIENT_SINGLE_BYTE, callback);
};

Ambient.prototype._normalizeBuffer = function(buf) {
  var numUInt16 = buf.length/2;
  var ret = new Array(numUInt16);

  for (var i = 0; i < numUInt16; i++) {
    ret[i] = this._normalizeValue(buf.readUInt16BE(i*2));
  }

  return ret;
};

Ambient.prototype._normalizeValue = function(value) {
  return (value/MAX_AMBIENT_VALUE);
};

Ambient.prototype._pollBuffers = function(cb) {
  var self = this;

  if (!self.connected) {
    self._establishCommunication(5, function(err) {
      if (err) {
        self.emit('error', new Error("Can't communicate with Ambient module..."));
      }
    });
  }
  if (self.lightPolling)
  {
    self.getLightBuffer(cb);
  }
  if (self.soundPolling)
  {
    self.getSoundBuffer(cb);
  }
};

Ambient.prototype._readBuffer = function(command, readLen, callback) {

  var self = this;

  // Create a packet with header, data bytes (16 bits) and stop byte
  var header = new Buffer([command, readLen/2, 0x00]);

  var bytes = new Buffer(readLen);
  bytes.fill(0);

  var stop = new Buffer(1);
  stop.writeUInt8(FIN_CONF, 0);

  var packet = Buffer.concat([header, bytes, stop]);

  // Synchronously transceive command to read
  self.attiny.transceive(packet, function spiComplete(err, data) {
    // If the response is valid
    if (self.attiny._validateResponse(data, [PACKET_CONF, command, readLen/2]) &&
      data[data.length-1] === FIN_CONF) {

      data = self._normalizeBuffer(data.slice(header.length, data.length-1));

      if (data.length === 1) {
        data = data[0];
      }

      var event = (command == LIGHT_CMD ? "light" : "sound");

      self.emit(event, data);

      // Return data
      if (callback) {
        callback(null, data);
      }

      return data;
    }
    else {

      var err = new Error("Invalid response from Ambient module");

      if (callback) {
        callback(err);
      }
    }
  });
};

Ambient.prototype._setListening = function(enable, event) {
  var self = this;
  if (event === "light") {
    this.lightPolling = enable;
  } else if (event === "sound") {
    this.soundPolling = enable;
  } else {
    return;
  }

  // if the other buffer is not already polling
  if (event === "light" && !this.soundPolling ||
      event === "sound" && !this.lightPolling) {

    function pollBuffers() {
      self._pollBuffers(function(){
        self._pollTimeout = setTimeout(pollBuffers, self.pollingFrequency);
      });
    }

    if (enable && !self._pollTimeout) {
      // if we want to enable polling & there isn't already a poll
      pollBuffers();
    } else if (!enable && self._pollTimeout) {
      // stop polling
      clearTimeout(self._pollTimeout);
      self._pollTimeout = null;
      if(this.irqwatcher) {
        this.attiny.irq.removeListener('high', this.irqwatcher);
      }
    }
  }
};

Ambient.prototype.disable = function () {
  this._setListening(false, 'light');
  this._setListening(false, 'sound');
};

Ambient.prototype._setTrigger = function(triggerCmd, triggerVal, callback) {

  var self = this;

  // Make the packet
  triggerVal = Math.ceil(triggerVal * MAX_AMBIENT_VALUE);

  var dataBuffer = new Buffer(2);
  dataBuffer.writeUInt16BE(triggerVal, 0);

  var packet = new Buffer([triggerCmd, dataBuffer.readUInt8(0), dataBuffer.readUInt8(1), 0x00]);

  // Send it over SPI
  self.attiny.transceive(packet, function spiComplete(err, data) {
    // If it's a valud response
    if (self.attiny._validateResponse(data, [PACKET_CONF, triggerCmd, dataBuffer.readUInt8(0), dataBuffer.readUInt8(1)]))
    {

      // Get the event title
      var event = (triggerCmd == LIGHT_TRIGGER_CMD ? "light-trigger-set" : "sound-trigger-set");

      // Store the trigger value locally
      if (triggerCmd == LIGHT_TRIGGER_CMD)
      {
        self.lightTriggerLevel = triggerVal;
      }
      else
      {
        self.soundTriggerLevel = triggerVal;
      }

      // Emit the event
      self.emit(event, triggerVal / MAX_AMBIENT_VALUE);
      // Return data
      if (callback) {
        callback(null, triggerVal / MAX_AMBIENT_VALUE);
      }
      // Return the value
      return triggerVal;
    }
    else
    {
      if (callback) {
        callback(new Error("Invalid response from Ambient module for trigger set."));
      }
    }
  });
};

// Clears trigger listener for light trigger
Ambient.prototype.clearLightTrigger = function(callback) {
  this.setLightTrigger(0, callback);
};

// Gets trigger listener for sound trigger
Ambient.prototype.clearSoundTrigger = function(callback) {
  this.setSoundTrigger(0, callback);
};

// Gets the last 20 light readings
Ambient.prototype.getLightBuffer = function(callback) {
  this._readBuffer(LIGHT_CMD, AMBIENT_BUF_SIZE, callback);
};

// Gets a single data point of light level
Ambient.prototype.getLightLevel = function(callback) {
  // Grab a single data point
  this._getSingleDatum(LIGHT_CMD, callback);
};

// Gets the last 20 sound readings
Ambient.prototype.getSoundBuffer = function(callback) {
  this._readBuffer(SOUND_CMD, AMBIENT_BUF_SIZE, callback);
};

// Gets a single data point of sound level
Ambient.prototype.getSoundLevel = function(callback) {
    // Grab a single data point
  this._getSingleDatum(SOUND_CMD, callback);
};

// Sets a trigger to emit a 'light-trigger' event when triggerVal is reached
Ambient.prototype.setLightTrigger = function(triggerVal, callback) {
  this._setTrigger(LIGHT_TRIGGER_CMD, triggerVal, callback);
};

// Sets a trigger to emit a 'sound-trigger' event when triggerVal is reached
Ambient.prototype.setSoundTrigger = function(triggerVal, callback) {
  this._setTrigger(SOUND_TRIGGER_CMD, triggerVal, callback);
};

function use (hardware, callback) {
  if(!hardware) {
    console.warn(new Error('Improperly specified Tessel port.'));
  }
  return new Ambient(hardware, callback);
}

exports.Ambient = Ambient;
exports.use = use;
<|endoftext|>


<commit_before>const game = {
	score: 0,
	totalPlays: 0,
	playCredits: 0,
	modAttr: function (attr, amount, relative) {
		relative = relative || true;
		if (relative) {
			this[attr] += amount;
		} else {
			this[attr] = amount;
		}
	},
	addPlay: function () {
		++this.totalPlays;
	}
};

const flagList = [
	{
		"flagName": "Novice Better",
		"attr": "totalPlays",
		"condition": "===",
		"condValue": "10"
	},
	{
		"flagName": "Experienced Better",
		"attr": "totalPlays",
		"condition": "===",
		"condValue": "100"
	}
];

const checkFlags = buildFlags(flagList);
const trippedFlags = [];

function choose (guess) {
	let choice = guess || "carrots";
	let result = getCarrotOrGarbage();
	game.modAttr("playCredits",1);
	game.addPlay();
	checkFlags.forEach((flag) => {
		console.log(flag.flagName + " checked")
		let tripped = flag.checkMe();
		if (tripped) {
			trippedFlags.push(flag.flagName);
			checkFlags.splice(checkFlags.indexOf(flag),1);
		}
	})
	updateDisplay(choice, result);
}

function capitalizeFirstLetter (string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
}

function getRandomInt (upper, lower) {
	const min = Math.ceil(lower || 0);
	const max = Math.floor(upper || 1);
	return Math.floor(Math.random() * (max + 1 - min) + min);
}

function getCarrotOrGarbage () {
	let rand = getRandomInt(2,1);
	return rand > 1 ? "garbage" : "carrots";
}

function updateDisplay (guess, result) {
	const [choiceDisplay] = document.getElementsByClassName("guess");
	const [resultsDisplay] = document.getElementsByClassName("result");
	const [winDisplay] = document.getElementsByClassName("win-lose");
	const [scoreDisplay] = document.getElementsByClassName("score");
	const [totalPlays] = document.getElementsByClassName("total-plays");
	const [playCredits] = document.getElementsByClassName("play-credits");
	const [flagDisplay] = document.getElementsByClassName("flag-display");
	const [flagList] = document.getElementsByClassName("flag-list");
	let winText = "YOU LOSE!";

	if(didWin(guess, result)) {
		winText = "WINNER!";
		game.modAttr("score",1);
	} else {
		game.modAttr("score",-1);
	}

	while (flagList.firstChild) {
		flagList.removeChild(flagList.firstChild);
	}

	if(trippedFlags && trippedFlags.length > 0) {
		trippedFlags.forEach((flag => {
			let listItem = document.createElement("li");
			listItem.appendChild(document.createTextNode(flag));
			flagList.appendChild(listItem);
		}))
	}

	choiceDisplay.innerHTML = capitalizeFirstLetter(guess);
	resultsDisplay.innerHTML = capitalizeFirstLetter(result);
	winDisplay.innerHTML = winText;
	scoreDisplay.innerHTML = game.score;
	totalPlays.innerHTML = game.totalPlays;
	playCredits.innerHTML = game.playCredits;

}

function didWin (guess, result) {
	return guess === result;
}

function Flag (flagName, attr, condition, condValue) {
	this.flagName = flagName;
	this.attr = attr;
	this.condition = condition;
	this.condValue = parseInt(condValue);
	this.checkMe = function () {
		if (condition === "===") {
			return game[attr] === this.condValue;
		}
		if (condition === "<") {
			return game[attr] < this.condValue;
		}
		if (condition === ">") {
			return game[attr] > this.condValue;
		}
	}
}

function buildFlags (flagList) {
	const flagArray = flagList.map((flag)=> {
		return new Flag (flag.flagName, flag.attr, flag.condition, flag.condValue);
	});
	return flagArray;
}
<commit_msg>better tripped flag structure<commit_after>const game = {
	score: 0,
	totalPlays: 0,
	playCredits: 0,
	modAttr: function (attr, amount, relative) {
		relative = relative || true;
		if (relative) {
			this[attr] += amount;
		} else {
			this[attr] = amount;
		}
	},
	addPlay: function () {
		++this.totalPlays;
	}
};

const flagList = [
	{
		"flagName": "Novice Better",
		"attr": "totalPlays",
		"condition": "===",
		"condValue": "10"
	},
	{
		"flagName": "Experienced Better",
		"attr": "totalPlays",
		"condition": "===",
		"condValue": "100"
	}
];

const checkFlags = buildFlags(flagList);
const trippedFlags = [];

function choose (guess) {
	let choice = guess || "carrots";
	let result = getCarrotOrGarbage();
	game.modAttr("playCredits",1);
	game.addPlay();
	checkFlags.forEach((flag) => {
		let tripped = flag.checkMe();
		if (tripped) {
			trippedFlags.push(flag);
			checkFlags.splice(checkFlags.indexOf(flag),1);
		}
	})
	updateDisplay(choice, result);
}

function capitalizeFirstLetter (string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
}

function getRandomInt (upper, lower) {
	const min = Math.ceil(lower || 0);
	const max = Math.floor(upper || 1);
	return Math.floor(Math.random() * (max + 1 - min) + min);
}

function getCarrotOrGarbage () {
	let rand = getRandomInt(2,1);
	return rand > 1 ? "garbage" : "carrots";
}

function updateDisplay (guess, result) {
	const [choiceDisplay] = document.getElementsByClassName("guess");
	const [resultsDisplay] = document.getElementsByClassName("result");
	const [winDisplay] = document.getElementsByClassName("win-lose");
	const [scoreDisplay] = document.getElementsByClassName("score");
	const [totalPlays] = document.getElementsByClassName("total-plays");
	const [playCredits] = document.getElementsByClassName("play-credits");
	const [flagDisplay] = document.getElementsByClassName("flag-display");
	const [flagList] = document.getElementsByClassName("flag-list");
	let winText = "YOU LOSE!";

	if(didWin(guess, result)) {
		winText = "WINNER!";
		game.modAttr("score",1);
	} else {
		game.modAttr("score",-1);
	}

	while (flagList.firstChild) {
		flagList.removeChild(flagList.firstChild);
	}

	if(trippedFlags && trippedFlags.length > 0) {
		trippedFlags.forEach((flag => {
			let listItem = document.createElement("li");
			listItem.appendChild(document.createTextNode(flag.flagName));
			flagList.appendChild(listItem);
		}))
	}

	choiceDisplay.innerHTML = capitalizeFirstLetter(guess);
	resultsDisplay.innerHTML = capitalizeFirstLetter(result);
	winDisplay.innerHTML = winText;
	scoreDisplay.innerHTML = game.score;
	totalPlays.innerHTML = game.totalPlays;
	playCredits.innerHTML = game.playCredits;

}

function didWin (guess, result) {
	return guess === result;
}

function Flag (flagName, attr, condition, condValue) {
	this.flagName = flagName;
	this.attr = attr;
	this.condition = condition;
	this.condValue = parseInt(condValue);
	this.checkMe = function () {
		if (condition === "===") {
			return game[attr] === this.condValue;
		}
		if (condition === "<") {
			return game[attr] < this.condValue;
		}
		if (condition === ">") {
			return game[attr] > this.condValue;
		}
	}
}

function buildFlags (flagList) {
	const flagArray = flagList.map((flag)=> {
		return new Flag (flag.flagName, flag.attr, flag.condition, flag.condValue);
	});
	return flagArray;
}
<|endoftext|>


<commit_before>/* Internal constants */

const E_NODE = 'Argument 1 of TextIterator.seek is neither Element nor Text.';
const E_TYPE = 'Argument 1 of TextIterator.seek is neither Numer nor Node.';
const SEEKABLE_NODES = [Node.ELEMENT_NODE, Node.TEXT_NODE, Node.DOCUMENT_NODE];

/* Public interface */

export class TextIterator {};

export function createTextIterator(root, filter) {
  let document = global.document;
  let iter = document.createNodeIterator(root, NodeFilter.SHOW_TEXT, filter);

  return Object.create(TextIterator.prototype, {
    root: {
      value: root
    },

    whatToShow: {
      value: NodeFilter.SHOW_TEXT
    },

    filter: {
      value: filter
    },

    referenceNode: {
      get: function () {
        if (iter.referenceNode) {
          return iter.referenceNode;
        } else {
          // IE portability
          iter.nextNode();
          return iter.previousNode();
        }
      }
    },

    seek: {
      value: function (where) {
        let self = this;

        if (!isNaN(parseInt(where)) && isFinite(where)) {
          return seek_offset(iter, parseInt(where));
        } else if (where.nodeType) {
          if (SEEKABLE_NODES.indexOf(where.nodeType) !== -1) {
            return seek_node(iter, where);
          } else {
            return Promise.reject(new TypeError(E_NODE));
          }
        } else {
          return Promise.reject(new TypeError(E_TYPE));
        }
      }
    }
  });
}

export function install() {
  let document = global.document;

  if (typeof global.TextIterator === 'undefined') {
    global.TextIterator = TextIterator;
  }

  if (typeof document.createTextIterator === 'undefined') {
    document.createTextIterator = createTextIterator;
  }
}

/* Private implementation */

function before(referenceNode, node) {
  return referenceNode.compareDocumentPosition(node) &
    (Node.DOCUMENT_POSITION_FOLLOWING | Node.DOCUMENT_CONTAINED_BY);
}

function after(referenceNode, node) {
  return referenceNode.compareDocumentPosition(node) &
    (Node.DOCUMENT_POSITION_PRECEDING | Node.DOCUMENT_CONTAINS);
}

function seek_node(iter, node) {
  function forward(count) {
    let curNode = iter.nextNode();
    if (curNode === null) {
      return Promise.resolve(count);
    } else {
      count += curNode.textContent.length;
      if (after(curNode, node)) {
        return Promise.resolve(count);
      } else {
        return new Promise((r) => setTimeout(r, 0, count)).then(forward);
      }
    }
  }

  function backward(count) {
    let curNode = iter.previousNode();
    if (curNode === null) {
      return Promise.resolve(count);
    } else {
      count -= curNode.textContent.length;
      if(curNode === node || before(curNode, node)) {
        return Promise.resolve(count);
      } else {
        return new Promise((r) => setTimeout(r, 0, count)).then(backward);
      }
    }
  }

  return forward(0).then(backward);
}

function seek_offset(iter, offset) {
  function forward(count) {
    let curNode = iter.nextNode()
    if (curNode === null) {
      return Promise.resolve(count);
    } else {
      count += curNode.textContent.length;
      if (count > offset) {
        return Promise.resolve(count);
      } else {
        return new Promise((r) => setTimeout(r, 0, count)).then(forward);
      }
    }
  }

  function backward(count) {
    let curNode = iter.previousNode();
    if (curNode === null) {
      return Promise.resolve(count);
    } else {
      count -= curNode.textContent.length;
      if (count <= offset) {
        return Promise.resolve(count);
      } else {
        return new Promise((r) => setTimeout(r, 0, count)).then(backward);
      }
    }
  }

  return forward(0).then(backward);
}
<commit_msg>Seek only to Text nodes<commit_after>/* Internal constants */

const E_TYPE = 'Argument 1 of TextIterator.seek is neither a number nor Text.';

/* Public interface */

export class TextIterator {};

export function createTextIterator(root, filter) {
  let document = global.document;
  let iter = document.createNodeIterator(root, NodeFilter.SHOW_TEXT, filter);

  return Object.create(TextIterator.prototype, {
    root: {
      value: root
    },

    whatToShow: {
      value: NodeFilter.SHOW_TEXT
    },

    filter: {
      value: filter
    },

    referenceNode: {
      get: function () {
        if (iter.referenceNode) {
          return iter.referenceNode;
        } else {
          // IE portability
          iter.nextNode();
          return iter.previousNode();
        }
      }
    },

    seek: {
      value: function (where) {
        let self = this;

        if (isNumber(where)) {
          return seek_offset(iter, parseInt(where));
        } else if (isText(where)) {
          return seek_node(iter, where);
        } else {
          return Promise.reject(new TypeError(E_TYPE));
        }
      }
    }
  });
}

export function install() {
  let document = global.document;

  if (typeof global.TextIterator === 'undefined') {
    global.TextIterator = TextIterator;
  }

  if (typeof document.createTextIterator === 'undefined') {
    document.createTextIterator = createTextIterator;
  }
}

/* Private implementation */

function isNumber(n) {
  return !isNaN(parseInt(n)) && isFinite(n));
}

function isText(node) {
  if (typeof(node.nodeType) === 'number') {
    return node.nodeType === Node.TEXT_NODE;
  } else {
    return false;
  }
}

function before(referenceNode, node) {
  return referenceNode.compareDocumentPosition(node) &
    (Node.DOCUMENT_POSITION_FOLLOWING | Node.DOCUMENT_CONTAINED_BY);
}

function after(referenceNode, node) {
  return referenceNode.compareDocumentPosition(node) &
    (Node.DOCUMENT_POSITION_PRECEDING | Node.DOCUMENT_CONTAINS);
}

function seek_node(iter, node) {
  function forward(count) {
    let curNode = iter.nextNode();
    if (curNode === null) {
      return Promise.resolve(count);
    } else {
      count += curNode.textContent.length;
      if (after(curNode, node)) {
        return Promise.resolve(count);
      } else {
        return new Promise((r) => setTimeout(r, 0, count)).then(forward);
      }
    }
  }

  function backward(count) {
    let curNode = iter.previousNode();
    if (curNode === null) {
      return Promise.resolve(count);
    } else {
      count -= curNode.textContent.length;
      if(curNode === node || before(curNode, node)) {
        return Promise.resolve(count);
      } else {
        return new Promise((r) => setTimeout(r, 0, count)).then(backward);
      }
    }
  }

  return forward(0).then(backward);
}

function seek_offset(iter, offset) {
  function forward(count) {
    let curNode = iter.nextNode()
    if (curNode === null) {
      return Promise.resolve(count);
    } else {
      count += curNode.textContent.length;
      if (count > offset) {
        return Promise.resolve(count);
      } else {
        return new Promise((r) => setTimeout(r, 0, count)).then(forward);
      }
    }
  }

  function backward(count) {
    let curNode = iter.previousNode();
    if (curNode === null) {
      return Promise.resolve(count);
    } else {
      count -= curNode.textContent.length;
      if (count <= offset) {
        return Promise.resolve(count);
      } else {
        return new Promise((r) => setTimeout(r, 0, count)).then(backward);
      }
    }
  }

  return forward(0).then(backward);
}
<|endoftext|>


<commit_before>'use strict';

const repl = require('repl');
const io = require('socket.io');

let randInt = (min, max) => Math.floor(Math.random() * (max - min)) + min;
let randChoose = choices => choices[randInt(0, choices.length)];
class Player {
  constructor(server, id) {
    let config = server.config;
    this.id = id;
    this.clan = null;
    this.server = server;
    this.untilSend = 1;

    this.name = 'unknown';
    this.skin = 0;
    this.size = config.playerScale;

    this.aimAngle = 0;
    this.movement = null;
    this.kill();
  }
  updateMovement(delta) {
    let config = this.server.config;
    let tx = 0;
    let ty = 0;
    if (this.movement != null) {
      tx = Math.cos(this.movement);
      ty = Math.sin(this.movement);
    }
    this.vx *= Math.pow(config.playerDecel, delta);
    this.vy *= Math.pow(config.playerDecel, delta);
    this.vx += tx * config.playerSpeed * delta * this.size / 2;
    this.vy += ty * config.playerSpeed * delta * this.size / 2;
    this.x += this.vx;
    this.y += this.vy;
  }
  update(delta) {
    if (this.alive) {
      this.updateMovement(delta);
      this.untilSend--;
      if (!this.untilSend) {
        this.untilSend = this.server.config.clientSendRate;
        this.sendPosition();
      }
    }
  }
  sendPosition() {
    let socket = this.socket;
    socket.emit('a');
    socket.emit('3', [
      this.id,
      this.x,
      this.y, -2.26,-1,0,0,null,0,0,0,0]);
  }
  link(socket) {
    this.socket = socket;
    socket.once('error', err => {
      console.log(err);
      this.destroy();
    });
    socket.on('2', angle => this.aimAngle = angle);
    socket.on('3', angle => this.movement = angle);
    socket.once('disconnect', () => this.destroy());
    socket.emit('id', {
      teams: this.server.clans
    });
    socket.on('1', data => {
      this.name = data.name.length > 15 || !data.name ? 'unknown' : data.name;
      this.skin = data.skin;
      this.spawn();
    });
  }
  destroy() {
    this.kill();
    this.server.remove(this.id);
    this.socket.disconnect();
  }
  kill() {
    this.alive = false;
    this.x = 0;
    this.y = 0;
    this.slowDown();
  }
  slowDown() {
    this.vx = 0;
    this.vy = 0;
  }
  spawn() {
    let config = this.server.config;
    let socket = this.socket;
    this.alive = true;
    let { x, y } = this.server.allocatePosition(this.size);
    this.x = x;
    this.y = y;
    this.slowDown();
    socket.emit('1', this.id);
    socket.emit('2', [socket.id,this.id,this.name,this.x,this.y,0,100,100,this.size,this.skin],true);
  }
  hitResource(type) {

  }
}
class Resource {
  constructor(server, x, y, size, type) {
    let config = server.config;
    this.x = x;
    this.y = y;
    this.type = config.resourceTypes.indexOf(type);
    this.size = size;
  }
  reward(by) {
    by.hitResource(this.type);
  }
}
class Server {
  constructor(config) {
    this.config = config;
    this.players = Array(config.maxPlayers).fill(null);
    this.lastRun = Date.now();
    this.clans = [];
    this.objects = [];
    setInterval(() => this.update(), config.serverUpdateRate);
    this.generateWorld();
  }
  remove(sid) {
    this.players[sid] = null;
  }
  update() {
    let now = Date.now();
    let delta = now - this.lastRun;
    this.lastRun = now;
    for (let i of this.players) {
      if (i != null) {
        i.update(delta);
      }
    }
  }
  generateWorld() {
    let config = this.config;
    let areaCount = config.areaCount;
    let mapScale = config.mapScale;
    let areaSize = mapScale / areaCount;
    let all = [];
    for (let afx = 0, atx = 1; afx < areaCount; afx++, atx++) {
      for (let afy = 0, aty = 1; afy < areaCount; afy++, aty++) {
        for (let i = 0; i < config.treesPerArea; i++) {
          let x = randInt(areaSize * afx, areaSize * atx);
          let y = randInt(areaSize * afy, areaSize * aty);
          all.push(new Resource(this, x, y, randChoose(config.treeScales), 'wood'));
        }
        for (let i = 0; i < config.bushesPerArea; i++) {
          let x = randInt(areaSize * afx, areaSize * atx);
          let y = randInt(areaSize * afy, areaSize * aty);
          all.push(new Resource(this, x, y, randChoose(config.bushScales), 'food'));
        }
      }
    }
    for (let i = 0; i < config.totalRocks; i++) {
      let x = randInt(0, mapScale);
      let y = randInt(0, mapScale);
      all.push(new Resource(this, x, y, randChoose(config.rockScales), 'stone'));
    }
    for (let i = 0; i < config.goldOres; i++) {
      let x = randInt(0, mapScale);
      let y = randInt(0, mapScale);
      all.push(new Resource(this, x, y, 0, 'points'));
    }
    this.objects = all;
  }
  allocatePosition(size) {
    let scale = this.config.mapScale;
    let x = 0;
    let y = 0;
    while (true) {
      x = randInt(0, scale);
      y = randInt(0, scale);
      if (true) { // check if there's nothing overlapping
        break;
      }
    }
    return { x, y };
  }
  handle(socket) {
    for (let i = 0; i < this.players.length; i++) {
      if (this.players[i] == null) {
        let player = new Player(this, i);
        player.link(socket);
        this.players[i] = player;
        break;
      }
    }
  }
}

let app = new Server({
  mapScale: 14400,
  maxPlayers: 50,
  clientSendRate: 5,
  serverUpdateRate: 9,
  playerDecel: 0.993,
  playerSpeed: 0.0016,
  playerScale: 35,
  areaCount: 7,
  treesPerArea: 9,
  bushesPerArea: 3,
  totalRocks: 32,
  goldOres: 7,
  resourceTypes: ['wood', 'food', 'stone', 'points'],
  treeScales: [140, 145, 150, 155],
  bushScales: [80, 85, 95],
  rockScales: [80, 85, 90],
});

for (let i = 5000; i <= 5010; i++) {
  io(i).on('connection', socket => app.handle(socket));
}
/*
let teams = [];
let sockets = [];
  io(i).on('connection', function (socket) {
    let emit = (...arg) => {
      try {
        socket.broadcast.emit(...arg);
        socket.emit(...arg);
      } catch (e) {
        sockets.forEach(a => a.emit(...arg));
      }
    };
    sockets.push(socket);
    socket.on('1', function (data) {
      let id = 27;
      let name = data.name.length > 15 ? 'unknown' : data.name;
      socket.emit('id', {
        "teams": teams
      });
      socket.emit('1', id);
      socket.emit('mm', 0);
      socket.emit('3', []);
      let x = randInt(0, config.mapScale);
      let y = randInt(0, config.mapScale);
      let userteam = null;
      let last = 0;
      socket.emit("2", ["a3Pm5dMzeKOjc5gvAJEF", id, name, x, 7200, 0, 100, 100, 35, data.skin], true);
      socket.emit("5", [27, data.name, 9001]); //[5,"RIP",31988,45,"KADEJO503",23404,34,"winter wolf",4821,28,"Godenot",4500,33,"Arena Closer",3000,32,"LightTheif",2940,6,"CarlosKoS-_-16",2800,4,"GD desconhecido",2635,35,"jack black GD",2357,19,"AMIGO BOM",1623])
      socket.emit("6", [
        29, 3115.1, 13592.9, 0, 109.2, 1, null, -1,
        353, 4103, 13436, 0, 80, 2, null, -1,
        339, 2498, 14155, 0, 90, 2, null, -1
      ]);
      socket.emit("8", 2.6, 28);
      socket.on("ch", data => {
        emit("ch", id, data);
      });
      socket.on("8", data => {
        console.log('CLAN CREATE REQUEST:', data);
        teams.push([{
          "sid": data,
          "owner": id
        }]);
        let userteam = data;
        emit("st", data, true);
      });
      socket.on("3", function (data) {
        if (data == null) {
          vx = vy = 0;
          return;
        } else if (x < 0 || x > config.mapScale || y < 0 || y > config.mapScale) {
          x = 7200;
          y = 7200;
        }
        if (y >= 6840 && y <= 7560) {
          x += 0.44;
        }
        let speed = y > 2400 ? 60 * 0.8 : 60;
        vx = Math.cos(data) * speed;
        vy = Math.sin(data) * speed;
        x += vx;
        y += vy;
        socket.emit('a');
        socket.emit("3", [id, x, y, -2.26, -1, 0, 0, null, 0, 0, 0, 0]);
      });
      socket.on("14", function (data) {
        console.log('ping!!!', arguments);
      });
    });
  });
}
*/
repl.start({
  eval: (a, _c, _f, cb) => {
    try {
      cb(null, eval(a)); // jshint ignore: line
    } catch (e) {
      cb(e);
    }
  }
});
<commit_msg>Add half-broken ping<commit_after>'use strict';

const repl = require('repl');
const io = require('socket.io');

let randInt = (min, max) => Math.floor(Math.random() * (max - min)) + min;
let randChoose = choices => choices[randInt(0, choices.length)];
class Player {
  constructor(server, id) {
    let config = server.config;
    this.id = id;
    this.clan = null;
    this.server = server;
    this.untilSend = 1;

    this.name = 'unknown';
    this.skin = 0;
    this.size = config.playerScale;

    this.aimAngle = 0;
    this.movement = null;
    this.kill();
  }
  updateMovement(delta) {
    let config = this.server.config;
    let tx = 0;
    let ty = 0;
    if (this.movement != null) {
      tx = Math.cos(this.movement);
      ty = Math.sin(this.movement);
    }
    this.vx *= Math.pow(config.playerDecel, delta);
    this.vy *= Math.pow(config.playerDecel, delta);
    this.vx += tx * config.playerSpeed * delta * this.size / 2;
    this.vy += ty * config.playerSpeed * delta * this.size / 2;
    this.x += this.vx;
    this.y += this.vy;
  }
  update(delta) {
    if (this.alive) {
      this.updateMovement(delta);
      this.untilSend--;
      if (!this.untilSend) {
        this.untilSend = this.server.config.clientSendRate;
        this.sendPosition();
      }
    }
  }
  sendPosition() {
    let socket = this.socket;
    socket.emit('a');
    socket.emit('3', [
      this.id,
      this.x,
      this.y, -2.26,-1,0,0,null,0,0,0,0]);
  }
  link(socket) {
    this.socket = socket;
    socket.once('error', err => {
      console.log(err);
      this.destroy();
    });
    socket.on('2', angle => this.aimAngle = angle);
    socket.on('3', angle => this.movement = angle);

    socket.on("14",function(data){
        console.log('ping!!!', arguments)
        emit("p",x,y)
    });

    socket.once('disconnect', () => this.destroy());
    socket.emit('id', {
      teams: this.server.clans
    });
    socket.on('1', data => {
      this.name = data.name.length > 15 || !data.name ? 'unknown' : data.name;
      this.skin = data.skin;
      this.spawn();
    });
  }
  destroy() {
    this.kill();
    this.server.remove(this.id);
    this.socket.disconnect();
  }
  kill() {
    this.alive = false;
    this.x = 0;
    this.y = 0;
    this.slowDown();
  }
  slowDown() {
    this.vx = 0;
    this.vy = 0;
  }
  spawn() {
    let config = this.server.config;
    let socket = this.socket;
    this.alive = true;
    let { x, y } = this.server.allocatePosition(this.size);
    this.x = x;
    this.y = y;
    this.slowDown();
    socket.emit('1', this.id);
    socket.emit('2', [socket.id,this.id,this.name,this.x,this.y,0,100,100,this.size,this.skin],true);
  }
  hitResource(type) {

  }
}
class Resource {
  constructor(server, x, y, size, type) {
    let config = server.config;
    this.x = x;
    this.y = y;
    this.type = config.resourceTypes.indexOf(type);
    this.size = size;
  }
  reward(by) {
    by.hitResource(this.type);
  }
}
class Server {
  constructor(config) {
    this.config = config;
    this.players = Array(config.maxPlayers).fill(null);
    this.lastRun = Date.now();
    this.clans = [];
    this.objects = [];
    setInterval(() => this.update(), config.serverUpdateRate);
    this.generateWorld();
  }
  remove(sid) {
    this.players[sid] = null;
  }
  update() {
    let now = Date.now();
    let delta = now - this.lastRun;
    this.lastRun = now;
    for (let i of this.players) {
      if (i != null) {
        i.update(delta);
      }
    }
  }
  generateWorld() {
    let config = this.config;
    let areaCount = config.areaCount;
    let mapScale = config.mapScale;
    let areaSize = mapScale / areaCount;
    let all = [];
    for (let afx = 0, atx = 1; afx < areaCount; afx++, atx++) {
      for (let afy = 0, aty = 1; afy < areaCount; afy++, aty++) {
        for (let i = 0; i < config.treesPerArea; i++) {
          let x = randInt(areaSize * afx, areaSize * atx);
          let y = randInt(areaSize * afy, areaSize * aty);
          all.push(new Resource(this, x, y, randChoose(config.treeScales), 'wood'));
        }
        for (let i = 0; i < config.bushesPerArea; i++) {
          let x = randInt(areaSize * afx, areaSize * atx);
          let y = randInt(areaSize * afy, areaSize * aty);
          all.push(new Resource(this, x, y, randChoose(config.bushScales), 'food'));
        }
      }
    }
    for (let i = 0; i < config.totalRocks; i++) {
      let x = randInt(0, mapScale);
      let y = randInt(0, mapScale);
      all.push(new Resource(this, x, y, randChoose(config.rockScales), 'stone'));
    }
    for (let i = 0; i < config.goldOres; i++) {
      let x = randInt(0, mapScale);
      let y = randInt(0, mapScale);
      all.push(new Resource(this, x, y, 0, 'points'));
    }
    this.objects = all;
  }
  allocatePosition(size) {
    let scale = this.config.mapScale;
    let x = 0;
    let y = 0;
    while (true) {
      x = randInt(0, scale);
      y = randInt(0, scale);
      if (true) { // check if there's nothing overlapping
        break;
      }
    }
    return { x, y };
  }
  handle(socket) {
    for (let i = 0; i < this.players.length; i++) {
      if (this.players[i] == null) {
        let player = new Player(this, i);
        player.link(socket);
        this.players[i] = player;
        break;
      }
    }
  }
}

let app = new Server({
  mapScale: 14400,
  maxPlayers: 50,
  clientSendRate: 5,
  serverUpdateRate: 9,
  playerDecel: 0.993,
  playerSpeed: 0.0016,
  playerScale: 35,
  areaCount: 7,
  treesPerArea: 9,
  bushesPerArea: 3,
  totalRocks: 32,
  goldOres: 7,
  resourceTypes: ['wood', 'food', 'stone', 'points'],
  treeScales: [140, 145, 150, 155],
  bushScales: [80, 85, 95],
  rockScales: [80, 85, 90],
});

for (let i = 5000; i <= 5010; i++) {
  io(i).on('connection', socket => app.handle(socket));
}
/*
let teams = [];
let sockets = [];
  io(i).on('connection', function (socket) {
    let emit = (...arg) => {
      try {
        socket.broadcast.emit(...arg);
        socket.emit(...arg);
      } catch (e) {
        sockets.forEach(a => a.emit(...arg));
      }
    };
    sockets.push(socket);
    socket.on('1', function (data) {
      let id = 27;
      let name = data.name.length > 15 ? 'unknown' : data.name;
      socket.emit('id', {
        "teams": teams
      });
      socket.emit('1', id);
      socket.emit('mm', 0);
      socket.emit('3', []);
      let x = randInt(0, config.mapScale);
      let y = randInt(0, config.mapScale);
      let userteam = null;
      let last = 0;
      socket.emit("2", ["a3Pm5dMzeKOjc5gvAJEF", id, name, x, 7200, 0, 100, 100, 35, data.skin], true);
      socket.emit("5", [27, data.name, 9001]); //[5,"RIP",31988,45,"KADEJO503",23404,34,"winter wolf",4821,28,"Godenot",4500,33,"Arena Closer",3000,32,"LightTheif",2940,6,"CarlosKoS-_-16",2800,4,"GD desconhecido",2635,35,"jack black GD",2357,19,"AMIGO BOM",1623])
      socket.emit("6", [
        29, 3115.1, 13592.9, 0, 109.2, 1, null, -1,
        353, 4103, 13436, 0, 80, 2, null, -1,
        339, 2498, 14155, 0, 90, 2, null, -1
      ]);
      socket.emit("8", 2.6, 28);
      socket.on("ch", data => {
        emit("ch", id, data);
      });
      socket.on("8", data => {
        console.log('CLAN CREATE REQUEST:', data);
        teams.push([{
          "sid": data,
          "owner": id
        }]);
        let userteam = data;
        emit("st", data, true);
      });
      socket.on("3", function (data) {
        if (data == null) {
          vx = vy = 0;
          return;
        } else if (x < 0 || x > config.mapScale || y < 0 || y > config.mapScale) {
          x = 7200;
          y = 7200;
        }
        if (y >= 6840 && y <= 7560) {
          x += 0.44;
        }
        let speed = y > 2400 ? 60 * 0.8 : 60;
        vx = Math.cos(data) * speed;
        vy = Math.sin(data) * speed;
        x += vx;
        y += vy;
        socket.emit('a');
        socket.emit("3", [id, x, y, -2.26, -1, 0, 0, null, 0, 0, 0, 0]);
      });
      socket.on("14", function (data) {
        console.log('ping!!!', arguments);
      });
    });
  });
}
*/
repl.start({
  eval: (a, _c, _f, cb) => {
    try {
      cb(null, eval(a)); // jshint ignore: line
    } catch (e) {
      cb(e);
    }
  }
});
<|endoftext|>


<commit_before>'use strict';
var cp = require('child_process');
var fs = require('fs');
var path = require('path');

var _ = require('lodash');
var async = require('neo-async');
var cchangelog = require('conventional-changelog');
var semver = require('semver');

var COMMIT_PATTERN = /^(\w*)(\(([\w\$\.\-\* ]*)\))?\: (.*)$/;

function getUrl() {
  return require(path.join(__dirname, '..', 'package.json')).homepage;
}

module.exports = function(url, callback) {
  if (arguments.length === 1) {
    callback = url;
    url = null;
  }
  if (!url)
    url = getUrl();

  var dates = {};
  async.waterfall([
    function(next) {
      cp.exec('git for-each-ref --format "%(refname:short) %09 %(taggerdate:short)" refs/tags', function(err, stdout) {
        if (err)
          return next(err);

        var list = [];
        String(stdout).split('\n').forEach(function(v) {
          var _v = v.split('\t');
          if (!_v || !_v[0]) {
            return;
          }
          var ver = _v[0].trim();
          list.push(ver);
          dates[ver] = _v[1].trim();
        });
        list.sort(semver.compare);

        var _list = _.clone(list);
        _list.shift();
        list.pop();

        next(null, _.zip(list, _list));
      });
    },
    function(pair, next) {
      function matcher(subject) {
        var match = subject.match(COMMIT_PATTERN);
        if (match && match[1] && match[4]) {
          return match;
        }
        var _s = subject.split(' ');
        if (_s[0] === 'Merge' && _s[1] === 'pull' && _s[2] === 'request') {
          return;
        }
        if (_s.length === 1 && semver.valid(_s[0])) {
          return;
        }

        var list = [
          subject,
          _s[0].replace(/\./g, '').toLowerCase(),
          null,
          null,
          subject
        ];
        list.index = 0;
        list.input = subject;
        return list;
      }

      var str = '';
      async.eachSeries(pair, function(p, done) {
        cchangelog({
          repository: url,
          version: p[1],
          file: '',
          from: p[0],
          to: p[1],
          grep: '',
          matcher: matcher,
          date: dates[p[1]]
        }, function(err, result) {
          if (err)
            return done(err);
          str = result + str;
          done();
        });
      }, function(err) {
        if (err)
          return next(err);

        next(null, str);
      });
    },
    function(contents, next) {
      fs.writeFile('CHANGELOG.md', contents, { encoding: 'utf8' }, next);
    },
  ], callback);
};
<commit_msg>fix(main) default callback<commit_after>'use strict';
var cp = require('child_process');
var fs = require('fs');
var path = require('path');

var _ = require('lodash');
var async = require('neo-async');
var cchangelog = require('conventional-changelog');
var semver = require('semver');

var COMMIT_PATTERN = /^(\w*)(\(([\w\$\.\-\* ]*)\))?\: (.*)$/;

function getUrl() {
  return require(path.join(__dirname, '..', 'package.json')).homepage;
}

function defaultCallback(err) {
  if (err) {
    console.error(err);
  }
}

module.exports = function(url, callback) {
  if (arguments.length === 0) {
    callback = defaultCallback;
    url = null;
  }
  if (arguments.length === 1) {
    if (typeof url === 'function') {
      callback = url;
      url = null;
    } else {
      callback = defaultCallback;
    }
  }
  if (!url)
    url = getUrl();

  var dates = {};
  async.waterfall([
    function(next) {
      cp.exec('git for-each-ref --format "%(refname:short) %09 %(taggerdate:short)" refs/tags', function(err, stdout) {
        if (err)
          return next(err);

        var list = [];
        String(stdout).split('\n').forEach(function(v) {
          var _v = v.split('\t');
          if (!_v || !_v[0]) {
            return;
          }
          var ver = _v[0].trim();
          list.push(ver);
          dates[ver] = _v[1].trim();
        });
        list.sort(semver.compare);

        var _list = _.clone(list);
        _list.shift();
        list.pop();

        next(null, _.zip(list, _list));
      });
    },
    function(pair, next) {
      function matcher(subject) {
        var match = subject.match(COMMIT_PATTERN);
        if (match && match[1] && match[4]) {
          return match;
        }
        var _s = subject.split(' ');
        if (_s[0] === 'Merge' && _s[1] === 'pull' && _s[2] === 'request') {
          return;
        }
        if (_s.length === 1 && semver.valid(_s[0])) {
          return;
        }

        var list = [
          subject,
          _s[0].replace(/\./g, '').toLowerCase(),
          null,
          null,
          subject
        ];
        list.index = 0;
        list.input = subject;
        return list;
      }

      var str = '';
      async.eachSeries(pair, function(p, done) {
        cchangelog({
          repository: url,
          version: p[1],
          file: '',
          from: p[0],
          to: p[1],
          grep: '',
          matcher: matcher,
          date: dates[p[1]]
        }, function(err, result) {
          if (err)
            return done(err);
          str = result + str;
          done();
        });
      }, function(err) {
        if (err)
          return next(err);

        next(null, str);
      });
    },
    function(contents, next) {
      fs.writeFile('CHANGELOG.md', contents, { encoding: 'utf8' }, next);
    },
  ], callback);
};
<|endoftext|>


<commit_before>function CBuffer() {
	// handle cases where "new" keyword wasn't used
	if (!( this instanceof CBuffer )) {
		if ( arguments.length > 1 || typeof arguments[0] !== 'number' ) {
			return CBuffer.apply( new CBuffer(), arguments );
		} else {
			return new CBuffer( arguments[0] );
		}
	}
	// this is the same in either scenario
	this.size = this.start = 0;
	// build CBuffer based on passed arguments
	if ( arguments.length > 1 || typeof arguments[0] !== 'number' ) {
		this.data = new Array( arguments.length );
		this.end = ( this.length = arguments.length ) - 1;
		this.push.apply( this, arguments );
	} else {
		this.data = new Array( arguments[0] );
		this.end = ( this.length = arguments[0] ) - 1;
	}
	return this;
}

CBuffer.prototype = {
	// push item to the end
	push : function() {
		var i = 0;
		// push items to the end, wrapping and erasing existing items
		// using arguments variable directly to reduce gc footprint
		for ( ; i < arguments.length; i++ ) {
			this.data[( this.end + i + 1 ) % this.length ] = arguments[i];
		}
		// recalculate size
		if ( this.size < this.length ) {
			if ( this.size + i > this.length ) this.size = this.length;
			else this.size += i;
		}
		// recalculate end
		this.end = ( this.end + i ) % this.length;
		// recalculate start
		this.start = this.end - this.size + 1;
		if ( this.start < 0 ) this.start += this.length;
		// return number current number of items in CBuffer
		return this.size;
	},
	// shift first item
	shift : function() {
		var item;
		// check if there are any items in CBuff
		if ( this.size === 0 ) return undefined;
		// store first item for return
		item = this.data[ this.start ];
		// delete first item from memory
		delete this.data[ this.start ];
		// recalculate start of CBuff
		this.start = ( this.start + 1 ) % this.length;
		// decrement size
		this.size--;
		return item;
	},
	first : function() {
		return this.data[ this.start ];
	},
	last : function() {
		return this.data[ this.end ];
	},
	idx : function( arg ) {
		return this.data[( this.start + arg ) % this.length ];
	}
};

this.CBuffer = CBuffer;
<commit_msg>add forEach feature<commit_after>function CBuffer() {
	// handle cases where "new" keyword wasn't used
	if (!( this instanceof CBuffer )) {
		if ( arguments.length > 1 || typeof arguments[0] !== 'number' ) {
			return CBuffer.apply( new CBuffer(), arguments );
		} else {
			return new CBuffer( arguments[0] );
		}
	}
	// this is the same in either scenario
	this.size = this.start = 0;
	// build CBuffer based on passed arguments
	if ( arguments.length > 1 || typeof arguments[0] !== 'number' ) {
		this.data = new Array( arguments.length );
		this.end = ( this.length = arguments.length ) - 1;
		this.push.apply( this, arguments );
	} else {
		this.data = new Array( arguments[0] );
		this.end = ( this.length = arguments[0] ) - 1;
	}
	return this;
}

CBuffer.prototype = {
	// push item to the end
	push : function() {
		var i = 0;
		// push items to the end, wrapping and erasing existing items
		// using arguments variable directly to reduce gc footprint
		for ( ; i < arguments.length; i++ ) {
			this.data[( this.end + i + 1 ) % this.length ] = arguments[i];
		}
		// recalculate size
		if ( this.size < this.length ) {
			if ( this.size + i > this.length ) this.size = this.length;
			else this.size += i;
		}
		// recalculate end
		this.end = ( this.end + i ) % this.length;
		// recalculate start
		this.start = this.end - this.size + 1;
		if ( this.start < 0 ) this.start += this.length;
		// return number current number of items in CBuffer
		return this.size;
	},
	// shift first item
	shift : function() {
		var item;
		// check if there are any items in CBuff
		if ( this.size === 0 ) return undefined;
		// store first item for return
		item = this.data[ this.start ];
		// delete first item from memory
		delete this.data[ this.start ];
		// recalculate start of CBuff
		this.start = ( this.start + 1 ) % this.length;
		// decrement size
		this.size--;
		return item;
	},
	// loop through each item in buffer
	forEach : function( callback, context ) {
		var i = 0;
		// check if context was passed
		if ( context ) {
			for (; i < this.size; i++ ) {
				callback.call( context, this.idx( i ), i, this );
			}
		} else {
			for (; i < this.size; i++ ) {
				callback( this.idx( i ), i, this );
			}
		}
	},
	// return first item in buffer
	first : function() {
		return this.data[ this.start ];
	},
	// return last item in buffer
	last : function() {
		return this.data[ this.end ];
	},
	// return specific index in buffer
	idx : function( arg ) {
		return this.data[( this.start + arg ) % this.length ];
	}
};

this.CBuffer = CBuffer;
<|endoftext|>


<commit_before>var util = require('util');
var sourceMaps = require('source-map-support');

var indexToNumberAndLowerCaseKey = function(index) {
  if (index <= 9) {
    return 48 + index;
  } else if (index === 10) {
    return 48;
  } else if (index > 10 && index <= 36) {
    return 64 + (index-10);
  } else {
    return null;
  }
};

var defaults = [
  { name: 'Show FPS', entry: 'showFps', default: true },
  { name: 'Show Key Codes', entry: 'showKeyCodes', default: true },
  { name: 'Show Time', entry: 'showTime', default: true }
];

var Debugger = function(app, options) {
  this.app = app;
  options = options || [];

  options = options.concat(defaults);

  this.options = options;

  for (var i=0; i<options.length; i++) {
    var option = options[i];
    option.type = option.type || 'toggle';
    option.default = option.default == null ? false : option.default;

    if (option.type === 'toggle') {
      this[option.entry] = option.default;
    }
  }

  if (window.localStorage && window.localStorage.__debug) {
    var data = JSON.parse(window.localStorage.__debug);
    for (var name in data) {
      this[name] = data[name];
    }
  }

  sourceMaps.install();

  this.fps = 0;
  this.fpsCount = 0;
  this.fpsElapsedTime = 0;
  this.fpsUpdateInterval = 0.5;

  this.logs = [];

  this.showDebug = true;
  this.enableDebugKeys = true;
  this.enableShortcuts = false;

  this.enableShortcutsKey = 220;

  this.lastKey = null;

  this.keyShortcuts = [
    { key: 123, entry: 'showDebug', type: 'toggle' }
  ];

  var self = this;

  window.addEventListener('error', function(error) {
    self.log(error.error.stack, 'red');
  });
};

Debugger.prototype.log = function(message, color) {
  color = color || 'white';
  message = typeof message === 'string' ? message : util.inspect(message);

  var messages = message.replace(/\\'/g, "'").split('\n');

  for (var i=0; i<messages.length; i++) {
    var msg = messages[i];
    this.logs.push({ text: msg, life: 10, color: color });
  }
};

Debugger.prototype.enterUpdate = function() {
  if (this.pause) {
    return true;
  }
};

Debugger.prototype.update = function(time) {
  if (this.showDebug) {
    this.fpsCount += 1;
    this.fpsElapsedTime += time;

    if (this.fpsElapsedTime > this.fpsUpdateInterval) {
      var fps = this.fpsCount/this.fpsElapsedTime;

      if (this.showFps) {
        this.fps = this.fps * (1-0.8) + 0.8 * fps;
      }

      this.fpsCount = 0;
      this.fpsElapsedTime = 0;
    }

    for (var i=0, len=this.logs.length; i<len; i++) {
      var log = this.logs[i];
      if (log) {
        log.life -= time;
        if (log.life <= 0) {
          var index = this.logs.indexOf(log);
          if (index > -1) { this.logs.splice(index, 1); }
        }
      }
    }
  }
};

Debugger.prototype.keydown = function(key) {
  this.lastKey = key;

  var i;

  if (this.enableDebugKeys) {
    if (key === this.enableShortcutsKey) {
      this.enableShortcuts = !this.enableShortcuts;
      return true;
    }

    if (this.enableShortcuts) {
      for (i=0; i<this.options.length; i++) {
        var option = this.options[i];

        var keyIndex = i + 1;

        keyIndex = indexToNumberAndLowerCaseKey(keyIndex);

        if (keyIndex && key === keyIndex) {
          if (option.type === 'toggle') {

            this[option.entry] = !this[option.entry];

            var data = {};

            if (window.localStorage.__debug) {
              data = JSON.parse(window.localStorage.__debug);
            }

            data[option.entry] = this[option.entry];

            window.localStorage.__debug = JSON.stringify(data);

          } else if (option.type === 'call') {
            option.entry();
          }

          return true;
        }
      }
    }
  }

  for (i=0; i<this.keyShortcuts.length; i++) {
    var keyShortcut = this.keyShortcuts[i];
    if (keyShortcut.key === key) {

      if (keyShortcut.type === 'toggle') {
        this[keyShortcut.entry] = !this[keyShortcut.entry];
      } else if (keyShortcut.type === 'call') {
        this[keyShortcut.entry]();
      }

      return true;
    }
  }

  return false;
};

Debugger.prototype.render = function() {
  if (this.showDebug) {
    this.app.video.ctx.save();
    this.app.video.ctx.font = '15px sans-serif';

    this._renderLogs();
    this._renderData();
    this._renderShortcuts();

    this.app.video.ctx.restore();
  }
};

Debugger.prototype._renderLogs = function() {
  this.app.video.ctx.textAlign = 'left';
  this.app.video.ctx.textBaseline = 'bottom';

  for (var i=0, len=this.logs.length; i<len; i++) {
    var log = this.logs[i];

    var y = -10 + this.app.height + (i - this.logs.length + 1) * 20;
    this._renderText(log.text, 10, y, log.color);
  }
};

Debugger.prototype._renderData = function() {
  this.app.video.ctx.textAlign = 'right';
  this.app.video.ctx.textBaseline = 'top';

  var x = this.app.width - 14;
  var y = 14;

  if (this.showFps) {
    this._renderText(Math.round(this.fps) + ' fps', x, y);
  }

  y += 20;

  this.app.video.ctx.font = '20px sans-serif';
  if (this.showTime) {
    if (this.app.runtime && this.app.runtime.time != null) {
      this._renderText(this.app.runtime.time.toFixed(2) + ' s', x, y);
    }
  }
  y += 30;

  this.app.video.ctx.font = '15px sans-serif';

  if (this.showKeyCodes) {
    this._renderText('key ' + this.lastKey, x, y, this.app.input.isKeyDown(this.lastKey) ? '#e9dc7c' : 'white');
    this._renderText('btn ' + this.app.input.mouse.button, x - 60, y, this.app.input.mouse.isDown ? '#e9dc7c' : 'white');
  }
};

Debugger.prototype._renderShortcuts = function() {
  if (this.enableShortcuts) {
    var height = 24;

    this.app.video.ctx.textAlign = 'left';
    this.app.video.ctx.textBaseline = 'top';
    var maxPerCollumn = Math.floor((this.app.height - 14)/height);

    for (var i=0; i<this.options.length; i++) {
      var option = this.options[i];
      var x = 14 + Math.floor(i/maxPerCollumn) * 220;
      var y = 14 + i%maxPerCollumn * height;

      var keyIndex = i + 1;
      keyIndex = indexToNumberAndLowerCaseKey(keyIndex);

      var isOn = this[option.entry];

      var text = '[' + String.fromCharCode(keyIndex) + '] ' + option.name;
      if (option.type === 'toggle') {
        text += ' (' + (isOn ? 'ON' : 'OFF') + ')';
      } else if (option.type === 'call') {
        text += ' (CALL)';
      }

      var color = 'rgba(255, 255, 255, 1)';
      var outline = 'rgba(0, 0, 0, 1)';

      if (!isOn) {
        color = 'rgba(255, 255, 255, .7)';
        outline = 'rgba(0, 0, 0, .7)';
      }

      this._renderText(text, x, y, color, outline);
    }
  }
};

Debugger.prototype._renderText = function(text, x, y, color, outline) {
  color = color || 'white';
  outline = outline || 'black';
  this.app.video.ctx.fillStyle = color;
  this.app.video.ctx.lineJoin = 'round';
  this.app.video.ctx.strokeStyle = outline;
  this.app.video.ctx.lineWidth = 3;
  this.app.video.ctx.strokeText(text, x, y);
  this.app.video.ctx.fillText(text, x, y);
};

module.exports = Debugger;
<commit_msg>add support for shortcuts with ctrl<commit_after>var util = require('util');
var sourceMaps = require('source-map-support');

var indexToNumberAndLowerCaseKey = function(index) {
  if (index <= 9) {
    return 48 + index;
  } else if (index === 10) {
    return 48;
  } else if (index > 10 && index <= 36) {
    return 64 + (index-10);
  } else {
    return null;
  }
};

var defaults = [
  { name: 'Show FPS', entry: 'showFps', default: true },
  { name: 'Show Key Codes', entry: 'showKeyCodes', default: true },
  { name: 'Show Time', entry: 'showTime', default: true }
];

var Debugger = function(app, options) {
  this.app = app;
  options = options || [];

  options = options.concat(defaults);

  this.options = options;

  for (var i=0; i<options.length; i++) {
    var option = options[i];
    option.type = option.type || 'toggle';
    option.default = option.default == null ? false : option.default;

    if (option.type === 'toggle') {
      this[option.entry] = option.default;
    }
  }

  if (window.localStorage && window.localStorage.__debug) {
    var data = JSON.parse(window.localStorage.__debug);
    for (var name in data) {
      this[name] = data[name];
    }
  }

  sourceMaps.install();

  this.fps = 0;
  this.fpsCount = 0;
  this.fpsElapsedTime = 0;
  this.fpsUpdateInterval = 0.5;

  this.logs = [];

  this.showDebug = true;
  this.enableDebugKeys = true;
  this.enableShortcuts = false;

  this.enableShortcutsKey = 220;

  this.lastKey = null;

  this.keyShortcuts = [
    { key: 123, entry: 'showDebug', type: 'toggle' }
  ];

  var self = this;

  window.addEventListener('error', function(error) {
    self.log(error.error.stack, 'red');
  });
};

Debugger.prototype.log = function(message, color) {
  color = color || 'white';
  message = typeof message === 'string' ? message : util.inspect(message);

  var messages = message.replace(/\\'/g, "'").split('\n');

  for (var i=0; i<messages.length; i++) {
    var msg = messages[i];
    this.logs.push({ text: msg, life: 10, color: color });
  }
};

Debugger.prototype.enterUpdate = function() {
  if (this.pause) {
    return true;
  }
};

Debugger.prototype.update = function(time) {
  if (this.showDebug) {
    this.fpsCount += 1;
    this.fpsElapsedTime += time;

    if (this.fpsElapsedTime > this.fpsUpdateInterval) {
      var fps = this.fpsCount/this.fpsElapsedTime;

      if (this.showFps) {
        this.fps = this.fps * (1-0.8) + 0.8 * fps;
      }

      this.fpsCount = 0;
      this.fpsElapsedTime = 0;
    }

    for (var i=0, len=this.logs.length; i<len; i++) {
      var log = this.logs[i];
      if (log) {
        log.life -= time;
        if (log.life <= 0) {
          var index = this.logs.indexOf(log);
          if (index > -1) { this.logs.splice(index, 1); }
        }
      }
    }
  }
};

Debugger.prototype.keydown = function(key) {
  this.lastKey = key;

  var i;

  if (this.enableDebugKeys) {
    if (key === this.enableShortcutsKey) {
      this.enableShortcuts = !this.enableShortcuts;
      return true;
    }

    if (this.enableShortcuts) {
      for (i=0; i<this.options.length; i++) {
        var option = this.options[i];

        var keyIndex = i + 1;

        if (this.app.input.isKeyDown('ctrl')) {
          keyIndex -= 36;
        }

        var charId = indexToNumberAndLowerCaseKey(keyIndex);

        if (charId && key === charId) {
          if (option.type === 'toggle') {

            this[option.entry] = !this[option.entry];

            var data = {};

            if (window.localStorage.__debug) {
              data = JSON.parse(window.localStorage.__debug);
            }

            data[option.entry] = this[option.entry];

            window.localStorage.__debug = JSON.stringify(data);

          } else if (option.type === 'call') {
            option.entry();
          }

          return true;
        }
      }
    }
  }

  for (i=0; i<this.keyShortcuts.length; i++) {
    var keyShortcut = this.keyShortcuts[i];
    if (keyShortcut.key === key) {

      if (keyShortcut.type === 'toggle') {
        this[keyShortcut.entry] = !this[keyShortcut.entry];
      } else if (keyShortcut.type === 'call') {
        this[keyShortcut.entry]();
      }

      return true;
    }
  }

  return false;
};

Debugger.prototype.render = function() {
  if (this.showDebug) {
    this.app.video.ctx.save();
    this.app.video.ctx.font = '15px sans-serif';

    this._renderLogs();
    this._renderData();
    this._renderShortcuts();

    this.app.video.ctx.restore();
  }
};

Debugger.prototype._renderLogs = function() {
  this.app.video.ctx.textAlign = 'left';
  this.app.video.ctx.textBaseline = 'bottom';

  for (var i=0, len=this.logs.length; i<len; i++) {
    var log = this.logs[i];

    var y = -10 + this.app.height + (i - this.logs.length + 1) * 20;
    this._renderText(log.text, 10, y, log.color);
  }
};

Debugger.prototype._renderData = function() {
  this.app.video.ctx.textAlign = 'right';
  this.app.video.ctx.textBaseline = 'top';

  var x = this.app.width - 14;
  var y = 14;

  if (this.showFps) {
    this._renderText(Math.round(this.fps) + ' fps', x, y);
  }

  y += 20;

  this.app.video.ctx.font = '20px sans-serif';
  if (this.showTime) {
    if (this.app.runtime && this.app.runtime.time != null) {
      this._renderText(this.app.runtime.time.toFixed(2) + ' s', x, y);
    }
  }
  y += 30;

  this.app.video.ctx.font = '15px sans-serif';

  if (this.showKeyCodes) {
    this._renderText('key ' + this.lastKey, x, y, this.app.input.isKeyDown(this.lastKey) ? '#e9dc7c' : 'white');
    this._renderText('btn ' + this.app.input.mouse.button, x - 60, y, this.app.input.mouse.isDown ? '#e9dc7c' : 'white');
  }
};

Debugger.prototype._renderShortcuts = function() {
  if (this.enableShortcuts) {
    var height = 24;

    this.app.video.ctx.textAlign = 'left';
    this.app.video.ctx.textBaseline = 'top';
    var maxPerCollumn = Math.floor((this.app.height - 14)/height);

    for (var i=0; i<this.options.length; i++) {
      var option = this.options[i];
      var x = 14 + Math.floor(i/maxPerCollumn) * 220;
      var y = 14 + i%maxPerCollumn * height;

      var keyIndex = i + 1;
      var charId = indexToNumberAndLowerCaseKey(keyIndex);

      var isOn = this[option.entry];

      var shortcut = String.fromCharCode(charId);

      if (!charId) {
        shortcut = '^+' + String.fromCharCode(indexToNumberAndLowerCaseKey(keyIndex - 36));
      }

      var text = '[' + shortcut + '] ' + option.name;
      if (option.type === 'toggle') {
        text += ' (' + (isOn ? 'ON' : 'OFF') + ')';
      } else if (option.type === 'call') {
        text += ' (CALL)';
      }

      var color = 'rgba(255, 255, 255, 1)';
      var outline = 'rgba(0, 0, 0, 1)';

      if (!isOn) {
        color = 'rgba(255, 255, 255, .7)';
        outline = 'rgba(0, 0, 0, .7)';
      }

      this._renderText(text, x, y, color, outline);
    }
  }
};

Debugger.prototype._renderText = function(text, x, y, color, outline) {
  color = color || 'white';
  outline = outline || 'black';
  this.app.video.ctx.fillStyle = color;
  this.app.video.ctx.lineJoin = 'round';
  this.app.video.ctx.strokeStyle = outline;
  this.app.video.ctx.lineWidth = 3;
  this.app.video.ctx.strokeText(text, x, y);
  this.app.video.ctx.fillText(text, x, y);
};

module.exports = Debugger;
<|endoftext|>


<commit_before>'use strict';

module.exports = require('./lib/raindrop');
<commit_msg>remove pesky semis<commit_after>'use strict'

module.exports = require('./lib/raindrop')
<|endoftext|>


<commit_before>'use strict';
const Koa = require('koa');
const MqttServer = require('./mqtt-server');
const server = new MqttServer();
const router = require('./router');
const data = {};
const jsonp = require('koa-jsonp');

server.ready(() => {
  const app = new Koa();
  const redis = server.redisClient;
  app.server = server;
  app.use(router.routes());
  app.use(function*(next){
    this.set('Access-Control-Allow-Origin','*');
    yield next;
  });
  app.queryData = function(metric) {
    return redis.get(metric);
  }
  server.on('published', (message, client) => {
    if (message.topic === 'sensor') {
      try {
        const msg = JSON.parse(message.payload);
        const metric = msg.metric;
        const value = msg.value;
        if (!data[metric]) {
          data[metric] = [];
        }
        data[metric].push({
          time: Date.now(),
          value,
        });
        if (data[metric].length > 1000) {
          data[metric] = data[metric].slice(-1000);
        }
        redis.set(metric, JSON.stringify(data[metric]));
      } catch (err) {
        console.log(message.toString());
        console.error(err);
      }
    }
  });

  const port = 80;
  app.listen(port, () => {
    console.log(`app is listening on ${port}`);
  });
});
<commit_msg>fix: add Access-Control-Allow-Origin<commit_after>'use strict';
const Koa = require('koa');
const MqttServer = require('./mqtt-server');
const server = new MqttServer();
const router = require('./router');
const data = {};
const jsonp = require('koa-jsonp');

server.ready(() => {
  const app = new Koa();
  const redis = server.redisClient;
  app.server = server;
  app.use(function*(next){
    this.set('Access-Control-Allow-Origin','*');
    yield next;
  });
  app.use(router.routes());

  app.queryData = function(metric) {
    return redis.get(metric);
  }
  server.on('published', (message, client) => {
    if (message.topic === 'sensor') {
      try {
        const msg = JSON.parse(message.payload);
        const metric = msg.metric;
        const value = msg.value;
        if (!data[metric]) {
          data[metric] = [];
        }
        data[metric].push({
          time: Date.now(),
          value,
        });
        if (data[metric].length > 1000) {
          data[metric] = data[metric].slice(-1000);
        }
        redis.set(metric, JSON.stringify(data[metric]));
      } catch (err) {
        console.log(message.toString());
        console.error(err);
      }
    }
  });

  const port = 80;
  app.listen(port, () => {
    console.log(`app is listening on ${port}`);
  });
});
<|endoftext|>


<commit_before>var express = require('express');
var app = express();
var port = process.env.PORT || 3000;
var verificationToken = process.env.SLACK_VERIFICATION_TOKEN || 'foobar';
var clientID = process.env.SLACK_CLIENT_ID || 'foobar';
var clientSecret = process.env.SLACK_CLIENT_SECRET || 'foobar';
var callbackURL = process.env.SLACK_CALLBACK_URL || 'foobar';
var request = require('request');
var bodyParser = require('body-parser');
var passport = require('passport');
var SlackStrategy = require('passport-slack').Strategy;

app.use(bodyParser.urlencoded({extended: true}));
passport.use(new SlackStrategy({
        clientID: clientID,
        clientSecret: clientSecret,
        callbackURL: callbackURL,
        scope: 'commands chat:write:bot',
        skipUserProfile: true
    }, ()=>{}));

app.get('/auth/slack', passport.authenticate('slack'));

app.get('/auth/slack/callback', function(req, res) {
    res.redirect('https://my.slack.com');
  });

//Slack token authentication middleware
app.get('/',function (req, res){
  res.json({"message":"OK"})
})
function sendSecret(responseUrl, username, text){
  var message = {
    "response_type":"in_channel",
    "attachments": [
      {
        "title": username + " sent a secret message:",
        "callback_id": "readMessage",
        "color": "#3AA3E3",
        "attachment_type": "default",
        "actions": [
          {
            "name": "readMessage",
            "text": "View message",
            "type": "button",
            "value": "readMessage",
            "confirm": {
              "title": "This message will self destruct after reading!",
              "text": text,
              "ok_text":"I have read the message!",
              "dismiss_text":"Cancel"
            }
          }
        ]
      }
    ]
  }
  request(
    {
      method: 'post',
      uri: responseUrl,
      json: true,
      body: message
    }
  , function (error, response, body) {
      if(!error && response.statusCode == 200){
        return
      } else {
        console.log(error)
        console.log('error: '+ response.statusCode)
        console.log(body)
      }
    }
  );
}

app.post('/secret', function (req, res) {
  console.log(req)
  var body = req.body
  if (body.token == verificationToken){
    res.end(null,function(err){
      sendSecret(body.response_url, body.user_name, body.text);
    });
  } else {
    console.log('Failed token verification.');
    console.log('Expected token: '+verificationToken)
    console.log('Received token: '+req.body.token);
    return
  }
});

app.post('/update', function (req, res) {
  console.log(JSON.stringify(req.body));

});
app.listen(process.env.PORT, function () {
  console.log('Example app listening');
});
<commit_msg>git gud<commit_after>var express = require('express');
var app = express();
var port = process.env.PORT || 3000;
var verificationToken = process.env.SLACK_VERIFICATION_TOKEN || 'foobar';
var clientID = process.env.SLACK_CLIENT_ID || 'foobar';
var clientSecret = process.env.SLACK_CLIENT_SECRET || 'foobar';
var callbackURL = process.env.SLACK_CALLBACK_URL || 'foobar';
var request = require('request');
var bodyParser = require('body-parser');
var passport = require('passport');
var SlackStrategy = require('passport-slack').Strategy;

app.use(bodyParser.urlencoded({extended: true}));
passport.use(new SlackStrategy({
        clientID: clientID,
        clientSecret: clientSecret,
        callbackURL: callbackURL,
        scope: 'commands chat:write:bot',
        skipUserProfile: true
    }, ()=>{}));

app.get('/auth/slack', passport.authorize('slack'));

app.get('/auth/slack/callback', function(req, res) {
    res.redirect('https://my.slack.com');
  });

//Slack token authentication middleware
app.get('/',function (req, res){
  res.json({"message":"OK"})
})
function sendSecret(responseUrl, username, text){
  var message = {
    "response_type":"in_channel",
    "attachments": [
      {
        "title": username + " sent a secret message:",
        "callback_id": "readMessage",
        "color": "#3AA3E3",
        "attachment_type": "default",
        "actions": [
          {
            "name": "readMessage",
            "text": "View message",
            "type": "button",
            "value": "readMessage",
            "confirm": {
              "title": "This message will self destruct after reading!",
              "text": text,
              "ok_text":"I have read the message!",
              "dismiss_text":"Cancel"
            }
          }
        ]
      }
    ]
  }
  request(
    {
      method: 'post',
      uri: responseUrl,
      json: true,
      body: message
    }
  , function (error, response, body) {
      if(!error && response.statusCode == 200){
        return
      } else {
        console.log(error)
        console.log('error: '+ response.statusCode)
        console.log(body)
      }
    }
  );
}

app.post('/secret', function (req, res) {
  console.log(req)
  var body = req.body
  if (body.token == verificationToken){
    res.end(null,function(err){
      sendSecret(body.response_url, body.user_name, body.text);
    });
  } else {
    console.log('Failed token verification.');
    console.log('Expected token: '+verificationToken)
    console.log('Received token: '+req.body.token);
    return
  }
});

app.post('/update', function (req, res) {
  console.log(JSON.stringify(req.body));

});
app.listen(process.env.PORT, function () {
  console.log('Example app listening');
});
<|endoftext|>


<commit_before>/*!
 * verb-toc <https://github.com/jonschlinkert/verb-toc>
 *
 * Copyright (c) 2016, Jon Schlinkert.
 * Licensed under the MIT License.
 */

'use strict';

var extend = require('extend-shallow');
var toc = require('markdown-toc');

module.exports = function(app) {
  app.postLayout(/\.md/, createToc('postLayout', app));
  app.postRender(/\.md/, createToc('postRender', app));
  app.preWrite(/\.md/, injectToc(app));
};

function createToc(method, app) {
  return function(file, next) {
    var opts = createOpts(app, file);

    if (method !== opts.toc.method) {
      next(null, file);
      return;
    }

    if (opts.toc.render !== true) {
      next(null, file);
      return;
    }

    opts.linkify = opts.linkify || function(token, name, slug, tocOpts) {
      if (/^[{<]%?/.test(name)) {
        var view = app.view('toctemp' + file.extname, {content: name});
        app.compile(view, opts);
        token.content = view.fn(app.cache.data);
      }
      toc.linkify(token, name, slug, tocOpts);
      return token;
    };

    file.toc = toc(file.content, opts);
    if (app.hasListeners('toc')) {
      app.emit('toc', file, next);
      return;
    }

    next(null, file);
  };
};

function injectToc(app) {
  return function(file, next) {
    var opts = createOpts(app, file);
    var str = file.contents.toString();

    if (opts.toc.method === 'preWrite') {
      file.toc = toc(file.content, opts);
    }

    var tocString = (file.toc && file.toc.content) ? file.toc.content : '';
    var min = opts.toc.minLevels;

    // does the TOC have the minimum expected levels to render?
    if (typeof min === 'number') {
      opts.toc.render = hasMinimumLevels(tocString, min);
    }

    if (tocString === '' || opts.toc.render !== true) {
      str = str.replace(/^#+ (TOC|table of contents)/gmi, '');
      tocString = '';
    } else {
      tocString += opts.toc.footer || '';
    }

    // don't render toc comments in backticks
    str = str.replace(/(?!`)<!-- toc -->(?!`)/g, tocString);
    // fix escaped code comments (used as macros)
    str = str.split('<!!--').join('<!--');
    str = str.replace(/\n{2,}/g, '\n\n');
    file.contents = new Buffer(str);
    next(null, file);
  };
}

function createOpts(app, file) {
  var opts = extend({toc: {}}, app.options, file.options, file.data);
  if (typeof opts.toc === 'string') {
    opts.toc = { method: opts.toc };
  }

  if (typeof opts.toc === 'boolean') {
    opts.toc = { render: opts.toc };
  }
  if (typeof opts.toc.method === 'string' || opts.toc.match || typeof opts.toc.minLevels === 'number') {
    opts.toc.render = true;
  }
  if (opts.toc && typeof opts.toc === 'object' && typeof opts.toc.method !== 'string') {
    opts.toc.method = 'postLayout';
  }

  opts = extend({}, opts, opts.toc);
  return opts;
}

function hasMinimumLevels(str, min) {
  var lines = str.split('\n');
  var len = lines.length;
  var max = 0;
  while (len--) {
    var line = lines[len]
    var ws = /^\s+/.exec(line);
    if (!ws) continue;
    var wlen = ws[0].length;
    if (wlen > max) {
      max = wlen;
    }
  }
  return max >= min;
}

module.exports.createToc = createToc;
module.exports.injectToc = injectToc;
<commit_msg>update template handling<commit_after>/*!
 * verb-toc <https://github.com/jonschlinkert/verb-toc>
 *
 * Copyright (c) 2016, Jon Schlinkert.
 * Licensed under the MIT License.
 */

'use strict';

var isObject = require('isobject');
var extend = require('extend-shallow');
var toc = require('markdown-toc');

module.exports = function(app) {
  app.postLayout(/\.md/, createToc('postLayout', app));
  app.postRender(/\.md/, createToc('postRender', app));
  app.postRender(/\.md/, createToc('preRender', app));
  app.preWrite(/\.md/, injectToc(app));
};

function createToc(method, app) {
  return function(file, next) {
    var opts = createOpts(app, file);

    if (method !== opts.toc.method) {
      next(null, file);
      return;
    }

    if (opts.toc.render !== true) {
      next(null, file);
      return;
    }

    opts.linkify = opts.linkify || function(tok, name, slug, tocOpts) {
      if (/^[{<]%?/.test(tok.content)) {
        var view = app.view('temp' + file.extname, {content: tok.content});
        app.compile(view, opts);
        name = tok.content = view.fn(app.cache.data);
      }
      toc.linkify(tok, name, slug, tocOpts);
      return tok;
    };

    file.toc = toc(file.content, opts);
    if (app.hasListeners('toc')) {
      app.emit('toc', file, next);
      return;
    }

    next(null, file);
  };
};

function injectToc(app) {
  return function(file, next) {
    var opts = createOpts(app, file);
    var str = file.contents.toString();

    if (opts.toc.method === 'preWrite') {
      file.toc = toc(file.content, opts);
    }

    var tocString = (file.toc && file.toc.content) ? file.toc.content : '';
    var min = opts.toc.minLevels;

    // does the TOC have the minimum expected levels to render?
    if (typeof min === 'number') {
      opts.toc.render = hasMinimumLevels(tocString, min);
    }

    if (tocString === '' || opts.toc.render !== true) {
      str = str.replace(/^#+ (TOC|table of contents)/gmi, '');
      tocString = '';
    } else {
      tocString += opts.toc.footer || '';
    }

    // don't render toc comments in backticks
    str = str.replace(/(?!`)<!-- toc -->(?!`)/g, tocString);

    // fix escaped code comments (used as macros)
    str = str.split('<!!--').join('<!--');
    str = str.replace(/\n{2,}/g, '\n\n');
    file.contents = new Buffer(str);
    next(null, file);
  };
}

function createOpts(app, file) {
  var opts = extend({toc: {}}, app.options, file.options, file.data);
  if (typeof opts.toc === 'string') {
    if (opts.toc === 'collapsible') {
      opts.toc = { method: 'postLayout', collapsible: true };
    } else {
      opts.toc = { method: opts.toc };
    }
  }

  if (typeof opts.toc === 'boolean') {
    opts.toc = { render: opts.toc };
  }

  if (!isObject(opts.toc)) {
    opts.toc = {};
  }

  if (typeof opts.toc.method === 'string' || opts.toc.match || typeof opts.toc.minLevels === 'number') {
    opts.toc.render = true;
  } else {
    opts.toc.method = 'postLayout';
  }

  opts = extend({}, opts, opts.toc);
  return opts;
}

function hasMinimumLevels(str, min) {
  var lines = str.split('\n');
  var len = lines.length;
  var max = 0;
  while (len--) {
    var line = lines[len];
    var ws = /^\s+/.exec(line);
    if (!ws) continue;
    var wlen = ws[0].length;
    if (wlen > max) {
      max = wlen;
    }
  }
  return max >= min;
}

module.exports.createToc = createToc;
module.exports.injectToc = injectToc;
<|endoftext|>


<commit_before>$('document').ready(function() {
	require(['composer', 'composer/controls'], function(composer, controls) {
		composer.addButton('fa fa-eraser', function(textarea, selectionStart, selectionEnd) {
			if (selectionStart === selectionEnd) {
				controls.insertIntoTextarea(textarea, '');
				controls.updateTextareaSelection(textarea, selectionStart + 5, selectionStart + 5);
			} else {
				controls.wrapSelectionInTextareaWith(textarea, '', 'text');
				controls.updateTextareaSelection(textarea, selectionEnd + 16, selectionEnd + 20);
			}
		});
		composer.addButton('fa fa-info-circle', function(textarea, selectionStart, selectionEnd) {
			if (selectionStart === selectionEnd) {
				controls.insertIntoTextarea(textarea, '');
				controls.updateTextareaSelection(textarea, selectionStart + 13, selectionStart + 18);
			} else {
				controls.wrapSelectionInTextareaWith(textarea, 'Text');
				controls.updateTextareaSelection(textarea, selectionEnd + 15, selectionEnd + 19);
			}
		});
	});
});

<commit_msg>Spoiler button<commit_after>$('document').ready(function() {
	require(['composer', 'composer/controls'], function(composer, controls) {
		composer.addButton('fa fa-eraser', function(textarea, selectionStart, selectionEnd) {
			if (selectionStart === selectionEnd) {
				controls.insertIntoTextarea(textarea, '');
				controls.updateTextareaSelection(textarea, selectionStart + 5, selectionStart + 5);
			} else {
				controls.wrapSelectionInTextareaWith(textarea, '', 'text');
				controls.updateTextareaSelection(textarea, selectionEnd + 16, selectionEnd + 20);
			}
		});
		composer.addButton('fa fa-info-circle', function(textarea, selectionStart, selectionEnd) {
			if (selectionStart === selectionEnd) {
				controls.insertIntoTextarea(textarea, '');
				controls.updateTextareaSelection(textarea, selectionStart + 13, selectionStart + 18);
			} else {
				controls.wrapSelectionInTextareaWith(textarea, 'Text');
				controls.updateTextareaSelection(textarea, selectionEnd + 15, selectionEnd + 19);
			}
		});
		composer.addButton('fa fa-eye-slash', function(textarea, selectionStart, selectionEnd) {
			if (selectionStart === selectionEnd) {
				controls.insertIntoTextarea(textarea, 'captioncontent');
				controls.updateTextareaSelection(textarea, selectionStart + 35, selectionStart + 42);
			} else {
				controls.wrapSelectionInTextareaWith(textarea, 'caption', '');
				controls.updateTextareaSelection(textarea, selectionEnd + 18, selectionEnd + 25);
			}
		});
	});
});

<|endoftext|>


<commit_before>#!/usr/bin/env node

var fs = require('fs');
var path = require('path');
var program = require('commander');
var pkg = require(path.join(__dirname, 'package.json'));

program
  .version(pkg.version)
  .arguments('<file>')
  .action(function(file) {
    file = file;

  });
program.parse(process.argv);
var data = '';
var CF = require('./formatter');

if (typeof file === 'undefined') {
  input = process.stdin;
  input.resume();
  input.setEncoding('utf8');
  input.on('data', function(chunk) {
    data += chunk;
  });
  input.on('end', function() {
    formatIt(data);
  });

} else {
  var text = fs.readFileSync(file, 'utf8');
  formatIt(text);
}

function formatIt(text) {
  var lines = text.split('\n');
  var resultArr = [];
  for (var i = 0; i < lines.length; i++) {
    var curr = lines[i];
    var p = CF.formatTwoSpaceOperator(curr);
    p = CF.formatOneSpaceOperator(p);
    p = CF.shortenSpaces(p);
    resultArr.push(p);
  }
  var result = resultArr.join('\n');
  process.stdout.write(result);
  process.exit(0);
}
<commit_msg>modify source format<commit_after>#!/usr/bin/env node

var fs = require('fs');
var path = require('path');
var program = require('commander');
var pkg = require(path.join(__dirname, 'package.json'));

program
  .version(pkg.version)
  .arguments('<file>')
  .action(function(file) {
    file = file;
  });

program.parse(process.argv);
var data = '';
var CF = require('./formatter');

if (typeof file === 'undefined') {
  input = process.stdin;
  input.resume();
  input.setEncoding('utf8');
  input.on('data', function(chunk) {
    data += chunk;
  });
  input.on('end', function() {
    formatIt(data);
  });

} else {
  var text = fs.readFileSync(file, 'utf8');
  formatIt(text);
}

function formatIt(text) {
  var lines = text.split('\n');
  var resultArr = [];
  for (var i = 0; i < lines.length; i++) {
    var curr = lines[i];
    var p = CF.formatTwoSpaceOperator(curr);
    p = CF.formatOneSpaceOperator(p);
    p = CF.shortenSpaces(p);
    resultArr.push(p);
  }
  var result = resultArr.join('\n');
  process.stdout.write(result);
  process.exit(0);
}
<|endoftext|>