Skip to content

Commit 5ad8171

Browse files
Auto-merging main (15c87fd) into docker-25 after successful release build
2 parents f862200 + 15c87fd commit 5ad8171

File tree

246 files changed

+1549
-1028
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

246 files changed

+1549
-1028
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.sap.sailing.domain.common.racelog.tracking;
2+
3+
/**
4+
* Error codes for the revocation of tracking times. These are used to report errors that occur during the revocation
5+
* process, e.g. when there is no regatta leaderboard or when there are no automated tracking times.
6+
*
7+
* @see com.sap.sailing.domain.racelogtracking.TrackingTimesRevocationReport
8+
*
9+
* @author Axel Uhl (d043530)
10+
*
11+
*/
12+
public enum TrackingTimesRevocationErrorCode {
13+
NO_REGATTA_LEADERBOARD,
14+
NO_AUTOMATED_TRACKING_TIMES
15+
}

java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/RaceLogTrackingAdapter.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,4 +140,6 @@ void copyCourse(RaceLog fromRaceLog, LeaderboardThatHasRegattaLike fromLeaderboa
140140
*/
141141
void copyPairingListFromOtherLeaderboard(RegattaLeaderboard sourceLeaderboard, RegattaLeaderboard targetLeaderboard,
142142
String fromRaceColumnName, String toRaceColumnInclusiveName) throws NotFoundException;
143+
144+
TrackingTimesRevocationReport revokeExplicitTrackingTimes(RegattaLeaderboard leaderboard, RacingEventService raceLogResolver);
143145
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.sap.sailing.domain.racelogtracking;
2+
3+
import java.util.Map;
4+
import java.util.Set;
5+
6+
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
7+
import com.sap.sailing.domain.base.Fleet;
8+
import com.sap.sailing.domain.base.RaceColumn;
9+
import com.sap.sailing.domain.common.racelog.tracking.TrackingTimesRevocationErrorCode;
10+
import com.sap.sse.common.TimePoint;
11+
import com.sap.sse.common.Util.Pair;
12+
13+
public interface TrackingTimesRevocationReport {
14+
/**
15+
* @return {@code null} means no error
16+
*/
17+
TrackingTimesRevocationErrorCode getErrorCode();
18+
19+
void revoked(RaceColumn raceColumn, Fleet fleet, RaceLogEvent event);
20+
21+
void notRevokedBecauseOfMissingStartOrFinishTime(RaceColumn raceColumn, Fleet fleet, TimePoint startTime, TimePoint finishedTime);
22+
23+
void notRevokedBecauseNotForTracking(RaceColumn raceColumn, Fleet fleet);
24+
25+
Map<Pair<RaceColumn, Fleet>, Pair<TimePoint, TimePoint>> getNotRevokedBecauseOfMissingStartOfFinishTime();
26+
27+
Map<Pair<RaceColumn, Fleet>, Set<RaceLogEvent>> getRevokedEvents();
28+
29+
Iterable<Pair<RaceColumn, Fleet>> getNotRevokedBecauseNotForTracking();
30+
31+
}

java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,14 @@
2222
import com.sap.sailing.domain.abstractlog.impl.LastEventOfTypeFinder;
2323
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
2424
import com.sap.sailing.domain.abstractlog.race.RaceLog;
25+
import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent;
2526
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
27+
import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent;
28+
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishedTimeFinder;
2629
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastPublishedCourseDesignFinder;
30+
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinder;
31+
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult;
32+
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.TrackingTimesEventFinder;
2733
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseDesignChangedEventImpl;
2834
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent;
2935
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent;
@@ -67,6 +73,7 @@
6773
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
6874
import com.sap.sailing.domain.racelogtracking.DeviceMappingWithRegattaLogEvent;
6975
import com.sap.sailing.domain.racelogtracking.RaceLogTrackingAdapter;
76+
import com.sap.sailing.domain.racelogtracking.TrackingTimesRevocationReport;
7077
import com.sap.sailing.domain.regattalike.LeaderboardThatHasRegattaLike;
7178
import com.sap.sailing.domain.tracking.RaceHandle;
7279
import com.sap.sailing.domain.tracking.RaceTrackingHandler;
@@ -463,4 +470,50 @@ private void copyPairingsFromRaceColumn(RegattaLeaderboard sourceLeaderboard, Re
463470
copyCompetitors(sourceRaceColumn, sourceFleet, Collections.singleton(new Pair<>(targetRaceColumn, targetFleet)));
464471
}
465472
}
473+
474+
@Override
475+
public TrackingTimesRevocationReport revokeExplicitTrackingTimes(RegattaLeaderboard leaderboard, RacingEventService service) {
476+
final TrackingTimesRevocationReportImpl result = new TrackingTimesRevocationReportImpl(/* error code */ null /* meaning no error */);
477+
for (final RaceColumn raceColumn : leaderboard.getRaceColumns()) {
478+
for (final Fleet fleet : raceColumn.getFleets()) {
479+
final RaceLog raceLog = raceColumn.getRaceLog(fleet);
480+
if (raceLog != null) {
481+
// handle only races denoted for smartphone tracking:
482+
if (new RaceLogTrackingStateAnalyzer(raceLog).analyze().isForTracking()) {
483+
final StartTimeFinder startTimeFinder = new StartTimeFinder(service, raceLog);
484+
final StartTimeFinderResult startTimeFinderResult = startTimeFinder.analyze();
485+
final FinishedTimeFinder finishedTimeFinder = new FinishedTimeFinder(raceLog);
486+
final TimePoint finishedTime = finishedTimeFinder.analyze();
487+
final TrackingTimesEventFinder trackingTimesEventFinder = new TrackingTimesEventFinder(raceLog);
488+
if (startTimeFinderResult != null && startTimeFinderResult.getStartTime() != null && finishedTime != null) {
489+
Pair<RaceLogStartOfTrackingEvent, RaceLogEndOfTrackingEvent> trackingTimes;
490+
while ((trackingTimes = trackingTimesEventFinder.analyze()) != null) {
491+
if (trackingTimes.getA() != null) {
492+
try {
493+
raceLog.revokeEvent(service.getServerAuthor(), trackingTimes.getA(), "revoke explicit start of tracking time");
494+
result.revoked(raceColumn, fleet, trackingTimes.getA());
495+
} catch (NotRevokableException e) {
496+
logger.log(Level.WARNING, "could not revoke explicit start of tracking time by adding RevokeEvent", e);
497+
}
498+
}
499+
if (trackingTimes.getB() != null) {
500+
try {
501+
raceLog.revokeEvent(service.getServerAuthor(), trackingTimes.getB(), "revoke explicit end of tracking time");
502+
result.revoked(raceColumn, fleet, trackingTimes.getB());
503+
} catch (NotRevokableException e) {
504+
logger.log(Level.WARNING, "could not revoke explicit end of tracking time by adding RevokeEvent", e);
505+
}
506+
}
507+
}
508+
} else {
509+
result.notRevokedBecauseOfMissingStartOrFinishTime(raceColumn, fleet, startTimeFinderResult != null ? startTimeFinderResult.getStartTime() : null, finishedTime);
510+
}
511+
} else {
512+
result.notRevokedBecauseNotForTracking(raceColumn, fleet);
513+
}
514+
}
515+
}
516+
}
517+
return result;
518+
}
466519
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package com.sap.sailing.domain.racelogtracking.impl;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collections;
5+
import java.util.HashSet;
6+
import java.util.LinkedHashMap;
7+
import java.util.List;
8+
import java.util.Map;
9+
import java.util.Set;
10+
11+
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
12+
import com.sap.sailing.domain.base.Fleet;
13+
import com.sap.sailing.domain.base.RaceColumn;
14+
import com.sap.sailing.domain.common.racelog.tracking.TrackingTimesRevocationErrorCode;
15+
import com.sap.sailing.domain.racelogtracking.TrackingTimesRevocationReport;
16+
import com.sap.sse.common.TimePoint;
17+
import com.sap.sse.common.Util.Pair;
18+
19+
public class TrackingTimesRevocationReportImpl implements TrackingTimesRevocationReport {
20+
private final Map<Pair<RaceColumn, Fleet>, Set<RaceLogEvent>> revokedEvents;
21+
private final Map<Pair<RaceColumn, Fleet>, Pair<TimePoint, TimePoint>> notRevokedBecauseOfMissingStartOrFinishTime;
22+
private final List<Pair<RaceColumn, Fleet>> notRevokedBecauseNotForTracking;
23+
private final TrackingTimesRevocationErrorCode errorCode;
24+
25+
public TrackingTimesRevocationReportImpl(TrackingTimesRevocationErrorCode errorCode) {
26+
super();
27+
this.errorCode = errorCode;
28+
this.revokedEvents = new LinkedHashMap<>();
29+
this.notRevokedBecauseOfMissingStartOrFinishTime = new LinkedHashMap<>();
30+
this.notRevokedBecauseNotForTracking = new ArrayList<>();
31+
}
32+
33+
@Override
34+
public TrackingTimesRevocationErrorCode getErrorCode() {
35+
return errorCode;
36+
}
37+
38+
@Override
39+
public void revoked(RaceColumn raceColumn, Fleet fleet, RaceLogEvent event) {
40+
final Set<RaceLogEvent> set = revokedEvents.computeIfAbsent(new Pair<>(raceColumn, fleet), k->new HashSet<>());
41+
set.add(event);
42+
}
43+
44+
@Override
45+
public void notRevokedBecauseOfMissingStartOrFinishTime(RaceColumn raceColumn, Fleet fleet, TimePoint startTime, TimePoint finishedTime) {
46+
notRevokedBecauseOfMissingStartOrFinishTime.put(new Pair<>(raceColumn, fleet), new Pair<>(startTime, finishedTime));
47+
}
48+
49+
@Override
50+
public void notRevokedBecauseNotForTracking(RaceColumn raceColumn, Fleet fleet) {
51+
notRevokedBecauseNotForTracking.add(new Pair<>(raceColumn, fleet));
52+
}
53+
54+
@Override
55+
public Map<Pair<RaceColumn, Fleet>, Pair<TimePoint, TimePoint>> getNotRevokedBecauseOfMissingStartOfFinishTime() {
56+
return Collections.unmodifiableMap(notRevokedBecauseOfMissingStartOrFinishTime);
57+
}
58+
59+
@Override
60+
public Map<Pair<RaceColumn, Fleet>, Set<RaceLogEvent>> getRevokedEvents() {
61+
return Collections.unmodifiableMap(revokedEvents);
62+
}
63+
64+
@Override
65+
public Iterable<Pair<RaceColumn, Fleet>> getNotRevokedBecauseNotForTracking() {
66+
return Collections.unmodifiableList(notRevokedBecauseNotForTracking);
67+
}
68+
}

