mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-27 23:35:01 +00:00
Extract the PasHub detailed room-in-roof block 🟩
_parse_room_in_roof captures the RdSAP §3.10 block (age range, floor area, gables with Exposed/Party type, slopes, common walls, flat ceiling as length x height) on main and extension roof spaces; both part builders now carry it to sap_room_in_roof (issue #1590 bug 5 — closes the last #1590 subtask). Harness MAE 1.748 (754917 corrects to pashub's own pre-SAP; RIR surfaces now billed per-surface instead of as insulated loft). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
518c682793
commit
955b4dc1e8
2 changed files with 48 additions and 0 deletions
|
|
@ -19,6 +19,8 @@ from datatypes.epc.surveys.pashub_rdsap_site_notes import (
|
|||
MainHeating,
|
||||
PasHubRdSapSiteNotes,
|
||||
PvArrayDetail,
|
||||
RoomInRoofDetail,
|
||||
RoomInRoofSurfaceDetail,
|
||||
Renewables,
|
||||
RoomCountElements,
|
||||
RoofSpace,
|
||||
|
|
@ -672,6 +674,49 @@ class PasHubRdSapSiteNotesExtractor:
|
|||
except (ValueError, IndexError):
|
||||
return None, val
|
||||
|
||||
def _parse_rir_surface(
|
||||
self, data: List[str], prefix: str, with_type: bool = False
|
||||
) -> Optional[RoomInRoofSurfaceDetail]:
|
||||
"""One room-in-roof surface's "{prefix} length/height[/type]" lines
|
||||
("6.64 m" → 6.64). None when the surface isn't lodged."""
|
||||
length = self._get_in(data, f"{prefix} length:")
|
||||
height = self._get_in(data, f"{prefix} height:")
|
||||
if length is None and height is None:
|
||||
return None
|
||||
return RoomInRoofSurfaceDetail(
|
||||
length_m=float(length.split()[0]) if length else None,
|
||||
height_m=float(height.split()[0]) if height else None,
|
||||
gable_type=self._get_in(data, f"{prefix} type:") if with_type else None,
|
||||
)
|
||||
|
||||
def _parse_room_in_roof(self, data: List[str]) -> Optional[RoomInRoofDetail]:
|
||||
"""The RdSAP §3.10 detailed room-in-roof block lodged under "Are there
|
||||
rooms in the roof? Yes" — dropped detail bills ~the whole RIR shell as
|
||||
well-insulated loft (issue #1590 bug 5)."""
|
||||
if not self._bool_in(data, "Are there rooms in the roof?"):
|
||||
return None
|
||||
area_raw = self._get_in(data, "Floor area of room in roof:")
|
||||
|
||||
def surfaces(
|
||||
prefix: str, with_type: bool = False
|
||||
) -> Optional[List[RoomInRoofSurfaceDetail]]:
|
||||
out = [
|
||||
s
|
||||
for n in (1, 2)
|
||||
if (s := self._parse_rir_surface(data, f"{prefix} {n}", with_type))
|
||||
is not None
|
||||
]
|
||||
return out or None
|
||||
|
||||
return RoomInRoofDetail(
|
||||
age_range=self._get_in(data, "Roof room age range:"),
|
||||
floor_area_m2=float(area_raw.split()[0]) if area_raw else None,
|
||||
gables=surfaces("Gable wall", with_type=True),
|
||||
slopes=surfaces("Slope"),
|
||||
common_walls=surfaces("Common wall"),
|
||||
flat_ceilings=surfaces("Flat ceiling"),
|
||||
)
|
||||
|
||||
def _parse_roof_space_detail(self, data: List[str]) -> RoofSpaceDetail:
|
||||
thickness_mm, thickness_str = self._parse_insulation_thickness(
|
||||
self._get_in(data, "Roofs - Insulation Thickness:")
|
||||
|
|
@ -687,6 +732,7 @@ class PasHubRdSapSiteNotesExtractor:
|
|||
rooms_in_roof=self._bool_in(data, "Are there rooms in the roof?"),
|
||||
insulation_thickness_mm=thickness_mm,
|
||||
insulation_thickness=thickness_str,
|
||||
room_in_roof=self._parse_room_in_roof(data),
|
||||
)
|
||||
|
||||
def _parse_extension_roof_space(
|
||||
|
|
@ -707,6 +753,7 @@ class PasHubRdSapSiteNotesExtractor:
|
|||
rooms_in_roof=self._bool_in(data, "Are there rooms in the roof?"),
|
||||
insulation_thickness_mm=thickness_mm,
|
||||
insulation_thickness=thickness_str,
|
||||
room_in_roof=self._parse_room_in_roof(data),
|
||||
)
|
||||
|
||||
def _parse_floor_measurements(self, data: List[str]) -> List[FloorMeasurement]:
|
||||
|
|
|
|||
|
|
@ -6085,6 +6085,7 @@ def _map_extension_building_part(
|
|||
roof_location, roof_thickness = _map_roof(roof)
|
||||
return SapBuildingPart(
|
||||
identifier=BuildingPartIdentifier.extension(ext_c.id),
|
||||
sap_room_in_roof=_pashub_room_in_roof(roof) if roof is not None else None,
|
||||
construction_age_band=_extract_age_band(ext_c.age_range),
|
||||
# PasHub surveys never lodge a basement wall; pin the flag so a
|
||||
# "System Build" wall (code 6, which doubles as the gov-API basement
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue