Public: anyone can read this; the crew can change it.
forked from trevato/cs
The standings can be kept per map: `standing` carries the map, and `standings` takes one or none #422
Check · Review · Land · Live done — Landed and live in production.
#419 (merged as `20f4f9d`) already shipped most of this data layer. `standing` is keyed by `(user_id, name, map)`. A database from before the change rebuilds that table from `match` when it opens. `standings(db, limit, map?)` takes a `PlayedMap`, which the server checks at the boundary with `playedOn` from `src/mapname.ts`. And pruning a match already recomputes that player's row on every map. Thi…
shipped production is serving it deploy ae07c2d
Sign in to join this conversation.
#419 (merged as
20f4f9d) already shipped most of this data layer.standingis keyed by(user_id, name, map). A database from before the change rebuilds that table frommatchwhen it opens.standings(db, limit, map?)takes aPlayedMap, which the server checks at the boundary withplayedOnfromsrc/mapname.ts. And pruning a match already recomputes that player's row on every map. This pull adds the proof #414 asked for, and fixes a failing check onmain.bun run testpasses: typecheck plus 1743 tests.New tests in
src/db.test.ts:standings(db)equals the originalGROUP BYovermatch, row for row. The per-map boards together contain each counted match exactly once.standing, gives the same board after opening as it did before. That board is also its wholede_forgeboard.de_forgeboard leaves out one player's results on a generated map, while the whole board adds them in.map = '').Why a kept row for the whole board, not a sum: summing a player's per-map rows means grouping every player and sorting the totals before
LIMITcan apply. That is the sameGROUP BYthestandingtable was built to replace. The keptmap = ''row costs one moreINSERT … SELECTper write, limited to that one player's matches. The reason is now written in the comment above the table insrc/db.ts.Query plans, for the whole board and for one map:
WHERE map = '':SEARCH standing USING INDEX standing_by_rank (map=?)WHERE map = 'gen_1z':SEARCH standing USING INDEX standing_by_rank (map=?)Neither needs a sort step. Timings, median of 21 reads, with 10,000 matches from 1,000 players on 200 maps (6,500
standingrows):de_forgeboardTest I changed because the budget was wrong:
mainfails the check. Insrc/server.test.ts,/weighs 10,687 B gzipped on that test file's heaviest database, over its 10,500 B budget, because of the map list and filter sentence #419 added to the board. I raised the budget to 11,000 B and wrote the reason in the comment above it.Not changed: no page or terminal changes.
src/tty.tsstill callsstandings(db)with no map and gets the same board, andStandingkeeps its shape for #234 and #89.🤖 Generated with Claude Code
Closes #414