<commit_before>function GameManager(size, InputManager, Actuator, ScoreManager) {
  this.size         = size; // Size of the grid
  this.inputManager = new InputManager;
  this.scoreManager = new ScoreManager;
  this.actuator     = new Actuator;

  this.startTiles   = 2;

  this.inputManager.on("move", this.move.bind(this));
  this.inputManager.on("restart", this.restart.bind(this));
  this.inputManager.on("keepPlaying", this.keepPlaying.bind(this));

  this.setup();
}

// Restart the game
GameManager.prototype.restart = function () {
  this.actuator.continue();
  this.setup();
};

// Keep playing after winning
GameManager.prototype.keepPlaying = function () {
  this.keepPlaying = true;
  this.actuator.continue();
};

GameManager.prototype.isGameTerminated = function () {
  if (this.over || (this.won && !this.keepPlaying)) {
    return true;
  } else {
    return false;
  }
};

// Set up the game
GameManager.prototype.setup = function () {
  this.grid        = new Grid(this.size);

  this.score       = 0;
  this.over        = false;
  this.won         = false;
  this.keepPlaying = false;

  // Add the initial tiles
  this.addStartTiles();

  // Update the actuator
  this.actuate();
};

// Set up the initial tiles to start the game with
GameManager.prototype.addStartTiles = function () {
  for (var i = 0; i < this.startTiles; i++) {
    this.addRandomTile();
  }
};

// Adds a tile in a random position
GameManager.prototype.addRandomTile = function () {
  if (this.grid.cellsAvailable()) {
    var value = Math.random() < 0.9 ? 2 : 4;
    var tile = new Tile(this.grid.randomAvailableCell(), value);

    this.grid.insertTile(tile);
  }
};

// Sends the updated grid to the actuator
GameManager.prototype.actuate = function () {
  if (this.scoreManager.get() < this.score) {
    this.scoreManager.set(this.score);
  }

  this.actuator.actuate(this.grid, {
    score:      this.score,
    over:       this.over,
    won:        this.won,
    bestScore:  this.scoreManager.get(),
    terminated: this.isGameTerminated()
  });

};

// Save all tile positions and remove merger info
GameManager.prototype.prepareTiles = function () {
  this.grid.eachCell(function (x, y, z, w, v, tile) {
    if (tile) {
      tile.mergedFrom = null;
      tile.savePosition();
    }
  });
};

// Move a tile and its representation
GameManager.prototype.moveTile = function (tile, cell) {
  this.grid.cells[tile.x][tile.y][tile.z][tile.w][tile.v] = null;
  this.grid.cells[cell.x][cell.y][cell.z][cell.w][cell.v] = tile;
  tile.updatePosition(cell);
};

// Move tiles on the grid in the specified direction
GameManager.prototype.move = function (direction) {
  // 0: up, 1: right, 2:down, 3: left
  // x + 4: hyper-x
  // 8: ultra-left, 9: ultra-right

  var self = this;

  if (this.isGameTerminated()) return; // Don't do anything if the game's over

  var cell, tile;

  var vector     = this.getVector(direction);
  var traversals = this.buildTraversals(vector);
  var moved      = false;

  // Save the current tile positions and remove merger information
  this.prepareTiles();

  // Traverse the grid in the right direction and move tiles
  traversals.x.forEach(function (x) {
    traversals.y.forEach(function (y) {
      traversals.z.forEach(function (z) {
        traversals.w.forEach(function (w) {
          traversals.v.forEach(function(v) {
            cell = { x: x, y: y, z: z, w: w, v: v };
            tile = self.grid.cellContent(cell);

            if (tile) {
              var positions = self.findFarthestPosition(cell, vector);
              var next      = self.grid.cellContent(positions.next);

              // Only one merger per row traversal?
              if (next && next.value === tile.value && !next.mergedFrom) {
                var merged = new Tile(positions.next, tile.value * 2);
                merged.mergedFrom = [tile, next];

                self.grid.insertTile(merged);
                self.grid.removeTile(tile);

                // Converge the two tiles' positions
                tile.updatePosition(positions.next);

                // Update the score
                self.score += merged.value;

                // The mighty 2048 tile
                if (merged.value === 2048) self.won = true;
              } else {
                self.moveTile(tile, positions.farthest);
              }

              if (!self.positionsEqual(cell, tile)) {
                moved = true; // The tile moved from its original cell!
              }
            }
          });
        });
      });
    });
  });

  if (moved) {
    this.addRandomTile();

    if (Math.random() < 0.8) {
      this.addRandomTile();
    }

    if (!this.movesAvailable()) {
      this.over = true; // Game over!
    }

    this.actuate();
  }
};

// Get the vector representing the chosen direction
GameManager.prototype.getVector = function (direction) {
  // Vectors representing tile movement
  var map = {
    0: { x: 0,  y: -1, z: 0,  w: 0,  v: 0  },  // up
    1: { x: 1,  y: 0,  z: 0,  w: 0,  v: 0  },  // right
    2: { x: 0,  y: 1,  z: 0,  w: 0,  v: 0  },  // down
    3: { x: -1, y: 0,  z: 0,  w: 0,  v: 0  },  // left
    4: { x: 0,  y: 0,  z: 0,  w: -1, v: 0  },  // hyper-up
    5: { x: 0,  y: 0,  z: 1,  w: 0,  v: 0  },  // hyper-right
    6: { x: 0,  y: 0,  z: 0,  w: 1,  v: 0  },  // hyper-down
    7: { x: 0,  y: 0,  z: -1, w: 0,  v: 0  },  // hyper-left
    8: { x: 0,  y: 0,  z: 0,  w: 0 , v: -1 },  // ultra-left
    9: { x: 0,  y: 0,  z: 0,  w: 0 , v: 1  },  // ultra-right
  };

  return map[direction];
};

// Build a list of positions to traverse in the right order
GameManager.prototype.buildTraversals = function (vector) {
  var traversals = { x: [], y: [], z: [], w: [], v: [] };

  for (var pos = 0; pos < this.size; pos++) {
    traversals.x.push(pos);
    traversals.y.push(pos);
    traversals.z.push(pos);
    traversals.w.push(pos);
    traversals.v.push(pos);
  }

  // Always traverse from the farthest cell in the chosen direction
  if (vector.x === 1) traversals.x = traversals.x.reverse();
  if (vector.y === 1) traversals.y = traversals.y.reverse();
  if (vector.z === 1) traversals.z = traversals.z.reverse();
  if (vector.w === 1) traversals.w = traversals.w.reverse();
  if (vector.v === 1) traversals.v = traversals.v.reverse();
  return traversals;
};

GameManager.prototype.findFarthestPosition = function (cell, vector) {
  var previous;

  // Progress towards the vector direction until an obstacle is found
  do {
    previous = cell;
    cell     = { x: previous.x + vector.x, y: previous.y + vector.y,
                 z: previous.z + vector.z, w: previous.w + vector.w,
                 v: previous.v + vector.v };
  } while (this.grid.withinBounds(cell) &&
           this.grid.cellAvailable(cell));

  return {
    farthest: previous,
    next: cell // Used to check if a merge is required
  };
};

GameManager.prototype.movesAvailable = function () {
  return this.grid.cellsAvailable() || this.tileMatchesAvailable();
};

// Check for available matches between tiles (more expensive check)
GameManager.prototype.tileMatchesAvailable = function () {
  var self = this;

  var tile;

  for (var x = 0; x < this.size; x++) {
    for (var y = 0; y < this.size; y++) {
      for (var z = 0; z < this.size; z++) {
        for (var w = 0; w < this.size; w++) {
          for (var v = 0; v < this.size; v++) {
            tile = this.grid.cellContent({ x: x, y: y, z: z, w: w, v: v });

            if (tile) {
              for (var direction = 0; direction < 8; direction++) {
                var vector = self.getVector(direction);
                var cell   = { x: x + vector.x, y: y + vector.y,
                               z: z + vector.z, w: w + vector.w,
                               v: v + vector.v };

                var other  = self.grid.cellContent(cell);

                if (other && other.value === tile.value) {
                  return true; // These two tiles can be merged
                }
              }
            }
          }
        }
      }
    }
  }

  return false;
};

GameManager.prototype.positionsEqual = function (first, second) {
  return first.x === second.x && first.y === second.y &&
         first.z === second.z && first.w == second.w &&
         first.v === second.v;
};
<commit_msg>tweaking difficulty again<commit_after>function GameManager(size, InputManager, Actuator, ScoreManager) {
  this.size         = size; // Size of the grid
  this.inputManager = new InputManager;
  this.scoreManager = new ScoreManager;
  this.actuator     = new Actuator;

  this.startTiles   = 2;

  this.inputManager.on("move", this.move.bind(this));
  this.inputManager.on("restart", this.restart.bind(this));
  this.inputManager.on("keepPlaying", this.keepPlaying.bind(this));

  this.setup();
}

// Restart the game
GameManager.prototype.restart = function () {
  this.actuator.continue();
  this.setup();
};

// Keep playing after winning
GameManager.prototype.keepPlaying = function () {
  this.keepPlaying = true;
  this.actuator.continue();
};

GameManager.prototype.isGameTerminated = function () {
  if (this.over || (this.won && !this.keepPlaying)) {
    return true;
  } else {
    return false;
  }
};

// Set up the game
GameManager.prototype.setup = function () {
  this.grid        = new Grid(this.size);

  this.score       = 0;
  this.over        = false;
  this.won         = false;
  this.keepPlaying = false;

  // Add the initial tiles
  this.addStartTiles();

  // Update the actuator
  this.actuate();
};

// Set up the initial tiles to start the game with
GameManager.prototype.addStartTiles = function () {
  for (var i = 0; i < this.startTiles; i++) {
    this.addRandomTile();
  }
};

// Adds a tile in a random position
GameManager.prototype.addRandomTile = function () {
  if (this.grid.cellsAvailable()) {
    var value = Math.random() < 0.9 ? 2 : 4;
    var tile = new Tile(this.grid.randomAvailableCell(), value);

    this.grid.insertTile(tile);
  }
};

// Sends the updated grid to the actuator
GameManager.prototype.actuate = function () {
  if (this.scoreManager.get() < this.score) {
    this.scoreManager.set(this.score);
  }

  this.actuator.actuate(this.grid, {
    score:      this.score,
    over:       this.over,
    won:        this.won,
    bestScore:  this.scoreManager.get(),
    terminated: this.isGameTerminated()
  });

};

// Save all tile positions and remove merger info
GameManager.prototype.prepareTiles = function () {
  this.grid.eachCell(function (x, y, z, w, v, tile) {
    if (tile) {
      tile.mergedFrom = null;
      tile.savePosition();
    }
  });
};

// Move a tile and its representation
GameManager.prototype.moveTile = function (tile, cell) {
  this.grid.cells[tile.x][tile.y][tile.z][tile.w][tile.v] = null;
  this.grid.cells[cell.x][cell.y][cell.z][cell.w][cell.v] = tile;
  tile.updatePosition(cell);
};

// Move tiles on the grid in the specified direction
GameManager.prototype.move = function (direction) {
  // 0: up, 1: right, 2:down, 3: left
  // x + 4: hyper-x
  // 8: ultra-left, 9: ultra-right

  var self = this;

  if (this.isGameTerminated()) return; // Don't do anything if the game's over

  var cell, tile;

  var vector     = this.getVector(direction);
  var traversals = this.buildTraversals(vector);
  var moved      = false;

  // Save the current tile positions and remove merger information
  this.prepareTiles();

  // Traverse the grid in the right direction and move tiles
  traversals.x.forEach(function (x) {
    traversals.y.forEach(function (y) {
      traversals.z.forEach(function (z) {
        traversals.w.forEach(function (w) {
          traversals.v.forEach(function(v) {
            cell = { x: x, y: y, z: z, w: w, v: v };
            tile = self.grid.cellContent(cell);

            if (tile) {
              var positions = self.findFarthestPosition(cell, vector);
              var next      = self.grid.cellContent(positions.next);

              // Only one merger per row traversal?
              if (next && next.value === tile.value && !next.mergedFrom) {
                var merged = new Tile(positions.next, tile.value * 2);
                merged.mergedFrom = [tile, next];

                self.grid.insertTile(merged);
                self.grid.removeTile(tile);

                // Converge the two tiles' positions
                tile.updatePosition(positions.next);

                // Update the score
                self.score += merged.value;

                // The mighty 2048 tile
                if (merged.value === 2048) self.won = true;
              } else {
                self.moveTile(tile, positions.farthest);
              }

              if (!self.positionsEqual(cell, tile)) {
                moved = true; // The tile moved from its original cell!
              }
            }
          });
        });
      });
    });
  });

  if (moved) {
    this.addRandomTile();

    if (Math.random() < 0.7) {
      this.addRandomTile();
    }

    if (!this.movesAvailable()) {
      this.over = true; // Game over!
    }

    this.actuate();
  }
};

