Ilia Denisov 6d0dd4fb14
Tests · Go / test (push) Successful in 6s
Tests · Integration / integration (push) Successful in 7s
Stage 2: engine package over scrabble-solver (registry, bag, Game, replay)
backend/internal/engine wraps the sibling scrabble-solver library in-process:

- Registry: versioned DAWG load via dafsa.Load, keyed by (variant, dict_version),
  latest-per-variant; English / Russian / Эрудит handled uniformly.
- Bag: own deterministic, seeded tile bag with Draw + Return (for exchanges),
  since the solver's self-play bag cannot return tiles.
- Game: pure rules engine — deal, play/pass/exchange/resign, refill, per-move
  scoring, turn order, and end-condition detection (empty bag + empty rack, six
  scoreless turns, resignation) with end-game rack adjustment.
- decode/ReplayBoard: dictionary-independent MoveRecords and board replay via
  scrabble.Apply (no internal/encoding), realising ARCHITECTURE §9.1.

Wiring: go.work gains "replace scrabble-solver => ../scrabble-solver"; backend
requires scrabble-solver (placeholder) and github.com/iliadenisov/dafsa directly.
Both Go CI workflows clone the public solver sibling (master HEAD, no token) and
set BACKEND_DICT_DIR.

Docs: ARCHITECTURE §5/§14, TESTING engine layer, backend README, and PLAN
refinements + deferred TODOs (publish/version solver; split engine vs dictionary
generator).
2026-06-02 15:10:08 +02:00

scrabble-game

Multiplatform Scrabble game. Players arrive from a platform (Telegram first; later VK/MAX/iOS/Android) or from standalone web (email / guest). The game supports English Scrabble, Russian Scrabble and Эрудит.

Components

  • gateway — the only public ingress: anti-abuse, platform authentication (resolves the player and injects X-User-ID), routing to backend, and an admin surface behind Basic Auth. (added in a later stage)
  • backend — internal-only service that owns every domain concern and embeds the scrabble-solver engine library in-process.
  • ui — pure-HTML5 client (plain Svelte + Vite), embeddable in platform webviews and packageable to native via Capacitor. (added in a later stage)
  • platform/* — per-platform side-services (e.g. the Telegram bot). (added in a later stage)

Documentation (sources of truth)

Build & test

go build ./backend/...  # per module (the workspace spans several modules)
go vet ./backend/...
gofmt -l .              # must print nothing
go test -count=1 ./backend/...                       # unit tests
go test -tags=integration -count=1 -p=1 ./backend/... # + Postgres (needs Docker)

The integration-tagged tests start a throwaway postgres:17-alpine container via testcontainers-go and require a reachable Docker daemon.

Run the backend locally

The backend now owns persistence, so it needs Postgres and applies its embedded migrations at startup:

docker run -d --name scrabble-pg -e POSTGRES_PASSWORD=dev -p 5432:5432 postgres:17-alpine
BACKEND_POSTGRES_DSN='postgres://postgres:dev@localhost:5432/postgres?search_path=backend&sslmode=disable' \
  go run ./backend/cmd/backend     # serves /healthz and /readyz on :8080

Key environment: BACKEND_HTTP_ADDR (default :8080), BACKEND_LOG_LEVEL (debug|info|warn|error, default info), BACKEND_POSTGRES_DSN (required). The full configuration surface and the go-jet regeneration step live in backend/README.md.

S
Description
No description provided
Readme 7.9 MiB
Languages
Go 64.7%
TypeScript 26.1%
Svelte 7.4%
Go Template 0.9%
CSS 0.5%
Other 0.2%