Mercurial > gemma
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 } |