Commit graph

10 commits

Author SHA1 Message Date
AyoubBenziza
1727b84644 feat: rebus game mode
New "Rébus" mode: guess the geek work from an emoji puzzle (free-text answer,
tolerant matching). Implemented as a quiz format `rebus` — reuses the whole quiz
machinery (pool, anti-repeat, speed scoring, recap, bots, back-office):

- shared: QuizFormat/GameType/MixMode + RoundConfig.pool gain "rebus"
- server: rebus is a text format; pool composes a rebus sub-pool (not filtered by
  category); ~9 seeded emoji rebus in the in-code bank; admin accepts the format
- client: lobby tile + sub-mode + count; big centered emoji display in the round;
  dedicated transition theme (🧩 RÉBUS); FR/EN strings; back-office form option

Verified e2e: a rebus game serves only rebus rounds with emoji prompts and the
recap shows the right answers. typecheck/lint/build/24 tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 14:46:31 +02:00
AyoubBenziza
6362b97508 fix(web): blindtest sound, hidden vote status, authoritative tracks, quiz input
From friends playtest feedback:
- blindtest "who added it?" (and mixed): hide the per-player vote status — the
  contributor never validates, which gave them away
- blindtest sound: set YT player `origin`/`enablejsapi` (fixes the postMessage
  origin warning) and add a per-game "Activer le son" gesture for non-DJ
  (browsers block audible autoplay without a user gesture)
- track list: render each player's own tracks from a server-sent, authoritative
  blindtest:myTracks event (emitted on submit/remove/reconnect) instead of local
  state that desynced on remount — fixes the "3/3 but only 2 shown" case
- quiz: reset the free-answer input between questions (was pre-filled with the
  previous answer)

Verified e2e: myTracks emitted on submit + reconnect.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:16:27 +02:00
AyoubBenziza
1e5ef2be90 feat(web): i18n (FR/EN) — homemade typed dictionary
- lightweight, dependency-free i18n: typed fr/en dictionaries (fr is the source
  of truth, en must match its shape → compile error on drift), I18nProvider +
  useI18n hook, browser detection + localStorage persistence
- FR/EN language switcher (home + room header)
- translated the whole player-facing flow: home, join, pseudo, room shell,
  lobby (incl. settings, categories, bots, track submission, history),
  quiz, blindtest, player-cards, round transitions, end screen (podium, awards,
  tracks, rounds recap), and server-error messages (mapped by code)
- history dates localized to the active language

Content (questions/categories) intentionally left as-is. Back-office (admin)
not translated yet — internal, token-gated tool.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 19:03:28 +02:00
AyoubBenziza
879bc5b388 feat: per-submode mixed settings, fastest award, wider desktop layout
Mixed settings fix:
- RoundConfig carries a `pool` hint (quiz | image) per quiz round; lobby shows
  a separate count for each selected sub-mode (Quiz, Images) and the blindtest
  config — not just the quiz one
- server pool composes the queue per round's pool (quiz formats vs image_reveal),
  in order; verified e2e (2 quiz + 2 images honored)

Awards:
- " Le plus rapide" — derived client-side from the speed bonus baked into
  quiz/image points (points above the 100 base on correct answers)

Desktop restyle:
- room page gets an ambient halo background and a responsive container
  (lobby max-w-3xl with a 2-column players|settings grid, game/end max-w-lg)
- game/end views widened to max-w-lg

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 15:10:09 +02:00
AyoubBenziza
8bc184fab7 feat: bigger image_reveal, optional image prompt, mixed sub-mode toggles, Pokémon seed
- image_reveal display: larger, object-contain (whole image up to 58vh), no crop
- image prompt optional in back-office (defaults to "Qui est-ce ?"), overridable
- mixed mode reworked: select "Mixte" then toggle sub-modes (Quiz/Images/
  Blindtest). Blindtest sub-mode locked under 3 players; mixed itself no longer
  needs 3. Server quiz pool formats derived from gameType + mixedModes.
  shared: MixMode + RoomSettings.mixedModes (default quiz+image).
- DB: prompt uniqueness is now a partial index (excludes image_reveal) + unique
  index on image_url; lets many images share the generic prompt, dedup by URL.
- seed: db:seed:images pulls Pokémon (PokéAPI) as image_reveal questions with
  official artwork (remote URL) + FR/EN accepted answers; idempotent by image_url.

