feat(ui+legacy): F8-05 owner-feedback round 1 — inspector tweaks + parser
Tests · UI / test (push) Has been cancelled
Tests · UI / test (pull_request) Successful in 2m45s

Owner-reported polish on top of #48, plus a legacy-parser gap that
prevented verifying stationed ship groups against a real .REP fixture.

UI:
- Production: drop the empty `(production)` placeholder option. Owned
  planets always produce something, so the primary select now opens on
  `industry` by default when `planet.production` is null/unknown,
  keeping the row inside the four real production kinds at all times.
- Production: lock the row to a single line (no flex-wrap) and strip
  border + padding from the ✓/✗ buttons so the apply/cancel icons read
  as glyphs and the row no longer breaks into two visual rows for
  Research / Ship contexts where both selects are present.
- Cargo routes: the placeholder option is now an `<option disabled>`
  styled like a section header (greyed, italic) and reads "manage
  routes" instead of "cargo routes". The wording shifts the intent
  from a section label to an action prompt.

Legacy parser:
- F8-05 (#48 п.32) "Stationed ship groups" couldn't be verified against
  the dg fixture because the legacy `<Race> Groups` blocks (outside
  battles) and the `Unidentified Groups` block were dropped by the
  parser — both are now wired up. Foreign group rows parse the
  `# T D W S C T Q D P M` columns and resolve the destination against
  the parsed planet tables (rows with an invisible destination drop,
  matching the existing local-group convention). The legacy row
  carries no origin / range columns, so foreign groups surface as
  stationed at the destination.
- Smoke tests on every fixture extended with `otherGroups` and
  `unidentifiedGroups` counts. New focused unit test
  `TestParseOtherAndUnidentifiedGroups` covers the column layout, the
  drop-on-unknown-destination rule, and the `X Y`-only unidentified
  rows.
- `tools/local-dev/reports/dg/KNNTS039.json` and
  `tools/local-dev/reports/dg/KNNTS041.json` regenerated so the
  synthetic-loader fixtures carry the new arrays.
- README updated: the two sections move out of "Skipped sections" into
  a "Foreign and unidentified groups" block; package doc-comment
  reflects the broader scope.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Ilia Denisov
2026-05-27 15:21:55 +02:00
parent aee5f39a7e
commit cc4bc3c2b7
10 changed files with 46770 additions and 9291 deletions
+21 -5
View File
@@ -129,17 +129,33 @@ do not flow through this parser. A ships-in-production row pointing
at a planet that did not appear in `Your Planets` (which would be a
malformed legacy file) is dropped.
## Foreign and unidentified groups
The legacy text format does carry top-level `<Race> Groups` blocks
and a single `Unidentified Groups` block, both outside the battle
rosters — earlier parser revisions silently dropped them. F8-05
wires them up:
- **`OtherGroup[]`** — every `<Race> Groups` section outside a
`Battle at` block contributes one entry per row. The legacy row
is `# T D W S C T Q D P M` (count, class, drive/weapons/shields/
cargo tech, cargo type, load, destination, power=drive·20 — not
retained, mass). The destination resolves against the parsed
planet tables (`Your Planets`, `<Race> Planets`, `Uninhabited
Planets`); rows whose destination is invisible to the local
player are dropped — preferable to fabricating a number. The
legacy row carries no origin / range columns, so foreign groups
surface as stationed at the destination (origin / range nil).
- **`UnidentifiedGroup[]`** — the `Unidentified Groups` section
carries `X Y` floats only. Each row maps directly onto
`UnidentifiedGroup{X, Y}`; no planet resolution needed.
## Skipped sections (today)
These exist in legacy reports but cannot be derived from the legacy
text format at all. Each could become in-scope if a strong enough
reason arises (see "Adding a new field" below).
- `OtherGroup[]` — no top-level legacy section. Foreign groups appear
only inside battle rosters; the synthetic JSON emits
`otherGroup: []`.
- `UnidentifiedGroup[]` — no legacy section at all; synthetic JSON
emits `unidentifiedGroup: []`.
- 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`.