Add Today planning module scaffold
This commit is contained in:
@@ -28,6 +28,13 @@ type TomorrowPlanning struct {
|
||||
OvernightChangeWatch []string
|
||||
}
|
||||
|
||||
type TodayPlanning struct {
|
||||
MorningReadiness []string
|
||||
CommuteSchoolWorkdayConcerns []string
|
||||
OutdoorPlanning []string
|
||||
LateDayChangeWatch []string
|
||||
}
|
||||
|
||||
func buildOutdoorWindows(dayparts []forecast.DaypartSummary) OutdoorWindows {
|
||||
var best *OutdoorWindow
|
||||
var worst *OutdoorWindow
|
||||
@@ -48,6 +55,49 @@ func buildOutdoorWindows(dayparts []forecast.DaypartSummary) OutdoorWindows {
|
||||
return OutdoorWindows{Best: best, Worst: worst}
|
||||
}
|
||||
|
||||
func buildTodayPlanning(summary *forecast.DailySummary) *TodayPlanning {
|
||||
planning := &TodayPlanning{}
|
||||
morning := daypartNamed(summary.Dayparts, "morning")
|
||||
if morning != nil {
|
||||
planning.MorningReadiness = append(planning.MorningReadiness, readinessNotes(*morning)...)
|
||||
}
|
||||
if len(planning.MorningReadiness) == 0 {
|
||||
planning.MorningReadiness = append(planning.MorningReadiness, "Morning weather looks routine based on the available hourly forecast.")
|
||||
}
|
||||
|
||||
for _, daypart := range summary.Dayparts {
|
||||
if daypart.Name == "overnight" || daypart.Name == "evening" {
|
||||
continue
|
||||
}
|
||||
planning.CommuteSchoolWorkdayConcerns = appendUnique(planning.CommuteSchoolWorkdayConcerns, concernNotes(daypart)...)
|
||||
}
|
||||
for _, alert := range summary.AlertOverlaps {
|
||||
if alert.Event != "" {
|
||||
planning.CommuteSchoolWorkdayConcerns = appendUnique(planning.CommuteSchoolWorkdayConcerns, "Active alert to plan around: "+alert.Event+".")
|
||||
}
|
||||
}
|
||||
if len(planning.CommuteSchoolWorkdayConcerns) == 0 {
|
||||
planning.CommuteSchoolWorkdayConcerns = append(planning.CommuteSchoolWorkdayConcerns, "No major commute, school, or workday weather concerns stand out in the available forecast.")
|
||||
}
|
||||
|
||||
planning.OutdoorPlanning = append(planning.OutdoorPlanning, outdoorPlanningNotes(summary.Dayparts)...)
|
||||
if len(planning.OutdoorPlanning) == 0 {
|
||||
planning.OutdoorPlanning = append(planning.OutdoorPlanning, "No standout outdoor weather constraints are evident in the available forecast.")
|
||||
}
|
||||
|
||||
for _, name := range []string{"afternoon", "evening"} {
|
||||
daypart := daypartNamed(summary.Dayparts, name)
|
||||
if daypart != nil {
|
||||
planning.LateDayChangeWatch = appendUnique(planning.LateDayChangeWatch, lateDayWatchNotes(*daypart)...)
|
||||
}
|
||||
}
|
||||
if len(planning.LateDayChangeWatch) == 0 {
|
||||
planning.LateDayChangeWatch = append(planning.LateDayChangeWatch, "Watch for forecast timing or intensity adjustments later today.")
|
||||
}
|
||||
|
||||
return planning
|
||||
}
|
||||
|
||||
func buildTomorrowPlanning(summary *forecast.DailySummary) *TomorrowPlanning {
|
||||
planning := &TomorrowPlanning{}
|
||||
morning := daypartNamed(summary.Dayparts, "morning")
|
||||
@@ -84,6 +134,18 @@ func buildTomorrowPlanning(summary *forecast.DailySummary) *TomorrowPlanning {
|
||||
return planning
|
||||
}
|
||||
|
||||
func outdoorPlanningNotes(dayparts []forecast.DaypartSummary) []string {
|
||||
windows := buildOutdoorWindows(dayparts)
|
||||
var notes []string
|
||||
if windows.Best != nil {
|
||||
notes = append(notes, fmt.Sprintf("Best outdoor window: %s (%s).", titleWord(windows.Best.Daypart), strings.Join(windows.Best.Reasons, ", ")))
|
||||
}
|
||||
if windows.Worst != nil && (windows.Best == nil || windows.Worst.Daypart != windows.Best.Daypart) {
|
||||
notes = append(notes, fmt.Sprintf("Toughest outdoor window: %s (%s).", titleWord(windows.Worst.Daypart), strings.Join(windows.Worst.Reasons, ", ")))
|
||||
}
|
||||
return appendUnique(nil, notes...)
|
||||
}
|
||||
|
||||
func readinessNotes(daypart forecast.DaypartSummary) []string {
|
||||
notes := []string{}
|
||||
if daypart.MaxPrecipitationProbability != nil && daypart.MaxPrecipitationProbability.Value >= 50 {
|
||||
@@ -104,6 +166,27 @@ func readinessNotes(daypart forecast.DaypartSummary) []string {
|
||||
return appendUnique(nil, notes...)
|
||||
}
|
||||
|
||||
func lateDayWatchNotes(daypart forecast.DaypartSummary) []string {
|
||||
notes := []string{}
|
||||
prefix := titleWord(daypart.Name)
|
||||
if prefix == "" {
|
||||
prefix = "Late-day"
|
||||
}
|
||||
if daypart.MaxPrecipitationProbability != nil && daypart.MaxPrecipitationProbability.Value >= 30 {
|
||||
notes = append(notes, fmt.Sprintf("%s precipitation timing may shift; current peak is near %.0f%%.", prefix, daypart.MaxPrecipitationProbability.Value))
|
||||
}
|
||||
if daypart.PeakWindGust != nil && daypart.PeakWindGust.Value >= 30 {
|
||||
notes = append(notes, fmt.Sprintf("%s gusts may reach %.0f mph.", prefix, daypart.PeakWindGust.Value))
|
||||
}
|
||||
if daypart.Indicators.Snow || daypart.Indicators.Ice {
|
||||
notes = append(notes, prefix+" wintry weather could affect late-day travel.")
|
||||
}
|
||||
if len(daypart.AlertOverlaps) > 0 {
|
||||
notes = append(notes, prefix+" alert timing could affect late-day plans.")
|
||||
}
|
||||
return appendUnique(nil, notes...)
|
||||
}
|
||||
|
||||
func concernNotes(daypart forecast.DaypartSummary) []string {
|
||||
notes := []string{}
|
||||
prefix := titleWord(daypart.Name)
|
||||
|
||||
Reference in New Issue
Block a user