cbb485ebd6
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 14s
CI / ui (pull_request) Successful in 51s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m11s
Replace the single "best move" number on the statistics screen with a
full-width per-variant breakdown: the highest-scoring play in each variant
the player has played, drawn as game tiles (a wildcard shows its letter but
no value), with the words and scores right-aligned to shared edges.
- backend: new account_best_move table (PK account_id+variant) keeping the
main word as JSON tiles {letter,value,blank}; captured at game finish in
buildStats (blank flags taken from every placed blank — equivalent to the
final board), upserted in the finish transaction and replaced only by a
strictly higher-scoring play. Guest/honest-AI games still record nothing.
GetStats + statsDTO expose best_moves.
- wire: StatsView gains best_moves:[BestMoveView{variant,score,word:[BestMoveTile]}]
(trailing, backward-compatible); gateway encodeStats + UI codec updated.
- ui: new WordTiles component (board's tile look, fixed px size); Stats.svelte
drops the maxWord card and adds the full-width best-move card (catalogue
order, empty variants omitted).
- docs: ARCHITECTURE §9 + schema, FUNCTIONAL (+ru), UI_DESIGN.
Tests: mainWordTiles unit + buildStats end-to-end (inttest) + gateway and UI
codec round-trips (incl. a blank tile) + e2e.
26 lines
1.3 KiB
SQL
26 lines
1.3 KiB
SQL
-- +goose Up
|
|
-- Per-account, per-variant best single move: the highest-scoring play the account has
|
|
-- ever made in each game variant. It exists so the statistics screen can show the word
|
|
-- itself broken down by variant, not just the dimensionless aggregate
|
|
-- account_stats.max_word_points. tiles is the move's main word as an ordered JSON array of
|
|
-- {letter, value, blank} objects (value 0 and blank true for a wildcard), so the client
|
|
-- renders it as game tiles without needing the variant's alphabet table. score is the
|
|
-- play's total points (every word it formed plus the all-tiles bonus), matching
|
|
-- max_word_points. A row is replaced only by a strictly higher-scoring play. It is written
|
|
-- at game finish alongside account_stats; guest and honest-AI games never record statistics,
|
|
-- so they never write here. See docs/ARCHITECTURE.md §9.
|
|
SET search_path = backend, pg_catalog;
|
|
|
|
CREATE TABLE account_best_move (
|
|
account_id uuid NOT NULL REFERENCES accounts (account_id) ON DELETE CASCADE,
|
|
variant text NOT NULL,
|
|
score integer NOT NULL,
|
|
tiles jsonb NOT NULL,
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
PRIMARY KEY (account_id, variant)
|
|
);
|
|
|
|
-- +goose Down
|
|
SET search_path = backend, pg_catalog;
|
|
DROP TABLE IF EXISTS account_best_move;
|