Example #1
0
    def test_assign_players_5(self):
        player_list = []
        for i in sorted(range(0, 5)):
            interface = BasicPlayer()
            player_list.append((interface, i))

        manager = Manager(player_list)
        assignments = manager.assign_players(manager.player_pool)
        self.assertEqual(len(assignments[0]), 3)
        self.assertEqual(len(assignments[1]), 2)
Example #2
0
    def setUp(self):
        self.player1 = Player(1)
        self.player2 = Player(1)
        self.player3 = Player(2)
        self.player4 = Player(1)
        self.player5 = Player(1)
        self.player6 = Player(2)
        self.players = [self.player1, self.player2, self.player3,
                        self.player4, self.player5, self.player6]

        self.manager = Manager()
Example #3
0
    def test_is_tournament_over_one_remaining_player(self):
        player_list = []
        for i in sorted(range(0, 8)):
            interface = BasicPlayer()
            player_list.append((interface, i))

        manager = Manager(player_list)
        manager.get_winners_and_cheaters = MagicMock(
            return_value=([player_list[0]], []))
        # manager.get_winners = MagicMock(return_value=[player_list[0]])
        manager.run_tournament()
        # make only one winner
        self.assertEqual(manager.round, 1)
Example #4
0
    def test_is_tournament_over_3_remaining_players_with_tie(self):
        player_list = []
        for i in sorted(range(0, 3)):
            interface = BasicPlayer()
            player_list.append((interface, i))

        manager = Manager(player_list)
        manager.get_winners_and_cheaters = MagicMock(
            return_value=([player_list[0], player_list[1]], []))
        manager.run_tournament()
        #have ties with 4 players left
        self.assertEqual(manager.round, 2)
        self.assertEqual(manager.last_round_winners,
                         [player_list[0], player_list[1]])
Example #5
0
 def test_run_tournament_large(self):
     """
     Purpose: Runs a tournament round given a list of passed players. Checks that the tournament has finished at the
     end, and checks if the remaining player pool is less than or equal to the starting pool.
     Signature: Void -> Void
     """
     player_list = []
     for i in sorted(range(0, 20)):
         interface = BasicPlayer()
         player_list.append((interface, i))
     manager = Manager(player_list)
     manager.run_tournament()
     # Checks if minimum amount of rounds has passed
     self.assertTrue(manager.round >= 2)
Example #6
0
    def test_assign_players_under_max(self):
        """
        Purpose: Test assigning the players when the player pool is less than than maximum number of players per game
        Signature: Void -> Void
        """
        player_list = []
        for i in sorted(range(0, 2)):
            interface = BasicPlayer()
            player_list.append((interface, i))

        manager = Manager(player_list)
        assignments = manager.assign_players(manager.player_pool,
                                             max_players=4)
        self.assertEqual(len(assignments), 1)
Example #7
0
 def test_run_tournament(self):
     """
     Purpose: Runs a tournament round given a list of passed players. Checks that the tournament has finished at the
     end, and checks if the remaining player pool is less than or equal to the starting pool.
     Signature: Void -> Void
     """
     player_list = []
     for i in sorted(range(0, 3)):
         interface = BasicPlayer()
         player_list.append((interface, i))
     manager = Manager(player_list)
     manager.run_tournament()
     # Checks that the winning player pool is less than or equal to the initial passed pool
     self.assertTrue(len(player_list) >= len(manager.player_pool))
     # Checks if rounds advanced
     self.assertTrue(manager.round > 0)
Example #8
0
    def test_assign_players_non_default(self):
        """
        Purpose: Test assigning the players with less than the default (4) players allowed per a single game.
        Signature: Void -> Void
        """
        player_list = []
        for i in sorted(range(0, 4)):
            interface = BasicPlayer()
            player_list.append((interface, i))

        manager = Manager(player_list)
        assignments = manager.assign_players(manager.player_pool,
                                             max_players=2)
        for assignment in assignments:
            self.assertNotEqual(len(assignment), 1)
            self.assertNotEqual(len(assignment), 0)
Example #9
0
    def run_tournament(self):
        """
        Run a tournament with all signed up players.

        Void -> Void
        """
        winners, cheaters = Manager(
            board_config=FishServer.BOARD_CONFIG).run_tournament(self.players)
        print(f"[{len(winners)}, {len(cheaters)}]")
