Mercurial > gemma
changeset 2967:7c301ff449bc
Fairway availibility: Started with class building.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Mon, 08 Apr 2019 18:54:13 +0200 |
parents | 4bc2cc6364bc |
children | ac5ba5a0e963 ef79b635857b |
files | pkg/controllers/bottlenecks.go |
diffstat | 1 files changed, 112 insertions(+), 20 deletions(-) [+] |
line wrap: on
line diff
--- a/pkg/controllers/bottlenecks.go Mon Apr 08 17:44:49 2019 +0200 +++ b/pkg/controllers/bottlenecks.go Mon Apr 08 18:54:13 2019 +0200 @@ -80,6 +80,108 @@ ` ) +type ( + availReferenceValue struct { + level int + value int + } + + availMeasurement struct { + when time.Time + depth int + value int + } +) + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func interpolate( + m1, m2 *availMeasurement, + diff time.Duration, +) int { + tdiff := m2.when.Sub(m1.when) + + // f(0) = m1.value + // f(tdiff) = m2.value + // f(x) = m*x + b + // m1.value = m*0 + b <=> b = m1.value + // m2.value = m*tdiff + b <=> m = (m2.value - b)/tdiff + // f(diff) = diff*(m2.value - m1.value)/tdiff + m1.value + + return int(diff*time.Duration(m2.value-m1.value)/tdiff) + m1.value +} + +func classifyAvailMeasurements( + from, to time.Time, + measurements []availMeasurement, + classes []availReferenceValue, +) []time.Duration { + + results := make([]time.Duration, len(classes)+2) + + if from.Before(measurements[0].when) { + results[len(results)-1] = measurements[0].when.Sub(from) + from = measurements[0].when + } + + if to.After(measurements[len(measurements)-1].when) { + results[len(results)-1] += to.Sub(measurements[len(measurements)-1].when) + to = measurements[len(measurements)-1].when + } + + for i := 0; i < len(measurements)-1; i++ { + p1 := &measurements[i] + p2 := &measurements[i+1] + tdiff := p2.when.Sub(p1.when) + if tdiff <= 0 { + continue + } + + if from.After(p2.when) || to.Before(p1.when) { + continue + } + + if from.After(p1.when) { + tdiff2 := from.Sub(p1.when) + vf := interpolate(p1, p2, tdiff2) + p1 = &availMeasurement{when: from, value: vf} + tdiff = p2.when.Sub(from) + } + + if to.Before(p2.when) { + tdiff2 := p2.when.Sub(to) + vt := interpolate(p1, p2, tdiff2) + p2 = &availMeasurement{when: to, value: vt} + tdiff = p2.when.Sub(p1.when) + } + + if max(p1.value, p2.value) <= classes[0].value { + results[0] += tdiff + continue + } + if min(p1.value, p2.value) > classes[len(classes)-1].value { + results[len(results)-2] += tdiff + continue + } + + // TODO: Do the real classes. + } + + return results +} + func bottleneckAvailabilty( _ interface{}, req *http.Request, @@ -95,21 +197,16 @@ return } - type referenceValue struct { - level int - value int - } - ctx := req.Context() - loadReferenceValues := func() ([]referenceValue, error) { + loadReferenceValues := func() ([]availReferenceValue, error) { rows, err := conn.QueryContext(ctx, selectGaugeLevelsSQL, bn) if err != nil { return nil, err } defer rows.Close() - var levels []referenceValue + var levels []availReferenceValue loop: for rows.Next() { @@ -135,7 +232,7 @@ continue loop } } - levels = append(levels, referenceValue{level: level, value: value}) + levels = append(levels, availReferenceValue{level: level, value: value}) } if err := rows.Err(); err != nil { @@ -147,7 +244,7 @@ return levels, nil } - var refVals []referenceValue + var refVals []availReferenceValue if refVals, err = loadReferenceValues(); err != nil { return } @@ -206,13 +303,7 @@ los = 1 } - type measurement struct { - when time.Time - depth int - level int - } - - loadDepthValues := func() ([]measurement, error) { + loadDepthValues := func() ([]availMeasurement, error) { rows, err := conn.QueryContext( ctx, selectAvailableDepthSQL, bn, los, from, to) @@ -221,13 +312,14 @@ } defer rows.Close() - var ms []measurement + var ms []availMeasurement for rows.Next() { - var m measurement - if err := rows.Scan(&m.when, &m.depth, &m.level); err != nil { + var m availMeasurement + if err := rows.Scan(&m.when, &m.depth, &m.value); err != nil { return nil, err } + m.when = m.when.UTC() ms = append(ms, m) } @@ -238,7 +330,7 @@ return ms, nil } - var ms []measurement + var ms []availMeasurement if ms, err = loadDepthValues(); err != nil { return