Polymorphism and pre validating class attributes - java

Basically I have been tasked with tackling the following scenario:
When you are designing your class/es, you have to decide what attributes and methods you will include in. For example, if you decide to work in millimeters, your size variable (length) could be of type integer (but later, when calculating the cost, you will have to convert the volume into square inches, because the cost is given per cubic inch of plastic (Table 2 and Table 3 of the coursework)). The volume of plastic material used will be the difference between the outer and inner volume of a pipe. If you decided to prompt the length in meters, then the type should be double, or float, etc.
Once you have validated the user order, your program should determine, based on Table 1, what is the type of the ordered pipe.
Table 1. Types of plastic pipes available.
Type Plastic’s grade Colour print Inner insulation Outer reinforcement Chemical resistance
0 1 2
I 1 – 3 YES NO NO NO NO YES/NO
II 2 – 4 NO YES NO NO NO YES/NO
III 2 – 5 NO NO YES NO NO YES/NO
IV 2 – 5 NO NO YES YES NO YES/NO
V 3 – 5 NO NO YES YES YES YES/NO
That's all fine but the part that is getting me is this bit here:
Say in your main class you have determined that client’s order is a pipe of type I, then you can create an object of TypeI and for this object you can call the cost() method to calculate the cost and to show it to the user.
It is basically asking to not instantiate any objects before figuring out which one you need to instantiate, which is hard when it classes a big if statement in the verification as a 'Brute force method'.
Here is what I have so far.
Main
public class Cw1 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
ArrayList<Pipe> pipeList = new ArrayList<Pipe>();
// TODO code application logic here
Grade g1 = new Grade(1,3,true,false,false,false,false);
Grade g2 = new Grade(2,4,false,true,false,false,false);
Grade g3 = new Grade(2,5,false,false,true,false,false);
Grade g4 = new Grade(2,5,false,false,true,true,false);
Grade g5 = new Grade(3,5,false,false,true,true,true);
pipeList.add(g1);
pipeList.add(g2);
pipeList.add(g3);
pipeList.add(g4);
pipeList.add(g5);
for (Pipe p: pipeList)
{
p.setGrade(1);
p.setColour0(false);
p.setColour1(false);
p.setColour2(true);
p.setIns(true);
p.setReinf(true);
p.validate();
}
}
}
Grade (It must have abstracting in the solution)
public class Grade extends Pipe {
public Grade(int minGrade, int maxGrade, boolean hasColour0, boolean hasColour1, boolean hasColour2, boolean hasIns, boolean hasReinf) {
super(minGrade, maxGrade, hasColour0, hasColour1, hasColour2, hasIns, hasReinf);
}
}
And pipe
public abstract class Pipe {
public boolean isChemRes() {
return chemRes;
}
public void setChemRes(boolean chemRes) {
this.chemRes = chemRes;
}
public boolean isColour0() {
return colour0;
}
public void setColour0(boolean colour0) {
this.colour0 = colour0;
}
public boolean isColour1() {
return colour1;
}
public void setColour1(boolean colour1) {
this.colour1 = colour1;
}
public boolean isColour2() {
return colour2;
}
public void setColour2(boolean colour2) {
this.colour2 = colour2;
}
public double getDiameter() {
return diameter;
}
public void setDiameter(double diameter) {
this.diameter = diameter;
}
public boolean isIns() {
return ins;
}
public void setIns(boolean ins) {
this.ins = ins;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public boolean isReinf() {
return reinf;
}
public void setReinf(boolean reinf) {
this.reinf = reinf;
}
public Pipe(int minGrade, int maxGrade, boolean hasColour0, boolean hasColour1, boolean hasColour2, boolean hasIns, boolean hasReinf) {
this.minGrade = minGrade;
this.maxGrade = maxGrade;
this.hasColour0 = hasColour0;
this.hasColour1 = hasColour1;
this.hasColour2 = hasColour2;
this.hasIns = hasIns;
this.hasReinf = hasReinf;
}
public Pipe() {
}
//<editor-fold desc="Class variables">
private int grade;
private double length, diameter;
private boolean colour0, colour1, colour2, ins, reinf, chemRes;
private int minGrade, maxGrade;
private boolean hasColour0, hasColour1, hasColour2, hasIns, hasReinf;
// </editor-fold>
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
//<editor-fold desc="Public Methods">
public double calcVol()
{
return 0;
}
public double calcCost()
{
return 0;
}
public void validate()
{
if ((grade >= minGrade && grade <= maxGrade) & (colour0 == true && hasColour0 || colour1 == true && hasColour1 || colour2 == true && hasColour2) && (ins == hasIns) && (reinf == hasReinf))
{
System.out.print("True");
}
else
{
System.out.print("False");
}
}
// </editor-fold>
}
So basically, I don't understand how I could achieve the same result without instantiating the objects before hand and validating them?
The class isn't high level, we have only just learned polymorphism.

Usually, the data which tells you which objects to create comes from an external source: a file, a socket, another object etc. In your case, you could use a text file. Create the Grade instances passing the values you read to the constructor and then call validate and cost on each.
public class PipeFactory(){
public Pipe CreatePipe( int minGrade, int maxGrade, boolean hasColour0, boolean hasColour1, boolean hasColour2, boolean hasIns, boolean hasReinf ){
if( (minGrade == 1 || maxGrade == 3) /* ... Complete this condition yourself */ )
return new TypeIPipe();
if( (minGrade == 2 || maxGrade == 4 /* ... Complete this condition yourself */ )
return new TypeIIPipe();
//If for other types...
//If no pipe was created, parameters are invalid, so we throw an exception
throw new InvalidArgumentException( "Can't create a pipe with these parameters" );
}
}

Related

New integer is equal to the difference of 2

I'm coding something for a theoretical airport case study and I need help with one bit. I've got 2 different integers with names: maxfuelCapacity and fuelCurrent, and I need something that says ' fuel needed to pump is '.....' being the difference between the maxfuelCapacity of the plane and the current amount. There are no real values so far. How do I go about doing that?
public static int maxfuelCapacity;
public int fuelCurrent;
public String name;
Boolean parked;
public String[] Plane = {
"BA103", "BA493", "BA209"
};
public void setName(String n) {
name = n;
}
public void setParked(Boolean o) {
parked = o;
}
public int getInt(String Maxfuelcapacity) {
return maxfuelCapacity;
}
public String getInt1 (String fuelCurrent) {
return fuelCurrent;
}
As has been mentioned in the comments, your method would look like:
public int fuelNeeded(int fuelCurrent, int maxfuelCapacity) {
if(fuelCurrent >= maxfuelCapacity) {
System.out.println("The tank already has enough");
return 0;
}
return maxfuelCapacity- fuelCurrent;
}
So you call this method in your main function that does the calculation.

Player class winning percentage java

I am trying to create a method for " winning percentage " in a player class. I know I need to incorporate total wins divided by total games played, but the code is meant to be simple so I cannot use complex code. (beginner project in computer science) Any useful feedback would be great as I have spent multiple days attempting this and getting no where. By the way, ties count as half a win.
Update: Implemented the getters into the getWinningPercentage method. Also calculated everything inside the getWinningPercentage and removed the setWinningPercentage considering it was useless code. Results were as follows:
Bob
5 wins, 1 losses, 2 ties
Winning percentage = 0.75
public class Player
{
private int numWins = 0;
private int numTies = 0;
private int numLosses = 0;
private String name;
public void setWins(int w)
{
numWins = w;
}
public int getWins()
{
return numWins;
}
public void setTies(int t)
{
numTies = t;
}
public int getTies()
{
return numTies;
}
public void setLosses(int L)
{
numLosses = L;
}
public int getLosses()
{
return numLosses;
}
public void setName(String n)
{
name = n;
}
public String getName()
{
return name;
}
public void incrementWins()
}
numWins++;
}
public void incrementTies()
{
numTies++;
}
public void incrementLosses()
{
numLosses++;
}
public double getWinningPercentage()
{
double totalGames = getWins() + getTies() + getLosses();
double totalWins = getWins() + (getTies() / 2.0);
double winningPercentage = (totalWins / totalGames);
return winningPercentage;
}
}
The winning percentage should be a calculated property, not a field, and not have a setter method. Instead there should only be a "getter" (public double getWinningPercentage()) method and you should calculate and return this value from within the method itself from the other fields that your class already has.
We should leave it up to you to create this method and formula yourself.

