changeset 3038:d47d289d6e68

Fairway availability: Fill classes.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Fri, 12 Apr 2019 17:00:30 +0200
parents 7f12a87c56ff
children 130da3cf5c8a
files pkg/controllers/bottlenecks.go
diffstat 1 files changed, 44 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/pkg/controllers/bottlenecks.go	Fri Apr 12 15:49:00 2019 +0200
+++ b/pkg/controllers/bottlenecks.go	Fri Apr 12 17:00:30 2019 +0200
@@ -93,20 +93,6 @@
 	}
 )
 
-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 classifyAvailMeasurements(
 	from, to time.Time,
 	measurements []availMeasurement,
@@ -118,13 +104,14 @@
 		kind common.ValueRangeKind
 	}
 
-	var invalid time.Duration
+	//var invalid time.Duration
+	result := make([]time.Duration, len(classes)+1)
 
 	cvs := make([]classValues, len(classes))
 
 	classify := func(v func(float64) (time.Time, common.ValueRangeKind)) {
-		for j := range classes {
-			cvs[j].when, cvs[j].kind = v(float64(classes[j].value))
+		for i := range classes {
+			cvs[i].when, cvs[i].kind = v(float64(classes[i].value))
 		}
 	}
 
@@ -153,8 +140,8 @@
 
 		case p1.when.After(from) && p2.when.Before(to):
 			// (from-to) is complete inside segment.
-			invalid += p1.when.Sub(from)
-			invalid += to.Sub(p2.when)
+			// invalid += p1.when.Sub(from)
+			// invalid += to.Sub(p2.when)
 			v := vbt(p1, p2)
 			f, _ := v(from)
 			t, _ := v(to)
@@ -163,7 +150,7 @@
 
 		case p1.when.After(from):
 			// from is inside segment
-			invalid += p1.when.Sub(from)
+			// invalid += p1.when.Sub(from)
 			f, _ := vbt(p1, p2)(from)
 			classify(common.InterpolateTimeByValue(
 				from, f,
@@ -173,7 +160,7 @@
 
 		case p2.when.Before(to):
 			// to is inside segment
-			invalid += to.Sub(p2.when)
+			// invalid += to.Sub(p2.when)
 			t, _ := vbt(p1, p2)(to)
 			classify(common.InterpolateTimeByValue(
 				p1.when, float64(p1.value),
@@ -192,11 +179,30 @@
 			log.Println("warn: unexpected case. That should not happen.")
 			continue pairs
 		}
-		// TODO: Distribute to classes.
-		_, _ = start, end
+
+		for i := len(cvs) - 1; i >= 0; i-- {
+			switch cvs[i].kind {
+			case common.ValueAbove:
+				result[i+1] += end.Sub(start)
+				continue pairs
+
+			case common.ValueInside:
+				// -> split
+				if p1.value < classes[i].value {
+					// started below -> second part above
+					result[i+1] = end.Sub(cvs[i].when)
+					end = cvs[i].when
+				} else {
+					// started above -> first part above
+					result[i+1] = cvs[i].when.Sub(start)
+					start = cvs[i].when
+				}
+			}
+		}
+		result[0] += end.Sub(start)
 	}
 
-	return nil
+	return result
 }
 
 func bottleneckAvailabilty(
@@ -361,7 +367,17 @@
 		return
 	}
 
-	// TODO: Calculate the ranges.
+	results := classifyAvailMeasurements(
+		from, to,
+		ms,
+		refVals,
+	)
+
+	classes := make([]float64, len(results))
+	total := 100 / to.Sub(from).Seconds()
+	for i, v := range results {
+		classes[i] = v.Seconds() * total
+	}
 
 	type outputLevel struct {
 		Level string `json:"level"`
@@ -369,10 +385,11 @@
 	}
 
 	type output struct {
-		Levels []outputLevel `json:"levels"`
+		Levels  []outputLevel `json:"levels"`
+		Classes []float64     `json:"classes"`
 	}
 
-	out := output{}
+	out := output{Classes: classes}
 
 	for i := range refVals {
 		var level string