mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-02 10:23:51 +00:00
added tests for RaceLog-based ORC PCS leg definitions
Change-Id: Iddb5c41079fea3de8428f45597a6d79f8d02bee4
This commit is contained in:
1 parent
a34966fc75
commit
f00585d4cd
14 files changed
+279
-47
No files matched your search
+2
-1
@@ -22,7 +22,8 @@ public interface ORCPerformanceCurveCourse {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return summed up {@link Distance} of all {@link ORCPerformanceCurveLeg}s of an implementing instance of this
|
* @return summed up {@link Distance} of all {@link ORCPerformanceCurveLeg}s of an implementing instance of this
|
||||||
* class
|
* class; {@code null} in case the length currently cannot be determined, e.g., because no explicit lengths
|
||||||
|
* have been set and the positions of one or more waypoints are unknown.
|
||||||
*/
|
*/
|
||||||
default Distance getTotalLength() {
|
default Distance getTotalLength() {
|
||||||
Distance result = Distance.NULL;
|
Distance result = Distance.NULL;
|
||||||
|
|||||||
+16
-26
@@ -1,50 +1,40 @@
|
|||||||
package com.sap.sailing.domain.common.orc.impl;
|
package com.sap.sailing.domain.common.orc.impl;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveCourse;
|
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveCourse;
|
||||||
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLeg;
|
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLeg;
|
||||||
import com.sap.sse.common.Distance;
|
import com.sap.sse.common.Util;
|
||||||
|
|
||||||
public class ORCPerformanceCurveCourseImpl implements ORCPerformanceCurveCourse {
|
public class ORCPerformanceCurveCourseImpl implements ORCPerformanceCurveCourse {
|
||||||
private final List<ORCPerformanceCurveLeg> legs;
|
private final Iterable<ORCPerformanceCurveLeg> legs;
|
||||||
private final Distance totalLength;
|
|
||||||
|
|
||||||
public ORCPerformanceCurveCourseImpl(List<ORCPerformanceCurveLeg> legs) {
|
public ORCPerformanceCurveCourseImpl(Iterable<ORCPerformanceCurveLeg> legs) {
|
||||||
this.legs = Collections.unmodifiableList(legs);
|
this.legs = legs;
|
||||||
Distance myTotalLength = Distance.NULL;
|
|
||||||
for (ORCPerformanceCurveLeg leg : legs) {
|
|
||||||
myTotalLength = myTotalLength.add(leg.getLength());
|
|
||||||
}
|
|
||||||
totalLength = myTotalLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ORCPerformanceCurveLeg getLeg(int i) {
|
|
||||||
return legs.get(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Distance getTotalLength() {
|
public Iterable<ORCPerformanceCurveLeg> getLegs() {
|
||||||
return totalLength;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ORCPerformanceCurveLeg> getLegs() {
|
|
||||||
return legs;
|
return legs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ORCPerformanceCurveCourse subcourse(int lastFinishedLegOneBased, double shareOfCurrentLeg) {
|
public ORCPerformanceCurveCourse subcourse(int lastFinishedLegOneBased, double shareOfCurrentLeg) {
|
||||||
// does function for empty courses, returns again empty course
|
// does function for empty courses, returns again empty course
|
||||||
if (lastFinishedLegOneBased >= legs.size()) {
|
if (lastFinishedLegOneBased >= Util.size(legs)) {
|
||||||
return this;
|
return this;
|
||||||
} else {
|
} else {
|
||||||
List<ORCPerformanceCurveLeg> resultLegs = new ArrayList<>();
|
List<ORCPerformanceCurveLeg> resultLegs = new ArrayList<>();
|
||||||
resultLegs.addAll(legs.subList(0, lastFinishedLegOneBased));
|
int count = 0;
|
||||||
ORCPerformanceCurveLeg lastFinishedLeg = legs.get(lastFinishedLegOneBased);
|
ORCPerformanceCurveLeg lastFinishedLeg = null;
|
||||||
|
for (final ORCPerformanceCurveLeg leg : getLegs()) {
|
||||||
|
if (count++ >= lastFinishedLegOneBased) {
|
||||||
|
lastFinishedLeg = leg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
resultLegs.add(leg);
|
||||||
|
}
|
||||||
resultLegs.add(lastFinishedLeg.scale(shareOfCurrentLeg));
|
resultLegs.add(lastFinishedLeg.scale(shareOfCurrentLeg));
|
||||||
return new ORCPerformanceCurveCourseImpl(resultLegs);
|
return new ORCPerformanceCurveCourseImpl(resultLegs);
|
||||||
}
|
}
|
||||||
@@ -52,6 +42,6 @@ public class ORCPerformanceCurveCourseImpl implements ORCPerformanceCurveCourse
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[legs=" + legs + ", totalLength=" + totalLength + "]";
|
return "[legs=" + legs + ", totalLength=" + getTotalLength().getNauticalMiles() + "NM]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -41,7 +41,7 @@ public class ORCPerformanceCurveLegImpl implements ORCPerformanceCurveLeg {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[length=" + length.getNauticalMiles() + "NM, "+(twa==null?type.name():"TWA=" + twa.getDegrees() + "°")+"]";
|
return "[length=" + length.getNauticalMiles() + "NM, "+(twa==null?type.name():"TWA=" + twa)+"]";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+1
-1
@@ -1019,7 +1019,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
|||||||
Document result = new Document();
|
Document result = new Document();
|
||||||
storeRaceLogEventProperties(event, result);
|
storeRaceLogEventProperties(event, result);
|
||||||
result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogORCLegDataEvent.class.getSimpleName());
|
result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogORCLegDataEvent.class.getSimpleName());
|
||||||
result.put(FieldNames.ORC_LEG_NR.name(), event.getLegNr());
|
result.put(FieldNames.ORC_LEG_NR.name(), event.getOneBasedLegNumber());
|
||||||
result.put(FieldNames.ORC_LEG_LENGTH_IN_NAUTICAL_MILES.name(), event.getLength().getNauticalMiles());
|
result.put(FieldNames.ORC_LEG_LENGTH_IN_NAUTICAL_MILES.name(), event.getLength().getNauticalMiles());
|
||||||
result.put(FieldNames.ORC_LEG_TWA_IN_DEG.name(), event.getTwa().getDegrees());
|
result.put(FieldNames.ORC_LEG_TWA_IN_DEG.name(), event.getTwa().getDegrees());
|
||||||
result.put(FieldNames.ORC_LEG_TYPE.name(), event.getType().name());
|
result.put(FieldNames.ORC_LEG_TYPE.name(), event.getType().name());
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ public interface RevokeEvent<VisitorT> extends AbstractLogEvent<VisitorT> {
|
|||||||
String getReason();
|
String getReason();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link Class#getSimpleName() Simple class name} of the revoked event.
|
* {@link Class#getName() Fully-qualified class name} of the revoked event.
|
||||||
*/
|
*/
|
||||||
String getRevokedEventType();
|
String getRevokedEventType();
|
||||||
}
|
}
|
||||||
+5
-5
@@ -12,10 +12,10 @@ import com.sap.sailing.domain.common.orc.impl.ORCPerformanceCurveLegImpl;
|
|||||||
import com.sap.sse.common.Distance;
|
import com.sap.sse.common.Distance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a map with unique entries per {@link RaceLogORCLegDataEvent#getLegNr() leg number} where the
|
* Returns a map with unique entries per {@link RaceLogORCLegDataEvent#getOneBasedLegNumber() one-based leg number}
|
||||||
* relevant valid leg data is converted to the {@link ORCPerformanceCurveLeg} data. Note that for legs
|
* where the relevant valid leg data is converted to the {@link ORCPerformanceCurveLeg} data. Note that for legs for
|
||||||
* for which no entry is found no adapter to any tracked race or tracked leg is created implicitly. Only
|
* which no entry is found no adapter to any tracked race or tracked leg is created implicitly. Only entries with
|
||||||
* entries with explicit race log events are returned.
|
* explicit race log events are returned.
|
||||||
*
|
*
|
||||||
* @author Axel Uhl (D043530)
|
* @author Axel Uhl (D043530)
|
||||||
*
|
*
|
||||||
@@ -40,7 +40,7 @@ public class RaceLogORCLegDataAnalyzer extends RaceLogAnalyzer<Map<Integer, ORCP
|
|||||||
} else {
|
} else {
|
||||||
leg = new ORCPerformanceCurveLegImpl(length, legDataEvent.getType());
|
leg = new ORCPerformanceCurveLegImpl(length, legDataEvent.getType());
|
||||||
}
|
}
|
||||||
result.put(legDataEvent.getLegNr(), leg);
|
result.put(legDataEvent.getOneBasedLegNumber(), leg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
+1
-1
@@ -23,6 +23,6 @@ public interface RaceLogORCLegDataEvent extends RaceLogEvent, Revokable {
|
|||||||
|
|
||||||
public Bearing getTwa();
|
public Bearing getTwa();
|
||||||
|
|
||||||
public int getLegNr();
|
public int getOneBasedLegNumber();
|
||||||
|
|
||||||
}
|
}
|
||||||
+6
-6
@@ -15,15 +15,15 @@ public class RaceLogORCLegDataEventImpl extends RaceLogEventImpl implements Race
|
|||||||
|
|
||||||
private static final long serialVersionUID = -5063350268001993185L;
|
private static final long serialVersionUID = -5063350268001993185L;
|
||||||
|
|
||||||
private final int legNr;
|
private final int oneBasedLegNumber;
|
||||||
private final Bearing twa;
|
private final Bearing twa;
|
||||||
private final Distance length;
|
private final Distance length;
|
||||||
private final ORCPerformanceCurveLegTypes type;
|
private final ORCPerformanceCurveLegTypes type;
|
||||||
|
|
||||||
public RaceLogORCLegDataEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author,
|
public RaceLogORCLegDataEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author,
|
||||||
Serializable pId, int pPassId, int legNr, Bearing twa, Distance length, ORCPerformanceCurveLegTypes type) {
|
Serializable pId, int pPassId, int oneBasedLegNumber, Bearing twa, Distance length, ORCPerformanceCurveLegTypes type) {
|
||||||
super(createdAt, logicalTimePoint, author, pId, pPassId);
|
super(createdAt, logicalTimePoint, author, pId, pPassId);
|
||||||
this.legNr = legNr;
|
this.oneBasedLegNumber = oneBasedLegNumber;
|
||||||
this.twa = twa;
|
this.twa = twa;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@@ -36,12 +36,12 @@ public class RaceLogORCLegDataEventImpl extends RaceLogEventImpl implements Race
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getShortInfo() {
|
public String getShortInfo() {
|
||||||
return "ORCLegData, legNr= " + legNr + ", twa: " + twa.getDegrees() + ", length: " + length.getNauticalMiles();
|
return "ORCLegData, oneBasedLegNumber= " + oneBasedLegNumber + ", twa: " + twa.getDegrees() + ", length: " + length.getNauticalMiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getLegNr() {
|
public int getOneBasedLegNumber() {
|
||||||
return legNr;
|
return oneBasedLegNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+211
@@ -0,0 +1,211 @@
|
|||||||
|
package com.sap.sailing.domain.orc;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||||
|
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
|
||||||
|
import com.sap.sailing.domain.abstractlog.orc.RaceLogORCCertificateAssignmentEvent;
|
||||||
|
import com.sap.sailing.domain.abstractlog.orc.RaceLogORCLegDataEvent;
|
||||||
|
import com.sap.sailing.domain.abstractlog.orc.RegattaLogORCCertificateAssignmentEvent;
|
||||||
|
import com.sap.sailing.domain.abstractlog.orc.impl.RaceLogORCCertificateAssignmentEventImpl;
|
||||||
|
import com.sap.sailing.domain.abstractlog.orc.impl.RaceLogORCLegDataEventImpl;
|
||||||
|
import com.sap.sailing.domain.abstractlog.orc.impl.RegattaLogORCCertificateAssignmentEventImpl;
|
||||||
|
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||||
|
import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier;
|
||||||
|
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
|
||||||
|
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl;
|
||||||
|
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||||
|
import com.sap.sailing.domain.base.Boat;
|
||||||
|
import com.sap.sailing.domain.base.Competitor;
|
||||||
|
import com.sap.sailing.domain.base.CompetitorWithBoat;
|
||||||
|
import com.sap.sailing.domain.common.abstractlog.NotRevokableException;
|
||||||
|
import com.sap.sailing.domain.common.impl.NauticalMileDistance;
|
||||||
|
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.orc.impl.ORCPerformanceCurveLegAdapter;
|
||||||
|
import com.sap.sailing.domain.orc.impl.ORCPerformanceCurveRankingMetric;
|
||||||
|
import com.sap.sailing.domain.test.TrackBasedTest;
|
||||||
|
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||||
|
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
|
||||||
|
import com.sap.sse.common.Util;
|
||||||
|
import com.sap.sse.common.impl.DegreeBearingImpl;
|
||||||
|
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An {@link ORCPerformanceCurveRankingMetric} observes its {@link TrackedRace} for the regatta log
|
||||||
|
* and the race logs, regarding the attachment and detachment of such logs, as well as regarding
|
||||||
|
* the appearance of new certificate assignment events in those logs. This test verifies that
|
||||||
|
* the dynamics work as expected.
|
||||||
|
*
|
||||||
|
* @author Axel Uhl (d043530)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class TestORCRankingMetricCollaborationWithRaceLogAndRegattaLog {
|
||||||
|
private Boat boat1, boat2;
|
||||||
|
private CompetitorWithBoat competitor1, competitor2;
|
||||||
|
private DynamicTrackedRaceImpl trackedRace;
|
||||||
|
private RaceLog raceLog;
|
||||||
|
private RegattaLog regattaLog;
|
||||||
|
private ORCPerformanceCurveRankingMetric rankingMetric;
|
||||||
|
private AbstractLogEventAuthor authorP1 = new LogEventAuthorImpl("Test Author P1", 1);
|
||||||
|
private AbstractLogEventAuthor authorP2 = new LogEventAuthorImpl("Test Author P2", 2);
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
final RaceLogResolver raceLogResolver = createRaceLogResolver();
|
||||||
|
competitor1 = TrackBasedTest.createCompetitorWithBoat("C1");
|
||||||
|
competitor2 = TrackBasedTest.createCompetitorWithBoat("C2");
|
||||||
|
final Map<Competitor, Boat> competitorsAndBoats = TrackBasedTest.createCompetitorAndBoatsMap(competitor1, competitor2);
|
||||||
|
boat1 = competitorsAndBoats.get(competitor1);
|
||||||
|
boat2 = competitorsAndBoats.get(competitor2);
|
||||||
|
trackedRace = TrackBasedTest.createTestTrackedRace("TestRegatta", "TestRace", "F18", competitorsAndBoats,
|
||||||
|
MillisecondsTimePoint.now(), /* useMarkPassingCalculator */ false, raceLogResolver, ORCPerformanceCurveRankingMetric::new);
|
||||||
|
regattaLog = trackedRace.getTrackedRegatta().getRegatta().getRegattaLog();
|
||||||
|
trackedRace.attachRegattaLog(regattaLog);
|
||||||
|
assertSame(regattaLog, trackedRace.getAttachedRegattaLogs().iterator().next());
|
||||||
|
raceLog = new RaceLogImpl(UUID.randomUUID());
|
||||||
|
rankingMetric = (ORCPerformanceCurveRankingMetric) trackedRace.getRankingMetric();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void attachRaceLog() {
|
||||||
|
trackedRace.attachRaceLog(raceLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RaceLogResolver createRaceLogResolver() {
|
||||||
|
return new RaceLogResolver() {
|
||||||
|
@Override
|
||||||
|
public RaceLog resolve(SimpleRaceLogIdentifier identifier) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCertificateAssignments() {
|
||||||
|
// no logs attached; therefore no certs
|
||||||
|
assertNoCertificate(boat1);
|
||||||
|
assertNoCertificate(boat2);
|
||||||
|
attachRaceLog();
|
||||||
|
// empty race log attached, still no certs:
|
||||||
|
assertNoCertificate(boat1);
|
||||||
|
assertNoCertificate(boat2);
|
||||||
|
ORCCertificate boat1RegattaCert1 = mock(ORCCertificate.class);
|
||||||
|
regattaLog.add(createRegattaLogCertificateAssignmentEvent(boat1RegattaCert1, boat1, authorP1));
|
||||||
|
assertCertificate(boat1, boat1RegattaCert1);
|
||||||
|
ORCCertificate boat1RegattaCert2 = mock(ORCCertificate.class);
|
||||||
|
regattaLog.add(createRegattaLogCertificateAssignmentEvent(boat1RegattaCert2, boat1, authorP2));
|
||||||
|
// the priority for Cert2 was 2 and therefore the P1 assignment still takes precedence
|
||||||
|
assertCertificate(boat1, boat1RegattaCert1);
|
||||||
|
regattaLog.add(createRegattaLogCertificateAssignmentEvent(boat1RegattaCert2, boat1, authorP1));
|
||||||
|
assertCertificate(boat1, boat1RegattaCert2);
|
||||||
|
ORCCertificate boat2RegattaCert1 = mock(ORCCertificate.class);
|
||||||
|
regattaLog.add(createRegattaLogCertificateAssignmentEvent(boat2RegattaCert1, boat2, authorP2));
|
||||||
|
assertCertificate(boat2, boat2RegattaCert1);
|
||||||
|
// now override on race log level:
|
||||||
|
ORCCertificate boat1RaceCert1 = mock(ORCCertificate.class);
|
||||||
|
raceLog.add(createRaceLogCertificateAssignmentEvent(boat1RaceCert1, boat1, authorP2));
|
||||||
|
assertCertificate(boat1, boat1RaceCert1);
|
||||||
|
trackedRace.detachRaceLog(raceLog.getId());
|
||||||
|
// after detaching race log, boat1 must have defaulted again to the regatta log's definition
|
||||||
|
assertCertificate(boat1, boat1RegattaCert2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoCourseDefinitionsInRaceLog() {
|
||||||
|
final ORCPerformanceCurveCourse orcCourse = rankingMetric.getTotalCourse();
|
||||||
|
assertEquals(trackedRace.getRace().getCourse().getLegs().size(), Util.size(orcCourse.getLegs()));
|
||||||
|
for (final ORCPerformanceCurveLeg leg : orcCourse.getLegs()) {
|
||||||
|
assertTrue(leg instanceof ORCPerformanceCurveLegAdapter); // only adapters, no explicit leg specification yet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOneLegDefinitionInRaceLog() throws NotRevokableException {
|
||||||
|
attachRaceLog();
|
||||||
|
final double lengthInNauticalMiles = 1.7;
|
||||||
|
final double twaInDegrees = 2.0;
|
||||||
|
final RaceLogORCLegDataEvent firstLegSpecificationEvent = createLegSpecificationEvent(
|
||||||
|
/* one-based leg number */ 1, ORCPerformanceCurveLegTypes.TWA, /* distance in nautical miles */ lengthInNauticalMiles,
|
||||||
|
/* TWA */ twaInDegrees, authorP2);
|
||||||
|
raceLog.add(firstLegSpecificationEvent);
|
||||||
|
final ORCPerformanceCurveCourse orcCourse = rankingMetric.getTotalCourse();
|
||||||
|
assertEquals(trackedRace.getRace().getCourse().getLegs().size(), Util.size(orcCourse.getLegs()));
|
||||||
|
final ORCPerformanceCurveLeg firstLeg = orcCourse.getLegs().iterator().next();
|
||||||
|
assertFalse(firstLeg instanceof ORCPerformanceCurveLegAdapter);
|
||||||
|
assertEquals(lengthInNauticalMiles, firstLeg.getLength().getNauticalMiles(), 0.000001);
|
||||||
|
assertEquals(twaInDegrees, firstLeg.getTwa().getDegrees(), 0.0000001);
|
||||||
|
// now revoke event and ensure that the course defaults back to all adapters:
|
||||||
|
raceLog.revokeEvent(authorP2, firstLegSpecificationEvent);
|
||||||
|
assertEquals(trackedRace.getRace().getCourse().getLegs().size(), Util.size(rankingMetric.getTotalCourse().getLegs()));
|
||||||
|
for (final ORCPerformanceCurveLeg leg : rankingMetric.getTotalCourse().getLegs()) {
|
||||||
|
assertTrue(leg instanceof ORCPerformanceCurveLegAdapter); // only adapters, no explicit leg specification anymore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHigherPriorityLegDefinitionInRaceLogWins() throws NotRevokableException {
|
||||||
|
attachRaceLog();
|
||||||
|
final double lengthInNauticalMiles = 1.7;
|
||||||
|
final double twaP1InDegrees = 1.0;
|
||||||
|
final double twaP2InDegrees = 2.0;
|
||||||
|
final RaceLogORCLegDataEvent firstLegP2SpecificationEvent = createLegSpecificationEvent(
|
||||||
|
/* one-based leg number */ 1, ORCPerformanceCurveLegTypes.TWA, /* distance in nautical miles */ lengthInNauticalMiles,
|
||||||
|
/* TWA */ twaP2InDegrees, authorP2);
|
||||||
|
raceLog.add(firstLegP2SpecificationEvent);
|
||||||
|
final RaceLogORCLegDataEvent firstLegP1SpecificationEvent = createLegSpecificationEvent(
|
||||||
|
/* one-based leg number */ 1, ORCPerformanceCurveLegTypes.TWA, /* distance in nautical miles */ lengthInNauticalMiles,
|
||||||
|
/* TWA */ twaP1InDegrees, authorP1);
|
||||||
|
raceLog.add(firstLegP1SpecificationEvent);
|
||||||
|
final ORCPerformanceCurveCourse orcCourse = rankingMetric.getTotalCourse();
|
||||||
|
assertEquals(trackedRace.getRace().getCourse().getLegs().size(), Util.size(orcCourse.getLegs()));
|
||||||
|
final ORCPerformanceCurveLeg firstLeg = orcCourse.getLegs().iterator().next();
|
||||||
|
assertFalse(firstLeg instanceof ORCPerformanceCurveLegAdapter);
|
||||||
|
assertEquals(lengthInNauticalMiles, firstLeg.getLength().getNauticalMiles(), 0.000001);
|
||||||
|
assertEquals(twaP1InDegrees, firstLeg.getTwa().getDegrees(), 0.0000001);
|
||||||
|
// now revoke P1 event and ensure that the course defaults to the P2 definition:
|
||||||
|
raceLog.revokeEvent(authorP1, firstLegP1SpecificationEvent);
|
||||||
|
assertEquals(trackedRace.getRace().getCourse().getLegs().size(), Util.size(rankingMetric.getTotalCourse().getLegs()));
|
||||||
|
assertEquals(twaP2InDegrees, rankingMetric.getTotalCourse().getLegs().iterator().next().getTwa().getDegrees(), 0.0000001);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RaceLogORCLegDataEvent createLegSpecificationEvent(int oneBasedLegNumber,
|
||||||
|
ORCPerformanceCurveLegTypes legType, double lengthInNauticalMiles, double twaInDegrees,
|
||||||
|
AbstractLogEventAuthor author) {
|
||||||
|
return new RaceLogORCLegDataEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author,
|
||||||
|
UUID.randomUUID(), /* pass */ 0, oneBasedLegNumber, new DegreeBearingImpl(twaInDegrees),
|
||||||
|
new NauticalMileDistance(lengthInNauticalMiles), legType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RaceLogORCCertificateAssignmentEvent createRaceLogCertificateAssignmentEvent(
|
||||||
|
ORCCertificate certificate, Boat boat, AbstractLogEventAuthor author) {
|
||||||
|
return new RaceLogORCCertificateAssignmentEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(), /* pass */ 0, certificate, boat);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RegattaLogORCCertificateAssignmentEvent createRegattaLogCertificateAssignmentEvent(
|
||||||
|
ORCCertificate certificate, Boat boat, AbstractLogEventAuthor author) {
|
||||||
|
return new RegattaLogORCCertificateAssignmentEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(), certificate, boat);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertNoCertificate(Boat boat) {
|
||||||
|
final ORCCertificate certificate = rankingMetric.getCertificate(boat);
|
||||||
|
assertNull(certificate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertCertificate(Boat boat, ORCCertificate expectedCertificate) {
|
||||||
|
final ORCCertificate certificate = rankingMetric.getCertificate(boat);
|
||||||
|
assertSame(expectedCertificate, certificate);
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -50,4 +50,9 @@ public class ORCPerformanceCurveLegAdapter implements ORCPerformanceCurveLeg {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ORCPerformanceCurveLegAdapter for "+trackedLeg.getLeg()+": length="+getLength().getNauticalMiles()+"NM, TWA="+getTwa();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+27
-2
@@ -1,8 +1,10 @@
|
|||||||
package com.sap.sailing.domain.orc.impl;
|
package com.sap.sailing.domain.orc.impl;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@@ -13,8 +15,10 @@ import com.sap.sailing.domain.abstractlog.orc.RaceLogORCLegDataAnalyzer;
|
|||||||
import com.sap.sailing.domain.abstractlog.orc.RaceLogORCLegDataEvent;
|
import com.sap.sailing.domain.abstractlog.orc.RaceLogORCLegDataEvent;
|
||||||
import com.sap.sailing.domain.abstractlog.orc.RegattaLogORCCertificateAssignmentEvent;
|
import com.sap.sailing.domain.abstractlog.orc.RegattaLogORCCertificateAssignmentEvent;
|
||||||
import com.sap.sailing.domain.abstractlog.orc.RegattaLogORCCertificateAssignmentFinder;
|
import com.sap.sailing.domain.abstractlog.orc.RegattaLogORCCertificateAssignmentFinder;
|
||||||
|
import com.sap.sailing.domain.abstractlog.orc.impl.RaceLogORCLegDataEventImpl;
|
||||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||||
|
import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent;
|
||||||
import com.sap.sailing.domain.abstractlog.race.impl.BaseRaceLogEventVisitor;
|
import com.sap.sailing.domain.abstractlog.race.impl.BaseRaceLogEventVisitor;
|
||||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
||||||
@@ -27,6 +31,7 @@ import com.sap.sailing.domain.common.Position;
|
|||||||
import com.sap.sailing.domain.common.orc.ORCCertificate;
|
import com.sap.sailing.domain.common.orc.ORCCertificate;
|
||||||
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveCourse;
|
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveCourse;
|
||||||
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLeg;
|
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLeg;
|
||||||
|
import com.sap.sailing.domain.common.orc.impl.ORCPerformanceCurveCourseImpl;
|
||||||
import com.sap.sailing.domain.ranking.AbstractRankingMetric;
|
import com.sap.sailing.domain.ranking.AbstractRankingMetric;
|
||||||
import com.sap.sailing.domain.ranking.RankingMetric;
|
import com.sap.sailing.domain.ranking.RankingMetric;
|
||||||
import com.sap.sailing.domain.tracking.TrackedLeg;
|
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||||
@@ -37,6 +42,7 @@ import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener;
|
|||||||
import com.sap.sse.common.Distance;
|
import com.sap.sse.common.Distance;
|
||||||
import com.sap.sse.common.Duration;
|
import com.sap.sse.common.Duration;
|
||||||
import com.sap.sse.common.TimePoint;
|
import com.sap.sse.common.TimePoint;
|
||||||
|
import com.sap.sse.common.Util;
|
||||||
|
|
||||||
public class ORCPerformanceCurveRankingMetric extends AbstractRankingMetric {
|
public class ORCPerformanceCurveRankingMetric extends AbstractRankingMetric {
|
||||||
private static final long serialVersionUID = -7814822523533929816L;
|
private static final long serialVersionUID = -7814822523533929816L;
|
||||||
@@ -62,6 +68,7 @@ public class ORCPerformanceCurveRankingMetric extends AbstractRankingMetric {
|
|||||||
super(trackedRace);
|
super(trackedRace);
|
||||||
boatsById = initBoatsById();
|
boatsById = initBoatsById();
|
||||||
updateCertificatesFromLogs();
|
updateCertificatesFromLogs();
|
||||||
|
updateCourseFromRaceLogs();
|
||||||
certificatesFromRaceLogUpdater = createCertificatesFromRaceLogUpdater();
|
certificatesFromRaceLogUpdater = createCertificatesFromRaceLogUpdater();
|
||||||
certificatesFromRegattaLogUpdater = createCertificatesFromRegattaLogUpdater();
|
certificatesFromRegattaLogUpdater = createCertificatesFromRegattaLogUpdater();
|
||||||
if (trackedRace != null) {
|
if (trackedRace != null) {
|
||||||
@@ -101,13 +108,20 @@ public class ORCPerformanceCurveRankingMetric extends AbstractRankingMetric {
|
|||||||
return new BaseRaceLogEventVisitor() {
|
return new BaseRaceLogEventVisitor() {
|
||||||
@Override
|
@Override
|
||||||
public void visit(RaceLogORCLegDataEvent orcLegDataEventImpl) {
|
public void visit(RaceLogORCLegDataEvent orcLegDataEventImpl) {
|
||||||
updateCertificatesFromLogs();
|
updateCourseFromRaceLogs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(RaceLogORCCertificateAssignmentEvent event) {
|
public void visit(RaceLogORCCertificateAssignmentEvent event) {
|
||||||
updateCertificatesFromLogs();
|
updateCertificatesFromLogs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(RaceLogRevokeEvent event) {
|
||||||
|
if (event.getRevokedEventType().equals(RaceLogORCLegDataEventImpl.class.getName())) {
|
||||||
|
updateCourseFromRaceLogs();
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +157,18 @@ public class ORCPerformanceCurveRankingMetric extends AbstractRankingMetric {
|
|||||||
for (final RaceLog raceLog : getTrackedRace().getAttachedRaceLogs()) {
|
for (final RaceLog raceLog : getTrackedRace().getAttachedRaceLogs()) {
|
||||||
legsWithDefinitions.putAll(new RaceLogORCLegDataAnalyzer(raceLog).analyze());
|
legsWithDefinitions.putAll(new RaceLogORCLegDataAnalyzer(raceLog).analyze());
|
||||||
}
|
}
|
||||||
// TODO continue here, taking only those definitions up to the true number of legs in the race's course and fill the blanks with tracked leg adapters
|
final Iterable<Leg> legs = getTrackedRace().getRace().getCourse().getLegs();
|
||||||
|
int oneBasedLegNumber = 1;
|
||||||
|
final List<ORCPerformanceCurveLeg> performanceCurveLegs = new ArrayList<>(Util.size(legs));
|
||||||
|
for (final Leg leg : legs) {
|
||||||
|
performanceCurveLegs.add(legsWithDefinitions.computeIfAbsent(oneBasedLegNumber, i->new ORCPerformanceCurveLegAdapter(getTrackedRace().getTrackedLeg(leg))));
|
||||||
|
oneBasedLegNumber++;
|
||||||
|
}
|
||||||
|
totalCourse = new ORCPerformanceCurveCourseImpl(performanceCurveLegs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ORCPerformanceCurveCourse getTotalCourse() {
|
||||||
|
return totalCourse;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+1
-1
@@ -445,7 +445,6 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
|||||||
RaceLogResolver raceLogResolver) {
|
RaceLogResolver raceLogResolver) {
|
||||||
super(race, trackedRegatta, windStore, millisecondsOverWhichToAverageWind);
|
super(race, trackedRegatta, windStore, millisecondsOverWhichToAverageWind);
|
||||||
this.raceLogResolver = raceLogResolver;
|
this.raceLogResolver = raceLogResolver;
|
||||||
rankingMetric = rankingMetricConstructor.apply(this);
|
|
||||||
raceStates = new WeakHashMap<>();
|
raceStates = new WeakHashMap<>();
|
||||||
shortTimeWindCache = new ShortTimeWindCache(this, millisecondsOverWhichToAverageWind / 2);
|
shortTimeWindCache = new ShortTimeWindCache(this, millisecondsOverWhichToAverageWind / 2);
|
||||||
locksForMarkPassings = new ConcurrentHashMap<IdentityWrapper<Iterable<MarkPassing>>, NamedReentrantReadWriteLock>();
|
locksForMarkPassings = new ConcurrentHashMap<IdentityWrapper<Iterable<MarkPassing>>, NamedReentrantReadWriteLock>();
|
||||||
@@ -579,6 +578,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
logger.log(Level.SEVERE, "Waiting for loading from stores to finish was interrupted", e);
|
logger.log(Level.SEVERE, "Waiting for loading from stores to finish was interrupted", e);
|
||||||
}
|
}
|
||||||
|
rankingMetric = rankingMetricConstructor.apply(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ public class RaceLogORCLegDataEventSerializer extends BaseRaceLogEventSerializer
|
|||||||
public JSONObject serialize(RaceLogEvent object) {
|
public JSONObject serialize(RaceLogEvent object) {
|
||||||
RaceLogORCLegDataEvent legData = (RaceLogORCLegDataEvent) object;
|
RaceLogORCLegDataEvent legData = (RaceLogORCLegDataEvent) object;
|
||||||
JSONObject result = super.serialize(legData);
|
JSONObject result = super.serialize(legData);
|
||||||
result.put(ORC_LEG_NR, legData.getLegNr());
|
result.put(ORC_LEG_NR, legData.getOneBasedLegNumber());
|
||||||
result.put(ORC_LEG_LENGTH, legData.getLength().getNauticalMiles());
|
result.put(ORC_LEG_LENGTH, legData.getLength().getNauticalMiles());
|
||||||
result.put(ORC_LEG_TWA, legData.getTwa().getDegrees());
|
result.put(ORC_LEG_TWA, legData.getTwa().getDegrees());
|
||||||
result.put(ORC_LEG_TYPE, legData.getType().name());
|
result.put(ORC_LEG_TYPE, legData.getType().name());
|
||||||
|
|||||||
+1
-1
@@ -101,7 +101,7 @@ public class RaceLogEventDeserializerTest {
|
|||||||
assertEquals(originalEvent.getClass(), newEvent.getClass());
|
assertEquals(originalEvent.getClass(), newEvent.getClass());
|
||||||
assertEquals(originalEvent.getId(), newEvent.getId());
|
assertEquals(originalEvent.getId(), newEvent.getId());
|
||||||
assertEquals(originalEvent.getShortInfo(), newEvent.getShortInfo());
|
assertEquals(originalEvent.getShortInfo(), newEvent.getShortInfo());
|
||||||
assertEquals(originalEvent.getLegNr(), newEvent.getLegNr());
|
assertEquals(originalEvent.getOneBasedLegNumber(), newEvent.getOneBasedLegNumber());
|
||||||
assertEquals(originalEvent.getTwa(), newEvent.getTwa());
|
assertEquals(originalEvent.getTwa(), newEvent.getTwa());
|
||||||
assertEquals(originalEvent.getType(), newEvent.getType());
|
assertEquals(originalEvent.getType(), newEvent.getType());
|
||||||
assertEquals(originalEvent.getLength(), newEvent.getLength());
|
assertEquals(originalEvent.getLength(), newEvent.getLength());
|
||||||
|
|||||||
Reference in new issue
Block a user