ui/phase-21: sciences CRUD list, designer, and production-picker integration
Lights up the player-defined sciences feature: a table view with sort and filter, a designer with four percent inputs and a strict sum-equals-100 gate, and a Research-sub-row integration so the planet production picker lists the user's sciences alongside the four tech buttons. Phase 21 decisions are baked back into ui/PLAN.md (no UpdateScience on the wire — write-once via createScience + removeScience; percentages instead of fractions; sciences live under the existing Research segment). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -11,8 +11,9 @@
|
||||
// against realistic values. Phase 15 adds a minimal `LocalShipClass`
|
||||
// projection so the planet inspector's Build-Ship sub-picker has data
|
||||
// in e2e specs (`name` only — Phase 17 widens this when ship-class
|
||||
// CRUD lands). Later phases extend the helper as fleets, sciences,
|
||||
// etc. land.
|
||||
// CRUD lands). Phase 21 adds a `LocalScience` projection so the
|
||||
// sciences table and the planet production picker's Research sub-row
|
||||
// have data in e2e specs.
|
||||
|
||||
import { Builder } from "flatbuffers";
|
||||
|
||||
@@ -23,6 +24,7 @@ import {
|
||||
Report,
|
||||
Route,
|
||||
RouteEntry,
|
||||
Science,
|
||||
ShipClass,
|
||||
UnidentifiedPlanet,
|
||||
UninhabitedPlanet,
|
||||
@@ -60,6 +62,14 @@ export interface ShipClassFixture {
|
||||
cargo?: number;
|
||||
}
|
||||
|
||||
export interface ScienceFixture {
|
||||
name: string;
|
||||
drive?: number;
|
||||
weapons?: number;
|
||||
shields?: number;
|
||||
cargo?: number;
|
||||
}
|
||||
|
||||
export interface PlayerFixture {
|
||||
name: string;
|
||||
drive?: number;
|
||||
@@ -84,6 +94,7 @@ export interface ReportFixture {
|
||||
uninhabitedPlanets?: PlanetFixture[];
|
||||
unidentifiedPlanets?: { number: number; x: number; y: number }[];
|
||||
localShipClass?: ShipClassFixture[];
|
||||
localScience?: ScienceFixture[];
|
||||
race?: string;
|
||||
players?: PlayerFixture[];
|
||||
routes?: RouteFixture[];
|
||||
@@ -178,6 +189,17 @@ export function buildReportPayload(fixture: ReportFixture): Uint8Array {
|
||||
return ShipClass.endShipClass(builder);
|
||||
});
|
||||
|
||||
const localScienceOffsets = (fixture.localScience ?? []).map((sci) => {
|
||||
const name = builder.createString(sci.name);
|
||||
Science.startScience(builder);
|
||||
Science.addName(builder, name);
|
||||
Science.addDrive(builder, sci.drive ?? 0);
|
||||
Science.addWeapons(builder, sci.weapons ?? 0);
|
||||
Science.addShields(builder, sci.shields ?? 0);
|
||||
Science.addCargo(builder, sci.cargo ?? 0);
|
||||
return Science.endScience(builder);
|
||||
});
|
||||
|
||||
const playerOffsets = (fixture.players ?? []).map((p) => {
|
||||
const name = builder.createString(p.name);
|
||||
Player.startPlayer(builder);
|
||||
@@ -221,6 +243,10 @@ export function buildReportPayload(fixture: ReportFixture): Uint8Array {
|
||||
localShipClassOffsets.length === 0
|
||||
? null
|
||||
: Report.createLocalShipClassVector(builder, localShipClassOffsets);
|
||||
const localScienceVec =
|
||||
localScienceOffsets.length === 0
|
||||
? null
|
||||
: Report.createLocalScienceVector(builder, localScienceOffsets);
|
||||
const playerVec =
|
||||
playerOffsets.length === 0
|
||||
? null
|
||||
@@ -251,6 +277,8 @@ export function buildReportPayload(fixture: ReportFixture): Uint8Array {
|
||||
if (unidentifiedVec !== null) Report.addUnidentifiedPlanet(builder, unidentifiedVec);
|
||||
if (localShipClassVec !== null)
|
||||
Report.addLocalShipClass(builder, localShipClassVec);
|
||||
if (localScienceVec !== null)
|
||||
Report.addLocalScience(builder, localScienceVec);
|
||||
if (routeVec !== null) Report.addRoute(builder, routeVec);
|
||||
const reportOff = Report.endReport(builder);
|
||||
builder.finish(reportOff);
|
||||
|
||||
Reference in New Issue
Block a user