// Two-line planet labels drawn on the map under each planet (F8-12 / // issue #55, п.29). The first line shows the planet name when known // and the `planetNames` toggle is on; the second line shows `#N`. For // unidentified or unnamed planets only the `#N` line is rendered. // // Selection is wired through `selectedPlanetId`: the renderer wraps // the selected planet's label in an inverse-fill frame (F8-12 / п.30) // instead of drawing a separate ring around the planet disc — see the // "label-driven selection" branch in `render.ts`. import type { GameReport } from "../api/game-state"; export interface PlanetLabelData { planetNumber: number; x: number; y: number; /** * The primary line: planet name. `null` when the `planetNames` * toggle is off or the planet has no name (unidentified, or a * legacy report row with an empty string). When null the renderer * only paints the secondary `#N` line. */ name: string | null; /** Secondary line — always present. Pre-formatted as `#N`. */ numberLabel: string; } export interface BuildPlanetLabelsOptions { /** Mirrors `MapToggles.planetNames`. */ showNames: boolean; } /** * buildPlanetLabels translates the report's planet list into the * on-map label dataset. The toggle drives whether the name line is * present; for unidentified planets the name is suppressed even when * the toggle is on, because the player has no name to display. */ export function buildPlanetLabels( report: GameReport, opts: BuildPlanetLabelsOptions, ): PlanetLabelData[] { const out: PlanetLabelData[] = []; for (const p of report.planets) { const named = opts.showNames && p.kind !== "unidentified" && p.name.length > 0; out.push({ planetNumber: p.number, x: p.x, y: p.y, name: named ? p.name : null, numberLabel: `#${p.number}`, }); } return out; }