Merge branch 'master' into issue_18_track_alpha
# Conflicts: # racevisionGame/src/main/java/visualiser/model/VisualiserRaceState.java
This commit is contained in:
@@ -4,6 +4,7 @@ import mock.model.RaceLogic;
|
|||||||
import mock.model.ClientConnection;
|
import mock.model.ClientConnection;
|
||||||
import mock.model.SourceIdAllocator;
|
import mock.model.SourceIdAllocator;
|
||||||
import mock.model.commandFactory.CompositeCommand;
|
import mock.model.commandFactory.CompositeCommand;
|
||||||
|
import network.AckSequencer;
|
||||||
import network.Messages.Enums.XMLMessageType;
|
import network.Messages.Enums.XMLMessageType;
|
||||||
import network.Messages.LatestMessages;
|
import network.Messages.LatestMessages;
|
||||||
import network.Messages.XMLMessage;
|
import network.Messages.XMLMessage;
|
||||||
@@ -58,11 +59,6 @@ public class ConnectionAcceptor implements Runnable {
|
|||||||
*/
|
*/
|
||||||
private SourceIdAllocator sourceIdAllocator;
|
private SourceIdAllocator sourceIdAllocator;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Acknowledgement number for packets
|
|
||||||
private int ackNumber = 0;
|
|
||||||
//race xml sequence number
|
//race xml sequence number
|
||||||
private short raceXMLSequenceNumber;
|
private short raceXMLSequenceNumber;
|
||||||
//boat xml sequence number
|
//boat xml sequence number
|
||||||
@@ -263,7 +259,7 @@ public class ConnectionAcceptor implements Runnable {
|
|||||||
//Create the message.
|
//Create the message.
|
||||||
XMLMessage message = new XMLMessage(
|
XMLMessage message = new XMLMessage(
|
||||||
XMLMessage.currentVersionNumber,
|
XMLMessage.currentVersionNumber,
|
||||||
getNextAckNumber(),
|
AckSequencer.getNextAckNum(),
|
||||||
System.currentTimeMillis(),
|
System.currentTimeMillis(),
|
||||||
messageType,
|
messageType,
|
||||||
sequenceNumber,
|
sequenceNumber,
|
||||||
@@ -272,15 +268,4 @@ public class ConnectionAcceptor implements Runnable {
|
|||||||
|
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Increments the ackNumber value, and returns it.
|
|
||||||
* @return Incremented ackNumber.
|
|
||||||
*/
|
|
||||||
private int getNextAckNumber(){
|
|
||||||
this.ackNumber++;
|
|
||||||
|
|
||||||
return this.ackNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package mock.model;
|
package mock.model;
|
||||||
|
|
||||||
|
|
||||||
import shared.model.*;
|
import shared.model.*;
|
||||||
|
|
||||||
|
|
||||||
@@ -74,7 +73,7 @@ public class MockBoat extends Boat {
|
|||||||
public Bearing calculateBearingToNextMarker() {
|
public Bearing calculateBearingToNextMarker() {
|
||||||
|
|
||||||
//Get the start and end points.
|
//Get the start and end points.
|
||||||
GPSCoordinate currentPosition = this.getCurrentPosition();
|
GPSCoordinate currentPosition = this.getPosition();
|
||||||
GPSCoordinate nextMarkerPosition;
|
GPSCoordinate nextMarkerPosition;
|
||||||
|
|
||||||
// if boat is at the finish
|
// if boat is at the finish
|
||||||
@@ -87,7 +86,6 @@ public class MockBoat extends Boat {
|
|||||||
|
|
||||||
//Calculate bearing.
|
//Calculate bearing.
|
||||||
Bearing bearing = GPSCoordinate.calculateBearing(currentPosition, nextMarkerPosition);
|
Bearing bearing = GPSCoordinate.calculateBearing(currentPosition, nextMarkerPosition);
|
||||||
|
|
||||||
return bearing;
|
return bearing;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +98,7 @@ public class MockBoat extends Boat {
|
|||||||
public double calculateDistanceToNextMarker() {
|
public double calculateDistanceToNextMarker() {
|
||||||
|
|
||||||
//Get start and end markers.
|
//Get start and end markers.
|
||||||
GPSCoordinate startPosition = this.getCurrentPosition();
|
GPSCoordinate startPosition = this.getPosition();
|
||||||
|
|
||||||
//When boats finish, their "current leg" doesn't have an end marker.
|
//When boats finish, their "current leg" doesn't have an end marker.
|
||||||
if (this.getCurrentLeg().getEndCompoundMark() == null) {
|
if (this.getCurrentLeg().getEndCompoundMark() == null) {
|
||||||
@@ -111,9 +109,7 @@ public class MockBoat extends Boat {
|
|||||||
|
|
||||||
|
|
||||||
//Calculate distance.
|
//Calculate distance.
|
||||||
double distanceNauticalMiles = GPSCoordinate.calculateDistanceNauticalMiles(startPosition, endMarker);
|
return GPSCoordinate.calculateDistanceNauticalMiles(startPosition, endMarker);
|
||||||
|
|
||||||
return distanceNauticalMiles;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -160,8 +156,8 @@ public class MockBoat extends Boat {
|
|||||||
*/
|
*/
|
||||||
public void moveForwards(double meters) {
|
public void moveForwards(double 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.getPosition(), meters, Azimuth.fromBearing(this.getBearing()));
|
||||||
this.setCurrentPosition(newPosition);
|
this.setPosition(newPosition);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +215,7 @@ public class MockBoat extends Boat {
|
|||||||
* @return true if mark is on port side
|
* @return true if mark is on port side
|
||||||
*/
|
*/
|
||||||
public boolean isPortSide(Mark mark){
|
public boolean isPortSide(Mark mark){
|
||||||
Bearing towardsMark = GPSCoordinate.calculateBearing(this.getCurrentPosition(), mark.getPosition());
|
Bearing towardsMark = GPSCoordinate.calculateBearing(this.getPosition(), mark.getPosition());
|
||||||
if (towardsMark.degrees() > 315 || towardsMark.degrees() <= 45){
|
if (towardsMark.degrees() > 315 || towardsMark.degrees() <= 45){
|
||||||
//south quadrant
|
//south quadrant
|
||||||
return this.getBearing().degrees() <= 180;
|
return this.getBearing().degrees() <= 180;
|
||||||
@@ -245,7 +241,7 @@ public class MockBoat extends Boat {
|
|||||||
*/
|
*/
|
||||||
public boolean isStarboardSide(Mark mark){
|
public boolean isStarboardSide(Mark mark){
|
||||||
//if this boat is lower than the mark check which way it is facing
|
//if this boat is lower than the mark check which way it is facing
|
||||||
Bearing towardsMark = GPSCoordinate.calculateBearing(this.getCurrentPosition(), mark.getPosition());
|
Bearing towardsMark = GPSCoordinate.calculateBearing(this.getPosition(), mark.getPosition());
|
||||||
if (towardsMark.degrees() > 315 || towardsMark.degrees() <= 45){
|
if (towardsMark.degrees() > 315 || towardsMark.degrees() <= 45){
|
||||||
//south quadrant
|
//south quadrant
|
||||||
return !(this.getBearing().degrees() <= 180);
|
return !(this.getBearing().degrees() <= 180);
|
||||||
@@ -297,12 +293,11 @@ public class MockBoat extends Boat {
|
|||||||
this.roundingStatus = 0;
|
this.roundingStatus = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getAutoVMG(){
|
||||||
|
return autoVMG;
|
||||||
|
}
|
||||||
|
|
||||||
public void setAutoVMG(boolean autoVMG) {
|
public void setAutoVMG(boolean autoVMG) {
|
||||||
this.autoVMG = autoVMG;
|
this.autoVMG = autoVMG;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getAutoVMG(){
|
|
||||||
return autoVMG;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package mock.model;
|
|||||||
|
|
||||||
import network.Messages.Enums.BoatStatusEnum;
|
import network.Messages.Enums.BoatStatusEnum;
|
||||||
import network.Messages.Enums.RaceStatusEnum;
|
import network.Messages.Enums.RaceStatusEnum;
|
||||||
import network.Messages.LatestMessages;
|
|
||||||
import shared.dataInput.BoatDataSource;
|
import shared.dataInput.BoatDataSource;
|
||||||
import shared.dataInput.RaceDataSource;
|
import shared.dataInput.RaceDataSource;
|
||||||
import shared.dataInput.RegattaDataSource;
|
import shared.dataInput.RegattaDataSource;
|
||||||
@@ -29,8 +28,6 @@ public class MockRace extends Race {
|
|||||||
*/
|
*/
|
||||||
private List<MockBoat> boats;
|
private List<MockBoat> boats;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A copy of the boundary list, except "shrunk" inwards by 50m.
|
* A copy of the boundary list, except "shrunk" inwards by 50m.
|
||||||
*/
|
*/
|
||||||
@@ -72,6 +69,8 @@ public class MockRace extends Race {
|
|||||||
|
|
||||||
//Wind.
|
//Wind.
|
||||||
this.setWind(windGenerator.generateBaselineWind());
|
this.setWind(windGenerator.generateBaselineWind());
|
||||||
|
|
||||||
|
this.colliderRegistry.addAllColliders(boats);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -195,7 +194,7 @@ public class MockRace extends Race {
|
|||||||
boat.setCurrentSpeed(0d);
|
boat.setCurrentSpeed(0d);
|
||||||
|
|
||||||
//Place the boat at its starting position.
|
//Place the boat at its starting position.
|
||||||
boat.setCurrentPosition(startPosition);
|
boat.setPosition(startPosition);
|
||||||
|
|
||||||
//Boats start facing their next marker.
|
//Boats start facing their next marker.
|
||||||
boat.setBearing(boat.calculateBearingToNextMarker());
|
boat.setBearing(boat.calculateBearingToNextMarker());
|
||||||
@@ -400,7 +399,7 @@ public class MockRace extends Race {
|
|||||||
Bearing bearing = Bearing.fromDegrees(angle);
|
Bearing bearing = Bearing.fromDegrees(angle);
|
||||||
|
|
||||||
//Check that if it is acceptable.
|
//Check that if it is acceptable.
|
||||||
boolean bearingIsGood = this.checkBearingInsideCourse(bearing, boat.getCurrentPosition());
|
boolean bearingIsGood = this.checkBearingInsideCourse(bearing, boat.getPosition());
|
||||||
|
|
||||||
|
|
||||||
if (lastAngle != -1) {
|
if (lastAngle != -1) {
|
||||||
@@ -475,7 +474,7 @@ public class MockRace extends Race {
|
|||||||
case 0://hasn't started rounding
|
case 0://hasn't started rounding
|
||||||
if (boat.isPortSide(roundingMark) &&
|
if (boat.isPortSide(roundingMark) &&
|
||||||
GPSCoordinate.passesLine(roundingMark.getPosition(),
|
GPSCoordinate.passesLine(roundingMark.getPosition(),
|
||||||
roundingChecks.get(0), boat.getCurrentPosition(), legBearing) &&
|
roundingChecks.get(0), boat.getPosition(), legBearing) &&
|
||||||
gateCheck && boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(0)))) {
|
gateCheck && boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(0)))) {
|
||||||
boat.increaseRoundingStatus();
|
boat.increaseRoundingStatus();
|
||||||
if (boat.getCurrentLeg().getLegNumber() + 2 >= legs.size()){
|
if (boat.getCurrentLeg().getLegNumber() + 2 >= legs.size()){
|
||||||
@@ -487,7 +486,7 @@ public class MockRace extends Race {
|
|||||||
case 1://has been parallel to the mark;
|
case 1://has been parallel to the mark;
|
||||||
if (boat.isPortSide(roundingMark) &&
|
if (boat.isPortSide(roundingMark) &&
|
||||||
GPSCoordinate.passesLine(roundingMark.getPosition(),
|
GPSCoordinate.passesLine(roundingMark.getPosition(),
|
||||||
roundingChecks.get(1), boat.getCurrentPosition(),
|
roundingChecks.get(1), boat.getPosition(),
|
||||||
Bearing.fromDegrees(legBearing.degrees() - 90)) &&//negative 90 from bearing because of port rounding
|
Bearing.fromDegrees(legBearing.degrees() - 90)) &&//negative 90 from bearing because of port rounding
|
||||||
boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(1)))) {
|
boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(1)))) {
|
||||||
boat.increaseRoundingStatus();
|
boat.increaseRoundingStatus();
|
||||||
@@ -519,7 +518,7 @@ public class MockRace extends Race {
|
|||||||
case 0://hasn't started rounding
|
case 0://hasn't started rounding
|
||||||
if (boat.isStarboardSide(roundingMark) &&
|
if (boat.isStarboardSide(roundingMark) &&
|
||||||
GPSCoordinate.passesLine(roundingMark.getPosition(),
|
GPSCoordinate.passesLine(roundingMark.getPosition(),
|
||||||
roundingChecks.get(0), boat.getCurrentPosition(), legBearing) &&
|
roundingChecks.get(0), boat.getPosition(), legBearing) &&
|
||||||
gateCheck &&
|
gateCheck &&
|
||||||
boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(0)))) {
|
boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(0)))) {
|
||||||
boat.increaseRoundingStatus();
|
boat.increaseRoundingStatus();
|
||||||
@@ -532,7 +531,7 @@ public class MockRace extends Race {
|
|||||||
case 1://has been parallel to the mark
|
case 1://has been parallel to the mark
|
||||||
if (boat.isStarboardSide(roundingMark) &&
|
if (boat.isStarboardSide(roundingMark) &&
|
||||||
GPSCoordinate.passesLine(roundingMark.getPosition(),
|
GPSCoordinate.passesLine(roundingMark.getPosition(),
|
||||||
roundingChecks.get(1), boat.getCurrentPosition(), Bearing.fromDegrees(legBearing.degrees() + 90)) && //positive 90 from bearing because of starboard rounding
|
roundingChecks.get(1), boat.getPosition(), Bearing.fromDegrees(legBearing.degrees() + 90)) && //positive 90 from bearing because of starboard rounding
|
||||||
boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(1)))) {
|
boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(1)))) {
|
||||||
boat.increaseRoundingStatus();
|
boat.increaseRoundingStatus();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package mock.model;
|
package mock.model;
|
||||||
|
|
||||||
import javafx.animation.AnimationTimer;
|
import javafx.animation.AnimationTimer;
|
||||||
|
import mock.model.collider.Collision;
|
||||||
|
import mock.model.commandFactory.Command;
|
||||||
import mock.model.commandFactory.CompositeCommand;
|
import mock.model.commandFactory.CompositeCommand;
|
||||||
import mock.model.commandFactory.CommandFactory;
|
import mock.model.commandFactory.CommandFactory;
|
||||||
import network.Messages.Enums.BoatActionEnum;
|
import network.Messages.Enums.BoatActionEnum;
|
||||||
@@ -9,8 +11,11 @@ import network.Messages.Enums.RaceStatusEnum;
|
|||||||
import network.Messages.LatestMessages;
|
import network.Messages.LatestMessages;
|
||||||
import shared.model.RunnableWithFramePeriod;
|
import shared.model.RunnableWithFramePeriod;
|
||||||
|
|
||||||
|
import java.util.Observable;
|
||||||
|
import java.util.Observer;
|
||||||
|
|
||||||
public class RaceLogic implements RunnableWithFramePeriod {
|
|
||||||
|
public class RaceLogic implements RunnableWithFramePeriod, Observer {
|
||||||
/**
|
/**
|
||||||
* State of current race modified by this object
|
* State of current race modified by this object
|
||||||
*/
|
*/
|
||||||
@@ -32,6 +37,8 @@ public class RaceLogic implements RunnableWithFramePeriod {
|
|||||||
this.race = race;
|
this.race = race;
|
||||||
this.server = new RaceServer(race, messages);
|
this.server = new RaceServer(race, messages);
|
||||||
this.commands = compositeCommand;
|
this.commands = compositeCommand;
|
||||||
|
|
||||||
|
race.getColliderRegistry().addObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -116,7 +123,7 @@ public class RaceLogic implements RunnableWithFramePeriod {
|
|||||||
//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) {
|
||||||
race.updatePosition(boat, framePeriod, race.getRaceClock().getDurationMilli());
|
race.updatePosition(boat, framePeriod, race.getRaceClock().getDurationMilli());
|
||||||
|
race.getColliderRegistry().rayCast(boat);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -168,4 +175,14 @@ public class RaceLogic implements RunnableWithFramePeriod {
|
|||||||
public MockRace getRace() {
|
public MockRace getRace() {
|
||||||
return race;
|
return race;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(Observable o, Object arg) {
|
||||||
|
Collision e = (Collision)arg;
|
||||||
|
|
||||||
|
if(e.getBearing().degrees() == 0) System.out.println("Ahead");
|
||||||
|
else if(e.getBearing().degrees() < 90) System.out.println("Starboard");
|
||||||
|
else if(e.getBearing().degrees() > 270) System.out.println("Port");
|
||||||
|
else System.out.println("Behind");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,8 @@ package mock.model;
|
|||||||
|
|
||||||
import network.Messages.*;
|
import network.Messages.*;
|
||||||
import network.Messages.Enums.BoatLocationDeviceEnum;
|
import network.Messages.Enums.BoatLocationDeviceEnum;
|
||||||
import network.Utils.AC35UnitConverter;
|
|
||||||
import shared.model.Bearing;
|
import shared.model.Bearing;
|
||||||
import shared.model.CompoundMark;
|
import shared.model.CompoundMark;
|
||||||
import shared.model.Constants;
|
|
||||||
import shared.model.Mark;
|
import shared.model.Mark;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -30,7 +28,6 @@ public class RaceServer {
|
|||||||
this.latestMessages = latestMessages;
|
this.latestMessages = latestMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the race to create a snapshot, and places it in latestMessages.
|
* Parses the race to create a snapshot, and places it in latestMessages.
|
||||||
*/
|
*/
|
||||||
@@ -127,8 +124,8 @@ public class RaceServer {
|
|||||||
|
|
||||||
BoatLocation boatLocation = new BoatLocation(
|
BoatLocation boatLocation = new BoatLocation(
|
||||||
boat.getSourceID(),
|
boat.getSourceID(),
|
||||||
boat.getCurrentPosition().getLatitude(),
|
boat.getPosition().getLatitude(),
|
||||||
boat.getCurrentPosition().getLongitude(),
|
boat.getPosition().getLongitude(),
|
||||||
this.boatLocationSequenceNumber,
|
this.boatLocationSequenceNumber,
|
||||||
BoatLocationDeviceEnum.RacingYacht,
|
BoatLocationDeviceEnum.RacingYacht,
|
||||||
boat.getBearing(),
|
boat.getBearing(),
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package mock.model.collider;
|
||||||
|
|
||||||
|
import shared.model.Bearing;
|
||||||
|
import shared.model.Boat;
|
||||||
|
import shared.model.GPSCoordinate;
|
||||||
|
import shared.model.Locatable;
|
||||||
|
|
||||||
|
import java.util.Observable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for all objects sensitive to collision in a race.
|
||||||
|
*/
|
||||||
|
public abstract class Collider extends Observable implements Locatable {
|
||||||
|
/**
|
||||||
|
* Indicates whether a ray cast from a boat to a target collider is within the specified length.
|
||||||
|
* @param boat potentially colliding with target
|
||||||
|
* @param distance distance for valid collision
|
||||||
|
* @return whether or not a collision has occurred
|
||||||
|
*/
|
||||||
|
public boolean rayCast(Boat boat, double distance) {
|
||||||
|
double actualDistance = GPSCoordinate.calculateDistanceMeters(boat.getPosition(), this.getPosition());
|
||||||
|
// Compass direction of collider
|
||||||
|
Bearing absolute = Bearing.fromAzimuth(GPSCoordinate.calculateAzimuth(boat.getPosition(), this.getPosition()));
|
||||||
|
// Direction of collider from heading
|
||||||
|
Bearing relative = Bearing.fromDegrees(absolute.degrees() - boat.getBearing().degrees());
|
||||||
|
|
||||||
|
if(actualDistance <= distance) {
|
||||||
|
Collision collision = new Collision(relative, distance);
|
||||||
|
// Notify object of collision
|
||||||
|
onCollisionEnter(boat, collision);
|
||||||
|
// Notify observers of collision
|
||||||
|
notifyObservers(collision);
|
||||||
|
this.setChanged();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether a ray cast from a boat to a target collider triggers a collision. Distance is set by the object.
|
||||||
|
* @param boat potentially colliding with target
|
||||||
|
* @return whether or not a collision has occurred
|
||||||
|
*/
|
||||||
|
public abstract boolean rayCast(Boat boat);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a collision event
|
||||||
|
* @param collider Boat that is colliding
|
||||||
|
* @param e details of collision
|
||||||
|
*/
|
||||||
|
public abstract void onCollisionEnter(Boat collider, Collision e);
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package mock.model.collider;
|
||||||
|
|
||||||
|
import shared.model.Boat;
|
||||||
|
import shared.model.GPSCoordinate;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registry for all Collider objects in a MockRace. Wraps the Collider interface as part of a Composite Pattern.
|
||||||
|
*/
|
||||||
|
public class ColliderRegistry extends Collider implements Observer {
|
||||||
|
/**
|
||||||
|
* List of all registered Colliders
|
||||||
|
*/
|
||||||
|
private List<Collider> colliders;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor for ColliderRegistry
|
||||||
|
*/
|
||||||
|
public ColliderRegistry() {
|
||||||
|
this.colliders = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCollider(Collider collider) {
|
||||||
|
collider.addObserver(this);
|
||||||
|
colliders.add(collider);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAllColliders(Collection<? extends Collider> colliders) {
|
||||||
|
for(Collider collider: colliders) addCollider(collider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean rayCast(Boat boat) {
|
||||||
|
for(Collider collider: colliders) {
|
||||||
|
if(collider.rayCast(boat)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCollisionEnter(Boat collider, Collision e) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GPSCoordinate getPosition() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPosition(GPSCoordinate position) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fire onCollisionEnter when collision bubbles up from registered colliders.
|
||||||
|
* @param o object collided with
|
||||||
|
* @param arg parameters of the collision
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void update(Observable o, Object arg) {
|
||||||
|
Collision collision = (Collision)arg;
|
||||||
|
|
||||||
|
notifyObservers(collision);
|
||||||
|
this.setChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package mock.model.collider;
|
||||||
|
|
||||||
|
import shared.model.Bearing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data structure for holding collision details for ray casting and event handling.
|
||||||
|
*/
|
||||||
|
public class Collision {
|
||||||
|
/**
|
||||||
|
* Bearing from boat heading to target
|
||||||
|
*/
|
||||||
|
private Bearing bearing;
|
||||||
|
/**
|
||||||
|
* Distance from boat centre to target centre
|
||||||
|
*/
|
||||||
|
private double distance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for Collision structure
|
||||||
|
* @param bearing from boat heading to target
|
||||||
|
* @param distance from boat centre to target centre
|
||||||
|
*/
|
||||||
|
public Collision(Bearing bearing, double distance) {
|
||||||
|
this.bearing = bearing;
|
||||||
|
this.distance = distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bearing getBearing() {
|
||||||
|
return bearing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getDistance() {
|
||||||
|
return distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package network;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common source of ack numbers for all messages
|
||||||
|
*/
|
||||||
|
public class AckSequencer {
|
||||||
|
/**
|
||||||
|
* Generator for ack numbers
|
||||||
|
*/
|
||||||
|
private static AtomicInteger ackNum = new AtomicInteger(0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve next ack number
|
||||||
|
* @return next ack number
|
||||||
|
*/
|
||||||
|
public static int getNextAckNum() {
|
||||||
|
return ackNum.getAndIncrement();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,7 +39,7 @@ public class DecoderFactory {
|
|||||||
|
|
||||||
case RACESTARTSTATUS: return new RaceStartStatusDecoder();
|
case RACESTARTSTATUS: return new RaceStartStatusDecoder();
|
||||||
|
|
||||||
//case YACHTEVENTCODE: return new YachtEventCodeDecoder();//TODO
|
case YACHTEVENTCODE: return new YachtEventCodeDecoder();
|
||||||
|
|
||||||
//case YACHTACTIONCODE: return new YachtActionCodeDecoder();//TODO
|
//case YACHTACTIONCODE: return new YachtActionCodeDecoder();//TODO
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package network.MessageDecoders;
|
||||||
|
|
||||||
|
import network.Exceptions.InvalidMessageException;
|
||||||
|
import network.Messages.AC35Data;
|
||||||
|
import network.Messages.Enums.YachtEventEnum;
|
||||||
|
import network.Messages.YachtEvent;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import static network.Utils.ByteConverter.bytesToInt;
|
||||||
|
import static network.Utils.ByteConverter.bytesToLong;
|
||||||
|
import static network.Utils.ByteConverter.bytesToShort;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes {@link YachtEvent} messages.
|
||||||
|
*/
|
||||||
|
public class YachtEventCodeDecoder implements MessageDecoder {
|
||||||
|
private YachtEvent message;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AC35Data decode(byte[] encodedMessage) throws InvalidMessageException {
|
||||||
|
// Deserialise message
|
||||||
|
byte[] timestamp = Arrays.copyOfRange(encodedMessage, 1, 7);
|
||||||
|
byte[] ackNum = Arrays.copyOfRange(encodedMessage, 7, 9);
|
||||||
|
byte[] raceID = Arrays.copyOfRange(encodedMessage, 9, 13);
|
||||||
|
byte[] sourceID = Arrays.copyOfRange(encodedMessage, 13, 17);
|
||||||
|
byte[] incidentID = Arrays.copyOfRange(encodedMessage, 17, 21);
|
||||||
|
byte eventID = encodedMessage[21];
|
||||||
|
|
||||||
|
// Unpack bytes into YachtEvent
|
||||||
|
this.message = new YachtEvent(
|
||||||
|
bytesToLong(timestamp),
|
||||||
|
bytesToShort(ackNum),
|
||||||
|
bytesToInt(raceID),
|
||||||
|
bytesToInt(sourceID),
|
||||||
|
bytesToInt(incidentID),
|
||||||
|
YachtEventEnum.fromByte(eventID)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Return YachtEvent
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public YachtEvent getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,7 +39,7 @@ public class EncoderFactory {
|
|||||||
|
|
||||||
case RACESTARTSTATUS: return new RaceStartStatusEncoder();
|
case RACESTARTSTATUS: return new RaceStartStatusEncoder();
|
||||||
|
|
||||||
//case YACHTEVENTCODE: return new YachtEventCodeEncoder();//TODO
|
case YACHTEVENTCODE: return new YachtEventCodeEncoder();
|
||||||
|
|
||||||
//case YACHTACTIONCODE: return new YachtActionCodeEncoder();//TODO
|
//case YACHTACTIONCODE: return new YachtActionCodeEncoder();//TODO
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package network.MessageEncoders;
|
||||||
|
|
||||||
|
import network.Exceptions.InvalidMessageException;
|
||||||
|
import network.Messages.AC35Data;
|
||||||
|
import network.Messages.YachtEvent;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import static network.Utils.ByteConverter.intToBytes;
|
||||||
|
import static network.Utils.ByteConverter.longToBytes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes a {@link YachtEvent} message.
|
||||||
|
*/
|
||||||
|
public class YachtEventCodeEncoder implements MessageEncoder {
|
||||||
|
@Override
|
||||||
|
public byte[] encode(AC35Data message) throws InvalidMessageException {
|
||||||
|
// Downcast message
|
||||||
|
YachtEvent yachtEvent = (YachtEvent)message;
|
||||||
|
|
||||||
|
// Serialise message
|
||||||
|
byte messageVersion = 0b10;
|
||||||
|
byte[] timestamp = longToBytes(yachtEvent.getCurrentTime(), 6);
|
||||||
|
byte[] ackNum = intToBytes(yachtEvent.getAckNum(), 2);
|
||||||
|
byte[] raceID = intToBytes(yachtEvent.getRaceID());
|
||||||
|
byte[] sourceID = intToBytes(yachtEvent.getSourceID());
|
||||||
|
byte[] incidentID = intToBytes(yachtEvent.getIncidentID());
|
||||||
|
byte eventID = yachtEvent.getYachtEvent().getValue();
|
||||||
|
|
||||||
|
// Pack bytes into string
|
||||||
|
ByteBuffer yachtEventMessage = ByteBuffer.allocate(22);
|
||||||
|
yachtEventMessage.put(messageVersion);
|
||||||
|
yachtEventMessage.put(timestamp);
|
||||||
|
yachtEventMessage.put(ackNum);
|
||||||
|
yachtEventMessage.put(raceID);
|
||||||
|
yachtEventMessage.put(sourceID);
|
||||||
|
yachtEventMessage.put(incidentID);
|
||||||
|
yachtEventMessage.put(eventID);
|
||||||
|
|
||||||
|
// Return byte string
|
||||||
|
return yachtEventMessage.array();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package network.Messages.Enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Yacht event codes
|
||||||
|
*/
|
||||||
|
public enum YachtEventEnum {
|
||||||
|
NOT_AN_EVENT(-1),
|
||||||
|
COLLISION(1);
|
||||||
|
|
||||||
|
private byte value;
|
||||||
|
|
||||||
|
YachtEventEnum(int value) { this.value = (byte)value; }
|
||||||
|
|
||||||
|
public byte getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static YachtEventEnum fromByte(byte value) {
|
||||||
|
switch(value) {
|
||||||
|
case 1: return COLLISION;
|
||||||
|
default: return NOT_AN_EVENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package network.Messages;
|
||||||
|
|
||||||
|
import network.Messages.Enums.MessageType;
|
||||||
|
import network.Messages.Enums.YachtEventEnum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a Yacht Event Code message defined in the AC35 spec, with Event IDs amended for the purposes of
|
||||||
|
* a game.
|
||||||
|
*/
|
||||||
|
public class YachtEvent extends AC35Data {
|
||||||
|
private long currentTime;
|
||||||
|
private int ackNum;
|
||||||
|
private int raceID;
|
||||||
|
private int sourceID;
|
||||||
|
private int incidentID;
|
||||||
|
private YachtEventEnum yachtEvent;
|
||||||
|
|
||||||
|
public YachtEvent(long currentTime, int ackNum, int raceID, int sourceID, int incidentID, YachtEventEnum yachtEvent) {
|
||||||
|
super(MessageType.YACHTEVENTCODE);
|
||||||
|
this.currentTime = currentTime;
|
||||||
|
this.ackNum = ackNum;
|
||||||
|
this.raceID = raceID;
|
||||||
|
this.sourceID = sourceID;
|
||||||
|
this.incidentID = incidentID;
|
||||||
|
this.yachtEvent = yachtEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public YachtEventEnum getYachtEvent() {
|
||||||
|
return yachtEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSourceID() {
|
||||||
|
return sourceID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIncidentID() {
|
||||||
|
return incidentID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getCurrentTime() {
|
||||||
|
return currentTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAckNum() {
|
||||||
|
return ackNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRaceID() {
|
||||||
|
return raceID;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ package shared.model;
|
|||||||
|
|
||||||
|
|
||||||
import javafx.beans.property.*;
|
import javafx.beans.property.*;
|
||||||
|
import mock.model.collider.Collider;
|
||||||
|
import mock.model.collider.Collision;
|
||||||
import network.Messages.Enums.BoatStatusEnum;
|
import network.Messages.Enums.BoatStatusEnum;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -10,7 +12,7 @@ import java.time.ZonedDateTime;
|
|||||||
/**
|
/**
|
||||||
* Boat Model that is used to store information on the boats that are running in the race.
|
* Boat Model that is used to store information on the boats that are running in the race.
|
||||||
*/
|
*/
|
||||||
public class Boat {
|
public class Boat extends Collider {
|
||||||
/**
|
/**
|
||||||
* The name of the boat/team.
|
* The name of the boat/team.
|
||||||
*/
|
*/
|
||||||
@@ -30,7 +32,7 @@ public class Boat {
|
|||||||
/**
|
/**
|
||||||
* The current position of the boat.
|
* The current position of the boat.
|
||||||
*/
|
*/
|
||||||
private GPSCoordinate currentPosition;
|
private GPSCoordinate position;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The country or team abbreviation of the boat.
|
* The country or team abbreviation of the boat.
|
||||||
@@ -57,7 +59,7 @@ public class Boat {
|
|||||||
/**
|
/**
|
||||||
* The boat's position within the race (e.g., 5th).
|
* The boat's position within the race (e.g., 5th).
|
||||||
*/
|
*/
|
||||||
private StringProperty positionInRace = new SimpleStringProperty();
|
private StringProperty placing = new SimpleStringProperty();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,7 +109,7 @@ public class Boat {
|
|||||||
|
|
||||||
this.bearing = Bearing.fromDegrees(0d);
|
this.bearing = Bearing.fromDegrees(0d);
|
||||||
|
|
||||||
setCurrentPosition(new GPSCoordinate(0, 0));
|
setPosition(new GPSCoordinate(0, 0));
|
||||||
|
|
||||||
this.status = BoatStatusEnum.UNDEFINED;
|
this.status = BoatStatusEnum.UNDEFINED;
|
||||||
}
|
}
|
||||||
@@ -256,41 +258,32 @@ public class Boat {
|
|||||||
* Returns the position within the race the boat has (e.g., 5th).
|
* Returns the position within the race the boat has (e.g., 5th).
|
||||||
* @return The boat's position in race.
|
* @return The boat's position in race.
|
||||||
*/
|
*/
|
||||||
public StringProperty positionProperty() {
|
public StringProperty placingProperty() {
|
||||||
return positionInRace;
|
return placing;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the position within the race the boat has (e.g., 5th).
|
* Sets the position within the race the boat has (e.g., 5th).
|
||||||
* @param position The boat's position in race.
|
* @param position The boat's position in race.
|
||||||
*/
|
*/
|
||||||
public void setPosition(String position) {
|
public void setPlacing(String position) {
|
||||||
this.positionInRace.set(position);
|
this.placing.set(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the position within the race the boat has (e.g., 5th).
|
|
||||||
* @return The boat's position in race.
|
|
||||||
*/
|
|
||||||
public String getPosition() {
|
|
||||||
return this.positionInRace.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current position of the boat.
|
* Returns the current position of the boat.
|
||||||
* @return The current position of the boat.
|
* @return The current position of the boat.
|
||||||
*/
|
*/
|
||||||
public GPSCoordinate getCurrentPosition() {
|
public GPSCoordinate getPosition() {
|
||||||
return currentPosition;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the current position of the boat.
|
* Sets the current position of the boat.
|
||||||
* @param currentPosition The new position for the boat.
|
* @param position The new position for the boat.
|
||||||
*/
|
*/
|
||||||
public void setCurrentPosition(GPSCoordinate currentPosition) {
|
public void setPosition(GPSCoordinate position) {
|
||||||
this.currentPosition = currentPosition;
|
this.position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -399,4 +392,22 @@ public class Boat {
|
|||||||
this.timeAtLastMark = timeAtLastMark;
|
this.timeAtLastMark = timeAtLastMark;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void bounce(double repulsionRadius) {
|
||||||
|
Azimuth reverseAzimuth = Azimuth.fromDegrees(getBearing().degrees() - 180d);
|
||||||
|
setPosition(GPSCoordinate.calculateNewPosition(getPosition(), 2 * repulsionRadius, reverseAzimuth));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean rayCast(Boat boat) {
|
||||||
|
if(boat != this) {
|
||||||
|
return rayCast(boat, 100);
|
||||||
|
} else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCollisionEnter(Boat collider, Collision e) {
|
||||||
|
if(e.getBearing().degrees() > 270 || e.getBearing().degrees() < 90) {
|
||||||
|
collider.bounce(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package shared.model;
|
package shared.model;
|
||||||
|
|
||||||
|
|
||||||
import shared.enums.RoundingType;
|
import shared.enums.RoundingType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -117,7 +116,7 @@ public class CompoundMark {
|
|||||||
* @return The position of the second mark in the compound mark.
|
* @return The position of the second mark in the compound mark.
|
||||||
*/
|
*/
|
||||||
public GPSCoordinate getMark2Position() {
|
public GPSCoordinate getMark2Position() {
|
||||||
return mark2.getPosition();
|
return mark2 == null? mark1.getPosition() : mark2.getPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -135,13 +134,6 @@ public class CompoundMark {
|
|||||||
* @return The average coordinate of the compound mark.
|
* @return The average coordinate of the compound mark.
|
||||||
*/
|
*/
|
||||||
private GPSCoordinate calculateAverage() {
|
private GPSCoordinate calculateAverage() {
|
||||||
|
|
||||||
//If the compound mark only contains one mark, the average is simply the first mark's position.
|
|
||||||
if (this.mark2 == null) {
|
|
||||||
return this.getMark1Position();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Otherwise, calculate the average of both marks.
|
//Otherwise, calculate the average of both marks.
|
||||||
GPSCoordinate averageCoordinate = GPSCoordinate.calculateAverageCoordinate(this.getMark1Position(), this.getMark2Position());
|
GPSCoordinate averageCoordinate = GPSCoordinate.calculateAverageCoordinate(this.getMark1Position(), this.getMark2Position());
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package shared.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by cbt24 on 16/08/17.
|
||||||
|
*/
|
||||||
|
public interface Locatable {
|
||||||
|
GPSCoordinate getPosition();
|
||||||
|
void setPosition(GPSCoordinate position);
|
||||||
|
}
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
package shared.model;
|
package shared.model;
|
||||||
|
|
||||||
|
import mock.model.collider.Collider;
|
||||||
|
import mock.model.collider.Collision;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an individual mark.
|
* Represents an individual mark.
|
||||||
* Has a source ID, name, and position.
|
* Has a source ID, name, and position.
|
||||||
*/
|
*/
|
||||||
public class Mark {
|
public class Mark extends Collider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The source ID of the mark.
|
* The source ID of the mark.
|
||||||
@@ -21,6 +24,10 @@ public class Mark {
|
|||||||
*/
|
*/
|
||||||
private GPSCoordinate position;
|
private GPSCoordinate position;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repulsion radius of the mark
|
||||||
|
*/
|
||||||
|
private double repulsionRadius = 50;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a mark with a given source ID, name, and position.
|
* Constructs a mark with a given source ID, name, and position.
|
||||||
@@ -75,4 +82,14 @@ public class Mark {
|
|||||||
public void setPosition(GPSCoordinate position) {
|
public void setPosition(GPSCoordinate position) {
|
||||||
this.position = position;
|
this.position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean rayCast(Boat boat) {
|
||||||
|
return rayCast(boat, repulsionRadius);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCollisionEnter(Boat collider, Collision e) {
|
||||||
|
collider.bounce(repulsionRadius);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,108 +4,87 @@ import javafx.beans.property.IntegerProperty;
|
|||||||
import javafx.beans.property.Property;
|
import javafx.beans.property.Property;
|
||||||
import javafx.beans.property.SimpleIntegerProperty;
|
import javafx.beans.property.SimpleIntegerProperty;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
import mock.model.collider.ColliderRegistry;
|
||||||
import network.Messages.Enums.RaceStatusEnum;
|
import network.Messages.Enums.RaceStatusEnum;
|
||||||
import network.Messages.Enums.RaceTypeEnum;
|
import network.Messages.Enums.RaceTypeEnum;
|
||||||
import shared.dataInput.BoatDataSource;
|
import shared.dataInput.BoatDataSource;
|
||||||
import shared.dataInput.RaceDataSource;
|
import shared.dataInput.RaceDataSource;
|
||||||
import shared.dataInput.RegattaDataSource;
|
import shared.dataInput.RegattaDataSource;
|
||||||
import visualiser.model.VisualiserRaceEvent;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a yacht race.
|
* Represents a yacht race.
|
||||||
* This is a base class inherited by {@link mock.model.MockRace} and {@link VisualiserRaceEvent}.
|
|
||||||
* Has a course, state, wind, boundaries, etc.... Boats are added by inheriting classes (see {@link Boat}, {@link mock.model.MockBoat}, {@link visualiser.model.VisualiserBoat}.
|
* Has a course, state, wind, boundaries, etc.... Boats are added by inheriting classes (see {@link Boat}, {@link mock.model.MockBoat}, {@link visualiser.model.VisualiserBoat}.
|
||||||
*/
|
*/
|
||||||
public abstract class Race {
|
public abstract class Race {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The source of race related data.
|
* The source of race related data.
|
||||||
*/
|
*/
|
||||||
protected RaceDataSource raceDataSource;
|
protected RaceDataSource raceDataSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The source of boat related data.
|
* The source of boat related data.
|
||||||
*/
|
*/
|
||||||
protected BoatDataSource boatDataSource;
|
protected BoatDataSource boatDataSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The source of regatta related data.
|
* The source of regatta related data.
|
||||||
*/
|
*/
|
||||||
protected RegattaDataSource regattaDataSource;
|
protected RegattaDataSource regattaDataSource;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of compound marks in the race.
|
* A list of compound marks in the race.
|
||||||
*/
|
*/
|
||||||
protected List<CompoundMark> compoundMarks;
|
protected List<CompoundMark> compoundMarks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of legs in the race.
|
* A list of legs in the race.
|
||||||
*/
|
*/
|
||||||
protected List<Leg> legs;
|
protected List<Leg> legs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of coordinates describing the boundary of the course.
|
* A list of coordinates describing the boundary of the course.
|
||||||
*/
|
*/
|
||||||
protected List<GPSCoordinate> boundary;
|
protected List<GPSCoordinate> boundary;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The clock which tracks the race's start time, current time, and elapsed duration.
|
* The clock which tracks the race's start time, current time, and elapsed duration.
|
||||||
*/
|
*/
|
||||||
protected RaceClock raceClock;
|
protected RaceClock raceClock;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The race ID of the course.
|
* The race ID of the course.
|
||||||
*/
|
*/
|
||||||
protected int raceId;
|
protected int raceId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the regatta.
|
* The name of the regatta.
|
||||||
*/
|
*/
|
||||||
protected String regattaName;
|
protected String regattaName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current status of the race.
|
* The current status of the race.
|
||||||
*/
|
*/
|
||||||
protected RaceStatusEnum raceStatusEnum;
|
protected RaceStatusEnum raceStatusEnum;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of race this is.
|
* The type of race this is.
|
||||||
*/
|
*/
|
||||||
protected RaceTypeEnum raceType;
|
protected RaceTypeEnum raceType;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The race's wind.
|
* The race's wind.
|
||||||
*/
|
*/
|
||||||
protected Property<Wind> raceWind = new SimpleObjectProperty<>();
|
protected Property<Wind> raceWind = new SimpleObjectProperty<>();
|
||||||
|
/**
|
||||||
|
* Registry for all collider object in this race
|
||||||
|
*/
|
||||||
|
protected ColliderRegistry colliderRegistry;
|
||||||
/**
|
/**
|
||||||
* The number of frames per second.
|
* 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;
|
private int currentFps = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of frames per second we generated over the last 1 second period.
|
* The number of frames per second we generated over the last 1 second period.
|
||||||
*/
|
*/
|
||||||
private IntegerProperty lastFps = new SimpleIntegerProperty(0);
|
private IntegerProperty lastFps = new SimpleIntegerProperty(0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The time, in milliseconds, since we last reset our {@link #currentFps} counter.
|
* The time, in milliseconds, since we last reset our {@link #currentFps} counter.
|
||||||
*/
|
*/
|
||||||
private long lastFpsResetTime;
|
private long lastFpsResetTime;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a race object with a given BoatDataSource, RaceDataSource, and RegattaDataSource.
|
* Constructs a race object with a given BoatDataSource, RaceDataSource, and RegattaDataSource.
|
||||||
* @param boatDataSource Data source for boat related data (yachts and marker boats).
|
* @param boatDataSource Data source for boat related data (yachts and marker boats).
|
||||||
@@ -119,39 +98,36 @@ public abstract class Race {
|
|||||||
this.boatDataSource = boatDataSource;
|
this.boatDataSource = boatDataSource;
|
||||||
this.regattaDataSource = regattaDataSource;
|
this.regattaDataSource = regattaDataSource;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Marks.
|
//Marks.
|
||||||
this.compoundMarks = raceDataSource.getCompoundMarks();
|
this.compoundMarks = raceDataSource.getCompoundMarks();
|
||||||
|
|
||||||
//Boundaries.
|
//Boundaries.
|
||||||
this.boundary = raceDataSource.getBoundary();
|
this.boundary = raceDataSource.getBoundary();
|
||||||
|
|
||||||
|
|
||||||
//Legs.
|
//Legs.
|
||||||
this.useLegsList(raceDataSource.getLegs());
|
this.useLegsList(raceDataSource.getLegs());
|
||||||
|
|
||||||
|
|
||||||
//Race ID.
|
//Race ID.
|
||||||
this.raceId = raceDataSource.getRaceId();
|
this.raceId = raceDataSource.getRaceId();
|
||||||
|
|
||||||
//Regatta name.
|
//Regatta name.
|
||||||
this.regattaName = regattaDataSource.getRegattaName();
|
this.regattaName = regattaDataSource.getRegattaName();
|
||||||
|
|
||||||
//Race clock.
|
//Race clock.
|
||||||
this.raceClock = new RaceClock(this.raceDataSource.getStartDateTime());
|
this.raceClock = new RaceClock(this.raceDataSource.getStartDateTime());
|
||||||
|
|
||||||
//Race status.
|
//Race status.
|
||||||
this.setRaceStatusEnum(RaceStatusEnum.NOT_ACTIVE);
|
this.setRaceStatusEnum(RaceStatusEnum.NOT_ACTIVE);
|
||||||
//Race type.
|
//Race type.
|
||||||
this.raceType = raceDataSource.getRaceType();
|
this.raceType = raceDataSource.getRaceType();
|
||||||
|
|
||||||
//Wind.
|
//Wind.
|
||||||
this.setWind(Bearing.fromDegrees(0), 0);
|
this.setWind(Bearing.fromDegrees(0), 0);
|
||||||
|
// Set up colliders
|
||||||
|
this.colliderRegistry = new ColliderRegistry();
|
||||||
|
|
||||||
|
for(CompoundMark mark: compoundMarks) {
|
||||||
|
colliderRegistry.addCollider(mark.getMark1());
|
||||||
|
if(mark.getMark2() != null) colliderRegistry.addCollider(mark.getMark2());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ColliderRegistry getColliderRegistry() {
|
||||||
|
return colliderRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialise the boats in the race.
|
* Initialise the boats in the race.
|
||||||
@@ -159,7 +135,6 @@ public abstract class Race {
|
|||||||
*/
|
*/
|
||||||
protected abstract void initialiseBoats();
|
protected abstract void initialiseBoats();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the race to use a new list of legs, and adds a dummy "Finish" leg at the end.
|
* 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.
|
* @param legs The new list of legs to use.
|
||||||
@@ -191,10 +166,6 @@ public abstract class Race {
|
|||||||
return legID == lastLegID;
|
return legID == lastLegID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current race status.
|
* Returns the current race status.
|
||||||
* @return The current race status.
|
* @return The current race status.
|
||||||
@@ -211,7 +182,6 @@ public abstract class Race {
|
|||||||
this.raceStatusEnum = raceStatusEnum;
|
this.raceStatusEnum = raceStatusEnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the type of race this is.
|
* Returns the type of race this is.
|
||||||
* @return The type of race this is.
|
* @return The type of race this is.
|
||||||
@@ -228,13 +198,12 @@ public abstract class Race {
|
|||||||
return regattaName;
|
return regattaName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the race to have a specified wind bearing and speed.
|
* Updates the race to have a specified wind bearing and speed.
|
||||||
* @param windBearing New wind bearing.
|
* @param windBearing New wind bearing.
|
||||||
* @param windSpeedKnots New wind speed, in knots.
|
* @param windSpeedKnots New wind speed, in knots.
|
||||||
*/
|
*/
|
||||||
public void setWind(Bearing windBearing, double windSpeedKnots) {
|
protected void setWind(Bearing windBearing, double windSpeedKnots) {
|
||||||
Wind wind = new Wind(windBearing, windSpeedKnots);
|
Wind wind = new Wind(windBearing, windSpeedKnots);
|
||||||
setWind(wind);
|
setWind(wind);
|
||||||
}
|
}
|
||||||
@@ -243,11 +212,10 @@ public abstract class Race {
|
|||||||
* Updates the race to have a specified wind (bearing and speed).
|
* Updates the race to have a specified wind (bearing and speed).
|
||||||
* @param wind New wind.
|
* @param wind New wind.
|
||||||
*/
|
*/
|
||||||
public void setWind(Wind wind) {
|
protected void setWind(Wind wind) {
|
||||||
this.raceWind.setValue(wind);
|
this.raceWind.setValue(wind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the wind bearing.
|
* Returns the wind bearing.
|
||||||
* @return The wind bearing.
|
* @return The wind bearing.
|
||||||
@@ -265,14 +233,6 @@ public abstract class Race {
|
|||||||
return raceWind.getValue().getWindSpeed();
|
return raceWind.getValue().getWindSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the race's wind.
|
|
||||||
* @return The race's wind.
|
|
||||||
*/
|
|
||||||
public Property<Wind> windProperty() {
|
|
||||||
return raceWind;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the RaceClock for this race.
|
* Returns the RaceClock for this race.
|
||||||
* This is used to track the start time, current time, and elapsed duration of the race.
|
* This is used to track the start time, current time, and elapsed duration of the race.
|
||||||
@@ -282,7 +242,6 @@ public abstract class Race {
|
|||||||
return raceClock;
|
return raceClock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the RaceDataSource used for the race.
|
* Returns the RaceDataSource used for the race.
|
||||||
* @return The RaceDataSource used for the race.
|
* @return The RaceDataSource used for the race.
|
||||||
@@ -300,7 +259,6 @@ public abstract class Race {
|
|||||||
return legs.size() - 1;
|
return legs.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the race boundary.
|
* Returns the race boundary.
|
||||||
* @return The race boundary.
|
* @return The race boundary.
|
||||||
@@ -326,14 +284,6 @@ public abstract class Race {
|
|||||||
return legs;
|
return legs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of frames generated per second.
|
|
||||||
* @return Frames per second.
|
|
||||||
*/
|
|
||||||
public int getFps() {
|
|
||||||
return lastFps.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the fps property.
|
* Returns the fps property.
|
||||||
* @return The fps property.
|
* @return The fps property.
|
||||||
@@ -342,8 +292,6 @@ public abstract class Race {
|
|||||||
return lastFps;
|
return lastFps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increments the FPS counter, and adds timePeriod milliseconds to our FPS reset timer.
|
* Increments the FPS counter, and adds timePeriod milliseconds to our FPS reset timer.
|
||||||
* @param timePeriod Time, in milliseconds, to add to {@link #lastFpsResetTime}.
|
* @param timePeriod Time, in milliseconds, to add to {@link #lastFpsResetTime}.
|
||||||
|
|||||||
+2
-3
@@ -8,7 +8,6 @@ import shared.exceptions.MarkNotFoundException;
|
|||||||
import shared.model.GPSCoordinate;
|
import shared.model.GPSCoordinate;
|
||||||
import shared.model.Mark;
|
import shared.model.Mark;
|
||||||
import visualiser.model.VisualiserBoat;
|
import visualiser.model.VisualiserBoat;
|
||||||
import visualiser.model.VisualiserRaceEvent;
|
|
||||||
import visualiser.model.VisualiserRaceState;
|
import visualiser.model.VisualiserRaceState;
|
||||||
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -68,7 +67,7 @@ public class BoatLocationCommand implements Command {
|
|||||||
boatLocation.getLatitude(),
|
boatLocation.getLatitude(),
|
||||||
boatLocation.getLongitude());
|
boatLocation.getLongitude());
|
||||||
|
|
||||||
boat.setCurrentPosition(gpsCoordinate);
|
boat.setPosition(gpsCoordinate);
|
||||||
|
|
||||||
//Bearing.
|
//Bearing.
|
||||||
boat.setBearing(boatLocation.getHeading());
|
boat.setBearing(boatLocation.getHeading());
|
||||||
@@ -96,7 +95,7 @@ public class BoatLocationCommand implements Command {
|
|||||||
*/
|
*/
|
||||||
private void attemptAddTrackPoint(VisualiserBoat boat) {
|
private void attemptAddTrackPoint(VisualiserBoat boat) {
|
||||||
if (boat.getStatus() == BoatStatusEnum.RACING) {
|
if (boat.getStatus() == BoatStatusEnum.RACING) {
|
||||||
boat.addTrackPoint(boat.getCurrentPosition(), visualiserRace.getRaceClock().getCurrentTime());
|
boat.addTrackPoint(boat.getPosition(), visualiserRace.getRaceClock().getCurrentTime());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public class FinishController extends Controller {
|
|||||||
boatNameColumn.setCellValueFactory(cellData -> cellData.getValue().nameProperty());
|
boatNameColumn.setCellValueFactory(cellData -> cellData.getValue().nameProperty());
|
||||||
|
|
||||||
//Rank/position.
|
//Rank/position.
|
||||||
boatRankColumn.setCellValueFactory(cellData -> cellData.getValue().positionProperty());
|
boatRankColumn.setCellValueFactory(cellData -> cellData.getValue().placingProperty());
|
||||||
|
|
||||||
|
|
||||||
//Winner label.
|
//Winner label.
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import visualiser.gameController.ControllerClient;
|
|||||||
import visualiser.gameController.Keys.ControlKey;
|
import visualiser.gameController.Keys.ControlKey;
|
||||||
import visualiser.gameController.Keys.KeyFactory;
|
import visualiser.gameController.Keys.KeyFactory;
|
||||||
import visualiser.model.*;
|
import visualiser.model.*;
|
||||||
import visualiser.network.ServerConnection;
|
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
@@ -293,7 +292,7 @@ public class RaceController extends Controller {
|
|||||||
|
|
||||||
//Current place within race.
|
//Current place within race.
|
||||||
boatPlacingColumn.setCellValueFactory(
|
boatPlacingColumn.setCellValueFactory(
|
||||||
cellData -> cellData.getValue().positionProperty() );
|
cellData -> cellData.getValue().placingProperty() );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ public class ResizableRaceCanvas extends ResizableCanvas {
|
|||||||
boat.getName(),
|
boat.getName(),
|
||||||
boat.getCountry(),
|
boat.getCountry(),
|
||||||
boat.getCurrentSpeed(),
|
boat.getCurrentSpeed(),
|
||||||
this.map.convertGPS(boat.getCurrentPosition()),
|
this.map.convertGPS(boat.getPosition()),
|
||||||
boat.getTimeToNextMarkFormatted(this.visualiserRace.getVisualiserRaceState().getRaceClock().getCurrentTime()),
|
boat.getTimeToNextMarkFormatted(this.visualiserRace.getVisualiserRaceState().getRaceClock().getCurrentTime()),
|
||||||
boat.getTimeSinceLastMarkFormatted(this.visualiserRace.getVisualiserRaceState().getRaceClock().getCurrentTime()),
|
boat.getTimeSinceLastMarkFormatted(this.visualiserRace.getVisualiserRaceState().getRaceClock().getCurrentTime()),
|
||||||
Color.BLACK,
|
Color.BLACK,
|
||||||
@@ -349,7 +349,7 @@ public class ResizableRaceCanvas extends ResizableCanvas {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Convert position to graph coordinate.
|
//Convert position to graph coordinate.
|
||||||
GraphCoordinate pos = this.map.convertGPS(boat.getCurrentPosition());
|
GraphCoordinate pos = this.map.convertGPS(boat.getPosition());
|
||||||
|
|
||||||
//The x coordinates of each vertex of the boat.
|
//The x coordinates of each vertex of the boat.
|
||||||
double[] x = {
|
double[] x = {
|
||||||
@@ -385,7 +385,7 @@ public class ResizableRaceCanvas extends ResizableCanvas {
|
|||||||
private void drawClientBoat(VisualiserBoat boat) {
|
private void drawClientBoat(VisualiserBoat boat) {
|
||||||
|
|
||||||
//Convert position to graph coordinate.
|
//Convert position to graph coordinate.
|
||||||
GraphCoordinate pos = this.map.convertGPS(boat.getCurrentPosition());
|
GraphCoordinate pos = this.map.convertGPS(boat.getPosition());
|
||||||
|
|
||||||
//The x coordinates of each vertex of the boat.
|
//The x coordinates of each vertex of the boat.
|
||||||
double[] x = {
|
double[] x = {
|
||||||
@@ -421,7 +421,7 @@ public class ResizableRaceCanvas extends ResizableCanvas {
|
|||||||
private void drawWake(VisualiserBoat boat) {
|
private void drawWake(VisualiserBoat boat) {
|
||||||
|
|
||||||
//Calculate either end of wake line.
|
//Calculate either end of wake line.
|
||||||
GraphCoordinate wakeFrom = this.map.convertGPS(boat.getCurrentPosition());
|
GraphCoordinate wakeFrom = this.map.convertGPS(boat.getPosition());
|
||||||
GraphCoordinate wakeTo = this.map.convertGPS(boat.getWake());
|
GraphCoordinate wakeTo = this.map.convertGPS(boat.getWake());
|
||||||
|
|
||||||
double lineWidth = 4;
|
double lineWidth = 4;
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ public class VisualiserBoat extends Boat {
|
|||||||
|
|
||||||
|
|
||||||
//Calculate the new coordinate.
|
//Calculate the new coordinate.
|
||||||
GPSCoordinate wakeCoordinate = GPSCoordinate.calculateNewPosition(getCurrentPosition(), wakeDistanceMeters, reverseAzimuth);
|
GPSCoordinate wakeCoordinate = GPSCoordinate.calculateNewPosition(getPosition(), wakeDistanceMeters, reverseAzimuth);
|
||||||
|
|
||||||
return wakeCoordinate;
|
return wakeCoordinate;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package visualiser.model;
|
package visualiser.model;
|
||||||
|
|
||||||
|
|
||||||
import javafx.application.Platform;
|
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
@@ -249,10 +248,10 @@ public class VisualiserRaceState extends RaceState {
|
|||||||
|
|
||||||
if ((boat.getStatus() == BoatStatusEnum.DNF) || (boat.getStatus() == BoatStatusEnum.PRESTART) || (boat.getCurrentLeg().getLegNumber() < 0)) {
|
if ((boat.getStatus() == BoatStatusEnum.DNF) || (boat.getStatus() == BoatStatusEnum.PRESTART) || (boat.getCurrentLeg().getLegNumber() < 0)) {
|
||||||
|
|
||||||
boat.setPosition("-");
|
boat.setPlacing("-");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
boat.setPosition(Integer.toString(i + 1));
|
boat.setPlacing(Integer.toString(i + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,174 +1,35 @@
|
|||||||
package mock.model;
|
package mock.model;
|
||||||
|
|
||||||
import mock.dataInput.PolarParser;
|
|
||||||
import mock.exceptions.InvalidPolarFileException;
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import shared.model.Bearing;
|
import shared.model.Bearing;
|
||||||
import shared.model.CompoundMark;
|
|
||||||
import shared.model.GPSCoordinate;
|
import shared.model.GPSCoordinate;
|
||||||
import shared.model.Mark;
|
import shared.model.Mark;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
public class MockBoatTest {
|
public class MockBoatTest {
|
||||||
|
private MockBoat boat;
|
||||||
|
private Mark near;
|
||||||
|
private Mark far;
|
||||||
|
|
||||||
/**
|
|
||||||
* boat made for testing
|
|
||||||
*/
|
|
||||||
private MockBoat firstTestBoat;
|
|
||||||
|
|
||||||
private Mark markToTest;
|
|
||||||
private Mark markToTest2;
|
|
||||||
|
|
||||||
private GPSCoordinate highGPS;
|
|
||||||
private GPSCoordinate middleGPS;
|
|
||||||
private GPSCoordinate lowGPS;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the Polars object for the tests.
|
|
||||||
*/
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
//Read in polars.
|
boat = new MockBoat(0, "Bob", "NZ", null);
|
||||||
try {
|
boat.setPosition(new GPSCoordinate(0,0));
|
||||||
//Parse data file.
|
boat.setBearing(Bearing.fromDegrees(180));
|
||||||
Polars polars = PolarParser.parse("mock/polars/acc_polars.csv");
|
|
||||||
|
|
||||||
firstTestBoat = new MockBoat(1, "test", "NZ", polars);
|
near = new Mark(0, "Near", new GPSCoordinate(-.0001, 0));
|
||||||
highGPS = new GPSCoordinate(32.296577, -64.854000);
|
far = new Mark(0, "Far", new GPSCoordinate(.001, 0));
|
||||||
middleGPS = new GPSCoordinate(32.292500, -64.854000);
|
|
||||||
lowGPS = new GPSCoordinate(32.290000, -64.854000);
|
|
||||||
markToTest = new Mark(1, "test MARK", middleGPS);
|
|
||||||
markToTest2 = new Mark(2, "test MARK2", middleGPS);
|
|
||||||
}
|
|
||||||
catch (InvalidPolarFileException e) {
|
|
||||||
fail("Couldn't parse polar file.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////Mark Higher////////////////////////////////
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if the boat is lower than the mark that the port side method works if
|
|
||||||
* boat is facing east
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void testIsPortSide() {
|
public void nearMarkWithin100m() {
|
||||||
firstTestBoat.setBearing(Bearing.fromDegrees(90));
|
assertTrue(near.rayCast(boat, 100));
|
||||||
firstTestBoat.setCurrentPosition(lowGPS);
|
|
||||||
markToTest.setPosition(highGPS);
|
|
||||||
|
|
||||||
assertEquals(firstTestBoat.isPortSide(markToTest), true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if the boat is lower than the mark that the port side method works if
|
|
||||||
* boat is facing west
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void testIsPortSideWrong() {
|
public void farMarkBeyond100m() {
|
||||||
firstTestBoat.setBearing(Bearing.fromDegrees(270));
|
assertFalse(far.rayCast(boat, 100));
|
||||||
firstTestBoat.setCurrentPosition(lowGPS);
|
|
||||||
markToTest.setPosition(highGPS);
|
|
||||||
|
|
||||||
assertEquals(firstTestBoat.isPortSide(markToTest), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if the boat is lower than the mark that the starboard side method works if
|
|
||||||
* boat is facing east
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testIsStarboardSideWrong() {
|
|
||||||
firstTestBoat.setBearing(Bearing.fromDegrees(90));
|
|
||||||
firstTestBoat.setCurrentPosition(lowGPS);
|
|
||||||
markToTest.setPosition(highGPS);
|
|
||||||
|
|
||||||
assertEquals(firstTestBoat.isStarboardSide(markToTest), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if the boat is lower than the mark that the starboard side method works if
|
|
||||||
* boat is facing west
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testIsStarboardSide() {
|
|
||||||
firstTestBoat.setBearing(Bearing.fromDegrees(270));
|
|
||||||
firstTestBoat.setCurrentPosition(lowGPS);
|
|
||||||
markToTest.setPosition(highGPS);
|
|
||||||
|
|
||||||
assertEquals(firstTestBoat.isStarboardSide(markToTest), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////Mark Lower////////////////////////////////
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if the boat is higher than the mark that the port side method works if
|
|
||||||
* boat is facing east
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testIsPortSideHigherWrong() {
|
|
||||||
firstTestBoat.setBearing(Bearing.fromDegrees(90));
|
|
||||||
firstTestBoat.setCurrentPosition(highGPS);
|
|
||||||
markToTest.setPosition(lowGPS);
|
|
||||||
|
|
||||||
assertEquals(firstTestBoat.isPortSide(markToTest), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if the boat is higher than the mark that the port side method works if
|
|
||||||
* boat is facing west
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testIsPortSideHigher() {
|
|
||||||
firstTestBoat.setBearing(Bearing.fromDegrees(270));
|
|
||||||
firstTestBoat.setCurrentPosition(highGPS);
|
|
||||||
markToTest.setPosition(lowGPS);
|
|
||||||
|
|
||||||
assertEquals(firstTestBoat.isPortSide(markToTest), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if the boat is higher than the mark that the starboard side method works if
|
|
||||||
* boat is facing east
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testIsStarboardSideHigher() {
|
|
||||||
firstTestBoat.setBearing(Bearing.fromDegrees(90));
|
|
||||||
firstTestBoat.setCurrentPosition(highGPS);
|
|
||||||
markToTest.setPosition(lowGPS);
|
|
||||||
|
|
||||||
assertEquals(firstTestBoat.isStarboardSide(markToTest), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if the boat is higher than the mark that the starboard side method works if
|
|
||||||
* boat is facing west
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testIsStarboardSideHigherWrong() {
|
|
||||||
firstTestBoat.setBearing(Bearing.fromDegrees(270));
|
|
||||||
firstTestBoat.setCurrentPosition(highGPS);
|
|
||||||
markToTest.setPosition(lowGPS);
|
|
||||||
|
|
||||||
assertEquals(firstTestBoat.isStarboardSide(markToTest), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if a boat is between a gate
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testIsBetweenGate(){
|
|
||||||
markToTest.setPosition(highGPS);
|
|
||||||
markToTest2.setPosition(lowGPS);
|
|
||||||
CompoundMark testGate = new CompoundMark(1, "test GATE", markToTest, markToTest2);
|
|
||||||
|
|
||||||
firstTestBoat.setCurrentPosition(middleGPS);
|
|
||||||
|
|
||||||
assertEquals(firstTestBoat.isBetweenGate(testGate), true);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package network.MessageDecoders;
|
||||||
|
|
||||||
|
import network.MessageEncoders.RaceVisionByteEncoder;
|
||||||
|
import network.Messages.Enums.YachtEventEnum;
|
||||||
|
import network.Messages.YachtEvent;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.testng.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for the YachtEvent decoder and encoder
|
||||||
|
*/
|
||||||
|
public class YachtEventCodeDecoderTest {
|
||||||
|
private YachtEvent decodedMessage;
|
||||||
|
private YachtEvent originalMessage;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
long timestamp = System.currentTimeMillis();
|
||||||
|
|
||||||
|
originalMessage = new YachtEvent(
|
||||||
|
timestamp,
|
||||||
|
55,
|
||||||
|
35,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
YachtEventEnum.COLLISION
|
||||||
|
);
|
||||||
|
|
||||||
|
byte[] encodedMessage = RaceVisionByteEncoder.encode(originalMessage);
|
||||||
|
|
||||||
|
YachtEventCodeDecoder testDecoder = new YachtEventCodeDecoder();
|
||||||
|
testDecoder.decode(encodedMessage);
|
||||||
|
decodedMessage = testDecoder.getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void decodingEqualsOriginal() {
|
||||||
|
assertEquals(originalMessage.getCurrentTime(), decodedMessage.getCurrentTime());
|
||||||
|
assertEquals(originalMessage.getAckNum(), decodedMessage.getAckNum());
|
||||||
|
assertEquals(originalMessage.getRaceID(), decodedMessage.getRaceID());
|
||||||
|
assertEquals(originalMessage.getSourceID(), decodedMessage.getSourceID());
|
||||||
|
assertEquals(originalMessage.getIncidentID(), decodedMessage.getIncidentID());
|
||||||
|
assertEquals(originalMessage.getYachtEvent(), decodedMessage.getYachtEvent());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,7 +19,7 @@ public class BoatTest {
|
|||||||
public void setUp() {
|
public void setUp() {
|
||||||
ORIGIN_COORDS = new GPSCoordinate(0, 0);
|
ORIGIN_COORDS = new GPSCoordinate(0, 0);
|
||||||
TEST_BOAT = new Boat(1, "Test", "tt");
|
TEST_BOAT = new Boat(1, "Test", "tt");
|
||||||
TEST_BOAT.setCurrentPosition(ORIGIN_COORDS);
|
TEST_BOAT.setPosition(ORIGIN_COORDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO these bearing tests could be tidied up to reduce code repetition.
|
//TODO these bearing tests could be tidied up to reduce code repetition.
|
||||||
@@ -113,7 +113,7 @@ public class BoatTest {
|
|||||||
|
|
||||||
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(GPSCoordinate.calculateAzimuth(TEST_BOAT.getCurrentPosition(), endMarker.getAverageGPSCoordinate()).degrees(), 0, 1e-8);
|
assertEquals(GPSCoordinate.calculateAzimuth(TEST_BOAT.getPosition(), endMarker.getAverageGPSCoordinate()).degrees(), 0, 1e-8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ public class BoatTest {
|
|||||||
|
|
||||||
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(GPSCoordinate.calculateAzimuth(TEST_BOAT.getCurrentPosition(), endMarker.getAverageGPSCoordinate()).degrees(), 90, 1e-8);
|
assertEquals(GPSCoordinate.calculateAzimuth(TEST_BOAT.getPosition(), endMarker.getAverageGPSCoordinate()).degrees(), 90, 1e-8);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -148,7 +148,7 @@ public class BoatTest {
|
|||||||
|
|
||||||
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(GPSCoordinate.calculateAzimuth(TEST_BOAT.getCurrentPosition(), endMarker.getAverageGPSCoordinate()).degrees(), -180, 1e-8);
|
assertEquals(GPSCoordinate.calculateAzimuth(TEST_BOAT.getPosition(), endMarker.getAverageGPSCoordinate()).degrees(), -180, 1e-8);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -165,7 +165,7 @@ public class BoatTest {
|
|||||||
|
|
||||||
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(GPSCoordinate.calculateBearing(TEST_BOAT.getCurrentPosition(), endMarker.getAverageGPSCoordinate()).degrees(), 270, 1e-8);
|
assertEquals(GPSCoordinate.calculateBearing(TEST_BOAT.getPosition(), endMarker.getAverageGPSCoordinate()).degrees(), 270, 1e-8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user