diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
new file mode 100644
index 00000000..e7bedf33
--- /dev/null
+++ b/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/racevisionGame/src/main/java/mock/app/Event.java b/racevisionGame/src/main/java/mock/app/Event.java
index a588a754..427fdb6a 100644
--- a/racevisionGame/src/main/java/mock/app/Event.java
+++ b/racevisionGame/src/main/java/mock/app/Event.java
@@ -75,9 +75,6 @@ public class Event {
* @throws EventConstructionException Thrown if we cannot create an Event for any reason.
*/
public Event(boolean singlePlayer, int mapIndex) throws EventConstructionException {
-
-// System.out.println(XMLUtilities.validateXML(this.getClass().getClassLoader().getResource("mock/mockXML/iMapLayout.xml").toString()
-// , this.getClass().getClassLoader().getResource("mock/mockXML/schema/raceSchema.xsd")));
this.mapIndex = mapIndex;
String raceXMLFile;
String boatsXMLFile = "mock/mockXML/boatTest.xml";
diff --git a/racevisionGame/src/main/java/mock/model/MockBoat.java b/racevisionGame/src/main/java/mock/model/MockBoat.java
index b6cd7a24..a5dc98fe 100644
--- a/racevisionGame/src/main/java/mock/model/MockBoat.java
+++ b/racevisionGame/src/main/java/mock/model/MockBoat.java
@@ -34,7 +34,10 @@ public class MockBoat extends Boat {
*/
private boolean autoVMG = false;
-
+ /**
+ * Indicates whether boat velocity is determined by wind
+ */
+ private boolean velocityDefault = true;
/**
* Constructs a boat object with a given sourceID, name, country/team abbreviation, and polars table.
@@ -300,4 +303,12 @@ public class MockBoat extends Boat {
public void setAutoVMG(boolean autoVMG) {
this.autoVMG = autoVMG;
}
+
+ public boolean isVelocityDefault() {
+ return velocityDefault;
+ }
+
+ public void setVelocityDefault(boolean velocityDefault) {
+ this.velocityDefault = velocityDefault;
+ }
}
diff --git a/racevisionGame/src/main/java/mock/model/MockRace.java b/racevisionGame/src/main/java/mock/model/MockRace.java
index a9f11770..c9c5a144 100644
--- a/racevisionGame/src/main/java/mock/model/MockRace.java
+++ b/racevisionGame/src/main/java/mock/model/MockRace.java
@@ -1,5 +1,7 @@
package mock.model;
+import mock.model.commandFactory.ActiveObserverCommand;
+import mock.model.commandFactory.ObserverCommand;
import mock.model.wind.WindGenerator;
import javafx.animation.AnimationTimer;
import mock.model.collider.ColliderRegistry;
@@ -64,6 +66,8 @@ public class MockRace extends RaceState {
*/
private Polars polars;
+ private ActiveObserverCommand activeObserverCommand;
+
/**
@@ -81,6 +85,7 @@ public class MockRace extends RaceState {
this.setRaceDataSource(raceDataSource);
this.setRegattaDataSource(regattaDataSource);
+ this.activeObserverCommand = new ActiveObserverCommand();
this.polars = polars;
this.scaleFactor = timeScale;
@@ -355,70 +360,25 @@ public class MockRace extends RaceState {
//Checks if the current boat has finished the race or not.
boolean finish = this.isLastLeg(boat.getCurrentLeg());
- if (!finish && totalElapsedMilliseconds >= updatePeriodMilliseconds && boat.isSailsOut()) {
+ if (!finish && totalElapsedMilliseconds >= updatePeriodMilliseconds) {
checkPosition(boat, totalElapsedMilliseconds);
- if (boat.getCurrentSpeed() == 0) {
- newOptimalVMG(boat);
- boat.setBearing(boat.calculateBearingToNextMarker());
- }
-
- setBoatSpeed(boat);
+ if(boat.isVelocityDefault()) setBoatSpeed(boat);
//Calculates the distance travelled, in meters, in the current timeslice.
- double distanceTravelledMeters = boat.calculateMetersTravelled(updatePeriodMilliseconds);
-
- //Scale it.
- distanceTravelledMeters = distanceTravelledMeters * this.scaleFactor;
-
+ double distanceTravelledMeters = boat.calculateMetersTravelled(updatePeriodMilliseconds) * this.scaleFactor;
//Move the boat forwards that many meters, and advances its time counters by enough milliseconds.
boat.moveForwards(distanceTravelledMeters);
boat.setTimeSinceTackChange(boat.getTimeSinceTackChange() + updatePeriodMilliseconds);
-
- if (boat.getAutoVMG()) {
- newOptimalVMG(boat);
- boat.setAutoVMG(false);
- }
-
- } else {
- boat.setCurrentSpeed(0);
}
this.updateEstimatedTime(boat);
}
- private void newOptimalVMG(MockBoat boat) {
- long tackPeriod = 1000;
- if (boat.getTimeSinceTackChange() > tackPeriod) {
- //System.out.println("optim called");
- //Calculate the new VMG.
-// VMG newVMG = boat.getPolars().calculateVMG(
-// this.getWindDirection(),
-// this.getWindSpeed(),
-// boat.calculateBearingToNextMarker(),
-// Bearing.fromDegrees(0d),
-// Bearing.fromDegrees(359.99999d));
-
- VMG newVMG = NewPolars.setBestVMG(this.getWindDirection(), this.getWindSpeed(), boat.getBearing());
- //System.out.println(newVMG);
- //If the new vmg improves velocity, use it.
- /*if (improvesVelocity(boat, newVMG)) {
- }*/
- boat.setVMG(newVMG);
- }
- }
-
private void setBoatSpeed(MockBoat boat) {
-// VMG vmg = boat.getPolars().calculateVMG(
-// this.getWindDirection(),
-// this.getWindSpeed(),
-// boat.getBearing(),
-// Bearing.fromDegrees(boat.getBearing().degrees() - 1),
-// Bearing.fromDegrees(boat.getBearing().degrees() + 1));
- //VMG vmg = boat.getPolars().setBestVMG(this.getWindDirection(), this.getWindSpeed(), boat.getBearing());
VMG vmg = new VMG(NewPolars.calculateSpeed(
this.getWindDirection(),
this.getWindSpeed(),
@@ -754,4 +714,18 @@ public class MockRace extends RaceState {
}
+ /**
+ * Made public, so race logic can control it
+ */
+ public void setChanged() {
+ super.setChanged();
+ }
+
+ public void addVelocityCommand(ObserverCommand c) {
+ this.activeObserverCommand.changeVelocityCommand(this, c);
+ }
+
+ public void addAngularCommand(ObserverCommand c) {
+ this.activeObserverCommand.changeAngularCommand(this, c);
+ }
}
diff --git a/racevisionGame/src/main/java/mock/model/NewPolars.java b/racevisionGame/src/main/java/mock/model/NewPolars.java
index c525316c..3a40e0e2 100644
--- a/racevisionGame/src/main/java/mock/model/NewPolars.java
+++ b/racevisionGame/src/main/java/mock/model/NewPolars.java
@@ -145,8 +145,6 @@ public class NewPolars {
* @return the best vmg that the boat can change to
*/
public static VMG setBestVMG(Bearing trueWindAngle, double trueWindSpeed, Bearing boatAngle){
- //System.out.println("VMG AUTO CALLED");
- //speed
double closestSpeed = getClosest(trueWindSpeed, polars.keySet());
double angle = modulateAngle(boatAngle.degrees() - trueWindAngle.degrees());
@@ -181,15 +179,29 @@ public class NewPolars {
}
+ /**
+ * gets the angle bound between 0 and 360 following modular arithmetic
+ * @param angle angle to modulate
+ * @return resultant angle after modulation.
+ */
public static double modulateAngle(double angle){
return (angle % 360 + 360) % 360;
}
+ /**
+ * DO NOT DELETE THIS FUNCTIONS THEY ARE USED FOR TESTING PURPOSES
+ * @return current polars map
+ */
+ @SuppressWarnings("unused")
private Map> getPolars(){
//this function is just for testing so therefore it is private
return polars;
}
+ /**
+ * DO NOT DELETE THESE FUNCTIONS THEY ARE USED FOR TESTING PURPOSES
+ */
+ @SuppressWarnings("unused")
private void printOutLinearInterpolated(){
for (double tws: polars.keySet()){
System.out.println("==================================================");
diff --git a/racevisionGame/src/main/java/mock/model/RaceLogic.java b/racevisionGame/src/main/java/mock/model/RaceLogic.java
index d1ef39e0..3b74d5c8 100644
--- a/racevisionGame/src/main/java/mock/model/RaceLogic.java
+++ b/racevisionGame/src/main/java/mock/model/RaceLogic.java
@@ -2,6 +2,7 @@ package mock.model;
import javafx.animation.AnimationTimer;
import mock.model.collider.Collision;
+import mock.model.commandFactory.CollisionCommand;
import mock.model.commandFactory.Command;
import mock.model.commandFactory.CompositeCommand;
import mock.model.commandFactory.CommandFactory;
@@ -145,9 +146,13 @@ public class RaceLogic implements RunnableWithFramePeriod, Observer {
//Get the current time.
long currentTime = System.currentTimeMillis();
- //Execute commands from clients.
+ // Execute commands from clients.
commands.execute();
+ // Notify Observers
+ race.setChanged();
+ race.notifyObservers();
+
//Update race time.
race.updateRaceTime(currentTime);
@@ -218,11 +223,9 @@ public class RaceLogic implements RunnableWithFramePeriod, Observer {
@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");
+ if(arg instanceof Collision) {
+ Collision collision = (Collision)arg;
+ commands.addCommand(new CollisionCommand(race, (MockBoat)collision.getBoat()));
+ }
}
}
diff --git a/racevisionGame/src/main/java/mock/model/collider/Collider.java b/racevisionGame/src/main/java/mock/model/collider/Collider.java
index 029fee57..28c01f9f 100644
--- a/racevisionGame/src/main/java/mock/model/collider/Collider.java
+++ b/racevisionGame/src/main/java/mock/model/collider/Collider.java
@@ -25,13 +25,9 @@ public abstract class Collider extends Observable implements Locatable {
Bearing relative = Bearing.fromDegrees(absolute.degrees() - boat.getBearing().degrees());
if(actualDistance <= distance) {
- Collision collision = new Collision(relative, distance);
+ Collision collision = new Collision(boat, relative, distance);
// Notify object of collision
- onCollisionEnter(boat, collision);
- // Notify observers of collision
- notifyObservers(collision);
- this.setChanged();
-
+ onCollisionEnter(collision);
return true;
} else return false;
}
@@ -45,8 +41,7 @@ public abstract class Collider extends Observable implements Locatable {
/**
* Handle a collision event
- * @param collider Boat that is colliding
* @param e details of collision
*/
- public abstract void onCollisionEnter(Boat collider, Collision e);
+ public abstract void onCollisionEnter(Collision e);
}
diff --git a/racevisionGame/src/main/java/mock/model/collider/ColliderRegistry.java b/racevisionGame/src/main/java/mock/model/collider/ColliderRegistry.java
index 69eac91a..6f82daeb 100644
--- a/racevisionGame/src/main/java/mock/model/collider/ColliderRegistry.java
+++ b/racevisionGame/src/main/java/mock/model/collider/ColliderRegistry.java
@@ -1,5 +1,6 @@
package mock.model.collider;
+import mock.model.MockBoat;
import shared.model.Boat;
import shared.model.GPSCoordinate;
@@ -39,7 +40,7 @@ public class ColliderRegistry extends Collider implements Observer {
}
@Override
- public void onCollisionEnter(Boat collider, Collision e) {}
+ public void onCollisionEnter(Collision e) {}
@Override
public GPSCoordinate getPosition() {
@@ -60,7 +61,7 @@ public class ColliderRegistry extends Collider implements Observer {
public void update(Observable o, Object arg) {
Collision collision = (Collision)arg;
- notifyObservers(collision);
this.setChanged();
+ notifyObservers(collision);
}
}
diff --git a/racevisionGame/src/main/java/mock/model/collider/Collision.java b/racevisionGame/src/main/java/mock/model/collider/Collision.java
index 5a987bde..225cf342 100644
--- a/racevisionGame/src/main/java/mock/model/collider/Collision.java
+++ b/racevisionGame/src/main/java/mock/model/collider/Collision.java
@@ -1,6 +1,7 @@
package mock.model.collider;
import shared.model.Bearing;
+import shared.model.Boat;
/**
* Data structure for holding collision details for ray casting and event handling.
@@ -14,13 +15,19 @@ public class Collision {
* Distance from boat centre to target centre
*/
private double distance;
+ /**
+ * Boat involved in the collision
+ */
+ private Boat boat;
/**
* Constructor for Collision structure
+ * @param boat involved in collision
* @param bearing from boat heading to target
* @param distance from boat centre to target centre
*/
- public Collision(Bearing bearing, double distance) {
+ public Collision(Boat boat, Bearing bearing, double distance) {
+ this.boat = boat;
this.bearing = bearing;
this.distance = distance;
}
@@ -32,4 +39,8 @@ public class Collision {
public double getDistance() {
return distance;
}
+
+ public Boat getBoat() {
+ return boat;
+ }
}
diff --git a/racevisionGame/src/main/java/mock/model/commandFactory/ActiveObserverCommand.java b/racevisionGame/src/main/java/mock/model/commandFactory/ActiveObserverCommand.java
new file mode 100644
index 00000000..ccd69a20
--- /dev/null
+++ b/racevisionGame/src/main/java/mock/model/commandFactory/ActiveObserverCommand.java
@@ -0,0 +1,27 @@
+package mock.model.commandFactory;
+
+import java.util.Observable;
+
+/**
+ * Used to track the current active observer command. This is to ensure two commands that do similar things do not overlap.
+ */
+public class ActiveObserverCommand {
+ private ObserverCommand currentVelocityCommand;
+ private ObserverCommand currentAngularCommand;
+
+ public ActiveObserverCommand() {
+
+ }
+
+ public void changeVelocityCommand(Observable o, ObserverCommand c) {
+ o.deleteObserver(currentVelocityCommand);
+ o.addObserver(c);
+ currentVelocityCommand = c;
+ }
+
+ public void changeAngularCommand(Observable o, ObserverCommand c) {
+ o.deleteObserver(currentAngularCommand);
+ o.addObserver(c);
+ currentAngularCommand = c;
+ }
+}
diff --git a/racevisionGame/src/main/java/mock/model/commandFactory/CollisionCommand.java b/racevisionGame/src/main/java/mock/model/commandFactory/CollisionCommand.java
new file mode 100644
index 00000000..b2fed2ac
--- /dev/null
+++ b/racevisionGame/src/main/java/mock/model/commandFactory/CollisionCommand.java
@@ -0,0 +1,44 @@
+package mock.model.commandFactory;
+
+import mock.model.MockBoat;
+import mock.model.MockRace;
+import shared.model.Azimuth;
+import shared.model.GPSCoordinate;
+
+import java.util.Observable;
+
+/**
+ * Command class for collisions
+ */
+public class CollisionCommand extends ObserverCommand {
+ private GPSCoordinate startingPosition;
+ private Azimuth azimuth;
+ private double distance;
+
+ /**
+ * Constructor for class
+ * @param race race context
+ * @param boat boat controlled by command
+ */
+ public CollisionCommand(MockRace race, MockBoat boat) {
+ super(race, boat);
+ }
+
+ @Override
+ public void execute() {
+ this.azimuth = Azimuth.fromDegrees(boat.getBearing().degrees() - 180d);
+ this.startingPosition = boat.getPosition();
+ this.distance = 30;
+ boat.setVelocityDefault(false);
+ }
+
+ @Override
+ public void update(Observable o, Object arg) {
+ if(GPSCoordinate.calculateDistanceMeters(boat.getPosition(), startingPosition) < distance) {
+ boat.setPosition(GPSCoordinate.calculateNewPosition(boat.getPosition(), 2, azimuth));
+ } else {
+ race.deleteObserver(this);
+ boat.setVelocityDefault(true);
+ }
+ }
+}
diff --git a/racevisionGame/src/main/java/mock/model/commandFactory/Command.java b/racevisionGame/src/main/java/mock/model/commandFactory/Command.java
index e0486114..421d5b32 100644
--- a/racevisionGame/src/main/java/mock/model/commandFactory/Command.java
+++ b/racevisionGame/src/main/java/mock/model/commandFactory/Command.java
@@ -3,6 +3,8 @@ package mock.model.commandFactory;
import mock.model.MockBoat;
import mock.model.MockRace;
+import java.util.Observer;
+
/**
* Allows RaceLogic to control MockRace state according to the Command pattern
*/
diff --git a/racevisionGame/src/main/java/mock/model/commandFactory/ObserverCommand.java b/racevisionGame/src/main/java/mock/model/commandFactory/ObserverCommand.java
new file mode 100644
index 00000000..987d24be
--- /dev/null
+++ b/racevisionGame/src/main/java/mock/model/commandFactory/ObserverCommand.java
@@ -0,0 +1,20 @@
+package mock.model.commandFactory;
+
+import mock.model.MockBoat;
+import mock.model.MockRace;
+
+import java.util.Observer;
+
+/**
+ * Command that can observe the race
+ */
+public abstract class ObserverCommand implements Command, Observer {
+ MockRace race;
+ MockBoat boat;
+
+ public ObserverCommand(MockRace race, MockBoat boat) {
+ this.race = race;
+ this.boat = boat;
+ boat.setAutoVMG(false);
+ }
+}
diff --git a/racevisionGame/src/main/java/mock/model/commandFactory/SailsCommand.java b/racevisionGame/src/main/java/mock/model/commandFactory/SailsCommand.java
index 7d620a42..ac4877c4 100644
--- a/racevisionGame/src/main/java/mock/model/commandFactory/SailsCommand.java
+++ b/racevisionGame/src/main/java/mock/model/commandFactory/SailsCommand.java
@@ -2,20 +2,50 @@ package mock.model.commandFactory;
import mock.model.MockBoat;
import mock.model.MockRace;
+import mock.model.NewPolars;
+import mock.model.VMG;
-public class SailsCommand implements Command {
- private MockRace race;
- private MockBoat boat;
+import java.util.Observable;
+
+public class SailsCommand extends ObserverCommand {
private boolean sailsOut;
+ private double goalVelocity;
- public SailsCommand(MockRace race, MockBoat boat, Boolean sailsOut) {
- this.race = race;
- this.boat = boat;
+ public SailsCommand(MockRace race, MockBoat boat, boolean sailsOut) {
+ super(race, boat);
+ race.addVelocityCommand(this);
this.sailsOut = sailsOut;
}
@Override
public void execute() {
this.boat.setSailsOut(this.sailsOut);
+ boat.setVelocityDefault(false);
+
+ if(sailsOut) {
+ // Accelerate to VMG speed
+ double polarSpeed = NewPolars.calculateSpeed(race.getWindDirection(), race.getWindSpeed(), boat.getBearing());
+ VMG vmg = new VMG(polarSpeed, boat.getBearing());
+ goalVelocity = vmg.getSpeed();
+ } else {
+ // Decelerate to 0
+ goalVelocity = 0;
+ }
+ }
+
+ @Override
+ public void update(Observable o, Object arg) {
+ double acceleration = 0.5;
+
+ if(sailsOut && boat.getCurrentSpeed() < goalVelocity) {
+ boat.setCurrentSpeed(Math.min(goalVelocity, boat.getCurrentSpeed() + acceleration));
+ } else if (!sailsOut && boat.getCurrentSpeed() > goalVelocity) {
+ // Apply deceleration to strictly 0 speed
+ boat.setCurrentSpeed(Math.max(0, boat.getCurrentSpeed() - acceleration));
+ } else {
+ // Release boat from SailsCommand control
+ if(sailsOut) boat.setVelocityDefault(true);
+ race.deleteObserver(this);
+ }
}
}
diff --git a/racevisionGame/src/main/java/mock/model/commandFactory/TackGybeCommand.java b/racevisionGame/src/main/java/mock/model/commandFactory/TackGybeCommand.java
index d0b0584b..e10ee74a 100644
--- a/racevisionGame/src/main/java/mock/model/commandFactory/TackGybeCommand.java
+++ b/racevisionGame/src/main/java/mock/model/commandFactory/TackGybeCommand.java
@@ -4,12 +4,16 @@ import mock.model.MockBoat;
import mock.model.MockRace;
import shared.model.Bearing;
+import java.util.Observable;
+
/**
* Command class for tacking and gybing
*/
-public class TackGybeCommand implements Command {
- private MockRace race;
- private MockBoat boat;
+public class TackGybeCommand extends ObserverCommand {
+ private double goalRotation;
+ private double totalRotation = 0;
+ private int direction; // -1 for anticlockwise, 1 for clockwise
+ private double goalAngle;
/**
* Constructor for class
@@ -17,24 +21,32 @@ public class TackGybeCommand implements Command {
* @param boat mock boat to update
*/
public TackGybeCommand(MockRace race, MockBoat boat) {
- this.race = race;
- this.boat = boat;
+ super(race, boat);
+ race.addAngularCommand(this);
}
@Override
public void execute() {
-
- boat.setAutoVMG(false);
-
double boatAngle = boat.getBearing().degrees();
- double windAngle =race.getWindDirection().degrees();
+ double windAngle = race.getWindDirection().degrees();
double differenceAngle = calcDistance(boatAngle, windAngle);
double angleA = windAngle + differenceAngle;
double angleB = windAngle - differenceAngle;
- if(angleA % 360 == boatAngle){
- boat.setBearing(Bearing.fromDegrees(angleB));
+ if (angleA % 360 == boatAngle) {
+ goalAngle = angleB % 360;
} else {
- boat.setBearing(Bearing.fromDegrees(angleA));
+ goalAngle = angleA % 360;
+ }
+
+ goalRotation = goalAngle - boatAngle;
+ if (goalRotation < 0) {
+ goalRotation += 360;
+ }
+ if (goalRotation > 180) {
+ goalRotation = 360 - goalRotation;
+ direction = -1;
+ } else {
+ direction = 1;
}
}
@@ -49,5 +61,16 @@ public class TackGybeCommand implements Command {
return phi > 180 ? 360 - phi : phi;
}
+ @Override
+ public void update(Observable o, Object arg) {
+ double offset = 3.0;
+ if (totalRotation < goalRotation) {
+ boat.setBearing(Bearing.fromDegrees(boat.getBearing().degrees() + offset * direction));
+ totalRotation += offset;
+ } else {
+ boat.setBearing(Bearing.fromDegrees(goalAngle));
+ race.deleteObserver(this);
+ }
+ }
}
diff --git a/racevisionGame/src/main/java/mock/model/commandFactory/VMGCommand.java b/racevisionGame/src/main/java/mock/model/commandFactory/VMGCommand.java
index 39469cf8..812f833a 100644
--- a/racevisionGame/src/main/java/mock/model/commandFactory/VMGCommand.java
+++ b/racevisionGame/src/main/java/mock/model/commandFactory/VMGCommand.java
@@ -2,13 +2,20 @@ package mock.model.commandFactory;
import mock.model.MockBoat;
import mock.model.MockRace;
+import mock.model.NewPolars;
+import mock.model.VMG;
+import shared.model.Bearing;
+
+import java.util.Observable;
/**
* Command class for autoVMG
*/
-public class VMGCommand implements Command {
- private MockRace race;
- private MockBoat boat;
+public class VMGCommand extends ObserverCommand {
+ private double goalAngle;
+ private double goalRotation;
+ private double totalRotation = 0;
+ private int direction;
/**
* Constructor for class
@@ -16,8 +23,8 @@ public class VMGCommand implements Command {
* @param boat mock boat to update
*/
public VMGCommand(MockRace race, MockBoat boat) {
- this.race = race;
- this.boat = boat;
+ super(race, boat);
+ race.addAngularCommand(this);
}
@Override
@@ -27,5 +34,37 @@ public class VMGCommand implements Command {
} else {
boat.setAutoVMG(true);
}
+ newOptimalVMG(boat);
+
+ goalRotation = goalAngle - boat.getBearing().degrees();
+ if (goalRotation < 0) {
+ goalRotation += 360;
+ }
+ if (goalRotation > 180) {
+ goalRotation = 360 - goalRotation;
+ direction = -1;
+ } else {
+ direction = 1;
+ }
+ }
+
+ private void newOptimalVMG(MockBoat boat) {
+ long tackPeriod = 1000;
+ if (boat.getTimeSinceTackChange() > tackPeriod) {
+ VMG newVMG = NewPolars.setBestVMG(race.getWindDirection(), race.getWindSpeed(), boat.getBearing());
+ goalAngle = newVMG.getBearing().degrees();
+ }
+ }
+
+ @Override
+ public void update(Observable o, Object arg) {
+ double offset = 3.0;
+ if (totalRotation < goalRotation) {
+ boat.setBearing(Bearing.fromDegrees(boat.getBearing().degrees() + offset * direction));
+ totalRotation += offset;
+ } else {
+ boat.setBearing(Bearing.fromDegrees(goalAngle));
+ race.deleteObserver(this);
+ }
}
}
diff --git a/racevisionGame/src/main/java/mock/model/commandFactory/WindCommand.java b/racevisionGame/src/main/java/mock/model/commandFactory/WindCommand.java
index 530bf5bc..85eec091 100644
--- a/racevisionGame/src/main/java/mock/model/commandFactory/WindCommand.java
+++ b/racevisionGame/src/main/java/mock/model/commandFactory/WindCommand.java
@@ -4,17 +4,23 @@ import mock.model.MockBoat;
import mock.model.MockRace;
import shared.model.Bearing;
+import java.util.Observable;
+
/**
- * Created by connortaylorbrown on 4/08/17.
+ * Command class for upwind and downwind controls
*/
-public class WindCommand implements Command {
- private MockRace race;
- private MockBoat boat;
+public class WindCommand extends ObserverCommand {
private int direction;
+ /**
+ * Constructor for class
+ * @param race race context
+ * @param boat boat controlled by command
+ * @param upwind if true, downwind if false
+ */
public WindCommand(MockRace race, MockBoat boat, boolean upwind) {
- this.race = race;
- this.boat = boat;
+ super(race, boat);
+ race.addAngularCommand(this);
this.direction = upwind? -1 : 1;
}
@@ -34,4 +40,9 @@ public class WindCommand implements Command {
boat.setBearing(Bearing.fromDegrees(heading + offset));
}
+
+ @Override
+ public void update(Observable o, Object arg) {
+ race.deleteObserver(this);
+ }
}
diff --git a/racevisionGame/src/main/java/mock/model/wind/ShiftingWindGenerator.java b/racevisionGame/src/main/java/mock/model/wind/ShiftingWindGenerator.java
index 4ceff627..3cbf14f2 100644
--- a/racevisionGame/src/main/java/mock/model/wind/ShiftingWindGenerator.java
+++ b/racevisionGame/src/main/java/mock/model/wind/ShiftingWindGenerator.java
@@ -105,7 +105,6 @@ public class ShiftingWindGenerator implements WindGenerator {
if (shiftedSoFar >= 180){
shiftAnticlockwise = Math.random() > 0.5;
shiftedSoFar = 0;
-// System.out.println("Swapping");
}
timeOfLastShift = System.currentTimeMillis();
diff --git a/racevisionGame/src/main/java/network/PacketDump/AC35DumpReader.java b/racevisionGame/src/main/java/network/PacketDump/AC35DumpReader.java
index 8022c374..1277e62b 100644
--- a/racevisionGame/src/main/java/network/PacketDump/AC35DumpReader.java
+++ b/racevisionGame/src/main/java/network/PacketDump/AC35DumpReader.java
@@ -41,7 +41,6 @@ public class AC35DumpReader {
messLen[1] = dump[pointer + 13];
messLen[0] = dump[pointer + 14];
int messageLength = ByteBuffer.wrap(messLen).getShort();
- //System.out.println(messageLength);
packets.add(new AC35Packet(Arrays.copyOfRange(dump, pointer, pointer + messageLength + 19)));
diff --git a/racevisionGame/src/main/java/shared/model/Boat.java b/racevisionGame/src/main/java/shared/model/Boat.java
index 31ce7ad4..bd3eea5e 100644
--- a/racevisionGame/src/main/java/shared/model/Boat.java
+++ b/racevisionGame/src/main/java/shared/model/Boat.java
@@ -403,10 +403,6 @@ public class Boat extends Collider {
public boolean isSailsOut() {
return sailsOut;
}
- 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) {
@@ -416,9 +412,11 @@ public class Boat extends Collider {
}
@Override
- public void onCollisionEnter(Boat collider, Collision e) {
+ public void onCollisionEnter(Collision e) {
if(e.getBearing().degrees() > 270 || e.getBearing().degrees() < 90) {
- collider.bounce(100);
+ // Notify observers of collision
+ this.setChanged();
+ notifyObservers(e);
}
}
}
diff --git a/racevisionGame/src/main/java/shared/model/Constants.java b/racevisionGame/src/main/java/shared/model/Constants.java
index 7a5e2820..81e0d81b 100644
--- a/racevisionGame/src/main/java/shared/model/Constants.java
+++ b/racevisionGame/src/main/java/shared/model/Constants.java
@@ -5,7 +5,6 @@ package shared.model;
* Created by Erika on 19-Mar-17.
*/
public class Constants {
-
/**
* Multiply by this factor to convert nautical miles to meters.
*
@@ -15,8 +14,6 @@ public class Constants {
*/
public static final int NMToMetersConversion = 1852;
-
-
/**
* Multiply by this factor to convert Knots to millimeters per second.
*
@@ -26,8 +23,6 @@ public class Constants {
*/
public static final double KnotsToMMPerSecond = 514.444;
-
-
/**
* The scale factor of the race.
* Frame periods are multiplied by this to get the amount of time a single frame represents.
@@ -36,23 +31,15 @@ public class Constants {
public static final int RaceTimeScale = 2;//10;
/**
- * The race pre-start time, in milliseconds. 3 minutes (30 seconds for development).
+ * The race pre-start time, in milliseconds. 3 minutes.
*/
-// public static final long RacePreStartTime = 30 * 1000;
- public static final long RacePreStartTime = 1000;
-
+ public static final long RacePreStartTime = 3 * 60 * 1000;
/**
* The race preparatory time, in milliseconds. 1 minute.
*/
-// public static final long RacePreparatoryTime = 60 * 1000;
public static final long RacePreparatoryTime = 1 * 60 * 1000;
-
-
-
-
-
/**
* The number of milliseconds in one hour.
*
@@ -70,7 +57,4 @@ public class Constants {
* Divide by this factor to convert hours to seconds.
*/
public static long OneHourSeconds = 1 * 60 * 60;
-
-
-
}
diff --git a/racevisionGame/src/main/java/shared/model/Mark.java b/racevisionGame/src/main/java/shared/model/Mark.java
index d236d076..23778cff 100644
--- a/racevisionGame/src/main/java/shared/model/Mark.java
+++ b/racevisionGame/src/main/java/shared/model/Mark.java
@@ -101,7 +101,8 @@ public class Mark extends Collider{
}
@Override
- public void onCollisionEnter(Boat collider, Collision e) {
- collider.bounce(repulsionRadius);
+ public void onCollisionEnter(Collision e) {
+ this.setChanged();
+ notifyObservers(e);
}
}
diff --git a/racevisionGame/src/main/java/shared/model/RaceState.java b/racevisionGame/src/main/java/shared/model/RaceState.java
index 48361da2..e755ba80 100644
--- a/racevisionGame/src/main/java/shared/model/RaceState.java
+++ b/racevisionGame/src/main/java/shared/model/RaceState.java
@@ -13,6 +13,7 @@ import shared.dataInput.RegattaDataSource;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
+import java.util.Observable;
/**
@@ -20,7 +21,7 @@ import java.util.List;
* This is a base class inherited by {@link mock.model.MockRace} and {@link visualiser.model.VisualiserRaceState}.
* 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 RaceState {
+public abstract class RaceState extends Observable{
diff --git a/racevisionGame/src/main/java/visualiser/gameController/InputChecker.java b/racevisionGame/src/main/java/visualiser/gameController/InputChecker.java
index 88cdcb74..86166dcf 100644
--- a/racevisionGame/src/main/java/visualiser/gameController/InputChecker.java
+++ b/racevisionGame/src/main/java/visualiser/gameController/InputChecker.java
@@ -27,7 +27,6 @@ public class InputChecker {
ControlKey controlKey = keyFactory.getKey(codeString);
if (controlKey != null) {
controlKey.onAction();
-// System.out.println(controlKey.toString() + " is Pressed.");
}
currentlyActiveKeys.put(codeString, true);
}
@@ -38,7 +37,6 @@ public class InputChecker {
ControlKey controlKey = keyFactory.getKey(codeString);
if (controlKey != null) {
controlKey.onRelease();
-// System.out.println(controlKey.toString() + " is Released.");
}
currentlyActiveKeys.remove(event.getCode().toString());
});
@@ -50,15 +48,8 @@ public class InputChecker {
ControlKey controlKey = keyFactory.getKey(key);
if (controlKey != null){
controlKey.onHold();
-// System.out.println(controlKey.toString() + " is Held.");
}
}
-// for (String key : InputKeys.stringKeysMap.keySet()){
-// if (removeActiveKey(key)) {
-// System.out.println(key);
-// }
-// }
-
}
}.start();
}
diff --git a/racevisionGame/src/test/java/shared/model/BearingTest.java b/racevisionGame/src/test/java/shared/model/BearingTest.java
deleted file mode 100644
index 876a0deb..00000000
--- a/racevisionGame/src/test/java/shared/model/BearingTest.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package shared.model;
-
-public class BearingTest {
-//TODO
-}