diff --git a/racevisionGame/src/main/java/mock/app/Event.java b/racevisionGame/src/main/java/mock/app/Event.java index 6b6ff4b4..602aed43 100644 --- a/racevisionGame/src/main/java/mock/app/Event.java +++ b/racevisionGame/src/main/java/mock/app/Event.java @@ -116,14 +116,17 @@ public class Event { //Read XML files. try { - //this.raceXML = RaceXMLCreator.alterRaceToWind(raceXMLFile, 90); - this.raceXML = Event.setRaceXMLAtCurrentTimeToNow(XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8)); + if(mapIndex==4){ - //this.raceXML = Event.setRaceXMLAtCurrentTimeToNow(XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8), 1000, 5000); - this.raceXML = RaceXMLCreator.alterRaceToWind(this.raceXML, XMLFileType.Contents, -1, true); + //This is the tutorial map. + this.raceXML = Event.setRaceXMLAtCurrentTimeToNow(XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8), 1000, 5000); + this.raceXML = RaceXMLCreator.alterRaceToWind(this.raceXML, XMLFileType.Contents, -1); + } else { - this.raceXML = RaceXMLCreator.alterRaceToWind(this.raceXML, XMLFileType.Contents, windAngle, false); + this.raceXML = Event.setRaceXMLAtCurrentTimeToNow(XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8)); + this.raceXML = RaceXMLCreator.alterRaceToWind(this.raceXML, XMLFileType.Contents, windAngle); this.raceXML = RaceXMLCreator.scaleRaceSize(raceXML, windSpeed, 15 * 60 * 1000); + } this.boatXML = XMLReader.readXMLFileToString(boatsXMLFile, StandardCharsets.UTF_8); @@ -219,16 +222,13 @@ public class Event { } public static String setRaceXMLAtCurrentTimeToNow(String raceXML, long racePreStartTime, long racePreparatoryTime){ - //The start time is current time + 4 minutes. prestart is 3 minutes, and we add another minute. - - long millisecondsToAdd = racePreStartTime + racePreparatoryTime; - long secondsToAdd = millisecondsToAdd / 1000; + long minutesToAdd = 10; DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ"); ZonedDateTime creationTime = ZonedDateTime.now(); raceXML = raceXML.replace("RACE_CREATION_TIME", dateFormat.format(creationTime)); - raceXML = raceXML.replace("RACE_START_TIME", dateFormat.format(creationTime.plusSeconds(secondsToAdd))); + raceXML = raceXML.replace("RACE_START_TIME", dateFormat.format(creationTime.plusMinutes(minutesToAdd))); return raceXML; } diff --git a/racevisionGame/src/main/java/mock/model/MockRace.java b/racevisionGame/src/main/java/mock/model/MockRace.java index 2ae5dc7c..26c63e9b 100644 --- a/racevisionGame/src/main/java/mock/model/MockRace.java +++ b/racevisionGame/src/main/java/mock/model/MockRace.java @@ -67,6 +67,11 @@ public class MockRace extends RaceState { private long racePreparatoryTime = Constants.RacePreparatoryTime; + /** + * True if the race has been manually started, false otherwise. + */ + private boolean hasBeenStarted = false; + /** * Constructs a race object with a given RaceDataSource, BoatDataSource, and RegattaDataSource and sends events to the given mockOutput. * @param boatDataSource Data source for boat related data (yachts and marker boats). @@ -157,6 +162,23 @@ public class MockRace extends RaceState { } + /** + * Delays the start of the race, if needed, to ensure that the race doesn't start until host wants it to. + * If the time until start is less that 5 minutes, it is extended to 10 minutes. + */ + public void delayRaceStart() { + long timeToStart = getRaceDataSource().getStartDateTime().toInstant().toEpochMilli() - System.currentTimeMillis(); + + long fiveMinutesMilli = 5 * 60 * 1000; + long tenMinutesMilli = 10 * 60 * 1000; + + if ((timeToStart < fiveMinutesMilli) && (timeToStart > 0) && !hasBeenStarted) { + startRace(tenMinutesMilli, false); + } + + } + + /** * Updates the race status enumeration based on the current time. */ @@ -165,7 +187,6 @@ public class MockRace extends RaceState { //The millisecond duration of the race. Negative means it hasn't started, so we flip sign. long timeToStart = - this.getRaceClock().getDurationMilli(); - if (timeToStart > racePreStartTime) { //Time > 3 minutes is the prestart period. this.setRaceStatusEnum(RaceStatusEnum.PRESTART); @@ -203,9 +224,16 @@ public class MockRace extends RaceState { /** * Starts the race in #timeToStartMilli milliseconds. * @param timeToStartMilli Millseconds before starting the race. + * @param manualStart True if the race has been manually started, false otherwise. */ - public void startRace(long timeToStartMilli) { - //TODO + public void startRace(long timeToStartMilli, boolean manualStart) { + this.hasBeenStarted = manualStart; + ZonedDateTime startTime = ZonedDateTime.now().plus(timeToStartMilli, ChronoUnit.MILLIS); + + getRaceDataSource().setStartDateTime(startTime); + getRaceDataSource().incrementSequenceNumber(); + + this.getRaceClock().setStartingTime(getRaceDataSource().getStartDateTime()); } /** diff --git a/racevisionGame/src/main/java/mock/model/RaceLogic.java b/racevisionGame/src/main/java/mock/model/RaceLogic.java index 0110716e..8814733a 100644 --- a/racevisionGame/src/main/java/mock/model/RaceLogic.java +++ b/racevisionGame/src/main/java/mock/model/RaceLogic.java @@ -81,6 +81,8 @@ public class RaceLogic implements RunnableWithFramePeriod, Observer { //Update race time. race.updateRaceTime(currentTime); + race.delayRaceStart(); + //Update the race status based on the current time. race.updateRaceStatusEnum(); diff --git a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java index 2c15e57f..af520a83 100644 --- a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java +++ b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java @@ -56,13 +56,12 @@ public class RaceXMLCreator { * Rotates the race in a specified direction. * @param s xml file name or contents. * @param fileType Whether s is a file name or contents. - * @param degrees degrees to rotate - * @param tutorial Whether we wish to run the tutorial - this changes the race start time. + * @param degrees degrees to rotate. -1 means don't rotate. * @return the new xml file as a string * @throws XMLReaderException if the xml is not readable * @throws InvalidRaceDataException if the race is invalid */ - public static String alterRaceToWind(String s, XMLFileType fileType, double degrees, boolean tutorial) throws XMLReaderException, InvalidRaceDataException { + public static String alterRaceToWind(String s, XMLFileType fileType, double degrees) throws XMLReaderException, InvalidRaceDataException { RaceXMLReader reader = new RaceXMLReader(s, fileType); @@ -73,11 +72,6 @@ public class RaceXMLCreator { RaceXMLCreator.class.getClassLoader().getResource("mock/mockXML/schema/raceSchema.xsd"), XMLRace.class); - if(tutorial){ - setRaceXMLAtCurrentTimeToNow(race, 1000l, 5000l); - } else { - setRaceXMLAtCurrentTimeToNow(race); - } CompoundMark leewardGate = getLeewardGate(reader); diff --git a/racevisionGame/src/main/java/shared/dataInput/EmptyRaceDataSource.java b/racevisionGame/src/main/java/shared/dataInput/EmptyRaceDataSource.java index e395e51f..3df46076 100644 --- a/racevisionGame/src/main/java/shared/dataInput/EmptyRaceDataSource.java +++ b/racevisionGame/src/main/java/shared/dataInput/EmptyRaceDataSource.java @@ -151,4 +151,9 @@ public class EmptyRaceDataSource implements RaceDataSource { public void incrementSequenceNumber() { sequenceNumber++; } + + @Override + public void setStartDateTime(ZonedDateTime time) { + raceStartTime = time; + } } diff --git a/racevisionGame/src/main/java/shared/dataInput/RaceDataSource.java b/racevisionGame/src/main/java/shared/dataInput/RaceDataSource.java index 765098f2..3b933329 100644 --- a/racevisionGame/src/main/java/shared/dataInput/RaceDataSource.java +++ b/racevisionGame/src/main/java/shared/dataInput/RaceDataSource.java @@ -67,6 +67,12 @@ public interface RaceDataSource { */ ZonedDateTime getStartDateTime(); + /** + * Sets the start time/date of the race. + * @param time Time to start at. + */ + void setStartDateTime(ZonedDateTime time); + /** * Returns the creation time/date of the race xml file. * @return The race xml file's creation time. diff --git a/racevisionGame/src/main/java/shared/dataInput/RaceXMLReader.java b/racevisionGame/src/main/java/shared/dataInput/RaceXMLReader.java index af274a9c..0beac26d 100644 --- a/racevisionGame/src/main/java/shared/dataInput/RaceXMLReader.java +++ b/racevisionGame/src/main/java/shared/dataInput/RaceXMLReader.java @@ -507,4 +507,9 @@ public class RaceXMLReader extends XMLReader implements RaceDataSource { public void incrementSequenceNumber() { sequenceNumber++; } + + @Override + public void setStartDateTime(ZonedDateTime time) { + raceStartTime = time; + } } diff --git a/racevisionGame/src/main/java/visualiser/Controllers/InGameLobbyController.java b/racevisionGame/src/main/java/visualiser/Controllers/InGameLobbyController.java index d31cbddb..ace84f80 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/InGameLobbyController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/InGameLobbyController.java @@ -270,7 +270,6 @@ public class InGameLobbyController extends Controller { } - //If the race has reached the preparatory phase, or has started... if (raceStatus == RaceStatusEnum.PREPARATORY || raceStatus == RaceStatusEnum.STARTED) { //Stop this timer. @@ -360,7 +359,7 @@ public class InGameLobbyController extends Controller { * Start button pressed. Currently only prints out start */ public void startBtnPressed(){ - App.game.getRaceLogic().getRace().startRace(App.game.getRaceLogic().getRace().getRacePreparatoryTime()); + App.game.getRaceLogic().getRace().startRace(App.game.getRaceLogic().getRace().getRacePreparatoryTime(), true); } public void joinSpecPressed(){