From 3a441f93db7cff52cebea335d265ce684c2e383e Mon Sep 17 00:00:00 2001 From: Jonas Tranberg Date: Sat, 27 Jul 2024 18:45:28 +0200 Subject: [PATCH] fix game exit and finish --- public/blackheart.svg | 4 +- public/whiteheart.svg | 4 +- src/api/websocket/index.tsx | 1 - src/stores/game.mapper.ts | 21 ++++-- src/stores/game.ts | 64 +++++++++++++++++-- src/views/Game/components/Chart.tsx | 2 - src/views/Game/components/DNFDialog.tsx | 4 -- .../Game/components/GamFinishedDialog.tsx | 19 ++++-- src/views/Game/components/Header.tsx | 7 +- 9 files changed, 98 insertions(+), 28 deletions(-) diff --git a/public/blackheart.svg b/public/blackheart.svg index 1c2d445..adfcd39 100644 --- a/public/blackheart.svg +++ b/public/blackheart.svg @@ -1,3 +1,5 @@ - + diff --git a/public/whiteheart.svg b/public/whiteheart.svg index f100872..2fb5b93 100644 --- a/public/whiteheart.svg +++ b/public/whiteheart.svg @@ -1,3 +1,5 @@ - + diff --git a/src/api/websocket/index.tsx b/src/api/websocket/index.tsx index ac8b834..06fcf20 100644 --- a/src/api/websocket/index.tsx +++ b/src/api/websocket/index.tsx @@ -34,7 +34,6 @@ const useWebSocket = () => { const send = (data: any) => { if (socket) { - console.log("sending", data); socket.send(JSON.stringify(data)); } }; diff --git a/src/stores/game.mapper.ts b/src/stores/game.mapper.ts index 5510d12..6f3bcef 100644 --- a/src/stores/game.mapper.ts +++ b/src/stores/game.mapper.ts @@ -1,8 +1,18 @@ import { Game } from "../api/models/game"; -import { CardValues } from "../models/card"; import { GameState } from "./game"; -const mapToRemote = (state: GameState): Game => { +const mapToRemote = ( + state: GameState, + options: { + dnf: boolean; + has_ended: boolean; + description?: string; + } = { + dnf: false, + has_ended: false, + description: undefined, + }, +): Game => { return { id: state.id as number, token: state.token as string, @@ -14,13 +24,14 @@ const mapToRemote = (state: GameState): Game => { official: !state.offline, shuffle_indices: state.shuffleIndices, - has_ended: - state.draws.length === (CardValues.length - 1) * state.players.length, + has_ended: options.has_ended, cards: state.draws, dnf_player_ids: playerIndexesToIds(state, state.dnf_player_indexes), - dnf: false, // TODO: Implement + dnf: options.dnf, + + description: state.description, }; }; diff --git a/src/stores/game.ts b/src/stores/game.ts index 6a9fbd8..60a21e4 100644 --- a/src/stores/game.ts +++ b/src/stores/game.ts @@ -33,6 +33,9 @@ interface GameState { dnf_player_indexes: number[]; draws: Card[]; + + imageBlob?: Blob; + description?: string; } interface GameActions { @@ -47,12 +50,15 @@ interface GameActions { SetPlayerDNF: (playerId: number, dnf: boolean) => void; + SetImageBlob: (blob: Blob | undefined) => void; + SetDescription: (description: string | undefined) => void; + StartChug: () => number; StopChug: () => number; DrawCard: () => Card; - Exit: (dnf?: boolean) => void; + Exit: (options?: { dnf: boolean; description?: string }) => void; Resume: (state: GameState) => void; } @@ -78,6 +84,9 @@ const initialState: GameState = { dnf_player_indexes: [], draws: [], + + description: undefined, + imageBlob: undefined, }; const useGame = create()( @@ -153,6 +162,8 @@ const useGame = create()( }, SetPlayerDNF: (playerIndex: number, dnf: boolean) => { + console.debug("[Game]", `Setting player ${playerIndex} DNF to ${dnf}`); + const state = useGame.getState(); let player; @@ -202,6 +213,22 @@ const useGame = create()( } }, + SetImageBlob: (blob: Blob | undefined) => { + console.debug("[Game]", "Setting image blob"); + + set({ + imageBlob: blob, + }); + }, + + SetDescription: (description: string | undefined) => { + console.debug("[Game]", "Setting game description"); + + set({ + description: description, + }); + }, + DrawCard: () => { console.debug("[Game]", "Drawing card"); @@ -231,15 +258,15 @@ const useGame = create()( const draws = [...state.draws, card]; - const done = - draws.length === (CardValues.length - 1) * state.players.length; + const done = draws.length === CardValues.length * state.players.length; const update: Partial = { draws: draws, }; if (done) { - useGamesPlayed.getState().incrementCompleted(); + console.debug("[Game]", "Last card drawn"); + update.gameEndTimestamp = Date.now(); } @@ -360,10 +387,35 @@ const useGame = create()( } }, - Exit: (dnf = false) => { + Exit: ( + options: { + dnf: boolean; + description?: string; + } = { + dnf: false, + description: undefined, + }, + ) => { console.debug("[Game]", "Exiting game"); - // TODO: Update game state on server + const state = useGame.getState(); + + if (!state.offline) { + try { + GameAPI.postUpdate( + state.token as string, + mapToRemote(state, { + dnf: options.dnf, + has_ended: true, + description: options.description, + }), + ); + } catch (error) { + console.error("[Game]", "Failed to update game state", error); + } + } + + useGamesPlayed.getState().incrementCompleted(); set(initialState); }, diff --git a/src/views/Game/components/Chart.tsx b/src/views/Game/components/Chart.tsx index ae18e5f..d688306 100644 --- a/src/views/Game/components/Chart.tsx +++ b/src/views/Game/components/Chart.tsx @@ -36,8 +36,6 @@ const Chart: FunctionComponent = () => { d.data.push(...Array(maxLength - d.data.length).fill(null)); }); - console.log(data); - return data; }, [playerMetrics, settings.themeMode]); diff --git a/src/views/Game/components/DNFDialog.tsx b/src/views/Game/components/DNFDialog.tsx index 17dbd30..99a5cc1 100644 --- a/src/views/Game/components/DNFDialog.tsx +++ b/src/views/Game/components/DNFDialog.tsx @@ -32,10 +32,6 @@ const DNFDialog: FunctionComponent = (props) => { const isDNF = dnf_player_indexes.includes(index); - const player = players[index]; - - console.log("Setting DNF for player", player.id, !isDNF); - SetPlayerDNF(index, !isDNF); }; diff --git a/src/views/Game/components/GamFinishedDialog.tsx b/src/views/Game/components/GamFinishedDialog.tsx index b12d84f..77dfa6f 100644 --- a/src/views/Game/components/GamFinishedDialog.tsx +++ b/src/views/Game/components/GamFinishedDialog.tsx @@ -24,10 +24,19 @@ const GameFinishedDialog: FunctionComponent = ( ) => { const theme = useTheme(); + const [description, setMessage] = useState(""); + const game = useGame((state) => ({ Exit: state.Exit, })); + const saveAndExit = () => { + game.Exit({ + dnf: false, + description, + }); + }; + return ( <> = ( }} > - Game finished! + Game finished = ( }} placeholder="Write a description" maxLength={1000} + value={description} + onChange={(e) => setMessage(e.target.value)} /> @@ -86,7 +97,7 @@ const GameFinishedDialog: FunctionComponent = ( fullWidth variant="contained" size="large" - onClick={() => game.Exit()} + onClick={saveAndExit} > Save and exit @@ -148,10 +159,6 @@ const Camera: FunctionComponent = () => { setSelectedDevice(cameraDevices[nextIndex]); }; - // if (!cameraDevices || cameraDevices.length === 0 || !!cameraError) { - // return null; - // } - return ( { setExitGameDialogOpen(false); if (e.ok) { - game.ExitGame(true); // DNF - navigate("/login"); // Should be handled by protected route + game.ExitGame({ + dnf: true, + }); + + navigate("/login"); } };