Spaces:
Running on Zero
Running on Zero
File size: 11,443 Bytes
6143b69 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | """Patch frontend/index.html with official 54-leaf STATIC_L3_SECTIONS."""
from __future__ import annotations
from pathlib import Path
from backend.domain.rics_level3_schema import CANONICAL_SCHEMA
HINTS = {
"A1": "surveyor name · RICS number · qualifications · company · contact",
"A2": "inspection date · time on site",
"A3": "related party · conflict of interest",
"A4": "weather · dry · wet · overcast",
"A5": "occupied · vacant · furnished · access limitations",
"B1": "condition ratings summary · Cat 1 · Cat 2 · Cat 3",
"B2": "overall opinion · key findings",
"B3": "further investigations · specialist reports",
"C1": "property type · construction · detached · cavity · timber frame",
"C2": "year built · approximate age · period",
"C3": "accommodation · bedrooms · bathrooms · storeys · room matrix",
"C4": "EPC · energy efficiency · double glazing",
"C5": "location · facilities · flood · radon · noise",
"D1": "chimney stacks · pots · flaunching · flashings · lean · condition rating",
"D2": "roof covering · slate · tile · felt · slipped tiles · moss · condition rating",
"D3": "gutters · downpipes · rainwater · hopper · leakage · condition rating",
"D4": "main walls · cavity · render · DPC · cracking · condition rating",
"D5": "windows · glazing · FENSA · frames · condition rating",
"D6": "outside doors · patio doors · entrance door · condition rating",
"D7": "conservatory · porch · glazing · condition rating",
"D8": "fascias · soffits · external joinery · condition rating",
"D9": "other outside elements · balconies · external stairs",
"E1": "roof structure · trusses · rafters · purlins · loft access · condition rating",
"E2": "ceilings · plaster · artex · cracking · condition rating",
"E3": "walls · partitions · damp · cracking · condition rating",
"E4": "floors · suspended · solid · springy · condition rating",
"E5": "fireplaces · chimney breasts · flues · hearth · condition rating",
"E6": "built-in kitchen · fitted wardrobes · cupboards · condition rating",
"E7": "staircase · skirting · architrave · internal doors · condition rating",
"E8": "bathroom fittings · sanitaryware · shower · WC · condition rating",
"E9": "cellar · basement · other inside · condition rating",
"F1": "electricity · consumer unit · wiring · EICR · condition rating",
"F2": "gas · oil · meter · pipework · Gas Safe · condition rating",
"F3": "water supply · stopcock · lead pipes · condition rating",
"F4": "heating · boiler · radiators · controls · condition rating",
"F5": "water heating · cylinder · combi · immersion · condition rating",
"F6": "drainage · manholes · sewers · condition rating",
"F7": "common services · shared utilities · flats only",
"G1": "garage · car port · door · condition rating",
"G2": "outbuildings · shed · workshop · condition rating",
"G3": "boundaries · garden · driveway · shared areas · condition rating",
"H1": "regulations · planning · listed building · conservation area",
"H2": "guarantees · NHBC · FENSA · warranties",
"H3": "tenure · lease · easements · other legal matters",
"I1": "structural movement · dampness · timber defects · building risks",
"I2": "flood · radon · mining · knotweed · ground risks",
"I3": "asbestos · fire safety · safety glass · people risks",
"I4": "other risks · contamination · hazards",
"J1": "insulation · loft · cavity · floor insulation",
"J2": "heating efficiency · boiler · heat pump",
"J3": "lighting · LED · natural light",
"J4": "ventilation · trickle vents · extract fans",
"J5": "general energy · solar · EPC improvements",
"K1": "surveyor declaration · signature · RICS · qualifications",
"L1": "quotations · next steps · recommended actions",
"M1": "terms of engagement · scope · fee · complaints",
"N1": "typical house diagram · illustration reference",
}
ROUTES_JS = """function routeLinesToSections(lines) {
const routes = [
{ code:'A1', rx:/surveyor|rics\\s*member|qualification|company\\s*name|indemnity/i },
{ code:'A2', rx:/date\\s*of\\s*inspection|inspection\\s*date|survey\\s*date/i },
{ code:'A3', rx:/related\\s*party|conflict\\s*of\\s*interest/i },
{ code:'A4', rx:/weather|conditions\\s*on\\s*site|dry\\s*day|wet\\s*day/i },
{ code:'A5', rx:/occupied|vacant|furnished|property\\s*status/i },
{ code:'B1', rx:/summary\\s*of\\s*condition|condition\\s*rat|category\\s*[123]/i },
{ code:'B2', rx:/overall\\s*opinion|general\\s*condition|key\\s*findings/i },
{ code:'B3', rx:/further\\s*invest|specialist\\s*report/i },
{ code:'C1', rx:/\\bsemi.?det|\\bdet(ached)?\\b|terraced|bungalow|maisonette|type\\s*and\\s*construct|timber\\s*frame|cavity\\s*wall/i },
{ code:'C2', rx:/year\\s*built|approximate\\s*year|circa\\s*19|circa\\s*20|built\\s*in\\s*19/i },
{ code:'C3', rx:/accommodation|bedroom|reception\\s*room|storey|room\\s*matrix|sq\\.?\\s*m\\b/i },
{ code:'C4', rx:/\\bepc\\b|energy\\s*effici|sap\\s*rating/i },
{ code:'C5', rx:/location|facilities|flood\\s*zone|radon|mining|contamination/i },
{ code:'D1', rx:/chimney\\s*stack|chimney\\s*pot|flaunch|\\bchimney\\b|stack.*brick|tv\\s*aerial/i },
{ code:'D2', rx:/roof\\s*cover|slate|slates|tile\\s*roof|felt\\s*roof|flat\\s*roof|hip\\s*roof|ridge\\s*tile|slipp|moss.*roof/i },
{ code:'D3', rx:/rainwater|gutter|gutters|downpipe|down\\s*pipe|gullies|rwp\\b|hopper|fittings.*brittle/i },
{ code:'D4', rx:/main\\s*wall|external\\s*wall|brick\\s*wall|cavity\\s*wall|render|pointing|dpc\\b|parapet/i },
{ code:'D5', rx:/window|glazing|fensa|upvc\\s*window|sash\\s*window|bay\\s*window/i },
{ code:'D6', rx:/external\\s*door|outside\\s*door|patio\\s*door|entrance\\s*door|front\\s*door/i },
{ code:'D7', rx:/conservatory|porch\\b/i },
{ code:'D8', rx:/fascia\\b|soffit\\b|bargeboard|external\\s*joinery|cladding/i },
{ code:'D9', rx:/balcony|external\\s*stair|other\\s*outside/i },
{ code:'E1', rx:/roof\\s*struct|truss|purlin|collar\\s*tie|cut\\s*rafter|trussed\\s*rafter|rafter.*loft|loft\\s*hatch/i },
{ code:'E2', rx:/ceil|ceiling|artex|lath.*plaster/i },
{ code:'E3', rx:/internal\\s*wall|partition|plaster.*wall|stud\\s*wall|rising\\s*damp|penetrat.*damp/i },
{ code:'E4', rx:/floor\\s*board|suspended\\s*floor|solid\\s*floor|sub.?floor|springy\\s*floor/i },
{ code:'E5', rx:/fireplace|chimney\\s*breast|hearth|open\\s*fire|flue\\s*liner/i },
{ code:'E6', rx:/built.?in\\s*fit|fitted\\s*kitchen|built.?in\\s*wardrobe|kitchen\\s*unit/i },
{ code:'E7', rx:/skirting|architrave|staircase|internal\\s*door|woodwork|joinery/i },
{ code:'E8', rx:/bathroom|sanitary|shower|wc\\b|basin/i },
{ code:'E9', rx:/cellar|basement|other\\s*inside/i },
{ code:'F1', rx:/electric|consumer\\s*unit|fuse\\s*board|wiring|earthing|rcd\\b|eicr/i },
{ code:'F2', rx:/\\bgas\\b|oil\\s*tank|lpg|gas\\s*meter|gas\\s*pipe|gas\\s*safe/i },
{ code:'F3', rx:/water\\s*supply|stopcock|mains\\s*water|lead\\s*pipe/i },
{ code:'F4', rx:/boiler|central\\s*heat|radiator|heating\\s*system|vaillant|worcester/i },
{ code:'F5', rx:/hot\\s*water|water\\s*heat|cylinder|combi|immersion/i },
{ code:'F6', rx:/drain|sewer|manhole|soil\\s*pipe|septic|gully/i },
{ code:'F7', rx:/common\\s*service|shared\\s*util/i },
{ code:'G1', rx:/\\bgarage\\b|car\\s*port/i },
{ code:'G2', rx:/outbuilding|shed\\b|workshop|permanent\\s*outbuild/i },
{ code:'G3', rx:/boundary|fence\\b|hedge|retaining\\s*wall|garden\\b|driveway|grounds/i },
{ code:'H1', rx:/building\\s*reg|planning\\s*permiss|listed\\s*build|conservation\\s*area|regulation/i },
{ code:'H2', rx:/guarantee|warranty|nhbc|fensa\\s*certif/i },
{ code:'H3', rx:/tenure|leasehold|freehold|easement|covenant|legal\\s*advis/i },
{ code:'I1', rx:/rising\\s*damp|penetrat.*damp|condensation|mould|subsiden|structural\\s*movement|woodworm|dry\\s*rot|wet\\s*rot|timber\\s*decay/i },
{ code:'I2', rx:/flood\\s*risk|radon|mining|knotweed|tree\\s*root|shrinkable\\s*clay|risk.*ground/i },
{ code:'I3', rx:/asbestos|chrysotile|aib\\b|fire\\s*safety|safety\\s*glass|lead\\s*pipe|trip\\s*hazard|balustrade/i },
{ code:'I4', rx:/contamination|unexploded|invasive\\s*species|other\\s*risk|other\\s*hazard/i },
{ code:'J1', rx:/loft\\s*insul|roof\\s*void\\s*insul|cavity\\s*insul|insulation/i },
{ code:'J2', rx:/boiler\\s*effici|heating\\s*effici|heat\\s*pump|zone\\s*control/i },
{ code:'J3', rx:/lighting|led\\b|low\\s*energy\\s*light/i },
{ code:'J4', rx:/ventilation|trickle\\s*vent|extract\\s*fan/i },
{ code:'J5', rx:/energy\\s*matter|renewable|solar\\s*panel|epc\\s*improv/i },
{ code:'K1', rx:/surveyor\\s*declar|signature|rics\\s*number/i },
{ code:'L1', rx:/what\\s*to\\s*do|obtain\\s*quot|next\\s*step/i },
{ code:'M1', rx:/terms\\s*of\\s*engage|scope\\s*of\\s*survey|service\\s*description/i },
{ code:'N1', rx:/typical\\s*house\\s*diagram|diagram\\s*reference/i },
];"""
GROUP_LABELS = """const STATIC_L3_GROUP_LABELS = {
A:'A — About the inspection',
B:'B — Overall opinion and summary of ratings',
C:'C — About the property',
D:'D — Outside the property',
E:'E — Inside the property',
F:'F — Services',
G:'G — Grounds (including shared areas for flats)',
H:'H — Issues for your legal advisers',
I:'I — Risks',
J:'J — Energy matters',
K:"K — Surveyor's declaration",
L:'L — What to do now',
M:'M — Description of the RICS Home Survey - Level 3 service and terms of engagement',
N:'N — Typical house diagram',
};"""
def _sections_block() -> str:
lines = ["const STATIC_L3_SECTIONS = ["]
for parent in CANONICAL_SCHEMA["sections"]:
gid = str(parent["id"])
for sub in parent.get("subsections") or []:
code = str(sub["id"])
title = str(sub["label"]).replace("'", "\\'")
hint = HINTS.get(code, title)
lines.append(
f" {{ code:'{code}', group:'{gid}', title:'{title}', hint:'{hint}' }},"
)
lines.append("];")
return "\n".join(lines)
def main() -> None:
path = Path(__file__).resolve().parents[2] / "frontend" / "index.html"
text = path.read_text(encoding="utf-8")
start = text.index("const STATIC_L3_SECTIONS = [")
end = text.index("];", start) + 2
text = text[:start] + _sections_block() + text[end:]
gl_start = text.index("const STATIC_L3_GROUP_LABELS = {")
gl_end = text.index("};", gl_start) + 2
text = text[:gl_start] + GROUP_LABELS + text[gl_end:]
fn_start = text.index("function routeLinesToSections(lines) {")
fn_end = text.index(" const routeCodes = ", fn_start)
text = text[:fn_start] + ROUTES_JS.strip() + "\n\n" + text[fn_end:]
# Fix comment above routeLinesToSections
text = text.replace(
" * Codes match backend schema (D1=chimney, D4=rainwater, E1=loft insulation, …).",
" * Codes match official RICS L3 matrix (D2=roof coverings, E1=roof structure, …).",
)
path.write_text(text, encoding="utf-8")
print(f"Patched {path}")
if __name__ == "__main__":
main()
|