ncode b32c38019e Phase 2: domain layer with tests
Vite + React + TypeScript + Vitest. No router, state library or UI kit.

The 159-row combo table is extracted from reference/index.html by
scripts/extract-reference-data.mjs rather than retyped: it balances
brackets past string literals to slice out the pure-data declarations and
evaluates them in a vm with no DOM. raw.ts and labels.ts are generated.
The extracted count matches the 159 the Phase 1 app reported on device.

Entry.id keeps the reference's format verbatim (shift>p1@S#FIX VEL),
built from the unsplit context string, so drill progress already on the
phone migrates instead of being orphaned.

The domain is pure where the reference was not: boxes go in and new
boxes come out, and the random source is injected. That is what made
card selection testable.

Two bugs found by doing so:

- pickCard returned the card just answered when random() gave exactly 0.
  A zero-weight card does not move the accumulator, so "r <= 0" matched
  it. The reference has this; at one draw in 2^53 it is invisible in use,
  but a pinned random source hits it every time. Fixed to "r < 0".
- boxDistribution incremented through an index that
  noUncheckedIndexedAccess types as possibly undefined.

65 tests. Several assert numbers observed on the device: 159 entries,
sample-mode layers of 3 / 35 / 2, a 16-card SHIFT+pads deck.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 00:54:34 +03:00
2026-09-17 00:54:34 +03:00
2026-09-17 00:54:34 +03:00
2026-09-17 00:54:34 +03:00
2026-09-17 00:54:34 +03:00
Description
An SP-404 MK2 key combos trainer & quick reference
MIT 920 KiB
2026-09-17 18:51:01 +00:00
Languages
TypeScript 41.6%
HTML 40.3%
CSS 7.3%
JavaScript 6.3%
Shell 3.9%
Other 0.6%