-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrainfall.go
138 lines (119 loc) · 4.24 KB
/
rainfall.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Rainfall data extraction tool to pull daily total rainfall data for an entire year from NEORSD Rainfall dashboard
// See github.com/AlecIsaacson/Rainfall for details.
//
package main
import (
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"time"
)
//NEORSD returns data in this struct.
type neorsdRainfallStruct struct {
Draw int `json:"draw"`
RecordsTotal int `json:"recordsTotal"`
RecordsFiltered int `json:"recordsFiltered"`
Data []struct {
TrendDataDay int `json:"trend_data_day"`
RainTotal float64 `json:"rain_total"`
} `json:"data"`
}
//Get the NEORSD rainfall info, returning the result as a byte string.
func getRainfall(urlToGet string, yearIndex int, month string, location string, logVerbose bool) []byte {
if logVerbose {
fmt.Println("In getRainfall")
}
//As you can see, most of the form attributes aren't required. I've left them here in case they're needed some day.
formData := url.Values{
//"draw": {"4"},
// "columns[0][data]": {"trend_data_day"},
// "columns[0][name]": {""},
// "columns[0][searchable]": {"true"},
// "columns[0][orderable]": {"false"},
// "columns[0][search][value]": {""},
// "columns[0][search][regex]": {"false"},
// "columns[1][data]": {"rain_total"},
// "columns[1][name]": {""},
// "columns[1][searchable]": {"true"},
// "columns[1][orderable]": {"false"},
// "columns[1][search][value]": {""},
// "columns[1][search][regex]": {"false"},
// "start": {"0"},
// "length": {"10"},
// "search[value]": {""},
// "search[regex]": {"false"},
"startingYear": {strconv.Itoa(yearIndex)},
"rainfallSite": {location},
//"day": {"1"},
"month": {month},
//"fullDate": {"March 1, 2012"},
}
//Post the request to NEORSD.
resp, err := http.PostForm(urlToGet, formData)
if logVerbose {
fmt.Println("Form data:", formData)
fmt.Println("NEORSD Response:", resp.Status)
}
if err != nil || resp.StatusCode != 200 {
fmt.Println("Error")
fmt.Println(resp)
}
defer resp.Body.Close()
response, err := ioutil.ReadAll(resp.Body)
if logVerbose {
fmt.Println("Raw response:", string(response))
fmt.Println("End of getRainfall")
}
return response
}
func main() {
fmt.Println("GetRainfall v1.5")
fmt.Println("Use -h for arguments.")
fmt.Println("Output is Location, Year Month Day, and rainfall in inches (rounded to nearest hundreth).")
fmt.Println("")
location := flag.String("location", "Beachwood", "The name of the gauge location whose data you want to get")
yearToGet := flag.Int("year", 2012, "Year of rainfall data to get")
logVerbose := flag.Bool("verbose", false, "Writes verbose logs for debugging")
flag.Parse()
if *logVerbose {
fmt.Println("Verbose logging enabled.")
fmt.Println("Getting data for:", *location, *yearToGet)
}
//Define the APIs base URL
neorsdBaseURL := "https://www.neorsd.org/Rainfall%20Dashboard/dataTableServerSide.php?rainfallDaily"
//The NEORSD API defines this year as year 1. Prior years are indexed backwards.
//Yes, I could have used the Go time library, but it'd be more work.
//yearOffset should be equal to last year.
yearOffset := time.Now().Year() - 1
yearIndex := *yearToGet - yearOffset
months := []string{"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
//Iterate through the months, getting the daily rain totals for each.
for _, month := range months {
if *logVerbose {
fmt.Println("Getting data for:", month, *yearToGet)
fmt.Println("Year Offset:", yearOffset)
}
//Call the function to actually get the data.
neorsdRainfallJSON := getRainfall(neorsdBaseURL, yearIndex, month, *location, *logVerbose)
//Unmarshal the data into a struct
if *logVerbose {
fmt.Println("JSON response:", string(neorsdRainfallJSON))
fmt.Println("Unmarshalling monitors into struct")
}
var neorsdRainfallList neorsdRainfallStruct
if err := json.Unmarshal(neorsdRainfallJSON, &neorsdRainfallList); err != nil {
panic(err)
}
if *logVerbose {
fmt.Println(neorsdRainfallList)
}
//For each day of the month, write out the info we've got.
for _, day := range neorsdRainfallList.Data {
fmt.Printf("%v,%v %v %v,%.2f\n", *location, *yearToGet, month, day.TrendDataDay, day.RainTotal)
}
}
}