Register competitors on RaceColumn/HasRegattaLike

This commit is contained in:
Jan Broß committed 2015-11-28 15:30:39 +01:00
1 parent 233b2b909f
commit ffe0a94c60
7 files changed
+186 -87

No files matched your search

@@ -492,6 +492,10 @@ public class MockedTrackedRace implements DynamicTrackedRace {
public Iterable<Competitor> getCompetitorsRegisteredInRegattaLog() {
return null;
}
@Override
public void registerCompetitor(Competitor competitor) {
}
};
}
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.base;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.MetaLeaderboard;
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
@@ -277,4 +278,13 @@ public interface RaceColumn extends Named {
* @return boolean if competitor registration on the RaceLog is enabled, false in case this column belongs to a {@link MetaLeaderboard}
*/
boolean isCompetitorRegistrationInRacelogEnabled(Fleet fleet);
/**
* Registers a competitor on the the race column's race log associated to the passed fleet.
* @param competitor
* @param fleet
* @throws CompetitorRegistrationOnRaceLogDisabledException
* thrown if competitor registration is disabled on racelog as well as if RaceColumn belongs to a {@link MetaLeaderboard}
*/
void registerCompetitor(Competitor competitor, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException;
}
@@ -8,11 +8,15 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Logger;
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.tracking.analyzing.impl.DefinedMarkFinder;
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RegisteredCompetitorsAnalyzer;
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet;
@@ -20,17 +24,22 @@ import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException;
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
import com.sap.sailing.domain.racelog.RaceLogStore;
import com.sap.sailing.domain.racelog.impl.RaceLogIdentifierImpl;
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.impl.MillisecondsTimePoint;
public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implements RaceColumn {
private static final long serialVersionUID = -7801617988982540470L;
private static final Logger logger = Logger.getLogger(AbstractRaceColumn.class.getName());
private final AbstractLogEventAuthor raceLogEventAuthorForRaceColumn = new LogEventAuthorImpl(
AbstractRaceColumn.class.getName(), 0);
private TrackedRaces trackedRaces;
private Map<Fleet, RaceIdentifier> raceIdentifiers;
@@ -265,6 +274,19 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
}
return result;
}
@Override
public void registerCompetitor(Competitor competitor, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException {
if (isCompetitorRegistrationInRacelogEnabled(fleet)){
throw new CompetitorRegistrationOnRaceLogDisabledException();
}
TimePoint now = MillisecondsTimePoint.now();
RaceLog raceLog = getRaceLog(fleet);
int passId = raceLog.getCurrentPassId();
raceLog.add(new RaceLogRegisterCompetitorEventImpl(now, now, raceLogEventAuthorForRaceColumn,
UUID.randomUUID(), passId, competitor));
}
@Override
public Iterable<Mark> getAllMarks() {
@@ -12,15 +12,19 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
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.RaceLogEvent;
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.CompetitorsInLogAnalyzer;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
@@ -43,6 +47,7 @@ import com.sap.sailing.domain.common.RegattaName;
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
import com.sap.sailing.domain.leaderboard.ResultDiscardingRule;
import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.leaderboard.impl.AbstractLeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike;
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
import com.sap.sailing.domain.racelog.RaceLogStore;
@@ -64,6 +69,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.impl.MillisecondsTimePoint;
import com.sap.sse.common.impl.NamedImpl;
public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListener {
@@ -96,48 +102,54 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
private transient RaceLogStore raceLogStore;
private final IsRegattaLike regattaLikeHelper;
private final RankingMetricConstructor rankingMetricConstructor;
private CourseArea defaultCourseArea;
private RegattaConfiguration configuration;
private RaceExecutionOrderCache raceExecutionOrderCache;
/**
* Regattas may be constructed as implicit default regattas in which case they won't need to be stored
* durably and don't contain valuable information worth being preserved; or they are constructed explicitly
* with series and race columns in which case this data needs to be protected. This flag indicates whether
* the data of this regatta needs to be maintained persistently.
* Regattas may be constructed as implicit default regattas in which case they won't need to be stored durably and
* don't contain valuable information worth being preserved; or they are constructed explicitly with series and race
* columns in which case this data needs to be protected. This flag indicates whether the data of this regatta needs
* to be maintained persistently.
*
* @see #isPersistent
*/
private final boolean persistent;
/**
* Defaults to <code>true</code>. See {@link Regatta#useStartTimeInference()}.
*/
private boolean useStartTimeInference;
private transient CompetitorProviderFromRaceColumnsAndRegattaLike competitorsProvider;
private AbstractLogEventAuthor regattaLogEventAuthorForRegatta = new LogEventAuthorImpl(
AbstractLeaderboardImpl.class.getName(), 0);;
/**
* Constructs a regatta with an empty {@link RaceLogStore}.
*/
public RegattaImpl(String name, BoatClass boatClass, TimePoint startDate, TimePoint endDate, Iterable<? extends Series> series, boolean persistent,
ScoringScheme scoringScheme, Serializable id, CourseArea courseArea) {
this(name, boatClass, startDate, endDate, series, persistent, scoringScheme, id, courseArea, OneDesignRankingMetric::new);
public RegattaImpl(String name, BoatClass boatClass, TimePoint startDate, TimePoint endDate,
Iterable<? extends Series> series, boolean persistent, ScoringScheme scoringScheme, Serializable id,
CourseArea courseArea) {
this(name, boatClass, startDate, endDate, series, persistent, scoringScheme, id, courseArea,
OneDesignRankingMetric::new);
}
/**
* Constructs a regatta with an empty {@link RaceLogStore}.
*/
public RegattaImpl(String name, BoatClass boatClass, TimePoint startDate, TimePoint endDate, Iterable<? extends Series> series, boolean persistent,
ScoringScheme scoringScheme, Serializable id, CourseArea courseArea, RankingMetricConstructor rankingMetricConstructor) {
this(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, name, boatClass, startDate, endDate, series, persistent,
scoringScheme, id, courseArea, /* useStartTimeInference */ true, rankingMetricConstructor);
public RegattaImpl(String name, BoatClass boatClass, TimePoint startDate, TimePoint endDate,
Iterable<? extends Series> series, boolean persistent, ScoringScheme scoringScheme, Serializable id,
CourseArea courseArea, RankingMetricConstructor rankingMetricConstructor) {
this(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, name, boatClass, startDate, endDate, series,
persistent, scoringScheme, id, courseArea, /* useStartTimeInference */true, rankingMetricConstructor);
}
/**
* Constructs a regatta with a single default series with empty race column list, and a single default fleet which
* is not {@link #isPersistent() marked for persistence}.
*
* @param trackedRegattaRegistry
* used to find the {@link TrackedRegatta} for this column's series' {@link Series#getRegatta() regatta}
* in order to re-associate a {@link TrackedRace} passed to {@link #setTrackedRace(Fleet, TrackedRace)}
@@ -145,9 +157,9 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
* this column's series {@link Regatta}, respectively. If <code>null</code>, the re-association won't be
* carried out.
*/
public RegattaImpl(RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, String name, BoatClass boatClass, TimePoint startDate, TimePoint endDate,
TrackedRegattaRegistry trackedRegattaRegistry, ScoringScheme scoringScheme, Serializable id,
CourseArea courseArea) {
public RegattaImpl(RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, String name, BoatClass boatClass,
TimePoint startDate, TimePoint endDate, TrackedRegattaRegistry trackedRegattaRegistry,
ScoringScheme scoringScheme, Serializable id, CourseArea courseArea) {
this(raceLogStore, regattaLogStore, name, boatClass, startDate, endDate, trackedRegattaRegistry, scoringScheme,
id, courseArea, OneDesignRankingMetric::new);
}
@@ -165,12 +177,14 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
*/
public RegattaImpl(RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, String name, BoatClass boatClass,
TimePoint startDate, TimePoint endDate, TrackedRegattaRegistry trackedRegattaRegistry,
ScoringScheme scoringScheme, Serializable id, CourseArea courseArea, RankingMetricConstructor rankingMetricConstructor) {
ScoringScheme scoringScheme, Serializable id, CourseArea courseArea,
RankingMetricConstructor rankingMetricConstructor) {
this(raceLogStore, regattaLogStore, name, boatClass, startDate, endDate, Collections
.singletonList(new SeriesImpl(LeaderboardNameConstants.DEFAULT_SERIES_NAME,
/* isMedal */false, Collections.singletonList(new FleetImpl(LeaderboardNameConstants.DEFAULT_FLEET_NAME)),
/* isMedal */false, Collections
.singletonList(new FleetImpl(LeaderboardNameConstants.DEFAULT_FLEET_NAME)),
/* race column names */new ArrayList<String>(), trackedRegattaRegistry)), /* persistent */false,
scoringScheme, id, courseArea, /* useStartTimeInference */ true, rankingMetricConstructor);
scoringScheme, id, courseArea, /* useStartTimeInference */true, rankingMetricConstructor);
}
/**
@@ -178,9 +192,10 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
* all {@link Series} in this iterable will have their {@link Series#setRegatta(Regatta) regatta set} to
* this new regatta.
*/
public <S extends Series> RegattaImpl(RaceLogStore raceLogStore, RegattaLogStore regattaLogStore,
String name, BoatClass boatClass, TimePoint startDate, TimePoint endDate, Iterable<S> series, boolean persistent, ScoringScheme scoringScheme,
Serializable id, CourseArea courseArea, boolean useStartTimeInference, RankingMetricConstructor rankingMetricConstructor) {
public <S extends Series> RegattaImpl(RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, String name,
BoatClass boatClass, TimePoint startDate, TimePoint endDate, Iterable<S> series, boolean persistent,
ScoringScheme scoringScheme, Serializable id, CourseArea courseArea, boolean useStartTimeInference,
RankingMetricConstructor rankingMetricConstructor) {
super(name);
this.rankingMetricConstructor = rankingMetricConstructor;
this.useStartTimeInference = useStartTimeInference;
@@ -244,19 +259,19 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
}
public static String getDefaultName(String baseName, String boatClassName) {
return baseName+(boatClassName==null?"":" ("+boatClassName+")").replace('/', '_');
return baseName + (boatClassName == null ? "" : " (" + boatClassName + ")").replace('/', '_');
}
@Override
public boolean isPersistent() {
return persistent;
}
/**
* When de-serializing, a possibly remote {@link #raceLogStore} is ignored because it is transient. Instead, an
* {@link EmptyRaceLogStore} is used for the de-serialized instance. A new {@link RaceLogInformation} is assembled
* for this empty race log and applied to all columns.
* Make sure to call {@link #initializeSeriesAfterDeserialize()} after the object graph has been de-serialized.
* for this empty race log and applied to all columns. Make sure to call {@link #initializeSeriesAfterDeserialize()}
* after the object graph has been de-serialized.
*/
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
@@ -269,17 +284,16 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
raceLogStore = EmptyRaceLogStore.INSTANCE;
}
}
protected Object readResolve() throws ObjectStreamException {
raceExecutionOrderCache.triggerUpdate(); // now we're fully initialized and the cache can do its job
return this;
}
/**
* {@link RaceColumnListeners} may not be de-serialized (yet) when the regatta
* is de-serialized. To avoid re-registering empty objects most probably leading
* to null pointer exception one needs to initialize all listeners after
* all objects have been read.
* {@link RaceColumnListeners} may not be de-serialized (yet) when the regatta is de-serialized. To avoid
* re-registering empty objects most probably leading to null pointer exception one needs to initialize all
* listeners after all objects have been read.
*/
public void initializeSeriesAfterDeserialize() {
for (Series series : getSeries()) {
@@ -291,7 +305,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
} else {
logger.warning("Race Columns were null during deserialization. This should not happen.");
}
}
}
}
@Override
@@ -304,7 +318,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
}
return result;
}
@Override
public Series getSeriesByName(String name) {
for (Series s : getSeries()) {
@@ -319,12 +333,12 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
public Iterable<RaceDefinition> getAllRaces() {
return races.values();
}
@Override
public RegattaIdentifier getRegattaIdentifier() {
return new RegattaName(getName());
}
@Override
public RegattaAndRaceIdentifier getRaceIdentifier(RaceDefinition race) {
return new RegattaNameAndRaceName(getName(), race.getName());
@@ -334,12 +348,13 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
public RaceDefinition getRaceByName(String raceName) {
return races.get(raceName);
}
@Override
public void addRace(RaceDefinition race) {
logger.info("Adding race "+race.getName()+" to regatta "+getName()+" ("+hashCode()+")");
logger.info("Adding race " + race.getName() + " to regatta " + getName() + " (" + hashCode() + ")");
if (getBoatClass() != null && race.getBoatClass() != getBoatClass()) {
throw new IllegalArgumentException("Boat class "+race.getBoatClass()+" doesn't match regatta's boat class "+getBoatClass());
throw new IllegalArgumentException("Boat class " + race.getBoatClass()
+ " doesn't match regatta's boat class " + getBoatClass());
}
races.put(race.getName(), race);
synchronized (regattaListeners) {
@@ -348,10 +363,10 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
}
}
}
@Override
public void removeRace(RaceDefinition race) {
logger.info("Removing race "+race.getName()+" from regatta "+getName()+" ("+hashCode()+")");
logger.info("Removing race " + race.getName() + " from regatta " + getName() + " (" + hashCode() + ")");
races.remove(race.getName());
synchronized (regattaListeners) {
for (RegattaListener l : regattaListeners) {
@@ -403,25 +418,28 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
public void trackedRaceUnlinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) {
raceColumnListeners.notifyListenersAboutTrackedRaceUnlinked(raceColumn, fleet, trackedRace);
}
@Override
public void isMedalRaceChanged(RaceColumn raceColumn, boolean newIsMedalRace) {
raceColumnListeners.notifyListenersAboutIsMedalRaceChanged(raceColumn, newIsMedalRace);
}
@Override
public void isStartsWithZeroScoreChanged(RaceColumn raceColumn, boolean newIsStartsWithZeroScore) {
raceColumnListeners.notifyListenersAboutIsStartsWithZeroScoreChanged(raceColumn, newIsStartsWithZeroScore);
}
@Override
public void isFirstColumnIsNonDiscardableCarryForwardChanged(RaceColumn raceColumn, boolean firstColumnIsNonDiscardableCarryForward) {
raceColumnListeners.notifyListenersAboutIsFirstColumnIsNonDiscardableCarryForwardChanged(raceColumn, firstColumnIsNonDiscardableCarryForward);
public void isFirstColumnIsNonDiscardableCarryForwardChanged(RaceColumn raceColumn,
boolean firstColumnIsNonDiscardableCarryForward) {
raceColumnListeners.notifyListenersAboutIsFirstColumnIsNonDiscardableCarryForwardChanged(raceColumn,
firstColumnIsNonDiscardableCarryForward);
}
@Override
public void hasSplitFleetContiguousScoringChanged(RaceColumn raceColumn, boolean hasSplitFleetContiguousScoring) {
raceColumnListeners.notifyListenersAboutHasSplitFleetContiguousScoringChanged(raceColumn, hasSplitFleetContiguousScoring);
raceColumnListeners.notifyListenersAboutHasSplitFleetContiguousScoringChanged(raceColumn,
hasSplitFleetContiguousScoring);
}
@Override
@@ -460,7 +478,8 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
}
@Override
public void resultDiscardingRuleChanged(ResultDiscardingRule oldDiscardingRule, ResultDiscardingRule newDiscardingRule) {
public void resultDiscardingRuleChanged(ResultDiscardingRule oldDiscardingRule,
ResultDiscardingRule newDiscardingRule) {
raceColumnListeners.notifyListenersAboutResultDiscardingRuleChanged(oldDiscardingRule, newDiscardingRule);
}
@@ -483,7 +502,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
public void raceLogEventAdded(RaceColumn raceColumn, RaceLogIdentifier raceLogIdentifier, RaceLogEvent event) {
raceColumnListeners.notifyListenersAboutRaceLogEventAdded(raceColumn, raceLogIdentifier, event);
}
@Override
public ScoringScheme getScoringScheme() {
return scoringScheme;
@@ -518,17 +537,17 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
public void setDefaultCourseArea(CourseArea newCourseArea) {
this.defaultCourseArea = newCourseArea;
}
@Override
public void setUseStartTimeInference(boolean useStartTimeInference) {
this.useStartTimeInference = useStartTimeInference;
}
@Override
public RegattaConfiguration getRegattaConfiguration() {
return configuration;
}
@Override
public void setRegattaConfiguration(RegattaConfiguration configuration) {
this.configuration = configuration;
@@ -536,8 +555,8 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
/**
* @return whether this regatta defines its local per-series result discarding rules; if so, any leaderboard based
* on the regatta has to respect this and has to use a result discarding rule implementation that
* keeps discards local to each series rather than spreading them across the entire leaderboard.
* on the regatta has to respect this and has to use a result discarding rule implementation that keeps
* discards local to each series rather than spreading them across the entire leaderboard.
*/
@Override
public boolean definesSeriesDiscardThresholds() {
@@ -548,7 +567,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
}
return false;
}
public String toString() {
return getId() + " " + getName() + " " + getScoringScheme().getType().name();
}
@@ -597,7 +616,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
}
this.series = newSeriesList;
}
}
}
}
@Override
@@ -624,7 +643,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
public void removeListener(RegattaLikeListener listener) {
regattaLikeHelper.removeListener(listener);
}
@Override
public Double getTimeOnTimeFactor(Competitor competitor) {
return regattaLikeHelper.getTimeOnTimeFactor(competitor);
@@ -652,7 +671,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
public RaceExecutionOrderProvider getRaceExecutionOrderProvider() {
return raceExecutionOrderCache;
}
private class RaceExecutionOrderCache extends AbstractRaceExecutionOrderProvider {
private static final long serialVersionUID = 1658153438012186894L;
@@ -680,10 +699,13 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
}
} catch (ConcurrentModificationException e) {
// getSeries() returns a live collection, and Series.getRaceColumns() does so, too.
// In the unlikely event of a modification is applied to either of these structures while iterating, an exception
// In the unlikely event of a modification is applied to either of these structures while
// iterating, an exception
// will be thrown. We catch and log it here and try again.
logger.log(Level.INFO,
"Got a ConcurrentModificationException while trying to update the RaceExecutionOrderCache", e);
logger.log(
Level.INFO,
"Got a ConcurrentModificationException while trying to update the RaceExecutionOrderCache",
e);
concurrentlyModified = true;
}
} while (concurrentlyModified);
@@ -733,7 +755,16 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
@Override
public Iterable<Competitor> getCompetitorsRegisteredInRegattaLog() {
RegattaLog regattaLog = getRegattaLog();
CompetitorsInLogAnalyzer<RegattaLog, RegattaLogEvent, RegattaLogEventVisitor> analyzer = new CompetitorsInLogAnalyzer<>(regattaLog);
CompetitorsInLogAnalyzer<RegattaLog, RegattaLogEvent, RegattaLogEventVisitor> analyzer = new CompetitorsInLogAnalyzer<>(
regattaLog);
return analyzer.analyze();
}
@Override
public void registerCompetitor(Competitor competitor) {
RegattaLog regattaLog = getRegattaLike().getRegattaLog();
TimePoint now = MillisecondsTimePoint.now();
regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(now, now, regattaLogEventAuthorForRegatta ,
UUID.randomUUID(), competitor));
}
}
@@ -5,11 +5,15 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.UUID;
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.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.CompetitorsInLogAnalyzer;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet;
@@ -21,34 +25,41 @@ 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.impl.MillisecondsTimePoint;
/**
* Abstract leaderboard implementation that already knows about carried points, competitor display name re-keying,
* score corrections and result discarding rules. It manages a set of registered {@link RaceColumnListener}s and
* is itself one. All events received this way are forwarded to all {@link RaceColumnListener}s subscribed. This can
* be used to subscribe a concrete leaderboard implementation to the data structure providing the actual race columns
* in order to be notified whenever the set of {@link TrackedRace}s attached to the leaderboard changes.
* Abstract leaderboard implementation that already knows about carried points, competitor display name re-keying, score
* corrections and result discarding rules. It manages a set of registered {@link RaceColumnListener}s and is itself
* one. All events received this way are forwarded to all {@link RaceColumnListener}s subscribed. This can be used to
* subscribe a concrete leaderboard implementation to the data structure providing the actual race columns in order to
* be notified whenever the set of {@link TrackedRace}s attached to the leaderboard changes.
*
* @author Axel Uhl (D043530)
*
*/
public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardImpl implements HasRaceColumnsAndRegattaLike {
public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardImpl implements
HasRaceColumnsAndRegattaLike {
private static final long serialVersionUID = -328091952760083438L;
/**
* Cache for the combined competitors of this leaderboard; taken from the {@link TrackedRace#getRace() races of the
* tracked races} associated with this leaderboard. Updated when the set of tracked races changes.
*/
private transient CompetitorProviderFromRaceColumnsAndRegattaLike competitorsProvider;
private final AbstractLogEventAuthor regattaLogEventAuthorForAbstraceLeaderboard = new LogEventAuthorImpl(
AbstractLeaderboardImpl.class.getName(), 0);
/**
* @param scoreComparator the comparator to use to compare basic scores, such as net points
* @param name must not be <code>null</code>
* @param scoreComparator
* the comparator to use to compare basic scores, such as net points
* @param name
* must not be <code>null</code>
*/
public AbstractLeaderboardImpl(ThresholdBasedResultDiscardingRule resultDiscardingRule) {
super(resultDiscardingRule);
}
@Override
public Fleet getFleet(String fleetName) {
for (RaceColumn raceColumn : getRaceColumns()) {
@@ -83,7 +94,7 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI
public Iterable<Competitor> getAllCompetitors() {
return getOrCreateCompetitorsProvider().getAllCompetitors();
}
@Override
public Iterable<Competitor> getAllCompetitors(RaceColumn raceColumn, Fleet fleet) {
return getOrCreateCompetitorsProvider().getAllCompetitors(raceColumn, fleet);
@@ -110,8 +121,8 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI
public int getTrackedRank(Competitor competitor, RaceColumn race, TimePoint timePoint) {
final TrackedRace trackedRace = race.getTrackedRace(competitor);
return trackedRace == null ? 0
: trackedRace.hasStarted(timePoint) ? improveByDisqualificationsOfBetterRankedCompetitors(race, trackedRace, timePoint, trackedRace
.getRank(competitor, timePoint)) : 0;
: trackedRace.hasStarted(timePoint) ? improveByDisqualificationsOfBetterRankedCompetitors(race,
trackedRace, timePoint, trackedRace.getRank(competitor, timePoint)) : 0;
}
/**
@@ -139,9 +150,11 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI
Iterator<Competitor> ci = competitorsFromBestToWorst.iterator();
while (betterCompetitorRank < rank && ci.hasNext()) {
Competitor betterTrackedCompetitor = ci.next();
MaxPointsReason maxPointsReasonForBetterCompetitor = getScoreCorrection().getMaxPointsReason(betterTrackedCompetitor, raceColumn, timePoint);
if (maxPointsReasonForBetterCompetitor != null && maxPointsReasonForBetterCompetitor != MaxPointsReason.NONE &&
maxPointsReasonForBetterCompetitor.isAdvanceCompetitorsTrackedWorse()) {
MaxPointsReason maxPointsReasonForBetterCompetitor = getScoreCorrection().getMaxPointsReason(
betterTrackedCompetitor, raceColumn, timePoint);
if (maxPointsReasonForBetterCompetitor != null
&& maxPointsReasonForBetterCompetitor != MaxPointsReason.NONE
&& maxPointsReasonForBetterCompetitor.isAdvanceCompetitorsTrackedWorse()) {
correctedRank--;
}
betterCompetitorRank++;
@@ -160,7 +173,8 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI
TrackedRace trackedRace = raceColumn.getTrackedRace(fleet);
if (trackedRace != null) {
if (startOfLatestRace == null
|| (trackedRace.getStartOfRace() != null && trackedRace.getStartOfRace().compareTo(startOfLatestRace) > 0)) {
|| (trackedRace.getStartOfRace() != null && trackedRace.getStartOfRace().compareTo(
startOfLatestRace) > 0)) {
delayToLiveInMillisForLatestRace = trackedRace.getDelayToLiveInMillis();
}
}
@@ -168,9 +182,9 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI
}
return delayToLiveInMillisForLatestRace;
}
@Override
public RaceLog getRacelog(String raceColumnName, String fleetName){
public RaceLog getRacelog(String raceColumnName, String fleetName) {
RaceColumn raceColumn = getRaceColumnByName(raceColumnName);
Fleet fleet = raceColumn.getFleetByName(fleetName);
return raceColumn.getRaceLog(fleet);
@@ -179,7 +193,16 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI
@Override
public Iterable<Competitor> getCompetitorsRegisteredInRegattaLog() {
RegattaLog regattaLog = getRegattaLike().getRegattaLog();
CompetitorsInLogAnalyzer<RegattaLog, RegattaLogEvent, RegattaLogEventVisitor> analyzer = new CompetitorsInLogAnalyzer<>(regattaLog);
CompetitorsInLogAnalyzer<RegattaLog, RegattaLogEvent, RegattaLogEventVisitor> analyzer = new CompetitorsInLogAnalyzer<>(
regattaLog);
return analyzer.analyze();
}
@Override
public void registerCompetitor(Competitor competitor) {
RegattaLog regattaLog = getRegattaLike().getRegattaLog();
TimePoint now = MillisecondsTimePoint.now();
regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(now, now, regattaLogEventAuthorForAbstraceLeaderboard,
UUID.randomUUID(), competitor));
}
}
@@ -14,6 +14,7 @@ import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnListener;
import com.sap.sailing.domain.base.impl.SimpleAbstractRaceColumn;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.ResultDiscardingRule;
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
@@ -245,4 +246,10 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R
TrackedRace trackedRace = getTrackedRace(fleet);
return trackedRace.getMarks();
}
@Override
public void registerCompetitor(Competitor competitor, Fleet fleet)
throws CompetitorRegistrationOnRaceLogDisabledException {
throw new CompetitorRegistrationOnRaceLogDisabledException();
}
}
@@ -18,4 +18,6 @@ public interface HasRegattaLike {
RaceLog getRacelog(String raceColumnName, String fleetName);
Iterable<Competitor> getCompetitorsRegisteredInRegattaLog();
void registerCompetitor(Competitor competitor);
}