Merge branch 'RaceFactory' of https://eng-git.canterbury.ac.nz/seng302-2017/team-7 into RaceFactory

# Conflicts:
#	racevisionGame/src/main/java/mock/model/MockRace.java
main
zwu18 8 years ago
commit b581b01a44

@ -134,20 +134,9 @@ public class MockBoat extends Boat {
/** /**
* Moves the boat meters forward in the direction that it is facing * Moves the boat meters forward in the direction that it is facing
* @param meters The number of meters to move forward. * @param meters The number of meters to move forward.
* @param milliseconds The number of milliseconds to advance the boat's timers by. *
*/ */
public void moveForwards(double meters, long milliseconds) { public void moveForwards(double meters) {
//Update the boat's time since last tack.
this.setTimeSinceTackChange(this.getTimeSinceTackChange() + milliseconds);
//Update the time into the current leg.
this.setTimeElapsedInCurrentLeg(this.getTimeElapsedInCurrentLeg() + milliseconds);
//Update the distance into the current leg.
this.setDistanceTravelledInLeg(this.getDistanceTravelledInLeg() + meters);
//Updates the current position of the boat. //Updates the current position of the boat.
GPSCoordinate newPosition = GPSCoordinate.calculateNewPosition(this.getCurrentPosition(), meters, Azimuth.fromBearing(this.getBearing())); GPSCoordinate newPosition = GPSCoordinate.calculateNewPosition(this.getCurrentPosition(), meters, Azimuth.fromBearing(this.getBearing()));
this.setCurrentPosition(newPosition); this.setCurrentPosition(newPosition);

@ -27,6 +27,7 @@ import static java.lang.Math.cos;
* Is responsible for simulating the race, and sending messages to a MockOutput instance. * Is responsible for simulating the race, and sending messages to a MockOutput instance.
*/ */
public class MockRace extends Race { public class MockRace extends Race {
private RaceServer server;
/** /**
* An observable list of boats in the race. * An observable list of boats in the race.
@ -82,6 +83,8 @@ public class MockRace extends Race {
//Wind. //Wind.
this.setWind(windGenerator.generateBaselineWind()); this.setWind(windGenerator.generateBaselineWind());
this.server = new RaceServer(this, latestMessages);
} }
/** /**
@ -122,88 +125,6 @@ public class MockRace extends Race {
} }
/**
* Parse the compound marker boats through mock output.
*/
private void parseMarks() {
for (CompoundMark compoundMark : this.compoundMarks) {
//Get the individual marks from the compound mark.
Mark mark1 = compoundMark.getMark1();
Mark mark2 = compoundMark.getMark2();
//If they aren't null, parse them (some compound marks only have one mark).
if (mark1 != null) {
this.parseIndividualMark(mark1);
}
if (mark2 != null) {
this.parseIndividualMark(mark2);
}
}
}
/**
* Parses an individual marker boat, and sends it to mockOutput.
* @param mark The marker boat to parse.
*/
private void parseIndividualMark(Mark mark) {
//Create message.
BoatLocation boatLocation = new BoatLocation(
mark.getSourceID(),
mark.getPosition().getLatitude(),
mark.getPosition().getLongitude(),
this.boatLocationSequenceNumber,
0, 0,
this.raceClock.getCurrentTimeMilli());
//Iterates the sequence number.
this.boatLocationSequenceNumber++;
this.latestMessages.setBoatLocation(boatLocation);
}
/**
* Parse the boats in the race, and send it to mockOutput.
*/
private void parseBoatLocations() {
//Parse each boat.
for (MockBoat boat : this.boats) {
this.parseIndividualBoatLocation(boat);
}
}
/**
* Parses an individual boat, and sends it to mockOutput.
* @param boat The boat to parse.
*/
private void parseIndividualBoatLocation(MockBoat boat) {
BoatLocation boatLocation = new BoatLocation(
boat.getSourceID(),
boat.getCurrentPosition().getLatitude(),
boat.getCurrentPosition().getLongitude(),
this.boatLocationSequenceNumber,
boat.getBearing().degrees(),
boat.getCurrentSpeed(),
this.raceClock.getCurrentTimeMilli());
//Iterates the sequence number.
this.boatLocationSequenceNumber++;
this.latestMessages.setBoatLocation(boatLocation);
}
/** /**
* Updates the race time to a specified value, in milliseconds since the unix epoch. * Updates the race time to a specified value, in milliseconds since the unix epoch.
* @param currentTime Milliseconds since unix epoch. * @param currentTime Milliseconds since unix epoch.
@ -241,48 +162,6 @@ public class MockRace extends Race {
} }
}
/**
* Parses the race status, and sends it to mockOutput.
*/
private void parseRaceStatus() {
//A race status message contains a list of boat statuses.
List<BoatStatus> boatStatuses = new ArrayList<>();
//Add each boat status to the status list.
for (MockBoat boat : this.boats) {
BoatStatus boatStatus = new BoatStatus(
boat.getSourceID(),
boat.getStatus(),
boat.getCurrentLeg().getLegNumber(),
boat.getEstimatedTimeAtNextMark().toInstant().toEpochMilli() );
boatStatuses.add(boatStatus);
}
//Convert wind direction and speed to ints. //TODO this conversion should be done inside the racestatus class.
int windDirectionInt = AC35UnitConverter.encodeHeading(this.getWindDirection().degrees());
int windSpeedInt = (int) (this.getWindSpeed() * Constants.KnotsToMMPerSecond);
//Create race status object, and send it.
RaceStatus raceStatus = new RaceStatus(
System.currentTimeMillis(),
this.raceId,
this.getRaceStatusEnum().getValue(),
this.raceClock.getStartingTimeMilli(),
windDirectionInt,
windSpeedInt,
this.getRaceType().getValue(),
boatStatuses);
this.latestMessages.setRaceStatus(raceStatus);
} }
@ -330,16 +209,16 @@ public class MockRace extends Race {
setBoatsTimeNextMark(raceClock.getCurrentTime()); setBoatsTimeNextMark(raceClock.getCurrentTime());
//Parse the boat locations. //Parse the boat locations.
parseBoatLocations(); server.parseBoatLocations();
//Parse the marks. //Parse the marks.
parseMarks(); server.parseMarks();
// Change wind direction // Change wind direction
changeWindDirection(); changeWindDirection();
//Parse the race status. //Parse the race status.
parseRaceStatus(); server.parseRaceStatus();
if (getRaceStatusEnum() == RaceStatusEnum.STARTED) { if (getRaceStatusEnum() == RaceStatusEnum.STARTED) {
@ -383,6 +262,7 @@ public class MockRace extends Race {
//Update race time. //Update race time.
updateRaceTime(currentTime); updateRaceTime(currentTime);
//As long as there is at least one boat racing, we still simulate the race. //As long as there is at least one boat racing, we still simulate the race.
if (getNumberOfActiveBoats() != 0) { if (getNumberOfActiveBoats() != 0) {
@ -391,6 +271,7 @@ public class MockRace extends Race {
//For each boat, we update its position, and generate a BoatLocationMessage. //For each boat, we update its position, and generate a BoatLocationMessage.
for (MockBoat boat : boats) { for (MockBoat boat : boats) {
//If it is still racing, update its position. //If it is still racing, update its position.
if (boat.getStatus() == BoatStatusEnum.RACING) { if (boat.getStatus() == BoatStatusEnum.RACING) {
@ -412,13 +293,13 @@ public class MockRace extends Race {
changeWindDirection(); changeWindDirection();
//Parse the boat locations. //Parse the boat locations.
parseBoatLocations(); server.parseBoatLocations();
//Parse the marks. //Parse the marks.
parseMarks(); server.parseMarks();
//Parse the race status. //Parse the race status.
parseRaceStatus(); server.parseRaceStatus();
//Update the last frame time. //Update the last frame time.
@ -435,7 +316,7 @@ public class MockRace extends Race {
@Override @Override
public void handle(long now) { public void handle(long now) {
parseRaceStatus(); server.parseRaceStatus();
if (iters > 500) { if (iters > 500) {
stop(); stop();
@ -450,7 +331,7 @@ public class MockRace extends Race {
* This sets their starting positions and current legs. * This sets their starting positions and current legs.
*/ */
@Override @Override
protected void initialiseBoats() { public void initialiseBoats() {
//Gets the starting positions of the boats. //Gets the starting positions of the boats.
List<GPSCoordinate> startingPositions = getSpreadStartingPositions(); List<GPSCoordinate> startingPositions = getSpreadStartingPositions();
@ -495,7 +376,7 @@ public class MockRace extends Race {
* *
* @return A list of starting positions. * @return A list of starting positions.
*/ */
public List<GPSCoordinate> getSpreadStartingPositions() { private List<GPSCoordinate> getSpreadStartingPositions() {
//The first compound marker of the race - the starting gate. //The first compound marker of the race - the starting gate.
CompoundMark compoundMark = this.legs.get(0).getStartCompoundMark(); CompoundMark compoundMark = this.legs.get(0).getStartCompoundMark();
@ -537,23 +418,6 @@ public class MockRace extends Race {
} }
/**
* Calculates a boat's VMG.
* @param boat The boat to calculate VMG for.
* @return VMG for the specified boat.
*/
public VMG calculateVMG(MockBoat boat) {
//Find the VMG inside these bounds.
VMG bestVMG = boat.getPolars().calculateVMG(this.getWindDirection(), this.getWindSpeed(), boat.calculateBearingToNextMarker(), Bearing.fromDegrees(0d), Bearing.fromDegrees(359.99999d));
return bestVMG;
}
/** /**
* Determines whether or not a given VMG improves the velocity of a boat, if it were currently using currentVMG. * Determines whether or not a given VMG improves the velocity of a boat, if it were currently using currentVMG.
* @param currentVMG The current VMG of the boat. * @param currentVMG The current VMG of the boat.
@ -568,7 +432,7 @@ public class MockRace extends Race {
//Calculates the angle between the new VMG and the boat's destination. //Calculates the angle between the new VMG and the boat's destination.
Angle angleBetweenDestAndNewVMG = Angle.fromDegrees(potentialVMG.getBearing().degrees() - bearingToDestination.degrees()); Angle angleBetweenDestAndNewVMG = Angle.fromDegrees(potentialVMG.getBearing().degrees() - bearingToDestination.degrees());
//System.out.println(angleBetweenDestAndHeading.degrees() + ":" + angleBetweenDestAndNewVMG.degrees());
//Calculate the boat's current velocity. //Calculate the boat's current velocity.
double currentVelocity = Math.cos(angleBetweenDestAndHeading.radians()) * currentVMG.getSpeed(); double currentVelocity = Math.cos(angleBetweenDestAndHeading.radians()) * currentVMG.getSpeed();
@ -579,7 +443,6 @@ public class MockRace extends Race {
//Return whether or not the new VMG gives better velocity. //Return whether or not the new VMG gives better velocity.
return vmgVelocity > currentVelocity; return vmgVelocity > currentVelocity;
} }
/** /**
@ -606,7 +469,7 @@ public class MockRace extends Race {
* @param updatePeriodMilliseconds The time, in milliseconds, since the last update. * @param updatePeriodMilliseconds The time, in milliseconds, since the last update.
* @param totalElapsedMilliseconds The total number of milliseconds that have elapsed since the start of the race. * @param totalElapsedMilliseconds The total number of milliseconds that have elapsed since the start of the race.
*/ */
protected void updatePosition(MockBoat boat, long updatePeriodMilliseconds, long totalElapsedMilliseconds) { public void updatePosition(MockBoat boat, long updatePeriodMilliseconds, long totalElapsedMilliseconds) {
//Checks if the current boat has finished the race or not. //Checks if the current boat has finished the race or not.
boolean finish = this.isLastLeg(boat.getCurrentLeg()); boolean finish = this.isLastLeg(boat.getCurrentLeg());
@ -622,74 +485,29 @@ public class MockRace extends Race {
//Move the boat forwards that many meters, and advances its time counters by enough milliseconds. //Move the boat forwards that many meters, and advances its time counters by enough milliseconds.
boat.moveForwards(distanceTravelledMeters, updatePeriodMilliseconds * this.scaleFactor); boat.moveForwards(distanceTravelledMeters);
long tackPeriod = 15000; long tackPeriod = 15000;
if (boat.getTimeSinceTackChange() > tackPeriod) { if (boat.getTimeSinceTackChange() > tackPeriod) {
System.out.println("tack loop");
//Calculate the new VMG. //Calculate the new VMG.
VMG newVMG = this.calculateVMG(boat); VMG newVMG = boat.getPolars().calculateVMG(
this.getWindDirection(),
this.getWindSpeed(),
boat.calculateBearingToNextMarker(),
Bearing.fromDegrees(0d),
Bearing.fromDegrees(359.99999d));
//If the new vmg improves velocity, use it. //If the new vmg improves velocity, use it.
if (improvesVelocity(boat, newVMG)) { if (improvesVelocity(boat, newVMG)) {
System.out.println("NEW VMG");
boat.setVMG(newVMG); boat.setVMG(newVMG);
} }
} }
this.updateEstimatedTime(boat); this.updateEstimatedTime(boat);
//Check the boats position (update leg and stuff).
this.checkPosition(boat, totalElapsedMilliseconds);
}
}
/**
* Checks if a boat has finished any legs, or has pulled out of race (DNF).
* @param boat The boat to check.
* @param timeElapsed The total time, in milliseconds, that has elapsed since the race started.
*/
protected void checkPosition(MockBoat boat, long timeElapsed) {
//The distance, in nautical miles, within which the boat needs to get in order to consider that it has reached the marker.
double epsilonNauticalMiles = 100.0 / Constants.NMToMetersConversion; //100 meters. TODO should be more like 5-10.
if (boat.calculateDistanceToNextMarker() < epsilonNauticalMiles) {
//Boat has reached its target marker, and has moved on to a new leg.
//Calculate how much the boat overshot the marker by.
double overshootMeters = boat.calculateDistanceToNextMarker();
//Move boat on to next leg.
Leg nextLeg = this.legs.get(boat.getCurrentLeg().getLegNumber() + 1);
boat.setCurrentLeg(nextLeg);
//Add overshoot distance into the distance travelled for the next leg.
boat.setDistanceTravelledInLeg(overshootMeters);
//Setting a high value for this allows the boat to immediately do a large turn, as it needs to in order to get to the next mark.
boat.setTimeSinceTackChange(999999);
//Check if the boat has finished or stopped racing.
if (this.isLastLeg(boat.getCurrentLeg())) {
//Boat has finished.
boat.setTimeFinished(timeElapsed);
boat.setCurrentSpeed(0);
boat.setStatus(BoatStatusEnum.FINISHED);
}
} }
} }
@ -724,18 +542,10 @@ public class MockRace extends Race {
return boats; return boats;
} }
/**
* Initialises the wind bearing with the value of the windBaselineBearing.
*/
protected void initialiseWindDirection() {
//Set the starting bearing.
this.setWind(windGenerator.generateBaselineWind());
}
/** /**
* Changes the wind direction randomly, while keeping it within [windLowerBound, windUpperBound]. * Changes the wind direction randomly, while keeping it within [windLowerBound, windUpperBound].
*/ */
protected void changeWindDirection() { public void changeWindDirection() {
Wind nextWind = windGenerator.generateNextWind(raceWind.getValue()); Wind nextWind = windGenerator.generateNextWind(raceWind.getValue());
@ -763,4 +573,8 @@ public class MockRace extends Race {
} }
} }
public List<CompoundMark> getCompoundMarks() {
return compoundMarks;
}
} }

@ -0,0 +1,153 @@
package mock.model;
import network.Messages.BoatLocation;
import network.Messages.BoatStatus;
import network.Messages.LatestMessages;
import network.Messages.RaceStatus;
import network.Utils.AC35UnitConverter;
import shared.model.CompoundMark;
import shared.model.Constants;
import shared.model.Mark;
import java.util.ArrayList;
import java.util.List;
/**
* Created by connortaylorbrown on 2/08/17.
*/
public class RaceServer {
private MockRace race;
private LatestMessages latestMessages;
/**
* The sequence number of the latest RaceStatus message sent or received.
*/
private int raceStatusSequenceNumber = 1;
/**
* The sequence number of the latest BoatLocation message sent or received.
*/
private int boatLocationSequenceNumber = 1;
public RaceServer(MockRace race, LatestMessages latestMessages) {
this.race = race;
this.latestMessages = latestMessages;
}
/**
* Parses an individual marker boat, and sends it to mockOutput.
* @param mark The marker boat to parse.
*/
private void parseIndividualMark(Mark mark) {
//Create message.
BoatLocation boatLocation = new BoatLocation(
mark.getSourceID(),
mark.getPosition().getLatitude(),
mark.getPosition().getLongitude(),
this.boatLocationSequenceNumber,
0, 0,
race.getRaceClock().getCurrentTimeMilli());
//Iterates the sequence number.
this.boatLocationSequenceNumber++;
this.latestMessages.setBoatLocation(boatLocation);
}
/**
* Parse the compound marker boats through mock output.
*/
public void parseMarks() {
for (CompoundMark compoundMark : race.getCompoundMarks()) {
//Get the individual marks from the compound mark.
Mark mark1 = compoundMark.getMark1();
Mark mark2 = compoundMark.getMark2();
//If they aren't null, parse them (some compound marks only have one mark).
if (mark1 != null) {
this.parseIndividualMark(mark1);
}
if (mark2 != null) {
this.parseIndividualMark(mark2);
}
}
}
/**
* Parse the boats in the race, and send it to mockOutput.
*/
public void parseBoatLocations() {
//Parse each boat.
for (MockBoat boat : race.getBoats()) {
this.parseIndividualBoatLocation(boat);
}
}
/**
* Parses an individual boat, and sends it to mockOutput.
* @param boat The boat to parse.
*/
private void parseIndividualBoatLocation(MockBoat boat) {
BoatLocation boatLocation = new BoatLocation(
boat.getSourceID(),
boat.getCurrentPosition().getLatitude(),
boat.getCurrentPosition().getLongitude(),
this.boatLocationSequenceNumber,
boat.getBearing().degrees(),
boat.getCurrentSpeed(),
race.getRaceClock().getCurrentTimeMilli());
//Iterates the sequence number.
this.boatLocationSequenceNumber++;
this.latestMessages.setBoatLocation(boatLocation);
}
/**
* Parses the race status, and sends it to mockOutput.
*/
public void parseRaceStatus() {
//A race status message contains a list of boat statuses.
List<BoatStatus> boatStatuses = new ArrayList<>();
//Add each boat status to the status list.
for (MockBoat boat : race.getBoats()) {
BoatStatus boatStatus = new BoatStatus(
boat.getSourceID(),
boat.getStatus(),
boat.getCurrentLeg().getLegNumber(),
boat.getEstimatedTimeAtNextMark().toInstant().toEpochMilli() );
boatStatuses.add(boatStatus);
}
//Convert wind direction and speed to ints. //TODO this conversion should be done inside the racestatus class.
int windDirectionInt = AC35UnitConverter.encodeHeading(race.getWindDirection().degrees());
int windSpeedInt = (int) (race.getWindSpeed() * Constants.KnotsToMMPerSecond);
//Create race status object, and send it.
RaceStatus raceStatus = new RaceStatus(
System.currentTimeMillis(),
race.getRaceId(),
race.getRaceStatusEnum().getValue(),
race.getRaceClock().getStartingTimeMilli(),
windDirectionInt,
windSpeedInt,
race.getRaceType().getValue(),
boatStatuses);
this.latestMessages.setRaceStatus(raceStatus);
}
}

@ -43,18 +43,6 @@ public abstract class Race implements Runnable {
*/ */
protected LatestMessages latestMessages; protected LatestMessages latestMessages;
/**
* The sequence number of the latest BoatLocation message sent or received.
*/
protected int boatLocationSequenceNumber = 1;
/**
* The sequence number of the latest RaceStatus message sent or received.
*/
protected int raceStatusSequenceNumber = 1;
/** /**
* A list of compound marks in the race. * A list of compound marks in the race.
*/ */
@ -364,4 +352,8 @@ public abstract class Race implements Runnable {
this.lastFpsResetTime = 0; this.lastFpsResetTime = 0;
} }
} }
public int getRaceId() {
return raceId;
}
} }

Loading…
Cancel
Save