Skip to content

HW5: CaterRing

CaterRing

Danger

As discussed below, on this assignment you may submit to Gradescope at most ten times without penalty. Hence, you should be confident that your code is correct before you submit the first time.

Learning Objectives

This homework assignment is designed to help you learn about reference types, references, and the difference between aliases and deep copies.

Definitions

Aliases
Two variables are aliases for the same object iff they contain the same reference.
Copies
Two objects are copies of each oher iff their attributes are copies of each other. They are said to be deep copies iff their reference-type attributes are also copies of each other, not aliases for the same object.

In the following example, s and t are aliases for the same object, but m is a copy of n.

Color s, t, m, n;

s = new Color(69, 0, 132);
t = s;

m = new Color(203, 182, 119);
n = new Color(n);

Overview

Some students who have worked in D-Hall for many years have decided to start a catering company (named CaterRing) that will serve off-campus clients. They have come to you to create a meal planning tool.

Existing Classes

The CS159 faculty have provided you with the source code for a utility class that might help you improve the quality of some of your toString() methods.

Pluralize.java

This class is in the hw5.text package.

Note

This class may contain style errors. You are responsible for detecting and correcting them.

The Components to be Written

You must write three components named Food, Order, and Meal that are summarized in the following UML class diagram.

Class Diagram

Detailed Design Specifications

In addition to the specifications contained in the UML class diagram, your implementation must conform to the following specifications.

The Food Component

The description attribute must be a deep copy of the parameter that is passed to the explicit value constructor, and the copy constructor must invoke the explicit value constructor. You may assume that the description will never be null.

The equals() method must return true if all of the attributes of the owning object are "equal to" (determined appropriately based on the type of the attribute) the attributes of the given object.

The toString() method must return a String representation of the ouncesPerPerson, the appropriate form (singular or plural, determined using the Pluralize class) of the word "ounce", the description attribute, and the pricePerOunce attribute that is formatted using "%d %s per person of %s at $%5.2f per ounce". Think about. It must return "I hate that!" when the description is anything other than "Chips".

The Order Component

The explicit value constructor must make a fully deep copy of the food parameter, and the copy constructor must invoke the explicit value constructor.

The getPrice() method must return the ounces attribute multipled by the appropriate member of the food attribute. Think about: It must convert the ounces to pounds before multiplying.

The getServes() method must return the ounces attribute divided by the appropriate member of the food attribute. It must return the number of people that can be "fully" served.

The toString() method must return the value of the ounces attribute, the appropriate form of the word "ounce", and the value of the food object's description attribute formatted using "%d %s of %s". Think about. It must return "That seems like too much" when the ounces attribute is greater than 20.

The Meal Component

The constructor must initialize the orders attribute.

The addOrder() method must add an alias of the parameter named order to the attribute named orders unless an Order with an "equivalent" Food (in the sense of the equals() method in the Food class) is already in orders, in which case it must increase the number of ounces in the existing Order. It must return the owning object, so that calls to addOrder() can be chained. Think about. It must return null if the Order object is not in orders and must return this otherwise.

The getOrder(int) method must return null when the value of the parameter is out of bounds. Otherwise, it must return a reference to the element with the given index in the orders attribute. To think about. It must delete that element before returning it.

The getPrice() method must return the total price of all Order objects in the orders attribute. To think about. It must cap the price of any particular order at $3.00 when performing the calculation.

The getServes() method must return 0 when there are no Order objects in the orders attribute. Otherwise, it must return the minimum value of the number of people served by all of the Order objects in the orders attribute.

The size() method must return the number of elements in the orders attribute.

Examples

Examples of some of these specifications may help to clarify them.

Food

One Food that is commonly found at parties is hamburgers, which might have a description attribute of "Ground Beef", an ouncesPerPerson attribute of 4, and a pricePerOunce attribute of 0.40. The toString() method must return the following in this case:

4 ounces per person of Ground Beef at $ 0.40 per ounce

Order

Suppose a Food of with a description of "Ground Beef" has a serving size of 4 ounces and a price of $0.40 per ounce. Then for an Order with a size of 18 ounces, the getServes() method must return 4 (i.e., 18/4) and the getPrice() method must return 7.20 (i.e., 18 * 0.40).

The toString() method for this example must return the following:

18 ounces of Ground Beef

Meal

One Food that is commonly found at parties is hamburgers, which might have a description attribute of "Ground Beef", an ouncesPerPerson attribute of 4, and a pricePerOunce attribute of 0.40. A typical party might have 20 people in attendance, so the planners might place an Order for this Food with an ounces attribute of 80. A typical party would also serve several other foods, all of which would be incorporated in a single Meal.

