mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-27 23:35:01 +00:00
Carry the surveyed room-in-roof block onto the SAP building part 🟩
_pashub_room_in_roof mirrors _api_build_room_in_roof: every surveyed RIR surface (gable typed Exposed/Party per Table 4, slopes, common walls, flat ceiling) becomes a detailed_surfaces entry of length x height, so the cascade bills exact RIR surfaces instead of treating the shell as well-insulated loft (issue #1590 bug 5). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9599fd8239
commit
0ca5108584
1 changed files with 60 additions and 0 deletions
|
|
@ -154,6 +154,7 @@ from datatypes.epc.surveys.pashub_rdsap_site_notes import (
|
|||
HeatingAndHotWater,
|
||||
PasHubRdSapSiteNotes,
|
||||
Renewables as PasHubRenewables,
|
||||
RoomInRoofSurfaceDetail,
|
||||
RoofSpaceDetail,
|
||||
Ventilation,
|
||||
WaterUse,
|
||||
|
|
@ -5979,6 +5980,64 @@ def _map_roof(
|
|||
return roof.insulation_at or None, thickness
|
||||
|
||||
|
||||
# PasHub gable "type" label → the Table 4 surface kind the cascade's
|
||||
# per-surface RR branch dispatches on (Exposed = as-common-wall U,
|
||||
# Party = 0.25 W/m²K).
|
||||
_PASHUB_GABLE_TYPE_TO_KIND: Dict[str, str] = {
|
||||
"Exposed": "gable_wall_external",
|
||||
"Party": "gable_wall",
|
||||
}
|
||||
|
||||
|
||||
def _pashub_room_in_roof(
|
||||
roof: Union[RoofSpaceDetail, ExtensionRoofSpace],
|
||||
) -> Optional[SapRoomInRoof]:
|
||||
"""Build `SapRoomInRoof` from the surveyed §Roof-Space room-in-roof block
|
||||
(RdSAP §3.10 detailed measurement), mirroring `_api_build_room_in_roof`:
|
||||
every surveyed surface (gable / slope / common wall / flat ceiling)
|
||||
becomes a `detailed_surfaces` entry of length × height, so the cascade
|
||||
bills exact RIR surfaces instead of treating the whole shell as
|
||||
well-insulated loft (issue #1590 bug 5). Returns None when no RIR is
|
||||
lodged. A gable with an unmapped type label strict-raises."""
|
||||
rir = roof.room_in_roof
|
||||
if not roof.rooms_in_roof or rir is None:
|
||||
return None
|
||||
surfaces: List[SapRoomInRoofSurface] = []
|
||||
|
||||
def _add(
|
||||
details: Optional[List[RoomInRoofSurfaceDetail]], kind: Optional[str]
|
||||
) -> None:
|
||||
for d in details or []:
|
||||
if d.length_m is None or d.height_m is None:
|
||||
continue
|
||||
surface_kind = kind
|
||||
if surface_kind is None: # gable — kind from the surveyed type
|
||||
if d.gable_type not in _PASHUB_GABLE_TYPE_TO_KIND:
|
||||
raise UnmappedPasHubLabel(
|
||||
"room-in-roof gable type", str(d.gable_type)
|
||||
)
|
||||
surface_kind = _PASHUB_GABLE_TYPE_TO_KIND[d.gable_type]
|
||||
surfaces.append(
|
||||
SapRoomInRoofSurface(
|
||||
kind=surface_kind,
|
||||
area_m2=d.length_m * d.height_m,
|
||||
u_value=d.u_value,
|
||||
)
|
||||
)
|
||||
|
||||
_add(rir.gables, None)
|
||||
_add(rir.slopes, "slope")
|
||||
_add(rir.common_walls, "common_wall")
|
||||
_add(rir.flat_ceilings, "flat_ceiling")
|
||||
if rir.floor_area_m2 is None:
|
||||
return None
|
||||
return SapRoomInRoof(
|
||||
floor_area=rir.floor_area_m2,
|
||||
construction_age_band=_extract_age_band(rir.age_range or ""),
|
||||
detailed_surfaces=surfaces or None,
|
||||
)
|
||||
|
||||
|
||||
def _map_main_building_part(
|
||||
construction: BuildingConstruction,
|
||||
measurements: BuildingMeasurements,
|
||||
|
|
@ -5989,6 +6048,7 @@ def _map_main_building_part(
|
|||
roof_location, roof_thickness = _map_roof(roof)
|
||||
return SapBuildingPart(
|
||||
identifier=BuildingPartIdentifier.MAIN,
|
||||
sap_room_in_roof=_pashub_room_in_roof(roof),
|
||||
construction_age_band=_extract_age_band(main.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