All files / src/pages/flowsheet-page/economics/capital economicsCapitalFactors.ts

83.87% Statements 26/31
65.51% Branches 19/29
100% Functions 2/2
92% Lines 23/25

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                        1x 1x 1x   4x 4x                               1x   1x   1x   1x                 8x 6x 2x       8x                 5x 5x 5x       6x 6x 6x           8x 6x       5x           20x    
import { formatAmount } from "../shared/model/economicsFormatters";
 
export type CapitalFactor = {
  kind: string;
  label: string;
  factor?: string | null;
  percent?: string | null;
  amount?: string | number | null;
  detail?: string;
};
 
export function capitalFactorsFromPayload(payload: unknown): CapitalFactor[] {
  const factors = objectValue(payload)?.capital_factors;
  Iif (!Array.isArray(factors)) return [];
  return factors
    .map(objectValue)
    .filter((factor): factor is Record<string, unknown> => factor != null)
    .map((factor) => ({
      kind: stringValue(factor.kind),
      label: stringValue(factor.label),
      factor: stringValue(factor.factor),
      percent: stringValue(factor.percent),
      amount:
        typeof factor.amount === "number" || typeof factor.amount === "string"
          ? factor.amount
          : null,
      detail: stringValue(factor.detail),
    }));
}
 
export function capitalFactorLabel(factor: CapitalFactor) {
  switch (factor.kind) {
    case "base_curve_cost":
      return "Curve base";
    case "index_adjustment":
      return "CPI/index";
    case "lang_factor":
      return "Lang factor";
    case "contingency":
      return "Contingency";
    case "electrical_upgrade":
      return "Electrical upgrade";
    default:
      return factor.label || "Factor";
  }
}
 
export function capitalFactorValue(factor: CapitalFactor) {
  if (factor.percent) return `${formatFactorValue(factor.percent)}%`;
  if (factor.factor) return `x${formatFactorValue(factor.factor)}`;
  return "";
}
 
export function capitalFactorMeta(factor: CapitalFactor) {
  return [capitalFactorValue(factor), humanReadableDetail(factor.detail)]
    .filter(Boolean)
    .join(" ยท ");
}
 
export function formatAmountWithUnit(
  amount: string | number | null | undefined,
  unit: string | null | undefined,
) {
  Iif (amount == null || amount === "") return "-";
  const formattedAmount = formatAmount(amount);
  return unit ? `${formattedAmount} ${unit}` : formattedAmount;
}
 
function formatFactorValue(value: string) {
  const parsed = Number(value);
  Iif (!Number.isFinite(parsed)) return value;
  return new Intl.NumberFormat("en-NZ", {
    maximumFractionDigits: 4,
  }).format(parsed);
}
 
function humanReadableDetail(value: string | undefined) {
  if (!value) return "";
  return value.replace(/_/g, " ");
}
 
function objectValue(value: unknown): Record<string, unknown> | null {
  return value && typeof value === "object" && !Array.isArray(value)
    ? (value as Record<string, unknown>)
    : null;
}
 
function stringValue(value: unknown) {
  return typeof value === "string" ? value : "";
}