add prediction scoring design spec
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
# Prediction Scoring — Design Spec
|
||||
|
||||
**Date:** 2026-03-12
|
||||
**Status:** Approved
|
||||
|
||||
---
|
||||
|
||||
## Goal
|
||||
|
||||
Allow the host to enter actual ESC results, calculate prediction scores for all players, and display them on the leaderboard.
|
||||
|
||||
## What Exists
|
||||
|
||||
- Players submit predictions (1st, 2nd, 3rd, last place) during lobby/pre-show via `PredictionsForm`
|
||||
- Predictions lock when host advances to live-event act
|
||||
- `GameManager` stores predictions in a `Map<string, Prediction>`
|
||||
- Leaderboard already shows jury (J:) and bingo (B:) points
|
||||
- DB schema has `actual_winner`, `actual_second`, `actual_third`, `actual_last` columns on `rooms` table (nullable, set when host enters results)
|
||||
|
||||
## New Functionality
|
||||
|
||||
### 1. Host Enters Actual Results
|
||||
|
||||
- New component: `ActualResultsForm` — shown in the Host tab during `scoring` and `ended` acts
|
||||
- Same country-picker UX as the predictions form (select from lineup, all 4 must be different)
|
||||
- New WS message: `submit_actual_results` (client → server) with `{ winner, second, third, last }`
|
||||
- Server stores on the `GameManager` (in-memory) and broadcasts updated game state
|
||||
- Host can re-submit to correct mistakes (overwrites previous entry)
|
||||
|
||||
### 2. Server Scores Predictions
|
||||
|
||||
- `GameManager.setActualResults(winner, second, third, last)` — stores the actual results
|
||||
- `GameManager.getPredictionScore(playerId)` — compares player's prediction to actuals:
|
||||
- `first` matches `winner`: 25 pts (`scoring.prediction_winner`)
|
||||
- `second` matches `second`: 10 pts (`scoring.prediction_top3`)
|
||||
- `third` matches `third`: 10 pts (`scoring.prediction_top3`)
|
||||
- `last` matches `last`: 15 pts (`scoring.prediction_nul_points`)
|
||||
- Total possible: 60 pts
|
||||
- Prediction scores feed into `buildLeaderboard` as a new `predictionPoints` field
|
||||
|
||||
### 3. Leaderboard Update
|
||||
|
||||
- `LeaderboardEntry` gains `predictionPoints: number`
|
||||
- Before results are entered: shows `P:?` on the leaderboard
|
||||
- After results are entered: shows `P:<score>` with actual points
|
||||
- `totalPoints` includes prediction points (0 if no results entered yet)
|
||||
|
||||
### 4. Player View — Results Reveal
|
||||
|
||||
- After actual results are entered, each player's `gameState` includes `actualResults: { winner, second, third, last } | null`
|
||||
- `PredictionsForm` (locked state) gains visual indicators: green checkmark for correct predictions, red X for incorrect
|
||||
- Players who didn't submit predictions get 0 prediction points
|
||||
|
||||
### 5. Display View
|
||||
|
||||
- Shows actual results summary when entered
|
||||
- Shows leaderboard with prediction scores revealed
|
||||
|
||||
## WS Messages
|
||||
|
||||
**Client → Server:**
|
||||
|
||||
| Type | Payload | Guard |
|
||||
|---|---|---|
|
||||
| `submit_actual_results` | `winner`, `second`, `third`, `last` (country codes) | Host only, scoring or ended act |
|
||||
|
||||
**No new server → client messages** — the existing `game_state` broadcast carries all the data.
|
||||
|
||||
## GameState Changes
|
||||
|
||||
```ts
|
||||
// Added to GameState
|
||||
actualResults: { winner: string; second: string; third: string; last: string } | null
|
||||
|
||||
// LeaderboardEntry gains
|
||||
predictionPoints: number
|
||||
```
|
||||
|
||||
## Scoring Config Values (existing)
|
||||
|
||||
```json
|
||||
{
|
||||
"prediction_winner": 25,
|
||||
"prediction_top3": 10,
|
||||
"prediction_nul_points": 15
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user