How to construct a method that needs to pass in the values from a constructor?

I'm writing a program that is based around registering the amount of energy consumption that is being used by appliances within a house. So far, I have created various meter classes such as WaterMeter, GasMeter etc. with empty methods that need to be filed with values, I have also created classes for appliances that have methods that will be used to register the consumption of energy within each appliance. What I am working on now is applying the energy values that are stored within a constructor, putting those values into a timePasses() method that will then return those values to their specific meter's methods so that they can be registered. This is what I have so far:
Appliance class example:
public class ElectricShower extends Shower
{
public int isOn = -1;
public int isOff = 0;
public int incrementTime;
public int x = -1;
private static ElectricMeter instance = new ElectricMeter();
public static ElectricMeter getInstance() { return instance; }
#Override
public int currentState()
{
if (x == 0)
return isOff;
else
{
return isOn;
}
//returns isOn;
}
#Override
public void useTime(int defaultTime)
{
defaultTime = 15;
incrementTime = 1;
}
public void shower()
{
//call timePasses() method
}
#Override
public int timePasses()
{
if(x == isOff)
return 0;
else
{
ElectricMeter.getInstance().incrementConsumed(electricityUse);
}
}
ElectricShower(int electricityUse, int gasUse, int waterUse, int timeOn)
{
super(electricityUse, gasUse, waterUse, timeOn);
this.electricityUse = 12 * incrementTime;
this.gasUse = 0 * incrementTime;
this.waterUse = 4 * incrementTime;
this.timeOn = 15 * incrementTime;
}
}
Meter example:
public class ElectricMeter
{
public int incrementConsumed(int value)
{
}
public int incrementGenerated()
{
}
public boolean canGenerate()
{
}
public String getConsumed()
{
}
public String getGenerated()
{
}
}
What I need to do next is:
take the values of electricityUse and waterUse and store them within the timePasses() else staement
Within the timePasses() else statement, place the value of electrcityUse in the incrementGenerated() method within the ElectricMeter class and do the same for the waterUse variable.
UPDATE
Classes have been updated, still struggling to find out how to make it work.
First of all, I assume you have an Appliance class that all the appliances extends from. You should create variables in the Appliance class that stores electricity, gas and water usage:
public class Appliance
{
public int electricityUse, gasUse, waterUse, timeOn;
// ...
}
Note that you should always use getters and setters instead of public fields. I'm just lazy :D
Change your constructor so that the variables above get set:
ElectricShower(int electricityUse, int gasUse, int waterUse, int timeOn)
{
super(electricityUse, gasUse, waterUse, timeOn);
// I don't know why you multiply the constant by incrementTime here. Seems weird. I think you can remove them.
this.electricityUse = 12 * incrementTime;
this.gasUse = 0 * incrementTime;
this.waterUse = 4 * incrementTime;
this.timeOn = 15 * incrementTime;
}
One way to write the else clause is to use the "Singleton Pattern".
In every meter class, write something like this:
private ElectricMeter() {}
private static ElectricMeter instance = new ElectricMeter();
public static ElectricMeter getInstance() { return instance; }
In the incrementConsumed method, you should accept a parameter that indicates how much to increment:
public int incrementConsumed(int value)
{
// logic here...
}
In the else clause, you can just do:
ElectricMeter.getInstance().incrementConsumed(electricityUse);
GasMeter.getInstance().incrementConsumed(gasUse);
WaterMeter.getInstance().incrementConsumed(waterUse);
You should review your design.
If you need to access to a class parameter you could just define it public or better create a so called getter method that returns the value.
Example:
public class MyData {
public int counter;
}
....
// Some other class
MyData data = new MyData();
data.counter = 5;
System.out.println(data.counter);
Or
public class MyData {
private int counter;
public void setCounter(int counter) {
this.counter = counter;
}
public int getCounter() {
return this.counter;
}
}
....
// Some other class
MyData data = new MyData();
data.setCounter(5);
System.out.println(data.getCounter());
In your code I see:
public int incrementConsumed()
{
//Store value of electricityUse.
}
But this method should just return an integer and have not parameter to get an input to store.
It should be:
public void incrementConsumed(int amount) {
this.amount += amount;
}
I'm concerned about this line:
gasUse = 0 * incrementTime;
If you multiply something to 0 it will be always 0...

