HW3: Barbed Wire Fencing

Homework 3

Barbed Wire Fencing

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.

Overview

Several former members of the JMU Fencing Club are upset with the United States Fencing Association (USFA) and would like to start an alternative named Barbed Wire Fencing. Thus far they have been quite successful in getting people to support their cause (in part because of their tough-sounding name). However, they know that they must offer all of the services that are provided by the USFA. So, they have come to you to start writing some of the software they need.

Specifically, they want you to write a Bout class that encapsulates a bout between two fencers, a FencingEvent enum that the Bout class uses, and a BladePart and BodyPart enum that are used by the FencingEvent enum. They have provided you with some classes that you can use to test these classes and enums.

Existing Classes

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 FencingEventTest class (that uses the modified Test class) that you can use to test the enums.

📄FencingEventTest.java

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

They have also provided a MeleeDriver class that you can use to test the entire system using a hypothetical three-person tournament called a melee.

📄MeleeDriver.java

It does not use the Test class and does not include the expected results. Hence, you will have to perform some calculations by hand before you can use it (i.e., it will report the actual results and you will have to determine if they are correct).

Finally, they have provided a WhiteBoxTests class (that uses the Test class) that you will use when answering the “Questions to Think About”.

📄WhiteBoxTests.java

This class contains unit tests that completely cover all of the enums and classes that you must write, but is not sufficient for verifying the correctness of your code. In other words, your code could contain defects and still pass all of these tests.

The Classes to be Written

You must write three enumerated types, two that are simple and have no attributes or methods, and one that is more complicated. You also must write one “normal” class. 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 BladePart Enum

Fencing blades have multiple different parts. The two that are relevant for fencing events are the edge and the tip.

The BodyPart Enum

As you (hopefully) already know, the human body has many different parts. The parts that are relevant for fencing are the head, arms, hands, torso, crotch, and legs.

The FencingEvent Enum

There are three different fencing events (named for the weapon that is used in each): foil, epee, and sabre. In addition to the weapon used during the event, the different events have different attributes, including: the maximum weight of the weapon, the parts of the blade that can be used to score a point, and the parts of the body that can be used to score a point. The attributes in the FencingEvent enum are used to keep track of these differences.

The Attributes

In foil events, the maximum weight of the weapon is 500 grams, only the tip of the blade can be used to score a point (hence the BladePart[] attribute named bladeParts will contain one element), and points can only be scored on the torso and crotch (hence the BodyPart[] attribute named targets will contain two elements).

In epee events, the maximum weight of the weapon is 775 grams, only the tip of the blade can be used to score a point (hence the bladeParts attribute will contain one element), and points can be scored on any part of the body (hence the targets attribute will contain six elements).

In sabre events, the maximum wight of the weapon is 500 grams, both the tip and edge of the blade can be used to score points (hence the bladeParts attribute will contain two elements), and points can only be scored on the head, arms, and torso (hence the targets attribute will contain three elements)

The Explicit Value Constructor

The explicit value constructor in the FencingEvent enum has parameters that can be used to initialize these attributes. The maximumWeight parameter obviously contains the maximum weight of the weapon. The edgeOK parameter will contain true if the edge can be used to score a point (and, hence, the bladeParts attribute will need to contain two elements) and will contain false if only the tip can be used to score points (and, hence, the bladeParts attribute will need to contain one element). The targets parameter is variable length (as indicated by the ... after the type, these are also called varargs ) 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 FencingEvent enum as follows:

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

and might be partially implemented as follows:

private FencingEvent(int maximumWeight, boolean edgeOK, BodyPart... targets) {
  this.maximumWeight = maximumWeight;
  this.targets = targets;
}

where targets[0] will be BodyPart.TORSO and targets[1] will be BodyPart.CROTCH.

The Methods

The getMaximumWeight() method must return the maximum weight for the weapon used in the FencingEvent.

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

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

The isScoringTouch() method must return true when a contact of the given BladePart 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 Bout Class

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

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

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

Submission

