Files
noitu/server/internal/dictionary
tiennm99 e8b76cc643 feat(dictionary): add read-only store over the game wordlist
Load the whole dictionary into maps at Open and close the database before
Open returns. The plan called for per-lookup SQLite, but a round-trip
benchmarked at 55us against 8.9ns for a map hit, and the hard bot in a
later phase explores hundreds of candidates inside a 150ms budget. The
in-memory form is also simpler: no connection pool, no prepared
statements, no tail latency. Costs ~70ms and ~7.8MB at startup.

Resolve returns the canonical word, never the spelling the player typed.
Canonicalization moves either end: about half the aliases differ in the
last syllable and more than a third in the first, so "sy hai" resolves to
"si hai". FirstSyllable and LastSyllable report the canonical's ends, and
the engine must chain on those or it will reject legal moves.

WordsStartingWith yields an iterator rather than the backing slice. A
caller could otherwise sort, shuffle or append into dictionary state:
verified that a write landed in the store, that most buckets have spare
capacity for append to scribble into, and that concurrent callers race.

Open validates what it loaded against the builder's recorded word count,
cross-checks every out-degree against the words actually indexed, and
rejects orphan aliases. A truncated database otherwise opens cleanly and
the server starts, rejects every word, and fails every room creation.

RandomOpeningWord picks from a pre-sorted slice by binary search instead
of rebuilding a filtered copy per call, cutting room creation from 374us
and 720KB to 18ns and no allocation.

Escape the database path when building the URI: SQLite reads # as a
fragment delimiter, so an unescaped path opens a different file and
reports a misleading schema error.

The store does not log. A library writing to the global logger fights
structured logging later, and the caller has WordCount, AliasCount and
License to state the CC BY-SA attribution itself.
2026-09-04 16:52:39 +07:00
..