mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
Slice 78: bulk-update cohort 000487 hand-built for Cat A diff parity
Closes 23 of 45 mapper-vs-hand-built load-bearing divergences by populating fields the Elmhurst mapper extracts from Summary_000487. pdf but the original hand-built left at their `make_minimal_sap10_ epc` / dataclass-default values. Every change is cascade-equivalent — none alter `_FIXTURE_PINS["000487"]` SapResult fields (all 11 1e-4 pins remain GREEN against worksheet `SAP value 61.6431`). Mirrors the Slice 64 / 72 / 75 pattern. 000487-specific deltas: - `wall_thickness_measured=True` on **both** bps (Summary §7 lodges measured thickness for Main and Ext1 on this cert). - Floor descriptive: Main "Ground floor" + suspended timber; Ext1 "Above unheated space" + suspended timber (the cert's `is_exposed_floor=True` for the lowest Ext1 floor). - `dwelling_type="Enclosed Mid-Terrace house"`, `built_form="Enclosed Mid-Terrace"` — the Summary distinguishes Enclosed from plain Mid-Terrace; mapper preserves the distinction. - `shower_outlets=ShowerOutlets(shower_outlet_type="Electric shower")` — 000487 lodges 1 instantaneous electric shower (vs Non-electric on 000477/000480 cohort certs). - `extensions_count=1`, plus standard top-level booleans, `number_of_storeys=3`, ventilation zero counts. Diff count: 45 → **22**. Remaining diffs are structural / encoding- choice: - RIR `detailed_surfaces` ordering mismatch + per-surface encoding (handbuilt pins explicit `u_value=0.86` on gable_wall_external; mapper extracts insulation_thickness=100 + mineral_wool) — Slice 79 - Alt-wall `wall_construction=8 (SAP10 Park-home)` is mislabeled in the hand-built — Elmhurst's "TI Timber Frame" maps to SAP10 code 5 (per `_ELMHURST_WALL_CODE_TO_SAP10`); mapper produces the correct code 5 — Slice 79 - `sap_windows: LEN 5 vs 2` — Slice 80 11 cohort 000487 cascade pins still GREEN; pyright net-zero. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
4b74281412
commit
b8f35af902
1 changed files with 60 additions and 4 deletions
|
|
@ -25,6 +25,8 @@ from datatypes.epc.domain.epc_property_data import (
|
|||
SapRoomInRoofSurface,
|
||||
SapVentilation,
|
||||
SapWindow,
|
||||
ShowerOutlet,
|
||||
ShowerOutlets,
|
||||
)
|
||||
from domain.ml.tests._fixtures import (
|
||||
make_main_heating_detail,
|
||||
|
|
@ -44,13 +46,21 @@ _WC_TIMBER_FRAME = 8
|
|||
|
||||
def build_epc() -> EpcPropertyData:
|
||||
"""EpcPropertyData mirroring the Elmhurst inputs. Field-by-field
|
||||
correspondence with the Summary_000487 PDF."""
|
||||
correspondence with the Summary_000487 PDF.
|
||||
|
||||
Also doubles as the ground-truth diff target for the Elmhurst
|
||||
mapper (`test_from_elmhurst_site_notes_matches_hand_built_000487`)
|
||||
— cascade-equivalent encoding-only fields (descriptive floor/roof
|
||||
strings, ventilation zero counts) are populated explicitly to
|
||||
eliminate noise without altering the SAP cascade output.
|
||||
"""
|
||||
main = SapBuildingPart(
|
||||
identifier=BuildingPartIdentifier.MAIN,
|
||||
construction_age_band="B",
|
||||
wall_construction=_WC_CAVITY,
|
||||
wall_insulation_type=4, # "A As Built"
|
||||
wall_thickness_measured=False,
|
||||
# Summary §7 lodges Wall Thickness measured for Main; matches mapper.
|
||||
wall_thickness_measured=True,
|
||||
party_wall_construction=0, # "U Unable to determine" → u_party_wall returns 0.25
|
||||
sap_floor_dimensions=[
|
||||
SapFloorDimension(
|
||||
|
|
@ -96,13 +106,22 @@ def build_epc() -> EpcPropertyData:
|
|||
# joist insulation 300mm row.
|
||||
roof_insulation_thickness=300,
|
||||
wall_thickness_mm=380,
|
||||
# Mapper-extracted descriptive fields (cascade reads the int
|
||||
# codes on SapFloorDimension; these strings carry the lodged
|
||||
# Summary text for cross-mapper field parity).
|
||||
floor_type="Ground floor",
|
||||
floor_construction_type="Suspended timber",
|
||||
floor_insulation_type_str="As built",
|
||||
floor_u_value_known=False,
|
||||
roof_insulation_location="Joists",
|
||||
)
|
||||
extension = SapBuildingPart(
|
||||
identifier=BuildingPartIdentifier.EXTENSION_1,
|
||||
construction_age_band="B",
|
||||
wall_construction=_WC_CAVITY,
|
||||
wall_insulation_type=4,
|
||||
wall_thickness_measured=False,
|
||||
# Summary §7 lodges Wall Thickness measured for the extension.
|
||||
wall_thickness_measured=True,
|
||||
party_wall_construction=0,
|
||||
sap_floor_dimensions=[
|
||||
# The worksheet labels the extension's storeys as (1c) "First
|
||||
|
|
@ -141,8 +160,13 @@ def build_epc() -> EpcPropertyData:
|
|||
# joist insulation 300mm row (same as Main).
|
||||
roof_insulation_thickness=300,
|
||||
wall_thickness_mm=380,
|
||||
floor_type="Above unheated space",
|
||||
floor_construction_type="Suspended timber",
|
||||
floor_insulation_type_str="As built",
|
||||
floor_u_value_known=False,
|
||||
roof_insulation_location="Joists",
|
||||
)
|
||||
return make_minimal_sap10_epc(
|
||||
epc = make_minimal_sap10_epc(
|
||||
total_floor_area_m2=81.57,
|
||||
country_code="ENG",
|
||||
postcode="bd3 9JZ",
|
||||
|
|
@ -153,12 +177,28 @@ def build_epc() -> EpcPropertyData:
|
|||
percent_draughtproofed=100,
|
||||
low_energy_fixed_lighting_bulbs_count=SECTION_5_BULB_COUNT_LEL,
|
||||
sap_windows=list(SECTION_6_VERTICAL_WINDOWS),
|
||||
extensions_count=1,
|
||||
blocked_chimneys_count=0,
|
||||
dwelling_type="Enclosed Mid-Terrace house",
|
||||
built_form="Enclosed Mid-Terrace",
|
||||
property_type="House",
|
||||
sap_ventilation=SapVentilation(
|
||||
extract_fans_count=1,
|
||||
sheltered_sides=3,
|
||||
has_suspended_timber_floor=True,
|
||||
suspended_timber_floor_sealed=False,
|
||||
has_draught_lobby=False,
|
||||
# SAP10.2 §2 — explicit zero counts match the mapper, which
|
||||
# parses the Summary's "No. of <flue>" rows. Cascade-equivalent
|
||||
# to leaving these None.
|
||||
open_flues_count=0,
|
||||
closed_flues_count=0,
|
||||
boiler_flues_count=0,
|
||||
other_flues_count=0,
|
||||
passive_vents_count=0,
|
||||
flueless_gas_fires_count=0,
|
||||
draught_lobby=True,
|
||||
pressure_test="Not available",
|
||||
),
|
||||
sap_heating=make_sap_heating(
|
||||
# 000487 line 88: PCDF Index 18119 — Vaillant ecoTEC sustain 28
|
||||
|
|
@ -181,6 +221,22 @@ def build_epc() -> EpcPropertyData:
|
|||
mixer_shower_count=0,
|
||||
),
|
||||
)
|
||||
# Top-level cert-lodgement booleans / counts the Elmhurst mapper
|
||||
# surfaces from the Summary PDF but `make_minimal_sap10_epc` doesn't
|
||||
# expose as kwargs. Set post-construction (dataclass is non-frozen).
|
||||
epc.has_conservatory = False
|
||||
epc.any_unheated_rooms = False
|
||||
epc.number_of_storeys = 3
|
||||
# `make_sap_heating` doesn't expose `shower_outlets` as a kwarg; the
|
||||
# Elmhurst mapper surfaces it from Summary §16. Cert lodges an
|
||||
# electric shower for 000487.
|
||||
epc.sap_heating.shower_outlets = ShowerOutlets(
|
||||
shower_outlet=ShowerOutlet(shower_outlet_type="Electric shower"),
|
||||
)
|
||||
# Summary §14 "Heat pump age: Unknown" — surfaced by the Elmhurst
|
||||
# mapper as the str dual-encoding that internal_gains.py reads.
|
||||
epc.sap_heating.main_heating_details[0].central_heating_pump_age_str = "Unknown"
|
||||
return epc
|
||||
|
||||
|
||||
# ============================================================================
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue