From 80d91f5f23aaf506b085929eac5f2e10d7a4063b Mon Sep 17 00:00:00 2001 From: David Florness Date: Sun, 14 Feb 2021 20:42:04 -0500 Subject: [PATCH] Allow user to see results of past elections --- cmd/tallyard/main.go | 13 ++++++------- election/election.go | 1 + election/msg.go | 12 ++++++++++++ election/result.go | 27 ++++++++++----------------- ui/tui.go | 22 +++++++++++++--------- 5 files changed, 42 insertions(+), 33 deletions(-) diff --git a/cmd/tallyard/main.go b/cmd/tallyard/main.go index 442c639..4e6d0a6 100644 --- a/cmd/tallyard/main.go +++ b/cmd/tallyard/main.go @@ -111,12 +111,12 @@ func main() { if err != nil { panic(err) } - if el == nil || el.LocalVoter == nil { + if el == nil { // no election selected; user likely hit C-c return } - // wait for election to start + // wait for election to start if needed err = ui.ElectionWaitTUI(client, el, elections.EventStore) if err != nil { panic(err) @@ -128,15 +128,14 @@ func main() { // vote if we need to (user may have voted in previous tallyard // invocation) - if el.LocalVoter.Poly == nil { - candidates := el.Candidates - ballot := ui.VoteTUI(candidates) + if el.LocalVoter != nil && el.LocalVoter.Poly == nil { + ballot := ui.VoteTUI(el.Candidates) el.LocalVoter.Poly = math.NewRandomPoly(uint(len(*el.FinalJoinIDs)-1), 1024, ballot) el.Save() } // send evals if needed - if el.LocalVoter.EvalsID == nil { + if el.LocalVoter != nil && el.LocalVoter.EvalsID == nil { err = el.SendEvals(client, elections.EventStore) if err != nil { panic(err) @@ -144,7 +143,7 @@ func main() { } // send sum if needed - if el.LocalVoter.SumID == nil { + if el.LocalVoter != nil && el.LocalVoter.SumID == nil { fmt.Println("waiting for evals...") err = el.SendSum(client, elections.EventStore) if err != nil { diff --git a/election/election.go b/election/election.go index 0d90490..3b50842 100644 --- a/election/election.go +++ b/election/election.go @@ -17,6 +17,7 @@ type Election struct { FinalJoinIDs *[]id.EventID `json:"final_voters,omitempty"` Joins map[id.EventID]*Voter `json:"joins"` LocalVoter *LocalVoter `json:"local_voter,omitempty"` + Result *[]byte `json:"result,omitempty"` RoomID id.RoomID `json:"room_id"` StartID *id.EventID `json:"start_id,omitempty"` Title string `json:"title"` diff --git a/election/msg.go b/election/msg.go index 729a886..d7a5e82 100644 --- a/election/msg.go +++ b/election/msg.go @@ -503,5 +503,17 @@ func (elections *ElectionsMap) onSumMessage(evt *event.Event) (success bool) { voter.SumID = &evt.ID voter.Sum = new(big.Int).SetBytes(bytes) + // once we've recieved all sums, calculate the election result! + receivedAllSums := true + for _, voterID := range *el.FinalJoinIDs { + if el.Joins[voterID].SumID == nil { + receivedAllSums = false + break + } + } + if receivedAllSums { + el.CalculateResult() + } + return true } diff --git a/election/result.go b/election/result.go index 94f032a..e5717ad 100644 --- a/election/result.go +++ b/election/result.go @@ -4,29 +4,15 @@ import ( "fmt" "math/big" "sort" - "sync" "time" log "github.com/sirupsen/logrus" - "maunium.net/go/mautrix/id" "tallyard.xyz/math" ) -func (el *Election) PrintResults() { - var sumIDs []id.EventID - var wg sync.WaitGroup - for _, voterJoinId := range *el.FinalJoinIDs { - wg.Add(1) - go func(voter *Voter) { - for voter.SumID == nil { - time.Sleep(time.Millisecond * 100) - } - sumIDs = append(sumIDs, *voter.SumID) - wg.Done() - }(el.Joins[voterJoinId]) - } - wg.Wait() - +func (el *Election) CalculateResult() { + // this assumes all sums have been received and successfully validated + // and processed M := constructPolyMatrix(el) M.RREF() constant := M[0][len(M[0])-1] @@ -37,7 +23,14 @@ func (el *Election) PrintResults() { // number of bytes we need to insert at the front since they're zero diff := (len(el.Candidates) * len(el.Candidates)) - len(result) result = append(make([]byte, diff), result...) + el.Result = &result +} +func (el *Election) PrintResults() { + for el.Result == nil { + time.Sleep(time.Millisecond * 200) + } + result := *el.Result candidates := el.Candidates log.Debugf("result: %v", result) diff --git a/ui/tui.go b/ui/tui.go index 5b726d6..4a74c74 100644 --- a/ui/tui.go +++ b/ui/tui.go @@ -130,12 +130,16 @@ func RoomTUI(client *mautrix.Client, roomID id.RoomID, elections *election.Elect el = L[i - 1] // don't need to lock because this goroutine controls LocalVoter if el.LocalVoter == nil { - // ask user if s/he wants to join election - if joinElectionConfirmation(el) { - err = el.JoinElection(client, elections.EventStore) - } else { - // user needs to select a different election + // ask user if s/he wants to join election (or + // display results if it's already started) + if !electionConfirmation(el) { + // user needs to select a different + // election el, err = RoomTUI(client, roomID, elections) + } else if el.StartID == nil { + // user selected yes on joining the + // election + err = el.JoinElection(client, elections.EventStore) } } return @@ -162,7 +166,7 @@ func RoomTUI(client *mautrix.Client, roomID id.RoomID, elections *election.Elect return } -func joinElectionConfirmation(el *election.Election) (shouldJoin bool) { +func electionConfirmation(el *election.Election) (shouldJoin bool) { app := newTallyardApplication() var buttons []string @@ -171,8 +175,8 @@ func joinElectionConfirmation(el *election.Election) (shouldJoin bool) { el.RLock() // TODO: handle when election starts while in modal if el.StartID != nil { - buttons = []string{"Ok"} - text = "Election has already started, sorry" + buttons = []string{"Yes", "No"} + text = "Election has already started; display results?" } else { buttons = []string{"Yes", "No"} text = "Join election?" @@ -250,7 +254,7 @@ func ElectionWaitTUI(client *mautrix.Client, el *election.Election, eventStore * frame.SetTitle(el.Title).SetBorder(true) app := newTallyardApplication() el.RLock() - if el.CreateEvt.Sender == el.LocalVoter.JoinEvt.Sender { + if el.LocalVoter != nil && el.CreateEvt.Sender == el.LocalVoter.JoinEvt.Sender { frame.AddText("Press enter to start the election", false, tview.AlignCenter, tcell.ColorWhite) app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { if event.Key() == tcell.KeyEnter { -- 2.38.4