Ejemplo n.º 1
0
 def test_get_next_with_invalid_command(self):
     CommandsParser.Register(ParserTestCase.MockCommand('MOVE'))
     parser = CommandsParser(['MOVE', 'DANCE', 'SIT', 'MOVE'])
     self.assertIsNotNone(parser.get_next_command())
     self.assertIsNotNone(parser.get_next_command())
     self.assertIsNone(parser.get_next_command()) # MOVE, MOVE, None
     CommandsParser.COMMANDS = {}
Ejemplo n.º 2
0
def main():
    """
    Main logic loop.
    Not tested under Unit testing, since it's more suitable for integration tests!
    """
    parser = argparse.ArgumentParser(description='REA Robot')
    parser.add_argument('--c', metavar='FILE', type=str, required=False, help='File with commands to execute. One command per line')
    args = parser.parse_args()

    # Get list of commands to execute
    commands = load_command_list(args.c)
    if len(commands) == 0:
        commands = read_commands_from_console()

    logger.debug('List of commands to execute: {}'.format(commands))

    # Run the Robot
    robot = Robot()
    cmd_parser = CommandsParser(commands)
    while True:
        cmd_and_args = cmd_parser.get_next_command()
        if cmd_and_args:
            cmd_and_args[0].run(robot, cmd_and_args[1])
        else:
            break
Ejemplo n.º 3
0
 def test_get_next_on_non_empty_list(self):
     CommandsParser.Register(ParserTestCase.MockCommand('MOVE'))
     CommandsParser.Register(ParserTestCase.MockCommand('REPORT'))
     parser = CommandsParser(['MOVE', 'REPORT'])
     self.assertIsNotNone(parser.get_next_command())
     self.assertIsNotNone(parser.get_next_command())
     self.assertIsNone(parser.get_next_command()) # MOVE, REPORT, None
     CommandsParser.COMMANDS = {}
Ejemplo n.º 4
0
 def test_static_register_method(self):
     self.assertEquals(len(CommandsParser.COMMANDS), 0)
     mock = ParserTestCase.MockCommand('mock')
     CommandsParser.Register(mock)
     self.assertEquals(len(CommandsParser.COMMANDS), 1)
     self.assertIsInstance(CommandsParser.COMMANDS['mock'], ParserTestCase.MockCommand)
Ejemplo n.º 5
0
 def test_get_next_on_empty_list(self):
     parser = CommandsParser([])
     self.assertIsNone(parser.get_next_command()) # None
Ejemplo n.º 6
0
 def test_instance(self):
     parser = CommandsParser()
     self.assertIsInstance(parser, CommandsParser)
Ejemplo n.º 7
0
    """
    Implementation of the MOVE command
    """
    def __init__(self):
        self.ID = 'RIGHT'

    def run(self, robot, arguments=None):
        """
        Execute the logic of the MOVE command
        """
        if robot is None:
            return

        # NOTE: This has to be done for every command except PLACE. I Could have also implemented this completely in
        # the Robot class. The choice between these two options, in my opinion, is a design decision for who's
        # responsible - is the Robot responsible for all it's business rules (and so there's not really a need for
        # Commands - they can be implemented inside the Robot, or is he a dumb state machine and the rules are applied
        # by the commands. I believe in the context of this exercise both are valid, and so I chose the latter.
        # Also, please note that the Initialised/PLACED rule IS DIFFERENT from the bounds rule. I consider the latter
        # to be input validation and not really a business rule (but of course, the line is very thin here).
        if str(robot) == RobotUninitialisedState:
            return

        logger.info('Running command RIGHT')
        robot.update(robot.X, robot.Y,
                     Robot.get_next_prev_direction(robot.Dir, 1))


