Skip to content

Commit 0cfbab7

Browse files
committed
fix: FindVoteResult logic
1 parent 1e1b02c commit 0cfbab7

File tree

1 file changed

+49
-65
lines changed

1 file changed

+49
-65
lines changed

base/vote.go

Lines changed: 49 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
package base
22

3-
import (
4-
"sort"
5-
)
6-
73
type VoteResult string
84

95
const (
@@ -47,86 +43,74 @@ func (v *VoteResult) UnmarshalText(b []byte) error {
4743
return nil
4844
}
4945

50-
// FindMajority finds the majority(over threshold) set between the given sets.
51-
// The returned value means,
52-
// 0-N: index number of set
53-
// -1: not yet majority
54-
// -2: draw
55-
func FindMajority(quorum, threshold uint, set ...uint) int {
46+
func FindVoteResult(quorum, threshold uint, s []string) (result VoteResult, key string) {
5647
th := threshold
5748
if th > quorum {
5849
th = quorum
5950
}
60-
61-
if len(set) < 1 {
62-
return -1
51+
if len(s) == 0 {
52+
return VoteResultNotYet, ""
6353
}
6454

65-
var sum uint
66-
67-
for i := range set {
68-
n := set[i]
69-
70-
if n >= quorum {
71-
return i
72-
}
55+
count := make(map[string]uint, len(s))
56+
for _, v := range s {
57+
count[v]++
58+
}
7359

74-
if n >= th {
75-
return i
60+
var (
61+
maxCount uint
62+
secondMaxCount uint
63+
topTies uint
64+
mhs string
65+
)
66+
67+
for hs, cn := range count {
68+
switch {
69+
case cn > maxCount:
70+
secondMaxCount = maxCount
71+
maxCount = cn
72+
mhs = hs
73+
topTies = 1
74+
case cn == maxCount:
75+
topTies++
76+
if hs < mhs {
77+
mhs = hs
78+
}
79+
case cn > secondMaxCount:
80+
secondMaxCount = cn
7681
}
77-
78-
sum += n
7982
}
8083

81-
sort.Slice(set, func(i, j int) bool {
82-
return set[i] > set[j]
83-
})
84-
85-
if quorum-sum+set[0] < th {
86-
return -2
84+
total := uint(len(s))
85+
var remain uint
86+
if total >= quorum {
87+
remain = 0
88+
} else {
89+
remain = quorum - total
8790
}
8891

89-
return -1
90-
}
91-
92-
func FindVoteResult(quorum, threshold uint, s []string) (result VoteResult, key string) {
93-
th := threshold
94-
if th > quorum {
95-
th = quorum
92+
if maxCount >= th {
93+
return VoteResultMajority, mhs
9694
}
9795

98-
if len(s) < 1 {
99-
return VoteResultNotYet, ""
96+
if remain == 0 {
97+
return VoteResultDraw, ""
10098
}
10199

102-
keys := map[uint]string{}
103-
defer clear(keys)
104-
105-
count := map[string]uint{}
106-
defer clear(count)
107-
108-
for i := range s {
109-
count[s[i]]++
100+
if topTies > 1 {
101+
if maxCount+remain < th {
102+
return VoteResultDraw, ""
103+
}
104+
return VoteResultNotYet, ""
110105
}
111106

112-
set := make([]uint, len(count))
113-
var i int
114-
115-
for j := range count {
116-
c := count[j]
117-
keys[c] = j
118-
set[i] = c
119-
i++
107+
maxPossible := maxCount + remain
108+
if maxPossible < th {
109+
return VoteResultDraw, ""
120110
}
121-
122-
sort.Slice(set, func(i, j int) bool { return set[i] > set[j] })
123-
124-
switch index := FindMajority(quorum, th, set...); index {
125-
case -1:
126-
return VoteResultNotYet, ""
127-
case -2:
111+
if secondMaxCount+remain <= maxCount && maxPossible <= th {
128112
return VoteResultDraw, ""
129-
default:
130-
return VoteResultMajority, keys[set[index]]
131113
}
114+
115+
return VoteResultNotYet, ""
132116
}

0 commit comments

Comments
 (0)