From 6321182b7e0031a66d872fdc482baa91fafab2d5 Mon Sep 17 00:00:00 2001 From: Chris Cummer Date: Mon, 16 Apr 2018 03:39:02 -0700 Subject: [PATCH] Fetches, stores, and returns multiweather, with ticks marks in display --- weather/client.go | 12 +++++-- weather/widget.go | 90 +++++++++++++++++++++++++++++++++++------------ wtf.go | 1 + wtf/utils.go | 17 ++++++--- 4 files changed, 91 insertions(+), 29 deletions(-) diff --git a/weather/client.go b/weather/client.go index c531dd8f..fba36fe5 100644 --- a/weather/client.go +++ b/weather/client.go @@ -9,9 +9,17 @@ import ( /* -------------------- Exported Functions -------------------- */ -func Fetch(cityID int) *owm.CurrentWeatherData { +func Fetch(cityids []int) []*owm.CurrentWeatherData { apiKey := os.Getenv("WTF_OWM_API_KEY") - data, _ := currentWeather(apiKey, cityID) + + data := []*owm.CurrentWeatherData{} + + for _, cityID := range cityids { + result, err := currentWeather(apiKey, cityID) + if err == nil { + data = append(data, result) + } + } return data } diff --git a/weather/widget.go b/weather/widget.go index 400d5768..0f6785c5 100644 --- a/weather/widget.go +++ b/weather/widget.go @@ -14,11 +14,14 @@ var Config *config.Config type Widget struct { wtf.TextWidget + + Current int } func NewWidget() *Widget { widget := Widget{ TextWidget: wtf.NewTextWidget(" Weather ", "weather"), + Current: 0, } return &widget @@ -31,52 +34,95 @@ func (widget *Widget) Refresh() { return } - data := Fetch(Config.UInt("wtf.mods.weather.cityId", 6176823)) - - widget.View.SetTitle(fmt.Sprintf(" %s %s ", icon(data), data.Name)) + data := Fetch(wtf.ToInts(Config.UList("wtf.mods.weather.cityids", widget.defaultCityCodes()))) widget.View.Clear() - fmt.Fprintf(widget.View, "%s", widget.contentFrom(data)) - + widget.contentFrom(data) widget.RefreshedAt = time.Now() } /* -------------------- Unexported Functions -------------------- */ -func (widget *Widget) contentFrom(data *owm.CurrentWeatherData) string { - if len(data.Weather) == 0 { - return " Weather data is unavailable." +func (widget *Widget) contentFrom(data []*owm.CurrentWeatherData) { + cityData := widget.currentCityData(data) + + if len(cityData.Weather) == 0 { + fmt.Fprintf(widget.View, "%s", " Weather data is unavailable.") } - str := "\n" + widget.View.SetTitle(widget.contentTitle(cityData)) + str := widget.contentTickMarks(data) + "\n" + str = str + widget.contentDescription(cityData) + "\n\n" + str = str + widget.contentTemperatures(cityData) + "\n" + str = str + widget.contentSunInfo(cityData) + + fmt.Fprintf(widget.View, "%s", str) +} + +func (widget *Widget) contentTickMarks(data []*owm.CurrentWeatherData) string { + str := "" + + if len(data) > 1 { + tickMarks := strings.Repeat("*", len(data)) + tickMarks = tickMarks[:widget.Current] + "_" + tickMarks[widget.Current+1:] + + str = "[lightblue]" + fmt.Sprintf(wtf.RightAlignFormat(widget.View), tickMarks) + "[white]" + } + + return str +} + +func (widget *Widget) contentTitle(cityData *owm.CurrentWeatherData) string { + return fmt.Sprintf(" %s %s ", widget.icon(cityData), cityData.Name) +} + +func (widget *Widget) contentDescription(cityData *owm.CurrentWeatherData) string { descs := []string{} - for _, weather := range data.Weather { + for _, weather := range cityData.Weather { descs = append(descs, fmt.Sprintf(" %s", weather.Description)) } - str = str + strings.Join(descs, ",") + "\n\n" + return strings.Join(descs, ",") +} +func (widget *Widget) contentTemperatures(cityData *owm.CurrentWeatherData) string { tempUnit := Config.UString("wtf.mods.weather.tempUnit", "C") - str = str + fmt.Sprintf("%8s: %4.1f° %s\n", "High", data.Main.TempMax, tempUnit) - str = str + fmt.Sprintf("%8s: [green]%4.1f° %s[white]\n", "Current", data.Main.Temp, tempUnit) - str = str + fmt.Sprintf("%8s: %4.1f° %s\n", "Low", data.Main.TempMin, tempUnit) - - str = str + "\n" - str = str + fmt.Sprintf( - " Sunrise: %s Sunset: %s\n", - wtf.UnixTime(int64(data.Sys.Sunrise)).Format("15:04"), - wtf.UnixTime(int64(data.Sys.Sunset)).Format("15:04"), - ) + str := fmt.Sprintf("%8s: %4.1f° %s\n", "High", cityData.Main.TempMax, tempUnit) + str = str + fmt.Sprintf("%8s: [green]%4.1f° %s[white]\n", "Current", cityData.Main.Temp, tempUnit) + str = str + fmt.Sprintf("%8s: %4.1f° %s\n", "Low", cityData.Main.TempMin, tempUnit) return str } +func (widget *Widget) contentSunInfo(cityData *owm.CurrentWeatherData) string { + return fmt.Sprintf( + " Rise: %s Set: %s\n", + wtf.UnixTime(int64(cityData.Sys.Sunrise)).Format("15:04 MST"), + wtf.UnixTime(int64(cityData.Sys.Sunset)).Format("15:04 MST"), + ) +} + +func (widget *Widget) currentCityData(data []*owm.CurrentWeatherData) *owm.CurrentWeatherData { + return data[widget.Current] +} + +func (widget *Widget) defaultCityCodes() []interface{} { + defaultArr := []int{6176823, 360630, 3413829} + + var defaults []interface{} = make([]interface{}, len(defaultArr)) + for i, d := range defaultArr { + defaults[i] = d + } + + return defaults +} + // icon returns an emoji for the current weather // src: https://github.com/chubin/wttr.in/blob/master/share/translations/en.txt // Note: these only work for English weather status. Sorry about that -func icon(data *owm.CurrentWeatherData) string { +func (widget *Widget) icon(data *owm.CurrentWeatherData) string { var icon string if len(data.Weather) == 0 { diff --git a/wtf.go b/wtf.go index 52c3126b..73174eab 100644 --- a/wtf.go +++ b/wtf.go @@ -62,6 +62,7 @@ func keyboardIntercept(event *tcell.EventKey) *tcell.EventKey { for _, module := range Widgets { go module.Refresh() } + } else if event.Key() == tcell.KeyTab { } return event diff --git a/wtf/utils.go b/wtf/utils.go index 4bb486ba..d5f4cd11 100644 --- a/wtf/utils.go +++ b/wtf/utils.go @@ -6,11 +6,13 @@ import ( "os/exec" "strings" "time" + + "github.com/rivo/tview" ) // DateFormat defines the format we expect to receive dates from BambooHR in const DateFormat = "2006-01-02" -const TimeFormat = "15:04 MST" +const TimeFormat = "15:04" func CenterText(str string, width int) string { return fmt.Sprintf("%[1]*s", -width, fmt.Sprintf("%[1]*s", (width+len(str))/2, str)) @@ -19,11 +21,11 @@ func CenterText(str string, width int) string { func ExecuteCommand(cmd *exec.Cmd) string { stdout, err := cmd.StdoutPipe() if err != nil { - return fmt.Sprintf("A: %v\n", err) + return fmt.Sprintf("%v\n", err) } if err := cmd.Start(); err != nil { - return fmt.Sprintf("B: %v\n", err) + return fmt.Sprintf("%v\n", err) } var str string @@ -77,8 +79,9 @@ func Now() time.Time { return time.Now().Local() } -func Tomorrow() time.Time { - return Now().AddDate(0, 0, 1) +func RightAlignFormat(view *tview.TextView) string { + _, _, w, _ := view.GetInnerRect() + return fmt.Sprintf("%%%ds", w-1) } func ToInts(slice []interface{}) []int { @@ -90,6 +93,10 @@ func ToInts(slice []interface{}) []int { return results } +func Tomorrow() time.Time { + return Now().AddDate(0, 0, 1) +} + func ToStrs(slice []interface{}) []string { results := []string{} for _, val := range slice {