lab07 : Pizza Time!

num ready? description assigned due
lab07 true Pizza Time! Sun 05/21 11:59PM Sun 05/28 11:59PM

In this lab, we will utilize many concepts covered in the course so far including:

Note: It is important that you try and start this lab early so you can utilize our office hours / lab sections to seek assistance / ask clarifying questions during the weekdays before the deadline if needed!

Introduction

The goal for this lab is to write a program that will manage incoming pizza orders. All pizza orders have an associated time representing when the customer expects to have their pizza ready (it’s possible for a customer to call ahead and schedule a later pickup time). All pizza orders will be managed by a MinHeap where the next order to prepare is the one that is the earliest compared to the other orders.

In order to manage pizza orders for this lab, you will design various Pizza classes (Pizza, CustomPizza, and SpecialtyPizza that utilizes inheritance / polymorphism), a PizzaOrder class representing a collection of Pizzas a customer wants to place in a single order, and an OrderQueue class that organizes the Pizza orders in a MinHeap data structure.

You will also write pytests in testFile.py illustrating your behavior works correctly. This lab writeup will provide some test cases for clarity, but the Gradescope autograder will run different tests shown here.

Instructions

You will need to create six files:

There will be no starter code for this assignment, but rather class descriptions and required methods are defined in the specification below.

You should organize your lab work in its own directory. This way all files for a lab are located in a single folder. Also, this will be easy to import various files into your code using the import / from technique shown in lecture.

Pizza.py

The Pizza.py file will contain the definition of a Pizza base class. We will define the Pizza attributes as follows:

You should write a constructor that allows the user to construct a Pizza object by passing in values for the size. Your constructor should also create a price attribute and set it to 0.0.

Your Pizza class definition should also support the “getter” and “setter” methods for the price and size. Since this will be a base class for other Pizza types, anything we write here can be inherited by its child classes.

CustomPizza.py and SpecialtyPizza.py

Pizza objects can be two different types. Both of these types of pizzas inherit from the Pizza class:

  1. CustomPizza that allows the customers to add additional toppings of their choosing
  2. SpecialtyPizza that has already been pre-configured and has a fixed price based on its size

CustomPizza.py

Your CustomPizza class definition will be defined in CustomPizza.py. The CustomPizza class will contain a constructor that takes in the size of the Pizza, and should use this size to call our base class’ constructor. In addition to the size, it will initialize a toppings list represented as a Python List.

The price of a CustomPizza is defined by two things:

  1. the size of the pizza
  2. the number of toppings the pizza will have (assuming no toppings is a simple cheese pizza). CustomPizzas will have the following fixed prices based on its size:

The size of the pizza also dictates the amount each additional topping will cost based on the following definition:

Since we now know what the price of a pizza should be based on the size, the CustomPizza constructor should determine the base price of the pizza and set it appropriately (remember, no need to write it in this class if we already have the method in Pizza.py).

There are two more methods this class should support:

CustomPizza without toppings example:

cp1 = CustomPizza("S")

assert cp1.getPizzaDetails() == \
"CUSTOM PIZZA\n\
Size: S\n\
Toppings:\n\
Price: $8.00\n"

CustomPizza with a list of toppings example (note that each topping will be indented with a tab):

cp1 = CustomPizza("L")
cp1.addTopping("extra cheese")
cp1.addTopping("sausage")

assert cp1.getPizzaDetails() == \
"CUSTOM PIZZA\n\
Size: L\n\
Toppings:\n\
\t+ extra cheese\n\
\t+ sausage\n\
Price: $14.00\n"

SpecialtyPizza.py

A SpecialtyPizza class definition will exist in SpecialtyPizza.py. Similar to a CustomPizza object, the class constructor will take in a size as well as the name for the specialty pizza.

Also similar to the CustomPizza class, SpecialtyPizza will use the size to set its price appropriately. The price of a SpecialtyPizza is defined as follows:

Unlike custom pizzas, specialty pizzas do not have a list of toppings associated with it, but do have a unique name that will be displayed when getting details for this pizza. This class should also have its own getPizzaDetails method described below:

A sample output test for getPizzaDetails():

sp1 = SpecialtyPizza("S", "Carne-more")
assert sp1.getPizzaDetails() == \
"SPECIALTY PIZZA\n\
Size: S\n\
Name: Carne-more\n\
Price: $12.00\n"

PizzaOrder.py

The PizzaOrder class will be defined in PizzaOrder.py. This class will keep track of various pizzas for single order. The PizzaOrder class will have the following attributes:

The constructor for a PizzaOrder will take in the expected time that order should be ready:

The time format will be stored as an int in a 24-hour time format. For example, given a hour:minute:second format, the corresponding int values would be:

In addition to the constructor, getters / setters for the time attribute, the ability to add Pizza objects to the order, as well as a method to construct a string representing the order details will need to be implemented:

An example of the getOrderDescription() string format is given below:

cp1 = CustomPizza("S")
cp1.addTopping("extra cheese")
cp1.addTopping("sausage")
sp1 = SpecialtyPizza("S", "Carne-more")
order = PizzaOrder(123000) #12:30:00PM
order.addPizza(cp1)
order.addPizza(sp1)

assert order.getOrderDescription() == \
"******\n\
Order Time: 123000\n\
CUSTOM PIZZA\n\
Size: S\n\
Toppings:\n\
\t+ extra cheese\n\
\t+ sausage\n\
Price: $9.00\n\
\n\
----\n\
SPECIALTY PIZZA\n\
Size: S\n\
Name: Carne-more\n\
Price: $12.00\n\
\n\
----\n\
TOTAL ORDER PRICE: $21.00\n\
******\n"

OrderQueue.py

The OrderQueue class will be defined in OrderQueue.py. This priority queue is implemented as a MinHeap data structure. The OrderQueue will manage PizzaOrder objects based on their time attribute.

Since it’s possible to remove from an empty OrderQueue, we will create and raise an exception when this is done. You will define a QueueEmptyException class in OrderQueue.py that doesn’t do anything except define an Exception object to raise when this happens (recall, we did do an example of defining basic Exception class types - you can refer to lect06 notes).

In addition to the construction of the MinHeap in this class, two methods are required to be implemented:

The automated tests will create various pizza orders with different time attributes. It will then call processNextOrder one at a time and check the removed PizzaOrder is in the right priority by checking their expected getOrderDescription() string. You should write similar tests to confirm the MinHeap state is in the correct order.

testFile.py

This file should test all of your classes using pytest. Think of various scenarios and edge cases when testing your code according to the given descriptions. You should test every class’ method functionality (except for getters / setters). Even though Gradescope will not use this file when running automated tests (there are separate tests defined for this), it is important to provide this file with various test cases (testing is important!!).

Of course, feel free to reach out / post questions on Piazza as they come up!

Submission

Once you’re done with writing your class definitions and tests, submit the following files to Gradescope’s Lab07 assignment:

There will be various unit tests Gradescope will run to ensure your code is working correctly based on the specifications given in this lab.

If the tests don’t pass, you may get some error message that may or may not be obvious at this point. Don’t worry - if the tests didn’t pass, take a minute to think about what may have caused the error. If your tests didn’t pass and you’re still not sure why you’re getting the error, feel free to ask your TAs or Learning Assistants.