Refactored Race, MockRace, and VisualiserRace to use RaceClock instead of keeping their own timers.

Moved FPS tracking to Race class, so both VisualiserRace and MockRace can monitor their FPS.
LatestMessages is now observable. It notifies observers when an XMLMessage is received.
Boat now has StringProperty for name and country/abbreviation.
Moved the MockRace timescale value to Constants.RaceTimeScale. This is passed in to MockRace on construction.
Tidied up StartController.
Copied the visualiser's resources into the resources folder.
Refactored RaceClock. Added comments. Tidied code a bit. Moved to shared.model.

Started work on RaceController.
This commit is contained in:
fjc40
2017-07-08 23:21:29 +12:00
parent f057ad58b7
commit abbbf70146
35 changed files with 2013 additions and 427 deletions
@@ -41,10 +41,9 @@ public class MockRace extends Race {
/**
* The scale factor of the race.
* Frame periods are multiplied by this to get the amount of time a single frame represents.
* E.g., frame period = 20ms, scale = 5, frame represents 20 * 5 = 100ms, and so boats are simulated for 100ms, even though only 20ms actually occurred.
* See {@link Constants#RaceTimeScale}.
*/
private int scaleFactor = 5;
private int scaleFactor;
/**
@@ -83,13 +82,15 @@ public class MockRace extends Race {
* @param boatDataSource Data source for boat related data (yachts and marker boats).
* @param raceDataSource Data source for race related data (participating boats, legs, etc...).
* @param regattaDataSource Data source for race related data (course name, location, timezone, etc...).
* @param polars The polars table to be used for boat simulation.
* @param latestMessages The LatestMessages to send events to.
* @param polars The polars table to be used for boat simulation.
* @param timeScale The timeScale for the race. See {@link Constants#RaceTimeScale}.
*/
public MockRace(BoatDataSource boatDataSource, RaceDataSource raceDataSource, RegattaDataSource regattaDataSource, Polars polars, LatestMessages latestMessages) {
public MockRace(BoatDataSource boatDataSource, RaceDataSource raceDataSource, RegattaDataSource regattaDataSource, LatestMessages latestMessages, Polars polars, int timeScale) {
super(boatDataSource, raceDataSource, regattaDataSource, latestMessages);
this.scaleFactor = timeScale;
this.boats = this.generateMockBoats(boatDataSource.getBoats(), raceDataSource.getParticipants(), polars);
@@ -138,7 +139,7 @@ public class MockRace extends Race {
public void run() {
initialiseBoats();
initialiseWindDirection();
countdownTimer.start();
this.countdownTimer.start();
}
@@ -175,12 +176,12 @@ public class MockRace extends Race {
mark.getSourceID(),
mark.getPosition().getLatitude(),
mark.getPosition().getLongitude(),
boatLocationSequenceNumber,
this.boatLocationSequenceNumber,
0, 0,
totalTimeElapsed + startTime);
this.raceClock.getCurrentTimeMilli());
//Iterates the sequence number.
boatLocationSequenceNumber++;
this.boatLocationSequenceNumber++;
this.latestMessages.setBoatLocation(boatLocation);
@@ -211,13 +212,13 @@ public class MockRace extends Race {
boat.getSourceID(),
boat.getCurrentPosition().getLatitude(),
boat.getCurrentPosition().getLongitude(),
boatLocationSequenceNumber,
this.boatLocationSequenceNumber,
boat.getBearing().degrees(),
boat.getCurrentSpeed(),
startTime + totalTimeElapsed);
this.raceClock.getCurrentTimeMilli());
//Iterates the sequence number.
boatLocationSequenceNumber++;
this.boatLocationSequenceNumber++;
this.latestMessages.setBoatLocation(boatLocation);
@@ -225,27 +226,32 @@ public class MockRace extends Race {
/**
* Updates the race status enumeration based on the current time, in milliseconds.
* @param currentTime The current time, in milliseconds.
* Updates the race time to a specified value, in milliseconds since the unix epoch.
* @param currentTime Milliseconds since unix epoch.
*/
private void updateRaceStatusEnum(long currentTime) {
private void updateRaceTime(long currentTime) {
this.raceClock.setUTCTime(currentTime);
}
/**
* Updates the race status enumeration based on the current time.
*/
private void updateRaceStatusEnum() {
//The amount of milliseconds until the race starts.
long timeToStart = this.startTime - currentTime;
//Scale the time to start based on the scale factor.
long timeToStartScaled = timeToStart / this.scaleFactor;
long timeToStart = this.raceClock.getDurationMilli();
if (timeToStartScaled > Constants.RacePreStartTime) {
if (timeToStart > Constants.RacePreStartTime) {
//Time > 3 minutes is the prestart period.
this.setRaceStatusEnum(RaceStatusEnum.PRESTART);
} else if ((timeToStartScaled <= Constants.RacePreStartTime) && (timeToStartScaled >= Constants.RacePreparatoryTime)) {
} else if ((timeToStart <= Constants.RacePreStartTime) && (timeToStart >= Constants.RacePreparatoryTime)) {
//Time between [1, 3] minutes is the warning period.
this.setRaceStatusEnum(RaceStatusEnum.WARNING);
} else if ((timeToStartScaled <= Constants.RacePreparatoryTime) && (timeToStartScaled > 0)) {
} else if ((timeToStart <= Constants.RacePreparatoryTime) && (timeToStart > 0)) {
//Time between (0, 1] minutes is the preparatory period.
this.setRaceStatusEnum(RaceStatusEnum.PREPARATORY);
@@ -267,7 +273,7 @@ public class MockRace extends Race {
List<BoatStatus> boatStatuses = new ArrayList<>();
//Add each boat status to the status list.
for (MockBoat boat : boats) {
for (MockBoat boat : this.boats) {
BoatStatus boatStatus = new BoatStatus(
boat.getSourceID(),
@@ -281,14 +287,14 @@ public class MockRace extends Race {
//Convert wind direction and speed to ints. //TODO this conversion should be done inside the racestatus class.
int windDirectionInt = AC35UnitConverter.encodeHeading(this.windDirection.degrees());
int windSpeedInt = (int) (windSpeed * Constants.KnotsToMMPerSecond);
int windSpeedInt = (int) (this.windSpeed * Constants.KnotsToMMPerSecond);
//Create race status object, and send it.
RaceStatus raceStatus = new RaceStatus(
System.currentTimeMillis(),
this.raceId,
this.getRaceStatusEnum().getValue(),
this.startTime,
this.raceClock.getStartingTimeMilli(),
windDirectionInt,
windSpeedInt,
this.getRaceType().getValue(),
@@ -323,8 +329,11 @@ public class MockRace extends Race {
@Override
public void handle(long arg0) {
//Update race time.
updateRaceTime(currentTime);
//Update the race status based on the current time.
updateRaceStatusEnum(this.currentTime);
updateRaceStatusEnum();
//Parse the boat locations.
parseBoatLocations();
@@ -361,6 +370,11 @@ public class MockRace extends Race {
*/
long timeRaceStarted = System.currentTimeMillis();
/**
* Current time during a loop iteration.
*/
long currentTime = System.currentTimeMillis();
/**
* The time of the previous frame, in milliseconds.
*/
@@ -370,19 +384,17 @@ public class MockRace extends Race {
public void handle(long arg0) {
//Get the current time.
long currentTime = System.currentTimeMillis();
currentTime = System.currentTimeMillis();
//Update race time.
updateRaceTime(currentTime);
//Update the total elapsed time.
totalTimeElapsed = currentTime - this.timeRaceStarted;
//As long as there is at least one boat racing, we still simulate the race.
if (getNumberOfActiveBoats() != 0) {
//Get the time period of this frame.
long framePeriod = currentTime - lastFrameTime;
//We actually simulate 20ms instead of the amount of time that has occurred, as that ensure that we don't end up with large frame periods on slow computers, causing position issues.
framePeriod = 20;
//For each boat, we update its position, and generate a BoatLocationMessage.
for (MockBoat boat : boats) {
@@ -390,7 +402,7 @@ public class MockRace extends Race {
//If it is still racing, update its position.
if (boat.getStatus() == BoatStatusEnum.RACING) {
updatePosition(boat, framePeriod, totalTimeElapsed);
updatePosition(boat, framePeriod, raceClock.getDurationMilli());
}
@@ -654,7 +666,7 @@ public class MockRace extends Race {
//Check the boats position (update leg and stuff).
this.checkPosition(boat, totalTimeElapsed);
this.checkPosition(boat, totalElapsedMilliseconds);
}
@@ -899,7 +911,7 @@ public class MockRace extends Race {
if (velocityToMark > 0) {
long timeFromNow = (long) (1000 * boat.calculateDistanceToNextMarker() / velocityToMark);
boat.setEstimatedTime(startTime + totalTimeElapsed + timeFromNow);
boat.setEstimatedTime(this.raceClock.getCurrentTimeMilli() + timeFromNow);
}
}