46 lines
2.0 KiB
TypeScript
46 lines
2.0 KiB
TypeScript
// Pure display formatters for the client panes (v0.9.0) — no game logic, unit-testable in node.
|
|
|
|
const CURRENCY = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'EUR' });
|
|
|
|
export function formatCash(value: number): string {
|
|
return CURRENCY.format(value);
|
|
}
|
|
|
|
// "6300 / 6300 L" — current value rounded (live fuel is fractional mid-flight).
|
|
export function formatFuel(fuel: number, maxFuel: number): string {
|
|
return `${Math.round(fuel)} / ${maxFuel} L`;
|
|
}
|
|
|
|
// Job-list cargo label: "Mail 10.0t" — type + tonnage, one decimal like the loadout display.
|
|
export function formatCargo(cargoType: string, weightKg: number): string {
|
|
return `${cargoType} ${(weightKg / 1000).toFixed(1)}t`;
|
|
}
|
|
|
|
// The sim clock is epoch ms (seeded from real time) — shown as a UTC wall-clock with
|
|
// seconds so the display is deterministic regardless of the viewer's timezone.
|
|
export function formatSimClock(clockMs: number): string {
|
|
const d = new Date(clockMs);
|
|
const pad = (n: number) => String(n).padStart(2, '0');
|
|
return `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())} ${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())} UTC`;
|
|
}
|
|
|
|
// Compact game-time duration rounded to the minute: "2d 3h" / "14h 30m" / "45m".
|
|
export function formatDuration(ms: number): string {
|
|
const totalMin = Math.max(0, Math.round(ms / 60_000));
|
|
const d = Math.floor(totalMin / (24 * 60));
|
|
const h = Math.floor((totalMin % (24 * 60)) / 60);
|
|
const m = totalMin % 60;
|
|
if (d > 0) return `${d}d ${h}h`;
|
|
if (h > 0) return `${h}h ${m}m`;
|
|
return `${m}m`;
|
|
}
|
|
|
|
// Contract deadline relative to the sim clock: "in 14h 30m"; a passed deadline reads
|
|
// "overdue" and a sub-minute one "now". Pure — unit-testable, no game logic.
|
|
export function formatDeadlineRelative(deadlineMs: number, nowMs: number): string {
|
|
const diff = deadlineMs - nowMs;
|
|
if (diff <= 0) return 'overdue';
|
|
if (diff < 60_000) return 'now'; // sub-minute — "in 1m" starts at a full minute
|
|
return `in ${formatDuration(diff)}`;
|
|
}
|