Example #10
0
    def test_assign_players_max(self):
        """
        Purpose: Test assigning the players with the maximum number of players in a game, 4
        Signature: Void -> Void
        """
        player_list = []
        for i in sorted(range(0, 14)):
            interface = BasicPlayer()
            player_list.append((interface, i))

        manager = Manager(player_list)
        assignments = manager.assign_players(manager.player_pool)

        for assignment in assignments:
            self.assertNotEqual(len(assignment), 1)
            self.assertNotEqual(len(assignment), 0)

        self.assertEqual(len(assignments[0]), 4)
        self.assertEqual(len(assignments[len(assignments) - 1]), 2)
Example #11
0
 def test_run_tournament(self):
     server = TCPServer('127.0.0.1', 1234)
     server.configure_server()
     player_list = []
     for i in sorted(range(0, 3)):
         interface = BasicPlayer()
         player_list.append((interface, i))
     manager = Manager(player_list)
     server.tournament_manager = manager
     self.assertEqual(server.run_tournament(), [1, 0])
Example #12
0
 def test_passing_small_pool(self):
     """
     Purpose: Tests passing a pool of players that is less than enough to run a game
     Signature: Void -> Void
     """
     with self.assertRaises(ValueError):
         player_list = []
         for i in sorted(range(0, 1)):
             interface = BasicPlayer()
             player_list.append((interface, i))
         manager = Manager(player_list)
    def wait_for_client(self, last_try=False) -> List[int]:
        """
        This TCPServer attempts to initiate a tournament. It listens on self.sock for 30 seconds or until 10 clients
        connect, creating a PlayerProxy for each client that connects. Then, if at least 5 clients have connected, it
        initializes self.tournament_manager and initiates a tournament via self.run_tournament()
        @param last_try: If, after initially waiting 30 seconds, less than 4 clients have connected, the function
                         tries again with last_try set to True. If last_try is True and less than 4 clients connect
                         before timeout, the function exits without trying again.
        @return: A List of the format [int, int], where the first element is the number of players that won the tournament
                 and the second element is the number of players that failed or cheated during the tournament
        """
        try:
            self.sock.listen(
                10)  # 10 clients before server refuses connections

            while len(self.clients) < 10:
                client_sock, client_address = self.sock.accept()
                player_client = PlayerProxy(client_sock)
                if player_client.name:
                    self.clients.append(player_client)

        except socket.timeout:
            if len(self.clients) < 5 and not last_try:
                self.wait_for_client(True)
            elif len(self.clients) >= 5:
                self.tournament_manager = Manager(
                    list(
                        zip(self.clients,
                            [i for i in range(len(self.clients))])))

        except KeyboardInterrupt:
            self.shutdown_server()

        if len(self.clients) < 5 and not last_try:
            self.wait_for_client(True)
        elif len(self.clients) >= 5:
            self.tournament_manager = Manager(
                list(zip(self.clients, [i for i in range(len(self.clients))])))

        if self.tournament_manager:
            return self.run_tournament()
Example #14
0
    def test_is_tournament_over_duplicate_round_winners(self):
        """
        Purpose: Checks to determine if a tournament has reached the end condition.
        Signature: Void -> Void.
        """
        player_list = []
        for i in sorted(range(0, 8)):
            interface = BasicPlayer()
            player_list.append((interface, i))

        manager = Manager(player_list)
        manager.get_winners_and_cheaters = MagicMock(return_value=(player_list,
                                                                   []))
        manager.last_round_winners = player_list
        manager.run_tournament()
        # get last round winners to equal current round winners
        self.assertEqual(manager.round, 1)