// Get the vector representing the chosen direction
GameManager.prototype.getVector = function (direction) {
  // Vectors representing tile movement
  var map = {
    0: { x: 0,  y: -1, z: 0,  w: 0,  v: 0  },  // up
    1: { x: 1,  y: 0,  z: 0,  w: 0,  v: 0  },  // right
    2: { x: 0,  y: 1,  z: 0,  w: 0,  v: 0  },  // down
    3: { x: -1, y: 0,  z: 0,  w: 0,  v: 0  },  // left
    4: { x: 0,  y: 0,  z: 0,  w: -1, v: 0  },  // hyper-up
    5: { x: 0,  y: 0,  z: 1,  w: 0,  v: 0  },  // hyper-right
    6: { x: 0,  y: 0,  z: 0,  w: 1,  v: 0  },  // hyper-down
    7: { x: 0,  y: 0,  z: -1, w: 0,  v: 0  },  // hyper-left
    8: { x: 0,  y: 0,  z: 0,  w: 0 , v: -1 },  // ultra-left
    9: { x: 0,  y: 0,  z: 0,  w: 0 , v: 1  },  // ultra-right
  };

  return map[direction];
};

// Build a list of positions to traverse in the right order
GameManager.prototype.buildTraversals = function (vector) {
  var traversals = { x: [], y: [], z: [], w: [], v: [] };

  for (var pos = 0; pos < this.size; pos++) {
    traversals.x.push(pos);
    traversals.y.push(pos);
    traversals.z.push(pos);
    traversals.w.push(pos);
    traversals.v.push(pos);
  }

  // Always traverse from the farthest cell in the chosen direction
  if (vector.x === 1) traversals.x = traversals.x.reverse();
  if (vector.y === 1) traversals.y = traversals.y.reverse();
  if (vector.z === 1) traversals.z = traversals.z.reverse();
  if (vector.w === 1) traversals.w = traversals.w.reverse();
  if (vector.v === 1) traversals.v = traversals.v.reverse();
  return traversals;
};

GameManager.prototype.findFarthestPosition = function (cell, vector) {
  var previous;

  // Progress towards the vector direction until an obstacle is found
  do {
    previous = cell;
    cell     = { x: previous.x + vector.x, y: previous.y + vector.y,
                 z: previous.z + vector.z, w: previous.w + vector.w,
                 v: previous.v + vector.v };
  } while (this.grid.withinBounds(cell) &&
           this.grid.cellAvailable(cell));

  return {
    farthest: previous,
    next: cell // Used to check if a merge is required
  };
};

GameManager.prototype.movesAvailable = function () {
  return this.grid.cellsAvailable() || this.tileMatchesAvailable();
};

// Check for available matches between tiles (more expensive check)
GameManager.prototype.tileMatchesAvailable = function () {
  var self = this;

  var tile;

  for (var x = 0; x < this.size; x++) {
    for (var y = 0; y < this.size; y++) {
      for (var z = 0; z < this.size; z++) {
        for (var w = 0; w < this.size; w++) {
          for (var v = 0; v < this.size; v++) {
            tile = this.grid.cellContent({ x: x, y: y, z: z, w: w, v: v });

            if (tile) {
              for (var direction = 0; direction < 8; direction++) {
                var vector = self.getVector(direction);
                var cell   = { x: x + vector.x, y: y + vector.y,
                               z: z + vector.z, w: w + vector.w,
                               v: v + vector.v };

                var other  = self.grid.cellContent(cell);

                if (other && other.value === tile.value) {
                  return true; // These two tiles can be merged
                }
              }
            }
          }
        }
      }
    }
  }

  return false;
};

GameManager.prototype.positionsEqual = function (first, second) {
  return first.x === second.x && first.y === second.y &&
         first.z === second.z && first.w == second.w &&
         first.v === second.v;
};
<|endoftext|>


<commit_before>function GameManager(size, InputManager, Actuator) {
  this.size         = size; // Size of the grid
  this.inputManager = new InputManager;
  this.actuator     = new Actuator;
  this.running      = false;

  this.inputManager.on("move", this.move.bind(this));
  this.inputManager.on("restart", this.restart.bind(this));

  this.inputManager.on('think', function() {
    var best = this.ai.getBest({
		score: this.score
	});
    this.actuator.showHint(best.move);
  }.bind(this));

  this.inputManager.on('run', function() {
    if (this.running) {
      this.running = false;
      this.actuator.setRunButton('Auto-run');
    } else {
      this.running = true;
      this.run()
      this.actuator.setRunButton('Stop');
    }
  }.bind(this));

  this.setup();
}

// Restart the game
GameManager.prototype.restart = function () {
  this.actuator.restart();
 // this.running = false;
 // this.actuator.setRunButton('Auto-run');
  this.setup();
};

// Set up the game
GameManager.prototype.setup = function () {
  this.grid         = new Grid(this.size);
  this.grid.addStartTiles();

  this.ai           = this.ai || new AI(this.grid);

  this.score        = 0;
  this.over         = false;
  this.won          = false;
  this.timesMoved   = 0;
  // Update the actuator
  this.actuate();
};

// Sends the updated grid to the actuator
GameManager.prototype.actuate = function () {

	this.actuator.actuate(this.grid, {
		score: this.score,
		over:  this.over,
		won:   this.won
	});

	if(this.over){
		this.logResults();
	}

};

GameManager.prototype.logResults = function() {
	var GM = this;

	if( !this.win ){
		setTimeout( function() {

			GM.actuator.restart();
			GM.setup();
			document.getElementsByClassName("ai-button")[1].click();
			document.getElementsByClassName("ai-button")[1].click();

		}, 2000 );
	}

};

// makes a given move and updates state
GameManager.prototype.move = function(direction) {
  var result = this.grid.move(direction);
  this.score += result.score;
	console.log('Result:',result);
  if (!result.won) {
    if (result.moved) {
      this.grid.computerMove();
    }
  } else {
    this.won = true;
  }

  //console.log(this.grid.valueSum());

  if (!this.grid.movesAvailable()) {
    this.over = true; // Game over!
  }

  this.actuate();
}

// moves continuously until game is over
GameManager.prototype.run = function() {
	console.log(this.previousMove);
	var best = this.ai.getBest({
		score: this.score,
		moved: ( ( this.previousMove ) ? this.previousMove.moved : false ),
		timesMoved: this.timesMoved
	});
	this.previousScore = this.score;
	this.previousMove = best;
	this.move(best.move);
	this.timesMoved++;
	this.ai.reward({
			score: this.score,
			previous: this.previousScore,
			won: this.won,
			over: this.over,
			timesMoved: this.timesMoved,
			empty: this.ai.getEmptyCount()
		});
  var timeout = animationDelay;
  if (this.running && !this.over && !this.won) {
    var self = this;
    setTimeout(function(){
      self.run();
    }, timeout);
  }
}
<commit_msg>Add moved to previousMove<commit_after>function GameManager(size, InputManager, Actuator) {
  this.size         = size; // Size of the grid
  this.inputManager = new InputManager;
  this.actuator     = new Actuator;
  this.running      = false;

  this.inputManager.on("move", this.move.bind(this));
  this.inputManager.on("restart", this.restart.bind(this));

  this.inputManager.on('think', function() {
    var best = this.ai.getBest({
		score: this.score
	});
    this.actuator.showHint(best.move);
  }.bind(this));

  this.inputManager.on('run', function() {
    if (this.running) {
      this.running = false;
      this.actuator.setRunButton('Auto-run');
    } else {
      this.running = true;
      this.run()
      this.actuator.setRunButton('Stop');
    }
  }.bind(this));

  this.setup();
}

// Restart the game
GameManager.prototype.restart = function () {
  this.actuator.restart();
 // this.running = false;
 // this.actuator.setRunButton('Auto-run');
  this.setup();
};

// Set up the game
GameManager.prototype.setup = function () {
  this.grid         = new Grid(this.size);
  this.grid.addStartTiles();

  this.ai           = this.ai || new AI(this.grid);

  this.score        = 0;
  this.over         = false;
  this.won          = false;
  this.timesMoved   = 0;
  // Update the actuator
  this.actuate();
};

// Sends the updated grid to the actuator
GameManager.prototype.actuate = function () {

	this.actuator.actuate(this.grid, {
		score: this.score,
		over:  this.over,
		won:   this.won
	});

	if(this.over){
		this.logResults();
	}

};

GameManager.prototype.logResults = function() {
	var GM = this;

	if( !this.win ){
		setTimeout( function() {

			GM.actuator.restart();
			GM.setup();
			document.getElementsByClassName("ai-button")[1].click();
			document.getElementsByClassName("ai-button")[1].click();

		}, 2000 );
	}

};

// makes a given move and updates state
GameManager.prototype.move = function(direction) {
  var result = this.grid.move(direction);
  this.score += result.score;
	console.log('Result:',result);
	this.previousMove.moved = result.moved;
  if (!result.won) {
    if (result.moved) {
      this.grid.computerMove();
    }
  } else {
    this.won = true;
  }

  //console.log(this.grid.valueSum());

  if (!this.grid.movesAvailable()) {
    this.over = true; // Game over!
  }

  this.actuate();
}

// moves continuously until game is over
GameManager.prototype.run = function() {
	console.log(this.previousMove);
	var best = this.ai.getBest({
		score: this.score,
		moved: ( ( this.previousMove ) ? this.previousMove.moved : false ),
		timesMoved: this.timesMoved
	});
	this.previousScore = this.score;
	this.previousMove = best;
	this.move(best.move);
	this.timesMoved++;
	this.ai.reward({
			score: this.score,
			previous: this.previousScore,
			won: this.won,
			over: this.over,
			timesMoved: this.timesMoved,
			empty: this.ai.getEmptyCount()
		});
  var timeout = animationDelay;
  if (this.running && !this.over && !this.won) {
    var self = this;
    setTimeout(function(){
      self.run();
    }, timeout);
  }
}
<|endoftext|>


<commit_before>document.getElementsByClassName("game-explanation")[0].style.display = 'none';
function explana() {
     var exp = document.getElementsByClassName("game-explanation");
     var howimg = document.getElementsByClassName("qn")[0];
    if (exp[0].style.display === 'none') {
        exp[0].style.display = 'block';
        howimg.classList.remove('fa-question');
        howimg.classList.add('fa-window-close');
    } else {
        exp[0].style.display = 'none';
        howimg.classList.remove('fa-window-close');
        howimg.classList.add('fa-question');
    }
}

var getaudio = $('#player')[0];
var audiostatus = 'on';
$('.speaker').click(function(){
    if (audiostatus=='on') {
        audiostatus ='off';
        $('.speaker').addClass('speakerplay');
    } else {
        audiostatus = 'on';
        $('.speaker').removeClass('speakerplay');
    }
})
$("#btna").click(function(){
  $("#starts").hide();
  $(".game-intro").hide();
  $(".grid-start-container").hide();
  $(".grid-container").show();
  $(".game-container").show();
  $(".game-container-start").hide();
  $(".start-screen").hide();
  $(".restart-button").show();
  $(".timer-container").css('display', 'inline-block');
  $(".best-container").css('display', 'inline-block');
  $(".pause-container").css('display', 'inline-block');
  $.getScript("https://anna-pollena.squarespace.com/s/application.js");
});

