Synthesise reduced-field windows for RdSAP-Schema-17.0 certs 🟩

Add the 17.0 synthesis seam over the shared _synthesise_reduced_field_windows
core (inherited 20.0.0 coefficients, ND glazing -> DG-modal default 2, per
ADR-0028). 17.0 glazed_type codes (1-4,7) are a subset of the verified 1-8
space. The 10 rich certs use lodged window_area directly; the windowless 990
synthesise a 4-way N/E/S/W split.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jun-te Kim 2026-06-12 12:47:40 +00:00
parent 887af58a25
commit 9b01e1d0c9

View file

@ -541,7 +541,28 @@ class EpcPropertyDataMapper:
secondary_heating_type=None,
cylinder_insulation_thickness_mm=None,
),
sap_windows=[],
# ADR-0028: 990/1000 omit sap_windows -> synthesised from the
# glazed_area band + TFA via the shared reduced-field core. The 10
# rich certs keep their lodged per-window geometry (used directly:
# window_width = area, height = 1.0).
sap_windows=[
SapWindow(
frame_material=None,
glazing_gap=0,
orientation=w.orientation,
window_type=w.window_type,
glazing_type=w.glazing_type,
window_width=_measurement_value(w.window_area),
window_height=1.0,
draught_proofed=False,
window_location=w.window_location,
window_wall_type=0,
permanent_shutters_present=False,
)
for w in schema.sap_windows
]
if schema.sap_windows
else _synthesise_17_0_sap_windows(schema),
sap_energy_source=SapEnergySource(
mains_gas=es.mains_gas == "Y",
meter_type=str(es.meter_type),
@ -3210,6 +3231,28 @@ def _synthesise_19_0_sap_windows(schema: RdSapSchema19_0) -> List[SapWindow]:
)
# ADR-0028: multiple_glazing_type "ND" (Not Defined, 54/1000 17.0 certs) → the
# DG-modal default, as for 18.0/17.1.
_RDSAP17_0_ND_GLAZING_TYPE: int = 2
def _synthesise_17_0_sap_windows(schema: RdSapSchema17_0) -> List[SapWindow]:
"""ADR-0028 seam: reuses the inherited 20.0.0 coefficients via the shared
core (968/1000 band-1 with no measured band-1 windows; only 10 rich certs).
17.0 glazed_type codes (observed 1-4, 7) are a subset of 20.0.0's verified
1-8 space: route integer codes through the verified cascade; the "ND" string
falls back to the DG-modal default. Own seam so 17.0 can diverge."""
mgt = schema.multiple_glazing_type
glazing_type = (
_api_cascade_glazing_type(mgt)
if isinstance(mgt, int)
else _RDSAP17_0_ND_GLAZING_TYPE
)
return _synthesise_reduced_field_windows(
schema.glazed_area, schema.total_floor_area, glazing_type
)
# ADR-0028: multiple_glazing_type "ND" (Not Defined, 56/1000 17.1 certs) → the
# DG-modal default, as for 18.0.
_RDSAP17_1_ND_GLAZING_TYPE: int = 2