From aa07265606fba9f971f634fd27d763728c3481de Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Tue, 19 May 2026 10:17:55 +0000 Subject: [PATCH] P5.1: add SapResult.intermediate; populate dimensions group MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First slice of P5 trace mode mechanical half (ADR-0010 / handover §11). SapResult.intermediate: dict[str, float] now exposes worksheet-named variables for per-section diffing against BRE worked examples and hand calcs. Dimensions group lands first: tfa_m2, volume_m3, storey_count. Subsequent slices (P5.2 heat transmission → P5.8 primary energy) extend the same dict; field defined here so the structural change lands once and later slices are pure additions. 131 SAP tests pass; 310 packages/domain tests pass. --- packages/domain/src/domain/sap/calculator.py | 8 ++++++++ .../src/domain/sap/tests/test_calculator.py | 15 +++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/packages/domain/src/domain/sap/calculator.py b/packages/domain/src/domain/sap/calculator.py index 39f47d92..68b1f5c1 100644 --- a/packages/domain/src/domain/sap/calculator.py +++ b/packages/domain/src/domain/sap/calculator.py @@ -163,6 +163,7 @@ class SapResult: primary_energy_kwh_per_yr: float primary_energy_kwh_per_m2: float monthly: tuple[MonthlyEntry, ...] + intermediate: dict[str, float] def _solar_gains_w( @@ -331,6 +332,12 @@ def calculate_sap_from_inputs(inputs: CalculatorInputs) -> SapResult: ) primary_energy_per_m2 = primary_energy_kwh / tfa if tfa > 0 else 0.0 + intermediate: dict[str, float] = { + "tfa_m2": inputs.dimensions.total_floor_area_m2, + "volume_m3": inputs.dimensions.volume_m3, + "storey_count": float(inputs.dimensions.storey_count), + } + return SapResult( sap_score=sap_int, sap_score_continuous=sap_cont, @@ -346,6 +353,7 @@ def calculate_sap_from_inputs(inputs: CalculatorInputs) -> SapResult: primary_energy_kwh_per_yr=primary_energy_kwh, primary_energy_kwh_per_m2=primary_energy_per_m2, monthly=monthly, + intermediate=intermediate, ) diff --git a/packages/domain/src/domain/sap/tests/test_calculator.py b/packages/domain/src/domain/sap/tests/test_calculator.py index 5e17e07f..d3d0de47 100644 --- a/packages/domain/src/domain/sap/tests/test_calculator.py +++ b/packages/domain/src/domain/sap/tests/test_calculator.py @@ -124,6 +124,21 @@ def test_calculator_returns_twelve_month_breakdown_and_plausible_sap_score() -> ) +def test_calculate_exposes_dimensions_intermediates() -> None: + # Arrange — P5 trace mode: `result.intermediate` must surface the + # worksheet-named dimensions variables for per-section diffing + # against BRE worked examples and hand calcs (ADR-0010 / handover §11). + inputs = _baseline_inputs() + + # Act + result = calculate_sap_from_inputs(inputs) + + # Assert + assert result.intermediate["tfa_m2"] == inputs.dimensions.total_floor_area_m2 + assert result.intermediate["volume_m3"] == inputs.dimensions.volume_m3 + assert result.intermediate["storey_count"] == float(inputs.dimensions.storey_count) + + def test_higher_main_heating_efficiency_reduces_fuel_use() -> None: # Arrange — Direction check: doubling the boiler efficiency must halve # the main-heating fuel kWh, holding everything else constant.