# Worked examples

> Package `@umriss-ui/calculation`, version 0.40.0. Demo page: <https://romanhaendler.github.io/umriss-ui/calculation/worked-examples/>. Every page in one line: [llms.txt](https://romanhaendler.github.io/umriss-ui/calculation/llms.txt); every page in full: [llms-full.txt](https://romanhaendler.github.io/umriss-ui/calculation/llms-full.txt).

Whole figures as a screen shows them: the cost per stop of a day's tours, invoices with discount and VAT, and the equipment effectiveness of a hall, each built from data.

```ts
import { Calculation, Chain, Given, Ref } from "@umriss-ui/calculation";
```

Demo page: https://romanhaendler.github.io/umriss-ui/calculation/worked-examples/

## Examples

### The cost per stop of a day's tours

Eight tours from data, some sixty quantities: the sheet stands open, every tree in it folded, and the stale diesel price says so.

```tsx
import { Calculation, Chain, DividedBy, Given, Interim, Plus, Product, Sum } from "@umriss-ui/calculation";

/* Data from the logistics world, written out here so the example runs on its own. */

/** A small LCG - the same numbers on every computer. */
function random(seed: number): () => number {
  let s = seed >>> 0;
  return () => {
    s = (Math.imul(s, 1664525) + 1013904223) >>> 0;
    return s / 4294967296;
  };
}

const at = (hours: number, minutes = 0) => new Date(2026, 2, 17, hours, minutes).getTime();
const MINUTE = 60_000;

interface Vehicle {
  id: string;
  plate: string;
  type: "van" | "e-van" | "truck";
  /** Payload, in kg. */
  capacity: number;
  depot: string;
}

const VEHICLES: readonly Vehicle[] = [
  { id: "v1", plate: "FP 214 K", type: "van", capacity: 1200, depot: "north" },
  { id: "v2", plate: "FP 377 K", type: "e-van", capacity: 900, depot: "north" },
  { id: "v3", plate: "FP 118 R", type: "truck", capacity: 7500, depot: "north" },
  { id: "v4", plate: "FP 402 R", type: "van", capacity: 1200, depot: "river" },
  { id: "v5", plate: "FP 455 R", type: "e-van", capacity: 900, depot: "river" },
  { id: "v6", plate: "FP 290 E", type: "van", capacity: 1200, depot: "east" },
  { id: "v7", plate: "FP 311 E", type: "e-van", capacity: 900, depot: "east" },
  { id: "v8", plate: "FP 520 E", type: "truck", capacity: 7500, depot: "east" },
];

const DRIVERS = [
  { id: "d1", name: "Martin Hale", depot: "north" },
  { id: "d2", name: "Nadia Petrova", depot: "north" },
  { id: "d3", name: "Owen Carter", depot: "north" },
  { id: "d4", name: "Lucia Romero", depot: "river" },
  { id: "d5", name: "Ben Adeyemi", depot: "river" },
  { id: "d6", name: "Hanna Berg", depot: "east" },
  { id: "d7", name: "Yusuf Demir", depot: "east" },
  { id: "d8", name: "Clara Wendt", depot: "east" },
] as const;

const CUSTOMERS = [
  "Holloway Garden Supplies",
  "Marlow & Finch Books",
  "Oakridge Pharmacy",
  "Brixley Cycles",
  "Tamsin's Bakery",
  "Northfold Office",
  "Pellham Hardware",
  "Greywick Studio",
  "Juniper Lane Florist",
  "Ashcombe Dental",
] as const;

interface Stop {
  id: string;
  shipment: string;
  customer: string;
  /** The window the customer was promised, `[from, to]`. */
  window: readonly [number, number];
  /** When the tour plans to be there. */
  arrival: number;
}

interface Tour {
  id: string;
  vehicle: string;
  driver: string;
  depot: string;
  /** Leaves the depot, loaded; back at the depot. */
  from: number;
  to: number;
  /** Minutes of loading before `from`. */
  loading: number;
  km: number;
  stops: readonly Stop[];
}

/** One tour per vehicle. Stops every half hour or so, each with a two-hour
    window; every seventh arrival misses its window - the late ones a
    dispatcher looks for. */
function tour(index: number): Tour {
  const r = random(700 + index);
  const vehicle = VEHICLES[index]!;
  const truck = vehicle.type === "truck";
  const from = at(truck ? 6 : 7, index % 2 === 0 ? 0 : 30);
  const count = truck ? 5 : 8 + Math.floor(r() * 4);
  const stops: Stop[] = [];
  let arrival = from + (20 + Math.floor(r() * 15)) * MINUTE;
  for (let i = 0; i < count; i++) {
    const n = index * 20 + i;
    const slot = Math.floor((arrival - at(0)) / (2 * 60 * MINUTE)) * 2;
    /* A late stop's window closed half an hour or more before the arrival. */
    const late = i >= 2 && n % 7 === 3;
    const halfHour = 30 * MINUTE;
    const windowFrom = late ? Math.floor(arrival / halfHour) * halfHour - 5 * halfHour : at(slot);
    stops.push({
      id: `s-${index + 1}-${i + 1}`,
      shipment: `FP-${(1_004_210 + n * 13).toString()}`,
      customer: CUSTOMERS[(n * 3) % CUSTOMERS.length]!,
      window: [windowFrom, windowFrom + 2 * 60 * MINUTE],
      arrival,
    });
    arrival += (truck ? 45 : 22) * MINUTE + Math.floor(r() * 18) * MINUTE;
  }
  return {
    id: `T-${String(index + 1).padStart(2, "0")}`,
    vehicle: vehicle.id,
    driver: DRIVERS[index]!.id,
    depot: vehicle.depot,
    from,
    to: arrival + 30 * MINUTE,
    loading: truck ? 45 : 30,
    km: Math.round((truck ? 140 : 70) + r() * 40),
    stops,
  };
}

const TOURS: readonly Tour[] = VEHICLES.map((_, index) => tour(index));

/** What a tour costs, per unit - the inputs of a cost per tour. */
const COST_RATES = {
  /** Diesel, per litre; electricity, per kWh. */
  dieselPerLitre: 1.68,
  electricityPerKwh: 0.31,
  /** Consumption per 100 km. */
  per100Km: { van: 9.5, truck: 24, "e-van": 22 },
  /** A driver's hour, all in. */
  driverPerHour: 34.5,
  /** Lease, insurance and upkeep, per day. */
  vehiclePerDay: { van: 58, truck: 145, "e-van": 72 },
} as const;

const typeOf = (vehicleId: string) => VEHICLES.find((vehicle) => vehicle.id === vehicleId)!.type;
const hours = (tour: (typeof TOURS)[number]) => (tour.to - tour.from) / 3_600_000 + tour.loading / 60;
const DIESEL = TOURS.filter((tour) => typeOf(tour.vehicle) !== "e-van");
const ELECTRIC = TOURS.filter((tour) => typeOf(tour.vehicle) === "e-van");
const STOPS = TOURS.reduce((sum, tour) => sum + tour.stops.length, 0);

const AGES = { stale: 24 * 3_600_000, lost: 14 * 24 * 3_600_000 };
/* The price was read on Saturday at 06:00, seen from Tuesday 10:30; its
   freshness counts from page load, the tours keep their Tuesday. */
const LOADED = Date.now();
const DIESEL_READ = LOADED - (at(10, 30) - new Date(2026, 2, 14, 6, 0).getTime());

export default function CostPerTour() {
  return (
    <Calculation aria-label="Cost per stop, all tours, Tuesday">
      <Chain>
        <Product label="Drivers" unit="€" decimals={2}>
          <Sum label="Driver hours" unit="h" decimals={1}>
            {TOURS.map((tour) => (
              <Given key={tour.id} label={`Hours, ${tour.id}`} value={hours(tour)} unit="h" decimals={1} />
            ))}
          </Sum>
          <Given label="Driver rate, all in" value={COST_RATES.driverPerHour} unit="€/h" decimals={2} />
        </Product>
        <Plus>
          <Product label="Diesel" unit="€" decimals={2}>
            <Sum label="Diesel used" unit="l" decimals={1}>
              {DIESEL.map((tour) => (
                <Product key={tour.id} label={`Diesel, ${tour.id}`} unit="l" decimals={1}>
                  <Given label={`Distance, ${tour.id}`} value={tour.km} unit="km" />
                  <Given label={`Consumption, ${tour.id}`} value={COST_RATES.per100Km[typeOf(tour.vehicle)] / 100} unit="l/km" />
                </Product>
              ))}
            </Sum>
            <Given
              label="Diesel price"
              value={COST_RATES.dieselPerLitre}
              unit="€/l"
              decimals={2}
              source="Fuel card, weekly price"
              asOf={DIESEL_READ}
              ages={AGES}
            />
          </Product>
        </Plus>
        <Plus>
          <Product label="Electricity" unit="€" decimals={2}>
            <Sum label="Electricity used" unit="kWh" decimals={1}>
              {ELECTRIC.map((tour) => (
                <Product key={tour.id} label={`Electricity, ${tour.id}`} unit="kWh" decimals={1}>
                  <Given label={`Distance, ${tour.id}`} value={tour.km} unit="km" />
                  <Given label={`Consumption, ${tour.id}`} value={COST_RATES.per100Km["e-van"] / 100} unit="kWh/km" />
                </Product>
              ))}
            </Sum>
            <Given label="Electricity price" value={COST_RATES.electricityPerKwh} unit="€/kWh" decimals={2} source="Depot tariff 2026" />
          </Product>
        </Plus>
        <Plus>
          <Sum label="Vehicle days" unit="€" decimals={2}>
            {TOURS.map((tour) => (
              <Given key={tour.id} label={`Vehicle day, ${tour.id}`} value={COST_RATES.vehiclePerDay[typeOf(tour.vehicle)]} unit="€" decimals={2} />
            ))}
          </Sum>
        </Plus>
        <Interim label="Cost of the day's tours" unit="€" decimals={2} />
        <DividedBy label="Stops" value={STOPS} unit="stops" />
        <Interim
          label="Cost per stop"
          unit="€/stop"
          decimals={2}
          limits={[{ value: 30, side: "upper", severity: "warning" }]}
        />
      </Chain>
    </Calculation>
  );
}
```

