From bbae86e23945568495e0f10a11f3e7248ab9bfac Mon Sep 17 00:00:00 2001 From: "@permadeath.com" Date: Wed, 19 Aug 2026 16:46:34 -0400 Subject: [PATCH] docs: write down what the battle value work settled Four things that were worked out and not recorded: what it costs to put a design in front of a page and the three ways of doing it, the four formats MegaMek keeps units in, the TechManual's own worked examples agreeing with this crate term by term, and the verification still worth having. --- TODO.md | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/TODO.md b/TODO.md index bdd98e0..0f2e5d4 100644 --- a/TODO.md +++ b/TODO.md @@ -317,6 +317,52 @@ The long pole, and the reason `helm-core` does no I/O. Tracked as and checks nothing. `HELM_PERF_BLESS=1` re-records, and a commit that moves a figure should say why. +## How a design reaches the page + +The one integration question still open, and the only thing on this list that +wants a decision rather than work. A `.mul` names a design by chassis and +model and carries nothing about what is in it, so the page needs the designs +from somewhere regardless. + +Measured rather than guessed. About three quarters of a `.mtf` is prose - +`overview:`, `history:`, `deployment:` - and stripping it leaves every one of +the 4,294 battle values identical: + +| how | per design | whole library | +|---|---|---| +| `.mtf` as shipped | 8.9 KB median | 31.9 MB zip | +| `.mtf` with the prose stripped | 2.6 KB median | **0.56 MB gzipped** | +| a minimal JSON of the fields the rules read | 2.0 KB median | 0.45 MB gzipped | + +Which makes "ship the whole library and look up by chassis and model" the +option that retires the question instead of answering it: 0.56 MB beside the +0.09 MB catalogue is under 0.7 MB for everything a page could ask about, and +it can be fetched in the background while somebody browses. + +The JSON form saves 0.6 KB a design and costs a format: a new encoder in +`helm`, a new decoder in `helm-wasm`, and both able to drift from the `.mtf` +parser that conformance actually tests. Not worth it at that price. + +- [ ] **Decide, then build it.** Either a lean-library command beside + `helm catalogue`, or a per-design fetch. helm's database already stores + `unit_criticals` and `unit_armor`, so headquarters can reconstruct a + design without a `.mtf` if that turns out to suit it better. + +## What MegaMek keeps units in + +Four readers, and that is the whole set - `megamek/common/loaders` in 0.51.0: + +| format | what it is | count | +|---|---|---| +| `.mtf` | one Mek design, line-oriented text | 4,294 | +| `.blk` | every other unit type, from tanks to warships | 6,694 | +| `.mul` | a *force in a state*, XML - not a design format | interchange | +| `units.cache` | a Java-serialised index: name, tonnage, BV, cost | 1 | + +Older MegaMek had HeavyMetal Pro importers (`.hmp`, `.hmv`); they are gone. +MegaMekLab reads and writes `.mtf` and `.blk` and has no format of its own, so +it is not a fifth thing to support. + ## What the web UI needs from a .mul The format lance.blue works in, so these are the jobs it has to do. Written @@ -380,6 +426,55 @@ not obvious from any one of them. - [ ] **Verify a post-match file and show it back.** The upload check above, run on the way out rather than the way in. +- [x] **Checked against the published rules, not only against MegaMek.** The + TechManual's own three worked examples, run through helm term by term: + + | | the book | helm | + |---|---|---| + | MON-66 Mongoose | DBR 433.3, OBR 325.08, BV 758 | 433.3, 325.1, 758 | + | TDR-10SE Thunderbolt | DBR 954.85, OBR 1052.98, BV 2008 | 954.9, 1053.0, 2008 | + | WI-DM DemolitionMech | DBR 328.2 | 328.2 | + + Armour, structure, gyro, defensive equipment, the explosive penalty, + both defensive factors and both speed factors agree. That is the rules, + MegaMek and this crate arriving at the same numbers by three routes. + + Two places the book and MegaMek genuinely differ, where helm follows + MegaMek because that is what conformance means: the book gives a cockpit + modifier only for the small cockpit, where MegaMek also has torso-mounted, + small command console, drone, interface and VRRP; and the book describes a + design's *armament* where MegaMek scores everything with a battle value, + so a DemolitionMech's wrecking ball and rock cutter count. The one real + disagreement is written up in `crates/helm-bv/UPSTREAM.md`. + +- [ ] **Verification still worth having.** The structural round trip and the + generated documents cover the losses found so far. Four more, in the + order they would earn their keep: + + - **Injection into real files.** Put an unknown attribute, element, + comment and text run at every position of every real `.mul` and assert + each survives. The generator makes plausible documents; this proves the + files that actually exist tolerate whatever a later MegaMek adds. + - **A named list of what the writer may touch.** A test asserting it only + ever modifies `points`, `index`, `isDestroyed`, `isHit`, `shots`, + `gunnery`, `piloting`, `hits`, `chassis`, `model`, `type` and + `version`. That turns "do not lose data" from a habit into a check. + - **Deliberately break the guards.** The performance gate was proved to + fire by making something slower on purpose; nothing has proved the + losslessness guards fail when they should. + - **Construct, write, read.** Every round trip currently starts from a + file. Building a force in code and writing it out is lightly covered. + +- [ ] **Generate more forces from MekBay when a reader changes.** + is MegaMek's own web client and its force generator + writes `.mul` files, so it is the only source of documents this + repository did not write. It found the one interop bug nothing in the + corpus could: MekBay folds a Clan design's second name into the chassis - + `Loki (Hellbringer)` - where MegaMek keeps `chassis:Loki` and + `clanname:Hellbringer` apart, so every Clan unit in a MekBay force + matched nothing. It also cross-checked three battle values against a + third implementation. + - [ ] **Zero unregistered disagreements.** Whatever is left after the above is either our bug or theirs, and theirs gets written down by name the way the Alpha Strike specials deviation is. @@ -405,6 +500,23 @@ not obvious from any one of them. being string work. So a lance re-scores in about 0.3 ms in a browser and a company in under a millisecond, which is inside a frame either way. + Measured again through the finished boundary, from Node against the + real module rather than a sketch of one: + + | what a page does | cost | + |---|---| + | instantiate the module | 3 ms | + | load the shipped catalogue | 88 ms, once | + | score a design from its `.mtf` text | 253 us | + | re-score a *held* design, damaged | 326 us | + | re-crew a *held* design | **1 us** | + + Holding the design is what makes the last row true: reading the `.mtf` + is most of what scoring costs, and a crew only scales a base that has + already been worked out. Without a handle the same re-crew was 432us, + which is the promise of the native benchmark being thrown away at the + boundary. A lance re-crews in 4us and re-scores for damage in 1.3ms. + Three things came out of writing it. Asking "is this location exposed" per item rather than per location made the cheapest rating cost more than reading the design; the loadout's mountings were rebuilt on every call -- 2.51.2