Cherry-picked multiple changes from master
This commit is contained in:
@@ -24,10 +24,18 @@ public class MockBoat extends Boat implements Collider {
|
||||
*/
|
||||
private long timeSinceTackChange = 0;
|
||||
|
||||
/**
|
||||
* This stores the boats current status of rounding a mark
|
||||
* 0: not started rounding
|
||||
* 1: passed only first check
|
||||
* 2: passed first and second check
|
||||
*/
|
||||
private Integer roundingStatus = 0;
|
||||
|
||||
/**
|
||||
* Stores whether the boat is on autoVMG or not
|
||||
*/
|
||||
private boolean autoVMG = true;
|
||||
private boolean autoVMG = false;
|
||||
|
||||
|
||||
|
||||
@@ -69,7 +77,15 @@ public class MockBoat extends Boat implements Collider {
|
||||
|
||||
//Get the start and end points.
|
||||
GPSCoordinate currentPosition = this.getCurrentPosition();
|
||||
GPSCoordinate nextMarkerPosition = this.getCurrentLeg().getEndCompoundMark().getAverageGPSCoordinate();
|
||||
GPSCoordinate nextMarkerPosition;
|
||||
|
||||
// if boat is at the finish
|
||||
if (this.getCurrentLeg().getEndCompoundMark() == null) {
|
||||
nextMarkerPosition = currentPosition;
|
||||
}
|
||||
else {
|
||||
nextMarkerPosition = this.getCurrentLeg().getEndCompoundMark().getAverageGPSCoordinate();
|
||||
}
|
||||
|
||||
//Calculate bearing.
|
||||
Bearing bearing = GPSCoordinate.calculateBearing(currentPosition, nextMarkerPosition);
|
||||
@@ -96,9 +112,7 @@ public class MockBoat extends Boat implements Collider {
|
||||
|
||||
|
||||
//Calculate distance.
|
||||
double distanceNauticalMiles = GPSCoordinate.calculateDistanceNauticalMiles(startPosition, endMarker);
|
||||
|
||||
return distanceNauticalMiles;
|
||||
return GPSCoordinate.calculateDistanceNauticalMiles(startPosition, endMarker);
|
||||
}
|
||||
|
||||
|
||||
@@ -198,7 +212,91 @@ public class MockBoat extends Boat implements Collider {
|
||||
return distanceTravelledMeters;
|
||||
}
|
||||
|
||||
public boolean isAutoVMG() {
|
||||
/**
|
||||
* Check if a mark is on the port side of the boat
|
||||
* @param mark mark to be passed
|
||||
* @return true if mark is on port side
|
||||
*/
|
||||
public boolean isPortSide(Mark mark){
|
||||
Bearing towardsMark = GPSCoordinate.calculateBearing(this.getCurrentPosition(), mark.getPosition());
|
||||
if (towardsMark.degrees() > 315 || towardsMark.degrees() <= 45){
|
||||
//south quadrant
|
||||
return this.getBearing().degrees() <= 180;
|
||||
} else if(towardsMark.degrees() > 45 && towardsMark.degrees() <= 135){
|
||||
//west quadrant
|
||||
return (this.getBearing().degrees() <= 270 && this.getBearing().degrees() >= 90);
|
||||
}else if(towardsMark.degrees() > 135 && towardsMark.degrees() <= 225){
|
||||
//north quadrant
|
||||
return this.getBearing().degrees() >= 180;
|
||||
}else if(towardsMark.degrees() > 225 && towardsMark.degrees() <= 315){
|
||||
//east quadrant
|
||||
return (this.getBearing().degrees() <= 90 || this.getBearing().degrees() >= 270);
|
||||
}else{
|
||||
//should not reach here
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a mark is on the starboard side of the boat
|
||||
* @param mark mark to be passed
|
||||
* @return true if mark is on starboard side
|
||||
*/
|
||||
public boolean isStarboardSide(Mark mark){
|
||||
//if this boat is lower than the mark check which way it is facing
|
||||
Bearing towardsMark = GPSCoordinate.calculateBearing(this.getCurrentPosition(), mark.getPosition());
|
||||
if (towardsMark.degrees() > 315 || towardsMark.degrees() <= 45){
|
||||
//south quadrant
|
||||
return !(this.getBearing().degrees() <= 180);
|
||||
} else if(towardsMark.degrees() > 45 && towardsMark.degrees() <= 135){
|
||||
//west quadrant
|
||||
return !(this.getBearing().degrees() <= 270 && this.getBearing().degrees() >= 90);
|
||||
}else if(towardsMark.degrees() > 135 && towardsMark.degrees() <= 225){
|
||||
//north quadrant
|
||||
return !(this.getBearing().degrees() >= 180);
|
||||
}else if(towardsMark.degrees() > 225 && towardsMark.degrees() <= 315){
|
||||
//east quadrant
|
||||
return !(this.getBearing().degrees() <= 90 || this.getBearing().degrees() >= 270);
|
||||
}else{
|
||||
//should not reach here
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to check if this boat is between a gate
|
||||
* @param gate the gate to be checked
|
||||
* @return true if the boat is between two marks that make up a gate
|
||||
*/
|
||||
public boolean isBetweenGate(CompoundMark gate){
|
||||
return (this.isPortSide(gate.getMark1()) && this.isStarboardSide(gate.getMark2())) ||
|
||||
(this.isStarboardSide(gate.getMark1()) && this.isPortSide(gate.getMark2()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to check if this boat is between a two marks
|
||||
* @param mark1 the first mark
|
||||
* @param mark2 the second mark
|
||||
* @return true if the boat is between two marks
|
||||
*/
|
||||
public boolean isBetweenGate(Mark mark1, Mark mark2){
|
||||
return (this.isPortSide(mark1) && this.isStarboardSide(mark2)) ||
|
||||
(this.isStarboardSide(mark1) && this.isPortSide(mark2));
|
||||
}
|
||||
|
||||
public Integer getRoundingStatus() {
|
||||
return Integer.valueOf(roundingStatus);
|
||||
}
|
||||
|
||||
public void increaseRoundingStatus() {
|
||||
this.roundingStatus++;
|
||||
}
|
||||
|
||||
public void resetRoundingStatus() {
|
||||
this.roundingStatus = 0;
|
||||
}
|
||||
|
||||
public boolean getAutoVMG(){
|
||||
return autoVMG;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
package mock.model;
|
||||
|
||||
import mock.model.collider.ColliderRegistry;
|
||||
import network.Messages.Enums.BoatStatusEnum;
|
||||
import network.Messages.Enums.RaceStatusEnum;
|
||||
import network.Messages.LatestMessages;
|
||||
import org.opengis.geometry.primitive.*;
|
||||
import shared.dataInput.BoatDataSource;
|
||||
import shared.dataInput.RaceDataSource;
|
||||
import network.Messages.Enums.RaceStatusEnum;
|
||||
import shared.dataInput.RegattaDataSource;
|
||||
import shared.model.*;
|
||||
import shared.model.Bearing;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.util.*;
|
||||
|
||||
import static java.lang.Math.cos;
|
||||
@@ -53,13 +49,13 @@ 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 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}.
|
||||
* @param windGenerator The wind generator used for the race.
|
||||
*/
|
||||
public MockRace(BoatDataSource boatDataSource, RaceDataSource raceDataSource, RegattaDataSource regattaDataSource, LatestMessages latestMessages, Polars polars, int timeScale) {
|
||||
public MockRace(BoatDataSource boatDataSource, RaceDataSource raceDataSource, RegattaDataSource regattaDataSource, Polars polars, int timeScale, WindGenerator windGenerator) {
|
||||
|
||||
super(boatDataSource, raceDataSource, regattaDataSource, latestMessages);
|
||||
super(boatDataSource, raceDataSource, regattaDataSource);
|
||||
|
||||
this.scaleFactor = timeScale;
|
||||
|
||||
@@ -67,14 +63,8 @@ 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 );
|
||||
|
||||
this.windGenerator = windGenerator;
|
||||
|
||||
//Wind.
|
||||
this.setWind(windGenerator.generateBaselineWind());
|
||||
@@ -341,7 +331,7 @@ public class MockRace extends Race {
|
||||
boat.moveForwards(distanceTravelledMeters);
|
||||
boat.setTimeSinceTackChange(boat.getTimeSinceTackChange() + updatePeriodMilliseconds);
|
||||
|
||||
if (boat.isAutoVMG()) {
|
||||
if (boat.getAutoVMG()) {
|
||||
newOptimalVMG(boat);
|
||||
}
|
||||
|
||||
@@ -351,7 +341,7 @@ public class MockRace extends Race {
|
||||
}
|
||||
|
||||
private void newOptimalVMG(MockBoat boat) {
|
||||
long tackPeriod = 15000;
|
||||
long tackPeriod = 1000;
|
||||
|
||||
if (boat.getTimeSinceTackChange() > tackPeriod) {
|
||||
//Calculate the new VMG.
|
||||
@@ -375,8 +365,8 @@ public class MockRace extends Race {
|
||||
this.getWindDirection(),
|
||||
this.getWindSpeed(),
|
||||
boat.getBearing(),
|
||||
boat.getBearing(),
|
||||
boat.getBearing());
|
||||
Bearing.fromDegrees(boat.getBearing().degrees() - 1),
|
||||
Bearing.fromDegrees(boat.getBearing().degrees() + 1));
|
||||
if (vmg.getSpeed() > 0) {
|
||||
boat.setCurrentSpeed(vmg.getSpeed());
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import javafx.beans.property.SimpleObjectProperty;
|
||||
import mock.model.collider.ColliderRegistry;
|
||||
import network.Messages.Enums.RaceStatusEnum;
|
||||
import network.Messages.Enums.RaceTypeEnum;
|
||||
import network.Messages.LatestMessages;
|
||||
import shared.dataInput.BoatDataSource;
|
||||
import shared.dataInput.RaceDataSource;
|
||||
import shared.dataInput.RegattaDataSource;
|
||||
@@ -33,11 +32,6 @@ public abstract class Race {
|
||||
* The source of regatta related data.
|
||||
*/
|
||||
protected RegattaDataSource regattaDataSource;
|
||||
/**
|
||||
* The collection of latest race messages.
|
||||
* Can be either read from or written to.
|
||||
*/
|
||||
protected LatestMessages latestMessages;
|
||||
/**
|
||||
* A list of compound marks in the race.
|
||||
*/
|
||||
@@ -80,7 +74,7 @@ public abstract class Race {
|
||||
protected ColliderRegistry colliderRegistry;
|
||||
/**
|
||||
* The number of frames per second.
|
||||
* We essentially track the number of frames generated per second, over a one second period. When {@link #lastFpsResetTime} reaches 1 second, {@link #currentFps} is reset.
|
||||
* We essentially track the number of frames generated per second, over a one second period. When {@link #lastFpsResetTime} reaches 1 second, currentFps is reset.
|
||||
*/
|
||||
private int currentFps = 0;
|
||||
/**
|
||||
@@ -92,53 +86,38 @@ public abstract class Race {
|
||||
*/
|
||||
private long lastFpsResetTime;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a race object with a given BoatDataSource, RaceDataSource, and RegattaDataSource.
|
||||
* @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 latestMessages The collection of latest messages, which can be written to, or read from.
|
||||
*/
|
||||
public Race(BoatDataSource boatDataSource, RaceDataSource raceDataSource, RegattaDataSource regattaDataSource, LatestMessages latestMessages) {
|
||||
public Race(BoatDataSource boatDataSource, RaceDataSource raceDataSource, RegattaDataSource regattaDataSource) {
|
||||
|
||||
//Keep a reference to data sources.
|
||||
this.raceDataSource = raceDataSource;
|
||||
this.boatDataSource = boatDataSource;
|
||||
this.regattaDataSource = regattaDataSource;
|
||||
|
||||
this.latestMessages = latestMessages;
|
||||
|
||||
|
||||
//Marks.
|
||||
this.compoundMarks = raceDataSource.getCompoundMarks();
|
||||
|
||||
//Boundaries.
|
||||
this.boundary = raceDataSource.getBoundary();
|
||||
|
||||
|
||||
//Legs.
|
||||
this.useLegsList(raceDataSource.getLegs());
|
||||
|
||||
|
||||
//Race ID.
|
||||
this.raceId = raceDataSource.getRaceId();
|
||||
|
||||
//Regatta name.
|
||||
this.regattaName = regattaDataSource.getRegattaName();
|
||||
|
||||
//Race clock.
|
||||
this.raceClock = new RaceClock(this.raceDataSource.getStartDateTime());
|
||||
|
||||
//Race status.
|
||||
this.setRaceStatusEnum(RaceStatusEnum.NOT_ACTIVE);
|
||||
//Race type.
|
||||
this.raceType = raceDataSource.getRaceType();
|
||||
|
||||
//Wind.
|
||||
this.setWind(Bearing.fromDegrees(0), 0);
|
||||
|
||||
// Set up colliders
|
||||
this.colliderRegistry = new ColliderRegistry();
|
||||
this.colliderRegistry.addAllColliders(compoundMarks);
|
||||
}
|
||||
@@ -153,7 +132,6 @@ public abstract class Race {
|
||||
*/
|
||||
protected abstract void initialiseBoats();
|
||||
|
||||
|
||||
/**
|
||||
* Updates the race to use a new list of legs, and adds a dummy "Finish" leg at the end.
|
||||
* @param legs The new list of legs to use.
|
||||
@@ -185,10 +163,6 @@ public abstract class Race {
|
||||
return legID == lastLegID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the current race status.
|
||||
* @return The current race status.
|
||||
@@ -205,7 +179,6 @@ public abstract class Race {
|
||||
this.raceStatusEnum = raceStatusEnum;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the type of race this is.
|
||||
* @return The type of race this is.
|
||||
@@ -222,7 +195,6 @@ public abstract class Race {
|
||||
return regattaName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates the race to have a specified wind bearing and speed.
|
||||
* @param windBearing New wind bearing.
|
||||
@@ -241,7 +213,6 @@ public abstract class Race {
|
||||
this.raceWind.setValue(wind);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the wind bearing.
|
||||
* @return The wind bearing.
|
||||
@@ -268,7 +239,6 @@ public abstract class Race {
|
||||
return raceClock;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the RaceDataSource used for the race.
|
||||
* @return The RaceDataSource used for the race.
|
||||
@@ -286,7 +256,6 @@ public abstract class Race {
|
||||
return legs.size() - 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the race boundary.
|
||||
* @return The race boundary.
|
||||
@@ -295,12 +264,21 @@ public abstract class Race {
|
||||
return boundary;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of frames generated per second.
|
||||
* @return Frames per second.
|
||||
* Returns the marks of the race.
|
||||
* @return Marks of the race.
|
||||
*/
|
||||
public int getFps() {
|
||||
return lastFps.getValue();
|
||||
public List<CompoundMark> getCompoundMarks() {
|
||||
return compoundMarks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the legs of the race.
|
||||
* @return Legs of the race.
|
||||
*/
|
||||
public List<Leg> getLegs() {
|
||||
return legs;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -311,7 +289,6 @@ public abstract class Race {
|
||||
return lastFps;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Increments the FPS counter, and adds timePeriod milliseconds to our FPS reset timer.
|
||||
* @param timePeriod Time, in milliseconds, to add to {@link #lastFpsResetTime}.
|
||||
|
||||
Reference in New Issue
Block a user