From c8c3f8da35d949a04f623d2b3792231bebbb5e2a Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Tue, 21 Apr 2020 19:10:50 +0200 Subject: [PATCH] bug5219: added logic to race log tracking that re-tracks race when competitors change; this makes the test case green that was previously red --- .../impl/RaceLogRaceTracker.java | 70 ++++++++++++++++--- ...ticRetrackUponCompetitorSetChangeTest.java | 1 - .../src/com/sap/sse/common/Util.java | 18 ++++- 3 files changed, 78 insertions(+), 11 deletions(-) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java index 596e42a0509..f0280bd3dc5 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java @@ -20,6 +20,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastPublishedCourseDesignFinder; @@ -28,12 +29,18 @@ import com.sap.sailing.domain.abstractlog.race.impl.BaseRaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEndOfTrackingEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartOfTrackingEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceInformationFinder; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogTrackingStateAnalyzer; +import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RegisteredCompetitorsAndBoatsAnalyzer; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.abstractlog.regatta.impl.BaseRegattaLogEventVisitor; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; @@ -146,6 +153,26 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl { trackedRace.updateStartAndEndOfTracking(/* waitForGPSFixesToLoad */ false); } } + + @Override + public void visit(RaceLogRevokeEvent event) { + if (event.getRevokedEventType().equals(RaceLogRegisterCompetitorEventImpl.class.getName())) { + try { + checkForChangeOfCompetitorSet(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + @Override + public void visit(RaceLogRegisterCompetitorEvent event) { + try { + checkForChangeOfCompetitorSet(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } }; visitors.put(log, visitor); ((RaceLog) log).addListener(visitor); @@ -155,6 +182,26 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl { public void visit(RegattaLogDefineMarkEvent event) { RaceLogRaceTracker.this.onDefineMarkEvent(event); } + + @Override + public void visit(RegattaLogRevokeEvent event) { + if (event.getRevokedEventType().equals(RegattaLogRegisterCompetitorEventImpl.class.getName())) { + try { + checkForChangeOfCompetitorSet(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + @Override + public void visit(RegattaLogRegisterCompetitorEvent event) { + try { + checkForChangeOfCompetitorSet(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } }; visitors.put(log, visitor); ((RegattaLog) log).addListener(visitor); @@ -168,6 +215,13 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl { } } + private void checkForChangeOfCompetitorSet() throws Exception { + final Map competitorsAndTheirBoats = new RegisteredCompetitorsAndBoatsAnalyzer(params.getRaceLog(), params.getRegattaLog()).analyze(); + if (!Util.setEquals(competitorsAndTheirBoats.keySet(), getRace().getCompetitors())) { + trackedRegattaRegistry.updateRaceCompetitors(getRegatta(), getRace()); + } + } + @Override protected void onStop(boolean preemptive, boolean willBeRemoved) { RaceLog raceLog = params.getRaceLog(); @@ -273,18 +327,18 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl { } private void startTracking(RaceLogStartTrackingEvent event) { - RaceLog raceLog = params.getRaceLog(); - RaceColumn raceColumn = params.getRaceColumn(); - Fleet fleet = params.getFleet(); - RaceLogDenoteForTrackingEvent denoteEvent = new RaceInformationFinder(raceLog).analyze(); + final RaceLog raceLog = params.getRaceLog(); + final RaceColumn raceColumn = params.getRaceColumn(); + final Fleet fleet = params.getFleet(); + final RaceLogDenoteForTrackingEvent denoteEvent = new RaceInformationFinder(raceLog).analyze(); final Pair trackingTimes = new TrackingTimesFinder(raceLog).analyze(); if (!trackedRegatta.getRegatta().isControlTrackingFromStartAndFinishTimes() && (trackingTimes == null || trackingTimes.getA() == null || trackingTimes.getA().getTimePoint() == null)) { // the start of tracking interval is unset or set to null; enter "now" as start of tracking into the race log raceLog.add(new RaceLogStartOfTrackingEventImpl(MillisecondsTimePoint.now(), raceLogEventAuthor, raceLog.getCurrentPassId())); } - BoatClass boatClass = denoteEvent.getBoatClass(); - String raceName = denoteEvent.getRaceName(); + final BoatClass boatClass = denoteEvent.getBoatClass(); + final String raceName = denoteEvent.getRaceName(); CourseBase courseBase = new LastPublishedCourseDesignFinder(raceLog, /* onlyCoursesWithValidWaypointList */ true).analyze(); if (courseBase == null) { courseBase = new CourseDataImpl("Default course for " + raceName); @@ -303,8 +357,8 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl { } throw new RaceNotCreatedException(String.format("Race for racelog (%s) has already been created", raceLog)); } - Map competitorsAndTheirBoats = raceColumn.getAllCompetitorsAndTheirBoats(params.getFleet()); - Serializable raceId = denoteEvent.getRaceId(); + final Map competitorsAndTheirBoats = raceColumn.getAllCompetitorsAndTheirBoats(params.getFleet()); + final Serializable raceId = denoteEvent.getRaceId(); try { final RaceDefinition raceDef = raceTrackingHandler.createRaceDefinition(trackedRegatta.getRegatta(), raceName, course, boatClass, competitorsAndTheirBoats, raceId); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/AutomaticRetrackUponCompetitorSetChangeTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/AutomaticRetrackUponCompetitorSetChangeTest.java index 2c958b00ddf..0bc7c72e049 100755 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/AutomaticRetrackUponCompetitorSetChangeTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/AutomaticRetrackUponCompetitorSetChangeTest.java @@ -208,7 +208,6 @@ public class AutomaticRetrackUponCompetitorSetChangeTest { final RegattaAndRaceIdentifier raceIdentifier = trackedRace.getRaceIdentifier(); assertEquals(1, Util.size(trackedRace.getRace().getCompetitors())); assertSame(firstCompetitor, trackedRace.getRace().getCompetitors().iterator().next()); - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), service.getServerAuthor(), firstCompetitor)); // Now add a second competitor registration ("late-comer") to the regatta log and expect the race to reload: regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), service.getServerAuthor(), secondCompetitor)); final CompletableFuture raceTrackerFuture = new CompletableFuture<>(); diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/Util.java b/java/com.sap.sse.common/src/com/sap/sse/common/Util.java index eb420f8cff3..05a7de6b6da 100755 --- a/java/com.sap.sse.common/src/com/sap/sse/common/Util.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/Util.java @@ -764,8 +764,13 @@ public class Util { } public static Set asSet(Iterable iterable) { - final Set result = new HashSet<>(); - addAll(iterable, result); + final Set result; + if (iterable instanceof Set) { + result = (Set) iterable; + } else { + result = new HashSet<>(); + addAll(iterable, result); + } return result; } @@ -967,4 +972,13 @@ public class Util { } return result; } + + /** + * Compares two iterable sequences based on {@link Set} semantics. If both objects turn out to be {@link Set}s, + * the {@link Set#equals(Object)} method will be used. Otherwise, non-{@link Set} objects will be filled into + * temporary {@link Set} objects and then compared as sets. + */ + public static boolean setEquals(Iterable a, Iterable b) { + return asSet(a).equals(asSet(b)); + } } \ No newline at end of file