Gameplay Workflow
Phase state machineβ
waiting
β host:start
βΌ
question_open βββββ host:resume
β β²
β host:pause β
βΌ β
question_paused ββββββββββ
β
β host:reveal (or timer alarm)
βΌ
question_revealed
β
β host:next
βΌ
round_leaderboard (only after last question in a round)
β
β host:next
βΌ
question_open (next round) OR
ended (after final round)
Session creationβ
The host fills in SessionForm:
- Title β optional display name
- Wines β one or more wines; each wine gets 5 questions (one per category, fixed order:
color,country,grape_variety,vintage_year,wine_name) - Correct answer β always blank; host fills in
- Distractors β 3 per question; pre-filled for most categories (grape_variety is empty)
- Timer β range slider 15β120 s (default 60 s); applies to all questions
Scoringβ
| Outcome | Points |
|---|---|
| Correct answer | 100 |
| Wrong answer | 0 |
| No answer (timer expires) | 0 |
Points are awarded at host:reveal. There is no speed bonus.
Answer changingβ
Participants can change their selected option at any time until the host clicks Reveal. The backend overwrites the answer on each submit_answer message. answeredCount (shown to host) increments only on a participant's first answer per question.
Timer behaviourβ
- Timer starts when the question is broadcast (not when
host:startfires) - Host can Pause and Resume any time during
question_open - Timer expiry (
alarm()) automatically triggers reveal (same ashost:reveal) game:timer_tickis emitted every second to all connected clients
Round leaderboardβ
After the last question of each wine (5th question), the server emits game:round_leaderboard instead of proceeding to the next question. After the final wine's last question, it emits game:final_leaderboard and transitions to ended.
Session endβ
Host clicks End Session at any time OR the game completes all questions. On end:
- Final rankings are written to KV (
host:{hostId}key,finalRankingsfield of the matching session entry) - All clients receive
session:ended - Phase transitions to
ended