Mercurial > gemma
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 } |