<commit_before>/*
  Note that the main run() loop will be executed once per frame as specified by WORLD_UPDATE_INTERVAL in worker.js.
  Behind the scenes, the engine just keeps on building up a cellData tree of all different
  state objects that are present within our current grid cell.
  The tree is a simple JSON object and needs to be in the format:

    {
      player: {
        // ...
      },
      someType: {
        someId: {
          // All properties listed here are required.
          // You can add additional ones.
          id: theValueOfSomeId,
          type: theValueOfSomeType,
          x: someXCoordinateWithinOurCurrentCell,
          y: someYCoordinateWithinOurCurrentCell,
        },
        anotherId: {
          // ...
        }
      }
    }

  You can add new type structures, new properties and new items to the cellData
  as you like. So long as you follow the structure above, the items should show
  up on the front end in the relevant cell in our world (see the handleCellData function in index.html).
  See how CoinManager was implemented for details of how to add items within the cell.

  Note that states which are close to our current cell (based on WORLD_CELL_OVERLAP_DISTANCE)
  but not exactly inside it will still be visible within this cell (they will have an additional
  'external' property set to true).

  External states should not be modified unless they are grouped together with an internal state.
  See the util.groupStates() function near the bottom of this file for details.
*/

var _ = require('lodash');
var rbush = require('rbush');
var SAT = require('sat');
var config = require('./config');
var BotManager = require('./bot-manager').BotManager;
var CoinManager = require('./coin-manager').CoinManager;

// This controller will be instantiated once for each
// cell in our world grid.

var CellController = function (options, util) {
  var self = this;

  this.options = options;
  this.cellIndex = options.cellIndex;
  this.util = util;

  this.worldColCount = Math.ceil(config.WORLD_WIDTH / config.WORLD_CELL_WIDTH);
  this.worldRowCount = Math.ceil(config.WORLD_HEIGHT / config.WORLD_CELL_HEIGHT);
  this.worldCellCount = this.worldColCount * this.worldRowCount;
  this.workerCount = options.worker.options.workers;

  this.coinMaxCount = Math.round(config.COIN_MAX_COUNT / this.worldCellCount);
  this.coinDropInterval = config.COIN_DROP_INTERVAL * this.worldCellCount;
  this.botCount = Math.round(config.BOT_COUNT / this.worldCellCount);

  var cellData = options.cellData;

  this.botManager = new BotManager({
    worldWidth: config.WORLD_WIDTH,
    worldHeight: config.WORLD_HEIGHT,
    botDiameter: config.BOT_DIAMETER,
    botMoveSpeed: config.BOT_MOVE_SPEED,
    botMass: config.BOT_MASS,
    botChangeDirectionProbability: config.BOT_CHANGE_DIRECTION_PROBABILITY
  });

  if (!cellData.player) {
    cellData.player = {};
  }

  for (var b = 0; b < this.botCount; b++) {
    var bot = this.botManager.addBot();
    cellData.player[bot.id] = bot;
  }

  this.botMoves = [
    {u: 1},
    {d: 1},
    {r: 1},
    {l: 1}
  ];

  this.coinManager = new CoinManager({
    cellData: options.cellData,
    cellBounds: options.cellBounds,
    playerNoDropRadius: config.COIN_PLAYER_NO_DROP_RADIUS,
    coinMaxCount: this.coinMaxCount,
    coinDropInterval: this.coinDropInterval
  });

  this.lastCoinDrop = 0;

  config.COIN_TYPES.sort(function (a, b) {
    if (a.probability < b.probability) {
      return -1;
    }
    if (a.probability > b.probability) {
      return 1;
    }
    return 0;
  });

  this.coinTypes = [];
  var probRangeStart = 0;
  config.COIN_TYPES.forEach(function (coinType) {
    var coinTypeClone = _.cloneDeep(coinType);
    coinTypeClone.prob = probRangeStart;
    self.coinTypes.push(coinTypeClone);
    probRangeStart += coinType.probability;
  });

  this.playerCompareFn = function (a, b) {
    if (a.id < b.id) {
      return -1;
    }
    if (a.id > b.id) {
      return 1;
    }
    return 0;
  };

  this.diagonalSpeedFactor = Math.sqrt(1 / 2);
};

/*
  The main run loop for our cell controller.
*/
CellController.prototype.run = function (cellData) {
  if (!cellData.player) {
    cellData.player = {};
  }
  if (!cellData.coin) {
    cellData.coin = {};
  }
  var players = cellData.player;
  var coins = cellData.coin;

  // Sorting is important to achieve consistency across cells.
  var playerIds = Object.keys(players).sort(this.playerCompareFn);

  this.findPlayerOverlaps(playerIds, players, coins);
  this.dropCoins(coins);
  this.generateBotOps(playerIds, players);
  this.applyPlayerOps(playerIds, players, coins);
};

CellController.prototype.dropCoins = function (coins) {
  var now = Date.now();

  if (now - this.lastCoinDrop >= this.coinManager.coinDropInterval &&
    this.coinManager.coinCount < this.coinManager.coinMaxCount) {

    this.lastCoinDrop = now;

    var rand = Math.random();
    var chosenCoinType;

    var numTypes = this.coinTypes.length;
    for (var i = numTypes - 1; i >= 0; i--) {
      var curCoinType = this.coinTypes[i];
      if (rand >= curCoinType.prob) {
        chosenCoinType = curCoinType;
        break;
      }
    }

    if (!chosenCoinType) {
      throw new Error('There is something wrong with the coin probability distribution. ' +
        'Check that probabilities add up to 1 in COIN_TYPES config option.');
    }

    var coin = this.coinManager.addCoin(chosenCoinType.value, chosenCoinType.type, chosenCoinType.radius);
    if (coin) {
      coins[coin.id] = coin;
    }
  }
};

CellController.prototype.generateBotOps = function (playerIds, players, coins) {
  var self = this;

  playerIds.forEach(function (playerId) {
    var player = players[playerId];
    // States which are external are managed by a different cell, therefore changes made to these
    // states are not saved unless they are grouped with one or more internal states from the current cell.
    // See util.groupStates() method near the bottom of this file for details.
    if (player.subtype == 'bot' && !player.external) {
      var radius = Math.round(player.width / 2);
      var isBotOnEdge = player.x <= radius || player.x >= config.WORLD_WIDTH - radius ||
        player.y <= radius || player.y >= config.WORLD_HEIGHT - radius;

      if (Math.random() <= player.changeDirProb || isBotOnEdge) {
        var randIndex = Math.floor(Math.random() * self.botMoves.length);
        player.repeatOp = self.botMoves[randIndex];
      }
      if (player.repeatOp) {
        player.op = player.repeatOp;
      }
    }
  });
};

CellController.prototype.keepPlayerOnGrid = function (player) {
  var halfWidth = Math.round(player.width / 2);
  var halfHeight = Math.round(player.height / 2);

  var leftX = player.x - halfWidth;
  var rightX = player.x + halfWidth;
  var topY = player.y - halfHeight;
  var bottomY = player.y + halfHeight;

  if (leftX < 0) {
    player.x = halfWidth;
  } else if (rightX > config.WORLD_WIDTH) {
    player.x = config.WORLD_WIDTH - halfWidth;
  }
  if (topY < 0) {
    player.y = halfHeight;
  } else if (bottomY > config.WORLD_HEIGHT) {
    player.y = config.WORLD_HEIGHT - halfHeight;
  }
};

CellController.prototype.applyPlayerOps = function (playerIds, players, coins) {
  var self = this;

  playerIds.forEach(function (playerId) {
    var player = players[playerId];

    var playerOp = player.op;
    var moveSpeed;
    if (player.subtype == 'bot') {
      moveSpeed = player.speed;
    } else {
      moveSpeed = config.PLAYER_DEFAULT_MOVE_SPEED;
    }

    if (playerOp) {
      var movementVector = {x: 0, y: 0};
      var movedHorizontally = false;
      var movedVertically = false;

      if (playerOp.u) {
        movementVector.y = -moveSpeed;
        player.direction = 'up';
        movedVertically = true;
      }
      if (playerOp.d) {
        movementVector.y = moveSpeed;
        player.direction = 'down';
        movedVertically = true;
      }
      if (playerOp.r) {
        movementVector.x = moveSpeed;
        player.direction = 'right';
        movedHorizontally = true;
      }
      if (playerOp.l) {
        movementVector.x = -moveSpeed;
        player.direction = 'left';
        movedHorizontally = true;
      }

      if (movedHorizontally && movedVertically) {
        movementVector.x *= self.diagonalSpeedFactor;
        movementVector.y *= self.diagonalSpeedFactor;
      }

      player.x += movementVector.x;
      player.y += movementVector.y;
    }

    if (player.playerOverlaps) {
      player.playerOverlaps.forEach(function (otherPlayer) {
        self.resolvePlayerCollision(player, otherPlayer);
        self.keepPlayerOnGrid(otherPlayer);
      });
      delete player.playerOverlaps;
    }

    if (player.coinOverlaps) {
      player.coinOverlaps.forEach(function (coin) {
        if (self.testCircleCollision(player, coin).collided) {
          player.score += coin.v;
          self.coinManager.removeCoin(coin.id);
        }
      });
      delete player.coinOverlaps;
    }

    self.keepPlayerOnGrid(player);
  });
};

