From c633de21f50f5def04c438a62ebd3c15831cf574 Mon Sep 17 00:00:00 2001 From: hba56 Date: Wed, 2 Aug 2017 16:33:03 +1200 Subject: [PATCH 01/28] added new methods to the mock boats to let them check which side a mark is on to them #story[1101] --- .../src/main/java/mock/model/MockBoat.java | 24 +++ .../test/java/mock/model/MockBoatTest.java | 153 +++++++++++++++++- 2 files changed, 175 insertions(+), 2 deletions(-) diff --git a/racevisionGame/src/main/java/mock/model/MockBoat.java b/racevisionGame/src/main/java/mock/model/MockBoat.java index c8c6825b..05efd0cf 100644 --- a/racevisionGame/src/main/java/mock/model/MockBoat.java +++ b/racevisionGame/src/main/java/mock/model/MockBoat.java @@ -203,4 +203,28 @@ public class MockBoat extends Boat { return distanceTravelledMeters; } + /** + * Check if a mark is on the port side of the boat + */ + public boolean isPortSide(Mark mark){ + //if this boat is lower than the mark check which way it is facing + if(this.getCurrentPosition().getLongitude() < mark.getPosition().getLongitude()){ + return this.getBearing().degrees() <= 180; + }else{ + return this.getBearing().degrees() > 180; + } + } + + /** + * Check if a mark is on the starboard side of the boat + */ + public boolean isStarboardSide(Mark mark){ + //if this boat is lower than the mark check which way it is facing + if(this.getCurrentPosition().getLongitude() < mark.getPosition().getLongitude()){ + return this.getBearing().degrees() >= 180; + }else{ + return this.getBearing().degrees() < 180; + } + } + } diff --git a/racevisionGame/src/test/java/mock/model/MockBoatTest.java b/racevisionGame/src/test/java/mock/model/MockBoatTest.java index b1ee551c..71b8f715 100644 --- a/racevisionGame/src/test/java/mock/model/MockBoatTest.java +++ b/racevisionGame/src/test/java/mock/model/MockBoatTest.java @@ -1,7 +1,156 @@ package mock.model; -import static org.junit.Assert.*; +import mock.dataInput.PolarParser; +import mock.exceptions.InvalidPolarFileException; +import org.junit.Before; +import org.junit.Test; +import shared.model.Bearing; +import shared.model.GPSCoordinate; +import shared.model.Mark; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; public class MockBoatTest { -//TODO + + /** + * boat made for testing + */ + private MockBoat firstTestBoat; + + private Mark markToTest; + + private GPSCoordinate highGPS; + private GPSCoordinate middleGPS; + private GPSCoordinate lowGPS; + + /** + * Creates the Polars object for the tests. + */ + @Before + public void setUp() { + //Read in polars. + try { + //Parse data file. + Polars polars = PolarParser.parse("mock/polars/acc_polars.csv"); + + firstTestBoat = new MockBoat(1, "test", "NZ", polars); + highGPS = new GPSCoordinate(100, 100); + middleGPS = new GPSCoordinate(100, 75); + lowGPS = new GPSCoordinate(100, 50); + markToTest = new Mark(1, "test MARK", middleGPS); + } + catch (InvalidPolarFileException e) { + fail("Couldn't parse polar file."); + } + } + + //////////////////////////////Mark Higher//////////////////////////////// + + /** + * Tests if the boat is lower than the mark that the port side method works if + * boat is facing east + */ + @Test + public void testIsPortSide() { + firstTestBoat.setBearing(Bearing.fromDegrees(90)); + firstTestBoat.setCurrentPosition(lowGPS); + markToTest.setPosition(highGPS); + + assertEquals(firstTestBoat.isPortSide(markToTest), true); + } + + /** + * Tests if the boat is lower than the mark that the port side method works if + * boat is facing west + */ + @Test + public void testIsPortSideWrong() { + firstTestBoat.setBearing(Bearing.fromDegrees(270)); + firstTestBoat.setCurrentPosition(lowGPS); + markToTest.setPosition(highGPS); + + assertEquals(firstTestBoat.isPortSide(markToTest), false); + } + + /** + * Tests if the boat is lower than the mark that the starboard side method works if + * boat is facing east + */ + @Test + public void testIsStarboardSideWrong() { + firstTestBoat.setBearing(Bearing.fromDegrees(90)); + firstTestBoat.setCurrentPosition(lowGPS); + markToTest.setPosition(highGPS); + + assertEquals(firstTestBoat.isStarboardSide(markToTest), false); + } + + /** + * Tests if the boat is lower than the mark that the starboard side method works if + * boat is facing west + */ + @Test + public void testIsStarboardSide() { + firstTestBoat.setBearing(Bearing.fromDegrees(270)); + firstTestBoat.setCurrentPosition(lowGPS); + markToTest.setPosition(highGPS); + + assertEquals(firstTestBoat.isStarboardSide(markToTest), true); + } + + + //////////////////////////////Mark Lower//////////////////////////////// + + /** + * Tests if the boat is higher than the mark that the port side method works if + * boat is facing east + */ + @Test + public void testIsPortSideHigherWrong() { + firstTestBoat.setBearing(Bearing.fromDegrees(90)); + firstTestBoat.setCurrentPosition(highGPS); + markToTest.setPosition(lowGPS); + + assertEquals(firstTestBoat.isPortSide(markToTest), false); + } + + /** + * Tests if the boat is higher than the mark that the port side method works if + * boat is facing west + */ + @Test + public void testIsPortSideHigher() { + firstTestBoat.setBearing(Bearing.fromDegrees(270)); + firstTestBoat.setCurrentPosition(highGPS); + markToTest.setPosition(lowGPS); + + assertEquals(firstTestBoat.isPortSide(markToTest), true); + } + + /** + * Tests if the boat is higher than the mark that the starboard side method works if + * boat is facing east + */ + @Test + public void testIsStarboardSideHigher() { + firstTestBoat.setBearing(Bearing.fromDegrees(90)); + firstTestBoat.setCurrentPosition(highGPS); + markToTest.setPosition(lowGPS); + + assertEquals(firstTestBoat.isStarboardSide(markToTest), true); + } + + /** + * Tests if the boat is higher than the mark that the starboard side method works if + * boat is facing west + */ + @Test + public void testIsStarboardSideHigherWrong() { + firstTestBoat.setBearing(Bearing.fromDegrees(270)); + firstTestBoat.setCurrentPosition(highGPS); + markToTest.setPosition(lowGPS); + + assertEquals(firstTestBoat.isStarboardSide(markToTest), false); + } } From 13922bc2841591178c95602159ca8d9cf88e0b03 Mon Sep 17 00:00:00 2001 From: hba56 Date: Wed, 2 Aug 2017 17:06:52 +1200 Subject: [PATCH 02/28] updated javadoc #story[1101] --- racevisionGame/src/main/java/mock/model/MockBoat.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/racevisionGame/src/main/java/mock/model/MockBoat.java b/racevisionGame/src/main/java/mock/model/MockBoat.java index 05efd0cf..44e8e4e6 100644 --- a/racevisionGame/src/main/java/mock/model/MockBoat.java +++ b/racevisionGame/src/main/java/mock/model/MockBoat.java @@ -205,6 +205,7 @@ public class MockBoat extends Boat { /** * Check if a mark is on the port side of the boat + * @param mark mark to be passed */ public boolean isPortSide(Mark mark){ //if this boat is lower than the mark check which way it is facing @@ -217,6 +218,7 @@ public class MockBoat extends Boat { /** * Check if a mark is on the starboard side of the boat + * @param mark mark to be passed */ public boolean isStarboardSide(Mark mark){ //if this boat is lower than the mark check which way it is facing From b7af4e19cfcfb4ce56776b8c39b802f79df2cf2f Mon Sep 17 00:00:00 2001 From: hba56 Date: Wed, 2 Aug 2017 18:09:12 +1200 Subject: [PATCH 03/28] new method to check if a boat is between gates as well as updated the gps values to fit better with real life values #story[1101] --- .../src/main/java/mock/model/MockBoat.java | 16 +++++++++++++ .../test/java/mock/model/MockBoatTest.java | 24 ++++++++++++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/racevisionGame/src/main/java/mock/model/MockBoat.java b/racevisionGame/src/main/java/mock/model/MockBoat.java index 44e8e4e6..97fe68ef 100644 --- a/racevisionGame/src/main/java/mock/model/MockBoat.java +++ b/racevisionGame/src/main/java/mock/model/MockBoat.java @@ -206,6 +206,7 @@ public class MockBoat extends Boat { /** * Check if a mark is on the port side of the boat * @param mark mark to be passed + * @return true if mark is on port side */ public boolean isPortSide(Mark mark){ //if this boat is lower than the mark check which way it is facing @@ -219,6 +220,7 @@ public class MockBoat extends Boat { /** * Check if a mark is on the starboard side of the boat * @param mark mark to be passed + * @return true if mark is on starboard side */ public boolean isStarboardSide(Mark mark){ //if this boat is lower than the mark check which way it is facing @@ -229,4 +231,18 @@ public class MockBoat extends Boat { } } + /** + * Used to check if this boat is between a gate + * @param gate the gate to be checked + * @return true if the boat is between two marks that make up a gate + */ + public boolean isBetweenGate(CompoundMark gate){ + if ((this.isPortSide(gate.getMark1()) && this.isStarboardSide(gate.getMark2())) || + (this.isStarboardSide(gate.getMark2()) && this.isPortSide(gate.getMark1()))){ + return true; + }else{ + return false; + } + } + } diff --git a/racevisionGame/src/test/java/mock/model/MockBoatTest.java b/racevisionGame/src/test/java/mock/model/MockBoatTest.java index 71b8f715..32c28ce1 100644 --- a/racevisionGame/src/test/java/mock/model/MockBoatTest.java +++ b/racevisionGame/src/test/java/mock/model/MockBoatTest.java @@ -5,6 +5,7 @@ import mock.exceptions.InvalidPolarFileException; import org.junit.Before; import org.junit.Test; import shared.model.Bearing; +import shared.model.CompoundMark; import shared.model.GPSCoordinate; import shared.model.Mark; @@ -19,6 +20,7 @@ public class MockBoatTest { private MockBoat firstTestBoat; private Mark markToTest; + private Mark markToTest2; private GPSCoordinate highGPS; private GPSCoordinate middleGPS; @@ -35,10 +37,11 @@ public class MockBoatTest { Polars polars = PolarParser.parse("mock/polars/acc_polars.csv"); firstTestBoat = new MockBoat(1, "test", "NZ", polars); - highGPS = new GPSCoordinate(100, 100); - middleGPS = new GPSCoordinate(100, 75); - lowGPS = new GPSCoordinate(100, 50); + highGPS = new GPSCoordinate(-64.854000, 32.296577); + middleGPS = new GPSCoordinate(-64.854000, 32.292500); + lowGPS = new GPSCoordinate(-64.854000, 32.290000); markToTest = new Mark(1, "test MARK", middleGPS); + markToTest2 = new Mark(2, "test MARK2", middleGPS); } catch (InvalidPolarFileException e) { fail("Couldn't parse polar file."); @@ -153,4 +156,19 @@ public class MockBoatTest { assertEquals(firstTestBoat.isStarboardSide(markToTest), false); } + + /** + * Tests if a boat is between a gate + */ + @Test + public void testIsBetweenGate(){ + markToTest.setPosition(highGPS); + markToTest2.setPosition(lowGPS); + CompoundMark testGate = new CompoundMark(1, "test GATE", markToTest, markToTest2); + + firstTestBoat.setCurrentPosition(middleGPS); + + assertEquals(firstTestBoat.isBetweenGate(testGate), true); + + } } From f212414bd99f5c4273e945fb9b325799e6ef6e40 Mon Sep 17 00:00:00 2001 From: hba56 Date: Thu, 3 Aug 2017 13:27:00 +1200 Subject: [PATCH 04/28] Added in a new basis for boats to round marks, gave mockboats a status to say how far through a rounding they are and made a method in GPScoordinate public so it can be used to calculate intersections. This branch will not run the game any more as boats can't move on to the next leg until they can be controlled by the user. #story[1087] --- .../src/main/java/mock/model/MockBoat.java | 19 ++++ .../src/main/java/mock/model/MockRace.java | 105 +++++++++++++++--- .../main/java/shared/model/GPSCoordinate.java | 2 +- 3 files changed, 110 insertions(+), 16 deletions(-) diff --git a/racevisionGame/src/main/java/mock/model/MockBoat.java b/racevisionGame/src/main/java/mock/model/MockBoat.java index 97fe68ef..2874aa30 100644 --- a/racevisionGame/src/main/java/mock/model/MockBoat.java +++ b/racevisionGame/src/main/java/mock/model/MockBoat.java @@ -22,6 +22,14 @@ public class MockBoat extends Boat { */ private long timeSinceTackChange = 0; + /** + * This stores the boats current status of rounding a mark + * 0: not started rounding + * 1: passed only first check + * 2: passed first and second check + */ + private Integer roundingStatus; + /** @@ -245,4 +253,15 @@ public class MockBoat extends Boat { } } + public Integer getRoundingStatus() { + return Integer.valueOf(roundingStatus); + } + + public void increaseRoundingStatus() { + this.roundingStatus++; + } + + public void resetRoundingStatus() { + this.roundingStatus = 0; + } } diff --git a/racevisionGame/src/main/java/mock/model/MockRace.java b/racevisionGame/src/main/java/mock/model/MockRace.java index ad259bdc..3c394767 100644 --- a/racevisionGame/src/main/java/mock/model/MockRace.java +++ b/racevisionGame/src/main/java/mock/model/MockRace.java @@ -771,39 +771,60 @@ public class MockRace extends Race { } - /** * Checks if a boat has finished any legs, or has pulled out of race (DNF). * @param boat The boat to check. * @param timeElapsed The total time, in milliseconds, that has elapsed since the race started. */ - protected void checkPosition(MockBoat boat, long timeElapsed) { + protected void checkPosition(MockBoat boat, long timeElapsed) {//TODO cater for gates and rounding that aren't port side //The distance, in nautical miles, within which the boat needs to get in order to consider that it has reached the marker. - double epsilonNauticalMiles = 100.0 / Constants.NMToMetersConversion; //100 meters. TODO should be more like 5-10. + double epsilonNauticalMiles = 250.0 / Constants.NMToMetersConversion; //250 meters. if (boat.calculateDistanceToNextMarker() < epsilonNauticalMiles) { - //Boat has reached its target marker, and has moved on to a new leg. - + //Boat is within an acceptable distance from the mark. + GPSCoordinate startDirectionLinePoint = boat.getCurrentLeg().getStartCompoundMark().getMark1Position(); + //todo will need to change this for gates, so that the end point is the side of the gate needed to be rounded + GPSCoordinate endDirectionLinePoint = boat.getCurrentLeg().getEndCompoundMark().getMark1Position(); - //Calculate how much the boat overshot the marker by. - double overshootMeters = boat.calculateDistanceToNextMarker(); + 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 + GPSCoordinate roundCheck1 = GPSCoordinate.calculateNewPosition(startDirectionLinePoint, + epsilonNauticalMiles, Azimuth.fromDegrees(bearingOfDirectionLine.degrees() + 90));//adding 90 so the check line is parallel - //Move boat on to next leg. - Leg nextLeg = this.legs.get(boat.getCurrentLeg().getLegNumber() + 1); - boat.setCurrentLeg(nextLeg); + GPSCoordinate roundCheck2 = GPSCoordinate.calculateNewPosition(startDirectionLinePoint, + epsilonNauticalMiles, Azimuth.fromDegrees(bearingOfDirectionLine.degrees())); - //Add overshoot distance into the distance travelled for the next leg. - boat.setDistanceTravelledInLeg(overshootMeters); - //Setting a high value for this allows the boat to immediately do a large turn, as it needs to in order to get to the next mark. - boat.setTimeSinceTackChange(999999); + //boats must pass all checks in order to round a mark + switch (boat.getRoundingStatus()){ + case 0://hasn't started rounding + if (boat.isPortSide(boat.getCurrentLeg().getEndCompoundMark().getMark1()) && + GPSCoordinate.intersects(boat.getCurrentLeg().getEndCompoundMark().getMark1().getPosition(), + roundCheck1, boat.getCurrentPosition())){ + boat.increaseRoundingStatus(); + } + break; + case 1://has been parallel to the mark + if (boat.isPortSide(boat.getCurrentLeg().getEndCompoundMark().getMark1()) && + GPSCoordinate.intersects(boat.getCurrentLeg().getEndCompoundMark().getMark1().getPosition(), + roundCheck2, boat.getCurrentPosition())){ + boat.increaseRoundingStatus(); + } + break; + case 2://has traveled 180 degrees around the mark + //Move boat on to next leg. + boat.resetRoundingStatus(); + Leg nextLeg = this.legs.get(boat.getCurrentLeg().getLegNumber() + 1); + boat.setCurrentLeg(nextLeg); + break; + } //Check if the boat has finished or stopped racing. - if (this.isLastLeg(boat.getCurrentLeg())) { //Boat has finished. boat.setTimeFinished(timeElapsed); @@ -824,6 +845,60 @@ public class MockRace extends Race { } +//old method fo checking if boats passed a mark +// +// /** +// * Checks if a boat has finished any legs, or has pulled out of race (DNF). +// * @param boat The boat to check. +// * @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 epsilonNauticalMiles = 100.0 / Constants.NMToMetersConversion; //100 meters. TODO should be more like 5-10. +// +// if (boat.calculateDistanceToNextMarker() < epsilonNauticalMiles) { +// //Boat has reached its target marker, and has moved on to a new leg. +// +// +// +// //Calculate how much the boat overshot the marker by. +// double overshootMeters = boat.calculateDistanceToNextMarker(); +// +// +// //Move boat on to next leg. +// Leg nextLeg = this.legs.get(boat.getCurrentLeg().getLegNumber() + 1); +// boat.setCurrentLeg(nextLeg); +// +// //Add overshoot distance into the distance travelled for the next leg. +// boat.setDistanceTravelledInLeg(overshootMeters); +// +// //Setting a high value for this allows the boat to immediately do a large turn, as it needs to in order to get to the next mark. +// boat.setTimeSinceTackChange(999999); +// +// +// //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); +// +// } else if (doNotFinish()) { +// //Boat has pulled out of race. +// boat.setTimeFinished(timeElapsed); +// boat.setCurrentLeg(new Leg("DNF", -1)); +// boat.setCurrentSpeed(0); +// boat.setStatus(BoatStatusEnum.DNF); +// +// } +// +// } +// +// } + + /** diff --git a/racevisionGame/src/main/java/shared/model/GPSCoordinate.java b/racevisionGame/src/main/java/shared/model/GPSCoordinate.java index ee5eaaff..566413c6 100644 --- a/racevisionGame/src/main/java/shared/model/GPSCoordinate.java +++ b/racevisionGame/src/main/java/shared/model/GPSCoordinate.java @@ -142,7 +142,7 @@ public class GPSCoordinate { * @param coordinate The coordinate to test. * @return true if a line from the point intersects the two boundary points */ - private static boolean intersects(GPSCoordinate boundaryA, GPSCoordinate boundaryB, GPSCoordinate coordinate) { + public static boolean intersects(GPSCoordinate boundaryA, GPSCoordinate boundaryB, GPSCoordinate coordinate) { double boundaryALat = boundaryA.getLatitude(); double boundaryALon = boundaryA.getLongitude(); double boundaryBLat = boundaryB.getLatitude(); From be8b0e672dfb2c77be2283e66ef89687d694bb02 Mon Sep 17 00:00:00 2001 From: hba56 Date: Fri, 4 Aug 2017 22:01:21 +1200 Subject: [PATCH 05/28] Updated the xml reader to pull in the rounding type of the compound marks and set each mark with that value #story[1101] --- .../java/shared/dataInput/RaceXMLReader.java | 15 ++++++++ .../main/java/shared/enums/RoundingType.java | 34 +++++++++++++++++++ .../main/java/shared/model/CompoundMark.java | 23 +++++++++++++ .../src/main/java/shared/model/Mark.java | 1 - 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 racevisionGame/src/main/java/shared/enums/RoundingType.java diff --git a/racevisionGame/src/main/java/shared/dataInput/RaceXMLReader.java b/racevisionGame/src/main/java/shared/dataInput/RaceXMLReader.java index 7e61b3de..a270056a 100644 --- a/racevisionGame/src/main/java/shared/dataInput/RaceXMLReader.java +++ b/racevisionGame/src/main/java/shared/dataInput/RaceXMLReader.java @@ -5,6 +5,7 @@ import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import shared.enums.RoundingType; import shared.enums.XMLFileType; import shared.exceptions.InvalidRaceDataException; import shared.exceptions.XMLReaderException; @@ -313,6 +314,8 @@ public class RaceXMLReader extends XMLReader implements RaceDataSource { return element.getAttribute("Name"); } + private String getCompoundMarkRounding(Element element){return element.getAttribute("Rounding");} + /** * Populates list of legs given CompoundMarkSequence element and referenced CompoundMark elements. @@ -331,12 +334,18 @@ public class RaceXMLReader extends XMLReader implements RaceDataSource { //Gets the ID number of this corner element. int cornerID = getCompoundMarkID(cornerElement); + //gets the Rounding of this corner element + String cornerRounding = getCompoundMarkRounding(cornerElement); + //Gets the CompoundMark associated with this corner. CompoundMark lastCompoundMark = this.compoundMarkMap.get(cornerID); //The name of the leg is the name of the first compoundMark in the leg. String legName = lastCompoundMark.getName(); + //Sets the rounding type of this compound mark + lastCompoundMark.setRoundingType(RoundingType.valueOf(cornerRounding)); + //For each following corner, create a leg between cornerN and cornerN+1. for(int i = 1; i < corners.getLength(); i++) { @@ -346,9 +355,15 @@ public class RaceXMLReader extends XMLReader implements RaceDataSource { //Gets the ID number of this corner element. cornerID = getCompoundMarkID(cornerElement); + //gets the Rounding of this corner element + cornerRounding = getCompoundMarkRounding(cornerElement); + //Gets the CompoundMark associated with this corner. CompoundMark currentCompoundMark = this.compoundMarkMap.get(cornerID); + //Sets the rounding type of this compound mark + currentCompoundMark.setRoundingType(RoundingType.valueOf(cornerRounding)); + //Create a leg from these two adjacent compound marks. Leg leg = new Leg(legName, lastCompoundMark, currentCompoundMark, i - 1); legs.add(leg); diff --git a/racevisionGame/src/main/java/shared/enums/RoundingType.java b/racevisionGame/src/main/java/shared/enums/RoundingType.java new file mode 100644 index 00000000..eaba4e73 --- /dev/null +++ b/racevisionGame/src/main/java/shared/enums/RoundingType.java @@ -0,0 +1,34 @@ +package shared.enums; + +/** + * Enum for the types of rounding that can be done + */ +public enum RoundingType { + /** + * This is means it must be rounded port side + */ + Port, + + /** + * This is means it must be rounded starboard side + */ + Starboard, + + /** + * The boat within the compound mark with the SeqID + * of 1 should be rounded to starboard and the boat + * within the compound mark with the SeqID of 2 should + * be rounded to port. + */ + SP, + + /** + * The boat within the compound mark with the SeqID + * of 1 should be rounded to port and the boat + * within the compound mark with the SeqID of 2 should + * be rounded to starboard. + * + * opposite of SP + */ + PS; +} diff --git a/racevisionGame/src/main/java/shared/model/CompoundMark.java b/racevisionGame/src/main/java/shared/model/CompoundMark.java index b9f45753..38e972dc 100644 --- a/racevisionGame/src/main/java/shared/model/CompoundMark.java +++ b/racevisionGame/src/main/java/shared/model/CompoundMark.java @@ -1,6 +1,8 @@ package shared.model; +import shared.enums.RoundingType; + /** * Represents a compound mark - that is, either one or two individual marks which form a single compound mark. */ @@ -31,6 +33,11 @@ public class CompoundMark { */ private GPSCoordinate averageGPSCoordinate; + /** + * The side that the mark must be rounded on + */ + private RoundingType roundingType; + /** * Constructs a compound mark from a single mark. @@ -141,4 +148,20 @@ public class CompoundMark { return averageCoordinate; } + + /** + * Used to get how this mark should be rounded + * @return rounding type for mark + */ + public RoundingType getRoundingType() { + return roundingType; + } + + /** + * Used to set the type of rounding for this mark + * @param roundingType rounding type to set + */ + public void setRoundingType(RoundingType roundingType) { + this.roundingType = roundingType; + } } diff --git a/racevisionGame/src/main/java/shared/model/Mark.java b/racevisionGame/src/main/java/shared/model/Mark.java index 5781861a..19dc8f26 100644 --- a/racevisionGame/src/main/java/shared/model/Mark.java +++ b/racevisionGame/src/main/java/shared/model/Mark.java @@ -22,7 +22,6 @@ public class Mark { private GPSCoordinate position; - /** * Constructs a mark with a given source ID, name, and position. * @param sourceID The source ID of the mark. From db1efab225d31ca3b6d99d8865fc423d68e603df Mon Sep 17 00:00:00 2001 From: hba56 Date: Fri, 4 Aug 2017 22:17:17 +1200 Subject: [PATCH 06/28] rounding checks are now done by port or starboard side depending on what the compound marks type is #story[1101] --- .../src/main/java/mock/model/MockRace.java | 93 ++++++++++++++----- 1 file changed, 71 insertions(+), 22 deletions(-) diff --git a/racevisionGame/src/main/java/mock/model/MockRace.java b/racevisionGame/src/main/java/mock/model/MockRace.java index 3c394767..448344a6 100644 --- a/racevisionGame/src/main/java/mock/model/MockRace.java +++ b/racevisionGame/src/main/java/mock/model/MockRace.java @@ -4,18 +4,17 @@ import javafx.animation.AnimationTimer; import network.Messages.BoatLocation; import network.Messages.BoatStatus; import network.Messages.Enums.BoatStatusEnum; +import network.Messages.Enums.RaceStatusEnum; 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; import shared.dataInput.RegattaDataSource; import shared.model.*; import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; -import java.time.temporal.TemporalUnit; import java.util.*; import static java.lang.Math.cos; @@ -771,6 +770,68 @@ public class MockRace extends Race { } + /** + * 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 + */ + private void boatRoundingCheckPort(MockBoat boat, List roundingChecks){ + //boats must pass all checks in order to round a mark + switch (boat.getRoundingStatus()) { + case 0://hasn't started rounding + if (boat.isPortSide(boat.getCurrentLeg().getEndCompoundMark().getMark1()) && + GPSCoordinate.intersects(boat.getCurrentLeg().getEndCompoundMark().getMark1().getPosition(), + roundingChecks.get(0), boat.getCurrentPosition())) { + boat.increaseRoundingStatus(); + } + break; + case 1://has been parallel to the mark + if (boat.isPortSide(boat.getCurrentLeg().getEndCompoundMark().getMark1()) && + GPSCoordinate.intersects(boat.getCurrentLeg().getEndCompoundMark().getMark1().getPosition(), + roundingChecks.get(1), boat.getCurrentPosition())) { + boat.increaseRoundingStatus(); + } + break; + case 2://has traveled 180 degrees around the mark + //Move boat on to next leg. + boat.resetRoundingStatus(); + Leg nextLeg = this.legs.get(boat.getCurrentLeg().getLegNumber() + 1); + boat.setCurrentLeg(nextLeg); + break; + } + } + + /** + * 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 + */ + private void boatRoundingCheckStarboard(MockBoat boat, List roundingChecks){ + //boats must pass all checks in order to round a mark + switch (boat.getRoundingStatus()) { + case 0://hasn't started rounding + if (boat.isStarboardSide(boat.getCurrentLeg().getEndCompoundMark().getMark1()) && + GPSCoordinate.intersects(boat.getCurrentLeg().getEndCompoundMark().getMark1().getPosition(), + roundingChecks.get(0), boat.getCurrentPosition())) { + boat.increaseRoundingStatus(); + } + break; + case 1://has been parallel to the mark + if (boat.isStarboardSide(boat.getCurrentLeg().getEndCompoundMark().getMark1()) && + GPSCoordinate.intersects(boat.getCurrentLeg().getEndCompoundMark().getMark1().getPosition(), + roundingChecks.get(1), boat.getCurrentPosition())) { + boat.increaseRoundingStatus(); + } + break; + case 2://has traveled 180 degrees around the mark + //Move boat on to next leg. + boat.resetRoundingStatus(); + Leg nextLeg = this.legs.get(boat.getCurrentLeg().getLegNumber() + 1); + boat.setCurrentLeg(nextLeg); + break; + } + } + /** * Checks if a boat has finished any legs, or has pulled out of race (DNF). * @param boat The boat to check. @@ -798,28 +859,16 @@ public class MockRace extends Race { GPSCoordinate roundCheck2 = GPSCoordinate.calculateNewPosition(startDirectionLinePoint, epsilonNauticalMiles, Azimuth.fromDegrees(bearingOfDirectionLine.degrees())); + List roundingChecks = new ArrayList(Arrays.asList(roundCheck1, roundCheck2)); - //boats must pass all checks in order to round a mark - switch (boat.getRoundingStatus()){ - case 0://hasn't started rounding - if (boat.isPortSide(boat.getCurrentLeg().getEndCompoundMark().getMark1()) && - GPSCoordinate.intersects(boat.getCurrentLeg().getEndCompoundMark().getMark1().getPosition(), - roundCheck1, boat.getCurrentPosition())){ - boat.increaseRoundingStatus(); - } - break; - case 1://has been parallel to the mark - if (boat.isPortSide(boat.getCurrentLeg().getEndCompoundMark().getMark1()) && - GPSCoordinate.intersects(boat.getCurrentLeg().getEndCompoundMark().getMark1().getPosition(), - roundCheck2, boat.getCurrentPosition())){ - boat.increaseRoundingStatus(); - } + switch (boat.getCurrentLeg().getEndCompoundMark().getRoundingType()) { + case SP://Not yet implemented so these gates will be rounded port side + case Port: + boatRoundingCheckPort(boat, roundingChecks); break; - case 2://has traveled 180 degrees around the mark - //Move boat on to next leg. - boat.resetRoundingStatus(); - Leg nextLeg = this.legs.get(boat.getCurrentLeg().getLegNumber() + 1); - boat.setCurrentLeg(nextLeg); + case PS://not yet implemented so these gates will be rounded starboard side + case Starboard: + boatRoundingCheckStarboard(boat, roundingChecks); break; } From 0b74acadff0488e2f61359a55567031851c09f3a Mon Sep 17 00:00:00 2001 From: hba56 Date: Fri, 4 Aug 2017 22:19:07 +1200 Subject: [PATCH 07/28] rounding checks are now done by port or starboard side depending on what the compound marks type is #story[1101] --- racevisionGame/src/main/java/mock/model/MockRace.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/racevisionGame/src/main/java/mock/model/MockRace.java b/racevisionGame/src/main/java/mock/model/MockRace.java index 448344a6..25997ebd 100644 --- a/racevisionGame/src/main/java/mock/model/MockRace.java +++ b/racevisionGame/src/main/java/mock/model/MockRace.java @@ -837,7 +837,7 @@ public class MockRace extends Race { * @param boat The boat to check. * @param timeElapsed The total time, in milliseconds, that has elapsed since the race started. */ - protected void checkPosition(MockBoat boat, long timeElapsed) {//TODO cater for gates and rounding that aren't port side + protected void checkPosition(MockBoat boat, long timeElapsed) {//TODO cater for gates (SP or PS in the switch) //The distance, in nautical miles, within which the boat needs to get in order to consider that it has reached the marker. double epsilonNauticalMiles = 250.0 / Constants.NMToMetersConversion; //250 meters. @@ -861,7 +861,7 @@ public class MockRace extends Race { List roundingChecks = new ArrayList(Arrays.asList(roundCheck1, roundCheck2)); - switch (boat.getCurrentLeg().getEndCompoundMark().getRoundingType()) { + switch (boat.getCurrentLeg().getEndCompoundMark().getRoundingType()) {//todo may need to implement SP and PS case SP://Not yet implemented so these gates will be rounded port side case Port: boatRoundingCheckPort(boat, roundingChecks); From 950a801d1609b09e7ef2465be97f239da810daa7 Mon Sep 17 00:00:00 2001 From: hba56 Date: Mon, 7 Aug 2017 12:16:37 +1200 Subject: [PATCH 08/28] rounding fix for the xml #story[1087] --- .idea/codeStyleSettings.xml | 6 ++++++ .../src/main/java/mock/model/MockBoat.java | 2 +- .../src/main/java/mock/model/MockRace.java | 3 +++ .../main/java/shared/dataInput/RaceXMLReader.java | 3 ++- .../src/main/java/shared/enums/RoundingType.java | 15 +++++++++++++++ .../src/main/resources/mock/mockXML/raceTest.xml | 12 ++++++------ 6 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 .idea/codeStyleSettings.xml diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml new file mode 100644 index 00000000..5352bdf8 --- /dev/null +++ b/.idea/codeStyleSettings.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/racevisionGame/src/main/java/mock/model/MockBoat.java b/racevisionGame/src/main/java/mock/model/MockBoat.java index 2874aa30..795e2675 100644 --- a/racevisionGame/src/main/java/mock/model/MockBoat.java +++ b/racevisionGame/src/main/java/mock/model/MockBoat.java @@ -28,7 +28,7 @@ public class MockBoat extends Boat { * 1: passed only first check * 2: passed first and second check */ - private Integer roundingStatus; + private Integer roundingStatus = 0; diff --git a/racevisionGame/src/main/java/mock/model/MockRace.java b/racevisionGame/src/main/java/mock/model/MockRace.java index 25997ebd..a3be5381 100644 --- a/racevisionGame/src/main/java/mock/model/MockRace.java +++ b/racevisionGame/src/main/java/mock/model/MockRace.java @@ -779,6 +779,7 @@ public class MockRace extends Race { //boats must pass all checks in order to round a mark switch (boat.getRoundingStatus()) { case 0://hasn't started rounding + System.out.println("round 0"); if (boat.isPortSide(boat.getCurrentLeg().getEndCompoundMark().getMark1()) && GPSCoordinate.intersects(boat.getCurrentLeg().getEndCompoundMark().getMark1().getPosition(), roundingChecks.get(0), boat.getCurrentPosition())) { @@ -786,6 +787,7 @@ public class MockRace extends Race { } break; case 1://has been parallel to the mark + System.out.println("round 1"); if (boat.isPortSide(boat.getCurrentLeg().getEndCompoundMark().getMark1()) && GPSCoordinate.intersects(boat.getCurrentLeg().getEndCompoundMark().getMark1().getPosition(), roundingChecks.get(1), boat.getCurrentPosition())) { @@ -793,6 +795,7 @@ public class MockRace extends Race { } break; case 2://has traveled 180 degrees around the mark + System.out.println("round 2"); //Move boat on to next leg. boat.resetRoundingStatus(); Leg nextLeg = this.legs.get(boat.getCurrentLeg().getLegNumber() + 1); diff --git a/racevisionGame/src/main/java/shared/dataInput/RaceXMLReader.java b/racevisionGame/src/main/java/shared/dataInput/RaceXMLReader.java index a270056a..135cd988 100644 --- a/racevisionGame/src/main/java/shared/dataInput/RaceXMLReader.java +++ b/racevisionGame/src/main/java/shared/dataInput/RaceXMLReader.java @@ -344,7 +344,8 @@ public class RaceXMLReader extends XMLReader implements RaceDataSource { String legName = lastCompoundMark.getName(); //Sets the rounding type of this compound mark - lastCompoundMark.setRoundingType(RoundingType.valueOf(cornerRounding)); + + lastCompoundMark.setRoundingType(RoundingType.getValueOf(cornerRounding)); //For each following corner, create a leg between cornerN and cornerN+1. for(int i = 1; i < corners.getLength(); i++) { diff --git a/racevisionGame/src/main/java/shared/enums/RoundingType.java b/racevisionGame/src/main/java/shared/enums/RoundingType.java index eaba4e73..8f8e719a 100644 --- a/racevisionGame/src/main/java/shared/enums/RoundingType.java +++ b/racevisionGame/src/main/java/shared/enums/RoundingType.java @@ -31,4 +31,19 @@ public enum RoundingType { * opposite of SP */ PS; + + public static RoundingType getValueOf(String value) { + switch (value) { + case "Port": + return RoundingType.Port; + case "Starboard": + return RoundingType.Starboard; + case "SP": + return RoundingType.Port; + case "PS": + return RoundingType.Starboard; + default: + return null; + } + } } diff --git a/racevisionGame/src/main/resources/mock/mockXML/raceTest.xml b/racevisionGame/src/main/resources/mock/mockXML/raceTest.xml index 83e36f85..e068e9b8 100644 --- a/racevisionGame/src/main/resources/mock/mockXML/raceTest.xml +++ b/racevisionGame/src/main/resources/mock/mockXML/raceTest.xml @@ -8,12 +8,12 @@ - - - - - - + + + + + + From 4195d41814021cd1ba6f7e27e82d104bcd196f30 Mon Sep 17 00:00:00 2001 From: hba56 Date: Mon, 7 Aug 2017 12:28:44 +1200 Subject: [PATCH 09/28] removed outdated comments #story[1087] --- racevisionGame/src/main/java/mock/model/MockBoat.java | 2 ++ racevisionGame/src/main/java/mock/model/MockRace.java | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/racevisionGame/src/main/java/mock/model/MockBoat.java b/racevisionGame/src/main/java/mock/model/MockBoat.java index 795e2675..214d9c10 100644 --- a/racevisionGame/src/main/java/mock/model/MockBoat.java +++ b/racevisionGame/src/main/java/mock/model/MockBoat.java @@ -71,6 +71,8 @@ public class MockBoat extends Boat { //Get the start and end points. GPSCoordinate currentPosition = this.getCurrentPosition(); GPSCoordinate nextMarkerPosition = this.getCurrentLeg().getEndCompoundMark().getAverageGPSCoordinate(); +// GPSCoordinate nextMarkerPosition = this.getCurrentLeg().getEndCompoundMark().getMark1Position(); +// todo:may need to change this so that boats are send to corners of the gates rather than the middle //Calculate bearing. Bearing bearing = GPSCoordinate.calculateBearing(currentPosition, nextMarkerPosition); diff --git a/racevisionGame/src/main/java/mock/model/MockRace.java b/racevisionGame/src/main/java/mock/model/MockRace.java index a3be5381..c534219b 100644 --- a/racevisionGame/src/main/java/mock/model/MockRace.java +++ b/racevisionGame/src/main/java/mock/model/MockRace.java @@ -779,7 +779,7 @@ public class MockRace extends Race { //boats must pass all checks in order to round a mark switch (boat.getRoundingStatus()) { case 0://hasn't started rounding - System.out.println("round 0"); +// System.out.println("round 0"); if (boat.isPortSide(boat.getCurrentLeg().getEndCompoundMark().getMark1()) && GPSCoordinate.intersects(boat.getCurrentLeg().getEndCompoundMark().getMark1().getPosition(), roundingChecks.get(0), boat.getCurrentPosition())) { @@ -787,7 +787,7 @@ public class MockRace extends Race { } break; case 1://has been parallel to the mark - System.out.println("round 1"); +// System.out.println("round 1"); if (boat.isPortSide(boat.getCurrentLeg().getEndCompoundMark().getMark1()) && GPSCoordinate.intersects(boat.getCurrentLeg().getEndCompoundMark().getMark1().getPosition(), roundingChecks.get(1), boat.getCurrentPosition())) { @@ -795,7 +795,7 @@ public class MockRace extends Race { } break; case 2://has traveled 180 degrees around the mark - System.out.println("round 2"); +// System.out.println("round 2"); //Move boat on to next leg. boat.resetRoundingStatus(); Leg nextLeg = this.legs.get(boat.getCurrentLeg().getLegNumber() + 1); @@ -840,7 +840,7 @@ public class MockRace extends Race { * @param boat The boat to check. * @param timeElapsed The total time, in milliseconds, that has elapsed since the race started. */ - protected void checkPosition(MockBoat boat, long timeElapsed) {//TODO cater for gates (SP or PS in the switch) + 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 = 250.0 / Constants.NMToMetersConversion; //250 meters. @@ -864,7 +864,7 @@ public class MockRace extends Race { List roundingChecks = new ArrayList(Arrays.asList(roundCheck1, roundCheck2)); - switch (boat.getCurrentLeg().getEndCompoundMark().getRoundingType()) {//todo may need to implement SP and PS + switch (boat.getCurrentLeg().getEndCompoundMark().getRoundingType()) { case SP://Not yet implemented so these gates will be rounded port side case Port: boatRoundingCheckPort(boat, roundingChecks); From 62752c142a3842a3518ee271b0a7702457284ece Mon Sep 17 00:00:00 2001 From: hba56 Date: Mon, 7 Aug 2017 12:47:55 +1200 Subject: [PATCH 10/28] building blocks for drawing the race line around the course #story[1087] --- racevisionGame/src/main/java/shared/model/Race.java | 7 +++++++ .../java/visualiser/model/ResizableRaceCanvas.java | 13 +++++++++++++ 2 files changed, 20 insertions(+) diff --git a/racevisionGame/src/main/java/shared/model/Race.java b/racevisionGame/src/main/java/shared/model/Race.java index 415e9f77..8b327fb4 100644 --- a/racevisionGame/src/main/java/shared/model/Race.java +++ b/racevisionGame/src/main/java/shared/model/Race.java @@ -323,6 +323,13 @@ public abstract class Race implements Runnable { return lastFps; } + /** + * Returns the legs of this race + * @return list of legs + */ + public List getLegs() { + return legs; + } /** * Increments the FPS counter, and adds timePeriod milliseconds to our FPS reset timer. diff --git a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java index 7664f854..386468c8 100644 --- a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java +++ b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java @@ -1,6 +1,7 @@ package visualiser.model; +import javafx.collections.ObservableList; import javafx.scene.Node; import javafx.scene.image.Image; import javafx.scene.paint.Color; @@ -9,6 +10,7 @@ import javafx.scene.transform.Rotate; import network.Messages.Enums.BoatStatusEnum; import shared.dataInput.RaceDataSource; import shared.model.GPSCoordinate; +import shared.model.Leg; import shared.model.Mark; import shared.model.RaceClock; @@ -516,6 +518,17 @@ public class ResizableRaceCanvas extends ResizableCanvas { } + /** + * draws a transparent line around the course that shows the paths boats must travel + */ + public void drawRaceLine(){ + List legs = this.visualiserRace.getLegs(); + + for (Leg leg: legs) { + //todo calculate and draw line around this leg + } + + } /** * Draws the race boundary image onto the canvas. From 2920b6cf235039c344c8158269083e51754afdd9 Mon Sep 17 00:00:00 2001 From: cbt24 Date: Mon, 7 Aug 2017 16:47:25 +1200 Subject: [PATCH 11/28] Removed build-breaking code from MockRace #story[1096] --- .../src/main/java/mock/model/MockRace.java | 83 ------------------- 1 file changed, 83 deletions(-) diff --git a/racevisionGame/src/main/java/mock/model/MockRace.java b/racevisionGame/src/main/java/mock/model/MockRace.java index 3a6ad64a..fe1a60c1 100644 --- a/racevisionGame/src/main/java/mock/model/MockRace.java +++ b/racevisionGame/src/main/java/mock/model/MockRace.java @@ -575,13 +575,6 @@ public class MockRace extends Race { boat.setCurrentSpeed(0); boat.setStatus(BoatStatusEnum.FINISHED); - } else if (doNotFinish()) { - //Boat has pulled out of race. - boat.setTimeFinished(timeElapsed); - boat.setCurrentLeg(new Leg("DNF", -1)); - boat.setCurrentSpeed(0); - boat.setStatus(BoatStatusEnum.DNF); - } } @@ -589,82 +582,6 @@ public class MockRace extends Race { } -//old method fo checking if boats passed a mark -// -// /** -// * Checks if a boat has finished any legs, or has pulled out of race (DNF). -// * @param boat The boat to check. -// * @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 epsilonNauticalMiles = 100.0 / Constants.NMToMetersConversion; //100 meters. TODO should be more like 5-10. -// -// if (boat.calculateDistanceToNextMarker() < epsilonNauticalMiles) { -// //Boat has reached its target marker, and has moved on to a new leg. -// -// -// -// //Calculate how much the boat overshot the marker by. -// double overshootMeters = boat.calculateDistanceToNextMarker(); -// -// -// //Move boat on to next leg. -// Leg nextLeg = this.legs.get(boat.getCurrentLeg().getLegNumber() + 1); -// boat.setCurrentLeg(nextLeg); -// -// //Add overshoot distance into the distance travelled for the next leg. -// boat.setDistanceTravelledInLeg(overshootMeters); -// -// //Setting a high value for this allows the boat to immediately do a large turn, as it needs to in order to get to the next mark. -// boat.setTimeSinceTackChange(999999); -// -// -// //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); -// -// } else if (doNotFinish()) { -// //Boat has pulled out of race. -// boat.setTimeFinished(timeElapsed); -// boat.setCurrentLeg(new Leg("DNF", -1)); -// boat.setCurrentSpeed(0); -// boat.setStatus(BoatStatusEnum.DNF); -// -// } -// -// } -// -// } - - - - - /** - * Sets the chance each boat has of failing at a gate or marker - * - * @param chance percentage chance a boat has of failing per checkpoint. - */ - protected void setDnfChance(int chance) { - if (chance >= 0 && chance <= 100) { - dnfChance = chance; - } - } - - /** - * Decides if a boat should received a DNF status. - * @return True means it should DNF, false means it shouldn't. - */ - protected boolean doNotFinish() { - Random rand = new Random(); - return rand.nextInt(100) < dnfChance; - } - /** From ef3f468b19e9caaa8de5ce17bc541e86d560ba3e Mon Sep 17 00:00:00 2001 From: hba56 Date: Tue, 8 Aug 2017 00:02:07 +1200 Subject: [PATCH 12/28] arrows displayed for each leg #story[1101] --- .../visualiser/model/ResizableRaceCanvas.java | 72 ++++++++++++++++--- 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java index 386468c8..10ff60ec 100644 --- a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java +++ b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java @@ -1,7 +1,6 @@ package visualiser.model; -import javafx.collections.ObservableList; import javafx.scene.Node; import javafx.scene.image.Image; import javafx.scene.paint.Color; @@ -9,12 +8,8 @@ import javafx.scene.paint.Paint; import javafx.scene.transform.Rotate; import network.Messages.Enums.BoatStatusEnum; import shared.dataInput.RaceDataSource; -import shared.model.GPSCoordinate; -import shared.model.Leg; -import shared.model.Mark; -import shared.model.RaceClock; +import shared.model.*; -import java.time.Duration; import java.util.List; /** @@ -513,6 +508,9 @@ public class ResizableRaceCanvas extends ResizableCanvas { //Marks. drawMarks(); + //Guiding Line + drawRaceLine(); + //Wind arrow. This rotates the wind arrow node. displayWindArrow(this.visualiserRace.getWindDirection().degrees()); @@ -523,11 +521,67 @@ public class ResizableRaceCanvas extends ResizableCanvas { */ public void drawRaceLine(){ List legs = this.visualiserRace.getLegs(); - - for (Leg leg: legs) { - //todo calculate and draw line around this leg + for (int i = 0; i < legs.size() -1; i++) { + drawLineRounding(legs.get(i)); } + } + + private void drawLineRounding(Leg leg){ + //finds the direction of the leg as a bearing + GPSCoordinate startDirectionLinePoint = leg.getStartCompoundMark().getAverageGPSCoordinate(); + GPSCoordinate endDirectionLinePoint = leg.getEndCompoundMark().getAverageGPSCoordinate(); + Bearing bearingOfDirectionLine = GPSCoordinate.calculateBearing(startDirectionLinePoint, endDirectionLinePoint); + + //use the direction line to find a point parallel to it by the mark + GPSCoordinate pointToStartCurve = GPSCoordinate.calculateNewPosition(endDirectionLinePoint, + 150, Azimuth.fromDegrees(bearingOfDirectionLine.degrees()+90)); + + //use the direction line to find a point to curve too + GPSCoordinate pointToEndCurve = GPSCoordinate.calculateNewPosition(endDirectionLinePoint, + 150, Azimuth.fromDegrees(bearingOfDirectionLine.degrees())); + + //use the curve points to find the two control points for the bezier curve + Bearing bearingOfCurveLine = GPSCoordinate.calculateBearing(pointToStartCurve, pointToEndCurve); + GPSCoordinate controlPoint1 = GPSCoordinate.calculateNewPosition(pointToStartCurve, + 150, Azimuth.fromDegrees(bearingOfCurveLine.degrees()+ 50)); + + //change all gps into graph coordinate + GraphCoordinate startPath = this.map.convertGPS(startDirectionLinePoint); + GraphCoordinate curvePoint = this.map.convertGPS(pointToStartCurve); + GraphCoordinate curvePointEnd = this.map.convertGPS(pointToEndCurve); + GraphCoordinate c1 = this.map.convertGPS(controlPoint1); + + gc.setStroke(Color.RED); + gc.setLineWidth(1); + + gc.beginPath(); + gc.moveTo(startPath.getX(), startPath.getY()); + gc.lineTo(curvePoint.getX(), curvePoint.getY()); + gc.bezierCurveTo(c1.getX(), c1.getY(), c1.getX(), c1.getY(), curvePointEnd.getX(), curvePointEnd.getY()); + gc.stroke(); + gc.closePath(); + gc.save(); + + drawArrowHead(controlPoint1, pointToEndCurve); + } + + private void drawArrowHead(GPSCoordinate start, GPSCoordinate end){ + + GraphCoordinate lineStart = this.map.convertGPS(start); + GraphCoordinate lineEnd = this.map.convertGPS(end); + + double arrowAngle = Math.toRadians(45.0); + double arrowLength = 10.0; + double dx = lineStart.getX() - lineEnd.getX(); + double dy = lineStart.getY() - lineEnd.getY(); + double angle = Math.atan2(dy, dx); + double x1 = Math.cos(angle + arrowAngle) * arrowLength + lineEnd.getX(); + double y1 = Math.sin(angle + arrowAngle) * arrowLength + lineEnd.getY(); + double x2 = Math.cos(angle - arrowAngle) * arrowLength + lineEnd.getX(); + double y2 = Math.sin(angle - arrowAngle) * arrowLength + lineEnd.getY(); + gc.strokeLine(lineEnd.getX(), lineEnd.getY(), x1, y1); + gc.strokeLine(lineEnd.getX(), lineEnd.getY(), x2, y2); } /** From 22722286ef40602e231b0fda5d4c11500bbce4c0 Mon Sep 17 00:00:00 2001 From: hba56 Date: Tue, 8 Aug 2017 14:47:11 +1200 Subject: [PATCH 13/28] all paths now join up #story[1087] --- .../visualiser/model/ResizableRaceCanvas.java | 109 ++++++++++++------ 1 file changed, 74 insertions(+), 35 deletions(-) diff --git a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java index 10ff60ec..2263de91 100644 --- a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java +++ b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java @@ -521,48 +521,87 @@ public class ResizableRaceCanvas extends ResizableCanvas { */ public void drawRaceLine(){ List legs = this.visualiserRace.getLegs(); + GPSCoordinate legStartPoint = legs.get(0).getStartCompoundMark().getAverageGPSCoordinate(); + GPSCoordinate nextStartPoint; for (int i = 0; i < legs.size() -1; i++) { - drawLineRounding(legs.get(i)); + nextStartPoint = drawLineRounding(legs, i, legStartPoint); + legStartPoint = nextStartPoint; } } - private void drawLineRounding(Leg leg){ - //finds the direction of the leg as a bearing - GPSCoordinate startDirectionLinePoint = leg.getStartCompoundMark().getAverageGPSCoordinate(); - GPSCoordinate endDirectionLinePoint = leg.getEndCompoundMark().getAverageGPSCoordinate(); - Bearing bearingOfDirectionLine = GPSCoordinate.calculateBearing(startDirectionLinePoint, endDirectionLinePoint); - - //use the direction line to find a point parallel to it by the mark - GPSCoordinate pointToStartCurve = GPSCoordinate.calculateNewPosition(endDirectionLinePoint, - 150, Azimuth.fromDegrees(bearingOfDirectionLine.degrees()+90)); - - //use the direction line to find a point to curve too - GPSCoordinate pointToEndCurve = GPSCoordinate.calculateNewPosition(endDirectionLinePoint, - 150, Azimuth.fromDegrees(bearingOfDirectionLine.degrees())); - - //use the curve points to find the two control points for the bezier curve - Bearing bearingOfCurveLine = GPSCoordinate.calculateBearing(pointToStartCurve, pointToEndCurve); - GPSCoordinate controlPoint1 = GPSCoordinate.calculateNewPosition(pointToStartCurve, - 150, Azimuth.fromDegrees(bearingOfCurveLine.degrees()+ 50)); - - //change all gps into graph coordinate - GraphCoordinate startPath = this.map.convertGPS(startDirectionLinePoint); - GraphCoordinate curvePoint = this.map.convertGPS(pointToStartCurve); - GraphCoordinate curvePointEnd = this.map.convertGPS(pointToEndCurve); - GraphCoordinate c1 = this.map.convertGPS(controlPoint1); + /** + * Draws a line around a course that shows where boats need to go. This method + * draws the line leg by leg + * @param legs the legs of a race + * @param index the index of the current leg to use + * @return the end point of the current leg that has been drawn + */ + private GPSCoordinate drawLineRounding(List legs, int index, GPSCoordinate legStartPoint){ + GPSCoordinate startDirectionLinePoint; + GPSCoordinate endDirectionLinePoint; + Bearing bearingOfDirectionLine; + + GPSCoordinate startNextDirectionLinePoint; + GPSCoordinate endNextDirectionLinePoint; + Bearing bearingOfNextDirectionLine; + + //finds the direction of the current leg as a bearing + startDirectionLinePoint = legStartPoint; + endDirectionLinePoint = legs.get(index).getEndCompoundMark().getMark1Position(); + bearingOfDirectionLine = GPSCoordinate.calculateBearing(startDirectionLinePoint, endDirectionLinePoint); + + //finds the direction of the next leg as a bearing + if (index < legs.size() -2){ // not last leg + startNextDirectionLinePoint = legs.get(index + 1).getStartCompoundMark().getMark1Position(); + endNextDirectionLinePoint = legs.get(index + 1).getEndCompoundMark().getMark1Position(); + bearingOfNextDirectionLine = GPSCoordinate.calculateBearing(startNextDirectionLinePoint, endNextDirectionLinePoint); + + //use the direction line to find a point parallel to it by the mark + GPSCoordinate pointToStartCurve = GPSCoordinate.calculateNewPosition(endDirectionLinePoint, + 150, Azimuth.fromDegrees(bearingOfDirectionLine.degrees()+90)); + + //use the direction line to find a point to curve too + GPSCoordinate pointToEndCurve = GPSCoordinate.calculateNewPosition(endDirectionLinePoint, + 150, Azimuth.fromDegrees(bearingOfNextDirectionLine.degrees()+90)); + + //use the curve points to find the two control points for the bezier curve + Bearing bearingOfCurveLine = GPSCoordinate.calculateBearing(pointToStartCurve, pointToEndCurve); + GPSCoordinate controlPoint = GPSCoordinate.calculateNewPosition(pointToStartCurve, + 75, Azimuth.fromDegrees(bearingOfCurveLine.degrees()+ 50)); + + //change all gps into graph coordinate + GraphCoordinate startPath = this.map.convertGPS(startDirectionLinePoint); + GraphCoordinate curvePoint = this.map.convertGPS(pointToStartCurve); + GraphCoordinate curvePointEnd = this.map.convertGPS(pointToEndCurve); + GraphCoordinate c1 = this.map.convertGPS(controlPoint); + + gc.setStroke(Color.RED); + gc.setLineWidth(1); + + gc.beginPath(); + gc.moveTo(startPath.getX(), startPath.getY()); + gc.lineTo(curvePoint.getX(), curvePoint.getY()); + gc.bezierCurveTo(c1.getX(), c1.getY(), c1.getX(), c1.getY(), curvePointEnd.getX(), curvePointEnd.getY()); + gc.stroke(); + gc.closePath(); + gc.save(); - gc.setStroke(Color.RED); - gc.setLineWidth(1); + drawArrowHead(controlPoint, pointToEndCurve); - gc.beginPath(); - gc.moveTo(startPath.getX(), startPath.getY()); - gc.lineTo(curvePoint.getX(), curvePoint.getY()); - gc.bezierCurveTo(c1.getX(), c1.getY(), c1.getX(), c1.getY(), curvePointEnd.getX(), curvePointEnd.getY()); - gc.stroke(); - gc.closePath(); - gc.save(); + return pointToEndCurve; + }else{//last leg so no curve + GraphCoordinate startPath = this.map.convertGPS(legStartPoint); + GraphCoordinate endPath = this.map.convertGPS(legs.get(index).getEndCompoundMark().getAverageGPSCoordinate()); - drawArrowHead(controlPoint1, pointToEndCurve); + gc.beginPath(); + gc.moveTo(startPath.getX(), startPath.getY()); + gc.lineTo(endPath.getX(), endPath.getY()); + gc.stroke(); + gc.closePath(); + gc.save(); + drawArrowHead(legStartPoint, legs.get(index).getEndCompoundMark().getAverageGPSCoordinate()); + return null; + } } private void drawArrowHead(GPSCoordinate start, GPSCoordinate end){ From bb75806781f46618deaf0c3ce4b4469db6efbc51 Mon Sep 17 00:00:00 2001 From: hba56 Date: Tue, 8 Aug 2017 23:23:46 +1200 Subject: [PATCH 14/28] Cleaned up line to be in a shippable shape #story[1101] --- .../visualiser/model/ResizableRaceCanvas.java | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java index 2263de91..379f99e5 100644 --- a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java +++ b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java @@ -3,8 +3,7 @@ package visualiser.model; import javafx.scene.Node; import javafx.scene.image.Image; -import javafx.scene.paint.Color; -import javafx.scene.paint.Paint; +import javafx.scene.paint.*; import javafx.scene.transform.Rotate; import network.Messages.Enums.BoatStatusEnum; import shared.dataInput.RaceDataSource; @@ -502,15 +501,15 @@ public class ResizableRaceCanvas extends ResizableCanvas { //Race boundary. drawBoundary(); + //Guiding Line + drawRaceLine(); + //Boats. drawBoats(); //Marks. drawMarks(); - //Guiding Line - drawRaceLine(); - //Wind arrow. This rotates the wind arrow node. displayWindArrow(this.visualiserRace.getWindDirection().degrees()); @@ -558,36 +557,49 @@ public class ResizableRaceCanvas extends ResizableCanvas { //use the direction line to find a point parallel to it by the mark GPSCoordinate pointToStartCurve = GPSCoordinate.calculateNewPosition(endDirectionLinePoint, - 150, Azimuth.fromDegrees(bearingOfDirectionLine.degrees()+90)); + 100, Azimuth.fromDegrees(bearingOfDirectionLine.degrees()+90)); //use the direction line to find a point to curve too GPSCoordinate pointToEndCurve = GPSCoordinate.calculateNewPosition(endDirectionLinePoint, - 150, Azimuth.fromDegrees(bearingOfNextDirectionLine.degrees()+90)); + 100, Azimuth.fromDegrees(bearingOfNextDirectionLine.degrees()+90)); //use the curve points to find the two control points for the bezier curve + GPSCoordinate controlPoint; + GPSCoordinate controlPoint2; Bearing bearingOfCurveLine = GPSCoordinate.calculateBearing(pointToStartCurve, pointToEndCurve); - GPSCoordinate controlPoint = GPSCoordinate.calculateNewPosition(pointToStartCurve, - 75, Azimuth.fromDegrees(bearingOfCurveLine.degrees()+ 50)); + if ((bearingOfDirectionLine.degrees() - bearingOfNextDirectionLine.degrees() +360)%360< 145){ + //small turn + controlPoint = GPSCoordinate.calculateNewPosition(pointToStartCurve, + 50, Azimuth.fromDegrees(bearingOfCurveLine.degrees()+45)); + controlPoint2 = controlPoint; + }else{ + //large turn + controlPoint = GPSCoordinate.calculateNewPosition(pointToStartCurve, + 150, Azimuth.fromDegrees(bearingOfCurveLine.degrees()+90)); + controlPoint2 = GPSCoordinate.calculateNewPosition(pointToEndCurve, + 150, Azimuth.fromDegrees(bearingOfCurveLine.degrees()+90)); + } + //change all gps into graph coordinate GraphCoordinate startPath = this.map.convertGPS(startDirectionLinePoint); GraphCoordinate curvePoint = this.map.convertGPS(pointToStartCurve); GraphCoordinate curvePointEnd = this.map.convertGPS(pointToEndCurve); GraphCoordinate c1 = this.map.convertGPS(controlPoint); + GraphCoordinate c2 = this.map.convertGPS(controlPoint2); - gc.setStroke(Color.RED); - gc.setLineWidth(1); + gc.setLineWidth(2); + gc.setStroke(Color.MEDIUMAQUAMARINE); gc.beginPath(); gc.moveTo(startPath.getX(), startPath.getY()); gc.lineTo(curvePoint.getX(), curvePoint.getY()); - gc.bezierCurveTo(c1.getX(), c1.getY(), c1.getX(), c1.getY(), curvePointEnd.getX(), curvePointEnd.getY()); + drawArrowHead(startDirectionLinePoint, pointToStartCurve); + gc.bezierCurveTo(c1.getX(), c1.getY(), c2.getX(), c2.getY(), curvePointEnd.getX(), curvePointEnd.getY()); gc.stroke(); gc.closePath(); gc.save(); - drawArrowHead(controlPoint, pointToEndCurve); - return pointToEndCurve; }else{//last leg so no curve GraphCoordinate startPath = this.map.convertGPS(legStartPoint); From e53d72f24b722c79e333e3917e6473925eca84d8 Mon Sep 17 00:00:00 2001 From: hba56 Date: Wed, 9 Aug 2017 23:25:42 +1200 Subject: [PATCH 15/28] compound marks now can give the mark they have that needs to be rounded this is used to draw the line around the correct mark #story[1101] --- .../main/java/shared/model/CompoundMark.java | 87 +++++++++++++++++++ .../visualiser/model/ResizableRaceCanvas.java | 32 +++++-- 2 files changed, 110 insertions(+), 9 deletions(-) diff --git a/racevisionGame/src/main/java/shared/model/CompoundMark.java b/racevisionGame/src/main/java/shared/model/CompoundMark.java index 38e972dc..05256655 100644 --- a/racevisionGame/src/main/java/shared/model/CompoundMark.java +++ b/racevisionGame/src/main/java/shared/model/CompoundMark.java @@ -164,4 +164,91 @@ public class CompoundMark { public void setRoundingType(RoundingType roundingType) { this.roundingType = roundingType; } + + /** + * Used to find the mark that is to be rounded at a gate when approaching from the south + * will also give the single mark if there is only one + * @param bearing the bearing a boat will approach form + * @return the mark to round + */ + public Mark getMarkForRounding(Bearing bearing){ + Mark westMostMark; + Mark eastMostMark; + Mark northMostMark; + Mark southMostMark; + + //check to see if there are two marks + if (mark2 == null){ + return mark1; + } + + //finds the mark furthest west and east + if(this.getMark1Position().getLatitude() > this.getMark2Position().getLatitude()){ + westMostMark = this.mark1; + eastMostMark = this.mark2; + }else{ + westMostMark = this.mark2; + eastMostMark = this.mark1; + } + + //finds the mark furthest north and south + if(this.getMark1Position().getLongitude() > this.getMark2Position().getLongitude()){ + northMostMark = this.mark1; + southMostMark = this.mark2; + }else{ + northMostMark = this.mark2; + southMostMark = this.mark1; + } + + if (bearing.degrees() > 315 || bearing.degrees() <= 45){ + //north + switch (this.getRoundingType()){ + case SP: + case Port: + return westMostMark; + case PS: + case Starboard: + return eastMostMark; + default:return null; + } + }else if(bearing.degrees() > 45 && bearing.degrees() <= 135){ + //east + switch (this.getRoundingType()){ + case SP: + case Port: + return northMostMark; + case PS: + case Starboard: + return southMostMark; + default:return null; + } + }else if(bearing.degrees() > 135 && bearing.degrees() <= 225){ + //south + switch (this.getRoundingType()){ + case SP: + case Port: + return eastMostMark; + case PS: + case Starboard: + return westMostMark; + default:return null; + } + }else if(bearing.degrees() > 225 && bearing.degrees() <= 315){ + //west + switch (this.getRoundingType()){ + case SP: + case Port: + return southMostMark; + case PS: + case Starboard: + return northMostMark; + default:return null; + } + }else{ + return null; + } + + } + + } diff --git a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java index 96a8d6f9..333ed54b 100644 --- a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java +++ b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java @@ -1,12 +1,13 @@ package visualiser.model; -import javafx.scene.Node; import javafx.scene.image.Image; -import javafx.scene.paint.*; +import javafx.scene.paint.Color; +import javafx.scene.paint.Paint; import javafx.scene.transform.Rotate; import network.Messages.Enums.BoatStatusEnum; import shared.dataInput.RaceDataSource; +import shared.enums.RoundingType; import shared.model.*; import java.util.List; @@ -510,7 +511,12 @@ public class ResizableRaceCanvas extends ResizableCanvas { //finds the direction of the current leg as a bearing startDirectionLinePoint = legStartPoint; - endDirectionLinePoint = legs.get(index).getEndCompoundMark().getMark1Position(); + GPSCoordinate tempEndDirectionLinePoint = legs.get(index).getEndCompoundMark().getAverageGPSCoordinate(); + + bearingOfDirectionLine = GPSCoordinate.calculateBearing(startDirectionLinePoint, tempEndDirectionLinePoint); + + //after finding the initial bearing pick the mark used for rounding + endDirectionLinePoint = legs.get(index).getEndCompoundMark().getMarkForRounding(bearingOfDirectionLine).getPosition(); bearingOfDirectionLine = GPSCoordinate.calculateBearing(startDirectionLinePoint, endDirectionLinePoint); //finds the direction of the next leg as a bearing @@ -519,13 +525,22 @@ public class ResizableRaceCanvas extends ResizableCanvas { endNextDirectionLinePoint = legs.get(index + 1).getEndCompoundMark().getMark1Position(); bearingOfNextDirectionLine = GPSCoordinate.calculateBearing(startNextDirectionLinePoint, endNextDirectionLinePoint); + double degreesToAdd; + //find which side is need to be used + if (legs.get(index).getEndCompoundMark().getRoundingType() == RoundingType.Port || + legs.get(index).getEndCompoundMark().getRoundingType() == RoundingType.SP){ + degreesToAdd = 90; + }else{ + degreesToAdd = -90; + } + //use the direction line to find a point parallel to it by the mark GPSCoordinate pointToStartCurve = GPSCoordinate.calculateNewPosition(endDirectionLinePoint, - 100, Azimuth.fromDegrees(bearingOfDirectionLine.degrees()+90)); + 100, Azimuth.fromDegrees(bearingOfDirectionLine.degrees()+degreesToAdd)); //use the direction line to find a point to curve too GPSCoordinate pointToEndCurve = GPSCoordinate.calculateNewPosition(endDirectionLinePoint, - 100, Azimuth.fromDegrees(bearingOfNextDirectionLine.degrees()+90)); + 100, Azimuth.fromDegrees(bearingOfNextDirectionLine.degrees()+degreesToAdd)); //use the curve points to find the two control points for the bezier curve GPSCoordinate controlPoint; @@ -534,14 +549,14 @@ public class ResizableRaceCanvas extends ResizableCanvas { if ((bearingOfDirectionLine.degrees() - bearingOfNextDirectionLine.degrees() +360)%360< 145){ //small turn controlPoint = GPSCoordinate.calculateNewPosition(pointToStartCurve, - 50, Azimuth.fromDegrees(bearingOfCurveLine.degrees()+45)); + 50, Azimuth.fromDegrees(bearingOfCurveLine.degrees()+(degreesToAdd/2))); controlPoint2 = controlPoint; }else{ //large turn controlPoint = GPSCoordinate.calculateNewPosition(pointToStartCurve, - 150, Azimuth.fromDegrees(bearingOfCurveLine.degrees()+90)); + 150, Azimuth.fromDegrees(bearingOfCurveLine.degrees()+degreesToAdd)); controlPoint2 = GPSCoordinate.calculateNewPosition(pointToEndCurve, - 150, Azimuth.fromDegrees(bearingOfCurveLine.degrees()+90)); + 150, Azimuth.fromDegrees(bearingOfCurveLine.degrees()+degreesToAdd)); } @@ -618,7 +633,6 @@ public class ResizableRaceCanvas extends ResizableCanvas { * @see TrackPoint */ private void drawTrack(VisualiserBoat boat) { - //Check that track points are enabled. if (this.annoPath) { From 4da37348046ccb232a47b750e0542d7f61539178 Mon Sep 17 00:00:00 2001 From: hba56 Date: Thu, 10 Aug 2017 12:17:19 +1200 Subject: [PATCH 16/28] added the ability to toggle the race guide line on and off #story[1087] --- .../java/visualiser/model/Annotations.java | 11 ++++++++++ .../visualiser/model/ResizableRaceCanvas.java | 12 +++++++++- .../resources/visualiser/scenes/race.fxml | 22 ++++++++++++------- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/racevisionGame/src/main/java/visualiser/model/Annotations.java b/racevisionGame/src/main/java/visualiser/model/Annotations.java index 09e3831a..54976c35 100644 --- a/racevisionGame/src/main/java/visualiser/model/Annotations.java +++ b/racevisionGame/src/main/java/visualiser/model/Annotations.java @@ -40,6 +40,7 @@ public class Annotations { private static String pathCheckAnno = "showBoatPath"; private static String timeCheckAnno = "showTime"; private static String estTimeCheckAnno = "showEstTime"; + private static String guideLineAnno = "showGuideline"; // string values match the fx:id value of radio buttons private static String noBtn = "noBtn"; @@ -160,6 +161,16 @@ public class Annotations { raceMap.draw(); } }); + + //listener to show estimated time for annotation + checkBoxes.get(guideLineAnno).selectedProperty() + .addListener((ov, old_val, new_val) -> { + if (old_val != new_val) { + raceMap.toggleGuideLine(); + storeCurrentAnnotationState(guideLineAnno, new_val); + raceMap.draw(); + } + }); } /** diff --git a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java index 333ed54b..a44dd8eb 100644 --- a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java +++ b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java @@ -49,6 +49,7 @@ public class ResizableRaceCanvas extends ResizableCanvas { private boolean annoPath = true; private boolean annoEstTime = true; private boolean annoTimeSinceLastMark = true; + private boolean annoGuideLine = false; @@ -116,6 +117,13 @@ public class ResizableRaceCanvas extends ResizableCanvas { annoSpeed = !annoSpeed; } + /** + * Toggle the guideline annotation + */ + public void toggleGuideLine() { + annoGuideLine = !annoGuideLine; + } + @@ -470,7 +478,9 @@ public class ResizableRaceCanvas extends ResizableCanvas { drawBoundary(); //Guiding Line - drawRaceLine(); + if (annoGuideLine){ + drawRaceLine(); + } //Boats. drawBoats(); diff --git a/racevisionGame/src/main/resources/visualiser/scenes/race.fxml b/racevisionGame/src/main/resources/visualiser/scenes/race.fxml index 159d725c..d7615b76 100644 --- a/racevisionGame/src/main/resources/visualiser/scenes/race.fxml +++ b/racevisionGame/src/main/resources/visualiser/scenes/race.fxml @@ -1,12 +1,17 @@ + + + + - + + @@ -30,16 +35,17 @@ - -