diff --git a/cmd/application/main.go b/cmd/application/main.go index 4441ae7..e778d41 100644 --- a/cmd/application/main.go +++ b/cmd/application/main.go @@ -4,7 +4,6 @@ package main import ( - "fmt" "github.com/GetSky/WeatherAlertBTA/config" "github.com/GetSky/WeatherAlertBTA/internal/application" "github.com/GetSky/WeatherAlertBTA/internal/infrastructure" @@ -12,17 +11,7 @@ import ( ) var cnf *config.Conf - -var weatherSrv application.WeatherService -var chartSrv application.ChartService -var notifySrv application.NotifyService -var scheduleSrv application.ScheduleService - -var ( - workActive bool - windAlertActive bool - lastWindAlertTime time.Time -) +var tracker *application.WeatherTracker func init() { var err error @@ -31,98 +20,21 @@ func init() { return } - chartSrv = infrastructure.NewChartService(cnf.ChartWeatherUrl) - weatherSrv = infrastructure.NewWeatherService(cnf.WeatherUrl) - notifySrv = infrastructure.NewTelegramNotifyService(cnf.BotToken, cnf.TelegramChat) - scheduleSrv = infrastructure.NewScheduleService(cnf.TimeReserveBeforeDusk) + chartSrv := infrastructure.NewChartService(cnf.ChartWeatherUrl) + weatherSrv := infrastructure.NewWeatherService(cnf.WeatherUrl) + notifySrv := infrastructure.NewTelegramNotifyService(cnf.BotToken, cnf.TelegramChat) + scheduleSrv := infrastructure.NewScheduleService(cnf.TimeReserveBeforeDusk) + + tracker = application.NewWeatherTracker( + application.NewTurnOnState(scheduleSrv, notifySrv, chartSrv, weatherSrv, cnf.WindThreshold, cnf.DelayTime), + application.NewTurnOffState(scheduleSrv, notifySrv), + ) + } func main() { for { - isWorkTime, _ := scheduleSrv.IsWorkNow() - if isWorkTime != workActive { - workActive = isWorkTime - checkWorkStatus() - } - if isWorkTime { - checkWeather() - } else { - } + tracker.Check() time.Sleep(cnf.PollInterval) } } - -func checkWorkStatus() { - switch workActive { - case true: - dusk, dawn, err := scheduleSrv.GetNautical(time.Now()) - if err != nil { - fmt.Printf("Main → %v\n", err) - return - } - err = notifySrv.SendWorkStarted(dusk, dawn) - if err != nil { - fmt.Printf("Main → %v\n", err) - return - } - case false: - err := notifySrv.SendWorkEnded() - if err != nil { - fmt.Printf("Main → %v\n", err) - return - } - } -} - -func checkWeather() { - chart, err := chartSrv.GetUpdatedChart() - if err != nil { - fmt.Printf("ChartService → %v\n", err) - return - } - - weather, err := weatherSrv.GetLatestWeather() - if err != nil { - fmt.Printf("WeatherService → %v\n", err) - return - } - - if weather.WindSpeed >= cnf.WindThreshold { - weather.Hazardous = true - lastWindAlertTime = time.Now() - windAlertActive = true - - err = notifySrv.SendUpdate(chart, weather) - if err != nil { - fmt.Printf("Main → %v\n", err) - return - } - - fmt.Println("Wind alert sent successfully.") - - } else { - if windAlertActive { - duration := time.Since(lastWindAlertTime) - if duration > cnf.DelayTime { - weather.Hazardous = false - err = notifySrv.SendUpdate(chart, weather) - if err != nil { - fmt.Printf("Main → %v\n", err) - return - } - - windAlertActive = false - fmt.Println("Wind speed below threshold message sent.") - } else { - fmt.Println("The wind speed is below the threshold, but the time has not come to cancel the alert.") - } - } else { - weather.Hazardous = false - err = notifySrv.SendUpdate(chart, weather) - if err != nil { - fmt.Printf("Main → %v\n", err) - return - } - } - } -} diff --git a/internal/application/tracker.go b/internal/application/tracker.go new file mode 100644 index 0000000..a5b67e1 --- /dev/null +++ b/internal/application/tracker.go @@ -0,0 +1,40 @@ +// Copyright 2024 Alexander Getmansky +// Licensed under the Apache License, Version 2.0 + +package application + +import "fmt" + +type State interface { + check() error + SetTracker(tracker *WeatherTracker) +} + +type WeatherTracker struct { + turnedOn State + turnedOff State + + currentState State +} + +func NewWeatherTracker(turnedOn State, turnedOff State) *WeatherTracker { + t := &WeatherTracker{ + turnedOn: turnedOn, + turnedOff: turnedOff, + } + turnedOn.SetTracker(t) + turnedOff.SetTracker(t) + t.switchState(turnedOff) + return t +} + +func (t *WeatherTracker) switchState(s State) { + t.currentState = s +} + +func (t *WeatherTracker) Check() { + err := t.currentState.check() + if err != nil { + fmt.Printf("Tracker → %v\n", err) + } +} diff --git a/internal/application/turn_off_state.go b/internal/application/turn_off_state.go new file mode 100644 index 0000000..8da879a --- /dev/null +++ b/internal/application/turn_off_state.go @@ -0,0 +1,51 @@ +// Copyright 2024 Alexander Getmansky +// Licensed under the Apache License, Version 2.0 + +package application + +import ( + "time" +) + +type TurnOffState struct { + tracker *WeatherTracker + scheduleSrv ScheduleService + notifySrv NotifyService +} + +func NewTurnOffState(schedule ScheduleService, notify NotifyService) *TurnOffState { + return &TurnOffState{ + scheduleSrv: schedule, + notifySrv: notify, + } +} + +func (t *TurnOffState) SetTracker(tracker *WeatherTracker) { + t.tracker = tracker +} + +func (t *TurnOffState) check() error { + isWorkTime, err := t.scheduleSrv.IsWorkNow() + if err != nil { + return err + } + + if isWorkTime == false { + return nil + } + + dusk, dawn, err := t.scheduleSrv.GetNautical(time.Now()) + if err != nil { + return err + } + + err = t.notifySrv.SendWorkStarted(dusk, dawn) + if err != nil { + return err + } + + t.tracker.switchState(t.tracker.turnedOn) + t.tracker.Check() + + return nil +} diff --git a/internal/application/turn_on_state.go b/internal/application/turn_on_state.go new file mode 100644 index 0000000..f3c01fd --- /dev/null +++ b/internal/application/turn_on_state.go @@ -0,0 +1,120 @@ +// Copyright 2024 Alexander Getmansky +// Licensed under the Apache License, Version 2.0 + +package application + +import ( + "fmt" + "time" +) + +type TurnOnState struct { + tracker *WeatherTracker + scheduleSrv ScheduleService + notifySrv NotifyService + chartSrv ChartService + weatherSrv WeatherService + + windThreshold float64 + delayTime time.Duration + + lastWindAlertTime time.Time + windAlertActive bool +} + +func NewTurnOnState( + schedule ScheduleService, + notify NotifyService, + chart ChartService, + weather WeatherService, + windThreshold float64, + delayTime time.Duration, +) *TurnOnState { + return &TurnOnState{ + scheduleSrv: schedule, + notifySrv: notify, + chartSrv: chart, + weatherSrv: weather, + windThreshold: windThreshold, + delayTime: delayTime, + } +} + +func (t *TurnOnState) SetTracker(tracker *WeatherTracker) { + t.tracker = tracker +} + +func (t *TurnOnState) check() error { + isWorkTime, err := t.scheduleSrv.IsWorkNow() + if err != nil { + return err + } + + if isWorkTime == false { + err = t.notifySrv.SendWorkEnded() + if err != nil { + return err + } + + t.tracker.switchState(t.tracker.turnedOff) + + return nil + } + + err = t.checkWeather() + if err != nil { + return err + } + + return nil +} + +func (t *TurnOnState) checkWeather() error { + chart, err := t.chartSrv.GetUpdatedChart() + if err != nil { + return err + } + + weather, err := t.weatherSrv.GetLatestWeather() + if err != nil { + return err + } + + if weather.WindSpeed >= t.windThreshold { + weather.Hazardous = true + t.lastWindAlertTime = time.Now() + t.windAlertActive = true + + err = t.notifySrv.SendUpdate(chart, weather) + if err != nil { + return err + } + + fmt.Println("Wind alert sent successfully.") + + } else { + if t.windAlertActive { + duration := time.Since(t.lastWindAlertTime) + if duration > t.delayTime { + weather.Hazardous = false + err = t.notifySrv.SendUpdate(chart, weather) + if err != nil { + return err + } + + t.windAlertActive = false + fmt.Println("Wind speed below threshold message sent.") + } else { + fmt.Println("The wind speed is below the threshold, but the time has not come to cancel the alert.") + } + } else { + weather.Hazardous = false + err = t.notifySrv.SendUpdate(chart, weather) + if err != nil { + return err + } + } + } + + return nil +}