tiennm99 fb0ef9f783 feat(card): avoid 3 consecutive filled columns in any row
Soft visual constraint: no row has cols n, n+1, n+2 all filled.
Implementation = constraint-aware per-row picker (uniformly samples
triple-free completions of the forced+candidate set) + whole-grid
rejection sampling (up to 200 attempts). Hard invariants (5 per row,
5 per col, ascending column values) are never sacrificed; if the soft
constraint can't be met, the generator returns the best attempt.

- src/lib/game-logic.js: hasThreeInARow, combinations,
  pickFilledColsOnce, pickFilledCols rejection wrapper
- src/lib/game-logic.test.js: 300-trial strict assertion
- docs/codebase-summary.md, project-overview-pdr.md: note the rule
2026-04-27 07:57:10 +07:00
2026-04-26 19:16:46 +07:00
2026-04-26 21:06:53 +07:00

Lô tô

Bàn số của trò chơi "Lô tô" — SvelteKit app.

Two routes: / for players, /master for the host (quản trò) — calls numbers, shows a tracking board, and has its own player card to play along.

See docs/ for architecture, code standards, and deployment.

Development

npm install
npm run dev

Inside code-server (reverse proxy)

cp .env.example .env.local
# edit .env.local: set CODESERVER_HOST and CODESERVER_PORT
npm run dev:codeserver

Open https://<CODESERVER_HOST>/absproxy/<CODESERVER_PORT>/.

Use /absproxy/{port}/, not /proxy/{port}/ — the latter strips the path prefix and breaks the SvelteKit base path.

Build

npm run build         # default — root basePath, for Cloudflare Pages
npm run build:gh      # /loto basePath, for tiennm99.github.io/loto manual export

Static export to build/. Deployed to Cloudflare Pages from main (set up via the CF dashboard — see docs/deployment-guide.md).

S
Description
Lô Tô (Vietnamese lottery bingo) number board — Next.js web app
Readme
3.7 MiB
Languages
TypeScript 89.9%
CSS 8%
JavaScript 2.1%