Skip to content

Quizz

Pollux includes a full quiz system with timed questions, multiple correct answers, scoring, and a podium.

How it works

sequenceDiagram
  actor Admin
  actor Player
  participant Server
  participant WS as WebSocket

  Admin->>Server: POST /api/quizz/:uuid/step
  Server-->>Admin: 201 Created

  Player->>Server: POST /api/quizz/:uuid/register
  Server-->>WS: broadcast players

  Admin->>Server: POST /api/quizz/:uuid/start
  Server-->>WS: broadcast start (timer, choices)
  WS-->>Player: render question

  Player->>Server: POST /api/quizz/vote
  Server-->>WS: broadcast result + score

  Admin->>Server: POST /api/quizz/:uuid/podium
  Server-->>WS: broadcast podium
  WS-->>Player: show podium

Run a quiz

1. Generate a quiz UUID

curl http://localhost:3000/api/uuid

2. Open the admin page

Go to http://localhost:3000/quizz-admin#YOUR_UUID.

3. Create a question

Fill in the form:

  • Step — Question number (starts at 0)
  • Question — The question text
  • Timer (s) — Default timer duration in seconds
  • Media URL — Optional URL to an image, video, or audio file (displayed on the result page)
  • Choices — Comma-separated list (e.g., Paris, London, Berlin, Madrid)
  • Correct — 0-based indices of correct answers (e.g., 0, 2)

Click Save Step.

4. Open the vote page

Go to http://localhost:3000/quizz-vote#YOUR_UUID.

Enter a pseudonym to register.

5. Start the question

Back on the admin page, set a timer and click Start. The question appears on all player screens.

6. Submit answers

Players select the correct answers and click Submit Answer. Points are awarded for correct answers plus a speed bonus for fast responses.

7. View results

Open http://localhost:3000/quizz-result?uuid=YOUR_UUID to see the live results display, leaderboard, and podium.

Scoring

Each submission is scored by the pure computeQuizzScore function (src/scoring.ts):

  • Correct answer: +1 point per correct selection (wrong extra picks are not penalised)
  • Speed bonus: only if at least one correct pick — decays linearly from full value to 0 over a 20-second window
  • Total: correctScore + speedBonus
flowchart TD
  A["Submission: picked choices + response time"] --> B{"≥ 1 correct pick?"}
  B -- no --> Z["speedBonus = 0"]
  B -- yes --> C["speedBonus = round(<br/>max(0, 1 − ms / 20000) × totalCorrect)"]
  Z --> S["score = correctScore + speedBonus"]
  C --> S

The server also enforces the per-question timer server-side and rejects late votes with 408 — the client clock can't be trusted to stop the round.

WebSocket events

Clients connected to /ws/quizz?uuid=YOUR_UUID&user=USER_ID receive:

Event Payload Description
players { "players": [...] } Updated player list
start { "step": 0, "choices": [...], "timer": 30, "startedAt": ..., "media": "..." } Question started
result { "step": 0, "result": [...] } Step results
score { "step": 0, "scores": [...] } Step scores
podium { "scores": [...] } Final podium