Lab 2: TempConverter; Pixar
Due Date: February 14
Objectives
- Learn the basics of Ruby programming
- Learn how to work with Time class in Ruby
- Learn to use irb command prompt
- Improve familiarity with basic git commands
Due Date: February 14
Objectives
Some students have had prior exposure to Ruby, but others in the class may have little or no experience with the language. This part of the lab will get everyone familiar with some Ruby basics and provide review of other key concepts. This is a short introduction, but there are some 'on your own' exercises at the very end that students are strongly encouraged to try to solidify their understanding of Ruby.
We are going to begin by writing a simple program for Ruby to convert temperatures and then modify it several times. To begin, create a new file called temp_conversions.rb
using your preferred editor/IDE. Ask a TA for help on this if you need.
In this file, create a method called convert
as follows:
def convert(temp)
end
Between these two lines, add in the following line of code to convert Fahrenheit to Celsius:
5 * (temp - 32)/9
After the end statement, create some simple tests for this method with the code below:
puts convert(32)
puts convert(50)
puts convert(212)
Run this code from the command line by changing to the same directory as the file and typing ruby temp_conversions.rb
. You should get the output 0, 10, 100 as a result. Once this is running, set up a git repository and add this file to it. (Ask the TA if you don't remember how to do this from the previous labs.)
Now go into the method and remove the parentheses to the right of 32 and rerun this code. Note the error returned. Fix the error and rerun the code with ruby -c -w temp_conversions.rb
. The -c
flag means 'check syntax only' and the –w
flag activates higher warnings. When you run this time, you should see a new message.
Add the test puts convert("zero")
to the tests and rerun the code normally. Why did you get an error? To correct this, we will limit all temperatures to integers by adding a line before the calculation in our method:
return "Temperature must be an integer" unless temp.class == Integer
Rerun these tests after adding this line. If the tests pass, add the revision to the git repository. Also notice that if I want to return before the end of method, I need to use the return keyword, but if the method runs its course, the last value is automatically returned by the method. Finally, notice that I can place the condition at the end of the line in Ruby, not just at the beginning (as we are used to in other languages).
puts convert(-500)
to the tests and rerun. Of course, remembering your basic physics leaves you distressed at this point because you know this answer is in error – Absolute Zero is at –474 degrees Fahrenheit or -270 degrees Celsius, making this result impossible. To make sure our program doesn't give silly answers, we will add another line after the last correction (and before the calculation):return "Temperature below Absolute Zero" if temp < -474
Rerun the tests; assuming they pass, save the revision to the git repository.
exp
(Again, ask a TA if you don't remember this from previous labs). Now in your code, add another argument called measure
and using an if ... else ... end
construct, correct the code so that either a Fahrenheit or Celsius temperature is converted. Set up the measure
argument so its default value is "F". Add the test below:puts convert(0, "C")
puts convert(10, "C")
puts convert(100, "C")
puts convert(-280, "C")
Rerun the code; if all tests pass, save to the repository.
below_absolute_zero?
which has two arguments: temp and measure. This method will simply return a boolean of true if the temperature for the measurement system is below the critical value; this is why this method will end in a question mark. Create the basic structure for this method now.Add the following code so your complete method looks like this:
def below_absolute_zero?(temp, measure)
(temp < -454 and measure == "F") or (temp < -270 and measure == "C")
end
A couple of things to note here: (1) we have used the words and
and or
to demonstrate that Ruby does understand these words, but most times we will use the programming standards of &&
and ||
for these conjunctions, (2) if we provide Ruby a statement like temp < -454
, the statement is evaluated as either true or false and that result is returned.
Back to the code: go to the convert method and change the if statement for the Absolute Zero condition so that it references this new method rather than the simple statement of temp < -474
. Rerun the code and make sure that everything is working properly. If so, save this code to the git repository. Checkout the master
branch, and then merge the exp
branch onto the master
branch. (Again, ask a TA is you don't remember how to do this.)
Show a TA that you have completed the temp_conversion program and have properly saved the code to git. Make sure the TA initials your sheet.
We are going to switch gears now and start to interact with Ruby with irb [interactive ruby]. The irb prompt is a useful command line tool that can allow you to try out simple ruby constructs and methods. To get to interactive ruby, just type irb
on the command line.
Once in irb, type
a = Time.now
This gives us an object a with a Ruby timestamp. Now type in
require 'date'
b = Date.today
Compare this result with the results of the first command. What is the difference between these two objects? Be sure you are clear on the difference before proceeding (ask a TA if you are unsure).
Now type a.month
and note what is output is. Now type a.strftime("%B")
and note the output. How would you find the year of a
? (Guess ...) Try your idea in irb now.
Now type the command
a.month == b.month
What was returned? Type the command
a.day == b.day - 1
and see that result as well. As we noted earlier in the temp conversion method, Ruby is evaluating these statements as either true or false and returning the result.
Use the strftime
method to format the object a
in the format of 99/99/9999. To see the options with strftime
we can take advantage of a gem Prof. H uses sometimes in class: cheat. (To install this gem, run gem install cheat
in a terminal window that is not running irb; you can verify it is there by typing gem list | grep cheat
which simply pipes your list of gems to grep so it can search for any gems with 'cheat' in its name.) In that other terminal window/tab, type cheat strftime
and see the output returned – this should guide you in reformatting the timestamp. If you are having issues with this gem, you can also use an online reference strfti.me.
We are going to add three variables at once through multiple assignment (an option in Ruby). To do this, type into irb:
m1, d1, y1 = 04, 01, 2014
Now we will use these values to create a new timestamp in Ruby with the command:
c = Time.mktime(y1, m1, d1)
Now we have the timestamp for this year's April Fool's Day. Let's change it a little bit by typing d1 = 31
and rerunning the command: c = Time.mktime(y1, m1, d1)
. What did Ruby do with the date 04/31/2014?
Show a TA that you have completed this part. Make sure the TA initials your sheet.
You are technically done with this part of the lab. However if you want to stretch yourself a bit and put this new Ruby knowledge to the test, then try the following: write a method called valid_date?
which takes year, month and day as arguments and returns true if the date is valid or false if not. Below is a frame for the method as well as some test cases.
def valid_date?(year, month, day)
# your code goes here ...
end
# Tests
puts valid_date?(2013, 1, 29) # => true
puts valid_date?(2013, 2, 28) # => true
puts valid_date?(2013, 2, 29) # => false
puts valid_date?(2014, 2, 29) # => false
puts valid_date?(2014, 9, 29) # => true
puts valid_date?(2014, 9, 31) # => false
puts valid_date?(2013, 12, 31) # => true
puts valid_date?(2013, 12, 32) # => false
puts valid_date?(2013, 13, 31) # => false
puts valid_date?("2014", "Jan", 31) # => false
Hint: IMO it is a lot easier to deal with 'exceptional dates' with Ruby exceptions.
In this part of the lab, you will work through block problems from a previous 67-272 exam. This section contains 4 problems, but you only need to complete the first 2 for full credit. However, you are encouraged to complete them all if time allows! They will be good practice for future exams and your projects.
In each problem you will be given an expected output, and your task is to write a block that will generate this output. You can complete the problems in a separate file, and run it the same way as TempConverter.
cast = {bob_parr: :incredibles, helen_parr: :incredibles, lucius: :incredibles,
edna: :incredibles, woody: :toy_story, buzz: :toy_story, bopeep: :toy_story,
andy: :toy_story, merida: :brave, marlin: :finding_nemo, dory: :finding_nemo,
nemo: :finding_nemo, sulley: :monsters_inc, mike: :monsters_inc,
randall: :monsters_inc, sally: :cars, mcqueen: :cars, doc: :cars,
mater: :cars, jessie: :toy_story_3, big_baby: :toy_story_3}
toys = [:woody, :bopeep, :buzz, :jessie, :big_baby]
females = [:helen_parr, :edna, :bopeep, :dory, :sally, :jessie, :merida]
year_produced = {incredibles: 2004, toy_story: 1995, brave: 2012, finding_nemo: 2003, up: 2009, walle: 2008, monsters_inc: 2001, cars: 2006, bugs_life: 1998, toy_story_3: 2010}
# EXPECTED OUTPUT:
bopeep
jessie
# EXPECTED OUTPUT:
[:brave]
# EXPECTED OUTPUT:
Toy_story - 1995
Monsters_inc - 2001
Finding_nemo - 2003
Incredibles - 2004
Cars - 2006
Toy_story_3 - 2010
Brave - 2012
# EXPECTED OUTPUT:
Brave
Bugs Life
Cars
Finding Nemo
Incredibles
Monsters Inc
Toy Story
Toy Story 3
Up
Walle
Show a TA that you have at least problems 1 and 2 completed. Make sure the TA initials your sheet.
If you need a refresher on HTML basics, feel free to review the following labs from 67-250.
This week the "on your own" assignment is to go to RubyMonk's free Ruby Primer and complete the following exercises:
Introduction To Ruby Objects
Arrays in Ruby
Introduction to Ruby Methods