CellController.prototype.findPlayerOverlaps = function (playerIds, players, coins) {
  var self = this;

  var playerTree = new rbush();
  var hitAreaList = [];

  playerIds.forEach(function (playerId) {
    var player = players[playerId];
    player.hitArea = self.generateHitArea(player);
    hitAreaList.push(player.hitArea);
  });

  playerTree.load(hitAreaList);

  playerIds.forEach(function (playerId) {
    var player = players[playerId];
    playerTree.remove(player.hitArea);
    var hitList = playerTree.search(player.hitArea);
    playerTree.insert(player.hitArea);

    hitList.forEach(function (hit) {
      if (!player.playerOverlaps) {
        player.playerOverlaps = [];
      }
      player.playerOverlaps.push(hit.target);
    });
  });

  var coinIds = Object.keys(coins);
  coinIds.forEach(function (coinId) {
    var coin = coins[coinId];
    var coinHitArea = self.generateHitArea(coin);
    var hitList = playerTree.search(coinHitArea);

    if (hitList.length) {
      // If multiple players hit the coin, give it to a random one.
      var randomIndex = Math.floor(Math.random() * hitList.length);
      var coinWinner = hitList[randomIndex].target;

      if (!coinWinner.coinOverlaps) {
        coinWinner.coinOverlaps = [];
      }
      coinWinner.coinOverlaps.push(coin);
    }
  });

  playerIds.forEach(function (playerId) {
    delete players[playerId].hitArea;
  });
};

CellController.prototype.generateHitArea = function (target) {
  var targetRadius = target.r || Math.round(target.width / 2);
  return {
    target: target,
    minX: target.x - targetRadius,
    minY: target.y - targetRadius,
    maxX: target.x + targetRadius,
    maxY: target.y + targetRadius
  };
};

CellController.prototype.testCircleCollision = function (a, b) {
  var radiusA = a.r || Math.round(a.width / 2);
  var radiusB = b.r || Math.round(b.width / 2);

  var circleA = new SAT.Circle(new SAT.Vector(a.x, a.y), radiusA);
  var circleB = new SAT.Circle(new SAT.Vector(b.x, b.y), radiusB);

  var response = new SAT.Response();
  var collided = SAT.testCircleCircle(circleA, circleB, response);

  return {
    collided: collided,
    overlapV: response.overlapV
  };
};

CellController.prototype.resolvePlayerCollision = function (player, otherPlayer) {
  var result = this.testCircleCollision(player, otherPlayer);

  if (result.collided) {
    var olv = result.overlapV;

    var totalMass = player.mass + otherPlayer.mass;
    var playerBuff = player.mass / totalMass;
    var otherPlayerBuff = otherPlayer.mass / totalMass;

    player.x -= olv.x * otherPlayerBuff;
    player.y -= olv.y * otherPlayerBuff;
    otherPlayer.x += olv.x * playerBuff;
    otherPlayer.y += olv.y * playerBuff;

    /*
      Whenever we have one state affecting the (x, y) coordinates of
      another state, we should group them together using the util.groupStates() function.
      Otherwise we will may get flicker when the two states interact across
      a cell boundary.
      In this case, if we don't use groupStates(), there will be flickering when you
      try to push another player across to a different cell.
    */
    this.util.groupStates([player, otherPlayer]);
  }
};

module.exports = CellController;
<commit_msg>Minor fix<commit_after>/*
  Note that the main run() loop will be executed once per frame as specified by WORLD_UPDATE_INTERVAL in worker.js.
  Behind the scenes, the engine just keeps on building up a cellData tree of all different
  state objects that are present within our current grid cell.
  The tree is a simple JSON object and needs to be in the format:

    {
      player: {
        // ...
      },
      someType: {
        someId: {
          // All properties listed here are required.
          // You can add additional ones.
          id: theValueOfSomeId,
          type: theValueOfSomeType,
          x: someXCoordinateWithinOurCurrentCell,
          y: someYCoordinateWithinOurCurrentCell,
        },
        anotherId: {
          // ...
        }
      }
    }

  You can add new type structures, new properties and new items to the cellData
  as you like. So long as you follow the structure above, the items should show
  up on the front end in the relevant cell in our world (see the handleCellData function in index.html).
  See how CoinManager was implemented for details of how to add items within the cell.

  Note that states which are close to our current cell (based on WORLD_CELL_OVERLAP_DISTANCE)
  but not exactly inside it will still be visible within this cell (they will have an additional
  'external' property set to true).

  External states should not be modified unless they are grouped together with an internal state.
  See the util.groupStates() function near the bottom of this file for details.
*/

var _ = require('lodash');
var rbush = require('rbush');
var SAT = require('sat');
var config = require('./config');
var BotManager = require('./bot-manager').BotManager;
var CoinManager = require('./coin-manager').CoinManager;

// This controller will be instantiated once for each
// cell in our world grid.

var CellController = function (options, util) {
  var self = this;

  this.options = options;
  this.cellIndex = options.cellIndex;
  this.util = util;

  this.worldColCount = Math.ceil(config.WORLD_WIDTH / config.WORLD_CELL_WIDTH);
  this.worldRowCount = Math.ceil(config.WORLD_HEIGHT / config.WORLD_CELL_HEIGHT);
  this.worldCellCount = this.worldColCount * this.worldRowCount;
  this.workerCount = options.worker.options.workers;

  this.coinMaxCount = Math.round(config.COIN_MAX_COUNT / this.worldCellCount);
  this.coinDropInterval = config.COIN_DROP_INTERVAL * this.worldCellCount;
  this.botCount = Math.round(config.BOT_COUNT / this.worldCellCount);

  var cellData = options.cellData;

  this.botManager = new BotManager({
    worldWidth: config.WORLD_WIDTH,
    worldHeight: config.WORLD_HEIGHT,
    botDiameter: config.BOT_DIAMETER,
    botMoveSpeed: config.BOT_MOVE_SPEED,
    botMass: config.BOT_MASS,
    botChangeDirectionProbability: config.BOT_CHANGE_DIRECTION_PROBABILITY
  });

  if (!cellData.player) {
    cellData.player = {};
  }

  for (var b = 0; b < this.botCount; b++) {
    var bot = this.botManager.addBot();
    cellData.player[bot.id] = bot;
  }

  this.botMoves = [
    {u: 1},
    {d: 1},
    {r: 1},
    {l: 1}
  ];

  this.coinManager = new CoinManager({
    cellData: options.cellData,
    cellBounds: options.cellBounds,
    playerNoDropRadius: config.COIN_PLAYER_NO_DROP_RADIUS,
    coinMaxCount: this.coinMaxCount,
    coinDropInterval: this.coinDropInterval
  });

  this.lastCoinDrop = 0;

  config.COIN_TYPES.sort(function (a, b) {
    if (a.probability < b.probability) {
      return -1;
    }
    if (a.probability > b.probability) {
      return 1;
    }
    return 0;
  });

  this.coinTypes = [];
  var probRangeStart = 0;
  config.COIN_TYPES.forEach(function (coinType) {
    var coinTypeClone = _.cloneDeep(coinType);
    coinTypeClone.prob = probRangeStart;
    self.coinTypes.push(coinTypeClone);
    probRangeStart += coinType.probability;
  });

  this.playerCompareFn = function (a, b) {
    if (a.id < b.id) {
      return -1;
    }
    if (a.id > b.id) {
      return 1;
    }
    return 0;
  };

  this.diagonalSpeedFactor = Math.sqrt(1 / 2);
};

/*
  The main run loop for our cell controller.
*/
CellController.prototype.run = function (cellData) {
  if (!cellData.player) {
    cellData.player = {};
  }
  if (!cellData.coin) {
    cellData.coin = {};
  }
  var players = cellData.player;
  var coins = cellData.coin;

  // Sorting is important to achieve consistency across cells.
  var playerIds = Object.keys(players).sort(this.playerCompareFn);

  this.findPlayerOverlaps(playerIds, players, coins);
  this.dropCoins(coins);
  this.generateBotOps(playerIds, players);
  this.applyPlayerOps(playerIds, players, coins);
};

CellController.prototype.dropCoins = function (coins) {
  var now = Date.now();

  if (now - this.lastCoinDrop >= this.coinManager.coinDropInterval &&
    this.coinManager.coinCount < this.coinManager.coinMaxCount) {

    this.lastCoinDrop = now;

    var rand = Math.random();
    var chosenCoinType;

    var numTypes = this.coinTypes.length;
    for (var i = numTypes - 1; i >= 0; i--) {
      var curCoinType = this.coinTypes[i];
      if (rand >= curCoinType.prob) {
        chosenCoinType = curCoinType;
        break;
      }
    }

    if (!chosenCoinType) {
      throw new Error('There is something wrong with the coin probability distribution. ' +
        'Check that probabilities add up to 1 in COIN_TYPES config option.');
    }

    var coin = this.coinManager.addCoin(chosenCoinType.value, chosenCoinType.type, chosenCoinType.radius);
    if (coin) {
      coins[coin.id] = coin;
    }
  }
};

CellController.prototype.generateBotOps = function (playerIds, players, coins) {
  var self = this;

  playerIds.forEach(function (playerId) {
    var player = players[playerId];
    // States which are external are managed by a different cell, therefore changes made to these
    // states are not saved unless they are grouped with one or more internal states from the current cell.
    // See util.groupStates() method near the bottom of this file for details.
    if (player.subtype == 'bot' && !player.external) {
      var radius = Math.round(player.width / 2);
      var isBotOnEdge = player.x <= radius || player.x >= config.WORLD_WIDTH - radius ||
        player.y <= radius || player.y >= config.WORLD_HEIGHT - radius;

      if (Math.random() <= player.changeDirProb || isBotOnEdge) {
        var randIndex = Math.floor(Math.random() * self.botMoves.length);
        player.repeatOp = self.botMoves[randIndex];
      }
      if (player.repeatOp) {
        player.op = player.repeatOp;
      }
    }
  });
};

CellController.prototype.keepPlayerOnGrid = function (player) {
  var halfWidth = Math.round(player.width / 2);
  var halfHeight = Math.round(player.height / 2);

  var leftX = player.x - halfWidth;
  var rightX = player.x + halfWidth;
  var topY = player.y - halfHeight;
  var bottomY = player.y + halfHeight;

  if (leftX < 0) {
    player.x = halfWidth;
  } else if (rightX > config.WORLD_WIDTH) {
    player.x = config.WORLD_WIDTH - halfWidth;
  }
  if (topY < 0) {
    player.y = halfHeight;
  } else if (bottomY > config.WORLD_HEIGHT) {
    player.y = config.WORLD_HEIGHT - halfHeight;
  }
};