### Invoices with discount and VAT

Each invoice is a chain from its lines, discounts and VAT by rate; as operands of one sum they fold to their totals.

```tsx
import type { ReactElement } from "react";
import { Calculation, Chain, Difference, Given, Interim, Plus, Product, Ref, Sum } from "@umriss-ui/calculation";

/* Data from the controlling world, written out here so the example runs on its own. */

const on = (month: number, day: number) => new Date(2026, month - 1, day).getTime();

interface InvoiceLine {
  description: string;
  quantity: number;
  unitPrice: number;
  /** A fraction: 0.1 is ten per cent off. */
  discount: number;
  /** A fraction: 0.19 or 0.07, or 0 where no VAT is charged. */
  vatRate: number;
}

interface Invoice {
  id: string;
  supplier: string;
  costCentre: string;
  received: number;
  due: number;
  status: "awaiting approval" | "approved" | "paid" | "rejected";
  lines: readonly InvoiceLine[];
}

const INVOICES: readonly Invoice[] = [
  {
    id: "INV-26-0318", supplier: "Brandlow Office Supply", costCentre: "CC-4400", received: on(3, 16), due: on(4, 15), status: "awaiting approval",
    lines: [
      { description: "Desk lamps, LED", quantity: 24, unitPrice: 48.9, discount: 0.1, vatRate: 0.19 },
      { description: "Printer paper, box of 5 reams", quantity: 40, unitPrice: 21.5, discount: 0, vatRate: 0.19 },
      { description: "Delivery", quantity: 1, unitPrice: 35, discount: 0, vatRate: 0.19 },
    ],
  },
  {
    id: "INV-26-0317", supplier: "Kettering & Shaw Events", costCentre: "CC-1200", received: on(3, 13), due: on(4, 12), status: "awaiting approval",
    lines: [
      { description: "Trade fair stand, 3 days", quantity: 1, unitPrice: 12_400, discount: 0.05, vatRate: 0.19 },
      { description: "Catering, per guest", quantity: 180, unitPrice: 18.5, discount: 0, vatRate: 0.07 },
    ],
  },
  {
    id: "INV-26-0309", supplier: "Nimbrel Software", costCentre: "CC-4300", received: on(3, 9), due: on(4, 8), status: "approved",
    lines: [
      { description: "Design tool licences, annual", quantity: 12, unitPrice: 540, discount: 0.15, vatRate: 0.19 },
      { description: "Onboarding session", quantity: 2, unitPrice: 890, discount: 0, vatRate: 0.19 },
    ],
  },
  {
    id: "INV-26-0302", supplier: "Fenwright Legal", costCentre: "CC-4100", received: on(3, 2), due: on(3, 16), status: "paid",
    lines: [{ description: "Contract review, hours", quantity: 14.5, unitPrice: 260, discount: 0, vatRate: 0.19 }],
  },
  {
    id: "INV-26-0226", supplier: "Corrin Travel", costCentre: "CC-1100", received: on(2, 26), due: on(3, 12), status: "paid",
    lines: [
      { description: "Rail tickets, sales conference", quantity: 22, unitPrice: 139, discount: 0, vatRate: 0.07 },
      { description: "Hotel, nights", quantity: 44, unitPrice: 112, discount: 0.08, vatRate: 0.07 },
    ],
  },
  {
    id: "INV-26-0221", supplier: "Stellbrook Consulting", costCentre: "CC-2100", received: on(2, 21), due: on(3, 23), status: "rejected",
    lines: [{ description: "Architecture review, days", quantity: 6, unitPrice: 1450, discount: 0, vatRate: 0 }],
  },
];

const OPEN = INVOICES.filter((invoice) => invoice.status === "awaiting approval" || invoice.status === "approved");
const percent = (rate: number) => `${Math.round(rate * 100)} %`;

/* A sum needs two operands; one stands for itself. */
const sumOf = (label: string, operands: ReactElement[]) =>
  operands.length === 1 ? operands[0] : (
    <Sum label={label} unit="€" decimals={2}>
      {operands}
    </Sum>
  );

function invoiceChain(invoice: Invoice) {
  const lineId = (index: number) => `${invoice.id}-line-${index}`;
  const rates = [...new Set(invoice.lines.map((line) => line.vatRate))];
  return (
    <Chain key={invoice.id}>
      {sumOf(
        `Net, ${invoice.id}`,
        invoice.lines.map((line, index) => {
          const amount = (
            <Product key={index} id={line.discount === 0 ? lineId(index) : `${lineId(index)}-list`} label={line.description} unit="€" decimals={2}>
              <Given label={`Quantity, ${line.description}`} value={line.quantity} />
              <Given label={`Unit price, ${line.description}`} value={line.unitPrice} unit="€" decimals={2} />
            </Product>
          );
          if (line.discount === 0) return amount;
          return (
            <Difference key={index} id={lineId(index)} label={`${line.description}, after discount`} unit="€" decimals={2}>
              {amount}
              <Product label={`Discount, ${line.description}`} unit="€" decimals={2}>
                <Given label={`Discount rate, ${line.description}`} value={line.discount} format="percent" />
                <Ref to={`${lineId(index)}-list`} />
              </Product>
            </Difference>
          );
        }),
      )}
      <Plus>
        {sumOf(
          `VAT, ${invoice.id}`,
          rates.map((rate) => {
            const lines = invoice.lines.flatMap((line, index) => (line.vatRate === rate ? [<Ref key={index} to={lineId(index)} />] : []));
            return (
              <Product key={rate} label={`VAT at ${percent(rate)}, ${invoice.id}`} unit="€" decimals={2}>
                <Given label={`VAT rate ${percent(rate)}`} value={rate} format="percent" />
                {sumOf(`Net at ${percent(rate)}, ${invoice.id}`, lines)}
              </Product>
            );
          }),
        )}
      </Plus>
      <Interim label={`${invoice.id}, ${invoice.supplier}`} unit="€" decimals={2} />
    </Chain>
  );
}

export default function Invoices() {
  return (
    <Calculation aria-label="Invoices to be paid, March">
      <Sum label="To be paid" unit="€" decimals={2}>
        {OPEN.map(invoiceChain)}
      </Sum>
    </Calculation>
  );
}
```

