/** * Picking a system for the effects demo (?fx=) — pure over the * seeded roster, so dev/system-effects.test.mjs can exercise the * ranking in bare Node. * * The demo wants to drop the player into a system of the requested * archetype that is GOOD for judging the effect: plenty of structure to * warp (worlds, a belt, a gate or two to jump out of). Candidates are * therefore ranked richest-first — more objects, then more jump gates — * with roster order as the stable tiebreak (seed-deterministic either * way: the roster is seed-ordered and the score is a pure function of * the record + its cached contents). */ /** * @param {object} galaxy a seeded galaxy (Galaxy.js) — reads `.records` * ({ id, type, ... }[]) and `.contentCache` (Map id -> contents, * possibly empty — content is lazy). * @param {string} type the requested archetype (systems.types key) * @returns {object | null} the chosen record (has `.id`), or null when * the roster holds no system of that type. */ export function pickFxSystem(galaxy, type) { const records = Array.isArray(galaxy?.records) ? galaxy.records : []; const cache = galaxy?.contentCache instanceof Map ? galaxy.contentCache : null; let best = null; let bestKey = null; for (const rec of records) { if (!rec || rec.type !== type) continue; const content = cache?.get(rec.id) ?? null; const objects = (Array.isArray(content?.planets) ? content.planets.length : 0) + (Array.isArray(content?.settlements) ? content.settlements.length : 0) + (Array.isArray(content?.asteroids) ? content.asteroids.length : 0); const gates = Array.isArray(content?.jumps) ? content.jumps.length : 0; const key = objects * 1000 + gates; if (!best || key > bestKey) { best = rec; bestKey = key; } } return best; }