javafx: How to monitor state change of a variable that has more than 2 states?

I have a variable money of type double. I want this variable to have 3 states like this:
double money = something;
public int getMoneyState(){
if (money > 0){
return 1;
} else if(money == 0){
return 0;
} else{
return -1;
}
}
Problem is: I only know how to formulate this problem in the most conventional way, that is without using any javafx libraries / functions.
Eventually, I want to have a tableView where one of the columns will display the money variable, and its font color will change depending on the state of this variable, i.e. if after editing the cell, money = 100, the state will be 1 and font color is yellow. If after editing the cell, money = 0, the state will be 0 and font color is grey.And if after editing the cell, money = -555, the state will be -1 and font color is Green.
What I am looking for: I want to be able to track the money variable as well as its state and any changes in state. By that, I mean a change in the money variable will lead to a change in the state by using a method similar to getMoneyState() above. And depending on the state of the variable, the cell's font color will change.
I need help re-writing getMoneyState() method such that the state will automatically be updated after the user edits the money cell.
Hope this makes more sense.
Assuming you have money represented as a DoubleProperty:
DoubleProperty money = new SimpleDoubleProperty();
for example, you can do
IntegerBinding moneyState = Bindings.createIntegerBinding(() -> {
if (money.get() > 0) {
return 1 ;
} else if (money.get() == 0) {
return 0 ;
} else {
return -1 ;
}
}, money);
The two arguments to createIntegerBinding are a function returning an Integer, and a list of other observables on which the binding depends (here there is only one, money).
Now you can add listeners to moneyState or bind to it in the usual way.
If money is a property in some bean, then you can expose moneyState as a ReadOnlyIntegerProperty in a similar way:
public class MyEntity {
private final DoubleProperty money = new SimpleDoubleProperty();
public DoubleProperty moneyProperty() {
return money ;
}
public final double getMoney() {
return moneyProperty().get();
}
public final void setMoney(double money) {
moneyProperty().set(money);
}
private final ReadOnlyIntegerWrapper moneyState = new ReadOnlyIntegerWrapper();
public ReadOnlyIntegerProperty moneyStateProperty() {
return moneyState.getReadOnlyProperty();
}
public int getMoneyState() {
return moneyStateProperty().get();
}
private IntegerBinding moneyStateBinding ;
public MyEntity(double money) {
setMoney(money) ;
moneyStateBinding = Bindings.createIntegerBinding(() -> {
if (getMoney() > 0) {
return 1 ;
} else if (getMoney() == 0) {
return 0 ;
} else {
return -1 ;
}
}, moneyProperty());
moneyState.bind(moneyStateBinding);
}
}
A couple of other options. First note that your logic is already implemented by Math.signum(), so you can do:
IntegerBinding moneyState = Bindings.createIntegerBinding(() ->
(int) Math.signum(money.get()), money);
You can also implement it with the fluent Bindings API:
IntegerBinding moneyState = Bindings.when(money.greaterThan(0)).then(1)
.otherwise(Bindings.when(money.isEqualTo(0)).then(0).otherwise(-1));
You could create and Observer and make a MoneyClass, which inherits the Observable Class for example. You could then track any changes to the Money and it´s state made
The result could be looking like this
// Money class
import java.util.Observable;
public class MoneyClass extends Observable{
private double money = 0;
private int state = 0;
public static final int POSITIV = 1;
public static final int ZERO = 0;
public static final int NEGATIV = -1;
public int getMoneyState(){
if (money > 0){
return MoneyClass.POSITIV;
} else if(money == 0){
return MoneyClass.ZERO;
} else{
return MoneyClass.NEGATIV;
}
}
public void setMoney(int money) {
this.money = money;
setChanged();
notifyObservers("Money");
setMoneyState();
}
public double getMoney() {
return money;
}
public int getState() {
return state;
}
private void setMoneyState() {
if (state != getMoneyState()) {
state = getMoneyState();
setChanged();
notifyObservers("State");
}
}
public static void main(String[] args) {
}
}
//Observer
import java.util.Observable;
import java.util.Observer;
public class MoneyObserver implements Observer{
public void addObserving(MoneyClass money) {
money.addObserver(this);
}
#Override
public void update(Observable o, Object arg) {
if(arg instanceof String) {
String type = (String) arg;
if(type.equals("Money")) {
System.out.println("Money got changed to " + ((MoneyClass)o).getMoney());
} else if(type.equals("State")) {
System.out.println("State got changed to " + ((MoneyClass)o).getState());
}
}
}
public static void main(String[] args) {
MoneyObserver o = new MoneyObserver();
MoneyClass c = new MoneyClass();
o.addObserving(c);
c.setMoney(20);
c.setMoney(50);
c.setMoney(-30);
}
}

