Update wind direction and precipitation window presentation

This commit is contained in:
2026-06-10 09:24:06 -05:00
parent c3da3af2f4
commit d1d0df11a8
10 changed files with 284 additions and 45 deletions

View File

@@ -30,8 +30,8 @@ func TestDerivedDailySummaryModulePackagesOrdinaryForecast(t *testing.T) {
if value.MaxPopPercent == nil || *value.MaxPopPercent != 80 || value.MaxPopWindow != "12 PM-6 PM" {
t.Fatalf("max precip = %#v %q, want 80 and afternoon window", value.MaxPopPercent, value.MaxPopWindow)
}
if value.FirstPrecipHour != "8 AM" || value.LastPrecipHour != "1 PM" || !value.ThunderMentioned {
t.Fatalf("precip timing = %#v, want morning through afternoon thunder", value)
if value.FirstPrecipHour != "8 AM" || value.LastPrecipHour != "2 PM" || !value.ThunderMentioned {
t.Fatalf("precip timing = %#v, want threshold windows from morning through afternoon thunder", value)
}
if value.MaxWindGustMph == nil || *value.MaxWindGustMph != 42 {
t.Fatalf("MaxWindGustMph = %#v, want 42", value.MaxWindGustMph)
@@ -63,8 +63,27 @@ func TestPrecipTimingModuleHandlesRainyAndDryForecasts(t *testing.T) {
t.Fatalf("BuildModule(rainy) error = %v", err)
}
rainy := moduleValue[PrecipTimingModule](t, output)
if rainy.MaxPopPercent == nil || *rainy.MaxPopPercent != 80 || rainy.FirstPrecipHour != "8 AM" || rainy.LastPrecipHour != "1 PM" || !rainy.ThunderMentioned {
t.Fatalf("rainy precip timing = %#v, want peak, first/last, thunder", rainy)
if rainy.MaxPopPercent == nil || *rainy.MaxPopPercent != 80 || rainy.MaxPopTime != "12 PM" || rainy.ProbabilityThreshold != forecast.DefaultPrecipWindowProbabilityThreshold || !rainy.ThunderMentioned {
t.Fatalf("rainy precip timing = %#v, want peak, threshold, and thunder", rainy)
}
if len(rainy.PrecipitationWindows) != 2 {
t.Fatalf("rainy precipitation windows = %#v, want two windows", rainy.PrecipitationWindows)
}
if rainy.PrecipitationWindows[0].Start != "8 AM" || rainy.PrecipitationWindows[0].End != "9 AM" || rainy.PrecipitationWindows[0].MaxPopPercent == nil || *rainy.PrecipitationWindows[0].MaxPopPercent != 60 {
t.Fatalf("first precipitation window = %#v, want 8-9 AM at 60%%", rainy.PrecipitationWindows[0])
}
if rainy.PrecipitationWindows[1].Start != "12 PM" || rainy.PrecipitationWindows[1].End != "2 PM" || rainy.PrecipitationWindows[1].MaxPopPercent == nil || *rainy.PrecipitationWindows[1].MaxPopPercent != 80 {
t.Fatalf("second precipitation window = %#v, want noon-2 PM at 80%%", rainy.PrecipitationWindows[1])
}
data, err := json.Marshal(output.Value)
if err != nil {
t.Fatalf("marshal precip timing: %v", err)
}
if !strings.Contains(string(data), "precipitation_windows") || !strings.Contains(string(data), "probability_threshold") {
t.Fatalf("precip timing json = %s, want threshold and windows", string(data))
}
if strings.Contains(string(data), "first_precip_hour") || strings.Contains(string(data), "last_precip_hour") {
t.Fatalf("precip timing json = %s, want no ambiguous first/last fields", string(data))
}
ctx.Derived.PrecipTiming = forecast.BuildPrecipTiming([]weatherdata.ForecastPeriod{derivedHour("2026-05-29T10:00:00-05:00", "Sunny", 0, 70, nil, 5)})
@@ -73,8 +92,8 @@ func TestPrecipTimingModuleHandlesRainyAndDryForecasts(t *testing.T) {
t.Fatalf("BuildModule(dry) error = %v", err)
}
dry := moduleValue[PrecipTimingModule](t, output)
if dry.FirstPrecipHour != "" || dry.LastPrecipHour != "" || dry.ThunderMentioned {
t.Fatalf("dry precip timing = %#v, want no precip hours and no thunder", dry)
if len(dry.PrecipitationWindows) != 0 || dry.ThunderMentioned {
t.Fatalf("dry precip timing = %#v, want no precip windows and no thunder", dry)
}
if dry.MaxPopPercent == nil || *dry.MaxPopPercent != 0 {
t.Fatalf("dry MaxPopPercent = %#v, want checked zero", dry.MaxPopPercent)
@@ -191,8 +210,10 @@ func derivedModuleContext(id report.ID) ModuleContext {
hours := []weatherdata.ForecastPeriod{
derivedHour("2026-05-29T00:00:00-05:00", "Clear and cold", 0, 31, nil, 5),
derivedHour("2026-05-29T08:00:00-05:00", "Showers", 60, 58, nil, 15),
derivedHour("2026-05-29T09:00:00-05:00", "Dry break", 20, 62, nil, 10),
derivedHour("2026-05-29T12:00:00-05:00", "Thunderstorms with gusty wind", 80, 96, floatPtr(101), 42),
derivedHour("2026-05-29T13:00:00-05:00", "Heavy rain", 70, 82, nil, 30),
derivedHour("2026-05-29T14:00:00-05:00", "Drying out", 20, 78, nil, 12),
}
narrative := []weatherdata.ForecastPeriod{
{