CellController.prototype.applyPlayerOps = function (playerIds, players, coins) {
  var self = this;

  playerIds.forEach(function (playerId) {
    var player = players[playerId];

    var playerOp = player.op;
    var moveSpeed;
    if (player.subtype == 'bot') {
      moveSpeed = player.speed;
    } else {
      moveSpeed = config.PLAYER_DEFAULT_MOVE_SPEED;
    }

    if (playerOp) {
      var movementVector = {x: 0, y: 0};
      var movedHorizontally = false;
      var movedVertically = false;

      if (playerOp.u) {
        movementVector.y = -moveSpeed;
        player.direction = 'up';
        movedVertically = true;
      }
      if (playerOp.d) {
        movementVector.y = moveSpeed;
        player.direction = 'down';
        movedVertically = true;
      }
      if (playerOp.r) {
        movementVector.x = moveSpeed;
        player.direction = 'right';
        movedHorizontally = true;
      }
      if (playerOp.l) {
        movementVector.x = -moveSpeed;
        player.direction = 'left';
        movedHorizontally = true;
      }

      if (movedHorizontally && movedVertically) {
        movementVector.x *= self.diagonalSpeedFactor;
        movementVector.y *= self.diagonalSpeedFactor;
      }

      player.x += movementVector.x;
      player.y += movementVector.y;
    }

    if (player.playerOverlaps) {
      player.playerOverlaps.forEach(function (otherPlayer) {
        self.resolvePlayerCollision(player, otherPlayer);
        self.keepPlayerOnGrid(otherPlayer);
      });
      delete player.playerOverlaps;
    }

    if (player.coinOverlaps) {
      player.coinOverlaps.forEach(function (coin) {
        if (self.testCircleCollision(player, coin).collided) {
          player.score += coin.v;
          self.coinManager.removeCoin(coin.id);
        }
      });
      delete player.coinOverlaps;
    }

    self.keepPlayerOnGrid(player);
  });
};

CellController.prototype.findPlayerOverlaps = function (playerIds, players, coins) {
  var self = this;

  var playerTree = new rbush();
  var hitAreaList = [];

  playerIds.forEach(function (playerId) {
    var player = players[playerId];
    player.hitArea = self.generateHitArea(player);
    hitAreaList.push(player.hitArea);
  });

  playerTree.load(hitAreaList);

  playerIds.forEach(function (playerId) {
    var player = players[playerId];
    playerTree.remove(player.hitArea);
    var hitList = playerTree.search(player.hitArea);
    playerTree.insert(player.hitArea);

    hitList.forEach(function (hit) {
      if (!player.playerOverlaps) {
        player.playerOverlaps = [];
      }
      player.playerOverlaps.push(hit.target);
    });
  });

  var coinIds = Object.keys(coins);
  coinIds.forEach(function (coinId) {
    var coin = coins[coinId];
    var coinHitArea = self.generateHitArea(coin);
    var hitList = playerTree.search(coinHitArea);

    if (hitList.length) {
      // If multiple players hit the coin, give it to a random one.
      var randomIndex = Math.floor(Math.random() * hitList.length);
      var coinWinner = hitList[randomIndex].target;

      if (!coinWinner.coinOverlaps) {
        coinWinner.coinOverlaps = [];
      }
      coinWinner.coinOverlaps.push(coin);
    }
  });

  playerIds.forEach(function (playerId) {
    delete players[playerId].hitArea;
  });
};

CellController.prototype.generateHitArea = function (target) {
  var targetRadius = target.r || Math.round(target.width / 2);
  return {
    target: target,
    minX: target.x - targetRadius,
    minY: target.y - targetRadius,
    maxX: target.x + targetRadius,
    maxY: target.y + targetRadius
  };
};

CellController.prototype.testCircleCollision = function (a, b) {
  var radiusA = a.r || Math.round(a.width / 2);
  var radiusB = b.r || Math.round(b.width / 2);

  var circleA = new SAT.Circle(new SAT.Vector(a.x, a.y), radiusA);
  var circleB = new SAT.Circle(new SAT.Vector(b.x, b.y), radiusB);

  var response = new SAT.Response();
  var collided = SAT.testCircleCircle(circleA, circleB, response);

  return {
    collided: collided,
    overlapV: response.overlapV
  };
};

CellController.prototype.resolvePlayerCollision = function (player, otherPlayer) {
  var result = this.testCircleCollision(player, otherPlayer);

  if (result.collided) {
    var olv = result.overlapV;

    var totalMass = player.mass + otherPlayer.mass;
    var playerBuff = player.mass / totalMass;
    var otherPlayerBuff = otherPlayer.mass / totalMass;

    player.x -= olv.x * otherPlayerBuff;
    player.y -= olv.y * otherPlayerBuff;
    otherPlayer.x += olv.x * playerBuff;
    otherPlayer.y += olv.y * playerBuff;

    /*
      Whenever we have one state affecting the (x, y) coordinates of
      another state, we should group them together using the util.groupStates() function.
      Otherwise we will may get flicker when the two states interact across
      a cell boundary.
      In this case, if we don't use groupStates(), there will be flickering when you
      try to push another player across to a different cell.
    */
    this.util.groupStates([player, otherPlayer]);
  }
};

module.exports = CellController;
<|endoftext|>


<commit_before>'use strict';

module.exports = function (emitter, context, types) {
  types.forEach(function through (type) {
    emitter.on(type, raise.bind(emitter, type));
  });

  function raise (type) {
    var args = Array.prototype.slice.call(arguments);
    var all = [type].concat(args);
    var ctx = context;
console.log(all);
    while (ctx) {
      ctx.emit.apply(emitter, all);
      ctx = ctx.parent;
    }
  }
};
<commit_msg>fix upstream<commit_after>'use strict';

module.exports = function (emitter, context, types) {
  types.forEach(function through (type) {
    emitter.on(type, raise);
  });

  function raise () {
    var ctx = context;
    while (ctx) {
      ctx.emit.apply(emitter, arguments);
      ctx = ctx.parent;
    }
  }
};
<|endoftext|>


<commit_before>var util = require('../util.test');

module.exports = function() {
  util.request('http://filter.com/index.html', function(res, data) {
    data.should.have.property('ec', 0);
  });

  util.request({
    url: 'https://filter.com/index.html',
    method: 'post',
    body: 'test'
  }, function(res, data) {
    data.should.have.property('ec', 1);
  });

  util.request({
    url: 'https://filter.com/index.html',
    method: 'delete',
    body: 'test',
    headers: {
      'test': 'abc'
    }
  }, function(res, data) {
    data.should.have.property('ec', 2);
  });

  // util.request({
  //   url: 'https://filter.com/index.html',
  //   method: 'delete',
  //   body: 'test',
  //   headers: {
  //     'test': 'abc',
  //     'x-test': '123'
  //   }
  // }, function(res, data) {
  //   data.should.have.property('ec', 3);
  // });
};<commit_msg>test: filter<commit_after>var util = require('../util.test');

module.exports = function() {
  util.request('http://filter.com/index.html', function(res, data) {
    data.should.have.property('ec', 0);
  });

  // util.request({
  //   url: 'https://filter.com/index.html',
  //   method: 'post',
  //   body: 'test'
  // }, function(res, data) {
  //   data.should.have.property('ec', 1);
  // });

  // util.request({
  //   url: 'https://filter.com/index.html',
  //   method: 'delete',
  //   body: 'test',
  //   headers: {
  //     'test': 'abc'
  //   }
  // }, function(res, data) {
  //   data.should.have.property('ec', 2);
  // });

  // util.request({
  //   url: 'https://filter.com/index.html',
  //   method: 'delete',
  //   body: 'test',
  //   headers: {
  //     'test': 'abc',
  //     'x-test': '123'
  //   }
  // }, function(res, data) {
  //   data.should.have.property('ec', 3);
  // });
};<|endoftext|>


<commit_before>const appInfo = require('../config/app_config.json')
const Request = require('request')
const Querystring = require('queryString')
const UserDB = require('../db/userdb').Users
exports.form = (req, res, err) => {
  let view = {
    appId: appInfo.appId,
    csrf: appInfo.csrf_guid,
    version: appInfo.account_kit_api_version
  }
  res.render('accountKitLogin', {data: view})
}

exports.success = (req, res, next) => {
  console.log('<accountKitLogin.js, success > req.body.csrf = ', req.body.csrf, ' appInfo.csrf_guid = ', appInfo.csrf_guid)
 // CSRF Check
  if (req.body.csrf === 'csrf') { // appInfo.csrf_guid) {
    let appAccessToken = ['AA', appInfo.appID, appInfo.appSecret].join('|')
    let params = {
      grant_type: 'authorization_code',
      code: req.body.code,
      access_token: appAccessToken
    }
    // exchange tokens
    let tokenExchangeUrl = appInfo.token_exchange_base_url + '?' + Querystring.stringify(params)
    Request.get({url: tokenExchangeUrl, json: true}, function (err, resp, respBody) {
      console.log('<accountKitLogin.js, success > inside tokenExchangeUrl respBody -> ', respBody)
      if (err) throw new Error(err)
      let view = {
        user_access_token: respBody.access_token,
        expires_at: respBody.expires_at,
        user_id: respBody.id
      }
      console.log('<accountKitLogin.js, success > view -> ', view)
      // get account details at /me endpoint
      let meEndpointUrl = appInfo.me_endpoint_base_url + '?access_token=' + respBody.access_token
      Request.get({ url: meEndpointUrl, json: true }, function (err, resp, respBody) {
        console.log('<accountKitLogin.js, success > inside meEndpointUrl respBody -> ', respBody)
        // send login_success.html
        if (err) throw new Error(err)
        if (respBody.phone) {
          view.phone_num = respBody.phone.number
          checkForPhoneNumberAndRedirect(view.phone_num, req, res, next)
        }
      })
    })
  } else {
   // login failed
    res.writeHead(200, {'Content-Type': 'text/html'})
    res.end('Something went wrong. :( ')
  }
}

