<commit_before>var DiceRoll = (function() {

  var dice_src = [];
  dice_src[4] = [];
  for (var i = 1; i <= 4; i++) {
    dice_src[4][i] = '/dice/4_dice/4_dice[' + i + '].png';
  }

  dice_src[6] = [];
  for (var i = 1; i <= 6; i++) {
    dice_src[6][i] = '/dice/6_dice/6_dice[' + i + '].png';
  }

  dice_src[8] = [];
  for (var i = 1; i <= 8; i++) {
    dice_src[8][i] = '/dice/8_dice/8_dice[' + i + '].png';
  }

  dice_src[10] = [];
  dice_src[10][0] = '/dice/10_dice/10_dice[10].png';
  for (var i = 1; i <= 10; i++) {
    dice_src[10][i] = '/dice/10_dice/10_dice[' + i + '].png';
  }

  dice_src[20] = [];
  for (var i = 1; i <= 20; i++) {
    dice_src[20][i] = '/dice/20_dice/20_dice[' + i + '].png';
  }

  dice_src[100] = [];
  dice_src[100][0] = '/dice/100_dice/100_dice[10].png';
  for (var i = 1; i <= 10; i++) {
    dice_src[100][i] = '/dice/100_dice/100_dice[' + i + '].png';
  }

  var drawing_dice = [4, 6, 8, 10, 20, 100];

  var que = [];
  var timer;
  var state = 'stop'; //'rolling' or 'stop'

  var window_width, window_height;

  var DiceRoll = function(option) {
    this.request = option.request;
    this.total   = option.total;
    this.dices   = option.dices;
    this.result  = option.result;
    this.name    = option.name;
    this.dice    = [];
    this.count   = 0;

    que.push(this);

    if (que.length == 1) {
      this.begin();
    }
    else if (que.length == 2 && state == 'stop') {
      erase();
      que.shift();
      this.begin();
    }
  };

  DiceRoll.prototype.begin = function() {
    var is_drawable = true;
    for (var i = 0; i < this.dices.length; i++) {
      is_drawable &= drawing_dice.indexOf(this.dices[i].d) != -1;
    }
    if (!is_drawable) {
      this.showResultToLog();
      return;
    }

    window_width  = $(window).width();
    window_height = $(window).height();

    var p = 0;
    for (var j = 0; j < this.dices.length; j++) {
      var data = this.dices[j];
      var num = data.numbers.length;
      for (var i = 0; i < num; i++) {
        var obj = genDiceObj(p, data.numbers[i], data.d);
        p++;
        document.body.appendChild(obj);
        this.dice.push(obj);
      }
    }

    timer = setInterval(this.updateDice, 50, this);
    state = 'rolling';
  };

  DiceRoll.prototype.updateDice = function(instans) {
    if (state == 'rolling') {
      instans.count++;
      for (var i = 0; i < instans.dice.length; i++) {
        var obj = instans.dice[i];

        if (obj.d == 100) {
          obj.img.src  = dice_src[100][instans.count % 10 + 1];
          obj.img2.src = dice_src[10][instans.count % 10 + 1];
        }
        else {
          obj.img.src = dice_src[obj.d][instans.count % obj.d + 1];
        }

        obj.vy = obj.vy - 9.8;
        obj.y -= obj.vy;
        obj.x -= obj.vx;

        if (obj.x < 0) {
          obj.x = 0
          obj.vx = -obj.vx * 0.9;
        }

        if (obj.vy < 0 && obj.base_of_dounding < obj.y) {
          obj.vy = -obj.vy * 0.94;
          obj.vx *= 0.86;
          obj.y = obj.base_of_dounding - (obj.y - obj.base_of_dounding);
          obj.base_of_dounding = obj.base_of_dounding * 0.75;
        }

        if (obj.base_of_dounding < obj.epsilon_y || state == 'stop') {
          state = 'stop';
          if (obj.d == 100) {
            obj.img.src  = dice_src[100][Math.floor(obj.number / 10)];
            obj.img2.src = dice_src[10][obj.number % 10];
          }
          else{
            obj.img.src = dice_src[obj.d][obj.number];
          }
          obj.onclick = erase;
          continue;
        }
        else {
          obj.style.top  = obj.y + "px";
          obj.style.left = obj.x + "px";
        }
      }
    }
    else if (state == 'stop') {
      clearInterval(timer);
      if (que.length > 1) {
        window.setTimeout(function() {
          erase();
          que.shift();
          que[0].begin();
        }, 500);
      }
      instans.showResultToLog();
      showAmount(instans.total, instans.result, (instans.dice[0].y - 50) + 'px', instans.dice[0].style.left);
    }
  };

  DiceRoll.prototype.showResultToLog = function() {
    var amount = this.total + ' ー>';
    this.dices.forEach(function(dice) {
      amount += ' D' + dice.d + '[' + dice.numbers + ']';
    });
    if (this.result) {
      amount += 'ー> ' + this.result;
    }
    addMessage(this.name + ' ( ' + this.request + ' ) ー> ' + amount);
  };

  var erase = function() {
    var objs = document.getElementsByClassName("dice");
    for (i = objs.length - 1; i >= 0; i--) {
      document.body.removeChild(objs[i]);
    }

    var total = document.getElementById('amount');
    if (total) {
      document.body.removeChild(total);
    }
  };

  var genDiceObj = function(id, number, d) {
    var obj = document.createElement("div");
    obj.number = number;
    obj.d = d;
    obj.className = "dice";

    obj.x = window_width - 100 - 150 * (id % 5);
    obj.y = window_height - 100 * Math.floor(id / 5 + 1);

    obj.epsilon_y = 110 * 1.8;
    obj.style.left = obj.x + "px";
    obj.style.top = obj.y + "px";

    obj.vy = 100 * (window_height / 800);
    if (obj.vy < 100) {
      obj.vy = 100;
    }
    obj.vx = 25 * (window_width / 1000);
    obj.base_of_dounding = obj.epsilon_y + (window_height - obj.epsilon_y) * 0.2;

    obj.img = document.createElement("img");
    obj.img.src = dice_src[obj.d][1];
    obj.appendChild(obj.img);

    if (d == 100) {
      obj.img2 = document.createElement("img");
      obj.img2.src = dice_src[10][1];
      obj.appendChild(obj.img2);
    }
    return obj;
  };

  var showAmount = function (number, result, top, left) {
    var obj = document.createElement("div");
    obj.id = 'amount'
    obj.textContent = result || number;
    obj.style.top = top;
    obj.style.left = left;
    document.body.appendChild(obj);
  };

  return DiceRoll;
})();
<commit_msg>サイコロ画像を事前にロードする<commit_after>var DiceRoll = (function() {

  var dice_src = [];
  dice_src[4] = [];
  for (var i = 1; i <= 4; i++) {
    dice_src[4][i] = '/dice/4_dice/4_dice[' + i + '].png';
    var tmp = new Image();
    tmp.src = dice_src[4][i];
  }

  dice_src[6] = [];
  for (var i = 1; i <= 6; i++) {
    dice_src[6][i] = '/dice/6_dice/6_dice[' + i + '].png';
    var tmp = new Image();
    tmp.src = dice_src[6][i];
  }

  dice_src[8] = [];
  for (var i = 1; i <= 8; i++) {
    dice_src[8][i] = '/dice/8_dice/8_dice[' + i + '].png';
    var tmp = new Image();
    tmp.src = dice_src[8][i];
  }

  dice_src[10] = [];
  dice_src[10][0] = '/dice/10_dice/10_dice[10].png';
  for (var i = 1; i <= 10; i++) {
    dice_src[10][i] = '/dice/10_dice/10_dice[' + i + '].png';
    var tmp = new Image();
    tmp.src = dice_src[10][i];
  }

  dice_src[20] = [];
  for (var i = 1; i <= 20; i++) {
    dice_src[20][i] = '/dice/20_dice/20_dice[' + i + '].png';
    var tmp = new Image();
    tmp.src = dice_src[20][i];
  }

  dice_src[100] = [];
  dice_src[100][0] = '/dice/100_dice/100_dice[10].png';
  for (var i = 1; i <= 10; i++) {
    dice_src[100][i] = '/dice/100_dice/100_dice[' + i + '].png';
    var tmp = new Image();
    tmp.src = dice_src[100][i];
  }

  var drawing_dice = [4, 6, 8, 10, 20, 100];

  var que = [];
  var timer;
  var state = 'stop'; //'rolling' or 'stop'

  var window_width, window_height;

  var DiceRoll = function(option) {
    this.request = option.request;
    this.total   = option.total;
    this.dices   = option.dices;
    this.result  = option.result;
    this.name    = option.name;
    this.dice    = [];
    this.count   = 0;

    que.push(this);

    if (que.length == 1) {
      this.begin();
    }
    else if (que.length == 2 && state == 'stop') {
      erase();
      que.shift();
      this.begin();
    }
  };

  DiceRoll.prototype.begin = function() {
    var is_drawable = true;
    for (var i = 0; i < this.dices.length; i++) {
      is_drawable &= drawing_dice.indexOf(this.dices[i].d) != -1;
    }
    if (!is_drawable) {
      this.showResultToLog();
      return;
    }

    window_width  = $(window).width();
    window_height = $(window).height();

    var p = 0;
    for (var j = 0; j < this.dices.length; j++) {
      var data = this.dices[j];
      var num = data.numbers.length;
      for (var i = 0; i < num; i++) {
        var obj = genDiceObj(p, data.numbers[i], data.d);
        p++;
        document.body.appendChild(obj);
        this.dice.push(obj);
      }
    }

    timer = setInterval(this.updateDice, 50, this);
    state = 'rolling';
  };

  DiceRoll.prototype.updateDice = function(instans) {
    if (state == 'rolling') {
      instans.count++;
      for (var i = 0; i < instans.dice.length; i++) {
        var obj = instans.dice[i];

        if (obj.d == 100) {
          obj.img.src  = dice_src[100][instans.count % 10 + 1];
          obj.img2.src = dice_src[10][instans.count % 10 + 1];
        }
        else {
          obj.img.src = dice_src[obj.d][instans.count % obj.d + 1];
        }

        obj.vy = obj.vy - 9.8;
        obj.y -= obj.vy;
        obj.x -= obj.vx;

        if (obj.x < 0) {
          obj.x = 0
          obj.vx = -obj.vx * 0.9;
        }

        if (obj.vy < 0 && obj.base_of_dounding < obj.y) {
          obj.vy = -obj.vy * 0.94;
          obj.vx *= 0.86;
          obj.y = obj.base_of_dounding - (obj.y - obj.base_of_dounding);
          obj.base_of_dounding = obj.base_of_dounding * 0.75;
        }

        if (obj.base_of_dounding < obj.epsilon_y || state == 'stop') {
          state = 'stop';
          if (obj.d == 100) {
            obj.img.src  = dice_src[100][Math.floor(obj.number / 10)];
            obj.img2.src = dice_src[10][obj.number % 10];
          }
          else{
            obj.img.src = dice_src[obj.d][obj.number];
          }
          obj.onclick = erase;
          continue;
        }
        else {
          obj.style.top  = obj.y + "px";
          obj.style.left = obj.x + "px";
        }
      }
    }
    else if (state == 'stop') {
      clearInterval(timer);
      if (que.length > 1) {
        window.setTimeout(function() {
          erase();
          que.shift();
          que[0].begin();
        }, 500);
      }
      instans.showResultToLog();
      showAmount(instans.total, instans.result, (instans.dice[0].y - 50) + 'px', instans.dice[0].style.left);
    }
  };

  DiceRoll.prototype.showResultToLog = function() {
    var amount = this.total + ' ー>';
    this.dices.forEach(function(dice) {
      amount += ' D' + dice.d + '[' + dice.numbers + ']';
    });
    if (this.result) {
      amount += 'ー> ' + this.result;
    }
    addMessage(this.name + ' ( ' + this.request + ' ) ー> ' + amount);
  };

  var erase = function() {
    var objs = document.getElementsByClassName("dice");
    for (i = objs.length - 1; i >= 0; i--) {
      document.body.removeChild(objs[i]);
    }

    var total = document.getElementById('amount');
    if (total) {
      document.body.removeChild(total);
    }
  };

  var genDiceObj = function(id, number, d) {
    var obj = document.createElement("div");
    obj.number = number;
    obj.d = d;
    obj.className = "dice";

    obj.x = window_width - 100 - 150 * (id % 5);
    obj.y = window_height - 100 * Math.floor(id / 5 + 1);

    obj.epsilon_y = 110 * 1.8;
    obj.style.left = obj.x + "px";
    obj.style.top = obj.y + "px";

    obj.vy = 100 * (window_height / 800);
    if (obj.vy < 100) {
      obj.vy = 100;
    }
    obj.vx = 25 * (window_width / 1000);
    obj.base_of_dounding = obj.epsilon_y + (window_height - obj.epsilon_y) * 0.2;

    obj.img = document.createElement("img");
    obj.img.src = dice_src[obj.d][1];
    obj.appendChild(obj.img);

    if (d == 100) {
      obj.img2 = document.createElement("img");
      obj.img2.src = dice_src[10][1];
      obj.appendChild(obj.img2);
    }
    return obj;
  };

  var showAmount = function (number, result, top, left) {
    var obj = document.createElement("div");
    obj.id = 'amount'
    obj.textContent = result || number;
    obj.style.top = top;
    obj.style.left = left;
    document.body.appendChild(obj);
  };

  return DiceRoll;
})();
<|endoftext|>


