class TestCommandLine(unittest.TestCase):
    def setUp(self):
        time_step = 0.05
        self.agents = [Agent(0, 0, time_step)]
        self.arena = Arena(10, 20)
        self.biased_grid = BiasedGrid(self.arena.get_dimensions())
        self.algorithm = AStar(self.arena, self.agents, self.biased_grid)
        self.cli = CommandLine(self.arena, self.agents)

    def test_help(self):
        command = 'help'
        retval = self.cli.parse_command(command)
        self.assertTrue(retval)

    def test_help_specific(self):
        command = 'help move_agent'
        retval = self.cli.parse_command(command)
        self.assertTrue(retval)

    def test_agent_move(self):
        command = 'move_agent 0 X 4'
        retval = self.cli.parse_command(command)
        self.assertTrue(retval)

    def test_blockage(self):
        command = 'blockage set 4 4'
        retval = self.cli.parse_command(command)
        self.assertTrue(retval)
        self.assertEqual(TileState.BLOCKED, self.arena.get_tile_state(4, 4))
class TestMultiAgentAlgorithm(unittest.TestCase):
    def setUp(self):
        time_step = 0.005
        self.arena = Arena(10, 10)
        self.biased_grid = BiasedGrid(self.arena.get_dimensions())
        self.agents = [Agent(0, 0, time_step), Agent(5, 5, time_step)]
        self.algorithm = SingleAgentAlgorithmMock(self.arena, self.agents,
                                                  self.biased_grid)
        self.routing_manager = MultiAgentAlgorithmMock(self.arena, self.agents,
                                                       self.algorithm)

    def tearDown(self):
        pass

    def test_is_simulation_completed_passes_if_final_goal_reached(self):
        self.routing_manager.add_agent_goal(0, (0, 0))
        self.routing_manager.add_agent_goal(1, (5, 5))
        self.assertTrue(self.routing_manager.is_simulation_complete())

    def test_simulation_not_completed_if_final_goal_not_reached(self):
        # add the current location as a segment, but also add a second location for each agent
        self.routing_manager.add_agent_goal(0, (0, 0))
        self.routing_manager.add_agent_goal(1, (5, 5))
        self.routing_manager.add_agent_goal(0, (1, 1))
        self.routing_manager.add_agent_goal(1, (4, 4))
        self.assertFalse(self.routing_manager.is_simulation_complete())

    def test_update_agent_goal(self):
        self.routing_manager.add_agent_goal(0, (0, 0))
        self.routing_manager.add_agent_goal(0, (1, 1))
        self.assertTrue(self.routing_manager.is_agent_at_goal(0))
        self.routing_manager.update_agent_goal(0)
        self.assertTupleEqual((1, 1), self.routing_manager.agent_goals[0][0])
        self.assertFalse(self.routing_manager.is_agent_at_goal(0))
        self.assertFalse(self.routing_manager.is_simulation_complete())

    def test_routing_blockages(self):
        move_x_task = AgentTask(AgentTasks.MOVE, [AgentCoordinates.X, 3])
        move_y_task = AgentTask(AgentTasks.MOVE, [AgentCoordinates.Y, 3])
        self.routing_manager.add_agent_task(0, move_x_task)
        for i in range(1, 3):
            self.assertEqual(TileState.RESERVED,
                             self.arena.get_tile_state(i, 0))
        self.assertEqual(TileState.AGENT_TARGET,
                         self.arena.get_tile_state(3, 0))
        self.routing_manager.add_agent_task(0, move_y_task)
        for i in range(1, 3):
            self.assertEqual(TileState.RESERVED,
                             self.arena.get_tile_state(3, i))
        self.assertEqual(TileState.AGENT_TARGET,
                         self.arena.get_tile_state(3, 3))

    def test_adding_and_completing_task_clears_blockage(self):
        move_x_task = AgentTask(AgentTasks.MOVE, [AgentCoordinates.X, 3])
        self.routing_manager.add_agent_task(0, move_x_task)
        for i in range(1, 3):
            self.assertEqual(TileState.RESERVED,
                             self.arena.get_tile_state(i, 0))
        self.assertEqual(TileState.AGENT_TARGET,
                         self.arena.get_tile_state(3, 0))
        self.routing_manager.signal_agent_event(0, AgentEvent.TASK_COMPLETED)
        for i in range(1, 4):
            self.assertEqual(TileState.FREE, self.arena.get_tile_state(i, 0))

    def test_completing_task_clears_agent_active(self):
        move_x_task = AgentTask(AgentTasks.MOVE, [AgentCoordinates.X, 3])
        self.routing_manager.add_agent_task(0, move_x_task)
        self.routing_manager.signal_agent_event(0, AgentEvent.TASK_COMPLETED)
        self.assertFalse(self.routing_manager.active_agents[0])

    def test_initialize_algorithm(self):
        self.routing_manager.initialize()
        self.assertTrue(self.routing_manager.initialized)

    def test_is_agent_at_goal(self):
        self.routing_manager.add_agent_goal(0, (0, 0))
        self.assertTrue(self.routing_manager.is_agent_at_goal(0))

    def test_start_new_task(self):
        move_x_task = AgentTask(AgentTasks.MOVE, [AgentCoordinates.X, 3])
        self.routing_manager.add_agent_task(0, move_x_task)
        self.routing_manager.start_new_task(0)
        self.assertTrue(self.routing_manager.active_agents[0])