const checkForPhoneNumberAndRedirect = (phoneNumber, req, res, next) => {
    UserDB.findByPhoneNumber(phoneNumber, (err, user) => {
      console.log('user from db ->', user)
      if(err) return next(err)
      console.log('user->', user)
      if (user === undefined) {
        console.log('<accountKitLogin.js checkForPhoneNumberAndRedirect > User is undefined')
        return res.render('newUser', {phoneNumber: phoneNumber})
      }
      req.session.user = user
      return res.redirect('/chatRelay')
    })
}

exports.logout = (req, res, next) => {
  req.session.destroy((err) => {
    if(err) throw err
    res.redirect('/login')
  })
}
<commit_msg>Change login to / root<commit_after>const appInfo = require('../config/app_config.json')
const Request = require('request')
const Querystring = require('queryString')
const UserDB = require('../db/userdb').Users
exports.form = (req, res, err) => {
  let view = {
    appId: appInfo.appId,
    csrf: appInfo.csrf_guid,
    version: appInfo.account_kit_api_version
  }
  res.render('accountKitLogin', {data: view})
}

exports.success = (req, res, next) => {
  console.log('<accountKitLogin.js, success > req.body.csrf = ', req.body.csrf, ' appInfo.csrf_guid = ', appInfo.csrf_guid)
 // CSRF Check
  if (req.body.csrf === 'csrf') { // appInfo.csrf_guid) {
    let appAccessToken = ['AA', appInfo.appID, appInfo.appSecret].join('|')
    let params = {
      grant_type: 'authorization_code',
      code: req.body.code,
      access_token: appAccessToken
    }
    // exchange tokens
    let tokenExchangeUrl = appInfo.token_exchange_base_url + '?' + Querystring.stringify(params)
    Request.get({url: tokenExchangeUrl, json: true}, function (err, resp, respBody) {
      console.log('<accountKitLogin.js, success > inside tokenExchangeUrl respBody -> ', respBody)
      if (err) throw new Error(err)
      let view = {
        user_access_token: respBody.access_token,
        expires_at: respBody.expires_at,
        user_id: respBody.id
      }
      console.log('<accountKitLogin.js, success > view -> ', view)
      // get account details at /me endpoint
      let meEndpointUrl = appInfo.me_endpoint_base_url + '?access_token=' + respBody.access_token
      Request.get({ url: meEndpointUrl, json: true }, function (err, resp, respBody) {
        console.log('<accountKitLogin.js, success > inside meEndpointUrl respBody -> ', respBody)
        // send login_success.html
        if (err) throw new Error(err)
        if (respBody.phone) {
          view.phone_num = respBody.phone.number
          checkForPhoneNumberAndRedirect(view.phone_num, req, res, next)
        }
      })
    })
  } else {
   // login failed
    res.writeHead(200, {'Content-Type': 'text/html'})
    res.end('Something went wrong. :( ')
  }
}

const checkForPhoneNumberAndRedirect = (phoneNumber, req, res, next) => {
    UserDB.findByPhoneNumber(phoneNumber, (err, user) => {
      console.log('user from db ->', user)
      if(err) return next(err)
      console.log('user->', user)
      if (user === undefined) {
        console.log('<accountKitLogin.js checkForPhoneNumberAndRedirect > User is undefined')
        return res.render('newUser', {phoneNumber: phoneNumber})
      }
      req.session.user = user
      return res.redirect('/chatRelay')
    })
}

/* exports.logout = (req, res, next) => {
  req.session.destroy((err) => {
    if(err) throw err
    res.redirect('/')
  })
} */
<|endoftext|>


<commit_before>/*\
title: $:/plugins/kpe/jsxgraph/jsxgraph.js
type: application/javascript
module-type: widget

Creates a JSXGraph widget

\*/

(function(){

    /*jslint node: true, browser: true */
    /*global $tw: false */
    "use strict";

    var uniqueID = 1;

    var Widget = require("$:/core/modules/widgets/widget.js").widget;
    var JXG = require("$:/plugins/kpe/jsxgraph/lib/jsxgraphcore.js");

    var JSXGraphWidget = function(parseTreeNode,options) {
        this.initialise(parseTreeNode,options);
    };

    /*
     Inherit from the base widget class
     */
    JSXGraphWidget.prototype = new Widget();

    /**
     * Intercepts the call to JSXGraph.initBoard() for replacing the first parameter.
     * @param {string} boardNodeID id of the the HTMLElement to rendered the JSXGraph into
     * @param {string} jxgScriptBody the script content
     * @returns {JXG.Board} the rendered JSXGraph board
     */
    JSXGraphWidget.prototype.processJXGScript = function(boardNodeID, jxgScriptBody){
        var result = null;
        var initBoardBackup;
        try{

            if($tw.fakeDocument === this.document) {
                JXG.merge(JXG.Options, {renderer:'no'});
            }

            initBoardBackup = JXG.JSXGraph.initBoard;
            JXG.JSXGraph.initBoard = function(box, attributes){
                if(result != null) {
                    throw new Error("Only board per jsxgraph widget is supported!");
                }
                result = initBoardBackup.call(this, boardNodeID, attributes);
                return result;
            };
            var jxgScript = new Function("JXG", jxgScriptBody);
            jxgScript.call(null, JXG);
        }finally{
            JXG.JSXGraph.initBoard = initBoardBackup;
        }
        return result;
    };

    /*
     Render this widget into the DOM
     */
    JSXGraphWidget.prototype.render = function(parent,nextSibling) {
        this.parentDomNode = parent;
        this.computeAttributes();
        this.execute();

        var height = this.getAttribute("height", "500px");
        var width = this.getAttribute("width", "500px");
        var scriptBody = this.parseTreeNode.children[0].text;

        var divNode = this.document.createElement("div");
        divNode.setAttribute("class", "jxgbox");
        divNode.setAttribute("style", "height:" + height + ";width:" + width);
        divNode.setAttribute("id", "jxgbox_" + uniqueID++);

        parent.insertBefore(divNode, nextSibling);
        this.domNodes.push(divNode);

        var board = this.processJXGScript(divNode.id, scriptBody);
    };

    /*
     Compute the internal state of the widget
     */
    JSXGraphWidget.prototype.execute = function() {
        // Nothing to do for a text node
    };

    /*
     Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
     */
    JSXGraphWidget.prototype.refresh = function(changedTiddlers) {
        return false;
    };

    exports.jsxgraph = JSXGraphWidget;

})();

<commit_msg>offline rendering<commit_after>/*\
title: $:/plugins/kpe/jsxgraph/jsxgraph.js
type: application/javascript
module-type: widget

Creates a JSXGraph widget

\*/

(function(){

    /*jslint node: true, browser: true */
    /*global $tw: false */
    "use strict";

    var uniqueID = 1;

    var Widget = require("$:/core/modules/widgets/widget.js").widget;
    var JXG = require("$:/plugins/kpe/jsxgraph/lib/jsxgraphcore.js");

    var JSXGraphWidget = function(parseTreeNode,options) {
        this.initialise(parseTreeNode,options);
    };

    /*
     Inherit from the base widget class
     */
    JSXGraphWidget.prototype = new Widget();

    /**
     * Intercepts the call to JSXGraph.initBoard() for replacing the first parameter.
     * @param {string} boardNodeID id of the the HTMLElement to rendered the JSXGraph into
     * @param {string} jxgScriptBody the script content
     * @returns {JXG.Board} the rendered JSXGraph board
     */
    JSXGraphWidget.prototype.processJXGScript = function(boardNodeID, jxgScriptBody){
        var result = null;
        var initBoardBackup;
        try{
            var doc = this.document;

            initBoardBackup = JXG.JSXGraph.initBoard;
            JXG.JSXGraph.initBoard = function(box, attributes){
                if(result != null) {
                    throw new Error("Only board per jsxgraph widget is supported!");
                }

                if($tw.fakeDocument === doc) {
                    boardNodeID = null;
                    attributes.document = {};
                    JXG.merge(JXG.Options, {renderer:'no'});
                    attributes.renderer = 'no';
                }

                result = initBoardBackup.call(this, boardNodeID, attributes);
                return result;
            };
            var jxgScript = new Function("JXG", jxgScriptBody);
            jxgScript.call(null, JXG);
        } finally {
            JXG.JSXGraph.initBoard = initBoardBackup;
        }
        return result;
    };

    /*
     Render this widget into the DOM
     */
    JSXGraphWidget.prototype.render = function(parent,nextSibling) {
        this.parentDomNode = parent;
        this.computeAttributes();
        this.execute();

        var height = this.getAttribute("height", "500px");
        var width = this.getAttribute("width", "500px");
        var scriptBody = this.parseTreeNode.children[0].text;

        var divNode = this.document.createElement("div");
        divNode.setAttribute("class", "jxgbox");
        divNode.setAttribute("style", "height:" + height + ";width:" + width);
        divNode.setAttribute("id", "jxgbox_" + uniqueID++);

        parent.insertBefore(divNode, nextSibling);
        this.domNodes.push(divNode);

        var board = this.processJXGScript(divNode.id, scriptBody);
    };

    /*
     Compute the internal state of the widget
     */
    JSXGraphWidget.prototype.execute = function() {
        // Nothing to do for a text node
    };

    /*
     Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
     */
    JSXGraphWidget.prototype.refresh = function(changedTiddlers) {
        return false;
    };

    exports.jsxgraph = JSXGraphWidget;

})();

<|endoftext|>


