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>
42 lines
1.4 KiB
JSON
42 lines
1.4 KiB
JSON
{
|
|
"name": "sp404-layers",
|
|
"version": "1.0.0",
|
|
"private": true,
|
|
"type": "module",
|
|
"description": "SP-404MK2 combo trainer, wrapped as an Android app",
|
|
"scripts": {
|
|
"sync:www": "bash scripts/sync-www.sh",
|
|
"sync": "npm run sync:www && npx cap sync android",
|
|
"apk": "npm run sync && cd android && ./gradlew assembleDebug",
|
|
"install:apk": "adb install -r android/app/build/outputs/apk/debug/app-debug.apk",
|
|
"device:awake": "bash scripts/device.sh awake",
|
|
"device:keep-awake": "bash scripts/device.sh keep-awake",
|
|
"device:sleep-normal": "bash scripts/device.sh sleep-normal",
|
|
"device:launch": "bash scripts/device.sh launch",
|
|
"run:android": "npm run apk && npm run install:apk && npm run device:launch",
|
|
"logcat": "adb logcat -s Capacitor:V Capacitor/Console:V chromium:V",
|
|
"test": "vitest run",
|
|
"test:watch": "vitest",
|
|
"typecheck": "tsc --noEmit",
|
|
"extract:data": "node scripts/extract-reference-data.mjs"
|
|
},
|
|
"dependencies": {
|
|
"@capacitor/android": "^8.5.2",
|
|
"@capacitor/app": "^8.1.1",
|
|
"@capacitor/core": "^8.5.2",
|
|
"@capacitor/haptics": "^8.0.2",
|
|
"@capacitor/preferences": "^8.0.1",
|
|
"react": "^19.3.0",
|
|
"react-dom": "^19.3.0"
|
|
},
|
|
"devDependencies": {
|
|
"@capacitor/cli": "^8.5.2",
|
|
"@types/react": "^19.3.0",
|
|
"@types/react-dom": "^19.3.0",
|
|
"@vitejs/plugin-react": "^6.1.1",
|
|
"typescript": "^7.0.2",
|
|
"vite": "^8.3.0",
|
|
"vitest": "^5.0.1"
|
|
}
|
|
}
|