From 7331ad1a20212dff99903c01a8858d18f9477db9 Mon Sep 17 00:00:00 2001 From: Fan-Wu Yang Date: Tue, 5 Sep 2017 19:26:06 +1200 Subject: [PATCH] VMG now works however some little bug in the interpolation in some quadrant that is making the speed all the same in the quadrant #story[1182] --- racevisionGame/pom.xml | 24 +++- .../main/java/mock/dataInput/PolarParser.java | 1 - .../src/main/java/mock/model/MockRace.java | 8 +- .../src/main/java/mock/model/NewPolars.java | 25 ++-- .../test/java/mock/model/NewPolarsTest.java | 107 ++++++++++++++++++ 5 files changed, 148 insertions(+), 17 deletions(-) create mode 100644 racevisionGame/src/test/java/mock/model/NewPolarsTest.java diff --git a/racevisionGame/pom.xml b/racevisionGame/pom.xml index 41157414..b137baa8 100644 --- a/racevisionGame/pom.xml +++ b/racevisionGame/pom.xml @@ -25,10 +25,30 @@ org.mockito - mockito-all - 1.9.5 + mockito-core + 2.9.0 + + + net.bytebuddy + byte-buddy + 1.7.0 + runtime + + + net.bytebuddy + byte-buddy-agent + 1.7.0 + runtime + + + org.objenesis + objenesis + 2.6 + runtime + + diff --git a/racevisionGame/src/main/java/mock/dataInput/PolarParser.java b/racevisionGame/src/main/java/mock/dataInput/PolarParser.java index 0e87696b..9a94d1f0 100644 --- a/racevisionGame/src/main/java/mock/dataInput/PolarParser.java +++ b/racevisionGame/src/main/java/mock/dataInput/PolarParser.java @@ -108,7 +108,6 @@ public class PolarParser { /** * Given a filename, this function parses it and generates a Polar object, which can be queried for polar information. * @param filename The filename to load and read data from (loaded as a resource). - * @return A Polar table containing data from the given file. */ public static void parseNewPolars(String filename) throws InvalidPolarFileException { NewPolars newPolars = new NewPolars(); diff --git a/racevisionGame/src/main/java/mock/model/MockRace.java b/racevisionGame/src/main/java/mock/model/MockRace.java index 77e7b04d..4e5858f3 100644 --- a/racevisionGame/src/main/java/mock/model/MockRace.java +++ b/racevisionGame/src/main/java/mock/model/MockRace.java @@ -209,7 +209,9 @@ public class MockRace extends Race { boat.setStatus(BoatStatusEnum.PRESTART); //We set a large time since tack change so that it calculates a new VMG when the simulation starts. - boat.setTimeSinceTackChange(Long.MAX_VALUE); + //boat.setTimeSinceTackChange(Long.MAX_VALUE); + boat.setTimeSinceTackChange(0); + } } @@ -353,8 +355,8 @@ public class MockRace extends Race { private void newOptimalVMG(MockBoat boat) { long tackPeriod = 1000; - if (boat.getTimeSinceTackChange() > tackPeriod) { + //System.out.println("optim called"); //Calculate the new VMG. // VMG newVMG = boat.getPolars().calculateVMG( // this.getWindDirection(), @@ -364,7 +366,7 @@ public class MockRace extends Race { // Bearing.fromDegrees(359.99999d)); VMG newVMG = NewPolars.setBestVMG(this.getWindDirection(), this.getWindSpeed(), boat.getBearing()); - System.out.println(newVMG); + //System.out.println(newVMG); //If the new vmg improves velocity, use it. if (improvesVelocity(boat, newVMG)) { boat.setVMG(newVMG); diff --git a/racevisionGame/src/main/java/mock/model/NewPolars.java b/racevisionGame/src/main/java/mock/model/NewPolars.java index 3f070a3a..71b041ed 100644 --- a/racevisionGame/src/main/java/mock/model/NewPolars.java +++ b/racevisionGame/src/main/java/mock/model/NewPolars.java @@ -31,7 +31,7 @@ public class NewPolars { } polars.get(tws).putIfAbsent(twa, bs); polars.get(tws).putIfAbsent(360d - twa, bs); - System.out.println(String.format("tws %f, twa %f, bs %f", tws, twa, bs)); + //System.out.println(String.format("tws %f, twa %f, bs %f", tws, twa, bs)); } public static void linearInterpolatePolars(){ @@ -69,7 +69,7 @@ public class NewPolars { double mult = i - previousTWA; double newSpeed = diff * mult + prevSpeed; //System.out.println(newSpeed); - System.out.println(String.format("tws %f, twa %f, bs %f", windSpeed, i, newSpeed)); + //System.out.println(String.format("tws %f, twa %f, bs %f", windSpeed, i, newSpeed)); tws.put(i, newSpeed); } previousTWA = twa; @@ -104,8 +104,10 @@ public class NewPolars { } private static double getBestSpeedInQuadrant(int quad, Map set){ - double min = quad* 90; - double max = (quad + 1) * 90; + double min = (quad - 1)* 90; + double max = quad * 90; + System.out.println(quad); + System.out.println(min + " " + max); double maxAngle = 0; double maxSpeed = 0; for (Double s: set.keySet()){ @@ -116,9 +118,6 @@ public class NewPolars { } } } - if (quad > 2){ - maxAngle += 180; - } return maxAngle; } @@ -130,13 +129,12 @@ public class NewPolars { * @return */ public static VMG setBestVMG(Bearing trueWindAngle, double trueWindSpeed, Bearing boatAngle){ + //System.out.println("VMG AUTO CALLED"); //speed double closestSpeed = getClosest(trueWindSpeed, polars.keySet()); - //not using true vmg, using general concept - double angle = Math.abs(trueWindAngle.degrees() - boatAngle.degrees()); - - int quad = getQuadrant(boatAngle.degrees()); + double angle = ((boatAngle.degrees() - trueWindAngle.degrees()) % 360 + 360) % 360; + int quad = getQuadrant(angle); double bestAngle = getBestSpeedInQuadrant(quad, polars.get(closestSpeed)); Bearing vmgAngle = Bearing.fromDegrees((bestAngle) % 360); @@ -159,4 +157,9 @@ public class NewPolars { } + private Map> getPolars(){ + //this function is just for testing so therefore it is private + return polars; + } + } diff --git a/racevisionGame/src/test/java/mock/model/NewPolarsTest.java b/racevisionGame/src/test/java/mock/model/NewPolarsTest.java new file mode 100644 index 00000000..4b5a0c80 --- /dev/null +++ b/racevisionGame/src/test/java/mock/model/NewPolarsTest.java @@ -0,0 +1,107 @@ +package mock.model; + +import mock.dataInput.PolarParser; +import org.junit.Before; +import org.junit.Test; +import shared.model.Bearing; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.*; + +/** + * Created by fwy13 on 5/09/17. + */ +public class NewPolarsTest { + + @Before + public void setUp(){ + PolarParser.parseNewPolars("mock/polars/acc_polars.csv"); + NewPolars.linearInterpolatePolars(); + } + + @Test + public void testQuads() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + //reflection for private class + Class[] parameterTypes = new Class[1]; + parameterTypes[0] = Double.TYPE; + Method getQuads = NewPolars.class.getDeclaredMethod("getQuadrant", parameterTypes); + getQuads.setAccessible(true); + + //start invoking + Object[] paras1 = new Object[1]; + paras1[0] = (new Double(0)).doubleValue(); + int q1 = (int) getQuads.invoke(NewPolars.newPolars, paras1); + assertEquals(q1, 1); + + //start invoking + Object[] paras2 = new Object[1]; + paras2[0] = (new Double(90)).doubleValue(); + int q2 = (int) getQuads.invoke(NewPolars.newPolars, paras2); + assertEquals(q2, 2); + + //start invoking + Object[] paras3 = new Object[1]; + paras3[0] = (new Double(180)).doubleValue(); + int q3 = (int) getQuads.invoke(NewPolars.newPolars, paras3); + assertEquals(q3, 3); + + //start invoking + Object[] paras4 = new Object[1]; + paras4[0] = (new Double(270)).doubleValue(); + int q4 = (int) getQuads.invoke(NewPolars.newPolars, paras4); + assertEquals(q4, 4); + + //start invoking + Object[] paras5 = new Object[1]; + paras5[0] = (new Double(360)).doubleValue(); + int q5 = (int) getQuads.invoke(NewPolars.newPolars, paras5); + assertEquals(q5, 1); + + } + + @Test + public void testEdgeSpeeds(){ + //just make sure that speeds at certain angles do not throw a null exception and are not negative + double maxTWS = 15; + + for (double tws = 0; tws < maxTWS; tws += 0.1){ + for (double j = 0; j < 360; j++){ + Bearing twa = Bearing.fromDegrees(j); + for (double i = 0; i < 360; i++){ + Bearing boatBearing = Bearing.fromDegrees(i); + double speed = NewPolars.calculateSpeed(twa, tws, boatBearing); + assertTrue(speed >= 0); + } + } + } + + } + + @Test + public void testClosestSpeeds() throws NoSuchMethodException, NoSuchFieldException, InvocationTargetException, IllegalAccessException { + //reflection for private class + Method getClosest = NewPolars.class.getDeclaredMethod("getClosest", double.class, Set.class); + getClosest.setAccessible(true); + + Method getPolars = NewPolars.class.getDeclaredMethod("getPolars"); + getPolars.setAccessible(true); + + double maxTWS = 15; + + //only catches for nulls + for (double tws = 0; tws < maxTWS; tws += 0.1){ + Map> polars = (Map>) getPolars.invoke(NewPolars.newPolars); + double speed = (double) getClosest.invoke(NewPolars.newPolars, tws, polars.keySet()); + assertTrue(speed >= 0); + } + } + +}