Toy Robot

August 2017 · 8 minute read


I have recently challenged my skills with the infamous toy robot simulator challenge and thought it would be great to document my thought process throughout the build. Not only can other see how I’ve gone about moving from A to B, but I can also gain a better insight into my own processes.

The completed project can be viewed at https://github.com/SelenaSmall/toy_robot

Planning

Research

The criteria for this program rings a bell, so the first thing I’m going to do is look back through some of own work to review two projects I’ve started working on in the past which can be directly useful to this challenge.

Approach

The first thing I’ve done is made some notes about what I’m trying to achieve. How the app might be structured and where methods might occur within that structure.

What methods belong where:

Table

5x5 square

valid input coordinates x & y == 0..4

User

Input value

  Valid if == “PLACE X,Y,F” || “MOVE” || “LEFT” || RIGHT” || “REPORT”

  X & Y == INT (0..4)

  F == “NORTH” || “SOUTH” || “EAST” || “WEST”

Robot

Initialised at position == NULL*

PLACE

  Place robot on table at position x,y,f

  Check: Is the position valid?

MOVE

      Move forward 1 space in the direction I am facing

      Check: If I move forward, will the new position be valid?

LEFT

      Turn 90 degress to left

RIGHT

      Turn 90 degrees to right

REPORT

      output current coordinates

App Structure

- /lib
	- table.rb		(define table vars)
	- robot.rb		(define robot vars)
	- position.rb		(define robots position on the table)
	- place.rb		(place robot and validate the new position is valid)
	- handle_input.rb	(manage the place and move commands)
	- direction.rb		(manage the robots facing direction)
	- move.rb		(move robot to new coordinates if new position is valid)
	- report.rb		(print our report data)
- /spec
- .rspec
- .ruby-version
- toy_robot.rb
- Gemfile
- Gemfile.lock
- README.md

Building

Initialise Repo

First thing with any project, of course is to create a new repo on Github with a README.md, clone it to your local and you’re good to go!

https://github.com/SelenaSmall/toy_robot/commit/faf4935ed424bcade17142f3ee2916794e3ca954


Directory Structure

I’ve already thought about how the app will structured, so I can start by generating the appropriate root files.

- Create a .ruby-version file
- Create Gemfile with rspec spec
- Generate your gemfile.lock $ gem install bundle && bundle install
- Initialise Rspec $ rspec --init
- Create the lib dir for the project files
- Create the project root file toy_robot.rb

Table class

First thing I think of is that I need a table to put the robot on. For this I simply need to specify an area that is 5x5. Now is also a good time add in a simple validation checking that any position on the table is within that 5x5 area.

https://github.com/SelenaSmall/toy_robot/commit/f5bb3b58b578a7ddf780d424215df76ee2f03cd1


User Input

For me, I like to have some sort of visuals so the next thing I’ll do is initialise the main loop to get user inputs. I’ve don’t this before both with the Elevator and Ordering programs I wrote when I was learning Ruby, so it should be a breeze.

https://github.com/SelenaSmall/toy_robot/commit/f03ae4b51dc9ced1b9d882b5710ee7065b68b479


!!! TESTING SHOULD START HERE !!!

Now that I have a table class and loop for reading user inputs that work successfully, it’s time to start testing!

The rest of the project will be test-driven, meaning I will try to write tests ahead of or at the same time as code. I will then ensure that all existing tests pass before committing anything else to my repo.

https://github.com/SelenaSmall/toy_robot/commit/8a6b7dffcc998baae67b94be603524802637b411


Robot class

I’ll now need to define a robot to be ‘placed’ on the table. The first thing I’ll need to know is what coordinates (x & y) is the robot being place at?

https://github.com/SelenaSmall/toy_robot/commit/b52bc1d8e4fd3081ffb19214552732df3b74f3e0


Position class

I need to define position coordinates x, y and update the robot’s position when a user inputs “PLACE x,y”

- Define position coordinates x and y
- Update robot.position
- Check that the robot’s position is now not nil

https://github.com/SelenaSmall/toy_robot/commit/0f842b78c4f83ba5d779937653bd6b972e70b0c4


Validate position

The only way to be sure that the robot’s new position is valid within the table’s 5x5 area is to check it against the Table#is_valid method.

https://github.com/SelenaSmall/toy_robot/commit/b39456f4fc8a632a678e8856b60792641c9e7f3f


HandleInput class

I need to handle user inputs and ensure the commands being parsed are valid

- Array of valid command patterns
- Match input to one of those patterns

- If input matches, do the action
- else return

- if robot.not_in_place? 
- the only valid command is ‘place’

https://github.com/SelenaSmall/toy_robot/commit/6809289affa0c1966e7dcece90eec81aa0581286


Place method

One of the criteria for ‘placing’ a robot is to also tell it what direction it needs to be facing. I’ll start by updating the test code to expect a direction - this will help me quickly pinpoint the locations that need to be updated through out my code base.

