|
|
Lab
3
***Do not modify the driver class. This is simply there to
provide you with some output - it is not part of the lab. If
webcat identifies any problems with the driver program - just ignore
them. I will adjust your score accordingly. You can
also
opt to remove the driver class and not submit it to webcat.
***Do
not modify the declaration - public - statement of any method.
These methods have been defined to webcat. If you
change
the name or add/remove an explicit parameter, or modify the return
type, webcat will reject your lab entirely as it will not
recognize the method. This will result in a 0 score by
webcat.
This lab builds upon Lab 1 & 2. The Location class is no longer
visible, but it's still there and you can still create a Location
object and call it's associated methods. It is included as an
executable and is fully functional, it's just not visible.
You can, however refer back to Lab 2 and the documentation
provided for Lab 2 if need be.
For this lab you are going to continue to work on the Station class.
Additional enhancements are being made to this class on the
price per gallon calculation and also some tracking elements.
Step
1
- read through the lab instructions in the Word document.
While
the scenario presented is for fun, there is some key information that
should be gleaned from the instructions.
Here are some key points that I pulled out of the documentation:
- New calculation for the price per gallon
- Different fuel types will be provided and the price
per gallon varies based upon the fuel types
- propane
- fuel type will equal "PROPANE"
- BTUs per gallon = 83500, to be contains in final constant variable with name of PROPANE_BTPG
- conversion factor = GASOLINE_BTPG / PROPANE_BTPG
- biodiesel
- fuel type will equal "BIODIESEL"
- BTUs per gallon = 127250, to be contains in final constant variable with name of BIODIESEL_BTPG
- conversion factor = GASOLINE_BTPG / BIODIESEL_BTPG
- ethanol
- fuel type will start with "E" with remaining portion being percentage, for example E80 would be 80% or .80
- BTUs per gallon = 75670, to be contains in final constant variable with name of ETHANOL_BTPG
- conversion factor = percentage * ETHANOL_BTPG + (1-percentage)*GASOLINE_BTPG
- biobutanol
- fuel type will start with "B" with remaining portion being percentage, for example B20 would be 20% or .20
- BTUs per gallon = 104800, to be contains in final constant variable with name of BIOBUTANOL_BTPG
- conversion factor = percentage * BIOBUTANOL_BTPG + (1-percentage)*GASOLINE_BTPG
- The conversion factors above are then multiplied against the price per gallon to calculate the price.
- Rating of the Stations
- Each station can receive ratings ranging from 1 through 5. These are to be accumulated and then averaged.
- Will need to make sure a rating has been received before an average can be calculated or a divide by 0 error will be generated.
- Categories
- Stations are categorized by fuel type and by rating.l
- Output - a to string method is written to generate a string containing information on the station.
Step
2
- now let's take a look at the program documentation. The
javadocs have already been created for you in this project.
Javadocs provide a description of each method including the
purpose, what will be returned, if anything, and what explicit
parameters are to be provided, if any. This is really helpful
information that you will definitely want to check out before you begin
working on your test cases - which is what you should do BEFORE you
begin working on the program itself.
To generate the
documentation in BlueJ, select TOOLS, PROJECT DOCUMENTATION.
When you view the
documentation, you will see a listing for both of the constructors and
all of the methods. If you click on a constructor or method
name
you will be taken to that particular constructor or method where you
will be able to see a description of the method. You will
also be
shown what will be returned, if anything, and what explicit parameters
are expected if any. A description of each is provided.
This is really useful information and can guide you as you
develop your test cases and eventually start working on coding the
object itself.
Step
3 While it is tempting to work on this entire lab all at once, I would like to recommend that you break it into pieces.
First
- work on the constructors and the set/get methods. These are
actually very similar to what you've done in Lab 2, so this should be
very straight forward. It is also good to point out that if the
constructors and set/get methods are not working, the rest of the
methods will not work. So, get your foundation working first and
then more on to the rest of the class.
Step
4a
- develop the test cases for the constructors and set methods. Open up the javadocs
for the Station class and open up the StationTest class. If
you have a wide screen monitor, put the javadocs on one side and the
StationTest class code on the other so that they are side by side and
you can see both at the same time.
Test the
constructors
- The process for testing a constructor is the same, regardless of
whether it is an empty/default constructor or an explicit constructor.
- Call the constructor you are testing to create the object.
- Assert that the object is not null
- Check each of the instance variables to make sure they are equal to what you are expecting.
- The empty/default constructor test case has been written for you.
- Take a moment to review how this is done.
- You will be writing the test case for the explicit constructor. The process is the same as above:
- Call the explicit constructor, passing in values for
latitude, longitude, description, price, and fuel type. Check the
javadocs for the order of the parameters and the data types that are
expected.
- Asset not null to make sure the object has been created successfully.
- Call the get methods for each instance variable, making sure the value returned is what you specified in the constructor.
Test the set Methods
- The format for testing a set method is:
- Use a constructor, default or explicit, to create the object.
- Call the set method to set the instance variable to a new value.
- Call the get method to retrieve the value of the instance variable.
- Compare what is returned from the get method against what you used when setting the value to make sure they match.
- The
code for testing the description and fuel type is provided for you.
Use these as a model when writing the test case for the
setPricePerGallon().
Test the distanceInMiles() Method
- This method is the same as what you had in Lab 2. The test cases have been provided for you.
Step
5a
- code the Station class
- Now
that the test cases have been written, writing the Station class
itself becomes much easier. You are already familiar with the
methods because you have reviewed the documentation and have written
tests for them.
- Documentation
- Take a moment, before you begin, to review the javadoc documentation
for this class. It can be viewed from BlueJ by,
Tools,
Project Documentation.
- This will show you the constructors
and all of the methods. From this documentation you will be
able
to determine if anything is returned and what explicit parameters are
expected.
- Coding - Look for the comments lines inserted
within the methods that tell
you that code should be inserted. This is where you will be
writing code. If you see a method that does not have any
comments
saying you should code, then please do not modify the method.
It
is correct as it is.
Instance
Variables
- These have already been coded for you.
In Lab 2 there were 4 instance variables, description,
pricePerGallon, fuelType, and a Location object. Notice that in
Lab 3 there are 6. Two new instance variables have been added -
ratingsTotal and ratingsCount. These will also need to be
initialized in your constructors.
Constant
Variables
- The constants for the fuel type have been coded for you.
These are used in determining the type of fuel. The
constant for the gasoline BTPG has been coded for you. You will
need to code the constants for the BTPG of the other fuel types.
Refer to the Word document instructions for these values.
Note that there are some additional constants that contain the
category types for the stations.
Constructors- You will be writing the code for the default/empty constructor.
Remember the purpose of a constructor is to set the instance
variables equal to default values.
- the description should be set equal to "NO DESCRIPTION PROVIDED"
- the price per gallon should be set equal to 0.0
- the fuel type should be set equal to 0
- both the ratings total and the ratings count will be set equal to 0
- location
- this one is a bit different. You're not going to set it equal
to value, but rather create a location object passing in the default
values.
- If you take a look at the instance variable you'll see:
- private Location stationLocation;
- notice
there's no equal sign. What this means is that the object
variable has been defined as holding data type Location - but that it
hasn't yet been initialized. It doesn't contain anything.
If you were to try and access the contents of this variable you
would get an error.
- In the constructor you need to complete the
right hand side of the equals sign. You need to initialize your
object variable by calling the Location constructor.
- = new Location(0.0, 0.0);
- Now DO NOT do the following:
- Location stationLocation = new Location(0.0, 0.0);
- See
the data type Location? As soon as you put this in front of a
variable you end up with a local variable that exists only within the
method.
- Instead do:
- this.stationLocation = new Location(0.0, 0.0);
- This says to take the existing object variable and just assign it to a new Location object.
- Explicit Constructor - This has been coded for you. Take a moment to see how this was done.
get Methods()
- The purpose of a get method is to return the value of an instance variable.
- For the description, price per gallon, and fuel type it's very straight forward.
- For
the latitude and longitude - there's a slight twist. You can't
just return the latitude and longitude because they don't exist within
the station class itself. Instead you have to call the
getLatitude and getLongitude methods from the Location class. See
the getLatitude() method for an example of how this is done.
set Methods()
- The
purpose of a set method is to change the value of an instance variable.
An explicit parameter is passed to the method containing the
value that the instance variable should be set to.
- The format will be:
- this.instanceVariableName = passedInParameterName;
calcDistance() Method
- The
formula for calculating the distance between 2 locations was written in
the Location class. What you have to do here is call that method.
But.... the method is the location class is expecting a Location
object to be passed to it as an explicit parameter. If you take a
look at the explicit parameters passed to this method, however, you
have a latitude and longitude, not a Location class. So, the
first thing you need to do is create a temporary location object using
the passed in latitude and longitude.
- Then call the Location
object method using your Location instance variable as the calling
object and passing in your temporary location object as the explicit
parameter. Something like:
- return stationLocation.calcDistance(tmpLocation);
Step 6a -
Complile both your Station and StationTest classes. When they
compile cleanly - no syntax errors, run your tests. Do all of
your test cases pass for the constructors and set methods? If so
you are ready to proceed on to the next portion of the code. If
not - then go back and review your logic and make corrections. Do
not proceed until these are working correctly as the remainder of your
code cannot function without these being correct!
Step
4b
- develop the test cases for the calcPricePerGGE method.
testCalcPricePerGGE()
- The
conversion factor will vary based upon the fuel type, so the first
thing to do is to figure out what fuel type you currently have. If you
refer back to the Word document you will find that the fuel type
instance variable will contain either:
- PROPANE
- BIODIESEL
- E followed by a percentage for ETHANOL
- B followed by a percentage for BIOBUTANOL
- You will need to develop test cases for each of the fuel types.
- I
created an excel spreadsheet, plugged in the BTPGs for each fuel type,
created the formula based upon the Word document instructions, and
computed the price per GGE.
- I made sure to include each
fuel type and for the ethanol and biobutanol I include several
different percentages, one that was 100, one that was 0 and several
inbetween.
- I entered these values for my test cases.
Step
5b
- code the pricePerGGE method.
calcPricePerGGE()
- The
conversion factor will vary based upon the fuel type, so the first
thing to do is to figure out what fuel type you currently have.
If you refer back to the Word document you will find that the
fuel type instance variable will contain either:
- PROPANE
- BIODIESEL
- E followed by a percentage for ETHANOL
- B followed by a percentage for BIOBUTANOL
- The
fuel type instance variable is data type string which means you cannot
use the == operator for comparison, you must use the .equals() method.
- One
other thing to note - you're going to have to be careful when checking
for your fuel type. BIOBUTANOL will start with a B followed by a
percentage, but BIODIESEL will also start with a B. You need to
make sure you are differentiating between these two fuel types.
- The best way to is have an If/else if construct
- create a local variable to hold your computed conversion factor
- check first for propane
- if it is, then move the propane BTPG value to the conversion factor
- if it's not propane then check if it's biodiesel
- if it is, then move the biodiesel BTPG value to the conversion factor
- if it's not biodiesel, then check if it's ethanol
- if it is - then you can to calculate the ethanol conversion factor
- 1st
- parse out the percentage. You'll need to use the .substring()
method to retrieve everything after the E. Keep in mind that you
can't assume there will be just 2 digits after the E, there could be 3
if it's 100% ethanol, so you cannot hardcode in an ending value.
Another thing to consider is that the value you end up with will
be a string. You can't multiply a string against a number.
You're going to have to convert your string value to a number
value.
- After you've obtained the percentage and it has been
converted from a string to a number, you can then plug in your values
to the formula in the Word document and determine the conversion factor.
- if it's not ethanol, then check if it's biobutanol
- Follow the same steps outlined for ethanol above
- Now that you've figured out the conversion factor you're ready to determine the price per GGE. It would be computed as:
- price per gallon * (gasoline BTPG / convFactor)
- Hmmm
- what if your conversion factor is equal to 0 - that will end up with
a divide by 0 error. So, you first need to check your conversion
factor. If it is equal to 0, then return 0, otherwise calculate
the price per GGE and return the value.
- Hmmm again - make sure
that you do not get caught by integer division! Make sure that
you conversion factor is a double value or that you case the result as
double or you will lose your precision.
Step 6b -
Complile both your Station and StationTest classes. When they
compile
cleanly - no syntax errors, run your tests. Is the test case for
your price per GGE calculation passing along with all of the
constructors and set methods? If so you are ready to
proceed on to the next portion of the code. If not - then go back
and
review your logic and make corrections. Do not proceed until
these are
working correctly!
Step
4c
- develop the test cases for the rateStation and calcAvgRating methods.
testRateStation()
- The
purpose of this method is to record a rating for a station. It
will increment the number of ratings that have been received by 1 and
add the rating to the rating total instance variable.
- The test cases for this method have already been written for you. Please take a moment to review.
testCalcRatingsAvg()
- The
purpose of this method is to compute the average rating for a station.
This is done by dividing the total ratings by the number of
ratings received.
- Several test cases are needed.
- The test case that is provided is to test if there are no ratings. This should return a -1.0.
- Add a rating - then test to make sure the average returned is what you expect.
- Add a second rating - test again.
- Add 2 or 3 more and test again.
Step
5c
- code the rateStation and calcRatingsAvg methods.
rateStation()
- The
purpose of this method is to record a rating for a station. It will
increment the number of ratings that have been received by 1 and add
the rating to the rating total instance variable.
- First
check to make sure the rating is valid, valid ratings are 1 through 5
inclusive. If a rating is invalid, do not do anything.
- For valid ratings, add the rating to the ratingsTotal instance variable and increment the ratingsCount instance variable.
calcRatingsAvg()
- The
purpose of this method is to compute the average rating for a station.
This is done by dividing the total ratings by the number of ratings
received.
- First check to make sure the ratingsCount is > 0, if it is not return -1.0. No ratings have been received.
- If
the count is greater than 0 then divide the ratingsTotal by the
ratingsCount - but..... both of these are integer values.
Integer division will result in the loss of the decimal places
and as a result loss of precision. One or the other must be
converted to a double value or the result must be cast as double.
Step 6c -
Complile both your Station and StationTest classes. When they
compile
cleanly - no syntax errors, run your tests. Is the test case for
your rate station and calculate ratings average passing along with all
of the previous test cases? If so you are ready to
proceed on to the next portion of the code. If not - then go back
and
review your logic and make corrections. Do not proceed until
these are
working correctly! Step
4d
- develop the test cases for the inCategory method.
testIsInCategory()
- The purpose of this method is to determine if a fuel type is within a specific category. There are 6 potential categories.
- ANY - true should be returned regardless of the fuel type
- ETH_REGULAR - true should be returned if the fuel type is ethanol and the percentage is
- ETH_LOW- true should be returned if the fuel type is ethanol and the percentage is
- ETH_HIGH - true should be returned if the fuel type is ethanol and the percentage is
- ETH_FLEX_FUEL - true should be returned if the fuel type is ethanol and the percentage is
- HIGH_RATED - true should be return if the rating average for a station is 4 or greater
- Some of the test cases have been developed for you. You must add additional test cases to test all of the categories.
Step
5d
- code the rateStation and calcRatingsAvg methods.
isInCategory()
- The purpose of this method is to determine if a fuel type is within a specific category. There are 6 potential categories.
- ANY - true should be returned regardless of the fuel type
- ETH_REGULAR - true should be returned if the fuel type is ethanol and the percentage is
- ETH_LOW- true should be returned if the fuel type is ethanol and the percentage is
- ETH_HIGH - true should be returned if the fuel type is ethanol and the percentage is
- ETH_FLEX_FUEL - true should be returned if the fuel type is ethanol and the percentage is
- HIGH_RATED - true should be return if the rating average for a station is 4 or greater
- This method will contain a bunch of IF statements.
- First
- check for the ANY category. It doesn't matter the fuel type for
this category so if it is the ANY category - return true.
- Next work your way through the ethanol categories
- The process for each of these is the same.
- Is the category an ethanol category?
- Is the fuel type ethanol?
- Is the percentage within the range for the category?
- Last check for the rating
- If
the category is the high rated category, then call the method to
calculate the rating and check to see if the value returned is > 4,
if it is return true
- last return false - if you made it this far, then none of your above conditions were met and false should be returned.
Step 6d -
Complile both your Station and StationTest classes. When they compile
cleanly - no syntax errors, run your tests. Is the test case for your is in category passing along with all of the
previous test cases? If so you are ready to
proceed on to the next portion of the code. If not - then go back and
review your logic and make corrections. Do not proceed until these are
working correctly!
Step
4e
- develop the test cases for the toString method.
testToString()
- The purpose of this method is to provide an output string in a specified format.
- The test cases have been developed for you. Please review to ensure you understand the testing that is taking place.
First
to write - the test case. Looking at the javadocs, we can see
that this method returns a value of type String and accepts no explicit
parameters. The format of the first line is to be:
description
[latitude, longitude] price: $price
This
is the same format we've had all along. Refer back to your
code
from Lab 2 to see what you did and duplicate this here in both the test
case and the method.
The format of the second line is to be:
Selling fuelType fuel
Where fuelType is to be replaced by the contained in the instance
field. This is a new line for this method.
The format of the third line is to be:
Rated avg (out of 4)
based on count customer ratings
Where
avg is to be replaced by the value returned from the calcRatingsAvg()
method and count is taken from the ratingsCount instance variable.
An
example of what this might look like altogether is provided in the
javadocs. In addition, there is a note at the end that says
if
there are no customer ratings (ratingsCount = 0), then the third line
should read:
No customer ratings
That's
a red flag for testing. That means there are 2 situations for
which you need to test. The situation is when the
ratingsCount is
greater than 0 and the second is when the ratingsCount is equal to 0.
If
you take a look at the toString test case, you'll see that the case
when the ratingsCount is equal to 0 has already been coded for you.
What remains is for you to test when the ratingsCount is
greater
than 0. The situation has already been set. If you
view the
code directly following the assertEquals statements you'll see:
station1.rateStation(1);
station1.rateStation(4);
station1.rateStation(2);
result = station1.toString();
Three
ratings have already been added to the object station1 for you and the
toString() method has been called with the result put into the String
variable result. All that remains is for you to test the
result
variable to make sure it contains what you are expecting. The
first 2 lines should contain the same value as above - right?
The
longitude, latitude, description, price, fuel type didn't change.
So you really don't need to retest those lines.
What did
change was the rating, so you really only need to test the third line.
- What are you expecting the count to be after these 4
lines execute?
- What average are you expecting to be returned?
(1 + 4 + 2) / total count
Write
a test statement that looks for the correct count and average, properly
formatted as you are expecting line 3 to be. (Don't forget to
check for all spaces, etc.)
Compile. Correct syntax errors.
Step
5e
- code the toString method
toString()
Ok
- test case is written, now to the actual method itself.
Remember, we've already done quite a bit of the legwork while
writing our test cases. We've read through the javadocs,
we've
determined what the output should look like. We've also
discovered a special case, that we need to display one thing if the
ratingsCount is equal to 0 and something else if it is not.
Go
ahead and write your code. Don't forget the spaces between
words
and your variables. Use an IF statement to check the
ratingsCount, adding the appropriate statement if the count is equal to
0 or if not.
Step 6e -
Complile both your Station and StationTest classes. When they compile
cleanly - no syntax errors, run your tests. Is the test case for your to string passing along with all of the
previous test cases? If so you are ready to
proceed on to the next portion of the code. If not - then go back and
review your logic and make corrections. Do not proceed until these are
working correctly!
Really - I cannot stress this enough. Do not try to code the
entire
class/test cases at one time. Please follow my guidance and
break this
down into components. When you work on the entire thing at
one time
and you encounter an error - you will have no idea where this error is
located. Is it in the original constructor? Is it
in the set or get?
You'll have to review all of your code. If,
however, you've been
working in pieces and testing each piece after it's completion, you'll
know that when you encounter an error it must be associated with the
code that you just wrote. You've narrowed down the scope
which makes
debugging much easier.
Step 7 - update the Readme.txt
file. Specific information is required to be entered into this
file. Make sure you view the instructions for this file so that
you do not lose points for an incorrect format.
Step 8 - use
the check style feature in BlueJ. This can be found under Tools,
Checkstyle. This tool will evaluate your program for style.
Each of the classes will be listed. Clicking on a class
name will reveal any style problems that have been found. These
would include such things as lines that are too long, incorrect
indentation, missing periods, etc. Correct all of these identified
problems. Recompile, retest. ****It is really important
that you do this. For each check style error found, webcat will
deduct 1 pt. These can really add up and you don't want to lose
points for things that can easily be corrected.
Step 9 - submit to WebCat.
This is not a one time submission. Webcat is a tool that
can be used to ensure you receive the maximum number of points possible. Submit, review the output. Make
corrections and submit again. Continue this process until you
have perfected your lab.
|