Merge branch 'master' into story_61

Also got client-server handshake working. Multiple clients can connect and control their own boat.
The client's boat has a larger black triangle drawn around it. Probably needs tidying up.
Added isClientBoat boolean to VisualiserBoat.

WindGenerator is now an interface, implemented by ConstantWindGenerator (useful for testing) and RandomWindGenerator. Added ConstantWindGeneratorTest.
RandomWindGenerator was formerly WindGenerator.
The WindGenerator is passed in to MockRace.

CommandFactory throws a CommandConstructionException if it cannot create a command.

MessageSerialiser and MessageDeserialiser correctly terminate on error.

Readded VisualiserInput's switch statement in the main loop, pending a refactor.

Removed the sleep statement from LobbyController - it was blocking javaFX thread.

Lobby.fxml: moved buttons and text input into grid panes, so they don't break when you resize screen.

Added some test object creation functions in several test classes (MockRaceTest.createMockRace(), BoatXMLReaderTest.createBoatDataSource(), etc...).

#story[1095]
This commit is contained in:
fjc40
2017-08-10 23:49:21 +12:00
45 changed files with 1320 additions and 556 deletions
@@ -0,0 +1,242 @@
package mock.model;
import shared.model.Bearing;
import shared.model.Wind;
import java.util.Random;
/**
* This class generates Wind objects for use in a MockRace.
* Bounds on bearing and speed can be specified.
* Wind can be completely random, or random incremental change.
*/
public class RandomWindGenerator implements WindGenerator {
/**
* The bearing the wind direction starts at.
*/
private Bearing windBaselineBearing;
/**
* The lower bearing angle that the wind may have.
*/
private Bearing windBearingLowerBound;
/**
* The upper bearing angle that the wind may have.
*/
private Bearing windBearingUpperBound;
/**
* The speed the wind starts at, in knots.
*/
private double windBaselineSpeed;
/**
* The lower speed that the wind may have, in knots.
*/
private double windSpeedLowerBound;
/**
* The upper speed that the wind may have, in knots.
*/
private double windSpeedUpperBound;
/**
* Creates a wind generator, with a baseline, lower bound, and upper bound, for the wind speed and direction.
* @param windBaselineBearing Baseline wind direction.
* @param windBearingLowerBound Lower bound for wind direction.
* @param windBearingUpperBound Upper bound for wind direction.
* @param windBaselineSpeed Baseline wind speed, in knots.
* @param windSpeedLowerBound Lower bound for wind speed, in knots.
* @param windSpeedUpperBound Upper bound for wind speed, in knots.
*/
public RandomWindGenerator(Bearing windBaselineBearing, Bearing windBearingLowerBound, Bearing windBearingUpperBound, double windBaselineSpeed, double windSpeedLowerBound, double windSpeedUpperBound) {
this.windBaselineBearing = windBaselineBearing;
this.windBearingLowerBound = windBearingLowerBound;
this.windBearingUpperBound = windBearingUpperBound;
this.windBaselineSpeed = windBaselineSpeed;
this.windSpeedLowerBound = windSpeedLowerBound;
this.windSpeedUpperBound = windSpeedUpperBound;
}
@Override
public Wind generateBaselineWind() {
return new Wind(windBaselineBearing, windBaselineSpeed);
}
/**
* Generates a random Wind object, that is within the provided bounds.
* @return Generated wind object.
*/
public Wind generateRandomWind() {
double windSpeed = generateRandomWindSpeed();
Bearing windBearing = generateRandomWindBearing();
return new Wind(windBearing, windSpeed);
}
/**
* Generates a random wind speed within the specified bounds. In knots.
* @return Wind speed, in knots.
*/
private double generateRandomWindSpeed() {
double randomSpeedKnots = generateRandomValueInBounds(windSpeedLowerBound, windSpeedUpperBound);
return randomSpeedKnots;
}
/**
* Generates a random wind bearing within the specified bounds.
* @return Wind bearing.
*/
private Bearing generateRandomWindBearing() {
double randomBearingDegrees = generateRandomValueInBounds(windBearingLowerBound.degrees(), windBearingUpperBound.degrees());
return Bearing.fromDegrees(randomBearingDegrees);
}
/**
* Generates a random value within a specified interval.
* @param lowerBound The lower bound of the interval.
* @param upperBound The upper bound of the interval.
* @return A random value within the interval.
*/
private static double generateRandomValueInBounds(double lowerBound, double upperBound) {
float proportion = new Random().nextFloat();
double delta = upperBound - lowerBound;
double amount = delta * proportion;
double finalAmount = amount + lowerBound;
return finalAmount;
}
/**
* Generates a new value within an interval, given a start value, chance to change, and change amount.
* @param lowerBound Lower bound of interval.
* @param upperBound Upper bound of interval.
* @param currentValue The current value to change.
* @param changeAmount The amount to change by.
* @param chanceToChange The change to actually change the value.
* @return The new value.
*/
private static double generateNextValueInBounds(double lowerBound, double upperBound, double currentValue, double changeAmount, double chanceToChange) {
float chance = new Random().nextFloat();
if (chance <= chanceToChange) {
currentValue += changeAmount;
} else if (chance <= (2 * chanceToChange)) {
currentValue -= changeAmount;
}
currentValue = clamp(lowerBound, upperBound, currentValue);
return currentValue;
}
@Override
public Wind generateNextWind(Wind currentWind) {
double windSpeed = generateNextWindSpeed(currentWind.getWindSpeed());
Bearing windBearing = generateNextWindBearing(currentWind.getWindDirection());
return new Wind(windBearing, windSpeed);
}
/**
* Generates the next wind speed to use.
* @param windSpeed Current wind speed, in knots.
* @return Next wind speed, in knots.
*/
private double generateNextWindSpeed(double windSpeed) {
double chanceToChange = 0.2;
double changeAmount = 0.1;
double nextWindSpeed = generateNextValueInBounds(
windSpeedLowerBound,
windSpeedUpperBound,
windSpeed,
changeAmount,
chanceToChange);
return nextWindSpeed;
}
/**
* Generates the next wind speed to use.
* @param windBearing Current wind bearing.
* @return Next wind speed.
*/
private Bearing generateNextWindBearing(Bearing windBearing) {
double chanceToChange = 0.2;
double changeAmount = 0.5;
double nextWindBearingDegrees = generateNextValueInBounds(
windBearingLowerBound.degrees(),
windBearingUpperBound.degrees(),
windBearing.degrees(),
changeAmount,
chanceToChange);
return Bearing.fromDegrees(nextWindBearingDegrees);
}
/**
* Clamps a value to be within an interval.
* @param lower Lower bound of the interval.
* @param upper Upper bound of the interval.
* @param value Value to clamp.
* @return The clamped value.
*/
private static double clamp(double lower, double upper, double value) {
if (value > upper) {
value = upper;
} else if (value < lower) {
value = lower;
}
return value;
}
}