mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
fix(mapper): map cylinder "No Insulation" to insulation_type=None
The Elmhurst §15.1 "Insulated: No Insulation" label was lodged but absent from `_ELMHURST_CYLINDER_INSULATION_LABEL_TO_SAP10`, so `_elmhurst_cylinder_insulation_code` raised UnmappedElmhurstLabel — blocking the parse of every Solar PV example cert (the solar `before` lodges "No Insulation"). An uninsulated cylinder has no insulation *type*, so per the no-misleading-insulation convention it maps to `cylinder_insulation_type = None` rather than naming a material; the lodged 0 mm thickness carries the storage-loss signal the SAP 10.2 Table 2 dispatch needs. Slice 1 of the Solar PV Recommendation Generator (ADR-0026). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
222704cbc2
commit
545bb8c328
2 changed files with 61 additions and 0 deletions
|
|
@ -4868,6 +4868,16 @@ _ELMHURST_CYLINDER_INSULATION_LABEL_TO_SAP10: Dict[str, int] = {
|
|||
"Jacket": 2,
|
||||
}
|
||||
|
||||
# Elmhurst §15.1 "Insulated" labels for an uninsulated cylinder. These are
|
||||
# lodged (not absent), but an uninsulated cylinder has no insulation *type* —
|
||||
# per the no-misleading-insulation convention it maps to
|
||||
# `cylinder_insulation_type = None` rather than naming a material. The lodged
|
||||
# §15.1 "Insulation Thickness" (0 mm) carries the storage-loss signal the
|
||||
# cascade's SAP 10.2 Table 2 dispatch needs.
|
||||
_ELMHURST_CYLINDER_NO_INSULATION_LABELS: frozenset[str] = frozenset({
|
||||
"No Insulation",
|
||||
})
|
||||
|
||||
|
||||
# Elmhurst §15.0 "Water Heating Fuel Type" labels that route to solid-
|
||||
# fuel Table 32 codes (Anthracite, House coal, Wood logs/pellets, etc.).
|
||||
|
|
@ -4978,6 +4988,8 @@ def _elmhurst_cylinder_insulation_code(
|
|||
mapping dict — see `_elmhurst_cylinder_size_code` rationale."""
|
||||
if not cylinder_present or cylinder_insulation_label is None:
|
||||
return None
|
||||
if cylinder_insulation_label in _ELMHURST_CYLINDER_NO_INSULATION_LABELS:
|
||||
return None
|
||||
code = _ELMHURST_CYLINDER_INSULATION_LABEL_TO_SAP10.get(cylinder_insulation_label)
|
||||
if code is None:
|
||||
raise UnmappedElmhurstLabel("cylinder_insulation", cylinder_insulation_label)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
"""Mapper boundary: the Elmhurst §15.1 "Insulated" cylinder label.
|
||||
|
||||
A cylinder lodged "No Insulation" is an uninsulated cylinder, not a mapper
|
||||
gap. Per the no-misleading-insulation convention it maps to
|
||||
`cylinder_insulation_type = None` (don't name an insulation material on an
|
||||
uninsulated surface) rather than raising `UnmappedElmhurstLabel`. This
|
||||
unblocks parsing every solar example cert (the solar `before` cert lodges
|
||||
"No Insulation").
|
||||
"""
|
||||
|
||||
from datatypes.epc.domain.mapper import (
|
||||
UnmappedElmhurstLabel,
|
||||
_elmhurst_cylinder_insulation_code, # pyright: ignore[reportPrivateUsage]
|
||||
)
|
||||
|
||||
|
||||
def test_no_insulation_label_maps_to_none() -> None:
|
||||
# Arrange
|
||||
label = "No Insulation"
|
||||
|
||||
# Act
|
||||
code = _elmhurst_cylinder_insulation_code(label, cylinder_present=True)
|
||||
|
||||
# Assert
|
||||
assert code is None
|
||||
|
||||
|
||||
def test_foam_label_still_maps_to_factory_code() -> None:
|
||||
# Arrange
|
||||
label = "Foam"
|
||||
|
||||
# Act
|
||||
code = _elmhurst_cylinder_insulation_code(label, cylinder_present=True)
|
||||
|
||||
# Assert
|
||||
assert code == 1
|
||||
|
||||
|
||||
def test_unknown_label_still_raises() -> None:
|
||||
# Arrange
|
||||
label = "Spray-on unicorn felt"
|
||||
|
||||
# Act / Assert
|
||||
try:
|
||||
_elmhurst_cylinder_insulation_code(label, cylinder_present=True)
|
||||
raised = False
|
||||
except UnmappedElmhurstLabel:
|
||||
raised = True
|
||||
assert raised
|
||||
Loading…
Add table
Reference in a new issue