915b4372dd
Adds the second end-to-end command (`setProductionType`) with a collapse-by-`planetNumber` rule on the order draft, the segmented production-controls component on the planet inspector, the FBS encoder/decoder pair for `CommandPlanetProduce`, and the `localShipClass` projection on `GameReport`. Forecast number is deferred and tracked in the new `ui/docs/calc-bridge.md`.
83 lines
5.5 KiB
Markdown
83 lines
5.5 KiB
Markdown
# Calc bridge
|
||
|
||
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
|
||
Go → WASM → TypeScript bridge mounted under `ui/core/calc/` and a
|
||
matching TS adapter in `ui/frontend/src/`.
|
||
|
||
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.
|
||
|
||
## Current `pkg/calc/` exports
|
||
|
||
| Function | Purpose |
|
||
| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------ |
|
||
| `ShipProductionCost(shipEmptyMass float64) float64` | Production units required per unit of ship empty mass (×10). |
|
||
| `PlanetProduceShipMass(L, Mat, Res float64) float64` | Ship mass produced per turn given free production `L`, material stockpile `Mat`, resources `Res`.|
|
||
| `DriveEffective`, `Speed`, `EmptyMass`, `FullMass`, … | Ship-level derivations (`pkg/calc/ship.go`). |
|
||
| `ValidateShipTypeValues`, `CheckShipTypeValueDWSC` | Ship-design validators (`pkg/calc/validator.go`). |
|
||
|
||
Nothing else lives in `pkg/calc/` today. Production-side formulas
|
||
(industry / materials / per-tech research / production capacity) sit
|
||
in `game/internal/model/game/planet.go` and `…/science.go` and have
|
||
never been exported.
|
||
|
||
## Required calc functions per UI feature
|
||
|
||
The table below tracks what UI features need from the bridge and
|
||
whether the underlying Go function exists.
|
||
|
||
| UI feature | Go formula | In `pkg/calc/`? | Surfaced to TS? |
|
||
| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | :-------------: | :-------------: |
|
||
| 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 |
|
||
| Per-tech research progress (DRIVE/WEAPONS/…) | `ResearchTech` (`game/internal/model/game/science.go`); `freeProduction / 5000` per tech level | no | no |
|
||
| Custom-science progress | weighted form of `ResearchTech` driven by `Race.Sciences[].(Drive\|Weapons\|Shields\|Cargo)` (`science.go`) | no | no |
|
||
| Ship build progress | `PlanetProduceShipMass(L, Mat, Res) / ShipProductionCost(class.EmptyMass)` (combination of two existing exports) | partial | no |
|
||
|
||
`partial` means the Go primitives exist in `pkg/calc/` but the
|
||
composition (and the conversion of TS-side `ReportPlanet`/
|
||
`ShipClass` to the formula inputs) is not implemented anywhere.
|
||
|
||
## Phase 15 waiver
|
||
|
||
Phase 15 ships the inspector's planet production controls
|
||
(segmented control + sub-pickers + collapse-by-`planetNumber`
|
||
order command) but **deliberately does not surface the per-type
|
||
forecast number**. The planning gate explicitly raised the gap as
|
||
a blocker per the plan's audit clause ("if any are missing in
|
||
`pkg/calc/`, raise as blocker") and the project owner approved
|
||
deferring the forecast to a dedicated future bridge phase. The
|
||
inspector still renders the existing `freeIndustry` row (free
|
||
production potential) — that number is computed engine-side and
|
||
ships in the report payload, so no calc-bridge access is required
|
||
for it today.
|
||
|
||
Acceptance criterion 3 of Phase 15 ("forecast output number
|
||
reflects the chosen production type and matches `pkg/calc/`
|
||
outputs") is therefore intentionally not satisfied; the rewritten
|
||
Phase 15 stage text records this decision and points back at this
|
||
document.
|
||
|
||
## Planned bridge shape (follow-up phase)
|
||
|
||
When the bridge phase lands, the contract should be:
|
||
|
||
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.
|