From 2a4a73dbd75c1e55833319d00619bce3d6ae9470 Mon Sep 17 00:00:00 2001 From: Yorick de Wid Date: Sun, 26 Jul 2026 21:18:58 +0000 Subject: [PATCH] feat(mapset): HotSpot legend + Risico mapset attachment Closes #919 (DB half). Adds the 'hotspot' application.mapset_layer row and appends it to the Risico mapset, same shape as add_contractor_tile_layer.sql (#882). A HotSpot is MAX(drystand_risk, dewatering_depth_risk) >= 'd'. No data work is needed - both columns are already in maplayer.building_tiles and in every zoom of maplayer.buildings(z,x,y) - so the layer is entirely a MapLibre filter + paint expression, shipped in FunderMapsWebFront src/config/layers/hotspot.json. Legend reuses the D and E colors of the existing drystand / dewatering legends; order = 0 puts HotSpot above the models it summarizes. Scope on 2026-07-26: 165,286 of 6,449,590 buildings (2.6%) qualify, 8,817 class E and 156,469 class D. Dry-run in a rolled-back transaction on prod: insert + update clean, mapset_collection serves HotSpot first. APPLY ONLY AFTER the WebFront layer config is live - the other order leaves a legend entry WebFront cannot resolve. Co-Authored-By: Claude Opus 5 (1M context) --- sql/migrate/add_hotspot_layer.sql | 48 +++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 sql/migrate/add_hotspot_layer.sql diff --git a/sql/migrate/add_hotspot_layer.sql b/sql/migrate/add_hotspot_layer.sql new file mode 100644 index 0000000..da53aeb --- /dev/null +++ b/sql/migrate/add_hotspot_layer.sql @@ -0,0 +1,48 @@ +-- HotSpot map layer for the Risico mapset (issue Laixer/FunderMaps#919). +-- +-- A HotSpot is a building whose HIGHEST risk class across the two +-- groundwater-driven models is D or E: +-- +-- MAX(drystand_risk, dewatering_depth_risk) >= 'd' +-- +-- The classes are ordered a < b < c < d < e, so "the maximum" is simply the +-- worse of the two; A/B/C are excluded entirely. The layer is a fast visual +-- answer to "where should we look first", not a new model. +-- +-- No data work is needed: maplayer.building_tiles already carries both +-- drystand_risk and dewatering_depth_risk, and maplayer.buildings(z,x,y) +-- emits both at every zoom (z12-13 included), so the whole layer is a +-- MapLibre filter + paint expression over the existing 'buildings' tile +-- source. Styling lives in FunderMapsWebFront src/config/layers/hotspot.json +-- and must stay in sync with the legend below. +-- +-- Scope on 2026-07-26: 165,286 of 6,449,590 buildings (2.6%) qualify - +-- 8,817 with a worst class of E, 156,469 with D. + +-------------------------------------------------------------------------------- +-- 1. Legend. Two entries, reusing the exact D and E colors of the existing +-- drystand-risk / dewatering-depth-risk legends so the HotSpot layer reads +-- as a summary of those two rather than a separate scale. +-- "order" = 0 puts HotSpot at the top of the Risico legend, above the +-- individual model layers it summarizes. +-------------------------------------------------------------------------------- + +INSERT INTO application.mapset_layer (id, name, fields, "order") VALUES ( + 'hotspot', + 'HotSpot', + '[ + {"name": "Verhoogd risico (D)", "color": "FFAC33"}, + {"name": "Hoog risico (E)", "color": "FF5533"} + ]'::jsonb, + 0 +) +ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, fields = EXCLUDED.fields; + +-------------------------------------------------------------------------------- +-- 2. Attach to the Risico mapset. +-------------------------------------------------------------------------------- + +UPDATE application.mapset +SET layers = array_append(layers, 'hotspot') +WHERE id = 'clcqkaaea000714o1v1jmdqwf' + AND NOT ('hotspot' = ANY (layers));