changeset 4353:97312d7954ba fa-round-in-backend

FA diagrams: round to full days in back end.
author Sascha Wilde <wilde@intevation.de>
date Mon, 09 Sep 2019 15:14:55 +0200
parents 69c54e2def2d
children e357730c090a
files pkg/common/round.go pkg/controllers/bottlenecks.go pkg/controllers/stretches.go
diffstat 3 files changed, 98 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkg/common/round.go	Mon Sep 09 15:14:55 2019 +0200
@@ -0,0 +1,71 @@
+// This is Free Software under GNU Affero General Public License v >= 3.0
+// without warranty, see README.md and license for details.
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+// License-Filename: LICENSES/AGPL-3.0.txt
+//
+// Copyright (C) 2018 by via donau
+//   – Österreichische Wasserstraßen-Gesellschaft mbH
+// Software engineering by Intevation GmbH
+//
+// Author(s):
+//  * Sascha Wilde <wilde@sha-bang.de>
+
+package common
+
+import (
+	"math"
+	"sort"
+	"time"
+)
+
+type Rest struct {
+	Key  int
+	Rest float64
+}
+
+// Simple sum preserving rounding method:
+func SumPreservingRound(arr []float64) []int {
+	var (
+		sum   float64
+		rests []Rest
+	)
+	result := make([]int, len(arr))
+
+	// floor all values
+	for i, v := range arr {
+		sum += v
+		result[i] = int(v)
+		rests = append(rests, Rest{Key: i, Rest: v - float64(result[i])})
+	}
+
+	// find the difference in summs
+	var newSum int
+	for _, v := range result {
+		newSum += v
+	}
+	delta := int(math.Round(sum)) - newSum
+
+	// spread delta over values with highest rest
+	sort.Slice(rests, func(i, j int) bool {
+		return rests[i].Rest > rests[j].Rest
+	})
+	for _, v := range rests {
+		if delta <= 0 {
+			break
+		}
+		result[v.Key]++
+		delta--
+	}
+
+	return result
+}
+
+// Round anarray of Duratons to full days
+func RoundToFullDays(durations []time.Duration) []int {
+	days := make([]float64, len(durations))
+	for i, v := range durations {
+		days[i] = v.Hours() / 24
+	}
+	return SumPreservingRound(days)
+}
--- a/pkg/controllers/bottlenecks.go	Fri Sep 06 18:09:48 2019 +0200
+++ b/pkg/controllers/bottlenecks.go	Mon Sep 09 15:14:55 2019 +0200
@@ -653,13 +653,13 @@
 	// label, ldc, classes
 	record := make([]string, 1+2+len(breaks)+1)
 	record[0] = "#time"
-	record[1] = fmt.Sprintf("# < LDC (%.1f) [h]", ldcRefs[0])
-	record[2] = fmt.Sprintf("# >= LDC (%.1f) [h]", ldcRefs[0])
+	record[1] = fmt.Sprintf("# < LDC (%.1f) [d]", ldcRefs[0])
+	record[2] = fmt.Sprintf("# >= LDC (%.1f) [d]", ldcRefs[0])
 	for i, v := range breaks {
 		if i == 0 {
-			record[3] = fmt.Sprintf("# < %.1f [h]", v)
+			record[3] = fmt.Sprintf("# < %.1f [d]", v)
 		}
-		record[i+4] = fmt.Sprintf("# >= %.1f [h]", v)
+		record[i+4] = fmt.Sprintf("# >= %.1f [d]", v)
 	}
 
 	if err := out.Write(record); err != nil {
@@ -701,13 +701,17 @@
 			access,
 		)
 
+		// Round to full days
+		ldcRounded := common.RoundToFullDays(ldc)
+		rangesRounded := common.RoundToFullDays(ranges)
+
 		record[0] = label
-		for i, v := range ldc {
-			record[i+1] = fmt.Sprintf("%.3f", v.Hours())
+		for i, v := range ldcRounded {
+			record[i+1] = fmt.Sprintf("%d", v)
 		}
 
-		for i, d := range ranges {
-			record[3+i] = fmt.Sprintf("%.3f", d.Hours())
+		for i, d := range rangesRounded {
+			record[3+i] = fmt.Sprintf("%d", d)
 		}
 
 		if err := out.Write(record); err != nil {
--- a/pkg/controllers/stretches.go	Fri Sep 06 18:09:48 2019 +0200
+++ b/pkg/controllers/stretches.go	Mon Sep 09 15:14:55 2019 +0200
@@ -27,6 +27,7 @@
 
 	"github.com/gorilla/mux"
 
+	"gemma.intevation.de/gemma/pkg/common"
 	"gemma.intevation.de/gemma/pkg/middleware"
 )
 
@@ -379,13 +380,23 @@
 	}
 
 	for _, r := range results {
-		record[0] = r.label
+		// Round to full days
 		for i, v := range r.ldc {
-			record[1+i] = fmt.Sprintf("%.3f", v.Hours()*scale)
+			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)
+
+		record[0] = r.label
+		for i, v := range ldcRounded {
+			record[1+i] = fmt.Sprintf("%d", v)
 		}
 
-		for i, d := range r.breaks {
-			record[3+i] = fmt.Sprintf("%.3f", d.Hours()*scale)
+		for i, d := range rangesRounded {
+			record[3+i] = fmt.Sprintf("%d", d)
 		}
 
 		if err := out.Write(record); err != nil {