"""Behaviour of the floor Recommendation Generator: detecting an uninsulated ground floor and its construction (suspended vs solid), emitting the matching single insulation Option with overlay + priced Cost. A floor is one construction, so this is a single-Option Recommendation (like cavity walls). """ from datatypes.epc.domain.epc_property_data import ( BuildingPartIdentifier, EpcPropertyData, SapBuildingPart, ) from domain.modelling.scoring.overlay_applicator import apply_simulations from domain.modelling.product import Product from domain.modelling.recommendation import Recommendation from domain.modelling.generators.floor_recommendation import recommend_floor_insulation from repositories.product.product_repository import ProductRepository from tests.domain.sap10_calculator.worksheet._elmhurst_worksheet_000490 import ( build_epc, ) class _StubProducts(ProductRepository): def get(self, measure_type: str) -> Product: return Product( measure_type=measure_type, unit_cost_per_m2=25.0, contingency_rate=0.20 ) def _main(epc: EpcPropertyData) -> SapBuildingPart: return next( p for p in epc.sap_building_parts if p.identifier is BuildingPartIdentifier.MAIN ) def test_uninsulated_suspended_floor_yields_suspended_insulation() -> None: # Arrange — 000490 MAIN: "Suspended timber", "As built" (uninsulated) baseline: EpcPropertyData = build_epc() # Act recommendation: Recommendation | None = recommend_floor_insulation( baseline, _StubProducts() ) # Assert assert recommendation is not None assert recommendation.surface == "Ground floor" assert len(recommendation.options) == 1 option = recommendation.options[0] assert option.measure_type == "suspended_floor_insulation" simulated: EpcPropertyData = apply_simulations(baseline, [option.overlay]) assert _main(simulated).floor_insulation_thickness == 100 def test_uninsulated_solid_floor_yields_solid_insulation() -> None: # Arrange baseline: EpcPropertyData = build_epc() _main(baseline).floor_construction_type = "Solid" # Act recommendation: Recommendation | None = recommend_floor_insulation( baseline, _StubProducts() ) # Assert assert recommendation is not None assert recommendation.options[0].measure_type == "solid_floor_insulation" def test_at_regs_age_band_floor_yields_no_recommendation() -> None: # Arrange — a solid ground floor lodged as-built at construction age band # L (2012-2022). RdSAP's BS EN ISO 13370 cascade assigns it the at-regs # U-value and 100 mm of added insulation resolves to the same (or a # no-better) value — the measure cannot change the modelled floor, so # offering it sells £3-4k of insulation for +0.00 SAP (portfolio 796: # properties 709782/709790). The Floor U-Value Gate withholds it — the # floor arm of ADR-0051's deferred follow-up. baseline: EpcPropertyData = build_epc() main: SapBuildingPart = _main(baseline) main.floor_construction_type = "Solid" main.construction_age_band = "L" # Act recommendation: Recommendation | None = recommend_floor_insulation( baseline, _StubProducts() ) # Assert assert recommendation is None def test_already_insulated_floor_yields_no_recommendation() -> None: # Arrange baseline: EpcPropertyData = build_epc() _main(baseline).floor_insulation_thickness = "100" # Act recommendation: Recommendation | None = recommend_floor_insulation( baseline, _StubProducts() ) # Assert assert recommendation is None def test_floor_option_carries_cost_from_ground_floor_area_and_product() -> None: # Arrange — 000490 MAIN ground floor area 14.85 m^2 baseline: EpcPropertyData = build_epc() # Act recommendation: Recommendation | None = recommend_floor_insulation( baseline, _StubProducts() ) # Assert assert recommendation is not None cost = recommendation.options[0].cost assert cost is not None assert abs(cost.total - 14.85 * 25.0) <= 0.01 assert abs(cost.contingency_rate - 0.20) <= 1e-9