Green and Going
A browser trainer for shot release timing that separates consistency from bias — because one is a single correction and the other is weeks of work.
- Section
- games
- Year
- 2026
- Role
- Solo project
- Stack
- TypeScript, Canvas, Vite, Vitest
Summary
A browser trainer for shot release timing. Instead of one green percentage, it reports consistency (the spread of your release error) separately from bias (the mean), because those are different problems with different fixes — one is a single correction, the other is weeks of work.
Story
Green percentage can’t tell two players apart: releasing 34 ms early with a 4 ms
spread greens about as much as averaging dead centre with a 45 ms spread, and
only one of those is one adjustment from fixed. Splitting the two lets the
coaching layer model your error as normal around your measured spread and
estimate what you’d green if you corrected only the bias — the number that
says where effort pays. Everything downstream follows from one rule: timing
comes from event timestamps, never from frames. The engine owns no clock and
touches no DOM, so scoring is testable against synthetic input. Gamepads were
the hard part, since the API fires no events and polling on rAF quantises every
measurement to ~16.7 ms — a third of the green window. It idles on rAF, switches
to a MessageChannel pump for the duration of a rep, and scores from
gamepad.timestamp rather than when the page noticed.
Lessons
- A single summary number can hide the distinction that decides what someone should practice.
- An instrument whose noise floor is a meaningful slice of its own window has to report that — the app says your controller’s resolution out loud.
- Measured claims need guarded language. Nothing shows below 8 reps, projections are labelled as models, and a test asserts the report contains no causal wording.