java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/tracking/TestTracTracRaceAndCompetitorStatusReconciler.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ public void testIRMUpdateFromTracTracMapsToRaceLogCompetitorResult() {
337337
// now simulate a yet newer TracTrac event that is expected to reset the "IRM" / MaxPointsReason:
338338
final TimePoint yetNewerResultTimePoint = startOfPass.plus(Duration.ONE_SECOND.times(3));
339339
when(tractracRaceCompetitor.getStatusLastChangedTime()).thenReturn(yetNewerResultTimePoint.asMillis());
340-
when(tractracRaceCompetitor.getStatus()).thenReturn(RaceCompetitorStatusType.NO_DATA);
340+
when(tractracRaceCompetitor.getStatus()).thenReturn(RaceCompetitorStatusType.FIN);
341341
reconciler.reconcileCompetitorStatus(tractracRaceCompetitor, trackedRace);
342342
{
343343
final Pair<CompetitorResult, TimePoint> raceLogBasedResult = reconciler.getRaceLogResultAndCreationTimePointForCompetitor(raceLog, competitor);
@@ -353,7 +353,7 @@ public void testOfficialRankUpdateToRaceLogCompetitorResult() {
353353
final TimePoint resultTimePoint = startOfPass.plus(Duration.ONE_SECOND);
354354
when(tractracRaceCompetitor.getStatusLastChangedTime()).thenReturn(resultTimePoint.asMillis());
355355
when(tractracRaceCompetitor.getOfficialRank()).thenReturn(42);
356-
when(tractracRaceCompetitor.getStatus()).thenReturn(RaceCompetitorStatusType.NO_DATA);
356+
when(tractracRaceCompetitor.getStatus()).thenReturn(RaceCompetitorStatusType.FIN);
357357
reconciler.reconcileCompetitorStatus(tractracRaceCompetitor, trackedRace);
358358
{
359359
final Pair<CompetitorResult, TimePoint> raceLogBasedResult = reconciler.getRaceLogResultAndCreationTimePointForCompetitor(raceLog, competitor);
@@ -403,7 +403,7 @@ public void testOfficialRankUpdateToRaceLogCompetitorResult() {
403403
@Test
404404
public void testOfficialNullFinishTimeAndZeroRank() {
405405
final TimePoint resultTimePoint = startOfPass.plus(Duration.ONE_SECOND.times(1));
406-
when(tractracRaceCompetitor.getStatus()).thenReturn(RaceCompetitorStatusType.NO_DATA);
406+
when(tractracRaceCompetitor.getStatus()).thenReturn(RaceCompetitorStatusType.FIN);
407407
when(tractracRaceCompetitor.getStatusLastChangedTime()).thenReturn(resultTimePoint.asMillis());
408408
when(tractracRaceCompetitor.getOfficialRank()).thenReturn(0);
409409
when(trackedRace.getFinishingTime()).thenReturn(null);
@@ -418,7 +418,7 @@ public void testOfficialNullFinishTimeAndZeroRank() {
418418
@Test
419419
public void testOfficialFinishTimeAndValidRankUpdateScoreCorrectionMetadata() {
420420
final TimePoint resultTimePoint = startOfPass.plus(Duration.ONE_SECOND.times(1));
421-
when(tractracRaceCompetitor.getStatus()).thenReturn(RaceCompetitorStatusType.FINISH_CONFIRMED);
421+
when(tractracRaceCompetitor.getStatus()).thenReturn(RaceCompetitorStatusType.FIN);
422422
when(tractracRaceCompetitor.getStatusLastChangedTime()).thenReturn(resultTimePoint.asMillis());
423423
when(tractracRaceCompetitor.getOfficialRank()).thenReturn(4);
424424
when(trackedRace.getFinishingTime()).thenReturn(null);

java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RaceAndCompetitorStatusWithRaceLogReconciler.java

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -316,13 +316,10 @@ private MaxPointsReason getMaxPointsReason(RaceCompetitorStatusType raceCompetit
316316
} else {
317317
switch (raceCompetitorStatusType) {
318318
// TODO we expect NSC and perhaps also TLE to show up; support the mapping to MaxPointsReason.NSC / TLE, respectively when they appear
319-
case ABANDONED:
320-
result = MaxPointsReason.NONE; // TODO bug 5154: find out what ABANDONED means and if/how we can translate it to a MaxPointsReason
321-
break;
322319
case BFD:
323320
result = MaxPointsReason.BFD;
324321
break;
325-
case DISQUALIFIED:
322+
case DSQ:
326323
result = MaxPointsReason.DSQ;
327324
break;
328325
case DNC:
@@ -331,31 +328,19 @@ private MaxPointsReason getMaxPointsReason(RaceCompetitorStatusType raceCompetit
331328
case DNF:
332329
result = MaxPointsReason.DNF;
333330
break;
334-
case DONT_RACE:
335-
result = MaxPointsReason.DNS; // TODO bug 5154: find out what DONT_RACE means and if/how we can translate it to a MaxPointsReason; is it DNS?
331+
case DNS:
332+
result = MaxPointsReason.DNS;
336333
break;
337334
case FIN:
338-
result = MaxPointsReason.NONE; // TODO bug 5154: find out what FIN means and if/how we can translate it to a MaxPointsReason; does it mean the competitor finished properly?
339-
break;
340-
case FINISH_CONFIRMED:
341-
result = MaxPointsReason.NONE; // TODO bug 5154: find out what FINISH_CONFIRMED means and if/how we can translate it to a MaxPointsReason; does it mean the competitor finished properly?
342-
break;
343-
case MIS:
344-
result = MaxPointsReason.NONE; // TODO bug 5154: find out what MIS means and if/how we can translate it to a MaxPointsReason; does it mean the competitor is "missing?"
345-
break;
346-
case NO_COLLECT:
347-
result = MaxPointsReason.NONE; // TODO bug 5154: find out what NO_COLLECT means and if/how we can translate it to a MaxPointsReason
348-
break;
349-
case NO_DATA:
350-
result = MaxPointsReason.NONE;
335+
result = MaxPointsReason.NONE; // TODO bug 5154: It is just a boat that has finished. MaxPointsReason.NONE is fine
351336
break;
352337
case OCS:
353338
result = MaxPointsReason.OCS;
354339
break;
355-
case RACING:
340+
case RAC:
356341
result = MaxPointsReason.NONE;
357342
break;
358-
case RETIRED:
343+
case RET:
359344
result = MaxPointsReason.RET;
360345
break;
361346
case UFD:
@@ -382,6 +367,15 @@ private MaxPointsReason getMaxPointsReason(RaceCompetitorStatusType raceCompetit
382367
case RCT:
383368
result = MaxPointsReason.RCT;
384369
break;
370+
case DPI:
371+
result = MaxPointsReason.DPI;
372+
break;
373+
case RDG:
374+
result = MaxPointsReason.RDG;
375+
break;
376+
case ZFP:
377+
result = MaxPointsReason.ZFP;
378+
break;
385379
default:
386380
result = MaxPointsReason.NONE;
387381
break;

java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleResources.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ public interface AdminConsoleResources extends ClientBundle {
118118

119119
@Source("com/sap/sailing/gwt/ui/client/images/compose_mail_small.png")
120120
ImageResource inviteBuoyTenders();
121+
122+
@Source("com/sap/sailing/gwt/ui/client/images/eraser-icon.png")
123+
ImageResource eraser();
121124

122125
@Source("com/sap/sailing/gwt/ui/client/images/ajax-loader.gif")
123126
ImageResource loaderGif();

java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingEventManagementImagesBarCell.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import com.google.gwt.core.client.GWT;
66
import com.google.gwt.text.shared.SafeHtmlRenderer;
7+
import com.sap.sailing.domain.common.LeaderboardType;
78
import com.sap.sailing.gwt.ui.client.StringMessages;
89
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
910
import com.sap.sse.gwt.client.IconResources;
@@ -17,6 +18,7 @@ public class RaceLogTrackingEventManagementImagesBarCell extends ImagesBarCell {
1718
public final static String ACTION_MAP_DEVICES = "ACTION_MAP_DEVICES";
1819
public final static String ACTION_INVITE_BUOY_TENDERS = "ACTION_INVITE_BUOY_TENDERS";
1920
public static final String ACTION_SHOW_REGATTA_LOG = "ACTION_SHOW_REGATTA_LOG";
21+
public static final String ACTION_REVOKE_EXPLICIT_TRACKING_TIMES = "ACTION_REVOKE_EXPLICIT_TRACKING_TIMES";
2022
private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class);
2123
private final StringMessages stringMessages;
2224

@@ -48,11 +50,14 @@ protected Iterable<ImageSpec> getImageSpecs() {
4850
makeImagePrototype(resources.inviteBuoyTenders())));
4951
result.add(new ImageSpec(ACTION_SHOW_REGATTA_LOG, stringMessages.regattaLog(),
5052
makeImagePrototype(resources.flagIcon())));
53+
if (selectedLeaderboard.type == LeaderboardType.RegattaLeaderboard) {
54+
result.add(new ImageSpec(ACTION_REVOKE_EXPLICIT_TRACKING_TIMES, stringMessages.revokeExplicitTrackingTimes(),
55+
makeImagePrototype(resources.eraser())));
56+
}
5157
result.add(new ImageSpec(DefaultActions.CHANGE_OWNERSHIP.name(), stringMessages.actionChangeOwnership(),
5258
IconResources.INSTANCE.changeOwnershipIcon()));
5359
result.add(new ImageSpec(DefaultActions.CHANGE_ACL.name(), stringMessages.actionChangeACL(),
5460
IconResources.INSTANCE.changeACLIcon()));
55-
5661
return result;
5762
}
5863
}

0 commit comments

Comments
 (0)