mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
more examples
This commit is contained in:
parent
269a7fdaa7
commit
e6a829aaea
35 changed files with 1467 additions and 451 deletions
|
|
@ -105,13 +105,52 @@ Pattern: `with E.session() as (ctx,page): E.goto(...); E.set_text/set_select(...
|
|||
default. Pin the engine's observed value; document the Elmhurst delta (don't tune).
|
||||
- **FGHRS** (full-SAP `has_fghrs`/`fghrs_index_number`) is dropped by the mapper
|
||||
and not yet modelled — omit it on BOTH sides so the comparison stays clean.
|
||||
- **Validation errors live on the Recommendations page as LINKS** (red ✗ anchors),
|
||||
not coloured spans — parse `[id*=ContentPlaceHolder1] a` text, not CSS colour.
|
||||
Until Recommendations shows ZERO errors the **Energy Report Summary nav silently
|
||||
redirects to the Address page** and the worksheet/Results PDFs won't generate
|
||||
(Results renders empty). Two errors that bit the 16.1/19.1.0 builds: *"Walls
|
||||
(Main): Insulation Thickness must be entered"* (set the insulation-thickness
|
||||
dropdown — "Unknown" is fine for a reduced cert) and *"Incorrect Controls (NNNN
|
||||
ctrl-group-X) for Heating System (idx ctrl-group-Y)"* (the heating control's
|
||||
system-type must match the boiler's — see the controls dialog below).
|
||||
- **All Elmhurst modal dialogs sit above a `modalBackground` that defeats element
|
||||
clicks** (Playwright sees it "intercepting pointer events", even with force).
|
||||
The cracked pattern is now in `elmhurst_lib.py`: open via JS click, set cascade
|
||||
`<select>`s by JS (`.value` + dispatch `change` → drives the AutoPostBack), and
|
||||
COMMIT by `page.mouse.click(x,y)` at the OK/Select control's centre (coordinate
|
||||
clicks hit the topmost element = the dialog). Helpers: `E.select_boiler(page,
|
||||
query, ref)`, `E.set_heating_dialog(page, button_suffix, *level_regexes)` (water
|
||||
method + main-heating controls), `E.dialog_commit(page, label)`,
|
||||
`E.clear_hot_water_cylinder(page)`.
|
||||
- **Boiler by exact PCDB code** (eliminates the boiler-efficiency divergence):
|
||||
`E.select_boiler(page, "<brand/model search>", "<pcdb_id>")` drives the search
|
||||
dialog two-step (click the result ROW to highlight → click the top **Select**
|
||||
span). The lodged `main_heating_index_number` IS the `pcdb_id`. Look up the Ref/
|
||||
type/efficiency in **`domain/elmhurst/pcdb_gas_oil_boiler_codes.csv`**. NB:
|
||||
typing the number straight into the *PCDF boiler Reference* box is COSMETIC — it
|
||||
doesn't re-resolve the boiler; only the search dialog sets type/efficiency. A
|
||||
combi keeps the cylinder checked from a prior regular boiler → `clear_hot_water_
|
||||
cylinder()`, then set water method "From Space Heating → primary" via
|
||||
`set_heating_dialog(..ButtonWaterHeatingCode, 'From Space Heating', 'From the
|
||||
primary heating system')`.
|
||||
- **Main-heating control must match the boiler's system type.** Heat-pump leftover
|
||||
control (e.g. CHJ/2210, ctrl-group-2) is invalid for a gas boiler (ctrl-group-1)
|
||||
and blocks the report. For a boiler programmer+room-stat+TRVs (SAP 2106):
|
||||
`set_heating_dialog(..ButtonMainHeatingControls, '^Boilers', '^Standard', 'CBE
|
||||
Programmer, room thermostat and TRVs')`.
|
||||
|
||||
## Limitations / next improvements (make the campaign scale)
|
||||
- **Per-assessment GUID** — `elmhurst_lib.py` reuses one `ASSESSMENT_GUID`
|
||||
(Khalim-test), overwritten per UPRN. For parallelism, create one assessment per
|
||||
UPRN and parameterize the GUID.
|
||||
- **Data-driven fill** — `elmhurst_lib.py` gives the primitives; a per-cert driver
|
||||
that reads field values straight from `elmhurst_inputs.md` (or a JSON sidecar)
|
||||
would remove the remaining hand-keying. `elmhurst_fill.py` is the older template.
|
||||
- **More dialogs** — boiler cascade is automatable; the control-code (2110) and
|
||||
FGHRS/MV-unit search dialogs still need the open→search→select→OK pattern.
|
||||
(Khalim-test), overwritten per UPRN. ⚠ This is a SHARED assessment: a concurrent
|
||||
user (Khalim) overwrote a build mid-session once — coordinate before long runs,
|
||||
or (better) create one assessment per UPRN and parameterize the GUID.
|
||||
- **Data-driven fill** — `build_<uprn>.py` per-cert scripts now drive every page
|
||||
incl. all dialogs via the `elmhurst_lib` helpers (see build_100021943298.py /
|
||||
build_10096028301.py as templates). A generic driver reading `elmhurst_inputs.md`
|
||||
is the remaining step. `elmhurst_fill.py` is the older single-cert template.
|
||||
- **Per-schema mappers** — every SAP/RdSAP schema gets its own dedicated
|
||||
`from_*_schema_*` mapper in `datatypes/epc/domain/mapper.py` (the 16.x family
|
||||
shares `_normalize_sap_schema_16_x`; full-SAP revisions delegate to
|
||||
`from_sap_schema_17_1`). Add new schema coverage as a dedicated method + dispatch
|
||||
branch, never by tuple-stuffing. Guard with the RdSAP-21.0.1 corpus gauge.
|
||||
|
|
|
|||
|
|
@ -10,6 +10,19 @@ UPRN, tick it and annotate: `— <schema> · eng <X> / elm <Y> · <note>`.
|
|||
2020 new-build flat) — full loop proven: eng 77 / elm 78, engine-on-Elmhurst-
|
||||
inputs 79 (calculator faithful within ~1). Use it to sanity-check the pipeline.
|
||||
|
||||
## Do next — new schemas (need a mapper)
|
||||
|
||||
These two were flagged NOT MAPPABLE in the UI (red ✗). Mapper coverage now ADDED
|
||||
(dedicated per-schema methods in `EpcPropertyDataMapper`; corpus gauge green, 0
|
||||
new pyright errors). Elmhurst build + pin still pending — run the normal loop.
|
||||
|
||||
- [x] 🔧 10096028301 — SAP-Schema-19.1.0 (full-SAP g/f FLAT, band M, combi PCDB 17929, MEV, AP50 3.5) · eng 82 / elm 82 (lodged 85) · PINNED engine 82. 🔧 mapper added: `from_sap_schema_19_1_0`. Built in Elmhurst (boiler 17929 via search, control CBE/2106, water from primary, MEV on, AP50 Blower Door 3.5+cert). Engine EXACTLY matches Elmhurst worksheet (82.11 vs 82); engine-on-Elmhurst-inputs 82.16 ≈ 82 → calculator faithful. −3 vs lodged = measured-U-vs-RdSAP-default + MEV extract-not-recovery (documented). No mapper change beyond coverage.
|
||||
- [x] 🔧 100021943298 — SAP-Schema-16.1 (g/f FLAT, band B, solid-brick internal, combi PCDB 10328) · eng 76 / elm 75 (lodged 72) · PINNED engine 76. 🔧 mapper added: `from_sap_schema_16_1`. Built in Elmhurst (boiler 10328 via search, control CBE/2106, water from primary, wall insulation thickness Unknown); worksheet 75 → engine within ~1 (tightest agreement, reduced-field). Boiler-select + water-heating + control dialogs all driven via automation (two-step row→Select / cascade + coordinate-OK). No mapper change beyond coverage.
|
||||
|
||||
(Refactor: split the full-SAP + 16.x dispatch tuples into dedicated per-schema
|
||||
mappers — from_sap_schema_17_0/18_0_0/19_1_0 + from_sap_schema_16_0/1/2/3 — so
|
||||
each schema has one mapper home for future divergence; all delegate to shared logic.)
|
||||
|
||||
## E2E testing set
|
||||
|
||||
UPRNs needed for end-to-end testing (also tracked in The 100 below).
|
||||
|
|
@ -41,8 +54,8 @@ Skip the 🚩 MVHR / 🚩 heat-pump-fuel and ⛔ sparse certs.
|
|||
- [x] 10093116543 — SAP-17.1 (2017 gas-combi semi) · eng 81 / elm 77 (lodged 82) · PINNED engine 81. +4 = documented full-SAP→RdSAP residual, NOT a mapper bug: ~1.5 floor-U (cert lodges measured 0.11 vs Elmhurst RdSAP solid default 0.23; U-known override disabled) + ~1 boiler-eff (cert PCDB 17644 88.5% vs Elmhurst generic BGW combi 84%; PCDB search disabled, 89% cascade option is a regular boiler needing a cylinder) + ~0.5 roof band-L/infil. Conservatory leftover from prior cert cleared (worksheet 73→77). No mapper change.
|
||||
- [x] 🔧 10093116529 — SAP-17.1 (2017 gas-combi ground-floor FLAT, TFA 49) · eng 81 / elm 78 (lodged 81) · PINNED engine 81. 🔧 FIXED a real calc bug: full-SAP flats took the 0.25 house party-wall default instead of the RdSAP Table-15 flat 0.0 (flatness is in dwelling_type, not property_type) — heat_transmission._is_flat_or_maisonette_dwelling; +regression test. Cert lodges party u_value 0; Elmhurst worksheet 0.0; fix 80→81. Residual +3 vs Elmhurst = documented full-SAP→RdSAP gap (measured wall 0.184/floor 0.12 + PCDB 88.5% vs generic 84%). Calculator faithful: fed Elmhurst's Us, HTC 93.4 vs ~94. House→Flat Elmhurst switch (storeys→1, roof→another-dwelling-above). No mapper change.
|
||||
- [ ] 🔧 100020933699 — SAP-16.2 SCHEMA COVERAGE ADDED (end-terrace house, band G). 16.2 is structurally RdSAP-17.1 (reduced fields, glazed_area band, construction-code building parts) under a different name; mapped via `_normalize_sap_schema_16_2` (renames windows→window, main_gas→mains_gas, boiler_index_number→main_heating_index_number, wwhrs→instantaneous_wwhrs + defaults) → reuses from_rdsap_schema_17_1. 🔧 Also fixed: "Single glazed" description honoured when multiple_glazing_type="ND" (was defaulting to double; RdSAP-21 code 5) → eng 72→71. +4 regression tests, sap_16_2.json fixture, 0 new pyright errors. eng 71 / lodged 70. ⚠ Known gap: 16.2 lodges no party_wall_length → end-terrace party wall unmodelled (likely the residual +1). ⏳ Elmhurst build (partial: PropDesc/Dims/Walls/Roofs done) + pin still pending.
|
||||
- [ ] 🔧 44012843 — SAP-16.3 schema coverage (same _normalize_sap_schema_16_x reduced-field path as 16.2) · eng 79 / lodged 81 · g/f flat band K · Elmhurst pin pending
|
||||
- [ ] 🔧 10023444324 — SAP-17.0 schema coverage (full-SAP shape ≡ 17.1; dispatched to from_sap_schema_17_1, no normalization) · eng 80 / lodged 82 · Elmhurst pin pending
|
||||
- [x] 🔧 44012843 — SAP-16.3 (g/f FLAT, band K, cavity insulated, REGULAR boiler PCDB 9895 + cylinder, double glazed) · eng 79 / elm 78 (lodged 81) · PINNED engine 79. Built in Elmhurst (boiler 9895 via search, control CBE/2106, cylinder Large/foam/50mm, water from primary). Engine within ~1 (78.82 vs 78); engine-on-Elmhurst-inputs 78.48 ≈ 78 → calculator faithful. −2 vs lodged = reduced-field defaults. No mapper change beyond coverage.
|
||||
- [x] 🔧 10023444324 — SAP-17.0 (full-SAP g/f FLAT, band M, combi PCDB 16211, MEV, AP50 3.2, party wall 6.43) · eng 80 / elm 80 (lodged 82) · PINNED engine 80. Built in Elmhurst (boiler 16211 via search, control CBE/2106, water from primary, MEV on, AP50 Blower Door 3.2, party wall 6.43). Engine EXACTLY matches Elmhurst worksheet (80.13 vs 80); engine-on-Elmhurst-inputs 81.03 ≈ 80 → calculator faithful. −2 vs lodged = full-SAP→RdSAP residual (measured U + MEV). No mapper change beyond coverage.
|
||||
- [⚠] 10092970673 — SAP-17.0 · eng 77 / lodged 86 · 🚩 MVHR idx 500418 not credited (flagged)
|
||||
- [⚠] 10094601287 — SAP-18.0.0 · eng 80 / lodged 84 · 🚩 MVHR idx 500230 not credited (flagged)
|
||||
- [ ] 10090844932 — RdSAP-20.0.0 · eng 78 / lodged 78
|
||||
|
|
@ -100,7 +113,7 @@ Skip the 🚩 MVHR / 🚩 heat-pump-fuel and ⛔ sparse certs.
|
|||
- [⚠] 10093305101 — SAP-17.1 · eng 81 / lodged 85 · 🚩 MVHR idx 500140 not credited (flagged)
|
||||
- [ ] 100020933894 — SAP-16.0 · eng 61 / lodged 56
|
||||
- [ ] 100020937013 — RdSAP-20.0.0 · eng 70 / lodged 73
|
||||
- [ ] 🔧 10023444320 — SAP-17.0 schema coverage (full-SAP ≡ 17.1) · eng 81 / lodged 81 · Elmhurst pin pending
|
||||
- [x] 🔧 10023444320 — SAP-17.0 (full-SAP MID-FLOOR FLAT, sibling of 324, combi PCDB 16211, MEV, AP50 3.09, no party wall) · eng 81 / elm 82 (lodged 81) · PINNED engine 81. Built in Elmhurst (boiler 16211, control CBE/2106, water from primary, MEV, AP50 3.09, mid-floor=floor to dwelling below). Within ~1 (81.38 vs 82); engine-on-Elmhurst-inputs 82.46 ≈ 82 → faithful. No mapper change beyond coverage.
|
||||
- [ ] 100062188801 — SAP-16.3 · eng 68 / lodged 70
|
||||
- [ ] 10008048040 — SAP-16.2 · eng 77 / lodged 75
|
||||
- [ ] 10093101966 — SAP-17.1 · eng 82 / lodged 84
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
# Elmhurst RdSAP inputs — UPRN 100021943298 (cert 0498-6963-7270-0822-1980, SAP-Schema-16.1)
|
||||
|
||||
**Lodged SAP:** 72 **Our engine:** 76 (continuous ~75.x) ← compare Elmhurst against the engine
|
||||
**Property:** Ground-floor FLAT, age band B (1900–1929), mains-gas combi + radiators, TFA 78 m²
|
||||
|
||||
**Schema note:** SAP-Schema-16.1 is reduced-field (RdSAP-shaped) — mapped via the
|
||||
new `from_sap_schema_16_1` → `_normalize_sap_schema_16_x` → `from_rdsap_schema_17_1`.
|
||||
Descriptions + glazed-area band, no measured U-values, so engine and Elmhurst should
|
||||
both use RdSAP age-band/description U-values — expect TIGHTER agreement (the +4 over
|
||||
lodged is the reconciliation target).
|
||||
|
||||
**Known divergences / gaps to watch:**
|
||||
- **Party wall:** 16.1 lodges no `party_wall_length`; normalizer defaults 0 → engine
|
||||
models no party wall. For a ground-floor flat the side/party walls to other dwellings
|
||||
are handled by Elmhurst's Flat position + corridor — keep party-wall length 0 and check
|
||||
the worksheet party-wall line.
|
||||
- Age band B → Elmhurst on-screen band **B 1900-1929**.
|
||||
|
||||
## Property Description
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Property Type | **Flat** | property_type 2 |
|
||||
| Built form | **End-Terrace** | built_form 3 |
|
||||
| Age band | **B 1900-1929** | construction_age_band B |
|
||||
| Storeys | 1 | ground-floor flat, single storey |
|
||||
| Habitable rooms | 3 | habitable_room_count 3 |
|
||||
|
||||
## Flats
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Position of flat | **Ground Floor** | dwelling_type "Ground-floor flat" |
|
||||
| Floor | 0 | ground = storey 0 |
|
||||
| Corridor | None | all-exposed (no unheated corridor lodged) |
|
||||
|
||||
## Dimensions
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Floor area (lowest) | 77.69 m² | floor 0 |
|
||||
| Room height | 2.65 m | room_height |
|
||||
| Heat-loss perimeter | 28.9 m | heat_loss_perimeter |
|
||||
| Party-wall length | **0** | 16.1 lodges none |
|
||||
|
||||
## Walls
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Construction | **Solid Brick** | wall_construction 3 |
|
||||
| Insulation | **Internal** | wall_insulation_type 3 = internal insulation ("Solid brick, with internal insulation") |
|
||||
| Thickness | (as built) | wall_thickness_measured True |
|
||||
|
||||
## Roofs
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Type | **Another dwelling above** | roof "(another dwelling above)" → no roof heat loss |
|
||||
|
||||
## Floors
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Location / type | Ground floor / **Suspended** | "Suspended, no insulation (assumed)" |
|
||||
| Insulation | **As built** (none) | no insulation |
|
||||
|
||||
## Openings
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Windows | **Double glazed**, total 11.544 m² (4 × 2.886, N/E/S/W) | glazed_area band 1, multiple_glazing_type 2 (double). Enter ONE combined "Double …" row of 11.544 m². |
|
||||
| Doors | **2, uninsulated** | door_count 2, insulated_door_count 0 |
|
||||
|
||||
## Ventilation & Lighting
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Ventilation | Natural | no MV |
|
||||
| Extract fans / flues | 0 / 0 | none lodged |
|
||||
| Sheltered sides | 1 | sheltered_sides 1 |
|
||||
| Air Pressure Test | **Not available** (no test lodged) | clear any Blower Door |
|
||||
| Lighting | **100% low-energy** (6 of 6 outlets) | low_energy 6 / total 6 |
|
||||
|
||||
## Space Heating
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Main heating | Mains gas **combi** + radiators | fuel 26, emitter 1, control 2106, fan flue, PCDB 10328, category 2, NO cylinder → BGW condensing combi cascade |
|
||||
| Secondary | None | secondary "None" |
|
||||
|
||||
## Water Heating
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Water heating | From main (901), gas | water_heating from combi |
|
||||
| Hot water cylinder | **None** | has_hot_water_cylinder False (combi/instantaneous) |
|
||||
| Solar / WWHRS / FGHRS | None | — |
|
||||
|
||||
## Fields to clear in Elmhurst (do NOT map)
|
||||
| Elmhurst field | Set to | Why absent |
|
||||
|---|---|---|
|
||||
| Conservatory | none | not lodged |
|
||||
| Air Pressure Test method | **Not available** | no test lodged (clear any prior Blower Door) |
|
||||
| Mechanical ventilation | off | natural ventilation |
|
||||
| Cylinder size/insulation | (gone — combi) | no cylinder |
|
||||
| Main Heating 2 / Secondary | none | single combi system |
|
||||
| PV / Wind / Hydro | none | none lodged |
|
||||
| Room-in-roof / extensions | blank | single building part, no RiR |
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,232 @@
|
|||
{
|
||||
"uprn": 100021943298,
|
||||
"roofs": [
|
||||
{
|
||||
"description": "(another dwelling above)",
|
||||
"energy_efficiency_rating": 0,
|
||||
"environmental_efficiency_rating": 0
|
||||
}
|
||||
],
|
||||
"walls": [
|
||||
{
|
||||
"description": "Solid brick, with internal 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,
|
||||
"windows": [
|
||||
{
|
||||
"description": "Fully double glazed",
|
||||
"energy_efficiency_rating": 3,
|
||||
"environmental_efficiency_rating": 3
|
||||
}
|
||||
],
|
||||
"lighting": {
|
||||
"description": "Low energy lighting in all fixed outlets",
|
||||
"energy_efficiency_rating": 5,
|
||||
"environmental_efficiency_rating": 5
|
||||
},
|
||||
"postcode": "SE4 1YN",
|
||||
"hot_water": {
|
||||
"description": "From main system",
|
||||
"energy_efficiency_rating": 4,
|
||||
"environmental_efficiency_rating": 4
|
||||
},
|
||||
"post_town": "LONDON",
|
||||
"built_form": 3,
|
||||
"created_at": "2012-10-02 23:16:59.000000",
|
||||
"door_count": 2,
|
||||
"glazed_area": 1,
|
||||
"region_code": 17,
|
||||
"report_type": 2,
|
||||
"sap_heating": {
|
||||
"wwhrs": {
|
||||
"rooms_with_bath_and_or_shower": 1,
|
||||
"rooms_with_mixer_shower_no_bath": 0,
|
||||
"rooms_with_bath_and_mixer_shower": 0
|
||||
},
|
||||
"cylinder_size": 1,
|
||||
"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,
|
||||
"boiler_index_number": 10328,
|
||||
"main_heating_number": 1,
|
||||
"main_heating_control": 2106,
|
||||
"main_heating_category": 2,
|
||||
"main_heating_fraction": 1,
|
||||
"main_heating_data_source": 1
|
||||
}
|
||||
],
|
||||
"has_fixed_air_conditioning": "false"
|
||||
},
|
||||
"sap_version": 9.91,
|
||||
"schema_type": "SAP-Schema-16.1",
|
||||
"uprn_source": "Energy Assessor",
|
||||
"country_code": "EAW",
|
||||
"main_heating": [
|
||||
{
|
||||
"description": "Boiler and radiators, mains gas",
|
||||
"energy_efficiency_rating": 4,
|
||||
"environmental_efficiency_rating": 4
|
||||
}
|
||||
],
|
||||
"dwelling_type": "Ground-floor flat",
|
||||
"language_code": 1,
|
||||
"property_type": 2,
|
||||
"address_line_1": "11a, Chalsey Road",
|
||||
"schema_version": "LIG-16.1",
|
||||
"assessment_type": "RdSAP",
|
||||
"completion_date": "2012-10-02",
|
||||
"inspection_date": "2012-10-01",
|
||||
"extensions_count": 0,
|
||||
"measurement_type": 1,
|
||||
"sap_flat_details": {
|
||||
"level": 1,
|
||||
"top_storey": "N",
|
||||
"flat_location": 0,
|
||||
"heat_loss_corridor": 0
|
||||
},
|
||||
"total_floor_area": 78,
|
||||
"transaction_type": 8,
|
||||
"conservatory_type": 1,
|
||||
"heated_room_count": 3,
|
||||
"registration_date": "2012-10-02",
|
||||
"restricted_access": 0,
|
||||
"sap_energy_source": {
|
||||
"main_gas": "Y",
|
||||
"meter_type": 2,
|
||||
"photovoltaic_supply": {
|
||||
"percent_roof_area": 0
|
||||
},
|
||||
"wind_turbines_count": 0,
|
||||
"wind_turbines_terrain_type": 2
|
||||
},
|
||||
"secondary_heating": {
|
||||
"description": "None",
|
||||
"energy_efficiency_rating": 0,
|
||||
"environmental_efficiency_rating": 0
|
||||
},
|
||||
"sap_building_parts": [
|
||||
{
|
||||
"identifier": "Main Dwelling",
|
||||
"wall_dry_lined": "N",
|
||||
"wall_thickness": 300,
|
||||
"floor_heat_loss": 7,
|
||||
"roof_construction": 3,
|
||||
"wall_construction": 3,
|
||||
"building_part_number": 1,
|
||||
"sap_floor_dimensions": [
|
||||
{
|
||||
"floor": 0,
|
||||
"room_height": 2.65,
|
||||
"floor_insulation": 1,
|
||||
"total_floor_area": 77.69,
|
||||
"floor_construction": 2,
|
||||
"heat_loss_perimeter": 28.9
|
||||
}
|
||||
],
|
||||
"wall_insulation_type": 3,
|
||||
"construction_age_band": "B",
|
||||
"wall_thickness_measured": "Y",
|
||||
"roof_insulation_location": "ND",
|
||||
"roof_insulation_thickness": "ND",
|
||||
"wall_insulation_thickness": "50mm"
|
||||
}
|
||||
],
|
||||
"low_energy_lighting": 100,
|
||||
"solar_water_heating": "N",
|
||||
"bedf_revision_number": 329,
|
||||
"habitable_room_count": 3,
|
||||
"heating_cost_current": {
|
||||
"value": 421,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"insulated_door_count": 0,
|
||||
"co2_emissions_current": 2.4,
|
||||
"energy_rating_average": 60,
|
||||
"energy_rating_current": 72,
|
||||
"lighting_cost_current": {
|
||||
"value": 46,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"main_heating_controls": [
|
||||
{
|
||||
"description": "Programmer, room thermostat and TRVs",
|
||||
"energy_efficiency_rating": 4,
|
||||
"environmental_efficiency_rating": 4
|
||||
}
|
||||
],
|
||||
"multiple_glazing_type": 1,
|
||||
"open_fireplaces_count": 0,
|
||||
"has_hot_water_cylinder": "false",
|
||||
"heating_cost_potential": {
|
||||
"value": 360,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"hot_water_cost_current": {
|
||||
"value": 85,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"mechanical_ventilation": 0,
|
||||
"percent_draughtproofed": 100,
|
||||
"suggested_improvements": [
|
||||
{
|
||||
"sequence": 1,
|
||||
"typical_saving": {
|
||||
"value": 61,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"indicative_cost": "\u00a3800 - \u00a31,200",
|
||||
"improvement_type": "W",
|
||||
"improvement_details": {
|
||||
"improvement_number": 47
|
||||
},
|
||||
"improvement_category": 5,
|
||||
"energy_performance_rating": 75,
|
||||
"environmental_impact_rating": 77
|
||||
}
|
||||
],
|
||||
"co2_emissions_potential": 2.0,
|
||||
"energy_rating_potential": 75,
|
||||
"lighting_cost_potential": {
|
||||
"value": 46,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"hot_water_cost_potential": {
|
||||
"value": 85,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"renewable_heat_incentive": {
|
||||
"water_heating": 2121,
|
||||
"space_heating_existing_dwelling": 7355
|
||||
},
|
||||
"seller_commission_report": "Y",
|
||||
"energy_consumption_current": 160,
|
||||
"has_fixed_air_conditioning": "false",
|
||||
"multiple_glazed_proportion": 100,
|
||||
"calculation_software_version": 8.0,
|
||||
"energy_consumption_potential": 137,
|
||||
"environmental_impact_current": 72,
|
||||
"fixed_lighting_outlets_count": 6,
|
||||
"current_energy_efficiency_band": "C",
|
||||
"environmental_impact_potential": 77,
|
||||
"has_heated_separate_conservatory": "false",
|
||||
"potential_energy_efficiency_band": "C",
|
||||
"co2_emissions_current_per_floor_area": 31,
|
||||
"low_energy_fixed_lighting_outlets_count": 6
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,96 @@
|
|||
# Elmhurst RdSAP inputs — UPRN 10096028301 (cert 0390-3321-6060-2405-7985, SAP-Schema-19.1.0)
|
||||
|
||||
**Lodged SAP:** 85 **Our engine:** 82 ← compare Elmhurst against the engine
|
||||
**Property:** Ground-floor FLAT, age band M (2023 onwards), mains-gas combi + radiators, decentralised MEV, TFA 73 m²
|
||||
|
||||
**Schema note:** SAP-Schema-19.1.0 is FULL SAP (measured U-values, measured air
|
||||
permeability) — mapped via the new `from_sap_schema_19_1_0` (parses with the 17.1
|
||||
dataclass, delegates to `from_sap_schema_17_1`). Near-twin of the worked-ref flat
|
||||
10092973954 (same PCDB combi 17929, MEV, AP50). Expect the documented full-SAP→RdSAP
|
||||
residual: the engine uses the cert's MEASURED U (wall 0.24 / floor 0.13 — WORSE than
|
||||
RdSAP band-M defaults), so here the engine *under*-rates vs RdSAP (eng 82 < lodged 85).
|
||||
|
||||
**Known divergences / gaps to watch:**
|
||||
- **MEV (decentralised, EXTRACT_OR_PIV_OUTSIDE):** engine prices it as extract loss,
|
||||
not heat recovery — the documented MVHR gap. Omit/parallel on both sides.
|
||||
- **Measured vs RdSAP U:** Elmhurst can't set the U-value-known override → it uses band-M
|
||||
age defaults (better than the cert's measured 0.24 wall). Note the divergence; don't tune.
|
||||
- Age band M → Elmhurst on-screen band **M 2023 onwards**.
|
||||
|
||||
## Property Description
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Property Type | **Flat** | ground-floor flat |
|
||||
| Built form | **Detached** (block) | built_form not lodged (full SAP) — use Detached as for worked-ref flat |
|
||||
| Age band | **M 2023 onwards** | construction_age_band M |
|
||||
| Storeys | 1 | ground-floor flat |
|
||||
| Habitable rooms | 3 | habitable_room_count 3 |
|
||||
|
||||
## Flats
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Position of flat | **Ground Floor** | dwelling_type ground-floor flat |
|
||||
| Floor | 0 | ground = storey 0 |
|
||||
| Corridor | None | all-exposed |
|
||||
|
||||
## Dimensions
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Floor area (lowest) | 72.99 m² | floor 0 |
|
||||
| Room height | 2.36 m | room_height |
|
||||
| Heat-loss perimeter | 36.04 m | heat_loss_perimeter |
|
||||
| Party-wall length | **0** | not lodged |
|
||||
|
||||
## Walls
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Construction | **Cavity** | wall_construction 4 |
|
||||
| Insulation | **As Built** | measured U 0.24 W/m²K (U-known override not settable → accept band-M default; note divergence) |
|
||||
|
||||
## Roofs
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Type | **Another dwelling above** | roof "(other premises above)" → no roof heat loss |
|
||||
|
||||
## Floors
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Location / type | Ground floor / Solid | measured U 0.13 (accept band-M default) |
|
||||
| Insulation | As built | — |
|
||||
|
||||
## Openings
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Windows | total ~11.37 m² (4 windows), U 1.3, g 0.46 | glazing_type 7. Enter ONE combined band row ("Double … 2022" ≈ U1.4/g0.72) of 11.37 m² — `…known data` demands per-row frame-factor/source and fails validation. |
|
||||
| Doors | **1, solid (uninsulated)** U 1.2 | sap_opening_types: 1 Solid Door, U 1.2 |
|
||||
|
||||
## Ventilation & Lighting
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Ventilation | **Mechanical — decentralised MEV** (extract) | ventilation EXTRACT_OR_PIV_OUTSIDE. 🚩 engine models as extract loss not heat recovery. |
|
||||
| Air Pressure Test | **Blower Door**, result **3.5** (AP50) | air_tightness "AP50 = 3.5 as tested"; Elmhurst (18)=AP50/20. Needs a certificate number to pass Recommendations validation. |
|
||||
| Sheltered sides | (from built form) | — |
|
||||
| Lighting | per cert low-energy % | sap_lighting |
|
||||
|
||||
## Space Heating
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Main heating | Mains gas **combi** + radiators | fuel mains gas, PCDB 17929 (Vaillant combi), control 2110, category 2, NO cylinder → BGW condensing combi cascade |
|
||||
| Flue | Balanced (room-sealed) | fan_flue_present; balanced flue |
|
||||
| Secondary | None | — |
|
||||
|
||||
## Water Heating
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Water heating | From main (901), gas | combi |
|
||||
| Hot water cylinder | **None** | has_hot_water_cylinder False (combi) |
|
||||
| Solar / WWHRS / FGHRS | None | — |
|
||||
|
||||
## Fields to clear in Elmhurst (do NOT map)
|
||||
| Elmhurst field | Set to | Why absent |
|
||||
|---|---|---|
|
||||
| Conservatory | none | not lodged |
|
||||
| Cylinder size/insulation | (gone — combi) | no cylinder |
|
||||
| Main Heating 2 / Secondary | none | single combi system |
|
||||
| PV / Wind / Hydro / WWHRS / FGHRS | none | none lodged |
|
||||
| Room-in-roof / extensions | blank | single building part |
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,456 @@
|
|||
{
|
||||
"der": 12.66,
|
||||
"ter": 13.84,
|
||||
"dfee": 36.3,
|
||||
"dper": 69.44,
|
||||
"tfee": 38.6,
|
||||
"tper": 72.99,
|
||||
"uprn": 10096028301,
|
||||
"roofs": [
|
||||
{
|
||||
"description": {
|
||||
"value": "(other premises above)",
|
||||
"language": "1"
|
||||
},
|
||||
"energy_efficiency_rating": 0,
|
||||
"environmental_efficiency_rating": 0
|
||||
}
|
||||
],
|
||||
"walls": [
|
||||
{
|
||||
"description": {
|
||||
"value": "Average thermal transmittance 0.24 W/m\u00b2K",
|
||||
"language": "1"
|
||||
},
|
||||
"energy_efficiency_rating": 5,
|
||||
"environmental_efficiency_rating": 5
|
||||
}
|
||||
],
|
||||
"floors": [
|
||||
{
|
||||
"description": {
|
||||
"value": "Average thermal transmittance 0.13 W/m\u00b2K",
|
||||
"language": "1"
|
||||
},
|
||||
"energy_efficiency_rating": 5,
|
||||
"environmental_efficiency_rating": 5
|
||||
}
|
||||
],
|
||||
"status": "entered",
|
||||
"tenure": "ND",
|
||||
"windows": {
|
||||
"description": {
|
||||
"value": "High performance glazing",
|
||||
"language": "1"
|
||||
},
|
||||
"energy_efficiency_rating": 4,
|
||||
"environmental_efficiency_rating": 4
|
||||
},
|
||||
"lighting": {
|
||||
"description": {
|
||||
"value": "Good lighting efficiency",
|
||||
"language": "1"
|
||||
},
|
||||
"energy_efficiency_rating": 4,
|
||||
"environmental_efficiency_rating": 4
|
||||
},
|
||||
"postcode": "CT5 1TN",
|
||||
"data_type": 2,
|
||||
"hot_water": {
|
||||
"description": {
|
||||
"value": "From main system, waste water heat recovery",
|
||||
"language": "1"
|
||||
},
|
||||
"energy_efficiency_rating": 5,
|
||||
"environmental_efficiency_rating": 5
|
||||
},
|
||||
"post_town": "Whitstable",
|
||||
"built_form": 1,
|
||||
"created_at": "2025-06-09 10:49:27",
|
||||
"living_area": 26.89,
|
||||
"orientation": 3,
|
||||
"region_code": 14,
|
||||
"report_type": 3,
|
||||
"sap_heating": {
|
||||
"number_baths": 1,
|
||||
"thermal_store": 1,
|
||||
"shower_outlets": [
|
||||
{
|
||||
"shower_wwhrs": 2,
|
||||
"shower_flow_rate": 9,
|
||||
"shower_outlet_type": 3
|
||||
}
|
||||
],
|
||||
"water_fuel_type": 1,
|
||||
"water_heating_code": 901,
|
||||
"instantaneous_wwhrs": {
|
||||
"wwhrs_index_number1": 80137
|
||||
},
|
||||
"main_heating_details": [
|
||||
{
|
||||
"has_fghrs": "false",
|
||||
"main_fuel_type": 1,
|
||||
"heat_emitter_type": 1,
|
||||
"is_flue_fan_present": "true",
|
||||
"main_heating_number": 1,
|
||||
"is_condensing_boiler": "true",
|
||||
"main_heating_control": 2110,
|
||||
"is_interlocked_system": "true",
|
||||
"main_heating_category": 2,
|
||||
"main_heating_fraction": 1,
|
||||
"gas_or_oil_boiler_type": 2,
|
||||
"main_heating_flue_type": 2,
|
||||
"central_heating_pump_age": 2,
|
||||
"main_heating_data_source": 1,
|
||||
"main_heating_index_number": 17929,
|
||||
"has_separate_delayed_start": "true",
|
||||
"is_oil_pump_in_heated_space": "false",
|
||||
"is_main_heating_hetas_approved": "false",
|
||||
"is_central_heating_pump_in_heated_space": "true"
|
||||
}
|
||||
],
|
||||
"has_hot_water_cylinder": "false",
|
||||
"has_cylinder_thermostat": "false",
|
||||
"has_fixed_air_conditioning": "false",
|
||||
"secondary_heating_category": 1,
|
||||
"is_immersion_for_summer_use": "false",
|
||||
"is_hot_water_separately_timed": "false",
|
||||
"is_heat_pump_assisted_by_immersion": "false"
|
||||
},
|
||||
"sap_version": 10.2,
|
||||
"schema_type": "SAP-Schema-19.1.0",
|
||||
"uprn_source": "Address Matched",
|
||||
"country_code": "ENG",
|
||||
"main_heating": [
|
||||
{
|
||||
"description": {
|
||||
"value": "Boiler and radiators, mains gas",
|
||||
"language": "1"
|
||||
},
|
||||
"energy_efficiency_rating": 5,
|
||||
"environmental_efficiency_rating": 4
|
||||
}
|
||||
],
|
||||
"sap_lighting": [
|
||||
[
|
||||
{
|
||||
"lighting_power": 9,
|
||||
"lighting_outlets": 6,
|
||||
"lighting_efficacy": 80
|
||||
}
|
||||
]
|
||||
],
|
||||
"terrain_type": 2,
|
||||
"air_tightness": {
|
||||
"description": {
|
||||
"value": "Air permeability [AP50] = 3.5 m\u00b3/h.m\u00b2 (as tested)",
|
||||
"language": "1"
|
||||
},
|
||||
"energy_efficiency_rating": 4,
|
||||
"environmental_efficiency_rating": 4
|
||||
},
|
||||
"dwelling_type": "Ground-floor flat",
|
||||
"language_code": 1,
|
||||
"property_type": 2,
|
||||
"pv_connection": 1,
|
||||
"address_line_1": "1 Ransome Way",
|
||||
"assessment_date": "2025-06-09",
|
||||
"assessment_type": "SAP",
|
||||
"completion_date": "2025-06-09",
|
||||
"inspection_date": "2025-06-09",
|
||||
"sap_ventilation": {
|
||||
"psv_count": 0,
|
||||
"wall_type": 2,
|
||||
"pressure_test": 1,
|
||||
"wet_rooms_count": 2,
|
||||
"air_permeability": 3.52,
|
||||
"open_flues_count": 0,
|
||||
"ventilation_type": 6,
|
||||
"has_draught_lobby": "true",
|
||||
"other_flues_count": 0,
|
||||
"closed_flues_count": 0,
|
||||
"extract_fans_count": 0,
|
||||
"boilers_flues_count": 0,
|
||||
"open_chimneys_count": 0,
|
||||
"sheltered_sides_count": 2,
|
||||
"blocked_chimneys_count": 0,
|
||||
"kitchen_duct_fans_count": 0,
|
||||
"kitchen_room_fans_count": 0,
|
||||
"kitchen_wall_fans_count": 1,
|
||||
"flueless_gas_fires_count": 0,
|
||||
"mechanical_vent_duct_type": 1,
|
||||
"non_kitchen_duct_fans_count": 0,
|
||||
"non_kitchen_room_fans_count": 0,
|
||||
"non_kitchen_wall_fans_count": 1,
|
||||
"mechanical_ventilation_data_source": 1,
|
||||
"mechanical_vent_system_index_number": 500769,
|
||||
"is_mechanical_vent_approved_installer_scheme": "false"
|
||||
},
|
||||
"design_water_use": 1,
|
||||
"sap_data_version": 10.2,
|
||||
"sap_flat_details": {
|
||||
"level": 1,
|
||||
"storeys": 3
|
||||
},
|
||||
"total_floor_area": 73,
|
||||
"transaction_type": 6,
|
||||
"cold_water_source": 1,
|
||||
"conservatory_type": 1,
|
||||
"registration_date": "2025-06-09",
|
||||
"sap_energy_source": {
|
||||
"pv_arrays": [
|
||||
{
|
||||
"pitch": 3,
|
||||
"peak_power": 0.38,
|
||||
"orientation": 5,
|
||||
"overshading": 1
|
||||
}
|
||||
],
|
||||
"electricity_tariff": 1
|
||||
},
|
||||
"sap_opening_types": [
|
||||
{
|
||||
"name": "Solid Door",
|
||||
"type": 1,
|
||||
"u_value": 1.2,
|
||||
"data_source": 2,
|
||||
"glazing_type": 1,
|
||||
"isargonfilled": "false"
|
||||
},
|
||||
{
|
||||
"name": "Windows",
|
||||
"type": 4,
|
||||
"u_value": 1.3,
|
||||
"data_source": 4,
|
||||
"frame_factor": 1.0,
|
||||
"glazing_type": 7,
|
||||
"isargonfilled": "false",
|
||||
"solar_transmittance": 0.46
|
||||
}
|
||||
],
|
||||
"secondary_heating": {
|
||||
"description": {
|
||||
"value": "None",
|
||||
"language": "1"
|
||||
},
|
||||
"energy_efficiency_rating": 0,
|
||||
"environmental_efficiency_rating": 0
|
||||
},
|
||||
"lowest_storey_area": 72.99,
|
||||
"lzc_energy_sources": [
|
||||
11
|
||||
],
|
||||
"sap_building_parts": [
|
||||
{
|
||||
"sap_roofs": [
|
||||
{
|
||||
"name": "Party roof 1",
|
||||
"u_value": 0,
|
||||
"roof_type": 4,
|
||||
"kappa_value": 30,
|
||||
"total_roof_area": 72.99
|
||||
}
|
||||
],
|
||||
"sap_walls": [
|
||||
{
|
||||
"name": "Walls (1)",
|
||||
"u_value": 0.24,
|
||||
"wall_type": 2,
|
||||
"kappa_value": 60,
|
||||
"total_wall_area": 68.76,
|
||||
"is_curtain_walling": "false"
|
||||
},
|
||||
{
|
||||
"name": "Walls (2)",
|
||||
"u_value": 0.26,
|
||||
"wall_type": 3,
|
||||
"kappa_value": 110,
|
||||
"total_wall_area": 16.3,
|
||||
"is_curtain_walling": "false"
|
||||
},
|
||||
{
|
||||
"name": "Internal Wall (1)",
|
||||
"u_value": 0,
|
||||
"wall_type": 5,
|
||||
"kappa_value": 9,
|
||||
"total_wall_area": 114.18,
|
||||
"is_curtain_walling": "false"
|
||||
}
|
||||
],
|
||||
"sap_openings": [
|
||||
{
|
||||
"name": "Front Door",
|
||||
"type": "Solid Door",
|
||||
"width": 2.15,
|
||||
"height": 1,
|
||||
"location": "Walls (1)",
|
||||
"orientation": 3
|
||||
},
|
||||
{
|
||||
"name": "Front Windows",
|
||||
"type": "Windows",
|
||||
"width": 4.77,
|
||||
"height": 1,
|
||||
"location": "Walls (1)",
|
||||
"orientation": 3
|
||||
},
|
||||
{
|
||||
"name": "RH Windows",
|
||||
"type": "Windows",
|
||||
"width": 4.39,
|
||||
"height": 1,
|
||||
"location": "Walls (1)",
|
||||
"orientation": 1
|
||||
},
|
||||
{
|
||||
"name": "Rear Window",
|
||||
"type": "Windows",
|
||||
"width": 0.62,
|
||||
"height": 1,
|
||||
"location": "Walls (1)",
|
||||
"orientation": 7
|
||||
},
|
||||
{
|
||||
"name": "LH Window",
|
||||
"type": "Windows",
|
||||
"width": 1.59,
|
||||
"height": 1,
|
||||
"location": "Walls (1)",
|
||||
"orientation": 5
|
||||
}
|
||||
],
|
||||
"construction_year": 2025,
|
||||
"sap_thermal_bridges": {
|
||||
"thermal_bridges": [
|
||||
{
|
||||
"length": 9.65,
|
||||
"psi_value": 0.021,
|
||||
"psi_value_source": 1,
|
||||
"thermal_bridge_type": "E2"
|
||||
},
|
||||
{
|
||||
"length": 8.16,
|
||||
"psi_value": 0.017,
|
||||
"psi_value_source": 1,
|
||||
"thermal_bridge_type": "E3"
|
||||
},
|
||||
{
|
||||
"length": 16.95,
|
||||
"psi_value": 0.013,
|
||||
"psi_value_source": 1,
|
||||
"thermal_bridge_type": "E4"
|
||||
},
|
||||
{
|
||||
"length": 29.14,
|
||||
"psi_value": 0.054,
|
||||
"psi_value_source": 1,
|
||||
"thermal_bridge_type": "E5"
|
||||
},
|
||||
{
|
||||
"length": 29.14,
|
||||
"psi_value": 0.052,
|
||||
"psi_value_source": 1,
|
||||
"thermal_bridge_type": "E7"
|
||||
},
|
||||
{
|
||||
"length": 11.61,
|
||||
"psi_value": 0.046,
|
||||
"psi_value_source": 1,
|
||||
"thermal_bridge_type": "E16"
|
||||
},
|
||||
{
|
||||
"length": 6.91,
|
||||
"psi_value": 0.111,
|
||||
"psi_value_source": 1,
|
||||
"thermal_bridge_type": "E5"
|
||||
},
|
||||
{
|
||||
"length": 6.91,
|
||||
"psi_value": 0.056,
|
||||
"psi_value_source": 1,
|
||||
"thermal_bridge_type": "E7"
|
||||
},
|
||||
{
|
||||
"length": 4.72,
|
||||
"psi_value": -0.1,
|
||||
"psi_value_source": 1,
|
||||
"thermal_bridge_type": "E17"
|
||||
}
|
||||
],
|
||||
"thermal_bridge_code": 5
|
||||
},
|
||||
"building_part_number": 1,
|
||||
"sap_floor_dimensions": [
|
||||
{
|
||||
"storey": 0,
|
||||
"u_value": 0.13,
|
||||
"floor_type": 2,
|
||||
"kappa_value": 75,
|
||||
"storey_height": 2.36,
|
||||
"heat_loss_area": 72.99,
|
||||
"total_floor_area": 72.99
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"user_interface_name": "Design SAP 10",
|
||||
"windows_overshading": 2,
|
||||
"heating_cost_current": {
|
||||
"value": 218,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"co2_emissions_current": 0.8,
|
||||
"energy_rating_average": 60,
|
||||
"energy_rating_current": 85,
|
||||
"lighting_cost_current": {
|
||||
"value": 57,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"main_heating_controls": [
|
||||
{
|
||||
"description": {
|
||||
"value": "Time and temperature zone control",
|
||||
"language": "1"
|
||||
},
|
||||
"energy_efficiency_rating": 5,
|
||||
"environmental_efficiency_rating": 5
|
||||
}
|
||||
],
|
||||
"has_hot_water_cylinder": "false",
|
||||
"heating_cost_potential": {
|
||||
"value": 218,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"hot_water_cost_current": {
|
||||
"value": 118,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"user_interface_version": "2.22.1",
|
||||
"co2_emissions_potential": 0.8,
|
||||
"energy_rating_potential": 85,
|
||||
"gas_smart_meter_present": "false",
|
||||
"lighting_cost_potential": {
|
||||
"value": 57,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"schema_version_original": "SAP-Schema-19.1.0",
|
||||
"hot_water_cost_potential": {
|
||||
"value": 118,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"is_in_smoke_control_area": "unknown",
|
||||
"seller_commission_report": "Y",
|
||||
"energy_consumption_current": 59,
|
||||
"has_fixed_air_conditioning": "false",
|
||||
"is_dwelling_export_capable": "true",
|
||||
"multiple_glazed_percentage": 100,
|
||||
"calculation_software_version": "2.22.1",
|
||||
"energy_consumption_potential": 59,
|
||||
"environmental_impact_current": 90,
|
||||
"current_energy_efficiency_band": "B",
|
||||
"environmental_impact_potential": 90,
|
||||
"electricity_smart_meter_present": "false",
|
||||
"has_heated_separate_conservatory": "false",
|
||||
"potential_energy_efficiency_band": "B",
|
||||
"co2_emissions_current_per_floor_area": 10.7
|
||||
}
|
||||
|
|
@ -883,6 +883,74 @@ class EpcPropertyDataMapper:
|
|||
)
|
||||
return roof_windows
|
||||
|
||||
@staticmethod
|
||||
def from_sap_schema_19_1_0(schema: SapSchema17_1) -> EpcPropertyData:
|
||||
"""Map a full-SAP `SAP-Schema-19.1.0` cert.
|
||||
|
||||
19.1.0 is a later full-SAP revision whose load-bearing fabric — measured
|
||||
`sap_opening_types`, construction-code `sap_building_parts`,
|
||||
`sap_heating` / `sap_ventilation` — is structurally identical to
|
||||
`SAP-Schema-17.1`, so it parses with the 17.1 dataclass and reuses the
|
||||
tested `from_sap_schema_17_1` mapper. This thin wrapper gives 19.1.0 its
|
||||
own dispatch entry point: 19.1.0-only fields (e.g. `air_tightness`,
|
||||
`windows_overshading`) are not yet consumed, and when one needs modelling
|
||||
it is handled here rather than by widening the 17.1 mapper.
|
||||
"""
|
||||
return EpcPropertyDataMapper.from_sap_schema_17_1(schema)
|
||||
|
||||
@staticmethod
|
||||
def from_sap_schema_17_0(schema: SapSchema17_1) -> EpcPropertyData:
|
||||
"""Map a full-SAP `SAP-Schema-17.0` cert. Structurally identical to the
|
||||
17.1 measured shape, so it parses with the 17.1 dataclass and reuses
|
||||
`from_sap_schema_17_1`. Dedicated entry point per the one-mapper-per-
|
||||
schema convention (note: distinct from RdSAP `from_rdsap_schema_17_0`)."""
|
||||
return EpcPropertyDataMapper.from_sap_schema_17_1(schema)
|
||||
|
||||
@staticmethod
|
||||
def from_sap_schema_18_0_0(schema: SapSchema17_1) -> EpcPropertyData:
|
||||
"""Map a full-SAP `SAP-Schema-18.0.0` cert. Structurally identical to the
|
||||
17.1 measured shape, so it parses with the 17.1 dataclass and reuses
|
||||
`from_sap_schema_17_1`. Dedicated entry point per the one-mapper-per-
|
||||
schema convention."""
|
||||
return EpcPropertyDataMapper.from_sap_schema_17_1(schema)
|
||||
|
||||
@staticmethod
|
||||
def from_sap_schema_16_0(data: Dict[str, Any]) -> EpcPropertyData:
|
||||
"""Map a reduced-field `SAP-Schema-16.0` cert (see `from_sap_schema_16_2`)."""
|
||||
return EpcPropertyDataMapper._from_sap_schema_16_x(data)
|
||||
|
||||
@staticmethod
|
||||
def from_sap_schema_16_1(data: Dict[str, Any]) -> EpcPropertyData:
|
||||
"""Map a reduced-field `SAP-Schema-16.1` cert (see `from_sap_schema_16_2`)."""
|
||||
return EpcPropertyDataMapper._from_sap_schema_16_x(data)
|
||||
|
||||
@staticmethod
|
||||
def from_sap_schema_16_2(data: Dict[str, Any]) -> EpcPropertyData:
|
||||
"""Map a reduced-field `SAP-Schema-16.2` cert.
|
||||
|
||||
The SAP-Schema-16.x family is structurally RdSAP-17.1 (reduced fields,
|
||||
`glazed_area` band, construction-code building parts) under a different
|
||||
name plus a handful of renamed/omitted fields. Each revision gets a
|
||||
dedicated mapper that normalises onto the RdSAP-17.1 shape via the shared
|
||||
`_normalize_sap_schema_16_x` and reuses the tested `from_rdsap_schema_17_1`.
|
||||
"""
|
||||
return EpcPropertyDataMapper._from_sap_schema_16_x(data)
|
||||
|
||||
@staticmethod
|
||||
def from_sap_schema_16_3(data: Dict[str, Any]) -> EpcPropertyData:
|
||||
"""Map a reduced-field `SAP-Schema-16.3` cert (see `from_sap_schema_16_2`)."""
|
||||
return EpcPropertyDataMapper._from_sap_schema_16_x(data)
|
||||
|
||||
@staticmethod
|
||||
def _from_sap_schema_16_x(data: Dict[str, Any]) -> EpcPropertyData:
|
||||
"""Shared body for the SAP-Schema-16.x dedicated mappers: normalise the
|
||||
reduced-field doc onto the RdSAP-17.1 shape and reuse that mapper."""
|
||||
from datatypes.epc.schema.rdsap_schema_17_1 import RdSapSchema17_1
|
||||
|
||||
return EpcPropertyDataMapper.from_rdsap_schema_17_1(
|
||||
from_dict(RdSapSchema17_1, _normalize_sap_schema_16_x(data))
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def from_rdsap_schema_17_1(schema: RdSapSchema17_1) -> EpcPropertyData:
|
||||
es = schema.sap_energy_source
|
||||
|
|
@ -2578,27 +2646,36 @@ class EpcPropertyDataMapper:
|
|||
mapped = EpcPropertyDataMapper.from_rdsap_schema_17_0(
|
||||
from_dict(RdSapSchema17_0, data)
|
||||
)
|
||||
elif schema in ("SAP-Schema-17.1", "SAP-Schema-17.0", "SAP-Schema-18.0.0"):
|
||||
# Full SAP (not RdSAP). SAP-Schema-17.0 / 18.0.0 are structurally
|
||||
# identical to 17.1 (same measured sap_opening_types / building
|
||||
# parts), so they parse with the 17.1 dataclass and reuse the same
|
||||
# mapper. The common post-processing below (incl.
|
||||
# _clear_basement_flag_when_system_built) is a no-op for full SAP
|
||||
# (explicit wall types — no RdSAP code-6 basement ambiguity).
|
||||
# Full-SAP family: each revision gets a dedicated mapper (see the
|
||||
# per-schema methods) even where it currently delegates to the 17.1
|
||||
# logic — so divergences land in one place rather than a shared tuple.
|
||||
elif schema == "SAP-Schema-17.1":
|
||||
mapped = EpcPropertyDataMapper.from_sap_schema_17_1(
|
||||
from_dict(SapSchema17_1, data)
|
||||
)
|
||||
elif schema in ("SAP-Schema-16.2", "SAP-Schema-16.3", "SAP-Schema-16.0"):
|
||||
# The SAP-Schema-16.x family is structurally RdSAP-17.1 (reduced
|
||||
# fields, glazed_area band, construction-code building parts) under a
|
||||
# different name + a handful of renamed/omitted fields — normalise
|
||||
# onto the RdSAP-17.1 shape and reuse that tested mapper. See
|
||||
# `_normalize_sap_schema_16_x`.
|
||||
from datatypes.epc.schema.rdsap_schema_17_1 import RdSapSchema17_1
|
||||
|
||||
mapped = EpcPropertyDataMapper.from_rdsap_schema_17_1(
|
||||
from_dict(RdSapSchema17_1, _normalize_sap_schema_16_x(data))
|
||||
elif schema == "SAP-Schema-17.0":
|
||||
mapped = EpcPropertyDataMapper.from_sap_schema_17_0(
|
||||
from_dict(SapSchema17_1, data)
|
||||
)
|
||||
elif schema == "SAP-Schema-18.0.0":
|
||||
mapped = EpcPropertyDataMapper.from_sap_schema_18_0_0(
|
||||
from_dict(SapSchema17_1, data)
|
||||
)
|
||||
elif schema == "SAP-Schema-19.1.0":
|
||||
mapped = EpcPropertyDataMapper.from_sap_schema_19_1_0(
|
||||
from_dict(SapSchema17_1, data)
|
||||
)
|
||||
# SAP-Schema-16.x family: reduced-field (RdSAP-shaped) certs. Each gets a
|
||||
# dedicated mapper that normalises onto the RdSAP-17.1 shape via the
|
||||
# shared `_normalize_sap_schema_16_x` and reuses `from_rdsap_schema_17_1`.
|
||||
elif schema == "SAP-Schema-16.0":
|
||||
mapped = EpcPropertyDataMapper.from_sap_schema_16_0(data)
|
||||
elif schema == "SAP-Schema-16.1":
|
||||
mapped = EpcPropertyDataMapper.from_sap_schema_16_1(data)
|
||||
elif schema == "SAP-Schema-16.2":
|
||||
mapped = EpcPropertyDataMapper.from_sap_schema_16_2(data)
|
||||
elif schema == "SAP-Schema-16.3":
|
||||
mapped = EpcPropertyDataMapper.from_sap_schema_16_3(data)
|
||||
else:
|
||||
raise ValueError(f"Unsupported EPC schema: {schema!r}")
|
||||
|
||||
|
|
|
|||
28
domain/elmhurst/README.md
Normal file
28
domain/elmhurst/README.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# Elmhurst reference data
|
||||
|
||||
Lookup tables to support re-keying certs into the Elmhurst RdSAP entry tool
|
||||
(see `scripts/hyde/` and the `expand-sap-accuracy-corpus` skill).
|
||||
|
||||
## `pcdb_gas_oil_boiler_codes.csv`
|
||||
|
||||
Every gas/oil boiler in the SAP Product Characteristics Database (PCDB Table
|
||||
105), one row per boiler, so you can look up the **Ref No** to type into
|
||||
Elmhurst's *PCDF boiler Reference* field (Space Heating → 🔍 search → Select).
|
||||
|
||||
Columns: `pcdb_id` (the Ref No), `brand`, `model`, `qualifier`, `type`
|
||||
(Regular / Combi / Combi-storage / CPSU), `winter_eff_pct`, `summer_eff_pct`,
|
||||
`output_kw_max`, `final_year`.
|
||||
|
||||
- Generated from `domain/sap10_calculator/tables/pcdb/data/pcdb_table_105_gas_oil_boilers.jsonl`.
|
||||
- `type` is decoded from the raw PCDB row's boiler-type code (`raw[14]`:
|
||||
`1`→Regular, `2`→Combi, `3`→Combi-storage, `4`→CPSU). This is the field that
|
||||
decides whether Elmhurst wants a hot-water cylinder (Regular) or not (Combi).
|
||||
- Find a boiler: `grep -i "ecotec pro,28" pcdb_gas_oil_boiler_codes.csv` or
|
||||
filter by brand/model; the cert's lodged `main_heating_index_number` is the
|
||||
`pcdb_id`.
|
||||
|
||||
**Note on entering it in Elmhurst:** the on-screen *PCDF boiler Reference* text
|
||||
box is editable and will *display* a number you type, but typing alone does NOT
|
||||
re-resolve the boiler — its type/efficiency/cylinder behaviour stays from the
|
||||
previously-selected boiler. Only selecting via the 🔍 **search dialog** genuinely
|
||||
sets the boiler. This CSV tells you which Ref to pick.
|
||||
|
|
@ -87,12 +87,6 @@
|
|||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionConservatories_Link"
|
||||
},
|
||||
{
|
||||
"text": "Flats",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionFlats$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionFlats_Link"
|
||||
},
|
||||
{
|
||||
"text": "Walls",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionWalls$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$RadioButtonDimensionsType",
|
||||
"label": "Type",
|
||||
"value": "Internal",
|
||||
"disabled": true,
|
||||
"disabled": false,
|
||||
"autopostback": false,
|
||||
"options": [
|
||||
{
|
||||
|
|
@ -29,13 +29,53 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "text",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelMain_WebUserControlDimensionsMain_TextBoxFloorArea1stFloor",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelMain$WebUserControlDimensionsMain$TextBoxFloorArea1stFloor",
|
||||
"label": "",
|
||||
"value": "31.06",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "text",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelMain_WebUserControlDimensionsMain_TextBoxRoomHeight1stFloor",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelMain$WebUserControlDimensionsMain$TextBoxRoomHeight1stFloor",
|
||||
"label": "",
|
||||
"value": "2.65",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "text",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelMain_WebUserControlDimensionsMain_TextBoxWallPerimeter1stFloor",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelMain$WebUserControlDimensionsMain$TextBoxWallPerimeter1stFloor",
|
||||
"label": "",
|
||||
"value": "15.80",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "text",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelMain_WebUserControlDimensionsMain_TextBoxPartyWallLength1stFloor",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelMain$WebUserControlDimensionsMain$TextBoxPartyWallLength1stFloor",
|
||||
"label": "",
|
||||
"value": "0.00",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "text",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelMain_WebUserControlDimensionsMain_TextBoxFloorAreaLowestFloor",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelMain$WebUserControlDimensionsMain$TextBoxFloorAreaLowestFloor",
|
||||
"label": "",
|
||||
"value": "59.50",
|
||||
"value": "31.06",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
|
|
@ -55,7 +95,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelMain_WebUserControlDimensionsMain_TextBoxWallPerimeterLowestFloor",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelMain$WebUserControlDimensionsMain$TextBoxWallPerimeterLowestFloor",
|
||||
"label": "",
|
||||
"value": "13.86",
|
||||
"value": "15.80",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
|
|
@ -65,7 +105,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelMain_WebUserControlDimensionsMain_TextBoxPartyWallLengthLowestFloor",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelMain$WebUserControlDimensionsMain$TextBoxPartyWallLengthLowestFloor",
|
||||
"label": "",
|
||||
"value": "13.86",
|
||||
"value": "0.00",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
|
|
@ -154,12 +194,6 @@
|
|||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionConservatories_Link"
|
||||
},
|
||||
{
|
||||
"text": "Flats",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionFlats$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionFlats_Link"
|
||||
},
|
||||
{
|
||||
"text": "Walls",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionWalls$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
|
|
|
|||
|
|
@ -198,12 +198,6 @@
|
|||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionConservatories_Link"
|
||||
},
|
||||
{
|
||||
"text": "Flats",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionFlats$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionFlats_Link"
|
||||
},
|
||||
{
|
||||
"text": "Walls",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionWalls$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
|
|
|
|||
|
|
@ -184,12 +184,6 @@
|
|||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionConservatories_Link"
|
||||
},
|
||||
{
|
||||
"text": "Flats",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionFlats$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionFlats_Link"
|
||||
},
|
||||
{
|
||||
"text": "Walls",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionWalls$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
|
|
|
|||
|
|
@ -22,73 +22,13 @@
|
|||
"disabled": false,
|
||||
"autopostback": false
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "image",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWindowsPanel_GridViewExtendedWidows_DeleteButton_1",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWindowsPanel$GridViewExtendedWidows$ctl03$DeleteButton",
|
||||
"label": "2",
|
||||
"value": "",
|
||||
"disabled": false,
|
||||
"autopostback": false
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "image",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWindowsPanel_GridViewExtendedWidows_CopyButton_1",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWindowsPanel$GridViewExtendedWidows$ctl03$CopyButton",
|
||||
"label": "2",
|
||||
"value": "",
|
||||
"disabled": false,
|
||||
"autopostback": false
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "image",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWindowsPanel_GridViewExtendedWidows_DeleteButton_2",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWindowsPanel$GridViewExtendedWidows$ctl04$DeleteButton",
|
||||
"label": "3",
|
||||
"value": "",
|
||||
"disabled": false,
|
||||
"autopostback": false
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "image",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWindowsPanel_GridViewExtendedWidows_CopyButton_2",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWindowsPanel$GridViewExtendedWidows$ctl04$CopyButton",
|
||||
"label": "3",
|
||||
"value": "",
|
||||
"disabled": false,
|
||||
"autopostback": false
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "image",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWindowsPanel_GridViewExtendedWidows_DeleteButton_3",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWindowsPanel$GridViewExtendedWidows$ctl05$DeleteButton",
|
||||
"label": "4",
|
||||
"value": "",
|
||||
"disabled": false,
|
||||
"autopostback": false
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "image",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWindowsPanel_GridViewExtendedWidows_CopyButton_3",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWindowsPanel$GridViewExtendedWidows$ctl05$CopyButton",
|
||||
"label": "4",
|
||||
"value": "",
|
||||
"disabled": false,
|
||||
"autopostback": false
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "text",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWindowsPanel_TextBoxExtWidth",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWindowsPanel$TextBoxExtWidth",
|
||||
"label": "",
|
||||
"value": "1.44",
|
||||
"value": "0.00",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
|
|
@ -98,7 +38,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWindowsPanel_TextBoxExtHeight",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWindowsPanel$TextBoxExtHeight",
|
||||
"label": "",
|
||||
"value": "1.00",
|
||||
"value": "0.00",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
|
|
@ -108,7 +48,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWindowsPanel_TextBoxExtArea",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWindowsPanel$TextBoxExtArea",
|
||||
"label": "",
|
||||
"value": "1.44",
|
||||
"value": "0.00",
|
||||
"disabled": true,
|
||||
"autopostback": false
|
||||
},
|
||||
|
|
@ -140,14 +80,14 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWindowsPanel_DropDownListExtGlazing",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWindowsPanel$DropDownListExtGlazing",
|
||||
"label": "",
|
||||
"value": "Double with unknown install date",
|
||||
"value": "",
|
||||
"disabled": false,
|
||||
"autopostback": true,
|
||||
"options": [
|
||||
{
|
||||
"value": "",
|
||||
"text": "",
|
||||
"selected": false
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "Single glazing",
|
||||
|
|
@ -172,7 +112,7 @@
|
|||
{
|
||||
"value": "Double with unknown install date",
|
||||
"text": "Double with unknown install date",
|
||||
"selected": true
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "Secondary glazing",
|
||||
|
|
@ -216,89 +156,25 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tag": "select",
|
||||
"type": "select-one",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWindowsPanel_DropDownListExtFrameType",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWindowsPanel$DropDownListExtFrameType",
|
||||
"label": "",
|
||||
"value": "PVC",
|
||||
"disabled": false,
|
||||
"autopostback": true,
|
||||
"options": [
|
||||
{
|
||||
"value": "",
|
||||
"text": "",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "PVC",
|
||||
"text": "PVC",
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "Wood",
|
||||
"text": "Wood",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "Metal",
|
||||
"text": "Metal",
|
||||
"selected": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tag": "select",
|
||||
"type": "select-one",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWindowsPanel_DropDownListExtGlazingGap",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWindowsPanel$DropDownListExtGlazingGap",
|
||||
"label": "",
|
||||
"value": "12 mm",
|
||||
"disabled": false,
|
||||
"autopostback": true,
|
||||
"options": [
|
||||
{
|
||||
"value": "",
|
||||
"text": "",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "6 mm",
|
||||
"text": "6 mm",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "12 mm",
|
||||
"text": "12 mm",
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "16 mm or more",
|
||||
"text": "16 mm or more",
|
||||
"selected": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tag": "select",
|
||||
"type": "select-one",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWindowsPanel_DropDownListExtBuildingPartId",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWindowsPanel$DropDownListExtBuildingPartId",
|
||||
"label": "",
|
||||
"value": "Main",
|
||||
"value": "",
|
||||
"disabled": false,
|
||||
"autopostback": true,
|
||||
"options": [
|
||||
{
|
||||
"value": "",
|
||||
"text": "",
|
||||
"selected": false
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "Main",
|
||||
"text": "Main",
|
||||
"selected": true
|
||||
"selected": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -308,24 +184,14 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWindowsPanel_DropDownListExtLocation",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWindowsPanel$DropDownListExtLocation",
|
||||
"label": "",
|
||||
"value": "External wall",
|
||||
"value": "",
|
||||
"disabled": false,
|
||||
"autopostback": true,
|
||||
"options": [
|
||||
{
|
||||
"value": "",
|
||||
"text": "",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "External wall",
|
||||
"text": "External wall",
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "Alternative wall 1",
|
||||
"text": "Alternative wall 1",
|
||||
"selected": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -335,19 +201,19 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWindowsPanel_DropDownListExtOrientation",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWindowsPanel$DropDownListExtOrientation",
|
||||
"label": "",
|
||||
"value": "North",
|
||||
"value": "",
|
||||
"disabled": false,
|
||||
"autopostback": true,
|
||||
"options": [
|
||||
{
|
||||
"value": "",
|
||||
"text": "",
|
||||
"selected": false
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "North",
|
||||
"text": "North",
|
||||
"selected": true
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "North East",
|
||||
|
|
@ -397,7 +263,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWindowsPanel_TextBoxExtUValue",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWindowsPanel$TextBoxExtUValue",
|
||||
"label": "",
|
||||
"value": "2.80",
|
||||
"value": "0.00",
|
||||
"disabled": true,
|
||||
"autopostback": true
|
||||
},
|
||||
|
|
@ -407,7 +273,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWindowsPanel_TextBoxExtGValue",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWindowsPanel$TextBoxExtGValue",
|
||||
"label": "",
|
||||
"value": "0.76",
|
||||
"value": "0.00",
|
||||
"disabled": true,
|
||||
"autopostback": true
|
||||
},
|
||||
|
|
@ -420,7 +286,7 @@
|
|||
"value": "on",
|
||||
"disabled": false,
|
||||
"autopostback": false,
|
||||
"checked": true
|
||||
"checked": false
|
||||
},
|
||||
{
|
||||
"tag": "select",
|
||||
|
|
@ -582,12 +448,6 @@
|
|||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionConservatories_Link"
|
||||
},
|
||||
{
|
||||
"text": "Flats",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionFlats$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionFlats_Link"
|
||||
},
|
||||
{
|
||||
"text": "Walls",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionWalls$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_DropDownListPropertyType1",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$DropDownListPropertyType1",
|
||||
"label": "",
|
||||
"value": "F Flat",
|
||||
"value": "H House",
|
||||
"disabled": false,
|
||||
"autopostback": true,
|
||||
"options": [
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
{
|
||||
"value": "H House",
|
||||
"text": "H House",
|
||||
"selected": false
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "B Bungalow",
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
{
|
||||
"value": "F Flat",
|
||||
"text": "F Flat",
|
||||
"selected": true
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "M Maisonette",
|
||||
|
|
@ -44,13 +44,60 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tag": "select",
|
||||
"type": "select-one",
|
||||
"id": "ContentBody_ContentPlaceHolder1_DropDownListPropertyType2",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$DropDownListPropertyType2",
|
||||
"label": "",
|
||||
"value": "E End-Terrace",
|
||||
"disabled": false,
|
||||
"autopostback": true,
|
||||
"options": [
|
||||
{
|
||||
"value": "",
|
||||
"text": "",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "D Detached",
|
||||
"text": "D Detached",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "S Semi-Detached",
|
||||
"text": "S Semi-Detached",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "M Mid-Terrace",
|
||||
"text": "M Mid-Terrace",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "E End-Terrace",
|
||||
"text": "E End-Terrace",
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "EM Enclosed Mid-Terrace",
|
||||
"text": "EM Enclosed Mid-Terrace",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "EE Enclosed End-Terrace",
|
||||
"text": "EE Enclosed End-Terrace",
|
||||
"selected": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "text",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TextBoxStoreys",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TextBoxStoreys",
|
||||
"label": "Storeys",
|
||||
"value": "1",
|
||||
"value": "2",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
|
|
@ -60,7 +107,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TextBoxHabitableRooms",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TextBoxHabitableRooms",
|
||||
"label": "Habitable Rooms",
|
||||
"value": "3",
|
||||
"value": "4",
|
||||
"disabled": false,
|
||||
"autopostback": false
|
||||
},
|
||||
|
|
@ -70,7 +117,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TextBoxHeatedHabitableRooms",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TextBoxHeatedHabitableRooms",
|
||||
"label": "Heated Habitable Rooms",
|
||||
"value": "3",
|
||||
"value": "4",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
|
|
@ -80,7 +127,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_DropDownListDateBuiltMain",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$DropDownListDateBuiltMain",
|
||||
"label": "Main Property",
|
||||
"value": "L 2012-2022",
|
||||
"value": "G 1983-1990",
|
||||
"disabled": false,
|
||||
"autopostback": true,
|
||||
"options": [
|
||||
|
|
@ -122,7 +169,7 @@
|
|||
{
|
||||
"value": "G 1983-1990",
|
||||
"text": "G 1983-1990",
|
||||
"selected": false
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "H 1991-1995",
|
||||
|
|
@ -147,7 +194,7 @@
|
|||
{
|
||||
"value": "L 2012-2022",
|
||||
"text": "L 2012-2022",
|
||||
"selected": true
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "M 2023 onwards",
|
||||
|
|
@ -968,12 +1015,6 @@
|
|||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionConservatories_Link"
|
||||
},
|
||||
{
|
||||
"text": "Flats",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionFlats$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionFlats_Link"
|
||||
},
|
||||
{
|
||||
"text": "Walls",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionWalls$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
|
|
|
|||
|
|
@ -228,12 +228,6 @@
|
|||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionConservatories_Link"
|
||||
},
|
||||
{
|
||||
"text": "Flats",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionFlats$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionFlats_Link"
|
||||
},
|
||||
{
|
||||
"text": "Walls",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionWalls$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelMain_WebUserControlRoofMain_DropDownListThickness",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelMain$WebUserControlRoofMain$DropDownListThickness",
|
||||
"label": "Insulation Thickness",
|
||||
"value": "270 mm",
|
||||
"value": "100 mm",
|
||||
"disabled": false,
|
||||
"autopostback": true,
|
||||
"options": [
|
||||
|
|
@ -129,7 +129,7 @@
|
|||
{
|
||||
"value": "100 mm",
|
||||
"text": "100 mm",
|
||||
"selected": false
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "125 mm",
|
||||
|
|
@ -164,7 +164,7 @@
|
|||
{
|
||||
"value": "270 mm",
|
||||
"text": "270 mm",
|
||||
"selected": true
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "300 mm",
|
||||
|
|
@ -273,12 +273,6 @@
|
|||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionConservatories_Link"
|
||||
},
|
||||
{
|
||||
"text": "Flats",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionFlats$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionFlats_Link"
|
||||
},
|
||||
{
|
||||
"text": "Walls",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionWalls$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelMainHeating1_WebUserControlMainHeating1_TextBoxMainHeatingCode",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelMainHeating1$WebUserControlMainHeating1$TextBoxMainHeatingCode",
|
||||
"label": "Main Heating EES Code",
|
||||
"value": "BGB",
|
||||
"value": "BGW",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
|
|
@ -114,7 +114,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelMainHeating1_WebUserControlMainHeating1_RadioButtonListFlueType",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelMainHeating1$WebUserControlMainHeating1$RadioButtonListFlueType",
|
||||
"label": "Flue Type",
|
||||
"value": "Open",
|
||||
"value": "Balanced",
|
||||
"disabled": false,
|
||||
"autopostback": true,
|
||||
"options": [
|
||||
|
|
@ -126,12 +126,12 @@
|
|||
{
|
||||
"value": "Balanced",
|
||||
"text": "Balanced",
|
||||
"selected": false
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "Open",
|
||||
"text": "Open",
|
||||
"selected": true
|
||||
"selected": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -335,7 +335,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_DropDownListSecondaryHeatingPresent",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$DropDownListSecondaryHeatingPresent",
|
||||
"label": "",
|
||||
"value": "Yes",
|
||||
"value": "No",
|
||||
"disabled": false,
|
||||
"autopostback": true,
|
||||
"options": [
|
||||
|
|
@ -347,25 +347,15 @@
|
|||
{
|
||||
"value": "No",
|
||||
"text": "No",
|
||||
"selected": false
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "Yes",
|
||||
"text": "Yes",
|
||||
"selected": true
|
||||
"selected": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "text",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TextBoxSecondaryHeatingCode",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TextBoxSecondaryHeatingCode",
|
||||
"label": "Secondary Heating EES Code",
|
||||
"value": "RWM",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "image",
|
||||
|
|
@ -845,12 +835,6 @@
|
|||
"onclick": null,
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelMainHeating2_WebUserControlMainHeating2_ButtonMainHeatingCode"
|
||||
},
|
||||
{
|
||||
"text": "",
|
||||
"href": "javascript:__doPostBack('ctl00$ctl00$ContentBody$ContentPlaceHolder1$ButtonSecondaryHeatingCode','')",
|
||||
"onclick": null,
|
||||
"id": "ContentBody_ContentPlaceHolder1_ButtonSecondaryHeatingCode"
|
||||
},
|
||||
{
|
||||
"text": "Boiler search",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$ContentPlaceHolder1$SelectBoilerDialog$HyperLinkActionBoilerSearch\", \"\", true, \"\", \"\", false, true))",
|
||||
|
|
@ -911,12 +895,6 @@
|
|||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionConservatories_Link"
|
||||
},
|
||||
{
|
||||
"text": "Flats",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionFlats$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionFlats_Link"
|
||||
},
|
||||
{
|
||||
"text": "Walls",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionWalls$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
|
|
|
|||
|
|
@ -152,19 +152,19 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelAirPressureTest_DropDownListTestMethod",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelAirPressureTest$DropDownListTestMethod",
|
||||
"label": "Test Method",
|
||||
"value": "Not available",
|
||||
"value": "Blower Door",
|
||||
"disabled": false,
|
||||
"autopostback": true,
|
||||
"options": [
|
||||
{
|
||||
"value": "Not available",
|
||||
"text": "Not available",
|
||||
"selected": true
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "Blower Door",
|
||||
"text": "Blower Door",
|
||||
"selected": false
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "Pulse",
|
||||
|
|
@ -173,13 +173,33 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "text",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelAirPressureTest_TextBoxTestResult",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelAirPressureTest$TextBoxTestResult",
|
||||
"label": "Pressure Test Result",
|
||||
"value": "3.59",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "text",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelAirPressureTest_TextBoxTestCertificateNumber",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelAirPressureTest$TextBoxTestCertificateNumber",
|
||||
"label": "Certificate Number",
|
||||
"value": "APT-10093116330",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "text",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelLighting_TextBoxLightsTotal",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelLighting$TextBoxLightsTotal",
|
||||
"label": "",
|
||||
"value": "6",
|
||||
"value": "9",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
|
|
@ -200,7 +220,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelLighting_TextBoxLedLightsTotal",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelLighting$TextBoxLedLightsTotal",
|
||||
"label": "",
|
||||
"value": "6",
|
||||
"value": "0",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
|
|
@ -210,7 +230,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelLighting_TextBoxCflLightsTotal",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelLighting$TextBoxCflLightsTotal",
|
||||
"label": "",
|
||||
"value": "0",
|
||||
"value": "2",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
|
|
@ -220,7 +240,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelLighting_TextBoxLelLightsTotal",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelLighting$TextBoxLelLightsTotal",
|
||||
"label": "",
|
||||
"value": "6",
|
||||
"value": "2",
|
||||
"disabled": true,
|
||||
"autopostback": true
|
||||
},
|
||||
|
|
@ -230,7 +250,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelLighting_TextBoxIncandescentLights",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelLighting$TextBoxIncandescentLights",
|
||||
"label": "",
|
||||
"value": "0",
|
||||
"value": "7",
|
||||
"disabled": true,
|
||||
"autopostback": false
|
||||
},
|
||||
|
|
@ -402,12 +422,6 @@
|
|||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionConservatories_Link"
|
||||
},
|
||||
{
|
||||
"text": "Flats",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionFlats$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionFlats_Link"
|
||||
},
|
||||
{
|
||||
"text": "Walls",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionWalls$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelMain_InnerTabContainerMain_TabPanelExternalWallMain_WebUserControlWallMain_DropDownListType",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelMain$InnerTabContainerMain$TabPanelExternalWallMain$WebUserControlWallMain$DropDownListType",
|
||||
"label": "Type",
|
||||
"value": "TI Timber Frame",
|
||||
"value": "CA Cavity",
|
||||
"disabled": false,
|
||||
"autopostback": true,
|
||||
"options": [
|
||||
|
|
@ -40,12 +40,12 @@
|
|||
{
|
||||
"value": "CA Cavity",
|
||||
"text": "CA Cavity",
|
||||
"selected": false
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "TI Timber Frame",
|
||||
"text": "TI Timber Frame",
|
||||
"selected": true
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "SY System Build",
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelMain_InnerTabContainerMain_TabPanelExternalWallMain_WebUserControlWallMain_DropDownListInsulation",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelMain$InnerTabContainerMain$TabPanelExternalWallMain$WebUserControlWallMain$DropDownListInsulation",
|
||||
"label": "Insulation",
|
||||
"value": "A As Built",
|
||||
"value": "F Filled Cavity",
|
||||
"disabled": false,
|
||||
"autopostback": true,
|
||||
"options": [
|
||||
|
|
@ -74,6 +74,36 @@
|
|||
"text": "",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "E External",
|
||||
"text": "E External",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "F Filled Cavity",
|
||||
"text": "F Filled Cavity",
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "FI Filled Cavity + Internal",
|
||||
"text": "FI Filled Cavity + Internal",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "FE Filled Cavity + External",
|
||||
"text": "FE Filled Cavity + External",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "UI Unfilled Cavity + Internal",
|
||||
"text": "UI Unfilled Cavity + Internal",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "UE Unfilled Cavity + External",
|
||||
"text": "UE Unfilled Cavity + External",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "I Internal",
|
||||
"text": "I Internal",
|
||||
|
|
@ -82,7 +112,7 @@
|
|||
{
|
||||
"value": "A As Built",
|
||||
"text": "A As Built",
|
||||
"selected": true
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "U Unknown",
|
||||
|
|
@ -97,7 +127,7 @@
|
|||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelMain_InnerTabContainerMain_TabPanelExternalWallMain_WebUserControlWallMain_TextBoxWallThickness",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelMain$InnerTabContainerMain$TabPanelExternalWallMain$WebUserControlWallMain$TextBoxWallThickness",
|
||||
"label": "Wall Thickness [mm]",
|
||||
"value": "400",
|
||||
"value": "280",
|
||||
"disabled": false,
|
||||
"autopostback": true
|
||||
},
|
||||
|
|
@ -217,12 +247,6 @@
|
|||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionConservatories_Link"
|
||||
},
|
||||
{
|
||||
"text": "Flats",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionFlats$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionFlats_Link"
|
||||
},
|
||||
{
|
||||
"text": "Walls",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionWalls$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
|
|
|
|||
|
|
@ -21,154 +21,7 @@
|
|||
"value": "on",
|
||||
"disabled": true,
|
||||
"autopostback": false,
|
||||
"checked": true
|
||||
},
|
||||
{
|
||||
"tag": "select",
|
||||
"type": "select-one",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWaterHeating_DropDownListCylinderSize",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWaterHeating$DropDownListCylinderSize",
|
||||
"label": "",
|
||||
"value": "Large",
|
||||
"disabled": false,
|
||||
"autopostback": true,
|
||||
"options": [
|
||||
{
|
||||
"value": "",
|
||||
"text": "",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "No Access",
|
||||
"text": "No Access",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "Normal",
|
||||
"text": "Normal",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "Medium",
|
||||
"text": "Medium",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "Large",
|
||||
"text": "Large",
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "Value known",
|
||||
"text": "Value known",
|
||||
"selected": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tag": "select",
|
||||
"type": "select-one",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWaterHeating_DropDownListInsulated",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWaterHeating$DropDownListInsulated",
|
||||
"label": "",
|
||||
"value": "Foam",
|
||||
"disabled": false,
|
||||
"autopostback": true,
|
||||
"options": [
|
||||
{
|
||||
"value": "",
|
||||
"text": "",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "No Insulation",
|
||||
"text": "No Insulation",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "Jacket",
|
||||
"text": "Jacket",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "Foam",
|
||||
"text": "Foam",
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "Measured Loss",
|
||||
"text": "Measured Loss",
|
||||
"selected": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tag": "select",
|
||||
"type": "select-one",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWaterHeating_DropDownListInsulationThickness",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWaterHeating$DropDownListInsulationThickness",
|
||||
"label": "",
|
||||
"value": "120 mm",
|
||||
"disabled": false,
|
||||
"autopostback": true,
|
||||
"options": [
|
||||
{
|
||||
"value": "",
|
||||
"text": "",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "None",
|
||||
"text": "None",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "12 mm",
|
||||
"text": "12 mm",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "25 mm",
|
||||
"text": "25 mm",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "38 mm",
|
||||
"text": "38 mm",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "50 mm",
|
||||
"text": "50 mm",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "80 mm",
|
||||
"text": "80 mm",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"value": "120 mm",
|
||||
"text": "120 mm",
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "160 mm",
|
||||
"text": "160 mm",
|
||||
"selected": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
"type": "checkbox",
|
||||
"id": "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelWaterHeating_CheckBoxCylinderThermostat",
|
||||
"name": "ctl00$ctl00$ContentBody$ContentPlaceHolder1$TabContainer$TabPanelWaterHeating$CheckBoxCylinderThermostat",
|
||||
"label": "",
|
||||
"value": "on",
|
||||
"disabled": false,
|
||||
"autopostback": false,
|
||||
"checked": true
|
||||
"checked": false
|
||||
},
|
||||
{
|
||||
"tag": "input",
|
||||
|
|
@ -811,12 +664,6 @@
|
|||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionConservatories_Link"
|
||||
},
|
||||
{
|
||||
"text": "Flats",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionFlats$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
"onclick": "waitForAction(this);",
|
||||
"id": "ContentBody_buttonActionFlats_Link"
|
||||
},
|
||||
{
|
||||
"text": "Walls",
|
||||
"href": "javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(\"ctl00$ctl00$ContentBody$buttonActionWalls$Link\", \"\", true, \"\", \"\", false, true))",
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ SESSION_DIR = HERE / ".elmhurst-session"
|
|||
SAMPLE_DIR = (
|
||||
HERE.parent.parent
|
||||
/ "backend/epc_api/json_samples/real_life_examples"
|
||||
/ "SAP-Schema-17.1/uprn_10092973954"
|
||||
/ "SAP-Schema-17.0/uprn_10023444320"
|
||||
)
|
||||
|
||||
ASSESSMENT_GUID = "B44A0DB4-4C08-4241-B818-86F060172105"
|
||||
|
|
@ -85,6 +85,12 @@ def download_reports() -> int:
|
|||
|
||||
print(f"entering assessment {ASSESSMENT_GUID} ...", flush=True)
|
||||
page.goto(ENTRY_URL, wait_until="networkidle", timeout=60_000)
|
||||
# The Summary nav only fires AFTER the Recommendations validation gate has
|
||||
# been visited — clicking Summary straight from the Address page is a no-op.
|
||||
print("navigating via Recommendations ...", flush=True)
|
||||
with page.expect_navigation(wait_until="networkidle", timeout=60_000):
|
||||
page.click("#ContentBody_buttonActionRecommendations_Link", timeout=15_000)
|
||||
page.wait_for_timeout(600)
|
||||
print("navigating to Energy Report Summary ...", flush=True)
|
||||
with page.expect_navigation(wait_until="networkidle", timeout=60_000):
|
||||
page.click("#ContentBody_buttonActionSummary_Link", timeout=15_000)
|
||||
|
|
|
|||
|
|
@ -226,3 +226,113 @@ def delete_first_window(page: Page) -> None:
|
|||
page.wait_for_timeout(200)
|
||||
if window_row_count(page) < before:
|
||||
break
|
||||
|
||||
|
||||
# --- Heating dialogs (boiler search + cascade) ---------------------------
|
||||
# Hard-won (campaign certs 100021943298 / 10096028301): every Elmhurst modal
|
||||
# dialog (PCDF boiler search, the SelectHeatingDialog cascade for water-heating
|
||||
# method and main-heating controls) sits ABOVE a `modalBackground` overlay that
|
||||
# makes Playwright's actionability hit-test see the background "intercepting
|
||||
# pointer events" — so element .click()/.fill()/.select_option() all fail even
|
||||
# with force. The reliable pattern is:
|
||||
# * open the dialog with a JS .click() on its button,
|
||||
# * set <select> values by JS (set .value + dispatch 'change') — this drives
|
||||
# the AutoPostBack cascade without a real click,
|
||||
# * commit by a raw `page.mouse.click(x, y)` at the OK/Select control's centre
|
||||
# (coordinate clicks land on the topmost element = the dialog, not the
|
||||
# background).
|
||||
# Typing into the boiler search box needs force-click-then-keyboard (the box is
|
||||
# overlapped); result cells are clicked by coordinate (the model column is
|
||||
# display:none at >=1024px, so match the row by its Ref-No cell and click the
|
||||
# first VISIBLE cell). Direct-writing the PCDF reference number is COSMETIC — it
|
||||
# does NOT re-resolve the boiler type/efficiency; only the search dialog does.
|
||||
MH1 = (
|
||||
"ContentBody_ContentPlaceHolder1_TabContainer_TabPanelMainHeating1_"
|
||||
"WebUserControlMainHeating1_"
|
||||
)
|
||||
HEATING_DIALOG = "ContentBody_OutsideUpdatePanel_SelectHeatingDialog_"
|
||||
|
||||
|
||||
def dialog_commit(page: Page, label: str = "OK") -> bool:
|
||||
"""Coordinate-click a dialog's commit control (a styled <span>, e.g. 'OK' or
|
||||
'Select') — bypasses the modalBackground that defeats element clicks."""
|
||||
pt = page.evaluate(
|
||||
"""(lbl)=>{const e=[...document.querySelectorAll('[id*=SelectHeatingDialog] span,[id*=SelectHeatingDialog] a,[id*=SelectHeatingDialog] input,[id*=SelectBoilerDialog] span')]
|
||||
.find(x=>new RegExp('^'+lbl+'$','i').test((x.value||x.innerText||'').trim()) && x.offsetParent);
|
||||
if(!e)return null;const c=e.getBoundingClientRect();return {x:c.x+c.width/2,y:c.y+c.height/2};}""",
|
||||
label,
|
||||
)
|
||||
if not pt:
|
||||
return False
|
||||
page.mouse.click(pt["x"], pt["y"])
|
||||
page.wait_for_timeout(SETTLE_MS * 3)
|
||||
return True
|
||||
|
||||
|
||||
def set_heating_dialog(page: Page, open_button_suffix: str, *level_regexes: str) -> None:
|
||||
"""Open a SelectHeatingDialog cascade (water-heating method or main-heating
|
||||
controls) via the button at FP+`open_button_suffix`, set DropDownList1..N to
|
||||
the options matching each regex (JS, fires the cascade), then coordinate-OK.
|
||||
e.g. water (combi): set_heating_dialog(page, MH..ButtonWaterHeatingCode,
|
||||
'From Space Heating', 'From the primary heating system');
|
||||
control 2106: set_heating_dialog(page, ..ButtonMainHeatingControls,
|
||||
'^Boilers', '^Standard', 'CBE Programmer, room thermostat and TRVs')."""
|
||||
page.evaluate("(id)=>{const e=document.getElementById(id); if(e)e.click();}", f"{FP}{open_button_suffix}")
|
||||
page.wait_for_timeout(SETTLE_MS * 3)
|
||||
for i, rx in enumerate(level_regexes, start=1):
|
||||
page.evaluate(
|
||||
"""(a)=>{const s=document.getElementById(a[0]);if(!s)return;
|
||||
const o=[...s.options].find(o=>new RegExp(a[1],'i').test(o.text));
|
||||
if(o){s.value=o.value;s.dispatchEvent(new Event('change',{bubbles:true}));}}""",
|
||||
[f"{HEATING_DIALOG}DropDownList{i}", rx],
|
||||
)
|
||||
page.wait_for_timeout(SETTLE_MS * 4) # AutoPostBack re-renders the next level
|
||||
dialog_commit(page, "OK")
|
||||
|
||||
|
||||
def select_boiler(page: Page, query: str, ref: str) -> str:
|
||||
"""Set the main-heating boiler to PCDB `ref` via the search dialog. `query`
|
||||
is a full-text search (brand/model) that surfaces `ref` on page 1. TWO-STEP
|
||||
commit: click the result ROW (highlights it) then the top 'Select' span."""
|
||||
page.evaluate("(id)=>{const e=document.getElementById(id); if(e)e.click();}", f"{MH1}ButtonBoilerReference")
|
||||
page.wait_for_selector("[id*='SelectBoilerDialog_TextBoxFullSearch']", state="visible", timeout=10_000)
|
||||
page.locator("[id*='SelectBoilerDialog_TextBoxFullSearch']").click(force=True)
|
||||
page.keyboard.type(query)
|
||||
page.locator("[id*='SelectBoilerDialog_HyperLinkActionBoilerSearch']").click(force=True)
|
||||
page.wait_for_timeout(SETTLE_MS * 4)
|
||||
pt = page.evaluate(
|
||||
"""(ref)=>{const t=document.querySelector("[id*=SelectBoilerDialog] [id*=GridView]");if(!t)return null;
|
||||
for(const r of t.querySelectorAll('tr')){const tds=[...r.querySelectorAll('td')];
|
||||
if(tds.length>2 && tds[2].innerText.replace(/\\s+/g,' ').trim()===ref){
|
||||
const v=tds.find(td=>td.offsetParent&&td.getClientRects().length);
|
||||
if(v){const c=v.getBoundingClientRect();return {x:c.x+c.width/2,y:c.y+c.height/2};}}}return null;}""",
|
||||
ref,
|
||||
)
|
||||
if not pt:
|
||||
return "row-not-found"
|
||||
page.mouse.click(pt["x"], pt["y"]) # highlight the row
|
||||
page.wait_for_timeout(SETTLE_MS)
|
||||
page.locator("[id*=SelectBoilerDialog] span", has_text="Select").filter(
|
||||
visible=True
|
||||
).first.click(force=True, timeout=8_000)
|
||||
page.wait_for_timeout(SETTLE_MS * 3)
|
||||
return "ok"
|
||||
|
||||
|
||||
def clear_hot_water_cylinder(page: Page, panel: str = "TabContainer_TabPanelWaterHeating_") -> None:
|
||||
"""Uncheck the HW cylinder (combi). The checkbox won't uncheck via
|
||||
.uncheck()/commit (a regular-boiler default re-asserts it); JS-set
|
||||
checked=false + fire click + change drives the AutoPostBack."""
|
||||
cid = f"{FP}{panel}CheckBoxHotWaterCylinder"
|
||||
if not page.locator(f"#{cid}").is_checked():
|
||||
return
|
||||
try:
|
||||
with page.expect_navigation(wait_until="load", timeout=8_000):
|
||||
page.evaluate(
|
||||
"""(id)=>{const c=document.getElementById(id);if(c){c.checked=false;
|
||||
c.dispatchEvent(new Event('click',{bubbles:true}));
|
||||
c.dispatchEvent(new Event('change',{bubbles:true}));}}""",
|
||||
cid,
|
||||
)
|
||||
except PlaywrightTimeoutError:
|
||||
page.wait_for_timeout(2_000)
|
||||
|
|
|
|||
|
|
@ -256,6 +256,99 @@ _EXPECTATIONS: Final[tuple[RealCertExpectation, ...]] = (
|
|||
cert_num="0215-2818-7357-9703-2145",
|
||||
sap_score=61,
|
||||
),
|
||||
# UPRN 100021943298 → cert 0498-6963-7270-0822-1980. SAP-Schema-16.1 — a
|
||||
# reduced-field (RdSAP-shaped) ground-floor FLAT, band B (1900-1929), solid
|
||||
# brick with internal insulation, mains-gas COMBI (PCDB 10328 Vaillant Ecotec
|
||||
# Pro 28), double glazed, TFA 78 m². New-schema coverage: mapped via the
|
||||
# dedicated `from_sap_schema_16_1` → `_normalize_sap_schema_16_x` →
|
||||
# `from_rdsap_schema_17_1`. Lodged 72 (old 2012 assessment); engine 76.
|
||||
# Built in Elmhurst RdSAP10 on the mapped inputs (evidence saved:
|
||||
# elmhurst_summary.pdf / elmhurst_worksheet.pdf): Elmhurst worksheet SAP 75 —
|
||||
# engine within ~1 (continuous 75.70 vs 75), the tightest agreement in the
|
||||
# cohort because this is reduced-field (both sides use RdSAP age-band/
|
||||
# description U-values, not measured). Boiler set to the cert's exact PCDB
|
||||
# 10328 via the search dialog; control 2106 (CBE programmer + room stat +
|
||||
# TRVs); water from primary (combi, no cylinder). The ~0.7 residual is minor
|
||||
# RdSAP defaults (wall thickness 280 vs 300 mm, internal-insulation thickness
|
||||
# Unknown vs lodged 50 mm). PINNED to the observed 76 — mapping untuned.
|
||||
RealCertExpectation(
|
||||
schema="SAP-Schema-16.1",
|
||||
sample="uprn_100021943298",
|
||||
cert_num="0498-6963-7270-0822-1980",
|
||||
sap_score=76,
|
||||
),
|
||||
# UPRN 10096028301 → cert 0390-3321-6060-2405-7985. SAP-Schema-19.1.0 — a
|
||||
# FULL-SAP ground-floor FLAT (band M 2023+, mains-gas COMBI Ideal Logic Combi
|
||||
# PCDB 17929, decentralised MEV, measured AP50 3.5, TFA 73 m²). New-schema
|
||||
# coverage: mapped via the dedicated `from_sap_schema_19_1_0` (parses with the
|
||||
# 17.1 dataclass, delegates to from_sap_schema_17_1). Lodged 85; engine 82.
|
||||
# Built in Elmhurst RdSAP10 on the mapped inputs (evidence saved:
|
||||
# elmhurst_summary.pdf / elmhurst_worksheet.pdf): Elmhurst worksheet SAP 82 —
|
||||
# engine EXACTLY matches (82.11 vs 82), and engine-on-Elmhurst's-own-parsed-
|
||||
# inputs is 82.16 ≈ 82, so the calculator is confirmed faithful on identical
|
||||
# inputs. Boiler set to the cert's exact PCDB 17929 via the search dialog;
|
||||
# control 2106 (CBE); water from primary (combi); MEV on; AP50 Blower Door 3.5.
|
||||
# The −3 vs lodged 85 is the documented full-SAP→RdSAP gap: the engine uses the
|
||||
# cert's MEASURED U (wall 0.24 / floor 0.13, WORSE than RdSAP band-M defaults)
|
||||
# + MEV priced as extract loss not heat recovery. PINNED to the observed 82 —
|
||||
# mapping untuned; engine == Elmhurst.
|
||||
RealCertExpectation(
|
||||
schema="SAP-Schema-19.1.0",
|
||||
sample="uprn_10096028301",
|
||||
cert_num="0390-3321-6060-2405-7985",
|
||||
sap_score=82,
|
||||
),
|
||||
# UPRN 44012843 → cert 0775-2898-6628-9594-8005. SAP-Schema-16.3 — a
|
||||
# reduced-field (RdSAP-shaped) ground-floor FLAT, band K (2007-2011), cavity
|
||||
# insulated, mains-gas REGULAR boiler (PCDB 9895 Ideal icos HE15) + cylinder,
|
||||
# double glazed, TFA 55 m². New-schema coverage via the dedicated
|
||||
# `from_sap_schema_16_3` → `_normalize_sap_schema_16_x` → from_rdsap_schema_17_1.
|
||||
# Lodged 81; engine 79. Built in Elmhurst RdSAP10 on the mapped inputs
|
||||
# (evidence saved: elmhurst_summary.pdf / elmhurst_worksheet.pdf): Elmhurst
|
||||
# worksheet SAP 78 — engine within ~1 (continuous 78.82 vs 78), and engine-on-
|
||||
# Elmhurst's-own-parsed-inputs is 78.48 ≈ 78 → calculator confirmed faithful.
|
||||
# Boiler set to the cert's exact PCDB 9895 via the search dialog; control 2106
|
||||
# (CBE); regular boiler + cylinder (Large, foam, 50 mm), water from primary.
|
||||
# The −2 vs lodged 81 is reduced-field RdSAP defaults. PINNED to the observed
|
||||
# 79 — mapping untuned.
|
||||
RealCertExpectation(
|
||||
schema="SAP-Schema-16.3",
|
||||
sample="uprn_44012843",
|
||||
cert_num="0775-2898-6628-9594-8005",
|
||||
sap_score=79,
|
||||
),
|
||||
# UPRN 10023444324 → cert 8501-5064-6739-1407-0163. SAP-Schema-17.0 — a
|
||||
# FULL-SAP ground-floor FLAT (band M, mains-gas COMBI Ideal Logic+ combi 35
|
||||
# PCDB 16211, decentralised MEV, measured AP50 3.2, lodged party wall 6.43 m,
|
||||
# TFA 50 m²). Full-SAP shape ≡ 17.1, dispatched via from_sap_schema_17_1.
|
||||
# Lodged 82; engine 80. Built in Elmhurst RdSAP10 on the mapped inputs
|
||||
# (evidence saved: elmhurst_summary.pdf / elmhurst_worksheet.pdf): Elmhurst
|
||||
# worksheet SAP 80 — engine EXACTLY matches (80.13 vs 80); engine-on-Elmhurst's-
|
||||
# own-parsed-inputs 81.03 ≈ 80 → calculator faithful. Boiler set to the cert's
|
||||
# exact PCDB 16211 via the search dialog; control 2106 (CBE); water from primary
|
||||
# (combi); MEV on; AP50 Blower Door 3.2; party wall 6.43 m entered. The −2 vs
|
||||
# lodged 82 is the documented full-SAP→RdSAP gap (measured U 0.2/0.1 + MEV
|
||||
# extract loss). PINNED to the observed 80 — mapping untuned; engine == Elmhurst.
|
||||
RealCertExpectation(
|
||||
schema="SAP-Schema-17.0",
|
||||
sample="uprn_10023444324",
|
||||
cert_num="8501-5064-6739-1407-0163",
|
||||
sap_score=80,
|
||||
),
|
||||
# UPRN 10023444320 → cert 0868-6045-7331-4376-0914. SAP-Schema-17.0 — FULL-SAP
|
||||
# MID-FLOOR FLAT (sibling of 10023444324, same block / combi PCDB 16211 / MEV),
|
||||
# band M, no party wall, floor + roof both to other dwellings, TFA 50.68 m².
|
||||
# Lodged 81; engine 81. Built in Elmhurst RdSAP10 (evidence saved): Elmhurst
|
||||
# worksheet 82 — engine within ~1 (81.38 vs 82); engine-on-Elmhurst-inputs 82.46
|
||||
# ≈ 82 → calculator faithful. Boiler PCDB 16211 via search; control 2106 (CBE);
|
||||
# water from primary (combi); MEV on; AP50 Blower Door 3.09; mid-floor (floor =
|
||||
# another dwelling below). PINNED to the observed 81 — mapping untuned.
|
||||
RealCertExpectation(
|
||||
schema="SAP-Schema-17.0",
|
||||
sample="uprn_10023444320",
|
||||
cert_num="0868-6045-7331-4376-0914",
|
||||
sap_score=81,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue