94 lines
4.5 KiB
Go
94 lines
4.5 KiB
Go
package briefing
|
|
|
|
import (
|
|
"time"
|
|
|
|
"gitea.maximumdirect.net/eric/weatherreporter/internal/module"
|
|
"gitea.maximumdirect.net/eric/weatherreporter/internal/timeutil"
|
|
"gitea.maximumdirect.net/eric/weatherreporter/internal/weatherdata"
|
|
)
|
|
|
|
type NarrativeForecastModule struct {
|
|
Product string `json:"product,omitempty"`
|
|
IssuedAt time.Time `json:"issued_at,omitempty"`
|
|
UpdatedAt *time.Time `json:"updated_at,omitempty"`
|
|
SourceLocation string `json:"source_location,omitempty"`
|
|
SourceLocationID string `json:"source_location_id,omitempty"`
|
|
Periods []NarrativeForecastPeriod `json:"periods,omitempty"`
|
|
}
|
|
|
|
type NarrativeForecastPeriod struct {
|
|
Name string `json:"name,omitempty"`
|
|
PeriodBegins string `json:"period_begins,omitempty"`
|
|
PeriodEnds string `json:"period_ends,omitempty"`
|
|
IsDay *bool `json:"is_day,omitempty"`
|
|
TextDescription string `json:"text_description,omitempty"`
|
|
TemperatureC *float64 `json:"temperature_c,omitempty"`
|
|
TemperatureF *float64 `json:"temperature_f,omitempty"`
|
|
TemperatureCMin *float64 `json:"temperature_c_min,omitempty"`
|
|
TemperatureFMin *float64 `json:"temperature_f_min,omitempty"`
|
|
TemperatureCMax *float64 `json:"temperature_c_max,omitempty"`
|
|
TemperatureFMax *float64 `json:"temperature_f_max,omitempty"`
|
|
WindSpeedKmh *float64 `json:"wind_speed_kmh,omitempty"`
|
|
WindSpeedMph *float64 `json:"wind_speed_mph,omitempty"`
|
|
WindGustKmh *float64 `json:"wind_gust_kmh,omitempty"`
|
|
WindGustMph *float64 `json:"wind_gust_mph,omitempty"`
|
|
WindDirection string `json:"wind_direction,omitempty"`
|
|
ProbabilityOfPrecipitationPercent *float64 `json:"probability_of_precipitation_percent,omitempty"`
|
|
}
|
|
|
|
func buildNarrativeForecastModule(ctx ModuleContext, _ any) (*module.Output, error) {
|
|
narrative := ctx.Collected.Narrative
|
|
if narrative == nil || len(ctx.Derived.ValidPeriodNarrativePeriods) == 0 {
|
|
return nil, nil
|
|
}
|
|
value := NarrativeForecastModule{
|
|
Product: narrative.Product,
|
|
IssuedAt: narrative.IssuedAt,
|
|
UpdatedAt: copyTime(narrative.UpdatedAt),
|
|
SourceLocation: narrative.LocationName,
|
|
SourceLocationID: narrative.LocationID,
|
|
Periods: narrativeForecastPeriods(ctx.Derived.ValidPeriodNarrativePeriods, ctx.Timezone),
|
|
}
|
|
if value.isEmpty() {
|
|
return nil, nil
|
|
}
|
|
return &module.Output{ID: module.NarrativeForecast, StanzaName: "narrative_forecast", Value: value}, nil
|
|
}
|
|
|
|
func narrativeForecastPeriods(periods []weatherdata.ForecastPeriod, timezone string) []NarrativeForecastPeriod {
|
|
out := make([]NarrativeForecastPeriod, 0, len(periods))
|
|
for _, period := range periods {
|
|
validPeriod := timeutil.Period{Start: period.StartTime, End: period.EndTime}
|
|
out = append(out, NarrativeForecastPeriod{
|
|
Name: period.Name,
|
|
PeriodBegins: friendlyPeriodBeginsLabel(validPeriod, timezone),
|
|
PeriodEnds: friendlyPeriodEndsLabel(validPeriod, timezone),
|
|
IsDay: copyBool(period.IsDay),
|
|
TextDescription: period.TextDescription,
|
|
TemperatureC: copyFloat(period.TemperatureC),
|
|
TemperatureF: copyFloat(period.TemperatureF),
|
|
TemperatureCMin: copyFloat(period.TemperatureCMin),
|
|
TemperatureFMin: copyFloat(period.TemperatureFMin),
|
|
TemperatureCMax: copyFloat(period.TemperatureCMax),
|
|
TemperatureFMax: copyFloat(period.TemperatureFMax),
|
|
WindSpeedKmh: copyFloat(period.WindSpeedKmh),
|
|
WindSpeedMph: copyFloat(period.WindSpeedMph),
|
|
WindGustKmh: copyFloat(period.WindGustKmh),
|
|
WindGustMph: copyFloat(period.WindGustMph),
|
|
WindDirection: windDirectionLabel(period.WindDirectionDegrees),
|
|
ProbabilityOfPrecipitationPercent: copyFloat(period.ProbabilityOfPrecipitationPercent),
|
|
})
|
|
}
|
|
return out
|
|
}
|
|
|
|
func (v NarrativeForecastModule) isEmpty() bool {
|
|
return v.Product == "" &&
|
|
v.IssuedAt.IsZero() &&
|
|
v.UpdatedAt == nil &&
|
|
v.SourceLocation == "" &&
|
|
v.SourceLocationID == "" &&
|
|
len(v.Periods) == 0
|
|
}
|