Skip to content

Commit

Permalink
forecast.io backend: cleanup parseDaily
Browse files Browse the repository at this point in the history
  • Loading branch information
schachmat committed Apr 9, 2016
1 parent 8e619e2 commit e4e9a6e
Showing 1 changed file with 33 additions and 91 deletions.
124 changes: 33 additions & 91 deletions backends/forecast.io.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,15 @@ import (
"io/ioutil"
"log"
"net/http"
"os"
"time"

"github.com/schachmat/wego/iface"
)

type forecastConfig struct {
apiKey string
latitude string
longitude string
debug bool
apiKey string
language string
debug bool
}

type forecastDataPoint struct {
Expand Down Expand Up @@ -57,93 +55,41 @@ const (
// see https://developer.forecast.io/docs/v2
// see also https://github.com/mlbright/forecast
//https://api.forecast.io/forecast/APIKEY/LATITUDE,LONGITUDE
forecastWuri = "https://api.forecast.io/forecast/%s/%s?units=ca&lang=de&exclude=minutely,daily,alerts,flags&extend=hourly"
forecastWuri = "https://api.forecast.io/forecast/%s/%s?units=ca&lang=%s&exclude=minutely,daily,alerts,flags&extend=hourly"
)

func (dp forecastDataPoint) Render() {
var b []byte
var err error
b, err = json.MarshalIndent(dp, "", "\t")
if err != nil {
log.Fatal(err)
}
os.Stdout.Write(b)
}

func (db *forecastDataBlock) Convert(c *forecastConfig) []iface.Day {
func forecastParseDaily(db forecastDataBlock, numdays int) []iface.Day {
var forecast []iface.Day

var day *iface.Day
day = new(iface.Day)

for cnt, dp := range db.Data {
slot := forecastParseCond(&dp)
if slot == nil {
continue
}

//skip today
// if *slot.Time.Day() == time.Now().Day() {
// continue
// }
//TODO: fill current day forecast with time machine call

// dp.Render()

if c.debug {
log.Printf("DataPoint: %02d\t%v\n", cnt, slot.Time)
for _, dp := range db.Data {
slot, err := forecastParseCond(dp)
if err != nil {
log.Println("Error parsing hourly weather condition:", err)
continue
}

if day == nil || day.Date.Day() != slot.Time.Day() {
//is day already set?
if len(day.Slots) >= 1 {
if dp.TemperatureMax != nil && *dp.TemperatureMax >= 0 {
day.MaxtempC = new(float32)
*day.MaxtempC = *dp.TemperatureMax
}

if dp.TemperatureMax != nil && *dp.TemperatureMax >= 0 {
day.MintempC = new(float32)
*day.MintempC = *dp.TemperatureMin
}

forecast = append(forecast, *day)

if c.debug {
log.Printf("New Day: %02d\t%v\n", cnt, day)
for i, cond := range day.Slots {
log.Printf("New Day Slot: %02d\t%v\n", i, cond)
}
}
if day != nil && day.Date.Day() != slot.Time.Day() {
if len(forecast) >= numdays-1 {
break
}

forecast = append(forecast, *day)
day = nil
}
if day == nil {
day = new(iface.Day)
day.Date = slot.Time
day.Slots = []iface.Cond{*slot}
// only add relevant Slots
} else {
if slot.Time.Hour() == 8 ||
slot.Time.Hour() == 12 ||
slot.Time.Hour() == 19 ||
slot.Time.Hour() == 23 {
day.Date = slot.Time
day.Slots = append(day.Slots, *slot)

if c.debug {
// log.Printf("Adding Slot: %02d\t>%p<\t>%v<\t>%v<\n",
// len(day.Slots), slot, *slot.Time, day)
}
} else if false {
day.Date = slot.Time
day.Slots = append(day.Slots, *slot)
}
//TODO: min-,max-temperature, astronomy
}
}
forecast = append(forecast, *day)

return forecast
day.Slots = append(day.Slots, slot)
}
return append(forecast, *day)
}

func forecastParseCond(dp *forecastDataPoint) (ret *iface.Cond) {
func forecastParseCond(dp forecastDataPoint) (ret iface.Cond, err error) {
codemap := map[string]iface.WeatherCode{
"clear-day": iface.CodeSunny,
"clear-night": iface.CodeSunny,
Expand All @@ -158,10 +104,8 @@ func forecastParseCond(dp *forecastDataPoint) (ret *iface.Cond) {
"thunderstorm": iface.CodeThunderyShowers,
}

ret = &iface.Cond{}

if dp.Time == nil {
return nil
return iface.Cond{}, fmt.Errorf("The forecast.io response did not provide a time for the weather condition")
}
ret.Time = time.Unix(int64(*dp.Time), 0)

Expand Down Expand Up @@ -200,11 +144,12 @@ func forecastParseCond(dp *forecastDataPoint) (ret *iface.Cond) {
ret.WinddirDegree = &p
}

return
return ret, nil
}

func (c *forecastConfig) Setup() {
flag.StringVar(&c.apiKey, "forecast-api-key", "", "forecast backend: the api `KEY` to use")
flag.StringVar(&c.language, "forecast-lang", "en", "forecast backend: the `LANGUAGE` to request from forecast.io")
flag.BoolVar(&c.debug, "forecast-debug", false, "forecast backend: print raw requests and responses")
}

Expand All @@ -214,10 +159,10 @@ func (c *forecastConfig) Fetch(location string, numdays int) iface.Data {
if len(c.apiKey) == 0 {
log.Fatal("No forecast.io API key specified.")
}
requri := fmt.Sprintf(forecastWuri, c.apiKey, location)
requri := fmt.Sprintf(forecastWuri, c.apiKey, location, c.language)

if c.debug {
log.Printf("Weather service: %s\n", requri)
log.Println("Weather request:", requri)
}

res, err := http.Get(requri)
Expand All @@ -234,27 +179,24 @@ func (c *forecastConfig) Fetch(location string, numdays int) iface.Data {
}

if c.debug {
log.Println("Weather request:", requri)
//log.Printf("Weather response: %s\n", body)
log.Println("Weather response:", string(body))
}

var resp forecastResponse
if err = json.Unmarshal(body, &resp); err != nil {
log.Println(err)
}

//log.Printf("Weather response: %v\n", resp)

//log.Printf("Weather response: %v\n", resp.Currently)

ret.Location = fmt.Sprintf("%f:%f", *resp.Latitude, *resp.Longitude)
var reqLatLon iface.LatLon
reqLatLon.Latitude = *resp.Latitude
reqLatLon.Longitude = *resp.Longitude
ret.GeoLoc = &reqLatLon

ret.Current = *forecastParseCond(&resp.Currently)
ret.Forecast = resp.Hourly.Convert(c)
if ret.Current, err = forecastParseCond(resp.Currently); err != nil {
log.Fatalf("Could not parse current weather condition: %v", err)
}
ret.Forecast = forecastParseDaily(resp.Hourly, numdays)

return ret
}
Expand Down

0 comments on commit e4e9a6e

Please sign in to comment.