Welcome, Guest User :: Click here to login

Logo 67272q

Lab 2: TempConverter; blocks;classes and objects

Due Date: January 28

Objectives

  • Learn the basics of Ruby programming
  • Learn how to work with Time class in Ruby
  • Learn how to create classes and objects in Ruby
  • Learn to use irb command prompt
  • Improve familiarity with basic git commands

README.md

Part 1: Ruby Introduction

This part of the lab will get everyone familiar with some Ruby basics and provides a 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.

  1. We are going to begin by writing a simple program for Ruby to convert temperatures and then modify it several times. **Create a new folder named lab2 in your workspace[Mac/Windows/PaizaCloud], and you will save all your ruby files for this lab **. To begin, create a new file called temp_conversions.rb using your preferred editor/IDE.

  2. In this file, create a method called convert that takes temp as a parameter (temperature in Fahrenheit) and converts it to its equivalent in Celsius.

Run this code from the command line. Once this is running, set up a git repository and add this file to it.

  1. 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.

  1. Add the test 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.

  1. Of course, we have only half the temperature conversion problem – converting Fahrenheit to Celsius – and have no capability to convert Celsius to Fahrenheit. Create a new branch in git called exp. 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.

  1. Looking at the results, we see that the code is still problematic: we get a result for –280 oC even though we know that value is below Absolute Zero. There are a number of ways to correct this, but for learning purposes here, we are going to create a new method called 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.

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.

Part 2: Interactive Ruby

  1. 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.

  2. 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.

  1. 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.

  2. 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.

  1. 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.

  2. 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?


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 are some test cases.

 # Tests
valid_date?(2013, 1, 29) # => true
valid_date?(2013, 2, 28) # => true
valid_date?(2013, 2, 29) # => false
valid_date?(2014, 2, 29) # => false
valid_date?(2014, 9, 29) # => true
valid_date?(2014, 9, 31) # => false
valid_date?(2013, 12, 31) # => true
valid_date?(2013, 12, 32) # => false
valid_date?(2013, 13, 31) # => false
valid_date?("2014", "Jan", 31) # => false


Part 3: Ruby Blocks

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.

  1. Add the following dictionaries to the top of your file, as these will be used in the problems.
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}

  1. Create a block that prints out all the female toys in alphabetical order.
# EXPECTED OUTPUT: 
  bopeep
  jessie
  1. Create a block that will print out a list of all the movies produced in the past 10 years.
# EXPECTED OUTPUT: 
  [:brave, :toy_story_3]
  1. Create a block that will print out a list of movies that have some cast members in the cast dictionary, arranged by year produced.
# EXPECTED OUTPUT: 
  Toy_story - 1995
  Monsters_inc - 2001
  Finding_nemo - 2003
  Incredibles - 2004
  Cars - 2006
  Toy_story_3 - 2010
  Brave - 2012
  1. Create a block that will print out a list of all movies in the year_produced dictionary in a user-friendly format (spacing and capitalization). Make sure they are in alphabetical order.
# EXPECTED OUTPUT: 
  Brave
  Bugs Life
  Cars
  Finding Nemo
  Incredibles
  Monsters Inc
  Toy Story
  Toy Story 3
  Up
  Walle

Part 4: Classes and Objects

In this part, we want to build a micro-blogging platform Tweeter similar to Twitter. Users have a valid
account to be able to post tweets. A Tweet is 140 characters long text message that can contain hashtags
or referrers. A hashtag is a word that starts with the # character. A referrer is a word that starts with the
@ character and that refers to an existing ID of a Tweeter user. Users can see all the tweets posted by all
users.

1. The User Class

The User class is a structure that manages the characteristics of a given user.
Each user is identified with the following attributes:

  • id is the user's unique identifier in Tweeter (string).
  • firstname is the user's first name (string).
  • lastname is the user's last name (string).
  • password is the user's password (string).

1- Create the User class. In order to create a new user, one should provide the id, first name, last name, and password.

2- Write a class method get_full_name that returns a user's full name.

3- Write a class method check_password(p) that checks if a given password p matches the user's password. This method should return true if p matches the current user's password

2. The Tweet Class

The Tweet class is a structure that manages the characteristics of a given tweet.
Each tweet has:

  • An owner: the user that published the tweet
  • A message: a string representing the message of the tweet

1- Create and complete this class. Keep in mind that while creating a tweet the constructor (initialize method) should ensure that the message is 140 characters long. If the message given as input is longer, the message is truncated.

2- Write and test a class method get_hashtags that returns the list of hashtags conatined in the message.

3- Add a to_s method that returns a text representation of the tweet such as user name said message. For example:

Houda Bouamor said, "The next assignment in #cmuq67272 will be #easy"

or also

Ahmed Mohammad said, "Professor @HoudaBouamor has posted the latest #cmuq67272 lab"

3. The Tweeter Class

The Tweeter class is a structure that manages the characteristics of Tweeter.
Tweeter is defined by:

  • users: an array of users
  • tweets: an array of tweets

1- Create this class and define its initialize method. At first, there are no users no tweets.

2- Write and test a method signup(id, password, firstname, lastname) that creates
a new Tweeter user if the id is not already taken and returns true. It returns false otherwise.

3- Write and test a method signin(id, password) that returns the Tweeter user corresponding to the given Tweeter ID if and only if the password matches the one stored in the user's profile. It returns nil if either the user ID does not exist or if the password does not match.

4- Write and test a method add_tweet(user, message) that publishes a new tweet to Twitter.

5- Add the to_str method. It should return a text representation of the last 20 tweets only posted on Tweeter. Each Tweet should be separated by an empty line.