From c633de21f50f5def04c438a62ebd3c15831cf574 Mon Sep 17 00:00:00 2001 From: hba56 Date: Wed, 2 Aug 2017 16:33:03 +1200 Subject: [PATCH 1/9] 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 2/9] 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 3/9] 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 4/9] 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 5/9] 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 6/9] 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 7/9] 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 8/9] 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 9/9] 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);