From 9d02d2fbea64d465d88ffb301a99647a12624d0b Mon Sep 17 00:00:00 2001 From: alistairjmcintyre Date: Thu, 10 Aug 2017 02:04:51 +1200 Subject: [PATCH 1/7] Implemented a fairly simple auto pilot setting for the yacht, on update if the boat is set to autopilot it will adjust the heading towards the desired heading. Needs some refinement. #story[1105] --- .mailmap | 2 +- src/main/java/seng302/model/Yacht.java | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.mailmap b/.mailmap index cad3a3a8..caf8a624 100644 --- a/.mailmap +++ b/.mailmap @@ -23,5 +23,5 @@ Haoming Yin Peter Galloway Peter Zhi You Tan zyt10 Zhi You Tan Ryan Tan -Alistair McIntyre alistairjmcintyre +Alistair McIntyre Calum cir27 \ No newline at end of file diff --git a/src/main/java/seng302/model/Yacht.java b/src/main/java/seng302/model/Yacht.java index d7cd1f9e..9804314c 100644 --- a/src/main/java/seng302/model/Yacht.java +++ b/src/main/java/seng302/model/Yacht.java @@ -54,6 +54,9 @@ public class Yacht { private GeoPoint location; private Integer boatStatus; private Double velocity; + private Boolean isAuto; + private Double autoHeading; + //MARK ROUNDING INFO private GeoPoint lastLocation; //For purposes of mark rounding calculations private Boolean hasEnteredRoundingZone; //The distance that the boat must be from the mark to round @@ -78,6 +81,7 @@ public class Yacht { this.boatName = boatName; this.country = country; this.sailIn = false; + this.isAuto = false; this.location = new GeoPoint(57.670341, 11.826856); this.lastLocation = location; this.heading = 120.0; //In degrees @@ -121,6 +125,13 @@ public class Yacht { } } + if (isAuto) { + turnTowardsHeading(autoHeading); + if (Math.abs(heading - autoHeading) <= 5) { + isAuto = false; + } + } + //UPDATE BOAT LOCATION location = GeoUtility.getGeoCoordinate(location, heading, velocity * secondsElapsed); @@ -159,9 +170,18 @@ public class Yacht { heading = (double) Math.floorMod(newVal.longValue(), 360L); } + /** + * Should tell boat to auto pilot towards the autopilot heading. + */ public void tackGybe(Double windDirection) { Double normalizedHeading = normalizeHeading(); - adjustHeading(-2 * normalizedHeading); + setAutoPilot(-2 * normalizedHeading); + } + + private void setAutoPilot(Double thisHeading) { + isAuto = true; + Double newVal = heading + thisHeading; + autoHeading = (double) Math.floorMod(newVal.longValue(), 360L); } public void toggleSailIn() { From 430779c94375bd4664d1dc3b76724746c4eae026 Mon Sep 17 00:00:00 2001 From: Alistair McIntyre Date: Thu, 10 Aug 2017 14:53:24 +1200 Subject: [PATCH 2/7] Boat auto pilots correctly for tacking/gybing. Needs proper testing. #story[1105] --- src/main/java/seng302/model/Yacht.java | 86 +++++++++++++++++++------- 1 file changed, 63 insertions(+), 23 deletions(-) diff --git a/src/main/java/seng302/model/Yacht.java b/src/main/java/seng302/model/Yacht.java index 9804314c..e1d7f5da 100644 --- a/src/main/java/seng302/model/Yacht.java +++ b/src/main/java/seng302/model/Yacht.java @@ -48,7 +48,7 @@ public class Yacht { private Integer legNumber = 0; //SERVER SIDE - private final Double TURN_STEP = 5.0; + private final Double TURN_STEP = 3.0; private Double lastHeading; private Boolean sailIn; private GeoPoint location; @@ -102,6 +102,7 @@ public class Yacht { Double trueWindAngle = Math.abs(GameState.getWindDirection() - heading); Double boatSpeedInKnots = PolarTable.getBoatSpeed(windSpeedKnots, trueWindAngle); Double maxBoatSpeed = boatSpeedInKnots / 1.943844492 * 1000; + // TODO: 10/08/17 ajm412: this acceleration stuff should be its own method, and shouldn't have all these magic numbers, could possibly be modelled better. if (sailIn && velocity <= maxBoatSpeed && maxBoatSpeed != 0d) { if (velocity < maxBoatSpeed) { @@ -112,7 +113,6 @@ public class Yacht { } } else { // Deceleration - if (velocity > 0d) { if (maxBoatSpeed != 0d) { velocity -= maxBoatSpeed / 600; @@ -126,10 +126,7 @@ public class Yacht { } if (isAuto) { - turnTowardsHeading(autoHeading); - if (Math.abs(heading - autoHeading) <= 5) { - isAuto = false; - } + runAutoPilot(); } //UPDATE BOAT LOCATION @@ -144,7 +141,6 @@ public class Yacht { // TODO: 3/08/17 wmu16 - Implement line cross check here } - /** * Calculates the distance to the next mark (closest of the two if a gate mark). * @@ -164,6 +160,12 @@ public class Yacht { } } + /** + * Adjusts the heading of the boat by a given amount, while recording the boats + * last heading. + * + * @param amount the amount by which to adjust the boat heading. + */ public void adjustHeading(Double amount) { Double newVal = heading + amount; lastHeading = heading; @@ -171,17 +173,46 @@ public class Yacht { } /** - * Should tell boat to auto pilot towards the autopilot heading. + * Swaps the boats direction from one side of the wind to the other. */ public void tackGybe(Double windDirection) { Double normalizedHeading = normalizeHeading(); - setAutoPilot(-2 * normalizedHeading); + Double newVal = (-2 * normalizedHeading) + heading; + //newVal += heading; + Double newHeading = (double) Math.floorMod(newVal.longValue(), 360L); + setAutoPilot(newHeading); } + /** + * Enables the boats auto pilot feature, which will move the boat towards a given heading. + * @param thisHeading The heading to move the boat towards. + */ private void setAutoPilot(Double thisHeading) { isAuto = true; - Double newVal = heading + thisHeading; - autoHeading = (double) Math.floorMod(newVal.longValue(), 360L); + autoHeading = thisHeading; + } + + /** + * Disables the auto pilot function. + */ + public void disableAutoPilot() { + isAuto = false; + } + + /** + * Moves the boat towards the given heading when the auto pilot was set. Disables the auto pilot + * in the event that the boat is within the range of 1 turn step of its goal. + */ + private void runAutoPilot() { + if (autoHeading == null) { + isAuto = false; + // TODO: 10/08/17 possibly throw some sort of exception here maybe? autopilot shouldn't be true if there's no heading. + } + turnTowardsHeading(autoHeading); + if (Math.abs(heading - autoHeading) + <= TURN_STEP) { //Cancel when within 1 turn step of target. + isAuto = false; + } } public void toggleSailIn() { @@ -231,6 +262,7 @@ public class Yacht { } public void turnToVMG() { + // TODO: 10/08/17 ajm412: The way this works is absolute rubbish. Needs to determine upwind/downwind, then which side of the wind, then move to the correct values. Double normalizedHeading = normalizeHeading(); Double optimalHeading; HashMap optimalPolarMap; @@ -242,27 +274,37 @@ public class Yacht { optimalPolarMap = PolarTable.getOptimalUpwindVMG(GameState.getWindSpeedKnots()); optimalHeading = optimalPolarMap.keySet().iterator().next(); } - // Take optimal heading and turn into correct + + // Take optimal heading and turn into a boat heading rather than a wind heading. optimalHeading = optimalHeading + (double) Math.floorMod(GameState.getWindDirection().longValue(), 360L); - turnTowardsHeading(optimalHeading); - + setAutoPilot(optimalHeading); } + /** + * Takes a given heading and rotates the boat towards that heading. + * This does not care about being upwind or downwind, just which direction will reach a given + * heading faster. + * + * @param newHeading The heading to turn the yacht towards. + */ private void turnTowardsHeading(Double newHeading) { System.out.println(newHeading); - if (heading < 90 && newHeading > 270) { - adjustHeading(-TURN_STEP); + Double newVal = heading - newHeading; + if (Math.floorMod(newVal.longValue(), 360L) > 180) { + adjustHeading(TURN_STEP); } else { - if (heading < newHeading) { - adjustHeading(TURN_STEP); - } else { - adjustHeading(-TURN_STEP); - } + adjustHeading(-TURN_STEP); } } + /** + * Returns a heading normalized for the wind direction. Heading direction into the wind is 0, + * directly away is 180. + * + * @return The normalized heading accounting for wind direction. + */ private Double normalizeHeading() { Double normalizedHeading = heading - GameState.windDirection; normalizedHeading = (double) Math.floorMod(normalizedHeading.longValue(), 360L); @@ -431,7 +473,6 @@ public class Yacht { this.timeTillNext = timeTillNext; } - public Color getColour() { return colour; } @@ -440,7 +481,6 @@ public class Yacht { this.colour = colour; } - public Double getVelocity() { return velocity; } From a746191dba85ed7fbf6407bfe0e48f14a71d0492 Mon Sep 17 00:00:00 2001 From: Alistair McIntyre Date: Thu, 10 Aug 2017 17:46:28 +1200 Subject: [PATCH 3/7] VMG works correctly, auto pilot is interupted by a repeated keypress or an upwind/downwind press. tags: #story[1105] --- src/main/java/seng302/model/Yacht.java | 57 ++++++++++++++++---------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/src/main/java/seng302/model/Yacht.java b/src/main/java/seng302/model/Yacht.java index e1d7f5da..b7abf817 100644 --- a/src/main/java/seng302/model/Yacht.java +++ b/src/main/java/seng302/model/Yacht.java @@ -176,11 +176,14 @@ public class Yacht { * Swaps the boats direction from one side of the wind to the other. */ public void tackGybe(Double windDirection) { - Double normalizedHeading = normalizeHeading(); - Double newVal = (-2 * normalizedHeading) + heading; - //newVal += heading; - Double newHeading = (double) Math.floorMod(newVal.longValue(), 360L); - setAutoPilot(newHeading); + if (isAuto) { + disableAutoPilot(); + } else { + Double normalizedHeading = normalizeHeading(); + Double newVal = (-2 * normalizedHeading) + heading; + Double newHeading = (double) Math.floorMod(newVal.longValue(), 360L); + setAutoPilot(newHeading); + } } /** @@ -220,6 +223,7 @@ public class Yacht { } public void turnUpwind() { + disableAutoPilot(); Double normalizedHeading = normalizeHeading(); if (normalizedHeading == 0) { if (lastHeading < 180) { @@ -241,6 +245,7 @@ public class Yacht { } public void turnDownwind() { + disableAutoPilot(); Double normalizedHeading = normalizeHeading(); if (normalizedHeading == 0) { if (lastHeading < 180) { @@ -261,25 +266,36 @@ public class Yacht { } } + /** + * Takes the VMG from the polartable for upwind or downwind depending on the boats direction, + * and uses this to calculate a heading to move the yacht towards. + */ public void turnToVMG() { - // TODO: 10/08/17 ajm412: The way this works is absolute rubbish. Needs to determine upwind/downwind, then which side of the wind, then move to the correct values. - Double normalizedHeading = normalizeHeading(); - Double optimalHeading; - HashMap optimalPolarMap; - - if (normalizedHeading >= 90 && normalizedHeading <= 270) { // Downwind - optimalPolarMap = PolarTable.getOptimalDownwindVMG(GameState.getWindSpeedKnots()); - optimalHeading = optimalPolarMap.keySet().iterator().next(); + if (isAuto) { + disableAutoPilot(); } else { - optimalPolarMap = PolarTable.getOptimalUpwindVMG(GameState.getWindSpeedKnots()); + Double normalizedHeading = normalizeHeading(); + Double optimalHeading; + HashMap optimalPolarMap; + + if (normalizedHeading >= 90 && normalizedHeading <= 270) { // Downwind + optimalPolarMap = PolarTable.getOptimalDownwindVMG(GameState.getWindSpeedKnots()); + } else { + optimalPolarMap = PolarTable.getOptimalUpwindVMG(GameState.getWindSpeedKnots()); + } optimalHeading = optimalPolarMap.keySet().iterator().next(); + + if (normalizedHeading > 180) { + optimalHeading = 360 - optimalHeading; + } + + // Take optimal heading and turn into a boat heading rather than a wind heading. + optimalHeading = + optimalHeading + (double) Math + .floorMod(GameState.getWindDirection().longValue(), 360L); + + setAutoPilot(optimalHeading); } - - // Take optimal heading and turn into a boat heading rather than a wind heading. - optimalHeading = - optimalHeading + (double) Math.floorMod(GameState.getWindDirection().longValue(), 360L); - - setAutoPilot(optimalHeading); } /** @@ -290,7 +306,6 @@ public class Yacht { * @param newHeading The heading to turn the yacht towards. */ private void turnTowardsHeading(Double newHeading) { - System.out.println(newHeading); Double newVal = heading - newHeading; if (Math.floorMod(newVal.longValue(), 360L) > 180) { adjustHeading(TURN_STEP); From a2ee4411be7b748edffc0685f32b12061fe9bea8 Mon Sep 17 00:00:00 2001 From: Alistair McIntyre Date: Thu, 10 Aug 2017 17:59:19 +1200 Subject: [PATCH 4/7] Merge branch 'develop' into Story71_TackAndGybeSmoothly --- .../simulator/parsers/CourseParser.java | 14 ++++---- .../java/seng302/model/mark/CompoundMark.java | 2 +- .../java/seng302/model/mark/MarkOrder.java | 35 +++++++++---------- .../java/seng302/visualiser/GameClient.java | 4 +-- .../seng302/model/mark/CompoundMarkTest.java | 4 ++- .../java/seng302/models/MarkOrderTest.java | 9 +++-- 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/main/java/seng302/gameServer/server/simulator/parsers/CourseParser.java b/src/main/java/seng302/gameServer/server/simulator/parsers/CourseParser.java index e4cbf676..36164af2 100644 --- a/src/main/java/seng302/gameServer/server/simulator/parsers/CourseParser.java +++ b/src/main/java/seng302/gameServer/server/simulator/parsers/CourseParser.java @@ -8,10 +8,10 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; -import seng302.model.mark.CompoundMark; import seng302.gameServer.server.simulator.Corner; -import seng302.model.mark.Mark; import seng302.gameServer.server.simulator.RoundingType; +import seng302.model.mark.CompoundMark; +import seng302.model.mark.Mark; /** * Parses the race xml file to get course details @@ -84,17 +84,17 @@ public class CourseParser extends FileParser { NodeList marks = e.getElementsByTagName("Mark"); List subMarks = new ArrayList<>(); for (int i = 0; i < marks.getLength(); i++) { - Mark mark = getMark(marks.item(i)); + Mark mark = getMark(marks.item(i)); if (mark != null) { subMarks.add(mark); } - } + } return new CompoundMark(markID, name, subMarks); } - System.out.println("Failed to create compound mark."); - return null; - } + System.out.println("Failed to create compound mark."); + return null; + } private Mark getMark(Node node) { diff --git a/src/main/java/seng302/model/mark/CompoundMark.java b/src/main/java/seng302/model/mark/CompoundMark.java index a4cc8d0c..fe5147de 100644 --- a/src/main/java/seng302/model/mark/CompoundMark.java +++ b/src/main/java/seng302/model/mark/CompoundMark.java @@ -15,7 +15,7 @@ public class CompoundMark { public CompoundMark(int markID, String name, List marks) { this.compoundMarkId = markID; - this.name = name; + this.name = name; this.marks.addAll(marks); if (marks.size() > 1) { this.midPoint = GeoUtility.getDirtyMidPoint(marks.get(0), marks.get(1)); diff --git a/src/main/java/seng302/model/mark/MarkOrder.java b/src/main/java/seng302/model/mark/MarkOrder.java index 141d5c6d..1b744fc2 100644 --- a/src/main/java/seng302/model/mark/MarkOrder.java +++ b/src/main/java/seng302/model/mark/MarkOrder.java @@ -1,5 +1,14 @@ package seng302.model.mark; +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; @@ -10,20 +19,11 @@ import seng302.model.stream.xml.parser.RaceXMLData; import seng302.utilities.XMLGenerator; import seng302.utilities.XMLParser; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import java.io.IOException; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - /** * Class to hold the order of the marks in the race. */ public class MarkOrder { + private List raceMarkOrder; private Logger logger = LoggerFactory.getLogger(MarkOrder.class); @@ -35,7 +35,7 @@ public class MarkOrder { * @return An ordered list of marks in the race * OR null if the mark order could not be loaded */ - public List getMarkOrder(){ + public List getMarkOrder() { if (raceMarkOrder == null){ logger.warn("Race order accessed but not instantiated"); return null; @@ -55,10 +55,9 @@ public class MarkOrder { /** * @param currentSeqID The seqID of the current mark the boat is heading to * @return The mark last passed - * @throws IndexOutOfBoundsException if there is no next mark. - * Check seqID != 0 first + * @throws IndexOutOfBoundsException if there is no next mark. Check seqID != 0 first */ - public CompoundMark getPreviousMark(Integer currentSeqID) throws IndexOutOfBoundsException{ + public CompoundMark getPreviousMark(Integer currentSeqID) throws IndexOutOfBoundsException { return raceMarkOrder.get(currentSeqID - 1); } @@ -69,10 +68,10 @@ public class MarkOrder { /** * @param currentSeqID The seqID of the current mark the boat is heading to * @return The mark following the mark that the boat is heading to - * @throws IndexOutOfBoundsException if there is no next mark. - * Check using {@link #isLastMark(Integer)} + * @throws IndexOutOfBoundsException if there is no next mark. Check using {@link + * #isLastMark(Integer)} */ - public CompoundMark getNextMark(Integer currentSeqID) throws IndexOutOfBoundsException{ + public CompoundMark getNextMark(Integer currentSeqID) throws IndexOutOfBoundsException { return raceMarkOrder.get(currentSeqID + 1); } @@ -81,7 +80,7 @@ public class MarkOrder { * @param xml An AC35 RaceXML * @return An ordered list of marks in the race */ - private List loadRaceOrderFromXML(String xml){ + private List loadRaceOrderFromXML(String xml) { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db; diff --git a/src/main/java/seng302/visualiser/GameClient.java b/src/main/java/seng302/visualiser/GameClient.java index b00a6cda..5b3ba1f5 100644 --- a/src/main/java/seng302/visualiser/GameClient.java +++ b/src/main/java/seng302/visualiser/GameClient.java @@ -13,6 +13,8 @@ import javafx.scene.Node; import javafx.scene.input.KeyEvent; import javafx.scene.layout.Pane; import seng302.gameServer.MainServerThread; +import seng302.gameServer.server.messages.BoatActionMessage; +import seng302.gameServer.server.messages.BoatActionType; import seng302.model.RaceState; import seng302.model.Yacht; import seng302.model.stream.packets.StreamPacket; @@ -22,8 +24,6 @@ import seng302.model.stream.parser.PositionUpdateData.DeviceType; import seng302.model.stream.parser.RaceStatusData; import seng302.model.stream.xml.parser.RaceXMLData; import seng302.model.stream.xml.parser.RegattaXMLData; -import seng302.gameServer.server.messages.BoatActionMessage; -import seng302.gameServer.server.messages.BoatActionType; import seng302.utilities.StreamParser; import seng302.utilities.XMLParser; import seng302.visualiser.controllers.LobbyController; diff --git a/src/test/java/seng302/model/mark/CompoundMarkTest.java b/src/test/java/seng302/model/mark/CompoundMarkTest.java index 55ccebf3..83b2b2bb 100644 --- a/src/test/java/seng302/model/mark/CompoundMarkTest.java +++ b/src/test/java/seng302/model/mark/CompoundMarkTest.java @@ -1,6 +1,8 @@ package seng302.model.mark; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.List; diff --git a/src/test/java/seng302/models/MarkOrderTest.java b/src/test/java/seng302/models/MarkOrderTest.java index 42531563..92bbc664 100644 --- a/src/test/java/seng302/models/MarkOrderTest.java +++ b/src/test/java/seng302/models/MarkOrderTest.java @@ -1,16 +1,15 @@ package seng302.models; +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import seng302.model.mark.CompoundMark; -import seng302.model.mark.Mark; import seng302.model.mark.MarkOrder; -import static junit.framework.TestCase.assertEquals; -import static junit.framework.TestCase.assertFalse; -import static junit.framework.TestCase.assertTrue; - public class MarkOrderTest { private static MarkOrder markOrder; private static Integer currentSeqID; From 1c2870649ada04ede72aae8df9acf97467572308 Mon Sep 17 00:00:00 2001 From: Alistair McIntyre Date: Thu, 10 Aug 2017 18:58:38 +1200 Subject: [PATCH 5/7] Added testing for the tack/gybe settings. tags: #story[1105] --- src/main/java/seng302/model/Yacht.java | 23 ++++----- src/test/java/seng302/models/YachtTest.java | 53 +++++++++++++++++++++ 2 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 src/test/java/seng302/models/YachtTest.java diff --git a/src/main/java/seng302/model/Yacht.java b/src/main/java/seng302/model/Yacht.java index 0dfe0018..d8479a94 100644 --- a/src/main/java/seng302/model/Yacht.java +++ b/src/main/java/seng302/model/Yacht.java @@ -131,9 +131,7 @@ public class Yacht { } } - if (isAuto) { - runAutoPilot(); - } + runAutoPilot(); //UPDATE BOAT LOCATION lastLocation = location; @@ -353,15 +351,13 @@ public class Yacht { * Moves the boat towards the given heading when the auto pilot was set. Disables the auto pilot * in the event that the boat is within the range of 1 turn step of its goal. */ - private void runAutoPilot() { - if (autoHeading == null) { - isAuto = false; - // TODO: 10/08/17 possibly throw some sort of exception here maybe? autopilot shouldn't be true if there's no heading. - } - turnTowardsHeading(autoHeading); - if (Math.abs(heading - autoHeading) - <= TURN_STEP) { //Cancel when within 1 turn step of target. - isAuto = false; + public void runAutoPilot() { + if (isAuto) { + turnTowardsHeading(autoHeading); + if (Math.abs(heading - autoHeading) + <= TURN_STEP) { //Cancel when within 1 turn step of target. + isAuto = false; + } } } @@ -438,8 +434,7 @@ public class Yacht { // Take optimal heading and turn into a boat heading rather than a wind heading. optimalHeading = - optimalHeading + (double) Math - .floorMod(GameState.getWindDirection().longValue(), 360L); + optimalHeading + GameState.getWindDirection(); setAutoPilot(optimalHeading); } diff --git a/src/test/java/seng302/models/YachtTest.java b/src/test/java/seng302/models/YachtTest.java new file mode 100644 index 00000000..00d9dea6 --- /dev/null +++ b/src/test/java/seng302/models/YachtTest.java @@ -0,0 +1,53 @@ +package seng302.models; + +import static org.junit.Assert.assertEquals; + +import java.util.HashMap; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import seng302.gameServer.GameState; +import seng302.model.Yacht; + + +public class YachtTest { + + private static Yacht y1; + //Yacht y2; + private static Double windDirection = 45d; + private static Double windSpeed = 20d; + private static GameState gs; + + @BeforeClass + public static void setUp() { + y1 = new Yacht("Yacht", 101, "Y1", "Y1", "Yacht 1", "C1"); + gs = new GameState("localhost"); + } + + @Test + public void tackGybeTest() { + HashMap values = new HashMap<>(); + values.put(280.0, 80.0); + values.put(270.0, 90.0); + values.put(359.0, 1.0); + values.put(180.0, 180.0); + values.put(75.0, 285.0); + + for (Double begin : values.keySet()) { + y1.setHeading(begin); + y1.tackGybe(windDirection); + for (int i = 0; i < 50; i++) { + y1.runAutoPilot(); + } + assertEquals(values.get(begin), y1.getHeading(), 5.0); + } + + } + + + @AfterClass + public static void tearDown() { + y1 = null; + } + +} From 32b231e78a25c4ad5b9614ba69c4e6c1ee325e73 Mon Sep 17 00:00:00 2001 From: Alistair McIntyre Date: Thu, 10 Aug 2017 19:19:41 +1200 Subject: [PATCH 6/7] Added testing for the vmg autopilot tags: #story[1107] --- src/test/java/seng302/models/YachtTest.java | 41 ++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/test/java/seng302/models/YachtTest.java b/src/test/java/seng302/models/YachtTest.java index 00d9dea6..9e33c91b 100644 --- a/src/test/java/seng302/models/YachtTest.java +++ b/src/test/java/seng302/models/YachtTest.java @@ -7,6 +7,7 @@ import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import seng302.gameServer.GameState; +import seng302.model.PolarTable; import seng302.model.Yacht; @@ -14,7 +15,7 @@ public class YachtTest { private static Yacht y1; //Yacht y2; - private static Double windDirection = 45d; + private static Double windDirection = 180d; private static Double windSpeed = 20d; private static GameState gs; @@ -44,6 +45,44 @@ public class YachtTest { } + @Test + public void vmgTest() { + + PolarTable.parsePolarFile(getClass().getResourceAsStream("/config/acc_polars.csv")); + Double upwind = PolarTable.getOptimalUpwindVMG(windSpeed).keySet().iterator().next(); + Double downwind = PolarTable.getOptimalDownwindVMG(windSpeed).keySet().iterator().next(); + + HashMap values = new HashMap<>(); + + upwind = (double) Math.floorMod(upwind.longValue() + windDirection.longValue(), 360L); + Double upwindRight = upwind; + Double upwindLeft = 360 - upwindRight; + downwind = (double) Math.floorMod(downwind.longValue() + windDirection.longValue(), 360L); + Double downwindRight = downwind; + Double downwindLeft = 360 - downwindRight; + + System.out.println( + String.format("%f %f %f %f", upwindLeft, upwindRight, downwindLeft, downwindRight)); + + values.put(190d, upwindRight); + values.put(170d, upwindLeft); + values.put(10d, downwindLeft); + values.put(350d, downwindRight); + + for (Double begin : values.keySet()) { + System.out.println(begin); + y1.setHeading(begin); + y1.turnToVMG(); + for (int i = 0; i < 50; i++) { + y1.runAutoPilot(); + System.out.println(y1.getHeading()); + } + y1.disableAutoPilot(); + assertEquals(values.get(begin), y1.getHeading(), 5.0); + } + + } + @AfterClass public static void tearDown() { From 6ddaaa0dfae1a53dd56acca50194e50691de5181 Mon Sep 17 00:00:00 2001 From: alistairjmcintyre Date: Thu, 10 Aug 2017 20:18:36 +1200 Subject: [PATCH 7/7] Removed extra print statement from test. --- src/test/java/seng302/models/YachtTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/test/java/seng302/models/YachtTest.java b/src/test/java/seng302/models/YachtTest.java index 9e33c91b..fd610dfc 100644 --- a/src/test/java/seng302/models/YachtTest.java +++ b/src/test/java/seng302/models/YachtTest.java @@ -61,9 +61,6 @@ public class YachtTest { Double downwindRight = downwind; Double downwindLeft = 360 - downwindRight; - System.out.println( - String.format("%f %f %f %f", upwindLeft, upwindRight, downwindLeft, downwindRight)); - values.put(190d, upwindRight); values.put(170d, upwindLeft); values.put(10d, downwindLeft);