CS21 Lab 11: Object-Oriented Programming

Part 1: Due in your lab (either May 1 or May 2)

Part 2: Due Saturday night, May 5


Make sure all programs are saved to your cs21/labs/11 directory. Files outside this directory will not be graded.

$ update21
$ cd ~/cs21/labs/11

Introduction

This is a two-week lab and will be due in two parts. For part 1, you need to bring a completed version of this worksheet to your normally schedule lab. You also need to have a working definiton of the Book class (described below) to demonstrate to your lab instructor. For part 2, you need to complete the rest of the lab.

In this lab, you will build an e-reader called the Swindle (any resemblance to current e-readers is completely coincidental). You will use object-oriented programming to create two classes.

The first class you will develop is the Book class that encapsulates one electronic book (or ebook). We have made several free ebooks available for you to load and experiment with once you get your Book class working.

The second class you will develop is the Swindle class that encapsulates the concept of an e-reader. You will be able to perform several core operations of an e-reader, including buying books, picking a book from your virtual shelf, and reading a book.

To get started, take note of the files that we have provided for you:

Here is a sample run. Read through this carefully so that you can see how the ereader should operate, and understand which parts you need to implement and which parts are already implemented for you.

Read through this entire lab writeup BEFORE you begin to write any code. Taking the time to thoroughly understand what you are trying to accomplish will allow you to more effectively implement the code.


Top-down design

Continue to use top-down design. As the first step, you should stub out the entire class definition. All methods (except getters and setters) should have a triple-quoted comment explaining their input parameters, return value, and purpose. Each method should have a print statement. If a method returns a value, it should return a dummy value of the correct type. Use bottom-up implementation and thoroughly test each method as you complete it. You should be incrementally testing your code. You should not wait until you have implemented every method before you begin testing.

Both lab instructors and ninjas will expect to see you practicing these good top-down design techniques.


Complete the Book class

A Book object represents an electronic book to read on your e-reader. You should define your class such that each book maintains the following data (also called instance variables):

Your Book class should define the following methods:

       Alice in Wonderland by        Lewis Carroll (1865)
        Gettysburg Address by          Abe Lincoln (1863)       
# Here is a silly poem
Roses are red,
Violets are blue.
# Second verse
Sugar is sweet,
And so are you!

Then getText() would return a string that looks like this, where the comment lines (starting with the pound sign) have been removed:

"Roses are red,\nViolets are blue.\nSugar is sweet,\nAnd so are you!\n"

When you print this string it will look like this:

Roses are red,
Violets are blue.
Sugar is sweet,
And so are you!

Incrementally test the Book class

As you complete each method of the Book class you should test it. Notice that at the bottom of your book.py file we have provided some initial tests. When you do $ python3 book.py this test code will be executed.

if __name__ == '__main__':
    print("Testing the Book class...")
    mybook = Book("Gettysburg Address", "Abe Lincoln", 1863,
                  "/usr/local/doc/GettysburgAddress")
    print("Testing toString...")
    print(mybook.toString())
    print("Testing getFilename...")
    print(mybook.getFilename())
    print("Testing getText...")
    text = mybook.getText()
    print(text[:105]) #only print the first couple of lines
    print("bookmark is:", mybook.getBookmark())
    mybook.setBookmark(12)
    print("now bookmark is:", mybook.getBookmark())
    ################ Write additional tests below ###################

Enhance this test code by adding a number of your own tests. Remember that in your lab section on either May 1 or May 2, you will need to demonstrate to your lab instructor that your Book class is working properly.

Do not move on to the Swindle class until you are sure that your Book class is working correctly!


Complete the Swindle class

The Swindle class defines an e-reader device. Every instance must maintain a few pieces of data:

The constructor

We have provided the beginning of the class definition by defining the constructor (which includes the functionality for loading the database of available books). You only need to add a few lines of code where you see the comment:

#TODO: using the information just obtained from the file,
# create a Book object with this data and add it to the
# availableBooks list

When first creating a Swindle object, the user does not own any books, and all books in the database should be considered books available for purchase.

It is important to note that both the variables availableBooks and ownedBooks are lists of Book objects. Here is a clear example of the power of encapsulation. A Book object stores all of the important information and functionality needed to interact with a book. By keeping lists of Book objects, the Swindle class can easily implement the functionality for reading these books.

Methods provided for you to display a book

We have also provided the methods displayText(), displayPage(), and getLetter(). These methods take care of the details involved in displaying a certain number of lines from the book. You do not need to change these methods. The method displayText() is the method you will call to allow the user to read one of their books. This method calls the method displayPage() to show a single page at a time. It also calls the method getLetter() to determine what the user wants to do next. Once the user decides to quit reading a particular book, the displayText() method returns the current page number of the book.

Methods you must implement

Your Swindle class should define the following methods:

$python3
>>> ls = ["this", "is", "a", "test"]
>>> word = ls.pop(1) #remove and return the item at index 1
>>> word
'is'
>>> ls
['this', 'a', 'test']

For both the buy() and read() methods, you should ensure that the user selects a valid book number from the menu. You can assume that the user always enters an integer.


Incrementally test the Swindle class

As you complete each method of the Swindle class you should test it. Notice that at the bottom of your swindle.py file we have provided some initial tests. When you do $ python3 swindle.py this test code will be executed.

if __name__ == '__main__':
    print("Testing the Swindle class...")
    myswindle = Swindle()
    print("Testing showAvailable...")
    myswindle.showAvailable()
    print("Testing showOwned...")
    myswindle.showOwned()
    ################ Write additional tests below ###################

Putting it all together

Once you have written (and thoroughly tested!) the Book and Swindle classes, according to the above requirements, you should be able to successfully run the main ereader program: $ python3 ereader.py

Here again is the sample run demonstrating how the ereader should behave.

Test out all of features of your classes by trying every possible menu option from the ereader. Be sure to gracefully handle these edge cases:


Optional Enhancements

This section is completely optional. Feel free to attempt this once you have successfully completed all of the required portions of the lab. Because this is optional extension, we are leaving a lot of the details for you to figure out on your own.

If you wish to attempt this part, be sure to make copies of your orignal code as shown below. Only modify the copies, leaving the original solution alone.

$ cd cs21/labs/11
$ cp swindle.py enhancedSwindle.py
$ cp ereader.py enhancedEreader.py

The original version of the ereader starts from scratch every time, which is unrealistic. Instead, we would like the ereader to remember the owner's name, the books that have been purchased (and what page number the owner is on), as well as the books that are still available.

Here is a sample run demonstrating how the enhanced ereader should behave.

To accomplish this you will need to learn how to write to a file. Below is a short example program showing how to do this.

def main():
    name = "Sedi"
    age = 21
    fp = open("test.txt", "w")
    fp.write("%s is %d years old\n" % (name, age))
    fp.write("this is a test\n")
    fp.write("here's another line\n")
    fp.write("goodbye\n")
    fp.close()

main()

Here's what the file test.txt would now contain:

Sedi is 21 years old
this is a test
here's another line
goodbye

One other new python feature you'll need is to be able to check whether a particular file exists or not. You can try this in the python intepreter:

$ python3
>>> from os.path import isfile
>>> isfile("ereader.py")
True
>>> isfile("foobar")
False

Now that you know how to write a file and how to check whether a file exists, you are ready to implement the enhanced ereader. The basic idea is as follows.

Without too much effort you'll have an enhanced ereader that is much more like an actual device.


Submit

Once you are satisfied with your programs, fill out the questionnaire in QUESTIONS-11.txt. Then run handin21 a final time to make sure we have access to the most recent versions of your file.