<commit_before>;(function () {

  var game = new Phaser.Game(GAME_WIDTH, GAME_HEIGHT, Phaser.AUTO, 'breakout', { preload: preload, create: create, update: update });
  var GAME_WIDTH = 800;
  var GAME_HEIGHT = 600;

  var background;

  var bricks;
  var BRICK_ROWS = 4;
  var BRICK_COLS = 15;
  var BRICK_START_X = 120;
  var BRICK_START_Y = 100;
  var BRICK_SPACING_X = 36;
  var BRICK_SPACING_Y = 52;

  var paddle;
  var PADDLE_Y = 500;
  var PADDLE_WIDTH = 48;

  var ball;
  var ballOnPaddle = true;
  var BALL_WIDTH = 16;
  var BALL_HEIGHT = 16;
  var BALL_RELEASE_VELOCITY_X = -75;
  var BALL_RELEASE_VELOCITY_Y = -300;
  var BALL_VELOCITY_MULTIPLIER_X = 10;

  var score = 0;
  var lives = 3;
  var scoreText;
  var livesText;
  var infoText;
  var TEXT_Y = 550;

  var socket;
  var localPlayerName;
  var localPlayerID;
  var remotePlayers = {};

  var $leaderboard = $("#leaderboard-table-body");

  function preload() {
    console.log('preload invoked');
    game.load.atlas('breakout', '/assets/breakout.png', '/assets/breakout.json');
    game.load.image('starfield', '/assets/starfield.jpg');
  }

  function create() {
    console.log('create invoked');

    // Prevent game from pausing when browser tab loses focus
    game.stage.disableVisibilityChange = true;

    game.physics.startSystem(Phaser.Physics.ARCADE);

    background = game.add.tileSprite(0, 0, GAME_WIDTH, GAME_HEIGHT, 'starfield');

    // Check bounds collisions on all walls except bottom
    game.physics.arcade.checkCollision.down = false;

    createBricks();
    createLocalPaddle();
    createLocalBall();
    createText();

    game.input.onDown.add(releaseBall, this);

    socket = io.connect(window.location.hostname);
    attachSocketHandlers();
  }

  function createBricks() {
    console.log('createBricks invoked');
    bricks = game.add.group();
    bricks.enableBody = true;
    bricks.physicsBodyType = Phaser.Physics.ARCADE;

    var brick;
    var brickCount = 0;

    for (var row = 0; row < BRICK_ROWS; row++) {
      for (var col = 0; col < BRICK_COLS; col++) {
        brick = bricks.create(
          BRICK_START_X + (col * BRICK_SPACING_X),
          BRICK_START_Y + (row * BRICK_SPACING_Y),
          'breakout',
          'brick_' + (row + 1) + '_1.png'
        );
        brick.body.bounce.set(1);
        brick.body.immovable = true;
        brick.brickIndex = brickCount++;
      }
    }
  }

  function createLocalPaddle() {
    console.log('createLocalPaddle invoked');
    paddle = game.add.sprite(game.world.centerX, PADDLE_Y, 'breakout', 'paddle_big.png');
    paddle.anchor.setTo(0.5, 0.5);

    game.physics.enable(paddle, Phaser.Physics.ARCADE);

    paddle.body.collideWorldBounds = true;
    paddle.body.bounce.set(1);
    paddle.body.immovable = true;
  }

  function createLocalBall() {
    console.log('createLocalBall invoked');
    ball = game.add.sprite(game.world.centerX, PADDLE_Y - BALL_HEIGHT, 'breakout', 'ball_1.png');
    ball.anchor.set(0.5);
    ball.checkWorldBounds = true;

    game.physics.enable(ball, Phaser.Physics.ARCADE);

    ball.body.collideWorldBounds = true;
    ball.body.bounce.set(1);

    ball.animations.add('spin', [ 'ball_1.png', 'ball_2.png', 'ball_3.png', 'ball_4.png', 'ball_5.png' ], 50, true, false);

    ball.events.onOutOfBounds.add(ballLost, this);
  }

  function createText() {
    console.log('createText invoked');
    scoreText = game.add.text(32, TEXT_Y, 'score: 0',
      { font: '20px Arial', fill: '#ffffff', align: 'left' });
    livesText = game.add.text(GAME_WIDTH - 120, TEXT_Y, 'lives: 3',
      { font: '20px Arial', fill: '#ffffff', align: 'left' });
    infoText = game.add.text(game.world.centerX, GAME_HEIGHT * (2 / 3), 'Click to start',
      { font: '40px Arial', fill: '#ffffff', align: 'center' });
    infoText.anchor.setTo(0.5, 0.5);
  }

  function attachSocketHandlers() {
    console.log('attachSocketHandlers invoked');
    socket.on('connect', onSocketConnect);
    socket.on('disconnect', onSocketDisconnect);
    socket.on('local player', onLocalPlayer);
    socket.on('new player', onNewPlayer);
    socket.on('remove player', onRemovePlayer);
    socket.on('initial bricks', onInitialBricks);
    socket.on('brick kill to other clients', onBrickKillToOtherClients);
    socket.on('update local score', onUpdateLocalScore);
    socket.on('update remote score', onUpdateRemoteScore);
  }

  function onSocketConnect() {
    console.log('onSocketConnect invoked');
    console.log('emitting "new player" message with existingBricks = ' + bricksString(bricks));
    socket.emit('new player', { existingBricks: bricksString(bricks) });
  }

  function onSocketDisconnect() {
    console.log('onSocketDisconnect invoked');
  }

  function onLocalPlayer(data) {
    localPlayerID = data.id;
    localPlayerName = data.name;
    addPlayerToLeaderboard(data);
  }

  function onNewPlayer(data) {
    console.log('onNewPlayer invoked.');
    remotePlayers[data.id] = {
      name: data.name,
      score: data.score
    };
    addPlayerToLeaderboard(data);
    console.log(data.id + ' added to remotePlayers: ' + JSON.stringify(remotePlayers));
  }

  function addPlayerToLeaderboard(message) {
    var playerScore;
    var $tr;
    var $tdScore;
    var $tdName;

    if (message.hasOwnProperty('score')) {
      // remote player
      playerScore = message.score;
    } else {
      // local player
      playerScore = score;
    }

    $tr = $('

');
    $tr.attr('data-score', playerScore);
    $tr.attr('data-id', message.id);
    $tdScore = $('	').text(playerScore);
    $tdName = $('	').text(message.name);

    $tr.append($tdScore).append($tdName).appendTo($leaderboard);
  }

  function onRemovePlayer(data) {
    console.log('onRemovePlayer invoked');
    var newRemotePlayers = {};
    for (var id in remotePlayers) {
      if (id !== data.id) {
        newRemotePlayers[id] = remotePlayers[id];
      }
    }
    remotePlayers = newRemotePlayers;
    console.log('remotePlayers: ' + JSON.stringify(remotePlayers));
  }

  function onInitialBricks(data) {
    console.log('onInitialBricks invoked. data = ' + JSON.stringify(data));
    var i;
    for (var row = 0; row < BRICK_ROWS; row++) {
      for (var col = 0; col < BRICK_COLS; col++) {
        i = row * BRICK_COLS + col;
        if (data.initialBricks.charAt(i) === "0") {
          bricks.children[i].kill();
        }
      }
    }
  }

  function onBrickKillToOtherClients(data) {
    console.log('onBrickKillToOtherClients invoked');
    bricks.children[data.brickIndex].kill();
  }

  function onUpdateLocalScore(data) {
    console.log('onLocalRemoteScore invoked');
    score = data.score;
    scoreText.text = 'score: ' + score;
    updateLeaderboard(data);
  }

  function onUpdateRemoteScore(data) {
    console.log('onUpdateRemoteScore invoked');
    remotePlayers[data.id].score = data.score;
    updateLeaderboard(data);
  }

  function updateLeaderboard(message) {
    var $tr = $leaderboard.find("[data-id='" + message.id + "']");
    $tr.attr('data-score', message.score);

    var $tdScore = $tr.children().first();
    $tdScore.text(message.score);
  }

  function update() {
    paddle.body.x = game.input.x - 0.5 * PADDLE_WIDTH;

    if (paddle.body.x < 0) {
      paddle.body.x = 0;
    } else if (paddle.body.x > game.width - PADDLE_WIDTH) {
      paddle.body.x = game.width - PADDLE_WIDTH;
    }

    if (ballOnPaddle) {
      ball.body.x = paddle.body.x + 0.5 * PADDLE_WIDTH - 0.5 * BALL_WIDTH;
    } else {
      game.physics.arcade.collide(ball, paddle, ballHitPaddle, null, this);
      game.physics.arcade.collide(ball, bricks, ballHitBrick, null, this);
    }

    if (bricks.countLiving() === 0) {
      startNewRound();
    }
  }

  function releaseBall() {
    if (ballOnPaddle) {
      ballOnPaddle = false;
      ball.body.velocity.x = BALL_RELEASE_VELOCITY_X * ( Math.random() * 4 - 1 );
      ball.body.velocity.y = BALL_RELEASE_VELOCITY_Y;
      ball.animations.play('spin');
      infoText.visible = false;
    }
  }

  function ballLost() {
    lives--;
    livesText.text = 'lives: ' + lives;
    if (lives === 0) {
      gameOver();
    } else {
      putBallOnPaddle();
    }
  }

  function putBallOnPaddle() {
    ballOnPaddle = true;
    ball.reset(paddle.body.x + 0.5 * PADDLE_WIDTH - 0.5 * BALL_WIDTH, PADDLE_Y - BALL_HEIGHT);
    ball.animations.stop();
  }

  function startNewRound() {
    console.log('startNewRound invoked');
    bricks.callAll('revive');
    if (lives !==0 ) {
      putBallOnPaddle();
      infoText.text = 'Next Round';
    }
  }

  function gameOver() {
    ball.body.velocity.setTo(0, 0);

    infoText.text = 'Game Over!';
    infoText.visible = true;
  }

  function ballHitBrick(_ball, _brick) {
    socket.emit('brick kill from client', { brickIndex: _brick.brickIndex });
    _brick.kill();
  }

  function ballHitPaddle(_ball, _paddle) {
    var diff = 0;

    if (_ball.body.x < _paddle.body.x) {
      //  Ball is on the left-hand side of the paddle
      diff = _paddle.body.x - _ball.body.x;
      _ball.body.velocity.x = (BALL_VELOCITY_MULTIPLIER_X * diff * -1);
    } else if (_ball.body.x > _paddle.body.x) {
      //  Ball is on the right-hand side of the paddle
      diff = _ball.body.x -_paddle.body.x;
      _ball.body.velocity.x = (BALL_VELOCITY_MULTIPLIER_X * diff);
    } else {
      //  Ball is perfectly in the middle
      //  Add a little random X to stop it bouncing straight up!
      _ball.body.velocity.x = BALL_VELOCITY_MULTIPLIER_X * 0.2 + Math.random() * BALL_VELOCITY_MULTIPLIER_X * 0.8;
    }
  }

  function bricksString(bricksGroup) {
    var i;
    var length = bricksGroup.children.length;
    var result = "";
    for (i = 0; i < length; i++) {
      if (bricksGroup.children[i].alive) {
        result += "1";
      } else {
        result += "0";
      }
    }
    return result;
  }

}());
<commit_msg>Add MixItUp sorting<commit_after>;(function () {

  var game = new Phaser.Game(GAME_WIDTH, GAME_HEIGHT, Phaser.AUTO, 'breakout', { preload: preload, create: create, update: update });
  var GAME_WIDTH = 800;
  var GAME_HEIGHT = 600;

  var background;

  var bricks;
  var BRICK_ROWS = 4;
  var BRICK_COLS = 15;
  var BRICK_START_X = 120;
  var BRICK_START_Y = 100;
  var BRICK_SPACING_X = 36;
  var BRICK_SPACING_Y = 52;

  var paddle;
  var PADDLE_Y = 500;
  var PADDLE_WIDTH = 48;

  var ball;
  var ballOnPaddle = true;
  var BALL_WIDTH = 16;
  var BALL_HEIGHT = 16;
  var BALL_RELEASE_VELOCITY_X = -75;
  var BALL_RELEASE_VELOCITY_Y = -300;
  var BALL_VELOCITY_MULTIPLIER_X = 10;

  var score = 0;
  var lives = 3;
  var scoreText;
  var livesText;
  var infoText;
  var TEXT_Y = 550;

  var socket;
  var localPlayerName;
  var localPlayerID;
  var remotePlayers = {};

  var $leaderboard = $("#leaderboard-table-body");

  function preload() {
    console.log('preload invoked');
    game.load.atlas('breakout', '/assets/breakout.png', '/assets/breakout.json');
    game.load.image('starfield', '/assets/starfield.jpg');
  }

  function create() {
    console.log('create invoked');

    // Prevent game from pausing when browser tab loses focus
    game.stage.disableVisibilityChange = true;

    game.physics.startSystem(Phaser.Physics.ARCADE);

    background = game.add.tileSprite(0, 0, GAME_WIDTH, GAME_HEIGHT, 'starfield');

    // Check bounds collisions on all walls except bottom
    game.physics.arcade.checkCollision.down = false;

    createBricks();
    createLocalPaddle();
    createLocalBall();
    createText();

    game.input.onDown.add(releaseBall, this);

    initializeMixItUp();

    socket = io.connect(window.location.hostname);
    attachSocketHandlers();
  }

  function createBricks() {
    console.log('createBricks invoked');
    bricks = game.add.group();
    bricks.enableBody = true;
    bricks.physicsBodyType = Phaser.Physics.ARCADE;

    var brick;
    var brickCount = 0;

    for (var row = 0; row < BRICK_ROWS; row++) {
      for (var col = 0; col < BRICK_COLS; col++) {
        brick = bricks.create(
          BRICK_START_X + (col * BRICK_SPACING_X),
          BRICK_START_Y + (row * BRICK_SPACING_Y),
          'breakout',
          'brick_' + (row + 1) + '_1.png'
        );
        brick.body.bounce.set(1);
        brick.body.immovable = true;
        brick.brickIndex = brickCount++;
      }
    }
  }

  function createLocalPaddle() {
    console.log('createLocalPaddle invoked');
    paddle = game.add.sprite(game.world.centerX, PADDLE_Y, 'breakout', 'paddle_big.png');
    paddle.anchor.setTo(0.5, 0.5);

    game.physics.enable(paddle, Phaser.Physics.ARCADE);

    paddle.body.collideWorldBounds = true;
    paddle.body.bounce.set(1);
    paddle.body.immovable = true;
  }

  function createLocalBall() {
    console.log('createLocalBall invoked');
    ball = game.add.sprite(game.world.centerX, PADDLE_Y - BALL_HEIGHT, 'breakout', 'ball_1.png');
    ball.anchor.set(0.5);
    ball.checkWorldBounds = true;

    game.physics.enable(ball, Phaser.Physics.ARCADE);

    ball.body.collideWorldBounds = true;
    ball.body.bounce.set(1);

    ball.animations.add('spin', [ 'ball_1.png', 'ball_2.png', 'ball_3.png', 'ball_4.png', 'ball_5.png' ], 50, true, false);

    ball.events.onOutOfBounds.add(ballLost, this);
  }

  function createText() {
    console.log('createText invoked');
    scoreText = game.add.text(32, TEXT_Y, 'score: 0',
      { font: '20px Arial', fill: '#ffffff', align: 'left' });
    livesText = game.add.text(GAME_WIDTH - 120, TEXT_Y, 'lives: 3',
      { font: '20px Arial', fill: '#ffffff', align: 'left' });
    infoText = game.add.text(game.world.centerX, GAME_HEIGHT * (2 / 3), 'Click to start',
      { font: '40px Arial', fill: '#ffffff', align: 'center' });
    infoText.anchor.setTo(0.5, 0.5);
  }

  function initializeMixItUp() {
    $(function(){
      $leaderboard.mixItUp({
        selectors: {
          target: "tr"
        },
        layout: {
          display: 'block'
        }
      });
    });
  }

  function attachSocketHandlers() {
    console.log('attachSocketHandlers invoked');
    socket.on('connect', onSocketConnect);
    socket.on('disconnect', onSocketDisconnect);
    socket.on('local player', onLocalPlayer);
    socket.on('new player', onNewPlayer);
    socket.on('remove player', onRemovePlayer);
    socket.on('initial bricks', onInitialBricks);
    socket.on('brick kill to other clients', onBrickKillToOtherClients);
    socket.on('update local score', onUpdateLocalScore);
    socket.on('update remote score', onUpdateRemoteScore);
  }

  function onSocketConnect() {
    console.log('onSocketConnect invoked');
    console.log('emitting "new player" message with existingBricks = ' + bricksString(bricks));
    socket.emit('new player', { existingBricks: bricksString(bricks) });
  }

  function onSocketDisconnect() {
    console.log('onSocketDisconnect invoked');
  }

  function onLocalPlayer(data) {
    localPlayerID = data.id;
    localPlayerName = data.name;
    addPlayerToLeaderboard(data);
  }

  function onNewPlayer(data) {
    console.log('onNewPlayer invoked.');
    remotePlayers[data.id] = {
      name: data.name,
      score: data.score
    };
    addPlayerToLeaderboard(data);
    console.log(data.id + ' added to remotePlayers: ' + JSON.stringify(remotePlayers));
  }

  function addPlayerToLeaderboard(message) {
    var playerScore;
    var $tr;
    var $tdScore;
    var $tdName;

    if (message.hasOwnProperty('score')) {
      // remote player
      playerScore = message.score;
    } else {
      // local player
      playerScore = score;
    }

    $tr = $('

');
    $tr.attr('data-score', playerScore);
    $tr.attr('data-id', message.id);
    $tdScore = $('	').text(playerScore);
    $tdName = $('	').text(message.name);

    $tr.append($tdScore).append($tdName).appendTo($leaderboard);
  }

  function onRemovePlayer(data) {
    console.log('onRemovePlayer invoked');
    var newRemotePlayers = {};
    for (var id in remotePlayers) {
      if (id !== data.id) {
        newRemotePlayers[id] = remotePlayers[id];
      }
    }
    remotePlayers = newRemotePlayers;
    console.log('remotePlayers: ' + JSON.stringify(remotePlayers));
  }

  function onInitialBricks(data) {
    console.log('onInitialBricks invoked. data = ' + JSON.stringify(data));
    var i;
    for (var row = 0; row < BRICK_ROWS; row++) {
      for (var col = 0; col < BRICK_COLS; col++) {
        i = row * BRICK_COLS + col;
        if (data.initialBricks.charAt(i) === "0") {
          bricks.children[i].kill();
        }
      }
    }
  }

  function onBrickKillToOtherClients(data) {
    console.log('onBrickKillToOtherClients invoked');
    bricks.children[data.brickIndex].kill();
  }

  function onUpdateLocalScore(data) {
    console.log('onLocalRemoteScore invoked');
    score = data.score;
    scoreText.text = 'score: ' + score;
    updateLeaderboard(data);
  }

  function onUpdateRemoteScore(data) {
    console.log('onUpdateRemoteScore invoked');
    remotePlayers[data.id].score = data.score;
    updateLeaderboard(data);
  }

  function updateLeaderboard(message) {
    var $tr = $leaderboard.find("[data-id='" + message.id + "']");
    $tr.attr('data-score', message.score);

    var $tdScore = $tr.children().first();
    $tdScore.text(message.score);

    $leaderboard.mixItUp('sort', 'score:desc');
  }

  function update() {
    paddle.body.x = game.input.x - 0.5 * PADDLE_WIDTH;

    if (paddle.body.x < 0) {
      paddle.body.x = 0;
    } else if (paddle.body.x > game.width - PADDLE_WIDTH) {
      paddle.body.x = game.width - PADDLE_WIDTH;
    }

    if (ballOnPaddle) {
      ball.body.x = paddle.body.x + 0.5 * PADDLE_WIDTH - 0.5 * BALL_WIDTH;
    } else {
      game.physics.arcade.collide(ball, paddle, ballHitPaddle, null, this);
      game.physics.arcade.collide(ball, bricks, ballHitBrick, null, this);
    }

    if (bricks.countLiving() === 0) {
      startNewRound();
    }
  }

  function releaseBall() {
    if (ballOnPaddle) {
      ballOnPaddle = false;
      ball.body.velocity.x = BALL_RELEASE_VELOCITY_X * ( Math.random() * 4 - 1 );
      ball.body.velocity.y = BALL_RELEASE_VELOCITY_Y;
      ball.animations.play('spin');
      infoText.visible = false;
    }
  }

  function ballLost() {
    lives--;
    livesText.text = 'lives: ' + lives;
    if (lives === 0) {
      gameOver();
    } else {
      putBallOnPaddle();
    }
  }

  function putBallOnPaddle() {
    ballOnPaddle = true;
    ball.reset(paddle.body.x + 0.5 * PADDLE_WIDTH - 0.5 * BALL_WIDTH, PADDLE_Y - BALL_HEIGHT);
    ball.animations.stop();
  }

  function startNewRound() {
    console.log('startNewRound invoked');
    bricks.callAll('revive');
    if (lives !==0 ) {
      putBallOnPaddle();
      infoText.text = 'Next Round';
    }
  }

  function gameOver() {
    ball.body.velocity.setTo(0, 0);

    infoText.text = 'Game Over!';
    infoText.visible = true;
  }

  function ballHitBrick(_ball, _brick) {
    socket.emit('brick kill from client', { brickIndex: _brick.brickIndex });
    _brick.kill();
  }

  function ballHitPaddle(_ball, _paddle) {
    var diff = 0;

    if (_ball.body.x < _paddle.body.x) {
      //  Ball is on the left-hand side of the paddle
      diff = _paddle.body.x - _ball.body.x;
      _ball.body.velocity.x = (BALL_VELOCITY_MULTIPLIER_X * diff * -1);
    } else if (_ball.body.x > _paddle.body.x) {
      //  Ball is on the right-hand side of the paddle
      diff = _ball.body.x -_paddle.body.x;
      _ball.body.velocity.x = (BALL_VELOCITY_MULTIPLIER_X * diff);
    } else {
      //  Ball is perfectly in the middle
      //  Add a little random X to stop it bouncing straight up!
      _ball.body.velocity.x = BALL_VELOCITY_MULTIPLIER_X * 0.2 + Math.random() * BALL_VELOCITY_MULTIPLIER_X * 0.8;
    }
  }

  function bricksString(bricksGroup) {
    var i;
    var length = bricksGroup.children.length;
    var result = "";
    for (i = 0; i < length; i++) {
      if (bricksGroup.children[i].alive) {
        result += "1";
      } else {
        result += "0";
      }
    }
    return result;
  }

}());
<|endoftext|>


<commit_before>;(function () {

  var game = new Phaser.Game(GAME_WIDTH, GAME_HEIGHT, Phaser.AUTO, 'breakout', { preload: preload, create: create, update: update });
  var GAME_WIDTH = 800;
  var GAME_HEIGHT = 600;

  var background;

  var bricks;
  var BRICK_ROWS = 4;
  var BRICK_COLS = 15;
  var BRICK_START_X = 120;
  var BRICK_START_Y = 100;
  var BRICK_SPACING_X = 36;
  var BRICK_SPACING_Y = 52;

  var paddle;
  var PADDLE_Y = 500;
  var PADDLE_WIDTH = 48;

  var ball;
  var ballOnPaddle = true;
  var BALL_WIDTH = 16;
  var BALL_HEIGHT = 16;
  var BALL_RELEASE_VELOCITY_X = -75;
  var BALL_RELEASE_VELOCITY_Y = -300;
  var BALL_VELOCITY_MULTIPLIER_X = 10;

  var score = 0;
  var lives = 3;
  var scoreText;
  var livesText;
  var infoText;
  var TEXT_Y = 550;

  var socket;
  var remotePlayers = {};

  function preload() {
    console.log('preload invoked');
    game.load.atlas('breakout', '/assets/breakout.png', '/assets/breakout.json');
    game.load.image('starfield', '/assets/starfield.jpg');
  }

  function create() {
    console.log('create invoked');

    // Prevent game from pausing when browser tab loses focus
    game.stage.disableVisibilityChange = true;

    game.physics.startSystem(Phaser.Physics.ARCADE);

    background = game.add.tileSprite(0, 0, GAME_WIDTH, GAME_HEIGHT, 'starfield');

    // Check bounds collisions on all walls except bottom
    game.physics.arcade.checkCollision.down = false;

    createBricks();
    createLocalPaddle();
    createLocalBall();
    createText();

    game.input.onDown.add(releaseBall, this);

    socket = io.connect(window.location.hostname);
    attachSocketHandlers();
  }

  function createBricks() {
    console.log('createBricks invoked');
    bricks = game.add.group();
    bricks.enableBody = true;
    bricks.physicsBodyType = Phaser.Physics.ARCADE;

    var brick;
    var brickCount = 0;

    for (var row = 0; row < BRICK_ROWS; row++) {
      for (var col = 0; col < BRICK_COLS; col++) {
        brick = bricks.create(
          BRICK_START_X + (col * BRICK_SPACING_X),
          BRICK_START_Y + (row * BRICK_SPACING_Y),
          'breakout',
          'brick_' + (row + 1) + '_1.png'
        );
        brick.body.bounce.set(1);
        brick.body.immovable = true;
        brick.brickIndex = brickCount++;
      }
    }
  }

  function createLocalPaddle() {
    console.log('createLocalPaddle invoked');
    paddle = game.add.sprite(game.world.centerX, PADDLE_Y, 'breakout', 'paddle_big.png');
    paddle.anchor.setTo(0.5, 0.5);

    game.physics.enable(paddle, Phaser.Physics.ARCADE);

    paddle.body.collideWorldBounds = true;
    paddle.body.bounce.set(1);
    paddle.body.immovable = true;
  }

  function createLocalBall() {
    console.log('createLocalBall invoked');
    ball = game.add.sprite(game.world.centerX, PADDLE_Y - BALL_HEIGHT, 'breakout', 'ball_1.png');
    ball.anchor.set(0.5);
    ball.checkWorldBounds = true;

    game.physics.enable(ball, Phaser.Physics.ARCADE);

    ball.body.collideWorldBounds = true;
    ball.body.bounce.set(1);

    ball.animations.add('spin', [ 'ball_1.png', 'ball_2.png', 'ball_3.png', 'ball_4.png', 'ball_5.png' ], 50, true, false);

    ball.events.onOutOfBounds.add(ballLost, this);
  }

  function createText() {
    console.log('createText invoked');
    scoreText = game.add.text(32, TEXT_Y, 'score: 0',
      { font: '20px Arial', fill: '#ffffff', align: 'left' });
    livesText = game.add.text(GAME_WIDTH - 120, TEXT_Y, 'lives: 3',
      { font: '20px Arial', fill: '#ffffff', align: 'left' });
    infoText = game.add.text(game.world.centerX, GAME_HEIGHT * (2 / 3), 'Click to start',
      { font: '40px Arial', fill: '#ffffff', align: 'center' });
    infoText.anchor.setTo(0.5, 0.5);
  }

  function attachSocketHandlers() {
    console.log('attachSocketHandlers invoked');
    socket.on('connect', onSocketConnect);
    socket.on('disconnect', onSocketDisconnect);
    socket.on('new player', onNewPlayer);
    socket.on('remove player', onRemovePlayer);
    socket.on('initial bricks', onInitialBricks);
    socket.on('brick kill to other clients', onBrickKillToOtherClients);
  }

  function onSocketConnect() {
    console.log('onSocketConnect invoked');
    console.log('emitting "new player" message with existingBricks = ' + bricksString(bricks));
    socket.emit('new player', { existingBricks: bricksString(bricks) });
  }

  function onSocketDisconnect() {
    console.log('onSocketDisconnect invoked');
  }

  function onNewPlayer(data) {
    console.log('onNewPlayer invoked. data = ' + JSON.stringify(data));
    remotePlayers[data.id] = { score: data.score };
    console.log(data.id + ' added to remotePlayers: ' + JSON.stringify(remotePlayers));
  }

  function onRemovePlayer(data) {
    if (delete remotePlayers[data.id]) {
      console.log(data.id + ' removed from remotePlayers: ' + JSON.stringify(remotePlayers));
    } else {
      console.log(data.id + ' not found in remotePlayers');
    }
  }

  function onInitialBricks(data) {
    console.log('onInitialBricks invoked. data = ' + JSON.stringify(data));
    var i;
    for (var row = 0; row < BRICK_ROWS; row++) {
      for (var col = 0; col < BRICK_COLS; col++) {
        i = row * BRICK_COLS + col;
        if (data.initialBricks.charAt(i) === "0") {
          bricks.children[i].kill();
        }
      }
    }
  }

  function onBrickKillToOtherClients(data) {
    console.log('onBrickKillToOtherClients invoked');
    bricks.children[data.brickIndex].kill();
  }

  function update() {
    paddle.body.x = game.input.x - 0.5 * PADDLE_WIDTH;

    if (paddle.body.x < 0) {
      paddle.body.x = 0;
    } else if (paddle.body.x > game.width - PADDLE_WIDTH) {
      paddle.body.x = game.width - PADDLE_WIDTH;
    }

    if (ballOnPaddle) {
      ball.body.x = paddle.body.x + 0.5 * PADDLE_WIDTH - 0.5 * BALL_WIDTH;
    } else {
      game.physics.arcade.collide(ball, paddle, ballHitPaddle, null, this);
      game.physics.arcade.collide(ball, bricks, ballHitBrick, null, this);
    }

    if (bricks.countLiving() === 0) {
      startNewRound();
    }
  }

  function releaseBall() {
    if (ballOnPaddle) {
      ballOnPaddle = false;
      ball.body.velocity.x = BALL_RELEASE_VELOCITY_X;
      ball.body.velocity.y = BALL_RELEASE_VELOCITY_Y;
      ball.animations.play('spin');
      infoText.visible = false;
    }
  }

  function ballLost() {
    lives--;
    livesText.text = 'lives: ' + lives;
    if (lives === 0) {
      gameOver();
    } else {
      putBallOnPaddle();
    }
  }

  function putBallOnPaddle() {
    ballOnPaddle = true;
    ball.reset(paddle.body.x + 0.5 * PADDLE_WIDTH - 0.5 * BALL_WIDTH, PADDLE_Y - BALL_HEIGHT);
    ball.animations.stop();
  }

  function startNewRound() {
    console.log('startNewRound invoked');
    bricks.callAll('revive');
    if (lives !==0 ) {
      putBallOnPaddle();
      score += 1000;
      scoreText.text = 'score: ' + score;
      infoText.text = 'Next Round';
    }
  }

  function gameOver() {
    ball.body.velocity.setTo(0, 0);

    infoText.text = 'Game Over!';
    infoText.visible = true;
  }

  function ballHitBrick(_ball, _brick) {
    socket.emit('brick kill from client', { brickIndex: _brick.brickIndex });

    _brick.kill();

    score += 10;
    scoreText.text = 'score: ' + score;
  }

  function ballHitPaddle(_ball, _paddle) {
    var diff = 0;

    if (_ball.body.x < _paddle.body.x) {
      //  Ball is on the left-hand side of the paddle
      diff = _paddle.body.x - _ball.body.x;
      _ball.body.velocity.x = (BALL_VELOCITY_MULTIPLIER_X * diff * -1);
    } else if (_ball.body.x > _paddle.body.x) {
      //  Ball is on the right-hand side of the paddle
      diff = _ball.body.x -_paddle.body.x;
      _ball.body.velocity.x = (BALL_VELOCITY_MULTIPLIER_X * diff);
    } else {
      //  Ball is perfectly in the middle
      //  Add a little random X to stop it bouncing straight up!
      _ball.body.velocity.x = BALL_VELOCITY_MULTIPLIER_X * 0.2 + Math.random() * BALL_VELOCITY_MULTIPLIER_X * 0.8;
    }
  }

  function bricksString(bricksGroup) {
    var i;
    var length = bricksGroup.children.length;
    var result = "";
    for (i = 0; i < length; i++) {
      if (bricksGroup.children[i].alive) {
        result += "1";
      } else {
        result += "0";
      }
    }
    return result;
  }

}());
<commit_msg>Fix issue 6: Add random ball release x velocity<commit_after>;(function () {

  var game = new Phaser.Game(GAME_WIDTH, GAME_HEIGHT, Phaser.AUTO, 'breakout', { preload: preload, create: create, update: update });
  var GAME_WIDTH = 800;
  var GAME_HEIGHT = 600;

  var background;

  var bricks;
  var BRICK_ROWS = 4;
  var BRICK_COLS = 15;
  var BRICK_START_X = 120;
  var BRICK_START_Y = 100;
  var BRICK_SPACING_X = 36;
  var BRICK_SPACING_Y = 52;

  var paddle;
  var PADDLE_Y = 500;
  var PADDLE_WIDTH = 48;

  var ball;
  var ballOnPaddle = true;
  var BALL_WIDTH = 16;
  var BALL_HEIGHT = 16;
  var BALL_RELEASE_VELOCITY_X = -75;
  var BALL_RELEASE_VELOCITY_Y = -300;
  var BALL_VELOCITY_MULTIPLIER_X = 10;

  var score = 0;
  var lives = 3;
  var scoreText;
  var livesText;
  var infoText;
  var TEXT_Y = 550;

  var socket;
  var remotePlayers = {};

  function preload() {
    console.log('preload invoked');
    game.load.atlas('breakout', '/assets/breakout.png', '/assets/breakout.json');
    game.load.image('starfield', '/assets/starfield.jpg');
  }

  function create() {
    console.log('create invoked');

    // Prevent game from pausing when browser tab loses focus
    game.stage.disableVisibilityChange = true;

    game.physics.startSystem(Phaser.Physics.ARCADE);

    background = game.add.tileSprite(0, 0, GAME_WIDTH, GAME_HEIGHT, 'starfield');

    // Check bounds collisions on all walls except bottom
    game.physics.arcade.checkCollision.down = false;

    createBricks();
    createLocalPaddle();
    createLocalBall();
    createText();

    game.input.onDown.add(releaseBall, this);

    socket = io.connect(window.location.hostname);
    attachSocketHandlers();
  }

  function createBricks() {
    console.log('createBricks invoked');
    bricks = game.add.group();
    bricks.enableBody = true;
    bricks.physicsBodyType = Phaser.Physics.ARCADE;

    var brick;
    var brickCount = 0;

    for (var row = 0; row < BRICK_ROWS; row++) {
      for (var col = 0; col < BRICK_COLS; col++) {
        brick = bricks.create(
          BRICK_START_X + (col * BRICK_SPACING_X),
          BRICK_START_Y + (row * BRICK_SPACING_Y),
          'breakout',
          'brick_' + (row + 1) + '_1.png'
        );
        brick.body.bounce.set(1);
        brick.body.immovable = true;
        brick.brickIndex = brickCount++;
      }
    }
  }

  function createLocalPaddle() {
    console.log('createLocalPaddle invoked');
    paddle = game.add.sprite(game.world.centerX, PADDLE_Y, 'breakout', 'paddle_big.png');
    paddle.anchor.setTo(0.5, 0.5);

    game.physics.enable(paddle, Phaser.Physics.ARCADE);

    paddle.body.collideWorldBounds = true;
    paddle.body.bounce.set(1);
    paddle.body.immovable = true;
  }

  function createLocalBall() {
    console.log('createLocalBall invoked');
    ball = game.add.sprite(game.world.centerX, PADDLE_Y - BALL_HEIGHT, 'breakout', 'ball_1.png');
    ball.anchor.set(0.5);
    ball.checkWorldBounds = true;

    game.physics.enable(ball, Phaser.Physics.ARCADE);

    ball.body.collideWorldBounds = true;
    ball.body.bounce.set(1);

    ball.animations.add('spin', [ 'ball_1.png', 'ball_2.png', 'ball_3.png', 'ball_4.png', 'ball_5.png' ], 50, true, false);

    ball.events.onOutOfBounds.add(ballLost, this);
  }

  function createText() {
    console.log('createText invoked');
    scoreText = game.add.text(32, TEXT_Y, 'score: 0',
      { font: '20px Arial', fill: '#ffffff', align: 'left' });
    livesText = game.add.text(GAME_WIDTH - 120, TEXT_Y, 'lives: 3',
      { font: '20px Arial', fill: '#ffffff', align: 'left' });
    infoText = game.add.text(game.world.centerX, GAME_HEIGHT * (2 / 3), 'Click to start',
      { font: '40px Arial', fill: '#ffffff', align: 'center' });
    infoText.anchor.setTo(0.5, 0.5);
  }

  function attachSocketHandlers() {
    console.log('attachSocketHandlers invoked');
    socket.on('connect', onSocketConnect);
    socket.on('disconnect', onSocketDisconnect);
    socket.on('new player', onNewPlayer);
    socket.on('remove player', onRemovePlayer);
    socket.on('initial bricks', onInitialBricks);
    socket.on('brick kill to other clients', onBrickKillToOtherClients);
  }

  function onSocketConnect() {
    console.log('onSocketConnect invoked');
    console.log('emitting "new player" message with existingBricks = ' + bricksString(bricks));
    socket.emit('new player', { existingBricks: bricksString(bricks) });
  }

  function onSocketDisconnect() {
    console.log('onSocketDisconnect invoked');
  }

  function onNewPlayer(data) {
    console.log('onNewPlayer invoked. data = ' + JSON.stringify(data));
    remotePlayers[data.id] = { score: data.score };
    console.log(data.id + ' added to remotePlayers: ' + JSON.stringify(remotePlayers));
  }

  function onRemovePlayer(data) {
    if (delete remotePlayers[data.id]) {
      console.log(data.id + ' removed from remotePlayers: ' + JSON.stringify(remotePlayers));
    } else {
      console.log(data.id + ' not found in remotePlayers');
    }
  }

  function onInitialBricks(data) {
    console.log('onInitialBricks invoked. data = ' + JSON.stringify(data));
    var i;
    for (var row = 0; row < BRICK_ROWS; row++) {
      for (var col = 0; col < BRICK_COLS; col++) {
        i = row * BRICK_COLS + col;
        if (data.initialBricks.charAt(i) === "0") {
          bricks.children[i].kill();
        }
      }
    }
  }

  function onBrickKillToOtherClients(data) {
    console.log('onBrickKillToOtherClients invoked');
    bricks.children[data.brickIndex].kill();
  }

  function update() {
    paddle.body.x = game.input.x - 0.5 * PADDLE_WIDTH;

    if (paddle.body.x < 0) {
      paddle.body.x = 0;
    } else if (paddle.body.x > game.width - PADDLE_WIDTH) {
      paddle.body.x = game.width - PADDLE_WIDTH;
    }

    if (ballOnPaddle) {
      ball.body.x = paddle.body.x + 0.5 * PADDLE_WIDTH - 0.5 * BALL_WIDTH;
    } else {
      game.physics.arcade.collide(ball, paddle, ballHitPaddle, null, this);
      game.physics.arcade.collide(ball, bricks, ballHitBrick, null, this);
    }

    if (bricks.countLiving() === 0) {
      startNewRound();
    }
  }

  function releaseBall() {
    if (ballOnPaddle) {
      ballOnPaddle = false;
      ball.body.velocity.x = BALL_RELEASE_VELOCITY_X * ( Math.random() * 4 - 1 );
      ball.body.velocity.y = BALL_RELEASE_VELOCITY_Y;
      ball.animations.play('spin');
      infoText.visible = false;
    }
  }

  function ballLost() {
    lives--;
    livesText.text = 'lives: ' + lives;
    if (lives === 0) {
      gameOver();
    } else {
      putBallOnPaddle();
    }
  }

  function putBallOnPaddle() {
    ballOnPaddle = true;
    ball.reset(paddle.body.x + 0.5 * PADDLE_WIDTH - 0.5 * BALL_WIDTH, PADDLE_Y - BALL_HEIGHT);
    ball.animations.stop();
  }

  function startNewRound() {
    console.log('startNewRound invoked');
    bricks.callAll('revive');
    if (lives !==0 ) {
      putBallOnPaddle();
      score += 1000;
      scoreText.text = 'score: ' + score;
      infoText.text = 'Next Round';
    }
  }

  function gameOver() {
    ball.body.velocity.setTo(0, 0);

    infoText.text = 'Game Over!';
    infoText.visible = true;
  }

  function ballHitBrick(_ball, _brick) {
    socket.emit('brick kill from client', { brickIndex: _brick.brickIndex });

    _brick.kill();

    score += 10;
    scoreText.text = 'score: ' + score;
  }

  function ballHitPaddle(_ball, _paddle) {
    var diff = 0;

    if (_ball.body.x < _paddle.body.x) {
      //  Ball is on the left-hand side of the paddle
      diff = _paddle.body.x - _ball.body.x;
      _ball.body.velocity.x = (BALL_VELOCITY_MULTIPLIER_X * diff * -1);
    } else if (_ball.body.x > _paddle.body.x) {
      //  Ball is on the right-hand side of the paddle
      diff = _ball.body.x -_paddle.body.x;
      _ball.body.velocity.x = (BALL_VELOCITY_MULTIPLIER_X * diff);
    } else {
      //  Ball is perfectly in the middle
      //  Add a little random X to stop it bouncing straight up!
      _ball.body.velocity.x = BALL_VELOCITY_MULTIPLIER_X * 0.2 + Math.random() * BALL_VELOCITY_MULTIPLIER_X * 0.8;
    }
  }

  function bricksString(bricksGroup) {
    var i;
    var length = bricksGroup.children.length;
    var result = "";
    for (i = 0; i < length; i++) {
      if (bricksGroup.children[i].alive) {
        result += "1";
      } else {
        result += "0";
      }
    }
    return result;
  }

}());
<|endoftext|>


<commit_before>document.getElementsByClassName("form-torrent-name")[0].onkeyup = function(){
    document.getElementsByClassName("table-torrent-name")[0].innerText = document.getElementsByClassName("form-torrent-name")[0].value;
};

document.getElementsByClassName("form-torrent-category")[0].onchange = function(){
    document.getElementsByClassName("table-torrent-category")[0].className = "table-torrent-category nyaa-cat nyaa-cat-" + Categorylist[document.getElementsByClassName("form-torrent-category")[0].selectedIndex];
};

document.getElementsByClassName("form-torrent-remake")[0].onchange = function(){
    document.getElementsByClassName("table-torrent-category")[0].className = "table-torrent-category nyaa-cat nyaa-cat-" + Categorylist[document.getElementsByClassName("form-torrent-category")[0].selectedIndex] + (document.getElementsByClassName("table-torrent-category")[0] == on) ? "remake" : "");
};

document.getElementsByClassName("torrent-preview-table")[0].display = "block";

var CategoryList = [
    5
    12,
    5,
    13,
    6,
    3,
    4,
    7,
    14,
    8,
    9,
    10,
    18,
    11,
    15,
    16,
    1,
    2
];
<commit_msg>Update kilo.js<commit_after>document.getElementsByClassName("form-torrent-name")[0].onkeyup = function(){
    document.getElementsByClassName("table-torrent-name")[0].innerText = document.getElementsByClassName("form-torrent-name")[0].value;
};

document.getElementsByClassName("form-torrent-category")[0].onchange = function(){
    document.getElementsByClassName("table-torrent-category")[0].className = "table-torrent-category nyaa-cat nyaa-cat-" + Categorylist[document.getElementsByClassName("form-torrent-category")[0].selectedIndex];
};

document.getElementsByClassName("form-torrent-remake")[0].onchange = function(){
    document.getElementsByClassName("table-torrent-category")[0].className = "table-torrent-category nyaa-cat nyaa-cat-" + Categorylist[document.getElementsByClassName("form-torrent-category")[0].selectedIndex] + (document.getElementsByClassName("torrent-form-remake")[0].value == "on" ? "remake" : "");
};

document.getElementsByClassName("torrent-preview-table")[0].display = "block";

var CategoryList = [
    5
    12,
    5,
    13,
    6,
    3,
    4,
    7,
    14,
    8,
    9,
    10,
    18,
    11,
    15,
    16,
    1,
    2
];
<|endoftext|>


<commit_before>/**
 * manual_mint.js
 *
 * Provices function to create ARKs manually
 */
const {clipboard} = require('electron').remote;

/**
 * Displays the minter display to input ERC to mint a ark
 */
function displayMinter() {
  $('#minter .display').show();

  $('#minter_erc_who').val(settings.erc_who);
  $('#minter_erc_when').val(formatTodaysDate());
  $('#minter_erc_where').val(settings.erc_where);

  $('#minter').animate({
    opacity: 1,
    top: "0px"
  });
  $('#minter').show();
}

/**
 * Closes the minter display
 */
function closeMinter() {
  $('#minter').animate({
    opacity: 0,
    top: "-300px"
  }, 400, function(){
    $(this).hide();
    $('#minter .loading').hide();
    $('#minter .response').hide();
  });
}

/**
 * Mints a ARK
 */
function mintArk() {
  $('#minter .display').hide();
  $('#minter .loading').show();

  var update_where = false;
  var post_data = {
    who: $('#minter_erc_who').val() || 'unknown',
    what: $('#minter_erc_what').val(),
    when: $('#minter_erc_when').val()
  };

  var update_where = $('#minter_erc_where').val().indexOf('$ark$') > -1;
  if (!update_where) {
    post_data.where = $('#minter_erc_where').val();
  }

  if ( settings.mint_url === '' || settings.api_key === '' ) {
    logger.error('Unable to mint. Please provide the URL and/or API key for the minter.');
    closeMinter();
    return false;
  }

  $.ajax({
    url: settings.mint_url,
    headers: {
      'api-key': settings.api_key
    },
    dataType: 'json',
    method: 'POST',
    data: post_data,
    success: function (data) {
      var id = data['id'];
      if (update_where) {
        minter_update_erc_where(data);
      }
      else {
        minter_get_ark(data['id']);
      }
    },
    error: function(data) {
      logger.warn('FAILED to mint');
      closeMinter();
    }
  });
}

/**
 * Updates the ARK with new ERC.where.
 * This is used when the ERC.where has the ARK identifier in it.
 *
 * @param Object ark The returned object containing ARK information
 */
function minter_update_erc_where(ark) {
  var post_data = {
    where: $('#minter_erc_where').val().replace('$ark$', encodeURIComponent(ark['id']))
  };

  $.ajax({
    url: settings.update_url + ark['id'],
    headers: {
      'api-key': settings.api_key
    },
    data: post_data,
    method: 'PUT',
    success: function (data) {
      showMinterComplete(data);
    },
    error: function(data) {
      logger.error('FAILED to update erc.where for identifier "' + ark ['id'] + '"');
      closeMinter();
    }
  });
}

/**
 * Gets ARK ERC information for the given identifier
 *
 * @param String id The ark identifier
 */
function minter_get_ark(id) {
  $.get(settings.update_url + id).done(function(data){
    showMinterComplete(data);
  }).fail(function(){
    logger.error('FAILED to get ark information for identifier "' + id + '"');
  });
}

/**
 * Displays the ARK information after minting
 *
 * @param Object data The ark information
 */
function showMinterComplete(data) {
  var ark = data.ark;
  logger.log('Identifier created: ' + ark.id , 'good');
  logger.log('erc:');
  logger.log('who: ' + ark.who);
  logger.log('what: ' + ark.what);
  logger.log('when: ' + ark.when);
  logger.log('where: ' + ark.where);

  $('#minter .response #ark_identifier').val(ark.id);
  $('#minter .response .erc .who').text(ark.who);
  $('#minter .response .erc .what').text(ark.what);
  $('#minter .response .erc .when').text(ark.when);
  $('#minter .response .erc .where').text(ark.where);

  $('#minter .loading').hide();
  $('#minter .response').show();
}

/**
 * Copies the ARK identifier to the clipboard
 *
 * @param String selector The DOM selector holding the value to add
 */
function minterCopyToClipboard(selector) {
  clipboard.write({text: $(selector).val()})
}<commit_msg>fix #4<commit_after>/**
 * manual_mint.js
 *
 * Provices function to create ARKs manually
 */
const {clipboard} = require('electron').remote;

/**
 * Displays the minter display to input ERC to mint a ark
 */
function displayMinter() {
  $('#minter .display').show();

  $('#minter_erc_who').val(settings.erc_who);
  $('#minter_erc_what').val('');
  $('#minter_erc_when').val(formatTodaysDate());
  $('#minter_erc_where').val(settings.erc_where);

  $('#minter').animate({
    opacity: 1,
    top: "0px"
  });
  $('#minter').show();
}

/**
 * Closes the minter display
 */
function closeMinter() {
  $('#minter').animate({
    opacity: 0,
    top: "-300px"
  }, 400, function(){
    $(this).hide();
    $('#minter .loading').hide();
    $('#minter .response').hide();
  });
}

/**
 * Mints a ARK
 */
function mintArk() {
  $('#minter .display').hide();
  $('#minter .loading').show();

  var update_where = false;
  var post_data = {
    who: $('#minter_erc_who').val() || 'unknown',
    what: $('#minter_erc_what').val(),
    when: $('#minter_erc_when').val()
  };

  var update_where = $('#minter_erc_where').val().indexOf('$ark$') > -1;
  if (!update_where) {
    post_data.where = $('#minter_erc_where').val();
  }

  if ( settings.mint_url === '' || settings.api_key === '' ) {
    logger.error('Unable to mint. Please provide the URL and/or API key for the minter.');
    closeMinter();
    return false;
  }

  $.ajax({
    url: settings.mint_url,
    headers: {
      'api-key': settings.api_key
    },
    dataType: 'json',
    method: 'POST',
    data: post_data,
    success: function (data) {
      var id = data['id'];
      if (update_where) {
        minter_update_erc_where(data);
      }
      else {
        minter_get_ark(data['id']);
      }
    },
    error: function(data) {
      logger.warn('FAILED to mint');
      closeMinter();
    }
  });
}

/**
 * Updates the ARK with new ERC.where.
 * This is used when the ERC.where has the ARK identifier in it.
 *
 * @param Object ark The returned object containing ARK information
 */
function minter_update_erc_where(ark) {
  var post_data = {
    where: $('#minter_erc_where').val().replace('$ark$', encodeURIComponent(ark['id']))
  };

  $.ajax({
    url: settings.update_url + ark['id'],
    headers: {
      'api-key': settings.api_key
    },
    data: post_data,
    method: 'PUT',
    success: function (data) {
      showMinterComplete(data);
    },
    error: function(data) {
      logger.error('FAILED to update erc.where for identifier "' + ark ['id'] + '"');
      closeMinter();
    }
  });
}

/**
 * Gets ARK ERC information for the given identifier
 *
 * @param String id The ark identifier
 */
function minter_get_ark(id) {
  $.get(settings.update_url + id).done(function(data){
    showMinterComplete(data);
  }).fail(function(){
    logger.error('FAILED to get ark information for identifier "' + id + '"');
  });
}

/**
 * Displays the ARK information after minting
 *
 * @param Object data The ark information
 */
function showMinterComplete(data) {
  var ark = data.ark;
  logger.log('Identifier created: ' + ark.id , 'good');
  logger.log('erc:');
  logger.log('who: ' + ark.who);
  logger.log('what: ' + ark.what);
  logger.log('when: ' + ark.when);
  logger.log('where: ' + ark.where);

  $('#minter .response #ark_identifier').val(ark.id);
  $('#minter .response .erc .who').text(ark.who);
  $('#minter .response .erc .what').text(ark.what);
  $('#minter .response .erc .when').text(ark.when);
  $('#minter .response .erc .where').text(ark.where);

  $('#minter .loading').hide();
  $('#minter .response').show();
}

/**
 * Copies the ARK identifier to the clipboard
 *
 * @param String selector The DOM selector holding the value to add
 */
function minterCopyToClipboard(selector) {
  clipboard.write({text: $(selector).val()})
}<|endoftext|>


<commit_before>var app = (function(me) {
  me.engine = (function(me) {

    var _itemUID = 0;
    var numberOfCreatedItems = 0;

    var movementOffset = 5;

    me.items = ko.observableArray();

    function createItem() {
      me.items.push(
        new app.engine.Item('item' + _itemUID++, 'ball')
      );

      if (numberOfCreatedItems++ === 3) {
        me.offTick(createItem);
      }
    }

    function moveConveyor() {
      me.items().forEach(moveSingleItem);
    }

    function moveSingleItem(item) {
      item.xpos(item.xpos() + movementOffset);
    }

    me.onTick(createItem, 30);
    me.onTick(moveConveyor, 25);

    return me;
  })(me.engine);

  return me;
})(window.app);
<commit_msg>Really speed up conveyor<commit_after>var app = (function(me) {
  me.engine = (function(me) {

    var _itemUID = 0;
    var numberOfCreatedItems = 0;

    var movementOffset = 5;

    me.items = ko.observableArray();

    function createItem() {
      me.items.push(
        new app.engine.Item('item' + _itemUID++, 'ball')
      );

      if (numberOfCreatedItems++ === 3) {
        me.offTick(createItem);
      }
    }

    function moveConveyor() {
      me.items().forEach(moveSingleItem);
    }

    function moveSingleItem(item) {
      item.xpos(item.xpos() + movementOffset);
    }

    me.onTick(createItem, 30);
    me.onTick(moveConveyor, 5);

    return me;
  })(me.engine);

  return me;
})(window.app);
<|endoftext|>


<commit_before>"use strict";

//Load dependencies
var async = require("async");
var applicationStorage = process.require("core/applicationStorage.js");
var rankModel = process.require("ranks/rankModel.js");
var realmModel = process.require("realms/realmModel.js");
var guildModel = process.require("guilds/guildModel.js");
var guildProgressModel = process.require("guildProgress/guildProgressModel.js");

module.exports.getRank = function (req, res, next) {

    var logger = applicationStorage.logger;
    logger.info("%s %s %s %s", req.headers['x-forwarded-for'] || req.connection.remoteAddress, req.method, req.path, JSON.stringify(req.params));

    async.parallel({
        world: function (callback) {
            rankModel.getRank(req.params.tier, req.params.region, req.params.realm, req.params.name, function (error, rank) {
                if (rank != null) {
                    callback(error, rank + 1)
                } else {
                    callback(error, null)
                }
            });
        },
        region: function (callback) {
            rankModel.getRank(req.params.tier + "_" + req.params.region, req.params.region, req.params.realm, req.params.name, function (error, rank) {
                if (rank != null) {
                    callback(error, rank + 1)
                } else {
                    callback(error, null)
                }
            });
        },
        realmlocale: function (callback) {
            realmModel.findOne({
                region: req.params.region,
                name: req.params.realm
            }, {connected_realms: 1, "bnet.locale": 1, "bnet.timezone": 1}, function (error, realm) {
                if (realm && realm.connected_realms && realm.bnet && realm.bnet.locale && realm.bnet.timezone) {
                    async.parallel({
                        realm: function (callback) {
                            rankModel.getRank(req.params.tier + "_" + req.params.region + "_" + realm.connected_realms.join('_'), req.params.region, req.params.realm, req.params.name, function (error, rank) {
                                if (rank != null) {
                                    callback(error, rank + 1)
                                } else {
                                    callback(error, null)
                                }
                            });
                        },
                        locale: function (callback) {
                            var zoneArray = realm.bnet.timezone.split('/');
                            if(zoneArray.length > 0 ) {
                                rankModel.getRank(req.params.tier + "_" + realm.bnet.locale+"_"+zoneArray[0], req.params.region, req.params.realm, req.params.name, function (error, rank) {
                                    if (rank != null) {
                                        var result = {};
                                        result['rank'] = rank + 1;
                                        result['type'] = realm.bnet.locale+"_"+zoneArray[0];
                                        callback(error, result)
                                    } else {
                                        callback(error, null)
                                    }
                                });
                            }else {
                                callback(error,null);
                            }
                        }
                    }, function (error, result) {
                        if (result.realm != null && result.locale != null) {
                            callback(error, result);
                        } else {
                            callback(error, null);
                        }
                    });

                } else {
                    logger.warn("Realm %s-%s not found", req.params.region, req.params.realm);
                    callback(error);
                }
            });
        }
    }, function (error, result) {
        if (error) {
            logger.error(error.message);
            res.status(500).send(error.message);
        } else if (result && result.world !== null && result.region != null) {
            if (result.realmlocale != null) {
                result.realm = result.realmlocale.realm;
                result.locale = result.realmlocale.locale;
            }
            delete result.realmlocale;
            res.json(result);
        } else {
            next();
        }
    });
};

module.exports.getRanking = function (req, res, next) {

    var logger = applicationStorage.logger;
    var config = applicationStorage.config;

    logger.info("%s %s %s %s", req.headers['x-forwarded-for'] || req.connection.remoteAddress, req.method, req.path, JSON.stringify(req.params));

    var start = 0;
    if (req.query && req.query.start) {
        start = parseInt(req.query.start, 10) > 0 ? parseInt(req.query.start, 10) - 1 : 0
    }

    var end = start + 500;
    if (req.query && req.query.limit) {
        var limit = parseInt(req.query.limit, 10);

        if (limit < 0) {
            limit = 50;
        }

        if (limit > 50) {
            limit = 50;
        }

        end = start + limit - 1;
    }

    async.waterfall([
        function (callback) {
            var key = req.params.tier;
            if (req.params.realm && req.params.region) {
                realmModel.findOne({
                    region: req.params.region,
                    name: req.params.realm
                }, {connected_realms: 1}, function (error, realm) {
                    if (realm) {
                        key = req.params.tier + "_" + req.params.region + "_" + realm.connected_realms.join('_');
                        callback(error, key);
                    } else {
                        callback(new Error("Realm %s-%s not found", req.params.region, req.params.realm));
                    }
                });
            } else if (req.params.region) {
                key = req.params.tier + "_" + req.params.region;
                callback(null, key);
            } else if (req.params.locale) {
                key = req.params.tier + "_" + req.params.locale;
                callback(null, key);
            } else {
                callback(null, key);
            }
        },
        function (key, callback) {
            rankModel.getRanking(key, start, end, function (error, ranking) {
                callback(error, ranking);
            });
        }
    ], function (error, ranking) {
        if (error) {
            logger.error(error.message);
            res.status(500).send(error.message);
        } else if (ranking) {
            var finalRanking = {};
            var counter = 1;
            async.forEachSeries(ranking, function (rank, callback) {
                var rankArray = rank.split('-');

                //Fix realm with - ...
                if (rankArray.length == 4) {
                    rankArray[1] = rankArray[1] + "-" + rankArray[2];
                    rankArray[2] = rankArray[3];
                }

                finalRanking[start + counter] = {region: rankArray[0], realm: rankArray[1], name: rankArray[2]};
                async.parallel([
                    function (callback) {
                        //GET GUILD SIDE and add it
                        guildModel.getGuildInfo(rankArray[0], rankArray[1], rankArray[2], function (error, guild) {
                            if (guild && guild.bnet && guild.bnet.side != null) {
                                finalRanking[start + counter]["side"] = guild.bnet.side;
                            }
                            if (guild && guild.ad && guild.ad.lfg == true) {
                                finalRanking[start + counter]["lfg"] = true;
                            }
                            callback(error);
                        });
                    },
                    function (callback) {
                        //GET GUILD Progress and add it
                        var project = {};
                        config.progress.raids.forEach(function (raid) {
                            if (raid.tier == parseInt(req.params.tier, 10)) {
                                var difficulties = ["normal", "heroic", "mythic"];
                                difficulties.forEach(function (difficulty) {
                                    raid.bosses.forEach(function (boss) {
                                        project["progress.tier_" + req.params.tier + "." + difficulty + "." + boss.name] = {$size: {$ifNull: ["$progress.tier_" + req.params.tier + "." + difficulty + "." + boss.name + ".timestamps", []]}};
                                    });
                                });
                            }
                        });
                        project["progress.tier_" + req.params.tier + ".normalCount"] = 1;
                        project["progress.tier_" + req.params.tier + ".heroicCount"] = 1;
                        project["progress.tier_" + req.params.tier + ".mythicCount"] = 1;

                        guildProgressModel.aggregate({
                            region: rankArray[0],
                            realm: rankArray[1],
                            name: rankArray[2]
                        }, project, function (error, result) {

                            if (result && result.length > 0 && result[0]['progress'] && result[0]['progress']["tier_" + req.params.tier]) {
                                finalRanking[start + counter]["progress"] = result[0]["progress"]["tier_" + req.params.tier];
                            }
                            callback(error);
                        });

                    },
                    function (callback) {
                        rankModel.getRank(req.params.tier, rankArray[0], rankArray[1], rankArray[2], function (error, rank) {
                            if (rank) {
                                finalRanking[start + counter]["world"] = rank + 1;
                            }
                            callback(error);
                        });

                    }
                ], function (error) {
                    counter++;
                    callback(error);
                })

            }, function (error) {
                if (error) {
                    logger.error(error.message);
                    res.status(500).send(error.message)
                } else {
                    res.json(finalRanking);
                }
            });
        } else {
            next();
        }
    });

};<commit_msg>Change default number guilds return on ranking from 500 to 20<commit_after>"use strict";

//Load dependencies
var async = require("async");
var applicationStorage = process.require("core/applicationStorage.js");
var rankModel = process.require("ranks/rankModel.js");
var realmModel = process.require("realms/realmModel.js");
var guildModel = process.require("guilds/guildModel.js");
var guildProgressModel = process.require("guildProgress/guildProgressModel.js");

module.exports.getRank = function (req, res, next) {

    var logger = applicationStorage.logger;
    logger.info("%s %s %s %s", req.headers['x-forwarded-for'] || req.connection.remoteAddress, req.method, req.path, JSON.stringify(req.params));

    async.parallel({
        world: function (callback) {
            rankModel.getRank(req.params.tier, req.params.region, req.params.realm, req.params.name, function (error, rank) {
                if (rank != null) {
                    callback(error, rank + 1)
                } else {
                    callback(error, null)
                }
            });
        },
        region: function (callback) {
            rankModel.getRank(req.params.tier + "_" + req.params.region, req.params.region, req.params.realm, req.params.name, function (error, rank) {
                if (rank != null) {
                    callback(error, rank + 1)
                } else {
                    callback(error, null)
                }
            });
        },
        realmlocale: function (callback) {
            realmModel.findOne({
                region: req.params.region,
                name: req.params.realm
            }, {connected_realms: 1, "bnet.locale": 1, "bnet.timezone": 1}, function (error, realm) {
                if (realm && realm.connected_realms && realm.bnet && realm.bnet.locale && realm.bnet.timezone) {
                    async.parallel({
                        realm: function (callback) {
                            rankModel.getRank(req.params.tier + "_" + req.params.region + "_" + realm.connected_realms.join('_'), req.params.region, req.params.realm, req.params.name, function (error, rank) {
                                if (rank != null) {
                                    callback(error, rank + 1)
                                } else {
                                    callback(error, null)
                                }
                            });
                        },
                        locale: function (callback) {
                            var zoneArray = realm.bnet.timezone.split('/');
                            if(zoneArray.length > 0 ) {
                                rankModel.getRank(req.params.tier + "_" + realm.bnet.locale+"_"+zoneArray[0], req.params.region, req.params.realm, req.params.name, function (error, rank) {
                                    if (rank != null) {
                                        var result = {};
                                        result['rank'] = rank + 1;
                                        result['type'] = realm.bnet.locale+"_"+zoneArray[0];
                                        callback(error, result)
                                    } else {
                                        callback(error, null)
                                    }
                                });
                            }else {
                                callback(error,null);
                            }
                        }
                    }, function (error, result) {
                        if (result.realm != null && result.locale != null) {
                            callback(error, result);
                        } else {
                            callback(error, null);
                        }
                    });

                } else {
                    logger.warn("Realm %s-%s not found", req.params.region, req.params.realm);
                    callback(error);
                }
            });
        }
    }, function (error, result) {
        if (error) {
            logger.error(error.message);
            res.status(500).send(error.message);
        } else if (result && result.world !== null && result.region != null) {
            if (result.realmlocale != null) {
                result.realm = result.realmlocale.realm;
                result.locale = result.realmlocale.locale;
            }
            delete result.realmlocale;
            res.json(result);
        } else {
            next();
        }
    });
};

module.exports.getRanking = function (req, res, next) {

    var logger = applicationStorage.logger;
    var config = applicationStorage.config;

    logger.info("%s %s %s %s", req.headers['x-forwarded-for'] || req.connection.remoteAddress, req.method, req.path, JSON.stringify(req.params));

    var start = 0;
    if (req.query && req.query.start) {
        start = parseInt(req.query.start, 10) > 0 ? parseInt(req.query.start, 10) - 1 : 0
    }

    var end = start + 20;
    if (req.query && req.query.limit) {
        var limit = parseInt(req.query.limit, 10);

        if (limit < 0) {
            limit = 50;
        }

        if (limit > 50) {
            limit = 50;
        }

        end = start + limit - 1;
    }

    async.waterfall([
        function (callback) {
            var key = req.params.tier;
            if (req.params.realm && req.params.region) {
                realmModel.findOne({
                    region: req.params.region,
                    name: req.params.realm
                }, {connected_realms: 1}, function (error, realm) {
                    if (realm) {
                        key = req.params.tier + "_" + req.params.region + "_" + realm.connected_realms.join('_');
                        callback(error, key);
                    } else {
                        callback(new Error("Realm %s-%s not found", req.params.region, req.params.realm));
                    }
                });
            } else if (req.params.region) {
                key = req.params.tier + "_" + req.params.region;
                callback(null, key);
            } else if (req.params.locale) {
                key = req.params.tier + "_" + req.params.locale;
                callback(null, key);
            } else {
                callback(null, key);
            }
        },
        function (key, callback) {
            rankModel.getRanking(key, start, end, function (error, ranking) {
                callback(error, ranking);
            });
        }
    ], function (error, ranking) {
        if (error) {
            logger.error(error.message);
            res.status(500).send(error.message);
        } else if (ranking) {
            var finalRanking = {};
            var counter = 1;
            async.forEachSeries(ranking, function (rank, callback) {
                var rankArray = rank.split('-');

                //Fix realm with - ...
                if (rankArray.length == 4) {
                    rankArray[1] = rankArray[1] + "-" + rankArray[2];
                    rankArray[2] = rankArray[3];
                }

                finalRanking[start + counter] = {region: rankArray[0], realm: rankArray[1], name: rankArray[2]};
                async.parallel([
                    function (callback) {
                        //GET GUILD SIDE and add it
                        guildModel.getGuildInfo(rankArray[0], rankArray[1], rankArray[2], function (error, guild) {
                            if (guild && guild.bnet && guild.bnet.side != null) {
                                finalRanking[start + counter]["side"] = guild.bnet.side;
                            }
                            if (guild && guild.ad && guild.ad.lfg == true) {
                                finalRanking[start + counter]["lfg"] = true;
                            }
                            callback(error);
                        });
                    },
                    function (callback) {
                        //GET GUILD Progress and add it
                        var project = {};
                        config.progress.raids.forEach(function (raid) {
                            if (raid.tier == parseInt(req.params.tier, 10)) {
                                var difficulties = ["normal", "heroic", "mythic"];
                                difficulties.forEach(function (difficulty) {
                                    raid.bosses.forEach(function (boss) {
                                        project["progress.tier_" + req.params.tier + "." + difficulty + "." + boss.name] = {$size: {$ifNull: ["$progress.tier_" + req.params.tier + "." + difficulty + "." + boss.name + ".timestamps", []]}};
                                    });
                                });
                            }
                        });
                        project["progress.tier_" + req.params.tier + ".normalCount"] = 1;
                        project["progress.tier_" + req.params.tier + ".heroicCount"] = 1;
                        project["progress.tier_" + req.params.tier + ".mythicCount"] = 1;

                        guildProgressModel.aggregate({
                            region: rankArray[0],
                            realm: rankArray[1],
                            name: rankArray[2]
                        }, project, function (error, result) {

                            if (result && result.length > 0 && result[0]['progress'] && result[0]['progress']["tier_" + req.params.tier]) {
                                finalRanking[start + counter]["progress"] = result[0]["progress"]["tier_" + req.params.tier];
                            }
                            callback(error);
                        });

                    },
                    function (callback) {
                        rankModel.getRank(req.params.tier, rankArray[0], rankArray[1], rankArray[2], function (error, rank) {
                            if (rank) {
                                finalRanking[start + counter]["world"] = rank + 1;
                            }
                            callback(error);
                        });

                    }
                ], function (error) {
                    counter++;
                    callback(error);
                })

            }, function (error) {
                if (error) {
                    logger.error(error.message);
                    res.status(500).send(error.message)
                } else {
                    res.json(finalRanking);
                }
            });
        } else {
            next();
        }
    });

};<|endoftext|>