Resizing maps to time taking now works #story[1323]
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user