Split weather data types from forecast derivation

This commit is contained in:
2026-06-09 20:16:47 +00:00
parent d8b417458b
commit 454f47b2b5
22 changed files with 234 additions and 223 deletions

View File

@@ -8,32 +8,33 @@ import (
"time"
"gitea.maximumdirect.net/eric/weatherreporter/internal/timeutil"
"gitea.maximumdirect.net/eric/weatherreporter/internal/weatherdata"
)
type DailySummary struct {
Date string `json:"date"`
Period timeutil.Period `json:"period"`
Dayparts []DaypartSummary `json:"dayparts"`
NarrativePeriods []ForecastPeriod `json:"narrativePeriods,omitempty"`
AlertOverlaps []AlertOverlap `json:"alertOverlaps,omitempty"`
Discussion *Discussion `json:"discussion,omitempty"`
SourceWarnings []SourceWarning `json:"sourceWarnings,omitempty"`
SourceProvenance []Source `json:"sourceProvenance,omitempty"`
Date string `json:"date"`
Period timeutil.Period `json:"period"`
Dayparts []DaypartSummary `json:"dayparts"`
NarrativePeriods []weatherdata.ForecastPeriod `json:"narrativePeriods,omitempty"`
AlertOverlaps []AlertOverlap `json:"alertOverlaps,omitempty"`
Discussion *weatherdata.Discussion `json:"discussion,omitempty"`
SourceWarnings []weatherdata.SourceWarning `json:"sourceWarnings,omitempty"`
SourceProvenance []weatherdata.Source `json:"sourceProvenance,omitempty"`
}
type DaypartSummary struct {
Name string `json:"name"`
Period timeutil.Period `json:"period"`
HourlyPeriods []ForecastPeriod `json:"hourlyPeriods"`
Temperature Range `json:"temperature,omitempty"`
ApparentTemperature Range `json:"apparentTemperature,omitempty"`
MaxPrecipitationProbability *TimedValue `json:"maxPrecipitationProbability,omitempty"`
PeakWindSpeed *TimedValue `json:"peakWindSpeed,omitempty"`
PeakWindGust *TimedValue `json:"peakWindGust,omitempty"`
DominantCondition string `json:"dominantCondition,omitempty"`
NotableConditions []string `json:"notableConditions,omitempty"`
Indicators Indicators `json:"indicators"`
AlertOverlaps []AlertOverlap `json:"alertOverlaps,omitempty"`
Name string `json:"name"`
Period timeutil.Period `json:"period"`
HourlyPeriods []weatherdata.ForecastPeriod `json:"hourlyPeriods"`
Temperature Range `json:"temperature,omitempty"`
ApparentTemperature Range `json:"apparentTemperature,omitempty"`
MaxPrecipitationProbability *TimedValue `json:"maxPrecipitationProbability,omitempty"`
PeakWindSpeed *TimedValue `json:"peakWindSpeed,omitempty"`
PeakWindGust *TimedValue `json:"peakWindGust,omitempty"`
DominantCondition string `json:"dominantCondition,omitempty"`
NotableConditions []string `json:"notableConditions,omitempty"`
Indicators Indicators `json:"indicators"`
AlertOverlaps []AlertOverlap `json:"alertOverlaps,omitempty"`
}
type Range struct {
@@ -64,7 +65,7 @@ type AlertOverlap struct {
Description string `json:"description,omitempty"`
}
func BuildDailySummary(bundle *Bundle, date time.Time, location *time.Location, dayparts []DaypartDefinition) (*DailySummary, error) {
func BuildDailySummary(bundle *weatherdata.Bundle, date time.Time, location *time.Location, dayparts []DaypartDefinition) (*DailySummary, error) {
if bundle == nil {
return nil, fmt.Errorf("forecast bundle is required")
}
@@ -99,7 +100,7 @@ func BuildDailySummary(bundle *Bundle, date time.Time, location *time.Location,
return summary, nil
}
func BuildPeriodDailySummaries(bundle *Bundle, period timeutil.Period, location *time.Location, dayparts []DaypartDefinition) ([]DailySummary, error) {
func BuildPeriodDailySummaries(bundle *weatherdata.Bundle, period timeutil.Period, location *time.Location, dayparts []DaypartDefinition) ([]DailySummary, error) {
if !period.IsValid() {
return nil, fmt.Errorf("valid forecast period is required")
}
@@ -121,7 +122,7 @@ func BuildPeriodDailySummaries(bundle *Bundle, period timeutil.Period, location
return summaries, nil
}
func buildDailySummaryForPeriod(bundle *Bundle, period timeutil.Period, location *time.Location, dayparts []DaypartDefinition) (*DailySummary, error) {
func buildDailySummaryForPeriod(bundle *weatherdata.Bundle, period timeutil.Period, location *time.Location, dayparts []DaypartDefinition) (*DailySummary, error) {
if bundle == nil {
return nil, fmt.Errorf("forecast bundle is required")
}
@@ -155,11 +156,11 @@ func buildDailySummaryForPeriod(bundle *Bundle, period timeutil.Period, location
return summary, nil
}
func SelectHourlyPeriods(run *ForecastRun, period timeutil.Period) []ForecastPeriod {
func SelectHourlyPeriods(run *weatherdata.ForecastRun, period timeutil.Period) []weatherdata.ForecastPeriod {
if run == nil {
return nil
}
var selected []ForecastPeriod
var selected []weatherdata.ForecastPeriod
for _, forecastPeriod := range run.Periods {
if PeriodForForecastPeriod(forecastPeriod).Overlaps(period) {
selected = append(selected, forecastPeriod)
@@ -171,21 +172,21 @@ func SelectHourlyPeriods(run *ForecastRun, period timeutil.Period) []ForecastPer
return selected
}
func SelectNarrativePeriods(bundle *Bundle, period timeutil.Period) []ForecastPeriod {
func SelectNarrativePeriods(bundle *weatherdata.Bundle, period timeutil.Period) []weatherdata.ForecastPeriod {
if bundle == nil || bundle.Narrative == nil {
return nil
}
return SelectHourlyPeriods(bundle.Narrative, period)
}
func SelectDiscussion(bundle *Bundle) *Discussion {
func SelectDiscussion(bundle *weatherdata.Bundle) *weatherdata.Discussion {
if bundle == nil {
return nil
}
return bundle.Discussion
}
func SummarizeDaypart(name string, period timeutil.Period, periods []ForecastPeriod) DaypartSummary {
func SummarizeDaypart(name string, period timeutil.Period, periods []weatherdata.ForecastPeriod) DaypartSummary {
summary := DaypartSummary{
Name: name,
Period: period,
@@ -215,7 +216,7 @@ func SummarizeDaypart(name string, period timeutil.Period, periods []ForecastPer
return summary
}
func periodTemperatureValues(period ForecastPeriod) []*float64 {
func periodTemperatureValues(period weatherdata.ForecastPeriod) []*float64 {
values := []*float64{}
values = append(values, valueFromPointers(period.TemperatureF, period.TemperatureC)...)
values = append(values, valueFromPointers(period.TemperatureFMin, period.TemperatureCMin)...)
@@ -297,7 +298,7 @@ func indicatorsForText(text string) Indicators {
}
}
func numericIndicators(period ForecastPeriod) Indicators {
func numericIndicators(period weatherdata.ForecastPeriod) Indicators {
windGust := firstValue(period.WindGustMph, period.WindGustKmh)
windSpeed := firstValue(period.WindSpeedMph, period.WindSpeedKmh)
indicators := Indicators{}
@@ -325,7 +326,7 @@ func mergeIndicators(left Indicators, right Indicators) Indicators {
}
}
func AlertOverlaps(alertRun *AlertRun, period timeutil.Period) []AlertOverlap {
func AlertOverlaps(alertRun *weatherdata.AlertRun, period timeutil.Period) []AlertOverlap {
if alertRun == nil {
return nil
}