-
Notifications
You must be signed in to change notification settings - Fork 0
/
statistics.go
110 lines (89 loc) · 2.46 KB
/
statistics.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package main
import (
"fmt"
"sort"
"strconv"
"strings"
"sync"
)
// statsCalls wraps data and behaviours needed to process
// mostly used parameters in calls to fizzbuzz endpoint
type statsCalls struct {
mux *sync.Mutex
info map[string]int
}
func (stats statsCalls) add(params string) {
stats.mux.Lock()
defer stats.mux.Unlock()
stats.info[params]++
}
// most return the most used parameters it has been presented
func (stats statsCalls) most() (string, int) {
var (
mostParams string
mostNbCalls int
)
stats.mux.Lock()
defer stats.mux.Unlock()
for params, nbCalls := range stats.info {
if nbCalls > mostNbCalls {
mostParams = params
mostNbCalls = nbCalls
}
}
return mostParams, mostNbCalls
}
// nMost returns the n most used strings it has been presented
// which is to say the n most used sets of parameters used in calls to
// fizzbuzz endpoint
func (stats statsCalls) nMost(n int) ([]string, []int) {
type callInfo struct {
params string
nbCalls int
}
toSort := make([]callInfo, len(stats.info))
i := 0
stats.mux.Lock()
for params, nbCalls := range stats.info {
toSort[i] = callInfo{
params: params,
nbCalls: nbCalls,
}
i++
}
stats.mux.Unlock()
sort.Slice(toSort, func(i, j int) bool {
return toSort[i].nbCalls > toSort[j].nbCalls
})
resultStrings := make([]string, n)
resultNumbers := make([]int, n)
for i := 0 ; i < n && i < len(toSort); i++ {
resultStrings[i] = toSort[i].params
resultNumbers[i] = toSort[i].nbCalls
}
return resultStrings, resultNumbers
}
// transformQuery takes a set of parameters representing a call to
// fizzbuzz endpoint and transforms it to an easily parsable string
func transformQuery(d1, d2, limit int, str1, str2 string) string {
return fmt.Sprintf("%d|%d|%d|%s|%s", d1, d2, limit, str1, str2)
}
// getQuery takes a 'transformQuery'-formatted string and returns
// the original set of parameters it represent.
// Both functions work as a dependant couple to easily store call
// parameters in a map[string]int.
func getQuery(params string) (int, int, int, string, string) {
var i int
for i = 0 ; params[i] != '|' ; i++ {}
d1, _ := strconv.Atoi(params[:i])
params = params[i+1:]
for i = 0 ; params[i] != '|' ; i++ {}
d2, _ := strconv.Atoi(params[:i])
params = params[i+1:]
for i = 0 ; params[i] != '|' ; i++ {}
limit, _ := strconv.Atoi(params[:i])
params = params[i+1:]
i = strings.IndexByte(params, '|')
str1, str2 := params[:i], params[i+1:]
return d1, d2, limit, str1, str2
}