comparison pkg/controllers/gauges.go @ 2783:2806821cfd63

Added min and max values to CSV output of /api/data/waterlevels/{gauge} .
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Fri, 22 Mar 2019 21:55:30 +0100
parents 1f173d1a731d
children db1052bc162a
comparison
equal deleted inserted replaced
2782:615b0a9b8098 2783:2806821cfd63
56 56
57 selectWaterlevelsSQL = ` 57 selectWaterlevelsSQL = `
58 SELECT 58 SELECT
59 measure_date, 59 measure_date,
60 water_level, 60 water_level,
61 value_min,
62 value_max,
61 predicted 63 predicted
62 FROM waterway.gauge_measurements 64 FROM waterway.gauge_measurements
63 WHERE 65 WHERE
64 ` 66 `
65 selectWaterlevelsMeasuredSQL = ` 67 selectWaterlevelsMeasuredSQL = `
81 $7::timestamp with time zone 83 $7::timestamp with time zone
82 ORDER BY measure_date 84 ORDER BY measure_date
83 ` 85 `
84 ) 86 )
85 87
88 func float64format(v float64) string {
89 return strconv.FormatFloat(v, 'f', -1, 64)
90 }
91
92 func nullFloat64format(v sql.NullFloat64) string {
93 if v.Valid {
94 return float64format(v.Float64)
95 }
96 return ""
97 }
98
99 func boolFormat(b bool) string {
100 if b {
101 return "t"
102 }
103 return "f"
104 }
105
86 func averageWaterlevels(rw http.ResponseWriter, req *http.Request) { 106 func averageWaterlevels(rw http.ResponseWriter, req *http.Request) {
87 gauge := mux.Vars(req)["gauge"] 107 gauge := mux.Vars(req)["gauge"]
88 108
89 isrs, err := models.IsrsFromString(gauge) 109 isrs, err := models.IsrsFromString(gauge)
90 if err != nil { 110 if err != nil {
170 log.Printf("error: %v\n", err) 190 log.Printf("error: %v\n", err)
171 // Too late for an HTTP error code. 191 // Too late for an HTTP error code.
172 return 192 return
173 } 193 }
174 194
175 format := func(v float64) string {
176 return strconv.FormatFloat(v, 'f', -1, 64)
177 }
178
179 write := func() error { 195 write := func() error {
180 if len(values) > 0 { 196 if len(values) > 0 {
181 sort.Float64s(values) 197 sort.Float64s(values)
182 // date 198 // date
183 record[0] = last.Format(common.DateFormat) 199 record[0] = last.Format(common.DateFormat)
184 // min 200 // min
185 record[1] = format(values[0]) 201 record[1] = float64format(values[0])
186 // max 202 // max
187 record[2] = format(values[len(values)-1]) 203 record[2] = float64format(values[len(values)-1])
188 // mean 204 // mean
189 record[3] = format(stat.Mean(values, nil)) 205 record[3] = float64format(stat.Mean(values, nil))
190 // median 206 // median
191 record[4] = format(values[len(values)/2]) 207 record[4] = float64format(values[len(values)/2])
192 // Q25 208 // Q25
193 record[5] = format( 209 record[5] = float64format(
194 stat.Quantile(0.25, stat.Empirical, values, nil)) 210 stat.Quantile(0.25, stat.Empirical, values, nil))
195 // Q75 211 // Q75
196 record[6] = format( 212 record[6] = float64format(
197 stat.Quantile(0.75, stat.Empirical, values, nil)) 213 stat.Quantile(0.75, stat.Empirical, values, nil))
198 214
199 err := out.Write(record) 215 err := out.Write(record)
200 values = values[:0] 216 values = values[:0]
201 return err 217 return err
396 412
397 rw.Header().Add("Content-Type", "text/csv") 413 rw.Header().Add("Content-Type", "text/csv")
398 414
399 out := csv.NewWriter(rw) 415 out := csv.NewWriter(rw)
400 416
401 record := make([]string, 3) 417 record := []string{
418 "#date",
419 "#water_level",
420 "#value_min",
421 "#value_max",
422 "#predicted",
423 }
424
425 if err := out.Write(record); err != nil {
426 log.Printf("error: %v", err)
427 // Too late for an HTTP error code.
428 return
429 }
402 430
403 for rows.Next() { 431 for rows.Next() {
404 var ( 432 var (
405 measureDate time.Time 433 measureDate time.Time
406 waterlevel float64 434 waterlevel float64
435 valueMin sql.NullFloat64
436 valueMax sql.NullFloat64
407 predicted bool 437 predicted bool
408 ) 438 )
409 if err := rows.Scan(&measureDate, &waterlevel, &predicted); err != nil { 439 if err := rows.Scan(
440 &measureDate,
441 &waterlevel,
442 &valueMin,
443 &valueMax,
444 &predicted,
445 ); err != nil {
410 log.Printf("error: %v\n", err) 446 log.Printf("error: %v\n", err)
411 // Too late for an HTTP error code. 447 // Too late for an HTTP error code.
412 return 448 return
413 } 449 }
414 record[0] = measureDate.Format(models.ImportTimeFormat) 450 record[0] = measureDate.Format(models.ImportTimeFormat)
415 record[1] = strconv.FormatFloat(waterlevel, 'f', -1, 64) 451 record[1] = float64format(waterlevel)
416 if predicted { 452 record[2] = nullFloat64format(valueMin)
417 record[2] = "t" 453 record[3] = nullFloat64format(valueMax)
418 } else { 454 record[4] = boolFormat(predicted)
419 record[2] = "f" 455
420 }
421 if err := out.Write(record); err != nil { 456 if err := out.Write(record); err != nil {
422 log.Printf("error: %v", err) 457 log.Printf("error: %v", err)
423 // Too late for an HTTP error code. 458 // Too late for an HTTP error code.
424 return 459 return
425 } 460 }