mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-16 17:21:00 +00:00
Register competitors on RaceColumn/HasRegattaLike
This commit is contained in:
1 parent
233b2b909f
commit
ffe0a94c60
7 files changed
+186
-87
No files matched your search
+4
@@ -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;
|
||||
}
|
||||
+22
@@ -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));
|
||||
}
|
||||
}
|
||||
+43
-20
@@ -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));
|
||||
}
|
||||
}
|
||||
+7
@@ -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);
|
||||
}
|
||||
Reference in new issue
Block a user