class TCPServer:
    """
    Represents the Fish tournament server that accepts a certain number of client connections and then conducts a Fish
    tournament by creating PlayerProxy components and handing those to the tournament manager, which interacts with the
    player proxies as if they were internal players. The PlayerProxy component handles direct communication with the
    associated client.
    """
    def __init__(self, host, port):
        """
        Initializes a TCPServer instance with the given host and port number for creating a socket via self.configure_server()
        @param host: The host IP address to connect to
        @param port: The port number to use for connection
        """
        self.host = host  # Host address
        self.port = port  # Host port
        self.sock = None  # Connection socket
        self.tournament_manager = None
        self.clients = []

    def configure_server(self) -> None:
        """
        Initializes this TCPServer's self.sock, connects it to (self.host, self.port), and sets its timeout to 30 seconds
        @return: None
        """
        # create TCP socket with IPv4 addressing
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        # bind server to the address
        self.sock.bind((self.host, self.port))
        self.sock.settimeout(30)  # set listen timeout to 30

    def wait_for_client(self, last_try=False) -> List[int]:
        """
        This TCPServer attempts to initiate a tournament. It listens on self.sock for 30 seconds or until 10 clients
        connect, creating a PlayerProxy for each client that connects. Then, if at least 5 clients have connected, it
        initializes self.tournament_manager and initiates a tournament via self.run_tournament()
        @param last_try: If, after initially waiting 30 seconds, less than 4 clients have connected, the function
                         tries again with last_try set to True. If last_try is True and less than 4 clients connect
                         before timeout, the function exits without trying again.
        @return: A List of the format [int, int], where the first element is the number of players that won the tournament
                 and the second element is the number of players that failed or cheated during the tournament
        """
        try:
            self.sock.listen(
                10)  # 10 clients before server refuses connections

            while len(self.clients) < 10:
                client_sock, client_address = self.sock.accept()
                player_client = PlayerProxy(client_sock)
                if player_client.name:
                    self.clients.append(player_client)

        except socket.timeout:
            if len(self.clients) < 5 and not last_try:
                self.wait_for_client(True)
            elif len(self.clients) >= 5:
                self.tournament_manager = Manager(
                    list(
                        zip(self.clients,
                            [i for i in range(len(self.clients))])))

        except KeyboardInterrupt:
            self.shutdown_server()

        if len(self.clients) < 5 and not last_try:
            self.wait_for_client(True)
        elif len(self.clients) >= 5:
            self.tournament_manager = Manager(
                list(zip(self.clients, [i for i in range(len(self.clients))])))

        if self.tournament_manager:
            return self.run_tournament()

    def run_tournament(self) -> List[int]:
        """
        Calls this TCPServer's tournament manager to run a tournament and returns the results.
        @return: AList of the format [int, int], where the first element is the number of players that won the tournament
                 and the second element is the number of players that failed or cheated during the tournament
        """
        self.tournament_manager.run_tournament()
        self.shutdown_server()
        return [
            len(self.tournament_manager.player_pool),
            len(self.tournament_manager.cheaters)
        ]

    def shutdown_server(self) -> None:
        """
        Closes this TCPServer's self.sock
        @return: None
        """
        self.sock.close()
Example #16
0
 def test_constructor(self):
     Manager(Referee)
     Manager(ExtendedReferee)
     with self.assertRaisesRegex(ValueError, "referee_type must be Referee or a subclass of Referee"):
         Manager(Move)
