Mercurial > gemma
changeset 4362:89d2d9309a38
Merge in fa-round-in-backend branch
author | Bernhard Reiter <bernhard@intevation.de> |
---|---|
date | Mon, 09 Sep 2019 17:25:28 +0200 |
parents | 90b72e811efd (current diff) 8a26225b6133 (diff) |
children | d6439e7c8b1c |
files | |
diffstat | 4 files changed, 119 insertions(+), 46 deletions(-) [+] |
line wrap: on
line diff
--- a/client/src/components/fairway/AvailableFairwayDepth.vue Mon Sep 09 17:13:37 2019 +0200 +++ b/client/src/components/fairway/AvailableFairwayDepth.vue Mon Sep 09 17:25:28 2019 +0200 @@ -93,15 +93,6 @@ import { FREQUENCIES } from "@/store/fairwayavailability"; import { defaultDiagramTemplate } from "@/lib/DefaultDiagramTemplate"; -// FIXME This is a rounding methods that shows that we have fractions, -// because we are coming from hours. Users will understand the underlying -// math better and we can see if this is wanted. -// With the backend just giving us the summarized hours, we cannot do -// a classification of each day into a category. -// (The name of the function is kept to keep the diff more readable and -// should changed if this is more clarified.) -const hoursInDays = x => Math.round((x * 10) / 24) / 10; - export default { mixins: [diagram, pdfgen, templateLoader], components: { @@ -475,19 +466,15 @@ .querySelector(".diagram-container") .getBoundingClientRect().left; d3.select("#tooltip") - .text(hoursInDays(d.height)) + .text(d.height) .attr("y", y - 10) .attr("x", d3.event.pageX - dy); //d3.event.pageX gives coordinates relative to SVG //dy gives offset of svg on page }) - .attr("y", d => { - return ( - 2 * yScale(0) - yScale(hoursInDays(d.translateY)) + this.paddingTop - ); - }) + .attr("y", d => 2 * yScale(0) - yScale(d.translateY) + this.paddingTop) .attr("height", d => { - return yScale(0) - yScale(hoursInDays(d.height)); + return yScale(0) - yScale(d.height); }) .attr("x", ldcOffset + spaceBetween / 2) .attr("width", widthPerItem - ldcOffset - spaceBetween) @@ -500,19 +487,19 @@ .selectAll("g.bars") .data(d => d.lowerLevels) .enter() - .filter(d => hoursInDays(d.height) > 0) + .filter(d => d.height > 0) .insert("text") .attr("y", d => { return ( 2 * yScale(0) - - yScale(hoursInDays(d.translateY)) + + yScale(d.translateY) + this.paddingTop + - (yScale(0) - yScale(hoursInDays(d.height))) + + (yScale(0) - yScale(d.height)) + (yScale(0) - yScale(1.9)) //instead o alignment-baseline hanging ); }) .attr("x", widthPerItem / 2) - .text(d => hoursInDays(d.height)) + .text(d => d.height) // does not work with svg2pdf .attr("alignment-baseline", "hanging") .attr("text-anchor", "middle") .attr("font-size", "8") @@ -520,7 +507,7 @@ } }, fnheight({ name, yScale }) { - return d => yScale(0) - yScale(hoursInDays(d[name])); + return d => yScale(0) - yScale(d[name]); }, drawLDC({ everyBar, yScale, widthPerItem, spaceBetween, ldcOffset }) { const height = this.fnheight({ name: "ldc", yScale }); @@ -540,7 +527,7 @@ .querySelector(".diagram-container") .getBoundingClientRect().left; d3.select("#tooltip") - .text(hoursInDays(d.ldc)) + .text(d.ldc) .attr("y", y - 50) .attr("x", d3.event.pageX - dy); //d3.event.pageX gives coordinates relative to SVG @@ -558,11 +545,11 @@ .attr("id", "ldc"); if (this.showNumbers) { everyBar - .filter(d => hoursInDays(d.ldc) > 0) + .filter(d => d.ldc > 0) .append("text") .attr("y", yScale(0.5)) // some distance from the bar .attr("x", spaceBetween / 2) - .text(d => hoursInDays(d.ldc)) + .text(d => d.ldc) .attr("text-anchor", "left") .attr("font-size", "8") .attr( @@ -596,7 +583,7 @@ .querySelector(".diagram-container") .getBoundingClientRect().left; d3.select("#tooltip") - .text(hoursInDays(d.highestLevel)) + .text(d.highestLevel) .attr("y", y - 50) .attr("x", d3.event.pageX - dy); //d3.event.pageX gives coordinates relative to SVG @@ -613,11 +600,11 @@ .attr("fill", this.$options.COLORS.HIGHEST); if (this.showNumbers) { everyBar - .filter(d => hoursInDays(d.highestLevel) > 0) + .filter(d => d.highestLevel > 0) .append("text") .attr("y", yScale(0.5)) // some distance from the bar .attr("x", widthPerItem / 2) - .text(d => hoursInDays(d.highestLevel)) + .text(d => d.highestLevel) .attr("text-anchor", "middle") .attr("font-size", "8") .attr(
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/common/round.go Mon Sep 09 17:25:28 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 Mon Sep 09 17:13:37 2019 +0200 +++ b/pkg/controllers/bottlenecks.go Mon Sep 09 17:25:28 2019 +0200 @@ -503,8 +503,8 @@ 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) [%%]", ldcRefs[0]) + record[2] = fmt.Sprintf("# >= LDC (%.1f) [%%]", ldcRefs[0]) for i, v := range breaks { if i == 0 { record[3] = fmt.Sprintf("#d < %.1f [%%]", v) @@ -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 Mon Sep 09 17:13:37 2019 +0200 +++ b/pkg/controllers/stretches.go Mon Sep 09 17:25:28 2019 +0200 @@ -27,6 +27,7 @@ "github.com/gorilla/mux" + "gemma.intevation.de/gemma/pkg/common" "gemma.intevation.de/gemma/pkg/middleware" ) @@ -348,19 +349,19 @@ // label, lnwl, classes record := make([]string, 1+2+len(breaks)+1) record[0] = "# time" - record[1] = "# < LDC [h]" - record[2] = "# >= LDC [h]" + record[1] = "# < LDC [d]" + record[2] = "# >= LDC [d]" for i, v := range breaks { if useDepth && useWidth { if i == 0 { - record[3] = "# < break_1 [h]" + record[3] = "# < break_1 [d]" } record[i+4] = fmt.Sprintf("# >= break_%d", i+1) } else { 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) } } @@ -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 {