From d08f25bd965254647aa996e9454f306db6b2fcce Mon Sep 17 00:00:00 2001 From: tiennm99 Date: Mon, 27 Apr 2026 10:51:08 +0700 Subject: [PATCH] feat: three-mode display (player/master/both) with master auto-tick - Add `mode` setting to replace legacy `masterMode` with migration path - Implement 3-button display mode picker (player-only, master-only, both) - Auto-increment master when card drawn via call-bus event system - Add voice hint on settings button, gate auto-call on mode changes - Broadcast draw events from MasterPanel, reset call-bus on new game - Broadened announce condition to cover both modes - New call-bus.svelte.js module for event coordination - Update settings-store tests to cover mode migration - Update codebase docs for mode setting and call-bus architecture --- web/docs/codebase-summary.md | 20 +- web/docs/design-guidelines.md | 10 + web/docs/development-roadmap.md | 8 + web/docs/system-architecture.md | 68 +++++-- .../phase-01-three-mode-settings.md | 175 ++++++++++++++++++ ...phase-02-master-broadcast-and-auto-tick.md | 152 +++++++++++++++ .../phase-03-master-cho-kinh-announcements.md | 125 +++++++++++++ .../plan.md | 77 ++++++++ .../code-reviewer-260427-1036-three-mode.md | 68 +++++++ web/src/lib/MasterPanel.svelte | 33 ++-- web/src/lib/PlayerBoard.svelte | 47 ++++- web/src/lib/SettingsButton.svelte | 71 +++++-- web/src/lib/call-bus.svelte.js | 22 +++ web/src/lib/call-bus.test.js | 35 ++++ web/src/lib/settings-store.svelte.js | 34 +++- web/src/lib/settings-store.test.js | 71 ++++--- web/src/routes/+page.svelte | 22 ++- 17 files changed, 937 insertions(+), 101 deletions(-) create mode 100644 web/plans/260427-1036-three-mode-and-master-auto-tick/phase-01-three-mode-settings.md create mode 100644 web/plans/260427-1036-three-mode-and-master-auto-tick/phase-02-master-broadcast-and-auto-tick.md create mode 100644 web/plans/260427-1036-three-mode-and-master-auto-tick/phase-03-master-cho-kinh-announcements.md create mode 100644 web/plans/260427-1036-three-mode-and-master-auto-tick/plan.md create mode 100644 web/plans/reports/code-reviewer-260427-1036-three-mode.md create mode 100644 web/src/lib/call-bus.svelte.js create mode 100644 web/src/lib/call-bus.test.js diff --git a/web/docs/codebase-summary.md b/web/docs/codebase-summary.md index 1909538..6fb6a1d 100644 --- a/web/docs/codebase-summary.md +++ b/web/docs/codebase-summary.md @@ -6,24 +6,25 @@ | File | Purpose | |------|---------| | `src/routes/+layout.svelte` | Root HTML layout. Sets Vietnamese lang, imports Geist font, applies global flex layout. | -| `src/routes/+page.svelte` | Player page (`/`) — the ONLY page. Header + SettingsButton, PlayerBoard, conditional MasterPanel (when `settings.masterMode`), PageFooter. Indigo→purple gradient branding. | +| `src/routes/+page.svelte` | Single page (`/`). Header + SettingsButton, renders player/master/both via `settings.mode`. Indigo→purple gradient branding. | ### Shared Components | File | Purpose | |------|---------| | `src/lib/PlayerBoard.svelte` | Reusable player card (9×9 grid rendered as 3 stacked 3×9 mini-cards: Tân Tân / An khang thịnh vượng / Tân Tân tốt nhất). Tall (3:4 on mobile; 3:5 on sm+) cells with condensed bold black numbers (`tan-tan-num` font stack), white number cells, purple empty cells (dark mode dims via `filter:brightness(0.85)`). Handles crossed state, animated cross-out (200 ms `cross-draw` keyframe), `active:scale-90` press, 10 ms haptic on tap. Two header actions: "Tạo bảng mới" / "Xoá đánh dấu". First-run state shows a faded preview card. Bingo popup tiers: row 1 = standard celebration; row 3+ = falling-emoji confetti rain via CSS `confetti-fall`. Toast "Chờ N" + audio. Accepts `storagePrefix` prop for multi-card isolation. | | `src/lib/SettingsButton.svelte` | Gear icon + modal (responsive `max-w-sm sm:max-w-md`). 5 fieldsets: Giao diện (theme pills), Chế độ quản trò (switch row), Tự động xổ (switch + speed slider), Âm thanh (two switches + voice picker), Màu ô trống (10 Excel color swatches + custom picker). Boolean toggles use a shared `switchRow` snippet (`role="switch"` + keyboard support). Reset-to-default button. Mounted on `/`. | -| `src/lib/MasterPanel.svelte` | Host controls. New game / draw, large "Số vừa xổ" hero token (160 px mobile, 224 px sm+) with `aria-live="assertive"` + auto `scrollIntoView` on each new draw, "Thứ tự đã xổ" history list, 11×9 last-digit-aligned tracking grid (with circular tokens + draw-order overlay). No host's own player card (the player already has one above). "Xổ số" / "Bắt đầu / Dừng" button bound to auto-call. Mounted conditionally on `/` when `settings.masterMode === true`; the wrapping section uses `transition:slide` for smooth toggle-in. | +| `src/lib/MasterPanel.svelte` | Host controls. New game / draw, large "Số vừa xổ" hero token (160 px mobile, 224 px sm+) with `aria-live="assertive"` + auto `scrollIntoView` on each new draw, "Thứ tự đã xổ" history list, 11×9 last-digit-aligned tracking grid (with circular tokens + draw-order overlay). Publishes draws to `call-bus` for player auto-tick. "Xổ số" / "Bắt đầu / Dừng" button bound to auto-call. Mounted conditionally on `/` when `settings.mode !== "player"`; the wrapping section uses `transition:slide` for smooth toggle-in. | | `src/lib/PageFooter.svelte` | Footer with tagline ("Made by miti99 with ❤️ SVG icon") + link. Mounted on `/`. | -### Game Logic +### Game Logic & Coordination | File | Purpose | |------|---------| | `src/lib/game-logic.js` | Stateless utilities: generateGrid (constraint-aware picker — exact 5 per row & per col, ascending-sorted columns, soft "no 3 consecutive filled cols per row" via rejection sampling), saveGrid, loadGrid, saveCrossedState, loadCrossedState, isRowComplete, getWaitingNumber. | +| `src/lib/call-bus.svelte.js` | Pub/sub for master draws → player auto-tick. Reactive `bus.lastDrawn` slot (emits `{ num, at }`). Used in `mode: "both"` to auto-mark master-called numbers on player board. | | `src/lib/vietnamese-number.js` | `numberToVietnamese(n)` — pure utility mapping 0..90 to spoken Vietnamese, with tonal exceptions (15 → "mười lăm", 21 → "hai mươi mốt", 25 → "hai mươi lăm"). Out-of-range falls back to `String(n)`. | | `src/lib/voice.js` | Bundled-MP3 playback. Exports `playNumber(n)`, `playWaiting(n)` (sequences cho + N), `playBingo()`, `cancelPlayback()`. Lazy `