-
Notifications
You must be signed in to change notification settings - Fork 0
/
protocol.go
111 lines (97 loc) · 2.56 KB
/
protocol.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
111
package protocol
import (
"github.com/google/uuid"
log "github.com/sirupsen/logrus"
)
// Consumed by cmd/serve.go
var ProtocolCommandMap = map[string]Protocol{
"simpleMajority": new(SimpleMajority),
}
type Candidate struct {
Name string
}
type Vote struct {
Value float64
Candidate Candidate
}
type Election struct {
Id string
Name string
Candidates []Candidate
Votes []Vote
Totals map[string]float64 // Candidate name to their total
}
type Protocol interface {
Init([]Candidate)
Cast(Vote) // Cast a vote
Tally() // Compute the candidate's totals
Result() ([]string, float64) // Get the final result(s)
Display() // Print the current totals
GetId() string // Get the id of the election
ValidateVote(Vote) bool // Return if a cast vote is valid
}
type SimpleMajority struct {
Election
}
func (election *SimpleMajority) Init(candidates []Candidate) {
election.Votes = make([]Vote, 0)
election.Totals = make(map[string]float64)
election.Candidates = candidates
election.Name = "Simple Majority"
id, _ := uuid.NewRandom()
election.Id = id.String()
log.Info("Election initialized.")
election.Display()
}
func (election *SimpleMajority) Cast(vote Vote) {
election.Votes = append(election.Votes, vote)
log.WithFields(log.Fields{
"candidate": vote.Candidate,
"value": vote.Value,
}).Info("Ballot cast")
}
func (election *SimpleMajority) Result() ([]string, float64) {
election.Tally()
var winners []string
max := 0.0
for candidateName, total := range election.Totals {
if total > max {
winners = []string{candidateName}
max = total
} else if total == max {
winners = append(winners, candidateName)
}
}
return winners, max
}
func (election *SimpleMajority) Tally() {
election.Totals = make(map[string]float64)
for _, vote := range election.Votes {
if _, exists := election.Totals[vote.Candidate.Name]; exists {
election.Totals[vote.Candidate.Name] += vote.Value
} else {
election.Totals[vote.Candidate.Name] = vote.Value
}
}
}
func (election *SimpleMajority) Display() {
log.WithFields(log.Fields{
"id": election.Id,
"name": election.Name,
"candidates": election.Candidates,
"totals": election.Totals,
}).Info()
}
func (election *SimpleMajority) GetId() string {
return election.Id
}
func (election *SimpleMajority) ValidateVote(vote Vote) bool {
if vote.Value == 1 {
for _, candidate := range election.Candidates {
if vote.Candidate.Name == candidate.Name {
return true
}
}
}
return false
}