From dad3044740bcd6340ca0e1126bcf06f487e6d9df Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Tue, 16 Jun 2026 12:17:43 +0000 Subject: [PATCH] save skills and automation progress --- .../epc-to-elmhurst-rdsap-inputs/SKILL.md | 40 +- .../expand-sap-accuracy-corpus/SKILL.md | 70 +++ .../start-prompt.md | 39 ++ .../expand-sap-accuracy-corpus/worklist.md | 114 +++++ .../validate-cert-sap-accuracy/SKILL.md | 8 + .gitignore | 4 + applications/sharepoint_renamer/handler.py | 3 +- .../uprn_60027826/elmhurst_inputs.md | 182 ++++++++ .../uprn_60027826/epc.json | 343 ++++++++++++++ .../uprn_10092973954/elmhurst_inputs.md | 182 ++++++++ .../uprn_10092973954/elmhurst_summary.pdf | Bin 0 -> 76883 bytes .../uprn_10092973954/elmhurst_worksheet.pdf | Bin 0 -> 23833 bytes .../SAP-Schema-17.1/uprn_10093116528/epc.json | 438 ++++++++++++++++++ 13 files changed, 1420 insertions(+), 3 deletions(-) create mode 100644 .claude/skills/expand-sap-accuracy-corpus/SKILL.md create mode 100644 .claude/skills/expand-sap-accuracy-corpus/start-prompt.md create mode 100644 .claude/skills/expand-sap-accuracy-corpus/worklist.md create mode 100644 backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-20.0.0/uprn_60027826/elmhurst_inputs.md create mode 100644 backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-20.0.0/uprn_60027826/epc.json create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10092973954/elmhurst_inputs.md create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10092973954/elmhurst_summary.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10092973954/elmhurst_worksheet.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093116528/epc.json diff --git a/.claude/skills/epc-to-elmhurst-rdsap-inputs/SKILL.md b/.claude/skills/epc-to-elmhurst-rdsap-inputs/SKILL.md index 56cfc72b..65fa7526 100644 --- a/.claude/skills/epc-to-elmhurst-rdsap-inputs/SKILL.md +++ b/.claude/skills/epc-to-elmhurst-rdsap-inputs/SKILL.md @@ -53,10 +53,20 @@ mapping reference must be looked up in the cited source file, not invented. useful the **EES dropdown path** and **SAP code**. Use the lookup tables and gotchas in [reference/mapping.md](reference/mapping.md). -4. **Save** the file next to the cert json as `elmhurst_inputs.md` +4. **Flag what must NOT be mapped / must be cleared.** Elmhurst pages carry + defaults and (when re-keying into an existing assessment) stale values that + silently survive and corrupt the result — a phantom 1st extension, a + room-in-roof area, a party-wall length, leftover window rows. For every + element the cert does **not** have, say so explicitly with the Elmhurst + field to blank and the value to set (usually empty or 0). The automated + filler (`scripts/hyde/elmhurst_fill.py`) and a human both rely on this list + — an unflagged absent element defaults to "present" and skews SAP. See the + **Fields to clear** section in Output shape below. + +5. **Save** the file next to the cert json as `elmhurst_inputs.md` (e.g. `.../real_life_examples//uprn_/elmhurst_inputs.md`). -5. **Tell the operator**: key it into Elmhurst, then report the SAP score (and +6. **Tell the operator**: key it into Elmhurst, then report the SAP score (and heating cost £ if shown). If it differs from our engine's score, that's a calculator finding — capture it. @@ -70,6 +80,27 @@ Start the file with a header block: ``` Then the page sections as tables: `| Elmhurst field | Value | Notes (SAP code / EES path) |`. +End the file with a **Fields to clear in Elmhurst (do NOT map)** section — one +table listing every element the cert lacks but Elmhurst defaults or stale data +would otherwise assert. This is the explicit "absent" set the filler and the +operator clear: +``` +## Fields to clear in Elmhurst (do NOT map) +| Elmhurst field | Set to | Why absent | +|---|---|---| +| Property Description · 1st–4th Extension age band | (blank) | no extensions lodged | +| Property Description · Room-in-Roof age band | (blank) | no room-in-roof building part | +| Dimensions · Room(s) in Roof area | (blank) | ditto — leave empty, not 0 | +| Dimensions · 1st–4th Ext. sub-tabs | 0 / blank | single building part | +| Walls · Party wall | none/blank | `party_walls_w_per_k` = 0 | +| Openings · surplus window rows | delete | window count from glazed-area band only | +| Water Heating · cylinder | none | combi / instantaneous | +| Conservatory / PV / Wind / Hydro / WWHRS / FGHRS | none | not lodged | +``` +Give the **Elmhurst page · field**, the **cleared value** (prefer *blank* over +0 where the field is "not applicable"; some validators reject 0), and the +one-line reason. Absent ≠ zero everywhere — note which. + ## Critical gotchas (full detail in reference) - **Economy-7 / off-peak electricity** (`main_fuel_type`/`water_heating_fuel` 29): @@ -84,6 +115,11 @@ Then the page sections as tables: `| Elmhurst field | Value | Notes (SAP code / - **Water heating** 903 = Electric immersion off-peak → Elmhurst "Water Heater" category, not "Boiler Circulator" (901 = from main system). - **Windows** are synthesised from `glazed_area` band × TFA — not real geometry. +- **Age band — pick by construction YEAR, not the engine's band letter.** The + live RdSAP-10 tool bands differently from `mapping.md`'s older table: it + offers `…K 2007-2011`, **`L 2012-2022`**, **`M 2023 onwards`**. A 2020 build + is **L** even though the engine labels `construction_age_band` "M". Map the + year to Elmhurst's on-screen band; flag the letter divergence. ## Canonical example diff --git a/.claude/skills/expand-sap-accuracy-corpus/SKILL.md b/.claude/skills/expand-sap-accuracy-corpus/SKILL.md new file mode 100644 index 00000000..2507f61e --- /dev/null +++ b/.claude/skills/expand-sap-accuracy-corpus/SKILL.md @@ -0,0 +1,70 @@ +--- +name: expand-sap-accuracy-corpus +description: Drive the per-UPRN SAP-accuracy corpus campaign. For each UPRN ensure the EPC-API→EpcPropertyData mapping exists (extend the mapper if the schema isn't covered), build the cert in Elmhurst (hyde Playwright automation), download its Input Summary + SAP Worksheets, reconcile our SAP calculator to within 0.5 of Elmhurst's accredited worksheet by fixing mapper gaps (not tuning), and pin a RealCertExpectation regression. Use when expanding SAP-calculator schema coverage/accuracy across many real certs, working the 100-UPRN worklist one at a time, validating the EPC mapper against Elmhurst, or when the user mentions the SAP accuracy corpus / Elmhurst worksheets / the UPRN campaign. +--- + +# Expand SAP accuracy corpus + +A campaign wrapper around **`validate-cert-sap-accuracy`**, run **one UPRN at a +time** over [worklist.md](worklist.md). Why a UPRN at a time: we are rewriting / +extending the mapper incrementally, and each pass should (a) widen EPC-schema +coverage, (b) fix one real mapper gap, (c) leave the skills/tests sharper for the +next UPRN. + +**Goal per UPRN:** our SAP calculator within **0.5 SAP** of Elmhurst's +accredited worksheet, the agreed score pinned as a `RealCertExpectation`. + +The big picture: an old EPC → `EpcPropertyData` → our SAP calculator predicts the +score the property would get unchanged. Elmhurst is the accredited ground truth; +its Input Summary (parsed back to `EpcPropertyData`) exposes mapper holes, and its +worksheet exposes calculator holes. + +## The loop (one UPRN) + +1. **Pick** the first `[ ]` UPRN in [worklist.md](worklist.md). +2. **Capture** — `PYTHONPATH=/workspaces/model python scripts/fetch_real_life_epc_sample.py ` + → `epc.json` + schema + engine SAP under `…/real_life_examples//uprn_/`. + - **`NOT MAPPABLE`** (schema uncovered, e.g. full SAP) → this *is* the coverage + work: **extend the mapper** for that schema (`EpcPropertyDataMapper` / per-cert + mapper — Khalim's domain). Mark `🔧 mapper-gap`, build it, re-run. Guard with + the RdSAP-21.0.1 corpus gauge (`test_sap_accuracy_corpus.py`). +3. **Inputs** — run the **`epc-to-elmhurst-rdsap-inputs`** skill on the UPRN → + complete `elmhurst_inputs.md` (+ its **Fields to clear** section). +4. **Build in Elmhurst** (`scripts/hyde/`, mechanics in `elmhurst_README.md`): + `bash scripts/hyde/start_viewer.sh` (noVNC on :99) → log in once + (`elmhurst_session.py login`) → **create a NEW assessment for this UPRN** → + fill from `elmhurst_inputs.md`: `elmhurst_fill.py` auto-fills the derivable + pages (incl. the boiler cascade) + the clears; key the 🔸 fields by hand. Then + `elmhurst_download.py` saves **`elmhurst_summary.pdf`** + **`elmhurst_worksheet.pdf`** + into the sample dir. ⚠ The filler hard-codes one assessment + one cert's values + today — see **Limitations**. +5. **Compare** — `PYTHONPATH=/workspaces/model python scripts/compare_epc_paths.py ` + → deep-diffs gov-API vs Elmhurst-parsed `EpcPropertyData`, runs **both** through + the engine, and prints Elmhurst's own worksheet SAP. Read it: engine-on-Elmhurst- + inputs ≈ worksheet ⇒ calculator faithful; gov-API vs Elmhurst gap ⇒ input diffs. +6. **Reconcile to ≤0.5** — triage every field diff (use the + `epc-to-elmhurst-rdsap-inputs` `reference/mapping.md` for code semantics): + - **Elmhurst data-entry error** → fix in Elmhurst, re-export, re-run step 5. + - **gov-API mapper gap** → the leverage point. Fix the mapper **generically**; + never tune to one cert. Cosmetic diffs (codes vs strings, empty lists) are noise. + - **Genuine ground-truth** → align both sides to the lodged data. +7. **Pin** — add a `RealCertExpectation` to + `tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py`; run it. If a + known engine bug still blocks, use `known_bug_xfail="…"` (strict xfail) — don't widen. +8. **Bank** — fold what you learned into `mapping.md` / this skill / the tests so + the next UPRN is easier, and set the worklist status (see legend). + +## Worklist status legend +`[ ]` todo · `[x]` pinned (≤0.5) · `🔧` mapper extended · `⚠` xfail (engine bug) · +`⛔` blocked. Annotate each done line: `— · eng / elm · `. + +## Limitations / next improvements (make the campaign scale) +- **Per-assessment GUID** — `elmhurst_fill.py` / `elmhurst_download.py` hard-code + `ASSESSMENT_GUID` (the Khalim-test cert). Each UPRN needs its own Elmhurst + assessment; create one and update the GUID, or parameterize it (`--guid`). +- **Cert-specific fill values** — `PAGES` in `elmhurst_fill.py` hold one cert's + values. Make it **data-driven** (read field values from each cert's + `elmhurst_inputs.md` or a JSON sidecar) so one filler serves all UPRNs. Until + then, build each cert guided by its `elmhurst_inputs.md` (the filler is a template). +- **More dialogs** — boiler is automated (cascade); apply the same + open→select→OK pattern to the control code (2110) and the MV unit when wanted. diff --git a/.claude/skills/expand-sap-accuracy-corpus/start-prompt.md b/.claude/skills/expand-sap-accuracy-corpus/start-prompt.md new file mode 100644 index 00000000..16127a59 --- /dev/null +++ b/.claude/skills/expand-sap-accuracy-corpus/start-prompt.md @@ -0,0 +1,39 @@ +# Start prompt — run the corpus campaign one UPRN at a time + +Paste the block below into Claude to process the **next** UPRN. It does exactly +one UPRN and stops; reply **"next"** (or re-paste) to advance. Reuses the single +Elmhurst assessment/GUID and overwrites it each time — the EPC-API ↔ Input-Summary +diff in the Compare step is the safety net for leftover state. + +--- + +``` +Run the `expand-sap-accuracy-corpus` skill to process the NEXT UPRN, ONE at a time. + +1. Open `.claude/skills/expand-sap-accuracy-corpus/worklist.md` and take the first `[ ]` UPRN. +2. Run that single UPRN through the skill's loop: + - Capture: `PYTHONPATH=/workspaces/model python scripts/fetch_real_life_epc_sample.py `. + If it prints NOT MAPPABLE (schema uncovered), that's the job — extend the + EpcPropertyDataMapper for that schema generically, then re-run. Guard with the + RdSAP-21.0.1 corpus gauge. + - Inputs: run the `epc-to-elmhurst-rdsap-inputs` skill on the UPRN → complete + `elmhurst_inputs.md` (with the "Fields to clear" section). + - Build in Elmhurst, REUSING the existing assessment: + GUID B44A0DB4-4C08-4241-B818-86F060172105 (the "Khalim-test" cert). + `bash scripts/hyde/start_viewer.sh` (noVNC on :99). The filler's PAGES values + are from the previous cert — update them to THIS cert's values from the new + `elmhurst_inputs.md` (it's one-at-a-time, so editing the specs is fine), set + AND clear every field (overwrite the prior UPRN's state — use the Fields-to-clear + list), and key the 🔸 dialog fields by hand. Then run `elmhurst_download.py` + to save `elmhurst_summary.pdf` + `elmhurst_worksheet.pdf` into the sample dir. + NEVER click Submit. + - Compare: `PYTHONPATH=/workspaces/model python scripts/compare_epc_paths.py `. + - Reconcile to ≤0.5 SAP: fix mapper gaps GENERICALLY (never tune to one cert); + Elmhurst's Input Summary diff localises them. Cosmetic diffs are noise. + - Pin a RealCertExpectation in + tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py and run it. + Use strict known_bug_xfail for a known engine bug instead of widening. + - Update that worklist line: [x]/🔧/⚠/⛔ — · eng / elm · . +3. STOP after this one UPRN. Report: schema, any mapper changes, engine vs Elmhurst + SAP and what reconciled them, and the test result. Then wait for me to say "next". +``` diff --git a/.claude/skills/expand-sap-accuracy-corpus/worklist.md b/.claude/skills/expand-sap-accuracy-corpus/worklist.md new file mode 100644 index 00000000..6794e933 --- /dev/null +++ b/.claude/skills/expand-sap-accuracy-corpus/worklist.md @@ -0,0 +1,114 @@ +# SAP accuracy corpus — UPRN worklist + +Process **one at a time**, top to bottom (see [SKILL.md](SKILL.md)). After each +UPRN, tick it and annotate: `— · eng / elm · `. + +**Legend:** `[ ]` todo · `[x]` pinned (≤0.5) · `🔧` mapper extended · `⚠` xfail +(engine bug) · `⛔` blocked. + +**Worked reference (not in the 100):** `uprn_10092973954` (SAP-Schema-17.1, +2020 new-build flat) — full loop proven: eng 77 / elm 78, engine-on-Elmhurst- +inputs 79 (calculator faithful within ~1). Use it to sanity-check the pipeline. + +## The 100 + +- [ ] 10093116528 +- [ ] 10093116543 +- [ ] 10093116529 +- [ ] 100020933699 +- [ ] 44012843 +- [ ] 10023444324 +- [ ] 10092970673 +- [ ] 10094601287 +- [ ] 10090844932 +- [ ] 10090844948 +- [ ] 100090182288 +- [ ] 10093114053 +- [ ] 10091568921 +- [ ] 10093718424 +- [ ] 10022893721 +- [ ] 10023443426 +- [ ] 10093412452 +- [ ] 10014314798 +- [ ] 10094601294 +- [ ] 10090343335 +- [ ] 10093115480 +- [ ] 68151071 +- [ ] 100021985993 +- [ ] 100020665611 +- [ ] 10093388044 +- [ ] 10090944225 +- [ ] 10090341811 +- [ ] 10010215568 +- [ ] 10093117227 +- [ ] 10023444170 +- [ ] 100020980961 +- [ ] 200003714056 +- [ ] 10094601280 +- [ ] 10093386418 +- [ ] 100090108846 +- [ ] 10093116324 +- [ ] 10094895444 +- [ ] 10092973960 +- [ ] 10012028763 +- [ ] 10093049867 +- [ ] 10093116336 +- [ ] 100020235156 +- [ ] 10093116334 +- [ ] 10014314853 +- [ ] 10013924849 +- [ ] 100062116493 +- [ ] 10091636116 +- [ ] 10093049853 +- [ ] 10093390790 +- [ ] 10093116330 +- [ ] 10093116326 +- [ ] 10090317693 +- [ ] 10090034872 +- [ ] 10093115985 +- [ ] 10023230742 +- [ ] 10009432998 +- [ ] 100022015916 +- [ ] 202211170 +- [ ] 200003400077 +- [ ] 100061795739 +- [ ] 10093305101 +- [ ] 100020933894 +- [ ] 100020937013 +- [ ] 10023444320 +- [ ] 100062188801 +- [ ] 10008048040 +- [ ] 10093101966 +- [ ] 10093084691 +- [ ] 100061086424 +- [ ] 10023443568 +- [ ] 100090182702 +- [ ] 10090342180 +- [ ] 200003398613 +- [ ] 10093718415 +- [ ] 100061850726 +- [ ] 10091636031 +- [ ] 10014314830 +- [ ] 202211161 +- [ ] 10094895409 +- [ ] 100060930947 +- [ ] 10093388053 +- [ ] 100020973465 +- [ ] 100062190000 +- [ ] 10093114178 +- [ ] 10093303593 +- [ ] 10093303465 +- [ ] 10091194525 +- [ ] 10093386427 +- [ ] 10002917849 +- [ ] 100020212302 +- [ ] 10012028772 +- [ ] 10093083532 +- [ ] 10090034761 +- [ ] 10070622696 +- [ ] 200003725383 +- [ ] 10093387673 +- [ ] 10093412389 +- [ ] 10090343767 +- [ ] 10090845805 +- [ ] 10013924858 diff --git a/.claude/skills/validate-cert-sap-accuracy/SKILL.md b/.claude/skills/validate-cert-sap-accuracy/SKILL.md index be3a6283..a7d84c46 100644 --- a/.claude/skills/validate-cert-sap-accuracy/SKILL.md +++ b/.claude/skills/validate-cert-sap-accuracy/SKILL.md @@ -30,6 +30,14 @@ Sample home for every cert: `backend/epc_api/json_samples/real_life_examples/ None: diff --git a/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-20.0.0/uprn_60027826/elmhurst_inputs.md b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-20.0.0/uprn_60027826/elmhurst_inputs.md new file mode 100644 index 00000000..3d479b91 --- /dev/null +++ b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-20.0.0/uprn_60027826/elmhurst_inputs.md @@ -0,0 +1,182 @@ +# Elmhurst RdSAP inputs — UPRN 60027826 (cert 0080-2673-2086-2299-1061, RdSAP-Schema-20.0.0) + +**Lodged SAP:** 72 **Our engine:** 70 ← compare Elmhurst against **70** (the production gov-API path) +**Known divergences:** None of the off-peak Economy-7 bugs apply — this is a **mains-gas** boiler with **mains-gas** hot water. Watch instead: (a) RdSAP-20 synthesised-window U translation, (b) the room-in-roof entry, (c) the unlodged party wall defaulting to U=0.25. + +10 Kingsland Close, Shoreham-by-Sea, BN43 6NQ · Semi-detached house · inspected 2021-08-17, lodged 2022-04-13. + +--- + +## Property Description + +| Elmhurst field | Value | Notes (SAP code / EES path) | +|---|---|---| +| Property Type | House | `property_type` 0 | +| Built Form | Semi-detached | `built_form` 2 | +| Age Band (England & Wales) | **H — 1991–1995** | `construction_age_band` H | +| Storeys | **3** | ground + first + room-in-roof (intermediate `storey_count`=3.0) | +| Habitable rooms | 6 | `habitable_room_count` | +| Heated rooms | 6 | `heated_room_count` | +| Extensions | 0 | `extensions_count` | +| Rooms in roof | **Yes — 1** | `sap_room_in_roof` lodged (see Roofs) | + +## Dimensions (`measurement_type` 1 = Internal) + +| Floor | Area m² | Room Height m | Heat-Loss Perimeter m | Party-Wall Length m | +|---|---|---|---|---| +| Ground (floor 0) | **42.85** | 2.3 | 21.7 | 6 | +| First (floor 1) | **36** | 2.3 | 18 | 6 | +| Room-in-roof | **36** | (entered on Rooms-in-Roof page, not as a dimension floor) | — | — | + +TFA check: 42.85 + 36 + 36 = **114.85 m²** (lodged `total_floor_area` 115). No heated basement. + +## Conservatory + +None — `conservatory_type` 1, `has_heated_separate_conservatory` false → leave unchecked. + +## Walls + +**Main / external wall** +| Elmhurst field | Value | Notes | +|---|---|---| +| Construction | **Cavity wall** | `wall_construction` 4; description "Cavity wall, filled cavity" | +| Insulation | **Filled cavity** | `wall_insulation_type` 2 (retrofit cavity fill) | +| Dry-lined | **Yes** | `wall_dry_lined` Y | +| Wall Thickness | **300 mm** | `wall_thickness` 300; `wall_thickness_measured` Y → "Wall Thickness Unknown" unchecked | +| (cross-check) | lodged `wall_u_value` 0.33; engine `walls_w_per_k` 26.27 | | + +No alternative wall lodged. + +**Party wall** — `party_wall_construction` **0 (not lodged)** +| Elmhurst field | Value | Notes | +|---|---|---| +| Type | **Unable to determine** | code 0 → engine default **U = 0.25** (NOT the code-1 "Solid" trap — here it is genuinely unlodged, so "Unable to determine" is correct and matches the engine). Engine `party_walls_w_per_k` 7.275 ≈ 29 m² × 0.25. | + +## Roofs + +| Elmhurst field | Value | Notes | +|---|---|---| +| Type | **Room in roof** (pitched, slates/tiles) | description "Roof room(s), insulated (assumed)"; `roof_construction` 4 | +| Rooms-in-roof area | **36 m²** | `sap_room_in_roof.floor_area` 36 | +| Rooms-in-roof insulation | **As built** | `sap_room_in_roof.insulation` "AB"; age band H; `roof_room_connected` N | +| Roof insulation location | **At joists** | `roof_insulation_location` 2 | +| Roof insulation thickness | **100 mm** | `roof_insulation_thickness` "100mm" (drives default U) | +| (cross-check) | engine `roof_w_per_k` 24.17 | | + +## Floors + +| Elmhurst field | Value | Notes | +|---|---|---| +| Construction | **Solid** | `floor_construction` 1; description "Solid, no insulation (assumed)" | +| Insulation | **As built** (none) | `floor_insulation_thickness` "NI" | +| (cross-check) | engine `floor_w_per_k` 30.0 | | + +## Openings — Windows (RdSAP reduced-data, synthesised) + +Glazed-area band = **Normal** (`glazed_area` 1, ×1.00). Synthesised total glazing area += 0.148 × 114.85 × 1.00 = **17.02 m²**, split 4-way N/E/S/W (4 windows × 4.255 m wide × 1.0 m high). + +| Elmhurst field | Value | Notes | +|---|---|---| +| Glazing Type | **Double, unknown install date** | `multiple_glazing_type` 3; "Fully double glazed" | +| Frame Type | **PVC** | `pvc_window_frames` true | +| Glazing Gap | **16 mm** | `glazing_gap` "16+" | +| Orientation | spread evenly N / E / S / W | not lodged — matches engine synth (orients 1,3,5,7) | +| Location | External wall | | +| Draught Proofed | **Yes (100%)** | `percent_draughtproofed` 100 | +| U-value / g-value | leave Elmhurst default; **lodged U = 2.6, g = 0.76** | `windows_transmission_details`; engine effective U = `windows_w_per_k` 42.86 ÷ 17.02 ≈ **2.52**. ⚠️ Report the U Elmhurst assigns — RdSAP-20 glazing-coefficient translation is the most likely source of the lodged-72-vs-engine-70 gap. | + +## Openings — Doors + +| Elmhurst field | Value | Notes | +|---|---|---| +| Total doors | **2** | `door_count` 2 | +| Insulated | **0** | `insulated_door_count` 0 | +| Draught proofed | 2 | `percent_draughtproofed` 100 → engine `doors_w_per_k` 11.1 ≈ 2 × 1.85 m² × 3.0 | + +## Ventilation & Lighting + +| Elmhurst field | Value | Notes | +|---|---|---| +| Open chimneys | 0 | `open_fireplaces_count` 0 | +| Open flues / passive vents / flueless gas / extract fans | 0 | none lodged | +| Fixed air conditioning | No | `has_fixed_air_conditioning` false | +| Mechanical Ventilation | **Natural** (unchecked) | `mechanical_ventilation` 0 | +| Air Pressure Test | **Not available** (uses % draughtproofing) | RdSAP cert | +| Lighting — total fixed outlets | **14** | `fixed_lighting_outlets_count` 14 | +| Lighting — low-energy outlets | **12** | `low_energy_fixed_lighting_outlets_count` 12 (86%) | + +## Space Heating + +**Main Heating 1** — `sap_main_heating_code` **102** +| Elmhurst field | Value | Notes | +|---|---|---| +| System | **Boiler + radiators, mains gas** | "Boiler and radiators, mains gas"; `main_heating_category` 2; `heat_emitter_type` 1 = radiators | +| Boiler type | **Regular condensing, automatic ignition** | code 102 (Table 4b) | +| Efficiency | **84% winter / 74% summer** | Table 4b code 102; engine `main_heating_efficiency` 0.84. `main_heating_data_source` 2 (age-band/Table default, no PCDB record) | +| Fuel | **Mains gas** | `main_fuel_type` 26 (engine space-heat cost 3.48 p/kWh) | +| Flue | Fanned flue present | `boiler_flue_type` 2, `fan_flue_present` Y | +| Controls | **Programmer + room thermostat + TRVs** | `main_heating_control` 2106 | +| % of heat | 100% | `main_heating_fraction` 1 | +| Heat Emitter / Pump Age | leave default (no PCDF) | `central_heating_pump_age` 0 | + +**Main Heating 2** — none (single main system). + +**Secondary Heating** — leave Elmhurst **default (assumed portable electric heaters)**. +`secondary_heating_type` 691; engine applies fraction **0.1** at **standard-tariff electricity** (fuel 30), `secondary_heating_fuel_kwh` ≈ 976 kWh. (Cert lodges `secondary_fuel_type` 29 but the engine prices the assumed secondary at standard tariff per SAP convention — leave the Elmhurst default and it agrees.) + +**Community Heating** — none. + +## Meters + +| Elmhurst field | Value | Notes | +|---|---|---| +| Mains gas supply available | **Yes** | `sap_energy_source.mains_gas` Y | +| Electricity meter type | **Single (standard)** | `meter_type` 1 — no Economy-7 here; off-peak fuel-cost bug **does not apply** | + +## Water Heating + +| Elmhurst field | Value | Notes | +|---|---|---| +| Source | **From main heating system** (Boiler Circulator) | `water_heating_code` 901; "From main system" | +| Fuel | **Mains gas** | `water_heating_fuel` 26 (engine HW cost 3.48 p/kWh) | +| Hot Water Cylinder Present | **Yes** | `has_hot_water_cylinder` true | +| Cylinder size | **110 L** (pick the litre value, not "Normal") | `cylinder_size` code 2 = 110 L | +| Cylinder insulation type | **Factory foam** | `cylinder_insulation_type` 1 = Foam | +| Cylinder insulation thickness | **50 mm** | `cylinder_insulation_thickness` 50 | +| Cylinder thermostat | **Yes** | `cylinder_thermostat` Y | +| (cross-check) | engine `hot_water_kwh_per_yr` 3640 | | + +- **Number of baths** (Water Heating → **WWHRS sub-tab → "Total no. of Baths"**): **1** + — `instantaneous_wwhrs.rooms_with_bath_and_or_shower` 1 + `rooms_with_bath_and_mixer_shower` 0 = 1. Elmhurst defaults to 0; set it to **1** or HW demand diverges. +- **WWHRS**: **No** — the `instantaneous_wwhrs` block is bath/shower ROOM counts (ADR-0028), not a heat-recovery device. +- **Community Hot Water**: none. +- **Solar Water Heating**: No — `solar_water_heating` N. +- **FGHRS**: No — `main_heating_details[].has_fghrs` N. + +## New Technologies + +| Elmhurst field | Value | Notes | +|---|---|---| +| PV | **None** | `photovoltaic_supply.none_or_no_details` | +| Wind | **None** | `wind_turbines_count` 0 | +| Hydro | None | not lodged | +| Special Features (Appendix Q) | None | not lodged | + +--- + +### Engine reference outputs (the numbers Elmhurst should reproduce) + +| Quantity | Engine value | +|---|---| +| SAP score (integer) | **70** (continuous 69.77) | +| Space-heating demand | 9 755 kWh/yr | +| Main-heating fuel (gas) | 10 452 kWh/yr | +| Hot-water | 3 640 kWh/yr | +| Secondary (electric, assumed) | 976 kWh/yr | +| CO₂ | 3 184 kg/yr | +| Total fuel cost | £824.73/yr | +| Heat-transfer coefficient | 245.96 W/K | +| Heat-loss parameter | 2.14 W/m²K | + +**Operator: key this into Elmhurst, then export the Summary PDF (`elmhurst_summary.pdf`) and the SAP-10.2 worksheet PDF (`elmhurst_worksheet.pdf`) into this directory, and report the Elmhurst SAP score.** Then re-run `scripts/compare_epc_paths.py 60027826` to diff the two paths. diff --git a/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-20.0.0/uprn_60027826/epc.json b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-20.0.0/uprn_60027826/epc.json new file mode 100644 index 00000000..243c1f2d --- /dev/null +++ b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-20.0.0/uprn_60027826/epc.json @@ -0,0 +1,343 @@ +{ + "uprn": 60027826, + "roofs": [ + { + "description": { + "value": "Roof room(s), insulated (assumed)", + "language": "1" + }, + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "walls": [ + { + "description": { + "value": "Cavity wall, filled cavity", + "language": "1" + }, + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "floors": [ + { + "description": { + "value": "Solid, no insulation (assumed)", + "language": "1" + }, + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + } + ], + "status": "entered", + "tenure": 2, + "window": { + "description": { + "value": "Fully double glazed", + "language": "1" + }, + "energy_efficiency_rating": 3, + "environmental_efficiency_rating": 3 + }, + "lighting": { + "description": { + "value": "Low energy lighting in 86% of fixed outlets", + "language": "1" + }, + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + }, + "postcode": "BN43 6NQ", + "hot_water": { + "description": { + "value": "From main system", + "language": "1" + }, + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + }, + "post_town": "SHOREHAM-BY-SEA", + "built_form": 2, + "created_at": "2022-04-13 09:33:39.943417", + "door_count": 2, + "glazed_area": 1, + "glazing_gap": "16+", + "region_code": 14, + "report_type": 2, + "sap_heating": { + "cylinder_size": 2, + "water_heating_code": 901, + "water_heating_fuel": 26, + "cylinder_thermostat": "Y", + "instantaneous_wwhrs": { + "rooms_with_bath_and_or_shower": 1, + "rooms_with_mixer_shower_no_bath": 0, + "rooms_with_bath_and_mixer_shower": 0 + }, + "secondary_fuel_type": 29, + "main_heating_details": [ + { + "has_fghrs": "N", + "main_fuel_type": 26, + "boiler_flue_type": 2, + "fan_flue_present": "Y", + "heat_emitter_type": 1, + "emitter_temperature": 0, + "main_heating_number": 1, + "main_heating_control": 2106, + "main_heating_category": 2, + "main_heating_fraction": 1, + "sap_main_heating_code": 102, + "central_heating_pump_age": 0, + "main_heating_data_source": 2 + } + ], + "immersion_heating_type": "NA", + "secondary_heating_type": 691, + "cylinder_insulation_type": 1, + "has_fixed_air_conditioning": "false", + "cylinder_insulation_thickness": 50 + }, + "sap_version": 9.94, + "schema_type": "RdSAP-Schema-20.0.0", + "uprn_source": "Energy Assessor", + "country_code": "EAW", + "main_heating": [ + { + "description": { + "value": "Boiler and radiators, mains gas", + "language": "1" + }, + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "dwelling_type": { + "value": "Semi-detached house", + "language": "1" + }, + "language_code": 1, + "property_type": 0, + "address_line_1": "10 KINGSLAND CLOSE", + "assessment_type": "RdSAP", + "completion_date": "2022-04-13", + "inspection_date": "2021-08-17", + "extensions_count": 0, + "measurement_type": 1, + "total_floor_area": 115, + "transaction_type": 13, + "conservatory_type": 1, + "heated_room_count": 6, + "pvc_window_frames": "true", + "registration_date": "2022-04-13", + "sap_energy_source": { + "mains_gas": "Y", + "meter_type": 1, + "photovoltaic_supply": { + "none_or_no_details": { + "pv_connection": 0, + "percent_roof_area": 0 + } + }, + "wind_turbines_count": 0, + "wind_turbines_terrain_type": 2 + }, + "secondary_heating": { + "description": { + "value": "None", + "language": "1" + }, + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + }, + "sap_building_parts": [ + { + "identifier": "Main Dwelling", + "wall_u_value": 0.33, + "wall_dry_lined": "Y", + "wall_thickness": 300, + "floor_heat_loss": 7, + "sap_room_in_roof": { + "floor_area": { + "value": 36, + "quantity": "square metres" + }, + "insulation": "AB", + "roof_room_connected": "N", + "construction_age_band": "H" + }, + "roof_construction": 4, + "wall_construction": 4, + "building_part_number": 1, + "sap_floor_dimensions": [ + { + "floor": 0, + "room_height": { + "value": 2.3, + "quantity": "metres" + }, + "floor_insulation": 1, + "total_floor_area": { + "value": 42.85, + "quantity": "square metres" + }, + "party_wall_length": { + "value": 6, + "quantity": "metres" + }, + "floor_construction": 1, + "heat_loss_perimeter": { + "value": 21.7, + "quantity": "metres" + } + }, + { + "floor": 1, + "room_height": { + "value": 2.3, + "quantity": "metres" + }, + "total_floor_area": { + "value": 36, + "quantity": "square metres" + }, + "party_wall_length": { + "value": 6, + "quantity": "metres" + }, + "heat_loss_perimeter": { + "value": 18, + "quantity": "metres" + } + } + ], + "wall_insulation_type": 2, + "construction_age_band": "H", + "party_wall_construction": 0, + "wall_thickness_measured": "Y", + "roof_insulation_location": 2, + "roof_insulation_thickness": "100mm", + "floor_insulation_thickness": "NI" + } + ], + "low_energy_lighting": 86, + "solar_water_heating": "N", + "habitable_room_count": 6, + "heating_cost_current": { + "value": 522, + "currency": "GBP" + }, + "insulated_door_count": 0, + "co2_emissions_current": 3.4, + "energy_rating_average": 60, + "energy_rating_current": 72, + "lighting_cost_current": { + "value": 111, + "currency": "GBP" + }, + "main_heating_controls": [ + { + "description": { + "value": "Programmer, room thermostat and TRVs", + "language": "1" + }, + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "multiple_glazing_type": 3, + "open_fireplaces_count": 0, + "has_hot_water_cylinder": "true", + "heating_cost_potential": { + "value": 486, + "currency": "GBP" + }, + "hot_water_cost_current": { + "value": 129, + "currency": "GBP" + }, + "mechanical_ventilation": 0, + "percent_draughtproofed": 100, + "suggested_improvements": [ + { + "sequence": 1, + "typical_saving": { + "value": 37, + "currency": "GBP" + }, + "indicative_cost": "\u00a34,000 - \u00a36,000", + "improvement_type": "W2", + "improvement_details": { + "improvement_number": 58 + }, + "improvement_category": 5, + "energy_performance_rating": 74, + "environmental_impact_rating": 71 + }, + { + "sequence": 2, + "typical_saving": { + "value": 42, + "currency": "GBP" + }, + "indicative_cost": "\u00a34,000 - \u00a36,000", + "improvement_type": "N", + "improvement_details": { + "improvement_number": 19 + }, + "improvement_category": 5, + "energy_performance_rating": 75, + "environmental_impact_rating": 73 + }, + { + "sequence": 3, + "typical_saving": { + "value": 400, + "currency": "GBP" + }, + "indicative_cost": "\u00a33,500 - \u00a35,500", + "improvement_type": "U", + "improvement_details": { + "improvement_number": 34 + }, + "improvement_category": 5, + "energy_performance_rating": 84, + "environmental_impact_rating": 81 + } + ], + "co2_emissions_potential": 1.8, + "energy_rating_potential": 84, + "lighting_cost_potential": { + "value": 111, + "currency": "GBP" + }, + "schema_version_original": "LIG-19.0", + "hot_water_cost_potential": { + "value": 85, + "currency": "GBP" + }, + "renewable_heat_incentive": { + "water_heating": 2737, + "impact_of_loft_insulation": -71, + "space_heating_existing_dwelling": 8821 + }, + "energy_consumption_current": 167, + "has_fixed_air_conditioning": "false", + "multiple_glazed_proportion": 100, + "calculation_software_version": "2.1.1.0", + "energy_consumption_potential": 89, + "environmental_impact_current": 69, + "fixed_lighting_outlets_count": 14, + "windows_transmission_details": { + "u_value": 2.6, + "data_source": 2, + "solar_transmittance": 0.76 + }, + "current_energy_efficiency_band": "C", + "environmental_impact_potential": 81, + "has_heated_separate_conservatory": "false", + "potential_energy_efficiency_band": "B", + "co2_emissions_current_per_floor_area": 29, + "low_energy_fixed_lighting_outlets_count": 12 +} \ No newline at end of file diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10092973954/elmhurst_inputs.md b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10092973954/elmhurst_inputs.md new file mode 100644 index 00000000..f531a917 --- /dev/null +++ b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10092973954/elmhurst_inputs.md @@ -0,0 +1,182 @@ +# Elmhurst RdSAP inputs — UPRN 10092973954 (cert 0862-3892-7875-2690-2325, SAP-Schema-17.1) + +**Lodged SAP:** 83 (band B) **Our engine:** 77 (continuous 76.85) ← compare Elmhurst against this +**Total fuel cost (engine):** £445.80/yr **Heat transfer coeff:** 112.11 W/K +**Known divergences:** full-SAP cert forced through RdSAP — window area is banded, U-values/thermal-bridging are age-band proxies (see notes). MEV extract is the engine's −4 SAP driver. + +> **Complete + filler-ready.** Every row names the **live Elmhurst control id** +> (suffix after `ContentBody_ContentPlaceHolder1_`) from the DOM dumps in +> `scripts/hyde/elmhurst_dom/`, so `scripts/hyde/elmhurst_fill.py` can map each +> directly. Dropdown values are the **exact option labels** (they carry a code +> prefix, e.g. `F Flat`). 🔸 = **assessor-only** field the EPC can't supply. +> The **Fields to clear** table at the bottom is the explicit "absent" set. + +--- + +## Property Details (admin — does NOT affect SAP) +| Elmhurst field (`id`) | Enter | Notes | +|---|---|---| +| `DropDownListPurpose` | None of the above | not a retrofit/modelling job | +| `DropDownListTenure` | Owner-occupied | `tenure` ND; tenure doesn't affect SAP | +| `DropDownListTransactionType` | None of the above | `transaction_type` 6 = new dwelling (no exact option) | +| `TextBoxInspectionDate` | as lodged | admin only | + +## Property Description ✅ committed +| Elmhurst field (`id`) | Enter | Notes | +|---|---|---| +| `DropDownListPropertyType1` | **F Flat** | `property_type` 2 | +| `DropDownListPropertyType2` | **D Detached** | `built_form` 1 (block form) | +| `TextBoxStoreys` | **1** | single-storey flat | +| `TextBoxHabitableRooms` | **3** | back-solved from `living_area` 23.45 / TFA | +| `TextBoxHeatedHabitableRooms` | **3** | all heated | +| `DropDownListDateBuiltMain` | **L 2012-2022** | 2020 build — by YEAR (engine band "M"; see gotcha) | + +## Dimensions (Type = Internal) — Lowest Floor row only +| Elmhurst field (`id`, under `…DimensionsMain_`) | Enter | Notes | +|---|---|---| +| `RadioButtonDimensionsType` | Internal | `measurement_type` 1 | +| `TextBoxFloorAreaLowestFloor` | **67.84** | engine TFA (cert top-level 68) | +| `TextBoxRoomHeightLowestFloor` | **2.40** | volume 162.816 ÷ 67.84 | +| `TextBoxWallPerimeterLowestFloor` | **38.14** | heat-loss perimeter (= 91.54 m² ÷ 2.4) | +| `TextBoxPartyWallLengthLowestFloor` | **0** | `party_walls_w_per_k` = 0 | + +## Conservatory ✅ already correct +| Elmhurst field (`id`) | Enter | Notes | +|---|---|---| +| `CheckBoxIsConservatory` | unchecked | `conservatory_type` 1 = none | + +## Flats +| Elmhurst field (`id`) | Enter | Notes | +|---|---|---| +| `DropDownListPositionOfFlat` | **Ground Floor** | `sap_flat_details.level` 1 / ground-floor flat | +| `TextBoxFloor` | **0** | ground = storey 0 | +| 🔸 `TextBoxStoriesInBlock` | *assessor* | EPC doesn't give block height; not in cert | +| 🔸 `RadioButtonListFlatCoridor` | *assessor* | corridor/stairwell adjacency; `sheltered_sides_count` 1 hints 1 sheltered side | +| 🔸 `TextBoxLengthOfShelteredWall` | *assessor* | only if a sheltered/corridor wall is set | + +## Walls (Main + alternative + party) +| Elmhurst field (`id`, under `…WallMain_`) | Enter | Notes | +|---|---|---| +| `DropDownListType` | **TI Timber Frame** | new-build timber frame | +| `DropDownListInsulation` | **A As Built** | factory-insulated | +| `TextBoxWallThickness` | as built | — | +| `CheckBoxUvalueKnown` + U-value | **0.17** if override offered | cert "0.17 W/m²K"; engine wall ≈12.60 W/K | +| `CheckBoxAditionalWallSheltered` / `DropDownListAlternativeWall1Type` | **clear** (area 0) | leftover `SO Solid Brick` is placeholder — see Fields to clear | +| `DropDownListPartyWallType` | n/a | party-wall **length 0** on Dimensions makes type irrelevant | + +## Roofs ✅ committed +| Elmhurst field (`id`, under `…RoofMain_`) | Enter | Notes | +|---|---|---| +| `DropDownListType` | **A Another dwelling above** | "(other premises above)" → `roof_w_per_k` = 0 (insulation fields disappear) | + +## Floors +| Elmhurst field (`id`, under `…FloorsMain_`) | Enter | Notes | +|---|---|---| +| `DropDownListLocation` | **G Ground floor** | already correct | +| `DropDownListType` | **S Solid** | `floor_type` 2 | +| `DropDownListInsulation` | **A As built** | new-build | +| `CheckBoxUValueKnown` + U-value | **0.13** if override offered | cert "0.13 W/m²K"; engine floor ≈8.82 W/K | + +## Openings — Windows (Elmhurst uses a per-window GRID) +RdSAP synthesises window area from `glazed_area` band × TFA = **15.16 m²** +("Much more than typical", ×1.51), whole-window **U 1.4**, **g 0.63**, 5 windows, +PVC frame (factor 0.7). Engine windows = **20.68 W/K**. +| Elmhurst grid field (`id`, under `…WindowsPanel_`) | Enter | Notes | +|---|---|---| +| `DropDownListExtGlazing` | **Double post or during 2022** (high-perf low-E) | cert `glazing_type` 7, 100% multiple-glazed | +| `DropDownListExtFrameType` | **PVC** | `frame_type` 2 | +| `TextBoxExtUValue` | **1.4** | manufacturer whole-window U | +| `TextBoxExtGValue` | **0.63** | cert g | +| 🔸 `TextBoxExtWidth` / `TextBoxExtHeight` / per-row geometry | *assessor* | RdSAP has no per-window geometry; enter rows totalling **15.16 m²**, or one combined row | +| `DropDownListExtOrientation` | as RdSAP default | cert orientations 8,2,6,2,4 — RdSAP ignores per-window orientation | + +## Openings — Doors +| Elmhurst field (`id`, under `…DoorsPanel_`) | Enter | Notes | +|---|---|---| +| `TextBoxDoors` | **1** | `door_count` 1 | +| `TextBoxDoorsInsulated` | **1** | new-build, cert door U 1.4 (engine `doors_w_per_k` 2.59) | + +## Ventilation & Lighting +| Elmhurst field (`id`) | Enter | Notes | +|---|---|---| +| `TabPanelMechVent_CheckBoxMechanicalVentilation` | **checked → dMEV** | 🔶 `ventilation_type` 6, EXTRACT_OR_PIV_OUTSIDE — the **−4 SAP driver** | +| 🔸 `SelectMVDialog_*` (MV unit) | *assessor* | pick the dMEV unit; `is_mechanical_vent_approved_installer_scheme` true | +| `TabPanelAirPressureTest_DropDownListTestMethod` | **Blower Door → 2.6** | `air_permeability` 2.6, `pressure_test` 1 (don't leave "Not available") | +| `TabPanelLighting_*` low-energy | **100% LED** (6 of 6) | "Low energy lighting in all fixed outlets" | +| `TabPanelVentilationPanel_TextBox*` chimneys/flues/fans | **0** | none lodged | +| Sheltered sides | **1** | `sheltered_sides_count` 1 (RdSAP defaults 2 — change) | + +## Space Heating — Main Heating 1 +Cert: "Boiler and radiators, mains gas", `main_fuel_type` 1, combi, **PCDB index 17929**, +efficiency **89%**, controls **2110** (time + temp zone), radiators. +| Elmhurst field (`id`, under `…MainHeating1_`) | Enter | Notes | +|---|---|---| +| 🔸 `TextBoxPCDFBoilerReference` (via `SelectBoilerDialog`) | **17929** | PCDB index; entered through the boiler-search dialog | +| `RadioButtonListHeatEmitter` | **Radiators** | `heat_emitter_type` 1 | +| `RadioButtonListFlueType` | **Balanced** | room-sealed; `is_flue_fan_present` true | +| `RadioButtonListFanAssistedFlue` | **Yes** | `main_heating_flue_type` 2 | +| `RadioButtonListHeatingPumpAge` | **2013 or later** | `central_heating_pump_age` 2, in heated space | +| 🔸 `TextBoxMainHeatingControls` (via `SelectHeatingControlsDialog`) | **2110** | time & temperature zone control; interlocked | +| `TextBoxPercentageOfHeat` | **100** | single main system | + +## Space Heating — Meters +| Elmhurst field (`id`, under `TabPanelMeters_`) | Enter | Notes | +|---|---|---| +| `RadioButtonListElectricityType` | **Single** | `electricity_tariff` 1 — **not** Economy 7 (no off-peak bug here) | +| `CheckBoxMainGas` | **checked** | mains gas available | + +## Water Heating +Cert: from main system (combi), `water_heating_code` 901, mains gas. Engine HW = **2,271 kWh/yr**. +| Elmhurst field (`id`, under `TabPanelWaterHeating_`) | Enter | Notes | +|---|---|---| +| 🔸 `TextBoxWaterHeatingCode` | **from main system** (901) | combi; **Boiler Circulator / from main** category (not Water Heater) | +| `CheckBoxHotWaterCylinder` | **unchecked** | combi instantaneous — **no cylinder** (clears CylinderSize/Insulated/Thickness/Thermostat) | +| `TabPanelWWHRS_DropDownListWWHRSPresent` | **No** | none lodged (`instantaneous_wwhrs` = bath/shower ROOM count, ADR-0028, not a device) | +| `TabPanelWWHRS_TextBoxRoomsWithBath` | leave default | baths not separately lodged; `design_water_use` 1 | + +## New Technologies ✅ already correct (all none) +| Elmhurst field (`id`) | Enter | Notes | +|---|---|---| +| `…PvPanelData` | None | no PV | +| `…CheckBoxWindTurbinePresent` | unchecked | `wind_turbines_count` 0 | +| `…TextBoxElectricityGenerated` (hydro) | 0 | none | + +--- + +## Fields to clear in Elmhurst (do NOT map) +These default/stale values read as **present** and skew SAP. Blank them. +| Elmhurst page · field (`id`) | Set to | Why absent | +|---|---|---| +| Property Description · `DropDownListDateBuiltFirst`…`Forth` | (blank) | no extensions lodged | +| Property Description · `DropDownListRoomInRoofMain`…`Forth` | (blank) | no room-in-roof building part | +| Dimensions · `…TextBoxFloorAreaRoomInRoof` | (blank) | leave empty, **not 0** (0 flags ✖) | +| Dimensions · 1st–4th Ext. sub-tabs (`TabPanel1stExt_…` etc.) | 0 / blank | single building part — phantom extension otherwise | +| Walls · `…DropDownListAlternativeWall1Type` + `TextBoxAddWallArea` | (blank / 0) | leftover `SO Solid Brick` placeholder; cert wall is one timber-frame element | +| Walls · `…CheckBoxAditionalWallSheltered` | unchecked | unless an assessor sets a sheltered wall | +| Openings · surplus window grid rows (`GridViewExtendedWidows_DeleteButton_*`) | delete | window count from glazed-area band, not real rows | +| Space Heating · `DropDownListSecondaryHeatingPresent` + `TextBoxSecondaryHeatingCode` | **No** / (blank) | `secondary_heating_category` 1 = None (placeholder `RWM`) | +| Space Heating · `TabPanelMainHeating2_*` | (blank) | single main system | +| Water Heating · `CheckBoxHotWaterCylinder` + cylinder fields | unchecked / (blank) | combi instantaneous, no cylinder | +| Water Heating · Solar (`…CheckBoxSolaWaterHeating`), WWHRS, FGHRS | none | not lodged | +| Conservatory / PV / Wind / Hydro | none | not lodged | + +## Engine reference figures (reconcile against Elmhurst's worksheet) +| Quantity | Engine value | +|---|---| +| **SAP score** | **77** (continuous 76.85) | +| Total fuel cost | £445.80/yr | +| Space-heating demand | 3,917.4 kWh/yr | +| Main heating fuel | 4,401.5 kWh/yr | +| Hot water | 2,271.0 kWh/yr | +| Pumps & fans | 483.3 kWh/yr | +| Lighting | 222.4 kWh/yr | +| CO₂ | 1,501.8 kg/yr | +| Heat transfer coefficient | 112.11 W/K | + +**Heat-loss element breakdown (W/K):** walls 12.60 · floor 8.82 · roof 0 · party wall 0 · +windows 20.68 · doors 2.59 · thermal bridging 12.75 · infiltration 54.68 → total HTC 112.11. + +> **🔸 Assessor-only fields** (EPC can't supply — a human must set them): +> stories-in-block & corridor type (Flats), per-window geometry rows (Openings), +> boiler PCDB reference 17929 & control code 2110 via their search dialogs +> (Space Heating), MV unit selection (Ventilation), water-heating code dialog. diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10092973954/elmhurst_summary.pdf b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10092973954/elmhurst_summary.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c48e5752e147d8901e3612a49967339bb94a0ab1 GIT binary patch literal 76883 zcmeF)1ymeCqA=3Si0y-dzPXWsBcrmDzT;Cyq^uruzz8xkbTlPqVPayG zG%_+8%GSo(=rK!NjPiO` zkMS@uikn$F8rd_7Tk1I)i5eN$7#cCk8d;k>M$FE^!o|<;;An58XNB+~U|$>FK}90w z{wwlDe;LR3J=Z`dG)uHqyS;FN{;rNa*X|Fxg2KWTD24?1`i{?pv4hAE39?=iY&B`T z$etKCFC1^o1Z%7-sZQ*=dp%=07YlePFkV#p?NU|Em>{_)$NxXP+LycJdGFoU&rOtB zZR$x;n(@Pf5`{Mz-q(3T*rO#I_VKv!tv?Fm9R7e)3c&=2H0*!l##ifa21nOAo~8Cl zlcI}!?+&Q++=Iy=Cx`Cnpn17TA!JLb^FcY6S&#F z0+~I&%A~PaZ(i8h@d~SS;=(N0-%H>=o!qTnJ+8?p@p6TrI|ocq;CSJL}fMT-0? zVRz}@$XLh*iTx~r?Pli8l^uooiX{cg&6VuJ8Ga$`JfP(W$-f3^PEk0tPI4)U|LgoUe zNzqcR*O5!B=Em|P-0<83Z&;_b)gc$SaR{x!9M`tN{wH4A`}Z*EuY%iFg9eZE5`~uJZRd-Ys7GU*?=IS_Qw5&r@KozFC(Pze!KSg zXtYh*(87c=?3`K8))}Sw#?m}c>1OM-_xwiZ`G>vM)97ZEc_g#tSMrH!3$CNAwP)s> z{!#eE-$u=@xP5dW6j?Hv;c~$o*ZED`(>Tkyi53>PT^MdJ8{SRYf(|`X9rKD2yka^v zs0F+4uG_HIB_6b#+8;{JOG+5O*{E}5=Y0)xB2Ry1`4KfIi@#Se5_JeCXYv7hpajA> zde+bQn;K6V0)?%Q<{3wA%>o^a$6H94pOOR5t znnZ&nx3_7!_^UU@uUex7&2kc2_4+hgNskzJ+)Z3Qau`Q~$|Uy0$dQm6PTba=9-!n@ zJF>U%GGz(Fn;iFMX%$@_ZamIQFrdkk($&H9yKj&nqPp(EY;4uTe9Wq|(9Y$$ZkHagm>U<{%7d3clZv5Dae2e_ zk*D|U)`y2Px;@e8I!X$jZi;U_b@%)F+1vTE;@~OgQg&;nbERd*wlK)V#Cm4?!*#>Y zlU^MxSf^=cg8C0hA;+aHF(8LNT1%q~KMy?VKrO6!a`7+Z_m2C5f<>{QzUBfo5UX*q z>Wc(WlIShZvG;>RRZm%V#nc1T$oq#39a5jqm8PK|WOyM;0ST#WvV5lyP{lZ@44D0l zqE6lml@7(7zBuXyw>-*?~B0(>o>O9+^A;u3WG!7)Y*E3h1XT*t)3TvjPv;?$=$n ze~n`lmg-u|?eP6__E_R3TJ^p)utQ3B*9B#&Et~kVE@+!y)PHnWPc(R}il^d|;UO!> z+KtPKaO*6^oA(?w=#AvRt>|*zMA^Qn8hoI+ z1G^QR_KK>=VD-H!`~KOi4dc~Keja&j)Q?`Bn>-U`?3;sA1V0=KTRg_R0a|Cq7R(7W zf`IAi3>6X^T!|39ffE}21!dDp@V;yaw>(!L-d+SHU$2gp8*s5}+BSb!2uM(`Pej@KjCDaS*uv3)E}ltE%c>pQ?(d)6C7qj>H?kq2YE`A)q1p}Ld=8En8?XwJc$o-*nESR=HWV@1i7p`vMvph!+>{x4+fSStp-^XLu zFbHhU+Mwf2)lnYP#25`popE-dGN}D8BLQXLIIx3udH1hF9s8Mvoy-iQH^C(MKb*K< z^cD415ixt|*1R_-!u4k|!+m`+ox`#3A?#y(db2mAAH%0=PmczPSujsRC0Tc@D9|dH zY~c0WTLvt z?hkB;Y`cp*%8?KAL%t#P@?n-)FpD*ot4i++GO_4hE)vm73oMBsj zY(z8d?@NyZ<%$ z7<=Y9{RU>{P%`rETzBHH%HHb?{!9+z0FW6*Sxr!E?GxIXMCHzC}!T2``RXAz-q+w5(REr;i8whv|8|55fzZ#Nbma&|vHrqgwOWSCZ2x{q4+Y8oPqUF|GHV#lBX|EFPFOEa!y^)g@c)pwbIN*O%R`|MJJeuAjrBNTEb?!HxLJtnOI3PHZ0e=SZ z|3*yFobE5?i$7uD^=(v3qX(DgR~Z(C&P(vWS3FS{JKr9azV(;88cRN*Nr)qUG;d9^qCSQ8PX-x6rw8k$>3iYCfBE68m*59at*= z)=S+XY@lB{Fh-?YI(r9y97QMD6)Uov`cwz9c)?5xC0ilsDd)`ffnoF2hxXIyU*RzW zk0)*qG8PFpFnx%=@1|DgNO8^GLwx)R-QbIb?RTi7Yfz-;>yJyyR7REcIE{duxHrocJmV=WZB$pt$%da8}RhBnDU$4E~$U8n#QuWBErtB+P zcRK%4kn!2u0ar&_V3dyXH{2zPOVg!5Sf9VQMb&ukPSI*S%7rJ-8NQb$N%TY;`&CvZ z{Cn5Vj2fA@J>sw)b?gxiNqZ^|k4mJRVo%Im6}t`U!9m`> ziX1l&atV0I;nv>HJyDBkcRRPI6lakW{JTC2{iFQ-h*($Eb=@*UssLf+tQJX!q0o)a z^}JxF(@1=ToEm@9XnrTwH4C0$Vg~DeAKab_RVKFaUD!Q~>tkOAnFnPxeRT5NWiU>4 zI&;%E@NKg^dDgCHDObSTBA>DL< zQc~n#k<5AO6%y4p*f}14B?Q(FPtoUcA|@pigm2-8>mR8*+O%oD=hoDuWbu6ORaCaF zHzTn5OuhQGI<$i>ryk3TbjyZCC>o+yNE{pA3zH8*sF8?nJ=pQ?po3q){^J)e?VD7c zi8%yJMjAFCA9p&%?L!~1iD44f+74#-yiXDskO#jDlj+`Rm|fjfUzNP^PEDUUkwxaMAYDacFE8N$@$cN|1I~y+xeb(sMn(8eMr|Ie%$GADbqt`W$ zeO@ccHrC*dMj2DPSQ*Ac{x^c`U5VgpDku2E-iMM>u;bNgG*0oZ25+3l_T$~u+9++V z=$T>n7T33+1#Bz$UR?;3E@>!d1?ik-L z%c<`41Gy>PacD!NaKw8SB5oJ>fyC3ylKFZsgX^XOUTtiQs~T$-P~hh;#8G>$VT#L^R4iVlg^mnpt~k5yMa14Z^ulR%_LRgeOU27bvkWJ&g{j zmU5JShTOhFk~%RKbfcNQz(-7yb-K2#W5lteCTy2>?MFjTTZi=CsYJwU~t#t^?-eYFjP|4vj9lU*V*Ag3T0YGph_ z*>ouT;ISf?l7a!7nqM$b&F7bPZMvd^-|aXN+%Xt^%`(di6F$p6ulHSxQqzh5lA7~S z-2679tbw%F7mE5@oNYw`{vwXQwoBw9|GPlYQA7vE3Ra5Gr+OXPOZ@fd-67hu@HX10 zovG@8Ow0tD5eBN_R~?l~!Yf(4q|_!v9-sYAcUalAX++mMF;>P85oJb>rj1lx#+&i9 zkBvpfVg#_&%c4v&9{bb^@ddudTNXPcZ%0VTGJRZfRd{n2Cguf4DldmlG1%x3#rr~jnJpS7)n&?91_ zFU#jc1#}skI9v}uygy2J6}F~zyqt{siCPq84QP`v*5 zv0%fO@~#USFM?W72xt;XCA#u@&09cmSC;%M)`}AXR!*e5`DdvwG1A43#JI{Qs&)mm zy*Y0M*$emg0tX}Wdf-XVoG+EP`rAGkx;fQ34$0AK^1X^F-hGb&k-g!FlS!*FSu~-T^!?NBLC-qac2F@OF->bedu|*z^YMpg095; zVeKjk9R1khLB#~oBwv%-ZNfl?mM8=CRNR^ujmFgeBOSD7NHe*YD76>Y)1Y`0#JzzA z?9v9`hA!jS7yjF-6UdMK?@usD3~I1~oV_z~sE`i#nhGeA3BC{D=&wtjHtPL8ID`aZ z3}GY}*#vb$4umqHs=Ne*tPhn&m`~Dj+|-Cn4c$)WJ;h+ z^mY{C+W2nCs*lf|AV^W3u}blFj*?J(ZS;taR4PX#kgReBukum#{LgwQn~oN+g_CO;~tggMFRSD#00r+v5?&;2rDLIhg|kO5u*uIxVpwD z=+&o;3Vudj%dqKT37dS><#t*(fxZW=%)z3yrp7|D8ScBs_Fy@Fis+ZGU4EiJg z1$}`&O1@S&k+1zc_D{DgZ2lrWLC2(i)*?AWxWd8uOOZi|uCW8LQx%j-KL`w_e+XM# z)ABRqAaqghAWej96IQl8i*q>OJBD{kkrYHP+1~Plfu`+|SYHU~evd(Ql<=H<1Rjmp zG3w=yUoOsq{;kv8W27|hLz@sp+UV;A{y3yqqRP>F_n}&R&c5B|3cQGe{rv-hR$eFB z@38Qg%!-Tl_O?f`C9Gv04pQ4tVg4e-TlM8H*eq^fHC0EDB$wc+yC5g!bH) zhuEwiE%?QqMlxVyu~iFKV={XkX{n88HMLa*IEi4Fdb_u_3c>V0Ptq+@2w=W48lay? zz~IRrUYni=|CbI<(A@IFb4ir?X9$l&+xxD+rKtE{Wwzn&kavA|AXOaPBwO? z|1>-e>-c6eemui!I!>;_qk%ibWwMb+KFu&Pc1mfF%Q|L`yf1-XJ)rRtL9NW?J!U;Z zp>R28nQtQo*@qUGS5Q1cWx+X9^<{~#;h#T8f*ZvSW4pZd7eTr2e_(ZZ@VLB#i4J}N zjetp|m?h}@_Zw~gA<4O#VMVMw+K33KcwBeW>U?U5w5vSY=m@ANYKfvRUy77lnM=)6 z)>Fzj*S*6eM4QWK;A1DFISi?5ePGM*@ngrVXs9b2i~mx#$;`sS!biGthCR1+RVTR= z*CLQSZo$zsTse0Br7Wnttc;0^i|ZW=KMPw%2kYS0Sl@27%>JnKTIPzv#=he|)t;)X zygUMw-|}*HuHAc%ALv2CGcYAUG%Jns+?u*qc;teqXfRykVd81rrjWq{+*F`jzQx%lywT$oJ)4-uE> zqL9F8JEjOcu!ls_<5ux^QQoPQsMk|sPfc!Qf6i%huSAv%z5nGs=6zVCJpYj z)G-r!nG(Ww(fdN7Pz}tVc90-F0^@Gc0WYJ2N(j?U3Hgq8s0N#Ob!&=9+E;v1=*}o~ z5R`bJ%|K*`-wuEHS`&z4t4GVG0J9Nva@zCO3Y>fa^P3!`P*eo{Lc3rZfy|^}!J=-k!Qbj-v$*{1!qXG*0qdVW2<) zXw&6djcSjye_){JO;P>(>?y44$)?rCD<3RjA~%rhr1|-XQr#~ZsD&aI=WAoCJv<}? zD6huG)z#IL20z*cR+3)x%gW+ww~>$E8{C^sDok_z2|3~;$xa4buC1x|ux&Lpr`g%> z?(VWCwzdk8D)Veg&Jf%YM&(uM1jjO+RC~^hHsAncw5-RVipMjdn z%4|0Wy*Lwxznq?)%E-uE)@L<-USD5N*x1nEsBbF$JhZu3=Y&|kd|hDcXs3nw!6O)a zgL(B2<60b|j?$m>}0WkMPgo3x^doTBVh_s=`{g zcMPTw17~BHaPu|Ws2y_)O-+rgO5GZ9aq%2&JraSovb{`JkAB1Jg=m@}&-PT*3GSJ+0SVc85R%ynj{{}ji9j2_Xy~KC8$)q zHz81;?eOs2JM9sx!iG<61H9T$PAeqZH2FWeC!RHKo@uoDk-L~{f_QgY+`DS8p~)mB zzRv{QOto`X?_;+VwS06K{4D>r{q1Faal!^RhRABt8_ok4p~bgH8Ux{S-&t6zzYmjS zm*v%Iv=!y$Q5+!zhD|P@l(17^pMIi6vfwgSJw-^pQ zVgY8My{Ub>TU)yxvR?}w3hI5|SIXzHWqz0+w>W9`Kn-i?iU#vTnE41>(a8E z(+csCCa5NgUp$h~&aKYS>`n9+9~seeNMmFMAnXVi2(Ms1bM>AfV)yZbttaSv^U*W6}GA!A`b zdb@QiVT`$EZ4ogcaRw5u0k6?ovxLDU==x0&eF3bPa$yXd-bFgsk&1`x?VDru$W}BD zlchUSA+V1Z40wWi250_a-=**k6eUemS{x=WA-X-u)%CbV0CWHbM#VvVIH>I5rvR&i z%L?0^yR+KFdRU@ugcgPJeeuD;LHHSxCr$12Mb$-rxa@M4qJ574q%SQh0!)YxB_*Ydj5J#4 z$&6bJFI(M<~r^87knTm?B4 zi-1!h@4Cn|Urid33Z3cwC3S92kt3moO%vx8kg$UGO_&&vmP8Xh0&} zHZ{-2OsPbc|D@g$uf5H1``PK#Y;0^);GH9vc44Pr(eJabk$ru=&l zAAdORi0#bjEF3w!>FzoQk~p*h?xHBKtDBh_ePNQH213(7K0miY*5>stQXV)Zbb_Q= zaOtWZ7ratJr;sVK)zM14#-@S62z4>kH|+245&9sFpO&6p^sP8&dTPhid{Sjnk|p+- zhLojJ1q3MQYKRxsI07vGYGp}R58lZ(@KBZ+uwmH!2kuF?fVn%WO~D-Up2wOGAQrIYs|3l)iLun!EN325bZVE*7gQJbCWgP z%dX*}Zqx|G<%SrGR|Ur9RmmV3eQ=>EBS{8?V%ckg>0py!5B5qJ)r67xhvSgM!q0t6h$wi++3Dq65YW}#82y@T3^>v zpsF%KF8lGl4d!N+>zv3?ebgyQWw59Nm5ge2cFAx@8tKmuB$y1d$h9>d3c{BtRMTIy=`XYw&jpi z=%nfF?(}7f`rxVtr?-Ytj0T>r+%ko_8PkWA=%VFP{^1h*p`yZm@>3LtFj)l>9Hc+o z$SuJ2sLRPH)Xt(oT25+wawK*c%QQAK5wb>i)w-00Sc53X?)0I`@77bwCmm{bh?WU| zz)iWq+{$v5-3hjAvC{Akwy=E1RhH*If>T!BTTtM{_cWT*3bk?dsAs80Iu`jA#;ao{ zT3Q;8L3dQchS2cfALT!GcK6@%pf?DAR8&%tP4Eo|_1?@@cNIN0NP+G!EDdeys`2sC zgQU-f-VnVB63_A8D5jl<_7=OI-QUFeVdtTly5oJ6L7Ns)^tBc19j$%9L7Iuy)DV&V z?>(zjh#*bQWjg;u<#Hw>o|H}|8yb|Eg*o$g2bJb9zLuif7nnJpK*5K8FNQQz)Tvgm z%(UqIkB{xj5I?_hO1QWWF4h}nsfq>(Iyg8qy5{877D|bkpR+|^v3IDK6WV?AR*SB1 zmwmhOEPPz(dJ_urSOnbEHc_*u6IBWoytLEHv){X#z80+ytuBLgRaJZzNK8h;6EN1| zds&@7?S%tI|2Z_k%E5$yj1rAsSXekRHZs5Q8;Oc7wzZ(J6b915aO5chwtM4N60y(E z4qL4LK;BLp*_AI;a+&`5cHlzBPes&ydP#v}GEKD*Rr1x+W+a!k)I&THHa7MkG}JIb zx(hvork8eU4r2x5r+lp~f3UH^?%LATyc;|1(6A5asnI+X&^n3)K zy(1^5*f2EtD%Xnc&p}gWQR07QUeaW#^3%OF@^UJ9t2!qFE85%S1ZM!v0ITSe`RkqS zvGlZfNoz2V%`F(Tj0d@WiErxc<+V%o!^1T|cc85we}DaAfA-`z`Y{RA=XzWVE4{*Z zkjKtwTalBKlkXSrg{GKn1;e)+WA=D>aVj@A(9K`pl5^wQL9tR&^3Wps2vU*uKC9Qz z)cEN-KI_O+eIE+FYvPkh*6!Z=ecSBjByq9wVTE9Z*-VL~(fIg+^B%9rMNPFBtK(xr zAcfXTjk<7=w4|huP<&1+IcH1^exkt(KjKuj)9QmjuANN_{7iUgo1@~Z6I-T+t{vO4 ziz{ZU<$c}$h7Eo+fuccVvB__l-EKJcVyXg-cdjL(Gg9*MOLo_nLnb90xfT!EDVS2X z&CGtgxrz1~v9y*p%*}T#q<|^OD>1E ze6f(;;R^!;wW8+GQ;UbMmQNlVGMYLj(Q3TB%X6pEy`1pQT2hicGt6uoI|!zzO--8yboPBa#9V^&2OhQq@orrWsZl<&yj;oVH9v24-e?b;C?U`#+a-xZA?U*coFrfmaztvGwS%O77c z2Ee|0{6#;r!a~D_7_u_N!h*7>tvJ)olR8at;VB9FZ$5kTC%+PL__=g1B7_YB&P+41>}yaZN^ zIXxkp&&?Y501v6TW>gR&GBR@E$^wjP0l6MX)ms^Cx9=os^GgcAnokqkKd*7H2Q z%u3@zOz%?H(2$Ie9$86R3_KqX=7tWKHrm`>WTSn+`gvN~XjvUk)|m4kar3%5y-5av z=i|wVeV~d<DjPK7EDoK-IQRWCqV|!n$2R4r!jQc5ic)9XS=R?bhKT=oMDXNoY?5 z{fXW3o#Otr?@MD!%#$6y{HMp7;@mC{t6H!6`}@xvU0jad1%7H9S5@`cOH53FdigTl z)7wX9(GOvyT5@hW_*Qb&9`RYvM_mHFde44-cJ}eH`LXe7c3xgji4m&ylaq?j==*Q4 zX(miuz7+q!^v&L(K`bOo?CdwVs^T?Bx?9mHX;z||zkDndQQnT0?qjJqPA)D%fuCOO zV%~b)ZOIQx=8{*$Hj1tEBqZbFb}Tx4{~iJ#B7gCjL4FWS2D)C(a=TeyL)iHL)p z?TuyA!=)8j%D_+x3JTJpR1^8NJ}%sKGxF+ zCkTB>l{n^$tPuA#;=7+b&In`^wBnH6z+~$x7U~}Ax|w&A5b*BK-lrbn;djovYIb_j z*%{uhrb)6JONgxR<>195;Udc9U@k)3}&PIM*Y|7KaH;4i66v4fXY{_u3dQ zHn&192|j}3&qT$RlaohALBYnsO2td<&}t@mjrP%|W2r`w>etvrA!Jc^#z%4Kx5NGO zR4>PRw6ws$oQ{rxq+%^Kc@LH3LhZh0Ld17hdAXJ9|3&&i^jVz0 z?~03K7M({50dJP$JqH6wSx(z~KU|WRak8&{Y^a-)jZ39MiI5l83UjgfbyiVrh?$3G zeGIP$wCy_acwU1Z^mppqqc1#%n>);qKAGa?X`kDa&RMIM75rlGI~Kdc3AsV>M#H0{ z`Z+dJv!|EpYvC=4wAO`=_%@@%U*FPh6IhRP|`=y039Lm1O-Xek@hl4(j z)?jYY$Ku`}T(gf(K?x%sjE^VF7oVfer(O`(nCz~h6XBq8#CX+jGCj6>Bp{U>H9KoD zFd=K!y3t+n=0e3g2KsW{;w30{k#G*x=bShoTn92#UfXT>DD~vz$J<3}vRwuEoV=Wj z#0u1Qk#^&*Jmj^nb)?5b8`u-hb-@Se00tx1&H2B2E+&(lQx%R}1I1C}|#qBNm!-nBzOQF>VqQ{ob zF|lQM|HvroF74L>BGig?*9z@=qW)xA2|Zn|O-VyBekdYl%#fCvQs^e}syWfKmfBUf zZ{j6$-_kCoUb%En5P9R?Hs!3|Wt~O~s5dzTdpjzR84L?=e;y1TuJ@?pk$fhEGWO|6 z?qo`Dk+?Zt2e(%u1vK)0gapTrr01u!?}fN+5ZW{D5M@RDjt`dMe)J6J)xsDwkY{b0 zpMr!7p-XCrKgUsr+BWhwt`H5++Z{s@|5(D{%)u6J3-{wXypR~0yIS=gtADjy)`z2D ze#a4oURNlLc!IcRWtL%mVC{(Gf&&VGr|InM!PQGNltyy&h@0yoV0i|~F`yMqailcS zl9Lj;>Rp&%pglbpT+VtfPfbG?*X;UH=b3E534&mG`$SJaEJhd=V{%%@0>!9@9-nRv zA9HJekMFX^t`e~cNDpjhXKiFV=FPXU>Qkw{+xc$G^X#!-vrxgq%Tin02zigK!o0Bb zShJGBTZakcroVSoi955@3y50AvIOPTD2Eltc?8TS$eR0E!!nzH!`j;lptXqrals)t z6)y^t?VPM5`i54My6HZ)J}LwH

C7swWnW$Rl(Frzx49TNl%draFYq+!r|;HZMl~ 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 literal 0 HcmV?d00001 diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10092973954/elmhurst_worksheet.pdf b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10092973954/elmhurst_worksheet.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7f785404cfd3efc7a296fb34bec7f9f4c5ba6398 GIT binary patch literal 23833 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


_{RJ{Z79LjVqN|;YH@w|2+%rag?*x|I zJ@I}%J8EQveBXhBZu&NvdGBz@dwQhKQMjj~JrGcDOMgpR?;nBtttsac@0;pdsto>l zUA&#rAMwEWBnWnQwd(Mw(jxTeJr;$)uN=G9tr_uLWN%8cit+fuIvrHKjDFBcKtLwP zaF!AlC@MBYW+d}dLs&hs;dIVRT?Un!j+doEh8!@Ix7GA!q8uPFXGYu?$iB&**^LLr zY})qKd9)~}_ET{=SG0R_S=B8%1K`=FwA|0b+og`!yv?85Z%!dFoD$m=m^@~^@Jl!+ z2ccy^OlchQrno)3=WStA!=!skOOKkDxwI?S%UZNxhf%SjZ0@$0ldGt-fp){ihq1z} za7sE3p;|rG)yKQ&H+*4rL>~b1uto47lR7<78=<)ZV7Yit^IEYybz<3_MnhZLK{y=d zU@={|{x%{~}KQpQ?=+{$2k6|139VVrA#} zPZ{%u>qhf@_qEdQyah7m@qlh6#&*qCkqz=!-9}Z{nf5HQNkhCajiTel@fzLh3=pb_ zlyn4pb5*qKkWfUx(EyNBzuy<{n}2)*^k?5!#l(k^Ec4QV^+TZXpo2^_Q$iNpbIdS6 zUl%RV&_{~)-a^;p-dkKZfo&*{a%`^>#j)FsKJ#$Fz(Hs`hmSaR71LyP7czM9cqS+N z<6~fM4dLsP6ZNS47calX+B@HFPtIW=(f34!oGAB^Aj!3k*5!V(wFYY;~#Xd0PIs)_~6dr{4>NJk>Qr6EjsY7M^8oEdsbOxH&` z$hHzN%_4`Nk7|l$H*!HN|EM5=k>67^*u-CAXjNXX7|fErB7Yk-*%YdDM7m4Q1WcUGe-{Ui}$k_C5zFHwLM;$ zW0uzqJ2k+wlAYFMNHMj3UYWjDjq~&-n?OS+Ro`Kj-<$SGjbLTWm_eig+kvOq)-t)W zo)Im~8C5#xDp5QeVf>W7(iY#3hfgqp) z+_772x^~wSOzILi3u7z`-0NV8EGcJfhB{@ASKZYNiiY8)qD{Na%T-&G24(6^CAeuaLkN3X!WB~7p*K@$5j~f4jUQ$DW?1AxOvzKm*$x}L)sj5U@_=Vq*yl6S_h{& z4(G2i4J&`BBW-Bx8IZx<&#`9?X!7l7arPh2d^UA)fHO%lOA)g?F%2tFJU}EVu!ix+ zz{lb<$9z?$Umuu`9gEe+x}j})$@Xd);*ZHq4P;ps66Yx=n!}dnbO1q-|8`;3J_tsG*H+^9mqOJET}OkSkznU-X(z_j?^C^PwVpXcsV1vJPt0M zmT1v3BI+$|9_I0E-98yTD!@7|ZtlF_RfM*9cM3y|^0oea>wlC>#f+~BKA)O8u-~#5 zjYhgE?{^Ue*L(J0;HxBo;jNW$L4#95y-3`dv)3UDJzv*4OS+dst6_?&TOlDLd6AI~ z1&fe?>@Qc`Rv5hF84 zGjLWczORE-@saR#Ch?$X2O1p6D6ZN9os!A~7lRAUi(H66L)xS;b`@1v9b7yQ-EAbz za29It2eg8SIVdZ)|!ENN=@ zmyG;cuZP3^3*YhK>Ewg%OX3ad=*Nop2t=-fWuL$XMM=_%azFPLO-WWE9w;*GCWVJv zwwijx?6kyWsSrWB8oLIhg@2)AfF+?DY#B?E6LIq|4JpbGc8A z7>q>jXy5&E6W*IIh{6?BVT7IOXR;3f_ee?C)HI_rzSj!XyxeEzE7wxKMM#{A{Rj1$j8&`I(7uS6tKcK>PZ>w5S2% z{hLvCZbtZ6ZTQ&1J&jZ~OYgFzf=P!qElmkc%PMH;Z<3#rrT2ze!AYDcXQWSk6vC-o z5Yj)+U=y|ETO@3Vgc@B{Xy+3`Bed!}x zG52gu<8cu4A&;bFn%PXx7OCq0C@GKcMi_xIT&=cwAcmj&tG^Pzrf3zmV%Jo-U^A}= zaDUf66k?Vg&4m6630!6KzwPI&Yubud#8`qF`{F6t#=il?_C5+Ic zg)*Tow|`XGChHGq%SQd2fs=Dxup&22+vs_(b$7rao47teG0FOL9*v@dajJ=N2 zTk@Q1;O}?VjG3rH4n3UcBZi*!#aGof7R*b047$GOmC+~V7+S2e0SFZ}&TOcSJ$Z1^ z_C3(H2KI;$L<=_DaVc#Mz~|8P`|W8_*i}VhUs?c zTY~9qv}hwgPJXr^(2ocA%49CWft3GBBSTk=U!txQ8jV^40&BEm<74g8OF#LEZ3|VR zswP=ZAxwfKR!UiS0)0`puIDcorVbDba}a>Q^cQNn_T^Yhu#0t zA126u0_e+AFztrkN{Hj>w&)`GK2yN)f+b#(iAm`%}GD*i;&j`6@T*WV7NB(H5&=uti zGdZj0ps4l;2WKE;eAl6SNTQE_8b_8(QMMe2pR0;%S}cjx&$M0~dNkTJ!Az|HeU=}2}ja2WZ;D3y-b?U6YImZ&p!nF=jN z*zAUQ$e*`KX0m;Bf2I3?Pq%W`4d2`SUf20jeZ8=Q3{20B`E#fGv8&ws4eprjfxm@NG=J&^ca$_wl;&l0JRwI$rEQiGZVAV0evIReP+r1EaDjsu_-qwc z+Z772ld7e@aAJ{tl_#Lcw<;5lRrf2+;$n)iC@pAzR(~dgO+TA8Y65Dh z!=Xkum%jI)o&kadAS>Xx*umvo9C%;vf&&E6q)Qzx`-}k7cd+~kXOm9Rm2(gzBWvI( zjV&cNBC{cU@e4y>dLBXTADIos3R{DQFzE1nAcX5Uba_qVU-z8x|JMStX>XD0OB}oY3V_FQ^84kJj0~|%}PNN66=A?jB#gD zu}pD+rfkqLJ#qSUEZl#Q!tQbvq5X)$6f!qH%<=;aLi+sc*wp~A&FKr?KEXQ3wv zz9V4snJCI0tL}2z0_SPB-FJ@T}e`ni~XBui7N?h#{N&JFo1D(dg>x6%&gEU^! zPf#E65VEwoB>N_drbm4HBkE9U-rzYti5jn@P0BS#Ct+fmNXkMytsi9-SOO~KNQJdp zEKdc(gcqCiaSu1g`wEH74EY0UBW_Z&O%~dFCr5{z<1vNiTGCd>X@!A?b?j-4OAjWy zPrS$!yH9|TSG5CIzv<2d&qntGBpNJgemLilm<_BTiP3`YbirMAIkj){@-mZGt;yFXYst0)Atdi?l-kbQWZtCri^D|72eSp zGzwDk^007t19&NY38LY^K9KsC>wA|Ocpzx0rP&l}cO6nTwSl$M5oh16g~IFUp7`J1 z(R?R8kB|4MlC8tx_my^0s0wYvVs?Xohj5$04%db1A(<6h(+R6NnvTcEY<0JCsv<~8pJcse#NvhUuS-HkG>BpZXd?qX#34sCn6 zx(wOIhAT%Kir)ELwB)+bpsE@)8_ACPby}=iW%Nt>W6R~nxvX~evLVBpU+!Dx(#%$S zZI%M-yhzS%;UUKYW-3Wyy94bHG8H4k2jTU_AEhXX`400p>M$_(AtRa_?r0A;tYCV> zlHZr;0~d!=JxqQLgeEs=(A!iS7g%&EJrRy+H)m!_h6l}>TU~|;JDUg8SrSAqPi8#H z{Nn5ZzZQTbqoI~%7+7bf$PnbTn4;$w)flC}k!5P#b-gzQ>|1RcQcE1vs}c#Y&ILh| z)~|2g%;*%WciL3N8yPap7C6L9P%C>J4Z5efEw=*u65gAQmI?Y)W*8TIq;X@~-&jE= z;(8mt(1)8SQlVpv9i_!$Tz9a98?8?tx&1!k7soxynqfV!@#VF-rp@7P4dq)XOtO}~ z%TQ-n$||D{H;NAHX`B%3zMzEx7?Hl3MqaT;AydXD#;QMqu@ei@>Tdg*K2lt!o-Fht*WLcb&xB^fHRC}QOR$B;-4 zkvwJHP9rd>)1{kT+{J;&q1VkdN)3iq9)ey`4Y?1FI0kC0A3APK_nhc*>e;Nfy{L9> z(cV>Hy!=rws@;+WagycnL*@;-a-6fBuN}HFY0(UMFFgkg?%fa4)06YU-f1XLN3WtI zZiog*1?ddoC}D>2D4nyusor7FEFO}PD zd4DfUMd>9-{CqOaIiEWG_&gp%PP^Kf$MuhFyy5m$Qu^ws;SiOvqpGUkWfTey2%PFVG$$<5Nd!{dj_uESAHkH{C{7lT)JiD)$g3cFeJ?~{ZiCagQXp3m^@ z~=&>jhkFelSLVG z*E;9a2?*{L_Nmit=nnCQNxxUt-tMz{%tUv0SgUUCIuQ+e_cPomSkoJo5xz5|cDj!s z=w%UF?leFE?oH3DT@mvRy*zZmL_tZ|OF}Lc5|3Ys6EQHOoYCOphHCZ*k;CH#WYKXf z2){s(vA8-+w*pZ&GNgl@B@n_h5$uH@qHrSgh9lV9#Oie)|wL zEyC(TL4MabTwHetxGsP=uCi7>Fh*pZbcx;)LL-8r^5J2mEC0V*xyqn8)Fq1r4;I`V z26txy6JT(H1$PJu&M*+%Ef5BWAcO0m!NU+F*x(itNQ!ZeYy{fRH-lt-kbCF;;|#O@&}x(0T;Z=RiBZ)9}&J@oJsH|^F_Z@EJ%`M zCC6dwc`yf&OQ#z;l$C^J8O$pyyon)jOgyfvp;Y$+lI9Hh@*^*;=!Om{lAOKeWvsY` z!#I@AAft&Y$1u1-Ut1em8?GMZ!i|mFN{!W|5mJCP`!)AAq`Vo$W*5(I9#NZrs-8An z&zF8p@fk}GA^^kH2V0FBLN&?%(AX=lP>*nFEe7m{@fOnt=vSfGONt_Fq2;>Z@*dymP=vCvXm5Ur$-PGIzNy*uPqrCzE3@IEo$pDduGV z!gU^dR%sm=l+x@#mP0=&EvCG;?c=$W|F+6U`it5qW3YU5AYt|IEqf}R@ak>00Zy8s zzz&lO`IZ;+=8{DLtKVwpOb)4ZGFHS(391`Tdhvm3Q-O zEVYXWvId~NrseU$XsJJxyy;-)+<;Jr%~n@Wa+uR+5OtlhWyg@bD<#3?*?Vf7KGB@K z@+ehf|Kx$)@I^Z*%Ls%hxi=4K%Y+`Ff|ZptxCG=vA!=i8dD>Ze^-Xjj*IAVR7DDeJ z=!2^dal@<@29z$9E=+*vR8_?%L%RpY8sE=ZU^7x#e*w*|d;65YF{@#@Iubc1K;9AI zOq11wwmf%+M#e`M@#x4SPUqfLh*|p7=XrRabBgjIprW+5idv^?wa-*$*{FkiHP#&L zAL+FFPIlqRCSC>Mha{>Cck87;vBTf{+nwJ$Y+jjX~|6l38EBsl_c(>&8zZhFsbREIkgR9nmWG+ z1CR5LO+JTXX9y%(X~AgnVWUPLgSCkI@-hrHKwEFAF6L+bz4W;h5DSFN1s#gx8#K;G zOrXO{@D#7#El=Q2eBB9*+n&dBFTN0lQ*OwgpFUf1S6cBJjlpJOaU|=?CPwwi^pkc; zB#Nr(-`ILx2mKzou%Vd zlC;jzQxv971J&%-$i43QX+rK1kU(Yau_i1{Z)`EqLq=*h&hC_SvS1T!)nq%kkLLl`Bh_XC6QDN{05S zpQmZ_yexpPep~LHfX1fMg=E-X_DluT9Jj150QFa84 z@?vAdc$&pf>enuXv3Z(v_{ltP&cfcQWr1j|P}YH!cGBgW3fb!?1nd}5jH<_W3lqh+LCGc&iHrVi+9WjIxJl1Gk=`&e8NWn%2XQ9QvqjLb z6fX(W&fdEw*=_YK$kR|K4w%Xz*q$f+3_zMc;kK}Nn`7u&C;qPC13=zB>zO1VCxMre z9Os$@VEDnvii~5SV9o)}T!ZD~B=CK0Yb7;Qr2i_cZ`fXlcJ7rczyt@YIBkg=B|>b7 zpib-$Ycfz6v!A}EC6Gq$E*D_&YfZs5g6qyOAs(5PAAl5I@6-oZI_5Hnzq48+ly_)j z$+1b#ljm*Fz>y`Y*A97Al7fA$8z&JHm0s^rMrW?s(6_RXL)G_DGykw4u zE1fZMw)!QuY{la=+4*CzkVnl@u^ld&EU-i(jhjWhvAYHCFQTu}(`_%s3^~y?%a}#` zk~|%i*li?xcigf%8PqOVlBxr|CNGAeA9Oc4V4oEsE2+gG_;D3uRbm!|ko6{izBNtS zW5_1hrSG9Nm_9_i?tzcUlz`=(vfF>@#3>UYgPT(KF46KUaVGcEfaB89LFB1lS!zjq z*bVnZOxEzCq%wV2#w){%LRmGEz9>>oKl=Vg6eVKv)1T>(wRygDF_6BkD%sQ#cyr{0 z6y%d?&y!`pgH{RkYnE{u!+c=cp1Bi_vM1Y%nT@~J@5>sXB;yPEe(ffGB|Qu8X|`no zYzvKr;6`~b|Uhr~ij3xt)`n;^L0lJjagmj(_i2SYR@Huarqm-^Zzf7BXr^vsD5*S;3A;Bn0!P zE+yo#G-Uyv!f9~BCG-Lg3heh{J$8ddKIk=zM4yP=GL+nlZxAC;E1tXtm|v z^>p@e#+4m~=bmLxA{H~Pm}=C&SHL0FyxUl&Z}h7_@hL3f?48B3@7B&8ZLGOhkAZD~ z?V{PaG#>_?9B6gsXI0YtXz3b%eU1d->T^oQ$aRP=@pc}ehVLJz-J;-?k5}U8Y{Fi6 zA5;I&)^84MdUq0iIB7z(fZlr)fDKJ&C4>+D@KC(!QRiB{q@#D6BE+1NPjKgKLfoO_z9(-&uEKAX%!;ZqW?M(u zEUW{_xo$?h8V2zcW@i5gU|3kwt#1{=J@acsPh%z~qMxo6x5T|OX1_bWYQenh&C$WW zlAHR2emSFa`#+2){{JMyg#T}vVgGdh-^LRnQc{xtjl~}`TY@Y}kp)c{txZ)nkS+`U z-jOciqwmn?h$$MAbxuWGo3{JpsROZ&p31m*Id)=SkWpD0w?j~%6bfPZM z2WHv#%I)8C&hT|{?X6hMO-y(ELEB77<#X?>WJJ7{;gq`}4VU3HWmnF1>UN!8QPBJ2 zSf3-`W5P~!@YqnLHFn=E1GX4NE-$8OjFfO_Ap4?HRLf1!&RWtd&{`ldUBpBEj6-x` zTTgF7eAOT;vSdJrUQt*reHJLUpvML$VvVzKIsfO`m|!fD5m;Bdno(M5UG1mTWM= zAu)cc@V7`a8GOs@y_FKpKY0!gGTP^_w^YN`>n`;D@JXonpdPyBdVo(owL)LeJa!?+ zm0zM`1R~YyPI2gS>2JAjyCM5ExOrosjw%cCH-sB*yZG3=7?;stZjV$}B_p(QID}cJ z*tQ=acBM~c{WBvE(Z;q)ciJ7Y$RcwSqRF|S zvx||Fl{Qp)ZyRYA`t4j3chwsb3_k`Pidi6*?mE_qSi~6_tx|a)ZsxFFTP%pI;_e-r zDN88$`lhuYRPSrSQ5-r&HPSR}Cw?+2$<-lfHiCgJ_9ZtB6EDp`h1e+HC)+M=l?0>Z zFVT;U^XI2Wy;V-YGBZ)WEVkD%p7j#LSlm>NrzNavK;}U;SDpG72u`p<)~ECXBYua0 zy@e{eRcr-&ITCH@c1<)$$_jCWmnAnZf>5%Mfb*r82PGTqTNhY3q&QR{GPTF zQ=P<@m4%Vjgx^6RNh`_^1lr8fJNJZFCNQB`ULmudF3_Fq;<9JF?dC2xSnHc=giYT! zVSSegV!nKxmtj4M3Hhxc05lTXUAIr!iTHsd{mGAj>HH^S^{tuueICa(`O({;BJ}eo zi{rB#!E_wAT{FrB0pQ0$<8;!9qaj`85nc3;cKhEU z^gzPl4Q6=Ar>k0SE4?!H=bNr<`YZBT`>(RpF-a3YdS{LEkZ?ur%fVBAN}D7$0#P@+ zoBarv3C0l#B!S)N@kpGUk1a_YJhhe-(iH$Y0^9XOF3XXg@wV&0l1C(`Q(NJwjM@M) zf_n3UkFuWmgk&@|L7PA%7np(<%&b8!!qeq^St-vRm~<+h@t=uhRI^L`S!du#oyS@E zq&|Qx#mh*!*a3{6FX}_Lg(e(_Vm0Gmiy%NdS4o@>%R(yp^DkxzujkP5O52qUb6twn zUP?PG41~>!iJ!+16z})W91ya6aB24u}f6(8za=+wt%LcIH$uM1;#_fa>7eMoc(WwpZG~) zl(=4P&qzbf?Z^ZAh&|xty=m;N{jJchx9)WbeOVkSuM8i_Hg|6>8hAHx`>g!9NYxFI zz)!=Ot1gu0Qt+}Y#*0P*7hMd#=~?RIy`(BYn`#eXHavU0^T%xni4r>`KDRYkcC5lv zVFKo++%;Nfh715Fr1v=pCXiPhpd(9V_7AS&lJVHA6$2JH@0i|)d1DMaLC6XEXoo-I zDF9o_6mVZBl(|!>L)E}EI{fDw*K)_9xwiX?rh19|HgBU@0SjuO)0*cxTQR9k`C-Q$ z5!6DwGdyl$t`+Cv2jrLy~8KObzqbQ{TM5-?D$sO@HY%p7_ z3})~(U%jvi4PO22p~>kGYbP172sSHw{)J{vxO-W*)Zrj3i^^@#*-!b3e(UO|Bljul znqb)A;A2Ln%S6NQknEMy-Nw^X3d(*l@#)qyW6P%Y2ELqXaTI)qu4sf4i*deEr@M0D zS@?7Sev=CS-SpH)W;H_!5^o{Zz=^VF#`CAX8FsH~JU_LBIMG)(e8AH3SAckimk0QdFlTPhiVdy1n~owl0qnE&S9uwd0keWOW|bYaqqKIjsa3qEW?zkK z0W~GjfED`L1>*j??#-BeCKo3qwn62~?*;_56{Y+{MlM zbX_aiw_@0_DsZZv=g_7D5yHtvv@H)Il#nO-pQv_m1?D>&y>IR@>f#Ba^Sc?a8bQ^X z3aDNkx%$3$k4O9Lo?s5Tv-FaUi?_^M(HL#(x_aM0ak8j5 zrmxH#ds0zA5IylMCMPSu7 z#xQ!@Yd*au^?PPR7+@AimAR_UQekk^{C!o0sp}itGt=V4^Z2Qsx*K1``^Rc`*|vfL zS8(W1&*kfgKV`p~@0W`b>+?wi4*TBVPQ?){HO#j$+@Ma3Zx#)Y=<_=9feU>Yq~D(N z?rY7gOb))-p6-w^jwCZfkTaHqgU@or6&o&gRWIC&7wSE?yVaYB3 zdX0DoSz6{8rjn+5zGx$TlJ^nfBx#PTx7?RN%E#+m0`+BUto;f zSMiBdaRMxQRF5~@0eM^Yu`y(}Nm0yb>q&G}^4$2a1U8s*KD`7Pf2j$f<6VEk&pTI@>n4$Lli4&W5# z&KNMy-`@MUbA+Bq-GafAWE_=wJ`!RT^y8v-==7Rn?+%41=!rPqdu8xj{mRB8MKU0N zMkFmps&6m|lKU+~^a}-gEx-r<{vuYddc`!}4kb&caKtl9y2kaHj)^Nq&Q@Frc0MNV4xCA7C>96u$2%i)y2W5-Of z1pJ1uX`4ZfGgWs^#|`{?xng>aw~-+tPTO)0C%Ih|u*{HhkzBN5%r*#D;$N&j-N42D zF?%r!+=B_KWkTvVL-CG)?qhZEU<7_-~IF!6^~+`nMLq7O9X zUoa7ozrU3d`@5gC#NRM6A)$vB<=^9p35)yH>w>ymoPb;LFM33+li2clbx0 l1@+wBq0IkOB*zB=@x7on5a>UDK}1wcL=vBaLs>`VKLF;cAJ6~* literal 0 HcmV?d00001 diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093116528/epc.json b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093116528/epc.json new file mode 100644 index 00000000..e6cf72d9 --- /dev/null +++ b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093116528/epc.json @@ -0,0 +1,438 @@ +{ + "uprn": 10093116528, + "roofs": [ + { + "description": "Average thermal transmittance 0.11 W/m\u00b2K", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + } + ], + "walls": [ + { + "description": "Average thermal transmittance 0.19 W/m\u00b2K", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + } + ], + "floors": [ + { + "description": "Average thermal transmittance 0.11 W/m\u00b2K", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + } + ], + "status": "entered", + "tenure": "ND", + "windows": { + "description": "High performance glazing", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + }, + "lighting": { + "description": "Low energy lighting in all fixed outlets", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + }, + "postcode": "PO10 8BG", + "data_type": 2, + "hot_water": { + "description": "From main system, flue gas heat recovery", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + }, + "post_town": "EMSWORTH", + "built_form": 2, + "created_at": "2018-06-04 10:56:39", + "living_area": 28.81, + "orientation": 0, + "region_code": 16, + "report_type": 3, + "sap_heating": { + "thermal_store": 1, + "water_fuel_type": 1, + "water_heating_code": 901, + "main_heating_details": [ + { + "has_fghrs": "true", + "main_fuel_type": 1, + "heat_emitter_type": 1, + "fghrs_index_number": 60031, + "emitter_temperature": 1, + "is_flue_fan_present": "true", + "main_heating_number": 1, + "main_heating_control": 2110, + "is_interlocked_system": "true", + "main_heating_category": 2, + "main_heating_fraction": 1, + "main_heating_flue_type": 2, + "central_heating_pump_age": 2, + "main_heating_data_source": 1, + "main_heating_index_number": 17644, + "has_separate_delayed_start": "true", + "load_or_weather_compensation": 0, + "is_central_heating_pump_in_heated_space": "true" + } + ], + "has_hot_water_cylinder": "false", + "has_fixed_air_conditioning": "false", + "secondary_heating_category": 1 + }, + "sap_version": 9.92, + "schema_type": "SAP-Schema-17.1", + "uprn_source": "Energy Assessor", + "country_code": "ENG", + "main_heating": [ + { + "description": "Boiler and radiators, mains gas", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "air_tightness": { + "description": "Air permeability 4.5 m\u00b3/h.m\u00b2 (as tested)", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + }, + "dwelling_type": "Semi-detached house", + "language_code": 1, + "property_type": 0, + "address_line_1": "4, Woodfield Park Road", + "assessment_date": "2018-06-01", + "assessment_type": "SAP", + "completion_date": "2018-06-04", + "inspection_date": "2018-06-01", + "sap_ventilation": { + "psv_count": 0, + "pressure_test": 1, + "air_permeability": 4.5, + "open_flues_count": 0, + "ventilation_type": 1, + "extract_fans_count": 3, + "open_fireplaces_count": 0, + "sheltered_sides_count": 1, + "flueless_gas_fires_count": 0 + }, + "design_water_use": 1, + "sap_data_version": 9.92, + "total_floor_area": 90, + "transaction_type": 6, + "conservatory_type": 1, + "registration_date": "2018-06-04", + "sap_energy_source": { + "electricity_tariff": 1, + "wind_turbines_count": 0, + "wind_turbine_terrain_type": 2, + "fixed_lighting_outlets_count": 10, + "low_energy_fixed_lighting_outlets_count": 10, + "low_energy_fixed_lighting_outlets_percentage": 100 + }, + "sap_opening_types": [ + { + "name": 1, + "type": 4, + "u_value": 1.4, + "data_source": 2, + "frame_factor": 0.7, + "glazing_type": 4, + "solar_transmittance": 0.72 + }, + { + "name": 5, + "type": 1, + "u_value": 1.6, + "data_source": 2, + "glazing_type": 1 + } + ], + "secondary_heating": { + "description": "None", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + }, + "sap_building_parts": [ + { + "sap_roofs": [ + { + "name": "Roof 1", + "u_value": 0.113, + "roof_type": 2, + "description": "Roof 1", + "total_roof_area": 44.93 + } + ], + "sap_walls": [ + { + "name": "Wall 1", + "u_value": 0.187, + "wall_type": 2, + "description": "External", + "total_wall_area": 67.29, + "is_curtain_walling": "false" + }, + { + "name": "Wall 2", + "u_value": 0, + "wall_type": 4, + "description": "To other house", + "total_wall_area": 79.1 + } + ], + "identifier": "Main Dwelling", + "overshading": 2, + "sap_openings": [ + { + "name": 1, + "type": 1, + "width": 0.9, + "height": 2.5, + "location": "Wall 1", + "orientation": 3 + }, + { + "name": 2, + "type": 1, + "width": 2.85, + "height": 2.5, + "location": "Wall 1", + "orientation": 3 + }, + { + "name": 3, + "type": 1, + "width": 0.8, + "height": 2.5, + "location": "Wall 1", + "orientation": 3 + }, + { + "name": 4, + "type": 1, + "width": 1.4, + "height": 2.5, + "location": "Wall 1", + "orientation": 3 + }, + { + "name": 5, + "type": 5, + "width": 1, + "height": 2.3, + "location": "Wall 1", + "orientation": 0 + }, + { + "name": 6, + "type": 1, + "width": 1, + "height": 2.45, + "location": "Wall 1", + "orientation": 7 + }, + { + "name": 7, + "type": 1, + "width": 1.45, + "height": 2.2, + "location": "Wall 1", + "orientation": 7 + }, + { + "name": 8, + "type": 1, + "width": 1.35, + "height": 2.45, + "location": "Wall 1", + "orientation": 7 + } + ], + "construction_year": 2017, + "sap_thermal_bridges": { + "thermal_bridges": [ + { + "length": 10.75, + "psi_value": 0.3, + "psi_value_source": 2, + "thermal_bridge_type": "E2" + }, + { + "length": 9.75, + "psi_value": 0.04, + "psi_value_source": 2, + "thermal_bridge_type": "E3" + }, + { + "length": 38.8, + "psi_value": 0.05, + "psi_value_source": 2, + "thermal_bridge_type": "E4" + }, + { + "length": 12.94, + "psi_value": 0.16, + "psi_value_source": 2, + "thermal_bridge_type": "E5" + }, + { + "length": 12.94, + "psi_value": 0.14, + "psi_value_source": 4, + "thermal_bridge_type": "E7" + }, + { + "length": 10, + "psi_value": 0.06, + "psi_value_source": 2, + "thermal_bridge_type": "E10" + }, + { + "length": 2.1, + "psi_value": 0.24, + "psi_value_source": 2, + "thermal_bridge_type": "E12" + }, + { + "length": 5.2, + "psi_value": 0.09, + "psi_value_source": 2, + "thermal_bridge_type": "E16" + }, + { + "length": 5.2, + "psi_value": 0.06, + "psi_value_source": 2, + "thermal_bridge_type": "E18" + }, + { + "length": 15.21, + "psi_value": 0.16, + "psi_value_source": 4, + "thermal_bridge_type": "P1" + }, + { + "length": 15.21, + "psi_value": 0, + "psi_value_source": 4, + "thermal_bridge_type": "P3" + }, + { + "length": 15.24, + "psi_value": 0.24, + "psi_value_source": 4, + "thermal_bridge_type": "P4" + } + ], + "thermal_bridge_code": 5 + }, + "building_part_number": 1, + "sap_floor_dimensions": [ + { + "storey": 0, + "u_value": 0.11, + "floor_type": 2, + "description": "Ground floor", + "storey_height": 2.6, + "heat_loss_area": 44.93, + "total_floor_area": 44.93 + }, + { + "storey": 1, + "u_value": 0, + "floor_type": 3, + "storey_height": 2.6, + "heat_loss_area": 0, + "total_floor_area": 44.93 + } + ], + "thermal_mass_parameter": 250 + } + ], + "heating_cost_current": { + "value": 202, + "currency": "GBP" + }, + "co2_emissions_current": 1.2, + "energy_rating_average": 60, + "energy_rating_current": 84, + "lighting_cost_current": { + "value": 61, + "currency": "GBP" + }, + "main_heating_controls": [ + { + "description": "Time and temperature zone control", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + } + ], + "has_hot_water_cylinder": "false", + "heating_cost_potential": { + "value": 202, + "currency": "GBP" + }, + "hot_water_cost_current": { + "value": 72, + "currency": "GBP" + }, + "suggested_improvements": [ + { + "sequence": 1, + "typical_saving": { + "value": 29, + "currency": "GBP" + }, + "indicative_cost": "\u00a34,000 - \u00a36,000", + "improvement_type": "N", + "improvement_details": { + "improvement_number": 19 + }, + "improvement_category": 5, + "energy_performance_rating": 85, + "environmental_impact_rating": 88 + }, + { + "sequence": 2, + "typical_saving": { + "value": 327, + "currency": "GBP" + }, + "indicative_cost": "\u00a35,000 - \u00a38,000", + "improvement_type": "U", + "improvement_details": { + "improvement_number": 34 + }, + "improvement_category": 5, + "energy_performance_rating": 95, + "environmental_impact_rating": 97 + } + ], + "co2_emissions_potential": -0.1, + "energy_rating_potential": 95, + "lighting_cost_potential": { + "value": 61, + "currency": "GBP" + }, + "schema_version_original": "LIG-17.0", + "hot_water_cost_potential": { + "value": 43, + "currency": "GBP" + }, + "is_in_smoke_control_area": "unknown", + "renewable_heat_incentive": { + "rhi_new_dwelling": { + "space_heating": 2310, + "water_heating": 1818 + } + }, + "seller_commission_report": "Y", + "energy_consumption_current": 75, + "has_fixed_air_conditioning": "false", + "multiple_glazed_percentage": 100, + "calculation_software_version": 6.2, + "energy_consumption_potential": -6, + "environmental_impact_current": 87, + "current_energy_efficiency_band": "B", + "environmental_impact_potential": 97, + "has_heated_separate_conservatory": "false", + "potential_energy_efficiency_band": "A", + "co2_emissions_current_per_floor_area": 13 +} \ No newline at end of file