Codebase list golang-github-vbauerster-mpb / 3efa27e
refactoring percentage decorator Vladimir Bauer 6 years ago
6 changed file(s) with 98 addition(s) and 44 deletion(s). Raw diff Collapse all Expand all
6363
6464 bb := make([][]byte, width)
6565
66 cwidth := int(internal.Percentage(stat.Total, stat.Current, int64(width)))
66 cwidth := int(internal.PercentageRound(stat.Total, stat.Current, width))
6767
6868 for i := 0; i < cwidth; i++ {
6969 bb[i] = s.format[rFill]
7474 if s.refillAmount > stat.Current {
7575 rwidth = cwidth
7676 } else {
77 rwidth = int(internal.Percentage(stat.Total, int64(s.refillAmount), int64(width)))
77 rwidth = int(internal.PercentageRound(stat.Total, int64(s.refillAmount), width))
7878 }
7979 for i := 0; i < rwidth; i++ {
8080 bb[i] = s.format[rRefill]
11
22 import (
33 "fmt"
4 "io"
5 "strconv"
6 "strings"
47
58 "github.com/vbauerster/mpb/v4/internal"
69 )
10
11 type PercentageType float64
12
13 func (s PercentageType) Format(st fmt.State, verb rune) {
14 var prec int
15 switch verb {
16 case 'd':
17 case 's':
18 prec = -1
19 default:
20 if p, ok := st.Precision(); ok {
21 prec = p
22 } else {
23 prec = 6
24 }
25 }
26
27 res := strconv.FormatFloat(float64(s), 'f', prec, 64)
28
29 if st.Flag(' ') {
30 res += " "
31 }
32 res += "%"
33
34 if w, ok := st.Width(); ok {
35 if len(res) < w {
36 pad := strings.Repeat(" ", w-len(res))
37 if st.Flag('-') {
38 res += pad
39 } else {
40 res = pad + res
41 }
42 }
43 }
44
45 io.WriteString(st, res)
46 }
747
848 // Percentage returns percentage decorator.
949 //
1050 // `wcc` optional WC config
1151 func Percentage(wcc ...WC) Decorator {
52 return PercentageFmt("% d", wcc...)
53 }
54
55 // PercentageFmt percentage decorator with custom fmt.
56 // "%.1f" = "1.0%" or "% .1f" = "1.0 %"
57 // "%d" = "1%" or "% d" = "1 %"
58 func PercentageFmt(fmt string, wcc ...WC) Decorator {
1259 var wc WC
1360 for _, widthConf := range wcc {
1461 wc = widthConf
1562 }
1663 wc.Init()
1764 d := &percentageDecorator{
18 WC: wc,
65 WC: wc,
66 fmt: fmt,
1967 }
2068 return d
2169 }
2270
2371 type percentageDecorator struct {
2472 WC
73 fmt string
2574 completeMsg *string
2675 }
2776
2978 if st.Completed && d.completeMsg != nil {
3079 return d.FormatMsg(*d.completeMsg)
3180 }
32 str := fmt.Sprintf("%d %%", internal.Percentage(st.Total, st.Current, 100))
33 return d.FormatMsg(str)
81 p := internal.Percentage(st.Total, st.Current, 100)
82 return d.FormatMsg(fmt.Sprintf(d.fmt, PercentageType(p)))
3483 }
3584
3685 func (d *percentageDecorator) OnCompleteMessage(msg string) {
1313 type SpeedKiB float64
1414
1515 func (s SpeedKiB) Format(st fmt.State, verb rune) {
16 prec, ok := st.Precision()
17
18 if verb == 'd' || !ok {
19 prec = 0
20 }
21 if verb == 'f' && !ok {
22 prec = 6
23 }
24 // retain old beahavior if s verb used
25 if verb == 's' {
26 prec = 1
16 var prec int
17 switch verb {
18 case 'd':
19 case 's':
20 prec = -1
21 default:
22 if p, ok := st.Precision(); ok {
23 prec = p
24 } else {
25 prec = 6
26 }
2727 }
2828
2929 var res, unit string
5353 if w, ok := st.Width(); ok {
5454 if len(res) < w {
5555 pad := strings.Repeat(" ", w-len(res))
56 if st.Flag(int('-')) {
56 if st.Flag('-') {
5757 res += pad
5858 } else {
5959 res = pad + res
6767 type SpeedKB float64
6868
6969 func (s SpeedKB) Format(st fmt.State, verb rune) {
70 prec, ok := st.Precision()
71
72 if verb == 'd' || !ok {
73 prec = 0
74 }
75 if verb == 'f' && !ok {
76 prec = 6
77 }
78 // retain old beahavior if s verb used
79 if verb == 's' {
80 prec = 1
70 var prec int
71 switch verb {
72 case 'd':
73 case 's':
74 prec = -1
75 default:
76 if p, ok := st.Precision(); ok {
77 prec = p
78 } else {
79 prec = 6
80 }
8181 }
8282
8383 var res, unit string
4848 "1024 %f": {1024, "%f", "1.000000KiB/s"},
4949 "1024 %d": {1024, "%d", "1KiB/s"},
5050 "1024 %.1f": {1024, "%.1f", "1.0KiB/s"},
51 "1024 %s": {1024, "%s", "1.0KiB/s"},
51 "1024 %s": {1024, "%s", "1KiB/s"},
5252 "3*MiB/s+140KiB/s %f": {3*MiB + 140*KiB, "%f", "3.136719MiB/s"},
5353 "3*MiB/s+140KiB/s %d": {3*MiB + 140*KiB, "%d", "3MiB/s"},
5454 "3*MiB/s+140KiB/s %.1f": {3*MiB + 140*KiB, "%.1f", "3.1MiB/s"},
55 "3*MiB/s+140KiB/s %s": {3*MiB + 140*KiB, "%s", "3.1MiB/s"},
55 "3*MiB/s+140KiB/s %s": {3*MiB + 140*KiB, "%s", "3.13671875MiB/s"},
5656 "2*GiB/s %f": {2 * GiB, "%f", "2.000000GiB/s"},
5757 "2*GiB/s %d": {2 * GiB, "%d", "2GiB/s"},
5858 "2*GiB/s %.1f": {2 * GiB, "%.1f", "2.0GiB/s"},
59 "2*GiB/s %s": {2 * GiB, "%s", "2.0GiB/s"},
59 "2*GiB/s %s": {2 * GiB, "%s", "2GiB/s"},
6060 "4*TiB/s %f": {4 * TiB, "%f", "4.000000TiB/s"},
6161 "4*TiB/s %d": {4 * TiB, "%d", "4TiB/s"},
6262 "4*TiB/s %.1f": {4 * TiB, "%.1f", "4.0TiB/s"},
63 "4*TiB/s %s": {4 * TiB, "%s", "4.0TiB/s"},
63 "4*TiB/s %s": {4 * TiB, "%s", "4TiB/s"},
6464 }
6565 for name, tc := range cases {
6666 t.Run(name, func(t *testing.T) {
112112
113113 "1000 %f": {1000, "%f", "1.000000kB/s"},
114114 "1000 %d": {1000, "%d", "1kB/s"},
115 "1000 %s": {1000, "%s", "1.0kB/s"},
115 "1000 %s": {1000, "%s", "1kB/s"},
116116 "1024 %f": {1024, "%f", "1.024000kB/s"},
117117 "1024 %d": {1024, "%d", "1kB/s"},
118118 "1024 %.1f": {1024, "%.1f", "1.0kB/s"},
119 "1024 %s": {1024, "%s", "1.0kB/s"},
119 "1024 %s": {1024, "%s", "1.024kB/s"},
120120 "3*MB/s+140*KB/s %f": {3*MB + 140*KB, "%f", "3.140000MB/s"},
121121 "3*MB/s+140*KB/s %d": {3*MB + 140*KB, "%d", "3MB/s"},
122122 "3*MB/s+140*KB/s %.1f": {3*MB + 140*KB, "%.1f", "3.1MB/s"},
123 "3*MB/s+140*KB/s %s": {3*MB + 140*KB, "%s", "3.1MB/s"},
123 "3*MB/s+140*KB/s %s": {3*MB + 140*KB, "%s", "3.14MB/s"},
124124 "2*GB/s %f": {2 * GB, "%f", "2.000000GB/s"},
125125 "2*GB/s %d": {2 * GB, "%d", "2GB/s"},
126126 "2*GB/s %.1f": {2 * GB, "%.1f", "2.0GB/s"},
127 "2*GB/s %s": {2 * GB, "%s", "2.0GB/s"},
127 "2*GB/s %s": {2 * GB, "%s", "2GB/s"},
128128 "4*TB/s %f": {4 * TB, "%f", "4.000000TB/s"},
129129 "4*TB/s %d": {4 * TB, "%d", "4TB/s"},
130130 "4*TB/s %.1f": {4 * TB, "%.1f", "4.0TB/s"},
131 "4*TB/s %s": {4 * TB, "%s", "4.0TB/s"},
131 "4*TB/s %s": {4 * TB, "%s", "4TB/s"},
132132 }
133133 for name, tc := range cases {
134134 t.Run(name, func(t *testing.T) {
22 import "math"
33
44 // Percentage is a helper function, to calculate percentage.
5 func Percentage(total, current, width int64) int64 {
5 func Percentage(total, current int64, width int) float64 {
66 if total <= 0 {
77 return 0
88 }
9 p := float64(width*current) / float64(total)
10 return int64(math.Round(p))
9 return float64(int64(width)*current) / float64(total)
1110 }
11
12 func PercentageRound(total, current int64, width int) float64 {
13 return math.Round(Percentage(total, current, width))
14 }
33
44 func TestPercentage(t *testing.T) {
55 // key is barWidth
6 testSuite := map[int64][]struct {
7 name string
8 total, current, expected int64
6 testSuite := map[int][]struct {
7 name string
8 total int64
9 current int64
10 expected int64
911 }{
1012 100: {
1113 {"t,c,e{-1,-1,0}", -1, -1, 0},
6365
6466 for width, cases := range testSuite {
6567 for _, tc := range cases {
66 got := Percentage(tc.total, tc.current, width)
68 got := int64(PercentageRound(tc.total, tc.current, width))
6769 if got != tc.expected {
6870 t.Errorf("width %d; %s: Expected: %d, got: %d\n", width, tc.name, tc.expected, got)
6971 }