mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
feat(modelling): roof dispatcher insulates a flat roof
Slice 3 (ADR-0021). The dispatcher gains a flat-roof branch: a "flat" roof_construction_type with no lodged thickness (uninsulated → None on the Elmhurst path) gets a single flat_roof_insulation Option whose overlay raises roof_insulation_thickness to 200 mm — tested before the loft fallback so a flat roof's None doesn't trip the loft trigger. Pinned against the Elmhurst before→after cert at 1e-4. Golden cohort roof firing unchanged (none across 57). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
7d40cddf3b
commit
13b18ce9fb
4 changed files with 42 additions and 0 deletions
|
|
@ -32,6 +32,9 @@ _ROOF_UNINSULATED_MM = 0
|
|||
_RECOMMENDED_LOFT_THICKNESS_MM = 300
|
||||
# Recommended sloping-ceiling depth (mm); Elmhurst re-lodges 100 mm (ADR-0021).
|
||||
_RECOMMENDED_SLOPING_CEILING_THICKNESS_MM = 100
|
||||
_FLAT_ROOF_MEASURE_TYPE = "flat_roof_insulation"
|
||||
# Recommended flat-roof depth (mm); Elmhurst re-lodges 200 mm (ADR-0021).
|
||||
_RECOMMENDED_FLAT_ROOF_THICKNESS_MM = 200
|
||||
|
||||
|
||||
def recommend_roof_insulation(
|
||||
|
|
@ -65,6 +68,19 @@ def recommend_roof_insulation(
|
|||
thickness_mm=_RECOMMENDED_SLOPING_CEILING_THICKNESS_MM,
|
||||
)
|
||||
|
||||
if "flat" in roof_type:
|
||||
# A flat roof lodges no thickness when uninsulated ("As Built" → None
|
||||
# on the Elmhurst path); a lodged thickness means it's already done.
|
||||
if main.roof_insulation_thickness is not None:
|
||||
return None
|
||||
return _roof_recommendation(
|
||||
epc,
|
||||
products,
|
||||
measure_type=_FLAT_ROOF_MEASURE_TYPE,
|
||||
description="Flat-roof insulation",
|
||||
thickness_mm=_RECOMMENDED_FLAT_ROOF_THICKNESS_MM,
|
||||
)
|
||||
|
||||
if "no access" in roof_type:
|
||||
return None # the roof void can't be reached to insulate it
|
||||
|
||||
|
|
|
|||
BIN
tests/domain/modelling/fixtures/flat_roof_001431_after.pdf
Normal file
BIN
tests/domain/modelling/fixtures/flat_roof_001431_after.pdf
Normal file
Binary file not shown.
BIN
tests/domain/modelling/fixtures/flat_roof_001431_before.pdf
Normal file
BIN
tests/domain/modelling/fixtures/flat_roof_001431_before.pdf
Normal file
Binary file not shown.
|
|
@ -392,6 +392,32 @@ def test_roof_generator_insulates_a_thatched_roof_as_loft_pinning_its_after() ->
|
|||
)
|
||||
|
||||
|
||||
def test_roof_generator_insulates_a_flat_roof_pinning_its_after() -> None:
|
||||
# Arrange — a flat roof, uninsulated (As Built → None on the Elmhurst path);
|
||||
# the re-lodged after raises it to 200 mm (ADR-0021).
|
||||
before: EpcPropertyData = parse_recommendation_summary(
|
||||
"flat_roof_001431_before.pdf"
|
||||
)
|
||||
after: EpcPropertyData = parse_recommendation_summary(
|
||||
"flat_roof_001431_after.pdf"
|
||||
)
|
||||
|
||||
# Act
|
||||
recommendation: Recommendation | None = recommend_roof_insulation(
|
||||
before, _AnyProduct()
|
||||
)
|
||||
assert recommendation is not None
|
||||
options: dict[str, MeasureOption] = {
|
||||
option.measure_type: option for option in recommendation.options
|
||||
}
|
||||
|
||||
# Assert — one flat-roof Option whose overlay reproduces the after.
|
||||
assert set(options) == {"flat_roof_insulation"}
|
||||
_assert_overlay_reproduces_after(
|
||||
before, after, options["flat_roof_insulation"].overlay
|
||||
)
|
||||
|
||||
|
||||
def test_solid_floor_overlay_reproduces_the_relodged_after() -> None:
|
||||
# Arrange
|
||||
before: EpcPropertyData = parse_recommendation_summary(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue