package com.flexpoker.game.command.aggregate; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; import org.junit.Test; import com.flexpoker.game.command.events.GameCreatedEvent; import com.flexpoker.game.command.events.GameTablesCreatedAndPlayersAssociatedEvent; import com.flexpoker.game.command.framework.GameEvent; public class TableAssignmentTest { @Test public void testAssignmentIsRandom() { boolean player1AlwaysWithPlayer2 = true; boolean player1SometimesWithPlayer2 = false; for (int i = 0; i < 1000; i++) { List<GameEvent> events = new ArrayList<>(); events.add(new GameCreatedEvent(UUID.randomUUID(), 1, "test", 4, 2, UUID.randomUUID(), 10)); Game game = new DefaultGameFactory().createFrom(events); // create a bunch of static UUIDs that will hash the same and will // thus be transformed into the same list before shuffling occurs // (and will fail the test without the shuffle(). // this gets rid of the randomizing effect of using a HashSet with // random/on-the-fly UUIDs, which isn't good when remain attached to // players over periods of time UUID player1Id = UUID.fromString("07755923-95b4-4ae7-9f45-b67a8e7929fe"); UUID player2Id = UUID.fromString("07755923-95b4-4ae7-9f45-b67a8e7929ff"); UUID player3Id = UUID.fromString("17755923-95b4-4ae7-9f45-b67a8e7929fe"); UUID player4Id = UUID.fromString("17755923-95b4-4ae7-9f45-b67a8e7929ff"); game.joinGame(player1Id); game.joinGame(player2Id); game.joinGame(player3Id); game.joinGame(player4Id); GameTablesCreatedAndPlayersAssociatedEvent event = (GameTablesCreatedAndPlayersAssociatedEvent) game .fetchAppliedEvents().get(6); Map<UUID, Set<UUID>> tableIdToPlayerIdsMap = event .getTableIdToPlayerIdsMap(); Set<UUID> player1sTable = tableIdToPlayerIdsMap.values().stream() .filter(y -> y.contains(player1Id)).findAny().get(); if (player1sTable.contains(player2Id)) { player1SometimesWithPlayer2 = true; } else { player1AlwaysWithPlayer2 = false; } } assertFalse(player1AlwaysWithPlayer2); assertTrue(player1SometimesWithPlayer2); } @Test public void testTwoPlayersOneTable() { Game game = createGameAndJoinAllPlayers(2, 2); verifyTableDistribution(game, 2); } @Test public void testFourFitsAllInOneTable() { Game game = createGameAndJoinAllPlayers(4, 9); verifyTableDistribution(game, 4); } @Test public void testFourFitsAllInASmallerTable() { Game game = createGameAndJoinAllPlayers(4, 6); verifyTableDistribution(game, 4); } @Test public void testFourFitsPerfectlyInOneTable() { Game game = createGameAndJoinAllPlayers(4, 4); verifyTableDistribution(game, 4); } @Test public void testFourFitsEvenlyInTwoTables() { Game game = createGameAndJoinAllPlayers(4, 3); verifyTableDistribution(game, 2, 2); } @Test public void testTwentyFitsUnevenlyOverThreeTables() { Game game = createGameAndJoinAllPlayers(20, 9); verifyTableDistribution(game, 6, 7, 7); } @Test public void testTwentyFitsFourEvenTablesNoneFull() { Game game = createGameAndJoinAllPlayers(20, 6); verifyTableDistribution(game, 5, 5, 5, 5); } @Test public void testTwentyFitsFiveEvenTablesAllFull() { Game game = createGameAndJoinAllPlayers(20, 4); verifyTableDistribution(game, 4, 4, 4, 4, 4); } @Test public void testTwentyFitsSevenTablesUnevenly() { Game game = createGameAndJoinAllPlayers(20, 3); verifyTableDistribution(game, 2, 3, 3, 3, 3, 3, 3); } @Test public void testTwentyFitsTenTablesEvenly() { Game game = createGameAndJoinAllPlayers(20, 2); verifyTableDistribution(game, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); } @Test public void testTwoFitsOneTable1() { Game game = createGameAndJoinAllPlayers(2, 9); verifyTableDistribution(game, 2); } @Test public void testTwoFitsOneTable2() { Game game = createGameAndJoinAllPlayers(2, 6); verifyTableDistribution(game, 2); } @Test public void testTwoFitsOneTable3() { Game game = createGameAndJoinAllPlayers(2, 4); verifyTableDistribution(game, 2); } @Test public void testTwoFitsOneTable4() { Game game = createGameAndJoinAllPlayers(2, 3); verifyTableDistribution(game, 2); } @Test public void testTwoFitsOneTable5() { Game game = createGameAndJoinAllPlayers(2, 2); verifyTableDistribution(game, 2); } private Game createGameAndJoinAllPlayers(int numberOfPlayers, int numberOfPlayersPerTable) { List<GameEvent> events = new ArrayList<>(); events.add(new GameCreatedEvent(UUID.randomUUID(), 1, "test", numberOfPlayers, numberOfPlayersPerTable, UUID.randomUUID(), 10)); Game game = new DefaultGameFactory().createFrom(events); Stream.iterate(1, e -> e + 1) .limit(numberOfPlayers) .forEach(x -> game.joinGame(UUID.randomUUID())); return game; } private void verifyTableDistribution(Game game, int... expectedPlayersPerTable) { int expectedNumberOfTables = expectedPlayersPerTable.length; int totalNumberOfEvents = game.fetchNewEvents().size(); // this event will change locations depending on the number of players, // but it should be the 2nd to last every time GameTablesCreatedAndPlayersAssociatedEvent gameTablesCreatedAndPlayersAssociatedEvent = (GameTablesCreatedAndPlayersAssociatedEvent) game .fetchNewEvents().get(totalNumberOfEvents - 2); Map<UUID, Set<UUID>> tableIdToPlayerIdsMap = gameTablesCreatedAndPlayersAssociatedEvent .getTableIdToPlayerIdsMap(); List<Integer> playerSizes = tableIdToPlayerIdsMap.values().stream() .map(x -> x.size()) .sorted() .collect(Collectors.toList()); List<Integer> playersPerTableList = IntStream.of(expectedPlayersPerTable) .boxed() .collect(Collectors.toList()); assertEquals(expectedNumberOfTables, tableIdToPlayerIdsMap.size()); assertEquals(playerSizes, playersPerTableList); } }