The cost calculator: how it works, and how it's tuned
A guide, not a quote. Built once, calibrated per trade, runs in the browser.
1. In plain English
The calculator gives a customer a believable price range in under a minute, before they call. They answer a small set of multiple-choice questions ("what do you need?", "how big?", "where?", "access?", "anything alongside?") and see a low–high range with a tier label ("Tree removal", "Major renovation"). It is honest about being a guide, not a binding number.
The job of the calculator is to filter, not to quote — to send the right enquiries through and to spend three quiet seconds explaining cost factors to the wrong ones.
2. The model
One formula, two layers:
point = (base + Σ add) × Π mult
low = round(point × lowFactor) // e.g. 0.85
high = round(point × highFactor) // e.g. 1.15
tier = first tier whose min the midpoint clears Each answer the customer picks may add a flat dollar amount (add) and/or multiply the running total (mult). Tiers turn a number into a label. The spread (low/high factor) controls how confident the range is.
3. Two layers kept separate
pricingModel holds the numbers — base, add, mult, tiers, spread. estimatorConfig holds the words — the heading, the input labels, the option labels customers see. Numbers and words evolve on different timelines, so the data shape keeps them apart. A copy edit never touches a price.
4. The five dials you tune
- base — the cheapest scenario starting point (a small consult, an assessment).
- add tables — the per-axis dollar deltas as scope grows.
- mult tables — the per-axis multipliers (access difficulty, terrain).
- tiers — the labels that turn the midpoint into "Tree removal" / "Major renovation" / etc.
- lowFactor / highFactor — how wide the band reads (typically 0.85 / 1.15 — narrower means more confident).
5. The safety rail (gate #14)
Per site, a small estimatorCalibration block declares the orderings each axis must respect (size: small < avg < large) and, for per-metre trades, the expected $/m bands. The build refuses to ship if the math violates them — so a price axis can't accidentally invert mid-edit. The calibration check is run by importing the same computeRange that the browser runs.
6. The numbers below are real
Each demo's sample range is computed by the generator against that demo's own pricingModel, using the same estimate.ts the demo itself runs. Pick one to see what it produces:
Phase B: a live in-browser try-it lets you change inputs and see the range update, using the same estimate.ts engine the demo runs. The numbers above already use that engine — the Phase B add is the interactive form.
7. Bespoke calcs (the outlier)
Not every calculator fits the shared engine. The solar payback calc is its own model — STC discount, postcode-zone yield, self-consumption — and ships as an embeddable web component (<solar-calculator>). It's themed via --sc-* CSS variables, so any host site (hardy is the live example) can drop it in and brand it. The explainer treats bespoke calcs as a distinct class with their own embed + data sources.
- · Hardy Electrical & Solar (Bespoke calculator (embedded web component))
- · Solar Payback Calculator (Bespoke solar payback calculator)