mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
feat(modelling): floor insulation-type overlay field + cascade pins (#1159)
Completes #1159 end-to-end with solid and suspended-floor before/after cascade pins on cert 001431, both closing at delta 0.000000. Adds floor_insulation_type_str to BuildingPartOverlay (the generic field-fold applicator picks it up with no change) and has recommend_floor_insulation set it to "Retro-fitted". Insulating an as-built floor re-lodges its insulation as retro-fitted; the calculator keys on this for a suspended timber floor's sealed/unsealed determination (cert_to_inputs.py: "retro" + no U-value supplied → sealed). Without it the suspended-floor cascade left a +1.40 SAP gap (the floor stayed "unsealed", wrong U-value); with it the cascade closes exactly. Solid floors are unaffected by the seal logic and stay at delta 0; both Elmhurst after-certs lodge "Retro-fitted", so setting it uniformly is faithful. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
44d62c0c9b
commit
a0b6a952c3
7 changed files with 48 additions and 1 deletions
|
|
@ -21,6 +21,12 @@ from repositories.product.product_repository import ProductRepository
|
|||
|
||||
# Recommended ground-floor insulation depth (mm).
|
||||
_RECOMMENDED_FLOOR_THICKNESS_MM = 100
|
||||
# Insulating an as-built floor re-lodges its insulation as retro-fitted. The
|
||||
# calculator keys on this for a suspended timber floor's sealed/unsealed
|
||||
# determination (cert_to_inputs: "retro" + no U-value → sealed), so the
|
||||
# overlay must set it or the suspended-floor cascade leaves a ~1.4 SAP gap
|
||||
# (see test_elmhurst_cascade_pins).
|
||||
_RETROFITTED_INSULATION = "Retro-fitted"
|
||||
|
||||
|
||||
def _is_uninsulated(thickness: Optional[Union[str, int]]) -> bool:
|
||||
|
|
@ -75,7 +81,8 @@ def recommend_floor_insulation(
|
|||
overlay=EpcSimulation(
|
||||
building_parts={
|
||||
BuildingPartIdentifier.MAIN: BuildingPartOverlay(
|
||||
floor_insulation_thickness=_RECOMMENDED_FLOOR_THICKNESS_MM
|
||||
floor_insulation_thickness=_RECOMMENDED_FLOOR_THICKNESS_MM,
|
||||
floor_insulation_type_str=_RETROFITTED_INSULATION,
|
||||
)
|
||||
}
|
||||
),
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ class BuildingPartOverlay:
|
|||
wall_insulation_type: Optional[int] = None
|
||||
roof_insulation_thickness: Optional[int] = None
|
||||
floor_insulation_thickness: Optional[int] = None
|
||||
floor_insulation_type_str: Optional[str] = None
|
||||
|
||||
|
||||
def _no_building_parts() -> dict[BuildingPartIdentifier, BuildingPartOverlay]:
|
||||
|
|
|
|||
BIN
tests/domain/modelling/fixtures/solid_floor_001431_after.pdf
Normal file
BIN
tests/domain/modelling/fixtures/solid_floor_001431_after.pdf
Normal file
Binary file not shown.
BIN
tests/domain/modelling/fixtures/solid_floor_001431_before.pdf
Normal file
BIN
tests/domain/modelling/fixtures/solid_floor_001431_before.pdf
Normal file
Binary file not shown.
BIN
tests/domain/modelling/fixtures/suspended_floor_001431_after.pdf
Normal file
BIN
tests/domain/modelling/fixtures/suspended_floor_001431_after.pdf
Normal file
Binary file not shown.
Binary file not shown.
|
|
@ -20,6 +20,7 @@ from datatypes.epc.domain.epc_property_data import EpcPropertyData
|
|||
from domain.modelling.package_scorer import PackageScorer, Score
|
||||
from domain.modelling.product import Product
|
||||
from domain.modelling.recommendation import Recommendation
|
||||
from domain.modelling.floor_recommendation import recommend_floor_insulation
|
||||
from domain.modelling.roof_recommendation import recommend_loft_insulation
|
||||
from domain.modelling.simulation import EpcSimulation
|
||||
from domain.modelling.wall_recommendation import recommend_cavity_wall
|
||||
|
|
@ -99,3 +100,41 @@ def test_loft_overlay_reproduces_the_relodged_after() -> None:
|
|||
_assert_overlay_reproduces_after(
|
||||
before, after, recommendation.options[0].overlay
|
||||
)
|
||||
|
||||
|
||||
def test_solid_floor_overlay_reproduces_the_relodged_after() -> None:
|
||||
# Arrange
|
||||
before: EpcPropertyData = parse_recommendation_summary(
|
||||
"solid_floor_001431_before.pdf"
|
||||
)
|
||||
after: EpcPropertyData = parse_recommendation_summary(
|
||||
"solid_floor_001431_after.pdf"
|
||||
)
|
||||
recommendation: Recommendation | None = recommend_floor_insulation(
|
||||
before, _AnyProduct()
|
||||
)
|
||||
assert recommendation is not None
|
||||
|
||||
# Act / Assert
|
||||
_assert_overlay_reproduces_after(
|
||||
before, after, recommendation.options[0].overlay
|
||||
)
|
||||
|
||||
|
||||
def test_suspended_floor_overlay_reproduces_the_relodged_after() -> None:
|
||||
# Arrange
|
||||
before: EpcPropertyData = parse_recommendation_summary(
|
||||
"suspended_floor_001431_before.pdf"
|
||||
)
|
||||
after: EpcPropertyData = parse_recommendation_summary(
|
||||
"suspended_floor_001431_after.pdf"
|
||||
)
|
||||
recommendation: Recommendation | None = recommend_floor_insulation(
|
||||
before, _AnyProduct()
|
||||
)
|
||||
assert recommendation is not None
|
||||
|
||||
# Act / Assert
|
||||
_assert_overlay_reproduces_after(
|
||||
before, after, recommendation.options[0].overlay
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue