2018-09-09 13:52:59 +00:00
|
|
|
// Copyright (C) 2018 The Syncthing Authors.
|
|
|
|
//
|
|
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
|
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
|
|
|
2014-06-28 09:24:25 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2017-11-09 22:22:47 +00:00
|
|
|
type NumberType int
|
|
|
|
|
|
|
|
const (
|
|
|
|
NumberMetric NumberType = iota
|
|
|
|
NumberBinary
|
|
|
|
NumberDuration
|
|
|
|
)
|
|
|
|
|
|
|
|
func number(ntype NumberType, v float64) string {
|
2019-05-18 09:59:32 +00:00
|
|
|
switch ntype {
|
|
|
|
case NumberMetric:
|
|
|
|
return metric(v)
|
|
|
|
case NumberDuration:
|
2017-11-09 22:22:47 +00:00
|
|
|
return duration(v)
|
2019-05-18 09:59:32 +00:00
|
|
|
case NumberBinary:
|
2014-06-28 09:24:25 +00:00
|
|
|
return binary(v)
|
2019-05-18 09:59:32 +00:00
|
|
|
default:
|
2014-06-28 09:24:25 +00:00
|
|
|
return metric(v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-09 22:22:47 +00:00
|
|
|
type suffix struct {
|
|
|
|
Suffix string
|
2014-06-28 09:24:25 +00:00
|
|
|
Multiplier float64
|
|
|
|
}
|
|
|
|
|
2017-11-09 22:22:47 +00:00
|
|
|
var metricSuffixes = []suffix{
|
2014-06-28 09:24:25 +00:00
|
|
|
{"G", 1e9},
|
|
|
|
{"M", 1e6},
|
|
|
|
{"k", 1e3},
|
|
|
|
}
|
|
|
|
|
2017-11-09 22:22:47 +00:00
|
|
|
var binarySuffixes = []suffix{
|
2014-06-28 09:24:25 +00:00
|
|
|
{"Gi", 1 << 30},
|
|
|
|
{"Mi", 1 << 20},
|
|
|
|
{"Ki", 1 << 10},
|
|
|
|
}
|
|
|
|
|
2017-11-09 22:22:47 +00:00
|
|
|
var durationSuffix = []suffix{
|
|
|
|
{"year", 365 * 24 * 60 * 60},
|
|
|
|
{"month", 30 * 24 * 60 * 60},
|
|
|
|
{"day", 24 * 60 * 60},
|
|
|
|
{"hour", 60 * 60},
|
|
|
|
{"minute", 60},
|
|
|
|
{"second", 1},
|
|
|
|
}
|
|
|
|
|
2014-06-28 09:24:25 +00:00
|
|
|
func metric(v float64) string {
|
2017-11-09 22:22:47 +00:00
|
|
|
return withSuffix(v, metricSuffixes, false)
|
2014-06-28 09:24:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func binary(v float64) string {
|
2017-11-09 22:22:47 +00:00
|
|
|
return withSuffix(v, binarySuffixes, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
func duration(v float64) string {
|
|
|
|
return withSuffix(v, durationSuffix, true)
|
2014-06-28 09:24:25 +00:00
|
|
|
}
|
|
|
|
|
2017-11-09 22:22:47 +00:00
|
|
|
func withSuffix(v float64, ps []suffix, pluralize bool) string {
|
2014-06-28 09:24:25 +00:00
|
|
|
for _, p := range ps {
|
|
|
|
if v >= p.Multiplier {
|
2017-11-09 22:22:47 +00:00
|
|
|
suffix := p.Suffix
|
|
|
|
if pluralize && v/p.Multiplier != 1.0 {
|
|
|
|
suffix += "s"
|
|
|
|
}
|
|
|
|
// If the number only has decimal zeroes, strip em off.
|
|
|
|
num := strings.TrimRight(strings.TrimRight(fmt.Sprintf("%.1f", v/p.Multiplier), "0"), ".")
|
|
|
|
return fmt.Sprintf("%s %s", num, suffix)
|
2014-06-28 09:24:25 +00:00
|
|
|
}
|
|
|
|
}
|
2017-11-09 22:22:47 +00:00
|
|
|
return strings.TrimRight(strings.TrimRight(fmt.Sprintf("%.1f", v), "0"), ".")
|
2014-06-28 09:24:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// commatize returns a number with sep as thousands separators. Handles
|
|
|
|
// integers and plain floats.
|
|
|
|
func commatize(sep, s string) string {
|
2017-11-09 22:22:47 +00:00
|
|
|
// If no dot, don't do anything.
|
|
|
|
if !strings.ContainsRune(s, '.') {
|
|
|
|
return s
|
|
|
|
}
|
2014-06-28 09:24:25 +00:00
|
|
|
var b bytes.Buffer
|
|
|
|
fs := strings.SplitN(s, ".", 2)
|
|
|
|
|
|
|
|
l := len(fs[0])
|
|
|
|
for i := range fs[0] {
|
|
|
|
b.Write([]byte{s[i]})
|
|
|
|
if i < l-1 && (l-i)%3 == 1 {
|
|
|
|
b.WriteString(sep)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(fs) > 1 && len(fs[1]) > 0 {
|
|
|
|
b.WriteString(".")
|
|
|
|
b.WriteString(fs[1])
|
|
|
|
}
|
|
|
|
|
|
|
|
return b.String()
|
|
|
|
}
|
2017-11-09 22:22:47 +00:00
|
|
|
|
|
|
|
func proportion(m map[string]int, count int) float64 {
|
|
|
|
total := 0
|
|
|
|
isMax := true
|
|
|
|
for _, n := range m {
|
|
|
|
total += n
|
|
|
|
if n > count {
|
|
|
|
isMax = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pct := (100 * float64(count)) / float64(total)
|
|
|
|
// To avoid rounding errors in the template, surpassing 100% and breaking
|
|
|
|
// the progress bars.
|
|
|
|
if isMax && len(m) > 1 && count != total {
|
|
|
|
pct -= 0.01
|
|
|
|
}
|
|
|
|
return pct
|
|
|
|
}
|