Functional Weave
Code in TypeScript

energy.carbon-emissions@1.0.1

impl/typescript.ts

1,461 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 { CONVERSION_FACTORS } from "./energy_carbon_emissions_data.ts";  ← this capability’s own data, compiled from data/conversion-factors.json into the same file by fune build
import { type CarbonEmissions } from "./energy_carbon_emissions_types.ts";

// quantity (thousandths of a unit) x factor (hundred-thousandths of a kg)
// / 100000 is grams.
const DIVISOR = 100_000;

/**
 * kgCO2e, as whole grams, for an amount of a fuel, from the UK government
 * conversion factor set for `year`.
 */
export function carbonEmissions(fuel: string, quantity: number, year: number): CarbonEmissions {
  if (!Number.isInteger(quantity) || quantity < 0) {
    throw new RangeError(`quantity must be a whole number of thousandths of a unit, 0 or more, received ${quantity}`);
  }
  if (!CONVERSION_FACTORS.some((f) => f.fuel === fuel)) {
    throw new RangeError(`unknown fuel "${fuel}"`);
  }
  const row = CONVERSION_FACTORS.find((f) => f.fuel === fuel && f.year === year);
  if (row === undefined) {
    throw new RangeError(`no conversion factor for ${fuel} in ${year}`);
  }
  // Split the quantity so the product never leaves the exact range.
  const whole = Math.floor(quantity / DIVISOR);
  const rest = quantity - whole * DIVISOR;
  const grams = whole * row.factor + roundDiv(rest * row.factor, DIVISOR, "half-up");
  if (grams > Number.MAX_SAFE_INTEGER) {
    throw new RangeError("emissions too large to calculate exactly");
  }
  return { fuel, unit: row.unit, year, scope: row.scope, factor: row.factor, grams };
}