mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
feat(modelling): wire the HHR storage bundle into the candidate pool
recommend_heating joins the free candidate pool in _candidate_recommendations; the HHR storage bundle reaches the optimised package for an electric/off-gas dwelling. Catalogue + contingency (legacy 0.10) gain high_heat_retention_storage_heaters; report.py _triggers_for explains the heating trigger (electric/off-gas main); the harness _GENERATOR_MEASURE_TYPES forcing test covers it. ASHP + boiler bundles still to come. ADR-0024. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
b3badc9b10
commit
b55ab3727f
5 changed files with 38 additions and 1 deletions
|
|
@ -18,6 +18,7 @@ _CONTINGENCY_RATES: dict[str, float] = {
|
|||
"double_glazing": 0.15,
|
||||
"secondary_glazing": 0.15,
|
||||
"low_energy_lighting": 0.26,
|
||||
"high_heat_retention_storage_heaters": 0.10,
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -134,6 +134,16 @@ def _triggers_for(epc: EpcPropertyData, measure_type: str) -> dict[str, Any]:
|
|||
epc.low_energy_fixed_lighting_bulbs_count
|
||||
),
|
||||
}
|
||||
if measure_type == "high_heat_retention_storage_heaters":
|
||||
# heating_recommendation.py offers HHR storage to an electrically-heated
|
||||
# or off-gas dwelling (translated from legacy is_high_heat_retention_valid).
|
||||
return {
|
||||
"main_fuel_type": epc.sap_heating.main_heating_details[0].main_fuel_type,
|
||||
"sap_main_heating_code": (
|
||||
epc.sap_heating.main_heating_details[0].sap_main_heating_code
|
||||
),
|
||||
"mains_gas": epc.sap_energy_source.mains_gas,
|
||||
}
|
||||
return {}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -10,5 +10,6 @@
|
|||
"internal_wall_insulation": { "unit_cost_per_m2": 90.0 },
|
||||
"double_glazing": { "unit_cost_per_m2": 600.0 },
|
||||
"secondary_glazing": { "unit_cost_per_m2": 510.0 },
|
||||
"low_energy_lighting": { "unit_cost_per_m2": 8.0 }
|
||||
"low_energy_lighting": { "unit_cost_per_m2": 8.0 },
|
||||
"high_heat_retention_storage_heaters": { "unit_cost_per_m2": 3500.0 }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ from domain.modelling.generators.wall_recommendation import recommend_cavity_wal
|
|||
from domain.modelling.generators.solid_wall_recommendation import recommend_solid_wall
|
||||
from domain.modelling.generators.glazing_recommendation import recommend_glazing
|
||||
from domain.modelling.generators.lighting_recommendation import recommend_lighting
|
||||
from domain.modelling.generators.heating_recommendation import recommend_heating
|
||||
from domain.geospatial.planning_restrictions import PlanningRestrictions
|
||||
from domain.sap10_calculator.calculator import SapCalculator
|
||||
from repositories.fuel_rates.fuel_rates_repository import FuelRatesRepository
|
||||
|
|
@ -209,6 +210,7 @@ def _candidate_recommendations(
|
|||
recommend_floor_insulation(effective_epc, products),
|
||||
recommend_glazing(effective_epc, products, planning_restrictions),
|
||||
recommend_lighting(effective_epc, products),
|
||||
recommend_heating(effective_epc, products),
|
||||
)
|
||||
return [recommendation for recommendation in found if recommendation is not None]
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ _GENERATOR_MEASURE_TYPES = (
|
|||
"double_glazing",
|
||||
"secondary_glazing",
|
||||
"low_energy_lighting",
|
||||
"high_heat_retention_storage_heaters",
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -179,6 +180,28 @@ def test_run_modelling_recommends_low_energy_lighting_for_non_led_bulbs() -> Non
|
|||
assert "double_glazing" not in measure_types
|
||||
|
||||
|
||||
def _electric_storage_lit_epc() -> EpcPropertyData:
|
||||
epc: EpcPropertyData = _build_uninsulated_cavity_and_floor_epc()
|
||||
main = epc.sap_heating.main_heating_details[0]
|
||||
main.main_fuel_type = 30
|
||||
main.sap_main_heating_code = 402
|
||||
main.main_heating_control = 2401
|
||||
return epc
|
||||
|
||||
|
||||
def test_run_modelling_recommends_hhr_storage_for_an_electric_dwelling() -> None:
|
||||
# Arrange — an electrically-heated dwelling on old storage heaters; the
|
||||
# heating generator is wired into the candidate pool (ADR-0024).
|
||||
epc: EpcPropertyData = _electric_storage_lit_epc()
|
||||
|
||||
# Act — Modelling only, no database.
|
||||
plan = run_modelling(epc, goal_band="C", print_table=False)
|
||||
|
||||
# Assert — the HHR storage bundle reaches the optimised package.
|
||||
measure_types = {measure.measure_type for measure in plan.measures}
|
||||
assert "high_heat_retention_storage_heaters" in measure_types
|
||||
|
||||
|
||||
def test_sample_catalogue_prices_every_generator_measure_type() -> None:
|
||||
# Arrange — the default offline catalogue.
|
||||
products: ProductJsonRepository = ProductJsonRepository(DEFAULT_CATALOGUE)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue