45 lines
1.7 KiB
JavaScript
45 lines
1.7 KiB
JavaScript
// Budget preview for the quarterly ledger: applies a draft budget to a copy of
|
|
// the game and runs the real daily tick forward, without noise, so the player
|
|
// sees where debt, deficit and the main indicators are heading.
|
|
// It assumes no new policies (future cards are unknown).
|
|
|
|
import { advanceDay, summarize } from "./game.js";
|
|
import { computeFiscal, setBudget } from "./economy.js";
|
|
|
|
const quietCache = new WeakMap();
|
|
|
|
// Same balance with all daily noise switched off.
|
|
function quietBalance(bal) {
|
|
let q = quietCache.get(bal);
|
|
if (!q) {
|
|
q = structuredClone(bal);
|
|
q.noise.indicator = 0;
|
|
for (const def of Object.values(q.vars)) def.noise = 0;
|
|
for (const def of Object.values(q.indicators)) if ("noise" in def) def.noise = 0;
|
|
quietCache.set(bal, q);
|
|
}
|
|
return q;
|
|
}
|
|
|
|
// Returns { ok, errors, fiscal, points }. points[0] is "now with the draft applied";
|
|
// points[i] is the state i quarters later (fewer if the term ends first).
|
|
export function previewBudget(state, bal, draft, { quarters = 4 } = {}) {
|
|
const sim = structuredClone(state);
|
|
sim.pending.review = true; // the preview may edit the budget even outside a review
|
|
const res = setBudget(sim, bal, draft);
|
|
if (!res.ok) return { ok: false, errors: res.errors, fiscal: null, points: [] };
|
|
|
|
const quiet = quietBalance(bal);
|
|
const fiscal = computeFiscal(sim, quiet);
|
|
const points = [summarize(sim, quiet)];
|
|
|
|
for (let q = 0; q < quarters && !sim.over; q++) {
|
|
for (let d = 0; d < bal.time.daysPerQuarter && !sim.over; d++) {
|
|
for (const k of Object.keys(sim.pending)) sim.pending[k] = false;
|
|
advanceDay(sim, quiet);
|
|
}
|
|
points.push(summarize(sim, quiet));
|
|
}
|
|
return { ok: true, errors: [], fiscal, points };
|
|
}
|