comparison pkg/common/round.go @ 4615:32d3e0cecf4f geoserver_sql_views

Merge default into geoserver_sql_views
author Tom Gottfried <tom@intevation.de>
date Mon, 09 Sep 2019 17:46:51 +0200
parents 97312d7954ba
children e739a4806d7c
comparison
equal deleted inserted replaced
4614:970e90d3d5eb 4615:32d3e0cecf4f
1 // This is Free Software under GNU Affero General Public License v >= 3.0
2 // without warranty, see README.md and license for details.
3 //
4 // SPDX-License-Identifier: AGPL-3.0-or-later
5 // License-Filename: LICENSES/AGPL-3.0.txt
6 //
7 // Copyright (C) 2018 by via donau
8 // – Österreichische Wasserstraßen-Gesellschaft mbH
9 // Software engineering by Intevation GmbH
10 //
11 // Author(s):
12 // * Sascha Wilde <wilde@sha-bang.de>
13
14 package common
15
16 import (
17 "math"
18 "sort"
19 "time"
20 )
21
22 type Rest struct {
23 Key int
24 Rest float64
25 }
26
27 // Simple sum preserving rounding method:
28 func SumPreservingRound(arr []float64) []int {
29 var (
30 sum float64
31 rests []Rest
32 )
33 result := make([]int, len(arr))
34
35 // floor all values
36 for i, v := range arr {
37 sum += v
38 result[i] = int(v)
39 rests = append(rests, Rest{Key: i, Rest: v - float64(result[i])})
40 }
41
42 // find the difference in summs
43 var newSum int
44 for _, v := range result {
45 newSum += v
46 }
47 delta := int(math.Round(sum)) - newSum
48
49 // spread delta over values with highest rest
50 sort.Slice(rests, func(i, j int) bool {
51 return rests[i].Rest > rests[j].Rest
52 })
53 for _, v := range rests {
54 if delta <= 0 {
55 break
56 }
57 result[v.Key]++
58 delta--
59 }
60
61 return result
62 }
63
64 // Round anarray of Duratons to full days
65 func RoundToFullDays(durations []time.Duration) []int {
66 days := make([]float64, len(durations))
67 for i, v := range durations {
68 days[i] = v.Hours() / 24
69 }
70 return SumPreservingRound(days)
71 }