mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
Historic stable attributes condition cohort selection on the relax ladder 🟩
Age band (Table S1 letter), main fuel code, and a ±5% floor-area band — the first numeric-tolerance filter — each ride _maybe_filter, so an unresolved attribute (None) is inactive and a starving filter relaxes. Existing callers pass no new fields and are behaviourally untouched. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
248aa5ad6a
commit
d2d696a1c5
1 changed files with 37 additions and 0 deletions
|
|
@ -21,6 +21,10 @@ from domain.geospatial.coordinates import Coordinates
|
|||
# else it is relaxed (ADR-0029 filter-then-relax ladder).
|
||||
_DEFAULT_MINIMUM_COHORT = 5
|
||||
|
||||
# Half-width of the floor-area conditioning band: an expired Historic EPC's
|
||||
# observed floor area keeps comparables within ±5% of it (ADR-0054).
|
||||
_FLOOR_AREA_TOLERANCE = 0.05
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ComparableProperty:
|
||||
|
|
@ -88,6 +92,27 @@ def select_comparables(
|
|||
active=target.wall_construction is not None,
|
||||
minimum_cohort=minimum_cohort,
|
||||
)
|
||||
cohort = _maybe_filter(
|
||||
cohort,
|
||||
lambda c: _main_construction_age_band(c) == target.construction_age_band,
|
||||
active=target.construction_age_band is not None,
|
||||
minimum_cohort=minimum_cohort,
|
||||
)
|
||||
cohort = _maybe_filter(
|
||||
cohort,
|
||||
lambda c: _main_fuel_type(c) == target.main_fuel,
|
||||
active=target.main_fuel is not None,
|
||||
minimum_cohort=minimum_cohort,
|
||||
)
|
||||
target_area = target.total_floor_area_m2
|
||||
cohort = _maybe_filter(
|
||||
cohort,
|
||||
lambda c: target_area is not None
|
||||
and abs(c.epc.total_floor_area_m2 - target_area)
|
||||
<= _FLOOR_AREA_TOLERANCE * target_area,
|
||||
active=target_area is not None,
|
||||
minimum_cohort=minimum_cohort,
|
||||
)
|
||||
return ComparableProperties(members=tuple(cohort))
|
||||
|
||||
|
||||
|
|
@ -124,3 +149,15 @@ def _main_wall_construction(comparable: ComparableProperty) -> object:
|
|||
"""The main building part's wall construction, or None when no part lodged."""
|
||||
parts = comparable.epc.sap_building_parts
|
||||
return parts[0].wall_construction if parts else None
|
||||
|
||||
|
||||
def _main_construction_age_band(comparable: ComparableProperty) -> object:
|
||||
"""The main building part's Table S1 band letter, or None when no part lodged."""
|
||||
parts = comparable.epc.sap_building_parts
|
||||
return parts[0].construction_age_band if parts else None
|
||||
|
||||
|
||||
def _main_fuel_type(comparable: ComparableProperty) -> object:
|
||||
"""The primary heating fuel code, or None when no main heating lodged."""
|
||||
details = comparable.epc.sap_heating.main_heating_details
|
||||
return details[0].main_fuel_type if details else None
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue