Rebalanced the resource rules so nothing is priced primarily in money: steel, electricity and high-tech lead every construction bill, chip foundries are seeded everywhere instead of being hand-placed, and cities open with stores of steel and high-tech. City building rows now lead with the resource bill and keep the money as an aside, and the region's resources expand into the buildings that demand them. Pulled the graph and cost maths into a framework-free shared/economy_graph.js, quoted currency through one helper, and gave every data table the same striping and row highlight.
71 lines
2.5 KiB
JavaScript
71 lines
2.5 KiB
JavaScript
// The viewer's currency. Money is quoted in whatever nation the player runs, so
|
||
// every money string reads in the right unit. The symbol is set from the
|
||
// snapshot; until then a neutral mark stands in.
|
||
|
||
import { groupDigits } from "../../shared/text_format.js";
|
||
|
||
let symbol = "¤";
|
||
// Every nation's currency and the instant rate from ours, indexed by civ, so a
|
||
// foreign figure can be shown in its own money with our equivalent beside it.
|
||
let currencies = [];
|
||
let rates = [];
|
||
let viewer = -1;
|
||
|
||
export function setCurrency(currency) {
|
||
if (currency && currency.symbol) symbol = currency.symbol;
|
||
}
|
||
|
||
// The per-nation currency list and the snapshot's instant exchange rates, so
|
||
// any figure can be re-quoted in the nation it belongs to.
|
||
export function setCurrencyBook(list, exchangeRates, viewerCiv) {
|
||
currencies = Array.isArray(list) ? list : [];
|
||
rates = Array.isArray(exchangeRates) ? exchangeRates : [];
|
||
viewer = Number.isInteger(viewerCiv) ? viewerCiv : -1;
|
||
}
|
||
|
||
export function currencySymbol() {
|
||
return symbol;
|
||
}
|
||
|
||
// A money amount in the viewer's currency, with the digits grouped by
|
||
// non-breaking spaces. Every panel quotes currency through here, so the figures
|
||
// read the same everywhere.
|
||
export function formatMoney(value) {
|
||
return `${symbol}${groupDigits(Math.round(value))}`;
|
||
}
|
||
|
||
// A signed money amount, for budget lines that show a movement.
|
||
export function formatMoneySigned(value) {
|
||
return `${value < 0 ? "−" : "+"}${formatMoney(Math.abs(value))}`;
|
||
}
|
||
|
||
export function viewerCurrencyCiv() {
|
||
return viewer;
|
||
}
|
||
|
||
export function currencyFor(civ) {
|
||
return currencies[civ] || null;
|
||
}
|
||
|
||
// How many units of `civ`'s currency one unit of the viewer's buys, at the
|
||
// snapshot's instant rate. One for our own currency, or when it is unknown.
|
||
export function rateToNational(civ) {
|
||
if (civ === viewer) return 1;
|
||
const entry = rates[civ];
|
||
if (entry && Number.isFinite(entry.rate)) return entry.rate;
|
||
const mine = currencies[viewer];
|
||
const theirs = currencies[civ];
|
||
if (mine && theirs && theirs.value > 0) return (mine.value || 1) / theirs.value;
|
||
return 1;
|
||
}
|
||
|
||
// A money amount belonging to `civ` as plain text: their money first, then ours
|
||
// in parentheses when they differ. `format` renders a bare number, so callers
|
||
// keep their own rounding and compacting.
|
||
export function moneyText(value, civ, format = (v) => groupDigits(Math.round(v))) {
|
||
const ours = `${currencySymbol()}${format(value)}`;
|
||
const info = currencyFor(civ);
|
||
if (!info || civ === viewer) return ours;
|
||
return `${info.symbol}${format(value * rateToNational(civ))} (${ours})`;
|
||
}
|