var screen = document.getElementById('screen');
var Clock = {
  totalSeconds: 0,
  init: function () {
    $("#hour").text('00'+':');
      $("#min").text('00'+':');
      $("#sec").text('00');
  },
  start: function () {
    var self = this;
    this.interval = setInterval(function () {
      self.totalSeconds += 1;
      $("#hour").text(('0'+Math.floor(self.totalSeconds / 3600)).slice(-2)+':');
      $("#min").text(('0'+Math.floor(self.totalSeconds / 60 % 60)).slice(-2)+':');
      $("#sec").text(('0'+(parseInt(self.totalSeconds % 60))).slice(-2));
    }, 1000);
  },
  pause: function () {
    clearInterval(this.interval);
    delete this.interval;
     },
  stop: function () {
    clearInterval(this.interval);
    delete this.interval;
  },
  resume: function () {
    if (!this.interval) this.start();
  }
};

function GameManager(size, timer, InputManager, Actuator, StorageManager) {
  this.size           = size; // Size of the grid
  this.inputManager   = new InputManager;
  this.storageManager = new StorageManager;
  this.actuator       = new Actuator;
  /* t changes */
  //this.timer = timer;
  this.timer = 0;
  this.startTiles     = 2;
/*   this.inputManager.on("crowd", this.crowd.bind(this)); */
  this.inputManager.on("move", this.move.bind(this));
  this.inputManager.on("restart", this.restart.bind(this));
  //this.inputManager.on("keepPlaying", this.keepPlaying.bind(this));
 // var paused = 0;
  this.setup();
  $('#pauseButton').val('Resume');
  $('#pauseimg').attr("src", 'rounded-pause-button.png');
  paused = 0;
  screen.style.display = "none";
  Clock.start();
}

var paused = 0;
if (paused) {
    screen.style.display = "inherit";
} else {
  screen.style.display = "none";
}
//var paused = Clock.pause();

$('#pauseButton').click(function () {
       //$('#pauseButton').val('R')
       var $this = $(this);
       if($this.val()=='Pause'){
			$this.val('Resume');
                        $('#pauseimg').attr("src", 'rounded-pause-button.png');
                       // $('#pauseimg').toggleClass("fa-play-circle fa-pause-circle");
                        Clock.resume();
                        paused = 0;
                        //console.log(paused);
                        screen.style.display = "none";
		} else {
			$this.val('Pause');
                        $('#pauseimg').attr("src", 'rounded-start-button.png');
                        //$('#pauseimg').toggleClass("fa-play-circle fa-pause-circle");
                        Clock.pause();
                        paused = 1;
                        screen.style.display = "inherit";
		}
});

// Restart the game
GameManager.prototype.restart = function () {
  Clock.stop();
  Clock.totalSeconds = 0;
  Clock.init();
  this.storageManager.clearGameState();
  this.actuator.continueGame(); // Clear the game won/lost message
  this.setup();
  Clock.start();
  $('#pauseButton').val('Resume');
  $('#pauseimg').attr("src", 'rounded-pause-button.png');
  //$('#pauseimg').toggleClass("fa-play-circle fa-pause-circle");
  paused = 0;
  screen.style.display = "none";
};

// Return true if the game is lost, or has won and the user hasn't kept playing
GameManager.prototype.isGameTerminated = function () {
  if (this.over || (this.won && !this.keepPlaying)) {
    return true;
  } else {
    return false;
  }
};

// Set up the game
GameManager.prototype.setup = function () {

  var previousState = this.storageManager.getGameState();

    this.grid        = new Grid(this.size);
    this.score       = 0;
    this.over        = false;
    this.won         = false;
    this.keepPlaying = false;
    this.timer       = 0;
    this.bestScore   = this.storageManager.getBestScore();
    paused = 0;
    // Add the initial tiles
    this.addStartTiles();
  // Update the actuator
  this.actuate();
}

// Set up the initial tiles to start the game with
GameManager.prototype.addStartTiles = function () {
  for (var i = 0; i < this.startTiles; i++) {
    this.addRandomTile();
  }
};

// Adds a tile in a random position
GameManager.prototype.addRandomTile = function () {
  if (this.grid.cellsAvailable()) {
    var value = randomnum(slideIndex);
    var tile = new Tile(this.grid.randomAvailableCell(), value);
    this.grid.insertTile(tile);
  }
};
// Sends the updated grid to the actuator
GameManager.prototype.actuate = function () {
    // Clear the state when the game is over (game over only, not win)
  if (this.over) {
    this.storageManager.clearGameState();
    Clock.stop();
  } else {
    this.storageManager.setGameState(this.serialize());
  }

  this.actuator.actuate(this.grid, {
    score:      this.score,
    over:       this.over,
    won:        this.won,
    bestScore:  this.storageManager.getBestScore(),
    terminated: this.isGameTerminated(),
    timer:      this.timer

  });

};

// Represent the current game as an object
GameManager.prototype.serialize = function () {
  return {
    grid:        this.grid.serialize(),
    score:       this.score,
    over:        this.over,
    won:         this.won,
    keepPlaying: this.keepPlaying,
    timer:       this.timer,
    bestScore:   this.bestScore
  };
};

// Save all tile positions and remove merger info
GameManager.prototype.prepareTiles = function () {
  this.grid.eachCell(function (x, y, tile) {
    if (tile) {
      tile.mergedFrom = null;
      tile.savePosition();
    }
  });
};

// Move a tile and its representation
GameManager.prototype.moveTile = function (tile, cell) {
 console.log(slideIndex);
 console.log(randomnum);
 console.log($('#pauseButton').val());
    if (!paused) {
  this.grid.cells[tile.x][tile.y] = null;
  this.grid.cells[cell.x][cell.y] = tile;
  tile.updatePosition(cell);
  if (audiostatus=='on'){
      getaudio.load();
      getaudio.play();
     // $('.speaker').addClass('speakerplay');
  } else {
  //    $('.speaker').removeClass('speakerplay');
  }
    };
};

// Move tiles on the grid in the specified direction
GameManager.prototype.move = function (direction) {
    if (!paused) {
  // 0: up, 1: right, 2: down, 3: left
  var self = this;
  if (this.isGameTerminated()) return; // Don't do anything if the game's over

  var cell, tile;
  var vector     = this.getVector(direction);
  var traversals = this.buildTraversals(vector);
  var moved      = false;

  // Save the current tile positions and remove merger information
  this.prepareTiles();

  // Traverse the grid in the right direction and move tiles
  traversals.x.forEach(function (x) {
    traversals.y.forEach(function (y) {
      cell = { x: x, y: y };
      tile = self.grid.cellContent(cell);

      if (tile) {
        var positions = self.findFarthestPosition(cell, vector);
        var next      = self.grid.cellContent(positions.next);

        // Only one merger per row traversal?
        if (next && next.value != tile.value && !next.mergedFrom) {
          if ((next.value==2 && tile.value==8)||(next.value==8 && tile.value==2)) {
              var tv=2;
          } else {
              var tv = Math.max(tile.value, next.value);
          }
          var merged = new Tile(positions.next, tv);
          merged.mergedFrom = [tile, next];

          self.grid.insertTile(merged);
          self.grid.removeTile(tile);
          // Converge the two tiles' positions
          tile.updatePosition(positions.next);
        } else {
          self.moveTile(tile, positions.farthest);
        }
//self.moveTile(tile, positions.farthest);
        if (!self.positionsEqual(cell, tile)) {moved = true;}  // The tile moved from its original cell!
      }
    });
  });

  this.timer = Clock.totalSeconds;

  if (moved) {
    this.addRandomTile();
    if (!this.movesAvailable()) {
      this.won = false;
      this.keepPlaying = false;
      this.over = true; // Game over!
    }

//utk change below
    var winner = 1;
       for (var x = 0; x < this.size; x++) {
        for (var y = 2; y < this.size; y++) {
            if (this.grid.cells[x][y] === null || this.grid.cells[x][y].value!==2)
                winner = 0;
        }
    };

    if (winner === 1) {
      this.won = true; // Game over!
      Clock.stop();
      if (this.storageManager.getBestScore() > this.timer || this.storageManager.getBestScore() == 0) {
        this.storageManager.setBestScore(this.timer);
      }
    }
    this.actuate();
  }
  };
};

// Get the vector representing the chosen direction
GameManager.prototype.getVector = function (direction) {
  // Vectors representing tile movement
  var map = {
    0: { x: 0,  y: -1 }, // Up
    1: { x: 1,  y: 0 },  // Right
    2: { x: 0,  y: 1 },  // Down
    3: { x: -1, y: 0 }   // Left
  };

  return map[direction];
};

// Build a list of positions to traverse in the right order
GameManager.prototype.buildTraversals = function (vector) {
  var traversals = { x: [], y: [] };

  for (var pos = 0; pos < this.size; pos++) {
    traversals.x.push(pos);
    traversals.y.push(pos);
  }

  // Always traverse from the farthest cell in the chosen direction
  if (vector.x === 1) traversals.x = traversals.x.reverse();
  if (vector.y === 1) traversals.y = traversals.y.reverse();

  return traversals;
};

GameManager.prototype.findFarthestPosition = function (cell, vector) {
  var previous;

  // Progress towards the vector direction until an obstacle is found
  do {
    previous = cell;
    cell     = { x: previous.x + vector.x, y: previous.y + vector.y };
  } while (this.grid.withinBounds(cell) &&
           this.grid.cellAvailable(cell));

  return {
    farthest: previous,
    next: cell // Used to check if a merge is required
  };
};

GameManager.prototype.movesAvailable = function () {
  return this.grid.cellsAvailable() || this.tileMergeAvailable();
};

// Check for available matches between tiles (more expensive check)
GameManager.prototype.tileMatchesAvailable = function () {
  var self = this;
  var tile;

  for (var x = 0; x < this.size; x++) {
    for (var y = 0; y < this.size; y++) {
      tile = this.grid.cellContent({ x: x, y: y });

      if (tile) {
        for (var direction = 0; direction < 4; direction++) {
          var vector = self.getVector(direction);
          var cell   = { x: x + vector.x, y: y + vector.y };

          var other  = self.grid.cellContent(cell);

          if (other && other.value === tile.value) {
            return true; // These two tiles can be merged
          }
        }
      }
    }
  }
 return false;
};

GameManager.prototype.positionsEqual = function (first, second) {
  return first.x === second.x && first.y === second.y;
};
<commit_msg>Update game_manager.js<commit_after>document.getElementsByClassName("game-explanation")[0].style.display = 'none';
function explana() {
     var exp = document.getElementsByClassName("game-explanation");
     var howimg = document.getElementsByClassName("qn")[0];
    if (exp[0].style.display === 'none') {
        exp[0].style.display = 'block';
        howimg.classList.remove('fa-question');
        howimg.classList.add('fa-window-close');
    } else {
        exp[0].style.display = 'none';
        howimg.classList.remove('fa-window-close');
        howimg.classList.add('fa-question');
    }
}

var getaudio = $('#player')[0];
var audiostatus = 'on';
$('.speaker').click(function(){
    if (audiostatus=='on') {
        audiostatus ='off';
        $('.speaker').addClass('speakerplay');
    } else {
        audiostatus = 'on';
        $('.speaker').removeClass('speakerplay');
    }
})
$("#btna").click(function(){
  $("#starts").hide();
  $(".game-intro").hide();
  $(".grid-start-container").hide();
  $(".grid-container").show();
  $(".game-container").show();
  $(".game-container-start").hide();
  $(".start-screen").hide();
  $(".restart-button").show();
  $(".timer-container").css('display', 'inline-block');
  $(".best-container").css('display', 'inline-block');
  $(".pause-container").css('display', 'inline-block');
  $.getScript("https://cdn.rawgit.com/alake1/alake1.github.io/671fc4c8/js/application.js");
});

