feat(storm-intel): damage-probability homes estimate + pinned events total in header

useStormEvents:
- Replace flat 1800/sq mi estimate with damage probability multiplier per type:
  hail ≥2.0" = 95%, 1.75" = 80%, 1.5" = 65%, 1.25" = 45%, 1.0" = 30%, <1.0" = 15%;
  tornado = 20% (path << polygon), flood = 25%, wind = 40%, winter = 20-30%
- Expose damagePct on event object for display in drawer

StormIntelPage:
- pinnedHomes useMemo — sums estimatedHomes across event-pinned events
- Header homes stat switches to amber + "Est. Homes · N pinned" label when events are pinned;
  hover tooltip notes zones may overlap
- Drawer: "Est. Homes Affected" now shows "~X% damage probability" as sub-label
This commit is contained in:
Satyam-Rastogi
2026-05-19 02:31:57 +05:30
parent 4c32266f3d
commit 30728a0db6
2 changed files with 44 additions and 8 deletions
+21 -3
View File
@@ -111,9 +111,7 @@ function featureToEvent(feature, idx) {
? Math.round((new Date(expireTime) - new Date(issueTime)) / 60000)
: null;
const areaSqMi = Math.round(polygonAreaSqMi(polygon));
// Suburban DFW density ~1 800 homes/sq mi — conservative (polygons often include open land)
const estHomes = Math.round(areaSqMi * 1800);
const areaSqMi = Math.round(polygonAreaSqMi(polygon));
const type = ph === 'TO' ? 'tornado'
: ph === 'FF' ? 'flood'
@@ -128,6 +126,25 @@ function featureToEvent(feature, idx) {
: ph === 'FF' ? 'moderate'
: 'significant';
// Damage probability: fraction of homes in the warning zone likely to have claimable damage.
// Tornado path is far narrower than the warning polygon, so we discount heavily.
// Hail probability scales with hail size — golf ball (2"+) damages nearly everything it hits.
const damagePct =
ph === 'TO' ? 20
: ph === 'FF' ? 25
: ph === 'WS' || ph === 'BZ' ? 30
: ph === 'WW' || ph === 'IS' ? 20
: hailIn === null ? 40 // SV wind only
: hailIn >= 2.0 ? 95
: hailIn >= 1.75 ? 80
: hailIn >= 1.5 ? 65
: hailIn >= 1.25 ? 45
: hailIn >= 1.0 ? 30
: 15; // <1" — cosmetic, rarely claimed
// Homes in zone × suburban DFW density (1 800/sq mi) × damage probability
const estHomes = Math.round(areaSqMi * 1800 * (damagePct / 100));
return {
id: `IEM-${WFO}-${ph}-${p.year ?? ''}-${p.eventid ?? idx}`,
date: issueTime || new Date().toISOString(),
@@ -142,6 +159,7 @@ function featureToEvent(feature, idx) {
areaName: derivedAreaName(rawCoords, ph),
county: 'Collin',
areaSqMi,
damagePct,
estimatedHomes: estHomes > 0 ? estHomes : null,
description: `${PH_LABEL[ph] ?? ph} — NWS ${WFO}`,
source: 'IEM/NWS',