compileable but untested approach to passing through the races already looked at for getAllCompetitors()

Change-Id: I44cc92525acc35b9eb2504517f992343ebc85ede
This commit is contained in:
Axel Uhl committed 2017-08-03 14:49:33 +02:00
1 parent 2a0831282c
commit 70d703d3b6
13 files changed
+152 -26

No files matched your search

@@ -87,6 +87,7 @@ import com.sap.sse.common.Duration;
import com.sap.sse.common.IsManagedByCache;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
public class MockedTrackedRace implements DynamicTrackedRace {
private static final long serialVersionUID = 5827912985564121181L;
@@ -324,6 +325,11 @@ public class MockedTrackedRace implements DynamicTrackedRace {
return null;
}
@Override
public Pair<Iterable<RaceDefinition>, Iterable<Competitor>> getAllCompetitorsWithRaceDefinitionsConsidered() {
return null;
}
@Override
public void addRace(RaceDefinition race) {
}
@@ -17,6 +17,7 @@ import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.util.impl.RaceColumnListeners;
import com.sap.sse.common.Named;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
/**
* One or more races that would be noted together in a single column in a {@link Leaderboard}. If the number of
@@ -251,6 +252,13 @@ public interface RaceColumn extends Named {
*/
Iterable<Competitor> getAllCompetitors();
/**
* Same as {@link #getAllCompetitors()}, but the {@link RaceDefinition}s whose {@link RaceDefinition#getCompetitors() competitors}
* were considered while computing the results are returned as the first element of the pair. The second element are the competitors
* as they are returned by {@link #getAllCompetitors()}.
*/
Pair<Iterable<RaceDefinition>, Iterable<Competitor>> getAllCompetitorsWithRaceDefinitionsConsidered();
/**
* Same as {@link #getAllCompetitors()}, but restricted to the single race identified by the <code>fleet</code> parameter.
*/
@@ -13,8 +13,10 @@ import com.sap.sailing.domain.tracking.RaceExecutionOrderProvider;
import com.sap.sailing.domain.tracking.RaceTracker;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.util.RegattaUtil;
import com.sap.sse.common.NamedWithID;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util.Pair;
/**
* The name shall be unique across all regattas tracked concurrently. In particular, if you want to keep apart regattas
@@ -119,6 +121,13 @@ public interface Regatta extends NamedWithID, IsRegattaLike, HasRaceColumnsAndRe
Iterable<Competitor> getAllCompetitors();
/**
* Same as {@link #getAllCompetitors()}, only that additionally the method returns as a first element of a pair
* which {@link RaceDefinition}s' {@link RaceDefinition#getCompetitors() competitors} were used in assembling the
* result.
*/
Pair<Iterable<RaceDefinition>, Iterable<Competitor>> getAllCompetitorsWithRaceDefinitionsConsidered();
/**
* Will remove the series from this regatta. Will also call {@link RaceColumn#removeRaceIdentifier(Fleet)} to make
* sure that all raceLogs and race associations get removed for all race columns in this series.
@@ -32,6 +32,7 @@ import com.sap.sailing.domain.base.CourseBase;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.abstractlog.NotRevokableException;
@@ -43,6 +44,7 @@ import com.sap.sailing.domain.regattalike.RegattaLikeIdentifier;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implements RaceColumn {
@@ -249,29 +251,52 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
@Override
public Iterable<Competitor> getAllCompetitors() {
Set<Competitor> result = new HashSet<>();
for (Fleet fleet : getFleets()) {
Util.addAll(getAllCompetitors(fleet), result);
}
return result;
return getAllCompetitorsWithRaceDefinitionsConsidered().getB();
}
@Override
public Iterable<Competitor> getAllCompetitors(final Fleet fleet) {
final Iterable<Competitor> result;
public Pair<Iterable<RaceDefinition>, Iterable<Competitor>> getAllCompetitorsWithRaceDefinitionsConsidered() {
Set<Competitor> competitors = new HashSet<>();
Set<RaceDefinition> raceDefinitionsConsidered = new HashSet<>();
for (Fleet fleet : getFleets()) {
final Pair<RaceDefinition, Iterable<Competitor>> allCompetitorsWithRaceDefinitionsConsidered = getAllCompetitorsWithRaceDefinitionsConsidered(fleet);
Util.addAll(allCompetitorsWithRaceDefinitionsConsidered.getB(), competitors);
if (allCompetitorsWithRaceDefinitionsConsidered.getA() != null) {
raceDefinitionsConsidered.add(allCompetitorsWithRaceDefinitionsConsidered.getA());
}
}
return new Pair<>(raceDefinitionsConsidered, competitors);
}
/**
* Same as {@link #getAllCompetitors(Fleet)}, but also returns the {@link RaceDefinition} as the first
* component of a pair if it contributed its {@link RaceDefinition#getCompetitors()}. If the resulting
* iterable of competitors did not consider a {@link RaceDefinition}'s competitor set, {@code null}
* is returned as the first component of the pair.
*/
private Pair<RaceDefinition, Iterable<Competitor>> getAllCompetitorsWithRaceDefinitionsConsidered(final Fleet fleet) {
final Iterable<Competitor> competitors;
final RaceDefinition raceDefinition;
TrackedRace trackedRace = getTrackedRace(fleet);
if (trackedRace != null) {
result = trackedRace.getRace().getCompetitors();
raceDefinition = trackedRace.getRace();
competitors = raceDefinition.getCompetitors();
} else {
raceDefinition = null;
// if no tracked race is found, use competitors from race/regatta log depending on whether
// the mapping event is present or not; this assumes that if a tracked
// race exists, its competitors set takes precedence over what's in the race log. Usually,
// the tracked race will have the same competitors as those in the race log, or more because
// those from the regatta log are added to the tracked race as well.
Set<Competitor> viaRaceLog = new RegisteredCompetitorsAnalyzer(getRaceLog(fleet), getRegattaLog()).analyze();
result = viaRaceLog;
competitors = viaRaceLog;
}
return result;
return new Pair<>(raceDefinition, competitors);
}
@Override
public Iterable<Competitor> getAllCompetitors(final Fleet fleet) {
return getAllCompetitorsWithRaceDefinitionsConsidered(fleet).getB();
}
@Override
@@ -73,6 +73,7 @@ import com.sap.sailing.util.impl.RaceColumnListeners;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.impl.NamedImpl;
@@ -417,11 +418,32 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
}
@Override
public Iterable<Competitor> getAllCompetitors() {
public Pair<Iterable<RaceDefinition>, Iterable<Competitor>> getAllCompetitorsWithRaceDefinitionsConsidered() {
if (competitorsProvider == null) {
competitorsProvider = new CompetitorProviderFromRaceColumnsAndRegattaLike(this);
}
return competitorsProvider.getAllCompetitors();
final Pair<Iterable<RaceDefinition>, Iterable<Competitor>> allCompetitorsWithRaceDefinitionsConsidered = competitorsProvider.getAllCompetitorsWithRaceDefinitionsConsidered();
Set<Competitor> newResult = null;
Set<RaceDefinition> newRaceDefinitions = null;
final Iterable<RaceDefinition> racesConsideredSoFar = allCompetitorsWithRaceDefinitionsConsidered.getA();
for (final RaceDefinition race : getAllRaces()) {
if (!Util.contains(racesConsideredSoFar, race)) {
if (newResult == null) {
newRaceDefinitions = new HashSet<>();
Util.addAll(allCompetitorsWithRaceDefinitionsConsidered.getA(), newRaceDefinitions);
newResult = new HashSet<>();
Util.addAll(allCompetitorsWithRaceDefinitionsConsidered.getB(), newResult);
}
Util.addAll(race.getCompetitors(), newResult);
newRaceDefinitions.add(race);
}
}
return newResult == null ? allCompetitorsWithRaceDefinitionsConsidered : new Pair<>(newRaceDefinitions, newResult);
}
@Override
public Iterable<Competitor> getAllCompetitors() {
return getAllCompetitorsWithRaceDefinitionsConsidered().getB();
}
@Override
@@ -14,6 +14,7 @@ import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.LeaderboardBase;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnListener;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.LeaderboardType;
@@ -97,6 +98,13 @@ public interface Leaderboard extends LeaderboardBase, HasRaceColumns {
*/
Iterable<Competitor> getAllCompetitors();
/**
* Same as {@link #getAllCompetitors()}, only that additionally the method returns as a first element in a pair
* which {@link RaceDefinition}s were used in order to fetch their {@link RaceDefinition#getCompetitors()} to
* assemble the results.
*/
Pair<Iterable<RaceDefinition>, Iterable<Competitor>> getAllCompetitorsWithRaceDefinitionsConsidered();
/**
* Retrieves all competitors expected to race in the fleet and column specified.
* When a {@link TrackedRace} is {@link RaceColumn#getTrackedRace(Fleet) attached} to the race
@@ -20,12 +20,14 @@ import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnListener;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.leaderboard.HasRaceColumnsAndRegattaLike;
import com.sap.sailing.domain.leaderboard.ScoreCorrection;
import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.impl.MillisecondsTimePoint;
/**
@@ -89,11 +91,11 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI
/**
* This default implementation collects all competitors by visiting all {@link TrackedRace}s associated with this
* leaderboard's columns (see {@link #getTrackedRaces()}).
* leaderboard's columns (see {@link #getTrackedRaces()}) and considering the race and regatta logs.
*/
@Override
public Iterable<Competitor> getAllCompetitors() {
return getOrCreateCompetitorsProvider().getAllCompetitors();
public Pair<Iterable<RaceDefinition>, Iterable<Competitor>> getAllCompetitorsWithRaceDefinitionsConsidered() {
return getOrCreateCompetitorsProvider().getAllCompetitorsWithRaceDefinitionsConsidered();
}
@Override
@@ -1105,6 +1105,11 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard {
}
return result;
}
@Override
public Iterable<Competitor> getAllCompetitors() {
return getAllCompetitorsWithRaceDefinitionsConsidered().getB();
}
@Override
public void destroy() {
@@ -62,12 +62,15 @@ public class CompetitorProviderFromRaceColumnsAndRegattaLike {
private final RaceColumnListener raceColumnListener;
private Iterable<Competitor> allCompetitorsCache;
private Set<RaceDefinition> raceDefinitionsConsidered;
private final ConcurrentMap<Pair<RaceColumn, Fleet>, Iterable<Competitor>> allCompetitorsCacheByRace;
public CompetitorProviderFromRaceColumnsAndRegattaLike(HasRaceColumnsAndRegattaLike provider) {
super();
this.provider = provider;
this.raceDefinitionsConsidered = new HashSet<>();
this.allCompetitorsCacheByRace = new ConcurrentHashMap<>();
// A note regarding listener serializability: RaceLogListener and RegattaLogListener objects
// don't need to be serializable as the log listeners are a transient structure. The race column
@@ -164,12 +167,26 @@ public class CompetitorProviderFromRaceColumnsAndRegattaLike {
* While subsequent calls may return different {@link Collection Collections} the contents of a {@link Collection} returned may never change.
*/
public Iterable<Competitor> getAllCompetitors() {
return getAllCompetitorsWithRaceDefinitionsConsidered().getB();
}
/**
* Returns a Collection of all {@link Competitor Competitors} collected over {@link RegattaLog}, {@link RaceLog} as
* well as the {@link RaceDefinition RaceDefinitions} of all {@link TrackedRace TrackedRaces} attached. While
* subsequent calls may return different {@link Collection Collections} the contents of a {@link Collection}
* returned may never change. The {@link RaceDefinition}s touched by this are returned as the first element
* of the resulting pair; the competitors as the second.
*/
public Pair<Iterable<RaceDefinition>, Iterable<Competitor>> getAllCompetitorsWithRaceDefinitionsConsidered() {
if (allCompetitorsCache == null) {
final Set<Competitor> result = new HashSet<>();
final Set<RaceDefinition> raceDefinitions = new HashSet<>();
boolean hasRaceColumns = false;
for (RaceColumn rc : provider.getRaceColumns()) {
hasRaceColumns = true;
Util.addAll(rc.getAllCompetitors(), result);
final Pair<Iterable<RaceDefinition>, Iterable<Competitor>> allCompetitorsInRaceColumnWithRaceDefinitionsConsidered = rc.getAllCompetitorsWithRaceDefinitionsConsidered();
Util.addAll(allCompetitorsInRaceColumnWithRaceDefinitionsConsidered.getB(), result);
Util.addAll(allCompetitorsInRaceColumnWithRaceDefinitionsConsidered.getA(), raceDefinitions);
for (final Fleet fleet : rc.getFleets()) {
rc.getRaceLog(fleet).addListener(raceLogCompetitorsCacheInvalidationListener);
}
@@ -189,9 +206,14 @@ public class CompetitorProviderFromRaceColumnsAndRegattaLike {
provider.addRaceColumnListener(raceColumnListener);
// consider {@link RegattaLog} competitor changes because the RaceColumns may have added the competitors from there
regattaLog.addListener(regattaLogCompetitorsCacheInvalidationListener);
allCompetitorsCache = result;
synchronized (this) {
allCompetitorsCache = result;
raceDefinitionsConsidered = raceDefinitions;
}
}
synchronized (this) {
return new Pair<>(raceDefinitionsConsidered, allCompetitorsCache);
}
return allCompetitorsCache;
}
/**
@@ -20,6 +20,7 @@ import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnListener;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.LeaderboardType;
import com.sap.sailing.domain.common.MaxPointsReason;
@@ -220,6 +221,11 @@ public class DelegatingRegattaLeaderboardWithCompetitorElimination extends Abstr
return getFullLeaderboard().getAllCompetitors();
}
@Override
public Pair<Iterable<RaceDefinition>, Iterable<Competitor>> getAllCompetitorsWithRaceDefinitionsConsidered() {
return getFullLeaderboard().getAllCompetitorsWithRaceDefinitionsConsidered();
}
public Iterable<Competitor> getAllCompetitors(RaceColumn raceColumn, Fleet fleet) {
return getFullLeaderboard().getAllCompetitors(raceColumn, fleet);
}
@@ -22,6 +22,7 @@ import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
import com.sap.sailing.domain.regattalike.IsRegattaLike;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.Util.Pair;
/**
* A leaderboard that is based on the definition of a {@link Regatta} with its {@link Series} and {@link Fleet}. The regatta
@@ -112,10 +113,10 @@ public class RegattaLeaderboardImpl extends AbstractLeaderboardImpl implements R
* {@link RegattaLog}.
*/
@Override
public Iterable<Competitor> getAllCompetitors() {
return regatta.getAllCompetitors();
public Pair<Iterable<RaceDefinition>, Iterable<Competitor>> getAllCompetitorsWithRaceDefinitionsConsidered() {
return regatta.getAllCompetitorsWithRaceDefinitionsConsidered();
}
@Override
public IsRegattaLike getRegattaLike() {
return regatta;
@@ -16,6 +16,7 @@ import java.util.WeakHashMap;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.impl.FleetImpl;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.leaderboard.Leaderboard;
@@ -28,6 +29,7 @@ import com.sap.sailing.domain.leaderboard.impl.AbstractSimpleLeaderboardImpl;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
/**
* A leaderboard whose columns are defined by leaderboards. This can be useful for a regatta series where many regattas
@@ -140,12 +142,15 @@ public abstract class AbstractMetaLeaderboard extends AbstractSimpleLeaderboardI
}
@Override
public Iterable<Competitor> getAllCompetitors() {
Set<Competitor> result = new HashSet<Competitor>();
public Pair<Iterable<RaceDefinition>, Iterable<Competitor>> getAllCompetitorsWithRaceDefinitionsConsidered() {
Set<Competitor> competitors = new HashSet<Competitor>();
Set<RaceDefinition> raceDefinitionsConsidered = new HashSet<>();
for (Leaderboard leaderboard : getLeaderboards()) {
Util.addAll(leaderboard.getCompetitors(), result);
final Pair<Iterable<RaceDefinition>, Iterable<Competitor>> allCompetitorsFromLeaderboardWithRaceDefinitionsConsidered = leaderboard.getAllCompetitorsWithRaceDefinitionsConsidered();
Util.addAll(allCompetitorsFromLeaderboardWithRaceDefinitionsConsidered.getA(), raceDefinitionsConsidered);
Util.addAll(allCompetitorsFromLeaderboardWithRaceDefinitionsConsidered.getB(), competitors);
}
return result;
return new Pair<>(raceDefinitionsConsidered, competitors);
}
@Override
@@ -11,6 +11,7 @@ import com.sap.sailing.domain.base.LeaderboardChangeListener;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnListener;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.impl.SimpleAbstractRaceColumn;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException;
@@ -21,6 +22,7 @@ import com.sap.sailing.domain.racelog.RaceLogStore;
import com.sap.sailing.domain.regattalike.RegattaLikeIdentifier;
import com.sap.sailing.domain.tracking.RaceExecutionOrderProvider;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.Util.Pair;
/**
* All {@link RaceColumnListener} events received from the underlying leaderboard's race columns
@@ -221,7 +223,12 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R
@Override
public Iterable<Competitor> getAllCompetitors() {
return leaderboard.getAllCompetitors();
return getAllCompetitorsWithRaceDefinitionsConsidered().getB();
}
@Override
public Pair<Iterable<RaceDefinition>, Iterable<Competitor>> getAllCompetitorsWithRaceDefinitionsConsidered() {
return leaderboard.getAllCompetitorsWithRaceDefinitionsConsidered();
}
@Override