Update wind direction and precipitation window presentation
This commit is contained in:
@@ -47,6 +47,8 @@ type TimedValue struct {
|
||||
Time time.Time `json:"time"`
|
||||
}
|
||||
|
||||
const DefaultPrecipWindowProbabilityThreshold = 40
|
||||
|
||||
type Indicators struct {
|
||||
Snow bool `json:"snow,omitempty"`
|
||||
Ice bool `json:"ice,omitempty"`
|
||||
@@ -66,34 +68,101 @@ type AlertOverlap struct {
|
||||
}
|
||||
|
||||
type PrecipTiming struct {
|
||||
MaxPrecipitationProbability *TimedValue `json:"maxPrecipitationProbability,omitempty"`
|
||||
FirstPrecipitation *TimedValue `json:"firstPrecipitation,omitempty"`
|
||||
LastPrecipitation *TimedValue `json:"lastPrecipitation,omitempty"`
|
||||
ThunderMentioned bool `json:"thunderMentioned,omitempty"`
|
||||
MaxPrecipitationProbability *TimedValue `json:"maxPrecipitationProbability,omitempty"`
|
||||
FirstPrecipitation *TimedValue `json:"firstPrecipitation,omitempty"`
|
||||
LastPrecipitation *TimedValue `json:"lastPrecipitation,omitempty"`
|
||||
ProbabilityThreshold float64 `json:"probabilityThreshold"`
|
||||
PrecipitationWindows []PrecipitationWindow `json:"precipitationWindows,omitempty"`
|
||||
ThunderMentioned bool `json:"thunderMentioned,omitempty"`
|
||||
}
|
||||
|
||||
type PrecipitationWindow struct {
|
||||
Start time.Time `json:"start"`
|
||||
End *time.Time `json:"end,omitempty"`
|
||||
MaxPrecipitationProbability TimedValue `json:"maxPrecipitationProbability"`
|
||||
ProbabilityThreshold float64 `json:"probabilityThreshold"`
|
||||
}
|
||||
|
||||
func BuildPrecipTiming(periods []weatherdata.ForecastPeriod) PrecipTiming {
|
||||
var timing PrecipTiming
|
||||
for _, forecastPeriod := range periods {
|
||||
setMaxTimedValue(&timing.MaxPrecipitationProbability, forecastPeriod.ProbabilityOfPrecipitationPercent, forecastPeriod.StartTime)
|
||||
if forecastPeriod.ProbabilityOfPrecipitationPercent != nil && *forecastPeriod.ProbabilityOfPrecipitationPercent > 0 {
|
||||
value := TimedValue{
|
||||
Value: *forecastPeriod.ProbabilityOfPrecipitationPercent,
|
||||
return buildPrecipTimingWithThreshold(periods, DefaultPrecipWindowProbabilityThreshold)
|
||||
}
|
||||
|
||||
func buildPrecipTimingWithThreshold(periods []weatherdata.ForecastPeriod, threshold float64) PrecipTiming {
|
||||
timing := PrecipTiming{ProbabilityThreshold: threshold}
|
||||
sorted := append([]weatherdata.ForecastPeriod(nil), periods...)
|
||||
sort.SliceStable(sorted, func(i int, j int) bool {
|
||||
return sorted[i].StartTime.Before(sorted[j].StartTime)
|
||||
})
|
||||
|
||||
var active *PrecipitationWindow
|
||||
var activeLastEnd time.Time
|
||||
closeActive := func() {
|
||||
if active == nil {
|
||||
return
|
||||
}
|
||||
end := activeLastEnd
|
||||
active.End = &end
|
||||
timing.PrecipitationWindows = append(timing.PrecipitationWindows, *active)
|
||||
active = nil
|
||||
}
|
||||
startActive := func(forecastPeriod weatherdata.ForecastPeriod, probability float64) {
|
||||
active = &PrecipitationWindow{
|
||||
Start: forecastPeriod.StartTime,
|
||||
MaxPrecipitationProbability: TimedValue{
|
||||
Value: probability,
|
||||
Time: forecastPeriod.StartTime,
|
||||
},
|
||||
ProbabilityThreshold: threshold,
|
||||
}
|
||||
activeLastEnd = forecastPeriod.EndTime
|
||||
if timing.FirstPrecipitation == nil {
|
||||
timing.FirstPrecipitation = &TimedValue{
|
||||
Value: probability,
|
||||
Time: forecastPeriod.StartTime,
|
||||
}
|
||||
if timing.FirstPrecipitation == nil || value.Time.Before(timing.FirstPrecipitation.Time) {
|
||||
copied := value
|
||||
timing.FirstPrecipitation = &copied
|
||||
}
|
||||
if timing.LastPrecipitation == nil || value.Time.After(timing.LastPrecipitation.Time) {
|
||||
copied := value
|
||||
timing.LastPrecipitation = &copied
|
||||
}
|
||||
}
|
||||
|
||||
for _, forecastPeriod := range sorted {
|
||||
setMaxTimedValue(&timing.MaxPrecipitationProbability, forecastPeriod.ProbabilityOfPrecipitationPercent, forecastPeriod.StartTime)
|
||||
if forecastPeriod.ProbabilityOfPrecipitationPercent == nil || *forecastPeriod.ProbabilityOfPrecipitationPercent < threshold {
|
||||
closeActive()
|
||||
} else {
|
||||
probability := *forecastPeriod.ProbabilityOfPrecipitationPercent
|
||||
if active == nil {
|
||||
startActive(forecastPeriod, probability)
|
||||
} else {
|
||||
if forecastPeriod.StartTime.After(activeLastEnd) {
|
||||
closeActive()
|
||||
startActive(forecastPeriod, probability)
|
||||
}
|
||||
if probability > active.MaxPrecipitationProbability.Value {
|
||||
active.MaxPrecipitationProbability = TimedValue{
|
||||
Value: probability,
|
||||
Time: forecastPeriod.StartTime,
|
||||
}
|
||||
}
|
||||
if forecastPeriod.EndTime.After(activeLastEnd) {
|
||||
activeLastEnd = forecastPeriod.EndTime
|
||||
}
|
||||
}
|
||||
}
|
||||
if mentionsThunder(forecastPeriod.TextDescription) {
|
||||
timing.ThunderMentioned = true
|
||||
}
|
||||
}
|
||||
if active != nil {
|
||||
timing.PrecipitationWindows = append(timing.PrecipitationWindows, *active)
|
||||
}
|
||||
if len(timing.PrecipitationWindows) > 0 {
|
||||
final := timing.PrecipitationWindows[len(timing.PrecipitationWindows)-1]
|
||||
if final.End != nil {
|
||||
timing.LastPrecipitation = &TimedValue{
|
||||
Value: final.MaxPrecipitationProbability.Value,
|
||||
Time: *final.End,
|
||||
}
|
||||
}
|
||||
}
|
||||
return timing
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user