rafaelgonzalez/loco_bot

View on GitHub
lib/loco_bot/cli.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'loco_bot/cli/command'

module LocoBot
  # Provides a 'command line'-like interface to interact with the API,
  # in a limited way: only one Robot and Table instances are available.
  class CLI
    # The regexp used to parse input.
    INPUT_SPLIT_REGEXP = / |,|\s/

    # @!attribute [r] table
    # @return [Robot] the Robot
    attr_reader :robot

    # @!attribute [r] table
    # @return [Table] the Table
    attr_reader :table

    def initialize
      @robot = Robot.new
      @table = Table.new
    end

    # Reads input for commands.
    # @param input [String] the input
    # @note Available commands are:
    #   - PLACE X,Y,F: put the robot on the table in position X,Y and facing NORTH, SOUTH, EAST or WEST.
    #   - MOVE: move the robot one unit forward in the direction it is currently facing.
    #   - LEFT and RIGHT rotate the robot 90 degrees in the specified direction without changing its position.
    #   - REPORT announces the X,Y and F of the robot.
    #   - HODOR outputs a friendly greating.
    # @return [void]
    def input!(input)
      parsed_data = parse_input(input)

      return if parsed_data[:command].nil?

      command_class = Command.class_from_name(parsed_data[:command])

      if command_class.nil?
        puts "#{parsed_data[:command].upcase}: not a known command. Valid commands are #{CLI::Command.list.join(', ')}."
      else
        execute_command(command_class, parsed_data[:arguments])
      end
    end

    private

    def execute_command(command_class, arguments)
      command_class.new(robot, table).execute(*arguments)
    rescue ArgumentError => exception
      puts "#{command_class.label}: #{exception.message}"
    end

    def parse_input(input)
      return {} if input.nil?

      split_data = input.split(INPUT_SPLIT_REGEXP)
      split_data.reject!(&:empty?)

      return {} if split_data.empty?

      { command: split_data[0], arguments: split_data.drop(1) }
    end
  end
end