CS21 Lab12: A CD Database

  Due: 11:59pm Wednesday Dec 7

Optional: working with a partner

You may work with one partner on this lab. If you work with a partner, only one of you should submit your joint solution using cs21handin, and you should make sure both your names appear in the top-level comments of every file. The best way to work with a partner is for both of you to work together in the lab on the entire assignment, doing all the code design, implementation, and testing together.

When working with a partner, it is sometimes necessary to copy files from one partner's cs21/labs/12 directory to another using remote secure copy (scp). Here is an example of how to do that:

# from partner 1's cs21/labs/12 directory, scp cdinfonode.py to partner 2's 
# cs21/labs/12/cdinfonode.py (scp source username@lab:path_to_destination)
# scp will prompt partner 2 to enter his/her password to complete the copy

$ scp cdinfonode.py partner2_username@lab:cs21/labs/12/cdinfonode.py
partner2_username@lab's password: 
cdinfonode.py                      100%   88     0.1KB/s   00:00    

Get Lab 12 starting point code:

Run update21 to create the cs21/labs/12 directory. Then cd into your cs21/labs/12 directory and create the python programs for lab 12 here. For this lab, we are giving you three starting point files for your python code and a CD database file:
$ cd ~/cs21/labs/12
$ ls
cd.db  cdinfonode.py  cdlinkedlist.py  mainprog.py
The cd.db that contains an example database of CD information, and three files in which you will implement your solution: cdinfonode.py; cdlinkedlist.py; and mainprog.py.

Read through the entire lab before you begin coding. Then go to the section on Getting Started and follow the instructions there to begin.

Introduction

For this lab you will write a program that reads in information from a CD data base into a linked list and then enters a loop with the following menu options for performing different operations on the list:

  1. Print all CDs by a given artist (and print out the number of matches)
  2. Print all CDs with a given title (and print out the number of matches)
  3. Print all CDs released in a given year (and print out the number of matches)
  4. List all the CDs in the database (in chronological order)
  5. Quit
You will use a linked list to store the CD information. You can adapt the code we've been creating in class to solve this problem.

The cd.db file is formated such that associated with each CD are three pieces of information: artist name, album title, and release year. The information for each CD is stored on a single line and is separated by commas. For example, the the first three lines of the file are:

Public Enemy,It Takes a Nation of Millions to Hold Us Back,1988
James Brown,Get on the Good Foot,1972
Sly & the Family Stone,Fresh,1973

