From ec82e65ae79fa030bf9f6d91e1086c6386b4f084 Mon Sep 17 00:00:00 2001 From: fjc40 Date: Fri, 8 Sep 2017 13:45:36 +1200 Subject: [PATCH 1/9] Fixed javadocs in xml creation classes. --- .../main/java/shared/xml/XMLUtilities.java | 8 +++---- .../java/shared/xml/boats/BoatConfig.java | 14 +++++------ .../java/shared/xml/boats/ObjectFactory.java | 8 +++---- .../shared/xml/regatta/RegattaConfig.java | 24 +++++++++---------- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/racevisionGame/src/main/java/shared/xml/XMLUtilities.java b/racevisionGame/src/main/java/shared/xml/XMLUtilities.java index 0a50f77d..6106f1ff 100644 --- a/racevisionGame/src/main/java/shared/xml/XMLUtilities.java +++ b/racevisionGame/src/main/java/shared/xml/XMLUtilities.java @@ -63,10 +63,10 @@ public class XMLUtilities { * @param c The XML class to convert to. * @param The XML class to convert to. * @return The XML class object. - * @throws ParserConfigurationException - * @throws IOException - * @throws SAXException - * @throws JAXBException + * @throws ParserConfigurationException Thrown if input cannot be converted to class. + * @throws IOException Thrown if input cannot be converted to class. + * @throws SAXException Thrown if input cannot be converted to class. + * @throws JAXBException Thrown if input cannot be converted to class. */ public static T xmlToClass(InputStream i, URL schemaURL, Class c) throws ParserConfigurationException, IOException, SAXException, JAXBException { DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); diff --git a/racevisionGame/src/main/java/shared/xml/boats/BoatConfig.java b/racevisionGame/src/main/java/shared/xml/boats/BoatConfig.java index c0361b52..e3d309fc 100644 --- a/racevisionGame/src/main/java/shared/xml/boats/BoatConfig.java +++ b/racevisionGame/src/main/java/shared/xml/boats/BoatConfig.java @@ -184,7 +184,7 @@ public class BoatConfig { * Objects of the following type(s) are allowed in the list * {@link BoatConfig.Boats.Boat } * - * + * @return List of Boat entries. */ public List getBoat() { if (boat == null) { @@ -327,7 +327,7 @@ public class BoatConfig { /** * Gets the value of the sourceID property. - * + * @return source id. */ public int getSourceID() { return sourceID; @@ -335,7 +335,7 @@ public class BoatConfig { /** * Sets the value of the sourceID property. - * + * @param value new source id. */ public void setSourceID(int value) { this.sourceID = value; @@ -494,7 +494,7 @@ public class BoatConfig { /** * Gets the value of the y property. - * + * @return Y value. */ public double getY() { return y; @@ -502,7 +502,7 @@ public class BoatConfig { /** * Sets the value of the y property. - * + * @param value new y value. */ public void setY(double value) { this.y = value; @@ -510,7 +510,7 @@ public class BoatConfig { /** * Gets the value of the z property. - * + * @return z value. */ public double getZ() { return z; @@ -518,7 +518,7 @@ public class BoatConfig { /** * Sets the value of the z property. - * + * @param value new z value. */ public void setZ(double value) { this.z = value; diff --git a/racevisionGame/src/main/java/shared/xml/boats/ObjectFactory.java b/racevisionGame/src/main/java/shared/xml/boats/ObjectFactory.java index 0319de9a..ed3dbfb2 100644 --- a/racevisionGame/src/main/java/shared/xml/boats/ObjectFactory.java +++ b/racevisionGame/src/main/java/shared/xml/boats/ObjectFactory.java @@ -38,7 +38,7 @@ public class ObjectFactory { /** * Create an instance of {@link BoatConfig } - * + * @return BoatConfig. */ public BoatConfig createBoatConfig() { return new BoatConfig(); @@ -46,7 +46,7 @@ public class ObjectFactory { /** * Create an instance of {@link BoatConfig.Boats } - * + * @return Boats. */ public BoatConfig.Boats createBoatConfigBoats() { return new BoatConfig.Boats(); @@ -54,7 +54,7 @@ public class ObjectFactory { /** * Create an instance of {@link BoatConfig.Boats.Boat } - * + * @return Boat. */ public BoatConfig.Boats.Boat createBoatConfigBoatsBoat() { return new BoatConfig.Boats.Boat(); @@ -62,7 +62,7 @@ public class ObjectFactory { /** * Create an instance of {@link BoatConfig.Boats.Boat.GPSposition } - * + * @return GPSposition. */ public BoatConfig.Boats.Boat.GPSposition createBoatConfigBoatsBoatGPSposition() { return new BoatConfig.Boats.Boat.GPSposition(); diff --git a/racevisionGame/src/main/java/shared/xml/regatta/RegattaConfig.java b/racevisionGame/src/main/java/shared/xml/regatta/RegattaConfig.java index d8cc1613..eebee2ae 100644 --- a/racevisionGame/src/main/java/shared/xml/regatta/RegattaConfig.java +++ b/racevisionGame/src/main/java/shared/xml/regatta/RegattaConfig.java @@ -74,7 +74,7 @@ public class RegattaConfig { /** * Gets the value of the regattaID property. - * + * @return regatta id. */ public int getRegattaID() { return regattaID; @@ -82,7 +82,7 @@ public class RegattaConfig { /** * Sets the value of the regattaID property. - * + * @param value new regatta id. */ public void setRegattaID(int value) { this.regattaID = value; @@ -138,7 +138,7 @@ public class RegattaConfig { /** * Gets the value of the centralLatitude property. - * + * @return central latitude. */ public double getCentralLatitude() { return centralLatitude; @@ -146,7 +146,7 @@ public class RegattaConfig { /** * Sets the value of the centralLatitude property. - * + * @param value new central latitude. */ public void setCentralLatitude(double value) { this.centralLatitude = value; @@ -154,7 +154,7 @@ public class RegattaConfig { /** * Gets the value of the centralLongitude property. - * + * @return central longitude. */ public double getCentralLongitude() { return centralLongitude; @@ -162,7 +162,7 @@ public class RegattaConfig { /** * Sets the value of the centralLongitude property. - * + * @param value new central longitude. */ public void setCentralLongitude(double value) { this.centralLongitude = value; @@ -170,7 +170,7 @@ public class RegattaConfig { /** * Gets the value of the centralAltitude property. - * + * @return central altitude. */ public double getCentralAltitude() { return centralAltitude; @@ -178,7 +178,7 @@ public class RegattaConfig { /** * Sets the value of the centralAltitude property. - * + * @param value new central altitude. */ public void setCentralAltitude(double value) { this.centralAltitude = value; @@ -186,7 +186,7 @@ public class RegattaConfig { /** * Gets the value of the utcOffset property. - * + * @return utc offset. */ public double getUtcOffset() { return utcOffset; @@ -194,7 +194,7 @@ public class RegattaConfig { /** * Sets the value of the utcOffset property. - * + * @param value new utc offset. */ public void setUtcOffset(double value) { this.utcOffset = value; @@ -202,7 +202,7 @@ public class RegattaConfig { /** * Gets the value of the magneticVariation property. - * + * @return magnetic variation. */ public double getMagneticVariation() { return magneticVariation; @@ -210,7 +210,7 @@ public class RegattaConfig { /** * Sets the value of the magneticVariation property. - * + * @param value new magnetic variation. */ public void setMagneticVariation(double value) { this.magneticVariation = value; From 346aa148ef495a7fb06cf4c420568f2b9a0b970c Mon Sep 17 00:00:00 2001 From: fjc40 Date: Mon, 11 Sep 2017 11:35:11 +1200 Subject: [PATCH 2/9] Added some debug statements, and WIP MarkRoundingSequence class. Temporarily disabled source id allocator time checks. Added mark rounding stuff to race canvas to help debug. #story[1185] --- .../src/main/java/mock/model/MockRace.java | 64 ++++++++--- .../java/mock/model/SourceIdAllocator.java | 4 +- .../main/java/shared/model/CompoundMark.java | 2 +- .../src/main/java/shared/model/Constants.java | 2 +- .../shared/model/MarkRoundingSequence.java | 78 ++++++++++++++ .../visualiser/model/ResizableRaceCanvas.java | 101 +++++++++++++++--- 6 files changed, 217 insertions(+), 34 deletions(-) create mode 100644 racevisionGame/src/main/java/shared/model/MarkRoundingSequence.java diff --git a/racevisionGame/src/main/java/mock/model/MockRace.java b/racevisionGame/src/main/java/mock/model/MockRace.java index a9f11770..c598eb05 100644 --- a/racevisionGame/src/main/java/mock/model/MockRace.java +++ b/racevisionGame/src/main/java/mock/model/MockRace.java @@ -8,6 +8,7 @@ import network.Messages.BoatLocation; import network.Messages.BoatStatus; import network.Messages.Enums.BoatStatusEnum; import network.Messages.Enums.RaceStatusEnum; +import network.Utils.AC35UnitConverter; import shared.dataInput.BoatDataSource; import shared.dataInput.RaceDataSource; import shared.dataInput.RegattaDataSource; @@ -524,12 +525,22 @@ public class MockRace extends RaceState { boolean gateCheck = boat.getCurrentLeg().getEndCompoundMark().getMark2() == null || boat.isBetweenGate(boat.getCurrentLeg().getEndCompoundMark()); Mark roundingMark = boat.getCurrentLeg().getEndCompoundMark().getMarkForRounding(legBearing); + System.out.println("boat rounding state: " + boat.getRoundingStatus());//TEMP REMOVE + switch (boat.getRoundingStatus()) { case 0://hasn't started rounding + System.out.println("portside? " + boat.isPortSide(roundingMark));//TEMP REMOVE + System.out.println("passes line? " + GPSCoordinate.passesLine(roundingMark.getPosition(), roundingChecks.get(0), boat.getPosition(), legBearing));//TEMP REMOVE + System.out.println("gatecheck? " + gateCheck);//TEMP REMOVE + System.out.println("between gates? " + boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(0))));//TEMP REMOVE if (boat.isPortSide(roundingMark) && - GPSCoordinate.passesLine(roundingMark.getPosition(), - roundingChecks.get(0), boat.getPosition(), legBearing) && - gateCheck && boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(0)))) { + GPSCoordinate.passesLine( + roundingMark.getPosition(), + roundingChecks.get(0), + boat.getPosition(), + legBearing) && + gateCheck && + boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(0)))) { boat.increaseRoundingStatus(); if (boat.getCurrentLeg().getLegNumber() + 2 >= getLegs().size()){ //boat has finished race @@ -539,8 +550,10 @@ public class MockRace extends RaceState { break; case 1://has been parallel to the mark; if (boat.isPortSide(roundingMark) && - GPSCoordinate.passesLine(roundingMark.getPosition(), - roundingChecks.get(1), boat.getPosition(), + GPSCoordinate.passesLine( + roundingMark.getPosition(), + roundingChecks.get(1), + boat.getPosition(), Bearing.fromDegrees(legBearing.degrees() - 90)) &&//negative 90 from bearing because of port rounding boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(1)))) { boat.increaseRoundingStatus(); @@ -568,6 +581,8 @@ public class MockRace extends RaceState { boolean gateCheck = boat.getCurrentLeg().getEndCompoundMark().getMark2() == null || boat.isBetweenGate(boat.getCurrentLeg().getEndCompoundMark()); Mark roundingMark = boat.getCurrentLeg().getEndCompoundMark().getMarkForRounding(legBearing); + System.out.println("boat rounding state: " + boat.getRoundingStatus());//TEMP REMOVE + switch (boat.getRoundingStatus()) { case 0://hasn't started rounding if (boat.isStarboardSide(roundingMark) && @@ -606,19 +621,27 @@ public class MockRace extends RaceState { */ protected void checkPosition(MockBoat boat, long timeElapsed) { //The distance, in nautical miles, within which the boat needs to get in order to consider that it has reached the marker. - double epsilonNauticalMiles = boat.getCurrentLeg().getEndCompoundMark().getRoundingDistance(); //250 meters. + double epsilonMeters = boat.getCurrentLeg().getEndCompoundMark().getRoundingDistance(); //250 meters. + //System.out.println("epsilon dist meters: " + epsilonMeters);//TEMP REMOVE + + //System.out.println("boat dist to next point NM: " + boat.calculateDistanceToNextMarker());//TEMP REMOVE + + double epsilonNM = epsilonMeters / Constants.NMToMetersConversion; - if (boat.calculateDistanceToNextMarker() < epsilonNauticalMiles) { + //System.out.println("epsilon NM: " + epsilonNM);//TEMP REMOVE + + if (boat.calculateDistanceToNextMarker() < epsilonNM) { //Boat is within an acceptable distance from the mark. - GPSCoordinate startDirectionLinePoint = boat.getCurrentLeg().getStartCompoundMark().getMark1Position(); - GPSCoordinate endDirectionLinePoint = boat.getCurrentLeg().getEndCompoundMark().getMark1Position(); + GPSCoordinate startDirectionLinePoint = boat.getCurrentLeg().getStartCompoundMark().getAverageGPSCoordinate(); + GPSCoordinate endDirectionLinePoint = boat.getCurrentLeg().getEndCompoundMark().getAverageGPSCoordinate(); Bearing bearingOfDirectionLine = GPSCoordinate.calculateBearing(startDirectionLinePoint, endDirectionLinePoint); //use the direction line to create three invisible points that act as crossover lines a boat must cross //to round a mark double bearingToAdd; + //System.out.println("leg: " + boat.getCurrentLeg().getName() + " has bearing DL of: " + bearingOfDirectionLine.degrees());//TEMP REMOVE if (boat.getCurrentLeg().getEndCompoundMark().getRoundingType() == RoundingType.Port || boat.getCurrentLeg().getEndCompoundMark().getRoundingType() == RoundingType.SP){ bearingToAdd = 90; @@ -626,25 +649,32 @@ public class MockRace extends RaceState { bearingToAdd = -90; } - GPSCoordinate roundCheck1 = GPSCoordinate.calculateNewPosition(endDirectionLinePoint, - epsilonNauticalMiles, Azimuth.fromDegrees(bearingOfDirectionLine.degrees() + bearingToAdd)); + //System.out.println("so new bearing is " + (bearingToAdd + bearingOfDirectionLine.degrees()));//TEMP REMOVE + + GPSCoordinate roundCheck1 = GPSCoordinate.calculateNewPosition( + endDirectionLinePoint, + epsilonMeters, + Azimuth.fromDegrees(bearingOfDirectionLine.degrees() + bearingToAdd) ); + //System.out.println("this has a rounding coordinate of (" + roundCheck1.getLongitude() + ", " + roundCheck1.getLatitude() + ")");//TEMP REMOVE GPSCoordinate roundCheck2; try{ Leg nextLeg = getLegs().get(getLegs().indexOf(boat.getCurrentLeg()) + 1); - GPSCoordinate startNextDirectionLinePoint = nextLeg.getStartCompoundMark().getMark1Position(); - GPSCoordinate endNextDirectionLinePoint = nextLeg.getEndCompoundMark().getMark1Position(); + GPSCoordinate startNextDirectionLinePoint = nextLeg.getStartCompoundMark().getAverageGPSCoordinate(); + GPSCoordinate endNextDirectionLinePoint = nextLeg.getEndCompoundMark().getAverageGPSCoordinate(); Bearing bearingOfNextDirectionLine = GPSCoordinate.calculateBearing(startNextDirectionLinePoint, endNextDirectionLinePoint); - roundCheck2 = GPSCoordinate.calculateNewPosition(endDirectionLinePoint, - epsilonNauticalMiles, Azimuth.fromDegrees(bearingOfNextDirectionLine.degrees() + bearingToAdd)); + roundCheck2 = GPSCoordinate.calculateNewPosition( + endDirectionLinePoint, + epsilonMeters, + Azimuth.fromDegrees(bearingOfNextDirectionLine.degrees() + bearingToAdd) ); }catch(NullPointerException e){ //this is caused by the last leg not being having a leg after it roundCheck2 = roundCheck1; } - List roundingChecks = new ArrayList(Arrays.asList(roundCheck1, roundCheck2)); + List roundingChecks = new ArrayList<>(Arrays.asList(roundCheck1, roundCheck2)); switch (boat.getCurrentLeg().getEndCompoundMark().getRoundingType()) { case SP://Not yet implemented so these gates will be rounded port side @@ -657,6 +687,8 @@ public class MockRace extends RaceState { break; } + System.out.println("resultant boat rounding state: " + boat.getRoundingStatus());//TEMP REMOVE + //Check if the boat has finished or stopped racing. if (this.isLastLeg(boat.getCurrentLeg())) { diff --git a/racevisionGame/src/main/java/mock/model/SourceIdAllocator.java b/racevisionGame/src/main/java/mock/model/SourceIdAllocator.java index 17a7e85f..ed36093c 100644 --- a/racevisionGame/src/main/java/mock/model/SourceIdAllocator.java +++ b/racevisionGame/src/main/java/mock/model/SourceIdAllocator.java @@ -36,10 +36,10 @@ public class SourceIdAllocator { */ public synchronized int allocateSourceID() throws SourceIDAllocationException { - if (!((mockRace.getRaceStatusEnum() == RaceStatusEnum.PRESTART) + /*if (!((mockRace.getRaceStatusEnum() == RaceStatusEnum.PRESTART) || (mockRace.getRaceStatusEnum() == RaceStatusEnum.WARNING))) { throw new SourceIDAllocationException("Could not allocate a source ID. Can only allocate during pre-start period. It is currently: " + mockRace.getRaceStatusEnum()); - } + }*///TEMP DISABLED FOR TESTING - RE-ENABLE THIS List allocatedIDs = mockRace.getRaceDataSource().getParticipants(); List allIDs = new ArrayList<>(mockRace.getBoatDataSource().getBoats().keySet()); diff --git a/racevisionGame/src/main/java/shared/model/CompoundMark.java b/racevisionGame/src/main/java/shared/model/CompoundMark.java index 4fa2599c..57d9a32b 100644 --- a/racevisionGame/src/main/java/shared/model/CompoundMark.java +++ b/racevisionGame/src/main/java/shared/model/CompoundMark.java @@ -187,7 +187,7 @@ public class CompoundMark extends XMLCompoundMark{ } //finds the mark furthest west and east - if(this.getMark1Position().getLongitude() > this.getMark2Position().getLongitude()){ + if(this.getMark1Position().getLongitude() < this.getMark2Position().getLongitude()){ westMostMark = this.mark1; eastMostMark = this.mark2; }else{ diff --git a/racevisionGame/src/main/java/shared/model/Constants.java b/racevisionGame/src/main/java/shared/model/Constants.java index bb7ec598..247b4c9b 100644 --- a/racevisionGame/src/main/java/shared/model/Constants.java +++ b/racevisionGame/src/main/java/shared/model/Constants.java @@ -33,7 +33,7 @@ public class Constants { * Frame periods are multiplied by this to get the amount of time a single frame represents. * E.g., frame period = 20ms, scale = 5, frame represents 20 * 5 = 100ms, and so boats are simulated for 100ms, even though only 20ms actually occurred. */ - public static final int RaceTimeScale = 2;//10; + public static final int RaceTimeScale = 10;//10; /** * The race pre-start time, in milliseconds. 3 minutes. diff --git a/racevisionGame/src/main/java/shared/model/MarkRoundingSequence.java b/racevisionGame/src/main/java/shared/model/MarkRoundingSequence.java new file mode 100644 index 00000000..48fc3999 --- /dev/null +++ b/racevisionGame/src/main/java/shared/model/MarkRoundingSequence.java @@ -0,0 +1,78 @@ +package shared.model; + +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * This class contains a sequence of points that describe the mark rounding order for a course. + */ +public class MarkRoundingSequence { + + + /** + * Legs in the race. + */ + private List legs; + + /** + * For each leg, a sequence of rounding points. + */ + private Map> roundingPoints; + + + + public MarkRoundingSequence(List legs) { + this.legs = legs; + generateRoundingPoints(); + } + + + /** + * Generates the rounding points for all legs in the race. + */ + private void generateRoundingPoints() { + this.roundingPoints = new HashMap<>(this.legs.size()); + + for (int i = 0; i < this.legs.size(); i++) { + Leg currentLeg = this.legs.get(i); + Optional nextLeg = Optional.ofNullable(this.legs.get(i + 1)); + + generateRoundingPoint(currentLeg, nextLeg); + } + + } + + + /** + * Generates the rounding points for a specific leg. + * @param currentLeg The leg to generate rounding points for. + * @param nextLeg The following leg, used to help generate rounding points. + */ + private void generateRoundingPoint(Leg currentLeg, Optional nextLeg) { + + + + + + + + //Rounding points: + + //each mark/gate has a specific mark to round. Call this ROUNDINGMARK + // with a mark, it is the mark + // with a gate, it depends if it is a starboard or port gate. + // it is the mark that allows the boat to enter between both marks of the gate, whilst obeying the starboard/port requirement. + + //let the bearing between start of leg and end of leg be called LEGBEARING + + //the first rounding point is ROUNDINGDISTANCE units away from the ROUNDINGMARK, on an angle perpendicular to LEGBEARING. + // the angle means that the rounding mark is at the center of a gate, for gates. + + //the second rounding point is the same as the first, except LEGBEARING is the bearing between end of current leg, and start of next leg. + } + +} diff --git a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java index 03e86e27..3f475e63 100644 --- a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java +++ b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java @@ -325,18 +325,6 @@ public class ResizableRaceCanvas extends ResizableCanvas { } - - -/* - //If the race hasn't started, we set the time since last mark to the current time, to ensure we don't start counting until the race actually starts. - if ((boat.getStatus() != BoatStatusEnum.RACING) && (boat.getStatus() == BoatStatusEnum.FINISHED)) { - boat.setTimeAtLastMark(visualiserRace.getVisualiserRaceState().getRaceClock().getCurrentTime()); - } -*/ - - - - } /** @@ -504,6 +492,87 @@ public class ResizableRaceCanvas extends ResizableCanvas { } + private void drawRoundingLines() { + + + + + //ugly hack + //rounding lines + + //Boat is within an acceptable distance from the mark. + VisualiserBoat boat = null; + for (VisualiserBoat visualiserBoat : new ArrayList<>(raceState.getBoats())) { + if (visualiserBoat.isClientBoat()) { + boat = visualiserBoat; + } + } + if (boat == null) { + return; + } + + GPSCoordinate startDirectionLinePoint = boat.getCurrentLeg().getStartCompoundMark().getAverageGPSCoordinate(); + GPSCoordinate endDirectionLinePoint = boat.getCurrentLeg().getEndCompoundMark().getAverageGPSCoordinate(); + Bearing bearingOfDirectionLine = GPSCoordinate.calculateBearing(startDirectionLinePoint, endDirectionLinePoint); + + //use the direction line to create three invisible points that act as crossover lines a boat must cross + //to round a mark + + double bearingToAdd; + if (boat.getCurrentLeg().getEndCompoundMark().getRoundingType() == RoundingType.Port || + boat.getCurrentLeg().getEndCompoundMark().getRoundingType() == RoundingType.SP) { + bearingToAdd = 90; + }else{ + bearingToAdd = -90; + } + + double epsilonMeters = boat.getCurrentLeg().getEndCompoundMark().getRoundingDistance(); + + GPSCoordinate endMarkPos = boat.getCurrentLeg().getEndCompoundMark().getMarkForRounding(bearingOfDirectionLine).getPosition(); + + GPSCoordinate roundCheck1 = GPSCoordinate.calculateNewPosition( + endMarkPos, + epsilonMeters, + Azimuth.fromDegrees(bearingOfDirectionLine.degrees() + bearingToAdd) ); + + GPSCoordinate roundCheck2; + try{ + Leg nextLeg = raceState.getLegs().get(raceState.getLegs().indexOf(boat.getCurrentLeg()) + 1); + + GPSCoordinate startNextDirectionLinePoint = nextLeg.getStartCompoundMark().getAverageGPSCoordinate(); + GPSCoordinate endNextDirectionLinePoint = nextLeg.getEndCompoundMark().getAverageGPSCoordinate(); + Bearing bearingOfNextDirectionLine = GPSCoordinate.calculateBearing(startNextDirectionLinePoint, endNextDirectionLinePoint); + + roundCheck2 = GPSCoordinate.calculateNewPosition( + endDirectionLinePoint, + epsilonMeters, + Azimuth.fromDegrees(bearingOfNextDirectionLine.degrees() + bearingToAdd) ); + } catch(NullPointerException e) { + //this is caused by the last leg not being having a leg after it + roundCheck2 = roundCheck1; + } + + //To screen coords. + GraphCoordinate legEnd = map.convertGPS(endDirectionLinePoint); + GraphCoordinate round1 = map.convertGPS(roundCheck1); + GraphCoordinate round2 = map.convertGPS(roundCheck2); + + + + gc.strokeLine( + legEnd.getX(), + legEnd.getY(), + round1.getX(), + round1.getY() ); + + gc.strokeLine( + legEnd.getX(), + legEnd.getY(), + round2.getX(), + round2.getY() ); + + } + /** * Draws all of the {@link Mark}s on the canvas. @@ -513,6 +582,7 @@ public class ResizableRaceCanvas extends ResizableCanvas { for (Mark mark : new ArrayList<>(raceState.getMarks())) { drawMark(mark); } + } @@ -621,6 +691,9 @@ public class ResizableRaceCanvas extends ResizableCanvas { //Marks. drawMarks(); + //TEMP + drawRoundingLines(); + } /** @@ -655,7 +728,7 @@ public class ResizableRaceCanvas extends ResizableCanvas { //finds the direction of the current leg as a bearing startDirectionLinePoint = legStartPoint; - GPSCoordinate tempEndDirectionLinePoint = legs.get(index).getEndCompoundMark().getAverageGPSCoordinate(); + GPSCoordinate tempEndDirectionLinePoint = legs.get(index).getEndCompoundMark().getMark1Position(); bearingOfDirectionLine = GPSCoordinate.calculateBearing(startDirectionLinePoint, tempEndDirectionLinePoint); @@ -826,4 +899,4 @@ public class ResizableRaceCanvas extends ResizableCanvas { -} \ No newline at end of file +} From 3fa6b9200d445d4382e908e9494948c52f1f31d9 Mon Sep 17 00:00:00 2001 From: fjc40 Date: Wed, 13 Sep 2017 00:38:58 +1200 Subject: [PATCH 3/9] Finished MarkRoundingSequence class. Added MarkRoundingData class. RaceState has a MarkRoundingSequenceMember. The temporary rounding line drawing in canvas uses MarkRoundingSequence. MockRace now uses MarkRoundingSequence. #story[1185] --- .../src/main/java/mock/model/MockRace.java | 179 +++++++----------- .../java/shared/model/MarkRoundingData.java | 118 ++++++++++++ .../shared/model/MarkRoundingSequence.java | 150 ++++++++++++++- .../src/main/java/shared/model/RaceState.java | 20 +- .../visualiser/model/ResizableRaceCanvas.java | 51 +---- 5 files changed, 349 insertions(+), 169 deletions(-) create mode 100644 racevisionGame/src/main/java/shared/model/MarkRoundingData.java diff --git a/racevisionGame/src/main/java/mock/model/MockRace.java b/racevisionGame/src/main/java/mock/model/MockRace.java index c598eb05..9560b665 100644 --- a/racevisionGame/src/main/java/mock/model/MockRace.java +++ b/racevisionGame/src/main/java/mock/model/MockRace.java @@ -1,19 +1,13 @@ package mock.model; import mock.model.wind.WindGenerator; -import javafx.animation.AnimationTimer; import mock.model.collider.ColliderRegistry; -import mock.xml.*; -import network.Messages.BoatLocation; -import network.Messages.BoatStatus; import network.Messages.Enums.BoatStatusEnum; import network.Messages.Enums.RaceStatusEnum; -import network.Utils.AC35UnitConverter; import shared.dataInput.BoatDataSource; import shared.dataInput.RaceDataSource; import shared.dataInput.RegattaDataSource; import shared.exceptions.BoatNotFoundException; -import shared.enums.RoundingType; import shared.model.*; import shared.model.Bearing; @@ -358,8 +352,6 @@ public class MockRace extends RaceState { if (!finish && totalElapsedMilliseconds >= updatePeriodMilliseconds && boat.isSailsOut()) { - checkPosition(boat, totalElapsedMilliseconds); - if (boat.getCurrentSpeed() == 0) { newOptimalVMG(boat); boat.setBearing(boat.calculateBearingToNextMarker()); @@ -373,6 +365,7 @@ public class MockRace extends RaceState { //Scale it. distanceTravelledMeters = distanceTravelledMeters * this.scaleFactor; + checkPosition(boat, totalElapsedMilliseconds); //Move the boat forwards that many meters, and advances its time counters by enough milliseconds. boat.moveForwards(distanceTravelledMeters); @@ -515,32 +508,28 @@ public class MockRace extends RaceState { /** * Checks to be run on boats rounding marks on the port side * @param boat the boat that is rounding a mark - * @param roundingChecks the checks to run - * @param legBearing the direction of the leg + * @param roundingData The data for the current leg's rounding. */ - private void boatRoundingCheckPort(MockBoat boat, List roundingChecks, Bearing legBearing) { + private void boatRoundingCheckPort(MockBoat boat, MarkRoundingData roundingData) { //boats must pass all checks in order to round a mark //boolean for if boat has to/needs to pass through a gate boolean gateCheck = boat.getCurrentLeg().getEndCompoundMark().getMark2() == null || boat.isBetweenGate(boat.getCurrentLeg().getEndCompoundMark()); - Mark roundingMark = boat.getCurrentLeg().getEndCompoundMark().getMarkForRounding(legBearing); - System.out.println("boat rounding state: " + boat.getRoundingStatus());//TEMP REMOVE + switch (boat.getRoundingStatus()) { case 0://hasn't started rounding - System.out.println("portside? " + boat.isPortSide(roundingMark));//TEMP REMOVE - System.out.println("passes line? " + GPSCoordinate.passesLine(roundingMark.getPosition(), roundingChecks.get(0), boat.getPosition(), legBearing));//TEMP REMOVE - System.out.println("gatecheck? " + gateCheck);//TEMP REMOVE - System.out.println("between gates? " + boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(0))));//TEMP REMOVE - if (boat.isPortSide(roundingMark) && + if (boat.isPortSide(roundingData.getMarkToRound()) && GPSCoordinate.passesLine( - roundingMark.getPosition(), - roundingChecks.get(0), + roundingData.getMarkToRound().getPosition(), + roundingData.getRoundCheck1(), boat.getPosition(), - legBearing) && + roundingData.getLegBearing()) && gateCheck && - boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(0)))) { + boat.isBetweenGate( + roundingData.getMarkToRound(), + Mark.tempMark(roundingData.getRoundCheck1())) ) { boat.increaseRoundingStatus(); if (boat.getCurrentLeg().getLegNumber() + 2 >= getLegs().size()){ //boat has finished race @@ -549,13 +538,18 @@ public class MockRace extends RaceState { } break; case 1://has been parallel to the mark; - if (boat.isPortSide(roundingMark) && + if (boat.isPortSide(roundingData.getMarkToRound()) && GPSCoordinate.passesLine( - roundingMark.getPosition(), - roundingChecks.get(1), + roundingData.getMarkToRound().getPosition(), + roundingData.getRoundCheck2(), boat.getPosition(), - Bearing.fromDegrees(legBearing.degrees() - 90)) &&//negative 90 from bearing because of port rounding - boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(1)))) { + Bearing.fromDegrees( + GPSCoordinate.calculateBearing( + roundingData.getMarkToRound().getPosition(), + roundingData.getRoundCheck2()).degrees() - 90)) &&//negative 90 from bearing because of port rounding + boat.isBetweenGate( + roundingData.getMarkToRound(), + Mark.tempMark(roundingData.getRoundCheck2()))) { boat.increaseRoundingStatus(); } break; @@ -571,25 +565,27 @@ public class MockRace extends RaceState { /** * Checks to be run on boats rounding marks on the starboard side * @param boat the boat that is rounding a mark - * @param roundingChecks the checks to run - * @param legBearing the direction of the leg + * @param roundingData The data for the current leg's rounding. */ - private void boatRoundingCheckStarboard(MockBoat boat, List roundingChecks, Bearing legBearing){ + private void boatRoundingCheckStarboard(MockBoat boat, MarkRoundingData roundingData){ //boats must pass all checks in order to round a mark //boolean for if boat has to/needs to pass through a gate boolean gateCheck = boat.getCurrentLeg().getEndCompoundMark().getMark2() == null || boat.isBetweenGate(boat.getCurrentLeg().getEndCompoundMark()); - Mark roundingMark = boat.getCurrentLeg().getEndCompoundMark().getMarkForRounding(legBearing); - System.out.println("boat rounding state: " + boat.getRoundingStatus());//TEMP REMOVE switch (boat.getRoundingStatus()) { case 0://hasn't started rounding - if (boat.isStarboardSide(roundingMark) && - GPSCoordinate.passesLine(roundingMark.getPosition(), - roundingChecks.get(0), boat.getPosition(), legBearing) && + if (boat.isStarboardSide(roundingData.getMarkToRound()) && + GPSCoordinate.passesLine( + roundingData.getMarkToRound().getPosition(), + roundingData.getRoundCheck1(), + boat.getPosition(), + roundingData.getLegBearing()) && gateCheck && - boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(0)))) { + boat.isBetweenGate( + roundingData.getMarkToRound(), + Mark.tempMark(roundingData.getRoundCheck1()))) { boat.increaseRoundingStatus(); if (boat.getCurrentLeg().getLegNumber() + 2 >= getLegs().size()){ //boat has finished race @@ -598,10 +594,18 @@ public class MockRace extends RaceState { } break; case 1://has been parallel to the mark - if (boat.isStarboardSide(roundingMark) && - GPSCoordinate.passesLine(roundingMark.getPosition(), - 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)))) { + if (boat.isStarboardSide(roundingData.getMarkToRound()) && + GPSCoordinate.passesLine( + roundingData.getMarkToRound().getPosition(), + roundingData.getRoundCheck2(), + boat.getPosition(), + Bearing.fromDegrees( + GPSCoordinate.calculateBearing( + roundingData.getMarkToRound().getPosition(), + roundingData.getRoundCheck2() ).degrees() + 90)) && //positive 90 from bearing because of starboard rounding + boat.isBetweenGate( + roundingData.getMarkToRound(), + Mark.tempMark(roundingData.getRoundCheck2())) ) { boat.increaseRoundingStatus(); } break; @@ -620,84 +624,29 @@ public class MockRace extends RaceState { * @param timeElapsed The total time, in milliseconds, that has elapsed since the race started. */ protected void checkPosition(MockBoat boat, long timeElapsed) { - //The distance, in nautical miles, within which the boat needs to get in order to consider that it has reached the marker. - double epsilonMeters = boat.getCurrentLeg().getEndCompoundMark().getRoundingDistance(); //250 meters. - //System.out.println("epsilon dist meters: " + epsilonMeters);//TEMP REMOVE - - //System.out.println("boat dist to next point NM: " + boat.calculateDistanceToNextMarker());//TEMP REMOVE - - double epsilonNM = epsilonMeters / Constants.NMToMetersConversion; - - //System.out.println("epsilon NM: " + epsilonNM);//TEMP REMOVE - - if (boat.calculateDistanceToNextMarker() < epsilonNM) { - //Boat is within an acceptable distance from the mark. - - GPSCoordinate startDirectionLinePoint = boat.getCurrentLeg().getStartCompoundMark().getAverageGPSCoordinate(); - GPSCoordinate endDirectionLinePoint = boat.getCurrentLeg().getEndCompoundMark().getAverageGPSCoordinate(); - Bearing bearingOfDirectionLine = GPSCoordinate.calculateBearing(startDirectionLinePoint, endDirectionLinePoint); - - //use the direction line to create three invisible points that act as crossover lines a boat must cross - //to round a mark - - double bearingToAdd; - //System.out.println("leg: " + boat.getCurrentLeg().getName() + " has bearing DL of: " + bearingOfDirectionLine.degrees());//TEMP REMOVE - if (boat.getCurrentLeg().getEndCompoundMark().getRoundingType() == RoundingType.Port || - boat.getCurrentLeg().getEndCompoundMark().getRoundingType() == RoundingType.SP){ - bearingToAdd = 90; - }else{ - bearingToAdd = -90; - } - - //System.out.println("so new bearing is " + (bearingToAdd + bearingOfDirectionLine.degrees()));//TEMP REMOVE - - GPSCoordinate roundCheck1 = GPSCoordinate.calculateNewPosition( - endDirectionLinePoint, - epsilonMeters, - Azimuth.fromDegrees(bearingOfDirectionLine.degrees() + bearingToAdd) ); - //System.out.println("this has a rounding coordinate of (" + roundCheck1.getLongitude() + ", " + roundCheck1.getLatitude() + ")");//TEMP REMOVE - - GPSCoordinate roundCheck2; - try{ - Leg nextLeg = getLegs().get(getLegs().indexOf(boat.getCurrentLeg()) + 1); - - GPSCoordinate startNextDirectionLinePoint = nextLeg.getStartCompoundMark().getAverageGPSCoordinate(); - GPSCoordinate endNextDirectionLinePoint = nextLeg.getEndCompoundMark().getAverageGPSCoordinate(); - Bearing bearingOfNextDirectionLine = GPSCoordinate.calculateBearing(startNextDirectionLinePoint, endNextDirectionLinePoint); - - roundCheck2 = GPSCoordinate.calculateNewPosition( - endDirectionLinePoint, - epsilonMeters, - Azimuth.fromDegrees(bearingOfNextDirectionLine.degrees() + bearingToAdd) ); - }catch(NullPointerException e){ - //this is caused by the last leg not being having a leg after it - roundCheck2 = roundCheck1; - } - - List roundingChecks = new ArrayList<>(Arrays.asList(roundCheck1, roundCheck2)); - - switch (boat.getCurrentLeg().getEndCompoundMark().getRoundingType()) { - case SP://Not yet implemented so these gates will be rounded port side - case Port: - boatRoundingCheckPort(boat, roundingChecks, bearingOfDirectionLine); - break; - case PS://not yet implemented so these gates will be rounded starboard side - case Starboard: - boatRoundingCheckStarboard(boat, roundingChecks, bearingOfDirectionLine); - break; - } - - System.out.println("resultant boat rounding state: " + boat.getRoundingStatus());//TEMP REMOVE + switch (boat.getCurrentLeg().getEndCompoundMark().getRoundingType()) { + case SP://Not yet implemented so these gates will be rounded port side + case Port: + boatRoundingCheckPort( + boat, + getMarkRoundingSequence().getRoundingData(boat.getCurrentLeg()) ); + break; + case PS://not yet implemented so these gates will be rounded starboard side + case Starboard: + boatRoundingCheckStarboard( + boat, + getMarkRoundingSequence().getRoundingData(boat.getCurrentLeg()) ); + break; + } - //Check if the boat has finished or stopped racing. - if (this.isLastLeg(boat.getCurrentLeg())) { - //Boat has finished. - boat.setTimeFinished(timeElapsed); - boat.setCurrentSpeed(0); - boat.setStatus(BoatStatusEnum.FINISHED); - } + //Check if the boat has finished or stopped racing. + if (this.isLastLeg(boat.getCurrentLeg())) { + //Boat has finished. + boat.setTimeFinished(timeElapsed); + boat.setCurrentSpeed(0); + boat.setStatus(BoatStatusEnum.FINISHED); } diff --git a/racevisionGame/src/main/java/shared/model/MarkRoundingData.java b/racevisionGame/src/main/java/shared/model/MarkRoundingData.java new file mode 100644 index 00000000..c9fb36a2 --- /dev/null +++ b/racevisionGame/src/main/java/shared/model/MarkRoundingData.java @@ -0,0 +1,118 @@ +package shared.model; + + + +/** + * Contains data related to mark rounding for a specific leg. + */ +public class MarkRoundingData { + + /** + * The leg this relates to. + */ + private Leg leg; + + /** + * The mark that should be rounded. + */ + private Mark markToRound; + + /** + * The bearing of the leg. + */ + private Bearing legBearing; + + /** + * The bearing of the next leg. + */ + private Bearing nextLegBearing; + + /** + * The location of the first rounding check point. + */ + private GPSCoordinate roundCheck1; + + /** + * The location of the second rounding check point. + */ + private GPSCoordinate roundCheck2; + + /** + * A halfway point between mark to round and roundCheck1. + */ + private GPSCoordinate roundCheck1Halfway; + + /** + * A halfway point between mark to round and roundCheck2. + */ + private GPSCoordinate roundCheck2Halfway; + + + public MarkRoundingData() { + } + + + public Leg getLeg() { + return leg; + } + + public void setLeg(Leg leg) { + this.leg = leg; + } + + public Mark getMarkToRound() { + return markToRound; + } + + public void setMarkToRound(Mark markToRound) { + this.markToRound = markToRound; + } + + public Bearing getLegBearing() { + return legBearing; + } + + public void setLegBearing(Bearing legBearing) { + this.legBearing = legBearing; + } + + public Bearing getNextLegBearing() { + return nextLegBearing; + } + + public void setNextLegBearing(Bearing nextLegBearing) { + this.nextLegBearing = nextLegBearing; + } + + public GPSCoordinate getRoundCheck1() { + return roundCheck1; + } + + public void setRoundCheck1(GPSCoordinate roundCheck1) { + this.roundCheck1 = roundCheck1; + } + + public GPSCoordinate getRoundCheck2() { + return roundCheck2; + } + + public void setRoundCheck2(GPSCoordinate roundCheck2) { + this.roundCheck2 = roundCheck2; + } + + public GPSCoordinate getRoundCheck1Halfway() { + return roundCheck1Halfway; + } + + public void setRoundCheck1Halfway(GPSCoordinate roundCheck1Halfway) { + this.roundCheck1Halfway = roundCheck1Halfway; + } + + public GPSCoordinate getRoundCheck2Halfway() { + return roundCheck2Halfway; + } + + public void setRoundCheck2Halfway(GPSCoordinate roundCheck2Halfway) { + this.roundCheck2Halfway = roundCheck2Halfway; + } +} diff --git a/racevisionGame/src/main/java/shared/model/MarkRoundingSequence.java b/racevisionGame/src/main/java/shared/model/MarkRoundingSequence.java index 48fc3999..de11c170 100644 --- a/racevisionGame/src/main/java/shared/model/MarkRoundingSequence.java +++ b/racevisionGame/src/main/java/shared/model/MarkRoundingSequence.java @@ -1,11 +1,8 @@ package shared.model; -import org.jetbrains.annotations.Nullable; +import java.util.*; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import static shared.enums.RoundingType.*; /** * This class contains a sequence of points that describe the mark rounding order for a course. @@ -19,9 +16,9 @@ public class MarkRoundingSequence { private List legs; /** - * For each leg, a sequence of rounding points. + * For each leg, mark rounding information. */ - private Map> roundingPoints; + private Map roundingPoints; @@ -31,6 +28,16 @@ public class MarkRoundingSequence { } + /** + * Returns the rounding points for a given leg. + * @param leg Leg to check. + * @return Rounding points for leg. + */ + public MarkRoundingData getRoundingData(Leg leg) { + return roundingPoints.get(leg); + } + + /** * Generates the rounding points for all legs in the race. */ @@ -39,7 +46,11 @@ public class MarkRoundingSequence { for (int i = 0; i < this.legs.size(); i++) { Leg currentLeg = this.legs.get(i); - Optional nextLeg = Optional.ofNullable(this.legs.get(i + 1)); + + Optional nextLeg = Optional.empty(); + if (i < legs.size() - 1) { + nextLeg = Optional.of(this.legs.get(i + 1)); + } generateRoundingPoint(currentLeg, nextLeg); } @@ -50,14 +61,85 @@ public class MarkRoundingSequence { /** * Generates the rounding points for a specific leg. * @param currentLeg The leg to generate rounding points for. - * @param nextLeg The following leg, used to help generate rounding points. + * @param nextLeg The following leg, used to help generate rounding points. Final leg of race doesn't have a following leg. */ private void generateRoundingPoint(Leg currentLeg, Optional nextLeg) { + Bearing bearingToAddFirstPoint = calculateBearingToAdd(currentLeg); + + GPSCoordinate startCoord = currentLeg.getStartCompoundMark().getAverageGPSCoordinate(); + GPSCoordinate endCoord = currentLeg.getEndCompoundMark().getAverageGPSCoordinate(); + Bearing legBearing = GPSCoordinate.calculateBearing(startCoord, endCoord); + Bearing nextBearing = legBearing; + + Mark markToRound = currentLeg.getEndCompoundMark().getMarkForRounding(legBearing); + + GPSCoordinate roundCheck1; + if (currentLeg.getEndCompoundMark().getMark2() == null) { + //End is a single mark. + roundCheck1 = calculateRoundingCheckPoint( + currentLeg, + markToRound, + legBearing, + bearingToAddFirstPoint); + } else { + //End is a gate. + if (markToRound == currentLeg.getEndCompoundMark().getMark1()) { + roundCheck1 = currentLeg.getEndCompoundMark().getMark2().getPosition(); + } else { + roundCheck1 = currentLeg.getEndCompoundMark().getMark1().getPosition(); + } + } + + //TODO the halfway points currently haven't been done properly. + + GPSCoordinate roundCheck1Halfway = calculateRoundingCheckPoint( + currentLeg, + markToRound, + legBearing, + bearingToAddFirstPoint); + + + GPSCoordinate roundCheck2 = roundCheck1; + GPSCoordinate roundCheck2Halfway = roundCheck1Halfway; + if (nextLeg.isPresent()) { + + Bearing bearingToAddSecondPoint = bearingToAddFirstPoint;//calculateBearingToAdd(nextLeg.get()); + + GPSCoordinate startCoord2 = nextLeg.get().getStartCompoundMark().getAverageGPSCoordinate(); + GPSCoordinate endCoord2 = nextLeg.get().getEndCompoundMark().getAverageGPSCoordinate(); + nextBearing = GPSCoordinate.calculateBearing(startCoord2, endCoord2); + + roundCheck2 = calculateRoundingCheckPoint( + currentLeg, + markToRound, + nextBearing, + bearingToAddSecondPoint); + + roundCheck2Halfway = calculateRoundingCheckPoint( + currentLeg, + markToRound, + nextBearing, + bearingToAddSecondPoint); + } + + + MarkRoundingData roundingData = new MarkRoundingData(); + roundingData.setLeg(currentLeg); + + roundingData.setLegBearing(legBearing); + roundingData.setNextLegBearing(nextBearing); + + roundingData.setMarkToRound(markToRound); + roundingData.setRoundCheck1(roundCheck1); + roundingData.setRoundCheck1Halfway(roundCheck1Halfway); + roundingData.setRoundCheck2(roundCheck2); + roundingData.setRoundCheck2Halfway(roundCheck2Halfway); + this.roundingPoints.put(currentLeg, roundingData); //Rounding points: @@ -75,4 +157,54 @@ public class MarkRoundingSequence { //the second rounding point is the same as the first, except LEGBEARING is the bearing between end of current leg, and start of next leg. } + + + /** + * Calculates the location of the rounding check point, which together with the mark to round, forms a line that the boat must cross to round the mark. + * @param leg Leg of race to check. + * @param markToRound Mark at end of leg to round. + * @param legBearing The bearing of the nearest leg. For the first rounding point this is the leg's bearing, for the second rounding point it is the next leg's bearing. + * @param bearingToAdd The bearing to add to the leg bearing to get a perpendicular bearing. + * @return The location of the rounding point, which together with the mark to round forms a line the boat must cross. + */ + private GPSCoordinate calculateRoundingCheckPoint(Leg leg, Mark markToRound, Bearing legBearing, Bearing bearingToAdd) { + + + double roundingDistanceMeters = leg.getEndCompoundMark().getRoundingDistance(); + + + //We project from rounding mark to get the second point which forms the line the boat must cross. + /* + c2 + | + | + r------c1 + b + */ + GPSCoordinate roundCheck = GPSCoordinate.calculateNewPosition( + markToRound.getPosition(), + roundingDistanceMeters, + Azimuth.fromDegrees(legBearing.degrees() + bearingToAdd.degrees()) ); + + return roundCheck; + } + + + /** + * Calculates the bearing that must be added to a leg's bearing to calculate a perpendicular bearing, used for finding rounding points. + * @param leg Leg to check. + * @return Bearing to add. Will be either +90 or -90. + */ + private Bearing calculateBearingToAdd(Leg leg) { + + if (leg.getEndCompoundMark().getRoundingType() == Port || + leg.getEndCompoundMark().getRoundingType() == SP) { + return Bearing.fromDegrees(90); + } else { + return Bearing.fromDegrees(-90); + } + + } + + } diff --git a/racevisionGame/src/main/java/shared/model/RaceState.java b/racevisionGame/src/main/java/shared/model/RaceState.java index 48361da2..36448981 100644 --- a/racevisionGame/src/main/java/shared/model/RaceState.java +++ b/racevisionGame/src/main/java/shared/model/RaceState.java @@ -46,6 +46,12 @@ public abstract class RaceState { private ObservableList legs; + /** + * The sequence of rounding points for each leg/mark. + */ + private MarkRoundingSequence markRoundingSequence; + + /** * The clock which tracks the race's start time, current time, and elapsed duration. @@ -102,10 +108,15 @@ public abstract class RaceState { */ protected void useLegsList(List legs) { this.legs.setAll(legs); + + //We create this before adding the extra finish leg, as it doesn't contain compound marks. + this.markRoundingSequence = new MarkRoundingSequence(getLegs()); + //We add a "dummy" leg at the end of the race. if (getLegs().size() > 0) { getLegs().add(new Leg("Finish", getLegs().size())); } + } @@ -367,6 +378,11 @@ public abstract class RaceState { } - - + /** + * Returns the rounding sequences for each leg. + * @return Rounding sequence for each leg. + */ + public MarkRoundingSequence getMarkRoundingSequence() { + return markRoundingSequence; + } } diff --git a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java index 3f475e63..6c0dee48 100644 --- a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java +++ b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java @@ -495,8 +495,6 @@ public class ResizableRaceCanvas extends ResizableCanvas { private void drawRoundingLines() { - - //ugly hack //rounding lines @@ -511,52 +509,16 @@ public class ResizableRaceCanvas extends ResizableCanvas { return; } - GPSCoordinate startDirectionLinePoint = boat.getCurrentLeg().getStartCompoundMark().getAverageGPSCoordinate(); - GPSCoordinate endDirectionLinePoint = boat.getCurrentLeg().getEndCompoundMark().getAverageGPSCoordinate(); - Bearing bearingOfDirectionLine = GPSCoordinate.calculateBearing(startDirectionLinePoint, endDirectionLinePoint); - - //use the direction line to create three invisible points that act as crossover lines a boat must cross - //to round a mark - - double bearingToAdd; - if (boat.getCurrentLeg().getEndCompoundMark().getRoundingType() == RoundingType.Port || - boat.getCurrentLeg().getEndCompoundMark().getRoundingType() == RoundingType.SP) { - bearingToAdd = 90; - }else{ - bearingToAdd = -90; - } - - double epsilonMeters = boat.getCurrentLeg().getEndCompoundMark().getRoundingDistance(); + Leg currentLeg = boat.getCurrentLeg(); - GPSCoordinate endMarkPos = boat.getCurrentLeg().getEndCompoundMark().getMarkForRounding(bearingOfDirectionLine).getPosition(); + MarkRoundingData roundingData = raceState.getMarkRoundingSequence().getRoundingData(currentLeg); - GPSCoordinate roundCheck1 = GPSCoordinate.calculateNewPosition( - endMarkPos, - epsilonMeters, - Azimuth.fromDegrees(bearingOfDirectionLine.degrees() + bearingToAdd) ); - GPSCoordinate roundCheck2; - try{ - Leg nextLeg = raceState.getLegs().get(raceState.getLegs().indexOf(boat.getCurrentLeg()) + 1); - - GPSCoordinate startNextDirectionLinePoint = nextLeg.getStartCompoundMark().getAverageGPSCoordinate(); - GPSCoordinate endNextDirectionLinePoint = nextLeg.getEndCompoundMark().getAverageGPSCoordinate(); - Bearing bearingOfNextDirectionLine = GPSCoordinate.calculateBearing(startNextDirectionLinePoint, endNextDirectionLinePoint); - - roundCheck2 = GPSCoordinate.calculateNewPosition( - endDirectionLinePoint, - epsilonMeters, - Azimuth.fromDegrees(bearingOfNextDirectionLine.degrees() + bearingToAdd) ); - } catch(NullPointerException e) { - //this is caused by the last leg not being having a leg after it - roundCheck2 = roundCheck1; - } //To screen coords. - GraphCoordinate legEnd = map.convertGPS(endDirectionLinePoint); - GraphCoordinate round1 = map.convertGPS(roundCheck1); - GraphCoordinate round2 = map.convertGPS(roundCheck2); - + GraphCoordinate legEnd = map.convertGPS(roundingData.getMarkToRound().getPosition()); + GraphCoordinate round1 = map.convertGPS(roundingData.getRoundCheck1()); + GraphCoordinate round2 = map.convertGPS(roundingData.getRoundCheck2()); gc.strokeLine( @@ -571,6 +533,9 @@ public class ResizableRaceCanvas extends ResizableCanvas { round2.getX(), round2.getY() ); + drawCircle(round1, 12, Color.ORANGE); + drawCircle(round2, 12, Color.GREEN); + } From 9fa1b9ee6733d8d61aa608acd5c2d54c9c9a40bb Mon Sep 17 00:00:00 2001 From: fjc40 Date: Wed, 13 Sep 2017 00:41:23 +1200 Subject: [PATCH 4/9] Re-enabled source id allocator check. Re-enabled rotation of map at startup. Changed race.xml schema so that yacht elements aren't required inside the participants element. #story[1185] --- .../src/main/java/mock/app/Event.java | 10 +++-- .../java/mock/model/SourceIdAllocator.java | 4 +- .../main/java/mock/xml/RaceXMLCreator.java | 37 +++++++++++-------- .../java/shared/xml/Race/XMLParticipants.java | 2 +- .../main/java/shared/xml/XMLUtilities.java | 2 +- .../mock/mockXML/schema/raceSchema.xsd | 4 +- 6 files changed, 33 insertions(+), 26 deletions(-) diff --git a/racevisionGame/src/main/java/mock/app/Event.java b/racevisionGame/src/main/java/mock/app/Event.java index 6f778852..bfdf174f 100644 --- a/racevisionGame/src/main/java/mock/app/Event.java +++ b/racevisionGame/src/main/java/mock/app/Event.java @@ -21,7 +21,7 @@ import shared.model.Constants; import javax.xml.bind.JAXBException; import javax.xml.parsers.ParserConfigurationException; -import java.io.IOException; +import java.io.*; import java.nio.charset.StandardCharsets; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; @@ -92,14 +92,16 @@ public class Event { //Read XML files. try { - //this.raceXML = RaceXMLCreator.alterRaceToWind(raceXMLFile, 90); - this.raceXML = XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8); + + //this.raceXML = XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8); this.raceXML = Event.setRaceXMLAtCurrentTimeToNow(XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8)); + this.raceXML = RaceXMLCreator.alterRaceToWind(this.raceXML, XMLFileType.Contents, 300); + this.boatXML = XMLReader.readXMLFileToString(boatsXMLFile, StandardCharsets.UTF_8); this.regattaXML = XMLReader.readXMLFileToString(regattaXMLFile, StandardCharsets.UTF_8); - } catch (XMLReaderException e) { + } catch (XMLReaderException | InvalidRaceDataException e) { throw new EventConstructionException("Could not read XML files.", e); } diff --git a/racevisionGame/src/main/java/mock/model/SourceIdAllocator.java b/racevisionGame/src/main/java/mock/model/SourceIdAllocator.java index ed36093c..17a7e85f 100644 --- a/racevisionGame/src/main/java/mock/model/SourceIdAllocator.java +++ b/racevisionGame/src/main/java/mock/model/SourceIdAllocator.java @@ -36,10 +36,10 @@ public class SourceIdAllocator { */ public synchronized int allocateSourceID() throws SourceIDAllocationException { - /*if (!((mockRace.getRaceStatusEnum() == RaceStatusEnum.PRESTART) + if (!((mockRace.getRaceStatusEnum() == RaceStatusEnum.PRESTART) || (mockRace.getRaceStatusEnum() == RaceStatusEnum.WARNING))) { throw new SourceIDAllocationException("Could not allocate a source ID. Can only allocate during pre-start period. It is currently: " + mockRace.getRaceStatusEnum()); - }*///TEMP DISABLED FOR TESTING - RE-ENABLE THIS + } List allocatedIDs = mockRace.getRaceDataSource().getParticipants(); List allIDs = new ArrayList<>(mockRace.getBoatDataSource().getBoats().keySet()); diff --git a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java index 5cb74625..16bb23d2 100644 --- a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java +++ b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java @@ -26,6 +26,7 @@ import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.io.StringWriter; import java.math.BigInteger; import java.net.URL; @@ -64,33 +65,37 @@ public class RaceXMLCreator { /** * Rotates the race in a specified direction. - * @param s xml file name + * @param s xml file name or contents. + * @param fileType Whether s is a file name or contents. * @param degrees degrees to rotate * @return the new xml file as a string * @throws XMLReaderException if the xml is not readable * @throws InvalidRaceDataException if the race is invalid - * @throws JAXBException if the Race class cannot be parsed into a xml. - * @throws IOException if the schema file cannot be found - * @throws SAXException error in schema file - * @throws ParserConfigurationException error in parsing the schema file */ - public static String alterRaceToWind(String s, double degrees) throws XMLReaderException, InvalidRaceDataException, JAXBException, IOException, SAXException, ParserConfigurationException { - RaceXMLReader reader = new RaceXMLReader(s, XMLFileType.ResourcePath); + public static String alterRaceToWind(String s, XMLFileType fileType, double degrees) throws XMLReaderException, InvalidRaceDataException { - XMLRace race = XMLUtilities.xmlToClass( - RaceXMLCreator.class.getClassLoader().getResourceAsStream(s), - RaceXMLCreator.class.getClassLoader().getResource("mock/mockXML/schema/raceSchema.xsd"), - XMLRace.class); + RaceXMLReader reader = new RaceXMLReader(s, fileType); - setRaceXMLAtCurrentTimeToNow(race); + try { - double raceOriginalBearing = getLineAngle(getLeewardGate(reader).getMark1Position(), getWindwardGate(reader).getMark1Position()); + XMLRace race = XMLUtilities.xmlToClass( + s, + RaceXMLCreator.class.getClassLoader().getResource("mock/mockXML/schema/raceSchema.xsd"), + XMLRace.class); - double degreesToRotate = degrees - raceOriginalBearing; + setRaceXMLAtCurrentTimeToNow(race); - alterRaceRotation(race, degreesToRotate); + double raceOriginalBearing = getLineAngle(getLeewardGate(reader).getMark1Position(), getWindwardGate(reader).getMark1Position()); - return XMLUtilities.classToXML(race); + double degreesToRotate = degrees - raceOriginalBearing; + + alterRaceRotation(race, degreesToRotate); + + return XMLUtilities.classToXML(race); + + } catch (ParserConfigurationException | IOException | SAXException | JAXBException e) { + throw new InvalidRaceDataException("Could not parse or marshall race data file.", e); + } } /** diff --git a/racevisionGame/src/main/java/shared/xml/Race/XMLParticipants.java b/racevisionGame/src/main/java/shared/xml/Race/XMLParticipants.java index 331cc861..a7fd3a8f 100644 --- a/racevisionGame/src/main/java/shared/xml/Race/XMLParticipants.java +++ b/racevisionGame/src/main/java/shared/xml/Race/XMLParticipants.java @@ -50,7 +50,7 @@ import javax.xml.bind.annotation.XmlType; }) public class XMLParticipants { - @XmlElement(name = "Yacht", required = true) + @XmlElement(name = "Yacht", required = false) protected List yacht; /** diff --git a/racevisionGame/src/main/java/shared/xml/XMLUtilities.java b/racevisionGame/src/main/java/shared/xml/XMLUtilities.java index 6106f1ff..0b789235 100644 --- a/racevisionGame/src/main/java/shared/xml/XMLUtilities.java +++ b/racevisionGame/src/main/java/shared/xml/XMLUtilities.java @@ -49,7 +49,7 @@ public class XMLUtilities { return xmlToClass(document, schemaURL, c); } - public static Object xmlToClass(String xml, URL schemaURL, Class c) throws ParserConfigurationException, IOException, SAXException, JAXBException { + public static T xmlToClass(String xml, URL schemaURL, Class c) throws ParserConfigurationException, IOException, SAXException, JAXBException { DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document document = parser.parse(new InputSource(new ByteArrayInputStream(xml.getBytes("utf-8")))); diff --git a/racevisionGame/src/main/resources/mock/mockXML/schema/raceSchema.xsd b/racevisionGame/src/main/resources/mock/mockXML/schema/raceSchema.xsd index 3752209e..34d2a7dd 100644 --- a/racevisionGame/src/main/resources/mock/mockXML/schema/raceSchema.xsd +++ b/racevisionGame/src/main/resources/mock/mockXML/schema/raceSchema.xsd @@ -15,7 +15,7 @@ - + @@ -77,4 +77,4 @@ - \ No newline at end of file + From a1684a410c1e4ea5643793acea23a3e3685e29db Mon Sep 17 00:00:00 2001 From: fjc40 Date: Wed, 13 Sep 2017 00:43:38 +1200 Subject: [PATCH 5/9] Javadoc. --- .../src/main/java/shared/xml/regatta/ObjectFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/racevisionGame/src/main/java/shared/xml/regatta/ObjectFactory.java b/racevisionGame/src/main/java/shared/xml/regatta/ObjectFactory.java index 7fc72202..23c875e0 100644 --- a/racevisionGame/src/main/java/shared/xml/regatta/ObjectFactory.java +++ b/racevisionGame/src/main/java/shared/xml/regatta/ObjectFactory.java @@ -38,7 +38,7 @@ public class ObjectFactory { /** * Create an instance of {@link RegattaConfig } - * + * @return RegattaConfig. */ public RegattaConfig createRegattaConfig() { return new RegattaConfig(); From 2a6085c9e8954c4807fe6e961571478decd8f363 Mon Sep 17 00:00:00 2001 From: fjc40 Date: Wed, 13 Sep 2017 00:52:35 +1200 Subject: [PATCH 6/9] Test fix. --- .../shared/dataInput/RaceXMLReaderTest.java | 3 ++- .../test/resources/mock/mockXML/raceTest.xml | 17 +++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/racevisionGame/src/test/java/shared/dataInput/RaceXMLReaderTest.java b/racevisionGame/src/test/java/shared/dataInput/RaceXMLReaderTest.java index 1f4e72f6..b41e1376 100644 --- a/racevisionGame/src/test/java/shared/dataInput/RaceXMLReaderTest.java +++ b/racevisionGame/src/test/java/shared/dataInput/RaceXMLReaderTest.java @@ -1,5 +1,6 @@ package shared.dataInput; +import mock.app.Event; import shared.enums.XMLFileType; import shared.exceptions.InvalidRaceDataException; import shared.exceptions.XMLReaderException; @@ -16,7 +17,7 @@ public class RaceXMLReaderTest { String raceXMLString = null; try { - raceXMLString = XMLReader.readXMLFileToString("mock/mockXML/raceTest.xml", StandardCharsets.UTF_8); + raceXMLString = Event.setRaceXMLAtCurrentTimeToNow(XMLReader.readXMLFileToString("mock/mockXML/raceTest.xml", StandardCharsets.UTF_8)); } catch (XMLReaderException e) { throw new InvalidRaceDataException("Could not read race XML file into a string.", e); diff --git a/racevisionGame/src/test/resources/mock/mockXML/raceTest.xml b/racevisionGame/src/test/resources/mock/mockXML/raceTest.xml index b10a0158..6ae04ef8 100644 --- a/racevisionGame/src/test/resources/mock/mockXML/raceTest.xml +++ b/racevisionGame/src/test/resources/mock/mockXML/raceTest.xml @@ -2,17 +2,18 @@ 5326 FLEET - 2017-04-19T15:30:00+1200 - + RACE_CREATION_TIME + + - - - - - - + + + + + + From ab96884dc68740a30b2abfad7e25951395a5d58a Mon Sep 17 00:00:00 2001 From: fjc40 Date: Wed, 13 Sep 2017 12:10:36 +1200 Subject: [PATCH 7/9] Javadoc. --- racevisionGame/src/main/java/mock/app/Event.java | 1 + racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java | 1 + 2 files changed, 2 insertions(+) diff --git a/racevisionGame/src/main/java/mock/app/Event.java b/racevisionGame/src/main/java/mock/app/Event.java index 488eb0c0..af1d505a 100644 --- a/racevisionGame/src/main/java/mock/app/Event.java +++ b/racevisionGame/src/main/java/mock/app/Event.java @@ -73,6 +73,7 @@ public class Event { /** * Constructs an event, using various XML files. * @param singlePlayer Whether or not to create a single player event. + * @param mapIndex Specifies which map to use. * @throws EventConstructionException Thrown if we cannot create an Event for any reason. */ public Event(boolean singlePlayer, int mapIndex) throws EventConstructionException { diff --git a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java index 1e5407dc..c179617f 100644 --- a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java +++ b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java @@ -56,6 +56,7 @@ public class RaceXMLCreator { * @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. * @return the new xml file as a string * @throws XMLReaderException if the xml is not readable * @throws InvalidRaceDataException if the race is invalid From 2ad947b57d9b3bb813c4c5cd85e632910ddad1c3 Mon Sep 17 00:00:00 2001 From: fjc40 Date: Wed, 13 Sep 2017 12:59:51 +1200 Subject: [PATCH 8/9] The start time of the race is no longer scaled by the race speed scalar. Changed the prestart time to 30 seconds (was 3 minutes). Changed the preparatory time to 10 seconds (was 1 minute). Phases: player list +prestart > warning > race view + preparatory + no more joining > started > finished. --- racevisionGame/src/main/java/mock/app/Event.java | 6 +----- .../src/main/java/mock/model/SourceIdAllocator.java | 2 +- .../src/main/java/mock/xml/RaceXMLCreator.java | 2 -- .../src/main/java/shared/model/Constants.java | 12 +++++++----- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/racevisionGame/src/main/java/mock/app/Event.java b/racevisionGame/src/main/java/mock/app/Event.java index af1d505a..246816e5 100644 --- a/racevisionGame/src/main/java/mock/app/Event.java +++ b/racevisionGame/src/main/java/mock/app/Event.java @@ -78,8 +78,6 @@ public class Event { */ 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"; @@ -117,6 +115,7 @@ public class Event { if(mapIndex==4){ this.raceXML = Event.setRaceXMLAtCurrentTimeToNow(XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8), 1000, 5000); } + this.boatXML = XMLReader.readXMLFileToString(boatsXMLFile, StandardCharsets.UTF_8); this.regattaXML = XMLReader.readXMLFileToString(regattaXMLFile, StandardCharsets.UTF_8); @@ -192,7 +191,6 @@ public class Event { - //TODO remove this after demo on 18th august! /** * Sets the xml description of the race to show the race was created now, and starts in 4 minutes * @param raceXML The race.xml contents. @@ -209,8 +207,6 @@ public class Event { long secondsToAdd = millisecondsToAdd / 1000; - //Scale the time using our time scalar. - secondsToAdd = secondsToAdd / Constants.RaceTimeScale; DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ"); ZonedDateTime creationTime = ZonedDateTime.now(); diff --git a/racevisionGame/src/main/java/mock/model/SourceIdAllocator.java b/racevisionGame/src/main/java/mock/model/SourceIdAllocator.java index f590d9b7..f6370d6e 100644 --- a/racevisionGame/src/main/java/mock/model/SourceIdAllocator.java +++ b/racevisionGame/src/main/java/mock/model/SourceIdAllocator.java @@ -38,7 +38,7 @@ public class SourceIdAllocator { if (!((mockRace.getRaceStatusEnum() == RaceStatusEnum.PRESTART) || (mockRace.getRaceStatusEnum() == RaceStatusEnum.WARNING))) { - throw new SourceIDAllocationException("Could not allocate a source ID. Can only allocate during pre-start period. It is currently: " + mockRace.getRaceStatusEnum()); + throw new SourceIDAllocationException("Could not allocate a source ID. Can only allocate during pre-start or warning period. It is currently: " + mockRace.getRaceStatusEnum()); } List allocatedIDs = mockRace.getRaceDataSource().getParticipants(); diff --git a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java index c179617f..3e769571 100644 --- a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java +++ b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java @@ -195,8 +195,6 @@ public class RaceXMLCreator { //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; - //Scale the time using our time scalar. - secondsToAdd = secondsToAdd / Constants.RaceTimeScale; DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ"); ZonedDateTime creationTime = ZonedDateTime.now(); diff --git a/racevisionGame/src/main/java/shared/model/Constants.java b/racevisionGame/src/main/java/shared/model/Constants.java index 247b4c9b..d5ae2334 100644 --- a/racevisionGame/src/main/java/shared/model/Constants.java +++ b/racevisionGame/src/main/java/shared/model/Constants.java @@ -33,18 +33,20 @@ public class Constants { * Frame periods are multiplied by this to get the amount of time a single frame represents. * E.g., frame period = 20ms, scale = 5, frame represents 20 * 5 = 100ms, and so boats are simulated for 100ms, even though only 20ms actually occurred. */ - public static final int RaceTimeScale = 10;//10; + public static final int RaceTimeScale = 10; /** - * The race pre-start time, in milliseconds. 3 minutes. + * The race pre-start time, in milliseconds. + * Official time is 3 minutes. */ - public static final long RacePreStartTime = 3 * 60 * 1000; + public static final long RacePreStartTime = 30 * 1000; /** - * The race preparatory time, in milliseconds. 1 minute. + * The race preparatory time, in milliseconds. 10 seconds. + * Official time is 1 minute. */ - public static final long RacePreparatoryTime = 1 * 60 * 1000; + public static final long RacePreparatoryTime = 10 * 1000; From b655b3e2333e49c9de546c514828ed6c434ef556 Mon Sep 17 00:00:00 2001 From: fjc40 Date: Wed, 13 Sep 2017 14:52:21 +1200 Subject: [PATCH 9/9] Fixed merge bug, and an unrelated null pointer exception. --- racevisionGame/src/main/java/mock/app/Event.java | 3 +-- racevisionGame/src/main/java/mock/model/MockRace.java | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/racevisionGame/src/main/java/mock/app/Event.java b/racevisionGame/src/main/java/mock/app/Event.java index a382f29c..4a7b38cf 100644 --- a/racevisionGame/src/main/java/mock/app/Event.java +++ b/racevisionGame/src/main/java/mock/app/Event.java @@ -109,11 +109,10 @@ public class Event { try { //this.raceXML = XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8); + this.raceXML = Event.setRaceXMLAtCurrentTimeToNow(XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8)); this.raceXML = RaceXMLCreator.alterRaceToWind(this.raceXML, XMLFileType.Contents, 300, false); if(mapIndex==4){ this.raceXML = Event.setRaceXMLAtCurrentTimeToNow(XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8), 1000, 5000); - } else { - this.raceXML = Event.setRaceXMLAtCurrentTimeToNow(XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8)); } this.boatXML = XMLReader.readXMLFileToString(boatsXMLFile, StandardCharsets.UTF_8); diff --git a/racevisionGame/src/main/java/mock/model/MockRace.java b/racevisionGame/src/main/java/mock/model/MockRace.java index 4319a5f6..1d966cd4 100644 --- a/racevisionGame/src/main/java/mock/model/MockRace.java +++ b/racevisionGame/src/main/java/mock/model/MockRace.java @@ -121,6 +121,7 @@ public class MockRace extends RaceState { //Construct a MockBoat using the Boat and Polars. MockBoat mockBoat = new MockBoat(boat, polars); mockBoat.setCurrentLeg(this.getLegs().get(0)); + mockBoat.setEstimatedTimeAtNextMark(this.getRaceClock().getCurrentTime()); //Update participant list. getRaceDataSource().getParticipants().add(sourceID);