From 693da8a82a44edfc7592c0b59faf69061336b12a Mon Sep 17 00:00:00 2001 From: fjc40 Date: Wed, 10 May 2017 17:21:18 +1200 Subject: [PATCH] Removed some unneccessary code and comments from PolarParser.parse(...). Fixed a bug where the polar parser would attempt to insert (wind speed, windspeed, windangle) instead of (windspeed, windangle, boatspeed). Removed some unused constructors from RaceXMLReader, and fixed a bug where it wouldn't actually use the polar table correctly. Boat's constructor now expects a Polars table. Added some comments to the Polars class, and specified the HashMap's template parameters Added PolarsTest - which needs to be implemented properly when the VMG calculations have been added. #story[900] --- mock/src/main/java/seng302/App.java | 3 ++ .../java/seng302/DataInput/PolarParser.java | 24 ++++------ .../java/seng302/DataInput/RaceXMLReader.java | 48 +++++++------------ mock/src/main/java/seng302/Model/Boat.java | 4 +- mock/src/main/java/seng302/Model/Polars.java | 33 ++++++++++--- .../test/java/seng302/Data/BoatDataTest.java | 3 +- .../test/java/seng302/Data/RaceDataTest.java | 3 +- .../seng302/DataInput/PolarParserTest.java | 16 ++++++- .../src/test/java/seng302/Model/BoatTest.java | 2 +- .../test/java/seng302/Model/PolarsTest.java | 47 ++++++++++++++++++ .../test/java/seng302/Model/RaceXMLTest.java | 8 ++-- mock/src/test/resources/polars/acc_polars.csv | 8 ++++ .../seng302/Controllers/StartController.java | 2 +- .../main/java/seng302/VisualiserInput.java | 2 +- 14 files changed, 140 insertions(+), 63 deletions(-) create mode 100644 mock/src/test/java/seng302/Model/PolarsTest.java create mode 100644 mock/src/test/resources/polars/acc_polars.csv diff --git a/mock/src/main/java/seng302/App.java b/mock/src/main/java/seng302/App.java index 0e6306bc..74e20255 100644 --- a/mock/src/main/java/seng302/App.java +++ b/mock/src/main/java/seng302/App.java @@ -5,6 +5,7 @@ import javafx.application.Application; import javafx.stage.Stage; import org.xml.sax.SAXException; import seng302.DataInput.*; +import seng302.Exceptions.InvalidPolarFileException; import seng302.Model.Event; import seng302.Model.Polars; @@ -37,6 +38,8 @@ public class App extends Application { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); + } catch (InvalidPolarFileException e) { + e.printStackTrace(); } } } diff --git a/mock/src/main/java/seng302/DataInput/PolarParser.java b/mock/src/main/java/seng302/DataInput/PolarParser.java index 6b977483..5a187192 100644 --- a/mock/src/main/java/seng302/DataInput/PolarParser.java +++ b/mock/src/main/java/seng302/DataInput/PolarParser.java @@ -50,18 +50,13 @@ public class PolarParser { //Angles are expected to be in degrees, and velocities in knots. - //We read the heading and data rows, and split them into arrays of elements. - String[] headings; + //We read data rows, and split them into arrays of elements. ArrayList dataRows = new ArrayList<>(7); try { - //Heading. - //Read heading row. + //Heading row. + //We skip the heading row by reading it. String headingRow = inputStream.readLine(); - //Split it into individual headings. - headings = headingRow.split(","); - - //Data rows. while (inputStream.ready()) { //Read line. @@ -83,19 +78,19 @@ public class PolarParser { //For each row... int rowNumber = 0; for (String[] row : dataRows) { - //Create Polar row object. - //For each column... - for (int i = 0; i < row.length / 2; i += 2) { + //For each pair of columns (the pair is angle, speed). + //We start at column 1 since column 0 is the wind speed column. + // (row.length - 1) / 2 means the number of pairs of angle+speed. + for (int i = 1; i < (row.length - 1) / 2; i += 2) { - //Convert value to a double. - Double value; + //Add angle+speed=velocity estimate to polar table. try { //Add the polar value to the polar table polarTable.addEstimate( Double.parseDouble(row[0]), Double.parseDouble(row[i]), Double.parseDouble(row[i + 1])); } catch (NumberFormatException e) { - throw new InvalidPolarFileException("Could not convert (Row,Col): (" + rowNumber + "," + i +") = " + row[i] + "to a double.", e); + throw new InvalidPolarFileException("Could not convert (Row,Col): (" + rowNumber + "," + i +") = " + row[i] + " to a double.", e); } } @@ -104,7 +99,6 @@ public class PolarParser { } - return polarTable; } diff --git a/mock/src/main/java/seng302/DataInput/RaceXMLReader.java b/mock/src/main/java/seng302/DataInput/RaceXMLReader.java index 00a14965..089f93c2 100644 --- a/mock/src/main/java/seng302/DataInput/RaceXMLReader.java +++ b/mock/src/main/java/seng302/DataInput/RaceXMLReader.java @@ -25,49 +25,36 @@ public class RaceXMLReader extends XMLReader implements RaceDataSource { private GPSCoordinate mapTopLeft, mapBottomRight; private List boundary = new ArrayList<>(); private List markers = new ArrayList<>(); + + ///Filename to read data from. + private String filePath; + ///The polar table object to assign to each boat. private Polars boatPolars; - /** - * Constractor for Race XML - * - * @param filePath path of the file - * @throws IOException error - * @throws SAXException error - * @throws ParserConfigurationException error - */ - public RaceXMLReader(String filePath) throws IOException, SAXException, ParserConfigurationException { - this(filePath, true); - } + /** * Constractor for Race XML * - * @param filePath path of the file + * @param filePath The path to the file to read data from. + * @param boatPolars The polar table to assign to each boat. * @throws IOException error * @throws SAXException error * @throws ParserConfigurationException error */ public RaceXMLReader(String filePath, Polars boatPolars) throws IOException, SAXException, ParserConfigurationException { - this(filePath, true); - this.boatPolars = boatPolars; - } - /** - * COnstructor for Race XML - * - * @param filePath file path to read - * @param read whether or not to read and store the files straight away. - * @throws IOException error - * @throws SAXException error - * @throws ParserConfigurationException error - */ - public RaceXMLReader(String filePath, boolean read) throws IOException, SAXException, ParserConfigurationException { super(filePath); - if (read) { - read(); - } + + this.filePath = filePath; + this.boatPolars = boatPolars; + + + read(); } + + /** * Read the files */ @@ -100,8 +87,9 @@ public class RaceXMLReader extends XMLReader implements RaceDataSource { String abbrev = getTextValueOfNode((Element) nBoats.item(i), "abbr"); double velo = Double.parseDouble(getTextValueOfNode((Element) nBoats.item(i), "speed")); int sourceID = Integer.parseInt(getTextValueOfNode((Element) nBoats.item(i), "sourceID")); - Boat boat = new Boat(name, velo, abbrev, sourceID); - boat.setPolars(boatPolars); + + Boat boat = new Boat(name, velo, abbrev, sourceID, this.boatPolars); + boat.setCurrentPosition(startPt1); if (legs.size() > 0) { boat.setCurrentLeg(legs.get(0)); diff --git a/mock/src/main/java/seng302/Model/Boat.java b/mock/src/main/java/seng302/Model/Boat.java index 052bcda3..9604680a 100644 --- a/mock/src/main/java/seng302/Model/Boat.java +++ b/mock/src/main/java/seng302/Model/Boat.java @@ -29,12 +29,14 @@ public class Boat { * @param velocity Speed in m/s that the boat travels at. * @param abbrev nam abbreviation * @param sourceID id of boat + * @param polars The polars table to use for this boat. */ - public Boat(String name, double velocity, String abbrev, int sourceID) { + public Boat(String name, double velocity, String abbrev, int sourceID, Polars polars) { this.velocity = velocity; this.abbrev = abbrev; this.name = name; this.sourceID = sourceID; + this.polars = polars; } /** diff --git a/mock/src/main/java/seng302/Model/Polars.java b/mock/src/main/java/seng302/Model/Polars.java index d4609d49..cef438c2 100644 --- a/mock/src/main/java/seng302/Model/Polars.java +++ b/mock/src/main/java/seng302/Model/Polars.java @@ -7,19 +7,40 @@ import java.util.HashMap; /** * Created by hba56 on 10/05/17. */ + +/** + * Encapsulates an entire polar table. Has a function to calculate VMG. + */ public class Polars { - private HashMap polarValues; + ///Internal store of data. Maps pair to boatSpeed. + private HashMap, Double> polarValues = new HashMap<>(); + + /** + * Ctor. + */ public Polars() { - polarValues = new HashMap(); } - public void addEstimate(double trueWindSpeed, double trueWindAngle, double boatSpeed){ - Pair newKey = new Pair(trueWindSpeed, trueWindAngle); + + /** + * Adds an estimated velocity to the polar table object, for a given (windSpeed, windAngle) pair. That is, stores a mapping from (windSpeed, windAngle) to (boatVelocity). + * @param trueWindSpeed The true wind speed of the estimate. + * @param trueWindAngle The true wind angle of the estimate. + * @param boatSpeed The boat speed of the estimate. + */ + public void addEstimate(double trueWindSpeed, double trueWindAngle, double boatSpeed){ + Pair newKey = new Pair(trueWindSpeed, trueWindAngle); polarValues.put(newKey, boatSpeed); - } + } + + //TODO calculate VMG from (windAngle, destAngle, windSpeed). - public HashMap getPolarValues() { + /** + * Returns the hashmap used to store polar data. + * @return A hashmap containing estimated boat speeds for a given (windSpeed, windAngle) pair. + */ + public HashMap, Double> getPolarValues() { return polarValues; } } diff --git a/mock/src/test/java/seng302/Data/BoatDataTest.java b/mock/src/test/java/seng302/Data/BoatDataTest.java index 14d3ff5a..8b098a02 100644 --- a/mock/src/test/java/seng302/Data/BoatDataTest.java +++ b/mock/src/test/java/seng302/Data/BoatDataTest.java @@ -6,6 +6,7 @@ import org.junit.Test; import org.xml.sax.SAXException; import seng302.DataInput.RaceDataSource; import seng302.DataInput.RaceXMLReader; +import seng302.Model.Polars; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; @@ -33,7 +34,7 @@ public class BoatDataTest { @Before public void initReader() { try { - raceDataSource = new RaceXMLReader("raceXML/bermuda_AC35.xml"); + raceDataSource = new RaceXMLReader("raceXML/bermuda_AC35.xml", new Polars()); BoatData boatData = new BoatData(raceDataSource.getBoats()); result = boatData.createXML(); diff --git a/mock/src/test/java/seng302/Data/RaceDataTest.java b/mock/src/test/java/seng302/Data/RaceDataTest.java index 5f9ed54c..62ba472e 100644 --- a/mock/src/test/java/seng302/Data/RaceDataTest.java +++ b/mock/src/test/java/seng302/Data/RaceDataTest.java @@ -5,6 +5,7 @@ import org.junit.Test; import org.xml.sax.SAXException; import seng302.DataInput.RaceDataSource; import seng302.DataInput.RaceXMLReader; +import seng302.Model.Polars; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; @@ -27,7 +28,7 @@ public class RaceDataTest { @Before public void initReader() { try { - raceDataSource = new RaceXMLReader("raceXML/bermuda_AC35.xml"); + raceDataSource = new RaceXMLReader("raceXML/bermuda_AC35.xml", new Polars()); RaceData raceData = new RaceData(raceDataSource); result = raceData.createXML(); diff --git a/mock/src/test/java/seng302/DataInput/PolarParserTest.java b/mock/src/test/java/seng302/DataInput/PolarParserTest.java index 0bb06326..2974c1ad 100644 --- a/mock/src/test/java/seng302/DataInput/PolarParserTest.java +++ b/mock/src/test/java/seng302/DataInput/PolarParserTest.java @@ -1,6 +1,9 @@ package seng302.DataInput; + import org.testng.annotations.Test; +import seng302.Exceptions.InvalidPolarFileException; +import seng302.Model.Polars; import java.io.File; @@ -17,10 +20,19 @@ public class PolarParserTest { */ public void testParse() throws Exception { + try { + //Parse data file. + Polars polars = PolarParser.parse("polars/acc_polars.csv"); - //Polars = PolarParser.parse("polars/acc_polars.csv"); - + //If the parse function didn't through, it worked. + assertTrue(true); + } + catch (InvalidPolarFileException e) { + assertTrue(false); + } } + + } diff --git a/mock/src/test/java/seng302/Model/BoatTest.java b/mock/src/test/java/seng302/Model/BoatTest.java index 75b01939..47c0e9c2 100644 --- a/mock/src/test/java/seng302/Model/BoatTest.java +++ b/mock/src/test/java/seng302/Model/BoatTest.java @@ -13,7 +13,7 @@ public class BoatTest { private GPSCoordinate ORIGIN_COORDS = new GPSCoordinate(0, 0); - private Boat TEST_BOAT = new Boat("Test", 1, "tt", 1); + private Boat TEST_BOAT = new Boat("Test", 1, "tt", 1, new Polars()); @Test public void calculateDueNorthAzimuthReturns0() { diff --git a/mock/src/test/java/seng302/Model/PolarsTest.java b/mock/src/test/java/seng302/Model/PolarsTest.java new file mode 100644 index 00000000..a12603c5 --- /dev/null +++ b/mock/src/test/java/seng302/Model/PolarsTest.java @@ -0,0 +1,47 @@ +package seng302.Model; + +import org.testng.annotations.Test; +import seng302.DataInput.PolarParser; +import seng302.Exceptions.InvalidPolarFileException; + +import static org.testng.Assert.*; + +/** + * Created by f123 on 10-May-17. + */ +public class PolarsTest { + + @Test + /** + * Tests if we can parse a polar data file (stored in a string), create a polar table, and calculate VMG for a variety of values. + */ + public void testParseAndVMG() throws Exception { + + //Read data. + Polars polars; + try { + //Parse data file. + polars = PolarParser.parse("polars/acc_polars.csv"); + } + catch (InvalidPolarFileException e) { + assertTrue(false); + } + + //Test 1. + //TODO make these tests actually do something when the calculateVMG function is added. + double windAngle1 = 31.5; + double destAngle1 = 65.32; + double windSpeed1 = 15;//knots + //double vmgAngle1 = TODO; + //double vmgSpeed1 = TODO; + + //VMG calcVMG1 = Polars.calculateVMG(windAngle1, destAngle1, windSpeed1); + //double calcVMGAngle1 = calcVMG1.getKey(); + //double calcVMGSpeed1 = calcVMG1.getValue(); + + //assertEquals(vmgAngle1, calcVMGAngle1, 0.1); + //assertEquals(vmgSpeed1, calcVMGSpeed1, 0.1); + + } + +} diff --git a/mock/src/test/java/seng302/Model/RaceXMLTest.java b/mock/src/test/java/seng302/Model/RaceXMLTest.java index bb06111d..13c28887 100644 --- a/mock/src/test/java/seng302/Model/RaceXMLTest.java +++ b/mock/src/test/java/seng302/Model/RaceXMLTest.java @@ -17,7 +17,7 @@ public class RaceXMLTest { @Test public void canFindFile() { try { - RaceXMLReader raceXMLReader = new RaceXMLReader("raceXML/bermuda_AC35.xml", false); + RaceXMLReader raceXMLReader = new RaceXMLReader("raceXML/bermuda_AC35.xml", new Polars()); } catch (Exception e) { fail("Cannot find raceXML/bermuda_AC35.xml in the resources folder"); } @@ -27,7 +27,7 @@ public class RaceXMLTest { @Test public void canReadBoats() { try { - RaceXMLReader raceXMLReader = new RaceXMLReader("raceXML/bermuda_AC35.xml", false); + RaceXMLReader raceXMLReader = new RaceXMLReader("raceXML/bermuda_AC35.xml", new Polars()); raceXMLReader.readBoats(); List boats = raceXMLReader.getBoats(); assertTrue(boats.size() == 6); @@ -62,7 +62,7 @@ public class RaceXMLTest { @Test public void canReadLegs() { try { - RaceXMLReader raceXMLReader = new RaceXMLReader("raceXML/bermuda_AC35.xml", false); + RaceXMLReader raceXMLReader = new RaceXMLReader("raceXML/bermuda_AC35.xml", new Polars()); raceXMLReader.readLegs(); assertTrue(raceXMLReader.getLegs().size() == 5); } catch (Exception e) { @@ -73,7 +73,7 @@ public class RaceXMLTest { @Test public void canReadCourse() { try { - RaceXMLReader raceXMLReader = new RaceXMLReader("raceXML/bermuda_AC35.xml", false); + RaceXMLReader raceXMLReader = new RaceXMLReader("raceXML/bermuda_AC35.xml", new Polars()); raceXMLReader.readCourse(); assertTrue(raceXMLReader.getMapTopLeft() != null); assertTrue(raceXMLReader.getMapBottomRight() != null); diff --git a/mock/src/test/resources/polars/acc_polars.csv b/mock/src/test/resources/polars/acc_polars.csv new file mode 100644 index 00000000..ee7ea80e --- /dev/null +++ b/mock/src/test/resources/polars/acc_polars.csv @@ -0,0 +1,8 @@ +Tws,Twa0,Bsp0,Twa1,Bsp1,UpTwa,UpBsp,Twa2,Bsp2,Twa3,Bsp3,Twa4,Bsp4,Twa5,Bsp5,Twa6,Bsp6,DnTwa,DnBsp,Twa7,Bsp7 +4,0,0,30,4,45,8,60,9,75,10,90,10,115,10,145,10,155,10,175,4 +8,0,0,30,7,43,10,60,11,75,11,90,11,115,12,145,12,153,12,175,10 +12,0,0,30,11,43,14.4,60,16,75,20,90,23,115,24,145,23,153,21.6,175,14 +16,0,0,30,12,42,19.2,60,25,75,27,90,31,115,32,145,30,153,28.8,175,20 +20,0,0,30,13,41,24,60,29,75,37,90,39,115,40,145,38,153,36,175,24 +25,0,0,30,15,40,30,60,38,75,44,90,49,115,50,145,49,151,47,175,30 +30,0,0,30,15,42,30,60,37,75,42,90,48,115,49,145,48,150,46,175,32 diff --git a/visualiser/src/main/java/seng302/Controllers/StartController.java b/visualiser/src/main/java/seng302/Controllers/StartController.java index f264cded..75434735 100644 --- a/visualiser/src/main/java/seng302/Controllers/StartController.java +++ b/visualiser/src/main/java/seng302/Controllers/StartController.java @@ -62,7 +62,7 @@ public class StartController extends Controller implements Observer { */ private void startRaceNoScaling() { //startRace(1); - while(visualiserInput.getRaceStatus() == null);//TODO probably remove this. + //while(visualiserInput.getRaceStatus() == null);//TODO probably remove this. countdownTimer(); } diff --git a/visualiser/src/main/java/seng302/VisualiserInput.java b/visualiser/src/main/java/seng302/VisualiserInput.java index ffba53c3..b70c8e53 100644 --- a/visualiser/src/main/java/seng302/VisualiserInput.java +++ b/visualiser/src/main/java/seng302/VisualiserInput.java @@ -219,7 +219,7 @@ public class VisualiserInput implements Runnable { //If no heartbeat has been received in more the heartbeat period //then the connection will need to be restarted. - System.out.println("time since last heartbeat: " + timeSinceHeartbeat());//TEMP REMOVE + //System.out.println("time since last heartbeat: " + timeSinceHeartbeat());//TEMP REMOVE long heartBeatPeriod = 10 * 1000; if (timeSinceHeartbeat() > heartBeatPeriod) { System.out.println("Connection has stopped, trying to reconnect.");