Classify an aggregate-mix glazing description as MIXED 🟩

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-07-01 11:04:24 +00:00
parent f959cc14c9
commit 38448e47cc

View file

@ -1,9 +1,17 @@
from __future__ import annotations
import re
from typing import Optional
from domain.epc.property_overrides.glazing_type import GlazingType
# "N% <base glazing type>" — 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