diff --git a/server/machines/round.ts b/server/machines/round.ts index 2b295b8b..540db1ba 100644 --- a/server/machines/round.ts +++ b/server/machines/round.ts @@ -1,23 +1,41 @@ +import type { Socket } from "socket.io"; import { assign, setup } from "xstate"; -import type { Question } from "../@types/entities"; +import type { Answer, Question } from "../@types/entities"; import questions from "../data/questions.json"; - const context = { questions: questions as Question[], selectedQuestion: {} as Question | undefined, + scores: {} as Record, }; type Context = typeof context; +type Events = { + type: "turnEnd"; + answers: Answer[]; +}; + const dynamicParamFuncs = { setQuestion: ({ context }: { context: Context }) => { return { questions: context.questions }; }, + // TODO: updateScores }; +// players are awarded one point for each person who guesses wrong plus any points from the bonus round +// show what answers every gave +// there could be no correct answers - bonus points are then reset +// all players could be correct and no score would be awarded but 1 point is added to the next round +// first to 10 + +// count how many players have correct answers +// if 0 correct answers set bonus points to 0 -> check win conditions -> next question +// if all answers are correct ++bonus points -> check win conditions -> next question +// if there are some correct and some incorrect answers add the number of incorrect answers (+ any bonus points - then reset bonus points) to the scores of the players with correct answers -> check win conditions -> next question const roundMachine = setup({ types: {} as { context: Context; + events: Events; }, actions: { @@ -29,17 +47,46 @@ const roundMachine = setup({ const questionIndex = Math.floor( Math.random() * (params.questions.length - 1), ); + // can we splice the selected question out of the questions array with params.questions.splice[questionIndex, 1]? return params.questions[questionIndex]; }, }), + updateScores: assign({ + // TODO + }), + }, + guards: { + noClearWinner: { + // TODO - need to work out how to transition into a new turn either here or in the model + }, }, }).createMachine({ - context, + context: context, id: "round", initial: "turn", + types: { + context: {} as Context, + events: {} as Event, + }, states: { turn: { - entry: [{ type: "setQuestion", params: dynamicParamFuncs.setQuestion }], + entry: [{ type: "setQuestion", params: dynamicParamFuncs.setQuestion }], // keep track of which questions have been asked in round and/or entire game/lobby] + on: { + turnEnd: { + target: "finished", + actions: { + type: "updateScores", + params: dynamicParamFuncs.updateScores, + }, + guard: { + type: "noClearWinner", + params: dynamicParamFuncs.noClearWinner, + }, + }, + }, + }, + finished: { + type: "final", }, }, }); diff --git a/server/models/round.ts b/server/models/round.ts index d7b5d555..71336914 100644 --- a/server/models/round.ts +++ b/server/models/round.ts @@ -8,7 +8,7 @@ import { machineLogger } from "../utils/loggingUtils"; class Round { machine: Actor; server: SocketServer; - turnMachine: Actor | undefined; + turnMachine?: Actor; constructor(server: SocketServer) { this.server = server; @@ -43,6 +43,11 @@ class Round { .selectedQuestion as Question, }, }); + this.turnMachine.subscribe((state) => { + if (state.value === "finished") { + this.machine.send({ type: "turnEnd", answers: state.context.answers }); + } + }); this.turnMachine.start(); } diff --git a/server/utils/machineLogger.ts b/server/utils/machineLogger.ts new file mode 100644 index 00000000..05c3ec54 --- /dev/null +++ b/server/utils/machineLogger.ts @@ -0,0 +1,10 @@ +import type { InspectionEvent } from "xstate"; + +export const machineLogger = (inspectionEvent: InspectionEvent, machine: 'turn' | 'round') => { + if (inspectionEvent.type === "@xstate.event") { + console.info(inspectionEvent.event, `machine: ${machine}`); + } + if (inspectionEvent.type === "@xstate.snapshot") { + console.info(inspectionEvent.snapshot, `machine: ${machine}`); + } +};