Synthesise glazing from the glazed_area band for windowless 18.0 certs 🟥

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jun-te Kim 2026-06-11 11:49:38 +00:00
parent 162259b255
commit bfedcd54dc

View file

@ -1491,3 +1491,37 @@ class TestRdSap18_0ReducedFieldSynthesis:
assert len(result.sap_windows) == len(lodged) assert len(result.sap_windows) == len(lodged)
total_area = sum(w.window_width * w.window_height for w in result.sap_windows) total_area = sum(w.window_width * w.window_height for w in result.sap_windows)
assert total_area == pytest.approx(expected_total) assert total_area == pytest.approx(expected_total)
def test_band_normal_synthesises_total_glazing_at_0_148_of_floor_area(
self,
) -> None:
# Arrange — ADR-0028 (inherit-and-validate): 18.0 lodges only a
# glazed_area *band* (1 = Normal, 958/1000), not window m². The inherited
# 20.0.0 coefficient — synthesised total glazing = 0.148 x total_floor_area
# — is reused unchanged; validated against 18.0's own band-4 rich certs
# (observed 0.223 ~ 0.148 x 1.51). A band-1 cert with no per-window array.
corpus = _load_18_0_corpus()
if not corpus:
pytest.skip("no RdSAP-Schema-18.0 corpus harvested")
cert = next(
(
c
for c in corpus
if not c.get("sap_windows") and c.get("glazed_area") == 1
),
None,
)
if cert is None:
pytest.skip("no band-1 corpus cert without sap_windows")
tfa = float(cert["total_floor_area"])
# Act
result = EpcPropertyDataMapper.from_api_response(cert)
# Assert — 4 windows (N/E/S/W avg-orientation split), each height 1.0,
# total width-sum (= total area, height=1) at 0.148 x TFA.
assert len(result.sap_windows) == 4
assert all(w.window_height == 1.0 for w in result.sap_windows)
assert sorted(w.orientation for w in result.sap_windows) == [1, 3, 5, 7]
total_area = sum(w.window_width * w.window_height for w in result.sap_windows)
assert total_area == pytest.approx(0.148 * tfa)