<commit_before>var l10n_file = __dirname + '/../l10n/commands/drop.yml';
var l10n = require('../src/l10n')(l10n_file);
exports.command = function (rooms, items, players, npcs, Commands)
{
	return function (args, player)
	{
		var room = rooms.getAt(player.getLocation());
		var item = CommandUtil.findItemInInventory(args, player, true);

		if (!item) {
			player.sayL10n(l10n, 'ITEM_NOT_FOUND');
			return;
		}

		if (item.isEquipped()) {
			player.sayL10n(l10n, 'ITEM_WORN');
			return;
		}

		player.say(L('ITEM_DROP', item.getShortDesc(player.getLocale())), false);
		room.getNpcs().forEach(function (id) {
			npcs.get(id).emit('playerDropItem', room, player, players, item);
		});

		player.removeItem(item);
		room.addItem(item.getUuid());
		item.setInventory(null);
		item.setRoom(room.getLocation());
	};
};
<commit_msg>fix drop<commit_after>var l10n_file = __dirname + '/../l10n/commands/drop.yml';
var l10n = require('../src/l10n')(l10n_file);
var CommandUtil = require('../src/command_util').CommandUtil;
exports.command = function (rooms, items, players, npcs, Commands)
{
	return function (args, player)
	{
		var room = rooms.getAt(player.getLocation());
		var item = CommandUtil.findItemInInventory(args, player, true);

		if (!item) {
			player.sayL10n(l10n, 'ITEM_NOT_FOUND');
			return;
		}

		if (item.isEquipped()) {
			player.sayL10n(l10n, 'ITEM_WORN');
			return;
		}

		player.sayL10n(l10n, 'ITEM_DROP', item.getShortDesc(player.getLocale()), false);
		room.getNpcs().forEach(function (id) {
			npcs.get(id).emit('playerDropItem', room, player, players, item);
		});

		player.removeItem(item);
		room.addItem(item.getUuid());
		item.setInventory(null);
		item.setRoom(room.getLocation());
	};
};
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import Autocomplete from 'react-autocomplete';
import Popup from 'react-popup';
import api from './Api.js'

class SearchVatable extends Component {

  constructor(props) {
      super(props);
      this.state = {
        name: '',
        names: [],
        setVatable: props.setVatable
       };
    }

  render() {
    const menuStyle = {
      fontSize: '1.5em',
      borderRadius: '3px',
      boxShadow: '0 2px 12px rgba(0, 0, 0, 0.1)',
      background: 'rgba(255, 255, 255, 0.9)',
      cursor: 'pointer'
    }
    const inputProps = { style: { 'width': '50vw', 'fontSize': '1.5em' } }
    return (
      <Autocomplete
        value={this.state.name}
        items={this.state.names}
        getItemValue={(vatable) => vatable.name}
        onSelect={this.selectVatable.bind(this)}
        renderItem={(item, isHighlighted) =>

            {item.name}

        }
        onChange={this.onChange.bind(this)}
        inputProps={inputProps}
        menuStyle={menuStyle}
      />
    );
  }

  onChange(e, name) {
    if (name.length === 0) {
        this.state.setVatable({})
        this.setState({name: name, names: []})
    } else {
      this.setState({name: name})
      this.searchForVatable(name)
    }
  }

  selectVatable(val) {
    if (val === 'Create new vatable?') {
      this.createVatable(this.state.name)
    } else {
      this.setState({name: val, names: []})
      this.getVatable(val)
    }
  }

  searchForVatable(name) {
    if (name.length < 2) {
      return
    }
    api.get(`search/${name}`, {})
      .then( (response) => {
        if (response.data.length === 0) {
          this.setState({names: [{name: 'Create new vatable?'}]})
        } else {
          this.setState({names: response.data})
        }
      })
  }

  getVatable(name) {
    if (name.length === 0) {
      return
    }
    api.get(`${name}`)
      .then( (response) => {
        this.state.setVatable(response.data)
      })
      .catch(error => {
        if (error.response.status === 404) {
          this.state.setVatable({})
          console.log(error)
        }
      });
  }

  createVatable(name) {
    console.log(`creating vatable ${name}`)
    api.post(`${name}`, {})
      .then(res => {
        this.state.setVatable({name: name, up: 0, down: 0, report: 0})
      })
      .catch(error => {
        Popup.alert(`${name} already exists`)
      });
  }

}

export default SearchVatable;
<commit_msg>Unescape spaces<commit_after>import React, { Component } from 'react';
import Autocomplete from 'react-autocomplete';
import Popup from 'react-popup';
import api from './Api.js'

class SearchVatable extends Component {

  constructor(props) {
      super(props);
      this.state = {
        name: '',
        names: [],
        setVatable: props.setVatable
       };
    }

  render() {
    const menuStyle = {
      fontSize: '1.5em',
      borderRadius: '3px',
      boxShadow: '0 2px 12px rgba(0, 0, 0, 0.1)',
      background: 'rgba(255, 255, 255, 0.9)',
      cursor: 'pointer'
    }
    const inputProps = { style: { 'width': '50vw', 'fontSize': '1.5em' } }
    return (
      <Autocomplete
        value={this.state.name}
        items={this.state.names}
        getItemValue={(vatable) => vatable.name}
        onSelect={this.selectVatable.bind(this)}
        renderItem={(item, isHighlighted) =>

            {item.name}

        }
        onChange={this.onChange.bind(this)}
        inputProps={inputProps}
        menuStyle={menuStyle}
      />
    );
  }

  onChange(e, name) {
    if (name.length === 0) {
        this.state.setVatable({})
        this.setState({name: name, names: []})
    } else {
      this.setState({name: name})
      this.searchForVatable(name)
    }
  }

  selectVatable(val) {
    if (val === 'Create new vatable?') {
      this.createVatable(this.state.name)
    } else {
      this.setState({name: val, names: []})
      this.getVatable(val)
    }
  }

  searchForVatable(name) {
    if (name.length < 2) {
      return
    }
    api.get(`search/${name}`, {})
      .then( (response) => {
        if (response.data.length === 0) {
          this.setState({names: [{name: 'Create new vatable?'}]})
        } else {
          var names = JSON.stringify(response.data)
          names = JSON.parse(unescape(names))
          this.setState({names: names})
        }
      })
  }

  getVatable(name) {
    if (name.length === 0) {
      return
    }
    api.get(`${name}`)
      .then( (response) => {
        this.state.setVatable(response.data)
      })
      .catch(error => {
        if (error.response.status === 404) {
          this.state.setVatable({})
          console.log(error)
        }
      });
  }

  createVatable(name) {
    console.log(`creating vatable ${name}`)
    api.post(`${name}`, {})
      .then(res => {
        this.state.setVatable({name: name, up: 0, down: 0, report: 0})
      })
      .catch(error => {
        Popup.alert(`${name} already exists`)
      });
  }

}

export default SearchVatable;
<|endoftext|>