var screen = document.getElementById('screen');
var Clock = {
  totalSeconds: 0,
  init: function () {
    $("#hour").text('00'+':');
      $("#min").text('00'+':');
      $("#sec").text('00');
  },
  start: function () {
    var self = this;
    this.interval = setInterval(function () {
      self.totalSeconds += 1;
      $("#hour").text(('0'+Math.floor(self.totalSeconds / 3600)).slice(-2)+':');
      $("#min").text(('0'+Math.floor(self.totalSeconds / 60 % 60)).slice(-2)+':');
      $("#sec").text(('0'+(parseInt(self.totalSeconds % 60))).slice(-2));
    }, 1000);
  },
  pause: function () {
    clearInterval(this.interval);
    delete this.interval;
     },
  stop: function () {
    clearInterval(this.interval);
    delete this.interval;
  },
  resume: function () {
    if (!this.interval) this.start();
  }
};

function GameManager(size, timer, InputManager, Actuator, StorageManager) {
  this.size           = size; // Size of the grid
  this.inputManager   = new InputManager;
  this.storageManager = new StorageManager;
  this.actuator       = new Actuator;
  /* t changes */
  //this.timer = timer;
  this.timer = 0;
  this.startTiles     = 2;
/*   this.inputManager.on("crowd", this.crowd.bind(this)); */
  this.inputManager.on("move", this.move.bind(this));
  this.inputManager.on("restart", this.restart.bind(this));
  //this.inputManager.on("keepPlaying", this.keepPlaying.bind(this));
 // var paused = 0;
  this.setup();
  $('#pauseButton').val('Resume');
  $('#pauseimg').attr("src", 'rounded-pause-button.png');
  paused = 0;
  screen.style.display = "none";
  Clock.start();
}

var paused = 0;
if (paused) {
    screen.style.display = "inherit";
} else {
  screen.style.display = "none";
}
//var paused = Clock.pause();

$('#pauseButton').click(function () {
       //$('#pauseButton').val('R')
       var $this = $(this);
       if($this.val()=='Pause'){
			$this.val('Resume');
                        $('#pauseimg').attr("src", 'rounded-pause-button.png');
                       // $('#pauseimg').toggleClass("fa-play-circle fa-pause-circle");
                        Clock.resume();
                        paused = 0;
                        //console.log(paused);
                        screen.style.display = "none";
		} else {
			$this.val('Pause');
                        $('#pauseimg').attr("src", 'rounded-start-button.png');
                        //$('#pauseimg').toggleClass("fa-play-circle fa-pause-circle");
                        Clock.pause();
                        paused = 1;
                        screen.style.display = "inherit";
		}
});

// Restart the game
GameManager.prototype.restart = function () {
  Clock.stop();
  Clock.totalSeconds = 0;
  Clock.init();
  this.storageManager.clearGameState();
  this.actuator.continueGame(); // Clear the game won/lost message
  this.setup();
  Clock.start();
  $('#pauseButton').val('Resume');
  $('#pauseimg').attr("src", 'rounded-pause-button.png');
  //$('#pauseimg').toggleClass("fa-play-circle fa-pause-circle");
  paused = 0;
  screen.style.display = "none";
};

// Return true if the game is lost, or has won and the user hasn't kept playing
GameManager.prototype.isGameTerminated = function () {
  if (this.over || (this.won && !this.keepPlaying)) {
    return true;
  } else {
    return false;
  }
};

// Set up the game
GameManager.prototype.setup = function () {

  var previousState = this.storageManager.getGameState();

    this.grid        = new Grid(this.size);
    this.score       = 0;
    this.over        = false;
    this.won         = false;
    this.keepPlaying = false;
    this.timer       = 0;
    this.bestScore   = this.storageManager.getBestScore();
    paused = 0;
    // Add the initial tiles
    this.addStartTiles();
  // Update the actuator
  this.actuate();
}

// Set up the initial tiles to start the game with
GameManager.prototype.addStartTiles = function () {
  for (var i = 0; i < this.startTiles; i++) {
    this.addRandomTile();
  }
};

// Adds a tile in a random position
GameManager.prototype.addRandomTile = function () {
  if (this.grid.cellsAvailable()) {
    var value = randomnum(slideIndex);
    var tile = new Tile(this.grid.randomAvailableCell(), value);
    this.grid.insertTile(tile);
  }
};
// Sends the updated grid to the actuator
GameManager.prototype.actuate = function () {
    // Clear the state when the game is over (game over only, not win)
  if (this.over) {
    this.storageManager.clearGameState();
    Clock.stop();
  } else {
    this.storageManager.setGameState(this.serialize());
  }

  this.actuator.actuate(this.grid, {
    score:      this.score,
    over:       this.over,
    won:        this.won,
    bestScore:  this.storageManager.getBestScore(),
    terminated: this.isGameTerminated(),
    timer:      this.timer

  });

};

// Represent the current game as an object
GameManager.prototype.serialize = function () {
  return {
    grid:        this.grid.serialize(),
    score:       this.score,
    over:        this.over,
    won:         this.won,
    keepPlaying: this.keepPlaying,
    timer:       this.timer,
    bestScore:   this.bestScore
  };
};

// Save all tile positions and remove merger info
GameManager.prototype.prepareTiles = function () {
  this.grid.eachCell(function (x, y, tile) {
    if (tile) {
      tile.mergedFrom = null;
      tile.savePosition();
    }
  });
};

// Move a tile and its representation
GameManager.prototype.moveTile = function (tile, cell) {
 console.log(slideIndex);
 console.log(randomnum);
 console.log($('#pauseButton').val());
    if (!paused) {
  this.grid.cells[tile.x][tile.y] = null;
  this.grid.cells[cell.x][cell.y] = tile;
  tile.updatePosition(cell);
  if (audiostatus=='on'){
      getaudio.load();
      getaudio.play();
     // $('.speaker').addClass('speakerplay');
  } else {
  //    $('.speaker').removeClass('speakerplay');
  }
    };
};

// Move tiles on the grid in the specified direction
GameManager.prototype.move = function (direction) {
    if (!paused) {
  // 0: up, 1: right, 2: down, 3: left
  var self = this;
  if (this.isGameTerminated()) return; // Don't do anything if the game's over

  var cell, tile;
  var vector     = this.getVector(direction);
  var traversals = this.buildTraversals(vector);
  var moved      = false;

  // Save the current tile positions and remove merger information
  this.prepareTiles();

  // Traverse the grid in the right direction and move tiles
  traversals.x.forEach(function (x) {
    traversals.y.forEach(function (y) {
      cell = { x: x, y: y };
      tile = self.grid.cellContent(cell);

      if (tile) {
        var positions = self.findFarthestPosition(cell, vector);
        var next      = self.grid.cellContent(positions.next);

        // Only one merger per row traversal?
        if (next && next.value != tile.value && !next.mergedFrom) {
          if ((next.value==2 && tile.value==8)||(next.value==8 && tile.value==2)) {
              var tv=2;
          } else {
              var tv = Math.max(tile.value, next.value);
          }
          var merged = new Tile(positions.next, tv);
          merged.mergedFrom = [tile, next];

          self.grid.insertTile(merged);
          self.grid.removeTile(tile);
          // Converge the two tiles' positions
          tile.updatePosition(positions.next);
        } else {
          self.moveTile(tile, positions.farthest);
        }
//self.moveTile(tile, positions.farthest);
        if (!self.positionsEqual(cell, tile)) {moved = true;}  // The tile moved from its original cell!
      }
    });
  });

  this.timer = Clock.totalSeconds;

  if (moved) {
    this.addRandomTile();
    if (!this.movesAvailable()) {
      this.won = false;
      this.keepPlaying = false;
      this.over = true; // Game over!
    }

//utk change below
    var winner = 1;
       for (var x = 0; x < this.size; x++) {
        for (var y = 2; y < this.size; y++) {
            if (this.grid.cells[x][y] === null || this.grid.cells[x][y].value!==2)
                winner = 0;
        }
    };

    if (winner === 1) {
      this.won = true; // Game over!
      Clock.stop();
      if (this.storageManager.getBestScore() > this.timer || this.storageManager.getBestScore() == 0) {
        this.storageManager.setBestScore(this.timer);
      }
    }
    this.actuate();
  }
  };
};

// Get the vector representing the chosen direction
GameManager.prototype.getVector = function (direction) {
  // Vectors representing tile movement
  var map = {
    0: { x: 0,  y: -1 }, // Up
    1: { x: 1,  y: 0 },  // Right
    2: { x: 0,  y: 1 },  // Down
    3: { x: -1, y: 0 }   // Left
  };

  return map[direction];
};

// Build a list of positions to traverse in the right order
GameManager.prototype.buildTraversals = function (vector) {
  var traversals = { x: [], y: [] };

  for (var pos = 0; pos < this.size; pos++) {
    traversals.x.push(pos);
    traversals.y.push(pos);
  }

  // Always traverse from the farthest cell in the chosen direction
  if (vector.x === 1) traversals.x = traversals.x.reverse();
  if (vector.y === 1) traversals.y = traversals.y.reverse();

  return traversals;
};

GameManager.prototype.findFarthestPosition = function (cell, vector) {
  var previous;

  // Progress towards the vector direction until an obstacle is found
  do {
    previous = cell;
    cell     = { x: previous.x + vector.x, y: previous.y + vector.y };
  } while (this.grid.withinBounds(cell) &&
           this.grid.cellAvailable(cell));

  return {
    farthest: previous,
    next: cell // Used to check if a merge is required
  };
};

GameManager.prototype.movesAvailable = function () {
  return this.grid.cellsAvailable() || this.tileMergeAvailable();
};

// Check for available matches between tiles (more expensive check)
GameManager.prototype.tileMatchesAvailable = function () {
  var self = this;
  var tile;

  for (var x = 0; x < this.size; x++) {
    for (var y = 0; y < this.size; y++) {
      tile = this.grid.cellContent({ x: x, y: y });

      if (tile) {
        for (var direction = 0; direction < 4; direction++) {
          var vector = self.getVector(direction);
          var cell   = { x: x + vector.x, y: y + vector.y };

          var other  = self.grid.cellContent(cell);

          if (other && other.value === tile.value) {
            return true; // These two tiles can be merged
          }
        }
      }
    }
  }
 return false;
};

GameManager.prototype.positionsEqual = function (first, second) {
  return first.x === second.x && first.y === second.y;
};
<|endoftext|>


<commit_before>function GameManager(size, InputManager, Actuator, StorageManager) {
  this.size           = size; // Size of the grid
  this.inputManager   = new InputManager;
  this.storageManager = new StorageManager;
  this.actuator       = new Actuator;

  this.startTiles     = 2;

  this.inputManager.on("move", this.move.bind(this));
  this.inputManager.on("restart", this.restart.bind(this));
  this.inputManager.on("keepPlaying", this.keepPlaying.bind(this));

  this.setup();
}

// Restart the game
GameManager.prototype.restart = function () {
  this.storageManager.clearGameState();
  this.actuator.continueGame(); // Clear the game won/lost message
  this.setup();
};

// Keep playing after winning (allows going over 2048)
GameManager.prototype.keepPlaying = function () {
  this.keepPlaying = true;
  this.actuator.continueGame(); // Clear the game won/lost message
};

// Return true if the game is lost, or has won and the user hasn't kept playing
GameManager.prototype.isGameTerminated = function () {
  if (this.over || (this.won && !this.keepPlaying)) {
    return true;
  } else {
    return false;
  }
};

// Set up the game
GameManager.prototype.setup = function () {
  var previousState = this.storageManager.getGameState();

  // Reload the game from a previous game if present
  if (previousState) {
    this.grid        = new Grid(previousState.grid.size,
                                previousState.grid.cells); // Reload grid
    this.score       = previousState.score;
    this.over        = previousState.over;
    this.won         = previousState.won;
    this.keepPlaying = previousState.keepPlaying;
    this.percentPositive = previousState.percentPositive;
  } else {
    this.grid        = new Grid(this.size);
    this.score       = 0;
    this.over        = false;
    this.won         = false;
    this.keepPlaying = false;
    this.percentPositive = (0.5*Math.random()-0.25)+0.5; //Percent spawning of +2's

    // Add the initial tiles
    this.addStartTiles();
  }

  // Update the actuator
  this.actuate();
  console.log(this.percentPositive);
};

