package seng302.Model; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.scene.paint.Color; import org.geotools.referencing.GeodeticCalculator; import seng302.Constants; import seng302.GPSCoordinate; import java.awt.geom.Point2D; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; /** * Boat in the Race extends Boat. * Created by esa46 on 15/03/17. */ public class BoatInRace extends Boat { protected Leg currentLeg; protected double scaledVelocity; protected double distanceTravelledInLeg; protected GPSCoordinate currentPosition; protected long timeFinished; protected Color colour; protected boolean finished = false; protected StringProperty currentLegName; protected boolean started = false; protected StringProperty position; protected double heading; protected Queue track = new ConcurrentLinkedQueue<>(); protected long nextValidTime = 0; protected static final float BASE_TRACK_POINT_TIME_INTERVAL = 5000; protected static float trackPointTimeInterval = 5000; // every 1 seconds protected final int TRACK_POINT_LIMIT = 10; /** * Constructor method. * * @param name Name of the boat. * @param velocity Speed that the boat travels. * @param colour Colour the boat will be displayed as on the map * @param abbrev of boat */ public BoatInRace(String name, double velocity, Color colour, String abbrev) { super(name, velocity, abbrev); setColour(colour); currentLegName = new SimpleStringProperty(""); position = new SimpleStringProperty("-"); } /** * Constructor method. * * @param name Name of the boat. * @param colour Colour the boat will be displayed as on the map * @param abbrev of boat */ public BoatInRace(String name, Color colour, String abbrev) { super(name, abbrev); setColour(colour); currentLegName = new SimpleStringProperty(""); position = new SimpleStringProperty("-"); } /** * 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() { GeodeticCalculator calc = new GeodeticCalculator(); GPSCoordinate start = currentLeg.getStartMarker().getAverageGPSCoordinate(); GPSCoordinate end = currentLeg.getEndMarker().getAverageGPSCoordinate(); calc.setStartingGeographicPoint(start.getLongitude(), start.getLatitude()); calc.setDestinationGeographicPoint(end.getLongitude(), end.getLatitude()); return calc.getAzimuth(); } /** * Converts an azimuth to a bearing * * @param azimuth azimuth value to be converted * @return the bearings in degrees (0 to 360). */ public static double calculateHeading(double azimuth) { if (azimuth >= 0) { return azimuth; } else { return azimuth + 360; } } public double getHeading() { return heading; } public void setHeading(double heading) { this.heading = heading; } /** * Calculates the bearing of the travel via map coordinates of the raceMarkers * * @return the direction that the boat is heading towards in degrees (0 to 360). */ public double calculateHeading() { double azimuth = calculateAzimuth(); return calculateHeading(azimuth); } /** * Returns the position of the end of the boat's wake, which is 180 degrees * from the boat's heading, and whose length is proportional to the boat's * speed. * * @return GPSCoordinate of wake endpoint. */ public GPSCoordinate getWake() { double reverseHeading = getHeading() - 180; double distance = Constants.wakeScale * getVelocity(); GeodeticCalculator calc = new GeodeticCalculator(); calc.setStartingGeographicPoint( new Point2D.Double(getCurrentPosition().getLongitude(), getCurrentPosition().getLatitude()) ); calc.setDirection(reverseHeading, distance); Point2D endpoint = calc.getDestinationGeographicPoint(); return new GPSCoordinate(endpoint.getY(), endpoint.getX()); } /** * @return Scaled velocity of the boat */ public double getScaledVelocity() { return scaledVelocity; } /** * Sets the boat's scaled velocity * * @param velocity of boat */ public void setScaledVelocity(double velocity) { this.scaledVelocity = velocity; } /** * @return Returns the current position of the boat in a GPSCoordinate Class. * @see GPSCoordinate */ public GPSCoordinate getCurrentPosition() { return currentPosition; } /** * Sets the current position on the GPS that the boat. * * @param position GPSCoordinate of the position that the boat is currently on. * @see GPSCoordinate */ public void setCurrentPosition(GPSCoordinate position) { this.currentPosition = position; } /** * @return Returns the time that the boat finished the race. */ public long getTimeFinished() { return timeFinished; } /** * Sets the time that the boat finished the race. * * @param timeFinished Time the boat finished the race. */ public void setTimeFinished(long timeFinished) { this.timeFinished = timeFinished; } /** * @return Returns the colour of the boat. */ public Color getColour() { return colour; } /** * Sets the colour that boat will be shown as when drawn on the ResizableRaceCanvas. * * @param colour Colour that the boat is to be set to. * @see ResizableRaceCanvas */ public void setColour(Color colour) { this.colour = colour; } /** * Gets the current leg that the boat is on. * * @return returns the leg the boat is on in a Leg class * @see Leg */ public Leg getCurrentLeg() { return currentLeg; } /** * Sets the boat's current leg. * * @param currentLeg Leg class that the boat is currently on. * @see Leg */ public void setCurrentLeg(Leg currentLeg) { this.currentLeg = currentLeg; this.currentLegName.setValue(currentLeg.getName()); } /** * @return Name of boat's current leg */ public StringProperty getCurrentLegName() { return currentLegName; } /** * Gets the distance travelled by the boat in the leg. * * @return Returns the value in nautical miles (1.852km) that the boat has traversed. */ public double getDistanceTravelledInLeg() { return distanceTravelledInLeg; } /** * Sets the distance travelled by the boat in the leg in nautical miles (1.852km) * * @param distanceTravelledInLeg Distance travelled by the boat in nautical miles. */ public void setDistanceTravelledInLeg(double distanceTravelledInLeg) { this.distanceTravelledInLeg = distanceTravelledInLeg; } /** * @return true if boat has finished, false if not */ public boolean isFinished() { return this.finished; } /** * Sets whether boat is finished or not * * @param bool is finished value */ public void setFinished(boolean bool) { this.finished = bool; } public boolean isStarted() { return started; } public void setStarted(boolean started) { this.started = started; } public String getPosition() { return position.get(); } public StringProperty positionProperty() { return position; } public void setPosition(String position) { this.position.set(position); } /** * Adds a new point to boat's track. * @param coordinate of point on track * @return whether add is successful * @see seng302.Model.TrackPoint */ public boolean addTrackPoint(GPSCoordinate coordinate) { Boolean added = System.currentTimeMillis() >= nextValidTime; long currentTime = System.currentTimeMillis(); if (added && this.started) { nextValidTime = currentTime + (long) trackPointTimeInterval; track.add(new TrackPoint(coordinate, currentTime, TRACK_POINT_LIMIT * (long) trackPointTimeInterval)); } return added; } /** * Returns the boat's sampled track between start of race and current time. * @return queue of track points * @see seng302.Model.TrackPoint */ public Queue getTrack() { return track; } /** * Get base track point time interval * @return base track point time interval */ public static float getBaseTrackPointTimeInterval() { return BASE_TRACK_POINT_TIME_INTERVAL; } /** * Set track point time interval * @param value track point time interval value */ public static void setTrackPointTimeInterval(float value) { trackPointTimeInterval = value; } }