Status: CodeReview with Axel

This commit is contained in:
Daniel Lisunkin committed 2019-07-05 15:19:09 +02:00
1 parent db16657ba0
commit 896b22fcca
4 files changed
+58 -47

No files matched your search

@@ -36,7 +36,7 @@ public class TestORCPerformanceCurve {
private final boolean collectErrors = true;
private static final String RESOURCES = "resources/orc/";
private static ORCPerformanceCurveCourse course;
private static ORCPerformanceCurveCourse course1;
private static ORCCertificateImporter importer;
@Rule
@@ -61,7 +61,7 @@ public class TestORCPerformanceCurve {
legs.add(new ORCPerformanceCurveLegImpl(new NauticalMileDistance(1.03), new DegreeBearingImpl(15)));
legs.add(new ORCPerformanceCurveLegImpl(new NauticalMileDistance(1.03), new DegreeBearingImpl(165)));
legs.add(new ORCPerformanceCurveLegImpl(new NauticalMileDistance(1.17), new DegreeBearingImpl(180)));
course = new ORCPerformanceCurveCourseImpl(legs);
course1 = new ORCPerformanceCurveCourseImpl(legs);
// Local File:
File fileGER = new File(RESOURCES + "GER2019.json");
@@ -75,10 +75,10 @@ public class TestORCPerformanceCurve {
public void testLagrangeInterpolation() throws FunctionEvaluationException {
Double accuracy = 0.21;
ORCCertificateImpl certificate = (ORCCertificateImpl) importer.getCertificate("GER 5549");
ORCPerformanceCurveImpl performanceCurve = (ORCPerformanceCurveImpl) certificate.getPerformanceCurve(course);
ORCPerformanceCurveImpl performanceCurve = (ORCPerformanceCurveImpl) certificate.getPerformanceCurve(course1);
Double value = performanceCurve.getDurationPerNauticalMileAtTrueWindAngleAndSpeed(new KnotSpeedImpl(6), new DegreeBearingImpl(60)).asSeconds();
assertNotNull(course);
assertNotNull(course1);
assertNotNull(performanceCurve);
assertEquals(value, performanceCurve.getLagrangeAllowancePerTrueWindSpeedAndAngle(new KnotSpeedImpl( 6),new DegreeBearingImpl( 60)).asSeconds(), 0.000001);
@@ -98,7 +98,7 @@ public class TestORCPerformanceCurve {
assertEquals(345.0, performanceCurve.getLagrangeAllowancePerTrueWindSpeedAndAngle(new KnotSpeedImpl(16),new DegreeBearingImpl(98.3)).asSeconds(), accuracy);
assertEquals(321.7, performanceCurve.getLagrangeAllowancePerTrueWindSpeedAndAngle(new KnotSpeedImpl(20),new DegreeBearingImpl(98.3)).asSeconds(), accuracy);
// TESTS of the corner areas of the polars
// TESTS of the corner areas of the polar
assertEquals(588.1, performanceCurve.getLagrangeAllowancePerTrueWindSpeedAndAngle(new KnotSpeedImpl( 6),new DegreeBearingImpl(138.7)).asSeconds(), accuracy);
assertEquals(468.4, performanceCurve.getLagrangeAllowancePerTrueWindSpeedAndAngle(new KnotSpeedImpl( 8),new DegreeBearingImpl(138.7)).asSeconds(), accuracy);
assertEquals(413.8, performanceCurve.getLagrangeAllowancePerTrueWindSpeedAndAngle(new KnotSpeedImpl(10),new DegreeBearingImpl(138.7)).asSeconds(), accuracy);
@@ -137,7 +137,7 @@ public class TestORCPerformanceCurve {
public void testPerformanceCurveInvertation() throws MaxIterationsExceededException, FunctionEvaluationException {
Double accuracy = 0.1;
ORCCertificateImpl certificate = (ORCCertificateImpl) importer.getCertificate("GER 5549");
ORCPerformanceCurveImpl performanceCurve = (ORCPerformanceCurveImpl) certificate.getPerformanceCurve(course);
ORCPerformanceCurveImpl performanceCurve = (ORCPerformanceCurveImpl) certificate.getPerformanceCurve(course1);
assertEquals( 11.5, performanceCurve.getImpliedWind(performanceCurve.getAllowancePerCourse(new KnotSpeedImpl( 11.5))).getKnots(), accuracy);
assertEquals(17.23, performanceCurve.getImpliedWind(performanceCurve.getAllowancePerCourse(new KnotSpeedImpl(17.23))).getKnots(), accuracy);
@@ -154,19 +154,19 @@ public class TestORCPerformanceCurve {
@Test
public void testImpliedWindSimple() throws MaxIterationsExceededException, FunctionEvaluationException {
double accuracy = 0.000001;
double courseLengthInNauticalMiles = course.getTotalLength().getNauticalMiles();
double courseLengthInNauticalMiles = course1.getTotalLength().getNauticalMiles();
ORCCertificate certificateMoana = importer.getCertificate("GER 5549");
ORCCertificate certificateMilan = importer.getCertificate("GER 7323");
ORCCertificate certificateTutima = importer.getCertificate("GER 5609");
ORCCertificate certificateBank = importer.getCertificate("GER 5555");
ORCCertificate certificateHaspa = importer.getCertificate("GER 6300");
ORCCertificate certificateHalbtrocken = importer.getCertificate("GER 5564");
ORCPerformanceCurve performanceCurveMoana = certificateMoana.getPerformanceCurve(course);
ORCPerformanceCurve performanceCurveMilan = certificateMilan.getPerformanceCurve(course);
ORCPerformanceCurve performanceCurveTutima = certificateTutima.getPerformanceCurve(course);
ORCPerformanceCurve performanceCurveBank = certificateBank.getPerformanceCurve(course);
ORCPerformanceCurve performanceCurveHaspa = certificateHaspa.getPerformanceCurve(course);
ORCPerformanceCurve performanceCurveHalbtrocken = certificateHalbtrocken.getPerformanceCurve(course);
ORCPerformanceCurve performanceCurveMoana = certificateMoana.getPerformanceCurve(course1);
ORCPerformanceCurve performanceCurveMilan = certificateMilan.getPerformanceCurve(course1);
ORCPerformanceCurve performanceCurveTutima = certificateTutima.getPerformanceCurve(course1);
ORCPerformanceCurve performanceCurveBank = certificateBank.getPerformanceCurve(course1);
ORCPerformanceCurve performanceCurveHaspa = certificateHaspa.getPerformanceCurve(course1);
ORCPerformanceCurve performanceCurveHalbtrocken = certificateHalbtrocken.getPerformanceCurve(course1);
assertNotNull(performanceCurveMoana);
assertNotNull(performanceCurveMilan);
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.orc;
import java.util.Map;
import com.sap.sailing.domain.base.Competitor;
/**
* Extracts ORC-Certificates from different sources and different formats. Returns ORC-Certificate objects for given
@@ -13,15 +14,28 @@ import java.util.Map;
public interface ORCCertificateImporter {
/**
* Returns an ORCCertificate object to a given sail number. If there is no certificate for the given id, the method
* returns {@link null}.
**/
//TODO Better input specification on identification of certificate.
* Creates an {@link ORCCertificate} object to a given sail number.
*
* @param sailnumber
* as specified for the boat of the {@link Competitor) in the ORC files. The sailnumber commonly consists
* out of an alphabetical national code (e.g. 'GER', 'GBR', 'SUI', ...) or an alphanumerical class code (e.g. 'F40',
* 'X41', ...) and a numerical identification code.
* @return {@code null}, if there isn't any data for the given sailnumber. Otherwise an {@link ORCCertificate}.
*/
ORCCertificate getCertificate(String sailnumber);
/**
* Returns a map of ORCCertificate objects to a given array of sail numbers.
**/
* Creates an {@link Map} of {@link ORCCertificate} objects to the given sail numbers.
* <p>
* Same functionality as {@code getCertificate} for a single sailnumber, just for multiple elements.
*
* @param sailnumbers
* represents an array of sailnumbers as specified for the boat of the {@link Competitor) in the ORC
* files. The sailnumber commonly consists out of an alphabetical national code (e.g. 'GER', 'GBR', 'SUI', ...) or
* an alphanumerical class code (e.g. 'F40', 'X41', ...) and a numerical identification code.
* @return {@link Map} of {@link ORCCertificate} values and the sailnumber parameters as keys. The value equals
* {@code null}, if there isn't any data for the given sailnumber.
*/
Map<String, ORCCertificate> getCertificates(String[] sailnumbers);
}
@@ -8,8 +8,6 @@ import com.sap.sailing.domain.base.Competitor;
import com.sap.sse.common.Duration;
import com.sap.sse.common.Speed;
// TODO Finish Comments for API
/**
* For a {@link Competitor} and the {@link ORCPerformanceCurveCourse} which the competitor sailed until the creation of
* an instance of an implementing class, this instance represents a so called "Perfromance Curve". This Curve is
@@ -18,13 +16,13 @@ import com.sap.sse.common.Speed;
* course. For a given windspeed the performance curve returns the allowance for the boat or in simpler words: how long
* should the boat need for a nautical mile when sailing 100% performance.
*
* @author Daniel Lisunkin (i505543)
* @author Daniel Lisunkin (i505543)˝
*
*/
public interface ORCPerformanceCurve {
/**
*
* TODO Comment
*
* @param timePerNauticalMile equals the average duration the boat needed to conquer one mile on the sailed subcourse, => totalTime / course.getTotalLength()
* @return
@@ -33,7 +31,7 @@ public interface ORCPerformanceCurve {
* @throws MaxIterationsExceededException
* @throws FunctionEvaluationException
*/
Speed getImpliedWind(Duration timePerNauticalMile) throws ArgumentOutsideDomainException, MaxIterationsExceededException, FunctionEvaluationException;
Speed getImpliedWind(Duration timePerNauticalMile) throws MaxIterationsExceededException, FunctionEvaluationException;
/**
* TODO getComment done
@@ -46,6 +44,7 @@ public interface ORCPerformanceCurve {
Duration getCalculatedTime(ORCPerformanceCurve referenceBoat, Duration sailedDurationPerNauticalMile);
/**
* TODO Comment
*
* @param impliedWind
* @return
@@ -1,9 +1,7 @@
package com.sap.sailing.domain.orc.impl;
import java.awt.List;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -134,24 +132,23 @@ public class ORCPerformanceCurveImpl implements Serializable, ORCPerformanceCurv
}
private Map<Speed, Duration> createAllowancePerLeg(ORCPerformanceCurveLeg leg) throws FunctionEvaluationException {
Map<Speed, Duration> result = new HashMap<>();
Double twa = leg.getTwa().getDegrees();
for (Speed entry : ORCCertificateImpl.ALLOWANCES_TRUE_WIND_SPEEDS) {
final Map<Speed, Duration> result = new HashMap<>();
final double twaDeg = leg.getTwa().getDegrees();
final double twaRad = leg.getTwa().getRadians();
for (final Speed entry : ORCCertificateImpl.ALLOWANCES_TRUE_WIND_SPEEDS) {
// Case switching on TWA (0. TWA == 0; 1. TWA < Beat; 2. Beat < TWA < Gybe; 3. Gybe < TWA; 4. TWA == 180)
if (twa < beatAngles.get(entry).getDegrees()) {
// Case 0 & 1 - result = beatVMG * distance / cos(TWA)
result.put(entry, Duration.ONE_SECOND.times(getDurationPerNauticalMileAtTrueWindAngleAndSpeed(entry, beatAngles.get(entry)).asSeconds() * leg.getLength().getNauticalMiles() * Math.abs(Math.cos(Math.toRadians(twa)))));
} else if (twa > gybeAngles.get(entry).getDegrees()) {
// Case 3 & 4 - result = runVMG * distance / cos(TWA)
result.put(entry, Duration.ONE_SECOND.times(getDurationPerNauticalMileAtTrueWindAngleAndSpeed(entry, gybeAngles.get(entry)).asSeconds() * leg.getLength().getNauticalMiles() * Math.abs(Math.cos(Math.toRadians(twa)))));
// TODO (so ? beatAngles : gybeAngles)
if (twaDeg <= beatAngles.get(entry).getDegrees()) {
// Case 0 & 1 - result = beatVMG * distance * cos(TWA)
result.put(entry, Duration.ONE_SECOND.times(getDurationPerNauticalMileAtTrueWindAngleAndSpeed(entry, beatAngles.get(entry)).asSeconds() * leg.getLength().getNauticalMiles()));
} else if (twaDeg >= gybeAngles.get(entry).getDegrees()) {
// Case 3 & 4 - result = runVMG * distance * cos(TWA)
result.put(entry, Duration.ONE_SECOND.times(getDurationPerNauticalMileAtTrueWindAngleAndSpeed(entry, gybeAngles.get(entry)).asSeconds() * leg.getLength().getNauticalMiles()));
} else {
// Case 2 - result is given through the laGrange Interpolation, between the Beat and Gybe Angles
result.put(entry, getLagrangeAllowancePerTrueWindSpeedAndAngle(entry, leg.getTwa()).times(leg.getLength().getNauticalMiles()));
}
}
return result;
}
@@ -243,26 +240,27 @@ public class ORCPerformanceCurveImpl implements Serializable, ORCPerformanceCurv
private double[][] createPolarsPerTrueWindSpeed(Speed trueWindSpeed) {
ArrayList<Double> resultWindAngles = new ArrayList<>();
ArrayList<Double> resultAllowances = new ArrayList<>();
Bearing beatAngle = beatAngles.get(trueWindSpeed);
Bearing gybeAngle = gybeAngles.get(trueWindSpeed);
final Bearing TWO_DEGREES = new DegreeBearingImpl(2);
final Bearing MINUS_TWO_DEGREES = new DegreeBearingImpl(-2);
resultWindAngles.add(beatAngle.add(new DegreeBearingImpl(-2)).getDegrees());
resultAllowances.add(getDurationPerNauticalMileAtTrueWindAngleAndSpeed(trueWindSpeed, beatAngle).divide(Math.cos(Math.toRadians(beatAngle.add(new DegreeBearingImpl(-2)).getDegrees()))).asSeconds());
resultWindAngles.add(beatAngle.add(MINUS_TWO_DEGREES).getDegrees());
resultAllowances.add(getDurationPerNauticalMileAtTrueWindAngleAndSpeed(trueWindSpeed, beatAngle).divide(Math.cos(beatAngle.add(MINUS_TWO_DEGREES).getRadians())).asSeconds());
resultWindAngles.add(beatAngle.getDegrees());
resultAllowances.add(getDurationPerNauticalMileAtTrueWindAngleAndSpeed(trueWindSpeed, beatAngle).asSeconds());
resultAllowances.add(getDurationPerNauticalMileAtTrueWindAngleAndSpeed(trueWindSpeed, beatAngle).divide(Math.cos(beatAngle.getRadians())).asSeconds());
for(Bearing twa : ORCCertificateImpl.ALLOWANCES_TRUE_WIND_ANGLES) {
if(twa.compareTo(beatAngle) > 0 && twa.compareTo(gybeAngle) < 0) {
for (Bearing twa : ORCCertificateImpl.ALLOWANCES_TRUE_WIND_ANGLES) {
if (twa.compareTo(beatAngle) > 0 && twa.compareTo(gybeAngle) < 0) {
resultWindAngles.add(twa.getDegrees());
resultAllowances.add(getDurationPerNauticalMileAtTrueWindAngleAndSpeed(trueWindSpeed, twa).asSeconds());
}
}
resultWindAngles.add(gybeAngle.getDegrees());
resultAllowances.add(getDurationPerNauticalMileAtTrueWindAngleAndSpeed(trueWindSpeed, gybeAngle).asSeconds());
resultWindAngles.add(gybeAngle.add(new DegreeBearingImpl(2)).getDegrees());
resultAllowances.add(getDurationPerNauticalMileAtTrueWindAngleAndSpeed(trueWindSpeed, gybeAngle).divide(Math.abs(Math.cos(Math.PI - Math.toRadians(gybeAngle.add(new DegreeBearingImpl(2)).getDegrees())))).asSeconds());
resultAllowances.add(getDurationPerNauticalMileAtTrueWindAngleAndSpeed(trueWindSpeed, gybeAngle).divide(Math.cos(Math.PI - gybeAngle.getRadians())).asSeconds());
resultWindAngles.add(gybeAngle.add(TWO_DEGREES).getDegrees());
resultAllowances.add(getDurationPerNauticalMileAtTrueWindAngleAndSpeed(trueWindSpeed, gybeAngle).divide(Math.cos(Math.PI - Math.toRadians(gybeAngle.add(TWO_DEGREES).getDegrees()))).asSeconds());
return new double[][] {resultWindAngles.stream().mapToDouble(d -> d).toArray(), resultAllowances.stream().mapToDouble(d -> d).toArray()};
}