How to compare three integer values?

I have three integer values along with its text. My requirement is to give rank to all of them.
E.g. I have A = 50 points, B = 500 Points, C = 50 points.
Now I would like to compare all of these and find max and equal values and its according name(like, A/B/C).
EDIT ::
As a output it should return, B = 1st Rank, A = 2nd Rank, C = 2nd Rank.
If anyone has any idea about how can I implement code as per my requirement then, it would be great.
Thanks in advance.
public class ScoreVO implements Comparator<Integer> {
private String playerName = Constants.BLANK_STRING;
private int playerScore;
public String getPlayerName () {
return playerName;
}
public void setPlayerName ( String playerName ) {
this.playerName = playerName;
}
public int getPlayerScore () {
return playerScore;
}
public void setPlayerScore ( int playerScore ) {
this.playerScore = playerScore;
}
#Override
public int compare ( Integer o1, Integer o2 ) {
return o2.compareTo ( o1 );
}
}
Here is my class with Comparator<>.
Please suggest me if I am wrong.
A sample running code which gives output shown below as per your requirement along with player rank. There is a separate method assignRank(List<>) which you can use to assign ranks to players.
Score List: [ScoreVO [playerName=B, playerScore=500, playerRank=1], ScoreVO [playerName=A, playerScore=50, playerRank=2], ScoreVO [playerName=C, playerScore=50, playerRank=2]]
public class ScoreExample {
public static void main(String[] args) {
List<ScoreVO> scoreList = new ArrayList<ScoreVO>();
scoreList.add(new ScoreVO("A", 50));
scoreList.add(new ScoreVO("C", 50));
scoreList.add(new ScoreVO("B", 500));
Collections.sort(scoreList);
assignRank(scoreList);
System.out.println("Score List: "+scoreList);
}
private static void assignRank(List<ScoreVO> scoreList) {
int rank = 0;
int score = 0;
for(ScoreVO scoreVO : scoreList) {
if(score != scoreVO.getPlayerScore()) {
rank++;
scoreVO.setPlayerRank(rank);
score = scoreVO.getPlayerScore();
} else {
scoreVO.setPlayerRank(rank);
}
}
}
}
class ScoreVO implements Comparable<ScoreVO> {
public String playerName;
public int playerScore;
public int playerRank;
public ScoreVO(String playerName, int playerScore) {
this.playerName = playerName;
this.playerScore = playerScore;
}
public String getPlayerName() {
return playerName;
}
public void setPlayerName(String playerName) {
this.playerName = playerName;
}
public int getPlayerScore() {
return playerScore;
}
public void setPlayerScore(int playerScore) {
this.playerScore = playerScore;
}
public int getPlayerRank() {
return playerRank;
}
public void setPlayerRank(int playerRank) {
this.playerRank = playerRank;
}
#Override
public int compareTo(ScoreVO o) {
if(o.getPlayerScore() != getPlayerScore()) {
if(getPlayerScore() > o.getPlayerScore())
return -1;
else
return 1;
}
return getPlayerName().compareTo(o.getPlayerName());
}
#Override
public String toString() {
return "ScoreVO [playerName=" + playerName + ", playerScore="
+ playerScore + ", playerRank=" + playerRank + "]";
}
}
ScoreVO should implement Comparable<ScoreVO>. And your compareTo method looks like this:
#Override
public int compareTo ( ScoreVO o ) {
if(playerScore != o.playerScore)
return Integer.compare(playerScore, o.playerScore);
return playerName.compareTo(o.playerName);
}
You should implment Comparable for ordering purpuses, and equals() for equation (that can use compareTo)
like this
public class ScoreVO implements Comparable<ScoreVO> {
#Override
public int compareTo(ScoreVO other) {
return other == null ? 1 : getPlayerScore() - other.getPlayerScore();
}
#Override
public boolean equals(object other) {
return !(other instanceof ScoreVO) ? false : compareTo(other) == 0 ;
}
}
However, you probably want to compare equality based on player name. think of putting ScoreVO object in a map - what is the key? so -
#Override
public boolean equals(object other) {
return other == null || !(other instanceof ScoreVO) ? false :
getPlayerName.equals(other.getPlayerName()) ;
}
As there are just three values, it is possible to hard-code all operations. You can think of a very compact and efficient way to work this out.
Every comparison of two values can give an outcome >, = or <. Assigning the value 0, 1 or 2 to these, you can pack the three comparisons in a single number using base 3 encoding. You will end up with a number in range 0 to 26, and every different value corresponds to a different answer that you can tabulate (or process in a switch statement).
int Compare(int A, int B) { return A > B ? 0 : (A == B ? 1 : 2); }
char* Answer[27]= { "A1B2C3", "A1B1C3", "B1A2C3", ... }; // To be filled
return Answer[Compare(A, B) + 3 * compare(B, C) + 9 * compare(A, C)];

Categories