From b25ad1e70ad62a7538de0750853e1998b0961bbc Mon Sep 17 00:00:00 2001 From: Mohnish G J Date: Sun, 30 Jun 2024 20:05:02 +0200 Subject: [PATCH] Refactor code further & update README - Navigating the steps in the path is the Responsibility of the Path class - Vehicle clan send a message to the specified vehicle which in this case is Rover to accordingly turn left, or right - Update README to see how the app is fairing with regard to its flog score with regard to different methods and compare that with a reference point as per the blog here: https://jakescruggs.blogspot.com/2008/08/whats-good-flog-score.html --- README.md | 7 ++++++- lib/path.rb | 17 +++++++++++++++++ lib/rover.rb | 43 +++++++++++++++++------------------------- spec/lib/path_spec.rb | 23 ++++++++++++++++++++++ spec/lib/rover_spec.rb | 10 ++++++++++ 5 files changed, 73 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 1267ba4..02833f4 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,12 @@ ## About -Based on the given [problem statement](https://github.com/boddhisattva/mars_rover/blob/main/problem_statement.md), this is a program that calculates a rovers final position after traversing along a given path within a certain terrain(in this case its a Rectangular plateau). One can see how the sample output looks like from the [program output](https://github.com/boddhisattva/mars_rover/blob/master/README.md#program-output) section +Based on [this problem statement](https://github.com/boddhisattva/mars_rover/blob/main/problem_statement.md), this program calculates a rovers final position after traversing a given path within a terrain. +* [Code related design decisions](https://github.com/boddhisattva/mars_rover/?tab=readme-ov-file#code-related-design-decisions) gives a high level overview of the **approach & thought process** behind the solution +* This program also uses the **Flog metric** to observe scores of individual methods. + * I make use of the blog: [What's a Good Flog Score?](https://jakescruggs.blogspot.com/2008/08/whats-good-flog-score.html) as a reference to see how the written code is currently fairing + * In the entire app, the method `Path#navigate_steps` has the **highest complexity score** of **10.8** +* One can see how the sample output looks like from the [program output](https://github.com/boddhisattva/mars_rover/blob/master/README.md#program-output) section ## Code related design decisions diff --git a/lib/path.rb b/lib/path.rb index 7476ff4..95d8051 100644 --- a/lib/path.rb +++ b/lib/path.rb @@ -11,5 +11,22 @@ def initialize(steps) @steps = steps end + def navigate_steps(vehicle, current_direction) + steps.each_char do |step| + case step + when LEFT + current_direction = vehicle.turn_left(current_direction) + when RIGHT + current_direction = vehicle.turn_right(current_direction) + when MOVE + current_direction.move(vehicle.get_current_position) + else + raise InvalidStepError, 'Invalid step in path' + end + end + end + + private + attr_reader :steps end diff --git a/lib/rover.rb b/lib/rover.rb index 1ba016e..2ded721 100644 --- a/lib/rover.rb +++ b/lib/rover.rb @@ -11,10 +11,6 @@ class InvalidStepError < StandardError; end require_relative 'west' class Rover - def initialize(current_position) - @current_position = current_position - end - COMPASS_DIRECTION = { 'N' => 'North', 'S' => 'South', @@ -22,33 +18,20 @@ def initialize(current_position) 'E' => 'East' }.freeze - def traverse(path) - current_direction = original_direction - - path.steps.each_char do |step| - case step - when Path::LEFT - current_direction = turn_left(current_direction) - when Path::RIGHT - current_direction = turn_right(current_direction) - when Path::MOVE - current_direction.move(current_position) - else - raise InvalidStepError, 'Invalid step in path' - end - end + def initialize(current_position) + @current_position = current_position end - def current_location - current_position.location + def get_current_position + current_position end - private - - attr_reader :current_position + def traverse(path) + path.navigate_steps(self, original_direction) + end - def original_direction - Object.const_get(COMPASS_DIRECTION[current_position.get_orientation]).new + def current_location + current_position.location end def turn_left(current_direction) @@ -62,4 +45,12 @@ def turn_right(current_direction) current_position.set_orientation(current_direction.short_form) current_direction end + + private + + attr_reader :current_position + + def original_direction + Object.const_get(COMPASS_DIRECTION[current_position.get_orientation]).new + end end diff --git a/spec/lib/path_spec.rb b/spec/lib/path_spec.rb index 2ef2896..42b4a28 100644 --- a/spec/lib/path_spec.rb +++ b/spec/lib/path_spec.rb @@ -12,4 +12,27 @@ it 'has a MOVE constant' do expect(Path::MOVE).to eq('M') end + + describe '#navigate_steps' do + let(:terrain) { RectangularPlateau.new(0, 0, 5, 5) } + + context 'when a vehicle pointing in a specific direction has a path to navigate' do + it 'navigates each step within that path' do + path1 = described_class.new('LMLMLMLMM') + rover1 = Rover.new(Position.new(1, 2, 'N', terrain)) + path1.navigate_steps(rover1, North.new) + + expect(rover1.current_location).to eq('1 3 N') + end + end + + context 'when a vehicle travels through an invalid path in a given terrain' do + it 'returns an Invalid Step Error error with an appropriate error message related to an invalid step' do + path1 = described_class.new('LMLMLSMLMM') + rover1 = Rover.new(Position.new(1, 2, 'N', terrain)) + + expect { path1.navigate_steps(rover1, North.new) }.to raise_error(InvalidStepError, 'Invalid step in path') + end + end + end end diff --git a/spec/lib/rover_spec.rb b/spec/lib/rover_spec.rb index 59f0641..9405397 100644 --- a/spec/lib/rover_spec.rb +++ b/spec/lib/rover_spec.rb @@ -50,6 +50,16 @@ end end + describe '#get_current_position' do + it 'returns the current compass based position of a given entity' do + rover1 = described_class.new(Position.new(1, 2, 'N', terrain)) + + expect(rover1.get_current_position.x_coordinate).to eq(1) + expect(rover1.get_current_position.y_coordinate).to eq(2) + expect(rover1.get_current_position.orientation).to eq('N') + end + end + describe '#current_location' do context 'when given a rover that is present at a specified position' do it 'returns the current location of that rover' do