From 2672c2b13b2a02ed3a0589bd76edbb7a24153c0e Mon Sep 17 00:00:00 2001 From: Connor Taylor-Brown Date: Thu, 3 Aug 2017 00:32:17 +1200 Subject: [PATCH] Separated RaceLogic from MockRace - MockRace satisfies refactor requirement for RaceState - VisualiserRace directly implements Runnable to remove method from MockRace #story[1094] --- .../src/main/java/mock/app/Event.java | 3 +- .../src/main/java/mock/model/MockRace.java | 163 +---------------- .../src/main/java/mock/model/RaceLogic.java | 172 +++++++++++++++++- .../src/main/java/shared/model/Race.java | 4 +- .../java/visualiser/model/VisualiserRace.java | 2 +- 5 files changed, 180 insertions(+), 164 deletions(-) diff --git a/racevisionGame/src/main/java/mock/app/Event.java b/racevisionGame/src/main/java/mock/app/Event.java index c94a691f..b4b0586c 100644 --- a/racevisionGame/src/main/java/mock/app/Event.java +++ b/racevisionGame/src/main/java/mock/app/Event.java @@ -3,6 +3,7 @@ package mock.app; import mock.dataInput.PolarParser; import mock.model.MockRace; import mock.model.Polars; +import mock.model.RaceLogic; import network.Messages.LatestMessages; import shared.dataInput.*; import shared.enums.XMLFileType; @@ -91,7 +92,7 @@ public class Event { RegattaDataSource regattaDataSource = new RegattaXMLReader(this.regattaXML, this.xmlFileType); //Create and start race. - MockRace newRace = new MockRace(boatDataSource, raceDataSource, regattaDataSource, this.latestMessages, this.boatPolars, Constants.RaceTimeScale); + RaceLogic newRace = new RaceLogic(new MockRace(boatDataSource, raceDataSource, regattaDataSource, this.latestMessages, this.boatPolars, Constants.RaceTimeScale), this.latestMessages); new Thread(newRace).start(); } diff --git a/racevisionGame/src/main/java/mock/model/MockRace.java b/racevisionGame/src/main/java/mock/model/MockRace.java index 08c56a2d..a32787d2 100644 --- a/racevisionGame/src/main/java/mock/model/MockRace.java +++ b/racevisionGame/src/main/java/mock/model/MockRace.java @@ -1,12 +1,7 @@ package mock.model; -import javafx.animation.AnimationTimer; -import network.Messages.BoatLocation; -import network.Messages.BoatStatus; import network.Messages.Enums.BoatStatusEnum; import network.Messages.LatestMessages; -import network.Messages.RaceStatus; -import network.Utils.AC35UnitConverter; import shared.dataInput.BoatDataSource; import shared.dataInput.RaceDataSource; import network.Messages.Enums.RaceStatusEnum; @@ -26,7 +21,6 @@ import static java.lang.Math.cos; * Is responsible for simulating the race, and sending messages to a MockOutput instance. */ public class MockRace extends Race { - private RaceServer server; /** * An observable list of boats in the race. @@ -82,8 +76,6 @@ public class MockRace extends Race { //Wind. this.setWind(windGenerator.generateBaselineWind()); - - this.server = new RaceServer(this, latestMessages); } /** @@ -115,20 +107,11 @@ public class MockRace extends Race { } - /** - * Runnable for the thread. - */ - public void run() { - initialiseBoats(); - this.countdownTimer.start(); - } - - /** * Updates the race time to a specified value, in milliseconds since the unix epoch. * @param currentTime Milliseconds since unix epoch. */ - private void updateRaceTime(long currentTime) { + public void updateRaceTime(long currentTime) { this.raceClock.setUTCTime(currentTime); } @@ -136,7 +119,7 @@ public class MockRace extends Race { /** * Updates the race status enumeration based on the current time. */ - private void updateRaceStatusEnum() { + public void updateRaceStatusEnum() { //The millisecond duration of the race. Negative means it hasn't started, so we flip sign. long timeToStart = - this.raceClock.getDurationMilli(); @@ -167,7 +150,7 @@ public class MockRace extends Race { /** * Sets the status of all boats in the race to RACING. */ - private void setBoatsStatusToRacing() { + public void setBoatsStatusToRacing() { for (MockBoat boat : this.boats) { boat.setStatus(BoatStatusEnum.RACING); @@ -179,7 +162,7 @@ public class MockRace extends Race { * Sets the estimated time at next mark for each boat to a specified time. This is used during the countdown timer to provide this value to boat before the race starts. * @param time The time to provide to each boat. */ - private void setBoatsTimeNextMark(ZonedDateTime time) { + public void setBoatsTimeNextMark(ZonedDateTime time) { for (MockBoat boat : this.boats) { boat.setEstimatedTimeAtNextMark(time); @@ -187,144 +170,6 @@ public class MockRace extends Race { } - /** - * Countdown timer until race starts. - */ - protected AnimationTimer countdownTimer = new AnimationTimer() { - - - long currentTime = System.currentTimeMillis(); - - @Override - public void handle(long arg0) { - - //Update race time. - updateRaceTime(currentTime); - - //Update the race status based on the current time. - updateRaceStatusEnum(); - - //Provide boat's with an estimated time at next mark until the race starts. - setBoatsTimeNextMark(raceClock.getCurrentTime()); - - //Parse the boat locations. - server.parseBoatLocations(); - - //Parse the marks. - server.parseMarks(); - - // Change wind direction - changeWindDirection(); - - //Parse the race status. - server.parseRaceStatus(); - - - if (getRaceStatusEnum() == RaceStatusEnum.STARTED) { - setBoatsStatusToRacing(); - raceTimer.start(); - this.stop(); - } - - //Update the animations timer's time. - currentTime = System.currentTimeMillis(); - } - }; - - - /** - * Timer that runs for the duration of the race, until all boats finish. - */ - private AnimationTimer raceTimer = new AnimationTimer() { - - /** - * Start time of loop, in milliseconds. - */ - long timeRaceStarted = System.currentTimeMillis(); - - /** - * Current time during a loop iteration. - */ - long currentTime = System.currentTimeMillis(); - - /** - * The time of the previous frame, in milliseconds. - */ - long lastFrameTime = timeRaceStarted; - - @Override - public void handle(long arg0) { - - //Get the current time. - currentTime = System.currentTimeMillis(); - - //Update race time. - updateRaceTime(currentTime); - - - //As long as there is at least one boat racing, we still simulate the race. - if (getNumberOfActiveBoats() != 0) { - - //Get the time period of this frame. - long framePeriod = currentTime - lastFrameTime; - - //For each boat, we update its position, and generate a BoatLocationMessage. - for (MockBoat boat : boats) { - - //If it is still racing, update its position. - if (boat.getStatus() == BoatStatusEnum.RACING) { - - updatePosition(boat, framePeriod, raceClock.getDurationMilli()); - - } - - } - - } else { - //Otherwise, the race is over! - raceFinished.start(); - setRaceStatusEnum(RaceStatusEnum.FINISHED); - this.stop(); - } - - if (getNumberOfActiveBoats() != 0) { - // Change wind direction - changeWindDirection(); - - //Parse the boat locations. - server.parseBoatLocations(); - - //Parse the marks. - server.parseMarks(); - - //Parse the race status. - server.parseRaceStatus(); - - - //Update the last frame time. - this.lastFrameTime = currentTime; - } - } - }; - - /** - * Broadcast that the race has finished. - */ - protected AnimationTimer raceFinished = new AnimationTimer(){ - int iters = 0; - @Override - public void handle(long now) { - - server.parseRaceStatus(); - - if (iters > 500) { - stop(); - } - iters++; - } - }; - - /** * Initialise the boats in the race. * This sets their starting positions and current legs. diff --git a/racevisionGame/src/main/java/mock/model/RaceLogic.java b/racevisionGame/src/main/java/mock/model/RaceLogic.java index b8e904a6..73b38c0d 100644 --- a/racevisionGame/src/main/java/mock/model/RaceLogic.java +++ b/racevisionGame/src/main/java/mock/model/RaceLogic.java @@ -1,4 +1,174 @@ package mock.model; -public class RaceLogic { +import javafx.animation.AnimationTimer; +import network.Messages.Enums.BoatStatusEnum; +import network.Messages.Enums.RaceStatusEnum; +import network.Messages.LatestMessages; + +public class RaceLogic implements Runnable { + /** + * State of current race modified by this object + */ + private MockRace race; + /** + * High-level interface to AC35 protocol server + */ + private RaceServer server; + + /** + * Initialises race loop with state and server message queue + * @param race state of race to modify + * @param messages to send to server + */ + public RaceLogic(MockRace race, LatestMessages messages) { + this.race = race; + this.server = new RaceServer(race, messages); + } + + /** + * Initialise boats and start countdown timer + */ + @Override + public void run() { + race.initialiseBoats(); + this.countdownTimer.start(); + } + + + /** + * Countdown timer until race starts. + */ + protected AnimationTimer countdownTimer = new AnimationTimer() { + + + long currentTime = System.currentTimeMillis(); + + @Override + public void handle(long arg0) { + + //Update race time. + race.updateRaceTime(currentTime); + + //Update the race status based on the current time. + race.updateRaceStatusEnum(); + + //Provide boat's with an estimated time at next mark until the race starts. + race.setBoatsTimeNextMark(race.getRaceClock().getCurrentTime()); + + //Parse the boat locations. + server.parseBoatLocations(); + + //Parse the marks. + server.parseMarks(); + + // Change wind direction + race.changeWindDirection(); + + //Parse the race status. + server.parseRaceStatus(); + + + if (race.getRaceStatusEnum() == RaceStatusEnum.STARTED) { + race.setBoatsStatusToRacing(); + raceTimer.start(); + this.stop(); + } + + //Update the animations timer's time. + currentTime = System.currentTimeMillis(); + } + }; + + + /** + * Timer that runs for the duration of the race, until all boats finish. + */ + private AnimationTimer raceTimer = new AnimationTimer() { + + /** + * Start time of loop, in milliseconds. + */ + long timeRaceStarted = System.currentTimeMillis(); + + /** + * Current time during a loop iteration. + */ + long currentTime = System.currentTimeMillis(); + + /** + * The time of the previous frame, in milliseconds. + */ + long lastFrameTime = timeRaceStarted; + + @Override + public void handle(long arg0) { + + //Get the current time. + currentTime = System.currentTimeMillis(); + + //Update race time. + race.updateRaceTime(currentTime); + + + //As long as there is at least one boat racing, we still simulate the race. + if (race.getNumberOfActiveBoats() != 0) { + + //Get the time period of this frame. + long framePeriod = currentTime - lastFrameTime; + + //For each boat, we update its position, and generate a BoatLocationMessage. + for (MockBoat boat : race.getBoats()) { + + //If it is still racing, update its position. + if (boat.getStatus() == BoatStatusEnum.RACING) { + + race.updatePosition(boat, framePeriod, race.getRaceClock().getDurationMilli()); + + } + + } + + } else { + //Otherwise, the race is over! + raceFinished.start(); + race.setRaceStatusEnum(RaceStatusEnum.FINISHED); + this.stop(); + } + + if (race.getNumberOfActiveBoats() != 0) { + // Change wind direction + race.changeWindDirection(); + + //Parse the boat locations. + server.parseBoatLocations(); + + //Parse the marks. + server.parseMarks(); + + //Parse the race status. + server.parseRaceStatus(); + + + //Update the last frame time. + this.lastFrameTime = currentTime; + } + } + }; + + /** + * Broadcast that the race has finished. + */ + protected AnimationTimer raceFinished = new AnimationTimer(){ + int iters = 0; + @Override + public void handle(long now) { + + server.parseRaceStatus(); + + if (iters > 500) { + stop(); + } + iters++; + } + }; } diff --git a/racevisionGame/src/main/java/shared/model/Race.java b/racevisionGame/src/main/java/shared/model/Race.java index 040e0d19..f9fc984e 100644 --- a/racevisionGame/src/main/java/shared/model/Race.java +++ b/racevisionGame/src/main/java/shared/model/Race.java @@ -19,7 +19,7 @@ import java.util.List; * This is a base class inherited by {@link mock.model.MockRace} and {@link visualiser.model.VisualiserRace}. * 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 implements Runnable { +public abstract class Race { /** @@ -214,7 +214,7 @@ public abstract class Race implements Runnable { * Sets the current race status. * @param raceStatusEnum The new status of the race. */ - protected void setRaceStatusEnum(RaceStatusEnum raceStatusEnum) { + public void setRaceStatusEnum(RaceStatusEnum raceStatusEnum) { this.raceStatusEnum = raceStatusEnum; } diff --git a/racevisionGame/src/main/java/visualiser/model/VisualiserRace.java b/racevisionGame/src/main/java/visualiser/model/VisualiserRace.java index 976a4b6e..2969fbb8 100644 --- a/racevisionGame/src/main/java/visualiser/model/VisualiserRace.java +++ b/racevisionGame/src/main/java/visualiser/model/VisualiserRace.java @@ -27,7 +27,7 @@ import java.util.Map; * Has a course, boats, boundaries, etc... * Observes LatestMessages and updates its state based on new messages. */ -public class VisualiserRace extends Race { +public class VisualiserRace extends Race implements Runnable { /**