Getting Started
For this program, you will add code to three starting point files that we give you: the first file cdinfonode.py will contain the class definition for the CDInfoNode class; the second file cdlinkedlist.py will contain the class definition for the CDLinkedList class; and the third mainprog.py will contain the code that creates a CDLinkedList object by reading in values from the cd.db and then uses the CDLinkedList object to perform operations on the database.

  1. Edit the file called cdinfonode.py to create one classes: CDInfoNode:

    CDInfoNode

    CDInfoNode should store data about an individual CD: album, artist, and year. It should also have a next field to point to another CDInfoNode object.

    CDInfoNode should have a constructor (__init__) and a __str__ method. The __init__ function has been given to you with the starting point code. However, you need to implement the__str__ method function to return a string representation of a CD. For example, a sample string representation could be: "Mingus Ah Um - Charles Mingus (1959)" In addition, your class definition should have accessor and mutator method functions to get and set CDInfoNode data fields.

    Once you have this class written, add some test code to mainprog.py to create a CDInfoNode objects and call its methods to test them out.

  2. Once your CDInfoNode class is tested and debugged, in cdlinkedlist.py complete the implementation of the CDLinkedList class.

    CDLinkedList

    Your CDInfoNode class will form the basis of a CDLinkedList class that will be very similar to the LinkedList class described during class. Follow these steps to get your class started:

    • Create a class called CDLinkedList that contains head, tail and size fields.
    • Add an __init__ method to this class.
    • Add a __str__ method that returns a string containing all the CD information in the list. Add a newline character between entries to make it more readable.
    • Add an insertAtHead method that takes an artist, title, and year. It creates a CDInfoNode containing that data and adds it to the start of the linked list.
    • Test the CDLinkedList class before moving on. In mainprog.py, add some code to create a new CDLinkedList object, add a couple of CDs to it. Print the contents of the list and make sure that all of the data you added is in the list.
    You will also add other method functions to this class as you add main program functionality.
    Creating a CD database

    Once you have tested the starting methods of your CDLinkedList class, modify mainprog.py to contain the following function (you can add additional helper functions as you see the need... think top-down-design and add functions that encapsulate parts of the larger program's functionality):

    1. Write a function that reads in the CD database from a file. This function will create and return a CDLinkedList object, with one CDInfoNode object for each CD in the database file. The filename of the CD database should be passed to this function, in addition to any other parameters that you think this function needs. To create the linked list, your function should make calls to the insertAtHead method to add each CD's information read in from the file to the CDLinkedList object.
    2. Write a function that prints out the menu of options.
    3. Write a function that gets and returns a valid menu option entered by the user.
    4. In cdlinkelist.py add methods to the CDLinkedList class to implement the searches listed in the menu (by artist, year, album, and all). Note that these method functions only need to print the result and number of matches. These methods do not need to return anything. Be sure to print an informative message if no matches are found.

    Test all this functionality before moving on to the next step (note: the output in the Sample Output section, reflects a solution that includes the next step (creating a CD database sorted by year), so the order in which ouput appears may differ from the sample output, but the set of outputed results should be the same).

    Creating a sorted CD database
    Note: Do not try this part before getting a completely correct running solution using insertAtHead. It is much better to submit a fully working program without supporting inserting in sorted order than it is to submit a program that calls an insertSortedByYear method that doesn't work and that also doesn't have other program functionality fulling implemented and working. If you attempt this, but don't get it working, leave your attempted insertSortedByYear method in the code you submit, but have your main program call insertAtHead so that we can run and test your program for all other working functionality.

    Once all of the functionality described above is working correctly add an insertSortedByYear method to the CDLinkedList class that takes an artist, title, and year as parameters. It should creates a new CDInfoNode, and add it to the CDLinkedList object such that the resulting linked list is sorted in chronological order by year.

    Here is some pseudocode to help you get started on this method:

    if list is empty or year <= head's year
       insert new data at head
    elif year >= tail's year
       insert new data at tail
    else
       set previous to None
       set current to head
       while current's year < year
          set previous to current
          set current to current's next
       insert the new node between previous and current
    
    in every case need to increment the size field   
    

    Modify your function that reads in the data from a file so that it calls this new method insertSortedByYear rather than the original method insertAtHead. Once you make this change, and view all of the data, you should see that it is now in sorted order.

    Sample output
    $ python mainprog.py
    
    ##############    CD DB Menu  ########################
    
       1. Print all CDs by a given artist and the total number
       2. Print all CDs with a given title and the total number
       3. Print all CDs released on a give year and the total number
       4. Print all CDs in the DB and the total number
       5. Quit
    ######################################################
    
    Enter a value between 1 and 5 : hello
    Hey, hello isn't a number...try again
    Enter a value between 1 and 5 : 0
    Hey, 0 isn't between 1 and 5 ...try again
    Enter a value between 1 and 5 : 7
    Hey, 7 isn't between 1 and 5 ...try again
    Enter a value between 1 and 5 : 1
    Enter an artist's name: X
    
     Los Angeles - X (1980)
     Under the Big Black Sun - X (1982)
     More Fun in the New World - X (1983)
    
    There are 3 CDs by this artist
    
    
    ##############    CD DB Menu  ########################
    
       1. Print all CDs by a given artist and the total number
       2. Print all CDs with a given title and the total number
       3. Print all CDs released on a give year and the total number
       4. Print all CDs in the DB and the total number
       5. Quit
    ######################################################
    
    Enter a value between 1 and 5 : 2
    Enter an album title: Greatest Hits
    
     Greatest Hits - Sly & the Family Stone (1970)
     Greatest Hits - Ramones (1990)
     Greatest Hits - Al Green (2005)
    
    There are 3 CDs with this title
    
    
    ##############    CD DB Menu  ########################
    
       1. Print all CDs by a given artist and the total number
       2. Print all CDs with a given title and the total number
       3. Print all CDs released on a give year and the total number
       4. Print all CDs in the DB and the total number
       5. Quit
    ######################################################
    
    Enter a value between 1 and 5 : 3
    Enter a year: 1980
    
     New York - Lou Reed (1980)
     Right Time - The Mighty Diamonds (1980)
     London Calling - The Clash (1980)
     Los Angeles - X (1980)
     The Specials - The Specials (1980)
     Off The Wall - Michael Jackson (1980)
    
    There are 6 CDs produced in 1980
    
    
    ##############    CD DB Menu  ########################
    
       1. Print all CDs by a given artist and the total number
       2. Print all CDs with a given title and the total number
       3. Print all CDs released on a give year and the total number
       4. Print all CDs in the DB and the total number
       5. Quit
    ######################################################
    
    Enter a value between 1 and 5 : 4
    ------------------------------------------------------
    CD Collection:
    ------------------------------------------------------
    Mingus Ah Um - Charles Mingus (1959)
    Avalon Blues - Mississippi John Hurt (1962)
    Time Out - Dave Brubeck Quartet (1964)
    Kind of Blue - Miles Davis (1964)
    Kick Out the Jams - MC5 (1969)
    Greatest Hits - Sly & the Family Stone (1970)
    There's a Riot Goin' On - Sly & the Family  Stone (1971)
    Get on the Good Foot - James Brown (1972)
    Fresh - Sly & the Family Stone (1973)
    Horses - Patti Smith (1975)
    Mothership Connection - Parliament (1975)
    What's Going On - Marvin Gaye (1978)
    Survival - Bob Marley (1979)
    New York - Lou Reed (1980)
    Right Time - The Mighty Diamonds (1980)
    London Calling - The Clash (1980)
    Los Angeles - X (1980)
    The Specials - The Specials (1980)
    Off The Wall - Michael Jackson (1980)
    Under the Big Black Sun - X (1982)
    Doolittle - Pixies (1983)
    More Fun in the New World - X (1983)
    Blowout Comb - Digable Planets (1986)
    Sister - Sonic Youth (1986)
    Spot 1019 - Spot 1019 (1986)
    It Takes a Nation of Millions to Hold Us Back - Public Enemy (1988)
    For Ladies Only - Killdozer (1989)
    3 Feet High and Rising - De La Soul (1989)
    Greatest Hits - Ramones (1990)
    De La Soul Is Dead - De La Soul (1991)
    Live Through This - Hole (1993)
    The Infotainment Scan - The Fall (1993)
    Dig Me Out - Sleater-Kinney (1997)
    Car Wheels on a Gravel Road - Lucinda Williams (1998)
    Californication - Red Hot Chili Peppers (2001)
    One Beat - Sleater-Kinney (2002)
    Greatest Hits - Al Green (2005)
    White Blood Cells - The White Stripes (2005)
    
    ------------------------------------------------------
    There are a total of 38 CDs in the library
    ------------------------------------------------------
    
    
    ##############    CD DB Menu  ########################
    
       1. Print all CDs by a given artist and the total number
       2. Print all CDs with a given title and the total number
       3. Print all CDs released on a give year and the total number
       4. Print all CDs in the DB and the total number
       5. Quit
    ######################################################
    
    Enter a value between 1 and 5 : 5
    
    bye bye
    

    Optional extras

    Do not attempt to solve these problems until the required portion of the lab is complete. There are many extensions you could add to this program. Here are a few we thought might be interesting.

    • Add a menu option that allows a user to add a new album to the data base. The user interaction might look like this:
      Enter the Artist Name : Soul Coughing
      Enter the Album Name : Ruby Vroom
      Enter the Year : 1994
      
      Added Soul Coughing, Ruby Vroom, 1994
      
      You should do some error checking on the values entered by the user so that you do not corrupt your data base with bad (or incomplete) data.

    • Add a method writeOut that writes the CDLinkedList to a specified filename. Be careful not to overwrite the original cd.db file. Below is a code snippet to write two lines to a file. Note that newlines "\n" need to be stated explicitly and close() is required to save the file.
      savefile = open("cdsaved.db", 'w')
      savefile.write("a, b, c\n")
      savefile.write("1, 2, 3\n")
      savefile.close()
      
      Add a menu option to allow the user to save the updated database to a specified file. You should write your output file in the same format as the original cd.db file so you could use your saved file as input later.
    • Allow the user to specify the database to use on the command line. e.g., if the user types at the linux prompt python mainprog.py mycatalog.db, the program should read the CD info from the file mycatalog.db. Below is a some sample code that shows how to read options that are specified on the command line.
      from sys import argv
      
      """
      argv is a list of strings containing all the words that appear
      after the python command
      """
      
      if len(argv) < 2:
        #argv[0] is always the name of the file you are running
        print "usage: python %s <filename>" % (argv[0])
      else:
        #other options start at argv[1]
        print "reading from file: %s" % (argv[1])
      
      
    Submit

    Once you are satisfied with your program, hand it in by typing handin21 in a terminal window.