mock:
Moved wind generation logic and state into the WindGenerator class. MockRace initialises this, and calls it to update wind.
This commit is contained in:
@@ -55,26 +55,10 @@ public class MockRace extends Race {
|
||||
private int dnfChance = 0;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Used to generate random numbers when changing the wind direction.
|
||||
* Object used to generate changes in wind speed/direction.
|
||||
*/
|
||||
private int changeWind = 4;
|
||||
|
||||
/**
|
||||
* The bearing the wind direction starts at.
|
||||
*/
|
||||
private static final Bearing windBaselineBearing = Bearing.fromDegrees(225);
|
||||
|
||||
/**
|
||||
* The lower bearing angle that the wind may have.
|
||||
*/
|
||||
private static final Bearing windLowerBound = Bearing.fromDegrees(215);
|
||||
|
||||
/**
|
||||
* The upper bearing angle that the wind may have.
|
||||
*/
|
||||
private static final Bearing windUpperBound = Bearing.fromDegrees(235);
|
||||
private WindGenerator windGenerator;
|
||||
|
||||
|
||||
|
||||
@@ -99,8 +83,17 @@ public class MockRace extends Race {
|
||||
this.shrinkBoundary = GPSCoordinate.getShrinkBoundary(this.boundary);
|
||||
|
||||
|
||||
//Set up wind generator. It may be tidier to create this outside the race (with the values sourced from a data file maybe?) and pass it in.
|
||||
this.windGenerator = new WindGenerator(
|
||||
Bearing.fromDegrees(225),
|
||||
Bearing.fromDegrees(215),
|
||||
Bearing.fromDegrees(235),
|
||||
12d,
|
||||
8d,
|
||||
16d );
|
||||
|
||||
//Wind.
|
||||
this.setWind(Bearing.fromDegrees(180), 12);
|
||||
this.setWind(windGenerator.generateBaselineWind());
|
||||
|
||||
}
|
||||
|
||||
@@ -887,9 +880,7 @@ public class MockRace extends Race {
|
||||
*/
|
||||
protected void initialiseWindDirection() {
|
||||
//Set the starting bearing.
|
||||
this.setWind(
|
||||
Bearing.fromDegrees(MockRace.windBaselineBearing.degrees()),
|
||||
this.getWindSpeed() );
|
||||
this.setWind(windGenerator.generateBaselineWind());
|
||||
}
|
||||
|
||||
|
||||
@@ -897,34 +888,10 @@ public class MockRace extends Race {
|
||||
* Changes the wind direction randomly, while keeping it within [windLowerBound, windUpperBound].
|
||||
*/
|
||||
protected void changeWindDirection() {
|
||||
//TODO this wind generation could probably be moved to its own object?
|
||||
//Randomly add or remove 0.5 degrees.
|
||||
int r = new Random().nextInt(changeWind) + 1;
|
||||
|
||||
double newWindBearingDegrees = this.getWindDirection().degrees();
|
||||
Wind nextWind = windGenerator.generateNextWind(raceWind.getValue());
|
||||
|
||||
if (r == 1) {
|
||||
//Add 0.5 degrees to the wind bearing.
|
||||
newWindBearingDegrees += 0.5;
|
||||
|
||||
} else if (r == 2) {
|
||||
//Minus 0.5 degrees from the wind bearing.
|
||||
newWindBearingDegrees -= 0.5;
|
||||
|
||||
}
|
||||
|
||||
//Ensure that the wind is in the correct bounds.
|
||||
if (newWindBearingDegrees > MockRace.windUpperBound.degrees()) {
|
||||
newWindBearingDegrees = MockRace.windUpperBound.degrees();
|
||||
|
||||
} else if (newWindBearingDegrees < MockRace.windLowerBound.degrees()) {
|
||||
newWindBearingDegrees = MockRace.windLowerBound.degrees();
|
||||
|
||||
}
|
||||
|
||||
this.setWind(
|
||||
Bearing.fromDegrees(newWindBearingDegrees),
|
||||
this.getWindSpeed() );
|
||||
setWind(nextWind);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
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 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 WindGenerator(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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a wind object using the baseline wind speed and bearing.
|
||||
* @return Baseline wind object.
|
||||
*/
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates the next Wind object, that is within the provided bounds. This randomly increases or decreases the wind's speed and bearing.
|
||||
* @param currentWind The current wind to change. This is not modified.
|
||||
* @return Generated wind object.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -255,6 +255,14 @@ public abstract class Race implements Runnable {
|
||||
*/
|
||||
protected void setWind(Bearing windBearing, double windSpeedKnots) {
|
||||
Wind wind = new Wind(windBearing, windSpeedKnots);
|
||||
setWind(wind);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the race to have a specified wind (bearing and speed).
|
||||
* @param wind New wind.
|
||||
*/
|
||||
protected void setWind(Wind wind) {
|
||||
this.raceWind.setValue(wind);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user