add jury voting, bingo WS message handlers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -47,7 +47,8 @@ function sendGameState(ws: WSContext, roomCode: string, sessionId: string) {
|
||||
if (!gm || !playerId) return
|
||||
|
||||
const allPlayerIds = roomManager.getAllPlayerIds(roomCode)
|
||||
const gameState = gm.getGameStateForPlayer(playerId, allPlayerIds)
|
||||
const displayNames = roomManager.getPlayerDisplayNames(roomCode)
|
||||
const gameState = gm.getGameStateForPlayer(playerId, allPlayerIds, displayNames)
|
||||
sendTo(ws, { type: "game_state", gameState })
|
||||
}
|
||||
|
||||
@@ -56,7 +57,8 @@ function sendDisplayGameState(ws: WSContext, roomCode: string) {
|
||||
if (!gm) return
|
||||
|
||||
const allPlayerIds = roomManager.getAllPlayerIds(roomCode)
|
||||
const gameState = gm.getGameStateForDisplay(allPlayerIds)
|
||||
const displayNames = roomManager.getPlayerDisplayNames(roomCode)
|
||||
const gameState = gm.getGameStateForDisplay(allPlayerIds, displayNames)
|
||||
sendTo(ws, { type: "game_state", gameState })
|
||||
}
|
||||
|
||||
@@ -211,12 +213,15 @@ export function registerWebSocketRoutes() {
|
||||
type: "act_changed",
|
||||
newAct: result.newAct,
|
||||
})
|
||||
// Lock predictions when moving from pre-show to live-event
|
||||
// Lock predictions and generate bingo cards when entering live-event
|
||||
if (result.newAct === "live-event") {
|
||||
const gm = roomManager.getGameManager(roomCode)
|
||||
if (gm) {
|
||||
gm.lockPredictions()
|
||||
broadcast(roomCode, { type: "predictions_locked" })
|
||||
const allPlayerIds = roomManager.getAllPlayerIds(roomCode)
|
||||
gm.generateBingoCards(allPlayerIds)
|
||||
broadcastGameStateToAll(roomCode)
|
||||
}
|
||||
}
|
||||
break
|
||||
@@ -258,6 +263,141 @@ export function registerWebSocketRoutes() {
|
||||
broadcastGameStateToAll(roomCode)
|
||||
break
|
||||
}
|
||||
|
||||
case "open_jury_vote": {
|
||||
if (!sessionId) {
|
||||
sendError(ws, "Not joined")
|
||||
return
|
||||
}
|
||||
const room = roomManager.getRoom(roomCode)
|
||||
if (room?.currentAct !== "live-event") {
|
||||
sendError(ws, "Jury voting is only available during Live Event")
|
||||
return
|
||||
}
|
||||
if (!roomManager.isHost(roomCode, sessionId)) {
|
||||
sendError(ws, "Only the host can open jury voting")
|
||||
return
|
||||
}
|
||||
const gm = roomManager.getGameManager(roomCode)
|
||||
if (!gm) {
|
||||
sendError(ws, "Room not found")
|
||||
return
|
||||
}
|
||||
const entry = gm.getLineup().entries.find((e) => e.country.code === msg.countryCode)
|
||||
if (!entry) {
|
||||
sendError(ws, "Invalid country code")
|
||||
return
|
||||
}
|
||||
const result = gm.openJuryRound(entry.country.code, entry.country.name, entry.country.flag)
|
||||
if ("error" in result) {
|
||||
sendError(ws, result.error)
|
||||
return
|
||||
}
|
||||
const round = gm.getCurrentJuryRound()!
|
||||
broadcast(roomCode, {
|
||||
type: "jury_vote_opened",
|
||||
roundId: round.id,
|
||||
countryCode: round.countryCode,
|
||||
countryName: round.countryName,
|
||||
countryFlag: round.countryFlag,
|
||||
})
|
||||
broadcastGameStateToAll(roomCode)
|
||||
break
|
||||
}
|
||||
|
||||
case "close_jury_vote": {
|
||||
if (!sessionId) {
|
||||
sendError(ws, "Not joined")
|
||||
return
|
||||
}
|
||||
if (!roomManager.isHost(roomCode, sessionId)) {
|
||||
sendError(ws, "Only the host can close jury voting")
|
||||
return
|
||||
}
|
||||
const gm = roomManager.getGameManager(roomCode)
|
||||
if (!gm) {
|
||||
sendError(ws, "Room not found")
|
||||
return
|
||||
}
|
||||
const result = gm.closeJuryRound()
|
||||
if ("error" in result) {
|
||||
sendError(ws, result.error)
|
||||
return
|
||||
}
|
||||
broadcast(roomCode, {
|
||||
type: "jury_vote_closed",
|
||||
countryCode: result.countryCode,
|
||||
countryName: result.countryName,
|
||||
countryFlag: result.countryFlag,
|
||||
averageRating: result.averageRating,
|
||||
totalVotes: result.totalVotes,
|
||||
})
|
||||
broadcastGameStateToAll(roomCode)
|
||||
break
|
||||
}
|
||||
|
||||
case "submit_jury_vote": {
|
||||
if (!sessionId) {
|
||||
sendError(ws, "Not joined")
|
||||
return
|
||||
}
|
||||
if (roomManager.getRoom(roomCode)?.currentAct !== "live-event") {
|
||||
sendError(ws, "Jury voting is only available during Live Event")
|
||||
return
|
||||
}
|
||||
const playerId = roomManager.getPlayerIdBySession(roomCode, sessionId)
|
||||
const gm = roomManager.getGameManager(roomCode)
|
||||
if (!playerId || !gm) {
|
||||
sendError(ws, "Room not found")
|
||||
return
|
||||
}
|
||||
const result = gm.submitJuryVote(playerId, msg.rating)
|
||||
if ("error" in result) {
|
||||
sendError(ws, result.error)
|
||||
return
|
||||
}
|
||||
sendGameState(ws, roomCode, sessionId)
|
||||
break
|
||||
}
|
||||
|
||||
case "tap_bingo_square": {
|
||||
if (!sessionId) {
|
||||
sendError(ws, "Not joined")
|
||||
return
|
||||
}
|
||||
if (roomManager.getRoom(roomCode)?.currentAct !== "live-event") {
|
||||
sendError(ws, "Bingo is only available during Live Event")
|
||||
return
|
||||
}
|
||||
const playerId = roomManager.getPlayerIdBySession(roomCode, sessionId)
|
||||
const gm = roomManager.getGameManager(roomCode)
|
||||
if (!playerId || !gm) {
|
||||
sendError(ws, "Room not found")
|
||||
return
|
||||
}
|
||||
const result = gm.tapBingoSquare(playerId, msg.tropeId)
|
||||
if ("error" in result) {
|
||||
sendError(ws, result.error)
|
||||
return
|
||||
}
|
||||
sendGameState(ws, roomCode, sessionId)
|
||||
if (result.hasBingo) {
|
||||
const room = roomManager.getRoom(roomCode)
|
||||
const player = room?.players.find((p) => p.sessionId === sessionId)
|
||||
if (player) {
|
||||
const isNew = gm.addBingoAnnouncement(playerId, player.displayName)
|
||||
if (isNew) {
|
||||
broadcast(roomCode, {
|
||||
type: "bingo_announced",
|
||||
playerId,
|
||||
displayName: player.displayName,
|
||||
})
|
||||
broadcastGameStateToAll(roomCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user