orbit/js/galaxy/SystemReport.js

63 lines
2.4 KiB
JavaScript

import { config } from '../config/Config.js';
/**
* Formats a generated system into a readable "dossier" for UI.
*
* Pure — no Phaser — so it's testable in Node and reusable anywhere a
* system needs describing (the HUD today; the star map, tooltips, saves,
* or a terminal UI later). Scenes stay thin: they render what this
* returns.
*
* The dossier is deliberately compact — the per-settlement and gate
* detail lives elsewhere (star chart, map, the content itself). What it
* carries: identity (type + star class), who controls the system, and
* how many are settled here.
*
* const report = formatSystemReport(content);
* // { title, subtitle, faction, population, status, statusColor }
* // title — the system name
* // subtitle — "Main Sequence system · star G"
* // status — "Faction: Apex · Pop ~1.2M" (or "… · Unclaimed")
* // The FACTION (data/factions.json — the roster's faction pass, on
* // content.faction): the controlling faction's label + color, or
* // Neutral (light gray) for the wild space + the neutral ring.
*/
export function formatSystemReport(content, typeDefs = null) {
const types = typeDefs ?? config.get('systems.types', {});
const typeDef = types[content.type] ?? {};
const population = (content.settlements ?? []).reduce(
(sum, s) => sum + (s.population ?? 0),
0,
);
// FACTION CONTROL (data/factions.json — the roster's faction pass):
// the system's faction (content.faction — null = neutral wild space)
// names the power + its color; a content without the field (old
// saves / hand-built content) reads Neutral, as before.
const FACTIONS = config.get('factions.factions', {});
const fid = content.faction ?? null;
const fdef = fid ? FACTIONS[fid] : null;
const faction = fdef?.label ?? 'Neutral';
const statusColor = fdef?.color ?? '#c4cad8';
return {
title: content.name,
subtitle: `${typeDef.label ?? content.type} system · star ${content.star.class}`,
faction,
population,
status:
population > 0
? `Faction: ${faction} · Pop ~${formatPop(population)}`
: `Faction: ${faction} · Unclaimed`,
statusColor,
};
}
/** 1234 → "1.2k", 9000000 → "9.0M" */
export function formatPop(n) {
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}k`;
return String(n);
}