diff --git a/server/@types/entities.d.ts b/server/@types/entities.d.ts index a395f481..72d35998 100644 --- a/server/@types/entities.d.ts +++ b/server/@types/entities.d.ts @@ -28,4 +28,9 @@ type Question = { subject: string; }; -export type { Answer, Colour, Player, Question }; +type PlayerScore = { + player: Player; + score: number; +}; + +export type { Answer, Colour, Player, PlayerScore, Question }; diff --git a/server/machines/round.ts b/server/machines/round.ts index 2b295b8b..45e52140 100644 --- a/server/machines/round.ts +++ b/server/machines/round.ts @@ -1,10 +1,12 @@ import { assign, setup } from "xstate"; -import type { Question } from "../@types/entities"; +import type { PlayerScore, Question } from "../@types/entities"; import questions from "../data/questions.json"; const context = { questions: questions as Question[], + playerScores: [] as PlayerScore[], selectedQuestion: {} as Question | undefined, + bonusPoints: 0, }; type Context = typeof context; diff --git a/server/models/round.ts b/server/models/round.ts index c4c34918..176f1f8a 100644 --- a/server/models/round.ts +++ b/server/models/round.ts @@ -4,6 +4,7 @@ import { context, roundMachine } from "../machines/round"; import { turnMachine } from "../machines/turn"; import type { SocketServer } from "../socketServer"; import { machineLogger } from "../utils/loggingUtils"; +import { getUpdatedScoresAndBonusPoints } from "../utils/scoringUtils"; class Round { machine: Actor; @@ -46,13 +47,15 @@ class Round { this.turnMachine.subscribe((state) => { switch (state.value) { case "finished": { - // TODO: - // - add logic for updating scores then checking if there's a clear winner in the round machine - // - delete the console.info below - console.info( - "turn machine finished with context:", - this.turnMachine?.getSnapshot().context, - ); + this.machine.send({ + type: "turnEnd", + scoresAndBonusPoints: getUpdatedScoresAndBonusPoints( + this.machine.getSnapshot().context.bonusPoints, + this.machine.getSnapshot().context.playerScores, + this.turnMachine?.getSnapshot().context.correctPlayerSocketIds || + [], + ), + }); } } }); diff --git a/server/utils/scoringUtils.ts b/server/utils/scoringUtils.ts index 6516309e..75eedc52 100644 --- a/server/utils/scoringUtils.ts +++ b/server/utils/scoringUtils.ts @@ -1,3 +1,59 @@ +import type { Answer, Player, PlayerScore, Question } from "../@types/entities"; + +const allCorrect = ( + totalPlayerCount: number, + correctPlayerSocketIds: Player["socketId"][], +): boolean => { + return correctPlayerSocketIds.length === totalPlayerCount; +}; + +const allIncorrect = ( + correctPlayerSocketIds: Player["socketId"][], +): boolean => { + return correctPlayerSocketIds.length === 0; +}; + +const awardPointsForCorrectAnswers = ( + currentPlayerScores: PlayerScore[], + bonusPoints: number, + correctPlayerSocketIds: Player["socketId"][], +): PlayerScore[] => { + const numberOfIncorrectAnswers = + currentPlayerScores.length - correctPlayerSocketIds.length; + const pointsToAward = numberOfIncorrectAnswers + bonusPoints; + + return currentPlayerScores.map(({ player, score }) => { + if (correctPlayerSocketIds.includes(player.socketId)) { + return { player, score: score + pointsToAward }; + } + + return { player, score }; + }); +}; + +const getUpdatedScoresAndBonusPoints = ( + currentBonusPoints: number, + currentPlayerScores: PlayerScore[], + correctPlayerSocketIds: Player["socketId"][], +): { bonusPoints: number; scores: PlayerScore[] } => { + if (allCorrect(currentPlayerScores.length, correctPlayerSocketIds)) { + return { bonusPoints: currentBonusPoints + 1, scores: currentPlayerScores }; + } + + if (allIncorrect(correctPlayerSocketIds)) { + return { bonusPoints: 0, scores: currentPlayerScores }; + } + + return { + bonusPoints: 0, + scores: awardPointsForCorrectAnswers( + currentPlayerScores, + currentBonusPoints, + correctPlayerSocketIds, + ), + }; +}; + const getCorrectSocketIdsFromAnswers = ( answers: Answer[], correctAnswer: Question["colours"], @@ -13,4 +69,4 @@ const getCorrectSocketIdsFromAnswers = ( .map((answer) => answer.socketId); }; -export { getCorrectSocketIdsFromAnswers }; +export { getCorrectSocketIdsFromAnswers, getUpdatedScoresAndBonusPoints };