Homework 9: Book Bandit (Part One)

Due: Tuesday April 28th, 2020 at 9:00PM anywhere in the world.

For a summary of all handout corrections/frequently asked questions about this homework, please continue referring to this Campuswire post!


Setup and Handin

For this homework, we are providing you with some source code, including a stencil for hw9_code.py , in which you will write all of your code. We’ll also be providing you with a file that will contain all of your tests called hw9_test.py.A zip file containing the source code, including the stencil and testing file, can be downloaded here.

When finished, hand in your hw9_code.py and hw9_test.py into Gradescope. Make sure to use your anonymous account!

The Assignment

Yee-haw! The tyrannical sheriff has gone rogue and started outlawing books left and right. You are a book-loving, entrepreneurial cowboy and you’ve accumulated a wide range of contraband books that you want to sell because it’s important literature.

There’s one problem though…

The cowboy book club doesn’t know which books they want to buy (they’re indecisive) and so it’s up to you to help them out (so you can reap the profits).

You must build a system so that:

(1) customers can browse, check out and buy those books (without the sheriff knowing),
(2) they can get recommendations for what books to buy,
(3) display this all on a website!

The website has already been handled for you, with details about how to run it described below. In this homework assignment, we’ll also be doing the recomendations part for you this time around, but don’t worry, you’ll get your turn at the rodeo! This is the first part of a two-part homework assignment that will lead to you completing what would have previously been the third project.

Resources We Provide

Click for more details about the website!

Home page

The home page shows a collection of books, organized by genre. There is no particular order to these books, they should be chosen randomly from the dataset every time the page is loaded.

Recommendations page

The recommendations page shows a list of books, sorted by how highly the system ranks those books for the user (for example, a book with 7 points comes before a book with 3 points; the point system is detailed below in the implementation details section).

Search page

The search page shows a list of books matching the user’s search query, sorted by the rating of the books in descending order (for example, 4.8 stars comes before 3.5 stars).

Viewing page

The book viewing page gives you more information about a book, and allows you to add the book to your cart.

Cart page

The cart displays all the books in the user’s cart, allowing them to remove individual books and purchase all the books in the cart.

Headers and footers

Each page has a header with links to useful pages and a search bar to look for books, and a footer that displays the book covers of the user’s previously purchased books.

Tasks

For this homework, you’ll be handling four major components of the backbone of our website:

  1. Internally representing our data, stored in a CSV, as a list of Books
  2. Keeping track of a cart of books, which we can add and remove things from
  3. Keeping track of a set of purchased books, for when we buy books from our cart
  4. Searching for a book based on title, author, or genre

Functions to Implement

In the stencil, we’ve instantiated four global lists. For this homework, you’ll be working with three of them: book_master_list, cart, and purchases. You’ll be working on the following functions. Please read the information below carefully.

Note: Functions with no output types don’t return anything.

  1. setup():
    Reads through the CSV file and creates a master list of books, b by ID (which you assign). The ID assigned to each Book should just be its index in the master list. For help figuring out how to read a CSV file, look at the example below. You can also find more examples in the solution to Lab 10.

    CSV Processing Example
    @dataclass
    class Posn:
        x : int
        y : int
    
    with open('books.csv') as f:
        lines = list(csv.reader(f))
    
    for line in lines:
        my_posn =  Posn(line[0], line[1])
    
  2. get_cart() -> list:
    Returns the current shopping cart of books.

  3. get_book(ident: int) -> Book
    Returns the book with ID ident (e.g. 1). If a book with the IDident is not found, you can raise an error using raise ValueError(<string>). For example:

    def divide(num1, num2):
        if num2 != 0:
            return num1 / num2
        else:
            raise ValueError("Cannot divide by zero")
    

    This might be helpful with debugging, and is also good coding practice. For more information about how to test errors, take a look at the Python testing guide.

  4. add_book_to_cart(ident: int):
    Adds the book identified by the index ident to the cart. You cannot have duplicates of books in a cart.

  5. remove_book_from_cart(ident: int):
    Removes a book from the cart at index ident (e.g. 1) if it is in the cart.

  6. buy_books_in_cart():
    Buys all books in the cart. You should call update_recs (a function we’ve provided; see Implementations We Provide below) on each book in your cart before moving it to the purchases. At the end, your cart should be empty! Also, books can be bought twice.

  7. search_books(query: str) -> list:
    Given a query, return up to 20 of the books that contain the query in the title, author, or genre (case-insensitive in both directions). If there are fewer than 20 books that match, return all of those books.

  8. make_genre_list(list) -> list:
    Creates a list of lists (we’re calling itgenre_list), with each sublist representing one genre. For this homework assignment, we only have 5 genres. These lists must come in the order we specify. Check out the Implementations We Provide section for more information about genre_list.

  9. get_purchases() -> list:
    Returns all purchased books.

  10. book_matches(query: str, book: Book)->bool
    Checks to see if given the query if its in the book’s title, author, or genre.