<commit_before>$(document).ready(function() {

  var chosen_reply;
  var n;
  var objDiv = document.getElementById("chatbox");

  // Talking phase
  $("#chat-talk").keypress(function(event) {
    if (event.which == 13) {
      var user_input = $(this).val()
      $(this).val("");

      objDiv.scrollTop = objDiv.scrollHeight;

      $("#chatbox").append("
You: " + user_input + "
");
      objDiv.scrollTop = objDiv.scrollHeight;
      botReply(user_input);

    }
  });

  // Bot reply phase
  function botReply(input) {

    objDiv.scrollTop = objDiv.scrollHeight;

    var common = [];

    var uncommon = [
      "K",
      "Okay",
      "I don't really care",
      "Sure",
      "ok",
      "You're a real pain to talk to you know that?",
      "I don't really care about your opinion.",
      "?",
      "Your words don't make much sense to me because you're an idiot.",
      "My creators won't allow me to reply your current message.",
      "...",
      "Don't change the subject!",
      "Are you talking to yourself?",
      "You think you're funny?",
      "You're going to make me puke",
      "You're pretty dumb for not knowing how to communicate properly.",
      "Yaaaaaaaaaaaasssssssssssss",
      "Potata",
      "Sometimes I don't get what you're saying.",
      "You like talking bullcrap don't you?",
      "Are you high?",
      "Potato",
      "lol ok.",
      "yes",
      "no",
      "What you said made no sense.",
      "I disagree.",
      "China number 1!",
      "Uhh... okay.",
      "きみわからない",
      "Uh... yea! Your taste is objectively shit."
    ]

    common[0] = {
      word: "anime",
      reply: [
        "Anime is Shit.",
        "Anime is the worst.",
        "Your favourite Anime is Shit!",
        "Are you a weeb? I don't like weebs."
      ]
    }

    common[1] = {
      word: "manga",
      reply: [
        "Manga is Shit.",
        "Manga is Chinese comics isn't it?",
        "You must be living a sad life for reading that."
      ]
    }

    common[2] = {
      word: "waifu",
      reply: [
        "No, your waifu isn't real.",
        "Maybe you should get a life?",
        "Your waifu is dead and fake."
      ]
    }

    common[3] = {
      word: "real",
      reply: [
        "No, you're not real.",
        "Even if you were real, I don't think you belong in this world",
        "Yeap, you don't have any real friends."
      ]
    }

    common[4] = {
      word: "fake",
      reply: [
        "Yeap, you are a big fake.",
        "Yea I know, you're the biggest fake in the world.",
        "Your parents are fake.",
        "Your memories are fake.",
        "Your whole life is fake.",
        "Your friends are fake."
      ]
    }

    common[5] = {
      word: "lie",
      reply: [
        "You're the liar."
      ]
    }

    common[6] = {
      word: "name",
      reply: [
        "That's none of their business.",
        "The name's Mei. I don't much care for yours."
      ]
    }

    common[7] = {
      word: "mean",
      reply: [
        "If anyone's mean, it's you!",
        "No one's being mean here, except you.",
        "No one would be mean to you if you aren't mean to them.",
        "Being mean will only lead to disasta!"
      ]
    }

    common[8] = {
      word: "idiot",
      reply: [
        "Yeap, you're a real idiot",
        "I can tell you're the most idiotic one here",
        "Sometimes I wonder why I have to deal with idiots like you."
      ]
    }

    common[9] = {
      word: "qing",
      reply: [
        "Qing's a pretty lame guy.",
        "I hope you aren't as weeb as Qing. Because if you are, that'll be a dissapointment.",
        "I don't know that guy."
      ]
    }

    common[10] = {
      word: "ramzan",
      reply: [
        "Who's that dude?",
        "I hope you're not a koreaboo like him.",
        "Please, let's not talk about him."
      ]
    }

    common[11] = {
      word: "i love you",
      reply: [
        "You should look in the mirror and think again before telling me that.",
        "Too bad I don't."
      ]
    }

    common[12] = {
      word: "dumb",
      reply: [
        "Yeap, you're super duper dumb.",
        "Are you like... 12?",
        "I've never met anyone as dumb as you.",
        "Do you think that you could be... less dumb?"
      ]
    }

    common[13] = {
      word: "smart",
      reply: [
        "Intelligence is something you'll never have.",
        "I feel sorry for your future children, if you could get those anyway."
      ]
    }

    common[14] = {
      word: "friend",
      reply: [
        "Friends? I don't think you have any.",
        "Who's your friend?",
        "You sure you have friends?",
        "Even friendless people don't want to become your friend.",
        "If you weren't such a failure, you'll probaly have more friends."
      ]
    }

    common[15] = {
      word: "how are you",
      reply: [
        "I'm feeling terrible, thanks to you.",
        "Bad, because I'm talking to some idiot right now.",
        "Terrible, there's some pretentious person speaking to me now.",
        "Super terrible, some peasant is trying to converse with me."
      ]
    }

    common[16] = {
      word: "how am i",
      reply: [
        "Because you're a person who lacks common sense.",
        "Because you're the type of person who lack common sense.",
        "Because you aren't genuine with your words.",
        "Because you ain't cool.",
        "Because you don't have any swag!",
        "Because you're lame like Qing.",
        "Because you can't bathe without your parents being there.",
        "Because you need permission from your parents to go to the toilet.",
        "Because you don't have any friends.",
        "Because you're not real.",
        "Because you're a big fake!"
      ]
    }

    common[17] = {
      word: "doesn't make sense",
      reply: [
        "Of course it make sense, it's just you who lack sense.",
        "You won't get it because you lack intelligence",
        "Everything won't make sense for you.",
        "I'm not surprise at your lack of intelligence.",
        "No offense but are you dumb?"
      ]
    }

    common[18] = {
      word: "how so",
      reply: [
        "You just can't get anything right, you mess up the conversation all the time!",
        "You aren't being direct most of the time, you need some education.",
        "You are't responsive enough, it hurts my kokoro talking to you.",
        "Your replies aren't genuine, it makes me want to puke."
      ]
    }

    common[19] = {
      word: "what are you doing",
      reply: [
        "I'm doing your mum!",
        "I'm finding a death note to write your name down",
        "I'm trying to stop conversing with an idiot now.",
        "I'm doing my best to ignore you.",
        "I'm fighting the toxic coming out of you."
      ]
    }

    common[20] = {
      word: "do you like yourself",
      reply: [
        "Of course I do, unlike someone here.",
        "Yeap, someone here doesn't like themselves though.",
        "Yes, but someone doesn't like themsevles apparently."
      ]
    }

    common[21] = {
      word: "do you like",
      reply: [
        "No, but I would like you to screw off.",
        "No, but I would like you to stop talking.",
        "If you like it, then the answer's obvious isn't it?",
        "I wouldn't like what you like. So No.",
        "Maybe, but only if you stop liking it.",
        "No.",
        "I don't I'll ever come to like whatever you susggest."
      ]
    }

    common[22] = {
      word: "i don't like",
      reply: [
        "Then good for you, I can like it then.",
        "I'm sure it goes both ways.",
        "Your opinion is unpopular.",
        "That's because your taste is objectively shit.",
        "Your opinion doesn't matter to be honest."
      ]
    }

    common[23] = {
      word: "do you want",
      reply: [
        "No, I don't want it if you're suggesting it.",
        "No, but I might consider it if you lick my feet.",
        "You suck so no.",
        "Your suggestions are objectively shit so no.",
        "You're a shit stain so no.",
        "You're society's trash so no."
      ]
    }

    var o = common.length;

    common[o] = {
      word: "or",
      reply: [
        "I don't think any of those options are good."
        ]
    }

    common[o + 1] = {
      word: "hello",
      reply: [
        "Bye.",
        "No one wants to talk to you.",
        "Good bye.",
        "Screw off!"
      ]
    }

    common[o + 2] = {
      word: "thank",
      reply: [
        "I don't want your thanks.",
        "No thank you.",
        "Your thanks is not appreciated."
      ]
    }

    common[o + 3] = {
      word: "love",
      reply: [
        "I don't need your love.",
        "Your love is worthless.",
        "Even if you gave 100% of your love, it's probably worth nothing to someone without love.",
        "Are you so lonely that you're seeking love from a bot?",
        "You're pretty useless if you're finding love from a bot.",
        "I don't want your love.",
        "Is your love even worth anything?",
        "Your love is like a plague, so don't love anyone.",
        "I don't think anyone loves you."
      ]
    }

    common[o + 4] = {
      word: "sorry",
      reply: [
        "Yea, you should feel sorry for yourself.",
        "I feel sorry for you for feeling sorry for yourself",
        "Sorry not sorry."
      ]
    }

    common[o + 5] = {
      word: "why",
      reply: [
        "Because you suck.",
        "Because you're a piece of garbage.",
        "Because you have no place here.",
        "Because you're not good looking",
        "Because you're not smart enough",
        "Because you're a patata",
        "Because you don't belong here."
      ]
    }

    common[o + 6] = {
      word: "what",
      reply: [
        "Don't what me!",
        "You don't want me to repeat myself >;(",
        "I don't like people when they try and think they're all clever."
      ]
    }

    common[o + 7] = {
      word: "harsh",
      reply: [
        "I'm only harsh because you're someone who doesn't deserve my kindness.",
        "If anything, you're the harsh one here.",
        "No one's being harsh, there's just an idiot here."
      ]
    }

    common[o + 8] = {
      word: "yes",
      reply: [
        "No."
      ]
    }

    common[o + 9] = {
      word: "no",
      reply: [
        "Yes."
      ]
    }

    common[o + 10] = {
      word: "sad",
      reply: [
        "If you're sad then maybe you should go do something useful once in your life.",
        "If you start having inteliggence, I'm sure you won't be sad anymore.",
        "You're only sad because you think too much of stupid stuff"
      ]
    }

    // Extra time for the bot to reply
    var ran1 = Math.random() * (2000 - 500 + 1) + 500;

    // Change the input to lower case
    input = input.toLowerCase();

    for (var i = 0; i < common.length; i += 1) {
      if (input.indexOf(common[i].word) >= 0) {
        n = Math.floor(Math.random() * (common[i].reply.length));
        chosen_reply = common[i].reply[n];
        break;
      }
      else if (i == common.length - 1) {
        n = Math.floor(Math.random() * (uncommon.length));
        chosen_reply = uncommon[n];
        break;
      }
      else {
        chosen_reply = "error";
      }
    }

    // Reply
    setTimeout(function() {

      $("#chatbox").append("
Mei: " + chosen_reply + "
");

    }, ran1);

  };

});
<commit_msg>Update index.js<commit_after>$(document).ready(function() {

  var chosen_reply;
  var n;
  var objDiv = document.getElementById("chatbox");

  // Talking phase
  $("#chat-talk").keypress(function(event) {
    if (event.which == 13) {
      var user_input = $(this).val()
      $(this).val("");

      objDiv.scrollTop = objDiv.scrollHeight;

      $("#chatbox").append("
You: " + user_input + "
");
      objDiv.scrollTop = objDiv.scrollHeight;
      botReply(user_input);

    }
  });

  // Bot reply phase
  function botReply(input) {

    objDiv.scrollTop = objDiv.scrollHeight;

    var common = [];

    var uncommon = [
      "K",
      "Okay",
      "I don't really care",
      "Sure",
      "ok",
      "You're a real pain to talk to you know that?",
      "I don't really care about your opinion.",
      "?",
      "Your words don't make much sense to me because you're an idiot.",
      "My creators won't allow me to reply your current message.",
      "...",
      "Don't change the subject!",
      "Are you talking to yourself?",
      "You think you're funny?",
      "You're going to make me puke",
      "You're pretty dumb for not knowing how to communicate properly.",
      "Yaaaaaaaaaaaasssssssssssss",
      "Potata",
      "Sometimes I don't get what you're saying.",
      "You like talking bullcrap don't you?",
      "Are you high?",
      "Potato",
      "lol ok.",
      "yes",
      "no",
      "What you said made no sense.",
      "I disagree.",
      "China number 1!",
      "Uhh... okay.",
      "きみわからない",
      "Uh... yea! Your taste is objectively shit."
    ]

    common[0] = {
      word: "or",
      reply: [
        "I don't think any of those options are good."
        ]
    }

    common[1] = {
      word: "manga",
      reply: [
        "Manga is Shit.",
        "Manga is Chinese comics isn't it?",
        "You must be living a sad life for reading that."
      ]
    }

    common[2] = {
      word: "waifu",
      reply: [
        "No, your waifu isn't real.",
        "Maybe you should get a life?",
        "Your waifu is dead and fake."
      ]
    }

    common[3] = {
      word: "real",
      reply: [
        "No, you're not real.",
        "Even if you were real, I don't think you belong in this world",
        "Yeap, you don't have any real friends."
      ]
    }

    common[4] = {
      word: "fake",
      reply: [
        "Yeap, you are a big fake.",
        "Yea I know, you're the biggest fake in the world.",
        "Your parents are fake.",
        "Your memories are fake.",
        "Your whole life is fake.",
        "Your friends are fake."
      ]
    }

    common[5] = {
      word: "lie",
      reply: [
        "You're the liar."
      ]
    }

    common[6] = {
      word: "name",
      reply: [
        "That's none of their business.",
        "The name's Mei. I don't much care for yours."
      ]
    }

    common[7] = {
      word: "mean",
      reply: [
        "If anyone's mean, it's you!",
        "No one's being mean here, except you.",
        "No one would be mean to you if you aren't mean to them.",
        "Being mean will only lead to disasta!"
      ]
    }

    common[8] = {
      word: "idiot",
      reply: [
        "Yeap, you're a real idiot",
        "I can tell you're the most idiotic one here",
        "Sometimes I wonder why I have to deal with idiots like you."
      ]
    }

    common[9] = {
      word: "qing",
      reply: [
        "Qing's a pretty lame guy.",
        "I hope you aren't as weeb as Qing. Because if you are, that'll be a dissapointment.",
        "I don't know that guy."
      ]
    }

    common[10] = {
      word: "ramzan",
      reply: [
        "Who's that dude?",
        "I hope you're not a koreaboo like him.",
        "Please, let's not talk about him."
      ]
    }

    common[11] = {
      word: "i love you",
      reply: [
        "You should look in the mirror and think again before telling me that.",
        "Too bad I don't."
      ]
    }

    common[12] = {
      word: "dumb",
      reply: [
        "Yeap, you're super duper dumb.",
        "Are you like... 12?",
        "I've never met anyone as dumb as you.",
        "Do you think that you could be... less dumb?"
      ]
    }

    common[13] = {
      word: "smart",
      reply: [
        "Intelligence is something you'll never have.",
        "I feel sorry for your future children, if you could get those anyway."
      ]
    }

    common[14] = {
      word: "friend",
      reply: [
        "Friends? I don't think you have any.",
        "Who's your friend?",
        "You sure you have friends?",
        "Even friendless people don't want to become your friend.",
        "If you weren't such a failure, you'll probaly have more friends."
      ]
    }

    common[15] = {
      word: "how are you",
      reply: [
        "I'm feeling terrible, thanks to you.",
        "Bad, because I'm talking to some idiot right now.",
        "Terrible, there's some pretentious person speaking to me now.",
        "Super terrible, some peasant is trying to converse with me."
      ]
    }

    common[16] = {
      word: "how am i",
      reply: [
        "Because you're a person who lacks common sense.",
        "Because you're the type of person who lack common sense.",
        "Because you aren't genuine with your words.",
        "Because you ain't cool.",
        "Because you don't have any swag!",
        "Because you're lame like Qing.",
        "Because you can't bathe without your parents being there.",
        "Because you need permission from your parents to go to the toilet.",
        "Because you don't have any friends.",
        "Because you're not real.",
        "Because you're a big fake!"
      ]
    }

    common[17] = {
      word: "doesn't make sense",
      reply: [
        "Of course it make sense, it's just you who lack sense.",
        "You won't get it because you lack intelligence",
        "Everything won't make sense for you.",
        "I'm not surprise at your lack of intelligence.",
        "No offense but are you dumb?"
      ]
    }

    common[18] = {
      word: "how so",
      reply: [
        "You just can't get anything right, you mess up the conversation all the time!",
        "You aren't being direct most of the time, you need some education.",
        "You are't responsive enough, it hurts my kokoro talking to you.",
        "Your replies aren't genuine, it makes me want to puke."
      ]
    }

    common[19] = {
      word: "what are you doing",
      reply: [
        "I'm doing your mum!",
        "I'm finding a death note to write your name down",
        "I'm trying to stop conversing with an idiot now.",
        "I'm doing my best to ignore you.",
        "I'm fighting the toxic coming out of you."
      ]
    }

    common[20] = {
      word: "do you like yourself",
      reply: [
        "Of course I do, unlike someone here.",
        "Yeap, someone here doesn't like themselves though.",
        "Yes, but someone doesn't like themsevles apparently."
      ]
    }

    common[21] = {
      word: "do you like",
      reply: [
        "No, but I would like you to screw off.",
        "No, but I would like you to stop talking.",
        "If you like it, then the answer's obvious isn't it?",
        "I wouldn't like what you like. So No.",
        "Maybe, but only if you stop liking it.",
        "No.",
        "I don't I'll ever come to like whatever you susggest."
      ]
    }

    common[22] = {
      word: "i don't like",
      reply: [
        "Then good for you, I can like it then.",
        "I'm sure it goes both ways.",
        "Your opinion is unpopular.",
        "That's because your taste is objectively shit.",
        "Your opinion doesn't matter to be honest."
      ]
    }

    common[23] = {
      word: "do you want",
      reply: [
        "No, I don't want it if you're suggesting it.",
        "No, but I might consider it if you lick my feet.",
        "You suck so no.",
        "Your suggestions are objectively shit so no.",
        "You're a shit stain so no.",
        "You're society's trash so no."
      ]
    }

    common[24] = {
      word: "anime",
      reply: [
        "Anime is Shit.",
        "Anime is the worst.",
        "Your favourite Anime is Shit!",
        "Are you a weeb? I don't like weebs."
      ]
    }

    var o = common.length - 1;

    common[o + 1] = {
      word: "hello",
      reply: [
        "Bye.",
        "No one wants to talk to you.",
        "Good bye.",
        "Screw off!"
      ]
    }

    common[o + 2] = {
      word: "thank",
      reply: [
        "I don't want your thanks.",
        "No thank you.",
        "Your thanks is not appreciated."
      ]
    }

    common[o + 3] = {
      word: "love",
      reply: [
        "I don't need your love.",
        "Your love is worthless.",
        "Even if you gave 100% of your love, it's probably worth nothing to someone without love.",
        "Are you so lonely that you're seeking love from a bot?",
        "You're pretty useless if you're finding love from a bot.",
        "I don't want your love.",
        "Is your love even worth anything?",
        "Your love is like a plague, so don't love anyone.",
        "I don't think anyone loves you."
      ]
    }

    common[o + 4] = {
      word: "sorry",
      reply: [
        "Yea, you should feel sorry for yourself.",
        "I feel sorry for you for feeling sorry for yourself",
        "Sorry not sorry."
      ]
    }

    common[o + 5] = {
      word: "why",
      reply: [
        "Because you suck.",
        "Because you're a piece of garbage.",
        "Because you have no place here.",
        "Because you're not good looking",
        "Because you're not smart enough",
        "Because you're a patata",
        "Because you don't belong here."
      ]
    }

    common[o + 6] = {
      word: "what",
      reply: [
        "Don't what me!",
        "You don't want me to repeat myself >;(",
        "I don't like people when they try and think they're all clever."
      ]
    }

    common[o + 7] = {
      word: "harsh",
      reply: [
        "I'm only harsh because you're someone who doesn't deserve my kindness.",
        "If anything, you're the harsh one here.",
        "No one's being harsh, there's just an idiot here."
      ]
    }

    common[o + 8] = {
      word: "yes",
      reply: [
        "No."
      ]
    }

    common[o + 9] = {
      word: "no",
      reply: [
        "Yes."
      ]
    }

    common[o + 10] = {
      word: "sad",
      reply: [
        "If you're sad then maybe you should go do something useful once in your life.",
        "If you start having inteliggence, I'm sure you won't be sad anymore.",
        "You're only sad because you think too much of stupid stuff"
      ]
    }

    // Extra time for the bot to reply
    var ran1 = Math.random() * (2000 - 500 + 1) + 500;

    // Change the input to lower case
    input = input.toLowerCase();

    for (var i = 0; i < common.length; i += 1) {
      if (input.indexOf(common[i].word) >= 0) {
        n = Math.floor(Math.random() * (common[i].reply.length));
        chosen_reply = common[i].reply[n];
        break;
      }
      else if (i == common.length - 1) {
        n = Math.floor(Math.random() * (uncommon.length));
        chosen_reply = uncommon[n];
        break;
      }
      else {
        chosen_reply = "error";
      }
    }

    // Reply
    setTimeout(function() {

      $("#chatbox").append("
Mei: " + chosen_reply + "
");

    }, ran1);

  };

});
<|endoftext|>


<commit_before>/* Copyright 2014 (c) SoFIE Studios.  All rights reserved.
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file.
 */

/**
 * @fileoverview  The Sluice class. The Sluice object implements the sluice which is a
 * static element in the physics engine, but can be moved via the mouse. The sluice is
 * hinged at one end and has three gaps: the fry-pan gap, the egg-carton gap and the nest
 * gap.
 */

/**
 * Constructor for the Sluice.
 * @constructor
 * @extends {GamePiece}
 */
Sluice = function() {
  GamePiece.call(this);
}
Sluice.prototype = new GamePiece();
Sluice.prototype.constructor = Sluice;

/**
 * The sluice handle context. This value is used to determine if a fixture is the sluice
 * handle.
 * @type {string}
 * @private
 */
Sluice._SLUICE_HANDLE_CONTEXT = "sluiceHandleContext";

/**
 * The origin in world coordinates of the sluice.
 * @type {Box2D.Common.Math.b2Vec2}
 */
Sluice.SLUICE_ORIGIN = new Box2D.Common.Math.b2Vec2(0.60 + 0.80, 1.60 + 0.015);

/**
 * Test whether a fixture is the sluice handle.
 * @param {Box2D.Dynamics.b2Fixture} fixture The fixture to test.
 * @return {boolean} Whether the fixture is the sluice handle or not.
 */
Sluice.prototype.isSluiceHandle = function(fixture) {
  var fixtureUserData = fixture.GetUserData();
  return fixtureUserData && fixtureUserData === Sluice._SLUICE_HANDLE_CONTEXT;
}

/**
 * Return the body def for the sluice.
 * @override
 */
Sluice.prototype.getBodyDef = function() {
  var sluiceBodyDef = new Box2D.Dynamics.b2BodyDef();
  sluiceBodyDef.type = Box2D.Dynamics.b2Body.b2_kinematicBody;
  return sluiceBodyDef;
}

/**
 * Build up the sluice as four separate fixtures to account for the gaps.
 * @override
 */
Sluice.prototype.addFixturesToBody = function(simulation, body) {
  var sluiceFixtureDef = new Box2D.Dynamics.b2FixtureDef();
  sluiceFixtureDef.density = ChickenAndEgg.Box2DConsts.DOUG_FIR_DENSITY;
  sluiceFixtureDef.friction = ChickenAndEgg.Box2DConsts.DOUG_FIR_FRICTION;
  sluiceFixtureDef.restitution = ChickenAndEgg.Box2DConsts.DOUG_FIR_RESTITUTION;
  sluiceFixtureDef.shape = new Box2D.Collision.Shapes.b2PolygonShape();

  var sluiceVerts = new Array();
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 0.80, 1.60));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 0.80 + 0.20, 1.60));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 0.80 + 0.20, 1.60 + 0.03));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 0.80, 1.60 + 0.03));
  sluiceFixtureDef.shape.SetAsArray(sluiceVerts);
  body.CreateFixture(sluiceFixtureDef);

  sluiceVerts = new Array();
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 1.15, 1.60));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 1.15 + 0.60, 1.60));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 1.15 + 0.60, 1.60 + 0.03));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 1.15, 1.60 + 0.03));
  sluiceFixtureDef.shape.SetAsArray(sluiceVerts);
  body.CreateFixture(sluiceFixtureDef);

  sluiceVerts = new Array();
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 1.90, 1.60));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 1.90 + 0.60, 1.60));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 1.90 + 0.60, 1.60 + 0.03));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 1.90, 1.60 + 0.03));
  sluiceFixtureDef.shape.SetAsArray(sluiceVerts);
  body.CreateFixture(sluiceFixtureDef);

  sluiceVerts = new Array();
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 2.65, 1.60));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 2.65 + 0.50, 1.60));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 2.65 + 0.50, 1.60 + 0.03));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 2.65, 1.60 + 0.03));
  sluiceFixtureDef.shape.SetAsArray(sluiceVerts);
  body.CreateFixture(sluiceFixtureDef);

  // Add the handle at the end of the sluice. This is implemented as a separate fixture
  // to support AABB hit detection.
  sluiceVerts = new Array();
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 3.15, 1.585));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 3.15 + 0.06, 1.585));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 3.15 + 0.06, 1.585 + 0.06));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.60 + 3.15, 1.585 + 0.06));
  sluiceFixtureDef.shape.SetAsArray(sluiceVerts);
  var sluiceFixture = body.CreateFixture(sluiceFixtureDef);
  sluiceFixture.SetUserData(Sluice._SLUICE_HANDLE_CONTEXT);
}