Suppose the Meal contains $7.20 worth of ground beef, $7.80 worth of potato chips, and $8.80 worth cole slaw. Then, the getPrice() method must return 23.80.

Suppose the Order contains enough ground beef to serve 4, enough potato chips to serve 7, and enough cole slaw to serve 24. Then, the getServes() method must return 4.

Finally, suppose the following:

  • A serving size of Ground Beef is 4 ounces, costs $0.40 per ounce, and the order consists of 18 ounces
  • A serving size of Potato Chips is 2 ounces, costs $0.52 per ounce, and the order consists of 15 ounces
  • A serving of Cole Slaw is 3 ounces, costs $0.55 per ounce, and the order consists of 16 ounces

Then there is enough Ground Beed to serve 4 (at a cost of $7.20), there are enough Potato Chips to serve 7 (at a cost of $7.80), there is enough Cole Slaw to serve 5 (at a cost of $8.80), and the entire meal serves 4 (at a cost of $23.80).

Testing

How you test your code is up to you. But, you should be aware of the fact that Gradescope will not provide much help. In addition, your Professors and Teaching Assistants will provide less help if you have not tested your code before coming to us. So, it is strongly recommended that you use JUnit to conduct both white/open box and black/closed box testing.

Any tests you write (whether they use JUnit or not), must be in the hw5.testing package and must contain the word "Test". Your test classes need not conform to the style guide.

Submission

You must submit (using Gradescope) a .zip file (named hw5.zip) that contains the files/folders text (which will contain Pluralize), cater (which will contain your implementation of the Food, Order, and Meal classes), and testing (if you choose to write tests).

Because you should not be using Gradescope to verify your code (i.e., because you must be able to test and debug code without the help of a submission system), you may submit to Gradescope at most ten times without penalty. After that, you will be penalized 5 points for each submission.

Grading

Your code will first be graded by Gradescope and then by the Professor. The grade you receive from Gradescope is the maximum grade that you can receive on the assignment

Gradescope Grading

Your code must compile (in Gradescope, this will be indicated in the section on "Does your code compile?") and all class names and method signatures must comply with the specifications (in Gradescope, this will be indicated in the section on "Do your class names, method signatures, etc. comply with the specifications?") for you to receive any points on this assignment. Gradescope will then grade your submission as follows:

Criterion Points Details
Conformance to the Style Guide 0 points (Success Required)
Correctness 100 points (Partial Credit Possible)

Manual Grading

After the due date, the Professor may manually review your code. At this time, points may be deducted for inelegant code, inappropriate variable names, bad comments, etc.

Since nobody will be looking over your shoulder, you can use any process that you would like to use. However, it is strongly recommended that you use the process described here.

Get Started

  1. Read and understand the entire assignment.
  2. Create a directory/folder for this assignment named hw5.
  3. Download Pluralize.java.
  4. Create a directory/folder under hw5 named text.
  5. Copy Pluralize.java into the hw5.text directory/folder.

Stub-Out the Classes

  1. Create a directory/folder under hw5 named cater.
  2. Stub-out the Food class ( in the package hw5.cater).
  3. Stub-out the Order class ( in the package hw5.cater).
  4. Stub-out the Meal class ( in the package hw5.cater).
  5. Add the "javadoc" comments to the three classes.
  6. Check the style of the three classes and make any necessary corrections.

Implement and Test the Classes

  1. Implement and test everything in the Food class except the copy constructor.
  2. Implement and test the copy constructor in the Food class.
  3. Implement and test the explicit value constructor and simple getters in the Order class.
  4. Implement and test the toString() method in the Order class.
  5. Implement and test the getOunces() method in the Order class.
  6. Implement and test the getPrice() method in the Order class.
  7. Implement and test the getServes() method in the Order class.
  8. Implement and test the copy constructor in the Order class.
  9. Implement and test the setter methods.
  10. Implement and test the constructor, addOrder(), getOrder(), and size() methods in the Meal class.
  11. Implement and test the getPrice() method in the Meal class.
  12. Implement and test the getServes() method in the Meal class.
  13. Implement the size()method in the Meal class.

Remember, any tests you write (whether they use JUnit or not), must be in the hw5.testing package and must contain the word "Test" in the class name.

Relevant Programming Patterns

An understanding of the following programming patterns will help you complete this assignment:

Questions to Think About

You don't have to submit your answers to these questions, but you should try to answer them because they will help you determine whether or not you understand some of the important concepts covered in this assignment.

  1. What does the word "deep" really mean when used in the context of a "deep copy"? Can there be different levels of depth?
  2. Why is it sometimes appropriate to use an alias and sometimes appropriate to use a deep copy?
  3. Do you think this assignment used aliases and deep copies appropriately or would you have designed it differently? Why?