diff --git a/src/main/java/org/rulez/demokracia/pdengine/ComputedVote.java b/src/main/java/org/rulez/demokracia/pdengine/ComputedVote.java index 90f188b4..022f0a67 100644 --- a/src/main/java/org/rulez/demokracia/pdengine/ComputedVote.java +++ b/src/main/java/org/rulez/demokracia/pdengine/ComputedVote.java @@ -68,7 +68,7 @@ private BeatTable ignoreChoices(final List ignoredChoices) { BeatTable filteredBeatTable = new BeatTable(activeChoices); for (String key1 : activeChoices) { for (String key2 : activeChoices) { - Pair source = beatTable.getElement(key1, key2); + Pair source = beatPathTable.getElement(key1, key2); if (Objects.nonNull(source)) filteredBeatTable.setElement(key1, key2, source); } diff --git a/src/main/java/org/rulez/demokracia/pdengine/Normalizable.java b/src/main/java/org/rulez/demokracia/pdengine/Normalizable.java index 31a09a16..9e10e90d 100644 --- a/src/main/java/org/rulez/demokracia/pdengine/Normalizable.java +++ b/src/main/java/org/rulez/demokracia/pdengine/Normalizable.java @@ -10,16 +10,16 @@ public interface Normalizable extends ContainingBeats { default void normalize() { Collection keys = getKeyCollection(); - + for (String key1 : keys) { for (String key2 : keys) { Pair beats1 = getPair(key1, key2); Pair beats2 = getPair(key2, key1); Pair pair = compareBeats(beats1, beats2); - - if(pair.equals(beats1)) + + if (pair.equals(beats1)) setElement(key2, key1, new Pair(0, 0)); - if(pair.equals(beats2)) + if (pair.equals(beats2)) setElement(key1, key2, new Pair(0, 0)); } } diff --git a/src/main/java/org/rulez/demokracia/pdengine/WinnerCalculatorImpl.java b/src/main/java/org/rulez/demokracia/pdengine/WinnerCalculatorImpl.java index dcccd18d..aeb11862 100644 --- a/src/main/java/org/rulez/demokracia/pdengine/WinnerCalculatorImpl.java +++ b/src/main/java/org/rulez/demokracia/pdengine/WinnerCalculatorImpl.java @@ -1,12 +1,26 @@ package org.rulez.demokracia.pdengine; import java.util.List; +import java.util.stream.Collectors; + +import org.rulez.demokracia.pdengine.dataobjects.Pair; public class WinnerCalculatorImpl implements WinnerCalculator { @Override public List calculateWinners(final BeatTable beatTable) { - throw new UnsupportedOperationException(); + return beatTable.getKeyCollection() + .stream() + .filter(choice -> isWinner(choice, beatTable)) + .collect(Collectors.toList()); + } + + private boolean isWinner(final String choice, final BeatTable beatTable) { + Pair nonbeatingPair = new Pair(0, 0); + + return beatTable.getKeyCollection() + .stream() + .allMatch(otherChoice -> nonbeatingPair.equals(beatTable.getElement(otherChoice, choice))); } } diff --git a/src/test/java/org/rulez/demokracia/pdengine/CalculateWinnersTest.java b/src/test/java/org/rulez/demokracia/pdengine/CalculateWinnersTest.java index e2587369..ad937f58 100644 --- a/src/test/java/org/rulez/demokracia/pdengine/CalculateWinnersTest.java +++ b/src/test/java/org/rulez/demokracia/pdengine/CalculateWinnersTest.java @@ -1,44 +1,34 @@ package org.rulez.demokracia.pdengine; import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; - import org.junit.Before; import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.stubbing.Answer; import org.rulez.demokracia.pdengine.annotations.TestedBehaviour; import org.rulez.demokracia.pdengine.annotations.TestedFeature; import org.rulez.demokracia.pdengine.annotations.TestedOperation; +import org.rulez.demokracia.pdengine.dataobjects.Pair; import org.rulez.demokracia.pdengine.testhelpers.CreatedDefaultCastVoteWithRankedChoices; @TestedFeature("Vote") @TestedOperation("calculate winners") public class CalculateWinnersTest extends CreatedDefaultCastVoteWithRankedChoices { - private final Answer answerKeyCollection = (invocation) -> { - BeatTable beatTable = (BeatTable) invocation.getArguments()[0]; - return beatTable.getKeyCollection().stream().collect(Collectors.toList()); - }; - private ComputedVote computedVote; - private final ArgumentCaptor captor = ArgumentCaptor.forClass(BeatTable.class); + private WinnerCalculator winnerCalculator; + private BeatTable beatPathTable; @Override @Before public void setUp() { super.setUp(); getTheVote().votesCast = castVote; - WinnerCalculatorImpl winnerCalculator = mock(WinnerCalculatorImpl.class); - when(winnerCalculator.calculateWinners(captor.capture())).thenAnswer(answerKeyCollection); computedVote = new ComputedVote(getTheVote()); computedVote.computeVote(); - computedVote.setWinnerCalculator(winnerCalculator); + winnerCalculator = new WinnerCalculatorImpl(); + beatPathTable = computedVote.getBeatPathTable(); } @TestedBehaviour("only choices not in ignoredChoices are considered") @@ -53,14 +43,40 @@ public void calculate_winners_returns_none_of_the_ignored_choices() { @Test public void calculate_winners_returns_not_ignored_winner() { List winners = computedVote.calculateWinners(Arrays.asList("C")); - assertBeatTableContainChoice(winners, "A"); + assertTrue(winners.contains("D")); + } + + @TestedBehaviour("all non-beaten candidates are winners") + @Test + public void calculate_winners_doesnt_return_beaten_candidates() { + assertNoWinnerIsBeaten(winnerCalculator.calculateWinners(beatPathTable)); } - private void assertBeatTableContainChoice(final List winners, final String choice) { - assertTrue(winners.contains(choice)); - BeatTable capturedBeatTable = captor.getValue(); - assertNotNull(capturedBeatTable.getElement(choice, "B")); + @TestedBehaviour("all non-beaten candidates are winners") + @Test + public void calculate_winners_return_all_non_beaten_candidates() { + assertNonbeatensAreWinner(winnerCalculator.calculateWinners(beatPathTable)); + } + + private void assertNoWinnerIsBeaten(final List winners) { + assertTrue(winners.stream().allMatch(choice -> isAWinner(choice, beatPathTable))); } + private void assertNonbeatensAreWinner(final List winners) { + assertTrue(beatPathTable.getKeyCollection() + .stream() + .filter(choice -> isAWinner(choice, beatPathTable)) + .allMatch(choice -> winners.contains(choice))); + } + + private boolean isAWinner(final String player1, final BeatTable beatPathTable) { + for (String player2 : beatPathTable.getKeyCollection()) { + Pair forward = beatPathTable.getElement(player1, player2); + Pair backward = beatPathTable.getElement(player2, player1); + if (!forward.equals(beatPathTable.compareBeats(forward, backward))) + return false; + } + return true; + } } diff --git a/src/test/java/org/rulez/demokracia/pdengine/UnimplementedTests.java b/src/test/java/org/rulez/demokracia/pdengine/UnimplementedTests.java index 19b12115..0e0ab92a 100644 --- a/src/test/java/org/rulez/demokracia/pdengine/UnimplementedTests.java +++ b/src/test/java/org/rulez/demokracia/pdengine/UnimplementedTests.java @@ -16,9 +16,4 @@ public class UnimplementedTests extends ThrowableTester { public void the_getAssurances_method_is_not_implemented_yet() { assertUnimplemented(() -> new CastVote("proxyId", new ArrayList<>()).getAssurances()); } - - @Test - public void the_calculateWinners_method_is_not_implemented_yet() { - assertUnimplemented(() -> new WinnerCalculatorImpl().calculateWinners(null)); - } }