{"version":3,"sources":["index.js"],"names":["gameP1","FisherYatesShuffle","myArray","i","j","tempi","tempj","length","Math","floor","random","debounce","func","wait","immediate","timeout","result","context","args","arguments","callNow","clearTimeout","setTimeout","apply","throttle","throttling","more","whenDone","TemporalFlags","timeouts","flags","getFlag","flag","addTemporalFlag","timeoutInMillisecons","callback","window","Date","elapsed","getTime","removeTemporalFlag","addTemporalProperty","name","undefined","timeoutOverrride","PointsTracker","sendMarblesCallback","setMarbleMultiplier","type","marbleMultiplierType","marbleMultiplier","console","log","trackRemoved","removedAmount","marbleType","lastRemoveAt","points","push","combo","sendMarblesLoop","isMultiplierType","baseAmount","sendMarbles","amount","Marble","isEmpty","isNew","addedFromTop","tf","Game","initialize","container","scoreContainer","pointsTracker","temporalFlags","resetAnimations","columnSize","center","cursor","columns","getEmptyColumn","fillColumns","createDom","otherGame","receiveMarbles","attachReceiveMarble","addRandomMarbles","setOtherPlayerGame","game","size","column","getTopSectionOfColumn","columnIndex","includeCenter","slice","getBottomSectionOfcolumn","getNumberOfMarblesInTopSection","filter","marble","getNumberOfMarblesInBottomSection","getNumberOfMarblesInColumn","fillColumn","setLocked","marblesInColumn","shouldAdd","col","addFromTop","columnsIndexes","pop","fromTop","addedMarble","addMarbleFromTop","getRandomMarble","addMarbleFromBottom","getRandomMarbles","m","checkForEquals","howMany","startingAt","removeMarbles","howManyColumns","startingAtColumn","splice","unshift","forEach","setMovingUp","setMovingDown","translateCenterRight","isLocked","lastMarble","setTranslatingRight","checkCenterMarbles","_checkAndRemove","added","doGravity","swapCenterMarbles","colA","colB","A","B","left","dragMarble","oldCursor","max","right","min","down","shift","up","columnsDom","element","classList","remove","offsetWidth","draw","setMarbleClasses","contains","c","add","isTranslatingRight","isMovingDown","isMovingUp","drawMarble","marbleIndex","cursorDom","marbleMultiplierDom","innerText","throttledDraw","createRowElement","parent","isCenter","document","createElement","className","appendChild","createMarbleElement","bindAnimationLock","addEventListener","e","animationName","receiveDom","prepend","getElementsByClassName","Array","row","gameP2","which","getElementById","setInterval"],"mappings":"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","file":"marbles.1f29920c.map","sourceRoot":"..","sourcesContent":["import './style.css'\n\nfunction FisherYatesShuffle (myArray) {\n  var i = myArray.length\n  var j\n  var tempi\n  var tempj\n  if (i === 0) return false\n  while (--i) {\n    j = Math.floor(Math.random() * (i + 1))\n    tempi = myArray[i]\n    tempj = myArray[j]\n    myArray[i] = tempj\n    myArray[j] = tempi\n  }\n  return myArray\n}\n\n// extracted from underscore\nfunction debounce (func, wait, immediate) {\n  var timeout\n  var result\n  return function () {\n    var context = this\n    var args = arguments\n    var later = function () {\n      timeout = null\n      if (!immediate) result = func.apply(context, args)\n    }\n    var callNow = immediate && !timeout\n    clearTimeout(timeout)\n    timeout = setTimeout(later, wait)\n    if (callNow) result = func.apply(context, args)\n    return result\n  }\n}\n\nfunction throttle (func, wait) {\n  var context\n  var args\n  var timeout\n  var throttling\n  var more\n  var result\n  var whenDone = debounce(function () { more = throttling = false }, wait)\n  return function () {\n    context = this\n    args = arguments\n    var later = function () {\n      timeout = null\n      if (more) func.apply(context, args)\n      whenDone()\n    }\n    if (!timeout) timeout = setTimeout(later, wait)\n    if (throttling) {\n      more = true\n    } else {\n      result = func.apply(context, args)\n    }\n    whenDone()\n    throttling = true\n    return result\n  }\n}\n\nfunction TemporalFlags () {\n  this.timeouts = {}\n  this.flags = {}\n\n  this.getFlag = function (flag) {\n    return this.flags[flag]\n  }\n\n  this.addTemporalFlag = function (flag, timeoutInMillisecons, callback) {\n    window.clearTimeout(this.timeouts[flag])\n    this.flags[flag] = new Date()\n    this.timeouts[flag] = setTimeout(() => {\n      var elapsed = (new Date().getTime()) - this.flags[flag]\n      this.flags[flag] = false\n      callback(elapsed)\n    }, timeoutInMillisecons)\n  }\n\n  this.removeTemporalFlag = function (flag) {\n    window.clearTimeout(this.timeouts[flag])\n    this.flags[flag] = false\n  }\n\n  this.addTemporalProperty = function (name, timeoutInMillisecons, callback) {\n    callback = callback === undefined ? () => {} : callback\n    // name will be used to construct setter and getter\n    this[`is${name}`] = () => {\n      return this.getFlag(name)\n    }\n    this[`set${name}`] = (timeoutOverrride) => {\n      timeoutOverrride = timeoutOverrride !== undefined ? timeoutOverrride : timeoutInMillisecons\n      return this.addTemporalFlag(name, timeoutOverrride, callback)\n    }\n    this[`unset${name}`] = () => {\n      this.removeTemporalFlag(name)\n    }\n  }\n}\n\nfunction PointsTracker (sendMarblesCallback) {\n  this.setMarbleMultiplier = function (type) {\n    if (type === undefined) {\n      this.marbleMultiplierType = ['d', 'r', 'g', 'o', 'b'][Math.floor(Math.random() * 5)]\n    } else {\n      this.marbleMultiplierType = type\n    }\n    this.marbleMultiplier = 1\n    console.log(`Multiplier: ${this.marbleMultiplierType}`)\n  }\n\n  this.trackRemoved = function (removedAmount, marbleType) {\n    let elapsed = (new Date()).getTime() - this.lastRemoveAt\n    this.lastRemoveAt = (new Date()).getTime()\n    this.points.push(\n      [removedAmount, marbleType, this.lastRemoveAt, elapsed]\n    )\n\n    if (marbleType === this.marbleMultiplierType) {\n      this.marbleMultiplier += 1\n      // if removed the marble multiplier color then send 3\n    }\n\n    if (elapsed > 200) {\n      this.combo = 0\n    } else {\n      this.combo += 1\n    }\n\n    if (removedAmount === 5) {\n      this.sendMarblesLoop()\n      this.setMarbleMultiplier(marbleType)\n      return\n    }\n\n    var isMultiplierType = marbleType === this.marbleMultiplierType\n    var baseAmount = 1\n    if (removedAmount === 3) {\n      if (isMultiplierType) {\n        baseAmount = 3\n      } else {\n        baseAmount = 1\n      }\n    } else if (removedAmount === 4) {\n      if (isMultiplierType) {\n        baseAmount = 4\n      } else {\n        baseAmount = 2\n      }\n    }\n    return this.sendMarbles(baseAmount + this.combo * 2)\n  }\n\n  this.sendMarblesLoop = function () {\n    console.log(`Do Loop: ${this.marbleMultiplier}`)\n    for (let i = 1; i <= this.marbleMultiplier; i++) {\n      setTimeout(() => {\n        this.sendMarbles(3)\n      }, i * 1000)\n    }\n  }\n\n  this.sendMarbles = function (amount) {\n    console.log(`Sending: ${amount}`)\n    this.sendMarblesCallback(amount)\n  }\n\n  this.setMarbleMultiplier()\n  this.combo = 0\n  this.lastRemoveAt = (new Date()).getTime()\n  this.points = []\n  this.sendMarblesCallback = sendMarblesCallback\n}\n\nfunction Marble (type) {\n  this.type = type\n  this.isEmpty = type === 'x'\n  this.isNew = true\n  this.addedFromTop = false\n  setTimeout(() => {\n    this.isNew = false\n  }, 550)\n\n  this.tf = new TemporalFlags()\n  this.tf.addTemporalProperty('TranslatingRight', 90)\n  this.tf.addTemporalProperty('MovingDown', 110)\n  this.tf.addTemporalProperty('MovingUp', 110)\n}\n\nfunction Game () {\n  this.initialize = function (container, scoreContainer) {\n    this.container = container\n    this.scoreContainer = scoreContainer\n    this.pointsTracker = new PointsTracker((amount) => {\n      this.sendMarbles(amount)\n    })\n    this.temporalFlags = new TemporalFlags()\n    // animation lock system\n    this.temporalFlags.addTemporalProperty('Locked', 130, (elapsed) => {\n      this.resetAnimations()\n    })\n    // 7 1 7\n    // from left to right\n    // from bottom to top\n    this.columnSize = 15 // must be odd\n    this.center = Math.floor(15 / 2)\n    this.cursor = 2 // column index\n    this.columns = [\n      // 0\n      this.getEmptyColumn(this.columnSize),\n      // 1\n      this.getEmptyColumn(this.columnSize),\n      // 2\n      this.getEmptyColumn(this.columnSize),\n      // 3\n      this.getEmptyColumn(this.columnSize),\n      // 4\n      this.getEmptyColumn(this.columnSize)\n    ]\n    /*\n    for (let i = 0; i < 5; i++) {\n      this.addMarbleFromBottom(this.getRandomMarble(), i)\n      this.addMarbleFromTop(new Marble('r'), i)\n      this.addMarbleFromTop(new Marble('g'), i)\n      this.addMarbleFromTop(new Marble('b'), i)\n      this.addMarbleFromTop(new Marble('d'), i)\n      this.addMarbleFromTop(new Marble('r'), i)\n      this.addMarbleFromTop(new Marble('g'), i)\n      this.addMarbleFromTop(new Marble('b'), i)\n      this.addMarbleFromTop(new Marble('d'), i)\n    }\n    */\n    this.fillColumns()\n    // this marble type will get a bonus\n    this.createDom()\n  }\n\n  this.sendMarbles = function (amount) {\n    this.otherGame.receiveMarbles(amount)\n  }\n\n  this.receiveMarbles = function (amount) {\n    this.attachReceiveMarble(amount)\n    this.addRandomMarbles(amount)\n  }\n\n  this.setOtherPlayerGame = function (game) {\n    this.otherGame = game\n  }\n\n  this.getEmptyColumn = function (size) {\n    var column = []\n    for (var i = 0; i < size; i++) {\n      column.push(\n        new Marble('x')\n      )\n    }\n    return column\n  }\n\n  this.getTopSectionOfColumn = function (columnIndex, includeCenter) {\n    if (includeCenter) {\n      return this.columns[columnIndex].slice(this.center)\n    } else {\n      return this.columns[columnIndex].slice(this.center + 1)\n    }\n  }\n\n  this.getBottomSectionOfcolumn = function (columnIndex, includeCenter) {\n    if (includeCenter) {\n      return this.columns[columnIndex].slice(0, this.center + 1)\n    } else {\n      return this.columns[columnIndex].slice(0, this.center)\n    }\n  }\n\n  this.getNumberOfMarblesInTopSection = function (columnIndex) {\n    // doesn't includes the center one\n    // count x in the top part then substract to the total number of element on the half\n    return this.center - this.getTopSectionOfColumn(columnIndex).filter((marble) => {\n      return marble.isEmpty\n    }).length\n  }\n\n  this.getNumberOfMarblesInBottomSection = function (columnIndex) {\n    // doesn't includes the center one\n    // count x in the bottom part then substract to the total number of element on the half\n    return this.center - this.getBottomSectionOfcolumn(columnIndex).filter((marble) => {\n      return marble.isEmpty\n    }).length\n  }\n\n  this.getNumberOfMarblesInColumn = function (columnIndex) {\n    return this.columnSize - this.columns[columnIndex].filter((marble) => {\n      return marble.isEmpty\n    }).length\n  }\n\n  this.fillColumn = function (columnIndex) {\n    this.temporalFlags.setLocked()\n    let marblesInColumn = this.getNumberOfMarblesInColumn(columnIndex)\n    if (marblesInColumn >= 5) { return }\n    // always try to have the same amount at top and the bototm\n    // the top part of the column\n    // because we could add up 2 substract the number of marbles\n    var shouldAdd = 5 - marblesInColumn\n    var mts = this.getNumberOfMarblesInTopSection(columnIndex)\n    var mbs = this.getNumberOfMarblesInBottomSection(columnIndex)\n\n    if (mts < mbs) {\n      this.addRandomMarbles(1, columnIndex, true)\n    } else {\n      this.addRandomMarbles(1, columnIndex, false)\n    }\n    if (shouldAdd > 1) {\n      this.fillColumn(columnIndex)\n    }\n  }\n\n  this.fillColumns = function () {\n    for (let col = 0; col < 5; col++) {\n      this.fillColumn(col)\n    }\n  }\n\n  this.addRandomMarbles = function (amount, columnIndex, addFromTop) {\n    var col\n    if (columnIndex === undefined) {\n      // randomly adding marbles\n      var columnsIndexes = FisherYatesShuffle([\n        0, 1, 2, 3, 4,\n        0, 1, 2, 3, 4,\n        0, 1, 2, 3, 4\n      ]) // up to 3 marbles per column\n\n      while (amount > 0 && columnsIndexes.length > 0) {\n        col = columnsIndexes.pop()\n        let fromTop = addFromTop === undefined ? Math.random() > 0.5 : addFromTop\n        let addedMarble = false\n        if (fromTop) {\n          addedMarble = this.addMarbleFromTop(this.getRandomMarble(), col)\n        } else {\n          addedMarble = this.addMarbleFromBottom(this.getRandomMarble(), col)\n        }\n        // couldn't add in the requested order try the inverse\n        if (!addedMarble && fromTop) {\n          addedMarble = this.addMarbleFromBottom(this.getRandomMarble(), col)\n        } else if (!addedMarble && fromTop) {\n          addedMarble = this.addMarbleFromTop(this.getRandomMarble(), col)\n        }\n\n        if (addedMarble) {\n          amount -= 1\n        }\n      }\n    } else {\n      // add marbles to the same column multiple times\n      for (let i = 0; i < amount; i++) {\n        var fromTop = addFromTop === undefined ? Math.random() > 0.5 : addFromTop\n        if (fromTop) {\n          this.addMarbleFromTop(this.getRandomMarble(), columnIndex)\n        } else {\n          this.addMarbleFromBottom(this.getRandomMarble(), columnIndex)\n        }\n      }\n    }\n  }\n\n  this.getRandomMarbles = function (amount) {\n    var m = []\n    for (var i = 0; i < amount; i++) {\n      m.push(this.getRandomMarble())\n    }\n    return m\n  }\n\n  this.getRandomMarble = function () {\n    let type = ['d', 'r', 'g', 'o', 'b'][Math.floor(Math.random() * 5)]\n    return new Marble(type)\n  }\n\n  this.checkForEquals = function (howMany, startingAt) {\n    // return true if we have x amount to equals at that point\n    for (let i = startingAt; i < howMany + startingAt - 1; i++) {\n      if (this.columns[i][this.center].type !== this.columns[i + 1][this.center].type) {\n        return false\n      }\n    }\n    return true\n  }\n\n  this.removeMarbles = function (howManyColumns, startingAtColumn) {\n    this.pointsTracker.trackRemoved(\n      howManyColumns,\n      this.columns[startingAtColumn][this.center].type\n    )\n    this.temporalFlags.setLocked()\n    for (let columnIndex = startingAtColumn; columnIndex < howManyColumns + startingAtColumn; columnIndex++) {\n      const column = this.columns[columnIndex]\n      column.splice(this.center, 1)\n      // after removing a marble we know that we can safety add an empty space\n      column.push(new Marble('x'))\n      if (column[this.center].isEmpty) {\n        // the middle is empty after moving everything down\n        // move everythign up by one\n        column.unshift(new Marble('x'))\n        column.pop()\n        this.getBottomSectionOfcolumn(columnIndex, true).forEach((marble) => {\n          marble.tf.setMovingUp()\n        })\n      } else {\n        // all the marbles in the top porting should animate down\n        this.getTopSectionOfColumn(columnIndex, true).forEach((marble) => {\n          marble.tf.setMovingDown()\n        })\n      }\n    }\n    this.fillColumns()\n    return true\n  }\n\n  this.translateCenterRight = function () {\n    if (this.temporalFlags.isLocked()) {\n      return\n    }\n    this.temporalFlags.setLocked()\n    // used to trigger the animation as soon as posible\n    var lastMarble = this.columns[4][this.center]\n    for (let columnIndex = 4; columnIndex > 0; columnIndex--) {\n      // could use swapping this.swapCenterMarbles\n      this.columns[columnIndex][this.center] = this.columns[columnIndex - 1][this.center]\n      this.columns[columnIndex][this.center].tf.setTranslatingRight()\n    }\n    this.columns[0][this.center] = lastMarble\n    this.columns[0][this.center].tf.setTranslatingRight()\n    this.checkCenterMarbles()\n  }\n\n  this._checkAndRemove = function () {\n    if (this.checkForEquals(5, 0)) {\n      return this.removeMarbles(5, 0)\n    }\n    if (this.checkForEquals(4, 0)) {\n      return this.removeMarbles(4, 0)\n    }\n    if (this.checkForEquals(4, 1)) {\n      return this.removeMarbles(4, 1)\n    }\n    if (this.checkForEquals(3, 0)) {\n      return this.removeMarbles(3, 0)\n    }\n    if (this.checkForEquals(3, 1)) {\n      return this.removeMarbles(3, 1)\n    }\n    if (this.checkForEquals(3, 2)) {\n      return this.removeMarbles(3, 2)\n    }\n    return false\n  }\n\n  this.checkCenterMarbles = function () {\n    if (this.temporalFlags.isLocked()) {\n      setTimeout(() => { this.checkCenterMarbles() }, 140)\n      return\n    }\n    // check marbles for lines\n    if (this._checkAndRemove()) {\n      // after removing an element lock\n      this.temporalFlags.setLocked()\n      setTimeout(() => { this.checkCenterMarbles() }, 140)\n    }\n  }\n\n  this.addMarbleFromTop = function (marble, columnIndex) {\n    this.temporalFlags.setLocked()\n    marble.tf.setMovingDown()\n    var added = false\n    var column = this.columns[columnIndex]\n    for (let i = this.center; i < column.length; i++) {\n      if (column[i].isEmpty && !added) {\n        added = true\n        column[i] = marble\n      }\n      // after adding mark all the marbles as moving\n      // this is only for visual effects\n      if (added) {\n        column[i].tf.setMovingDown()\n      }\n    }\n    return added\n  }\n\n  this.addMarbleFromBottom = function (marble, columnIndex) {\n    this.temporalFlags.setLocked()\n    marble.tf.setMovingUp()\n    var added = false\n    var column = this.columns[columnIndex]\n    for (let i = this.center; i >= 0; i--) {\n      if (column[i].isEmpty && !added) {\n        added = true\n        column[i] = marble\n      }\n      // after adding mark all the marbles as moving\n      // this is only for visual effects\n      if (added) {\n        column[i].tf.setMovingUp()\n      }\n    }\n    return added\n  }\n\n  this.doGravity = function (columnIndex) {\n    var marble = this.columns[columnIndex][this.center]\n    if (!marble.isEmpty) {\n      // no need to apply gravity as the center is not empty\n      return\n    }\n    // the middle is empty after doing something\n    // remove the empty slot\n    this.removeMarbles(1, columnIndex)\n  }\n\n  this.swapCenterMarbles = function (colA, colB) {\n    let A = this.columns[colA][this.center]\n    let B = this.columns[colB][this.center]\n    if (A.isEmpty && B.isEmpty) {\n      return\n    }\n    // do the swap\n    this.columns[colA][this.center] = B\n    this.columns[colB][this.center] = A\n    // check either A or B is empty and move up and down as needed\n    this.doGravity(colA)\n    this.doGravity(colB)\n  }\n\n  this.left = function (dragMarble) {\n    // move cursor\n    let oldCursor = this.cursor\n    this.cursor -= 1\n    this.cursor = Math.max(this.cursor, 0)\n    if (dragMarble) {\n      this.swapCenterMarbles(oldCursor, this.cursor)\n    }\n    this.checkCenterMarbles()\n  }\n  this.right = function (dragMarble) {\n    // move cursor\n    let oldCursor = this.cursor\n    this.cursor += 1\n    this.cursor = Math.min(this.cursor, 4)\n    if (dragMarble) {\n      this.swapCenterMarbles(oldCursor, this.cursor)\n    }\n    this.checkCenterMarbles()\n  }\n  this.down = function () {\n    if (this.temporalFlags.isLocked()) {\n      return\n    }\n    // check we have space at the bottom to move everything\n    if (!this.columns[this.cursor][0].isEmpty) {\n      console.log('Doesn\\'t have space at bottom')\n      return\n    }\n    // check if the following item to the center is not an empty space\n    if (this.columns[this.cursor][this.center + 1].isEmpty) {\n      console.log('No marble to move into the center')\n      return\n    }\n    let column = this.columns[this.cursor]\n    let marble = new Marble('x')\n    column.push(marble)\n    column.shift()\n    column.forEach((marble) => {\n      marble.tf.setMovingDown()\n    })\n    this.temporalFlags.setLocked()\n    this.checkCenterMarbles()\n  }\n\n  this.up = function () {\n    if (this.temporalFlags.isLocked()) {\n      return\n    }\n    // check we have space on the top to move everything\n    if (!this.columns[this.cursor][this.columnSize - 1].isEmpty) {\n      console.log('Doesn\\'t have space at top')\n      return\n    }\n    // check if the following item to the center is not an empty space\n    if (this.columns[this.cursor][this.center - 1].isEmpty) {\n      console.log('No marble to move into the center')\n      return\n    }\n    let column = this.columns[this.cursor]\n    column.unshift(new Marble('x'))\n    column.pop()\n    column.forEach((marble) => {\n      marble.tf.setMovingUp()\n    })\n    this.temporalFlags.setLocked()\n    this.checkCenterMarbles()\n  }\n\n  // dom related\n\n  this.resetAnimations = function () {\n    this.columnsDom.forEach((column) => {\n      column.forEach((element) => {\n        element.classList.remove('translate-right')\n        element.classList.remove('moving-up')\n        element.classList.remove('moving-down')\n        void element.offsetWidth\n      })\n    })\n    this.draw()\n  }\n\n  this.setMarbleClasses = function (marble, element) {\n    if (!element.classList.contains(marble.type)) {\n      ['x', 'd', 'r', 'g', 'o', 'b'].forEach((c) => {\n        element.classList.remove(c)\n      })\n      element.classList.add(marble.type)\n    }\n    if (marble.tf.isTranslatingRight()) {\n      element.classList.add('translate-right')\n      element.classList.remove('moving-down')\n      element.classList.remove('moving-up')\n    } else if (marble.tf.isMovingDown()) {\n      element.classList.add('moving-down')\n      element.classList.remove('translate-right')\n      element.classList.remove('moving-up')\n    } else if (marble.tf.isMovingUp()) {\n      element.classList.add('moving-up')\n      element.classList.remove('translate-right')\n      element.classList.remove('moving-down')\n    } else {\n      element.classList.remove('moving-up')\n      element.classList.remove('moving-down')\n      element.classList.remove('translate-right')\n    }\n  }\n\n  this.drawMarble = function (marble, columnIndex, marbleIndex) {\n    let element = this.columnsDom[columnIndex][marbleIndex]\n    this.setMarbleClasses(marble, element)\n    if (marbleIndex === this.center) {\n      if (columnIndex === this.cursor) {\n        this.cursorDom[columnIndex].classList.add('cursor')\n      } else {\n        this.cursorDom[columnIndex].classList.remove('cursor')\n      }\n    }\n  }\n\n  this.draw = function () {\n    this.columns.forEach((column, columnIndex) => {\n      column.forEach((marble, marbleIndex) => {\n        this.drawMarble(marble, columnIndex, marbleIndex)\n      })\n    })\n    this.setMarbleClasses(\n      new Marble(this.pointsTracker.marbleMultiplierType),\n      this.marbleMultiplierDom\n    )\n    this.marbleMultiplierDom.innerText = this.pointsTracker.marbleMultiplier\n  }\n\n  this.throttledDraw = throttle(() => {\n    this.draw()\n  }, 10)\n\n  this.createRowElement = function (parent, isCenter) {\n    let element = document.createElement('div')\n    if (isCenter) {\n      element.className = 'row center'\n    } else {\n      element.className = 'row'\n    }\n    parent.appendChild(element)\n    return element\n  }\n\n  this.createMarbleElement = function (parent) {\n    let element = document.createElement('div')\n    element.className = 'marble'\n    if (parent) {\n      parent.appendChild(element)\n    }\n    return element\n  }\n\n  this.bindAnimationLock = function (element, columnIndex, marbleIndex) {\n    element.addEventListener('animationstart', (e) => {\n      if (e.animationName === 'moving-down' || e.animationName === 'moving-up' || e.animationName === 'translate-right') {\n        this.temporalFlags.setLocked()\n      }\n    })\n  }\n\n  this.attachReceiveMarble = function (amount) {\n    let element = document.createElement('div')\n    element.innerText = `${amount}x`\n    element.addEventListener('animationend', (e) => {\n      element.remove()\n    })\n    this.receiveDom.prepend(element)\n  }\n\n  this.createDom = function () {\n    this.receiveDom = this.scoreContainer.getElementsByClassName('receive')[0]\n    this.marbleMultiplierDom = this.scoreContainer.getElementsByClassName('marble')[0]\n    this.cursorDom = []\n    this.columnsDom = [\n      Array(this.columnSize),\n      Array(this.columnSize),\n      Array(this.columnSize),\n      Array(this.columnSize),\n      Array(this.columnSize)\n    ]\n    for (let marbleIndex = this.columnSize - 1; marbleIndex >= 0; marbleIndex--) {\n      var row = this.createRowElement(this.container)\n      var element\n      for (let columnIndex = 0; columnIndex < 5; columnIndex++) {\n        element = this.createMarbleElement(row)\n        this.columnsDom[columnIndex][marbleIndex] = element\n        this.bindAnimationLock(element, columnIndex, marbleIndex)\n      }\n      if (marbleIndex === this.center) {\n        row = this.createRowElement(this.container, true)\n        for (let columnIndex = 0; columnIndex < 5; columnIndex++) {\n          this.cursorDom[columnIndex] = this.createMarbleElement(row)\n        }\n      }\n    }\n  }\n}\n\nlet gameP1 = new Game()\nlet gameP2 = new Game()\n\ngameP1.setOtherPlayerGame(gameP2)\ngameP2.setOtherPlayerGame(gameP1)\n\nwindow.addEventListener('keydown', (e) => {\n  switch (e.which) {\n    case 37:\n      // 37 left\n      gameP2.left()\n      break\n    case 38:\n      // 38 up\n      gameP2.up()\n      break\n    case 39:\n      // 39 right\n      gameP2.right()\n      break\n    case 40:\n      // 40 down\n      gameP2.down()\n      break\n    case 76:\n      // L\n      gameP2.translateCenterRight()\n      break\n\n    // Player on the left\n    case 83:\n      // S left\n      gameP1.left()\n      break\n    case 69:\n      // E up\n      gameP1.up()\n      break\n    case 70:\n      // F right\n      gameP1.right()\n      break\n    case 68:\n      // D down\n      gameP1.down()\n      break\n    case 81:\n      // Q\n      gameP1.translateCenterRight()\n      break\n    default:\n      console.log(e.which)\n  }\n})\n\nwindow.addEventListener('load', function () {\n  gameP1.initialize(\n    document.getElementById('p1'),\n    document.getElementById('p1-score')\n  )\n  gameP2.initialize(\n    document.getElementById('p2'),\n    document.getElementById('p2-score')\n  )\n  setInterval(() => {\n    gameP1.checkCenterMarbles()\n    gameP2.checkCenterMarbles()\n    gameP1.draw()\n    gameP2.draw()\n  }, 20)\n})\n\nconsole.log(`\nThe keys are for the player on the left\nUp and Down with \"e\" \"d\"\nMove Cursor Left and right with \"s\" \"f\"\nRotate Center with \"q\"\n\nThe keys are for the player on the right\nArrow Keys for movement\nRotate Center with \"l\"\n\n`)\n\nexport default gameP1\n"]}