Show strikes on controller
This commit is contained in:
parent
0c1722a330
commit
0df4f8d489
4 changed files with 77 additions and 20 deletions
|
@ -187,6 +187,8 @@ def status():
|
||||||
for address, state
|
for address, state
|
||||||
in sorted(serial_to_web.registered_modules.items(), key=(lambda kv: kv[0].as_binary()))
|
in sorted(serial_to_web.registered_modules.items(), key=(lambda kv: kv[0].as_binary()))
|
||||||
]
|
]
|
||||||
|
status_dict['max_allowed_strikes'] = web_to_serial.max_allowed_strikes
|
||||||
|
status_dict['game_duration'] = web_to_serial.game_duration.total_seconds()
|
||||||
print(status_dict)
|
print(status_dict)
|
||||||
return jsonify(status_dict)
|
return jsonify(status_dict)
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,12 @@
|
||||||
<div>Game state: <span id="gamestate"></span></div>
|
<div>Game state: <span id="gamestate"></span></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Strikes -->
|
||||||
|
<div class="box" id="strikeContainer">
|
||||||
|
<div>Strikes</div>
|
||||||
|
<div id="strikeIndicatorContainer"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Actions -->
|
<!-- Actions -->
|
||||||
<div>
|
<div>
|
||||||
<button id="buttonStart" onclick="onStartButtonClick()">START</button>
|
<button id="buttonStart" onclick="onStartButtonClick()">START</button>
|
||||||
|
|
|
@ -94,6 +94,27 @@ button:disabled {
|
||||||
margin: 8px;
|
margin: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#strikeContainer {
|
||||||
|
text-align: center;
|
||||||
|
height: 4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#strikeContainer .strikeIndicator {
|
||||||
|
padding: 20px;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-weight: 900
|
||||||
|
}
|
||||||
|
|
||||||
|
#strikeContainer .inactive {
|
||||||
|
color: #ff000033;
|
||||||
|
}
|
||||||
|
|
||||||
|
#strikeContainer .active {
|
||||||
|
color: #ff0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.solved {
|
.solved {
|
||||||
background-color: green !important;
|
background-color: green !important;
|
||||||
color: white !important;
|
color: white !important;
|
||||||
|
|
|
@ -24,6 +24,12 @@ const state = {
|
||||||
|
|
||||||
// If the alarm has been played already
|
// If the alarm has been played already
|
||||||
alarmPlayed: false,
|
alarmPlayed: false,
|
||||||
|
|
||||||
|
// Number of mistakes allowed without exploding the bomb
|
||||||
|
maxAllowedStrikes: 0,
|
||||||
|
|
||||||
|
// Time on the timer at the beginning of a game
|
||||||
|
gameDuration: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,6 +81,22 @@ function updateModules(puzzles) {
|
||||||
modulesElement.replaceChildren(...modules);
|
modulesElement.replaceChildren(...modules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateStrikes() {
|
||||||
|
const indicators = [];
|
||||||
|
for (let idx = 0; idx < state.maxAllowedStrikes; idx++) {
|
||||||
|
let indicator = document.createElement("span");
|
||||||
|
indicator.classList.add('strikeIndicator');
|
||||||
|
indicator.textContent = '!';
|
||||||
|
if (idx < state.strikes) {
|
||||||
|
indicator.classList.add('active');
|
||||||
|
} else {
|
||||||
|
indicator.classList.add('inactive');
|
||||||
|
}
|
||||||
|
indicators.push(indicator);
|
||||||
|
}
|
||||||
|
document.getElementById("strikeIndicatorContainer").replaceChildren(...indicators);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the game state.
|
* Initialize the game state.
|
||||||
*/
|
*/
|
||||||
|
@ -92,11 +114,13 @@ function updateGameState() {
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
// Update the game state
|
// Update the game state
|
||||||
state.gamestate = data.gamestate;
|
state.gamestate = data.gamestate;
|
||||||
|
state.gameDuration = data.game_duration;
|
||||||
|
state.maxAllowedStrikes = data.max_allowed_strikes;
|
||||||
document.getElementById("gamestate").innerHTML = state.gamestate;
|
document.getElementById("gamestate").innerHTML = state.gamestate;
|
||||||
|
|
||||||
// Reset the strike amount if the game is not running anymore.
|
// Reset the strike amount if the game is not running anymore.
|
||||||
if (state.gamestate != "GAME") {
|
if (state.gamestate === "INACTIVE") {
|
||||||
state.strikeAmount = 0;
|
state.strikes = 0;
|
||||||
state.alarmPlayed = false;
|
state.alarmPlayed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,19 +135,17 @@ function updateGameState() {
|
||||||
.map((p) => p.strikes)
|
.map((p) => p.strikes)
|
||||||
.reduce((a, b) => a + b, 0);
|
.reduce((a, b) => a + b, 0);
|
||||||
|
|
||||||
// Play a "buzzer" sound when a strike is made.
|
// Play a "buzzer" sound when a strike is made and update total amount of strikes.
|
||||||
if (state.strikes < newStrikes) {
|
if (state.strikes < newStrikes) {
|
||||||
playSound(sounds.strike);
|
playSound(sounds.strike);
|
||||||
|
state.strikes = newStrikes;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Play a "alarm" sound when the time is at 10 seconds.
|
// Play a "alarm" sound when the time is at 20 seconds.
|
||||||
if (data.timeleft <= 20 && data.timeleft > 19 && !state.alarmPlayed) {
|
if (data.timeleft <= 20 && data.timeleft > 19 && !state.alarmPlayed) {
|
||||||
playSound(sounds.alarm);
|
playSound(sounds.alarm);
|
||||||
state.alarmPlayed = true;
|
state.alarmPlayed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the total amount of strikes
|
|
||||||
state.strikes = newStrikes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the start/restart button visibility.
|
// Update the start/restart button visibility.
|
||||||
|
@ -134,6 +156,7 @@ function updateGameState() {
|
||||||
|
|
||||||
// Update the modules
|
// Update the modules
|
||||||
updateModules(data.puzzles);
|
updateModules(data.puzzles);
|
||||||
|
updateStrikes();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,23 +196,12 @@ function initializeSegmentDisplay() {
|
||||||
setInterval(updateSegmentDisplay, 100);
|
setInterval(updateSegmentDisplay, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function setTimeleft(timeLeft) {
|
||||||
* Update the segment display with the latest game data.
|
|
||||||
*/
|
|
||||||
function updateSegmentDisplay() {
|
|
||||||
// Do not update the timer when the game is not running.
|
|
||||||
if (state.gamestate != "GAME" || !state.estimatedTimeout) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const timeLeft = (state.estimatedTimeout - new Date()) / 1000;
|
|
||||||
|
|
||||||
// Set the display to 0 when there is no time left.
|
// Set the display to 0 when there is no time left.
|
||||||
if (timeLeft <= 0) {
|
if (isNaN(timeLeft) || timeLeft <= 0) {
|
||||||
display.setValue("00:00.0");
|
display.setValue("00:00.0");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const integral = Math.floor(timeLeft);
|
const integral = Math.floor(timeLeft);
|
||||||
const fractional = timeLeft - integral;
|
const fractional = timeLeft - integral;
|
||||||
const minutes = Math.floor(integral / 60);
|
const minutes = Math.floor(integral / 60);
|
||||||
|
@ -202,6 +214,22 @@ function updateSegmentDisplay() {
|
||||||
display.setValue(`${minutesStr}:${secondsStr}.${fractionalStr}`);
|
display.setValue(`${minutesStr}:${secondsStr}.${fractionalStr}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the segment display with the latest game data.
|
||||||
|
*/
|
||||||
|
function updateSegmentDisplay() {
|
||||||
|
console.log(state.gamestate);
|
||||||
|
if (state.gamestate === "INACTIVE" || state.gamestate === "INFO" || state.gamestate === "DISCOVER") {
|
||||||
|
setTimeleft(state.gameDuration);
|
||||||
|
}
|
||||||
|
// Do not update the timer when the game is not running.
|
||||||
|
else if (state.gamestate != "GAME" || !state.estimatedTimeout) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
setTimeleft((state.estimatedTimeout - new Date()) / 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When the window is loaded.
|
* When the window is loaded.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue