Further refectoring and changes in function signatures of ORCPerformanceCurveImpl to adopt the different ORCPerformanceCurveLegTypes.

This commit is contained in:
Daniel Lisunkin committed 2019-09-04 14:32:19 +02:00
1 parent 3c23b6b2e1
commit 6b3fb021b0
4 files changed
+35 -106

No files matched your search

@@ -1,16 +0,0 @@
package com.sap.sailing.domain.abstractlog.orc;
import java.io.Serializable;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent;
import com.sap.sailing.domain.common.orc.ORCCertificate;
// TODO Here is needed a solution/concept to use this kind of events in race and regatta logs.
// Additionally the logic shouldn't be implemented at two different places.
public interface ORCCertificateAssignmentEvent extends RegattaLogEvent {
public Serializable getCompetitorID();
public ORCCertificate getCertificate();
}
@@ -2,7 +2,7 @@ package com.sap.sailing.domain.abstractlog.orc;
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
//TODO
//TODO Implementation and decision wether the sratch boat should be set for a whole regatta or per race
public interface ORCScratchBoatEvent extends RaceLogEvent {
}
@@ -1,50 +0,0 @@
package com.sap.sailing.domain.abstractlog.orc.impl;
import java.io.Serializable;
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.impl.AbstractLogEventImpl;
import com.sap.sailing.domain.abstractlog.orc.ORCCertificateAssignmentEvent;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorAndBoat;
import com.sap.sailing.domain.common.orc.ORCCertificate;
import com.sap.sse.common.TimePoint;
public class ORCCertificateAssignmentEventImpl extends AbstractLogEventImpl<RegattaLogEventVisitor> implements ORCCertificateAssignmentEvent {
private ORCCertificate certificate;
private Serializable competitorID;
public ORCCertificateAssignmentEventImpl(TimePoint createdAt, TimePoint logicalTimePoint,
AbstractLogEventAuthor author, Serializable pId, ORCCertificate certificate, Competitor competitor) {
super(createdAt, logicalTimePoint, author, pId);
this.certificate = certificate;
this.competitorID = competitor.getId();
}
public ORCCertificateAssignmentEventImpl(TimePoint createdAt, TimePoint logicalTimePoint,
AbstractLogEventAuthor author, Serializable pId, ORCCertificate certificate, Serializable competitorID) {
super(createdAt, logicalTimePoint, author, pId);
this.certificate = certificate;
this.competitorID = competitorID;
}
private static final long serialVersionUID = -3186019736784868848L;
@Override
public void accept(RegattaLogEventVisitor visitor) {
visitor.visit(this);
}
@Override
public ORCCertificate getCertificate() {
return certificate;
}
@Override
public Serializable getCompetitorID() {
return competitorID;
}
}
@@ -25,6 +25,7 @@ import com.sap.sailing.domain.common.impl.KnotSpeedImpl;
import com.sap.sailing.domain.common.orc.ORCCertificate;
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveCourse;
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLeg;
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLegTypes;
import com.sap.sailing.domain.common.orc.impl.ORCCertificateImpl;
import com.sap.sailing.domain.orc.ORCPerformanceCurve;
import com.sap.sse.common.Bearing;
@@ -77,12 +78,9 @@ public class ORCPerformanceCurveImpl implements Serializable, ORCPerformanceCurv
* map from the true wind angle (here expressed as an object of type {@link Bearing}) and the {@link Duration} the
* boat is assumed to need at that true wind speed/angle for one nautical mile.
*/
public ORCPerformanceCurveImpl(ORCCertificate cer, ORCPerformanceCurveCourse course) throws FunctionEvaluationException {
public ORCPerformanceCurveImpl(ORCCertificate certificate, ORCPerformanceCurveCourse course) throws FunctionEvaluationException {
this.course = course;
functionImpliedWindInKnotsToAverageSpeedInKnotsForCourse = createPerformanceCurve(
cer.getVelocityPredictionPerTrueWindSpeedAndAngle(),
cer.getBeatAngles(), cer.getBeatVMGPredictions(), cer.getBeatAllowances(),
cer.getRunAngles(), cer.getRunVMGPredictions(), cer.getRunAllowances());
functionImpliedWindInKnotsToAverageSpeedInKnotsForCourse = createPerformanceCurve(certificate);
}
/**
@@ -101,11 +99,8 @@ public class ORCPerformanceCurveImpl implements Serializable, ORCPerformanceCurv
* assumed at 10000kts true wind speed is the same as for the highest wind speed from the original list.
* <p>
*/
private UnivariateDifferentiableFunction createPerformanceCurve(Map<Speed, Map<Bearing, Speed>> twaAllowances,
Map<Speed, Bearing> beatAngles, Map<Speed, Speed> beatVMGPredictionPerTrueWindSpeed, Map<Speed, Duration> beatAllowancePerTrueWindSpeed,
Map<Speed, Bearing> runAngles, Map<Speed, Speed> runVMGPredictionPerTrueWindSpeed, Map<Speed, Duration> runAllowancePerTrueWindSpeed) throws FunctionEvaluationException {
final Map<Speed, Duration> allowancesForCoursePerTrueWindSpeed = createAllowancesPerCourse(twaAllowances, beatAngles,
beatVMGPredictionPerTrueWindSpeed, beatAllowancePerTrueWindSpeed, runAngles, runVMGPredictionPerTrueWindSpeed, runAllowancePerTrueWindSpeed);
private UnivariateDifferentiableFunction createPerformanceCurve(ORCCertificate certificate) throws FunctionEvaluationException {
final Map<Speed, Duration> allowancesForCoursePerTrueWindSpeed = createAllowancesPerCourse(certificate);
double[] xs = new double[ORCCertificateImpl.ALLOWANCES_TRUE_WIND_SPEEDS.length+2];
double[] ys = new double[ORCCertificateImpl.ALLOWANCES_TRUE_WIND_SPEEDS.length+2];
int i = 0;
@@ -142,15 +137,13 @@ public class ORCPerformanceCurveImpl implements Serializable, ORCPerformanceCurv
* {@link #course}, keyed by the different true wind speeds. The resulting {@link LinkedHashMap}'s iteration
* order is guaranteed to deliver the true wind speed keys in the order of ascending wind speeds.
*/
public LinkedHashMap<Speed, Duration> createAllowancesPerCourse(Map<Speed, Map<Bearing, Speed>> velocityPredictionPerTrueWindSpeedAndAngle,
Map<Speed, Bearing> beatAngles, Map<Speed, Speed> beatVMGPredictionPerTrueWindSpeed, Map<Speed, Duration> beatAllowancePerTrueWindSpeed,
Map<Speed, Bearing> runAngles, Map<Speed, Speed> runVMGPredictionPerTrueWindSpeed, Map<Speed, Duration> runAllowancePerTrueWindSpeed)
throws FunctionEvaluationException {
public LinkedHashMap<Speed, Duration> createAllowancesPerCourse(ORCCertificate certificate) throws FunctionEvaluationException {
final LinkedHashMap<Speed, Duration> result = new LinkedHashMap<>();
final Map<ORCPerformanceCurveLeg, Map<Speed, Duration>> allowancesPerLeg = new HashMap<>();
for (final ORCPerformanceCurveLeg leg : course.getLegs()) {
allowancesPerLeg.put(leg, createAllowancePerLeg(leg, velocityPredictionPerTrueWindSpeedAndAngle, beatAngles,
beatVMGPredictionPerTrueWindSpeed, beatAllowancePerTrueWindSpeed, runAngles, runVMGPredictionPerTrueWindSpeed, runAllowancePerTrueWindSpeed));
allowancesPerLeg.put(leg, createAllowancePerLeg(leg, certificate));
}
for (final Speed tws : ORCCertificateImpl.ALLOWANCES_TRUE_WIND_SPEEDS) {
double allowancePerTws = 0.0;
@@ -166,30 +159,32 @@ public class ORCPerformanceCurveImpl implements Serializable, ORCPerformanceCurv
* Computes the durations the boat to which this performance curve belongs is expected to sail to complete the {@code leg},
* considering the leg's {@link ORCPerformanceCurveLeg#getLength() length}.
*/
private Map<Speed, Duration> createAllowancePerLeg(ORCPerformanceCurveLeg leg,
Map<Speed, Map<Bearing, Speed>> twaAllowances, Map<Speed, Bearing> beatAngles,
Map<Speed, Speed> beatVMGPredictionPerTrueWindSpeed, Map<Speed, Duration> beatAllowancePerTrueWindSpeed, Map<Speed, Bearing> runAngles,
Map<Speed, Speed> runVMGPredictionPerTrueWindSpeed, Map<Speed, Duration> runAllowancePerTrueWindSpeed) throws FunctionEvaluationException {
private Map<Speed, Duration> createAllowancePerLeg(ORCPerformanceCurveLeg leg, ORCCertificate certificate) throws FunctionEvaluationException {
Map<Speed, Map<Bearing, Speed>> twaAllowances = certificate.getVelocityPredictionPerTrueWindSpeedAndAngle();
Map<Speed, Bearing> beatAngles = certificate.getBeatAngles();
Map<Speed, Speed> beatVMGPredictionPerTrueWindSpeed = certificate.getBeatVMGPredictions();
Map<Speed, Duration> beatAllowancePerTrueWindSpeed = certificate.getBeatAllowances();
Map<Speed, Bearing> runAngles = certificate.getRunAngles();
Map<Speed, Speed> runVMGPredictionPerTrueWindSpeed = certificate.getRunVMGPredictions();
Map<Speed, Duration> runAllowancePerTrueWindSpeed = certificate.getRunAllowances();
final Map<Speed, Duration> result = new HashMap<>();
for (final Speed tws : 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 (leg.getTwa().compareTo(beatAngles.get(tws)) <= 0) {
// Case 0 & 1 - result = beatVMG * distance * cos(TWA)
// TODO Test if it is necessary to provide the allowances for the accuracy (so the interfaces stay so large) or if calculating back from the velocity is accurate enough
//result.put(tws, beatVMGPredictionPerTrueWindSpeed.get(tws).getDuration(
// /* rhumb line distance of upwind leg projected to wind */ leg.getLength().scale(Math.cos(leg.getTwa().getRadians()))));
result.put(tws, beatAllowancePerTrueWindSpeed.get(tws).times(leg.getLength().getNauticalMiles()).times(Math.cos(leg.getTwa().getRadians())));
} else if (leg.getTwa().compareTo(runAngles.get(tws)) >= 0) {
// Case 3 & 4 - result = runVMG * distance * cos(TWA)
//result.put(tws, runVMGPredictionPerTrueWindSpeed.get(tws).getDuration(
// /* rhumb line distance of downwind leg projected to wind */ leg.getLength().scale(Math.cos(Math.PI-leg.getTwa().getRadians()))));
result.put(tws, runAllowancePerTrueWindSpeed.get(tws).times(leg.getLength().getNauticalMiles()).times(Math.cos(Math.PI - leg.getTwa().getRadians())));
} else {
// Case 2 - result is given through the laGrange Interpolation, between the Beat and Gybe Angles
result.put(tws,
getLagrangeSpeedPredictionForTrueWindSpeedAndAngle(twaAllowances, beatAngles,
beatVMGPredictionPerTrueWindSpeed, runAngles, runVMGPredictionPerTrueWindSpeed, tws,
leg.getTwa()).getDuration(leg.getLength()));
if(leg.getType().equals(ORCPerformanceCurveLegTypes.TWA)) {
for (final Speed tws : 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 (leg.getTwa().compareTo(beatAngles.get(tws)) <= 0) {
// Case 0 & 1 - result = beatVMG * distance * cos(TWA)
result.put(tws, beatAllowancePerTrueWindSpeed.get(tws).times(leg.getLength().getNauticalMiles()).times(Math.cos(leg.getTwa().getRadians())));
} else if (leg.getTwa().compareTo(runAngles.get(tws)) >= 0) {
// Case 3 & 4 - result = runVMG * distance * cos(TWA)
result.put(tws, runAllowancePerTrueWindSpeed.get(tws).times(leg.getLength().getNauticalMiles()).times(Math.cos(Math.PI - leg.getTwa().getRadians())));
} else {
// Case 2 - result is given through the laGrange Interpolation, between the Beat and Gybe Angles
result.put(tws,
getLagrangeSpeedPredictionForTrueWindSpeedAndAngle(twaAllowances, beatAngles,
beatVMGPredictionPerTrueWindSpeed, runAngles, runVMGPredictionPerTrueWindSpeed, tws,
leg.getTwa()).getDuration(leg.getLength()));
}
}
}
return result;