Verified: migration applied, Pokémon seed inserts FR+EN, image mode serves only
image_reveal, all checks green (23 tests).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 00:20:28 +02:00
AyoubBenziza
0619c02cdf feat(quiz): image_reveal format (progressive blur) end-to-end
Server:
- quiz-round handles image_reveal like a text-answer format (tolerant match
  on acceptedAnswers), exposing imageUrl in the round payload; degressive
  scoring comes for free from the existing speed bonus (earlier = blurrier =
  more points)
- repo includes image_reveal in the pool (requires imageUrl + acceptedAnswers)
- back-office: image upload (@fastify/multipart) saved to UPLOADS_DIR and
  served statically on /uploads (@fastify/static); create supports image_reveal
- env: UPLOADS_DIR; gitignore uploads/

Client:
- admin form: "Image à deviner" — upload + preview + accepted answers
- in-game: ImageReveal shows the image with a time-cadenced decreasing blur
  (synced via server timestamps) + text input; reveal shows the clear image
  and the answer

shared: QuizQuestionPayload.imageUrl

Verified against real server+DB: upload (url), static serve (200), create
(201), validation (400).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 21:41:34 +02:00
AyoubBenziza
e3315d3b35 feat: mixed games by default, free-text quiz, mode-aware transitions
Mixed mode (default):
- gameType is now mixed | quiz | blindtest, default "mixed"; the lobby
  interleaves quiz + blindtest rounds so modes alternate
- lobby reworked: 3-way game-type switch, quiz count and/or blindtest config
  + track submission shown per selected type

Free-text quiz questions:
- quiz supports the `free` format (e.g. maths) alongside mcq/truefalse:
  payload without choices, {text} vote, tolerant matching on acceptedAnswers
- shared QuizQuestionPayload.choices optional; reveal truth carries answer
- match util moved to game/match.ts (shared by quiz + blindtest)
- repo/seed include free + acceptedAnswers; in-code bank gains free questions
- client quiz view renders a text input for free questions

Mode-aware transitions:
- RoundTransition themed per mode (colors/label/emoji); announces the mode
  on change (quiz <-> blindtest), lighter teaser within the same mode
- custom media buckets per mode: assets/transitions/{quiz,blindtest}/ + shared
- store tracks roundModeChanged

Verified e2e: mixed game alternates quiz/blindtest to completion; free-text
scoring covered by tests (22 pass).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 13:41:29 +02:00
AyoubBenziza
7dda00c65c feat: lead-in timer compensation + GIF support for round transitions
Server (option 2 — don't eat answer time):
- engine: leadMs prep delay (default 1600ms) before the clock starts; the
  round timer now fires at lead + duration, and scoring uses the post-lead
  start so the speed bonus spans the full answer window
- shared: round:start carries startsAt (answers begin) alongside endsAt
- engine test passes leadMs:0

Client:
- Countdown shows the full duration (no ticking) until startsAt, then counts
  down — so the WarioWare transition plays in full without stealing time
- store/ActiveRound carry startsAt

Custom transition media:
- RoundTransition auto-loads any gif/webp/apng/png/avif dropped in
  src/assets/transitions/ (import.meta.glob), plays one at random per round,
  falls back to the Framer animation when none are present
- README documenting how to add animations

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 11:25:17 +02:00
AyoubBenziza
f82c7d9700 feat(web): bomb countdown, copyable room code, persistent score cards
- Countdown: under 10s it ramps into a "bomb" — white→red color and an
  escalating scale/wiggle pulse (faster & wider as it nears 0) via Framer Motion
- RoomCode: click-to-copy the room code with visual feedback
- PlayerCards: always-on score HUD during the game (cards per player,
  animated reorder, crown on the leader) so scores are tracked continuously
  instead of only appearing at reveal
- quiz view: drop the reveal-only scoreboard (now covered by PlayerCards)
- add framer-motion dependency

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 15:56:57 +02:00
AyoubBenziza
5cc9113b8c feat(quiz): quiz game mode end-to-end (server mode + playable client UI)
Server:
- quiz mode (GameRound): in-memory FR question bank (mcq + truefalse),
  per-room anti-repeat, first-vote lock, score = base + speed bonus ∝ time
  left; registered via registerRound, loaded at startup
- shared: typed quiz payloads (QuizQuestionPayload / reveal truth / result)
- tests: quiz scoring, vote lock, bounds, reveal (bun test)

Client:
- room store handles round:start / voteAck / reveal / game:end
- RoomPage dispatches by status: lobby (host start controls) → quiz view
  (question, countdown, vote, reveal + scoreboard) → game-end view
- replaces standalone lobby page

Roadmap V1 step 4. Verified end-to-end over the wire (start→vote→reveal→
score→next round→game:end, no answer leaked, anti-repeat works).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 15:43:17 +02:00