//===== Constructor const Controls = function() { this.moves = 0; this.names = {}; this.timers = {}; this.currentWinningGuess = Infinity; this.drawGuesses(); document.addEventListener('L-connected', this.msgConnected.bind(this)); document.addEventListener('L-move', this.msgMove.bind(this)); // Message handlers: "Local message" and "Global message" // document.addEventListener('G-move', this.msgMove.bind(this)); // document.addEventListener('G-win', this.msgWin.bind(this)); document.addEventListener('G-attempt', this.msgAttempt.bind(this)); document.addEventListener('G-guess', this.msgGuess.bind(this)); document.addEventListener('G-skip', this.msgSkip.bind(this)); document.addEventListener('G-start', this.msgStart.bind(this)); document.addEventListener('G-stop', this.msgStop.bind(this)); document.addEventListener('G-players', this.msgPlayers.bind(this)); // Click handlers document.getElementById('controls-start').addEventListener('click', this.onClickStart.bind(this)); document.getElementById('controls-stop').addEventListener('click', this.onClickStop.bind(this)); document.getElementById('controls-walls').addEventListener('click', this.onClickWalls.bind(this)); document.getElementById('controls-robots').addEventListener('click', this.onClickRobots.bind(this)); document.getElementById('controls-reset').addEventListener('click', this.onClickReset.bind(this)); document.getElementById('controls-skip').addEventListener('click', this.onClickSkip.bind(this)); } //===== UI Controls.prototype.countdownStart = function(seconds) { clearTimeout(this.timers.countdown); this.timers.countdown = this.countdownTick.bind(this); const countdown = document.getElementById('controls-countdown'); countdown.dataset.tick = seconds; this.countdownTick(); }; Controls.prototype.countdownTick = function() { const countdown = document.getElementById('controls-countdown'); const tick = countdown.dataset.tick * 1; countdown.dataset.tick = tick - 1; const s = (tick !== 1) ? 's' : ''; countdown.innerHTML = `${tick} second${s}!`; if (tick === 0) { this.countdownComplete(); return; } this.timers.countdown = setTimeout(this.countdownTick.bind(this), 1000); }; Controls.prototype.countdownComplete = function() { document.getElementById('controls-countdown').dataset.tick = 0; } ; Controls.prototype.drawGuesses = function() { const container = document.getElementById('controls-guesses'); container.querySelectorAll('.controls-guess').forEach(el => el.parentNode.removeChild(el)); for (let i = 1; i <= 30; i++) { const guess = document.createElement('div'); guess.className = 'controls-guess'; guess.innerHTML = i; guess.setAttribute('data-value', i); guess.addEventListener('click', this.onClickGuess.bind(this)) container.appendChild(guess); } }; Controls.prototype.showWaiting = function() { document.getElementById('controls-start').parentNode.style.display = ''; document.getElementById('controls-walls').parentNode.style.display = ''; document.getElementById('controls-robots').parentNode.style.display = ''; document.getElementById('controls-stop').parentNode.style.display = 'none'; // document.getElementById('controls-moves-reset').parentNode.style.display = 'none'; document.getElementById('controls-guesses').style.display = 'none'; document.getElementById('controls-panic').style.display = 'none'; }; Controls.prototype.showGuessing = function() { document.getElementById('controls-start').parentNode.style.display = 'none'; document.getElementById('controls-walls').parentNode.style.display = 'none'; document.getElementById('controls-robots').parentNode.style.display = 'none'; document.getElementById('controls-panic').style.display = 'none'; document.getElementById('controls-stop').parentNode.style.display = ''; // document.getElementById('controls-moves-reset').parentNode.style.display = ''; document.getElementById('controls-guesses').style.display = ''; } Controls.prototype.showPanic = function() { this.showGuessing(); document.getElementById('controls-panic').style.display = ''; }; //===== Message handlers Controls.prototype.msgAttempt = function() { alert("Ready for winning attempt!"); }; Controls.prototype.msgGuess = function(evt) { const blurbs = [ " has a solution: ", " can do it in ", " says, maybe ", " wagers ", " reckons ", " is pretty sure it's ", ", confidently: ", " wants it to be ", " says ", " hazards ", " guesses ", " thinks it might be "]; const blurb = blurbs[Math.floor(Math.random() * blurbs.length)]; const msg = evt.detail; const guess = msg.guess; this.currentWinningGuess = guess; document.getElementById('controls-panic').querySelector('.controls-alert-urgent').innerHTML = (`${this.names[msg.id]}${blurb}${guess} moves.`); this.showPanic(); this.countdownStart(5); } Controls.prototype.msgConnected = function() { this.showWaiting(); }; Controls.prototype.msgMove = function() { this.moves++; document.getElementById('controls-moves').innerHTML = this.moves; }; Controls.prototype.msgPlayers = function(evt) { const container = document.getElementById('controls-players'); const names = evt.detail.body; const keys = Object.keys(names); if (keys.length > 0) { const nobody = document.getElementById('controls-players-nobody'); nobody && nobody.parentNode.removeChild(nobody); } keys.forEach(connectionId => { const id = `player-${connectionId}`; if (document.getElementById(id)) { return; } const n = document.createElement('div'); n.id = id; n.innerHTML = names[connectionId]; n.className = 'controls-player'; container.appendChild(n) }); this.names = names; container.querySelectorAll('.controls-player').forEach(el => { const id = el.id.split('player-').pop(); if (!this.names[id]) { container.removeChild(el); } }); }; Controls.prototype.msgSkip = function() { this.coundownComplete(); }; Controls.prototype.msgStart = function() { this.showGuessing(); }; Controls.prototype.msgStop = function() { this.showWaiting(); } //===== Click handlers Controls.prototype.dispatch = function(evt, data) { const e = (data ? new CustomEvent(evt, { detail: data }) : new Event(evt)); document.dispatchEvent(e); } Controls.prototype.onClickGuess = function(evt) { const guess = evt.currentTarget.dataset.value * 1; if (!guess || guess < 1) { return; } if (guess < this.currentWinningGuess) { this.dispatch('L-guess', { moves: evt.currentTarget.dataset.value }); } else { alert(`That doesn't beat ${this.currentWinningGuess} - try again!`) } } Controls.prototype.onClickRobots = function() { this.dispatch('L-robots'); } Controls.prototype.onClickSkip = function() { this.dispatch('L-skip'); } Controls.prototype.onClickStart = function() { this.dispatch('L-start'); } Controls.prototype.onClickStop = function() { this.dispatch('L-stop'); } Controls.prototype.onClickWalls = function() { this.dispatch('L-walls'); } Controls.prototype.onClickReset = function() { this.moves = 0; document.getElementById('controls-moves').innerHTML = this.moves; this.dispatch('L-reset'); };