lab07 : Fresh Tea Shipping System

num ready? description assigned due
lab07 true Fresh Tea Shipping System Sun 11/17 11:59PM Sun 11/24 11:59PM

Introduction

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 to seek assistance / ask clarifying questions during the weekdays before the deadline if needed!

You are the owner of a small tea business preparing to ship out orders of tea blends in time for the holidays. All placed orders are guaranteed to arrive before the holidays. All tea orders also have an associated shipping distance, and you want to ensure that customers from farther distances will receive their tea fresh and in time for the holidays. The goal for this lab is to write a program that will manage incoming tea orders by prioritizing orders with larger shipping distances. All tea orders will be managed by a MaxHeap where the next order to ship is the one that has the largest shipping distance compared to other orders.

In order to manage tea orders, you will design various Tea classes (Tea, CustomTea, and SpecialtyTea that utilizes inheritance / polymorphism), a TeaOrder class representing a collection of teas a customer wants to place in a single order, and an OrderQueue class that organizes the tea orders in a MaxHeap data structure.

You will also write pytests in a 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.

Tea.py

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

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

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

CustomTea.py and SpecialtyTea.py

Tea objects can be categorized as two different types. Both of these types of teas inherit from the Tea class:

CustomTea.py

Your CustomTea class definition will be defined in CustomTea.py. In addition to the fields inherited from the Tea class, a CustomTea object will contain the following additional attributes specific to a CustomTea item:

The price of a CustomTea object is defined by two things:

CustomTea objects will have the following fixed prices based on its size:

The size of the Tea also dictates the amount each additional flavor will cost based on the following criteria:

Since we now know what the price of a Tea should be based on the size, the CustomTea constructor should determine the base price of the Tea and update it appropriately based on the size. The CustomTea class will contain a constructor that takes in the size and base values for this object:

Other methods this class should support:

An example (with escape characters shown for formatting) is given below. When constructing your string, please follow the EXACT format since this is what Gradescope will expect.

cp1 = CustomTea("S", "Oolong")

assert cp1.getTeaDetails() == \
"CUSTOM TEA\n\
Size: S\n\
Base: Oolong\n\
Flavors:\n\
Price: $10.00\n"

An example (with escape characters shown for formatting) with a list of flavors is given below (note that each flavor will be indented with a tab):

cp1 = CustomTea("L", "Green")
cp1.addFlavor("peach")
cp1.addFlavor("jasmine")

assert cp1.getTeaDetails() == \
"CUSTOM TEA\n\
Size: L\n\
Base: Green\n\
Flavors:\n\
\t+ peach\n\
\t+ jasmine\n\
Price: $21.50\n"

SpecialtyTea.py

A SpecialtyTea class definition is defined in SpecialtyTea.py. Similar to a CustomTea object, the SpecialtyTea constructor will take in a size as well as the specific name (str) for the specialty tea item.

Similar to the CustomTea class, SpecialtyTea will use the size to set its price appropriately. The fixed price of a SpecialtyTea object is defined as follows:

Unlike CustomTea objects, SpecialtyTea objects do not have a base or a list of flavors associated with it, but do have a unique name that will be displayed when getting details for this tea blend. This class needs to support its own definition for:

sp1 = SpecialtyTea("S", "Earl Grey")

assert sp1.getTeaDetails() == \
"SPECIALTY TEA\n\
Size: S\n\
Name: Earl Grey\n\
Price: $12.00\n"

TeaOrder.py

The TeaOrder class definition is defined in TeaOrder.py. This class will keep track of various teas items for a single order. The TeaOrder class will have the following attributes:

The constructor for a TeaOrder will take in the shipping distance and sets the distance attribute appropriately. Initially, the TeaOrder teas attribute will be empty when constructed, and tea objects can be added later:

The ability to add Tea 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 return string format is given below (be sure to format your return string in the EXACT format since this is what Gradescope is expecting):

ct1 = CustomTea("S", "Black")
ct1.addFlavor("rose")
ct1.addFlavor("cardamom")
st1 = SpecialtyTea("M", "Matcha")
order = TeaOrder(400) #shipping distance: 400 miles 
order.addTea(ct1)
order.addTea(st1)

assert order.getOrderDescription() == \
"******\n\
Shipping Distance: 400 miles\n\
CUSTOM TEA\n\
Size: S\n\
Base: Black\n\
Flavors:\n\
\t+ rose\n\
\t+ cardamom\n\
Price: $10.50\n\
\n\
----\n\
SPECIALTY TEA\n\
Size: M\n\
Name: Matcha\n\
Price: $16.00\n\
\n\
----\n\
TOTAL ORDER PRICE: $26.50\n\
******\n"

OrderQueue.py

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

The OrderQueue constructor (__init__(self)) will simply initialize the underlying Python List representing the MaxHeap.

Since it’s possible to attempt 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 and raising this exception in lecture - you can refer to lect06 notes).

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

The automated tests will create various tea orders with different distance attributes. It will then call processNextOrder one at a time and check the removed TeaOrder is in the right priority by checking their expected getOrderDescription string. You should write similar tests to confirm the MaxHeap 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 creating your own tests 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 - take a minute to think about what may have caused the error and try writing various test scenarios to see if your code is behaving correctly according to the specifications. If you’re still not sure why you’re getting the error, feel free to ask your TAs / Learning Assistants.

* Lab07 created by Emily Tian and adapted / updated by Richert Wang (F24)