HW3: Barbed Wire Fencing
12 minute read
Homework 3
![Barbed Wire Fencing](BarbedWireFencing.png)
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.
They have also provided a FencingEventTest
class (that uses the
modified Test
class) that you can use to test the enums.
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.
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”.
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](Design.png)
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):
- Your implementation of the
Bout
class, theBladePart
enum, theBodyPart
enum, and theFencingEvent
enum. Do not include theTest
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:
Criterion | Points | Details |
---|---|---|
Conformance to the Style Guide | 20 points | (All or Nothing; Success Required) |
Correctness | 80 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.
Recommended Process
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
- Read and understand the entire assignment.
- Create a project for this assignment named
hw3
. (Remember, do not create a module and create separate folders for source and class files). - Activate Checkstyle for this assignment.
- Download
Test.java
,FencingEventTest.java
,MeleeDriver.java
, andWhiteBoxTests.java
to a directory outside of your Eclipse workspace (e.g., thedownloads
directory for this course).
Understand the Test Cases
- Read and understand the test cases in
FencingEventTest.java
. - By hand (i.e., using pencil and paper), calculate the expected output from
MeleeDriver.java
.
Write the Simple enums
- Write
BladePart.java
. - Write
BodyPart.java
.
Stub-Out the Remaining Components
- Create a stub for the
FencingEvent
enum that includes all of the attributes and methods with “javadoc” comments. - 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
- Copy
Test.java
intohw3
. - Copy
FencingEventTest.java
intohw3
. - Copy
MeleeDriver.java
intohw3
. - Copy
WhiteBoxTests.java
intohw3
.
Write the Remaining enum and Class
- Write and test
FencingEvent.java
one method at a time. (You can do this using theFencingEventTest
class by commenting out the invocations of the methods that you don’t want to test.) - 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 theTest
class.) - 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
- What syntax error is generated in
FencingEvent
if you type aBodyPart
incorrectly? - If you used
String
literals instead of an enum, what syntax error would be generated if you type one of them incorrectly? - 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? - How would you invoke the
isScoringTouch()
method forFencingEvent.EPEE
(for example)? - Could you invoke the
isScoringTouch()
method on theString
literal"EPEE"
if, for example, you had usedString
literals instead of an enum? - 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
- “Launch WhiteBoxTests” using the coverage tool (i.e., click on the
WhiteBoxTests.java
tab to make it active and then click onto 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!)
- 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!) - Comment-out the first of the tests in the
WhiteBoxTests
class that checks theisScoringTouch()
method and “Launch WhiteBoxTests” using the coverage tool. What is now true of the branch coverage of theisScoringTouch()
method? Why? - What is now true of the coverage of the
isLegalBladePart()
method? Why? - Why is the
isOnTarget()
method still completely covered?
Before you proceed, undo any changes you made.
Questions About Unit Testing
- In the
FencingEvent
enum, temporarily change the maximum weight of theEPEE
to785
rather than775
, and “Launch WhiteBoxTests” using the coverage tool. Despite the fact that theFencingEvent
enum now contains defects, does it pass all of the tests? Is theFencingEvent
enum completely covered? - Is it enough to just cover code when writing unit tests?
- Temporarily, change the
increaseLeftScore()
method in theBout
class so that it increases thescoreLeft
attribute by 5 rather than 1, and “Launch WhiteBoxTests” using the coverage tool. Despite the fact that theBout
class now contains defects, does it pass all of the tests? Is theBout
class completely covered? - Does the
WhiteBoxTests
class test theincreaseLeftScore()
andincreaseRightScore()
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? - 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?
- Which testing process was easier to use, the one that used the
Test
class (i.e.,WhiteBoxTests.java
andFencingEvent.java
) or the one that didn’t (i.e.,MeleeDriver.java
)? Why? - You were given extensive tests for the
FencingEvent
enum. As a result, yourFencingEnum
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.