From 772e1e7734af7e565d7bf46548d8dd81ea22d077 Mon Sep 17 00:00:00 2001 From: conor Date: Mon, 19 Feb 2024 02:44:58 -0800 Subject: [PATCH] * add callback to pollservice so it can send updates to the client if a vote changes due to disconnect --- client/.eslintrc.cjs | 2 +- client/src/stores/game.ts | 6 +++--- common/src/socketioTypes.ts | 13 +++++++++++-- common/src/stateTypes.ts | 2 ++ server/src/routes/gameHandlers.ts | 10 +++++++--- server/src/state/gameState.ts | 7 ++++++- server/src/state/pollService.ts | 13 ++++++++++--- 7 files changed, 40 insertions(+), 13 deletions(-) diff --git a/client/.eslintrc.cjs b/client/.eslintrc.cjs index a8c687c..9d41601 100644 --- a/client/.eslintrc.cjs +++ b/client/.eslintrc.cjs @@ -36,7 +36,7 @@ module.exports = { 'vue/no-unused-properties': 2, 'vue/no-unused-refs': 2, '@intlify/vue-i18n/valid-message-syntax': 2, - '@intlify/vue-i18n/key-format-style': [2, 'camelCase', {allowArray: true}], + '@intlify/vue-i18n/key-format-style': [2, 'camelCase', { allowArray: true }], '@intlify/vue-i18n/no-duplicate-keys-in-locale': 2, '@intlify/vue-i18n/no-missing-keys-in-other-locales': 2, 'prettier/prettier': 2 diff --git a/client/src/stores/game.ts b/client/src/stores/game.ts index d95802b..cd2243b 100644 --- a/client/src/stores/game.ts +++ b/client/src/stores/game.ts @@ -6,11 +6,11 @@ import { acceptHMRUpdate, defineStore } from 'pinia'; import type { Player, Match as ServerMatch, - PollName, VoteCount, Score as ServerScore, Responses, - MidgameConnectData + MidgameConnectData, + PollVoteCount } from ':common/stateTypes'; import type { Options, VisibleOptions } from ':common/options'; import { defaultOptions } from ':common/options'; @@ -244,7 +244,7 @@ export const useGameStore = defineStore('game', { this.selectionType = selectionType; }); - socket.on('setVoteCount', (data: { pollName: PollName } & VoteCount) => { + socket.on('setVoteCount', (data: PollVoteCount) => { this.voteCounts[data.pollName] = { count: data.count, next: data.next }; }); socket.on('beginPrompt', (prompt: string) => { diff --git a/common/src/socketioTypes.ts b/common/src/socketioTypes.ts index 4a77029..5ed70f8 100644 --- a/common/src/socketioTypes.ts +++ b/common/src/socketioTypes.ts @@ -1,7 +1,16 @@ import { Server, Socket } from 'socket.io'; import { Socket as ClientSocket } from 'socket.io-client'; import { SettableOptions, VisibleOptions } from './options'; -import { Player, PollName, Match, MidgameConnectData, Responses, SelectionType, VoteCount, Score } from './stateTypes'; +import { + Player, + PollName, + Match, + MidgameConnectData, + Responses, + SelectionType, + Score, + PollVoteCount +} from './stateTypes'; import { Result } from './result'; interface ServerToClientRoomEvents { @@ -27,7 +36,7 @@ interface ServerToClientGameEvents { nextSelection(args: { selector: string; selectionType: SelectionType }): void; - setVoteCount(args: { pollName: PollName } & VoteCount): void; + setVoteCount(args: PollVoteCount): void; selectionTypeChosen(selectionType: SelectionType): void; diff --git a/common/src/stateTypes.ts b/common/src/stateTypes.ts index d122e9a..58ba271 100644 --- a/common/src/stateTypes.ts +++ b/common/src/stateTypes.ts @@ -36,6 +36,8 @@ export type VoteCount = { next: boolean; }; +export type PollVoteCount = { pollName: PollName } & VoteCount; + export const zPollName = z.enum(['skipPrompt', 'startNextRound', 'sikeDispute']); export type PollName = z.infer; diff --git a/server/src/routes/gameHandlers.ts b/server/src/routes/gameHandlers.ts index 1a183d5..ef7050d 100644 --- a/server/src/routes/gameHandlers.ts +++ b/server/src/routes/gameHandlers.ts @@ -9,7 +9,7 @@ import type { Result } from ':common/result'; import { isErr, isOk, isSuccess } from ':common/result'; import type { SettableOptions } from ':common/options'; import { getSettableOptionsSchema, getVisibleOptionsSchema } from ':common/options'; -import type { PollName } from ':common/stateTypes'; +import type { PollName, PollVoteCount } from ':common/stateTypes'; import { zPollName } from ':common/stateTypes'; import type { TypedServer, TypedSocket } from ':common/socketioTypes'; import type { Responses } from ':common/stateTypes'; @@ -216,11 +216,11 @@ function registerCallbacks(io: TypedServer, room: Room) { //continueSelection(io, room); //}); - state.registerDisputeCompleteCb((action) => { + state.registerDisputeCompleteCb((action: string) => { applyDisputeAction(io, room, action); }); - state.registerMatchingCompleteCb((selectorActive) => { + state.registerMatchingCompleteCb((selectorActive: boolean) => { // give a little time to show score before moving on to next selection if (!selectorActive) { state.promptTimeout = setTimeout(() => { @@ -228,6 +228,10 @@ function registerCallbacks(io: TypedServer, room: Room) { }, 5000); } }); + + state.registerPollVoteUpdateCb((pollVoteCount: PollVoteCount) => { + io.to(room.name).emit('setVoteCount', pollVoteCount); + }); } function beginPrompt(io: TypedServer, room: Room) { diff --git a/server/src/state/gameState.ts b/server/src/state/gameState.ts index 41c7907..f8c4925 100644 --- a/server/src/state/gameState.ts +++ b/server/src/state/gameState.ts @@ -15,7 +15,8 @@ import type { SelectionType, Stage, Player as RoomPlayer, - Score + Score, + PollVoteCount } from ':common/stateTypes'; type Player = { @@ -123,6 +124,10 @@ export class GameState { this._matchingCompleteCb = cb; } + registerPollVoteUpdateCb(cb: (pollVoteCounts: PollVoteCount) => void): void { + this.pollService.registerPollVoteUpdateCb(cb); + } + /*** PROMPT RESPONSE state changes ***/ hasNewPrompt(): boolean { // return false if no rounds left diff --git a/server/src/state/pollService.ts b/server/src/state/pollService.ts index 12a6fdb..a9ed3a2 100644 --- a/server/src/state/pollService.ts +++ b/server/src/state/pollService.ts @@ -1,7 +1,7 @@ import type { GameState } from './gameState'; import type { Result } from ':common/result'; import { Err, Ok, Warn } from ':common/result'; -import type { PollName, Stage } from ':common/stateTypes'; +import type { PollName, PollVoteCount, Stage } from ':common/stateTypes'; import logger from '../logger/logger'; type Poll = { @@ -15,12 +15,16 @@ type Poll = { export class PollService { private gameState: GameState; private readonly polls: Map; - + private _pollVoteUpdateCb: null | ((pollVoteCounts: PollVoteCount) => void) = null; constructor(gameState: GameState) { this.gameState = gameState; this.polls = new Map(); } + registerPollVoteUpdateCb(cb: (pollVoteCounts: PollVoteCount) => void): void { + this._pollVoteUpdateCb = cb; + } + registerPoll( pollName: PollName, completeCb: () => void, @@ -115,10 +119,13 @@ export class PollService { } disconnect(id: string): void { - for (const poll of this.polls.values()) { + for (const [pollName, poll] of this.polls.entries()) { const index = poll.inFavor.indexOf(id); if (index >= 0) { poll.inFavor.splice(index, 1); + if (this._pollVoteUpdateCb) { + this._pollVoteUpdateCb({ pollName, count: this._countVotes(poll), next: this._nextComplete(poll) }); + } } } }