Radar Plotting Trainer
Paper plots do not check themselves. This one is graded against two independent answer keys.
- 12 daysPython prototype to TypeScript monorepo
- 16 problemsgraded against two independent answer keys
- 1,589 testsgreen across both answer keys
Paper does not tell you when you are wrong.
Deck licence candidates work maneuvering board problems by hand, on a paper plotting sheet, under examination conditions. The construction is unforgiving and the feedback arrives at the end: one vector laid off a degree wide carries through every step after it, and the mistake only shows up when the final answer misses.
An earlier Python version of this got the method right and the frame of reference wrong. It drew the board head up, with own ship’s course sitting at 000, and recovered the true course by adding that course back at the very end. That is a legitimate way to work a relative plot on paper. On a screen it means the bearings drawn are relative rather than true, so certain valid inputs plotted wrongly, and nothing in the app said so.
Rebuild it in TypeScript, and let the answer keys decide.
The rewrite is a four-package TypeScript monorepo. Geometry holds every construction and knows nothing about a screen, render turns a solved problem into a scene, app is the React front end, and export is the interface for handing a worked sheet back out. The port took 12 days, and the language was new. Claude Code carried the debugging and refactoring and wrote a tutorial alongside each feature as it landed, 42 of them by the end.
Correctness here is graded, not asserted. The suite runs the solver against two independent answer keys: six worked examples from Pub. 217, the United States government maneuvering board manual, and ten problems from a separate training key. Sixteen problems, twelve of which require a maneuver. A branch protection rule blocks any merge to main until the whole suite passes.
The retired prototype is a second witness, on one scenario. Run on its own default problem, the two implementations agree on all nine reported values, down to the decimals behind the rounding. That is corroboration rather than proof, and worth saying why: own ship steers 000 there, which is the one heading the older frame of reference could not get wrong.
Two cases are skipped deliberately, each with its reason written down, and neither is quietly smoothed over. The standing rule when a hand-derived construction disagreed with a key was that the fixture is what gets questioned first, then the instrument doing the measuring, then the geometry. One suspected transcription error turned out to be neither: the tolerance had been set without allowing for answers already rounded to the nearest knot.


See the same run from either viewpoint.
It grades the plot, and it shows the motion.
Enter two radar observations of a contact, own ship’s course and speed, and the closest point of approach you need. It returns the contact’s true course and speed, the CPA and the time to it if nobody alters, and the course or speed change that opens the CPA to the distance required. It cites COLREGS Rule 19 for which way the turn should go, and leaves the decision with the mariner.
The board draws two ways. One is the familiar top-down plotting sheet. The other is a tilted sea view, and the transition eases between them while the clock keeps running, so the geometry stays continuous rather than cutting. Motion plays back across the run, which lets a trainee watch relative motion develop instead of reading it off a finished sheet. The prototype had neither view and no playback at all.
The modelling is deliberately narrow. It assumes instantaneous course changes, ignores advance and transfer, ignores set and drift, and takes every contact as holding a steady course and speed. It is a trainer, not a navigation instrument, and the repository says so in those words.
- TypeScript
- React
- SVG
- Node
- Vitest