add WS message types for predictions, dishes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-12 11:10:52 +01:00
parent 4ee2252dde
commit 22bae2aa82

View File

@@ -1,5 +1,6 @@
import { z } from "zod" import { z } from "zod"
import { ACTS } from "./constants" import { ACTS } from "./constants"
import { gameStateSchema, dishSchema } from "./game-types"
import { playerSchema, roomStateSchema } from "./room-types" import { playerSchema, roomStateSchema } from "./room-types"
// ─── Client → Server ─────────────────────────────────────────────── // ─── Client → Server ───────────────────────────────────────────────
@@ -22,12 +23,41 @@ export const endRoomMessage = z.object({
type: z.literal("end_room"), type: z.literal("end_room"),
}) })
// ─── Client → Server (Act 1 games) ─────────────────────────────────
export const submitPredictionMessage = z.object({
type: z.literal("submit_prediction"),
predictedWinner: z.string(),
top3: z.array(z.string()).length(3),
nulPointsPick: z.string(),
})
export const addDishMessage = z.object({
type: z.literal("add_dish"),
name: z.string().min(1).max(100),
correctCountry: z.string(),
})
export const submitDishGuessMessage = z.object({
type: z.literal("submit_dish_guess"),
dishId: z.string().uuid(),
guessedCountry: z.string(),
})
export const revealDishesMessage = z.object({
type: z.literal("reveal_dishes"),
})
/** Union of all client → server messages (room system only — games add more) */ /** Union of all client → server messages (room system only — games add more) */
export const clientMessage = z.discriminatedUnion("type", [ export const clientMessage = z.discriminatedUnion("type", [
joinRoomMessage, joinRoomMessage,
reconnectMessage, reconnectMessage,
advanceActMessage, advanceActMessage,
endRoomMessage, endRoomMessage,
submitPredictionMessage,
addDishMessage,
submitDishGuessMessage,
revealDishesMessage,
]) ])
export type ClientMessage = z.infer<typeof clientMessage> export type ClientMessage = z.infer<typeof clientMessage>
@@ -69,6 +99,45 @@ export const errorMessage = z.object({
message: z.string(), message: z.string(),
}) })
// ─── Server → Client (Act 1 games) ─────────────────────────────────
export const gameStateMessage = z.object({
type: z.literal("game_state"),
gameState: gameStateSchema,
})
export const predictionsLockedMessage = z.object({
type: z.literal("predictions_locked"),
})
export const dishAddedMessage = z.object({
type: z.literal("dish_added"),
dish: dishSchema,
})
export const dishGuessRecordedMessage = z.object({
type: z.literal("dish_guess_recorded"),
dishId: z.string().uuid(),
guessedCountry: z.string(),
})
export const dishesRevealedMessage = z.object({
type: z.literal("dishes_revealed"),
results: z.array(
z.object({
dish: dishSchema,
guesses: z.array(
z.object({
playerId: z.string().uuid(),
displayName: z.string(),
guessedCountry: z.string(),
correct: z.boolean(),
}),
),
}),
),
})
/** Union of all server → client messages (room system only) */ /** Union of all server → client messages (room system only) */
export const serverMessage = z.discriminatedUnion("type", [ export const serverMessage = z.discriminatedUnion("type", [
roomStateMessage, roomStateMessage,
@@ -78,6 +147,11 @@ export const serverMessage = z.discriminatedUnion("type", [
actChangedMessage, actChangedMessage,
roomEndedMessage, roomEndedMessage,
errorMessage, errorMessage,
gameStateMessage,
predictionsLockedMessage,
dishAddedMessage,
dishGuessRecordedMessage,
dishesRevealedMessage,
]) ])
export type ServerMessage = z.infer<typeof serverMessage> export type ServerMessage = z.infer<typeof serverMessage>