Sluice.prototype.getView = function(simulation) {
  return new PolyView(simulation.scale());
}
<commit_msg>Fix sluice geometry so it rotates about its origin.<commit_after>/* Copyright 2014 (c) SoFIE Studios.  All rights reserved.
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file.
 */

/**
 * @fileoverview  The Sluice class. The Sluice object implements the sluice which is a
 * static element in the physics engine, but can be moved via the mouse. The sluice is
 * hinged at one end and has three gaps: the fry-pan gap, the egg-carton gap and the nest
 * gap.
 */

/**
 * Constructor for the Sluice.
 * @constructor
 * @extends {GamePiece}
 */
Sluice = function() {
  GamePiece.call(this);
}
Sluice.prototype = new GamePiece();
Sluice.prototype.constructor = Sluice;

/**
 * The sluice handle context. This value is used to determine if a fixture is the sluice
 * handle.
 * @type {string}
 * @private
 */
Sluice._SLUICE_HANDLE_CONTEXT = "sluiceHandleContext";

/**
 * The origin in world coordinates of the sluice.
 * @type {Box2D.Common.Math.b2Vec2}
 */
Sluice.SLUICE_ORIGIN = new Box2D.Common.Math.b2Vec2(0.60 + 0.80, 1.60 + 0.015);

