110 lines
4.3 KiB
Go
110 lines
4.3 KiB
Go
package briefing
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"gitea.maximumdirect.net/eric/weatherreporter/internal/forecast"
|
|
"gitea.maximumdirect.net/eric/weatherreporter/internal/module"
|
|
)
|
|
|
|
const (
|
|
precipTimingChanceLowerBound = 40
|
|
precipTimingLikelyLowerBound = 50
|
|
precipTimingExpectLowerBound = 70
|
|
)
|
|
|
|
type PrecipTimingModule struct {
|
|
MaxPopPercent *int `json:"max_pop_percent,omitempty"`
|
|
MaxPopTime string `json:"max_pop_time,omitempty"`
|
|
ProbabilityThreshold float64 `json:"probability_threshold"`
|
|
PrecipitationWindows []PrecipitationWindowModule `json:"precipitation_windows,omitempty"`
|
|
ThunderMentioned bool `json:"thunder_mentioned"`
|
|
}
|
|
|
|
type PrecipitationWindowModule struct {
|
|
PeriodBegins string `json:"period_begins"`
|
|
PeriodBeginsHourLabel string `json:"period_begins_hour_label,omitempty"`
|
|
PeriodEnds string `json:"period_ends,omitempty"`
|
|
PeriodEndsHourLabel string `json:"period_ends_hour_label,omitempty"`
|
|
MaxPopPercent *int `json:"max_pop_percent,omitempty"`
|
|
MaxPopTime string `json:"max_pop_time,omitempty"`
|
|
MaxPopHourLabel string `json:"max_pop_hour_label,omitempty"`
|
|
PrecipitationType string `json:"precipitation_type,omitempty"`
|
|
ExpectationPhrase string `json:"expectation_phrase,omitempty"`
|
|
}
|
|
|
|
func buildPrecipTimingModule(ctx ModuleContext, _ any) (*module.Output, error) {
|
|
value := precipTimingValue(ctx.Derived.PrecipTiming, ctx.Timezone)
|
|
return &module.Output{ID: module.PrecipTiming, StanzaName: "precip_timing", Value: value}, nil
|
|
}
|
|
|
|
func precipTimingValue(timing forecast.PrecipTiming, timezone string) PrecipTimingModule {
|
|
value := PrecipTimingModule{
|
|
ProbabilityThreshold: timing.ProbabilityThreshold,
|
|
ThunderMentioned: timing.ThunderMentioned,
|
|
}
|
|
if timing.MaxPrecipitationProbability != nil {
|
|
value.MaxPopPercent = roundedInt(&timing.MaxPrecipitationProbability.Value)
|
|
value.MaxPopTime = clockLabel(timing.MaxPrecipitationProbability.Time, timezone)
|
|
}
|
|
for _, window := range timing.PrecipitationWindows {
|
|
item := PrecipitationWindowModule{
|
|
PeriodBegins: friendlyDateTimeLabel(window.Start, timezone),
|
|
PeriodBeginsHourLabel: hourMinuteLabel(window.Start, timezone),
|
|
}
|
|
if window.End != nil {
|
|
item.PeriodEnds = friendlyDateTimeLabel(*window.End, timezone)
|
|
item.PeriodEndsHourLabel = hourMinuteLabel(*window.End, timezone)
|
|
}
|
|
item.MaxPopPercent = roundedInt(&window.MaxPrecipitationProbability.Value)
|
|
item.MaxPopTime = clockLabel(window.MaxPrecipitationProbability.Time, timezone)
|
|
item.MaxPopHourLabel = hourMinuteLabel(window.MaxPrecipitationProbability.Time, timezone)
|
|
item.PrecipitationType = precipitationWindowType(window.TextDescriptions)
|
|
if item.MaxPopPercent != nil {
|
|
item.ExpectationPhrase = precipitationWindowExpectationPhrase(*item.MaxPopPercent, item.PrecipitationType)
|
|
}
|
|
value.PrecipitationWindows = append(value.PrecipitationWindows, item)
|
|
}
|
|
return value
|
|
}
|
|
|
|
func precipitationWindowType(descriptions []string) string {
|
|
combined := strings.ToLower(strings.Join(descriptions, " "))
|
|
switch {
|
|
case (strings.Contains(combined, "thunderstorm") || strings.Contains(combined, "t-storm")) &&
|
|
(strings.Contains(combined, "shower") || strings.Contains(combined, "rain")):
|
|
return "showers and thunderstorms"
|
|
case strings.Contains(combined, "freezing rain"):
|
|
return "freezing rain"
|
|
case strings.Contains(combined, "thunderstorm") || strings.Contains(combined, "t-storm"):
|
|
return "thunderstorms"
|
|
case strings.Contains(combined, "shower"):
|
|
return "showers"
|
|
case strings.Contains(combined, "snow"):
|
|
return "snow"
|
|
case strings.Contains(combined, "drizzle"):
|
|
return "drizzle"
|
|
case strings.Contains(combined, "rain"):
|
|
return "rain"
|
|
default:
|
|
return "precipitation"
|
|
}
|
|
}
|
|
|
|
func precipitationWindowExpectationPhrase(maxPopPercent int, precipitationType string) string {
|
|
if precipitationType == "" {
|
|
precipitationType = "precipitation"
|
|
}
|
|
switch {
|
|
case maxPopPercent >= precipTimingExpectLowerBound:
|
|
return fmt.Sprintf("Expect %s.", precipitationType)
|
|
case maxPopPercent >= precipTimingLikelyLowerBound:
|
|
return fmt.Sprintf("%s likely.", capitalizeFirst(strings.TrimSpace(precipitationType)))
|
|
case maxPopPercent >= precipTimingChanceLowerBound:
|
|
return fmt.Sprintf("Chance of %s.", precipitationType)
|
|
default:
|
|
return ""
|
|
}
|
|
}
|