mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-13 22:15:26 +00:00
Merge branch 'bug3535' into bug2840
This commit is contained in:
commit
11a7e371db
16 files changed
+131
-31
No files matched your search
+37
@@ -0,0 +1,37 @@
|
||||
package com.sap.sailing.domain.regattalog.tracking.analyzing.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorDeregistrator;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.impl.CompetitorImpl;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class CompetitorDeregistrationTest extends AbstractRegattaLogTrackingTest {
|
||||
private final Competitor competitor = new CompetitorImpl("comp", "Comp", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
|
||||
private final Competitor competitor2 = new CompetitorImpl("comp2", "Comp2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
|
||||
|
||||
@Test
|
||||
public void testCompetitorDeregistration() {
|
||||
log.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), author, competitor));
|
||||
log.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), author, competitor2));
|
||||
final CompetitorDeregistrator<RegattaLog, RegattaLogEvent, RegattaLogEventVisitor> deregistrator = new CompetitorDeregistrator<>(log,
|
||||
Collections.singleton(competitor2), author);
|
||||
final Set<RegattaLogEvent> events = deregistrator.analyze();
|
||||
deregistrator.deregister(events);
|
||||
final Set<Competitor> competitors = new CompetitorsInLogAnalyzer<>(log).analyze();
|
||||
assertEquals(1, competitors.size());
|
||||
assertSame(competitor, competitors.iterator().next());
|
||||
}
|
||||
}
|
||||
+27
-14
@@ -1,6 +1,7 @@
|
||||
package com.sap.sailing.domain.abstractlog.shared.analyzing;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -14,14 +15,21 @@ import com.sap.sailing.domain.common.abstractlog.NotRevokableException;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
/**
|
||||
* Generates events that close the events that are responsible for the {@link #mapping} that is passed to the
|
||||
* constructor.
|
||||
* Finds the competitor registration events for a given set of {@link Competitor competitors} that must be
|
||||
* {@link AbstractLog#revokeEvent(AbstractLogEventAuthor, AbstractLogEvent) revoked} in order to deregister the
|
||||
* competitors. Note that the de-registration cannot be performed during analysis because
|
||||
* {@link BaseLogAnalyzer#analyze()} obtains a read lock on the log whereas
|
||||
* {@link AbstractLog#revokeEvent(AbstractLogEventAuthor, AbstractLogEvent)} requires a write lock, and upgrading from a
|
||||
* read to a write lock is not possible.<p>
|
||||
*
|
||||
* Clients must call {@link #deregister} with the result of {@link #analyze()} in order to actually perform the
|
||||
* deregistration.
|
||||
*
|
||||
* @author Jan Bross
|
||||
*
|
||||
*/
|
||||
public class CompetitorDeregistrator<LogT extends AbstractLog<EventT, VisitorT>, EventT extends AbstractLogEvent<VisitorT>, VisitorT>
|
||||
extends BaseLogAnalyzer<LogT, EventT, VisitorT, Void> {
|
||||
extends BaseLogAnalyzer<LogT, EventT, VisitorT, Set<EventT>> {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CompetitorDeregistrator.class.getName());
|
||||
protected final Iterable<Competitor> competitorsToDeregister;
|
||||
@@ -34,24 +42,29 @@ extends BaseLogAnalyzer<LogT, EventT, VisitorT, Void> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void performAnalysis() {
|
||||
HashSet<Competitor> competitorSet = new HashSet<Competitor>();
|
||||
protected Set<EventT> performAnalysis() {
|
||||
final Set<EventT> result = new HashSet<>();
|
||||
final HashSet<Competitor> competitorSet = new HashSet<Competitor>();
|
||||
Util.addAll(competitorsToDeregister, competitorSet);
|
||||
|
||||
for (EventT event : log.getUnrevokedEventsDescending()) {
|
||||
if (event instanceof RegisterCompetitorEvent) {
|
||||
RegisterCompetitorEvent<?> registerEvent = (RegisterCompetitorEvent<?>) event;
|
||||
if (competitorSet.contains(registerEvent.getCompetitor())) {
|
||||
try {
|
||||
log.revokeEvent(eventAuthor, event,
|
||||
"unregistering competitor because no longer selected for registration");
|
||||
} catch (NotRevokableException e) {
|
||||
logger.log(Level.WARNING, "could not unregister competitor by adding RevokeEvent", e);
|
||||
}
|
||||
result.add(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void deregister(final Set<EventT> competitorRegistrationEvents) {
|
||||
for (final EventT event : competitorRegistrationEvents) {
|
||||
try {
|
||||
log.revokeEvent(eventAuthor, event,
|
||||
"unregistering competitor because no longer selected for registration");
|
||||
} catch (NotRevokableException e) {
|
||||
logger.log(Level.WARNING, "could not unregister competitor by adding RevokeEvent", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
-4
@@ -313,19 +313,36 @@ public class TrackImpl<FixType extends Timed> implements Track<FixType> {
|
||||
}
|
||||
|
||||
protected boolean add(FixType fix) {
|
||||
return add(fix, /* replace */ false);
|
||||
}
|
||||
|
||||
protected boolean add(FixType fix, boolean replace) {
|
||||
lockForWrite();
|
||||
try {
|
||||
return addWithoutLocking(fix);
|
||||
return addWithoutLocking(fix, replace);
|
||||
} finally {
|
||||
unlockAfterWrite();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The caller must ensure to hold the write lock for this track when calling this methos
|
||||
* The caller must ensure to hold the write lock for this track when calling this method.
|
||||
*
|
||||
* @param replace
|
||||
* whether or not to replace an existing fix in the track that is equal to {@link #fix} as defined by the
|
||||
* comparator used for the {@link #fixes} set. By default this is a comparator only comparing the
|
||||
* fixes' time stamps. Subclasses may use different comparator implementations.
|
||||
*/
|
||||
protected boolean addWithoutLocking(FixType fix) {
|
||||
return getInternalRawFixes().add(fix);
|
||||
protected boolean addWithoutLocking(FixType fix, boolean replace) {
|
||||
final boolean result;
|
||||
final boolean added = getInternalRawFixes().add(fix);
|
||||
if (!added && replace) {
|
||||
getInternalRawFixes().remove(fix);
|
||||
result = getInternalFixes().add(fix);
|
||||
} else {
|
||||
result = added;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -792,6 +792,6 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
public void deregisterCompetitors(Iterable<Competitor> competitors) {
|
||||
RegattaLog regattaLog = getRegattaLike().getRegattaLog();
|
||||
CompetitorDeregistrator<RegattaLog, RegattaLogEvent, RegattaLogEventVisitor> deregisterer = new CompetitorDeregistrator<>(regattaLog, competitors, regattaLogEventAuthorForRegatta);
|
||||
deregisterer.analyze();
|
||||
deregisterer.deregister(deregisterer.analyze());
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -224,6 +224,6 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI
|
||||
public void deregisterCompetitors(Iterable<Competitor> competitors) {
|
||||
RegattaLog regattaLog = getRegattaLike().getRegattaLog();
|
||||
CompetitorDeregistrator<RegattaLog, RegattaLogEvent, RegattaLogEventVisitor> deregisterer = new CompetitorDeregistrator<>(regattaLog, competitors, regattaLogEventAuthorForAbstractLeaderboard);
|
||||
deregisterer.analyze();
|
||||
deregisterer.deregister(deregisterer.analyze());
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,25 @@ import com.sap.sse.common.Timed;
|
||||
|
||||
public interface DynamicTrack<FixType extends Timed> extends Track<FixType> {
|
||||
/**
|
||||
* Tries to add {@code fix} to this track. If an {@link #equals(Object) equal} fix already exists
|
||||
* in this track, the track remains unchanged and {@code false} will be returned.
|
||||
*
|
||||
* @return <code>true</code> if the element was added, <code>false</code> otherwise.
|
||||
*/
|
||||
boolean add(FixType fix);
|
||||
|
||||
/**
|
||||
* Tries to add {@code fix} to this track. If an {@link #equals(Object) equal} fix already exists
|
||||
* in this track and {@code replace} is {@code false}, the track remains unchanged and {@code false} will be returned.
|
||||
* If {@code replace} is {@code true}, an equal (by definition of the comparator used for the fixes set) fix will
|
||||
* replace the fix contained in this track.
|
||||
*
|
||||
* @param replace
|
||||
* whether or not to replace an existing fix in the track that is equal to {@link #fix} as defined by the
|
||||
* comparator used for the {@link #fixes} set. By default this is a comparator only comparing the fixes'
|
||||
* time stamps. Subclasses may use different comparator implementations.
|
||||
*
|
||||
* @return <code>true</code> if the element was added, <code>false</code> otherwise.
|
||||
*/
|
||||
boolean add(FixType fix, boolean replace);
|
||||
}
|
||||
+6
-1
@@ -47,7 +47,7 @@ public class DynamicGPSFixMovingTrackImpl<ItemType> extends GPSFixTrackImpl<Item
|
||||
*/
|
||||
@Override
|
||||
public void addGPSFix(GPSFixMoving gpsFix) {
|
||||
add(gpsFix);
|
||||
add(gpsFix, /* replace */ true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,6 +55,11 @@ public class DynamicGPSFixMovingTrackImpl<ItemType> extends GPSFixTrackImpl<Item
|
||||
return super.add(new CompactGPSFixMovingImpl(fix));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(GPSFixMoving fix, boolean replace) {
|
||||
return super.add(new CompactGPSFixMovingImpl(fix), replace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpolates linearly between the two fixes based on their time difference and distance. This
|
||||
* intentionally ignores the {@link GPSFixMoving#getSpeed() speed values} provided by the fixes
|
||||
|
||||
+7
-2
@@ -12,12 +12,17 @@ public class DynamicGPSFixTrackImpl<ItemType> extends GPSFixTrackImpl<ItemType,
|
||||
}
|
||||
|
||||
public void addGPSFix(GPSFix gpsFix) {
|
||||
add(gpsFix);
|
||||
add(gpsFix, /* replace */ true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(GPSFix fix) {
|
||||
return super.add(new CompactGPSFixImpl(fix));
|
||||
return super.add(fix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(GPSFix fix, boolean replace) {
|
||||
return super.add(new CompactGPSFixImpl(fix), replace);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
@@ -17,4 +17,9 @@ public class DynamicTrackImpl<FixType extends Timed> extends TrackImpl<FixType>
|
||||
public boolean add(FixType fix) {
|
||||
return super.add(fix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(FixType fix, boolean replace) {
|
||||
return super.add(fix, replace);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1106,7 +1106,7 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
|
||||
lockForWrite();
|
||||
try {
|
||||
firstFixInTrack = getRawFixes().isEmpty();
|
||||
result = addWithoutLocking(fix);
|
||||
result = addWithoutLocking(fix, /* replace */ false);
|
||||
if (!validityCachingSuspended) {
|
||||
invalidateValidityAndEstimatedSpeedAndDistanceCaches(fix);
|
||||
}
|
||||
|
||||
+7
-2
@@ -108,9 +108,14 @@ public class WindTrackImpl extends TrackImpl<Wind> implements WindTrack {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(Wind wind) {
|
||||
public boolean add(Wind fix) {
|
||||
return super.add(fix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(Wind wind, boolean replace) {
|
||||
final CompactWindImpl compactWind = new CompactWindImpl(wind);
|
||||
final boolean result = super.add(compactWind);
|
||||
final boolean result = super.add(compactWind, replace);
|
||||
notifyListenersAboutReceive(compactWind);
|
||||
return result;
|
||||
}
|
||||
|
||||
-1
@@ -139,7 +139,6 @@ public interface TextMessages extends Messages {
|
||||
String latestRaceResultsHeadline();
|
||||
String latestRaceResultsIsNew();
|
||||
String latestRaceResultsIsUpdated();
|
||||
String latestRaceResultsRaceCountLabel();
|
||||
String latestRaceResultsRaceCountUnit();
|
||||
String latestRaceResultsRefresh();
|
||||
String leaderboardQuickAccessLabel();
|
||||
|
||||
-1
@@ -128,7 +128,6 @@ headerSponsoring=Sponsoring
|
||||
latestRaceResultsHeadline=Latest Official Race Results
|
||||
latestRaceResultsIsNew=New
|
||||
latestRaceResultsIsUpdated=Updated
|
||||
latestRaceResultsRaceCountLabel=Result after
|
||||
latestRaceResultsRaceCountUnit=races
|
||||
latestRaceResultsRefresh=refresh
|
||||
leaderboardQuickAccessLabel=Leaderboard Quick Access
|
||||
|
||||
-1
@@ -128,7 +128,6 @@ headerSponsoring=Sponsoren
|
||||
latestRaceResultsHeadline=Letzten ofiziellen Ergebnisse
|
||||
latestRaceResultsIsNew=Neu
|
||||
latestRaceResultsIsUpdated=Aktualisiert
|
||||
latestRaceResultsRaceCountLabel=Ergebnis nach
|
||||
latestRaceResultsRaceCountUnit=Rennen
|
||||
latestRaceResultsRefresh=aktualisieren
|
||||
leaderboardQuickAccessLabel=Ergebnisliste Schnellzugang
|
||||
|
||||
-1
@@ -128,7 +128,6 @@ headerSponsoring=Sponsoring
|
||||
latestRaceResultsHeadline=Latest Official Race Results
|
||||
latestRaceResultsIsNew=New
|
||||
latestRaceResultsIsUpdated=Updated
|
||||
latestRaceResultsRaceCountLabel=Result after
|
||||
latestRaceResultsRaceCountUnit=races
|
||||
latestRaceResultsRefresh=refresh
|
||||
leaderboardQuickAccessLabel=Leaderboard Quick Access
|
||||
|
||||
-1
@@ -159,7 +159,6 @@ headerSponsoring=Sponsoring
|
||||
latestRaceResultsHeadline=Latest Official Race Results
|
||||
latestRaceResultsIsNew=New
|
||||
latestRaceResultsIsUpdated=Updated
|
||||
latestRaceResultsRaceCountLabel=Result after
|
||||
latestRaceResultsRaceCountUnit=races
|
||||
latestRaceResultsRefresh=refresh
|
||||
leaderboardQuickAccessLabel=Leaderboard Quick Access
|
||||
|
||||
Reference in new issue
Block a user