class TestArena(unittest.TestCase):
    def setUp(self):
        # note: this means coordinates go from x = [0-4], y = [0-9]
        self.arena = Arena(5, 10)

    def test_generate_grid(self):
        self.assertEqual(TileState.FREE, self.arena.get_tile_state(4, 9))

    def test_set_blockage(self):
        x_values = list(range(3))
        y_values = [3]
        self.arena.set_blockage(x_values, y_values)
        for x in x_values:
            for y in y_values:
                self.assertEqual(TileState.BLOCKED,
                                 self.arena.get_tile_state(x, y))

    def test_set_reserved(self):
        x_values = list(range(3))
        y_values = [3]
        self.arena.set_reserved(x_values, y_values)
        for x in x_values:
            for y in y_values:
                self.assertEqual(TileState.RESERVED,
                                 self.arena.get_tile_state(x, y))

    def test_get_dimensions(self):
        dimensions = self.arena.get_dimensions()
        self.assertTupleEqual((5, 10), dimensions)

    def test_clear_blockage(self):
        x_values = list(range(3))
        y_values = [3]
        self.arena.set_blockage(x_values, y_values)
        self.arena.clear_blockage(x_values, y_values)
        for x in x_values:
            for y in y_values:
                self.assertEqual(TileState.FREE,
                                 self.arena.get_tile_state(x, y))

    def test_boundary_checking(self):
        x_range = list(range(5))
        y_range = list(range(10))
        # test the upper and lower rows
        for x in x_range:
            self.assertTrue(self.arena.is_boundary_tile(x, 0))
            self.assertTrue(self.arena.is_boundary_tile(x, 9))
        # test the sides
        for y in y_range:
            self.assertTrue(self.arena.is_boundary_tile(0, y))
            self.assertTrue(self.arena.is_boundary_tile(4, y))

    def test_neighbours_at_corners(self):
        corners = [(0, 0), (0, 9), (4, 9), (4, 0)]
        test_neighbours = [[(1, 0), (0, 1)], [(0, 8), (1, 9)], [(3, 9),
                                                                (4, 8)],
                           [(3, 0), (4, 1)]]
        for idx, corner in enumerate(corners):
            neighbours = self.arena.get_neighbours(corner[0], corner[1])
            # each corner should only have two neighbours
            self.assertEqual(2, len(neighbours))
            for check in test_neighbours[idx]:
                self.assertTrue((check in neighbours))

    def test_set_agent_target(self):
        self.arena.set_agent_target(4, 4)
        state = self.arena.get_tile_state(4, 4)
        self.assertEqual(TileState.AGENT_TARGET, state)