feat: on-device move preview (local eval) with network fallback
CI / changes (pull_request) Successful in 3s
CI / unit (pull_request) Successful in 10s
CI / integration (pull_request) Successful in 15s
CI / ui (pull_request) Successful in 58s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m17s
CI / changes (pull_request) Successful in 3s
CI / unit (pull_request) Successful in 10s
CI / integration (pull_request) Successful in 15s
CI / ui (pull_request) Successful in 58s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m17s
Score and validate a tentative move on-device instead of a per-arrangement network
round trip. The dawg reader and the validate/score/direction slice of the
scrabble-solver engine are ported to TypeScript (ui/src/lib/dict), pinned
byte-for-byte to the Go engine by a `conformance` CI job (full-dictionary reader
parity plus a battery of plays across every variant and both cross-word rules,
including the inferred orientation). The server stays authoritative — submit_play
re-validates — so the local result is an advisory accelerator only.
- backend: Registry.DictBytes + an authed GET /api/v1/user/dict/{variant}/{version}
(immutable) streaming the pinned per-game dawg; caddy routes /dict to the gateway.
- gateway: a session-gated /dict edge route proxying it; fetchDict on the transport.
- client: the dictionary loads on game open (low priority so it never starves the
game on a slow link; aborted at a 5s cap or when leaving the game), is cached in
IndexedDB (best-effort, self-healing on a rejected blob) and reused across
sessions; a warm-up overlay covers a cold load, then the network preview is the
fallback; a bad-connection breaker stops warming after repeated misses; the move
preview cancels its in-flight request when the tiles change.
- parity generators backend/cmd/{dictgen,validategen} + gated Vitest suites, run in
CI against the release dictionaries. A hidden debug readout lists the cached
dictionaries + breaker state, and its reset clears the cache.
- docs: ARCHITECTURE §5, TESTING, UI_DESIGN, FUNCTIONAL (+ru).
This commit is contained in:
+16
-2
@@ -85,5 +85,19 @@ export function centre(variant: Variant): { row: number; col: number } {
|
||||
return { row: 7, col: 7 };
|
||||
}
|
||||
|
||||
// Tile values and the per-variant alphabet now arrive from the server (lib/alphabet.ts);
|
||||
// the board geometry above is all this module owns.
|
||||
/** RACK_SIZE is the number of tiles drawn to a full rack — 7 for every variant. It sizes
|
||||
* the all-tiles (bingo) bonus test in the local move preview. */
|
||||
export const RACK_SIZE = 7;
|
||||
|
||||
/** BINGO is the all-tiles bonus per variant, ported from scrabble-solver/rules/rules.go:
|
||||
* 50 for the Scrabble variants, 15 for Эрудит. The local move preview adds it when a play
|
||||
* uses the whole rack. The dict conformance test pins these to the engine's rulesets. */
|
||||
export const BINGO: Record<Variant, number> = {
|
||||
scrabble_en: 50,
|
||||
scrabble_ru: 50,
|
||||
erudit_ru: 15,
|
||||
};
|
||||
|
||||
// Tile values and the per-variant alphabet arrive from the server (lib/alphabet.ts); the
|
||||
// board geometry, centre, rack size and bingo above are the static per-variant constants
|
||||
// this module owns (all ported from scrabble-solver/rules/rules.go).
|
||||
|
||||
Reference in New Issue
Block a user