From 050acd8d956f4753966f77c208a7a07df28dd677 Mon Sep 17 00:00:00 2001 From: Mike Wills Date: Wed, 12 Aug 2026 12:39:01 -0500 Subject: [PATCH] WPC ERO: drop the Day 3 Excessive Rainfall Outlook check Day 3's outlook is low-confidence enough that it was producing noisy, low-value alerts. Only Day 1 and Day 2 are checked now. Co-Authored-By: Claude Sonnet 5 --- CHANGELOG.md | 6 ++++++ Config/AppSettings.cs | 6 +++--- README.md | 2 +- Services/WpcEroService.cs | 6 +++--- docs/TECHNICAL.md | 16 ++++++++-------- 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b37dd4..edf3f9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ Notable changes to NwsAlertBot, most recent first. For setup and usage, see [README.md](README.md); for architecture and internals, see [docs/TECHNICAL.md](docs/TECHNICAL.md). +- **WPC ERO: dropped the Day 3 Excessive Rainfall Outlook check.** `WpcEroService` now only + checks Day 1 and Day 2 against WPC's categorical risk feeds — Day 3's outlook is low-confidence + enough that it was producing noisy, low-value alerts. `WPC Day 3 Excessive Rainfall Outlook` + will no longer be posted. See docs/TECHNICAL.md "WPC Excessive Rainfall Outlook (ERO) — How It + Works". + - **HWO: skip posting all-clear issuances.** New `Hwo.SkipIfNoHazards` setting (default `true`) suppresses a Hazardous Weather Outlook issuance when both its `.DAY ONE...` and `.DAYS TWO THROUGH SEVEN...` sections report "No hazardous weather is expected at this time" — diff --git a/Config/AppSettings.cs b/Config/AppSettings.cs index 6cb1445..824ac70 100644 --- a/Config/AppSettings.cs +++ b/Config/AppSettings.cs @@ -668,16 +668,16 @@ public class EroSettings { /// /// Whether to monitor the WPC (Weather Prediction Center) Excessive Rainfall Outlook (ERO) - /// Day 1/2/3 categorical risk for the locations derived from Location.Zones (or + /// Day 1/2 categorical risk for the locations derived from Location.Zones (or /// Location.Counties if Zones is empty). Alerts when a monitored location is in any - /// non-"None" categorical risk (Marginal or higher) on any of the three days. Note: despite + /// non-"None" categorical risk (Marginal or higher) on either day. Note: despite /// the "Spc"-prefixed sibling settings (Spc, SpcMcd), ERO is issued by WPC, not SPC. /// public bool Enabled { get; set; } = false; /// /// Minimum seconds between checks against the WPC ERO GeoJSON feeds. WPC re-issues Day 1 - /// several times a day and Day 2/3 less often, so polling more than every few minutes has + /// several times a day and Day 2 less often, so polling more than every few minutes has /// no benefit. Default 1800 (30 min) — matches Spc.CheckIntervalSeconds. /// public int CheckIntervalSeconds { get; set; } = 1800; diff --git a/README.md b/README.md index c209dbb..cb2f392 100644 --- a/README.md +++ b/README.md @@ -592,7 +592,7 @@ and per-platform severity-mapping tables for each are in docs/TECHNICAL.md, link | **SPC Convective Outlook** | Day 1/2 severe thunderstorm risk (tornado/wind/hail %) for your area | `"Spc": { "Enabled": true, "CheckIntervalSeconds": 1800 }` | [docs/TECHNICAL.md](docs/TECHNICAL.md#spc-convective-outlook-monitoring--how-it-works) | | **SPC Mesoscale Discussion (MCD)** | Short-fuse (1–3h) severe weather potential, ahead of/alongside active watches | `"SpcMcd": { "Enabled": true, "CheckIntervalSeconds": 300 }` | [docs/TECHNICAL.md](docs/TECHNICAL.md#spc-mesoscale-discussion-monitoring--how-it-works) | | **Hazardous Weather Outlook (HWO)** | Plain-text 7-day hazard summary from your local NWS office | `"Hwo": { "Enabled": true, "CheckIntervalSeconds": 300 }` | [docs/TECHNICAL.md](docs/TECHNICAL.md#hazardous-weather-outlook-hwo--how-it-works) | -| **WPC Excessive Rainfall Outlook (ERO)** | Day 1/2/3 flash-flood-guidance-exceedance risk | `"Ero": { "Enabled": true, "CheckIntervalSeconds": 1800 }` | [docs/TECHNICAL.md](docs/TECHNICAL.md#wpc-excessive-rainfall-outlook-ero--how-it-works) | +| **WPC Excessive Rainfall Outlook (ERO)** | Day 1/2 flash-flood-guidance-exceedance risk | `"Ero": { "Enabled": true, "CheckIntervalSeconds": 1800 }` | [docs/TECHNICAL.md](docs/TECHNICAL.md#wpc-excessive-rainfall-outlook-ero--how-it-works) | HWO is long-form text (no map image) intended primarily for personal use — its per-platform flag, `IncludeHwo`, defaults to `false` (opt-in) rather than `true` like the other three. A common setup diff --git a/Services/WpcEroService.cs b/Services/WpcEroService.cs index aac4bff..4889672 100644 --- a/Services/WpcEroService.cs +++ b/Services/WpcEroService.cs @@ -7,7 +7,7 @@ namespace NwsAlertBot.Services; /// -/// Polls the WPC (Weather Prediction Center) Excessive Rainfall Outlook (ERO) Day 1/2/3 GeoJSON +/// Polls the WPC (Weather Prediction Center) Excessive Rainfall Outlook (ERO) Day 1/2 GeoJSON /// feeds and checks each monitored location (derived from Location.Zones/Location.Counties) /// against the categorical risk polygons (Marginal/Slight/Moderate/High). Produces one synthetic /// NwsAlert per day that is in any non-"None" categorical risk, with a categorical outlook map @@ -64,7 +64,7 @@ private static TimeZoneInfo ResolveTimeZone(string id, ILogger logger) /// /// Returns synthetic alerts for every monitored location currently in a non-"None" - /// categorical ERO risk on Day 1, 2, or 3. Returns an empty list (no HTTP calls) if + /// categorical ERO risk on Day 1 or 2. Returns an empty list (no HTTP calls) if /// called before CheckIntervalSeconds has elapsed since the last check. /// public async Task> GetEroAlertsAsync() @@ -83,7 +83,7 @@ public async Task> GetEroAlertsAsync() } var results = new List(); - foreach (var day in new[] { 1, 2, 3 }) + foreach (var day in new[] { 1, 2 }) { var alert = await CheckDayAsync(day, locations); if (alert != null) results.Add(alert); diff --git a/docs/TECHNICAL.md b/docs/TECHNICAL.md index 996f09d..a26b4af 100644 --- a/docs/TECHNICAL.md +++ b/docs/TECHNICAL.md @@ -430,7 +430,7 @@ Per-platform delivery is controlled by the separate `IncludeHwo` flag, which def | Field | Description | Default | |---|---|---| -| `Enabled` | Whether to monitor the WPC Excessive Rainfall Outlook Day 1/2/3 categorical risk | `false` | +| `Enabled` | Whether to monitor the WPC Excessive Rainfall Outlook Day 1/2 categorical risk | `false` | | `CheckIntervalSeconds` | Minimum seconds between ERO checks | `1800` | Per-platform delivery is controlled by the separate `IncludeEro` flag (default `true`). @@ -594,17 +594,18 @@ The event name for `EventTypes` filtering is `Hazardous Weather Outlook`. ## WPC Excessive Rainfall Outlook (ERO) — How It Works The bot can also monitor the [WPC (Weather Prediction Center) Excessive Rainfall Outlook](https://www.wpc.ncep.noaa.gov/qpf/excessive_rainfall_outlook_ero.php) -(ERO) — Day 1, 2, and 3 forecasts of the probability that rainfall will exceed flash flood +(ERO) — Day 1 and 2 forecasts of the probability that rainfall will exceed flash flood guidance near a point, categorized into four risk levels: Marginal (≥5%), Slight (≥15%), Moderate (≥40%), and High (≥70%). Note: despite living alongside the SPC-issued feeds in this -bot, ERO is a **WPC** product, not SPC. +bot, ERO is a **WPC** product, not SPC. Day 3 is intentionally not checked — WPC's Day 3 +outlook is low-confidence enough that it produced noisy, low-value alerts in practice. - **Locations monitored** reuse the same `Location.Zones`/`Location.Counties` centroids as SPC Outlook/MCD — resolved once at startup and cached for the life of the process. - **Categorical risk** (`Marginal` / `Slight` / `Moderate` / `High`) is checked independently - for Day 1, 2, and 3 against WPC's GeoJSON feeds - (`https://www.wpc.ncep.noaa.gov/exper/eromap/geojson/Day{1,2,3}_Latest.geojson`). A location - with no categorical match ("None"/sub-5%) never triggers an alert, on any day. + for Day 1 and 2 against WPC's GeoJSON feeds + (`https://www.wpc.ncep.noaa.gov/exper/eromap/geojson/Day{1,2}_Latest.geojson`). A location + with no categorical match ("None"/sub-5%) never triggers an alert, on either day. - **Checked every `Ero.CheckIntervalSeconds`** (default 1800s = 30 min) — independent of `Polling.PollIntervalSeconds`. - **Re-alerts on every new WPC issuance**, not only on a category change, the same as SPC @@ -626,8 +627,7 @@ bot, ERO is a **WPC** product, not SPC. ERO alerts flow through each platform's existing `MinSeverity`/`EventTypes` dials — no new filter fields were added beyond `IncludeEro` (see [Configuration Reference](#configuration-reference)): -- **Event names** — `WPC Day 1 Excessive Rainfall Outlook`, `WPC Day 2 Excessive Rainfall Outlook`, - and `WPC Day 3 Excessive Rainfall Outlook`. +- **Event names** — `WPC Day 1 Excessive Rainfall Outlook` and `WPC Day 2 Excessive Rainfall Outlook`. - **Severity mapping** — WPC's own category names don't line up 1:1 in name with this bot's Severity scale, only in rank order: