ui/phase-18: ship-class calc bridge with live designer preview
Wires pkg/calc/ship.go into the WASM Core boundary as seven thin
wrappers (DriveEffective, EmptyMass, WeaponsBlockMass, FullMass,
Speed, CargoCapacity, CarryingMass). The ship-class designer reads
Core through a new CORE_CONTEXT_KEY populated by the in-game layout
and renders a five-row preview pane (mass, full-load mass, max
speed, range at full load, cargo capacity) that updates reactively
on every form edit and on the player's localPlayer{Drive,Weapons,
Shields,Cargo} tech levels — three of which are now decoded from
the report's Player block alongside the existing localPlayerDrive.
CarryingMass is the seventh wrapper added to the original six-function
list so that "full-load mass" composes through pkg/calc/ functions
without putting math in TypeScript.
This commit is contained in:
+71
-19
@@ -4,12 +4,58 @@ The Galaxy frontend renders predictive numbers (free production
|
||||
potential, forecast output for a chosen production type, ship build
|
||||
progress, tech progress) that depend on the same formulas the engine
|
||||
uses at turn cutoff. To keep one source of truth, those formulas live
|
||||
in Go under `pkg/calc/` and are surfaced to the UI through a planned
|
||||
in Go under `pkg/calc/` and are surfaced to the UI through a
|
||||
Go → WASM → TypeScript bridge mounted under `ui/core/calc/` and a
|
||||
matching TS adapter in `ui/frontend/src/`.
|
||||
matching TS adapter in `ui/frontend/src/platform/core/`.
|
||||
|
||||
The bridge does not exist yet. This document is the audit trail for
|
||||
what it must expose, what is already in place, and what is missing.
|
||||
Phase 18 lands the **ship-math slice** of the bridge — everything
|
||||
the ship-class designer needs to render its preview pane. Other
|
||||
slices (production forecast, science research, ship build progress)
|
||||
remain deferred to dedicated future phases. This document is the
|
||||
running audit trail of what is live, what is missing, and how each
|
||||
function maps to its `pkg/calc/` source.
|
||||
|
||||
## Live bridge surface (Phase 18)
|
||||
|
||||
The Go module `galaxy/core/calc` (`ui/core/calc/ship.go`) exposes
|
||||
seven thin wrappers around `pkg/calc/ship.go`. Each is a one-line
|
||||
passthrough — the bridge contains zero math. The same seven names
|
||||
appear on the JS-side `globalThis.galaxyCore` (registered in
|
||||
`ui/wasm/main.go`) and on the typed `Core` interface
|
||||
(`ui/frontend/src/platform/core/index.ts`).
|
||||
|
||||
| Bridge function | `pkg/calc/` source | JS return shape | Used by |
|
||||
| ------------------ | --------------------------------------------------- | --------------- | -------------------------------- |
|
||||
| `driveEffective` | `calc.DriveEffective(drive, driveTech)` | `number` | designer preview (`Speed` input) |
|
||||
| `emptyMass` | `calc.EmptyMass(drive, weapons, armament, …)` | `number\|null` | designer preview (mass row) |
|
||||
| `weaponsBlockMass` | `calc.WeaponsBlockMass(weapons, armament)` | `number\|null` | reserved for future stages |
|
||||
| `fullMass` | `calc.FullMass(emptyMass, carryingMass)` | `number` | designer preview (full-load row) |
|
||||
| `speed` | `calc.Speed(driveEffective, fullMass)` | `number` | designer preview (speed + range) |
|
||||
| `cargoCapacity` | `calc.CargoCapacity(cargo, cargoTech)` | `number` | designer preview (cargo row) |
|
||||
| `carryingMass` | `calc.CarryingMass(load, cargoTech)` | `number` | designer preview (full-load mass)|
|
||||
|
||||
`number|null` returns mirror the Go `(float64, bool)` signature: the
|
||||
upstream validator rejects weapons/armament pairings with one zero
|
||||
side and the other non-zero, so the bridge returns `null` instead of
|
||||
silently zeroing. The ship-class form gates the preview behind its
|
||||
own `validateShipClass` so a user-visible `null` is the safety net,
|
||||
not the common path.
|
||||
|
||||
Composition (e.g., "full-load mass = `fullMass(emptyMass,
|
||||
carryingMass(cargoCapacity, cargoTech))`") happens in the TS preview
|
||||
component, not in the bridge — the Go side stays purely a marshalling
|
||||
adapter. Parity is exercised by `ui/core/calc/ship_test.go`, which
|
||||
calls each wrapper alongside the direct `pkg/calc/` function on the
|
||||
same inputs and asserts byte-equal outputs.
|
||||
|
||||
## Still-deferred slices
|
||||
|
||||
Phase 18's Go-side bridge is intentionally narrow: it covers ship
|
||||
math and nothing else. Production forecasts, science, ship-build
|
||||
progress, and reach (`FligthDistance`) still depend on either
|
||||
inline TS arithmetic or the engine-shipped fields on `GameReport`.
|
||||
See the table further down for what is missing and the per-feature
|
||||
waivers below for the rationale on each deferral.
|
||||
|
||||
## Current `pkg/calc/` exports
|
||||
|
||||
@@ -32,6 +78,7 @@ whether the underlying Go function exists.
|
||||
|
||||
| UI feature | Go formula | In `pkg/calc/`? | Surfaced to TS? |
|
||||
| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | :-------------: | :-------------: |
|
||||
| Ship-class designer preview (Phase 18) | `EmptyMass`, `FullMass`, `Speed`, `DriveEffective`, `CargoCapacity`, `CarryingMass`, `WeaponsBlockMass` (`pkg/calc/ship.go`) | yes | yes |
|
||||
| Free production potential (`freeIndustry`) | `Planet.ProductionCapacity` → `industry*0.75 + population*0.25` (`game/internal/model/game/planet.go`) | no | no |
|
||||
| Industry production output per turn | `Planet.ProduceIndustry(freeProduction)` (`planet.go`); `freeProduction/5` modulo material constraint | no | no |
|
||||
| Materials production output per turn | `Planet.ProduceMaterial(freeProduction)` (`planet.go`); `freeProduction * resources` | no | no |
|
||||
@@ -100,20 +147,25 @@ cargo-route auto-removal at turn cutoff. Until then, the UI
|
||||
duplicates `flightDistance` knowingly — same precedent as the
|
||||
production forecast deferral above.
|
||||
|
||||
## Planned bridge shape (follow-up phase)
|
||||
## Planned bridge growth (follow-up phases)
|
||||
|
||||
When the bridge phase lands, the contract should be:
|
||||
Phase 18 set up the canonical bridge layout (Go subpackage + WASM
|
||||
registration + typed `Core` interface + parity tests). Future calc
|
||||
work follows the same shape:
|
||||
|
||||
1. Promote every formula in the table above into `pkg/calc/` so the
|
||||
engine and the UI share one Go-side implementation. The engine
|
||||
continues to call them through `game/internal/...` wrappers.
|
||||
2. Mount a `ui/core/calc/` Go module that re-exports the subset the
|
||||
UI needs. Keep it WASM-friendly (no `unsafe`, no goroutines,
|
||||
simple in/out values).
|
||||
3. Wire the WASM glue in `ui/wasm/main.go` so each calc function is
|
||||
reachable from `globalThis.galaxyCore`.
|
||||
4. Add a TypeScript adapter under `ui/frontend/src/platform/core/`
|
||||
that wraps the WASM calls in typed helpers
|
||||
(`forecastIndustry(freeProduction, …)` etc.).
|
||||
5. Update this document with the live function inventory and
|
||||
delete the "missing" rows above.
|
||||
1. Promote any still-engine-only formula from the table above into
|
||||
`pkg/calc/` so the engine and the UI share one Go-side
|
||||
implementation. The engine continues to call them through its
|
||||
`game/internal/...` wrappers.
|
||||
2. Add a thin one-line wrapper in `ui/core/calc/` (new file per
|
||||
topic, e.g. `ui/core/calc/planet.go` for production forecasts).
|
||||
No math in the bridge.
|
||||
3. Register the function in `ui/wasm/main.go` under
|
||||
`globalThis.galaxyCore`.
|
||||
4. Extend the `Core` interface in
|
||||
`ui/frontend/src/platform/core/index.ts` with a typed signature
|
||||
and add the passthrough in `wasm.ts.adaptBridge`.
|
||||
5. Add a parity test in `ui/core/calc/<topic>_test.go` and a
|
||||
feature-level test under `ui/frontend/tests/`.
|
||||
6. Update this document — move the row from "missing" to the live
|
||||
surface table and link the test files.
|
||||
|
||||
Reference in New Issue
Block a user