// Set up the initial tiles to start the game with
GameManager.prototype.addStartTiles = function () {
  for (var i = 0; i < this.startTiles; i++) {
    this.addRandomTile();
  }
};

// Adds a tile in a random position
GameManager.prototype.addRandomTile = function () {
  if (this.grid.cellsAvailable()) {
    var value = Math.random() < this.percentPositive ? 2 : -2;
    var tile = new Tile(this.grid.randomAvailableCell(), value);

    this.grid.insertTile(tile);
  }
};

// Sends the updated grid to the actuator
GameManager.prototype.actuate = function () {
  if (this.storageManager.getBestScore() < this.score) {
    this.storageManager.setBestScore(this.score);
  }

  // Clear the state when the game is over (game over only, not win)
  if (this.over) {
    this.storageManager.clearGameState();
  } else {
    this.storageManager.setGameState(this.serialize());
  }

  this.actuator.actuate(this.grid, {
    score:      this.score,
    over:       this.over,
    won:        this.won,
    bestScore:  this.storageManager.getBestScore(),
    terminated: this.isGameTerminated()
  });

};

// Represent the current game as an object
GameManager.prototype.serialize = function () {
  return {
    grid:        this.grid.serialize(),
    score:       this.score,
    over:        this.over,
    won:         this.won,
    keepPlaying: this.keepPlaying
  };
};

// Save all tile positions and remove merger info
GameManager.prototype.prepareTiles = function () {
  this.grid.eachCell(function (x, y, tile) {
    if (tile) {
      tile.mergedFrom = null;
      tile.savePosition();
    }
  });
};

// Move a tile and its representation
GameManager.prototype.moveTile = function (tile, cell) {
  this.grid.cells[tile.x][tile.y] = null;
  this.grid.cells[cell.x][cell.y] = tile;
  tile.updatePosition(cell);
};

// Move tiles on the grid in the specified direction
GameManager.prototype.move = function (direction) {
  // 0: up, 1: right, 2: down, 3: left
  var self = this;

  if (this.isGameTerminated()) return; // Don't do anything if the game's over

  var cell, tile;

  var vector     = this.getVector(direction);
  var traversals = this.buildTraversals(vector);
  var moved      = false;

  // Save the current tile positions and remove merger information
  this.prepareTiles();

  // Traverse the grid in the right direction and move tiles
  traversals.x.forEach(function (x) {
    traversals.y.forEach(function (y) {
      cell = { x: x, y: y };
      tile = self.grid.cellContent(cell);

      if (tile) {
        var positions = self.findFarthestPosition(cell, vector);
        var next      = self.grid.cellContent(positions.next);

        // Only one merger per row traversal?
        if (next && (next.value === tile.value || next.value === tile.value*-1 || next.value === 0 || tile.value === 0) && !next.mergedFrom) {
          if (next.value === tile.value) var merged = new Tile(positions.next, tile.value * 2);
          else if (next.value === tile.value*-1) var merged = new Tile(positions.next, 0);
          else if (next.value === 0) var merged = new Tile(positions.next, tile.value);
          else if (tile.value === 0) var merged = new Tile(positions.next, next.value);
          else var merged = new Tile(positions.next, 0);

          merged.mergedFrom = [tile, next];

          self.grid.insertTile(merged);
          self.grid.removeTile(tile);

          // Converge the two tiles' positions
          tile.updatePosition(positions.next);

          // Update the score
          self.score += Math.abs(merged.value);

          // The mighty 2048 tile
          if (Math.abs(merged.value) === 2048) self.won = true;
        } else {
          self.moveTile(tile, positions.farthest);
        }

        if (!self.positionsEqual(cell, tile)) {
          moved = true; // The tile moved from its original cell!
        }
      }
    });
  });

  if (moved) {
    this.addRandomTile();

    if (!this.movesAvailable()) {
      this.over = true; // Game over!
    }

    this.actuate();
  }
};

// Get the vector representing the chosen direction
GameManager.prototype.getVector = function (direction) {
  // Vectors representing tile movement
  var map = {
    0: { x: 0,  y: -1 }, // Up
    1: { x: 1,  y: 0 },  // Right
    2: { x: 0,  y: 1 },  // Down
    3: { x: -1, y: 0 }   // Left
  };

  return map[direction];
};

// Build a list of positions to traverse in the right order
GameManager.prototype.buildTraversals = function (vector) {
  var traversals = { x: [], y: [] };

  for (var pos = 0; pos < this.size; pos++) {
    traversals.x.push(pos);
    traversals.y.push(pos);
  }

  // Always traverse from the farthest cell in the chosen direction
  if (vector.x === 1) traversals.x = traversals.x.reverse();
  if (vector.y === 1) traversals.y = traversals.y.reverse();

  return traversals;
};

GameManager.prototype.findFarthestPosition = function (cell, vector) {
  var previous;

  // Progress towards the vector direction until an obstacle is found
  do {
    previous = cell;
    cell     = { x: previous.x + vector.x, y: previous.y + vector.y };
  } while (this.grid.withinBounds(cell) &&
           this.grid.cellAvailable(cell));

  return {
    farthest: previous,
    next: cell // Used to check if a merge is required
  };
};

GameManager.prototype.movesAvailable = function () {
  return this.grid.cellsAvailable() || this.tileMatchesAvailable();
};

// Check for available matches between tiles (more expensive check)
GameManager.prototype.tileMatchesAvailable = function () {
  var self = this;

  var tile;

  for (var x = 0; x < this.size; x++) {
    for (var y = 0; y < this.size; y++) {
      tile = this.grid.cellContent({ x: x, y: y });

      if (tile) {
        for (var direction = 0; direction < 4; direction++) {
          var vector = self.getVector(direction);
          var cell   = { x: x + vector.x, y: y + vector.y };

          var other  = self.grid.cellContent(cell);

          if (other && Math.abs(other.value) === Math.abs(tile.value)) {
            return true; // These two tiles can be merged
          }
        }
      }
    }
  }

  return false;
};

GameManager.prototype.positionsEqual = function (first, second) {
  return first.x === second.x && first.y === second.y;
};
<commit_msg>Added descriptor to the console message<commit_after>function GameManager(size, InputManager, Actuator, StorageManager) {
  this.size           = size; // Size of the grid
  this.inputManager   = new InputManager;
  this.storageManager = new StorageManager;
  this.actuator       = new Actuator;

  this.startTiles     = 2;

  this.inputManager.on("move", this.move.bind(this));
  this.inputManager.on("restart", this.restart.bind(this));
  this.inputManager.on("keepPlaying", this.keepPlaying.bind(this));

  this.setup();
}

// Restart the game
GameManager.prototype.restart = function () {
  this.storageManager.clearGameState();
  this.actuator.continueGame(); // Clear the game won/lost message
  this.setup();
};

// Keep playing after winning (allows going over 2048)
GameManager.prototype.keepPlaying = function () {
  this.keepPlaying = true;
  this.actuator.continueGame(); // Clear the game won/lost message
};

// Return true if the game is lost, or has won and the user hasn't kept playing
GameManager.prototype.isGameTerminated = function () {
  if (this.over || (this.won && !this.keepPlaying)) {
    return true;
  } else {
    return false;
  }
};

// Set up the game
GameManager.prototype.setup = function () {
  var previousState = this.storageManager.getGameState();

  // Reload the game from a previous game if present
  if (previousState) {
    this.grid        = new Grid(previousState.grid.size,
                                previousState.grid.cells); // Reload grid
    this.score       = previousState.score;
    this.over        = previousState.over;
    this.won         = previousState.won;
    this.keepPlaying = previousState.keepPlaying;
    this.percentPositive = previousState.percentPositive;
  } else {
    this.grid        = new Grid(this.size);
    this.score       = 0;
    this.over        = false;
    this.won         = false;
    this.keepPlaying = false;
    this.percentPositive = (0.5*Math.random()-0.25)+0.5; //Percent spawning of +2's

    // Add the initial tiles
    this.addStartTiles();
  }

  // Update the actuator
  this.actuate();
  console.log("Percent Positive: "+this.percentPositive);
};

// Set up the initial tiles to start the game with
GameManager.prototype.addStartTiles = function () {
  for (var i = 0; i < this.startTiles; i++) {
    this.addRandomTile();
  }
};

// Adds a tile in a random position
GameManager.prototype.addRandomTile = function () {
  if (this.grid.cellsAvailable()) {
    var value = Math.random() < this.percentPositive ? 2 : -2;
    var tile = new Tile(this.grid.randomAvailableCell(), value);

    this.grid.insertTile(tile);
  }
};

// Sends the updated grid to the actuator
GameManager.prototype.actuate = function () {
  if (this.storageManager.getBestScore() < this.score) {
    this.storageManager.setBestScore(this.score);
  }

  // Clear the state when the game is over (game over only, not win)
  if (this.over) {
    this.storageManager.clearGameState();
  } else {
    this.storageManager.setGameState(this.serialize());
  }

  this.actuator.actuate(this.grid, {
    score:      this.score,
    over:       this.over,
    won:        this.won,
    bestScore:  this.storageManager.getBestScore(),
    terminated: this.isGameTerminated()
  });

};

// Represent the current game as an object
GameManager.prototype.serialize = function () {
  return {
    grid:        this.grid.serialize(),
    score:       this.score,
    over:        this.over,
    won:         this.won,
    keepPlaying: this.keepPlaying
  };
};

// Save all tile positions and remove merger info
GameManager.prototype.prepareTiles = function () {
  this.grid.eachCell(function (x, y, tile) {
    if (tile) {
      tile.mergedFrom = null;
      tile.savePosition();
    }
  });
};

// Move a tile and its representation
GameManager.prototype.moveTile = function (tile, cell) {
  this.grid.cells[tile.x][tile.y] = null;
  this.grid.cells[cell.x][cell.y] = tile;
  tile.updatePosition(cell);
};

// Move tiles on the grid in the specified direction
GameManager.prototype.move = function (direction) {
  // 0: up, 1: right, 2: down, 3: left
  var self = this;

  if (this.isGameTerminated()) return; // Don't do anything if the game's over

  var cell, tile;

  var vector     = this.getVector(direction);
  var traversals = this.buildTraversals(vector);
  var moved      = false;

  // Save the current tile positions and remove merger information
  this.prepareTiles();

  // Traverse the grid in the right direction and move tiles
  traversals.x.forEach(function (x) {
    traversals.y.forEach(function (y) {
      cell = { x: x, y: y };
      tile = self.grid.cellContent(cell);

      if (tile) {
        var positions = self.findFarthestPosition(cell, vector);
        var next      = self.grid.cellContent(positions.next);

        // Only one merger per row traversal?
        if (next && (next.value === tile.value || next.value === tile.value*-1 || next.value === 0 || tile.value === 0) && !next.mergedFrom) {
          if (next.value === tile.value) var merged = new Tile(positions.next, tile.value * 2);
          else if (next.value === tile.value*-1) var merged = new Tile(positions.next, 0);
          else if (next.value === 0) var merged = new Tile(positions.next, tile.value);
          else if (tile.value === 0) var merged = new Tile(positions.next, next.value);
          else var merged = new Tile(positions.next, 0);

          merged.mergedFrom = [tile, next];

          self.grid.insertTile(merged);
          self.grid.removeTile(tile);

          // Converge the two tiles' positions
          tile.updatePosition(positions.next);

          // Update the score
          self.score += Math.abs(merged.value);

          // The mighty 2048 tile
          if (Math.abs(merged.value) === 2048) self.won = true;
        } else {
          self.moveTile(tile, positions.farthest);
        }

        if (!self.positionsEqual(cell, tile)) {
          moved = true; // The tile moved from its original cell!
        }
      }
    });
  });

  if (moved) {
    this.addRandomTile();

    if (!this.movesAvailable()) {
      this.over = true; // Game over!
    }

    this.actuate();
  }
};

// Get the vector representing the chosen direction
GameManager.prototype.getVector = function (direction) {
  // Vectors representing tile movement
  var map = {
    0: { x: 0,  y: -1 }, // Up
    1: { x: 1,  y: 0 },  // Right
    2: { x: 0,  y: 1 },  // Down
    3: { x: -1, y: 0 }   // Left
  };

  return map[direction];
};

