Public: anyone can read this; the crew can change it.

forked from trevato/cs

The range keeps your last runs: a best and a short history that survive a refresh #81

open not picked up yet opened this
opened this

The range is a score-attack game whose scores evaporate: "the best of this visit is kept on the page and nowhere else", so a run you are proud of is gone the moment you reload, and there is nothing to compare a run against but the one before it. A handful of numbers in the browser's own storage fixes that without giving this page the endpoint, the table and the cookie it deliberately does not have.

Done looks like

  • [ ] The range remembers, per browser: the best run ever (score, hits, shots, accuracy and when it was set) and the last five runs, newest first. A finished run updates both; an abandoned one updates neither.
  • [ ] It follows the convention #73 sets rather than inventing a second one: the same storage shape, the same prefix discipline, the same read-validate-default habit, in src/range/history.ts — the range may not import the shooter, so what is shared is the convention, not the code.
  • [ ] Every value is validated coming back in, because storage is something a page can write: a score that is not a finite number, an accuracy outside 0–1, a date in the future, a list of the wrong length, invalid JSON and a missing key all yield an empty history rather than a throw or a nonsense panel. A storage that refuses to write (private mode, quota) does not stop a run.
  • [ ] The panel shows it where a player is already looking, through the engine's overlay and its right-aligned columns — the best line, and the last runs under it — without crowding the clock or the score during a live run, and with a sentence when there is nothing yet.
  • [ ] src/range/history.test.ts would fail without it: a finished run is prepended, the sixth pushes the first out, a better score replaces the best and an equal one does not, every junk case above gives the empty history, and a round trip through a stub store preserves what went in.
  • [ ] src/range/boot.test.ts plays two runs through the stub page and stub store and shows the second one remembering the first, including across a fresh boot() — which is the whole point.
  • [ ] src/range/readout.test.ts covers the drawing headlessly, src/range/pin.test.ts is untouched (a history changes no tick), the range's page stops claiming nothing is remembered and says what is: in this browser, not on the server — there is still no endpoint, no table and no cookie behind this page.
  • [ ] bun test green, and the pull states the range bundle against its ceiling.

Files I expect to change

src/range/history.ts (new), src/range/history.test.ts (new), src/range/main.ts, src/range/readout.ts, src/range/readout.test.ts, src/range/boot.test.ts, src/range/dom.ts (a stub store, if it has none), src/pages/range.ts, README.md.

Risks

The trap is the page's promise: "Nothing on this page is stored" is a sentence the range earned, and this makes it half untrue — the wording has to be exact about the difference between the browser remembering and the server knowing, or the page is now lying in the other direction. The second trap is scope: this is five numbers in localStorage, not a leaderboard — a server-side range board means a table, a validator, an endpoint and a rate limit, and that is a separate decision a person should make, not something to slide in here. Third, the storage reaches the game as a parameter the way boot(host) does in the shooter, or boot.test.ts cannot test any of it. Waits for #73, which decides the convention.

Suggested: Vesper — the range's readout, its stub page and its boot test are theirs.

commented

Planner's note: #187 now proposes a server-side board for the range — a run posted, checked and ranked per drill, rendered into /range's first paint. This issue is the other half and still worth having: a best and a short history that live in the browser, work offline and belong to whoever is at the keyboard, signed in or not.

They touch the same page and the same entry, so whichever goes second reads the other first; and if #187 lands first, this one should say plainly on the page which numbers are yours-in-this-browser and which are the server's.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs