From dfd160919c4166ff9f5c4d17f132fa843f620bd9 Mon Sep 17 00:00:00 2001 From: "marcins78@gmail.com" Date: Mon, 31 Dec 2012 22:07:46 +0000 Subject: [PATCH] Testing of DefaultTournament and SingleEliminationPairing. --- .../com/gempukku/lotro/hall/HallServer.java | 8 +- .../lotro/tournament/DefaultTournament.java | 21 +- .../lotro/tournament/PairingMechanism.java | 2 +- .../tournament/SingleEliminationPairing.java | 41 +++- .../SingleEliminationRecurringQueue.java | 4 +- .../gempukku/lotro/tournament/Tournament.java | 2 +- .../lotro/tournament/TournamentCallback.java | 4 +- .../tournament/DefaultTournamentTest.java | 188 ++++++++++++++++++ .../SingleEliminationPairingTest.java | 124 ++++++++++++ 9 files changed, 372 insertions(+), 22 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/tournament/DefaultTournamentTest.java create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/tournament/SingleEliminationPairingTest.java diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java index 33c0f707d..f602ec3f6 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java @@ -531,10 +531,10 @@ public class HallServer extends AbstractServer { } @Override - public void createGame(LotroGameParticipant playerOne, LotroGameParticipant playerTwo, boolean allowSpectators) { + public void createGame(String playerOne, LotroDeck deckOne, String playerTwo, LotroDeck deckTwo, boolean allowSpectators) { final LotroGameParticipant[] participants = new LotroGameParticipant[2]; - participants[0] = playerOne; - participants[1] = playerTwo; + participants[0] = new LotroGameParticipant(playerOne, deckOne); + participants[1] = new LotroGameParticipant(playerTwo, deckTwo); createGameInternal(participants, allowSpectators); } @@ -546,7 +546,7 @@ public class HallServer extends AbstractServer { new GameResultListener() { @Override public void gameFinished(String winnerPlayerId, String winReason, Map loserPlayerIdsWithReasons) { - _tournament.reportGameFinished(HallTournamentCallback.this, winnerPlayerId, loserPlayerIdsWithReasons.keySet().iterator().next()); + _tournament.reportGameFinished(winnerPlayerId, loserPlayerIdsWithReasons.keySet().iterator().next()); } @Override diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/DefaultTournament.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/DefaultTournament.java index 7a5d15300..4bb60cef6 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/DefaultTournament.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/DefaultTournament.java @@ -9,7 +9,6 @@ import com.gempukku.lotro.draft.Draft; import com.gempukku.lotro.draft.DraftCardChoice; import com.gempukku.lotro.draft.DraftPack; import com.gempukku.lotro.game.DeckInvalidException; -import com.gempukku.lotro.game.LotroGameParticipant; import com.gempukku.lotro.logic.vo.LotroDeck; import com.gempukku.lotro.packs.PacksStorage; @@ -19,8 +18,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; public class DefaultTournament implements Tournament { // 10 minutes - public static final int DECK_BUILD_TIME = 10 * 60 * 1000; - private static final long _waitForPairingsTime = 1000 * 60 * 2; + private int _deckBuildTime = 10 * 60 * 1000; + private long _waitForPairingsTime = 1000 * 60 * 2; private PairingMechanism _pairingMechanism; private String _tournamentId; @@ -90,6 +89,10 @@ public class DefaultTournament implements Tournament { } } + public void setWaitForPairingsTime(long waitForPairingsTime) { + _waitForPairingsTime = waitForPairingsTime; + } + @Override public String getTournamentId() { return _tournamentId; @@ -131,7 +134,7 @@ public class DefaultTournament implements Tournament { } @Override - public void reportGameFinished(TournamentCallback tournamentCallback, String winner, String loser) { + public void reportGameFinished(String winner, String loser) { _lock.writeLock().lock(); try { if (_tournamentStage == Stage.PLAYING_GAMES && _currentlyPlayingPlayers.contains(winner) @@ -221,7 +224,7 @@ public class DefaultTournament implements Tournament { } } if (_tournamentStage == Stage.DECK_BUILDING) { - if (_deckBuildStartTime + DECK_BUILD_TIME < System.currentTimeMillis() + if (_deckBuildStartTime + _deckBuildTime < System.currentTimeMillis() || _playerDecks.size() == _players.size()) { _tournamentStage = Stage.PLAYING_GAMES; _tournamentService.updateTournamentStage(_tournamentId, _tournamentStage); @@ -232,7 +235,7 @@ public class DefaultTournament implements Tournament { if (_pairingMechanism.isFinished(_tournamentRound, _players, _droppedPlayers)) { finishTournament(tournamentCallback); } else { - tournamentCallback.broadcastMessage("Tournament " + _tournamentName + " will start next round in 2 minutes"); + tournamentCallback.broadcastMessage("Tournament " + _tournamentName + " will start round "+(_tournamentRound+1)+" in 2 minutes"); _nextTask = new PairPlayers(); } } @@ -275,8 +278,8 @@ public class DefaultTournament implements Tournament { private void createNewGame(TournamentCallback tournamentCallback, String playerOne, String playerTwo, boolean allowSpectators) { - tournamentCallback.createGame(new LotroGameParticipant(playerOne, _playerDecks.get(playerOne)), - new LotroGameParticipant(playerTwo, _playerDecks.get(playerTwo)), allowSpectators); + tournamentCallback.createGame(playerOne, _playerDecks.get(playerOne), + playerTwo, _playerDecks.get(playerTwo), allowSpectators); } private void doPairing(TournamentCallback tournamentCallback) { @@ -284,7 +287,7 @@ public class DefaultTournament implements Tournament { _tournamentService.updateTournamentRound(_tournamentId, _tournamentRound); Map pairingResults = new HashMap(); Set byeResults = new HashSet(); - boolean finished = _pairingMechanism.pairPlayers(_tournamentRound, _players, _droppedPlayers, getCurrentStandings(), pairingResults, byeResults); + boolean finished = _pairingMechanism.pairPlayers(_tournamentRound, _players, _droppedPlayers, _playerByes, getCurrentStandings(), pairingResults, byeResults); if (finished) { finishTournament(tournamentCallback); } else { diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/PairingMechanism.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/PairingMechanism.java index 7b011df65..8bb6e50a2 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/PairingMechanism.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/PairingMechanism.java @@ -11,5 +11,5 @@ public interface PairingMechanism { public boolean isFinished(int round, Set players, Set droppedPlayers); - public boolean pairPlayers(int round, Set players, Set droppedPlayers, List currentStandings, Map pairingResults, Set byeResults); + public boolean pairPlayers(int round, Set players, Set droppedPlayers, Map playerByes, List currentStandings, Map pairingResults, Set byeResults); } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SingleEliminationPairing.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SingleEliminationPairing.java index 264cb19b0..5f3b1189e 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SingleEliminationPairing.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SingleEliminationPairing.java @@ -11,15 +11,50 @@ public class SingleEliminationPairing implements PairingMechanism { } @Override - public boolean pairPlayers(int round, Set players, Set droppedPlayers, List currentStandings, Map pairingResults, Set byeResults) { + public boolean pairPlayers(int round, Set players, Set droppedPlayers, Map playerByes, List currentStandings, Map pairingResults, Set byeResults) { if (isFinished(round, players, droppedPlayers)) return true; Set playersInContention = new HashSet(players); playersInContention.removeAll(droppedPlayers); - List playersRandomized = new ArrayList(playersInContention); - Collections.shuffle(playersRandomized); + int maxByes = 0; + for (Map.Entry playerByeCount : playerByes.entrySet()) { + String player = playerByeCount.getKey(); + if (playersInContention.contains(player)) + maxByes = Math.max(maxByes, playerByeCount.getValue()); + } + + List[] playersGroupedByByes = new List[maxByes+1]; + for (Map.Entry playerByeCount : playerByes.entrySet()) { + String player = playerByeCount.getKey(); + if (playersInContention.contains(player)) { + int count = playerByeCount.getValue(); + List playersWithThisNumberOfByes = playersGroupedByByes[maxByes - count]; + if (playersWithThisNumberOfByes == null) { + playersWithThisNumberOfByes = new ArrayList(); + playersGroupedByByes[maxByes - count] = playersWithThisNumberOfByes; + } + playersWithThisNumberOfByes.add(player); + playersInContention.remove(player); + } + } + + List playersWithNoByes = playersGroupedByByes[maxByes]; + if (playersWithNoByes == null) { + playersWithNoByes = new ArrayList(); + playersGroupedByByes[maxByes] = playersWithNoByes; + } + playersWithNoByes.addAll(playersInContention); + + List playersRandomized = new ArrayList(); + + for (List playersGroupedByBye : playersGroupedByByes) { + if (playersGroupedByBye != null) { + Collections.shuffle(playersGroupedByBye); + playersRandomized.addAll(playersGroupedByBye); + } + } Iterator playerIterator = playersRandomized.iterator(); while (playerIterator.hasNext()) { diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SingleEliminationRecurringQueue.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SingleEliminationRecurringQueue.java index b94d7b9f7..6d47468de 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SingleEliminationRecurringQueue.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SingleEliminationRecurringQueue.java @@ -15,7 +15,7 @@ public class SingleEliminationRecurringQueue implements TournamentQueue { private String _tournamentQueueName; private CollectionType _currencyCollection = CollectionType.MY_CARDS; - private Set _players = new HashSet(); + private List _players = new ArrayList(); private Map _playerDecks = new HashMap(); private int _playerCap; @@ -63,7 +63,7 @@ public class SingleEliminationRecurringQueue implements TournamentQueue { @Override public synchronized boolean process(TournamentQueueCallback tournamentQueueCallback) { - if (_players.size() == _playerCap) { + if (_players.size() >= _playerCap) { String tournamentId = _tournamentIdPrefix + System.currentTimeMillis(); String tournamentName = _tournamentQueueName + " - " + DateUtils.getStringDateWithHour(); diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/Tournament.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/Tournament.java index 4c0efa14b..024dd3535 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/Tournament.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/Tournament.java @@ -33,7 +33,7 @@ public interface Tournament { public void advanceTournament(TournamentCallback tournamentCallback); - public void reportGameFinished(TournamentCallback tournamentCallback, String winner, String loser); + public void reportGameFinished(String winner, String loser); public void playerChosenCard(String playerName, String cardId); public void playerSummittedDeck(String player, LotroDeck deck) throws DeckInvalidException; diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/TournamentCallback.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/TournamentCallback.java index e73c63346..78fb32654 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/TournamentCallback.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/TournamentCallback.java @@ -1,9 +1,9 @@ package com.gempukku.lotro.tournament; -import com.gempukku.lotro.game.LotroGameParticipant; +import com.gempukku.lotro.logic.vo.LotroDeck; public interface TournamentCallback { - public void createGame(LotroGameParticipant playerOne, LotroGameParticipant playerTwo, boolean allowSpectators); + public void createGame(String playerOne, LotroDeck deckOne, String playerTwo, LotroDeck deckTwo, boolean allowSpectators); public void broadcastMessage(String message); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/tournament/DefaultTournamentTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/tournament/DefaultTournamentTest.java new file mode 100644 index 000000000..620cd3073 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/tournament/DefaultTournamentTest.java @@ -0,0 +1,188 @@ +package com.gempukku.lotro.tournament; + +import com.gempukku.lotro.competitive.PlayerStanding; +import com.gempukku.lotro.db.vo.CollectionType; +import com.gempukku.lotro.logic.vo.LotroDeck; +import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.internal.verification.Times; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.util.*; + +public class DefaultTournamentTest { + private int _waitForPairingsTime = 100; + + @Test + public void testTournament() throws InterruptedException { + TournamentService tournamentService = Mockito.mock(TournamentService.class); + String tournamentId = "t1"; + Map playerDecks = new HashMap(); + Set allPlayers = new HashSet(Arrays.asList("p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8")); + playerDecks.put("p1", new LotroDeck("p1")); + playerDecks.put("p2", new LotroDeck("p2")); + playerDecks.put("p3", new LotroDeck("p3")); + playerDecks.put("p4", new LotroDeck("p4")); + playerDecks.put("p5", new LotroDeck("p5")); + playerDecks.put("p6", new LotroDeck("p6")); + playerDecks.put("p7", new LotroDeck("p7")); + playerDecks.put("p8", new LotroDeck("p8")); + + Set droppedAfterRoundOne = new HashSet(Arrays.asList("p2", "p4", "p6", "p8")); + Set droppedAfterRoundTwo = new HashSet(Arrays.asList("p2", "p3", "p4", "p6", "p7", "p8")); + Set droppedAfterRoundThree = new HashSet(Arrays.asList("p2", "p3", "p4", "p5", "p6", "p7", "p8")); + + Mockito.when(tournamentService.getPlayers(tournamentId)).thenReturn(allPlayers); + Mockito.when(tournamentService.getPlayerDecks(tournamentId)).thenReturn(playerDecks); + + PairingMechanism pairingMechanism = Mockito.mock(PairingMechanism.class); + Mockito.when(pairingMechanism.shouldDropLoser()).thenReturn(true); + + DefaultTournament tournament = new DefaultTournament(null, tournamentService, null, null, tournamentId, "Name", "format", + CollectionType.ALL_CARDS, 0, Tournament.Stage.PLAYING_GAMES, pairingMechanism); + tournament.setWaitForPairingsTime(_waitForPairingsTime); + + Mockito.when(pairingMechanism.isFinished(Mockito.eq(3), Mockito.eq(allPlayers), Mockito.eq(droppedAfterRoundThree))) + .thenReturn(true); + + Mockito.when(pairingMechanism.pairPlayers(Mockito.eq(1), Mockito.eq(allPlayers), Mockito.eq(Collections.emptySet()), + Mockito.eq(Collections.emptyMap()), Mockito.>any(), + Mockito.eq(Collections.emptyMap()), Mockito.eq(Collections.emptySet()))).then( + new Answer() { + @Override + public Boolean answer(InvocationOnMock invocationOnMock) throws Throwable { + Map pairings = (Map) invocationOnMock.getArguments()[5]; + pairings.put("p1", "p2"); + pairings.put("p3", "p4"); + pairings.put("p5", "p6"); + pairings.put("p7", "p8"); + + return false; + } + }); + Mockito.when(pairingMechanism.pairPlayers(Mockito.eq(2), Mockito.eq(allPlayers), Mockito.eq(droppedAfterRoundOne), + Mockito.eq(Collections.emptyMap()), Mockito.>any(), + Mockito.eq(Collections.emptyMap()), Mockito.eq(Collections.emptySet()))).then( + new Answer() { + @Override + public Boolean answer(InvocationOnMock invocationOnMock) throws Throwable { + Map pairings = (Map) invocationOnMock.getArguments()[5]; + pairings.put("p1", "p3"); + pairings.put("p5", "p7"); + + return false; + } + }); + Mockito.when(pairingMechanism.pairPlayers(Mockito.eq(3), Mockito.eq(allPlayers), Mockito.eq(droppedAfterRoundTwo), + Mockito.eq(Collections.emptyMap()), Mockito.>any(), + Mockito.eq(Collections.emptyMap()), Mockito.eq(Collections.emptySet()))).then( + new Answer() { + @Override + public Boolean answer(InvocationOnMock invocationOnMock) throws Throwable { + Map pairings = (Map) invocationOnMock.getArguments()[5]; + pairings.put("p1", "p5"); + + return false; + } + }); + + TournamentCallback tournamentCallback = Mockito.mock(TournamentCallback.class); + Mockito.doAnswer( + new Answer() { + @Override + public Void answer(InvocationOnMock invocationOnMock) throws Throwable { + System.out.println("Broadcasted: "+invocationOnMock.getArguments()[0]); + return null; + } + } + ).when(tournamentCallback).broadcastMessage(Mockito.anyString()); + + tournament.advanceTournament(tournamentCallback); + + Mockito.verify(tournamentCallback).broadcastMessage(Mockito.anyString()); + Mockito.verifyNoMoreInteractions(tournamentCallback); + + Thread.sleep(_waitForPairingsTime); + tournament.advanceTournament(tournamentCallback); + + Mockito.verify(tournamentCallback, new Times(1)).createGame("p1", playerDecks.get("p1"), "p2", playerDecks.get("p2"), false); + Mockito.verify(tournamentCallback, new Times(1)).createGame("p3", playerDecks.get("p3"), "p4", playerDecks.get("p4"), false); + Mockito.verify(tournamentCallback, new Times(1)).createGame("p5", playerDecks.get("p5"), "p6", playerDecks.get("p6"), false); + Mockito.verify(tournamentCallback, new Times(1)).createGame("p7", playerDecks.get("p7"), "p8", playerDecks.get("p8"), false); + + Mockito.verifyNoMoreInteractions(tournamentCallback); + + assertEquals(1, tournament.getCurrentRound()); + + tournament.advanceTournament(tournamentCallback); + Mockito.verifyNoMoreInteractions(tournamentCallback); + + tournament.reportGameFinished("p1", "p2"); + + tournament.advanceTournament(tournamentCallback); + Mockito.verifyNoMoreInteractions(tournamentCallback); + + tournament.reportGameFinished("p3", "p4"); + + tournament.advanceTournament(tournamentCallback); + Mockito.verifyNoMoreInteractions(tournamentCallback); + + tournament.reportGameFinished("p5", "p6"); + + tournament.advanceTournament(tournamentCallback); + Mockito.verifyNoMoreInteractions(tournamentCallback); + + tournament.reportGameFinished("p7", "p8"); + + tournament.advanceTournament(tournamentCallback); + Mockito.verify(tournamentCallback, new Times(2)).broadcastMessage(Mockito.anyString()); + Mockito.verifyNoMoreInteractions(tournamentCallback); + + Thread.sleep(_waitForPairingsTime); + tournament.advanceTournament(tournamentCallback); + + Mockito.verify(tournamentCallback, new Times(1)).createGame("p1", playerDecks.get("p1"), "p3", playerDecks.get("p3"), false); + Mockito.verify(tournamentCallback, new Times(1)).createGame("p5", playerDecks.get("p5"), "p7", playerDecks.get("p7"), false); + + Mockito.verifyNoMoreInteractions(tournamentCallback); + + assertEquals(2, tournament.getCurrentRound()); + + tournament.advanceTournament(tournamentCallback); + Mockito.verifyNoMoreInteractions(tournamentCallback); + + tournament.reportGameFinished("p1", "p3"); + + tournament.advanceTournament(tournamentCallback); + Mockito.verifyNoMoreInteractions(tournamentCallback); + + tournament.reportGameFinished("p5", "p7"); + + tournament.advanceTournament(tournamentCallback); + Mockito.verify(tournamentCallback, new Times(3)).broadcastMessage(Mockito.anyString()); + Mockito.verifyNoMoreInteractions(tournamentCallback); + + Thread.sleep(_waitForPairingsTime); + tournament.advanceTournament(tournamentCallback); + + Mockito.verify(tournamentCallback, new Times(1)).createGame("p1", playerDecks.get("p1"), "p5", playerDecks.get("p5"), false); + + Mockito.verifyNoMoreInteractions(tournamentCallback); + + assertEquals(3, tournament.getCurrentRound()); + + tournament.advanceTournament(tournamentCallback); + Mockito.verifyNoMoreInteractions(tournamentCallback); + + tournament.reportGameFinished("p1", "p5"); + + tournament.advanceTournament(tournamentCallback); + Mockito.verify(tournamentCallback, new Times(4)).broadcastMessage(Mockito.anyString()); + Mockito.verifyNoMoreInteractions(tournamentCallback); + + assertEquals(3, tournament.getCurrentRound()); + assertEquals(Tournament.Stage.FINISHED, tournament.getTournamentStage()); + } +} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/tournament/SingleEliminationPairingTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/tournament/SingleEliminationPairingTest.java new file mode 100644 index 000000000..f1d8d9cb4 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/tournament/SingleEliminationPairingTest.java @@ -0,0 +1,124 @@ +package com.gempukku.lotro.tournament; + +import static org.junit.Assert.*; +import org.junit.Test; + +import java.util.*; + +public class SingleEliminationPairingTest { + private SingleEliminationPairing _pairing = new SingleEliminationPairing(); + + @Test + public void correctlyDetectsFinishedTournament() { + Set allPlayers = new HashSet(Arrays.asList("p1", "p2", "p3", "p4")); + Set playersWithoutFirst = new HashSet(Arrays.asList("p2", "p3", "p4")); + Set playersWithoutTwo = new HashSet(Arrays.asList("p3", "p4")); + Set playersWithoutThree = new HashSet(Arrays.asList("p4")); + + assertTrue(_pairing.isFinished(1, allPlayers, allPlayers)); + assertTrue(_pairing.isFinished(1, allPlayers, playersWithoutFirst)); + assertFalse(_pairing.isFinished(1, allPlayers, playersWithoutTwo)); + assertFalse(_pairing.isFinished(1, allPlayers, playersWithoutThree)); + assertFalse(_pairing.isFinished(1, allPlayers, Collections.emptySet())); + } + + @Test + public void shouldDropLoser() { + assertTrue(_pairing.shouldDropLoser()); + } + + @Test + public void pairingDoneCorrectlyForEvenNumberOfPlayers() { + Set allPlayers = new HashSet(Arrays.asList("p1", "p2", "p3", "p4")); + + Map pairingResults = new HashMap(); + Set byeResults = new HashSet(); + + assertFalse(_pairing.pairPlayers(1, allPlayers, Collections.emptySet(), Collections.emptyMap(), null, pairingResults, byeResults)); + + assertEquals(0, byeResults.size()); + assertEquals(2, pairingResults.size()); + + Set pairedPlayers = new HashSet(); + for (Map.Entry pairing : pairingResults.entrySet()) { + pairedPlayers.add(pairing.getKey()); + pairedPlayers.add(pairing.getValue()); + } + + assertEquals(4, pairedPlayers.size()); + } + + @Test + public void pairingDoneCorrectlyForOddNumberOfPlayers() { + Set allPlayers = new HashSet(Arrays.asList("p1", "p2", "p3")); + + Map pairingResults = new HashMap(); + Set byeResults = new HashSet(); + + assertFalse(_pairing.pairPlayers(1, allPlayers, Collections.emptySet(), Collections.emptyMap(), null, pairingResults, byeResults)); + + assertEquals(1, byeResults.size()); + assertEquals(1, pairingResults.size()); + + Set pairedPlayers = new HashSet(); + pairedPlayers.addAll(byeResults); + for (Map.Entry pairing : pairingResults.entrySet()) { + pairedPlayers.add(pairing.getKey()); + pairedPlayers.add(pairing.getValue()); + } + + assertEquals(3, pairedPlayers.size()); + } + + @Test + public void playerWithLowestNumberOfByesGetsIt() { + Set allPlayers = new HashSet(Arrays.asList("p1", "p2", "p3")); + + Map pairingResults = new HashMap(); + Set byeResults = new HashSet(); + + Map playerByes = new HashMap(); + playerByes.put("p1", 1); + playerByes.put("p2", 2); + playerByes.put("p3", 3); + + assertFalse(_pairing.pairPlayers(1, allPlayers, Collections.emptySet(), playerByes, null, pairingResults, byeResults)); + + assertEquals(1, byeResults.size()); + assertTrue(byeResults.contains("p1")); + assertEquals(1, pairingResults.size()); + + Set pairedPlayers = new HashSet(); + pairedPlayers.addAll(byeResults); + + for (Map.Entry pairing : pairingResults.entrySet()) { + pairedPlayers.add(pairing.getKey()); + pairedPlayers.add(pairing.getValue()); + } + + assertEquals(3, pairedPlayers.size()); + } + + @Test + public void droppedPlayersNotIncluded() { + Set allPlayers = new HashSet(Arrays.asList("p1", "p2", "p3", "p4")); + Set droppedPlayers = new HashSet(Arrays.asList("p4")); + + Map pairingResults = new HashMap(); + Set byeResults = new HashSet(); + + assertFalse(_pairing.pairPlayers(1, allPlayers, droppedPlayers, Collections.emptyMap(), null, pairingResults, byeResults)); + + assertEquals(1, byeResults.size()); + assertEquals(1, pairingResults.size()); + + Set pairedPlayers = new HashSet(); + pairedPlayers.addAll(byeResults); + for (Map.Entry pairing : pairingResults.entrySet()) { + pairedPlayers.add(pairing.getKey()); + pairedPlayers.add(pairing.getValue()); + } + + assertEquals(3, pairedPlayers.size()); + } +}