diff --git a/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_100061275133/elmhurst_summary.pdf b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_100061275133/elmhurst_summary.pdf new file mode 100644 index 000000000..7e17907d9 Binary files /dev/null and b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_100061275133/elmhurst_summary.pdf differ diff --git a/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_100061275133/elmhurst_worksheet.pdf b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_100061275133/elmhurst_worksheet.pdf new file mode 100644 index 000000000..da423eee1 Binary files /dev/null and b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_100061275133/elmhurst_worksheet.pdf differ diff --git a/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_100061275133/epc.json b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_100061275133/epc.json new file mode 100644 index 000000000..43225f661 --- /dev/null +++ b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_100061275133/epc.json @@ -0,0 +1,410 @@ +{ + "uprn": 100061275133, + "roofs": [ + { + "description": "Pitched, 300 mm loft insulation", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + } + ], + "walls": [ + { + "description": "Solid brick, with external insulation", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "floors": [ + { + "description": "Suspended, no insulation (assumed)", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + } + ], + "status": "entered", + "tenure": 2, + "window": { + "description": "High performance glazing", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + }, + "lighting": { + "description": "Excellent lighting efficiency", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + }, + "postcode": "ME7 2ES", + "hot_water": { + "description": "From main system", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + }, + "post_town": "GILLINGHAM", + "built_form": 2, + "created_at": "2026-05-20 08:39:48", + "door_count": 2, + "region_code": 14, + "report_type": 2, + "sap_heating": { + "number_baths": 1, + "cylinder_size": 1, + "number_baths_wwhrs": 0, + "water_heating_code": 901, + "water_heating_fuel": 26, + "main_heating_details": [ + { + "has_fghrs": "N", + "main_fuel_type": 26, + "boiler_flue_type": 2, + "fan_flue_present": "Y", + "heat_emitter_type": 1, + "emitter_temperature": 0, + "main_heating_number": 1, + "main_heating_control": 2106, + "main_heating_category": 2, + "main_heating_fraction": 1, + "central_heating_pump_age": 0, + "main_heating_data_source": 1, + "main_heating_index_number": 18908 + } + ], + "immersion_heating_type": "NA", + "has_fixed_air_conditioning": "false" + }, + "sap_version": 10.2, + "sap_windows": [ + { + "orientation": 8, + "window_type": 1, + "glazing_type": 13, + "window_width": 1.19, + "window_height": 1.13, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "orientation": 8, + "window_type": 1, + "glazing_type": 13, + "window_width": 0.57, + "window_height": 0.55, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "orientation": 8, + "window_type": 1, + "glazing_type": 13, + "window_width": 1.19, + "window_height": 1.11, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "orientation": 2, + "window_type": 1, + "glazing_type": 13, + "window_width": 1.05, + "window_height": 0.85, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "orientation": 2, + "window_type": 1, + "glazing_type": 13, + "window_width": 0.57, + "window_height": 0.56, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "orientation": 4, + "window_type": 1, + "glazing_type": 13, + "window_width": 2.11, + "window_height": 1.13, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "orientation": 4, + "window_type": 1, + "glazing_type": 13, + "window_width": 1.8, + "window_height": 0.97, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "orientation": 4, + "window_type": 1, + "glazing_type": 13, + "window_width": 1.8, + "window_height": 0.97, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "orientation": 4, + "window_type": 1, + "glazing_type": 13, + "window_width": 1.2, + "window_height": 0.99, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "orientation": 8, + "window_type": 1, + "glazing_type": 13, + "window_width": 1.8, + "window_height": 0.97, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "orientation": 8, + "window_type": 1, + "glazing_type": 13, + "window_width": 1.19, + "window_height": 0.97, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "orientation": 8, + "window_type": 1, + "glazing_type": 13, + "window_width": 1.18, + "window_height": 0.99, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + } + ], + "schema_type": "RdSAP-Schema-21.0.1", + "uprn_source": "Energy Assessor", + "country_code": "ENG", + "main_heating": [ + { + "description": "Boiler and radiators, mains gas", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "air_tightness": { + "description": "(not tested)", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + }, + "dwelling_type": "Semi-detached house", + "language_code": 1, + "pressure_test": 4, + "property_type": 0, + "address_line_1": "75 Toronto Road", + "assessment_type": "RdSAP", + "completion_date": "2026-05-20", + "inspection_date": "2026-05-19", + "extensions_count": 0, + "measurement_type": 1, + "total_floor_area": 78, + "transaction_type": 8, + "conservatory_type": 1, + "heated_room_count": 3, + "registration_date": "2026-05-20", + "sap_energy_source": { + "mains_gas": "Y", + "meter_type": 2, + "pv_connection": 0, + "photovoltaic_supply": { + "none_or_no_details": { + "percent_roof_area": 0 + } + }, + "wind_turbines_count": 0, + "gas_smart_meter_present": "true", + "is_dwelling_export_capable": "false", + "wind_turbines_terrain_type": 2, + "electricity_smart_meter_present": "true" + }, + "secondary_heating": { + "description": "None", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + }, + "sap_building_parts": [ + { + "identifier": "Main Dwelling", + "wall_dry_lined": "N", + "wall_thickness": 400, + "floor_heat_loss": 7, + "roof_construction": 4, + "wall_construction": 3, + "building_part_number": 1, + "sap_floor_dimensions": [ + { + "floor": 0, + "room_height": { + "value": 2.4, + "quantity": "metres" + }, + "floor_insulation": 1, + "total_floor_area": { + "value": 38.99, + "quantity": "square metres" + }, + "party_wall_length": { + "value": 5.09, + "quantity": "metres" + }, + "floor_construction": 0, + "heat_loss_perimeter": { + "value": 17.92, + "quantity": "metres" + } + }, + { + "floor": 1, + "room_height": { + "value": 2.4, + "quantity": "metres" + }, + "total_floor_area": { + "value": 38.99, + "quantity": "square metres" + }, + "party_wall_length": { + "value": 5.09, + "quantity": "metres" + }, + "heat_loss_perimeter": { + "value": 17.92, + "quantity": "metres" + } + } + ], + "wall_insulation_type": 1, + "construction_age_band": "B", + "party_wall_construction": 1, + "wall_thickness_measured": "Y", + "roof_insulation_location": 2, + "roof_insulation_thickness": "300mm", + "wall_insulation_thickness": "100mm", + "floor_insulation_thickness": "NI" + } + ], + "solar_water_heating": "N", + "habitable_room_count": 3, + "heating_cost_current": { + "value": 608, + "currency": "GBP" + }, + "insulated_door_count": 0, + "co2_emissions_current": 1.9, + "energy_rating_average": 60, + "energy_rating_current": 76, + "lighting_cost_current": { + "value": 58, + "currency": "GBP" + }, + "main_heating_controls": [ + { + "description": "Programmer, room thermostat and TRVs", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "has_hot_water_cylinder": "false", + "heating_cost_potential": { + "value": 608, + "currency": "GBP" + }, + "hot_water_cost_current": { + "value": 182, + "currency": "GBP" + }, + "mechanical_ventilation": 0, + "percent_draughtproofed": 100, + "suggested_improvements": [ + { + "sequence": 1, + "typical_saving": { + "value": 216, + "currency": "GBP" + }, + "indicative_cost": "\u00a38,000 - \u00a310,000", + "improvement_type": "U", + "improvement_details": { + "improvement_number": 34 + }, + "improvement_category": 5, + "energy_performance_rating": 81, + "environmental_impact_rating": 79 + } + ], + "co2_emissions_potential": 1.8, + "energy_rating_potential": 81, + "lighting_cost_potential": { + "value": 58, + "currency": "GBP" + }, + "schema_version_original": "21.0.1", + "hot_water_cost_potential": { + "value": 182, + "currency": "GBP" + }, + "renewable_heat_incentive": { + "water_heating": 2203.16, + "space_heating_existing_dwelling": 5517.85 + }, + "draughtproofed_door_count": 2, + "energy_consumption_current": 133, + "has_fixed_air_conditioning": "false", + "multiple_glazed_proportion": 100, + "calculation_software_version": "5.02r0344", + "energy_consumption_potential": 118, + "environmental_impact_current": 78, + "current_energy_efficiency_band": "C", + "environmental_impact_potential": 79, + "led_fixed_lighting_bulbs_count": 5, + "has_heated_separate_conservatory": "false", + "potential_energy_efficiency_band": "B", + "co2_emissions_current_per_floor_area": 24, + "incandescent_fixed_lighting_bulbs_count": 0 +} \ No newline at end of file diff --git a/scripts/hyde/build_100061275133.py b/scripts/hyde/build_100061275133.py new file mode 100644 index 000000000..c959a44f6 --- /dev/null +++ b/scripts/hyde/build_100061275133.py @@ -0,0 +1,224 @@ +"""Elmhurst build for UPRN 100061275133 (RdSAP-21.0.1, MID-TERRACE HOUSE, band B, +SOLID BRICK 250 mm uninsulated, pitched insulated (assumed) loft, floor to +UNHEATED space, mains-gas COMBI (PCDB 19008) + gas room-heater SECONDARY, DUAL +meter, 11 DG windows ~18.32 m², TFA 116. Lodged SAP 63; engine 65.0 (Δ +2.0). + +Per-cert Elmhurst validation. Uses set_single_window (deletes the shared +assessment's carried-over window rows) + reset_transient_state at the end so the +assessment is left neutral. Run: + DISPLAY=:99 python scripts/hyde/build_100061275133.py +""" +from __future__ import annotations +import sys +from pathlib import Path +import elmhurst_lib as E + +DIM = "TabContainer_TabPanelMain_WebUserControlDimensionsMain_" +WALL = ("TabContainer_TabPanelMain_InnerTabContainerMain_" + "TabPanelExternalWallMain_WebUserControlWallMain_") +PWALL = ("TabContainer_TabPanelMain_InnerTabContainerMain_" + "TabPanelPartyWallMain_WebUserControlPartyWallMain_") +ROOF = "TabContainer_TabPanelMain_WebUserControlRoofMain_" +FLOOR = "TabContainer_TabPanelMain_WebUserControlFloorsMain_" +DP = "TabContainer_TabPanelDoorsPanel_" +VP = "TabContainer_TabPanelVentilationPanel_" +APT = "TabContainer_TabPanelAirPressureTest_" +LP = "TabContainer_TabPanelLighting_" +MV = "TabContainer_TabPanelMechVent_" +WH = "TabContainer_TabPanelWaterHeating_" +MH1B = "TabContainer_TabPanelMainHeating1_WebUserControlMainHeating1_" +_SAMPLE_DIR = (Path(__file__).parent.parent.parent + / "backend/epc_api/json_samples/real_life_examples" + / "RdSAP-Schema-21.0.1/uprn_100061275133") + + +def _pick(page, suffix, contains): + val = page.evaluate( + """(a)=>{const s=document.getElementById(a[0]);if(!s)return null; + for(const o of s.options){if(o.text.toLowerCase().includes(a[1].toLowerCase()))return o.value;}return null;}""", + [f"{E.FP}{suffix}", contains]) + if val is not None: + E.set_select(page, suffix, val) + return val + + +def property_description(page): + E.goto(page, "PropertyDescription", "WebFormPropertyDescription.aspx") + E.set_select(page, "DropDownListPropertyType1", "H House") + _pick(page, "DropDownListPropertyType2", "semi") + E.set_text(page, "TextBoxStoreys", "2") + E.set_text(page, "TextBoxHabitableRooms", "3") + E.set_text(page, "TextBoxHeatedHabitableRooms", "3") + print("date ->", _pick(page, "DropDownListDateBuiltMain", "1900-1929")) + E.set_select(page, "DropDownListDateBuiltFirst", "") + E.set_select(page, "DropDownListRoomInRoofMain", "") + E.save_close(page) + + +def dimensions(page): + E.goto(page, "Dimensions", "WebFormDimensions.aspx") + E.set_text(page, f"{DIM}TextBoxFloorAreaLowestFloor", "38.99") + E.set_text(page, f"{DIM}TextBoxRoomHeightLowestFloor", "2.40") + E.set_text(page, f"{DIM}TextBoxWallPerimeterLowestFloor", "17.92") + E.set_text(page, f"{DIM}TextBoxPartyWallLengthLowestFloor", "5.09") + E.set_text(page, f"{DIM}TextBoxFloorArea1stFloor", "38.99") + E.set_text(page, f"{DIM}TextBoxRoomHeight1stFloor", "2.40") + E.set_text(page, f"{DIM}TextBoxWallPerimeter1stFloor", "17.92") + E.set_text(page, f"{DIM}TextBoxPartyWallLength1stFloor", "5.09") + E.save_close(page) + + +def walls(page): + E.goto(page, "Walls", "WebFormWalls.aspx") + _pick(page, f"{WALL}DropDownListType", "solid brick") + page.wait_for_timeout(500) + print("insulation ->", _pick(page, f"{WALL}DropDownListInsulation", "external")) + print("party ->", _pick(page, f"{PWALL}DropDownListPartyWallType", "determine") + or _pick(page, f"{PWALL}DropDownListPartyWallType", "masonry")) + E.save_close(page) + + +def roofs(page): + E.goto(page, "Roofs", "WebFormRoofs.aspx") + _pick(page, f"{ROOF}DropDownListType", "access to loft") or \ + _pick(page, f"{ROOF}DropDownListType", "loft") + _pick(page, f"{ROOF}DropDownListInsulationAt", "joists") + _pick(page, f"{ROOF}DropDownListThickness", "300") + E.save_close(page) + + +def floors(page): + E.goto(page, "Floors", "WebFormFloors.aspx") + _pick(page, f"{FLOOR}DropDownListLocation", "ground floor") + page.wait_for_timeout(400) + _pick(page, f"{FLOOR}DropDownListType", "suspended") + ins = page.locator(f"#{E.FP}{FLOOR}DropDownListInsulation") + if ins.count(): + E.set_select(page, f"{FLOOR}DropDownListInsulation", "A As built") + E.save_close(page) + + +def openings(page): + E.goto(page, "Openings", "WebFormOpenings.aspx") + E.click_tab(page, "TabContainer_TabPanelWindowsPanel") + page.wait_for_timeout(500) + E.set_single_window(page, 15.32, "North", _glazing(page)) + E.click_tab(page, "TabContainer_TabPanelDoorsPanel") + E.set_text(page, f"{DP}TextBoxDoors", "2") + E.set_text(page, f"{DP}TextBoxDoorsInsulated", "0") + E.set_text(page, f"{DP}TextBoxDraughtProofedDoors", "0") + E.save_close(page) + + +def _glazing(page): + # glazed_type 13 -> double glazed, 2022 or later (U 1.4) + return "Double post or during 2022" + + +def ventilation(page): + E.goto(page, "VentilationAndCooling", "WebFormVentilationAndCooling.aspx") + E.click_tab(page, "TabContainer_TabPanelVentilationPanel") + E.set_text(page, f"{VP}TextBoxIntermittentFans", "1") + cool = page.locator(f"#{E.FP}{VP}CheckBoxFixedSpaceCooling") + if cool.count() and cool.is_checked(): + E.commit(page, cool.uncheck) + E.click_tab(page, "TabContainer_TabPanelMechVent") + mv = page.locator(f"#{E.FP}{MV}CheckBoxMechanicalVentilation") + if mv.count() and mv.is_checked(): + E.commit(page, mv.uncheck) + E.click_tab(page, "TabContainer_TabPanelAirPressureTest") + E.set_select(page, f"{APT}DropDownListTestMethod", "Not available") + E.click_tab(page, "TabContainer_TabPanelLighting") + E.set_text(page, f"{LP}TextBoxLightsTotal", "6") + E.set_text(page, f"{LP}TextBoxLedLightsTotal", "0") + E.set_text(page, f"{LP}TextBoxCflLightsTotal", "0") + E.save_close(page) + + +def space_heating(page): + E.goto(page, "SpaceHeating", "WebFormSpaceHeating.aspx") + page.wait_for_timeout(1000) + mhc = page.locator(f"#{E.MH1}TextBoxMainHeatingCode") + code = mhc.input_value() if mhc.count() else "" + if code and code not in ("0",): + print(f"clearing leftover MainHeatingCode {code}") + page.evaluate("""(id)=>{const e=document.getElementById(id);if(e){e.value=''; + e.dispatchEvent(new Event('change',{bubbles:true}));}}""", f"{E.MH1}TextBoxMainHeatingCode") + page.wait_for_timeout(400) + E.save_close(page) + return + E.set_heating_dialog(page, f"{MH1B}ButtonMainHeatingCode", + "^Gas", "Mains gas", "Boilers", "Post 1998", "Condensing", + "Combi condens") + print("code:", page.locator(f"#{E.MH1}TextBoxMainHeatingCode").input_value()) + E.set_heating_dialog(page, f"{MH1B}ButtonMainHeatingControls", + "^Boilers", "^Standard", "CBE Programmer, room thermostat and TRVs") + print("control:", page.locator(f"#{E.MH1}TextBoxMainHeatingControls").input_value()) + E.set_select(page, "DropDownListSecondaryHeatingPresent", "No") + E.save_close(page) + + +def _unused_secondary(page): + E.goto(page, "SpaceHeating", "WebFormSpaceHeating.aspx") + page.wait_for_timeout(600) + E.set_select(page, "DropDownListSecondaryHeatingPresent", "Yes") + page.wait_for_timeout(900) + E.set_heating_dialog(page, "ButtonSecondaryHeatingCode", + "^Gas", "Mains gas", "Room Heater") + tb = page.locator(f"#{E.FP}TextBoxSecondaryHeatingCode") + print("secondary code:", tb.input_value() if tb.count() else "?") + E.save_close(page) + + +def water_heating(page): + E.goto(page, "WaterHeating", "WebFormWaterHeating.aspx") + E.click_tab(page, "TabContainer_TabPanelWaterHeating") + page.wait_for_timeout(400) + E.clear_hot_water_cylinder(page) + E.set_heating_dialog(page, f"{WH}ButtonWaterHeatingCode", + "From Space Heating", "From the primary heating system") + print("water code:", page.locator(f"#{E.FP}{WH}TextBoxWaterHeatingCode").input_value()) + E.save_close(page) + + +def download(page): + _SAMPLE_DIR.mkdir(parents=True, exist_ok=True) + E.goto(page, "Recommendations", "WebFormRecommendations.aspx") + page.wait_for_timeout(1500) + with page.expect_navigation(wait_until="networkidle", timeout=40000): + page.click("#ContentBody_buttonActionSummary_Link", timeout=15000) + page.wait_for_timeout(2000) + for btn, fname in (("ContentBody_ContentPlaceHolder1_LinkButtonSummary", "elmhurst_summary.pdf"), + ("ContentBody_ContentPlaceHolder1_ButtonDebugInforPdf", "elmhurst_worksheet.pdf")): + try: + with page.expect_download(timeout=60000) as dl: + page.click(f"#{btn}", timeout=15000) + dl.value.save_as(str(_SAMPLE_DIR / fname)) + print("saved", fname) + except Exception as e: + print("!! download failed", fname, type(e).__name__, str(e)[:120]) + + +def cleanup(page): + """Leave the shared assessment neutral for the next build.""" + E.reset_transient_state(page) + print("reset transient state (RR/secondary/meter)") + + +_ORDER = ["property_description", "dimensions", "walls", "roofs", "floors", + "openings", "ventilation", "space_heating", + "water_heating", "download", "cleanup"] + + +def main(): + if len(sys.argv) < 2 or sys.argv[1] not in _ORDER: + print("usage: build_100061275133.py <" + "|".join(_ORDER) + ">") + return 2 + with E.session() as (ctx, page): + globals()[sys.argv[1]](page) + print("done:", sys.argv[1], "->", page.url) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py b/tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py index a1caa14aa..21af95ba8 100644 --- a/tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py +++ b/tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py @@ -863,6 +863,28 @@ _EXPECTATIONS: Final[tuple[RealCertExpectation, ...]] = ( cert_num="uprn-217091901", sap_score=61, ), + # UPRN 100061275133 (corpus; no cert number lodged). RdSAP-21.0.1 native — + # 2-storey SEMI-DETACHED HOUSE, band B, SOLID BRICK 400 mm with EXTERNAL + # insulation, pitched 300 mm loft, SUSPENDED uninsulated ground floor, + # mains-gas COMBI, double glazing (glazed_type 13, 2022+), TFA 78. + # Lodged 76 / engine 77 (77.24). Built in accredited Elmhurst RdSAP10 + # (evidence saved: elmhurst_summary.pdf / elmhurst_worksheet.pdf): the + # checkable FABRIC matches the engine closely — ROOF (300 mm loft, U 0.14) + # and WINDOWS (15.32 m² × eff U 1.3258 = 20.3106 W/K) match EXACTLY; the + # externally-insulated WALL is U 0.29 (engine) vs 0.30 (Elmhurst) — which + # VALIDATES the slice-5 external-insulation default (100 mm added over solid + # brick, `_WALL_ADDED_INSULATION_UNKNOWN_THICKNESS_MM`); the suspended + # ground floor is U 0.68 (engine) vs 0.70 (Elmhurst). (Elmhurst''s overall + # worksheet SAP 67 is NOT comparable — the reused-assessment combi entered + # as a "Standard Combi" carries a ~50 kWh/month Table-3a keep-hot loss the + # lodged assessment did not, a build-side heating artifact, not an engine + # gap.) Engine 77 sits within 1.24 of lodged; PINNED to the observed 77. + RealCertExpectation( + schema="RdSAP-Schema-21.0.1", + sample="uprn_100061275133", + cert_num="uprn-100061275133", + sap_score=77, + ), )