Example #17
0
class RefereeTestCase(unittest.TestCase):

    def setUp(self):
        self.player1 = Player(1)
        self.player2 = Player(1)
        self.player3 = Player(2)
        self.player4 = Player(1)
        self.player5 = Player(1)
        self.player6 = Player(2)
        self.players = [self.player1, self.player2, self.player3,
                        self.player4, self.player5, self.player6]

        self.manager = Manager()

    ## TESTING TOURNAMENT CREATION ###########################################################

    def test_constructor(self):
        Manager(Referee)
        Manager(ExtendedReferee)
        with self.assertRaisesRegex(ValueError, "referee_type must be Referee or a subclass of Referee"):
            Manager(Move)

    ## TESTING RUN TOURNAMENT ################################################################

    def test_run_tournament(self):
        winners, cheaters = self.manager.run_tournament(self.players)
        self.assertEqual(winners, [self.player1, self.player4, self.player5])
        self.assertEqual(cheaters, set())

    def test_run_tournament_failing_player_start(self):
        self.player5.tournament_start = MagicMock(return_value=False)
        winners, cheaters = self.manager.run_tournament(self.players)
        self.assertEqual(winners, [self.player1, self.player3, self.player4])
        self.assertEqual(cheaters, set([self.player5]))

    def test_run_tournament_failing_player_winner(self):
        self.player5.tournament_end = MagicMock(return_value=False)
        winners, cheaters = self.manager.run_tournament(self.players)
        self.assertEqual(winners, [self.player1, self.player4])
        self.assertEqual(cheaters, set([self.player5]))

    def test_run_tournament_everyone_fails(self):
        self.player1.choose_next_move = MagicMock(return_value=Move((0, 0), (1, 1)))  # illegal move
        self.player2.choose_placement = MagicMock(return_value=(0, 0))  # penguin already there
        self.player3.choose_placement = MagicMock(return_value=(-1, 0))
        self.player4.choose_next_move = MagicMock(
            return_value=Move((0, 0), (2, 0)))  # no penguin to move
        self.player5.choose_next_move = MagicMock(return_value=Move((0, 0), (1, 1)))
        self.player6.choose_next_move = MagicMock(return_value=Move((0, 0), (1, 1)))

        winners, cheaters = self.manager.run_tournament(self.players)
        self.assertEqual(winners, [])
        self.assertEqual(cheaters, set(self.players))

    ## TESTING UPDATE BRACKET ################################################################

    def test_update_bracket(self):
        self.manager._Manager__queue = self.players
        self.manager._Manager__active_players = set(self.players)
        round_result = {
            "winners": {self.player1, self.player2},
            "losers": {self.player3, self.player4},
            "kicked_players": {self.player5, self.player6},
            "games_played": 2
        }
        self.assertEqual(self.manager._Manager__queue, self.players)
        self.assertEqual(self.manager._Manager__active_players, set(self.players))
        self.assertEqual(self.manager._Manager__previous_winners, set())
        self.assertEqual(self.manager._Manager__kicked_players, set())
        self.assertEqual(self.manager._Manager__games_in_previous_round, 0)

        self.manager._Manager__update_bracket(round_result)
        self.assertEqual(self.manager._Manager__queue, [self.player1, self.player2])
        self.assertEqual(self.manager._Manager__active_players, {
                         self.player1, self.player2, self.player3, self.player4})
        self.assertEqual(self.manager._Manager__previous_winners, {
                         self.player1, self.player2, self.player3, self.player4})
        self.assertEqual(self.manager._Manager__kicked_players, {self.player5, self.player6})
        self.assertEqual(self.manager._Manager__games_in_previous_round, 2)

    # TESTING KICK PLAYERS ------------------------------------------------------------

    def test_kick_players(self):
        self.manager._Manager__queue = self.players
        self.manager._Manager__active_players = set(self.players)

        bad_players = {self.player6, self.player1}
        self.manager._Manager__kick_players(bad_players)
        self.assertEqual(self.manager._Manager__queue, self.players[1:5])
        self.assertEqual(self.manager._Manager__active_players, set(self.players[1:5]))
        self.assertEqual(self.manager._Manager__kicked_players, bad_players)

    def test_kick_players_no_bad_players(self):
        self.manager._Manager__queue = self.players
        self.manager._Manager__active_players = set(self.players)

        bad_players = set()
        self.manager._Manager__kick_players(bad_players)
        self.assertEqual(self.manager._Manager__queue, self.players)
        self.assertEqual(self.manager._Manager__active_players, set(self.players))
        self.assertEqual(self.manager._Manager__kicked_players, bad_players)

    # TESTING RUN ROUNDS ################################################################-

    def test_run_round(self):
        match_players = [
            self.players[0:4],
            self.players[4:6]
        ]
        expected = {
            "winners": {self.player1, self.player3, self.player4, self.player5},
            "losers": {self.player2, self.player6},
            "kicked_players": set(),
            "games_played": 2
        }
        round_result = self.manager._Manager__run_round(match_players)
        self.assertEqual(round_result, expected)

    def test_run_round_failing_player(self):
        self.player1.choose_next_move = MagicMock(
            return_value=Move((0, 0), (4, 4)))  # runs into another penguin
        match_players = [
            self.players[0:4],
            self.players[4:6]
        ]
        expected = {
            "winners": {self.player3, self.player5},
            "losers": {self.player2, self.player4, self.player6},
            "kicked_players": {self.player1},
            "games_played": 2
        }
        round_result = self.manager._Manager__run_round(match_players)
        self.assertEqual(round_result, expected)

    ## TESTING MAKE ROUNDS ################################################################

    def test_make_rounds(self):
        self.manager._Manager__queue = self.players

        expected = [
            self.players[0:4],
            self.players[4:6]
        ]
        match_players = self.manager._Manager__make_rounds()
        self.assertEqual(match_players, expected)

    def test_make_rounds_no_players(self):
        self.assertRaisesRegex(
            ValueError, "Not enough players to run another round.", self.manager._Manager__make_rounds)

    def test_make_rounds_backtracking(self):
        self.manager._Manager__queue = self.players[0:5]
        expected = [
            self.players[0:3],
            self.players[3:5]
        ]
        match_players = self.manager._Manager__make_rounds()
        self.assertEqual(match_players, expected)

    def test_make_rounds_min_players(self):
        self.manager._Manager__queue = self.players[0:2]
        expected = [
            self.players[0:2]
        ]
        match_players = self.manager._Manager__make_rounds()
        self.assertEqual(match_players, expected)

    ## TESTING BALANCE GAME ################################################################

    def test_balance_games(self):
        match_players = [
            self.players[0:4],
            self.players[4:5]
        ]
        expected = [
            self.players[0:3],
            self.players[3:5]
        ]
        balanced = self.manager._Manager__balance_games(match_players)
        self.assertEqual(balanced, expected)

    def test_balance_games_already_balanced(self):
        match_players = [
            self.players[0:4],
            self.players[4:6]
        ]
        self.assertEqual(self.manager._Manager__balance_games(match_players), match_players)

    def test_balance_games_one_game(self):
        match_players = [
            self.players[0:2]
        ]
        self.assertEqual(self.manager._Manager__balance_games(match_players), match_players)

    ## TESTING IS TOURNAMENT OVER ###########################################################

    def test_is_tournament_over_false(self):
        self.manager._Manager__queue = self.players
        self.manager._Manager__previous_winners = set()
        self.manager._Manager__games_in_previous_round = 2
        self.assertFalse(self.manager._Manager__is_tournament_over())

    def test_is_tournament_over_same_winners(self):
        self.manager._Manager__queue = self.players
        self.manager._Manager__previous_winners = set(self.players)
        self.assertTrue(self.manager._Manager__is_tournament_over())

    def test_is_tournament_over_too_few_players(self):
        self.manager._Manager__queue = self.players[0:1]
        self.assertTrue(self.manager._Manager__is_tournament_over())

    def test_is_tournament_over_one_game_round(self):
        self.manager._Manager__queue = self.players[0:3]
        self.manager._Manager__previous_winners = set(self.players)
        self.manager._Manager__games_in_previous_round = 1
        self.assertTrue(self.manager._Manager__is_tournament_over())

    ## TESTING BROADCAST TOURNAMENT START ###################################################

    def test_broadcast_tournament_start(self):
        self.manager._Manager__queue = self.players
        self.manager._Manager__active_players = set(self.players)

        self.player1.tournament_start = MagicMock(return_value=True)
        self.manager._Manager__broadcast_tournament_start()
        self.player1.tournament_start.assert_called()
        self.assertEqual(self.manager._Manager__queue, self.players)
        self.assertEqual(self.manager._Manager__active_players, set(self.players))

    def test_broadcast_tournament_start_player_bad_response(self):
        self.player1.tournament_start = MagicMock(return_value=False)
        self.player2.tournament_start = MagicMock(return_value="True")
        self.manager._Manager__queue = self.players
        self.manager._Manager__active_players = set(self.players)
        self.manager._Manager__broadcast_tournament_start()
        self.assertEqual(self.manager._Manager__queue, self.players[2:6])
        self.assertEqual(self.manager._Manager__active_players, set(self.players[2:6]))

    ## TESTING BROADCAST TOURNAMENT END #####################################################

    def test_broadcast_tournament_end_good_players(self):
        self.manager._Manager__queue = self.players
        self.manager._Manager__active_players = set(self.players)
        round_result = {
            "winners": {self.player1, self.player4, self.player5},
            "losers": {self.player2, self.player6},
            "kicked_players": {self.player3},
            "games_played": 1
        }
        self.manager._Manager__update_bracket(round_result)
        self.player1.tournament_end = MagicMock(return_value=True)
        self.player2.tournament_end = MagicMock(return_value=True)
        self.manager._Manager__broadcast_tournament_end()
        self.player1.tournament_end.assert_called_with(True)
        self.player2.tournament_end.assert_called_with(False)

    def test_broadcast_tournament_end_bad_winner(self):
        self.manager._Manager__queue = self.players
        self.manager._Manager__active_players = set(self.players)
        round_result = {
            "winners": {self.player1, self.player4, self.player5},
            "losers": {self.player2, self.player6},
            "kicked_players": {self.player3},
            "games_played": 1
        }
        self.manager._Manager__update_bracket(round_result)
        self.player4.tournament_end = MagicMock(return_value=False)
        self.manager._Manager__broadcast_tournament_end()
        self.player4.tournament_end.assert_called_with(True)
        self.assertTrue(self.player4 in self.manager._Manager__kicked_players)

    def test_broadcast_tournament_end_kicked_player_not_called(self):
        self.manager._Manager__queue = self.players
        self.manager._Manager__active_players = set(self.players)
        round_result = {
            "winners": {self.player1, self.player4, self.player5},
            "losers": {self.player2, self.player6},
            "kicked_players": {self.player3},
            "games_played": 1
        }
        self.manager._Manager__update_bracket(round_result)
        self.player3.tournament_end = MagicMock(return_value=True)
        self.manager._Manager__broadcast_tournament_end()
        self.player3.tournament_end.assert_not_called()

    ## TESTING GET TOURNAMENT RESULT ########################################################

    def test_get_tournament_result(self):
        self.manager._Manager__queue = self.players
        self.assertEqual(self.manager._Manager__get_tournament_result(), (self.players, set()))