ui/phase-15: planet inspector production controls + order-draft collapse
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`.
This commit is contained in:
@@ -95,7 +95,7 @@ stored value).
|
||||
|
||||
`OrderCommand` is a discriminated union on the `kind` field. Phase
|
||||
12 shipped the skeleton with a single content-free variant; Phase
|
||||
14 adds the first real one:
|
||||
14 added the first real one and Phase 15 added the second:
|
||||
|
||||
```ts
|
||||
interface PlaceholderCommand {
|
||||
@@ -111,7 +111,20 @@ interface PlanetRenameCommand {
|
||||
readonly name: string;
|
||||
}
|
||||
|
||||
type OrderCommand = PlaceholderCommand | PlanetRenameCommand;
|
||||
interface SetProductionTypeCommand {
|
||||
readonly kind: "setProductionType";
|
||||
readonly id: string;
|
||||
readonly planetNumber: number;
|
||||
readonly productionType:
|
||||
| "MAT" | "CAP" | "DRIVE" | "WEAPONS"
|
||||
| "SHIELDS" | "CARGO" | "SCIENCE" | "SHIP";
|
||||
readonly subject: string;
|
||||
}
|
||||
|
||||
type OrderCommand =
|
||||
| PlaceholderCommand
|
||||
| PlanetRenameCommand
|
||||
| SetProductionTypeCommand;
|
||||
```
|
||||
|
||||
The `id` field is the canonical identifier the store uses for
|
||||
@@ -123,6 +136,35 @@ with the inline editor in `lib/inspectors/planet.svelte`, the
|
||||
local validator (`lib/util/entity-name.ts`, parity with
|
||||
`pkg/util/string.go.ValidateTypeName`), and the submit pipeline.
|
||||
|
||||
`setProductionType` is the wire-mirror of the engine's
|
||||
`CommandPlanetProduce` (`pkg/model/order/order.go`). The local
|
||||
validator runs the same `subject=Production` rule as
|
||||
`game/internal/router/validator.go`: `subject` is required and
|
||||
must satisfy `validateEntityName` when `productionType` is
|
||||
`SCIENCE` or `SHIP`; otherwise it is the empty string. The
|
||||
optimistic overlay rewrites `planet.production` using
|
||||
`productionDisplayFromCommand` (`api/game-state.ts`), which
|
||||
mirrors the engine's `Cache.PlanetProductionDisplayName` so the
|
||||
overlay stays byte-equal with the next server report.
|
||||
|
||||
### Collapse-by-target rule (Phase 15)
|
||||
|
||||
`setProductionType` is the first variant to carry a
|
||||
collapse-by-target rule. `OrderDraftStore.add` enforces it:
|
||||
when the incoming command's `kind` is `"setProductionType"` it
|
||||
drops every prior `setProductionType` entry with the same
|
||||
`planetNumber` (and the matching keys from `statuses`) before
|
||||
appending. Other variants keep their append-only behaviour —
|
||||
each `planetRename` is a distinct user-visible action and
|
||||
collapsing them would lose intent.
|
||||
|
||||
Net effect on the order tab: at most one `setProductionType`
|
||||
row per planet, regardless of how many times the player clicks
|
||||
through the inspector segments. Auto-sync still fires on every
|
||||
mutation; the engine accepts repeat submits idempotently. A
|
||||
`setProductionType` and a `planetRename` for the same planet
|
||||
coexist — the rules apply within a `kind`, not across.
|
||||
|
||||
## Store
|
||||
|
||||
`OrderDraftStore` lives in
|
||||
|
||||
Reference in New Issue
Block a user