ui/phase-19: legacy parser learns Your Groups / Your Fleets / Incoming Groups
The parity rule from ui/PLAN.md says every UI phase that decodes a
new Report field must extend the legacy converter in lockstep.
Phase 19 brings ship groups (LocalGroup / OtherGroup /
UnidentifiedGroup / IncomingGroup) and LocalFleet onto the wire-
compatible UI surface; this commit teaches
tools/local-dev/legacy-report to populate the three sections that
exist in the legacy text format:
- "Your Groups" → []LocalGroup. Cargo type, load, fleet name,
state, on-planet vs hyperspace position (origin / range) all
decoded; LocalGroup.ID is synthesised deterministically from
the per-report group index so re-running the converter
produces byte-identical JSON. Speed is left zero — the legacy
table doesn't expose it.
- "Your Fleets" → []LocalFleet. Origin / range / state mirror
the row layout used by Killer / Tancordia variants; gplus's
state-less rows still resolve.
- "Incoming Groups" → []IncomingGroup. Origin / destination
names — and `#NN` by-id references — resolve against the
parsed planet tables. Because the section can land before
"Your Planets" in some engines, group / fleet / incoming rows
are buffered and resolved in `parser.finish` after every
planet is known.
Battles, OtherGroup (only ever in battle rosters), and
UnidentifiedGroup stay out of scope — README.md spells out what
remains not-derivable.
Adds Killer031–033 / TSERCON_Z032–033 / Tancordia036–039 fixtures
to the dg directory and exercises three of them through new
TestParseDg{Killer031,Tancordia037,KNNTS041} smoke tests, plus
inline tests for each new section parser. Drops the stale
KNNTS039.json artefact left over from Phase 18 development.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -60,22 +60,47 @@ already decodes from server responses
|
||||
| `UninhabitedPlanet[]` | `Uninhabited Planets` |
|
||||
| `UnidentifiedPlanet[]`| `Unidentified Planets` |
|
||||
| `LocalShipClass[]` | `Your Ship Types` |
|
||||
| `LocalGroup[]` | `Your Groups` (Phase 19) |
|
||||
| `LocalFleet[]` | `Your Fleets` (Phase 19) |
|
||||
| `IncomingGroup[]` | `Incoming Groups` (Phase 19) |
|
||||
|
||||
Players whose name in the legacy file ends with `_RIP` are emitted with
|
||||
the suffix stripped and `Extinct: true`.
|
||||
|
||||
`LocalGroup.ID` is synthesised deterministically from the per-report
|
||||
group index via `uuid.NewSHA1`, so re-running the converter on the same
|
||||
input file yields byte-identical JSON.
|
||||
`LocalGroup.Speed` is left at zero — the legacy "Your Groups" table does
|
||||
not expose ship speed; the UI can derive it from `pkg/calc.Speed` if
|
||||
ever required.
|
||||
Origin / Range names that don't resolve against the parsed planet
|
||||
tables (foreign-only knowledge the local player lacks) cause the entire
|
||||
group / fleet / incoming row to be dropped — preferable to fabricating
|
||||
a destination.
|
||||
|
||||
## Skipped sections (today)
|
||||
|
||||
These exist in legacy reports but have no UI decoder yet, so the
|
||||
parser ignores them. Each becomes in-scope as soon as its UI phase
|
||||
lands (see "Adding a new field" below).
|
||||
These exist in legacy reports but either have no UI decoder yet or
|
||||
cannot be derived from the legacy text format at all. Each becomes
|
||||
in-scope as soon as its UI phase lands (see "Adding a new field"
|
||||
below).
|
||||
|
||||
- Foreign / other ship types (`<Race> Ship Types`)
|
||||
- Sciences, both local (`Your Sciences`) and foreign (`<Race> Sciences`)
|
||||
- Battles (`Battle at (#N) Name`, `Battle Protocol`)
|
||||
- Battles (`Battle at (#N) Name`, `Battle Protocol`) — battle rosters
|
||||
inside these blocks carry minimal columns (no origin / range /
|
||||
destination) and are intentionally skipped: parsing them would
|
||||
produce mostly-empty `OtherGroup` records that drift away from the
|
||||
typed contract.
|
||||
- Bombings (`Bombings`)
|
||||
- Approaching / foreign groups (`Approaching Groups`, `<Race> Groups`)
|
||||
- Ships in production (`Ships In Production`)
|
||||
- `OtherGroup[]` — no top-level legacy section. Foreign groups appear
|
||||
only inside battle rosters (see above), with stripped columns; the
|
||||
synthetic JSON emits `otherGroup: []`.
|
||||
- `UnidentifiedGroup[]` — no legacy section at all; synthetic JSON
|
||||
emits `unidentifiedGroup: []`.
|
||||
- `OtherShipClass[]` — present in legacy as `<Race> Ship Types`, but
|
||||
no UI decoder yet; synthetic JSON emits `otherShipClass: []`.
|
||||
- Cargo routes — no dedicated section in the legacy text format; the
|
||||
synthetic JSON emits `route: []`. The UI's overlay path
|
||||
(`applyOrderOverlay`) supports running on top of an empty `routes`.
|
||||
@@ -114,8 +139,20 @@ go test ./tools/local-dev/legacy-report/...
|
||||
```
|
||||
|
||||
Inline fixtures exercise the per-section row parsers; smoke tests
|
||||
parse the real `dg/KNNTS039.REP` and `gplus/40.REP` and assert
|
||||
top-level counts (number of planets, players, extinct races, ship
|
||||
classes). Field-level fidelity is the inline tests' responsibility;
|
||||
the smoke tests catch regressions where a refactor of the section
|
||||
classifier silently drops a whole table.
|
||||
parse the real fixtures under `tools/local-dev/reports/dg/` and
|
||||
`tools/local-dev/reports/gplus/` and assert top-level counts. The
|
||||
current smoke set spans:
|
||||
|
||||
- **dg/KNNTS039–041** — KnightErrants saga; `041` is the only one
|
||||
with `Incoming Groups`, exercising deferred name resolution.
|
||||
- **dg/Killer031** — Killer engine variant with two `Your Fleets`
|
||||
entries (`Fl1`, `F2`).
|
||||
- **dg/Tancordia037** — the richest fixture: 311 local groups in
|
||||
30 fleets, two incoming groups, "Incoming Groups" landing before
|
||||
"Your Planets".
|
||||
- **gplus/40.REP** — gplus variant; tabs in headers, pseudo-cyrillic
|
||||
ship class names, single fleet, ten incoming groups.
|
||||
|
||||
Field-level fidelity is the inline tests' responsibility; the smoke
|
||||
tests catch regressions where a refactor of the section classifier
|
||||
silently drops a whole table.
|
||||
|
||||
Reference in New Issue
Block a user