Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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" β€”
Expand Down
6 changes: 3 additions & 3 deletions Config/AppSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -668,16 +668,16 @@ public class EroSettings
{
/// <summary>
/// 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.
/// </summary>
public bool Enabled { get; set; } = false;

/// <summary>
/// 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.
/// </summary>
public int CheckIntervalSeconds { get; set; } = 1800;
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions Services/WpcEroService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace NwsAlertBot.Services;

/// <summary>
/// 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
Expand Down Expand Up @@ -64,7 +64,7 @@ private static TimeZoneInfo ResolveTimeZone(string id, ILogger logger)

/// <summary>
/// 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.
/// </summary>
public async Task<List<NwsAlert>> GetEroAlertsAsync()
Expand All @@ -83,7 +83,7 @@ public async Task<List<NwsAlert>> GetEroAlertsAsync()
}

var results = new List<NwsAlert>();
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);
Expand Down
16 changes: 8 additions & 8 deletions docs/TECHNICAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`).
Expand Down Expand Up @@ -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
Expand All @@ -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:

Expand Down
Loading