# Register with the CommandParser class so that this command can be used by the parser
CommandsParser.Register(RightCommand())
Ejemplo n.º 8
0
    """
    Implementation of the LEFT command
    """
    def __init__(self):
        self.ID = 'LEFT'

    def run(self, robot, arguments=None):
        """
        Execute the logic of the MOVE command
        """
        if robot is None:
            return

        # NOTE: This has to be done for every command except PLACE. I Could have also implemented this completely in
        # the Robot class. The choice between these two options, in my opinion, is a design decision for who's
        # responsible - is the Robot responsible for all it's business rules (and so there's not really a need for
        # Commands - they can be implemented inside the Robot, or is he a dumb state machine and the rules are applied
        # by the commands. I believe in the context of this exercise both are valid, and so I chose the latter.
        # Also, please note that the Initialised/PLACED rule IS DIFFERENT from the bounds rule. I consider the latter
        # to be input validation and not really a business rule (but of course, the line is very thin here).
        if str(robot) == RobotUninitialisedState:
            return

        logger.info('Running command LEFT')
        robot.update(robot.X, robot.Y,
                     Robot.get_next_prev_direction(robot.Dir, -1))


# Register with the CommandParser class so that this command can be used by the parser
CommandsParser.Register(LeftCommand())
Ejemplo n.º 9
0
from parser import CommandsParser
import logging


logger = logging.getLogger(__name__)


class PlaceCommand(CommandBase):
    """
    Implementation of the PLACE command
    """
    def __init__(self):
        self.ID = 'PLACE'

    def run(self, robot, arguments):
        """
        Execute the logic of the PLACE command
        """
        if robot is None:
            return

        if isinstance(arguments, str):
            arguments = [x.strip() for x in arguments.split(',') if x.strip() != '']

        logger.info('Running command PLACE with arguments {},{},{}'.format(arguments[0], arguments[1], arguments[2]))
        robot.update(int(arguments[0]), int(arguments[1]), arguments[2])


# Register with the CommandParser class so that this command can be used by the parser
CommandsParser.Register(PlaceCommand())
Ejemplo n.º 10
0
class ReportCommand(CommandBase):
    """
    Implementation of the MOVE command
    """
    def __init__(self):
        self.ID = 'REPORT'

    def run(self, robot, arguments=None):
        """
        Execute the logic of the MOVE command
        """
        if robot is None:
            return

        # NOTE: This has to be done for every command except PLACE. I Could have also implemented this completely in
        # the Robot class. The choice between these two options, in my opinion, is a design decision for who's
        # responsible - is the Robot responsible for all it's business rules (and so there's not really a need for
        # Commands - they can be implemented inside the Robot, or is he a dumb state machine and the rules are applied
        # by the commands. I believe in the context of this exercise both are valid, and so I chose the latter.
        # Also, please note that the Initialised/PLACED rule IS DIFFERENT from the bounds rule. I consider the latter
        # to be input validation and not really a business rule (but of course, the line is very thin here).
        if str(robot) == RobotUninitialisedState:
            return

        logger.info('Running command REPORT')
        print str(robot)


# Register with the CommandParser class so that this command can be used by the parser
CommandsParser.Register(ReportCommand())
Ejemplo n.º 11
0
    def run(self, robot, arguments=None):
        """
        Execute the logic of the MOVE command
        """
        if robot is None:
            return

        # NOTE: This has to be done for every command except PLACE. I Could have also implemented this completely in
        # the Robot class. The choice between these two options, in my opinion, is a design decision for who's
        # responsible - is the Robot responsible for all it's business rules (and so there's not really a need for
        # Commands - they can be implemented inside the Robot, or is he a dumb state machine and the rules are applied
        # by the commands. I believe in the context of this exercise both are valid, and so I chose the latter.
        # Also, please note that the Initialised/PLACED rule IS DIFFERENT from the bounds rule. I consider the latter
        # to be input validation and not really a business rule (but of course, the line is very thin here).
        if str(robot) == RobotUninitialisedState:
            return

        logger.info('Running command MOVE {}'.format(robot.Dir))
        if robot.Dir == 'NORTH':
            robot.update(robot.X, robot.Y + 1, robot.Dir)
        elif robot.Dir == 'SOUTH':
            robot.update(robot.X, robot.Y - 1, robot.Dir)
        elif robot.Dir == 'EAST':
            robot.update(robot.X + 1, robot.Y, robot.Dir)
        elif robot.Dir == 'WEST':
            robot.update(robot.X - 1, robot.Y, robot.Dir)


# Register with the CommandParser class so that this command can be used by the parser
CommandsParser.Register(MoveCommand())