### OEE of a hall, weighted by planned time

Three lines from data, three levels deep; line C's downtime is `null`, so its OEE and the hall's are missing while A and B stand.

```tsx
import { Calculation, Difference, Given, Product, Quotient, Ref, Sum } from "@umriss-ui/calculation";

/* Data from the plant world, written out here so the example runs on its own. */

/** The early shift, 06:00 to 14:00. */
const SHIFT_MINUTES = 480;

interface Line {
  name: string;
  planned: number;
  downtime: number | null;
  idealCycle: number;
  total: number;
  good: number;
}

const BREAKS = 30;

const LINES: Line[] = [
  { name: "A", planned: SHIFT_MINUTES - BREAKS, downtime: 38, idealCycle: 0.8, total: 480, good: 461 },
  { name: "B", planned: SHIFT_MINUTES - BREAKS, downtime: 62, idealCycle: 1.2, total: 300, good: 291 },
  { name: "C", planned: SHIFT_MINUTES / 2, downtime: null, idealCycle: 0.5, total: 402, good: 395 },
];

function lineOee(line: Line) {
  const n = line.name;
  return (
    <Product key={n} label={`Weighted OEE, line ${n}`} unit="min">
      <Product label={`OEE, line ${n}`} format="percent">
        <Quotient label={`Availability, line ${n}`} format="percent">
          <Difference id={`runtime-${n}`} label={`Run time, line ${n}`} unit="min">
            <Given id={`planned-${n}`} label={`Planned time, line ${n}`} value={line.planned} unit="min" />
            <Given label={`Downtime, line ${n}`} value={line.downtime} unit="min" source="Shift log" />
          </Difference>
          <Ref to={`planned-${n}`} />
        </Quotient>
        <Quotient label={`Performance, line ${n}`} format="percent">
          <Product label={`Ideal run time, line ${n}`} unit="min">
            <Given label={`Ideal cycle time, line ${n}`} value={line.idealCycle} unit="min/pc" />
            <Given id={`total-${n}`} label={`Total count, line ${n}`} value={line.total} unit="pcs" />
          </Product>
          <Ref to={`runtime-${n}`} />
        </Quotient>
        <Quotient label={`Quality, line ${n}`} format="percent">
          <Given label={`Good count, line ${n}`} value={line.good} unit="pcs" />
          <Ref to={`total-${n}`} />
        </Quotient>
      </Product>
      <Ref to={`planned-${n}`} />
    </Product>
  );
}

export default function HallOee() {
  return (
    <Calculation aria-label="OEE of hall 2, early shift">
      <Quotient label="OEE, hall 2" format="percent" target={0.8}>
        <Sum label="Weighted OEE, all lines" unit="min">
          {LINES.map(lineOee)}
        </Sum>
        <Sum label="Planned time, all lines" unit="min">
          {LINES.map((line) => (
            <Ref key={line.name} to={`planned-${line.name}`} />
          ))}
        </Sum>
      </Quotient>
    </Calculation>
  );
}
```

