Files
loto/docs/codebase-summary.md
T
tiennm99 e23ddcc7bc refactor: move shared modules out of app/
`app/` should hold route segments only. Game logic and the player-card
component are imported by both routes, so they belong outside:

  app/loto-game-logic.ts   -> lib/game-logic.ts
  app/loto-player-board.tsx -> components/player-board.tsx

Imports use the existing @/* alias. Drops the redundant `loto-` prefix.
Also fixes the package name from the scaffold default.
2026-04-26 19:34:37 +07:00

76 lines
3.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Codebase Summary
## File Organization
### Routing & Layout
| File | Purpose |
|------|---------|
| `app/layout.tsx` | Root HTML layout. Sets Vietnamese lang, imports Geist font, applies global flex layout. |
| `app/page.tsx` | Player page (`/`). Instructions toggle, PlayerBoard component, indigo gradient branding. |
| `app/master/page.tsx` | Host page (`/master`). Controls (new game, draw number), 9×10 master board, host's player card. |
### Shared Components
| File | Purpose |
|------|---------|
| `components/player-board.tsx` | Reusable player card (9×9 grid). Handles crossed state, bingo popup, "Chờ X" toast. Accepts `storagePrefix` prop for multi-card isolation. |
### Game Logic
| File | Purpose |
|------|---------|
| `lib/game-logic.ts` | Stateless utilities: generateGrid (weighted column selection), saveGrid, loadGrid, saveCrossedState, loadCrossedState, isRowComplete, getWaitingNumber. |
### Styling
| File | Purpose |
|------|---------|
| `app/globals.css` | Root styles: Tailwind @import, CSS variables (light/dark), `.loto-grid` & `.master-grid` (9-col), animations (fade-in, pop-in, bounce-slow, spin-slow, toast), `.cell-crossed` diagonal. |
### Configuration
| File | Purpose |
|------|---------|
| `next.config.ts` | Dual basePath: prod `/loto`, codeserver `/absproxy/{PORT}`. Exports static HTML. HMR-aware. |
| `package.json` | Next 16.2.2, React 19.2.4, Tailwind 4. Scripts: dev, dev:codeserver, build, start, lint. |
| `eslint.config.mjs` | ESLint 9 config (Next.js preset). |
| `.gitignore` | Excludes node_modules, .next, .env.local, etc. |
| `.env.example` | Template for env vars (currently none required for runtime; codeserver profile reads CODESERVER_HOST/PORT). |
## Key Data Structures
**Grid**: 9×9 2D array of numbers (190). Empty cells are 0.
**Crossed**: 9×9 2D array of booleans indicating marked cells.
**Master State**: `{ called: number[], remaining: number[] }` — drawn and undrawn numbers.
## Storage Keys (localStorage)
| Key | Use Case |
|-----|----------|
| `loto_grid` | Player's card numbers. |
| `loto_crossed` | Player's marked cells. |
| `loto_master` | Host's drawn/remaining numbers. |
| `loto_master_card_grid` | Host's player card numbers. |
| `loto_master_card_crossed` | Host's marked cells. |
## Component Hierarchy
```
RootLayout
├── HomePage (/)
│ ├── Instructions toggle
│ └── PlayerBoard (storagePrefix="loto")
└── MasterPage (/master)
├── Controls (new game, draw)
├── Master board (9×10)
└── PlayerBoard (storagePrefix="loto_master_card")
```
## Key Functions
| Function | Location | Effect |
|----------|----------|--------|
| `generateGrid()` | game-logic.ts:52 | Creates 9×9 with weighted column selection (5 nums/row). |
| `isRowComplete()` | game-logic.ts:108 | Boolean: all non-zero cells in row crossed? |
| `getWaitingNumber()` | game-logic.ts:120 | Returns the single uncrossed number in row, or null. |
| `handleCellClick()` | player-board.tsx:112 | Toggle crossed[row][col]. |
| `handleDrawNext()` | master/page.tsx:88 | Pop first number from remaining, add to called. |
Last reviewed: 2026-04-26