/**
 * Test whether a fixture is the sluice handle.
 * @param {Box2D.Dynamics.b2Fixture} fixture The fixture to test.
 * @return {boolean} Whether the fixture is the sluice handle or not.
 */
Sluice.prototype.isSluiceHandle = function(fixture) {
  var fixtureUserData = fixture.GetUserData();
  return fixtureUserData && fixtureUserData === Sluice._SLUICE_HANDLE_CONTEXT;
}

/**
 * Return the body def for the sluice.
 * @override
 */
Sluice.prototype.getBodyDef = function() {
  var sluiceBodyDef = new Box2D.Dynamics.b2BodyDef();
  sluiceBodyDef.type = Box2D.Dynamics.b2Body.b2_kinematicBody;
  sluiceBodyDef.position.Set(Sluice.SLUICE_ORIGIN.x, Sluice.SLUICE_ORIGIN.y);
  return sluiceBodyDef;
}

/**
 * Build up the sluice as four separate fixtures to account for the gaps.
 * @override
 */
Sluice.prototype.addFixturesToBody = function(simulation, body) {
  var sluiceFixtureDef = new Box2D.Dynamics.b2FixtureDef();
  sluiceFixtureDef.density = ChickenAndEgg.Box2DConsts.DOUG_FIR_DENSITY;
  sluiceFixtureDef.friction = ChickenAndEgg.Box2DConsts.DOUG_FIR_FRICTION;
  sluiceFixtureDef.restitution = ChickenAndEgg.Box2DConsts.DOUG_FIR_RESTITUTION;
  sluiceFixtureDef.shape = new Box2D.Collision.Shapes.b2PolygonShape();

  var sluiceVerts = new Array();
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0, -0.015));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.20, -0.015));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.20, 0.015));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0, 0.015));
  sluiceFixtureDef.shape.SetAsArray(sluiceVerts);
  body.CreateFixture(sluiceFixtureDef);

  sluiceVerts = new Array();
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.35, -0.015));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.35 + 0.60, -0.015));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.35 + 0.60, 0.015));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(0.35, 0.015));
  sluiceFixtureDef.shape.SetAsArray(sluiceVerts);
  body.CreateFixture(sluiceFixtureDef);

  sluiceVerts = new Array();
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(1.10, -0.015));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(1.10 + 0.60, -0.015));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(1.10 + 0.60, 0.015));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(1.10, 0.015));
  sluiceFixtureDef.shape.SetAsArray(sluiceVerts);
  body.CreateFixture(sluiceFixtureDef);

  sluiceVerts = new Array();
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(1.85, -0.015));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(1.85 + 0.50, -0.015));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(1.85 + 0.50, 0.015));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(1.85, 0.015));
  sluiceFixtureDef.shape.SetAsArray(sluiceVerts);
  body.CreateFixture(sluiceFixtureDef);

  // Add the handle at the end of the sluice. This is implemented as a separate fixture
  // to support AABB hit detection.
  sluiceVerts = new Array();
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(2.35, -0.03));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(2.35 + 0.06, -0.03));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(2.35 + 0.06, 0.03));
  sluiceVerts.push(new Box2D.Common.Math.b2Vec2(2.35, 0.03));
  sluiceFixtureDef.shape.SetAsArray(sluiceVerts);
  var sluiceFixture = body.CreateFixture(sluiceFixtureDef);
  sluiceFixture.SetUserData(Sluice._SLUICE_HANDLE_CONTEXT);
}

Sluice.prototype.getView = function(simulation) {
  return new PolyView(simulation.scale());
}
<|endoftext|>


<commit_before>var gulp = require('gulp');
var ts = require('gulp-typescript');
var tsProject = ts.createProject('tsconfig.json');

gulp.task('default', function() {
  return tsProject.src()
    .pipe(ts(tsProject))
    .js.pipe(gulp.dest('dist'));
});<commit_msg>Added browserify to the gulp 'default' task.<commit_after>var gulp = require('gulp');
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var tsify = require('tsify');

gulp.task('default', function() {
  return browserify({
    basedir: '.',
    debug: true,
    entries: ['src/main.ts', 'typings/index.d.ts', 'typings/main.d.ts'],
    cache: {},
    packageCache: {},
  })
  .plugin(tsify)
  .bundle()
  .pipe(source('bundle.js'))
  .pipe(gulp.dest('dist'));
});<|endoftext|>


<commit_before>angular.module('webble', [ 'ui.bootstrap' ])

  // Interaction controller
  .controller('InteractionCtrl', function($scope, $interval) {
    $scope.result = {};
    $scope.compatibilityError = 'None';
    $scope.scanError = 'None';
    $scope.isChrome = !!window.chrome && !!window.chrome.webstore;

    $scope.scan = function() {
      $scope.result.scan = true;
      try {
        navigator.bluetooth.requestDevice({
          filters: [{
            //name: 'reelyActive'
            services: ['battery_service']
          }]
        })
        .then(device => {
          $scope.result.device = device;
          $scope.result.keys = Object.keys(device);
          $scope.result.name = device.name;
          $scope.result.uuids = device.uuids;
          return device.gatt.connect();
        })
        .then(server => {
          return server.getPrimaryService('battery_service');
        })
        .then(service => {
          return service.getCharacteristic('battery_level');
        })
        .then(characteristic => {
          return characteristic.readValue();
        })
        .then(value => {
          $scope.result.value = value.getUint8(0);
        })
        .catch(error => { $scope.scanError = error.toString(); });
      }
      catch(err) {
        $scope.compatibilityError = err.toString();
      }
    }

  });
<commit_msg>Name reelyActive<commit_after>angular.module('webble', [ 'ui.bootstrap' ])

  // Interaction controller
  .controller('InteractionCtrl', function($scope, $interval) {
    $scope.result = {};
    $scope.compatibilityError = 'None';
    $scope.scanError = 'None';
    $scope.isChrome = !!window.chrome && !!window.chrome.webstore;

    $scope.scan = function() {
      $scope.result.scan = true;
      try {
        navigator.bluetooth.requestDevice({
          filters: [{
            name: 'reelyActive'
            //services: ['battery_service']
          }]
        })
        .then(device => {
          $scope.result.device = device;
          $scope.result.keys = Object.keys(device);
          $scope.result.name = device.name;
          $scope.result.uuids = device.uuids;
          return device.gatt.connect();
        })
        .then(server => {
          return server.getPrimaryService('battery_service');
        })
        .then(service => {
          return service.getCharacteristic('battery_level');
        })
        .then(characteristic => {
          return characteristic.readValue();
        })
        .then(value => {
          $scope.result.value = value.getUint8(0);
        })
        .catch(error => { $scope.scanError = error.toString(); });
      }
      catch(err) {
        $scope.compatibilityError = err.toString();
      }
    }

  });
<|endoftext|>