Began restructuring orc package. Added ORCCertificate interface. Changed API of ORCPerformanceCurve.

This commit is contained in:
Daniel Lisunkin committed 2019-05-13 15:14:11 +02:00
1 parent 19b45fe698
commit b460e4eb44
9 files changed
+178 -145

No files matched your search

@@ -11,6 +11,7 @@ import java.net.URL;
import org.json.simple.parser.ParseException;
import org.junit.Test;
import com.sap.sailing.domain.orc.impl.ORCCertificateImpl;
import com.sap.sailing.domain.orc.impl.ORCCertificateImporterJSON;
@@ -21,7 +22,7 @@ public class TestORCCertificateImporterJSON {
public void testSimpleLocalJSONFileRead () throws IOException, ParseException {
File fileGER = new File(RESOURCES + "GER2019.json");
ORCCertificateImporterJSON importer = new ORCCertificateImporterJSON(new FileInputStream(fileGER));
ORCCertificate milan = importer.getCertificate(" ger 7323");
ORCCertificateImpl milan = importer.getCertificate(" ger 7323");
assertNotNull(milan);
assertEquals("19.812", milan.getValueString("LOA"));
}
@@ -29,7 +30,7 @@ public class TestORCCertificateImporterJSON {
@Test
public void testSimpleOnlineJSONFileRead () throws IOException, ParseException {
ORCCertificateImporterJSON importer = new ORCCertificateImporterJSON(new URL("https://data.orc.org/public/WPub.dll?action=DownRMS&CountryId=GER&ext=json").openStream());
ORCCertificate swan = importer.getCertificate(" GER 5335");
ORCCertificateImpl swan = importer.getCertificate(" GER 5335");
assertNotNull(swan);
assertEquals("NAUTOR", swan.getValueString("Builder"));
}
@@ -16,6 +16,7 @@ import org.junit.Test;
import com.sap.sailing.domain.common.impl.KnotSpeedImpl;
import com.sap.sailing.domain.common.impl.NauticalMileDistance;
import com.sap.sailing.domain.orc.impl.ORCCertificateImpl;
import com.sap.sailing.domain.orc.impl.ORCCertificateImporterJSON;
import com.sap.sailing.domain.orc.impl.ORCPerformanceCurveCourseImpl;
import com.sap.sailing.domain.orc.impl.ORCPerformanceCurveImpl;
@@ -42,10 +43,12 @@ public class TestORCPerformanceCurve {
importer = new ORCCertificateImporterJSON(new URL("https://data.orc.org/public/WPub.dll?action=DownRMS&CountryId=GER&ext=json").openStream());
}
/*
@Test
public void testLagrangeInterpolation() throws FunctionEvaluationException {
// Moqutio? Or use just a normal Certificate from Import?
ORCCertificate certificate = importer.getCertificate("GER 5549");
ORCCertificateImpl certificate = importer.getCertificate("GER 5549");
ORCPerformanceCurveImpl performanceCurve = (ORCPerformanceCurveImpl) certificate.getPerformanceCurve();
Double value = performanceCurve.getDurationPerNauticalMileAtTrueWindAngleAndSpeed(new KnotSpeedImpl(6), new DegreeBearingImpl(60)).asSeconds();
@@ -57,7 +60,7 @@ public class TestORCPerformanceCurve {
@Test
public void testSimpleConstructedCourse() throws FunctionEvaluationException {
ORCCertificate certificate = importer.getCertificate("GER 5549");
ORCCertificateImpl certificate = importer.getCertificate("GER 5549");
ORCPerformanceCurveImpl performanceCurve = (ORCPerformanceCurveImpl) certificate.getPerformanceCurve();
List<ORCPerformanceCurveLeg> legs = new ArrayList<>();
legs.add(new ORCPerformanceCurveLegImpl(new NauticalMileDistance(1.0), new DegreeBearingImpl(0)));
@@ -84,7 +87,7 @@ public class TestORCPerformanceCurve {
@Test
public void testComplexConstructedCourse() throws FunctionEvaluationException {
ORCCertificate certificate = importer.getCertificate("GER 5549");
ORCCertificateImpl certificate = importer.getCertificate("GER 5549");
ORCPerformanceCurveImpl performanceCurve = (ORCPerformanceCurveImpl) certificate.getPerformanceCurve();
assertNotNull(certificate);
@@ -100,5 +103,7 @@ public class TestORCPerformanceCurve {
System.out.println(course.getTotalLength().getNauticalMiles());
System.out.println(performanceCurve.createAllowancesPerCourse(course));
}
*/
}
@@ -1,120 +1,7 @@
package com.sap.sailing.domain.orc;
import java.util.HashMap;
import java.util.Map;
public interface ORCCertificate {
import com.sap.sailing.domain.common.impl.KnotSpeedImpl;
import com.sap.sailing.domain.orc.impl.ORCPerformanceCurveImpl;
import com.sap.sse.common.Bearing;
import com.sap.sse.common.Duration;
import com.sap.sse.common.Speed;
import com.sap.sse.common.impl.DegreeBearingImpl;
/**
* For a {@link Competitor}
*
*
* @author Daniel Lisunkin (I505543)
*
*/
// TODO Improve public API in regards of semantic connection with real ORC Certificate (paper)
// TODO COMMENTS!
public class ORCCertificate {
private static final String BEAT = "Beat";
private Map<String, String> general;
private Map<String, Number> hull;
private Map<String, Number> sails;
private Map<String, Number> scoring;
private Map<String, Map<Speed, Duration>> twaCourses;
private Map<String, Map<Speed, Duration>> predefinedCourses;
private Map<Speed, Bearing> beatAngles;
private Map<Speed, Bearing> gybeAngles;
private ORCPerformanceCurve performanceCurve;
/**
*
* @param general
* @param hull
* @param sails
* @param scoring
* @param allowancesByTwa
* @param predefinedCourses
* @param beatAngles
* @param gybeAngles
*/
public ORCCertificate(Map<String, String> general, Map<String, Number> hull, Map<String, Number> sails,
Map<String, Number> scoring, Map<String, Map<Speed, Duration>> allowancesByTwa,
Map<String, Map<Speed, Duration>> predefinedCourses, Map<Speed, Bearing> beatAngles,
Map<Speed, Bearing> gybeAngles) {
this.general = general;
this.hull = hull;
this.sails = sails;
this.scoring = scoring;
this.twaCourses = allowancesByTwa;
this.predefinedCourses = predefinedCourses;
this.beatAngles = beatAngles;
this.gybeAngles = gybeAngles;
if (((String) getValue("C_Type")).equals("INTL")) {
initializePerformanceCurve();
} else {
initializePerformanceCurve();
}
}
private void initializePerformanceCurve() {
Map<Speed, Map<Bearing, Duration>> map = new HashMap<>();
// TODO Get Speed Deltas from RMS, create SubBug in Bugzilla, extract Deltas as static final variable
map.put(new KnotSpeedImpl( 6), new HashMap<Bearing, Duration>());
map.put(new KnotSpeedImpl( 8), new HashMap<Bearing, Duration>());
map.put(new KnotSpeedImpl(10), new HashMap<Bearing, Duration>());
map.put(new KnotSpeedImpl(12), new HashMap<Bearing, Duration>());
map.put(new KnotSpeedImpl(14), new HashMap<Bearing, Duration>());
map.put(new KnotSpeedImpl(16), new HashMap<Bearing, Duration>());
map.put(new KnotSpeedImpl(20), new HashMap<Bearing, Duration>());
for (String keyTWA : twaCourses.keySet()) {
int twa = Integer.parseInt(keyTWA.substring(1));
for (Speed keyTWS : twaCourses.get(keyTWA).keySet()) {
map.get(keyTWS).put(new DegreeBearingImpl(twa), twaCourses.get(keyTWA).get(keyTWS));
}
}
for (Speed tws : map.keySet()) {
// TODO Define constant "Beat"/"Run" as static final literals
map.get(tws).put(beatAngles.get(tws), predefinedCourses.get(BEAT).get(tws));
map.get(tws).put(gybeAngles.get(tws), predefinedCourses.get("Run").get(tws));
}
performanceCurve = new ORCPerformanceCurveImpl(map, beatAngles, gybeAngles);
performanceCurve.hashCode(); // Only to resolve "Warning"
}
public Object getValue(String key) {
Object result = null;
if (general.containsKey(key)) {
result = general.get(key);
} else if (hull.containsKey(key)) {
result = hull.get(key);
} else if (sails.containsKey(key)) {
result = sails.get(key);
} else if (scoring.containsKey(key)) {
result = scoring.get(key);
} else if (twaCourses.containsKey(key)) {
result = twaCourses.get(key);
} else if (predefinedCourses.containsKey(key)) {
result = predefinedCourses.get(key);
}
return result;
}
public ORCPerformanceCurve getPerformanceCurve (ORCPerformanceCurveCourse course);
public String getValueString(String key) {
return getValue(key).toString();
}
ORCPerformanceCurve getPerformanceCurve() {
return performanceCurve;
}
}
@@ -2,6 +2,8 @@ package com.sap.sailing.domain.orc;
import java.util.Map;
import com.sap.sailing.domain.orc.impl.ORCCertificateImpl;
/**
* Extracts ORC-Certificates from different sources and different formats. Returns ORC-Certificate objects for given
* identification (sail number).
@@ -16,11 +18,11 @@ public interface ORCCertificateImporter {
* returns {@link null}.
**/
//TODO Better input specification on identification of certificate.
ORCCertificate getCertificate(String sailnumber);
ORCCertificateImpl getCertificate(String sailnumber);
/**
* Returns a map of ORCCertificate objects to a given array of sail numbers.
**/
Map<String, ORCCertificate> getCertificates(String[] sailnumbers);
Map<String, ORCCertificateImpl> getCertificates(String[] sailnumbers);
}
@@ -1,7 +1,5 @@
package com.sap.sailing.domain.orc;
import java.util.List;
import com.sap.sse.common.Distance;
public interface ORCPerformanceCurveCourse {
@@ -17,4 +15,5 @@ public interface ORCPerformanceCurveCourse {
return result;
}
ORCPerformanceCurveCourse subcourse(int lastFinishedLeg, float perCentOfCurrentLeg);
}
@@ -0,0 +1,138 @@
package com.sap.sailing.domain.orc.impl;
import java.util.HashMap;
import java.util.Map;
import com.sap.sailing.domain.common.impl.KnotSpeedImpl;
import com.sap.sailing.domain.orc.ORCCertificate;
import com.sap.sailing.domain.orc.ORCPerformanceCurve;
import com.sap.sailing.domain.orc.ORCPerformanceCurveCourse;
import com.sap.sse.common.Bearing;
import com.sap.sse.common.Duration;
import com.sap.sse.common.Speed;
import com.sap.sse.common.impl.DegreeBearingImpl;
/**
* For a {@link Competitor}
* https://orc.org/index.asp?id=23
*
* @author Daniel Lisunkin (I505543)
*
*/
// TODO Improve public API in regards of semantic connection with real ORC Certificate (paper)
// TODO COMMENTS!
public class ORCCertificateImpl implements ORCCertificate {
/*
* Equals the column heading of the allowances table of an ORC certificate. The speeds are set by the offshore racing congress.
*/
public static final Speed[] ALLOWANCES_TRUE_WIND_SPEEDS = {new KnotSpeedImpl( 6),
new KnotSpeedImpl( 8),
new KnotSpeedImpl(10),
new KnotSpeedImpl(12),
new KnotSpeedImpl(14),
new KnotSpeedImpl(16),
new KnotSpeedImpl(20) };
/*
*
*/
public static final Bearing[] ALLOWANCES_TRUE_WIND_ANGLES = {new DegreeBearingImpl( 52),
new DegreeBearingImpl( 60),
new DegreeBearingImpl( 75),
new DegreeBearingImpl( 90),
new DegreeBearingImpl(110),
new DegreeBearingImpl(120),
new DegreeBearingImpl(135),
new DegreeBearingImpl(150) };
/*
*
*/
private static final String RUN = "Run";
private static final String BEAT = "Beat";
private Map<String, String> general;
private Map<String, Number> hull;
private Map<String, Number> sails;
private Map<String, Number> scoring;
private Map<String, Map<Speed, Duration>> twaCourses;
private Map<String, Map<Speed, Duration>> predefinedCourses;
private final Map<Speed, Bearing> beatAngles;
private final Map<Speed, Bearing> gybeAngles;
private ORCPerformanceCurve performanceCurve;
/**
*
* @param general
* @param hull
* @param sails
* @param scoring
* @param allowancesByTwa
* @param predefinedCourses
* @param beatAngles
* @param gybeAngles
*/
public ORCCertificateImpl(Map<String, String> general, Map<String, Number> hull, Map<String, Number> sails,
Map<String, Number> scoring, Map<String, Map<Speed, Duration>> allowancesByTwa,
Map<String, Map<Speed, Duration>> predefinedCourses, Map<Speed, Bearing> beatAngles,
Map<Speed, Bearing> gybeAngles) {
this.general = general;
this.hull = hull;
this.sails = sails;
this.scoring = scoring;
this.twaCourses = allowancesByTwa;
this.predefinedCourses = predefinedCourses;
this.beatAngles = beatAngles;
this.gybeAngles = gybeAngles;
}
public Object getValue(String key) {
Object result = null;
if (general.containsKey(key)) {
result = general.get(key);
} else if (hull.containsKey(key)) {
result = hull.get(key);
} else if (sails.containsKey(key)) {
result = sails.get(key);
} else if (scoring.containsKey(key)) {
result = scoring.get(key);
} else if (twaCourses.containsKey(key)) {
result = twaCourses.get(key);
} else if (predefinedCourses.containsKey(key)) {
result = predefinedCourses.get(key);
}
return result;
}
public String getValueString(String key) {
return getValue(key).toString();
}
@Override
public ORCPerformanceCurve getPerformanceCurve(ORCPerformanceCurveCourse course) {
Map<Speed, Map<Bearing, Duration>> twaAllowances = new HashMap<>();
twaAllowances.put(new KnotSpeedImpl( 6), new HashMap<Bearing, Duration>());
twaAllowances.put(new KnotSpeedImpl( 8), new HashMap<Bearing, Duration>());
twaAllowances.put(new KnotSpeedImpl(10), new HashMap<Bearing, Duration>());
twaAllowances.put(new KnotSpeedImpl(12), new HashMap<Bearing, Duration>());
twaAllowances.put(new KnotSpeedImpl(14), new HashMap<Bearing, Duration>());
twaAllowances.put(new KnotSpeedImpl(16), new HashMap<Bearing, Duration>());
twaAllowances.put(new KnotSpeedImpl(20), new HashMap<Bearing, Duration>());
for (String keyTWA : twaCourses.keySet()) {
int twa = Integer.parseInt(keyTWA.substring(1));
for (Speed keyTWS : twaCourses.get(keyTWA).keySet()) {
twaAllowances.get(keyTWS).put(new DegreeBearingImpl(twa), twaCourses.get(keyTWA).get(keyTWS));
}
}
for (Speed tws : twaAllowances.keySet()) {
twaAllowances.get(tws).put(beatAngles.get(tws), predefinedCourses.get(BEAT).get(tws));
twaAllowances.get(tws).put(gybeAngles.get(tws), predefinedCourses.get(RUN).get(tws));
}
return new ORCPerformanceCurveImpl(twaAllowances, beatAngles, gybeAngles, course);
}
}
@@ -12,7 +12,6 @@ import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import com.sap.sailing.domain.common.impl.KnotSpeedImpl;
import com.sap.sailing.domain.orc.ORCCertificate;
import com.sap.sailing.domain.orc.ORCCertificateImporter;
import com.sap.sse.common.Bearing;
import com.sap.sse.common.Duration;
@@ -65,10 +64,10 @@ public class ORCCertificateImporterJSON implements ORCCertificateImporter {
}
/**
* Returns an {@link ORCCertificate} object for a given {@link String} key. If there is no map value for the given key, the method returns {@link null}.
* Returns an {@link ORCCertificateImpl} object for a given {@link String} key. If there is no map value for the given key, the method returns {@link null}.
*/
@Override
public ORCCertificate getCertificate(String sailnumber) {
public ORCCertificateImpl getCertificate(String sailnumber) {
String searchString = sailnumber.replaceAll(" ", "").toUpperCase();
@@ -200,15 +199,15 @@ public class ORCCertificateImporterJSON implements ORCCertificateImporter {
}
}
return new ORCCertificate(general, hull, sails, scoring, twaCourses, predefinedCourses, beatAngles, gybeAngles);
return new ORCCertificateImpl(general, hull, sails, scoring, twaCourses, predefinedCourses, beatAngles, gybeAngles);
}
/**
* Returns a {@link Map} of {@link ORCCertificate} keyed by the {@link String} sailnumbers, which were given as an input inside an array.
* Returns a {@link Map} of {@link ORCCertificateImpl} keyed by the {@link String} sailnumbers, which were given as an input inside an array.
*/
@Override
public Map<String, ORCCertificate> getCertificates(String[] sailnumbers) {
Map<String, ORCCertificate> result = new HashMap<>();
public Map<String, ORCCertificateImpl> getCertificates(String[] sailnumbers) {
Map<String, ORCCertificateImpl> result = new HashMap<>();
for (String sailnumber : sailnumbers) {
result.put(sailnumber, getCertificate(sailnumber));
@@ -21,7 +21,6 @@ public class ORCPerformanceCurveCourseImpl implements ORCPerformanceCurveCourse
}
}
@Override
public ORCPerformanceCurveLeg getLeg(int i) {
return legs.get(i);
}
@@ -37,4 +36,10 @@ public class ORCPerformanceCurveCourseImpl implements ORCPerformanceCurveCourse
return legs;
}
@Override
public ORCPerformanceCurveCourse subcourse(int lastFinishedLeg, float perCentOfCurrentLeg) {
// TODO Auto-generated method stub
return null;
}
}
@@ -12,7 +12,6 @@ import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.analysis.polynomials.PolynomialFunctionLagrangeForm;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.impl.KnotSpeedImpl;
import com.sap.sailing.domain.orc.ORCPerformanceCurve;
import com.sap.sailing.domain.orc.ORCPerformanceCurveCourse;
import com.sap.sailing.domain.orc.ORCPerformanceCurveLeg;
@@ -33,14 +32,6 @@ import com.sap.sse.common.Speed;
public class ORCPerformanceCurveImpl implements Serializable, ORCPerformanceCurve {
private static final long serialVersionUID = 4113356173492168453L;
public static final Speed[] ALLOWANCES_TRUE_WIND_SPEEDS = { new KnotSpeedImpl( 6),
new KnotSpeedImpl( 8),
new KnotSpeedImpl(10),
new KnotSpeedImpl(12),
new KnotSpeedImpl(14),
new KnotSpeedImpl(16),
new KnotSpeedImpl(20) };
//TODO COMMENT for key
private final Map<Speed, Map<Bearing, Duration>> durationPerNauticalMileAtTrueWindAngleAndSpeed;
@@ -62,6 +53,11 @@ public class ORCPerformanceCurveImpl implements Serializable, ORCPerformanceCurv
* {@link #durationPerNauticalMileAtTrueWindAngleAndSpeed}.
*/
private transient Map<Speed, PolynomialFunctionLagrangeForm> lagrangePolynomialsPerTrueWindSpeed;
/*
*
*/
private final ORCPerformanceCurveCourse course;
/**
* Accepts the simplified polar data, one "column" for each of the defined true wind speeds, where each column is a
@@ -69,11 +65,11 @@ public class ORCPerformanceCurveImpl implements Serializable, ORCPerformanceCurv
* boat is assumed to need at that true wind speed/angle for one nautical mile.
*/
public ORCPerformanceCurveImpl(Map<Speed, Map<Bearing, Duration>> twaAllowances, Map<Speed, Bearing> beatAngles,
Map<Speed, Bearing> gybeAngles) {
Map<Speed, Map<Bearing, Duration>> map = twaAllowances;
durationPerNauticalMileAtTrueWindAngleAndSpeed = Collections.unmodifiableMap(map);
Map<Speed, Bearing> gybeAngles, ORCPerformanceCurveCourse course) {
durationPerNauticalMileAtTrueWindAngleAndSpeed = Collections.unmodifiableMap(twaAllowances);
this.beatAngles = Collections.unmodifiableMap(beatAngles);
this.gybeAngles = Collections.unmodifiableMap(gybeAngles);
this.course = course;
lagrangePolynomialsPerTrueWindSpeed = createLagrangePolynomials();
}
@@ -109,7 +105,7 @@ public class ORCPerformanceCurveImpl implements Serializable, ORCPerformanceCurv
allowancesPerLeg.put(leg, createAllowancePerLeg(leg));
}
for (Speed tws : ALLOWANCES_TRUE_WIND_SPEEDS) {
for (Speed tws : ORCCertificateImpl.ALLOWANCES_TRUE_WIND_SPEEDS) {
Double allowancePerTws = 0.0;
for (Entry<ORCPerformanceCurveLeg, Map<Speed, Duration>> entry : allowancesPerLeg.entrySet()) {
@@ -173,6 +169,7 @@ public class ORCPerformanceCurveImpl implements Serializable, ORCPerformanceCurv
public PolynomialFunctionLagrangeForm getLagrangeInterpolationPerTrueWindSpeed(Speed trueWindSpeed) {
return lagrangePolynomialsPerTrueWindSpeed.getOrDefault(trueWindSpeed, null);
}
// public accessibility needed for tests, not part of the ORCPerformanceCurve contract
public Duration getDurationPerNauticalMileAtTrueWindAngleAndSpeed(Speed trueWindSpeed, Bearing trueWindAngle) {
return durationPerNauticalMileAtTrueWindAngleAndSpeed.getOrDefault(trueWindSpeed, null).getOrDefault(trueWindAngle, null);