From f7da4977433935dded8f3eba1c94539e505ac983 Mon Sep 17 00:00:00 2001 From: Fan-Wu Yang Date: Mon, 18 Sep 2017 18:22:20 +1200 Subject: [PATCH] Resizing maps to time taking now works #story[1323] --- .../src/main/java/mock/app/Event.java | 6 +- .../main/java/mock/xml/RaceXMLCreator.java | 117 +++++++++++++++++- .../network/MatchBrowserInterface.java | 3 +- 3 files changed, 119 insertions(+), 7 deletions(-) diff --git a/racevisionGame/src/main/java/mock/app/Event.java b/racevisionGame/src/main/java/mock/app/Event.java index a9f55a7f..1e1b8966 100644 --- a/racevisionGame/src/main/java/mock/app/Event.java +++ b/racevisionGame/src/main/java/mock/app/Event.java @@ -80,6 +80,7 @@ public class Event { * @throws EventConstructionException Thrown if we cannot create an Event for any reason. */ public Event(boolean singlePlayer, int mapIndex) throws EventConstructionException { + PolarParser.parseNewPolars("mock/polars/acc_polars.csv"); this.mapIndex = mapIndex; String raceXMLFile; String boatsXMLFile = "mock/mockXML/boatTest.xml"; @@ -109,6 +110,7 @@ public class Event { } double windAngle = 300; + double windSpeed = 12; //Read XML files. try { @@ -119,6 +121,7 @@ public class Event { this.raceXML = RaceXMLCreator.alterRaceToWind(this.raceXML, XMLFileType.Contents, -1, true); } else { this.raceXML = RaceXMLCreator.alterRaceToWind(this.raceXML, XMLFileType.Contents, windAngle, false); + this.raceXML = RaceXMLCreator.scaleRaceSize(raceXML, windSpeed, 15 * 60 * 1000); } this.boatXML = XMLReader.readXMLFileToString(boatsXMLFile, StandardCharsets.UTF_8); @@ -131,7 +134,6 @@ public class Event { this.xmlFileType = XMLFileType.Contents; this.boatPolars = PolarParser.parse("mock/polars/acc_polars.csv"); - PolarParser.parseNewPolars("mock/polars/acc_polars.csv"); //Parse the XML files into data sources. @@ -152,7 +154,7 @@ public class Event { WindGenerator windGenerator = new ShiftingWindGenerator( Bearing.fromDegrees(windAngle), - 12 + windSpeed ); MockRace mockRace = new MockRace( diff --git a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java index 75024013..cb508aff 100644 --- a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java +++ b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java @@ -1,17 +1,16 @@ package mock.xml; +import mock.model.NewPolars; import org.xml.sax.SAXException; import shared.dataInput.RaceXMLReader; import shared.enums.XMLFileType; import shared.exceptions.InvalidRaceDataException; import shared.exceptions.XMLReaderException; +import shared.model.Bearing; import shared.model.CompoundMark; import shared.model.Constants; import shared.model.GPSCoordinate; -import shared.xml.Race.XMLCompoundMark; -import shared.xml.Race.XMLLimit; -import shared.xml.Race.XMLMark; -import shared.xml.Race.XMLRace; +import shared.xml.Race.*; import shared.xml.XMLUtilities; import javax.xml.bind.JAXBException; @@ -20,6 +19,8 @@ import java.io.IOException; import java.io.InputStream; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; +import java.util.Collections; +import java.util.Comparator; /** * Helper Class for creating a Race XML @@ -125,6 +126,114 @@ public class RaceXMLCreator { } } + + /** + * Rotates the race in a specified direction. + * @param s xml file name or contents. + * @param windSpeed speed that the wind is at. + * @param milliseconds time the race should take at fastest + * @return the new xml file as a string + * @throws XMLReaderException if the xml is not readable + * @throws InvalidRaceDataException if the race is invalid + */ + public static String scaleRaceSize(String s, double windSpeed, double milliseconds) throws XMLReaderException, InvalidRaceDataException { + + try { + + XMLRace race = XMLUtilities.xmlToClass( + s, + RaceXMLCreator.class.getClassLoader().getResource("mock/mockXML/schema/raceSchema.xsd"), + XMLRace.class); + + scaleRace(race, windSpeed, milliseconds); + + return XMLUtilities.classToXML(race); + + } catch (ParserConfigurationException | IOException | SAXException | JAXBException e) { + throw new InvalidRaceDataException("Could not parse or marshall race data file.", e); + } + } + + public static double getRaceLength(XMLRace race, double averageSpeed){ + double raceRoundingTime = 5000; //5 seconds to round a mark + double totalDistance = 0; //in nautical miles + XMLMark prevMark = null; + double avgSpeed = averageSpeed / 60 / 60; //knots is /hour + for (XMLCorner corner : race.getCompoundMarkSequence().getCorner()){ + int index = corner.getCompoundMarkID() - 1; + XMLCompoundMark cm = race.getCourse().getCompoundMark().get(index); + XMLMark mark = cm.getMark().get(0); + if (prevMark != null){ + System.out.println(getDistance(mark, prevMark)); + totalDistance += getDistance(mark, prevMark); + } + prevMark = mark; + } + //total time = total dist / average speed + race extra rounding time * number of marks + double totalTime = totalDistance / avgSpeed * 1000 + + raceRoundingTime * race.getCompoundMarkSequence().getCorner().size(); + return totalTime; + } + + private static double getDistance(XMLMark a, XMLMark b){ + GPSCoordinate coorda = new GPSCoordinate(a.getTargetLat(), a.getTargetLng()); + GPSCoordinate coordb = new GPSCoordinate(b.getTargetLat(), b.getTargetLng()); + return GPSCoordinate.calculateDistanceNauticalMiles(coorda, coordb); + } + + + private static void scaleRace(XMLRace race, double windSpeed, double milliseconds) { + GPSCoordinate center = getCenter(race); + //sort the compound marks + Collections.sort(race.getCompoundMarkSequence().getCorner(), (c1, c2) -> { + if (c1.getSeqID() < c2.getSeqID()) return -1; + if (c1.getSeqID() > c2.getSeqID()) return 1; + return 0; + }); + //sort compound mark id + Collections.sort(race.getCourse().getCompoundMark(), (c1, c2) -> { + if (c1.getCompoundMarkID() < c2.getCompoundMarkID()) return -1; + if (c1.getCompoundMarkID() > c2.getCompoundMarkID()) return 1; + return 0; + }); + //get the fastest time it would take. + double bestUpWindSpeed = NewPolars.setBestVMG(Bearing.fromDegrees(0), windSpeed, Bearing.fromDegrees(45)).getSpeed(); + double bestDownWindSpeed = NewPolars.setBestVMG(Bearing.fromDegrees(0), windSpeed, Bearing.fromDegrees(45)).getSpeed(); + double averageSpeed = (bestDownWindSpeed + bestUpWindSpeed) / 2; + double raceApproximateTime = getRaceLength(race, averageSpeed); + double scale = milliseconds / raceApproximateTime; + for (XMLCorner cm: race.getCompoundMarkSequence().getCorner()){ + int index = cm.getCompoundMarkID() - 1; + XMLCompoundMark mark = race.getCourse().getCompoundMark().get(index); + for (XMLMark m: mark.getMark()){ + scalePoint(m, center, scale); + } + } + for (XMLLimit limit: race.getCourseLimit().getLimit()){ + scalePoint(limit, center, scale); + } + } + + + + private static void scalePoint(XMLMark mark, GPSCoordinate center, double scale){ + double latDiff = mark.getTargetLat() - center.getLatitude(); + double longDiff = mark.getTargetLng() - center.getLongitude(); + double latScaled = latDiff * scale + center.getLatitude(); + double longScaled = longDiff * scale + center.getLongitude(); + mark.setTargetLat(latScaled); + mark.setTargetLng(longScaled); + } + + private static void scalePoint(XMLLimit limit, GPSCoordinate center, double scale){ + double latDiff = limit.getLat() - center.getLatitude(); + double longDiff = limit.getLon() - center.getLongitude(); + double latScaled = latDiff * scale + center.getLatitude(); + double longScaled = longDiff * scale + center.getLongitude(); + limit.setLat(latScaled); + limit.setLon(longScaled); + } + /** * Converts a Race.CourseLimit.Limit to a GPS coordinate * @param limit limit to convert diff --git a/racevisionGame/src/main/java/visualiser/network/MatchBrowserInterface.java b/racevisionGame/src/main/java/visualiser/network/MatchBrowserInterface.java index 02440612..e8beae5c 100644 --- a/racevisionGame/src/main/java/visualiser/network/MatchBrowserInterface.java +++ b/racevisionGame/src/main/java/visualiser/network/MatchBrowserInterface.java @@ -26,8 +26,9 @@ public class MatchBrowserInterface { public MatchBrowserInterface() { try {//132.181.16.13 is the ip of the CI as of 13/9/17 + //this.IPAddress = InetAddress.getByName("132.181.16.13"); //InetAddress.getLocalHost(); //this.IPAddress = InetAddress.getByName("umbrasheep.com"); //InetAddress.getLocalHost(); - this.IPAddress = InetAddress.getByName("132.181.16.13"); //InetAddress.getLocalHost(); + this.IPAddress = InetAddress.getByName("191.101.233.116"); //InetAddress.getLocalHost(); } catch (UnknownHostException e) { e.printStackTrace(); }