mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-11 13:22:43 +00:00
bug5154: added a first trivial test case for the reconciler
This commit is contained in:
1 parent
117cbff8c8
commit
b707fa6cb9
5 files changed
+157
-6
No files matched your search
-1
@@ -26,7 +26,6 @@ public class AbortingFlagFinder extends RaceLogAnalyzer<RaceLogFlagEvent> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
package com.sap.sailing.domain.tracking;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
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 static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
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.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.AbortingFlagFinder;
|
||||
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.race.impl.RaceLogPassChangeEventImpl;
|
||||
import com.sap.sailing.domain.common.racelog.Flags;
|
||||
import com.sap.sailing.domain.tractracadapter.DomainFactory;
|
||||
import com.sap.sailing.domain.tractracadapter.impl.RaceAndCompetitorStatusWithRaceLogReconciler;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.tractrac.model.lib.api.event.IRace;
|
||||
import com.tractrac.model.lib.api.event.RaceStatusType;
|
||||
|
||||
/**
|
||||
* See also bug 5154 and {@link RaceAndCompetitorStatusWithRaceLogReconciler}.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public class TestTracTracRaceAndCompetitorStatusReconciler {
|
||||
private AbstractLogEventAuthor author;
|
||||
private TrackedRace trackedRace;
|
||||
private IRace tractracRace;
|
||||
private RaceLog raceLog;
|
||||
private RaceAndCompetitorStatusWithRaceLogReconciler reconciler;
|
||||
private TimePoint startOfPass;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
author = new LogEventAuthorImpl("me", 1);
|
||||
startOfPass = MillisecondsTimePoint.now();
|
||||
tractracRace = mock(IRace.class);
|
||||
trackedRace = mock(TrackedRace.class);
|
||||
raceLog = new RaceLogImpl("RaceLogID");
|
||||
when(trackedRace.getAttachedRaceLogs()).thenReturn(Collections.singleton(raceLog));
|
||||
reconciler = new RaceAndCompetitorStatusWithRaceLogReconciler(DomainFactory.INSTANCE, new RaceLogResolver() {
|
||||
@Override
|
||||
public RaceLog resolve(SimpleRaceLogIdentifier identifier) {
|
||||
return raceLog;
|
||||
}
|
||||
});
|
||||
raceLog.add(new RaceLogPassChangeEventImpl(startOfPass, author, /* pPassId */ 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAbandonInFirstPass() {
|
||||
assertNull(new AbortingFlagFinder(raceLog).analyze());
|
||||
when(tractracRace.getStatus()).thenReturn(RaceStatusType.ABANDONED);
|
||||
final TimePoint abandonTimePoint = startOfPass.plus(Duration.ONE_MINUTE);
|
||||
when(tractracRace.getStatusTime()).thenReturn(abandonTimePoint.asMillis());
|
||||
reconciler.reconcileRaceStatus(tractracRace, trackedRace);
|
||||
final RaceLogFlagEvent abandonFlagEvent = new AbortingFlagFinder(raceLog).analyze();
|
||||
assertNotNull(abandonFlagEvent);
|
||||
assertSame(Flags.NOVEMBER, abandonFlagEvent.getUpperFlag());
|
||||
assertTrue(abandonFlagEvent.isDisplayed());
|
||||
assertEquals(abandonTimePoint, abandonFlagEvent.getLogicalTimePoint());
|
||||
}
|
||||
}
|
||||
+67
-2
@@ -6,10 +6,13 @@ import java.util.stream.StreamSupport;
|
||||
import com.sap.sailing.domain.abstractlog.race.CompetitorResult;
|
||||
import com.sap.sailing.domain.abstractlog.race.CompetitorResults;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.AbortingFlagFinder;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.impl.ReadonlyRaceStateImpl;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tractracadapter.DomainFactory;
|
||||
import com.sap.sse.common.Util;
|
||||
@@ -38,11 +41,73 @@ public class RaceAndCompetitorStatusWithRaceLogReconciler {
|
||||
this.raceLogResolver = raceLogResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* The following race status types are currently available on the TracTrac side (see {@link RaceStatusType}):
|
||||
* <ul>
|
||||
* <li>NONE(0)</li>
|
||||
* <li>START(4)</li>
|
||||
* <li>RACING(5)</li>
|
||||
* <li>UNOFFICIAL(7)</li>
|
||||
* <li>ABANDONED(8)</li>
|
||||
* <li>OFFICIAL(9)</li>
|
||||
* <li>GENERAL_RECALL(10)</li>
|
||||
* <li>POSTPONED(11)</li>
|
||||
* </ul>
|
||||
* We are interested in status transitions that need to be reflected by an "N" ("November", abort), "AP" (answering
|
||||
* pennant, postponement), or 1st substitute (general recall) flag status in the race log. The TracTrac-provided
|
||||
* status transition has a time stamp on it (see {@link IRace#getStatusTime()}), and so would any aborting flag
|
||||
* event in a {@link RaceLog} as well as any pass change event. If the TracTrac status time is later than the last
|
||||
* race log-based aborting flag event from the current pass and the TracTrac status is none of {@code ABANDONED},
|
||||
* {@code GENERAL_RECALL} or {@code POSTPONED}, a new pass will be established in the race log. If the TracTrac
|
||||
* status is any of {@code ABANDONED}, {@code GENERAL_RECALL} or {@code POSTPONED}, and the race log has not the
|
||||
* matching aborting flag in the current pass, and the TracTrac status update time is later than the last race log
|
||||
* status, the corresponding race log event that represents {@code ABANDONED}, {@code GENERAL_RECALL} or
|
||||
* {@code POSTPONED}, respectively, will be appended to the {@link #getDefaultRaceLog(TrackedRace) default race
|
||||
* log}.
|
||||
* <p>
|
||||
*
|
||||
* There is no API currently that allows us to determine the start mode flag. Manual intervention would be required
|
||||
* if a non-default start mode flag is to be shown.
|
||||
* <p>
|
||||
*
|
||||
* If multiple race logs are attached, a "default" race log will be determined, e.g., based on the one that already
|
||||
* has the most events in it. See {@link #getDefaultRaceLog}. Here go the cases:
|
||||
* <ul>
|
||||
* <li>any to {@code ABANDONED}: ensure the current pass has the "November" (N) flag set</li>
|
||||
* <li>any to {@code GENERAL_RECALL}: ensure the current pass has the "1st Substitute" flag set</li>
|
||||
* <li>any to {@code POSTPONED}: ensure the current pass has the "Answering Pennant" (AP) flag set</li>
|
||||
* <li></li>
|
||||
* <li></li>
|
||||
* </ul>
|
||||
*/
|
||||
public void reconcileRaceStatus(IRace tractracRace, TrackedRace trackedRace) {
|
||||
final RaceStatusType status = tractracRace.getStatus();
|
||||
final RaceStatusType raceStatus = tractracRace.getStatus();
|
||||
final long raceStatusUpdateTime = tractracRace.getStatusTime();
|
||||
for (final RaceLog raceLog : trackedRace.getAttachedRaceLogs()) {
|
||||
final ReadonlyRaceState raceState = ReadonlyRaceStateImpl.getOrCreate(raceLogResolver, raceLog);
|
||||
final RaceLogRaceStatus raceLogRaceStatus = raceState.getStatus();
|
||||
final AbortingFlagFinder abortingFlagFinder = new AbortingFlagFinder(raceLog);
|
||||
final RaceLogFlagEvent abortingFlagEvent = abortingFlagFinder.analyze();
|
||||
|
||||
// TODO bug5154:
|
||||
}
|
||||
// TODO bug5154 check IRace.getStatus() and somewhere update status once it reached RaceStatusType.OFFICIAL
|
||||
}
|
||||
|
||||
/**
|
||||
* If no race log is attached to the {@code trackedRace}, {@code null} is returned. If exactly one race log
|
||||
* is attached, it is returned. If multiple race logs are attached, the one with the most entries is returned.
|
||||
*/
|
||||
private RaceLog getDefaultRaceLog(TrackedRace trackedRace) {
|
||||
final RaceLog result;
|
||||
if (Util.isEmpty(trackedRace.getAttachedRaceLogs())) {
|
||||
result = null;
|
||||
} else {
|
||||
result = Util.stream(trackedRace.getAttachedRaceLogs()).max((rl1, rl2)->Integer.compare(rl1.size(), rl2.size())).get();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* If an official finish time exists on the {@link IRaceCompetitor} but not in any of the {@link TrackedRace}'s
|
||||
* {@link RaceLog}-based results, or the corresponding TracTrac information is newer than the race log-based result,
|
||||
@@ -60,7 +125,7 @@ public class RaceAndCompetitorStatusWithRaceLogReconciler {
|
||||
*/
|
||||
public void reconcileCompetitorStatus(IRaceCompetitor raceCompetitor, TrackedRace trackedRace) {
|
||||
final Competitor competitor = domainFactory.resolveCompetitor(raceCompetitor.getCompetitor());
|
||||
final RaceCompetitorStatusType status = raceCompetitor.getStatus();
|
||||
final RaceCompetitorStatusType competitorStatus = raceCompetitor.getStatus();
|
||||
final int officialRank = raceCompetitor.getOfficialRank();
|
||||
final long officialFinishingTime = raceCompetitor.getOfficialFinishTime();
|
||||
final long timePointForStatusEvent = raceCompetitor.getStatusTime();
|
||||
|
||||
+3
-3
@@ -550,13 +550,13 @@ public class RaceContext {
|
||||
RaceLogFlagEvent abortingFlagEvent = checkForAbortFlagEvent();
|
||||
if (abortingFlagEvent != null) {
|
||||
Flags upperFlag = abortingFlagEvent.getUpperFlag();
|
||||
if(upperFlag.equals(Flags.AP)) {
|
||||
if (upperFlag.equals(Flags.AP)) {
|
||||
return RaceViewState.POSTPONED;
|
||||
}
|
||||
if(upperFlag.equals(Flags.NOVEMBER)) {
|
||||
if (upperFlag.equals(Flags.NOVEMBER)) {
|
||||
return RaceViewState.ABANDONED;
|
||||
}
|
||||
if(upperFlag.equals(Flags.FIRSTSUBSTITUTE)) {
|
||||
if (upperFlag.equals(Flags.FIRSTSUBSTITUTE)) {
|
||||
return RaceViewState.ABANDONED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import com.sap.sse.common.util.MappingIterable;
|
||||
@@ -928,4 +929,12 @@ public class Util {
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a non-parallel stream for the {@link Iterable} passed. Short for
|
||||
* {@code StreamSupport.stream(iterable.spliterator(), false)}.
|
||||
*/
|
||||
public static <T> Stream<T> stream(Iterable<T> iterable) {
|
||||
return StreamSupport.stream(iterable.spliterator(), /* parallel */ false);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user