https://github.com/SelenaSmall/toy_robot/commit/c41c00481121fdcf16b7457cf6fb815fcbafcb4b


Direction class

I’m not sure yet how the #left and #right methods are going to fit in with the rest of the app, so I’ll start by defining an array of valid directions which I will iterate over to get the next or previous value, depending on which starting position was parsed.

- Define turn_right to check that the direction is valid and locate that direction in the directions_array
- Find the index of the current direction in the directions_array
- Iterate the directions_array to find the next direction’s value

https://github.com/SelenaSmall/toy_robot/commit/92324acfd6e5290c5a90dc040138540ceb8bf8a5


Right turn method

The right method needs to check whether the current direction is the last item in the array, if it is I can instead simply return the first value in the directions_array.

- Check if the current direction is the last value in the array
    * If it is the next direction will be the first value in the array.

Once the turn right method is working, I can then integrate my direction class with user inputs to update the robot’s position when the right command is parsed.

https://github.com/SelenaSmall/toy_robot/commit/ce8603d08969f874449279867628eafbeaa1756e


Left turn method

Essentially the reverse of the right_turn method. I can also refactor here since two methods are almost identical.

- Define turn_left method ( essentially the reverse of turn_right )
- Refactor theses two methods to increase flexibility

https://github.com/SelenaSmall/toy_robot/commit/de39a04f72f4c9a6864b484ce92fca8072361fe7


Move method

To move the object, I’ll need to know: What is my current position, made up of x,y,f and what are the rules for moving in each direction?

- If direction == North
- x stays the same
- y increase by 1

- If direction == East
- x increases by 1
- y stays the same

- If direction == South
- x stays the same
- y decreases by 1

- If direction == West
- x decreases by 1
- y stays the same

https://github.com/SelenaSmall/toy_robot/commit/fa0d47d0cd1d486dbf5aa0d02e577fdca5088e6b


Report method

The report method simply needs to display the current position of the robot at the time when when the method is called.

https://github.com/SelenaSmall/toy_robot/commit/133c78084ccc483b6c52e22c26b12ea5c5b09d9f


User Testing

Having implemented all of the spec features and ensured that the tests pass, I have reviewed the specs and tested the program manually to ensure everything is working as it should. I’ve found an issue where the MOVE action returns a false position validation but still updates the robot position.

To fix this, the best solution is to break down the problem and code to see where it’s going wrong. At this point, I have just commited a big chunck of unrefined code because you can’t refine code until you get it working in the first place!

https://github.com/SelenaSmall/toy_robot/commit/524094260e69e0aab67b0de29ac4b8165b44f239


Refactor

Now that I have working code which meets all of the project specs, I have a valid MVP (minimum viable product). Now is the time to go through, tidy up refactor and optimise my code.

https://github.com/SelenaSmall/toy_robot/commit/5152d5937e471c3be0bb639f8690a2b759306054 https://github.com/SelenaSmall/toy_robot/commit/ceed3ffc273abf2ae1642f7abd3e301e1062778a https://github.com/SelenaSmall/toy_robot/commit/5047899aa3bff4c6ad856e2122e7cf5299d69b59


Documentation

Now that my project is looking more complete, I will revise my top level documentation and update the README.

https://github.com/SelenaSmall/toy_robot/commit/8f18c6136c21db3bcc38d98cf6fad619fa98d098 https://github.com/SelenaSmall/toy_robot/commit/04f310f8c5513c105a01570bd4b90a1231c40f04


Reviewing

Review Code

Before passing code on for someone else to look at, it’s always good practice to review it yourself and see if there are any more improvements that you can make or if you have any specific areas that you think could be improved but your not sure how to implement. I will also review each method to ensure that any possible exceptions are being handled.

https://github.com/SelenaSmall/toy_robot/commit/e632750ed9e179612e4c9cb59780a3cec31746d7


Review Tests

I have written tests throughout the build process and ensured that they pass before committing any new changes. To ensure the robustness of this product, I’m going to review all of the test code to see if there’s anything I’ve missed and to make sure that the tests are relevant. I’ll add any additional tests I can think of.

https://github.com/SelenaSmall/toy_robot/commit/a2e442a3c5d146ca8da42abe523d2f7943af0877


User Testing

Upon testing, I have found that I missed an exception - when user presses enter without inputting a command, the program exits. This empty command should be ignored.

https://github.com/SelenaSmall/toy_robot/commit/7c3f7506094e12475029d132022735f5efde15ad


Sample Data

The final criteria in the project spec is to produce some sample data output and show that the program works according to specs

https://github.com/SelenaSmall/toy_robot/commit/6d25d96a0d47492ec3d0cf0f153da30c6fcf209c


Submitting

Like with any project, this can undoubtedly be improved. At this stage, however, I am pleased with what I have produced. I feel that my code is clean and simple with smart methods that don’t try to take on too much.

In saying that, I am also eager to hear feedback which will hopefully open my eyes to something I hadn’t previously thought of.