Functional Weave
Code in TypeScript

fleet.cost-per-mile@1.0.0

impl/typescript.ts

1,579 bytes · the TypeScript implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

import { roundDiv } from "./math_round_div.ts";  ← from math.round-div ^1.0.0 · built alongside by fune
import { type Money } from "./money_amount.ts";  ← from money.amount ^1.0.0 · built alongside by fune
import { sumMoney } from "./money_sum.ts";  ← from money.sum ^1.0.0 · built alongside by fune
import { type CostPerMile, type WholeLifeCosts } from "./fleet_cost_per_mile_types.ts";

function tenths(amount: Money, miles: number): number {
  return roundDiv(amount.minor * 10, miles, "half-up");
}

function display(value: number): string {
  const sign = value < 0 ? "-" : "";
  const magnitude = Math.abs(value);
  return `${sign}${Math.floor(magnitude / 10)}.${magnitude % 10}`;
}

/**
 * Whole-life cost per mile, in tenths of a penny, the unit fleet reports use.
 *
 * Each part is rounded on its own for the breakdown, and the total is rounded
 * from the total cost: adding up the rounded parts drifts by a tenth or two,
 * which is why the total is not their sum.
 */
export function costPerMile(costs: WholeLifeCosts, miles: number): CostPerMile {
  if (!Number.isInteger(miles) || miles <= 0) {
    throw new RangeError(`miles must be a whole number above zero, received ${miles}`);
  }
  const totalCost = sumMoney(
    [costs.depreciation, costs.fuel, costs.maintenance, costs.insurance, costs.tax],
    costs.depreciation.currency
  );
  const totalTenths = tenths(totalCost, miles);
  return {
    totalCost,
    depreciationTenths: tenths(costs.depreciation, miles),
    fuelTenths: tenths(costs.fuel, miles),
    maintenanceTenths: tenths(costs.maintenance, miles),
    insuranceTenths: tenths(costs.insurance, miles),
    taxTenths: tenths(costs.tax, miles),
    totalTenths,
    perMile: display(totalTenths),
  };
}