EECS 298: Social Consequences of Computing

Homework 1: Restaurant Recommendations

Due 11:59 PM EST on Friday, February 7, 2025.

Autograder points: 20

Written response points: 26

Total points: 46

Submission & Grading

This assignment is made up of two parts:

  1. Programming - submit HW1.py
  2. Written Reflection - submit a PDF with your responses

You’ll submit both parts on Gradescope. Part 1 will use the Code Submission assignment while Part 2 will use the Homework 1: Written Responses assignment. To access Gradescope, use the link on Canvas.

[!IMPORTANT]
Please do not handwrite your written responses - using any word processor (Word, Google Docs, etc.) or LaTeX is fine!

Part 1 will be graded using an autograder, so you’ll be able to get feedback as soon as you submit - you can submit any number of times until you feel happy with your score!

Part 2 will be graded manually, but you can still resubmit as many times as you need to before the deadline.

Introduction

Congratulations! You’ve been hired as a software engineer for LivingLikeALocal, a software company that creates a restaurant recommendation website for travelers in cities across the United States.

Your superiors have tasked you with designing a database of local restaurants for the site - you’ll also implement a class in Python to sort and search your database.

Your goal as the database’s designer is to provide the most amount of information to LivingLikeALocal customers, so they can find their way to highly recommended restaurants in the area.

Getting Started

To start, find a spot on your computer to store the files for this assignment and create a new folder - call it whatever you would like!

To navigate to this folder using your terminal, use the cd command followed by the path to your folder:

$ cd "/Users/coolstudent/EECS_298/HW1"

Part 1 - Task A: Creating the Database

Before you can reccomend the best restaurants, you’ll need a database of all restaurants.

Download the HW1.py file. To do this, open a terminal and navigate to your project folder using cd. Then, use the following wget command to download the file:

$ wget https://raw.githubusercontent.com/eecs298/eecs298.github.io/main/homeworks/HW1.py

Creating Your CSV File

Your database will live in a .csv file, which stands for “Comma Seperated Values”. You can think of them as a kind of watered-down Excel spreadsheet, or just a simple table with columns and rows of information.

CSV files are great to work with in Python, since they’re easy to read from and analyze in your code. You’ll create a .csv file on your own, then place it into your project’s folder so you can access it from HW1.py.

Setting Up Your File

To start, create a file named restaurants.csv in the same folder as your HW1.py file. Then, open your new file using a text editor of your choice.

[!NOTE] You can also create and edit CSV files in programs like Excel, Google Sheets, and Numbers. Although this assignment will teach you how to work with CSVs by hand, these programs can export spreadsheets you create right into CSVs.

When you open the file, you should see a blank screen. Before we start adding restaurant data points (which will appear as rows, one for each restaurant), we need to add a header row.

The header row lives at the top of your spreadsheet and denotes what each column of data means. Paste the following text into your blank CSV file to create your header row:

Restaurant name,Restaurant address,Rating,Relative price,Keyword,YOUR_CATEGORY

Adding Data

Now, let’s add data! We’ll follow the same format as our header row - for example, if we wanted to add Ann Arbor’s Cafe Zola to our CSV, we would add this line underneath our header row:

Cafe Zola,"112 W Washington St Ann Arbor, MI 48104",3.8,2,Eclectic restaurant,YOUR_CATEGORY_INFO

We can see that “Cafe Zola” matches up with “Restaurant name”, and so on. Our complete file would now look like this:

Restaurant name,Restaurant address,Rating,Relative price,Keyword,YOUR_CATEGORY
Cafe Zola,"112 W Washington St Ann Arbor, MI 48104",3.8,2,Eclectic restaurant,YOUR_CATEGORY_INFO

In this same way, we can add any number of restaurants to our dataset by adding new lines.

[!NOTE]
In CSV files, different pieces of data are seperated by commas. If you need to use a comma in your actual data, place that value in quotes. For example, to place the value 112 W Washington St Ann Arbor, MI 48104 in your dataset, it would appear as "112 W Washington St Ann Arbor, MI 48104" in your CSV file.

Adding Your Own Data

Before starting this section, delete the Cafe Zola line from your CSV file.

