mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
Predict ventilation kind from the cohort mode 🟥
Prediction never synthesises ventilation — it keeps the size-template's sap_ventilation, so a predicted dwelling in an MEV/MVHR neighbourhood is scored + displayed as natural (predicted property 721167 follow-up). Mode the mechanical_ventilation_kind across the cohort like glazing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
44726469d4
commit
80c5ad0c6c
1 changed files with 31 additions and 0 deletions
|
|
@ -17,6 +17,7 @@ from datatypes.epc.domain.epc_property_data import (
|
|||
SapEnergySource,
|
||||
SapFloorDimension,
|
||||
SapHeating,
|
||||
SapVentilation,
|
||||
SapWindow,
|
||||
)
|
||||
from domain.geospatial.coordinates import Coordinates
|
||||
|
|
@ -54,6 +55,7 @@ def _epc(
|
|||
meter_type: str = "2",
|
||||
main_heating_label: str = "Boiler and radiators, mains gas",
|
||||
main_heating_controls_label: Optional[str] = None,
|
||||
mechanical_ventilation_kind: Optional[str] = None,
|
||||
) -> EpcPropertyData:
|
||||
epc: EpcPropertyData = object.__new__(EpcPropertyData)
|
||||
epc.property_type = "2"
|
||||
|
|
@ -108,6 +110,10 @@ def _epc(
|
|||
)
|
||||
epc.has_hot_water_cylinder = has_hot_water_cylinder
|
||||
epc.solar_water_heating = solar_water_heating
|
||||
epc.sap_ventilation = SapVentilation(
|
||||
mechanical_ventilation_kind=mechanical_ventilation_kind,
|
||||
sheltered_sides=1,
|
||||
)
|
||||
energy: SapEnergySource = object.__new__(SapEnergySource)
|
||||
energy.meter_type = meter_type
|
||||
epc.sap_energy_source = energy
|
||||
|
|
@ -557,6 +563,31 @@ def test_heating_is_a_coherent_donor_not_the_structural_template() -> None:
|
|||
assert predicted.has_hot_water_cylinder is True
|
||||
|
||||
|
||||
def test_ventilation_kind_follows_the_cohort_mode() -> None:
|
||||
# Mechanical ventilation (MEV/MVHR) is a new-build / retrofit feature that
|
||||
# clusters by era and street — like glazing — so the predicted ventilation
|
||||
# kind takes the recency/geo-weighted cohort mode, not the size-template's.
|
||||
# The size-closest template here is natural (None); the cohort is
|
||||
# predominantly MVHR, so the prediction must reflect the MVHR neighbourhood
|
||||
# rather than leave the template's empty ventilation (predicted property
|
||||
# 721167 follow-up). Natural-vent cohorts mode to None and stay natural.
|
||||
cohort = _cohort(
|
||||
_epc(mechanical_ventilation_kind=None), # template (size tie → first)
|
||||
_epc(mechanical_ventilation_kind="MVHR"),
|
||||
_epc(mechanical_ventilation_kind="MVHR"),
|
||||
_epc(mechanical_ventilation_kind="MVHR"),
|
||||
)
|
||||
|
||||
# Act
|
||||
predicted: EpcPropertyData = EpcPrediction().predict(
|
||||
PredictionTarget(postcode="LS6 1AA", property_type="2"), cohort
|
||||
)
|
||||
|
||||
# Assert — the predicted kind is the cohort's MVHR mode, not the template's None.
|
||||
assert predicted.sap_ventilation is not None
|
||||
assert predicted.sap_ventilation.mechanical_ventilation_kind == "MVHR"
|
||||
|
||||
|
||||
def test_glazing_follows_the_recency_weighted_cohort_mode() -> None:
|
||||
# Arrange — an old majority single-glazed (type 1, 2015) and a recent
|
||||
# minority double-glazed (type 3, 2025). Glazing is retrofitted over time
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue