Model/domain/epc/property_overrides/main_heating_guard.py
Khalim Conn-Kowlessar 9d106d9d6d Deterministically guard the electric-underfloor descriptions 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 16:48:45 +00:00

53 lines
2.5 KiB
Python

from __future__ import annotations
from typing import Optional
from domain.epc.property_overrides.main_heating_system_type import (
MainHeatingSystemType,
)
def main_heating_guard(description: str) -> Optional[MainHeatingSystemType]:
"""Deterministically resolve the structured main-heating descriptions the LLM
funnelled into a garbage-drawer archetype for want of a correct target (#1376).
Two dumping grounds are rescued:
- **HHRSH** (ADR-0044): ``"…High heat retention storage heaters"`` went to
``"Electric storage heaters, old"`` (SAP 401) — the *worst* old type. HHRSH is
SAP Table 4a 409 with its own intrinsic charge control (2404).
- **Gas CPSU** (ADR-0045): the mains-gas CPSU garbage drawer also held
solid-fuel room heaters (open fire 631 / + back boiler 632 / closed + boiler
634) and electric ``"NA"``-type boilers (SAP 191). "NA" is the boiler-type
value meaning "not a gas combi/regular/CPSU", i.e. an electric boiler.
- **Electric underfloor** (ADR-0046): dumped into Direct-acting (191) / old
storage (401) for want of the dedicated SAP underfloor codes — in concrete
slab (421, off-peak), integrated storage+direct-acting (422), in screed (424,
meter deferred to the cert).
Returns ``None`` for descriptions the LLM already classifies correctly (genuine
gas boilers, other storage subtypes, a plain closed room heater) and for varied
phrasings, so they still reach the LLM via ``GuardedColumnClassifier``. Order
matters: the back-boiler open fire is tested before the bare open fire it
contains.
"""
text = description.lower()
if "high heat retention" in text:
return MainHeatingSystemType.ELECTRIC_STORAGE_HIGH_HEAT_RETENTION
if "underfloor" in text:
if "concrete slab" in text:
return MainHeatingSystemType.ELECTRIC_UNDERFLOOR_SLAB_OFF_PEAK
if "integrated" in text:
return MainHeatingSystemType.ELECTRIC_UNDERFLOOR_INTEGRATED
if "screed" in text:
return MainHeatingSystemType.ELECTRIC_UNDERFLOOR_SCREED
return None
if "rated na" in text:
return MainHeatingSystemType.ELECTRIC_BOILER
if "open fire" in text and "back boiler" in text:
return MainHeatingSystemType.SOLID_FUEL_ROOM_HEATER_OPEN_FIRE_BACK_BOILER
if "open fire" in text:
return MainHeatingSystemType.SOLID_FUEL_ROOM_HEATER_OPEN_FIRE
if "closed room heater" in text and "with boiler" in text:
return MainHeatingSystemType.SOLID_FUEL_ROOM_HEATER_CLOSED_WITH_BOILER
return None