Now it’s time to add your own restaurants! To get started, choose any city in the United States. Once you have a city in mind, you can use Yelp and Google Maps to look up 5 restaurants in that city. You’ll need to collect the following about each restaurant you choose:

  1. Restaurant name
  2. Restaurant address
  3. A rating out of 5 stars
  4. The relative price in the terms of the number of dollar signs shown
  5. A keyword describing the restaurant (bar, pizza place, etc.)
  6. A category of your choosing based on the information available on Yelp and Google Maps. Replace the header YOUR_CATEGORY with your category choice.

[!NOTE]
If you can’t find one of these categories for any of your restaurants, don’t leave it blank! Instead, simply write None. In Python, the reserved keyword None refers to a null value - this will help us later to ignore certain pieces of data. Since you have control over the restaurants you choose for the database, you should try to limit your use of None by choosing restaurants with most of the categories filled in.

As you find your data, record it in your CSV file using one line per restaurant. Once you’re done, you should have six lines total: One for the header row and five for your data rows.

Great job! Your source of data is ready to go.

Part 1 - Task B: Using Your Database In Python

Now that your CSV is ready to go, it’s time to implement HW1.py. You’ll see two classes already defined for you:

Implementing The Restaurant Constructor

To start, we’ll need to construct Restaurant objects by defining their data attributes.

In the constructor (__init__) function of Restaurant, you will see a list of input variables that corresponds to the list of categories of restaurant information above.

Recall that all attributes in Python are Public by default, so there is no need to add any get or set functions to this class. Instead, we access attributes as follows:

# create a new Restaurant object
restaurant = Restaurant(name, address, rating, price, keyword, category_choice)

print(restaurant.name) # accessing and printing the restaurant name

Printing A Restaurant

When you use the print() function in Python, you expect to see the data you printed in your console. For example, printing a string or numeric value simply outputs that value into your console.

Python knows how to print these basic types, but it dosen’t know how to print a Restaurant…yet!

We want to be able to easily see the information in a Restaurant object, so we are going to overload the __str__(self) function in the Restaurant class. This will define for Python how to print a Restaurant, letting you simply pass a Restaurant object into print().

[!NOTE]
This is because Python automatically calls the built-in function __str__(self) when you use the print() function and __str__(self) returns a str to be printed out. So, we can change the implementation of the __str__(self) function in the Restaurant class to get Python to display what we want when you use the print() function on a Restaurant object.

Name: NAME_VALUE Address: ADDRESS_VALUE\n
Rating: RATING_VALUE Price: PRICE_VALUE Keyword: KEYWORD_VALUE\n

An example output for Cafe Zola is given below:

Name: Cafe Zola Address: 112 W Washington St Ann Arbor, MI 48104
Rating: 3.8 Price: 2 Keyword: Eclectic restaurant

Great job! The Restaurant class is now ready to represent many different types of restaurants.

The RestaurantDatabase Class

Next, it’s time to implement the RestaurantDatabase class. This class will be used to read and store the restaurant information as well as sort and search through the information. The descriptions and implementation instructions of each function in the class are given below.

[!TIP] Look for the # TODO comment in HW1.py for where to add your implementations and remember to remove the pass keyword during your implementation.

__init__(self)

This is the constructor for the RestaurantDatabase class. This class has one attribute called self.restaurants to hold all the Restaurant objects and is initialized as an empty list here.

We’ll need this function to take in a list of restaurants - this way, the class functions can interact with the list by searching it, sorting it, and more.

read_data(self, file)

Our list of restaurants will start empty! We’ll need to be able to load the data from the .csv file you created into our Python code.

[!IMPORTANT]
As you read in data, you will discover attribute values that are "None" - this is from when you filled in your database earlier. When this happens, replace the string "None" with the Python keyword None, and pass that into the Restaurant constructor instead.

sort_database(self, attribute_name, reverse=False, k=0)

Arguments

When reccomending restaurants to LivingLikeALocal customers, we might need to be able to present them in certain orders, like least to most expensive, or closest to farthest.

  1. First, create a list of Restaurant objects that do not have the Python keyword None as the value for the given attribute_name. We will ignore these objects.

  2. Then, use the default sorting of the built-in Python sorted() function on this list of filtered Restaurant objects. Use the optional argument reverse boolean argument in the sorted() function to determine if this default sorting is reversed or not. Refer to Python sorting documentation for how to use the sorted() function.

  3. If provided, use the optional argument k to return the top k Restaurant objects in a list after sorting.

[!TIP]
Use getattr() to access an attribute of a class when attribute_name is given as a str.

sort_by_keyword(self)

Arguments

