From 8231c8eb577386d663adc72d4d678575a58184a0 Mon Sep 17 00:00:00 2001 From: Joshua Cold Date: Sun, 17 Mar 2024 19:21:56 -0600 Subject: [PATCH 1/4] New buttons to show mistake without team and reset mistakes --- components/admin.js | 47 +++++++++++++++++++++++++++++++++------------ pages/game.js | 23 +++++++++++++++++----- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/components/admin.js b/components/admin.js index a05a7d57..ee52332d 100644 --- a/components/admin.js +++ b/components/admin.js @@ -82,22 +82,23 @@ function FinalRoundButtonControls(props) { return controlRound?.map((x, i) => (

{x.question}

- {props.game.is_final_second && + {props.game.is_final_second && (
{/* PARTNER'S ANSWER PROVIDED FINAL ROUND */}
- {t("Partner's Answer")}: {props.game.final_round[i].input || `(${t("No Answer")})`} + {t("Partner's Answer")}:{" "} + {props.game.final_round[i].input || `(${t("No Answer")})`}
- {props.game.final_round[i].input && + {props.game.final_round[i].input && ( - } + )}
- } + )}
{/* ANSWER PROVIDED FINAL ROUND */} { - x.points = (x.selection !== -1) ? x.answers[x.selection][1] : 0; + x.points = x.selection !== -1 ? x.answers[x.selection][1] : 0; props.setGame((prv) => ({ ...prv })); props.send({ action: "data", data: props.game }); - props.send({ action: (x.selection !== -1) ? "final_submit" : "mistake" }); + props.send({ + action: x.selection !== -1 ? "final_submit" : "mistake", + }); }} > {t("Award points")} @@ -227,7 +230,7 @@ function TitleLogoUpload(props) { if (fileSize > 2098) { console.error("Logo image is too large"); props.setError( - t("Logo image is too large. 2MB is the limit") + t("Logo image is too large. 2MB is the limit"), ); return; } @@ -237,7 +240,7 @@ function TitleLogoUpload(props) { rawData = evt.target.result; var headerarr = new Uint8Array(evt.target.result).subarray( 0, - 4 + 4, ); var header = ""; for (var i = 0; i < headerarr.length; i++) { @@ -276,7 +279,7 @@ function TitleLogoUpload(props) { }; reader.readAsArrayBuffer(file); } - document.getElementById("logoUpload").value = null + document.getElementById("logoUpload").value = null; }} />
@@ -389,7 +392,7 @@ export default function Admin(props) { setInterval(() => { if (ws.current.readyState !== 1) { setError( - `lost connection to server refreshing in ${10 - refreshCounter}` + `lost connection to server refreshing in ${10 - refreshCounter}`, ); refreshCounter++; if (refreshCounter >= 10) { @@ -567,7 +570,7 @@ export default function Admin(props) { setError(t("Unknown file type in game load")); } // allow same file to be selected again - document.getElementById("gamePicker").value = null + document.getElementById("gamePicker").value = null; }} />
@@ -807,6 +810,26 @@ export default function Admin(props) { > {t("Next Round")} + + {/* GETS POINTS MISTAKE */} diff --git a/pages/game.js b/pages/game.js index 7dea9ac5..0770f5f2 100644 --- a/pages/game.js +++ b/pages/game.js @@ -15,6 +15,7 @@ export default function Game(props) { const [game, setGame] = useState({}); const [timer, setTimer] = useState(0); const [error, setErrorVal] = useState(""); + const [showMistake, setShowMistake] = useState(false); const ws = useRef(null); let refreshCounter = 0; @@ -35,13 +36,13 @@ export default function Game(props) { if (session != null) { console.debug("found user session", session); ws.current.send( - JSON.stringify({ action: "game_window", session: session }) + JSON.stringify({ action: "game_window", session: session }), ); setInterval(() => { console.debug("sending pong in game window"); let [room, id] = session.split(":"); ws.current.send( - JSON.stringify({ action: "pong", id: id, room: room }) + JSON.stringify({ action: "pong", id: id, room: room }), ); }, 5000); } @@ -66,9 +67,18 @@ export default function Game(props) { })}`; } setGame(json.data); - } else if (json.action === "mistake") { + } else if ( + json.action === "mistake" || + json.action === "show_mistake" + ) { var audio = new Audio("wrong.mp3"); audio.play(); + if (json.action === "show_mistake") { + setShowMistake(true); + setTimeout(() => { + setShowMistake(false) + }, 3000); + } } else if (json.action === "quit") { setGame({}); window.close(); @@ -115,7 +125,7 @@ export default function Game(props) { setInterval(() => { if (ws.current.readyState !== 1) { setError( - `lost connection to server refreshing in ${5 - refreshCounter}` + `lost connection to server refreshing in ${5 - refreshCounter}`, ); refreshCounter++; if (refreshCounter >= 5) { @@ -155,10 +165,13 @@ export default function Game(props) { } if (typeof window !== "undefined") { - document.body.className= game?.settings?.theme + " bg-background"; + document.body.className = game?.settings?.theme + " bg-background"; } return ( <> +
+ +
{gameSession} From eb71de44384518a2a0159b2cea7fbf145f779401 Mon Sep 17 00:00:00 2001 From: Joshua Cold Date: Sun, 24 Mar 2024 13:54:34 -0600 Subject: [PATCH 2/4] Finish stylizing the mistake overlay --- components/buzzer.js | 197 +++++++++++++++++++++++-------------------- pages/game.js | 14 ++- 2 files changed, 110 insertions(+), 101 deletions(-) diff --git a/components/buzzer.js b/components/buzzer.js index bf9d7322..f8314624 100644 --- a/components/buzzer.js +++ b/components/buzzer.js @@ -17,6 +17,7 @@ export default function Buzzer(props) { const [buzzerReg, setBuzzerReg] = useState(null); const [error, setErrorVal] = useState(""); const [timer, setTimer] = useState(0); + const [showMistake, setShowMistake] = useState(false); let refreshCounter = 0; function setError(e) { @@ -29,7 +30,7 @@ export default function Buzzer(props) { let game = props.game; let ws = props.ws; - const send = function (data) { + const send = function(data) { data.room = props.room; data.id = props.id; ws.current.send(JSON.stringify(data)); @@ -39,7 +40,7 @@ export default function Buzzer(props) { setInterval(() => { if (ws.current.readyState !== 1) { setError( - `lost connection to server refreshing in ${10 - refreshCounter}` + `lost connection to server refreshing in ${10 - refreshCounter}`, ); refreshCounter++; if (refreshCounter >= 10) { @@ -62,6 +63,15 @@ export default function Buzzer(props) { // server gets the average latency periodically console.debug(props.id); send({ action: "pong", id: props.id }); + } else if (json.action === "mistake" || json.action === "show_mistake") { + var audio = new Audio("wrong.mp3"); + audio.play(); + if (json.action === "mistake" || json.action === "show_mistake") { + setShowMistake(true); + setTimeout(() => { + setShowMistake(false); + }, 2000); + } } else if (json.action === "quit") { props.setGame(null); props.setTeam(null); @@ -112,6 +122,12 @@ export default function Buzzer(props) { console.debug(game); return ( <> + + <> + {props.game.settings.logo_url ? ( + + ) : ( + + )} +
+

+ {t("team")}:{" "} + {props.team != null + ? game.teams[props.team].name + : t("pick your team")} +

+
+
+ - -
-
- -
- {error != null && error !== "" ?

👾 {error}

: null} - - )} + +
+
+ +
+ {error != null && error !== "" ?

👾 {error}

: null} + + )} ); } else { diff --git a/pages/game.js b/pages/game.js index 0770f5f2..5ec0333a 100644 --- a/pages/game.js +++ b/pages/game.js @@ -73,12 +73,10 @@ export default function Game(props) { ) { var audio = new Audio("wrong.mp3"); audio.play(); - if (json.action === "show_mistake") { - setShowMistake(true); - setTimeout(() => { - setShowMistake(false) - }, 3000); - } + setShowMistake(true); + setTimeout(() => { + setShowMistake(false) + }, 2000); } else if (json.action === "quit") { setGame({}); window.close(); @@ -169,8 +167,8 @@ export default function Game(props) { } return ( <> -
- +
+
From e63e9f7c1ee34a4c7876db580b91e2e2e9c37b86 Mon Sep 17 00:00:00 2001 From: Joshua Cold Date: Sun, 24 Mar 2024 13:54:48 -0600 Subject: [PATCH 3/4] Format ws.j2 --- pages/api/ws.js | 70 ++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/pages/api/ws.js b/pages/api/ws.js index 4d0d6e70..99aa7527 100644 --- a/pages/api/ws.js +++ b/pages/api/ws.js @@ -3,7 +3,7 @@ const { v4: uuidv4 } = require("uuid"); const fs = require("fs"); const glob = require("glob"); const bson = require("bson"); -import * as loadGame from "backend/load-game" +import * as loadGame from "backend/load-game"; const ioHandler = (req, res) => { if (!res.socket.server.ws) { @@ -20,7 +20,7 @@ const ioHandler = (req, res) => { var charactersLength = characters.length; for (var i = 0; i < length; i++) { result.push( - characters.charAt(Math.floor(Math.random() * charactersLength)) + characters.charAt(Math.floor(Math.random() * charactersLength)), ); } return result.join(""); @@ -51,7 +51,7 @@ const ioHandler = (req, res) => { room.intervals[id] = interval; console.debug( "room.intervals length => ", - Object.keys(room.intervals).length + Object.keys(room.intervals).length, ); } @@ -120,7 +120,7 @@ const ioHandler = (req, res) => { round: 0, }; - wss.broadcast = function (room, data) { + wss.broadcast = function(room, data) { if (rooms[room]) { Object.keys(rooms[room].connections).forEach((rp) => { rooms[room].connections[rp].send(data); @@ -143,13 +143,13 @@ const ioHandler = (req, res) => { if (rooms[message.room].game) { if (message.action !== "pong") { // Show in logs if there are any active players - console.debug(`Tick => ${message.room} ${message.action}`) + console.debug(`Tick => ${message.room} ${message.action}`); } rooms[message.room].game.tick = new Date().getTime(); } } } - } + }; setInterval(() => { for (const [room, roomData] of Object.entries(rooms)) { @@ -163,7 +163,7 @@ const ioHandler = (req, res) => { JSON.stringify({ action: "error", message: "game closed, no activity for 1 hour", - }) + }), ); delete rooms[room]; cleanUpPublicRoomAssets(room); @@ -195,25 +195,25 @@ const ioHandler = (req, res) => { JSON.stringify({ action: "error", message: "Error parsing data in server", - }) + }), ); return; } // If there is activity in this room, do not clear - setTick(message) + setTick(message); // TODO seperate each of these into seperate functions if (message.action === "load_game") { if (message.file != null && message.lang != null) { let data = fs.readFileSync( - `games/${message.lang}/${message.file}` + `games/${message.lang}/${message.file}`, ); let loaded = data.toString(); message.data = JSON.parse(loaded); } - let loadGameData = loadGame.addGameKeys(message.data) + let loadGameData = loadGame.addGameKeys(message.data); let game = rooms[message.room].game; game.teams[0].points = 0; @@ -229,7 +229,7 @@ const ioHandler = (req, res) => { game.point_tracker = new Array(loadGameData.rounds.length).fill(0); wss.broadcast( message.room, - JSON.stringify({ action: "data", data: game }) + JSON.stringify({ action: "data", data: game }), ); } else if (message.action === "host_room") { // loop until we find an available room code @@ -254,14 +254,14 @@ const ioHandler = (req, res) => { room: roomCode, game: rooms[roomCode].game, id: id, - }) + }), ); } else if (message.action === "game_window") { let [room_code, user_id] = message.session.split(":"); rooms[room_code].connections[`game_window_${uuidv4()}`] = ws; wss.broadcast( room_code, - JSON.stringify({ action: "data", data: rooms[room_code].game }) + JSON.stringify({ action: "data", data: rooms[room_code].game }), ); } else if (message.action === "join_room") { let roomCode = message.room.toUpperCase(); @@ -274,12 +274,12 @@ const ioHandler = (req, res) => { room: roomCode, game: rooms[roomCode].game, id: id, - }) + }), ); } else { // TODO errors sent from server should be internationalized ws.send( - JSON.stringify({ action: "error", message: "room not found" }) + JSON.stringify({ action: "error", message: "room not found" }), ); } } else if (message.action === "quit") { @@ -287,7 +287,7 @@ const ioHandler = (req, res) => { "user quit game", message.room, message.id, - message.host + message.host, ); if (message.host) { wss.broadcast(message.room, JSON.stringify({ action: "quit" })); @@ -296,7 +296,7 @@ const ioHandler = (req, res) => { JSON.stringify({ action: "error", message: "host quit the game", - }) + }), ); // if host quits then we need to clean up the running intervals @@ -310,7 +310,7 @@ const ioHandler = (req, res) => { // clear ws from server if (rooms[message.room].connections) { for (const [id, ws_entry] of Object.entries( - rooms[message.room].connections + rooms[message.room].connections, )) { ws_entry.close(); } @@ -338,7 +338,7 @@ const ioHandler = (req, res) => { JSON.stringify({ action: "data", data: rooms[message.room].game, - }) + }), ); } } else if (message.action === "get_back_in") { @@ -349,7 +349,7 @@ const ioHandler = (req, res) => { "user session get_back_in:", room_code, user_id, - team + team, ); // set the new websocket connection rooms[room_code].connections[user_id] = ws; @@ -361,7 +361,7 @@ const ioHandler = (req, res) => { id: user_id, player: rooms[room_code].game.registeredPlayers[user_id], team: parseInt(team), - }) + }), ); if (Number.isInteger(parseInt(team))) { @@ -384,13 +384,13 @@ const ioHandler = (req, res) => { game.buzzed = []; wss.broadcast( message.room, - JSON.stringify({ action: "clearbuzzers" }) + JSON.stringify({ action: "clearbuzzers" }), ); } // get the current time to compare when users buzz in wss.broadcast( message.room, - JSON.stringify({ action: "data", data: game }) + JSON.stringify({ action: "data", data: game }), ); } else if (message.action === "registerbuzz") { let id = message.id; @@ -405,7 +405,7 @@ const ioHandler = (req, res) => { ws.send(JSON.stringify({ action: "registered", id: id })); wss.broadcast( message.room, - JSON.stringify({ action: "data", data: game }) + JSON.stringify({ action: "data", data: game }), ); } catch (e) { console.error("Problem in register ", e); @@ -429,17 +429,17 @@ const ioHandler = (req, res) => { game.buzzed = []; wss.broadcast( message.room, - JSON.stringify({ action: "data", data: game }) + JSON.stringify({ action: "data", data: game }), ); wss.broadcast( message.room, - JSON.stringify({ action: "clearbuzzers" }) + JSON.stringify({ action: "clearbuzzers" }), ); } else if (message.action === "change_lang") { glob( `**/*.json`, { cwd: `games/${message.data}/` }, - function (err, files) { + function(err, files) { // files is an array of filenames. // If the `nonull` option is set, and nothing // was found, then files is ["**/*.js"] @@ -458,9 +458,9 @@ const ioHandler = (req, res) => { action: "change_lang", data: message.data, games: files.sort(collator.compare), - }) + }), ); - } + }, ); } else if (message.action === "buzz") { let game = rooms[message.room].game; @@ -485,7 +485,7 @@ const ioHandler = (req, res) => { ws.send(JSON.stringify({ action: "buzzed" })); wss.broadcast( message.room, - JSON.stringify({ action: "data", data: game }) + JSON.stringify({ action: "data", data: game }), ); } else if (message.action === "logo_upload") { let dirpath = `./public/rooms/${message.room}/`; @@ -497,7 +497,7 @@ const ioHandler = (req, res) => { JSON.stringify({ action: "error", message: "Image too large", - }) + }), ); return; } @@ -526,7 +526,7 @@ const ioHandler = (req, res) => { JSON.stringify({ action: "error", message: "Unknown file type in image upload", - }) + }), ); return; } @@ -541,7 +541,7 @@ const ioHandler = (req, res) => { if (err != null) { console.error("Error saving logo file", err); } - } + }, ); } catch (e) { console.error("Error in logo upload", e); @@ -562,7 +562,7 @@ const ioHandler = (req, res) => { JSON.stringify({ action: "error", message: `Error on server: ${e}`, - }) + }), ); } }); From d2a5bc5a8b297f642cbfe5cde87163833b754ad7 Mon Sep 17 00:00:00 2001 From: Joshua Cold Date: Sun, 24 Mar 2024 14:37:54 -0600 Subject: [PATCH 4/4] Show mistake x in button instead of text --- components/admin.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/admin.js b/components/admin.js index ee52332d..0ee1852a 100644 --- a/components/admin.js +++ b/components/admin.js @@ -811,18 +811,18 @@ export default function Admin(props) { {t("Next Round")}