mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
feat(modelling): wire solid-wall insulation into the candidate pool
Slice 2e. recommend_solid_wall joins the orchestrator's fabric generator pool (restrictions default unrestricted until slice 3 sources them); the harness catalogue + contingencies (26%) gain external_wall_insulation / internal_wall_insulation. run_modelling on an uninsulated solid-brick dwelling (baseline SAP 36.6) now selects internal wall insulation into the optimised package; the catalogue-completeness guard covers both new measure types. Golden cohort 57/57 still error-free; IWI now fires on a real cohort cert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
0cef044503
commit
7648032d73
4 changed files with 29 additions and 2 deletions
|
|
@ -11,6 +11,8 @@ _CONTINGENCY_RATES: dict[str, float] = {
|
|||
"suspended_floor_insulation": 0.20,
|
||||
"solid_floor_insulation": 0.26,
|
||||
"mechanical_ventilation": 0.26,
|
||||
"external_wall_insulation": 0.26,
|
||||
"internal_wall_insulation": 0.26,
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,5 +3,7 @@
|
|||
"loft_insulation": { "unit_cost_per_m2": 12.0 },
|
||||
"suspended_floor_insulation": { "unit_cost_per_m2": 25.0 },
|
||||
"solid_floor_insulation": { "unit_cost_per_m2": 45.0 },
|
||||
"mechanical_ventilation": { "unit_cost_per_m2": 450.0 }
|
||||
"mechanical_ventilation": { "unit_cost_per_m2": 450.0 },
|
||||
"external_wall_insulation": { "unit_cost_per_m2": 100.0 },
|
||||
"internal_wall_insulation": { "unit_cost_per_m2": 90.0 }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ from domain.modelling.scoring.scoring import (
|
|||
marginals_from_scores,
|
||||
)
|
||||
from domain.modelling.generators.wall_recommendation import recommend_cavity_wall
|
||||
from domain.modelling.generators.solid_wall_recommendation import recommend_solid_wall
|
||||
from domain.sap10_calculator.calculator import SapCalculator
|
||||
from repositories.fuel_rates.fuel_rates_repository import FuelRatesRepository
|
||||
from repositories.product.product_repository import ProductRepository
|
||||
|
|
@ -194,6 +195,7 @@ def _candidate_recommendations(
|
|||
"""Run every fabric Recommendation Generator; keep the ones that apply."""
|
||||
generators = (
|
||||
recommend_cavity_wall,
|
||||
recommend_solid_wall,
|
||||
recommend_loft_insulation,
|
||||
recommend_floor_insulation,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,14 +10,19 @@ from datatypes.epc.domain.epc import Epc
|
|||
from datatypes.epc.domain.epc_property_data import EpcPropertyData
|
||||
from harness.console import DEFAULT_CATALOGUE, run_modelling, run_one
|
||||
from repositories.product.product_json_repository import ProductJsonRepository
|
||||
from tests.domain.modelling._elmhurst_recommendation import (
|
||||
parse_recommendation_summary,
|
||||
)
|
||||
from tests.domain.sap10_calculator.worksheet._elmhurst_worksheet_000490 import (
|
||||
build_epc as _build_uninsulated_cavity_and_floor_epc,
|
||||
)
|
||||
|
||||
# Every Measure Type the four fabric generators can emit; the harness catalogue
|
||||
# Every Measure Type the fabric generators can emit; the harness catalogue
|
||||
# must price all of them or an offline run raises mid-pipeline.
|
||||
_GENERATOR_MEASURE_TYPES = (
|
||||
"cavity_wall_insulation",
|
||||
"external_wall_insulation",
|
||||
"internal_wall_insulation",
|
||||
"loft_insulation",
|
||||
"suspended_floor_insulation",
|
||||
"solid_floor_insulation",
|
||||
|
|
@ -65,6 +70,22 @@ def test_run_modelling_inspects_a_plan_without_baseline_or_lodged_performance()
|
|||
assert len(plan.measures) >= 1
|
||||
|
||||
|
||||
def test_run_modelling_recommends_solid_wall_insulation_for_solid_brick() -> None:
|
||||
# Arrange — an uninsulated solid-brick dwelling (cert 001431 before),
|
||||
# which has no cavity to fill, so any wall measure must be solid-wall.
|
||||
epc: EpcPropertyData = parse_recommendation_summary(
|
||||
"solid_brick_ewi_001431_before.pdf"
|
||||
)
|
||||
|
||||
# Act — Modelling only, no database.
|
||||
plan = run_modelling(epc, goal_band="C", print_table=False)
|
||||
|
||||
# Assert — the solid-wall generator is wired into the candidate pool, so a
|
||||
# solid-wall Option reaches the optimised package.
|
||||
measure_types = {measure.measure_type for measure in plan.measures}
|
||||
assert measure_types & {"external_wall_insulation", "internal_wall_insulation"}
|
||||
|
||||
|
||||
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