Added Mock.Angle, Mock.Azimith, Mock.Bearing. These encapsulate the relevant angle type, to allow for better type safety (e.g., to avoid passing a bearing into an azimuth function).
Added more comments to Mock.Boat. Moved calculateAzimuth to GPSCoordinate, from Boat.
This commit is contained in:
@@ -0,0 +1,65 @@
|
|||||||
|
package seng302.Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This represents an angle.
|
||||||
|
* Has functions to return angle as either degrees or radians.
|
||||||
|
*/
|
||||||
|
public class Angle {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The angle stored in this object.
|
||||||
|
* Degrees.
|
||||||
|
*/
|
||||||
|
private double degrees;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ctor.
|
||||||
|
* Don't use this.
|
||||||
|
* This is protected because you need to use the static helper functions {@link #fromDegrees(double)} and {@link #fromRadians(double)} to construct an Angle object.
|
||||||
|
*
|
||||||
|
* @param degrees The value, in degrees, to initialize this Angle object with.
|
||||||
|
*/
|
||||||
|
protected Angle(double degrees) {
|
||||||
|
this.degrees = degrees;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an Angle object from an angle value in degrees.
|
||||||
|
* @param degrees Angle value in degrees.
|
||||||
|
* @return Angle object.
|
||||||
|
*/
|
||||||
|
public static Angle fromDegrees(double degrees) {
|
||||||
|
Angle angle = new Angle(degrees);
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an Angle object from an angle value in radians.
|
||||||
|
* @param radians Angle value in radians.
|
||||||
|
* @return Angle object.
|
||||||
|
*/
|
||||||
|
public static Angle fromRadians(double radians) {
|
||||||
|
return Angle.fromDegrees(Math.toDegrees(radians));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of this Angle object, in degrees.
|
||||||
|
* @return The value of this Angle object, in degrees.
|
||||||
|
*/
|
||||||
|
public double degrees() {
|
||||||
|
return this.degrees;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of this Angle object, in radians.
|
||||||
|
* @return The value of this Angle object, in radians.
|
||||||
|
*/
|
||||||
|
public double radians() {
|
||||||
|
return Math.toRadians(this.degrees);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package seng302.Model;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an azimuth.
|
||||||
|
* This is the angle between north and a target point.
|
||||||
|
* It has the interval [-180, 180), and clockwise from north is positive.
|
||||||
|
*/
|
||||||
|
public class Azimuth extends Angle{
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ctor.
|
||||||
|
* This is protected because you need to use the static helper functions {@link #fromDegrees(double)} and {@link #fromRadians(double)} to construct an Azimuth object.
|
||||||
|
*
|
||||||
|
* @param degrees The value, in degrees, to initialize this Azimuth object with.
|
||||||
|
*/
|
||||||
|
protected Azimuth(double degrees) {
|
||||||
|
super(degrees);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an angle in degrees into an angle in degrees in the correct interval for an azimuth - [-180, 180).
|
||||||
|
* E.g., converts -183 to 177, or converts 250 to -110, or converts 180 to -180.
|
||||||
|
* @param degrees Degree value to convert.
|
||||||
|
* @return Degree value in interval [-180, 180).
|
||||||
|
*/
|
||||||
|
public static double toAzimuthInterval(double degrees) {
|
||||||
|
|
||||||
|
if (degrees >= 180) {
|
||||||
|
//Too large.
|
||||||
|
degrees -= 360;
|
||||||
|
} else if (degrees < -180) {
|
||||||
|
//Too small.
|
||||||
|
degrees += 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
return degrees;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an Azimuth object from an angle value in degrees.
|
||||||
|
* @param degrees Azimuth value in degrees.
|
||||||
|
* @return Azimuth object.
|
||||||
|
*/
|
||||||
|
public static Azimuth fromDegrees(double degrees) {
|
||||||
|
//Ensure the angle is in the correct interval.
|
||||||
|
double degreesInInterval = Azimuth.toAzimuthInterval(degrees);
|
||||||
|
|
||||||
|
Azimuth azimuth = new Azimuth(degreesInInterval);
|
||||||
|
return azimuth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an Azimuth object from an angle value in radians.
|
||||||
|
* @param radians Azimuth value in radians.
|
||||||
|
* @return Azimuth object.
|
||||||
|
*/
|
||||||
|
public static Azimuth fromRadians(double radians) {
|
||||||
|
return Azimuth.fromDegrees(Math.toDegrees(radians));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package seng302.Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a bearing. Also known as a heading.
|
||||||
|
* This is the angle between north and a target point.
|
||||||
|
* Has the interval [0, 360), and clockwise from north is positive.
|
||||||
|
*/
|
||||||
|
public class Bearing extends Angle {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ctor.
|
||||||
|
* This is protected because you need to use the static helper functions {@link #fromDegrees(double)} and {@link #fromRadians(double)} to construct a Bearing object.
|
||||||
|
*
|
||||||
|
* @param degrees The value, in degrees, to initialize this Bearing object with.
|
||||||
|
*/
|
||||||
|
protected Bearing(double degrees) {
|
||||||
|
super(degrees);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an angle in degrees into an angle in degrees in the correct interval for a bearing - [0, 360).
|
||||||
|
* E.g., converts -183 to 177, or converts 425 to 65.
|
||||||
|
* @param degrees Degree value to convert.
|
||||||
|
* @return Degree value in interval [0, 360).
|
||||||
|
*/
|
||||||
|
public static double toBearingInterval(double degrees) {
|
||||||
|
|
||||||
|
if (degrees >= 360) {
|
||||||
|
//Too large.
|
||||||
|
degrees -= 360;
|
||||||
|
} else if (degrees < 0) {
|
||||||
|
//Too small.
|
||||||
|
degrees += 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
return degrees;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a Bearing object from an angle value in degrees.
|
||||||
|
* @param degrees Bearing value in degrees.
|
||||||
|
* @return Bearing object.
|
||||||
|
*/
|
||||||
|
public static Bearing fromDegrees(double degrees) {
|
||||||
|
//Ensure the angle is in the correct interval.
|
||||||
|
double degreesInInterval = Bearing.toBearingInterval(degrees);
|
||||||
|
|
||||||
|
Bearing bearing = new Bearing(degreesInInterval);
|
||||||
|
return bearing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a Bearing object from an angle value in radians.
|
||||||
|
* @param radians Bearing value in radians.
|
||||||
|
* @return Bearing object.
|
||||||
|
*/
|
||||||
|
public static Bearing fromRadians(double radians) {
|
||||||
|
return Bearing.fromDegrees(Math.toDegrees(radians));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,34 +5,91 @@ import seng302.Constants;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by esa46 on 1/05/17.
|
* This class represents a boat during a race.
|
||||||
*/
|
*/
|
||||||
public class Boat {
|
public class Boat {
|
||||||
private String name;
|
|
||||||
private double velocity;
|
|
||||||
private double scaledVelocity;
|
|
||||||
private String country;
|
|
||||||
private int sourceID;
|
|
||||||
private Leg currentLeg;
|
|
||||||
private double distanceTravelledInLeg;
|
|
||||||
private double distanceTravelledInTack;
|
|
||||||
private double distanceForTack;
|
|
||||||
private GPSCoordinate currentPosition;
|
|
||||||
private long timeFinished = -1;
|
|
||||||
private boolean started = false;
|
|
||||||
private double heading;
|
|
||||||
/**
|
/**
|
||||||
* This stores a boat's polars table. Can be used to calculate VMG.
|
* The name of the boat/team.
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current speed of the boat, in knots.
|
||||||
|
* TODO knots
|
||||||
|
*/
|
||||||
|
private double currentSpeed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current heading of the boat.
|
||||||
|
* TODO bearing
|
||||||
|
*/
|
||||||
|
private double heading;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current position of the boat.
|
||||||
|
*/
|
||||||
|
private GPSCoordinate currentPosition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The country or team abbreviation of the boat.
|
||||||
|
*/
|
||||||
|
private String country;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The source ID of the boat.
|
||||||
|
* This uniquely identifies an entity during a race.
|
||||||
|
*/
|
||||||
|
private int sourceID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The leg of the race that the boat is currently on.
|
||||||
|
*/
|
||||||
|
private Leg currentLeg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The distance, in meters, that the boat has travelled in the current leg.
|
||||||
|
* TODO meters
|
||||||
|
*/
|
||||||
|
private double distanceTravelledInLeg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The time, in milliseconds, that has elapsed during the current leg.
|
||||||
|
* TODO milliseconds
|
||||||
|
*/
|
||||||
|
private double timeElapsedInCurrentLeg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The timestamp, in milliseconds, of when the boat finished the race.
|
||||||
|
* Is -1 if it hasn't finished.
|
||||||
|
* TODO milliseconds
|
||||||
|
*/
|
||||||
|
private long timeFinished = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the boat has finished the race.
|
||||||
|
*/
|
||||||
|
private boolean hasFinishedRace = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the boat has started the race.
|
||||||
|
*/
|
||||||
|
private boolean hasStartedRace = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This stores a boat's polars table.
|
||||||
|
* Can be used to calculate VMG.
|
||||||
*/
|
*/
|
||||||
private Polars polars;
|
private Polars polars;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This stores the milliseconds since the boat has changed its tack, to allow for only updating the tack every X milliseconds.
|
* This stores the milliseconds since the boat has changed its tack, to allow for only updating the tack every X milliseconds.
|
||||||
|
* TODO milliseconds
|
||||||
*/
|
*/
|
||||||
private long timeSinceTackChange = 0;
|
private long timeSinceTackChange = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Boat initialiser which keeps all of the information of the boat.
|
* Constructs a boat object with a given sourceID, name, country/team abbreviation, and polars table.
|
||||||
*
|
*
|
||||||
* @param sourceID The id of the boat
|
* @param sourceID The id of the boat
|
||||||
* @param name The name of the Boat.
|
* @param name The name of the Boat.
|
||||||
@@ -46,34 +103,24 @@ public class Boat {
|
|||||||
this.polars = polars;
|
this.polars = polars;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the azimuth of the travel via map coordinates of the raceMarkers
|
|
||||||
*
|
|
||||||
* @return the direction that the boat is heading towards in degrees (-180 to 180).
|
|
||||||
*/
|
|
||||||
public double calculateAzimuth(GPSCoordinate start, GPSCoordinate end) {
|
|
||||||
|
|
||||||
GeodeticCalculator calc = new GeodeticCalculator();
|
|
||||||
|
|
||||||
calc.setStartingGeographicPoint(start.getLongitude(), start.getLatitude());
|
|
||||||
calc.setDestinationGeographicPoint(end.getLongitude(), end.getLatitude());
|
|
||||||
|
|
||||||
return calc.getAzimuth();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the heding depending on the calculated azimuth value
|
* Calculate the heading depending on the calculated azimuth value
|
||||||
* @return The azimuth value which is greater than 0
|
* @return The azimuth value which is greater than 0
|
||||||
*/
|
*/
|
||||||
public double calculateHeading() {
|
public double calculateHeading() {
|
||||||
double azimuth = this.calculateAzimuth(currentLeg.getStartCompoundMark().getAverageGPSCoordinate(),
|
double azimuth = GPSCoordinate.calculateAzimuth(currentLeg.getStartCompoundMark().getAverageGPSCoordinate(),
|
||||||
currentLeg.getEndCompoundMark().getAverageGPSCoordinate());
|
currentLeg.getEndCompoundMark().getAverageGPSCoordinate());
|
||||||
|
|
||||||
if (azimuth >= 0) {
|
//Azimuth is in the interval (-180, 180), but we need a heading in the interval [0, 360).
|
||||||
return azimuth;
|
if (azimuth < 0) {
|
||||||
} else {
|
|
||||||
return azimuth + 360;
|
return azimuth + 360;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return azimuth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,7 +128,7 @@ public class Boat {
|
|||||||
* @return The azimuth value which is greater than 0
|
* @return The azimuth value which is greater than 0
|
||||||
*/
|
*/
|
||||||
public double calculateBearingToDestination() {
|
public double calculateBearingToDestination() {
|
||||||
double azimuth = this.calculateAzimuth(this.currentPosition,
|
double azimuth = GPSCoordinate.calculateAzimuth(this.currentPosition,
|
||||||
currentLeg.getEndCompoundMark().getAverageGPSCoordinate());
|
currentLeg.getEndCompoundMark().getAverageGPSCoordinate());
|
||||||
|
|
||||||
if (azimuth >= 0) {
|
if (azimuth >= 0) {
|
||||||
@@ -125,21 +172,14 @@ public class Boat {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getVelocity() {
|
public double getCurrentSpeed() {
|
||||||
return velocity;
|
return currentSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVelocity(double velocity) {
|
public void setCurrentSpeed(double currentSpeed) {
|
||||||
this.velocity = velocity;
|
this.currentSpeed = currentSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getScaledVelocity() {
|
|
||||||
return scaledVelocity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setScaledVelocity(double scaledVelocity) {
|
|
||||||
this.scaledVelocity = scaledVelocity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCountry() {
|
public String getCountry() {
|
||||||
return country;
|
return country;
|
||||||
@@ -173,21 +213,6 @@ public class Boat {
|
|||||||
this.distanceTravelledInLeg = distanceTravelledInLeg;
|
this.distanceTravelledInLeg = distanceTravelledInLeg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getDistanceTravelledInTack() {
|
|
||||||
return distanceTravelledInTack;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDistanceTravelledInTack(double distanceTravelledInTack) {
|
|
||||||
this.distanceTravelledInTack = distanceTravelledInTack;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getDistanceForTack() {
|
|
||||||
return distanceForTack;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDistanceForTack(double distanceForTack) {
|
|
||||||
this.distanceForTack = distanceForTack;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GPSCoordinate getCurrentPosition() {
|
public GPSCoordinate getCurrentPosition() {
|
||||||
return currentPosition;
|
return currentPosition;
|
||||||
@@ -205,12 +230,12 @@ public class Boat {
|
|||||||
this.timeFinished = timeFinished;
|
this.timeFinished = timeFinished;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStarted() {
|
public boolean isHasStartedRace() {
|
||||||
return started;
|
return hasStartedRace;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStarted(boolean started) {
|
public void setHasStartedRace(boolean hasStartedRace) {
|
||||||
this.started = started;
|
this.hasStartedRace = hasStartedRace;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getHeading() {
|
public double getHeading() {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package seng302.Model;
|
package seng302.Model;
|
||||||
|
|
||||||
|
import org.geotools.referencing.GeodeticCalculator;
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -152,5 +154,22 @@ public class GPSCoordinate {
|
|||||||
return aRatio >= bRatio;
|
return aRatio >= bRatio;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the azimuth between two points.
|
||||||
|
* This is an angle in the interval (-180, 180), with
|
||||||
|
*
|
||||||
|
* @return the direction that the boat is heading towards in degrees (-180 to 180).
|
||||||
|
*/
|
||||||
|
public static double calculateAzimuth(GPSCoordinate start, GPSCoordinate end) {
|
||||||
|
|
||||||
|
GeodeticCalculator calc = new GeodeticCalculator();
|
||||||
|
|
||||||
|
calc.setStartingGeographicPoint(start.getLongitude(), start.getLatitude());
|
||||||
|
calc.setDestinationGeographicPoint(end.getLongitude(), end.getLatitude());
|
||||||
|
|
||||||
|
return calc.getAzimuth();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -143,10 +143,10 @@ public class Race implements Runnable {
|
|||||||
checkPosition(boat, totalTimeElapsed);
|
checkPosition(boat, totalTimeElapsed);
|
||||||
}
|
}
|
||||||
if (boat.getTimeFinished() > 0) {
|
if (boat.getTimeFinished() > 0) {
|
||||||
mockOutput.parseBoatLocation(boat.getSourceID(), boat.getCurrentPosition().getLatitude(), boat.getCurrentPosition().getLongitude(), boat.getHeading(), boat.getVelocity());
|
mockOutput.parseBoatLocation(boat.getSourceID(), boat.getCurrentPosition().getLatitude(), boat.getCurrentPosition().getLongitude(), boat.getHeading(), boat.getCurrentSpeed());
|
||||||
boatStatuses.add(new BoatStatus(boat.getSourceID(), BoatStatusEnum.FINISHED, boat.getCurrentLeg().getLegNumber()));
|
boatStatuses.add(new BoatStatus(boat.getSourceID(), BoatStatusEnum.FINISHED, boat.getCurrentLeg().getLegNumber()));
|
||||||
} else {
|
} else {
|
||||||
mockOutput.parseBoatLocation(boat.getSourceID(), boat.getCurrentPosition().getLatitude(), boat.getCurrentPosition().getLongitude(), boat.getHeading(), boat.getVelocity());
|
mockOutput.parseBoatLocation(boat.getSourceID(), boat.getCurrentPosition().getLatitude(), boat.getCurrentPosition().getLongitude(), boat.getHeading(), boat.getCurrentSpeed());
|
||||||
boatStatuses.add(new BoatStatus(boat.getSourceID(),
|
boatStatuses.add(new BoatStatus(boat.getSourceID(),
|
||||||
boat.getCurrentLeg().getLegNumber() >= 0 ? BoatStatusEnum.RACING : BoatStatusEnum.DNF, boat.getCurrentLeg().getLegNumber()));
|
boat.getCurrentLeg().getLegNumber() >= 0 ? BoatStatusEnum.RACING : BoatStatusEnum.DNF, boat.getCurrentLeg().getLegNumber()));
|
||||||
}
|
}
|
||||||
@@ -174,8 +174,7 @@ public class Race implements Runnable {
|
|||||||
if (boat != null) {
|
if (boat != null) {
|
||||||
Leg newLeg = new Leg(name, new Marker(startingPositions.get(i)), endMark, 0);
|
Leg newLeg = new Leg(name, new Marker(startingPositions.get(i)), endMark, 0);
|
||||||
boat.setCurrentLeg(newLeg);
|
boat.setCurrentLeg(newLeg);
|
||||||
boat.setVelocity(Constants.TEST_VELOCITIES[i]);
|
boat.setCurrentSpeed(Constants.TEST_VELOCITIES[i]);//TODO we should get rid of TEST_VELOCITIES since speed is based off of wind speed/angle.
|
||||||
boat.setScaledVelocity(boat.getVelocity() * scaleFactor);
|
|
||||||
boat.setCurrentPosition(startingPositions.get(i));
|
boat.setCurrentPosition(startingPositions.get(i));
|
||||||
boat.setHeading(boat.calculateHeading());
|
boat.setHeading(boat.calculateHeading());
|
||||||
boat.setTimeSinceTackChange(999999);//We set a large time since tack change so that it calculates a new VMG when the simulation starts.
|
boat.setTimeSinceTackChange(999999);//We set a large time since tack change so that it calculates a new VMG when the simulation starts.
|
||||||
@@ -248,14 +247,14 @@ public class Race implements Runnable {
|
|||||||
protected void updatePosition(Boat boat, int millisecondsElapsed) {
|
protected void updatePosition(Boat boat, int millisecondsElapsed) {
|
||||||
|
|
||||||
//distanceTravelled = velocity (nm p hr) * time taken to update loop
|
//distanceTravelled = velocity (nm p hr) * time taken to update loop
|
||||||
double distanceTravelled = (boat.getVelocity() * this.scaleFactor * millisecondsElapsed) / 3600000;
|
double distanceTravelled = (boat.getCurrentSpeed() * this.scaleFactor * millisecondsElapsed) / 3600000;
|
||||||
double totalDistanceTravelled = distanceTravelled + boat.getDistanceTravelledInLeg();
|
double totalDistanceTravelled = distanceTravelled + boat.getDistanceTravelledInLeg();
|
||||||
|
|
||||||
boolean finish = boat.getCurrentLeg().getName().equals("Finish");
|
boolean finish = boat.getCurrentLeg().getName().equals("Finish");
|
||||||
if (!finish) {
|
if (!finish) {
|
||||||
|
|
||||||
|
|
||||||
double totalDistanceTravelledInTack = distanceTravelled + boat.getDistanceTravelledInTack();
|
double totalDistanceTravelledInTack = distanceTravelled;//TODO FIX// + boat.getDistanceTravelledInTack();
|
||||||
|
|
||||||
double bound1 = (boat.calculateBearingToDestination() - 90) % 360;
|
double bound1 = (boat.calculateBearingToDestination() - 90) % 360;
|
||||||
double bound2 = (boat.calculateBearingToDestination() + 90) % 360;
|
double bound2 = (boat.calculateBearingToDestination() + 90) % 360;
|
||||||
@@ -295,15 +294,15 @@ public class Race implements Runnable {
|
|||||||
|
|
||||||
double angleBetweenDestAndHeading = boat.getHeading() - boat.calculateBearingToDestination();
|
double angleBetweenDestAndHeading = boat.getHeading() - boat.calculateBearingToDestination();
|
||||||
double angleBetweenDestAndNewVMG = newHeading.getBearing() - boat.calculateBearingToDestination();
|
double angleBetweenDestAndNewVMG = newHeading.getBearing() - boat.calculateBearingToDestination();
|
||||||
double currentVelocity = cos(Math.toRadians(angleBetweenDestAndHeading)) * boat.getVelocity();
|
double currentVelocity = cos(Math.toRadians(angleBetweenDestAndHeading)) * boat.getCurrentSpeed();
|
||||||
double vmgVelocity = cos(Math.toRadians(angleBetweenDestAndNewVMG)) * newHeading.getSpeed();
|
double vmgVelocity = cos(Math.toRadians(angleBetweenDestAndNewVMG)) * newHeading.getSpeed();
|
||||||
//System.out.println("boat " + boat.getAbbrev() + " current velocity is " + currentVelocity + " knots, possible VMG is " + vmgVelocity + " knots.");//TEMP DEBUG REMOVE
|
//System.out.println("boat " + boat.getAbbrev() + " current velocity is " + currentVelocity + " knots, possible VMG is " + vmgVelocity + " knots.");//TEMP DEBUG REMOVE
|
||||||
if (vmgVelocity > currentVelocity) {
|
if (vmgVelocity > currentVelocity) {
|
||||||
boat.setHeading(newHeading.getBearing());
|
boat.setHeading(newHeading.getBearing());
|
||||||
boat.setVelocity(newHeading.getSpeed());
|
boat.setCurrentSpeed(newHeading.getSpeed());
|
||||||
boat.setTimeSinceTackChange(0);
|
boat.setTimeSinceTackChange(0);
|
||||||
|
|
||||||
//System.out.println("boat " + boat.getAbbrev() + " has a new bearing " + boat.getHeading() + " degrees, and is " + boat.calculateDistanceToNextMarker() + " nautical miles to the next marker. Velocity to next marker is " + boat.getVelocity() + " knots.");//TEMP DEBUG REMOVE
|
//System.out.println("boat " + boat.getAbbrev() + " has a new bearing " + boat.getHeading() + " degrees, and is " + boat.calculateDistanceToNextMarker() + " nautical miles to the next marker. Velocity to next marker is " + boat.getCurrentSpeed() + " knots.");//TEMP DEBUG REMOVE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -346,14 +345,12 @@ public class Race implements Runnable {
|
|||||||
boatsFinished++;
|
boatsFinished++;
|
||||||
boat.setTimeFinished(timeElapsed);
|
boat.setTimeFinished(timeElapsed);
|
||||||
boat.setTimeFinished(timeElapsed);
|
boat.setTimeFinished(timeElapsed);
|
||||||
boat.setVelocity(0);
|
boat.setCurrentSpeed(0);
|
||||||
boat.setScaledVelocity(0);
|
|
||||||
} else if (doNotFinish()) {
|
} else if (doNotFinish()) {
|
||||||
boatsFinished++;
|
boatsFinished++;
|
||||||
boat.setTimeFinished(timeElapsed);
|
boat.setTimeFinished(timeElapsed);
|
||||||
boat.setCurrentLeg(new Leg("DNF", -1));
|
boat.setCurrentLeg(new Leg("DNF", -1));
|
||||||
boat.setVelocity(0);
|
boat.setCurrentSpeed(0);
|
||||||
boat.setScaledVelocity(0);
|
|
||||||
} else {
|
} else {
|
||||||
//Calculate how much the boat overshot the marker by
|
//Calculate how much the boat overshot the marker by
|
||||||
boat.setDistanceTravelledInLeg(boat.getDistanceTravelledInLeg() - boat.getCurrentLeg().getDistance());
|
boat.setDistanceTravelledInLeg(boat.getDistanceTravelledInLeg() - boat.getCurrentLeg().getDistance());
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class BoatTest {
|
|||||||
Marker endMarker = new Marker(new GPSCoordinate(50, 0));
|
Marker endMarker = new Marker(new GPSCoordinate(50, 0));
|
||||||
Leg start = new Leg("Start", startMarker, endMarker, 0);
|
Leg start = new Leg("Start", startMarker, endMarker, 0);
|
||||||
TEST_BOAT.setCurrentLeg(start);
|
TEST_BOAT.setCurrentLeg(start);
|
||||||
assertEquals(TEST_BOAT.calculateAzimuth(startMarker.getAverageGPSCoordinate(), endMarker.getAverageGPSCoordinate()), 0, 1e-8);
|
assertEquals(GPSCoordinate.calculateAzimuth(startMarker.getAverageGPSCoordinate(), endMarker.getAverageGPSCoordinate()), 0, 1e-8);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -31,7 +31,7 @@ public class BoatTest {
|
|||||||
Marker endMarker = new Marker(new GPSCoordinate(-50, 0));
|
Marker endMarker = new Marker(new GPSCoordinate(-50, 0));
|
||||||
Leg start = new Leg("Start", startMarker, endMarker, 0);
|
Leg start = new Leg("Start", startMarker, endMarker, 0);
|
||||||
TEST_BOAT.setCurrentLeg(start);
|
TEST_BOAT.setCurrentLeg(start);
|
||||||
assertEquals(TEST_BOAT.calculateAzimuth(startMarker.getAverageGPSCoordinate(), endMarker.getAverageGPSCoordinate()), 180, 1e-8);
|
assertEquals(GPSCoordinate.calculateAzimuth(startMarker.getAverageGPSCoordinate(), endMarker.getAverageGPSCoordinate()), 180, 1e-8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ public class BoatTest {
|
|||||||
Marker endMarker = new Marker(new GPSCoordinate(0, 50));
|
Marker endMarker = new Marker(new GPSCoordinate(0, 50));
|
||||||
Leg start = new Leg("Start", startMarker, endMarker, 0);
|
Leg start = new Leg("Start", startMarker, endMarker, 0);
|
||||||
TEST_BOAT.setCurrentLeg(start);
|
TEST_BOAT.setCurrentLeg(start);
|
||||||
assertEquals(TEST_BOAT.calculateAzimuth(startMarker.getAverageGPSCoordinate(), endMarker.getAverageGPSCoordinate()), 90, 1e-8);
|
assertEquals(GPSCoordinate.calculateAzimuth(startMarker.getAverageGPSCoordinate(), endMarker.getAverageGPSCoordinate()), 90, 1e-8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ public class BoatTest {
|
|||||||
Marker endMarker = new Marker(new GPSCoordinate(0, -50));
|
Marker endMarker = new Marker(new GPSCoordinate(0, -50));
|
||||||
Leg start = new Leg("Start", startMarker, endMarker, 0);
|
Leg start = new Leg("Start", startMarker, endMarker, 0);
|
||||||
TEST_BOAT.setCurrentLeg(start);
|
TEST_BOAT.setCurrentLeg(start);
|
||||||
assertEquals(TEST_BOAT.calculateAzimuth(startMarker.getAverageGPSCoordinate(), endMarker.getAverageGPSCoordinate()), -90, 1e-8);
|
assertEquals(GPSCoordinate.calculateAzimuth(startMarker.getAverageGPSCoordinate(), endMarker.getAverageGPSCoordinate()), -90, 1e-8);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ public class RaceTest{
|
|||||||
testBoat.setDistanceTravelledInLeg(1);
|
testBoat.setDistanceTravelledInLeg(1);
|
||||||
testRace.checkPosition(testBoat, 1);
|
testRace.checkPosition(testBoat, 1);
|
||||||
|
|
||||||
assertEquals(testBoat.getVelocity(), 0, 1e-8);
|
assertEquals(testBoat.getCurrentSpeed(), 0, 1e-8);
|
||||||
|
|
||||||
} catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) {
|
} catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|||||||
Reference in New Issue
Block a user