Note: Throughout the stencil, you might see the keyword global sprinkled throughout the functions (i.e., global book_master_list). This tells Python that, even within the individual functions, they should be referencing the same list that was defined globally at the top.

Note: You might notice that several of the methods above merely return one of the data structures we’re keeping track of globally! These get-functions might seem kind of useless at first, but these are important in making sure that external Python files (such as app.py, which will be used to run our website) can access the data contained in hw9_code.py.

If you take classes such as CS112 or CS18, you’ll learn more about the importance of get-functions!

Implementations We Provide

In the stencil code, there might be things that might seem unfamiliar. Please read the information below to get a better understanding of what’s going on.

Running the code

The zip file we provide you contains all the files required for this assignment. Your code will go into hw9_code.py.

To run the web app, you need to run app.py (also in that folder). app.py contains the code to create what is called a “Flask application.” Flask is a Python package (similar to how datetime and dataclasses are Python packages) which allows you to make web servers.

In PyCharm, run app.py. You should see something like this:

While this is running, you will be able to go onto your web browser and go to the url that it gives you (http://127.0.0.1:5000 above) and see the web app! This will only work on the computer that is running the application.

You can only have one version of the web app running; if you try to run app.py twice, you will see an error message. You should be able to have app.py running constantly; if you then make changes to hw9_code.py, the app will automatically reload itself and you can refresh the website.

If you are having a hard time running the web app, let the TAs know!

Testing Tips and Requirements

        def test_search():
            global book_master_list #this tells us to use the global variable, book_master_list
            setup() 
            # now book_master_list is populated
            test("Test for search", search_books("query"), ... )

Alternatively, we can also make our own smaller testing data:

    def test_function_small():
        global book_master_list
        # we can manually add books to this list
        book_master_list.append(Book("Hamlet", "Shakespeare", "Tragedy", "thisisanimage.jpg", 5.0, 5, 72))
        test("Test for search", search_books("shake"), ...)

We’ve provided an example of how you might do this in hw9_test.py.

Grading Requirements

Minimum Functionality:

Full Functionality:

Correctly implementing minimum functionality will warrant a passing grade, assuming some attempt at testing was made. This is a reminder that your code does not have to be functional to get testing points, so make sure to write tests for your code!

Some Final Notes

If this homework seems more complex than previous ones, know that is completely expected and normal! Most of this rather long handout is reading, and know that you’ve learned all the tools needed to complete the functions above, and that the staff is here for you to fill in any gaps. :) At the end of this project, you’ll get to learn several important skills that are used in the real world, including:

As always, remember your resources, and feel free to come to TA hours for any confusions. Also remember to make use of the Conceptual Express line at hours for any questions that don’t directly involve your code! Y’all got this!

Theme Song

Game of Thrones Theme - Western Cover


Brown University CSCI 0111 (Spring 2020)
Do you have feedback? Fill out this form.