You must submit (using Gradescope):

  1. Your implementation of the Bout class, the BladePart enum, the BodyPart enum, and the FencingEvent enum. Do not include the Test class or any of the drivers.

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/enums. (This will allow you to get credit for the classes/enums/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:

CriterionPointsDetails
Conformance to the Style Guide20 points(All or Nothing; Success Required)
Correctness80 points(Partial Credit Possible)

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

Note that some criteria are described as being “Success Required”. This means that Gradescope will not assess subsequent criteria unless these criteria are satisfied (and you will receive a grade of 0 for the subsequent criteria). So, for example, if your code does not conform to the style guide then it will not be assessed using any subsequent criteria and you will receive a grade of at most 20 for the assignment.

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 project for this assignment named hw3. (Remember, do not create a module and create separate folders for source and class files).
  3. Activate Checkstyle for this assignment.
  4. Download Test.java, FencingEventTest.java, MeleeDriver.java, and WhiteBoxTests.java to a directory outside of your Eclipse workspace (e.g., the downloads directory for this course).

Understand the Test Cases

  1. Read and understand the test cases in FencingEventTest.java.
  2. By hand (i.e., using pencil and paper), calculate the expected output from MeleeDriver.java.

Write the Simple enums

  1. Write BladePart.java.
  2. Write BodyPart.java.

Stub-Out the Remaining Components

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

Add the Provided Classes to the Project

  1. Copy Test.java into hw3.
  2. Copy FencingEventTest.java into hw3.
  3. Copy MeleeDriver.java into hw3.
  4. Copy WhiteBoxTests.java into hw3.

Write the Remaining enum and Class

  1. Write and test FencingEvent.java one method at a time. (You can do this using the FencingEventTest class by commenting out the invocations of the methods that you don’t want to test.)
  2. Write and test Bout.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.)
  3. Test the entire system using MeleeDriver.java and debug if necessary.

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.

Questions About Enumerated Types

  1. What syntax error is generated in FencingEvent if you type a BodyPart incorrectly?
  2. If you used String literals instead of an enum, what syntax error would be generated if you type 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 FencingEvent.EPEE (for example)?
  5. Could you invoke the isScoringTouch() method on the String literal "EPEE" if, for example, 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?

Questions About Test Coverage

  1. “Launch WhiteBoxTests” using the coverage tool (i.e., click on the WhiteBoxTests.java tab to make it active and then click on Launch to launch the tests using the coverage tool). Does your code pass all of the tests? (It should if you have gotten to this part of the assignment!)
  2. Click on the tab for FencingEvent.java. Are all of the statements and branches covered (i.e., is everything highlighted in green)? (They should be if you’ve gotten to this part of the assignment!)
  3. Comment-out the first of the tests in the WhiteBoxTests class that checks the isScoringTouch() method and “Launch WhiteBoxTests” using the coverage tool. What is now true of the branch coverage of the isScoringTouch() method? Why?
  4. What is now true of the coverage of the isLegalBladePart() method? Why?
  5. Why is the isOnTarget() method still completely covered?

Before you proceed, undo any changes you made.

Questions About Unit Testing

  1. In the FencingEvent enum, temporarily change the maximum weight of the EPEE to 785 rather than 775, and “Launch WhiteBoxTests” using the coverage tool. Despite the fact that the FencingEvent enum now contains defects, does it pass all of the tests? Is the FencingEvent enum completely covered?
  2. Is it enough to just cover code when writing unit tests?
  3. Temporarily, change the increaseLeftScore() method in the Bout class so that it increases the scoreLeft attribute by 5 rather than 1, and “Launch WhiteBoxTests” using the coverage tool. Despite the fact that the Bout class now contains defects, does it pass all of the tests? Is the Bout class completely covered?
  4. Does the WhiteBoxTests class test the increaseLeftScore() and increaseRightScore() methods or does it just execute them? Does the coverage tool indicate that statements/branches have been tested, or just that they’ve been executed?
  5. What are the implications of your answer to the previous questions? In other words, what must you be sure to do when you are required to write and submit unit tests for future assignments?
  6. Which testing process was easier to use, the one that used the Test class (i.e., WhiteBoxTests.java and FencingEvent.java) or the one that didn’t (i.e., MeleeDriver.java)? Why?
  7. You were given extensive tests for the FencingEvent enum. As a result, your FencingEnum enum should have been correct before you submitted your code. If you become a professional programmer, there will not be a submission system for you to rely on. Instead, what must you do to ensure that your code is correct? With that in mind, what must you now start doing this semester?

Before you proceed, undo any changes you made.