diff options
-rw-r--r-- | html/weather.html | 42 | ||||
-rw-r--r-- | main.go | 135 | ||||
-rw-r--r-- | static/peach.css | 15 |
3 files changed, 191 insertions, 1 deletions
diff --git a/html/weather.html b/html/weather.html new file mode 100644 index 0000000..520c284 --- /dev/null +++ b/html/weather.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>peach</title> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <meta name="author" content="siddharth"> + <link rel="preload" href="/static/peach.css" as="style" /> + <style>@import url("/static/peach.css");</style> +</head> +<body> + <div class="peach-container"> + <div class="location block"> + <p>{{.Location}}</p> + </div> + + <div class="summary"> + <div class="now"> + <p class="forecast">{{.Now.Forecast}}</p> + <p class="tempature">{{.Now.Temperature}}{{.Now.TemperatureUnit}}</p> + <p class="wind">{{.Now.WindSpeed}} {{.Now.WindDirection}}</p> + </div> + <div class="current-period"> + <p class="forecast">{{.Period.Forecast}}</p> + </div> + </div> + + {{ if .Timeline }} + <div class="timeline"> + <div class="container"> + {{ range .Timeline.Periods }} + <div class="period"> + <p class="temperature">{{.Temperature}}{{.TemperatureUnit}}</p> + <p class="hour">{{printf "%d" .Hour}}hrs</p> + </div> + {{ end }} + </div> + </div> + {{ end }} + + </div> +</body> @@ -3,4 +3,137 @@ package main -func main() {} +import ( + "embed" + "fmt" + "html/template" + "log" + "net/http" + "time" + + "ricketyspace.net/peach/nws" +) + +// Holds static content. +//go:embed html static +var peachFS embed.FS + +// HTML templates. +var peachTemplates = template.Must(template.ParseFS(peachFS, "html/*.html")) + +type Weather struct { + Location string + Now WeatherNow + Period WeatherPeriod + Timeline WeatherTimeline +} + +type WeatherNow struct { + Temperature int + TemperatureUnit string + Forecast string + WindSpeed string + WindDirection string +} + +type WeatherPeriod struct { + Forecast string + Hour int + Temperature int + TemperatureUnit string +} + +type WeatherTimeline struct { + Periods []WeatherPeriod +} + +func main() { + http.Handle("/static/", http.FileServer(http.FS(peachFS))) + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + if len(r.URL.Path[1:]) != 0 { + http.NotFound(w, r) + return + } + showWeather(w, 41.115, -83.177) + }) + log.Fatal(http.ListenAndServe(":8151", nil)) +} + +func showWeather(w http.ResponseWriter, lat, lng float32) { + point, err := nws.Points(lat, lng) + if err != nil { + http.Error(w, err.Error(), 500) + return + } + + // Get forecast + f, err := nws.Forecast(point) + if err != nil { + http.Error(w, err.Error(), 500) + return + } + fh, err := nws.ForecastHourly(point) + if err != nil { + http.Error(w, err.Error(), 500) + return + } + + // Make weather + weather, err := NewWeather(point, f, fh) + if err != nil { + http.Error(w, err.Error(), 500) + return + } + + err = peachTemplates.ExecuteTemplate(w, "weather.html", weather) + if err != nil { + http.Error(w, err.Error(), 500) + return + } +} + +func NewWeather(point *nws.NWSPoint, f, fh *nws.NWSForecast) (*Weather, error) { + w := new(Weather) + w.Location = fmt.Sprintf("%s, %s", + point.Properties.RelativeLocation.Properties.City, + point.Properties.RelativeLocation.Properties.State, + ) + w.Now = WeatherNow{ + Temperature: fh.Properties.Periods[0].Temperature, + TemperatureUnit: fh.Properties.Periods[0].TemperatureUnit, + Forecast: fh.Properties.Periods[0].ShortForecast, + WindSpeed: fh.Properties.Periods[0].WindSpeed, + WindDirection: fh.Properties.Periods[0].WindDirection, + } + w.Period = WeatherPeriod{ + Forecast: f.Properties.Periods[0].DetailedForecast, + } + + // Build timeline. + periods := []WeatherPeriod{} + max := 12 + for i, period := range fh.Properties.Periods { + if i%2 != 0 { + continue // Take every other period + } + t, err := time.Parse(time.RFC3339, period.StartTime) + if err != nil { + return nil, err + } + p := WeatherPeriod{ + Forecast: period.DetailedForecast, + Hour: t.Hour(), + Temperature: period.Temperature, + TemperatureUnit: period.TemperatureUnit, + } + periods = append(periods, p) + if len(periods) == max { + break + } + } + w.Timeline = WeatherTimeline{ + Periods: periods, + } + + return w, nil +} diff --git a/static/peach.css b/static/peach.css new file mode 100644 index 0000000..6d32955 --- /dev/null +++ b/static/peach.css @@ -0,0 +1,15 @@ +p { + margin: 0; +} + +.peach-container { + display: flex; + flex-direction: column; + gap: 15px; +} + +.timeline .container { + display: flex; + justify-content: space-around; + align-content: space-around; +} |