Skip to content

HW3: Classes and Enums

Learning Objectives

This homework assignment is designed to help you understand the differences between enumerated types and classes. It will also start you on the path to becoming a better unit tester.

Background

Poke@You Logo

Several student members of JMU’s PlayMU have used what they have learned from playing board games and video games to create an exciting new sport, Poke@You. (Any similarities between Pokémon, Pikachu, and other trademarks are coincidental.) Thus far they have been quite successful in getting people to support their cause, however they know that there are several services that they must provide in order to become a successful professional sport. So, they have come to you to start writing some of the software they need.

Participants

There are two participants in a given Poke@You event. They are referred to as the left and right participants (based on whether they stand on the left or right side of the playing field).

Equipment

Each player wears a foam Poke@You finger (that is several times larger than a normal hand) on one hand. A participant scores points by bringing (an appropriate part of) their foam finger into contact with (an appropriate part of) their opponents body.

Algorithms, Heuristics, Formulas, and Examples

What constitutes an appropriate part of the foam finger and an appropriate part of the body depends on the event. There are three different Poke@You events that are named for the size of the foam finger: small, medium, and large (which is a description of the length and width of the finger, not the weight). In addition to the size of the foam finger used during the event, the different events have different attributes, including: the maximum weight of the foam finger, the parts of the foam finger that can be used to score a point, and the parts of the body that can be used to score a point.

Event Max. Weight Finger Parts Body Parts
small 500 grams tip torso, crotch
medium 775 grams tip head, arms, hands, torso, crotch, legs
large 500 grams tip, side head, arms, torso

Existing Classes

They have provided you with some classes that you can use to test these classes and enums. Specifically, they have provided you with a modified version of the Test class (based on the Test class that you wrote for a previous assignment) that uses overridden forEquals() methods and reports on the number of failed tests.

Test.java

They have also provided a PokeEventTest class (that uses the modified Test class) that you can use to test the enums.

PokeEventTest.java

Note that the testIsScoringTouch() method in the PokeEventTest class uses nested loops to test all combinations of BodyPart objects and FingerPart objects.

The Components to be Written

They want you to write a Battle class that encapsulates a battle between two competitors, a PokeEvent enum that the Battle class uses, and FingerPart and BodyPart enums that are used by the PokeEvent enum. The relationships between these different components are illustrated in the following UML class diagram.

Class Diagram

Your implementation must conform to the specifications in this diagram as well as the specifications listed below.

The PokeEvent Enum

The attributes in the PokeEvent enum are used to keep track of the size of the foam finger, as well as the body part and finger part that are appropriate for each event (as described above). In small events, the FingerPart[] attribute named fingerParts will contain one element and the BodyPart[] attribute named targets will contain two elements. In medium events, the fingerParts attribute will contain one element and the targets attribute will contain six elements. In large events, the fingerParts attribute will contain two elements and the targets attribute will contain three elements.

The Explicit Value Constructor

The explicit value constructor in the PokeEvent enum has parameters that can be used to initialize these attributes. The maximumWeight parameter obviously contains the maximum weight of the foam finger. The sideOK parameter will contain true if the side can be used to score a point (and, hence, the fingerParts attribute will need to contain two elements) and will contain false if only the tip can be used to score points (and, hence, the fingerParts attribute will need to contain one element). The targets parameter is variable length (as indicated by the ... after the type) and will hold the (appropriately sized) array of BodyPart objects that can be scored on.

When invoking this constructor, the actual parameters must include an int and a boolean and may contain 0 or more BodyPart objects (separated by commas). Internal to this constructor, the formal parameter named targets will be a BodyPart[] that will contain 0 or more elements (corresponding to the BodyPart objects in the actual parameters). For example, this constructor might be invoked in the PokeEvent enum as follows:

SMALL(500, false, BodyPart.TORSO, BodyPart.CROTCH)

and might be partially implemented as follows:

private PokeEvent(int maximumWeight, boolean sideOK, BodyPart... targets) {
  this.maximumWeight = maximumWeight;
  this.targets = targets;
}

The Methods

The getMaximumWeight() method must return the maximum weight for the foam finger used in the PokeEvent.

The isOnTarget() method must return true when the BodyPart of interest can be scored on in this PokeEvent and must return false otherwise.

The isLegalFingerPart() method must return true when the FingerPart of interest can be used to score a point in this PokeEvent and must return false otherwise.

The isScoringTouch() method must return true when a contact of the given FingerPart on the given BodyPart scores a point, and and must return false otherwise. This method must not duplicate code in any of the other methods in the enum. (It can, of course, invoke other methods in the enum.)

The Battle Class

The explicit value constructor in the Battle class must initialize all of the attributes in the class in the obvious way, and the accessors in the Battle class must return the associated attributes.

The increaseRightScore() and increaseLeftScore() methods must increase the value of the associated attributes by 1.

The toString() method must return a String representation of the participantLeft, scoreLeft, participantRight, and scoreRight attributes formatted using "%s %s, %s %s" as the format String.

Submission

You must submit (using Gradescope):

  1. Your implementation of the Battle class.
  2. Your implementation of the FingerPart enum.
  3. Your implementation of the BodyPart enum.
  4. Your implementation of PokeEvent enum.

Do not submit the Test class or any of your tests.

There is no limit on the number of submissions and no penalty for excessive submissions. Note that your submission will not be graded if it does not comply with the specifications. So, your submission should include a stubbed-out version of all of the classes. (This will allow you to get credit for the classes/methods that you do implement correctly.)

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 20 points (Partial Credit Possible)
Correctness 80 points (Partial Credit Possible)

Gradescope will provide you with hints, but may not completely identify the defects in your submission.

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 hw3.
  3. Download Test.java into the hw3 directory/folder.

Write the Simple enums

  1. Write FingerParts.java.
  2. Write BodyParts.java.

Stub-Out the Remaining Components

  1. Create a stub for the PokeEvent enum that includes all of the attributes and methods with “javadoc” comments.
  2. Create a stub for the Battle class that includes all of the attributes and methods with “javadoc” comments.

Understand the Test Cases

  1. Download PokeEventTest.java into the hw3 directory/folder.
  2. Read and understand the test cases in PokeEventTest.java.
  3. By hand (i.e., using pencil and paper), calculate the expected output from PokeEventTest.java.

Write the Remaining enum and Class

  1. Write and test PokeEvent.java one method at a time. (You can do this using the PokeEventTest class by commenting out the invocations of the methods that you don’t want to test.)
  2. Write and test Battle.java one method at a time. (You will need to write your own tests for this. This will not be a difficult task if you use the Test class.)

Help

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 syntax error is generated in PokeEvent if you type a BodyPart incorrectly?
  2. If you used String literals instead of an enum, what syntax error would be generated if you typed one of them incorrectly?
  3. Taking your answers to the previous two questions into consideration, what is one of the big advantages of using an enum rather than a collection of String literals?
  4. How would you invoke the isScoringTouch() method for PokeEvent.MEDIUM?
  5. Could you invoke the isScoringTouch() method on the String literal "MEDIUM" if you had used String literals instead of an enum?
  6. Taking your answers to the previous two questions into consideration, what is another big advantage of using an enum rather than a collection of String literals?