feat(ui): Phase 30 ship-class calculator with goal-seek and reach circles
Fuse the standalone ship-class designer (Phases 17/18) into a sidebar calculator: live mass/speed/attack/defence/bombing results, a planet build-rate readout, single-target goal-seek, a modernization-cost mode, and auto reach circles on the map for the selected planet. pkg/calc becomes the single source for the new math (no mirroring): extract BombingPower from the engine model and the per-turn ship-production loop from controller.ProduceShip into pkg/calc (engine now delegates), and add inverse goal-seek solvers in pkg/calc/solve.go. Thin-bridge the combat, planet-build, and solver functions through ui/core/calc + ui/wasm and rebuild core.wasm. Remove the standalone designer view/route; the ship-classes table and the view/bottom menus open the calculator via a shared request store. Docs: rewrite ui/PLAN.md Phase 30, adjust Phase 34 (realistic forecast + CAP/COL ownership), add ui/docs/calculator-ux.md, extend calc-bridge.md, fix navigation.md; remove ui/CALCULATOR.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+118
-56
@@ -1968,7 +1968,11 @@ Decisions baked into Phase 16 (vs. the original stage description):
|
||||
|
||||
## ~~Phase 17. Ship Classes — CRUD Without Calc~~
|
||||
|
||||
Status: done (local-ci run 20).
|
||||
Status: done (local-ci run 20). Note: Phase 30 removed the standalone
|
||||
designer view/route described below and folded ship-class create/view
|
||||
into the sidebar calculator; the table's row-activate and "new" button
|
||||
now open the calculator. The table itself and the validator are
|
||||
unchanged.
|
||||
|
||||
Goal: list, view, create, and delete ship classes through a
|
||||
dedicated table view and a designer view; numeric calculations are
|
||||
@@ -2037,7 +2041,10 @@ Targeted tests:
|
||||
|
||||
## ~~Phase 18. Ship Classes — Calc Bridge~~
|
||||
|
||||
Status: done.
|
||||
Status: done. Note: the live mass/speed/range preview built here moved
|
||||
into the Phase 30 calculator when the standalone designer was removed;
|
||||
the `ui/core/calc` ship bridge wrapped here is reused unchanged and
|
||||
extended by Phase 30 (combat, planet build, solvers).
|
||||
|
||||
Goal: wire `pkg/calc/` ship math into the designer for live mass,
|
||||
speed, range, and cargo capacity previews.
|
||||
@@ -3314,39 +3321,92 @@ Decisions:
|
||||
rendered result is verified by a high-contrast screenshot during
|
||||
development plus the existing fog / render-on-demand e2e.
|
||||
|
||||
## Phase 30. Calculator Tab
|
||||
## Phase 30. Ship Class Calculator
|
||||
|
||||
Status: pending.
|
||||
|
||||
Goal: ship an independent calculator in the sidebar, callable from any
|
||||
view, exposing the full set of `pkg/calc/` functions wired through
|
||||
`Core`.
|
||||
Goal: replace the standalone Phase 17/18 ship-class designer with a
|
||||
fused designer + calculator living in the sidebar. It shows the ship
|
||||
design blocks, live derived results (mass, speed, attack, defence,
|
||||
bombing), and a planet build-rate readout, and adds single-target
|
||||
goal-seek — the player pins one result and the model back-solves the
|
||||
single input it claims. A second mode reuses the design area to price
|
||||
ship-class modernization. The standalone designer view and route are
|
||||
removed; the ship-classes table and the view/bottom menus open the
|
||||
calculator instead.
|
||||
|
||||
The original four detached modes (ship / path / modernization /
|
||||
bombing) were dropped during planning: path is deferred (MVP path is
|
||||
brute force) and replaced by auto reach circles on the map; bombing is
|
||||
folded in as a per-ship result; ship and modernization are the two
|
||||
modes. See `ui/CALCULATOR.md` history (removed) and the interview
|
||||
decisions baked below.
|
||||
|
||||
Goal-seek claim map (one lock at a time): attack → weapons,
|
||||
defence → shields, empty/loaded speed → drive, empty mass → cargo,
|
||||
loaded mass → cargo load. Locking one result disables the others'
|
||||
lock affordances; an unreachable target shows the locked cell in an
|
||||
error state. Tech levels and the planet MAT are override inputs with a
|
||||
reset lock; the player tech is the default.
|
||||
|
||||
Artifacts:
|
||||
|
||||
- `ui/frontend/src/lib/sidebar/calculator-tab.svelte` UI with mode
|
||||
selector (ship calculator, path calculator, modernization cost,
|
||||
bombing power) and per-mode forms
|
||||
- bridge entries in `ui/core/calc/` for any function not already
|
||||
wrapped by Phase 18
|
||||
- topic doc `ui/docs/calculator-ux.md` documenting modes,
|
||||
layouts, and the rule that calculator inputs persist across
|
||||
navigation
|
||||
- `pkg/calc/` additions, single-sourced (no mirroring): `BombingPower`
|
||||
extracted from `game/internal/model/game/group.go`; a pure
|
||||
`ProduceShipsInTurn` extracted from `controller.ProduceShip` (the
|
||||
engine now delegates to both); inverse solvers in `pkg/calc/solve.go`
|
||||
(`WeaponsForAttack`, `DriveForSpeed`, `ShieldsForDefence` by
|
||||
bisection, `CargoForEmptyMass`, `LoadForFullMass`)
|
||||
- thin bridges in `ui/core/calc/` (combat, planet build, solvers),
|
||||
registered in `ui/wasm/main.go`, typed on `Core`
|
||||
(`platform/core/index.ts` + `wasm.ts`)
|
||||
- `ui/frontend/src/lib/calculator/calc-model.ts` pure orchestration
|
||||
(forward results + single-target goal-seek + planet build)
|
||||
- `ui/frontend/src/lib/calculator/ship-design-area.svelte` reusable
|
||||
design block (5 blocks + 4 techs, override locks, computed-block
|
||||
read-only) — earmarked for the future ship-group upgrade flow
|
||||
- `ui/frontend/src/lib/sidebar/calculator-tab.svelte` shell (mode
|
||||
selector, name combobox + Create / Delete, the calc and planet areas
|
||||
inline)
|
||||
- `ui/frontend/src/map/reach-circles.ts` + `lib/calculator/reach.svelte.ts`
|
||||
shared store: the calculator publishes the selected planet origin and
|
||||
loaded speed, the map draws 1–3 reach circles
|
||||
- `lib/calculator/load-request.svelte.ts` shared store: the table /
|
||||
menus ask the layout to open the calculator on a class
|
||||
- topic doc `ui/docs/calculator-ux.md`; `ui/docs/calc-bridge.md`
|
||||
extended with the new wired functions
|
||||
|
||||
Dependencies: Phase 18.
|
||||
Dependencies: Phases 17, 18, 19/20 (selection store), 29 (map modes).
|
||||
|
||||
Acceptance criteria:
|
||||
|
||||
- every calculator mode produces results identical to direct
|
||||
`pkg/calc/` calls;
|
||||
- inputs persist across view switches per global state-preservation
|
||||
rule;
|
||||
- calculator works in history mode against the snapshot's tech levels.
|
||||
- every result is byte-identical to direct `pkg/calc/` calls on shared
|
||||
fixtures (Go parity tests);
|
||||
- locking one result back-solves its claimed input; a second lock is
|
||||
disabled; an unreachable target shows the error state;
|
||||
- Create reuses the existing ship-class command flow and validator;
|
||||
selecting an existing class loads it as a template;
|
||||
- inputs persist across view switches per the global state-preservation
|
||||
rule; the calculator works in history mode against the snapshot's
|
||||
tech levels;
|
||||
- selecting an own planet draws the reach circles; clearing the
|
||||
selection or an invalid design removes them;
|
||||
- the standalone designer view/route no longer exists.
|
||||
|
||||
Targeted tests:
|
||||
|
||||
- Vitest snapshot tests per mode on canonical inputs;
|
||||
- Playwright e2e: switch modes, confirm input persistence.
|
||||
- Go: `pkg/calc` unit tests + engine parity (`ProduceShip`,
|
||||
`BombingPower`); `ui/core/calc` bridge parity; solver round-trips;
|
||||
- Vitest: `calc-model` (forward, goal-seek per claim, infeasible),
|
||||
`calculator-tab` (results, goal-seek, Create, planet area),
|
||||
`reach-circles` math;
|
||||
- Playwright e2e: create / list / delete via the table + calculator,
|
||||
Create-disabled-while-invalid (`tests/e2e/ship-classes.spec.ts`).
|
||||
|
||||
Note: the WASM artefact `ui/frontend/static/core.wasm` must be rebuilt
|
||||
(`make wasm`, needs TinyGo) for the new bridge functions to be present
|
||||
at runtime and in the Playwright suite; Vitest injects a fake `Core`
|
||||
and does not need the rebuild.
|
||||
|
||||
## Phase 31. Wails Desktop Wrapper
|
||||
|
||||
@@ -3483,54 +3543,56 @@ Targeted tests:
|
||||
- regression test: bumping the app version invalidates the prior
|
||||
service worker.
|
||||
|
||||
## Phase 34. Multi-Turn Projection — Single-Turn Forecast and Range Circles
|
||||
## Phase 34. Multi-Turn Projection — Realistic Planet Forecast
|
||||
|
||||
Status: pending. Long-term scope deferred but this phase ships real
|
||||
features.
|
||||
|
||||
Goal: ship two concrete projection features (planet next-turn
|
||||
forecast and ship-designer reach circles) plus the transient
|
||||
map-overlay back-stack mechanism that the reach-circles feature is
|
||||
the first user of.
|
||||
Goal: ship a realistic multi-turn planet projection and surface it in
|
||||
the planet inspector and in the calculator's planet area. Reach circles
|
||||
already shipped in Phase 30 (auto-drawn from the calculator's selected
|
||||
planet); this phase no longer owns them.
|
||||
|
||||
The Phase 30 planet area is single-turn (MAT-only): it answers "ships
|
||||
this turn / turns per ship" at the current or overridden MAT. This phase
|
||||
makes it realistic and multi-turn by extracting the planet economy into
|
||||
`pkg/calc` and simulating turns: population growth (`×1.08`), material /
|
||||
capital / colonist supply, and the capital/colonist unpacking that
|
||||
mirrors `MakeTurn` steps 09/12/14/15. CAP and COL only affect future
|
||||
turns (post-production unpacking), so they become meaningful here and
|
||||
are added to the calculator's planet area as supply inputs alongside
|
||||
MAT.
|
||||
|
||||
Artifacts:
|
||||
|
||||
- `ui/frontend/src/lib/projection/` minimal projection engine that
|
||||
computes one-turn-ahead state for a single planet using `pkg/calc/`
|
||||
- planet inspector forecast section showing next-turn population,
|
||||
industry, materials stockpile, and production progress
|
||||
- `ui/frontend/src/lib/navigation/transient-overlay.ts` push/pop
|
||||
back-stack mechanism for map overlays driven by other views, with
|
||||
a back-button affordance on the map that returns to the originating
|
||||
view with state preserved
|
||||
- ship-designer `Preview range on map` action that pushes a transient
|
||||
overlay onto the map showing concentric reach circles for 1, 2, 3,
|
||||
4 turns from a chosen origin, computed from the in-progress ship
|
||||
design and the player's current Drive tech via `ui/core/calc/`
|
||||
- topic doc `ui/docs/multi-turn-projection.md` describing the
|
||||
long-term vision (multi-turn planning mode, scenario branches) and
|
||||
the phased path to it
|
||||
- `pkg/calc/` planet-economy extraction (single-sourced, engine
|
||||
delegates): `PlanetProduction`, `ProducePopulation`,
|
||||
`UnpackColonists`, `UnpackCapital`, reusing `ProduceShipsInTurn`; a
|
||||
multi-turn projector `ProjectPlanetBuild` answering "K ships in M
|
||||
turns" under guaranteed per-turn supply
|
||||
- thin bridges in `ui/core/calc/` + `Core` typings
|
||||
- planet inspector forecast section (next-turn population, industry,
|
||||
materials, production progress)
|
||||
- calculator planet area gains CAP and COL supply inputs and switches
|
||||
its readout to the multi-turn projector
|
||||
- topic doc `ui/docs/multi-turn-projection.md` (long-term vision:
|
||||
multi-turn planning mode, scenario branches)
|
||||
|
||||
Dependencies: Phases 17, 18.
|
||||
Dependencies: Phases 17, 18, 30.
|
||||
|
||||
Acceptance criteria:
|
||||
|
||||
- the planet inspector shows a forecast section with next-turn values
|
||||
matching `pkg/calc/` outputs;
|
||||
- the ship-designer `Preview range on map` button transitions to the
|
||||
map with reach circles drawn from the chosen origin; back returns
|
||||
to the designer with all in-progress state intact;
|
||||
- the transient overlay is cleared if the user navigates to any other
|
||||
view via the header dropdown.
|
||||
- projector output is byte-identical to running the engine's per-turn
|
||||
planet update over the same turns (Go parity);
|
||||
- the planet inspector shows a forecast section matching it;
|
||||
- the calculator planet area honours MAT / CAP / COL supply and shows
|
||||
"K ships in M turns" consistent with the projector.
|
||||
|
||||
Targeted tests:
|
||||
|
||||
- Vitest unit tests for the projection engine on canonical fixtures;
|
||||
- Vitest unit tests for the transient-overlay push/pop logic and
|
||||
state preservation;
|
||||
- Playwright e2e: open a planet inspector, observe one-turn forecast;
|
||||
open a ship designer, click `Preview range on map`, see reach
|
||||
circles, click back, return with state intact.
|
||||
- Go parity tests for each extracted economy formula and the projector;
|
||||
- Vitest for the calculator planet area with supply inputs;
|
||||
- Playwright e2e: planet inspector forecast section.
|
||||
|
||||
## Phase 35. Polish — Accessibility, Localisation, Error UX
|
||||
|
||||
|
||||
Reference in New Issue
Block a user