mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-19 08:53:17 +00:00
117 lines
4.7 KiB
Python
117 lines
4.7 KiB
Python
"""HistoricConditioning resolves an expired Historic EPC's stable attributes
|
|
into the cohort's code spaces (ADR-0054).
|
|
|
|
Only stable attributes are resolved — volatile ones (heating system, glazing,
|
|
PV, insulation states) never condition prediction. Every resolver degrades to
|
|
None on an unresolvable value, which leaves its cohort filter inactive.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import dataclasses
|
|
|
|
from datatypes.epc.domain.historic_epc import HistoricEpc
|
|
from domain.epc_prediction.historic_conditioning import (
|
|
HistoricConditioning,
|
|
conditioning_from_historic,
|
|
)
|
|
|
|
|
|
def _hist(**overrides: str) -> HistoricEpc:
|
|
fields = {f.name: "" for f in dataclasses.fields(HistoricEpc)}
|
|
fields.update(overrides)
|
|
return HistoricEpc(**fields)
|
|
|
|
|
|
def test_resolves_stable_attributes_into_cohort_code_spaces():
|
|
# Arrange — display-text values exactly as the old register lodged them.
|
|
record = _hist(
|
|
property_type="House",
|
|
built_form="Semi-Detached",
|
|
walls_description="Cavity wall, as built, no insulation (assumed)",
|
|
roof_description="Pitched, 100 mm loft insulation",
|
|
construction_age_band="England and Wales: 1930-1949",
|
|
main_fuel="mains gas (not community)",
|
|
total_floor_area="84",
|
|
)
|
|
|
|
# Act
|
|
conditioning = conditioning_from_historic(record)
|
|
|
|
# Assert — each attribute lands in the code space its cohort filter compares.
|
|
assert isinstance(conditioning, HistoricConditioning)
|
|
assert conditioning.property_type == "0"
|
|
assert conditioning.built_form == "2"
|
|
assert conditioning.wall_construction == 4
|
|
assert conditioning.roof_form == "pitched"
|
|
assert conditioning.construction_age_band == "C"
|
|
assert conditioning.main_fuel == 26
|
|
assert conditioning.total_floor_area_m2 == 84.0
|
|
|
|
|
|
def test_roof_descriptions_resolve_to_form_families():
|
|
# Arrange / Act / Assert — the FORM half of the description (before the
|
|
# comma) maps to a family, because the API's roof_construction codes group
|
|
# that way (7,974-cert co-occurrence sweep: 1=Flat 98%, 4/5/8=Pitched
|
|
# 88-99%, 3=another dwelling above 100%; 7/9=another premises above per
|
|
# the #1452 suppression fix). Insulation state is volatile and ignored.
|
|
cases = {
|
|
"Pitched, 250 mm loft insulation": "pitched",
|
|
"Pitched, no insulation (assumed)": "pitched",
|
|
"Flat, insulated (assumed)": "flat",
|
|
"(another dwelling above)": "dwelling_above",
|
|
"(another premises above)": "premises_above",
|
|
}
|
|
for text, family in cases.items():
|
|
record = _hist(roof_description=text)
|
|
assert conditioning_from_historic(record).roof_form == family, text
|
|
# Unpinned forms (roof rooms, thatched) must not guess.
|
|
assert conditioning_from_historic(
|
|
_hist(roof_description="Roof room(s), insulated")
|
|
).roof_form is None
|
|
assert conditioning_from_historic(
|
|
_hist(roof_description="Thatched, with additional insulation")
|
|
).roof_form is None
|
|
|
|
|
|
def test_legacy_register_fuel_descriptions_resolve():
|
|
# Arrange / Act / Assert — the old register lodged pre-RdSAP-17 fuels with
|
|
# a "backwards compatibility" rider or a SAP-style prefix; they name the
|
|
# same physical fuels (dominant in the pre-2012 dump: a 65-shard scan found
|
|
# 636/663 unresolved values were these variants).
|
|
cases = {
|
|
"mains gas - this is for backwards compatibility only and should not be used": 26,
|
|
"electricity - this is for backwards compatibility only and should not be used": 29,
|
|
"LPG - this is for backwards compatibility only and should not be used": 27,
|
|
"oil - this is for backwards compatibility only and should not be used": 28,
|
|
"Gas: mains gas": 26,
|
|
"Electricity: electricity, unspecified tariff": 29,
|
|
"dual fuel - mineral + wood": 10,
|
|
}
|
|
for text, code in cases.items():
|
|
record = _hist(main_fuel=text)
|
|
assert conditioning_from_historic(record).main_fuel == code, text
|
|
|
|
|
|
def test_unresolvable_values_degrade_to_none():
|
|
# Arrange — junk and blanks must never guess a code.
|
|
record = _hist(
|
|
property_type="Castle",
|
|
built_form="Not Recorded",
|
|
walls_description="Average thermal transmittance 0.3 W/m²K",
|
|
construction_age_band="INVALID!",
|
|
main_fuel="To be used only when there is no heating system",
|
|
total_floor_area="",
|
|
)
|
|
|
|
# Act
|
|
conditioning = conditioning_from_historic(record)
|
|
|
|
# Assert
|
|
assert conditioning.property_type is None
|
|
assert conditioning.built_form is None
|
|
assert conditioning.wall_construction is None
|
|
assert conditioning.roof_form is None
|
|
assert conditioning.construction_age_band is None
|
|
assert conditioning.main_fuel is None
|
|
assert conditioning.total_floor_area_m2 is None
|