Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | 13x 2x 2x 1x 10x 4x 35x 35x 35x 150x 150x 150x 120x 120x 2x 4x 4x 3x 1x 13x | import type {
ChartAssumption,
ChartRenderingMetadata,
ParsedChartDataset,
} from "../model/types";
import { cashFlowChartConfig } from "./constants";
export function formatAssumptionLabel(key: string) {
const labels: Record<string, string> = {
discount_rate_percent: "Discount rate",
project_lifetime_years: "Project lifetime",
basis_date: "Basis date",
currency: "Currency",
annual_operating_hours: "Annual operating hours",
capital_index_series: "Capital index series",
operating_index_series: "Operating index series",
};
return labels[key] ?? key.replace(/[_.-]+/g, " ");
}
export function cashFlowXDomain(
rows: Array<{ year: number }>,
paybackYears: number | null,
): [number, number] {
const values = rows.map((row) => row.year);
Iif (paybackYears != null) values.push(paybackYears);
if (values.length === 0) return [0, 1];
return [
Math.floor(Math.min(...values, 0)),
Math.ceil(Math.max(...values, 1)),
];
}
export function cashFlowRenderingMetadata(metadata: ChartRenderingMetadata) {
return "payback_years" in metadata ? metadata : null;
}
export function cashFlowLegendLabel(value: string) {
return (
cashFlowChartConfig[value as keyof typeof cashFlowChartConfig]?.label ??
value
);
}
export function formatYearAxisTick(value: string | number) {
const parsed = Number(value);
Iif (!Number.isFinite(parsed)) return String(value);
return String(Math.round(parsed));
}
export function formatCompactAxisTick(value: string | number) {
const parsed = Number(value);
Iif (!Number.isFinite(parsed)) return String(value);
if (parsed === 0) return "0";
const formatted = new Intl.NumberFormat("en-NZ", {
maximumFractionDigits: 1,
notation: "compact",
}).format(Math.abs(parsed));
return parsed < 0 ? `(${formatted})` : formatted;
}
export function cashFlowAxisUnit(rows: Array<{ unit: string }>) {
return rows.find((row) => row.unit)?.unit || "currency";
}
export function rankedBreakdownAxisUnit(dataset: ParsedChartDataset) {
return (
dataset.series
.flatMap((series) => series.points)
.find((point) => point.unit)?.unit ||
dataset.series.find((series) => series.unit)?.unit ||
"amount"
);
}
export function mergeAssumptions(assumptions: ChartAssumption[]) {
return Array.from(
new Map(
assumptions.map((assumption) => [assumption.key, assumption]),
).values(),
);
}
export function tooltipUnit(item: {
dataKey?: string | number;
payload?: {
unit?: string;
sourceRows?: Record<string, { unit?: string }>;
};
}) {
const sourceRowUnit = item.payload?.sourceRows?.[String(item.dataKey)]?.unit;
return sourceRowUnit || item.payload?.unit || "";
}
|