orbit/js/galaxy/SystemReport.js

76 lines
2.6 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.
*
* const report = formatSystemReport(content);
* // { title, subtitle, settlements: [{ text, color, population }],
* // gates: [{ text, color }], summary, population }
*/
export function formatSystemReport(content, typeDefs = null, kindDefs = null) {
const types = typeDefs ?? config.get('systems.types', {});
const kinds = kindDefs ?? config.get('settlements.kinds', {});
const typeDef = types[content.type] ?? {};
const planetName = (ordinal) => {
const p = content.planets.find((pl) => pl.ordinal === ordinal);
return p ? p.name : `planet ${ordinal}`;
};
const settlements = [];
for (const s of content.settlements ?? []) {
const def = kinds[s.kind] ?? {};
const where =
s.anchor?.type === 'planet' ? `on ${planetName(s.anchor.ordinal)}` : 'in open space';
settlements.push({
text: `${s.name} · ${def.label ?? s.kind} ${where}`,
color: def.theme?.color ?? '#8fa0c9',
population: s.population ?? 0,
});
}
const population = settlements.reduce((sum, s) => sum + s.population, 0);
// The jump gates — the system's exits (content.jumps; each line names
// the star the gate jumps to, in the gate's cyan).
const gates = (content.jumps ?? []).map((j) => ({
text: `${j.name} · jump to ${j.toName}`,
color: config.get('gates.theme.color', '#5fd4ff'),
}));
const n = settlements.length;
const g = gates.length;
const summary =
n === 0
? g === 0
? 'charted · unclaimed'
: `unclaimed · ${g} jump gate${g === 1 ? '' : 's'}`
: `${n} settlement${n === 1 ? '' : 's'} · pop ~${formatPop(population)}` +
(g ? ` · ${g} jump gate${g === 1 ? '' : 's'}` : '');
const planetN = content.planets.length;
const asteroidN = Array.isArray(content.asteroids) ? content.asteroids.length : 0;
return {
title: content.name,
subtitle:
`${typeDef.label ?? content.type} system · star ${content.star.class} · ${planetN} planet${planetN === 1 ? '' : 's'}` +
(asteroidN ? ` · ${asteroidN} asteroid cluster${asteroidN === 1 ? '' : 's'}` : ''),
settlements,
gates,
summary,
population,
};
}
/** 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);
}