Пример #1
0
class Controller:
    def __init__(self, plateau):
        self.plateau = plateau
        self.dict_rover = {}
        self.instructions_pattern = re.compile("[lrm]+", re.IGNORECASE)

    def set_plateau(self, x, y):
        """
        Setting plateau dimensions.
        :param x: (int) x dimension on plateau grid.
        :param y: (int) y dimension on plateau grid
        :return: plateau object
        """
        if self.plateau is None:
            self.plateau = Plateau(x_max=x, y_max=y)
        else:
            raise PlateauException("Plateau already defined")

    def is_rover_on_plateau(self, x, y):
        """
        Verifies if the rover position is on plateau grid.
        :param x: (int) y axis coordinate on plateau grid
        :param y: (int) y axis coordinate on plateau grid
        :return: bool
        """
        if self.plateau:
            is_x_on_plateau = (x >= 0) and (x <= self.plateau.x_max)
            is_y_on_plateau = (y >= 0) and (y <= self.plateau.y_max)

            return is_x_on_plateau and is_y_on_plateau
        return False

    def is_coordinate_available(self, x_move, y_move):
        """
        Verifies if a position on plateau is available

        :param x_move: (int) x axis coordinate on plateau grid
        :param y_move: (int) y axis coordinate on plateau grid
        :return: bool
        """
        return self.plateau.is_available(x_move, y_move)

    def land_rover(self, x, y, heading, name):
        """
        Land rover on a position on plateau.
        Conditions:
            1) The rover can not land out of plateau grid.

            2) The rover can not land on a position that
            there is other rover positioned (collision).

        :param x: (int) x axis coordinate on plateau grid
        :param y: (int) y axis coordinate on plateau grid
        :param name: (str) rover identifier name ex: rover1
        :return:
        """
        rover = Rover()

        try:
            if self.plateau:
                rover.land(x_pos=x, y_pos=y, heading=heading)

                self.plateau.set_pos_matrix(x, y)
                self.dict_rover[name] = rover
            else:
                raise ValueError('Plateau is required before landing')
        except (CollisionException, ValueError) as ex:
            rover.x_pos = None
            rover.y_pos = None

            raise ex

    def is_instructions_str_valid(self, instructions_str):
        """
        Verifies if instruction match the expected regex pattern
        :param instructions_str: (str) rover actions ex: 'lrmrmmrr'
        :return: Bool
        """
        return self.instructions_pattern.match(instructions_str) is not None

    def move_rover_action(self, instructions_str, rover_obj):
        """
        Execute the move action
        :param instructions_str: (str) rover actions ex: 'lrmrmmrr'
        :param rover_obj: (obj) rover object
        :return:
        """
        x_init, y_init = rover_obj.x_pos, rover_obj.y_pos
        try:
            instructions = instructions_str.lower()
            for instruction in instructions:
                if (instruction == c.LEFT) or (instruction == c.RIGHT):
                    rover_obj.spin(instruction)
                elif instruction == c.MOVE:
                    self.plateau.clean_pos_matrix(rover_obj.x_pos,
                                                  rover_obj.y_pos)
                    rover_obj.move()

                    self.plateau.set_pos_matrix(rover_obj.x_pos,
                                                rover_obj.y_pos)
                else:
                    raise ValueError('Invalid instruction: {}'
                                     .format(instruction))
        except (CollisionException, ValueError) as ex:
            self.plateau.set_pos_matrix(x_init, y_init)
            rover_obj.x_pos = x_init
            rover_obj.y_pos = y_init

            raise ex

    def instructions(self, rover_name, instructions_str):
        """
        Execute the instructions on rover.
        :param rover_name: (str) rover identifier name ex: 'rover1'
        :param instructions_str: (str) right, left, move ex: 'MMRMMRMRRM'

        :return:
        """
        try:
            rover_obj = self.dict_rover[rover_name]
        except KeyError:
            raise InvalidRover("Please make sure that {} "
                               "is landed on plateau".format(rover_name))

        try:
            if rover_obj and rover_obj.is_landed() and \
                    self.is_rover_on_plateau(rover_obj.x_pos,
                                             rover_obj.y_pos):

                if self.is_instructions_str_valid(instructions_str):
                    self.move_rover_action(instructions_str, rover_obj)

                else:
                    raise ValueError('Invalid instruction')

            else:
                raise InvalidRover("Please make sure that {} "
                         "is landed".format(rover_name))

        except (ValueError, InvalidRover, CollisionException) as ex:
            raise ex