From 38448e47cc6c5f939221bf2540017352669c89f6 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Wed, 1 Jul 2026 11:04:24 +0000 Subject: [PATCH] =?UTF-8?q?Classify=20an=20aggregate-mix=20glazing=20descr?= =?UTF-8?q?iption=20as=20MIXED=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../property_overrides/glazing_mix_guard.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/domain/epc/property_overrides/glazing_mix_guard.py b/domain/epc/property_overrides/glazing_mix_guard.py index 83f4c45c0..36d8fce58 100644 --- a/domain/epc/property_overrides/glazing_mix_guard.py +++ b/domain/epc/property_overrides/glazing_mix_guard.py @@ -1,9 +1,17 @@ from __future__ import annotations +import re from typing import Optional from domain.epc.property_overrides.glazing_type import GlazingType +# "N% " — the era (2002 / pre-2002) is irrelevant to whether it +# is a mix, so only the base type is captured. +_PERCENT_TYPE = re.compile(r"(\d+)%\s*(single|double|triple|secondary)") +# One base type at or above this share is a uniform assertion, not a mix — applied +# as that type (a near-uniform reglaze), not deferred. +_UNIFORM_THRESHOLD_PERCENT = 90 + def glazing_mix_guard(description: str) -> Optional[GlazingType]: """Deterministically resolve an aggregate-mix glazing description to ``MIXED``. @@ -21,4 +29,12 @@ def glazing_mix_guard(description: str) -> Optional[GlazingType]: uniform assertion or an unparseable description, so the LLM classifier still resolves it (a uniform reglaze is applied; varied phrasings are the LLM's job). """ - raise NotImplementedError + matches = _PERCENT_TYPE.findall(description.lower()) + base_types = {base_type for _, base_type in matches} + if len(base_types) < 2: + # One (or no) glazing type named — a uniform assertion, not a mix. + return None + if max(int(percent) for percent, _ in matches) >= _UNIFORM_THRESHOLD_PERCENT: + # One type dominates — treat as that (near-)uniform type, not a mix. + return None + return GlazingType.MIXED