mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
Goal-objective test uses the shared fixtures and a real boiler code 🟪
Review findings on PR #1527: - The overlay constants, ScoredOption builder, ventilation dependency and selected_types helper come from the shared _optimiser_fixtures module (landed on the fabric-first base) instead of local copies; the boiler overlay is the shared BOILER_OVERLAY (SAP Table 4a code 104, a mains-gas combi) rather than code 201, which is neither a boiler nor a heat pump. _IWI_OVERLAY (solid-wall internal, type 3) stays local — no shared equivalent — and the carbon stubs stay bespoke (the shared StubScorer has no CO2 knob). - The optimise_package_fabric_first import is lifted to module scope. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
98d2f7aa16
commit
7996eedf55
1 changed files with 20 additions and 55 deletions
|
|
@ -16,46 +16,25 @@ from datatypes.epc.domain.epc_property_data import (
|
|||
)
|
||||
from domain.modelling.measure_type import MeasureType
|
||||
from domain.modelling.optimisation.optimiser import (
|
||||
MeasureDependency,
|
||||
OptimisedPackage,
|
||||
ScoredOption,
|
||||
optimise_package,
|
||||
optimise_package_fabric_first,
|
||||
)
|
||||
from domain.modelling.recommendation import Cost, MeasureOption
|
||||
from domain.modelling.scoring.package_scorer import Score
|
||||
from domain.modelling.simulation import (
|
||||
BuildingPartOverlay,
|
||||
EpcSimulation,
|
||||
HeatingOverlay,
|
||||
VentilationOverlay,
|
||||
from domain.modelling.simulation import BuildingPartOverlay, EpcSimulation
|
||||
from tests.domain.modelling._optimiser_fixtures import (
|
||||
ASHP_OVERLAY,
|
||||
BOILER_OVERLAY,
|
||||
WALL_OVERLAY,
|
||||
scored_option,
|
||||
selected_types,
|
||||
ventilation_dependency,
|
||||
)
|
||||
from tests.domain.sap10_calculator.worksheet._elmhurst_worksheet_000490 import (
|
||||
build_epc,
|
||||
)
|
||||
|
||||
_WALL_OVERLAY = EpcSimulation(
|
||||
building_parts={
|
||||
BuildingPartIdentifier.MAIN: BuildingPartOverlay(wall_insulation_type=2)
|
||||
}
|
||||
)
|
||||
_VENT_OVERLAY = EpcSimulation(
|
||||
ventilation=VentilationOverlay(mechanical_ventilation_kind="EXTRACT_OR_PIV_OUTSIDE")
|
||||
)
|
||||
|
||||
|
||||
def _scored(
|
||||
measure_type: str, *, gain: float, cost: float, overlay: EpcSimulation
|
||||
) -> ScoredOption:
|
||||
return ScoredOption(
|
||||
option=MeasureOption(
|
||||
measure_type=MeasureType(measure_type),
|
||||
description=measure_type,
|
||||
overlay=overlay,
|
||||
cost=Cost(total=cost, contingency_rate=0.0),
|
||||
),
|
||||
sap_gain=gain,
|
||||
)
|
||||
|
||||
|
||||
class _CarbonScorer:
|
||||
"""A stub where the wall is a small carbon win (−20 kg/yr) and a large SAP
|
||||
|
|
@ -89,19 +68,10 @@ def test_dependency_signals_are_priced_in_the_objective_currency() -> None:
|
|||
# pricing the ventilation's −30 SAP would outweigh the wall's +20 signal
|
||||
# and the package would collapse to nothing.
|
||||
groups: list[list[ScoredOption]] = [
|
||||
[_scored("cavity_wall_insulation", gain=20.0, cost=1000.0, overlay=_WALL_OVERLAY)],
|
||||
[scored_option("cavity_wall_insulation", gain=20.0, cost=1000.0, overlay=WALL_OVERLAY)],
|
||||
]
|
||||
dependency = MeasureDependency(
|
||||
triggers=frozenset({MeasureType.CAVITY_WALL_INSULATION}),
|
||||
required=ScoredOption(
|
||||
option=MeasureOption(
|
||||
measure_type=MeasureType.MECHANICAL_VENTILATION,
|
||||
description="mechanical_ventilation",
|
||||
overlay=_VENT_OVERLAY,
|
||||
cost=Cost(total=300.0, contingency_rate=0.0),
|
||||
),
|
||||
sap_gain=0.0,
|
||||
),
|
||||
dependency = ventilation_dependency(
|
||||
cost=300.0, triggers=frozenset({MeasureType.CAVITY_WALL_INSULATION})
|
||||
)
|
||||
|
||||
# Act — a Reducing-CO2 brief: maximise carbon reduction within budget.
|
||||
|
|
@ -117,22 +87,21 @@ def test_dependency_signals_are_priced_in_the_objective_currency() -> None:
|
|||
|
||||
# Assert — the wall survives with its ventilation: the dependency is worth
|
||||
# 0 kg CO2, not −30 SAP, so the package is a net +20 kg saving.
|
||||
assert {s.option.measure_type for s in package.selected} == {
|
||||
assert selected_types(package.selected) == {
|
||||
"cavity_wall_insulation",
|
||||
"mechanical_ventilation",
|
||||
}
|
||||
assert abs(package.score.co2_kg_per_yr - 480.0) <= 1e-9
|
||||
|
||||
|
||||
# Internal wall insulation — a distinct fabric overlay so the fabric-first
|
||||
# phase-1 pick is unambiguous. No shared fixture (the shared WALL_OVERLAY is a
|
||||
# cavity fill, type 2); this is a solid-wall internal treatment, type 3.
|
||||
_IWI_OVERLAY = EpcSimulation(
|
||||
building_parts={
|
||||
BuildingPartIdentifier.MAIN: BuildingPartOverlay(wall_insulation_type=3)
|
||||
}
|
||||
)
|
||||
_BOILER_OVERLAY = EpcSimulation(heating=HeatingOverlay(sap_main_heating_code=201))
|
||||
_ASHP_OVERLAY = EpcSimulation(
|
||||
heating=HeatingOverlay(main_heating_index_number=13000)
|
||||
)
|
||||
|
||||
|
||||
class _CarbonHeatingScorer:
|
||||
|
|
@ -166,15 +135,11 @@ def test_fabric_first_phase_two_rescores_in_the_objective_currency() -> None:
|
|||
# Arrange — a fabric-first Reducing-CO2 brief. Phase 1 commits the wall;
|
||||
# phase 2 must choose the heating on its post-fabric *carbon* worth, not
|
||||
# its SAP worth. Signals are supplied in kg CO2 saved (the caller's job).
|
||||
from domain.modelling.optimisation.optimiser import (
|
||||
optimise_package_fabric_first,
|
||||
)
|
||||
|
||||
groups: list[list[ScoredOption]] = [
|
||||
[_scored("internal_wall_insulation", gain=10.0, cost=1000.0, overlay=_IWI_OVERLAY)],
|
||||
[scored_option("internal_wall_insulation", gain=10.0, cost=1000.0, overlay=_IWI_OVERLAY)],
|
||||
[
|
||||
_scored("gas_boiler_upgrade", gain=5.0, cost=2000.0, overlay=_BOILER_OVERLAY),
|
||||
_scored("air_source_heat_pump", gain=50.0, cost=6000.0, overlay=_ASHP_OVERLAY),
|
||||
scored_option("gas_boiler_upgrade", gain=5.0, cost=2000.0, overlay=BOILER_OVERLAY),
|
||||
scored_option("air_source_heat_pump", gain=50.0, cost=6000.0, overlay=ASHP_OVERLAY),
|
||||
],
|
||||
]
|
||||
|
||||
|
|
@ -190,7 +155,7 @@ def test_fabric_first_phase_two_rescores_in_the_objective_currency() -> None:
|
|||
|
||||
# Assert — the wall plus the heat pump (−50 kg), not the SAP-favoured
|
||||
# boiler; the truthful package carbon is 500 − 10 − 50 = 440.
|
||||
assert {s.option.measure_type for s in package.selected} == {
|
||||
assert selected_types(package.selected) == {
|
||||
"internal_wall_insulation",
|
||||
"air_source_heat_pump",
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue