{"version":3,"sources":["src/model.js","src/app.js","src/main.js"],"names":["Location","row","column","temp","EventName","Event","name","startLocation","endLocation","value","Direction","Game","eventHandler","deterministic","deterministic_","eventHandler_","board","score","score_","board_","i","j","val","NUMBER_ADDED","placeNewNumbers_","direction","events","UP","slideBoardLeft_","length","event","swapRowAndColumn","dispatchEvents_","DOWN","LEFT","RIGHT","copyBoard","isBoardFull_","col","currentNumber","locations","neighbor","isInBoard","count","emptyIndices","k","push","newNumber","index","getRandomInt","emptySlot","splice","forEach","concat","slideRowLeft_","rowNumber","currentIndex","NUMBER_MOVED","NUMBER_MERGED","max","Math","floor","random","copy","flipHorizontally","reverse","flipDiagonally","run","transitionsInProgress","boxes","game","deleteBox","boxesLength","aBox","rowBoxPosition","colBoxPosition","printBoxes","log","findBox","getBoxPosition","boardWidth","boxSize","space","setColor","box","classList","add","String","addBox","location","effect","domBox","document","createElement","theDiv","getElementById","clientWidth","boxPos","style","top","left","innerHTML","appendChild","handleAdd","handleMove","startRow","startCol","finalRow","finalCol","startBox","finalBoxPos","addEventListener","listener","removeEventListener","handleMerge","finalBox","startBoxDiv","finalBoxDiv","remove","showGameOver","gameoverOverlay","id","message","stopPropagation","backgroundContainer","overlayContainer","updateScore","newScore","previousScore","scoreDiff","scoreAnimationElement","getSavedBoard","JSON","parse","window","localStorage","getItem","saveBoard","setItem","stringify","getSavedScore","savedScore","parseInt","saveScore","getSavedBestScore","savedBestScore","saveBestScore","bestScore","showBestScore","layoutBoard","slide","isGameOver","getScore","getBoard","href","savedBoard","reload","restart","lastChild","removeChild","pressedKey","validKeys","key","code","includes","preventDefault","querySelector","hammer","Hammer","get","set","DIRECTION_ALL","on","e","app"],"mappings":"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","file":"main.549676b3.map","sourceRoot":"..","sourcesContent":["/**\n * Location represents a location on the game board by a row number and a column number.\n * Row 0 is the top-most row. Column 0 is the left-most column.\n */\n\n// Model\nexport class Location {\n  constructor(row, column) {\n    this.row = row;\n    this.column = column;\n  }\n\n  isInBoard() {\n    return this.row >= 0 && this.row < 4 && this.column >= 0 && this.column < 4;\n  }\n\n  /**\n   * Swap the row and column of this location.\n   */\n  swapRowAndColumn() {\n    this.temp = this.row;\n    this.row = this.column;\n    this.column = this.temp;\n  }\n}\n\n/**\n * Enums for possible Event names.\n */\nexport const EventName = {\n  NUMBER_ADDED: 'number_added',\n  NUMBER_MOVED: 'number_moved',\n  NUMBER_MERGED: 'number_merged'\n};\n\n/**\n *\n */\nexport class Event {\n  constructor(name, startLocation, endLocation, value) {\n    this.name = name;\n    this.startLocation = startLocation;\n    this.endLocation = endLocation;\n    this.value = value;\n  }\n}\n\nexport const Direction = {\n  UP: 'up',\n  DOWN: 'down',\n  LEFT: 'left',\n  RIGHT: 'right'\n};\n\nexport class Game {\n  constructor(eventHandler, deterministic) {\n    this.deterministic_ = deterministic;\n    this.eventHandler_ = eventHandler;\n  }\n\n  reload(board, score) {\n    this.score_ = score;\n    this.board_ = board;\n    for (let i = 0; i < 4; i++) {\n      for (let j = 0; j < 4; j++) {\n        let val = this.board_[i][j];\n        if (val !== 0) {\n          this.eventHandler_(\n            new Event(EventName.NUMBER_ADDED, new Location(i, j), null, val)\n          );\n        }\n      }\n    }\n  }\n\n  restart() {\n    this.score_ = 0;\n    this.board_ = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]];\n    this.placeNewNumbers_(2);\n  }\n\n  slide(direction) {\n    let events;\n    switch (direction) {\n      case Direction.UP:\n        flipDiagonally(this.board_);\n        events = this.slideBoardLeft_(this.board_);\n        flipDiagonally(this.board_);\n\n        for (let i = 0; i < events.length; i++) {\n          let event = events[i];\n          event.startLocation.swapRowAndColumn();\n          event.endLocation.swapRowAndColumn();\n        }\n        this.dispatchEvents_(events);\n        break;\n      case Direction.DOWN:\n        flipDiagonally(this.board_);\n        flipHorizontally(this.board_);\n        events = this.slideBoardLeft_(this.board_);\n        flipHorizontally(this.board_);\n        flipDiagonally(this.board_);\n\n        for (let i = 0; i < events.length; i++) {\n          let event = events[i];\n          event.startLocation.column = 3 - event.startLocation.column;\n          event.startLocation.swapRowAndColumn();\n\n          event.endLocation.column = 3 - event.endLocation.column;\n          event.endLocation.swapRowAndColumn();\n        }\n        this.dispatchEvents_(events);\n        break;\n      case Direction.LEFT:\n        events = this.slideBoardLeft_(this.board_);\n        this.dispatchEvents_(events);\n        break;\n      case Direction.RIGHT:\n        // slide right only needs to worry about the change in col\n        flipHorizontally(this.board_);\n        events = this.slideBoardLeft_(this.board_);\n        flipHorizontally(this.board_);\n\n        for (let i = 0; i < events.length; i++) {\n          let event = events[i];\n          event.startLocation.column = 3 - event.startLocation.column;\n          event.endLocation.column = 3 - event.endLocation.column;\n        }\n        this.dispatchEvents_(events);\n        break;\n    }\n    if (events.length > 0) {\n      this.placeNewNumbers_(1);\n    }\n  }\n\n  getScore() {\n    return this.score_;\n  }\n\n  getBoard() {\n    return copyBoard(this.board_);\n  }\n\n  isGameOver() {\n    if (this.isBoardFull_()) {\n      for (let row = 0; row < 4; row++) {\n        for (let col = 0; col < 4; col++) {\n          let currentNumber = this.board_[row][col];\n          let locations = [\n            new Location(row + 1, col),\n            new Location(row - 1, col),\n            new Location(row, col + 1),\n            new Location(row, col - 1)\n          ];\n          for (let i = 0; i < 4; i++) {\n            let neighbor = locations[i];\n            if (neighbor.isInBoard()) {\n              if (\n                currentNumber === this.board_[neighbor.row][neighbor.column]\n              ) {\n                return false;\n              }\n            }\n          }\n        }\n      }\n      return true;\n    }\n  }\n\n  // ------------------------------------------------------------------------\n  // Private methods\n\n  isBoardFull_() {\n    for (let i = 0; i < 4; i++) {\n      for (let j = 0; j < 4; j++) {\n        if (this.board_[i][j] === 0) {\n          return false;\n        }\n      }\n    }\n    return true;\n  }\n\n  placeNewNumbers_(count) {\n    let emptyIndices = [];\n    for (let j = 0; j < 4; j++) {\n      for (let k = 0; k < 4; k++) {\n        if (this.board_[j][k] === 0) {\n          emptyIndices.push([j, k]);\n        }\n      }\n    }\n\n    for (let j = 0; j < count; j++) {\n      let newNumber;\n      let index;\n      if (this.deterministic_) {\n        index = 0;\n        newNumber = 2;\n      } else {\n        index = getRandomInt(emptyIndices.length);\n        if (getRandomInt(10) <= 8) {\n          newNumber = 2;\n        } else {\n          newNumber = 4;\n        }\n      }\n      let emptySlot = emptyIndices[index];\n      emptyIndices.splice(index, 1);\n      const row = emptySlot[0];\n      const col = emptySlot[1];\n      this.board_[row][col] = newNumber;\n      let startLocation = new Location(row, col);\n      let event = new Event(\n        EventName.NUMBER_ADDED,\n        startLocation,\n        null,\n        newNumber\n      );\n      this.eventHandler_(event);\n    }\n  }\n\n  dispatchEvents_(events) {\n    events.forEach(event => this.eventHandler_(event));\n  }\n\n  slideBoardLeft_(board) {\n    let events = [];\n    for (let i = 0; i < 4; i++) {\n      events = events.concat(this.slideRowLeft_(board[i], i));\n    }\n    return events;\n  }\n\n  slideRowLeft_(row, rowNumber) {\n    let currentIndex = 0;\n    let events = [];\n    // return an array of objects that has what position it was from and moved to. Then it will\n    // make a board of transitions and we can rotate that board like we rotate board\n    // to accomodate for the different directions\n\n    for (let i = 1; i < 4; i++) {\n      if (row[i] === 0) {\n        continue;\n      }\n\n      let startLocation = new Location(rowNumber, i);\n      let endLocation = new Location(rowNumber, currentIndex);\n\n      // if currentIndex is 0, swap it with the next index value\n      if (row[currentIndex] === 0) {\n        let event = new Event(\n          EventName.NUMBER_MOVED,\n          startLocation,\n          endLocation,\n          row[i]\n        );\n        row[currentIndex] = row[i];\n        events.push(event);\n      }\n      // currentIndex value is the same as i, merge into one\n      else if (row[currentIndex] === row[i]) {\n        row[currentIndex] += row[i];\n        let event = new Event(\n          EventName.NUMBER_MERGED,\n          startLocation,\n          endLocation,\n          row[currentIndex]\n        );\n        this.score_ += row[currentIndex];\n        events.push(event);\n        currentIndex += 1;\n      }\n      // currentIndex is not same value as i AND value before i is 0\n      else if (row[currentIndex] !== row[i] && row[i - 1] === 0) {\n        currentIndex += 1;\n        i -= 1;\n      } else {\n        currentIndex += 1;\n        continue;\n      }\n      row[i] = 0;\n    }\n    return events;\n  }\n}\n\nfunction getRandomInt(max) {\n  return Math.floor(Math.random() * max);\n}\n\nfunction copyBoard(board) {\n  let copy = [[], [], [], []];\n  for (let i = 0; i < 4; i++) {\n    for (let j = 0; j < 4; j++) {\n      copy[i][j] = board[i][j];\n    }\n  }\n  return copy;\n}\n\nfunction flipHorizontally(board) {\n  for (let i = 0; i < 4; i++) {\n    board[i] = board[i].reverse();\n  }\n}\n\nfunction flipDiagonally(board) {\n  let copy = copyBoard(board);\n  for (let i = 0; i < 4; i++) {\n    board[i][0] = copy[0][i];\n    board[i][1] = copy[1][i];\n    board[i][2] = copy[2][i];\n    board[i][3] = copy[3][i];\n  }\n}\n","// Controller\n\nimport { Game, EventName, Direction } from './model';\n\nlet transitionsInProgress = 0;\nlet boxes = [];\nlet game;\n\nfunction deleteBox(row, col, boxes) {\n  const boxesLength = boxes.length;\n  for (let k = 0; k < boxesLength; k++) {\n    const aBox = boxes[k];\n    if (aBox.rowBoxPosition === row && aBox.colBoxPosition === col) {\n      boxes.splice(k, 1);\n      return;\n    }\n  }\n}\n\nfunction printBoxes(boxes) {\n  for (let i = 0; i < boxes.length; i++) {\n    console.log(boxes[i]);\n  }\n}\n\nfunction findBox(row, col, boxes) {\n  const boxesLength = boxes.length;\n  for (let k = 0; k < boxesLength; k++) {\n    const aBox = boxes[k];\n    if (aBox.rowBoxPosition === row && aBox.colBoxPosition === col) {\n      return aBox;\n    }\n  }\n}\n\nfunction getBoxPosition(row, col, boardWidth) {\n  const boxSize = (boardWidth * 107) / 500;\n  const space = (boardWidth - 4 * boxSize) / 5;\n  const topPosition = space * row + boxSize * row;\n  const leftPosition = space * col + boxSize * col;\n  return [topPosition, leftPosition];\n}\n\nfunction setColor(val, box) {\n  box.classList.add('b' + String(val));\n}\n\nfunction addBox(location, value, effect) {\n  let box = {};\n  box.rowBoxPosition = location.row;\n  box.colBoxPosition = location.column;\n  box.val = value;\n  let domBox = document.createElement('div');\n  box.theDiv = domBox;\n  const boardWidth = document.getElementById('board').clientWidth;\n  const boxPos = getBoxPosition(location.row, location.column, boardWidth);\n  domBox.classList.add('overlay-box');\n\n  setColor(value, domBox);\n\n  domBox.classList.add(effect);\n\n  domBox.style.top = boxPos[0] + 'px';\n  domBox.style.left = boxPos[1] + 'px';\n  domBox.innerHTML = value;\n  boxes.push(box);\n  let container = document.getElementById('overlay-container');\n\n  container.appendChild(domBox);\n}\n\nfunction handleAdd(event) {\n  addBox(event.startLocation, event.value, 'bounce-effect');\n}\n\nfunction handleMove(event) {\n  const startRow = event.startLocation.row;\n  const startCol = event.startLocation.column;\n  const finalRow = event.endLocation.row;\n  const finalCol = event.endLocation.column;\n\n  const startBox = findBox(startRow, startCol, boxes);\n  const boardWidth = document.getElementById('board').clientWidth;\n  const finalBoxPos = getBoxPosition(finalRow, finalCol, boardWidth);\n\n  startBox.theDiv.style.top = finalBoxPos[0] + 'px';\n  startBox.theDiv.style.left = finalBoxPos[1] + 'px';\n  startBox.colBoxPosition = finalCol;\n  startBox.rowBoxPosition = finalRow;\n  transitionsInProgress += 1;\n\n  const listener = function() {\n    transitionsInProgress -= 1;\n    startBox.theDiv.removeEventListener('transitionend', listener);\n  };\n  startBox.theDiv.addEventListener('transitionend', listener);\n}\n\nfunction handleMerge(event) {\n  const startRow = event.startLocation.row;\n  const startCol = event.startLocation.column;\n  const finalRow = event.endLocation.row;\n  const finalCol = event.endLocation.column;\n  const startBox = findBox(startRow, startCol, boxes);\n  const finalBox = findBox(finalRow, finalCol, boxes);\n\n  const boardWidth = document.getElementById('board').clientWidth;\n  const boxPos = getBoxPosition(finalRow, finalCol, boardWidth);\n\n  const startBoxDiv = startBox.theDiv;\n  const finalBoxDiv = finalBox.theDiv;\n  deleteBox(startRow, startCol, boxes);\n  deleteBox(finalRow, finalCol, boxes);\n  startBoxDiv.addEventListener('transitionend', function() {\n    // remove both boxes to create the new box\n    startBoxDiv.remove();\n    finalBoxDiv.remove();\n    addBox(event.endLocation, event.value, 'merge-effect');\n    transitionsInProgress -= 1;\n  });\n\n  // box move transition\n  startBox.theDiv.style.top = boxPos[0] + 'px';\n  startBox.theDiv.style.left = boxPos[1] + 'px';\n  transitionsInProgress += 1;\n}\n\nfunction eventHandler(event) {\n  let name = event.name;\n  if (name === EventName.NUMBER_MOVED) {\n    handleMove(event);\n  } else if (name === EventName.NUMBER_MERGED) {\n    handleMerge(event);\n  } else {\n    handleAdd(event);\n  }\n}\n\nfunction showGameOver() {\n  let board = document.getElementById('board');\n  const listener = function(event) {\n    board.removeEventListener('animationend', listener);\n    let gameoverOverlay = document.createElement('div');\n    gameoverOverlay.id = 'gameover-overlay';\n    let message = document.createElement('p');\n    message.innerHTML = 'Game over!';\n    // let tryAgainBtn = document.createElement('button');\n    // tryAgainBtn.onclick = function() {\n    //   container.removeChild(gameoverOverlay);\n    //   backgroundContainer.classList.remove('fade-effect');\n    //   overlayContainer.classList.remove('fade-effect');\n    //   resetBoxVisuals();\n    // };\n    gameoverOverlay.appendChild(message);\n    // gameoverOverlay.appendChild(tryAgainBtn);\n    // tryAgainBtn.innerHTML = 'Try again';\n    // tryAgainBtn.classList.add('try-again');\n    board.appendChild(gameoverOverlay);\n    event.stopPropagation();\n  };\n\n  board.addEventListener('animationend', listener(event));\n  let backgroundContainer = document.getElementById('background-container');\n  let overlayContainer = document.getElementById('overlay-container');\n  backgroundContainer.classList.add('fade-effect');\n  overlayContainer.classList.add('fade-effect');\n}\n\nfunction updateScore(newScore, previousScore) {\n  let scoreDiff = newScore - previousScore;\n  if (scoreDiff > 0) {\n    let scoreAnimationElement = document.createElement('div');\n    let scoreBox = document.getElementById('current-score');\n    scoreBox.innerHTML = newScore;\n    scoreAnimationElement.innerHTML = '+' + scoreDiff;\n    scoreAnimationElement.id = 'score-animation';\n    let scoreContainer = document.getElementById('left-score-rectangle');\n    scoreContainer.appendChild(scoreAnimationElement);\n    scoreAnimationElement.addEventListener('animationend', function() {\n      document.getElementById('score-animation').remove();\n    });\n  }\n}\n\nfunction getSavedBoard() {\n  return JSON.parse(window.localStorage.getItem('board'));\n}\n\nfunction saveBoard(board) {\n  window.localStorage.setItem('board', JSON.stringify(board));\n}\n\nfunction getSavedScore() {\n  let savedScore = window.localStorage.getItem('score');\n  if (savedScore === null) {\n    savedScore = 0;\n  }\n  return parseInt(savedScore, 10);\n}\n\nfunction saveScore(score) {\n  window.localStorage.setItem('score', score);\n}\n\nfunction getSavedBestScore() {\n  let savedBestScore = window.localStorage.getItem('bestScore');\n  if (savedBestScore === null) {\n    savedBestScore = 0;\n  }\n  return parseInt(savedBestScore, 10);\n}\n\nfunction saveBestScore(bestScore) {\n  window.localStorage.setItem('bestScore', bestScore);\n}\n\nfunction showBestScore(bestScore) {\n  document.getElementById('best-score').innerHTML = bestScore;\n}\n\nfunction layoutBoard() {\n  const boardWidth = document.getElementById('board').clientWidth;\n  for (let i = 0; i < boxes.length; i++) {\n    let box = boxes[i];\n    const boxPos = getBoxPosition(\n      box.rowBoxPosition,\n      box.colBoxPosition,\n      boardWidth\n    );\n    box.theDiv.style.top = boxPos[0] + 'px';\n    box.theDiv.style.left = boxPos[1] + 'px';\n  }\n}\n\nfunction slide(direction) {\n  if (transitionsInProgress !== 0) {\n    return;\n  }\n\n  if (game.isGameOver()) {\n    return;\n  }\n\n  let previousScore = game.getScore();\n\n  game.slide(direction);\n\n  let newScore = game.getScore();\n  updateScore(newScore, previousScore);\n  if (newScore > getSavedBestScore()) {\n    saveBestScore(newScore);\n    showBestScore(newScore);\n  }\n  saveBoard(game.getBoard());\n  saveScore(game.getScore());\n  if (game.isGameOver()) {\n    showGameOver();\n  }\n}\n\nexport function run() {\n  showBestScore(getSavedBestScore());\n  game = new Game(eventHandler, false);\n  if (window.location.href === 'https://2048.calvinln.com/test') {\n    game = new Game(eventHandler, true);\n  }\n\n  let savedBoard = getSavedBoard();\n  if (savedBoard) {\n    let savedScore = getSavedScore();\n    updateScore(savedScore, 0);\n    game.reload(savedBoard, savedScore);\n  } else {\n    game.restart();\n  }\n\n  const newGameButton = document.getElementById('new-game-btn');\n  newGameButton.addEventListener('click', function() {\n    const overlayContainer = document.getElementById('overlay-container');\n    while (overlayContainer.lastChild) {\n      overlayContainer.removeChild(overlayContainer.lastChild);\n    }\n\n    let currentScoreElement = document.getElementById('current-score');\n    currentScoreElement.innerHTML = 0;\n\n    boxes = [];\n    game.restart();\n    saveBoard(game.getBoard());\n    saveScore(game.getScore());\n  });\n\n  window.addEventListener('resize', function(event) {\n    layoutBoard();\n  });\n\n  document.addEventListener('keydown', function(pressedKey) {\n    // map arrowup to up for model\n    let validKeys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'];\n    let key = pressedKey.code;\n\n    if (validKeys.includes(key)) {\n      pressedKey.preventDefault();\n\n      switch (key) {\n        case 'ArrowUp':\n          slide(Direction.UP);\n          break;\n        case 'ArrowDown':\n          slide(Direction.DOWN);\n          break;\n        case 'ArrowLeft':\n          slide(Direction.LEFT);\n          break;\n        case 'ArrowRight':\n          slide(Direction.RIGHT);\n          break;\n      }\n    }\n  });\n\n  const board = document.querySelector('#board');\n  const options = {\n    preventDefault: true\n  };\n  const hammer = new Hammer(board, options);\n  hammer.get('swipe').set({ direction: Hammer.DIRECTION_ALL });\n\n  hammer.on('swipeleft', function(e) {\n    slide(Direction.LEFT);\n  });\n  hammer.on('swiperight', function(e) {\n    slide(Direction.RIGHT);\n  });\n  hammer.on('swipeup', function(e) {\n    slide(Direction.UP);\n  });\n  hammer.on('swipedown', function(e) {\n    slide(Direction.DOWN);\n  });\n}\n","import * as app from './app';\n\napp.run();\n"]}