// Shared number / planet formatters for the Phase 23 Report View // sections. Inlined in 10+ components, so factoring keeps each // section component focused on its data shape. The formatters // match the conventions of the per-entity tables (tabular numerals, // one-decimal percent without a `%` suffix — the header carries the // unit) so the report's grids read the same way as the // table-races / table-sciences views. import type { ReportPlanet } from "../../../api/game-state"; /** * formatPercent renders a `[0, 1]` fraction as a one-decimal * percent (without a `%` suffix — the column header carries the * unit). Matches the convention used by `table-races.svelte` and * `table-sciences.svelte`. */ export function formatPercent(fraction: number): string { return (fraction * 100).toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 1, }); } /** * formatCount renders an integer-ish value (population, industry, * planet count, …) without fractional digits and with locale-aware * thousand separators. */ export function formatCount(value: number): string { return value.toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 0, }); } /** * formatFloat renders a floating-point value with up to two * fractional digits. Used for stockpiles, distances, cost, mass — * everything the engine emits as a `Float` that is not a fraction. */ export function formatFloat(value: number): string { return value.toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 2, }); } /** * formatVotes renders a vote weight with up to two decimal digits — * mirrors the races table's column convention so the cumulative * vote totals line up across views. */ export function formatVotes(value: number): string { return value.toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 2, }); } /** * planetLabel renders a planet reference as `# ()` if * the planet is known in the report, or just `#` if the * lookup fails (visibility lost between turns, foreign-only data). * Sections that show planet numbers without a name column — * Ships in Production, Bombings — rely on this resolver to keep * cell width tight. */ export function planetLabel( number: number, planets: readonly ReportPlanet[], ): string { const p = planets.find((row) => row.number === number); if (p === undefined || p.name === "") return `#${number}`; return `#${number} (${p.name})`; }