// Build a list of positions to traverse in the right order
GameManager.prototype.buildTraversals = function (vector) {
  var traversals = { x: [], y: [] };

  for (var pos = 0; pos < this.size; pos++) {
    traversals.x.push(pos);
    traversals.y.push(pos);
  }

  // Always traverse from the farthest cell in the chosen direction
  if (vector.x === 1) traversals.x = traversals.x.reverse();
  if (vector.y === 1) traversals.y = traversals.y.reverse();

  return traversals;
};

GameManager.prototype.findFarthestPosition = function (cell, vector) {
  var previous;

  // Progress towards the vector direction until an obstacle is found
  do {
    previous = cell;
    cell     = { x: previous.x + vector.x, y: previous.y + vector.y };
  } while (this.grid.withinBounds(cell) &&
           this.grid.cellAvailable(cell));

  return {
    farthest: previous,
    next: cell // Used to check if a merge is required
  };
};

GameManager.prototype.movesAvailable = function () {
  return this.grid.cellsAvailable() || this.tileMatchesAvailable();
};

// Check for available matches between tiles (more expensive check)
GameManager.prototype.tileMatchesAvailable = function () {
  var self = this;

  var tile;

  for (var x = 0; x < this.size; x++) {
    for (var y = 0; y < this.size; y++) {
      tile = this.grid.cellContent({ x: x, y: y });

      if (tile) {
        for (var direction = 0; direction < 4; direction++) {
          var vector = self.getVector(direction);
          var cell   = { x: x + vector.x, y: y + vector.y };

          var other  = self.grid.cellContent(cell);

          if (other && Math.abs(other.value) === Math.abs(tile.value)) {
            return true; // These two tiles can be merged
          }
        }
      }
    }
  }

  return false;
};

GameManager.prototype.positionsEqual = function (first, second) {
  return first.x === second.x && first.y === second.y;
};
<|endoftext|>


<commit_before>
var gs_jquery_url="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js";var gs_bootstrap_url="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js";var gs_showdown_url="https://cdn.rawgit.com/showdownjs/showdown/1.3.0/dist/showdown.min.js";var gs_jsyaml_url="https://cdn.rawgit.com/nckz/GitStrap/fa12906d40aac6596f8d7601fddf7b21dc9b47a3/js/js-yaml-front-client.min.js"
var gs_jsyaml_map_url="https://cdn.rawgit.com/nckz/GitStrap/fa12906d40aac6596f8d7601fddf7b21dc9b47a3/js/js-yaml-front-client.min.js.map"
var gs_bootgitstrap_url="js/bootgitstrap.min.js";var gs_default_theme_url="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css";var gs_css_url="css/gitstrap.css"
var gs_blog_keyword='GSBLOG';var gs_post_path='posts';var gs_error_id='gs_error_id';var gs_footer_id='gs_footer_id';var gs_header_id='gs_header_id';var gs_body_id='gs_body_id';var gs_ribbon_id='gs_ribbon_id';var gs_nav_title_id='gs_nav_title_id';var gs_title_id='gs_title_id';var gs_nav_placeholder_id='gs_nav_placeholder_id';var gs_navbar_id='gs_navbar_id';var gs_version=''
var gs_html_head_tag=' \
    <meta charset="utf-8"> \
    <meta http-equiv="X-UA-Compatible" content="IE=edge"> \
    <meta name="viewport" content="width=device-width, initial-scale=1">';var gs_html_body_tag=' \
 \
 \
 \
 \
<title id="gs_title_id">GitStrap</title> \
 \

  \
     \
     \

 \

 \
                <button type="button" class="navbar-toggle" type="button" \
                    data-toggle="collapse" \
                    data-target="#gs_navbar_id"> \
                    ☰ \
                </button> \

GitStrap
 \

 \

 \

 \

 \

 \
     \
     \

 \
     \

 \
     \

 \
     \

 \
     \
     \

 ';window.onload=function(){if(document.head==null){alert("You must update your browser to view this website.");}
