diff --git a/judgment/majorityjudgment.go b/judgment/majorityjudgment.go index 282c84b..502e809 100644 --- a/judgment/majorityjudgment.go +++ b/judgment/majorityjudgment.go @@ -36,10 +36,14 @@ func (mj *MajorityJudgment) Deliberate(tally *PollTally) (_ *PollResult, err err } amountOfJudges := tally.AmountOfJudges + if 0 == amountOfJudges { + amountOfJudges = tally.GuessAmountOfJudges() + } if amountOfJudges < maximumAmountOfJudgments { return nil, fmt.Errorf("incoherent tally: " + "some proposals hold more judgments than the specified amount of judges ; " + - "perhaps you forgot to set PollTally.AmountOfJudges") + "perhaps you forgot to set PollTally.AmountOfJudges " + + "or to call PollTally.GuessAmountOfJudges()") } for proposalIndex, proposalTally := range tally.Proposals { diff --git a/judgment/majorityjudgment_test.go b/judgment/majorityjudgment_test.go index 9adda10..afe2a0b 100644 --- a/judgment/majorityjudgment_test.go +++ b/judgment/majorityjudgment_test.go @@ -95,6 +95,40 @@ func TestReadmeDemo(t *testing.T) { } +func TestGuessingAmountOfJudges(t *testing.T) { + poll := &PollTally{ + Proposals: []*ProposalTally{ + {Tally: []uint64{2, 2, 2, 2, 2}}, + {Tally: []uint64{2, 1, 1, 1, 5}}, + {Tally: []uint64{2, 1, 1, 2, 4}}, + {Tally: []uint64{2, 1, 5, 0, 2}}, + {Tally: []uint64{2, 2, 2, 2, 2}}, + }, + } + deliberator := &MajorityJudgment{} + result, err := deliberator.Deliberate(poll) + assert.NoError(t, err, "Deliberation should succeed") + assert.Len(t, result.Proposals, len(poll.Proposals), "There should be as many results as there are tallies.") + assert.Equal(t, 4, result.Proposals[0].Rank, "Rank of proposal A") + assert.Equal(t, 1, result.Proposals[1].Rank, "Rank of proposal B") + assert.Equal(t, 2, result.Proposals[2].Rank, "Rank of proposal C") + assert.Equal(t, 3, result.Proposals[3].Rank, "Rank of proposal D") + assert.Equal(t, 4, result.Proposals[4].Rank, "Rank of proposal E") + + assert.Equal(t, 1, result.ProposalsSorted[0].Rank, "Rank of sorted proposal A") + assert.Equal(t, 2, result.ProposalsSorted[1].Rank, "Rank of sorted proposal 1") + assert.Equal(t, 3, result.ProposalsSorted[2].Rank, "Rank of sorted proposal 2") + assert.Equal(t, 4, result.ProposalsSorted[3].Rank, "Rank of sorted proposal 3") + assert.Equal(t, 4, result.ProposalsSorted[4].Rank, "Rank of sorted proposal 4") + + assert.Equal(t, 1, result.ProposalsSorted[0].Index, "Index of sorted proposal A") + assert.Equal(t, 2, result.ProposalsSorted[1].Index, "Index of sorted proposal 1") + assert.Equal(t, 3, result.ProposalsSorted[2].Index, "Index of sorted proposal 2") + assert.Equal(t, 0, result.ProposalsSorted[3].Index, "Index of sorted proposal 3") + assert.Equal(t, 4, result.ProposalsSorted[4].Index, "Index of sorted proposal 4") + +} + func TestNoProposals(t *testing.T) { poll := &PollTally{ AmountOfJudges: 0, diff --git a/judgment/tally.go b/judgment/tally.go index 488688b..326d65b 100644 --- a/judgment/tally.go +++ b/judgment/tally.go @@ -1,6 +1,8 @@ package judgment -import "fmt" +import ( + "fmt" +) // PollTally describes the amount of judgments received by each proposal on each grade. type PollTally struct { @@ -8,6 +10,18 @@ type PollTally struct { Proposals []*ProposalTally // Tallies of each proposal. Its order is preserved in the result. } +// GuessAmountOfJudges also mutates the PollTally by filling the AmountOfJudges property +func (pollTally *PollTally) GuessAmountOfJudges() (_ uint64) { + pollTally.AmountOfJudges = 0 + for _, proposalTally := range pollTally.Proposals { + amountOfJudges := proposalTally.CountJudgments() + if pollTally.AmountOfJudges < amountOfJudges { + pollTally.AmountOfJudges = amountOfJudges + } + } + return pollTally.AmountOfJudges +} + // BalanceWithStaticDefault mutates the PollTally func (pollTally *PollTally) BalanceWithStaticDefault(defaultGrade uint8) (err error) { for _, proposalTally := range pollTally.Proposals {