## Keyboard

The keys of [Calculation](https://romanhaendler.github.io/umriss-ui/calculation/calculation/#keyboard-calculation) apply here.

## Props on this page

From `CalculationProps` — the full table stands on [Calculation](https://romanhaendler.github.io/umriss-ui/calculation/calculation/#type-CalculationProps).

| Prop | Type | Default | Description |
|---|---|---|---|
| [`children`](https://romanhaendler.github.io/umriss-ui/calculation/calculation/#CalculationProps-children) *required* | `ReactNode` | — | The result: exactly one quantity - a tree (`<Sum>`, `<Difference>`, `<Product>`, `<Quotient>` with their operands, `<Given>` as leaves) or a `<Chain>`, the two mixing freely; `<Ref>` for a quantity defined elsewhere. |

From `OperatorProps` — the full table stands on [Tree](https://romanhaendler.github.io/umriss-ui/calculation/tree/#type-OperatorProps).

| Prop | Type | Default | Description |
|---|---|---|---|
| [`children`](https://romanhaendler.github.io/umriss-ui/calculation/tree/#OperatorProps-children) | `ReactNode` | — | The operands, in order: quantities, givens and references. |
| [`label`](https://romanhaendler.github.io/umriss-ui/calculation/tree/#OperatorProps-label) *required* | `string` | — | What the quantity is called. It stands on its line, wherever it is an operand, and in the accessible sentence. From `QuantityProps`. |
| [`id`](https://romanhaendler.github.io/umriss-ui/calculation/tree/#OperatorProps-id) | `string` | — | Makes the quantity referable: `<Ref to>` stands for it elsewhere. Needed only for a quantity used more than once. From `QuantityProps`. |
| [`unit`](https://romanhaendler.github.io/umriss-ui/calculation/tree/#OperatorProps-unit) | `string` | — | A label written after the number - "min", "pcs", "€". Never converted and never checked; the calculation does no unit algebra. From `QuantityProps`. |
| [`format`](https://romanhaendler.github.io/umriss-ui/calculation/tree/#OperatorProps-format) | `"percent"` | — | `percent` presents a plain ratio as per cent: 0.916 is shown as 91.6 %. The quantity stays a ratio in every operation. From `QuantityProps`. |
| [`decimals`](https://romanhaendler.github.io/umriss-ui/calculation/tree/#OperatorProps-decimals) | `number` | one digit for a percentage, at most two for a derived number, a given as it was given | Fixed number of fraction digits as shown. Rounding happens only in presentation; every operation uses the full value. From `QuantityProps`. |
| [`target`](https://romanhaendler.github.io/umriss-ui/calculation/tree/#OperatorProps-target) | `number` | — | The value this quantity is meant to reach - missed, never violated. From `QuantityProps`. |
| [`limits`](https://romanhaendler.github.io/umriss-ui/calculation/tree/#OperatorProps-limits) | `readonly `[`Limit`](https://romanhaendler.github.io/umriss-ui/calculation/tree/#type-Limit)`[]` | — | Bounds the quantity is assessed against, through core's `assess()`. From `QuantityProps`. |

From `RefProps` — the full table stands on [Tree](https://romanhaendler.github.io/umriss-ui/calculation/tree/#type-RefProps).

| Prop | Type | Default | Description |
|---|---|---|---|
| [`to`](https://romanhaendler.github.io/umriss-ui/calculation/tree/#RefProps-to) *required* | `string` | — | The `id` of the quantity this reference stands for. |

From `ChainProps` — the full table stands on [Chain](https://romanhaendler.github.io/umriss-ui/calculation/chain/#type-ChainProps).

| Prop | Type | Default | Description |
|---|---|---|---|
| [`children`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#ChainProps-children) | `ReactNode` | — | The operands, top to bottom: a first quantity with no operator, then `Plus`, `Minus`, `Times` and `DividedBy` with their operands and `Interim`s naming the value where they stand. The last line is an `Interim`; a `Times` or `DividedBy` stands alone between two named values. |

From `ChainOperandProps` — the full table stands on [Chain](https://romanhaendler.github.io/umriss-ui/calculation/chain/#type-ChainOperandProps).

| Prop | Type | Default | Description |
|---|---|---|---|
| [`label`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#ChainOperandProps-label) | `string` | — | The operand's name, where the line is a given written in place. Left out where the line holds a quantity as its child. |
| [`value`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#ChainOperandProps-value) | `number \| null \| `[`MetricValues`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#type-MetricValues) | — | The operand's number, where the line is a given written in place. Absent as for a `Given`: the line and every interim after it are absent, with the reason. With `metrics`, an object by metric id, as on a `Given`. |
| [`children`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#ChainOperandProps-children) | `ReactNode` | — | Instead of `label` and `value`: exactly one quantity - a tree, a `<Ref>` or a `<Chain>`. |
| [`source`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#ChainOperandProps-source) | `string` | — | Where the number came from: a system, a report, a person. From `GivenProps`. |
| [`asOf`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#ChainOperandProps-asOf) | `Date \| number` | — | When the number was true - not when it was fetched. From `GivenProps`. |
| [`ages`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#ChainOperandProps-ages) | [`FreshnessAges`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#type-FreshnessAges) | — | The ages at which `asOf` turns stale and lost. With both, the given carries a freshness through core; with `asOf` alone, only the time. From `GivenProps`. |
| [`id`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#ChainOperandProps-id) | `string` | — | Makes the quantity referable: `<Ref to>` stands for it elsewhere. Needed only for a quantity used more than once. From `QuantityProps`. |
| [`unit`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#ChainOperandProps-unit) | `string` | — | A label written after the number - "min", "pcs", "€". Never converted and never checked; the calculation does no unit algebra. From `QuantityProps`. |
| [`format`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#ChainOperandProps-format) | `"percent"` | — | `percent` presents a plain ratio as per cent: 0.916 is shown as 91.6 %. The quantity stays a ratio in every operation. From `QuantityProps`. |
| [`decimals`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#ChainOperandProps-decimals) | `number` | one digit for a percentage, at most two for a derived number, a given as it was given | Fixed number of fraction digits as shown. Rounding happens only in presentation; every operation uses the full value. From `QuantityProps`. |
| [`target`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#ChainOperandProps-target) | `number` | — | The value this quantity is meant to reach - missed, never violated. From `QuantityProps`. |
| [`limits`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#ChainOperandProps-limits) | `readonly `[`Limit`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#type-Limit)`[]` | — | Bounds the quantity is assessed against, through core's `assess()`. From `QuantityProps`. |

From `QuantityProps` — the full table stands on [Chain](https://romanhaendler.github.io/umriss-ui/calculation/chain/#type-QuantityProps).

| Prop | Type | Default | Description |
|---|---|---|---|
| [`label`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#QuantityProps-label) *required* | `string` | — | What the quantity is called. It stands on its line, wherever it is an operand, and in the accessible sentence. |
| [`id`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#QuantityProps-id) | `string` | — | Makes the quantity referable: `<Ref to>` stands for it elsewhere. Needed only for a quantity used more than once. |
| [`unit`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#QuantityProps-unit) | `string` | — | A label written after the number - "min", "pcs", "€". Never converted and never checked; the calculation does no unit algebra. |
| [`format`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#QuantityProps-format) | `"percent"` | — | `percent` presents a plain ratio as per cent: 0.916 is shown as 91.6 %. The quantity stays a ratio in every operation. |
| [`decimals`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#QuantityProps-decimals) | `number` | one digit for a percentage, at most two for a derived number, a given as it was given | Fixed number of fraction digits as shown. Rounding happens only in presentation; every operation uses the full value. |
| [`target`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#QuantityProps-target) | `number` | — | The value this quantity is meant to reach - missed, never violated. |
| [`limits`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#QuantityProps-limits) | `readonly `[`Limit`](https://romanhaendler.github.io/umriss-ui/calculation/chain/#type-Limit)`[]` | — | Bounds the quantity is assessed against, through core's `assess()`. |

From `GivenProps` — the full table stands on [Given](https://romanhaendler.github.io/umriss-ui/calculation/given/#type-GivenProps).

| Prop | Type | Default | Description |
|---|---|---|---|
| [`value`](https://romanhaendler.github.io/umriss-ui/calculation/given/#GivenProps-value) *required* | `number \| null \| undefined \| `[`MetricValues`](https://romanhaendler.github.io/umriss-ui/calculation/given/#type-MetricValues) | — | The number the calculation starts from. Absent (`null`, `undefined`, not finite) makes every quantity that depends on it absent, with the reason - never zero. Where the calculation has `metrics`, an object with a number for each metric id instead; absence then stays in its metric. |
| [`source`](https://romanhaendler.github.io/umriss-ui/calculation/given/#GivenProps-source) | `string` | — | Where the number came from: a system, a report, a person. |
| [`asOf`](https://romanhaendler.github.io/umriss-ui/calculation/given/#GivenProps-asOf) | `Date \| number` | — | When the number was true - not when it was fetched. |
| [`ages`](https://romanhaendler.github.io/umriss-ui/calculation/given/#GivenProps-ages) | [`FreshnessAges`](https://romanhaendler.github.io/umriss-ui/calculation/given/#type-FreshnessAges) | — | The ages at which `asOf` turns stale and lost. With both, the given carries a freshness through core; with `asOf` alone, only the time. |
| [`label`](https://romanhaendler.github.io/umriss-ui/calculation/given/#GivenProps-label) *required* | `string` | — | What the quantity is called. It stands on its line, wherever it is an operand, and in the accessible sentence. From `QuantityProps`. |
| [`id`](https://romanhaendler.github.io/umriss-ui/calculation/given/#GivenProps-id) | `string` | — | Makes the quantity referable: `<Ref to>` stands for it elsewhere. Needed only for a quantity used more than once. From `QuantityProps`. |
| [`unit`](https://romanhaendler.github.io/umriss-ui/calculation/given/#GivenProps-unit) | `string` | — | A label written after the number - "min", "pcs", "€". Never converted and never checked; the calculation does no unit algebra. From `QuantityProps`. |
| [`format`](https://romanhaendler.github.io/umriss-ui/calculation/given/#GivenProps-format) | `"percent"` | — | `percent` presents a plain ratio as per cent: 0.916 is shown as 91.6 %. The quantity stays a ratio in every operation. From `QuantityProps`. |
| [`decimals`](https://romanhaendler.github.io/umriss-ui/calculation/given/#GivenProps-decimals) | `number` | one digit for a percentage, at most two for a derived number, a given as it was given | Fixed number of fraction digits as shown. Rounding happens only in presentation; every operation uses the full value. From `QuantityProps`. |
| [`target`](https://romanhaendler.github.io/umriss-ui/calculation/given/#GivenProps-target) | `number` | — | The value this quantity is meant to reach - missed, never violated. From `QuantityProps`. |
| [`limits`](https://romanhaendler.github.io/umriss-ui/calculation/given/#GivenProps-limits) | `readonly `[`Limit`](https://romanhaendler.github.io/umriss-ui/calculation/given/#type-Limit)`[]` | — | Bounds the quantity is assessed against, through core's `assess()`. From `QuantityProps`. |
