Slice 85: bulk-update cohort 000516 hand-built for Cat A diff parity

Closes 23 of 24 mapper-vs-hand-built load-bearing divergences by
populating fields the Elmhurst mapper extracts from Summary_000516.
pdf but the original hand-built left at their `make_minimal_sap10_
epc` / dataclass-default values. Every change is cascade-equivalent —
all 11 `_FIXTURE_PINS["000516"]` SapResult pins remain GREEN against
worksheet `SAP value 62.7937`.

000516-specific deltas:

- `wall_thickness_measured=True` on Main (Summary lodges 400 mm).
- `floor_type="Above unheated space"` (exposed timber floor, not
  Ground floor) — matches the cert's `is_exposed_floor=True` for
  the lowest Main floor.
- `roof_insulation_location="None"` — the Summary lodges the literal
  string "None" for an uninsulated roof; mapper surfaces it
  verbatim.

Standard Cat A additions (per Slice 72/75/78/82 pattern): floor
descriptive fields, 6 ventilation zero counts, draught_lobby=True,
pressure_test="Not available", top-level descriptive strings +
booleans, `number_of_storeys=3` (Main ground + first + RIR),
shower_outlets="Non-electric shower",
central_heating_pump_age_str="Unknown".

Diff count: 24 → **1**. Remaining diff is `sap_windows: LEN 5 vs 2`
— closes via Slice 86.

Pyright net-zero on the touched fixture.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-05-25 18:15:57 +00:00
parent 8fe96f03ea
commit f863598d39

View file

@ -33,6 +33,8 @@ from datatypes.epc.domain.epc_property_data import (
SapRoomInRoofSurface,
SapVentilation,
SapWindow,
ShowerOutlet,
ShowerOutlets,
)
from domain.ml.tests._fixtures import (
make_main_heating_detail,
@ -55,13 +57,23 @@ _WC_SOLID_BRICK = 3 # party walls — RdSAP10 maps to U=0.0 (solid masonry)
def build_epc() -> EpcPropertyData:
"""EpcPropertyData mirroring the Elmhurst 000516 inputs."""
"""EpcPropertyData mirroring the Elmhurst 000516 inputs.
Field-level parity with `from_elmhurst_site_notes(Summary_000516.
pdf)` for the load-bearing field allow-list cascade-equivalent
encoding-only fields (descriptive floor/roof strings, ventilation
zero counts) are populated explicitly to eliminate noise without
altering the SAP cascade output (the 11 1e-4 pins in
`test_e2e_elmhurst_sap_score.py` remain GREEN against the worksheet
PDF's `SAP value 62.7937`).
"""
main = SapBuildingPart(
identifier=BuildingPartIdentifier.MAIN,
construction_age_band="A",
wall_construction=_WC_CAVITY,
wall_insulation_type=4,
wall_thickness_measured=False,
# Summary §7 lodges Wall Thickness 400 mm explicitly; matches mapper.
wall_thickness_measured=True,
party_wall_construction=_WC_SOLID_BRICK, # Solid masonry → U=0.0
sap_floor_dimensions=[
SapFloorDimension(
@ -118,8 +130,18 @@ def build_epc() -> EpcPropertyData:
# u_roof cascade picks the Table 16 "none" row.
roof_insulation_thickness=0,
wall_thickness_mm=400,
# Mapper-extracted descriptive fields (cascade reads int codes
# on SapFloorDimension; these carry the lodged Summary text).
# `roof_insulation_location="None"` is literal — the Summary
# lodges "None" for an uninsulated roof, which the mapper
# surfaces as a string field.
floor_type="Above unheated space",
floor_construction_type="Suspended timber",
floor_insulation_type_str="As built",
floor_u_value_known=False,
roof_insulation_location="None",
)
return make_minimal_sap10_epc(
epc = make_minimal_sap10_epc(
total_floor_area_m2=90.54,
country_code="ENG",
postcode="BD4 7JR",
@ -152,11 +174,23 @@ def build_epc() -> EpcPropertyData:
percent_draughtproofed=75,
low_energy_fixed_lighting_bulbs_count=SECTION_5_BULB_COUNT_LEL,
sap_windows=list(SECTION_6_VERTICAL_WINDOWS),
blocked_chimneys_count=0,
dwelling_type="Mid-Terrace house",
built_form="Mid-Terrace",
property_type="House",
sap_ventilation=SapVentilation(
extract_fans_count=2,
sheltered_sides=2,
has_suspended_timber_floor=False,
has_draught_lobby=False,
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(
# 000516 line 82: PCDF Index 18118 — Vaillant ecoTEC sustain 24
@ -173,6 +207,15 @@ def build_epc() -> EpcPropertyData:
number_baths=1, # 000516 line 117: Total number of baths = 1
),
)
# Top-level cert-lodgement booleans the mapper surfaces.
epc.has_conservatory = False
epc.any_unheated_rooms = False
epc.number_of_storeys = 3
epc.sap_heating.shower_outlets = ShowerOutlets(
shower_outlet=ShowerOutlet(shower_outlet_type="Non-electric shower"),
)
epc.sap_heating.main_heating_details[0].central_heating_pump_age_str = "Unknown"
return epc
# ============================================================================