maux_robot 0.0.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3c587b90116be51790d2d74c04781ddf0aa1f29a
4
- data.tar.gz: 3d0d0a2f00d422c6a0eed9a789068623d5678428
2
+ SHA256:
3
+ metadata.gz: 9c718637133d2a7b8dfb7d42fdcd754ce4eff6ec1fba93f7fe5ddaaa612d1cc1
4
+ data.tar.gz: 064f6ebc5ceefaa8dc44a2ff1f577178675cf362ffb77c3726c6e2ae6f62f1f1
5
5
  SHA512:
6
- metadata.gz: 05ee766bbf7c5917d43f1310d8f9bfce858303810bbab6695760e154854c6af3232ff57b1d0575d446e46cfed32e1979c92e596ff1fd4a758444ff329d098c66
7
- data.tar.gz: 9fe5dd5b8edc18ad12864df9c08a41c58c75c59c6b4b875e7a33e8baea9bed0474a8fa43d8815fd16ab1653cc09ef07cc24c6b18a012ffcf5f32645a4d2c3e38
6
+ metadata.gz: 8cd5c5b6adfccdda316a95ac5f88cefbef598239ed2e981c47f10a70b63a0133af84b70b1effafa04dc0643efafa22bb183d8779d43630310e6068a6a854c370
7
+ data.tar.gz: 51e46cca8fc6e0239ae9c286611fc11e4589959d5338fac2317107fd2703e3112c201ca63e50bdda96aade74e1c2d71a78c02ff7d93f83b40009d9c41c4bed29
data/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ [![Build Status](https://travis-ci.org/mauriciovieira/maux_robot.svg?branch=master)](https://travis-ci.org/mauriciovieira/maux_robot)
2
+ [![Maintainability](https://api.codeclimate.com/v1/badges/b45a7baf1130fb9aa8f6/maintainability)](https://codeclimate.com/github/mauriciovieira/maux_robot/maintainability)
3
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/b45a7baf1130fb9aa8f6/test_coverage)](https://codeclimate.com/github/mauriciovieira/maux_robot/test_coverage)
4
+
1
5
  # maux_robot
2
6
 
3
7
  Maux version of a Toy Robot Simulator in Ruby
@@ -22,7 +26,8 @@ PLACE X,Y,F
22
26
  MOVE
23
27
  LEFT
24
28
  RIGHT
25
- REPORT
29
+ REPORT [csv|json]
30
+ VERBOSE
26
31
  ```
27
32
 
28
33
  * `PLACE` will put the toy robot on the table in position X,Y
@@ -38,7 +43,8 @@ in the direction it is currently facing.
38
43
  * `LEFT` and `RIGHT` will rotate the robot 90 degrees
39
44
  in the specified direction
40
45
  without changing the position of the robot.
41
- * `REPORT` will announce the X,Y and F of the robot.
46
+ * `REPORT` will announce the X,Y and F of the robot. If `csv` or `json` is passed, it formats the whereabouts accordingly. The default format is `csv`.
47
+ * `VERBOSE` will turn the error messages (talkative mode) on or off. The robot starts with talkative mode set to off.
42
48
 
43
49
  * A robot that is not on the table ignores the `MOVE`, `LEFT`, `RIGHT` and `REPORT` commands.
44
50
 
@@ -101,4 +107,4 @@ The Toy Robot Challenge was originally formulated by [Jon Eaves](https://twitter
101
107
  **Mauricio Vieira (mauriciovieira)**
102
108
  + <http://mauriciovieira.net>
103
109
  + <https://twitter.com/mauriciovieira>
104
- + <https://github.com/mauriciovieira>
110
+ + <https://github.com/mauriciovieira>
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  $LOAD_PATH.unshift("#{__dir__}/../lib")
4
5
 
@@ -1,5 +1,14 @@
1
- require 'maux_robot/version'
2
- require 'maux_robot/cli'
3
- require 'maux_robot/position'
4
- require 'maux_robot/table'
5
- require 'maux_robot/robot'
1
+ # frozen_string_literal: true
2
+
3
+ require "maux_robot/version"
4
+ require "maux_robot/cli"
5
+ require "maux_robot/formatter"
6
+ require "maux_robot/formatter/csv"
7
+ require "maux_robot/formatter/json"
8
+ require "maux_robot/parser"
9
+ require "maux_robot/position"
10
+ require "maux_robot/table"
11
+ require "maux_robot/robot"
12
+
13
+ module MauxRobot
14
+ end
@@ -1,11 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MauxRobot
4
-
5
4
  # The CLI is a class responsible of handling command line interface
6
5
  class CLI
7
- ALLOWED_ORDERS = %i[left right move place report].freeze
8
-
9
6
  attr_reader :robot
10
7
  def initialize
11
8
  @robot = Robot.new
@@ -19,43 +16,24 @@ module MauxRobot
19
16
  def run_script(all_input)
20
17
  all_input.split("\n").each do |line_input|
21
18
  command = parse(line_input)
22
- execute(command) if command
19
+ begin
20
+ execute(command) if command
21
+ rescue MauxRobot::RobotError => e
22
+ puts e if @robot.talkative
23
+ end
23
24
  end
24
25
  end
25
26
 
26
27
  def parse(line_input)
27
- clean_input = line_input.strip.squeeze(' ').split(' ')
28
- order = sanitize_order(clean_input.shift)
29
- return unless order
30
-
31
- command = { order: order }
32
-
33
- if clean_input.any?
34
- arguments = sanitize_arguments(clean_input.join(''))
35
- command[:arguments] = arguments
36
- end
37
-
38
- command
28
+ Parser.new.parse(line_input)
39
29
  end
40
30
 
41
31
  def execute(command)
42
- if command[:arguments].nil?
43
- @robot.send(command[:order])
44
- else
32
+ if command.key?(:arguments)
45
33
  @robot.send(command[:order], command[:arguments])
34
+ else
35
+ @robot.send(command[:order])
46
36
  end
47
37
  end
48
-
49
- private
50
-
51
- def sanitize_order(input_string)
52
- order = input_string.downcase.to_sym
53
- order if ALLOWED_ORDERS.include?(order)
54
- end
55
-
56
- def sanitize_arguments(arguments)
57
- arguments = arguments.delete(' ').split(',')
58
- { x: arguments[0], y: arguments[1], face: arguments[2] }
59
- end
60
38
  end
61
- end
39
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MauxRobot
4
+ module Formatter
5
+ def self.from(format_type)
6
+ case format_type
7
+ when :json
8
+ Formatter::Json.new
9
+ else
10
+ Formatter::Csv.new
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MauxRobot
4
+ module Formatter
5
+ class Csv
6
+ def generate(position)
7
+ "#{position.x},#{position.y},#{position.face.upcase}"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module MauxRobot
6
+ module Formatter
7
+ class Json
8
+ def generate(position)
9
+ JSON.generate(
10
+ x: position.x,
11
+ y: position.y,
12
+ face: position.face.upcase.to_s
13
+ )
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MauxRobot
4
+ class Parser
5
+ ALLOWED_ORDERS = %i[left right move place report verbose].freeze
6
+
7
+ def parse(line_input)
8
+ clean_input = line_input.strip.squeeze(" ").split(" ")
9
+ order = sanitize_order(clean_input.shift)
10
+ return unless order
11
+
12
+ command = {order: order}
13
+
14
+ if clean_input.any?
15
+ arguments = sanitize_arguments(order, clean_input.join(""))
16
+ command[:arguments] = arguments
17
+ end
18
+
19
+ command
20
+ end
21
+
22
+ private
23
+
24
+ def sanitize_order(input_string)
25
+ order = input_string.downcase.to_sym
26
+ order if ALLOWED_ORDERS.include?(order)
27
+ end
28
+
29
+ def sanitize_arguments(order, arguments)
30
+ case order
31
+ when :place
32
+ arguments = arguments.delete(" ").split(",")
33
+ {x: arguments[0], y: arguments[1], face: arguments[2]}
34
+ when :report
35
+ {format_type: arguments.downcase.to_sym}
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,22 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'maux_robot'
3
+ require "maux_robot"
4
4
 
5
5
  module MauxRobot
6
-
7
6
  # This class represents the Robot position on the table
8
7
  class Position
9
8
  attr_reader :x, :y, :face
10
9
 
11
- POSSIBLE_DIRECTIONS = [:north, :west, :south, :east]
10
+ POSSIBLE_DIRECTIONS = %i[north west south east].freeze
12
11
  POSSIBLE_MOVEMENTS = {
13
- north: { x: 0, y: 1 },
14
- west: { x: -1, y: 0 },
15
- south: { x: 0, y: -1 },
16
- east: { x: 1, y: 0 },
17
- }
12
+ north: {x: 0, y: 1},
13
+ west: {x: -1, y: 0},
14
+ south: {x: 0, y: -1},
15
+ east: {x: 1, y: 0}
16
+ }.freeze
18
17
 
19
- def initialize(x, y, face)
18
+ def initialize(x, y, face) # rubocop:disable Naming/UncommunicativeMethodParamName
20
19
  @x = x.to_i
21
20
  @y = y.to_i
22
21
  @face = face&.downcase&.to_sym || :invalid
@@ -26,24 +25,41 @@ module MauxRobot
26
25
  POSSIBLE_DIRECTIONS.include?(@face)
27
26
  end
28
27
 
29
- def turn_left
30
- next_direction_index = ( POSSIBLE_DIRECTIONS.index(@face) + 1 ) % 4
28
+ def left
29
+ return self unless valid_direction?
30
+
31
+ next_direction_index = (POSSIBLE_DIRECTIONS.index(@face) + 1) % 4
31
32
  @face = POSSIBLE_DIRECTIONS[next_direction_index]
32
33
  end
33
34
 
34
- def turn_right
35
- next_direction_index = ( POSSIBLE_DIRECTIONS.index(@face) - 1 )
35
+ def right
36
+ return self unless valid_direction?
37
+
38
+ next_direction_index = (POSSIBLE_DIRECTIONS.index(@face) - 1)
36
39
  @face = POSSIBLE_DIRECTIONS[next_direction_index]
37
40
  end
38
41
 
39
42
  def forward_position
43
+ return self unless valid_direction?
44
+
40
45
  x = @x + POSSIBLE_MOVEMENTS[@face][:x]
41
46
  y = @y + POSSIBLE_MOVEMENTS[@face][:y]
42
47
  Position.new(x, y, @face)
43
48
  end
44
49
 
45
- def to_s
46
- "#{@x},#{@y},#{@face.upcase.to_s}"
50
+ def report(format_type = :csv)
51
+ formatter = MauxRobot::Formatter.from(format_type)
52
+ puts formatter.generate(self)
53
+ end
54
+
55
+ def ==(other)
56
+ other.x == x && other.y == y && other.face == face
57
+ end
58
+ end
59
+
60
+ class NullPosition < Position
61
+ def initialize
62
+ super(nil, nil, nil)
47
63
  end
48
64
  end
49
- end
65
+ end
@@ -1,41 +1,91 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "forwardable"
4
+
3
5
  module MauxRobot
6
+ class RobotError < StandardError; end
7
+
8
+ # Error to notify that the robot was not placed yet
9
+ class RobotNotPlacedYet < RobotError
10
+ def initialize
11
+ super("The robot was not placed yet!")
12
+ end
13
+ end
14
+
15
+ # Error to notify that the position is/would be outside the table
16
+ class NotOkToGo < RobotError
17
+ def initialize(position)
18
+ super("It's not ok to go to #{position.x},#{position.y}")
19
+ end
20
+ end
4
21
 
5
22
  # The main class. It executes the actions using its table and position
6
23
  class Robot
7
- attr_reader :position
24
+ attr_reader :position, :talkative
8
25
 
9
- def initialize(table=MauxRobot::Table.new)
26
+ def initialize(table = MauxRobot::Table.new)
10
27
  @table = table
28
+ @position = MauxRobot::NullPosition.new
29
+ @talkative = false
11
30
  end
12
31
 
13
- def place(x:, y:, face:)
32
+ def place(x:, y:, face:) # rubocop:disable Naming/UncommunicativeMethodParamName
14
33
  position = MauxRobot::Position.new(x, y, face)
15
34
 
16
- if position.valid_direction? and @table.contains?(position)
35
+ ok_to_go?(position) do
17
36
  @position = position
18
37
  end
38
+ @position
39
+ end
40
+
41
+ def move
42
+ robot_placed? do
43
+ next_position = @position.forward_position
44
+
45
+ ok_to_go?(next_position) do
46
+ @position = next_position
47
+ end
48
+
49
+ @position
50
+ end
19
51
  end
20
52
 
21
53
  def left
22
- @position&.turn_left
54
+ robot_placed? do
55
+ @position.left
56
+ end
23
57
  end
24
58
 
25
59
  def right
26
- @position&.turn_right
60
+ robot_placed? do
61
+ @position.right
62
+ end
27
63
  end
28
64
 
29
- def move
30
- next_position = @position.forward_position
31
-
32
- if @table.contains?(next_position)
33
- @position = next_position
65
+ def report(format_type: :csv)
66
+ robot_placed? do
67
+ @position.report(format_type)
34
68
  end
35
69
  end
36
70
 
37
- def report
38
- puts @position if @position
71
+ def verbose
72
+ @talkative = !@talkative
73
+ is_not = @talkative ? "is" : "is not"
74
+ puts "Robot #{is_not} talkative now."
75
+ end
76
+
77
+ private
78
+
79
+ def ok_to_go?(position)
80
+ raise NotOkToGo, position unless @table.contains?(position)
81
+
82
+ yield
83
+ end
84
+
85
+ def robot_placed?
86
+ raise RobotNotPlacedYet if @position.class == MauxRobot::NullPosition
87
+
88
+ yield
39
89
  end
40
90
  end
41
- end
91
+ end
@@ -1,16 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MauxRobot
4
-
5
4
  # This class represents a table according to simulation rules
6
5
  class Table
7
- def initialize(x: [0, 4], y: [0, 4])
6
+ def initialize(x: [0, 4], y: [0, 4]) # rubocop:disable Naming/UncommunicativeMethodParamName
8
7
  @x = x
9
8
  @y = y
10
9
  end
11
10
 
12
11
  def contains?(position)
13
- position.x.between?(@x[0], @x[1]) &&
12
+ position.valid_direction? &&
13
+ position.x.between?(@x[0], @x[1]) &&
14
14
  position.y.between?(@y[0], @y[1])
15
15
  end
16
16
  end
@@ -3,14 +3,14 @@
3
3
  module MauxRobot
4
4
  # This module holds the MauxRobot version information.
5
5
  module Version
6
- STRING = '0.0.2'.freeze
6
+ STRING = "0.2.0"
7
7
 
8
- MSG = '%s (using Parser %s, running on %s %s %s)'.freeze
8
+ MSG = "%s (using Parser %s, running on %s %s %s)"
9
9
 
10
10
  def self.version(debug = false)
11
11
  if debug
12
12
  format(MSG, STRING, Parser::VERSION,
13
- RUBY_ENGINE, RUBY_VERSION, RUBY_PLATFORM)
13
+ RUBY_ENGINE, RUBY_VERSION, RUBY_PLATFORM)
14
14
  else
15
15
  STRING
16
16
  end
@@ -1,71 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'maux_robot'
3
+ require "maux_robot"
4
4
 
5
5
  describe MauxRobot::CLI do
6
- describe '#parse' do
7
- context 'valid orders' do
8
- it '#report' do
9
- expect(subject.parse('REPORT')).to eq(order: :report)
10
- end
11
-
12
- it '#move' do
13
- expect(subject.parse('MOVE')).to eq(order: :move)
14
- end
15
-
16
- it '#left' do
17
- expect(subject.parse('LEFT')).to eq(order: :left)
18
- end
19
-
20
- it '#right' do
21
- expect(subject.parse('RIGHT')).to eq(order: :right)
22
- end
23
-
24
- it '#place' do
25
- expect(subject.parse('PLACE 0,3,WEST')).to eq(order: :place, arguments: { x: '0', y: '3', face: 'WEST' })
26
- end
27
- end
28
-
29
- context 'orders with spaces and downcase' do
30
- it '#report' do
31
- expect(subject.parse(' repoRT')).to eq(order: :report)
32
- end
6
+ subject(:cli) { described_class.new }
33
7
 
34
- it '#move' do
35
- expect(subject.parse('move ')).to eq(order: :move)
36
- end
37
-
38
- it '#left' do
39
- expect(subject.parse(' LefT ')).to eq(order: :left)
40
- end
41
-
42
- it '#right' do
43
- expect(subject.parse(' rigHt')).to eq(order: :right)
44
- end
45
-
46
- it '#place' do
47
- expect(subject.parse('PLACE 2 , 1 , NOrth')).to eq(order: :place, arguments: { x: '2', y: '1', face: 'NOrth' })
48
- end
49
- end
50
-
51
- it 'ignores anything else' do
52
- expect(subject.parse('blablabla balbla')).to eq(order: nil)
53
- end
54
- end
8
+ describe "#execute" do
9
+ let(:position) { MauxRobot::Position.new(0, 2, :east) }
55
10
 
56
- describe '#execute' do
57
- context 'commands without arguments' do
58
- it 'sends proper message to robot' do
59
- expect(subject.robot).to receive(:move)
60
- subject.execute(order: :move)
11
+ context "when input is parsed without arguments" do
12
+ it "sends proper message to robot" do
13
+ allow(cli.robot).to receive(:move).and_return(position)
14
+ expect(cli.execute(order: :move)).to eq(position)
61
15
  end
62
16
  end
63
17
 
64
- context 'place' do
65
- it 'send place command along with arguments' do
66
- expect(subject.robot).to receive(:place).with(x: '0', y: '2', face: 'EAST')
67
- subject.execute(order: :place, arguments: { x: '0', y: '2', face: 'EAST' })
18
+ context "when place is parsed command with arguments" do
19
+ it "sends proper message to robot" do
20
+ expect(cli.execute(order: :place, arguments: {x: "0", y: "2", face: "EAST"})).to eq(position)
68
21
  end
69
22
  end
70
23
  end
71
- end
24
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe MauxRobot::Formatter::Csv do
4
+ let(:position) { MauxRobot::Position.new(1, 2, :west) }
5
+
6
+ describe "#generate" do
7
+ subject(:csv_formatter) { described_class.new }
8
+
9
+ it "Formats a position as CSV" do
10
+ expect(csv_formatter.generate(position)).to eq("1,2,WEST")
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe MauxRobot::Formatter::Json do
4
+ let(:position) { MauxRobot::Position.new(1, 2, :west) }
5
+
6
+ describe "#generate" do
7
+ subject(:json_formatter) { described_class.new }
8
+
9
+ it "Formats a position as JSON" do
10
+ expect(json_formatter.generate(position)).to eq('{"x":1,"y":2,"face":"WEST"}')
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe MauxRobot::Formatter do
4
+ subject(:formatter) { described_class }
5
+
6
+ describe "#from" do
7
+ describe "valid format_types" do
8
+ it "returns csv formatter" do
9
+ expect(formatter.from(:csv).class).to eq(MauxRobot::Formatter::Csv)
10
+ end
11
+
12
+ it "returns json formatter" do
13
+ expect(formatter.from(:json).class).to eq(MauxRobot::Formatter::Json)
14
+ end
15
+ end
16
+
17
+ describe "invalid format_types" do
18
+ it "defaults to csv formatter" do
19
+ expect(formatter.from(:anything).class).to eq(MauxRobot::Formatter::Csv)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Metrics/BlockLength
4
+ describe MauxRobot::Parser do
5
+ subject(:parser) { described_class.new }
6
+
7
+ describe "#parse" do
8
+ context "with valid orders" do
9
+ it "#report" do
10
+ expect(parser.parse("REPORT")).to eq(order: :report)
11
+ end
12
+
13
+ it "#report csv" do
14
+ expect(parser.parse("REPORT CSV")).to eq(order: :report, arguments: {format_type: :csv})
15
+ end
16
+
17
+ it "#report json" do
18
+ expect(parser.parse("REPORT JSON")).to eq(order: :report, arguments: {format_type: :json})
19
+ end
20
+
21
+ it "#move" do
22
+ expect(parser.parse("MOVE")).to eq(order: :move)
23
+ end
24
+
25
+ it "#left" do
26
+ expect(parser.parse("LEFT")).to eq(order: :left)
27
+ end
28
+
29
+ it "#right" do
30
+ expect(parser.parse("RIGHT")).to eq(order: :right)
31
+ end
32
+
33
+ it "#verbose" do
34
+ expect(parser.parse("VERBOSE")).to eq(order: :verbose)
35
+ end
36
+
37
+ it "#place" do
38
+ expect(parser.parse("PLACE 0,3,WEST")).to eq(order: :place, arguments: {x: "0", y: "3", face: "WEST"})
39
+ end
40
+ end
41
+
42
+ context "with orders with spaces and downcase" do
43
+ it "#report" do
44
+ expect(parser.parse(" repoRT")).to eq(order: :report)
45
+ end
46
+
47
+ it "#move" do
48
+ expect(parser.parse("move ")).to eq(order: :move)
49
+ end
50
+
51
+ it "#left" do
52
+ expect(parser.parse(" LefT ")).to eq(order: :left)
53
+ end
54
+
55
+ it "#right" do
56
+ expect(parser.parse(" rigHt")).to eq(order: :right)
57
+ end
58
+
59
+ it "#place" do
60
+ expect(parser.parse("PLACE 2 , 1 , NOrth")).to eq(
61
+ order: :place, arguments: {x: "2", y: "1", face: "NOrth"}
62
+ )
63
+ end
64
+ end
65
+
66
+ context "with invalid orders" do
67
+ it "ignores anything else" do
68
+ expect(parser.parse("blablabla balbla")).to be_nil
69
+ end
70
+ end
71
+ end
72
+ end
73
+ # rubocop:enable Metrics/BlockLength
@@ -1,12 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'maux_robot'
4
-
3
+ # rubocop:disable Metrics/BlockLength:
5
4
  describe MauxRobot::Position do
6
- describe '#initialize' do
7
- context 'given text input' do
8
- it 'should normalize arguments' do
9
- position = MauxRobot::Position.new('0', '1', 'SOUTH')
5
+ describe "#initialize" do
6
+ context "when text input is given" do
7
+ it "normalizes arguments" do
8
+ position = described_class.new("0", "1", "SOUTH")
10
9
 
11
10
  expect(position.x).to eq(0)
12
11
  expect(position.y).to eq(1)
@@ -15,65 +14,65 @@ describe MauxRobot::Position do
15
14
  end
16
15
  end
17
16
 
18
- describe '#valid_direction?' do
19
- context 'given a possible diretion' do
20
- it 'should be valid' do
21
- position = MauxRobot::Position.new(5, 0, :south)
17
+ describe "#valid_direction?" do
18
+ context "when a possible diretion is given" do
19
+ it "is valid" do
20
+ position = described_class.new(5, 0, :south)
22
21
 
23
22
  expect(position.valid_direction?).to eq(true)
24
23
  end
25
24
  end
26
25
 
27
- context 'given a not possible direction' do
28
- it 'should not be valid ' do
29
- position = MauxRobot::Position.new(1, 1, :south_west)
26
+ context "when a not possible direction is given" do
27
+ it "is not valid " do
28
+ position = described_class.new(1, 1, :south_west)
30
29
 
31
30
  expect(position.valid_direction?).to eq(false)
32
31
  end
33
32
  end
34
33
  end
35
34
 
36
- describe 'rotation' do
37
- let(:position) { MauxRobot::Position.new(2, 2, :north) }
35
+ describe "rotation" do
36
+ let(:position) { described_class.new(2, 2, :north) }
38
37
 
39
- context '#turn_left' do
40
- it 'should rotate counter-clockwise' do
41
- position.turn_left
38
+ describe "#left" do
39
+ it "rotates counter-clockwise" do
40
+ position.left
42
41
  expect(position.face).to eq(:west)
43
42
 
44
- position.turn_left
43
+ position.left
45
44
  expect(position.face).to eq(:south)
46
45
 
47
- position.turn_left
46
+ position.left
48
47
  expect(position.face).to eq(:east)
49
48
 
50
- position.turn_left
49
+ position.left
51
50
  expect(position.face).to eq(:north)
52
51
  end
53
52
  end
54
53
 
55
- context '#turn_right' do
56
- it 'should rotate clockwise' do
57
- position.turn_right
54
+ describe "#right" do
55
+ it "rotates clockwise" do
56
+ position.right
58
57
  expect(position.face).to eq(:east)
59
58
 
60
- position.turn_right
59
+ position.right
61
60
  expect(position.face).to eq(:south)
62
61
 
63
- position.turn_right
62
+ position.right
64
63
  expect(position.face).to eq(:west)
65
64
 
66
- position.turn_right
65
+ position.right
67
66
  expect(position.face).to eq(:north)
68
67
  end
69
68
  end
70
69
  end
71
70
 
72
- describe '#forward_position' do
73
- context 'facing north' do
74
- let(:position) { MauxRobot::Position.new(5, 0, :north) }
71
+ describe "#forward_position" do # rubocop:disable Metrics/BlockLength
72
+ context "when facing north" do
73
+ let(:position) { described_class.new(5, 0, :north) }
75
74
 
76
- it 'should return a new position 1 step upwards' do
75
+ it "returns a new position 1 step upwards" do
77
76
  new_position = position.forward_position
78
77
  expect(position.x).to eq(5)
79
78
  expect(position.y).to eq(0)
@@ -82,10 +81,10 @@ describe MauxRobot::Position do
82
81
  end
83
82
  end
84
83
 
85
- context 'facing west' do
86
- let(:position) { MauxRobot::Position.new(2, 1, :west) }
84
+ context "when facing west" do
85
+ let(:position) { described_class.new(2, 1, :west) }
87
86
 
88
- it 'should return a new position 1 step leftwards' do
87
+ it "returns a new position 1 step leftwards" do
89
88
  new_position = position.forward_position
90
89
  expect(position.x).to eq(2)
91
90
  expect(position.y).to eq(1)
@@ -94,10 +93,10 @@ describe MauxRobot::Position do
94
93
  end
95
94
  end
96
95
 
97
- context 'facing south' do
98
- let(:position) { MauxRobot::Position.new(1, 3, :south) }
96
+ context "when facing south" do
97
+ let(:position) { described_class.new(1, 3, :south) }
99
98
 
100
- it 'should return a new position 1 step downwards' do
99
+ it "returns a new position 1 step downwards" do
101
100
  new_position = position.forward_position
102
101
  expect(position.x).to eq(1)
103
102
  expect(position.y).to eq(3)
@@ -106,10 +105,10 @@ describe MauxRobot::Position do
106
105
  end
107
106
  end
108
107
 
109
- context 'facing east' do
110
- let(:position) { MauxRobot::Position.new(2, 0, :east) }
108
+ context "when facing east" do
109
+ let(:position) { described_class.new(2, 0, :east) }
111
110
 
112
- it 'should return a new position 1 step rightwards' do
111
+ it "returns a new position 1 step rightwards" do
113
112
  new_position = position.forward_position
114
113
  expect(position.x).to eq(2)
115
114
  expect(position.y).to eq(0)
@@ -119,26 +118,30 @@ describe MauxRobot::Position do
119
118
  end
120
119
  end
121
120
 
122
- describe '#to_s' do
123
- context 'if x, y and face are defined' do
124
- let(:position) { MauxRobot::Position.new(5, 0, :north) }
125
- it 'returns X,Y,FACE' do
126
- expect(position.to_s).to eq('5,0,NORTH')
121
+ describe "#report" do
122
+ context "when x, y and face are defined" do
123
+ let(:position) { described_class.new(5, 0, :north) }
124
+
125
+ it "prints X,Y,FACE" do
126
+ expect { position.report }.to output("5,0,NORTH\n").to_stdout
127
127
  end
128
128
  end
129
129
 
130
- context 'if only face is defined' do
131
- let(:position) { MauxRobot::Position.new(nil, nil, 'SOUTH') }
132
- it 'returns 0,0,FACE' do
133
- expect(position.to_s).to eq('0,0,SOUTH')
130
+ context "when only face is defined" do
131
+ let(:position) { described_class.new(nil, nil, "SOUTH") }
132
+
133
+ it "prints 0,0,FACE" do
134
+ expect { position.report }.to output("0,0,SOUTH\n").to_stdout
134
135
  end
135
136
  end
136
137
 
137
- context 'if face is not defined' do
138
- let(:position) { MauxRobot::Position.new(5, 0, nil) }
139
- it 'returns X,Y,INVALID' do
140
- expect(position.to_s).to eq('5,0,INVALID')
138
+ context "when face is not defined" do
139
+ let(:position) { described_class.new(5, 0, nil) }
140
+
141
+ it "prints X,Y,INVALID" do
142
+ expect { position.report }.to output("5,0,INVALID\n").to_stdout
141
143
  end
142
144
  end
143
145
  end
144
146
  end
147
+ # rubocop:enable Metrics/BlockLength:
@@ -1,48 +1,42 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'maux_robot'
4
-
5
- describe MauxRobot::Robot do
3
+ describe MauxRobot::Robot do # rubocop:disable Metrics/BlockLength
6
4
  subject(:robot) { described_class.new }
7
5
 
8
- describe '#place' do
9
- context 'given a valid place' do
10
- it 'should have a position' do
6
+ let(:null_position) { MauxRobot::NullPosition.new }
7
+
8
+ describe "#place" do
9
+ context "when given a valid place" do
10
+ it "has a position" do
11
11
  robot.place(x: 0, y: 0, face: :north)
12
12
 
13
- expect(robot.position).not_to be_nil
13
+ expect(robot.position).not_to eq null_position
14
14
  end
15
15
  end
16
16
 
17
- context 'given an invalid place' do
18
- it 'should not have a position' do
19
- robot.place(x: 5, y: 0, face: :south)
20
-
21
- expect(robot.position).to be_nil
17
+ context "when given an invalid place" do
18
+ it "raises NotOkToGo error" do
19
+ expect { robot.place(x: 5, y: 0, face: :south) }.to raise_error MauxRobot::NotOkToGo
22
20
  end
23
21
  end
24
22
 
25
- context 'given an invalid direction' do
26
- it 'should not have a position' do
27
- robot.place(x: 0, y: 2, face: :south_east)
28
-
29
- expect(robot.position).to be_nil
23
+ context "when given an invalid direction" do
24
+ it "raises NotOkToGo error" do
25
+ expect { robot.place(x: 0, y: 2, face: :south_east) }.to raise_error MauxRobot::NotOkToGo
30
26
  end
31
27
  end
32
28
  end
33
29
 
34
- describe '#left' do
35
- context 'robot not placed' do
36
- it 'should silently ignore' do
37
- robot.place(x: 0, y: 2, face: :south_east)
38
- robot.left
39
-
40
- expect(robot.position).to be_nil
30
+ describe "#left" do
31
+ context "when robot is not placed" do
32
+ it "raises RobotNotPlacedYet error" do
33
+ expect { robot.left }.to raise_error MauxRobot::RobotNotPlacedYet
34
+ expect(robot.position).to eq null_position
41
35
  end
42
36
  end
43
37
 
44
- context 'robot placed' do
45
- it 'should rotate accordingly' do
38
+ context "when robot is placed" do
39
+ it "rotates accordingly" do
46
40
  robot.place(x: 1, y: 2, face: :south)
47
41
  robot.left
48
42
 
@@ -51,18 +45,17 @@ describe MauxRobot::Robot do
51
45
  end
52
46
  end
53
47
 
54
- describe '#right' do
55
- context 'robot not placed' do
56
- it 'should silently ignore' do
57
- robot.place(x: 0, y: 2, face: :north_west)
58
- robot.right
48
+ describe "#right" do
49
+ context "when robot is not placed" do
50
+ it "raises RobotNotPlacedYet error" do
51
+ expect { robot.right }.to raise_error MauxRobot::RobotNotPlacedYet
59
52
 
60
- expect(robot.position).to be_nil
53
+ expect(robot.position).to eq null_position
61
54
  end
62
55
  end
63
56
 
64
- context 'robot placed' do
65
- it 'should rotate accordingly' do
57
+ context "with robot placed" do
58
+ it "rotates accordingly" do
66
59
  robot.place(x: 3, y: 2, face: :north)
67
60
  robot.right
68
61
 
@@ -71,9 +64,16 @@ describe MauxRobot::Robot do
71
64
  end
72
65
  end
73
66
 
74
- describe '#move' do
75
- context 'to a place on the table' do
76
- it 'should update its position' do
67
+ describe "#move" do
68
+ context "with robot not placed" do
69
+ it "raises RobotNotPlacedYet error" do
70
+ expect { robot.right }.to raise_error MauxRobot::RobotNotPlacedYet
71
+ expect(robot.position).to eq null_position
72
+ end
73
+ end
74
+
75
+ context "when placing on the table" do
76
+ it "updates its position" do
77
77
  robot.place(x: 3, y: 2, face: :north)
78
78
  robot.move
79
79
 
@@ -83,10 +83,11 @@ describe MauxRobot::Robot do
83
83
  end
84
84
  end
85
85
 
86
- context 'to outside the table' do
87
- it 'should stay where it is' do
86
+ context "when outside the table" do
87
+ it "stays where it is" do
88
88
  robot.place(x: 0, y: 0, face: :south)
89
- robot.move
89
+
90
+ expect { robot.move }.to raise_error MauxRobot::NotOkToGo
90
91
 
91
92
  expect(robot.position.x).to eq(0)
92
93
  expect(robot.position.y).to eq(0)
@@ -1,17 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'maux_robot'
4
-
5
3
  describe MauxRobot::Table do
6
4
  subject(:table) { described_class.new(x: [-1, 2], y: [3, 6]) }
7
5
 
8
- context '#contains?' do
9
- it 'should contain a position inside boundaries' do
6
+ describe "#contains?" do
7
+ it "contains a position inside boundaries" do
10
8
  position = MauxRobot::Position.new(0, 4, :north)
11
9
  expect(table.contains?(position)).to be true
12
10
  end
13
11
 
14
- it 'should not contain a position outside boundaries' do
12
+ it "does not contain a position outside boundaries" do
15
13
  position = MauxRobot::Position.new(3, 2, :east)
16
14
  expect(table.contains?(position)).to be false
17
15
  end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.unshift("#{__dir__}/../lib")
4
+
5
+ require "maux_robot"
metadata CHANGED
@@ -1,35 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: maux_robot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mauricio Vieira
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-18 00:00:00.000000000 Z
11
+ date: 2020-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rspec
14
+ name: standard
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '3.6'
20
- - - ">="
21
- - !ruby/object:Gem::Version
22
- version: 3.6.0
19
+ version: 0.4.7
23
20
  type: :development
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
26
23
  requirements:
27
24
  - - "~>"
28
25
  - !ruby/object:Gem::Version
29
- version: '3.6'
30
- - - ">="
31
- - !ruby/object:Gem::Version
32
- version: 3.6.0
26
+ version: 0.4.7
33
27
  description: " Maux version of a Toy Robot Simulator.\n"
34
28
  email: maux_robot@mauriciovieira.net
35
29
  executables:
@@ -44,19 +38,28 @@ files:
44
38
  - bin/maux_robot
45
39
  - lib/maux_robot.rb
46
40
  - lib/maux_robot/cli.rb
41
+ - lib/maux_robot/formatter.rb
42
+ - lib/maux_robot/formatter/csv.rb
43
+ - lib/maux_robot/formatter/json.rb
44
+ - lib/maux_robot/parser.rb
47
45
  - lib/maux_robot/position.rb
48
46
  - lib/maux_robot/robot.rb
49
47
  - lib/maux_robot/table.rb
50
48
  - lib/maux_robot/version.rb
51
49
  - spec/maux_robot/cli_spec.rb
50
+ - spec/maux_robot/formatter/csv_spec.rb
51
+ - spec/maux_robot/formatter/json_spec.rb
52
+ - spec/maux_robot/formatter_spec.rb
53
+ - spec/maux_robot/parser_spec.rb
52
54
  - spec/maux_robot/position_spec.rb
53
55
  - spec/maux_robot/robot_spec.rb
54
56
  - spec/maux_robot/table_spec.rb
57
+ - spec/spec_helper.rb
55
58
  homepage: https://github.com/mauriciovieira/maux_robot
56
59
  licenses:
57
60
  - GPL-3.0
58
61
  metadata:
59
- homepage_uri: https://rubocop.readthedocs.io/
62
+ homepage_uri: https://github.com/mauriciovieira/maux_robot/blob/master/README.md
60
63
  changelog_uri: https://github.com/mauriciovieira/maux_robot/blob/master/CHANGELOG.md
61
64
  source_code_uri: https://github.com/mauriciovieira/maux_robot/
62
65
  documentation_uri: https://github.com/mauriciovieira/maux_robot/
@@ -69,15 +72,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
69
72
  requirements:
70
73
  - - ">="
71
74
  - !ruby/object:Gem::Version
72
- version: 2.0.0
75
+ version: 2.6.0
73
76
  required_rubygems_version: !ruby/object:Gem::Requirement
74
77
  requirements:
75
78
  - - ">="
76
79
  - !ruby/object:Gem::Version
77
80
  version: '0'
78
81
  requirements: []
79
- rubyforge_project:
80
- rubygems_version: 2.6.12
82
+ rubygems_version: 3.0.3
81
83
  signing_key:
82
84
  specification_version: 4
83
85
  summary: Maux version of a Toy Robot Simulator.