P5.1: add SapResult.intermediate; populate dimensions group

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.
This commit is contained in:
Khalim Conn-Kowlessar 2026-05-19 10:17:55 +00:00
parent 62289ec6f6
commit aa07265606
2 changed files with 23 additions and 0 deletions

View file

@ -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,
)

View file

@ -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.