We also might want to sort restaurants based on their keyword specifically.

search_database(self, attribute_name, search_query)

Arguments

Another crucial function of services like Yelp and Google Maps is searching: LivingLikeALocal users should also be able to search your database of restaurants!

Use the Python keyword in to check if the search_query exists in the attribute of each Restaurant. As such, partial str matches are enough for the Restaurant to be in the returned list.

We assume searches are not case sensitive, so make sure to match the case between the search query and the database information for an accurate search.

[!TIP]
Use the lower() function for strs and remember to skip any Restaurant objects where the value of the attribute_name is the Python keyword None.

Congratulations! 🎉 You just finished Part 1! At this point, you can visit Gradescope to submit your HW1.py file and check out your results from the autograder.

Part 2 - Written Reflection

For this section, write a short paragraph response to each question. The purpose of this part is to reflect on the design process in this homework as a whole and the consequences the decisions made throughout this assignment could have when implemented. In your responses, we are looking for an effort to apply concepts from lectures and readings to answer each of these questions. Make sure to briefly justify each answer.

Analyzing Code Output

A few of the reflection questions below will be based on the output of your code and you may use your class implementation however you’d like here to answer these questions.

Recall that scripting code will execute in the __main__ branch of a Python file, so any code you write to view the output of your program will be under the conditional

if __name__ == "__main__":

Remember the importance of whitespace in Python and make sure all code in this section follows the indent of the # TODO comment.

  1. [6 pts] Suppose four users in the American city you chose are looking for the top k=2 restaurants sorted by name, price (low to high), rating (high to low), and your category_choice, respectively. Name two design decisions that could change the output of at least one of these recommendations if those design decisions had been made differently. In your answer, consider design decisions made by either us, the homework designers, or you in choosing the additional category, creating the csv file, and implementing the code. Cite specific examples from your dataset for each design decision you named and explain why the outputs would change.

  2. [3 pts] Great news! LivingLikeALocal has started to gain some attention from investors in Japan! Naturally, your company is excited to expand operations to this new country and has asked you to test the existing database to see if it can be deployed as-is as soon as possible for maximum profits. Suppose the following restaurant is added to the database. Restaurant name: Ippudo Umeda Restaurant address: 北区角田町6-7 角田町ビル1F Osaka 大阪府 〒530-0017 Japan Rating: 4.6 Relative price: 1 Keyword: Ramen Describe one way your implementation of the restaurant database may fail with this new data. Next, name and justify one assumption in the categories given to you for the database (or the one you chose) that might make it more difficult to collect data in contexts beyond the United States.

  3. [3 pts] An American tourist visiting the Japanese city you chose used your recommendation function and went to the first restaurant recommended when sorting by rating. They loved the restaurant and wanted to send a handwritten letter to the owners to personally thank them for the experience. The tourist knows that the Japanese addressing system is different than in the United States, but they forget how it works. However, they had such success with your recommendation that they trust your algorithm to return the address in the correct order it would go on a letter. You may assume the following ordering for the Japanese addressing system.

    Report the address output of your implementation for the restaurant recommendation described above using the output from the overloaded __str__(self) function. Does your implementation of search_database return the address in the correct order? Briefly explain why or why not. Describe one benefit for reporting address information as the user would understand it in their local context and one benefit for reporting address information as it is understood in the restaurant’s local context.

  4. [6 pts] The executives at LivingLikeALocal want to understand how their restaurant recommendation system’s affordances shape user behavior. Using concepts from the lecture about material affordances:

    (a) Identify and describe two material affordances in your restaurant database implementation that define or suggest how it should be used. For each affordance, explain how it relates to both the technical system and its users. In lecture, we discussed how material affordances have three key characteristics: the material itself, a property of that material, and what that property suggests or defines about how it should be used. All three must be clearly identified to fully describe an affordance.

    (b) Give two examples of how your identified affordances might harm stakeholders.

    (c) For each affordance you identified, describe a material change to the system that changes the affordances you provided and describe how those affordances change.

  5. [4 pts] Suppose LivingLikeALocal becomes very popular in a certain city such that hundreds of people (tourists and locals!) a day use the website to decide where to eat. Give two potential consequences on the local restaurants of deploying the website in this popular city compared to a city of the same size where only a few people use the website.

  6. [4 pts] Using concepts and specific terms from the Winner reading, name one way the website technology might influence the communities it is deployed in and one way the community use might affect future development of the website technology.