changeset 4795:fe838fc3ca69

FA: changed aggregation, so that worst classes are determining the result. Previously aggregation was done by calculating the mean, but that was not the expected behavior as the overall availability of the section can't be better than the availability of the worst included bottleneck.
author Sascha Wilde <wilde@intevation.de>
date Fri, 25 Oct 2019 17:11:37 +0200
parents a2b5021de297
children 199c49f967d2
files pkg/controllers/stretches.go
diffstat 1 files changed, 45 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/pkg/controllers/stretches.go	Fri Oct 25 16:12:43 2019 +0200
+++ b/pkg/controllers/stretches.go	Fri Oct 25 17:11:37 2019 +0200
@@ -10,6 +10,7 @@
 //
 // Author(s):
 //  * Sascha L. Teichmann <sascha.teichmann@intevation.de>
+//  * Sascha Wilde <wilde@intevation.de>
 
 package controllers
 
@@ -83,6 +84,45 @@
 	return false
 }
 
+func maxDuration(a time.Duration, b time.Duration) time.Duration {
+	if a > b {
+		return a
+	}
+	return b
+}
+
+func sumClassesTo(breaks []time.Duration, to int) time.Duration {
+	var result time.Duration
+	if to < 0 {
+		result = 0
+	}
+	for i := 0; i <= to; i++ {
+		result += breaks[i]
+	}
+	return result
+}
+
+func aggregateClasses(
+	new []time.Duration,
+	agg []time.Duration,
+) []time.Duration {
+	newAgg := make([]time.Duration, len(agg))
+
+	fmt.Printf("Old agg: %v\n", agg)
+	fmt.Printf("compwit: %v\n", new)
+	for i := 0; i < len(new)-1; i++ {
+		old_sum := sumClassesTo(agg, i)
+		new_sum := sumClassesTo(new, i)
+		newAgg[i] = maxDuration(new_sum, old_sum) - sumClassesTo(newAgg, i-1)
+	}
+	// adjust highest class so the sum of all classes in agg
+	// matches the original sum of all classes in new.
+	newAgg[len(new)-1] =
+		sumClassesTo(new, len(new)-1) - sumClassesTo(newAgg, len(new)-2)
+	fmt.Printf("New agg: %v\n", newAgg)
+	return newAgg
+}
+
 func loadFullStretchBottleneck(
 	ctx context.Context,
 	conn *sql.Conn,
@@ -311,12 +351,8 @@
 					if ldc == nil {
 						ldc, breaks = l, b
 					} else {
-						for i, v := range l {
-							ldc[i] += v
-						}
-						for i, v := range b {
-							breaks[i] += v
-						}
+						ldc = aggregateClasses(l, ldc)
+						breaks = aggregateClasses(b, breaks)
 					}
 				}
 
@@ -381,9 +417,6 @@
 		return
 	}
 
-	// Normalize to look like as we have only one bottleneck.
-	scale := 1 / float64(len(loaded))
-
 	empty := fmt.Sprintf("%.3f", 0.0)
 	for i := range record[1:] {
 		record[i+1] = empty
@@ -391,12 +424,6 @@
 
 	for _, r := range results {
 		// Round to full days
-		for i, v := range r.ldc {
-			r.ldc[i] = time.Duration(float64(v) * scale)
-		}
-		for i, v := range r.breaks {
-			r.breaks[i] = time.Duration(float64(v) * scale)
-		}
 		ldcRounded := common.RoundToFullDays(r.ldc)
 		rangesRounded := common.RoundToFullDays(r.breaks)
 
@@ -588,16 +615,12 @@
 					if ldc == nil {
 						ldc, breaks = l, b
 					} else {
-						for i, v := range l {
-							ldc[i] += v
-						}
-						for i, v := range b {
-							breaks[i] += v
-						}
+						ldc = aggregateClasses(l, ldc)
+						breaks = aggregateClasses(b, breaks)
 					}
 				}
 
-				duration := res.to.Sub(res.from) * time.Duration(len(loaded))
+				duration := res.to.Sub(res.from)
 
 				res.ldc = durationsToPercentage(duration, ldc)
 				res.breaks = durationsToPercentage(duration, breaks)