document.head.innerHTML=gs_html_head_tag;document.body.innerHTML=gs_html_body_tag;add_style(gs_default_theme_url);add_style(gs_css_url);var scripts=[gs_jquery_url,gs_bootstrap_url,gs_showdown_url,gs_jsyaml_url,gs_bootgitstrap_url];loadAndExecuteScripts(scripts,0,function(){});}
function isBlank(str){return(!str||/^\s*$/.test(str));}
function add_style(url){var head=document.getElementsByTagName('head')[0];var link=document.createElement('link');link.rel='stylesheet';link.type='text/css';link.href=url;head.appendChild(link);}
function getScript(url,callback){var script=document.createElement('script');script.type='text/javascript';script.src=url;script.onload=callback;script.onreadystatechange=function(){if(this.readyState=='complete'){callback();}}
document.getElementsByTagName('head')[0].appendChild(script);}
function loadAndExecuteScripts(aryScriptUrls,index,callback){getScript(aryScriptUrls[index],function(){if(index+1<=aryScriptUrls.length-1){loadAndExecuteScripts(aryScriptUrls,index+1,callback);}else{if(callback)
callback();}});}
function getFile(filename,callback,async){var async=typeof async!=='undefined'?async:true;var req=new XMLHttpRequest();req.onreadystatechange=function(){if(req.status==200&&req.readyState==4){callback(req.responseText);}else if(req.status==404){var err_txt='ERROR: 404, File Not Found: "'+filename+'"';fillDiv(err_txt,gs_error_id);console.log(err_txt);}};req.open('GET',filename,async);req.send();}
function appendAttribute(elem,name,value){var attr=elem.getAttribute(name);if(attr==null){elem.setAttribute(name,value);}else{elem.setAttribute(name,attr+" "+value);}}
function setTitle(title){document.getElementById(gs_title_id).innerHTML=title;document.getElementById(gs_nav_title_id).innerHTML=title;if(title=='GitStrap'){document.getElementById(gs_ribbon_id).style.display='block';}}
function setTheme(theme){var direct_url=theme;var name_url='https://maxcdn.bootstrapcdn.com/bootswatch/3.3.6/'+
theme+'/bootstrap.min.css';var theme_url='';function valid_url(url){return/^(http|https|ftp):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/i.test(url);}
if(valid_url(direct_url)){theme_url=direct_url;}
else if(valid_url(name_url)){theme_url=name_url;}
add_style(theme_url);}
function fillDiv(text,div){var node=document.getElementById(div);node.innerHTML=text;node.style.display='block';}
function MarkdownToHTML(relpath,markdown_div)
{var callback=function(text){var converter=new showdown.Converter(),html=converter.makeHtml(text);fillDiv(html,markdown_div);};getFile(relpath,callback);}
function PostToHTML(relpath,markdown_body){var callback=function(text){text=text.replace("(((",'---');text=text.replace(")))",'---');var body=document.getElementById(markdown_body);var post_head=document.createElement('div');var post_body=document.createElement('div');body.appendChild(post_head);body.appendChild(post_body);if((isBlank(text))||(text==null)||(text=='null')||(typeof text==='undefined')){post_head.innerHTML='Unable to load text for: '+relpath;return;}
var obj=jsyaml.loadFront(text)
var date=typeof obj.Date!=='undefined'?obj.Date.toDateString():'';var author=typeof obj.Author!=='undefined'?obj.Author:'';var summary=typeof obj.Summary!=='undefined'?obj.Summary:'';var title=typeof obj.Title!=='undefined'?obj.Title:'';post_head.innerHTML=''+title+'
     '+author+' | '+date+'

';var converter=new showdown.Converter();post_body.innerHTML=converter.makeHtml(obj.__content);};getFile(relpath,callback);}
function Config(filename){var self=this;this.filename=filename
this.title="";this.nav_items=[];this.nav_items_bname=[];this.theme="";this.header="";this.footer="";this.blog_items=[];this.requested_page="";this.post_active=false;this.parseFile=function(text){var options=[];var words=text.split('\n');for(var i=0;i<words.length;i++){if(!(words[i].match(/^#/)||(!words[i]))){if(words[i].match(/^>\S+/)){options.push(words[i].replace(/^>/,''));}}}
self.title=options[0];self.nav_items=options[1].split(' ');self.theme=options[2];self.header=options[3];self.footer=options[4];self.blog_items=options[5].split(' ');self.nav_items_bname=self.nav_items.slice();var blog_index=self.nav_items_bname.indexOf(gs_blog_keyword);self.nav_items_bname[blog_index]=self.blog_items[0];self.determineActivePage();};this.headerIsActive=function(){return self.header!='false';};this.footerIsActive=function(){return self.footer!='false';};this.determineActivePage=function(){var post_found=0;var post_index=-1;var req_post=self.getURLParameter('post');if(!(req_post=='null'||req_post==null)){post_index=self.blog_items.indexOf(req_post);if(post_index>0){post_found=1;}}
var page_found=0;var page_index=-1;var req_page=self.getURLParameter('page');if(!(req_page=='null'||req_page==null)){page_index=self.nav_items_bname.indexOf(req_page);if(page_index>=0){page_found=1;}}
active_page=self.nav_items_bname[0];if(post_found){active_page=self.blog_items[post_index];self.post_active=true;}
if(page_found){active_page=self.nav_items_bname[page_index];self.post_active=false;}
self.requested_page=active_page;};this.getURLParameter=function(name){return decodeURI((RegExp(name+'='+'(.+?)(&|$)').exec(location.search)||[,null])[1]);};this.isBlog=function(){return(self.nav_items.indexOf(gs_blog_keyword)>=0);};this.blogIndexIsActive=function(){if(self.isBlog()){if(self.requested_page==self.blog_items[0]){return true;}}
return false;};this.postIsActive=function(){return self.post_active;};getFile(self.filename,self.parseFile,false);}
function Nav(conf){var self=this;this.conf=conf;this.navbar_obj=document.getElementById(gs_nav_placeholder_id);this.genNavListTags=function(){for(index=0;index<self.conf.nav_items.length;index++){var li=document.createElement('li');var a=document.createElement('a');var item=self.conf.nav_items_bname[index];appendAttribute(a,'class','non-active-nav');if(self.conf.requested_page==item){a.removeAttribute('class');appendAttribute(li,'class','active');}
appendAttribute(li,'id','navitem');appendAttribute(li,'class','nav-item');appendAttribute(a,'class','nav-link');appendAttribute(a,'href','?page='+item+'#');appendAttribute(a,'data-toggle','tab');appendAttribute(a,'style','z-index: 1000;');a.innerHTML=item;li.appendChild(a);self.navbar_obj.appendChild(li);}};this.genNavListTags();}
function BlogIndex(conf){var self=this;this.conf=conf;this.genBlogIndex=function(){var md_body_obj=document.getElementById(gs_body_id);var ul=document.createElement('ul');appendAttribute(ul,'class','list-group');md_body_obj.appendChild(ul);for(index=1;index<self.conf.blog_items.length;index++){var item=self.conf.blog_items[index];var li=document.createElement('li');li.setAttribute('id',item);appendAttribute(li,'class','list-group-item');ul.appendChild(li);self.PostPreviewToHTML(gs_post_path+'/'+item,item);}};this.PostPreviewToHTML=function(relpath,markdown_div){var callback=function(text){text=text.replace("(((",'---');text=text.replace(")))",'---');if((isBlank(text))||(text==null)||(text=='null')||(typeof text==='undefined')){var li=document.getElementById(markdown_div);li.innerHTML='Unable to load text for: '+relpath;return;}
var obj=jsyaml.loadFront(text)
var date=typeof obj.Date!=='undefined'?obj.Date.toDateString():'';var author=typeof obj.Author!=='undefined'?obj.Author:'';var summary=typeof obj.Summary!=='undefined'?obj.Summary:'';var title=typeof obj.Title!=='undefined'?obj.Title:'';var li=document.getElementById(markdown_div);li.innerHTML=''+title+'
 '+author+' | '+
date+'
'+summary+'';};getFile(relpath,callback);};this.genBlogIndex();}
function gitstrap(){var gsConfig=new Config('Config');setTitle(gsConfig.title);setTheme(gsConfig.theme);var gsNav=new Nav(gsConfig);if(gsConfig.headerIsActive()&&!gsConfig.postIsActive()){MarkdownToHTML(gsConfig.header,gs_header_id);}
if(gsConfig.footerIsActive()){MarkdownToHTML(gsConfig.footer,gs_footer_id);}
if(gsConfig.blogIndexIsActive()){var gsBlogIndex=new BlogIndex(gsConfig);}else if(gsConfig.postIsActive()){PostToHTML(gs_post_path+'/'+gsConfig.requested_page,gs_body_id);}else{MarkdownToHTML(gsConfig.requested_page,gs_body_id);}}<commit_msg>updated pre-commit hook<commit_after>
var gs_jquery_url="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js";var gs_bootstrap_url="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js";var gs_showdown_url="https://cdn.rawgit.com/showdownjs/showdown/1.3.0/dist/showdown.min.js";var gs_jsyaml_url="https://cdn.rawgit.com/dworthen/js-yaml-front-matter/v3.4.0/dist/js-yaml-front-client.min.js"
var gs_jsyaml_map_url="https://cdn.rawgit.com/dworthen/js-yaml-front-matter/v3.4.0/dist/js-yaml-front-client.min.js.map"
var gs_bootgitstrap_url="js/bootgitstrap.min.js";var gs_default_theme_url="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css";var gs_css_url="css/gitstrap.css"
var gs_blog_keyword='GSBLOG';var gs_post_path='posts';var gs_error_id='gs_error_id';var gs_footer_id='gs_footer_id';var gs_header_id='gs_header_id';var gs_body_id='gs_body_id';var gs_ribbon_id='gs_ribbon_id';var gs_nav_title_id='gs_nav_title_id';var gs_title_id='gs_title_id';var gs_nav_placeholder_id='gs_nav_placeholder_id';var gs_navbar_id='gs_navbar_id';var gs_version=''
var gs_html_head_tag=' \
    <meta charset="utf-8"> \
    <meta http-equiv="X-UA-Compatible" content="IE=edge"> \
    <meta name="viewport" content="width=device-width, initial-scale=1">';var gs_html_body_tag=' \
 \
 \
 \
 \
<title id="gs_title_id">GitStrap</title> \
 \

  \
     \
     \

 \

 \
                <button type="button" class="navbar-toggle" type="button" \
                    data-toggle="collapse" \
                    data-target="#gs_navbar_id"> \
                    ☰ \
                </button> \

GitStrap
 \

 \

 \

 \

 \

 \
     \
     \

 \
     \

 \
     \

 \
     \

 \
     \
     \

 ';window.onload=function(){if(document.head==null){alert("You must update your browser to view this website.");}
document.head.innerHTML=gs_html_head_tag;document.body.innerHTML=gs_html_body_tag;add_style(gs_default_theme_url);add_style(gs_css_url);var scripts=[gs_jquery_url,gs_bootstrap_url,gs_showdown_url,gs_jsyaml_url,gs_bootgitstrap_url];loadAndExecuteScripts(scripts,0,function(){});}
function isBlank(str){return(!str||/^\s*$/.test(str));}
function add_style(url){var head=document.getElementsByTagName('head')[0];var link=document.createElement('link');link.rel='stylesheet';link.type='text/css';link.href=url;head.appendChild(link);}
function getScript(url,callback){var script=document.createElement('script');script.type='text/javascript';script.src=url;script.onload=callback;script.onreadystatechange=function(){if(this.readyState=='complete'){callback();}}
document.getElementsByTagName('head')[0].appendChild(script);}
function loadAndExecuteScripts(aryScriptUrls,index,callback){getScript(aryScriptUrls[index],function(){if(index+1<=aryScriptUrls.length-1){loadAndExecuteScripts(aryScriptUrls,index+1,callback);}else{if(callback)
callback();}});}
function getFile(filename,callback,async){var async=typeof async!=='undefined'?async:true;var req=new XMLHttpRequest();req.onreadystatechange=function(){if(req.status==200&&req.readyState==4){callback(req.responseText);}else if(req.status==404){var err_txt='ERROR: 404, File Not Found: "'+filename+'"';fillDiv(err_txt,gs_error_id);console.log(err_txt);}};req.open('GET',filename,async);req.send();}
function appendAttribute(elem,name,value){var attr=elem.getAttribute(name);if(attr==null){elem.setAttribute(name,value);}else{elem.setAttribute(name,attr+" "+value);}}
function setTitle(title){document.getElementById(gs_title_id).innerHTML=title;document.getElementById(gs_nav_title_id).innerHTML=title;if(title=='GitStrap'){document.getElementById(gs_ribbon_id).style.display='block';}}
function setTheme(theme){var direct_url=theme;var name_url='https://maxcdn.bootstrapcdn.com/bootswatch/3.3.6/'+
theme+'/bootstrap.min.css';var theme_url='';function valid_url(url){return/^(http|https|ftp):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/i.test(url);}
if(valid_url(direct_url)){theme_url=direct_url;}
else if(valid_url(name_url)){theme_url=name_url;}
add_style(theme_url);}
function fillDiv(text,div){var node=document.getElementById(div);node.innerHTML=text;node.style.display='block';}
function MarkdownToHTML(relpath,markdown_div)
{var callback=function(text){var converter=new showdown.Converter(),html=converter.makeHtml(text);fillDiv(html,markdown_div);};getFile(relpath,callback);}
function PostToHTML(relpath,markdown_body){var callback=function(text){text=text.replace("(((",'---');text=text.replace(")))",'---');var body=document.getElementById(markdown_body);var post_head=document.createElement('div');var post_body=document.createElement('div');body.appendChild(post_head);body.appendChild(post_body);if((isBlank(text))||(text==null)||(text=='null')||(typeof text==='undefined')){post_head.innerHTML='Unable to load text for: '+relpath;return;}
var obj=jsyaml.loadFront(text)
var date=typeof obj.Date!=='undefined'?obj.Date.toDateString():'';var author=typeof obj.Author!=='undefined'?obj.Author:'';var summary=typeof obj.Summary!=='undefined'?obj.Summary:'';var title=typeof obj.Title!=='undefined'?obj.Title:'';post_head.innerHTML=''+title+'
     '+author+' | '+date+'

';var converter=new showdown.Converter();post_body.innerHTML=converter.makeHtml(obj.__content);};getFile(relpath,callback);}
function Config(filename){var self=this;this.filename=filename
this.title="";this.nav_items=[];this.nav_items_bname=[];this.theme="";this.header="";this.footer="";this.blog_items=[];this.requested_page="";this.post_active=false;this.parseFile=function(text){var options=[];var words=text.split('\n');for(var i=0;i<words.length;i++){if(!(words[i].match(/^#/)||(!words[i]))){if(words[i].match(/^>\S+/)){options.push(words[i].replace(/^>/,''));}}}
self.title=options[0];self.nav_items=options[1].split(' ');self.theme=options[2];self.header=options[3];self.footer=options[4];self.blog_items=options[5].split(' ');self.nav_items_bname=self.nav_items.slice();var blog_index=self.nav_items_bname.indexOf(gs_blog_keyword);self.nav_items_bname[blog_index]=self.blog_items[0];self.determineActivePage();};this.headerIsActive=function(){return self.header!='false';};this.footerIsActive=function(){return self.footer!='false';};this.determineActivePage=function(){var post_found=0;var post_index=-1;var req_post=self.getURLParameter('post');if(!(req_post=='null'||req_post==null)){post_index=self.blog_items.indexOf(req_post);if(post_index>0){post_found=1;}}
var page_found=0;var page_index=-1;var req_page=self.getURLParameter('page');if(!(req_page=='null'||req_page==null)){page_index=self.nav_items_bname.indexOf(req_page);if(page_index>=0){page_found=1;}}
active_page=self.nav_items_bname[0];if(post_found){active_page=self.blog_items[post_index];self.post_active=true;}
if(page_found){active_page=self.nav_items_bname[page_index];self.post_active=false;}
self.requested_page=active_page;};this.getURLParameter=function(name){return decodeURI((RegExp(name+'='+'(.+?)(&|$)').exec(location.search)||[,null])[1]);};this.isBlog=function(){return(self.nav_items.indexOf(gs_blog_keyword)>=0);};this.blogIndexIsActive=function(){if(self.isBlog()){if(self.requested_page==self.blog_items[0]){return true;}}
return false;};this.postIsActive=function(){return self.post_active;};getFile(self.filename,self.parseFile,false);}
function Nav(conf){var self=this;this.conf=conf;this.navbar_obj=document.getElementById(gs_nav_placeholder_id);this.genNavListTags=function(){for(index=0;index<self.conf.nav_items.length;index++){var li=document.createElement('li');var a=document.createElement('a');var item=self.conf.nav_items_bname[index];appendAttribute(a,'class','non-active-nav');if(self.conf.requested_page==item){a.removeAttribute('class');appendAttribute(li,'class','active');}
appendAttribute(li,'id','navitem');appendAttribute(li,'class','nav-item');appendAttribute(a,'class','nav-link');appendAttribute(a,'href','?page='+item+'#');appendAttribute(a,'data-toggle','tab');appendAttribute(a,'style','z-index: 1000;');a.innerHTML=item;li.appendChild(a);self.navbar_obj.appendChild(li);}};this.genNavListTags();}
function BlogIndex(conf){var self=this;this.conf=conf;this.genBlogIndex=function(){var md_body_obj=document.getElementById(gs_body_id);var ul=document.createElement('ul');appendAttribute(ul,'class','list-group');md_body_obj.appendChild(ul);for(index=1;index<self.conf.blog_items.length;index++){var item=self.conf.blog_items[index];var li=document.createElement('li');li.setAttribute('id',item);appendAttribute(li,'class','list-group-item');ul.appendChild(li);self.PostPreviewToHTML(gs_post_path+'/'+item,item);}};this.PostPreviewToHTML=function(relpath,markdown_div){var callback=function(text){text=text.replace("(((",'---');text=text.replace(")))",'---');if((isBlank(text))||(text==null)||(text=='null')||(typeof text==='undefined')){var li=document.getElementById(markdown_div);li.innerHTML='Unable to load text for: '+relpath;return;}
var obj=jsyaml.loadFront(text)
var date=typeof obj.Date!=='undefined'?obj.Date.toDateString():'';var author=typeof obj.Author!=='undefined'?obj.Author:'';var summary=typeof obj.Summary!=='undefined'?obj.Summary:'';var title=typeof obj.Title!=='undefined'?obj.Title:'';var li=document.getElementById(markdown_div);li.innerHTML=''+title+'
 '+author+' | '+
date+'
'+summary+'';};getFile(relpath,callback);};this.genBlogIndex();}
function gitstrap(){var gsConfig=new Config('Config');setTitle(gsConfig.title);setTheme(gsConfig.theme);var gsNav=new Nav(gsConfig);if(gsConfig.headerIsActive()&&!gsConfig.postIsActive()){MarkdownToHTML(gsConfig.header,gs_header_id);}
if(gsConfig.footerIsActive()){MarkdownToHTML(gsConfig.footer,gs_footer_id);}
if(gsConfig.blogIndexIsActive()){var gsBlogIndex=new BlogIndex(gsConfig);}else if(gsConfig.postIsActive()){PostToHTML(gs_post_path+'/'+gsConfig.requested_page,gs_body_id);}else{MarkdownToHTML(gsConfig.requested_page,gs_body_id);}}<|endoftext|>


<commit_before>var projects = {
	"<project-name>":{
                      "image":"https://avatars3.githubusercontent.com/u/22071699?v=3&s=200",
                      "team":"IIIT-A Hacks",
                      "link":"https://github.com/iiitahacks"
                  },

}
<commit_msg>Update project.js<commit_after>var projects = {
	"<project-name>":{
                      "image":"https://avatars3.githubusercontent.com/u/22071699?v=3&s=200",
                      "team":"IIIT-A Hacks",
                      "link":"https://github.com/iiitahacks"
                  },
         "Gather":{
                      "image":"https://avatars3.githubusercontent.com/u/22071699?v=3&s=200",
                      "team":"checkmate",
                      "link":"https://github.com/magician03/gather"
                  },

}
<|endoftext|>


<commit_before>define('appHelpers', [

	'app'

], function(app){

	/******************************************
	* Helpers
	*/
	var AppHelpers = {

		many2oneObjectify : function (field) {
			return {id: field[0], name: field[1]}
		},

		/** Highlight an item
		*/
		highlight: function(highlight_element){
			highlight_element.addClass('highlight');
			var deferred = $.Deferred();

			highlight_element.one('webkitAnimationEnd oanimationend msAnimationEnd animationend',
				function(e) {
					highlight_element.removeClass('highlight');
					deferred.resolve();
				}
			);

			return deferred;
		},

		/** Build the url with the parameters
		*/
		urlBuilder: function(urlParameters, options){
			var self = this;

			// Retrieve the baseurl of the view //
			var url = _(Backbone.history.fragment).strLeft('/');

			// Iterate all urlParameters //
			_.each(urlParameters, function(value, index){

				// Check if the options parameter aren't undefined or null //
				if(!_.isUndefined(options[value]) && !_.isNull(options[value])){

					// Check if the value of the parameter is not an object //
					if(!_.isObject(options[value])){

						url += '/'+value+'/'+options[value];
					}
					else{

						// Check if the value is the page //
						if(value == 'page'){
							url += '/'+value+options[value].page;
						}
						else{

							var params = '';
							_.each(options[value], function(value, item){
								if(!_.isEmpty(params)){
									params += '-'+value;
								}
								else{
									params += value;
								}
							})

							url += '/'+value+'/'+params;
						}
					}
				}

			})

			return url;
		},

		/** Transform Decimal number to hour:minute
		*/
		decimalNumberToTime: function(decimalNumber){

			// Check if the number is decimal //
			if(_.str.include(decimalNumber, '.')){
				var minutes = _.lpad(((_.rpad(_(decimalNumber).strRight('.'), 2, '0') / 100) * 60), 2, '0');
				var hour = _(decimalNumber).strLeft('.');

				if(hour == 0){
					var date = _(minutes).toNumber()+app.lang.minuteShort;
				}
				else{
					var date = hour+'h'+_(minutes).toNumber();
				}
			}
			else{
				var date = decimalNumber+'h';
			}

			return date;
		},

		/** Calcul the page and the offset
		*/
		calculPageOffset: function(page, itemsPerPage){

			var paginate = {};

			if(_.isUndefined(page)){
				paginate.page = 1;
				paginate.offset = 0;
			}
			else{
				paginate.page = parseInt(page, 10);
				paginate.offset = (paginate.page - 1) * (!_.isUndefined(itemsPerPage) ? itemsPerPage : app.config.itemsPerPage);
			}

			return paginate;
		},

		/** Calcul the sort By column and the order
		*/
		calculPageSort: function(sort){

			var sorter = {};

			sorter.by = _(sort).strLeft('-');
			sorter.order = _(sort).strRight('-');

			return sorter;
		},

		/** Calcul the Filter By
		*/
		calculPageFilter: function(filter){

			var filt = {};

			filt.by = _(filter).strLeft('-');
			filt.value = _(filter).strRight('-');

			return filt;
		},

		/** Calcul the search argument of the page
		*/
		calculSearch: function (searchQuery, searchableFields) {

			//['|', ["name", "ilike", searchQuery], ["surface", "=", _(searchQuery).toNumber()]];
			//['&', ["state", "ilike", 'valid'], '|', ["name", "ilike", 'demande'], ["id", "=", _('demande').toNumber()]];

			var search = [];

			// Is Number //
			function isNumber(n) {
				return !isNaN(parseFloat(n)) && isFinite(n);
			};

			// Convert Field Filters //
			function convertFieldFilters(fieldsFilters) {
				var convertedFilters = [];

				function convertFilter(filter, operator) {
					return {key:filter.key, type: operator};
				};

				_.each(fieldsFilters, function (filter, index) {
					switch (filter.type) {
						case 'numeric':
							if (isNumber(searchQuery.search)) {
								convertedFilters.push(convertFilter(filter, '='));
							}
							break;
						case 'text':
							convertedFilters.push(convertFilter(filter, 'ilike'));
							break;
					}
				});
				return convertedFilters;
			};

			var filteredAndConvertedFilters = convertFieldFilters(searchableFields);

			function buildFilterObject(field,operator,value) {
				return {field: field, operator:operator, value:value}
			};

			// Check if there is a filter //
			if (!_.isUndefined(searchQuery.filter)) {
				if (!_.isUndefined(searchQuery.search)) {
					search.push('&');
				}
				search.push( buildFilterObject(searchQuery.filter.by,'ilike',searchQuery.filter.value));
			}

			// Check if there is a Search //
			if (!_.isUndefined(searchQuery.search)) {
				// Search on several fields //
				for(var i=1;i < _.size(filteredAndConvertedFilters);i++){
					search.push('|');
				}

				if (_.size(filteredAndConvertedFilters) > 1) {
					_.each(filteredAndConvertedFilters, function (item, index) {
						if (item.type == '=' && isNumber(searchQuery.search)) {
							var term = _(searchQuery.search).toNumber();
						} else {
							var term = searchQuery.search;

						}
						search.push(buildFilterObject(item.key,item.type,term));
					});
				}
				else {
					search.push( buildFilterObject(filteredAndConvertedFilters[0].key,filteredAndConvertedFilters[0].type,searchQuery.search));
				}
			}
			return app.objectifyFilters(search);
		},

		printError: function (e) {
			$('.form-group').removeClass('has-error');
			$('.help-block').html('');
			$('#'+fieldId).html(app.lang.errorMessages[message]);
			var fieldId = _(_(e.responseJSON.faultCode).strRight('*')).strLeft('*') + "-error";
			var message =  _.trim( _(e.responseJSON.faultCode).strRight("/") );
			$('#'+fieldId).html(app.lang.errorMessages[message]);
			$('#'+fieldId).parents('.form-group').addClass('has-error');
		},

	}

return AppHelpers;

});<commit_msg>fixed MainHelpers on _.str error<commit_after>define('appHelpers', [

	'app'

], function(app){

	/******************************************
	* Helpers
	*/
	var AppHelpers = {

		many2oneObjectify : function (field) {
			return {id: field[0], name: field[1]}
		},

		/** Highlight an item
		*/
		highlight: function(highlight_element){
			highlight_element.addClass('highlight');
			var deferred = $.Deferred();

			highlight_element.one('webkitAnimationEnd oanimationend msAnimationEnd animationend',
				function(e) {
					highlight_element.removeClass('highlight');
					deferred.resolve();
				}
			);

			return deferred;
		},

		/** Build the url with the parameters
		*/
		urlBuilder: function(urlParameters, options){
			var self = this;

			// Retrieve the baseurl of the view //
			var url = _(Backbone.history.fragment).strLeft('/');

			// Iterate all urlParameters //
			_.each(urlParameters, function(value, index){

				// Check if the options parameter aren't undefined or null //
				if(!_.isUndefined(options[value]) && !_.isNull(options[value])){

					// Check if the value of the parameter is not an object //
					if(!_.isObject(options[value])){

						url += '/'+value+'/'+options[value];
					}
					else{

						// Check if the value is the page //
						if(value == 'page'){
							url += '/'+value+options[value].page;
						}
						else{

							var params = '';
							_.each(options[value], function(value, item){
								if(!_.isEmpty(params)){
									params += '-'+value;
								}
								else{
									params += value;
								}
							})

							url += '/'+value+'/'+params;
						}
					}
				}

			})

			return url;
		},

		/** Transform Decimal number to hour:minute
		*/
		decimalNumberToTime: function(decimalNumber){

			// Check if the number is decimal //
			if(_.include(decimalNumber, '.')){
				var minutes = _.lpad(((_.rpad(_(decimalNumber).strRight('.'), 2, '0') / 100) * 60), 2, '0');
				var hour = _(decimalNumber).strLeft('.');

				if(hour == 0){
					var date = _(minutes).toNumber()+app.lang.minuteShort;
				}
				else{
					var date = hour+'h'+_(minutes).toNumber();
				}
			}
			else{
				var date = decimalNumber+'h';
			}

			return date;
		},

		/** Calcul the page and the offset
		*/
		calculPageOffset: function(page, itemsPerPage){

			var paginate = {};

			if(_.isUndefined(page)){
				paginate.page = 1;
				paginate.offset = 0;
			}
			else{
				paginate.page = parseInt(page, 10);
				paginate.offset = (paginate.page - 1) * (!_.isUndefined(itemsPerPage) ? itemsPerPage : app.config.itemsPerPage);
			}

			return paginate;
		},

		/** Calcul the sort By column and the order
		*/
		calculPageSort: function(sort){

			var sorter = {};

			sorter.by = _(sort).strLeft('-');
			sorter.order = _(sort).strRight('-');

			return sorter;
		},

		/** Calcul the Filter By
		*/
		calculPageFilter: function(filter){

			var filt = {};

			filt.by = _(filter).strLeft('-');
			filt.value = _(filter).strRight('-');

			return filt;
		},

		/** Calcul the search argument of the page
		*/
		calculSearch: function (searchQuery, searchableFields) {

			//['|', ["name", "ilike", searchQuery], ["surface", "=", _(searchQuery).toNumber()]];
			//['&', ["state", "ilike", 'valid'], '|', ["name", "ilike", 'demande'], ["id", "=", _('demande').toNumber()]];

			var search = [];

			// Is Number //
			function isNumber(n) {
				return !isNaN(parseFloat(n)) && isFinite(n);
			};

			// Convert Field Filters //
			function convertFieldFilters(fieldsFilters) {
				var convertedFilters = [];

				function convertFilter(filter, operator) {
					return {key:filter.key, type: operator};
				};

				_.each(fieldsFilters, function (filter, index) {
					switch (filter.type) {
						case 'numeric':
							if (isNumber(searchQuery.search)) {
								convertedFilters.push(convertFilter(filter, '='));
							}
							break;
						case 'text':
							convertedFilters.push(convertFilter(filter, 'ilike'));
							break;
					}
				});
				return convertedFilters;
			};

			var filteredAndConvertedFilters = convertFieldFilters(searchableFields);

			function buildFilterObject(field,operator,value) {
				return {field: field, operator:operator, value:value}
			};

			// Check if there is a filter //
			if (!_.isUndefined(searchQuery.filter)) {
				if (!_.isUndefined(searchQuery.search)) {
					search.push('&');
				}
				search.push( buildFilterObject(searchQuery.filter.by,'ilike',searchQuery.filter.value));
			}

			// Check if there is a Search //
			if (!_.isUndefined(searchQuery.search)) {
				// Search on several fields //
				for(var i=1;i < _.size(filteredAndConvertedFilters);i++){
					search.push('|');
				}

				if (_.size(filteredAndConvertedFilters) > 1) {
					_.each(filteredAndConvertedFilters, function (item, index) {
						if (item.type == '=' && isNumber(searchQuery.search)) {
							var term = _(searchQuery.search).toNumber();
						} else {
							var term = searchQuery.search;

						}
						search.push(buildFilterObject(item.key,item.type,term));
					});
				}
				else {
					search.push( buildFilterObject(filteredAndConvertedFilters[0].key,filteredAndConvertedFilters[0].type,searchQuery.search));
				}
			}
			return app.objectifyFilters(search);
		},

		printError: function (e) {
			$('.form-group').removeClass('has-error');
			$('.help-block').html('');
			$('#'+fieldId).html(app.lang.errorMessages[message]);
			var fieldId = _(_(e.responseJSON.faultCode).strRight('*')).strLeft('*') + "-error";
			var message =  _.trim( _(e.responseJSON.faultCode).strRight("/") );
			$('#'+fieldId).html(app.lang.errorMessages[message]);
			$('#'+fieldId).parents('.form-group').addClass('has-error');
		},

	}

return AppHelpers;

});<|endoftext|>