mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-30 01:16:40 +00:00
Merge branch 'master' into design2015
Conflicts: java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties
This commit is contained in:
+15
@@ -0,0 +1,15 @@
|
||||
package com.sap.sailing.domain.common;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class NotFoundException extends Exception implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1690510580423647161L;
|
||||
|
||||
public NotFoundException() {
|
||||
}
|
||||
|
||||
public NotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.sap.sailing.domain.common;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class UnableToCloseDeviceMappingException extends Exception implements Serializable{
|
||||
private static final long serialVersionUID = 4595827888350748956L;
|
||||
|
||||
public UnableToCloseDeviceMappingException() {}
|
||||
|
||||
public UnableToCloseDeviceMappingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.sap.sailing.domain.common.racelog.tracking;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class CompetitorRegistrationOnRaceLogDisabledException extends Exception implements Serializable {
|
||||
private static final long serialVersionUID = 963948633131929332L;
|
||||
|
||||
public CompetitorRegistrationOnRaceLogDisabledException() {
|
||||
super("Competitor registration not allowed on race");
|
||||
}
|
||||
|
||||
public CompetitorRegistrationOnRaceLogDisabledException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
+1
@@ -63,6 +63,7 @@ public class CompactGPSFixMovingImpl extends CompactGPSFixImpl implements GPSFix
|
||||
public String toString() {
|
||||
return super.toString()+" to "+getBearing().getDegrees()+"°";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode() ^ getBearing().hashCode();
|
||||
|
||||
+47
-80
@@ -57,6 +57,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultsImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseAreaChangeEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseDesignChangedEventImpl;
|
||||
@@ -82,23 +83,18 @@ import com.sap.sailing.domain.abstractlog.race.impl.SimpleRaceLogIdentifierImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.scoring.AdditionalScoringInformationType;
|
||||
import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.scoring.impl.RaceLogAdditionalScoringInformationEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogCloseOpenEndedDeviceMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDefineMarkEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceMarkMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsFromRaceLogEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent;
|
||||
@@ -106,6 +102,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogCloseOpenEndedDeviceMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDefineMarkEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceMarkMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl;
|
||||
@@ -1313,7 +1310,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public RaceLogEvent loadRaceLogEvent(DBObject dbObject) {
|
||||
TimePoint logicalTimePoint = loadTimePoint(dbObject);
|
||||
TimePoint createdAt = loadTimePoint(dbObject, FieldNames.RACE_LOG_EVENT_CREATED_AT);
|
||||
@@ -1363,10 +1360,6 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
return loadRaceLogProtestStartTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
|
||||
} else if (eventClass.equals(RaceLogWindFixEvent.class.getSimpleName())) {
|
||||
return loadRaceLogWindFixEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
|
||||
} else if (eventClass.equals(RaceLogDeviceCompetitorMappingEvent.class.getSimpleName())) {
|
||||
return loadRaceLogDeviceCompetitorMappingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
|
||||
} else if (eventClass.equals(RaceLogDeviceMarkMappingEvent.class.getSimpleName())) {
|
||||
return loadRaceLogDeviceMarkMappingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
|
||||
} else if (eventClass.equals(RaceLogDenoteForTrackingEvent.class.getSimpleName())) {
|
||||
return loadRaceLogDenoteForTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
|
||||
} else if (eventClass.equals(RaceLogStartTrackingEvent.class.getSimpleName())) {
|
||||
@@ -1375,21 +1368,24 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
return loadRaceLogRevokeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
|
||||
} else if (eventClass.equals(RaceLogRegisterCompetitorEvent.class.getSimpleName())) {
|
||||
return loadRaceLogRegisterCompetitorEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
|
||||
} else if (eventClass.equals(RaceLogDefineMarkEvent.class.getSimpleName())) {
|
||||
return loadRaceLogDefineMarkEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
|
||||
} else if (eventClass.equals(RaceLogCloseOpenEndedDeviceMappingEvent.class.getSimpleName())) {
|
||||
return loadRaceLogCloseOpenEndedDeviceMappingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
|
||||
} else if (eventClass.equals(RaceLogAdditionalScoringInformationEvent.class.getSimpleName())) {
|
||||
return loadRaceLogAdditionalScoringInformationEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
|
||||
} else if (eventClass.equals(RaceLogFixedMarkPassingEvent.class.getSimpleName())){
|
||||
return loadRaceLogFixedMarkPassingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
|
||||
} else if (eventClass.equals(RaceLogSuppressedMarkPassingsEvent.class.getSimpleName())){
|
||||
return loadRaceLogSuppressedMarkPassingsEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
|
||||
} else if (eventClass.equals(RaceLogUseCompetitorsFromRaceLogEvent.class.getSimpleName())){
|
||||
return loadRaceLogUseCompetitorsFromRaceLogEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
|
||||
}
|
||||
|
||||
throw new IllegalStateException(String.format("Unknown RaceLogEvent type %s", eventClass));
|
||||
}
|
||||
|
||||
private RaceLogEvent loadRaceLogUseCompetitorsFromRaceLogEvent(TimePoint createdAt, AbstractLogEventAuthor author,
|
||||
TimePoint logicalTimePoint, Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
|
||||
return new RaceLogUseCompetitorsFromRaceLogEventImpl(createdAt, author, logicalTimePoint, id, passId);
|
||||
}
|
||||
|
||||
private RaceLogEvent loadRaceLogWindFixEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint,
|
||||
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
|
||||
Wind wind = loadWind((DBObject) dbObject.get(FieldNames.WIND.name()));
|
||||
@@ -1397,40 +1393,6 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
return new RaceLogWindFixEventImpl(createdAt, logicalTimePoint, author, id, passId, wind, isMagnetic == null ? true : isMagnetic);
|
||||
}
|
||||
|
||||
private RaceLogEvent loadRaceLogDeviceCompetitorMappingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint,
|
||||
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
|
||||
DeviceIdentifier device = null;
|
||||
try {
|
||||
device = loadDeviceId(deviceIdentifierServiceFinder,
|
||||
(DBObject) dbObject.get(FieldNames.DEVICE_ID.name()));
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, "Could not load deviceId for RaceLogEvent", e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
Competitor mappedTo = baseDomainFactory.getExistingCompetitorById(
|
||||
(Serializable) dbObject.get(FieldNames.COMPETITOR_ID.name()));
|
||||
TimePoint from = loadTimePoint(dbObject, FieldNames.RACE_LOG_FROM);
|
||||
TimePoint to = loadTimePoint(dbObject, FieldNames.RACE_LOG_TO);
|
||||
return new RaceLogDeviceCompetitorMappingEventImpl(createdAt, logicalTimePoint, author, id, passId, mappedTo, device, from, to);
|
||||
}
|
||||
|
||||
private RaceLogEvent loadRaceLogDeviceMarkMappingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint,
|
||||
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
|
||||
DeviceIdentifier device = null;
|
||||
try {
|
||||
device = loadDeviceId(deviceIdentifierServiceFinder,
|
||||
(DBObject) dbObject.get(FieldNames.DEVICE_ID.name()));
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, "Could not load deviceId for RaceLogEvent", e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
//have to load complete mark, as no order is guaranteed for loading of racelog events
|
||||
Mark mappedTo = loadMark((DBObject) dbObject.get(FieldNames.MARK.name()));
|
||||
TimePoint from = loadTimePoint(dbObject, FieldNames.RACE_LOG_FROM);
|
||||
TimePoint to = loadTimePoint(dbObject, FieldNames.RACE_LOG_TO);
|
||||
return new RaceLogDeviceMarkMappingEventImpl(createdAt, logicalTimePoint, author, id, passId, mappedTo, device, from, to);
|
||||
}
|
||||
|
||||
private RaceLogEvent loadRaceLogDenoteForTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint,
|
||||
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
|
||||
String raceName = (String) dbObject.get(FieldNames.RACE_NAME.name());
|
||||
@@ -1462,20 +1424,6 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
return new RaceLogRegisterCompetitorEventImpl(createdAt, logicalTimePoint, author, id, passId, comp);
|
||||
}
|
||||
|
||||
private RaceLogEvent loadRaceLogDefineMarkEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint,
|
||||
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
|
||||
Mark mark = loadMark((DBObject) dbObject.get(FieldNames.RACE_LOG_MARK.name()));
|
||||
return new RaceLogDefineMarkEventImpl(createdAt, logicalTimePoint, author, id, passId, mark);
|
||||
}
|
||||
|
||||
private RaceLogEvent loadRaceLogCloseOpenEndedDeviceMappingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint,
|
||||
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
|
||||
Serializable deviceMappingEventId = Helpers.tryUuidConversion((Serializable) dbObject.get(FieldNames.RACE_LOG_DEVICE_MAPPING_EVENT_ID.name()));
|
||||
TimePoint closingTimePoint = loadTimePoint(dbObject, FieldNames.RACE_LOG_CLOSING_TIMEPOINT);
|
||||
return new RaceLogCloseOpenEndedDeviceMappingEventImpl(createdAt, logicalTimePoint, author, id, passId,
|
||||
deviceMappingEventId, closingTimePoint);
|
||||
}
|
||||
|
||||
private RaceLogEvent loadRaceLogAdditionalScoringInformationEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint,
|
||||
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
|
||||
Object additionalScoringInformationTypeInfo = dbObject.get(FieldNames.RACE_LOG_ADDITIONAL_SCORING_INFORMATION_TYPE.name());
|
||||
@@ -1568,27 +1516,30 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
}
|
||||
|
||||
private CompetitorResults loadPositionedCompetitors(BasicDBList dbPositionedCompetitorList) {
|
||||
CompetitorResults positionedCompetitors = new CompetitorResultsImpl();
|
||||
CompetitorResultsImpl positionedCompetitors = new CompetitorResultsImpl();
|
||||
int rankCounter = 1;
|
||||
for (Object object : dbPositionedCompetitorList) {
|
||||
DBObject dbObject = (DBObject) object;
|
||||
|
||||
Serializable competitorId = (Serializable) dbObject.get(FieldNames.COMPETITOR_ID.name());
|
||||
|
||||
String competitorName = (String) dbObject.get(FieldNames.COMPETITOR_DISPLAY_NAME.name());
|
||||
final Serializable competitorId = (Serializable) dbObject.get(FieldNames.COMPETITOR_ID.name());
|
||||
String competitorDisplayName = (String) dbObject.get(FieldNames.COMPETITOR_DISPLAY_NAME.name());
|
||||
//The Competitor name is a new field in the list. Therefore the name might be null for existing events. In this case a standard name is set.
|
||||
if (competitorName == null) {
|
||||
competitorName = "loaded competitor";
|
||||
if (competitorDisplayName == null) {
|
||||
competitorDisplayName = "loaded competitor";
|
||||
}
|
||||
|
||||
//At this point we do not retrieve the competitor object since at any point in time, especially after a server restart, the DomainFactory and its competitor
|
||||
//cache might be empty. But at this time the race log is loaded from database, so the competitor would be null.
|
||||
//By not using the Competitor object retrieved from the DomainFactory we get completely independent from server restarts and the timepoint of loading
|
||||
//competitors by tracking providers.
|
||||
|
||||
MaxPointsReason maxPointsReason = MaxPointsReason.valueOf((String) dbObject.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON.name()));
|
||||
|
||||
Util.Triple<Serializable, String, MaxPointsReason> positionedCompetitor = new Util.Triple<Serializable, String, MaxPointsReason>(competitorId, competitorName, maxPointsReason);
|
||||
final Integer rank = (Integer) dbObject.get(FieldNames.LEADERBOARD_RANK.name());
|
||||
final MaxPointsReason maxPointsReason = MaxPointsReason.valueOf((String) dbObject.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON.name()));
|
||||
final Double score = (Double) dbObject.get(FieldNames.LEADERBOARD_CORRECTED_SCORE.name());
|
||||
final Long finishingTimePointAsMillis = (Long) dbObject.get(FieldNames.RACE_LOG_FINISHING_TIME_AS_MILLIS.name());
|
||||
final TimePoint finishingTime = finishingTimePointAsMillis == null ? null : new MillisecondsTimePoint(finishingTimePointAsMillis);
|
||||
final String comment = (String) dbObject.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_COMMENT.name());
|
||||
CompetitorResultImpl positionedCompetitor = new CompetitorResultImpl(
|
||||
competitorId, competitorDisplayName, rank == null ? rankCounter : rank, maxPointsReason, score, finishingTime, comment);
|
||||
positionedCompetitors.add(positionedCompetitor);
|
||||
rankCounter++;
|
||||
}
|
||||
return positionedCompetitors;
|
||||
}
|
||||
@@ -1703,12 +1654,14 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
return loadRegattaLogSetCompetitorTimeOnTimeFactorEvent(createdAt, author, logicalTimePoint, id, dbObject);
|
||||
} else if (eventClass.equals(RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent.class.getSimpleName())) {
|
||||
return loadRegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent(createdAt, author, logicalTimePoint, id, dbObject);
|
||||
} else if (eventClass.equals(RegattaLogDefineMarkEvent.class.getSimpleName())) {
|
||||
return loadRegattaLogDefineMarkEvent(createdAt, author, logicalTimePoint, id, dbObject);
|
||||
} else if (eventClass.equals(RegattaLogRevokeEvent.class.getSimpleName())) {
|
||||
return loadRegattaLogRevokeEvent(createdAt, author, logicalTimePoint, id, dbObject);
|
||||
}
|
||||
throw new IllegalStateException(String.format("Unknown RegattaLogEvent type %s", eventClass));
|
||||
}
|
||||
|
||||
|
||||
private Competitor getCompetitorByID(DBObject dbObject) {
|
||||
Serializable competitorId = (Serializable) dbObject.get(FieldNames.REGATTA_LOG_COMPETITOR_ID.name());
|
||||
Competitor comp = baseDomainFactory.getCompetitorStore().getExistingCompetitorById(competitorId);
|
||||
@@ -1741,6 +1694,12 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
return new RegattaLogRevokeEventImpl(createdAt, logicalTimePoint, author, id,
|
||||
revokedEventId, revokedEventType, revokedEventShortInfo, reason);
|
||||
}
|
||||
|
||||
private RegattaLogEvent loadRegattaLogDefineMarkEvent(TimePoint createdAt, AbstractLogEventAuthor author,
|
||||
TimePoint logicalTimePoint, Serializable id, DBObject dbObject) {
|
||||
Mark mark = loadMark((DBObject) dbObject.get(FieldNames.REGATTA_LOG_MARK.name()));
|
||||
return new RegattaLogDefineMarkEventImpl(createdAt, author, logicalTimePoint, id, mark);
|
||||
}
|
||||
|
||||
private RegattaLogRegisterCompetitorEvent loadRegattaLogRegisterCompetitorEvent(TimePoint createdAt, AbstractLogEventAuthor author,
|
||||
TimePoint logicalTimePoint, Serializable id, DBObject dbObject) {
|
||||
@@ -1769,7 +1728,11 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
}
|
||||
//have to load complete mark, as no order is guaranteed for loading of racelog events
|
||||
Mark mappedTo = loadMark((DBObject) dbObject.get(FieldNames.MARK.name()));
|
||||
Triple<TimePoint, TimePoint, Boolean> times = loadFromToTimePoint(dbObject, FieldNames.REGATTA_LOG_FROM, FieldNames.RACE_LOG_FROM, FieldNames.REGATTA_LOG_TO, FieldNames.RACE_LOG_TO);
|
||||
@SuppressWarnings("deprecation") // used only for auto-migration; may be removed in future releases
|
||||
final FieldNames deprecatedFromFieldName = FieldNames.RACE_LOG_FROM;
|
||||
@SuppressWarnings("deprecation") // used only for auto-migration; may be removed in future releases
|
||||
final FieldNames deprecatedToFieldName = FieldNames.RACE_LOG_TO;
|
||||
Triple<TimePoint, TimePoint, Boolean> times = loadFromToTimePoint(dbObject, FieldNames.REGATTA_LOG_FROM, deprecatedFromFieldName, FieldNames.REGATTA_LOG_TO, deprecatedToFieldName);
|
||||
final TimePoint from = times.getA();
|
||||
final TimePoint to = times.getB();
|
||||
final RegattaLogDeviceMarkMappingEventImpl result = new RegattaLogDeviceMarkMappingEventImpl(createdAt, logicalTimePoint, author, id, mappedTo, device, from, to);
|
||||
@@ -1830,7 +1793,11 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
}
|
||||
Competitor mappedTo = baseDomainFactory.getExistingCompetitorById(
|
||||
(Serializable) dbObject.get(FieldNames.COMPETITOR_ID.name()));
|
||||
Triple<TimePoint, TimePoint, Boolean> times = loadFromToTimePoint(dbObject, FieldNames.REGATTA_LOG_FROM, FieldNames.RACE_LOG_FROM, FieldNames.REGATTA_LOG_TO, FieldNames.RACE_LOG_TO);
|
||||
@SuppressWarnings("deprecation") // used only for auto-migration; may be removed in future releases
|
||||
final FieldNames deprecatedFromFieldName = FieldNames.RACE_LOG_FROM;
|
||||
@SuppressWarnings("deprecation") // used only for auto-migration; may be removed in future releases
|
||||
final FieldNames deprecatedToFieldName = FieldNames.RACE_LOG_TO;
|
||||
Triple<TimePoint, TimePoint, Boolean> times = loadFromToTimePoint(dbObject, FieldNames.REGATTA_LOG_FROM, deprecatedFromFieldName, FieldNames.REGATTA_LOG_TO, deprecatedToFieldName);
|
||||
final TimePoint from = times.getA();
|
||||
final TimePoint to = times.getB();
|
||||
final boolean needsMigration = times.getC();
|
||||
|
||||
Executable → Regular
+7
-4
@@ -74,7 +74,7 @@ public enum FieldNames {
|
||||
LEADERBOARD_IS_MEDAL_RACE_COLUMN, LEADERBOARD_CARRIED_POINTS, LEADERBOARD_CARRIED_POINTS_BY_ID,
|
||||
LEADERBOARD_SCORE_CORRECTIONS, LEADERBOARD_DISCARDING_THRESHOLDS,
|
||||
LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON, LEADERBOARD_CORRECTED_SCORE, LEADERBOARD_SCORE_CORRECTION_TIMESTAMP,
|
||||
LEADERBOARD_SCORE_CORRECTION_COMMENT, LEADERBOARD_COLUMN_FACTORS,
|
||||
LEADERBOARD_RANK, LEADERBOARD_SCORE_CORRECTION_COMMENT, LEADERBOARD_COLUMN_FACTORS,
|
||||
|
||||
// leaderboard group
|
||||
LEADERBOARD_GROUP_UUID, LEADERBOARD_GROUP_NAME, LEADERBOARD_GROUP_DESCRIPTION,
|
||||
@@ -92,10 +92,13 @@ public enum FieldNames {
|
||||
CONTROLPOINT_VALUE, CONTROLPOINTWITHTWOMARKS_ID, CONTROLPOINTWITHTWOMARKS_NAME, CONTROLPOINTWITHTWOMARKS_LEFT, CONTROLPOINTWITHTWOMARKS_RIGHT,
|
||||
RACE_LOG_POSITIONED_COMPETITORS, RACE_LOG_PATHFINDER_ID, RACE_LOG_GATE_LINE_OPENING_TIME, RACE_LOG_GOLF_DOWN_TIME, RACE_LOG_START_PROCEDURE_TYPE,
|
||||
RACE_LOG_PROTEST_START_TIME, RACE_LOG_COURSE_DESIGN_NAME, RACE_LOG_REVOKED_EVENT_ID, RACE_LOG_REVOKED_EVENT_TYPE, RACE_LOG_REVOKED_EVENT_SHORT_INFO,
|
||||
RACE_LOG_REVOKED_REASON, RACE_LOG_FROM, RACE_LOG_TO, RACE_LOG_MARK, RACE_LOG_DEVICE_MAPPING_EVENT_ID,
|
||||
RACE_LOG_REVOKED_REASON, RACE_LOG_DEVICE_MAPPING_EVENT_ID,
|
||||
RACE_LOG_CLOSING_TIMEPOINT, TIMEPOINT_OF_FIXED_MARKPASSING, INDEX_OF_PASSED_WAYPOINT,INDEX_OF_FIRST_SUPPRESSED_WAYPOINT, MARK, RACE_LOG_COMPETITOR_ID,
|
||||
RACE_LOG_DEPDENDENT_ON_FLEET, RACE_LOG_DEPDENDENT_ON_RACECOLUMN, RACE_LOG_DEPDENDENT_ON_REGATTALIKE,
|
||||
RACE_LOG_START_TIME_DIFFERENCE_IN_MS,
|
||||
RACE_LOG_START_TIME_DIFFERENCE_IN_MS, RACE_LOG_FINISHING_TIME_AS_MILLIS,
|
||||
/** @deprecated Replaced by {@link #REGATTA_LOG_FROM}; auto-migration from race log device mappings to regatta log is implemented */ @Deprecated RACE_LOG_FROM,
|
||||
/** @deprecated Replaced by {@link #REGATTA_LOG_TO}; auto-migration from race log device mappings to regatta log is implemented */ @Deprecated RACE_LOG_TO,
|
||||
/** @deprecated Replaced by a regatta log entry with type {@link #REGATTA_LOG_MARK} */ @Deprecated RACE_LOG_MARK,
|
||||
/** @deprecated Replaced by WAYPOINT_PASSINGINSTRUCTIONS, still used to migrate old races*/ @Deprecated WAYPOINT_PASSINGSIDE,
|
||||
/** @deprecated Replaced by CONTROLPOINTWITHTWOMARKS_ID, still used to migrate old races*/ @Deprecated GATE_ID,
|
||||
/** @deprecated Replaced by CONTROLPOINTWITHTWOMARKS_NAME, still used to migrate old races*/ @Deprecated GATE_NAME,
|
||||
@@ -107,7 +110,7 @@ public enum FieldNames {
|
||||
REGATTA_LOG_IDENTIFIER_TYPE, REGATTA_LOG_IDENTIFIER_NAME, REGATTA_LOG_EVENT_ID, REGATTA_LOG_EVENT_CREATED_AT, REGATTA_LOG_EVENT_AUTHOR_NAME,
|
||||
REGATTA_LOG_EVENT_AUTHOR_PRIORITY, REGATTA_LOG_EVENT_CLASS, REGATTA_LOG_REVOKED_EVENT_ID, REGATTA_LOG_REVOKED_EVENT_TYPE, REGATTA_LOG_REVOKED_EVENT_SHORT_INFO,
|
||||
REGATTA_LOG_REVOKED_REASON, REGATTA_LOG_COMPETITOR_ID, REGATTA_LOG_DEVICE_MAPPING_EVENT_ID, REGATTA_LOG_CLOSING_TIMEPOINT,
|
||||
REGATTA_LOG_FROM, REGATTA_LOG_TO, REGATTA_LOG_EVENT,
|
||||
REGATTA_LOG_FROM, REGATTA_LOG_TO, REGATTA_LOG_EVENT, REGATTA_LOG_MARK,
|
||||
|
||||
// remote server reference fields
|
||||
SERVER_NAME,
|
||||
|
||||
+1487
-1533
File diff suppressed because it is too large
Load Diff
+10
-31
@@ -3,14 +3,14 @@ package com.sap.sailing.domain.persistence.impl;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogCourseAreaChangedEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningListChangedEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogGateLineOpeningTimeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogPassChangeEvent;
|
||||
@@ -21,16 +21,13 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent;
|
||||
import com.sap.sailing.domain.persistence.MongoObjectFactory;
|
||||
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
|
||||
|
||||
@@ -125,18 +122,6 @@ public class MongoRaceLogStoreVisitor implements RaceLogEventVisitor {
|
||||
mongoObjectFactory.storeRaceLogEventEvent(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogDeviceCompetitorMappingEvent event) {
|
||||
DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event);
|
||||
mongoObjectFactory.storeRaceLogEventEvent(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogDeviceMarkMappingEvent event) {
|
||||
DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event);
|
||||
mongoObjectFactory.storeRaceLogEventEvent(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogDenoteForTrackingEvent event) {
|
||||
DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event);
|
||||
@@ -161,18 +146,6 @@ public class MongoRaceLogStoreVisitor implements RaceLogEventVisitor {
|
||||
mongoObjectFactory.storeRaceLogEventEvent(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogDefineMarkEvent event) {
|
||||
DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event);
|
||||
mongoObjectFactory.storeRaceLogEventEvent(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogCloseOpenEndedDeviceMappingEvent event) {
|
||||
DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event);
|
||||
mongoObjectFactory.storeRaceLogEventEvent(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogAdditionalScoringInformationEvent event) {
|
||||
DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event);
|
||||
@@ -208,4 +181,10 @@ public class MongoRaceLogStoreVisitor implements RaceLogEventVisitor {
|
||||
DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event);
|
||||
mongoObjectFactory.storeRaceLogEventEvent(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) {
|
||||
DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event);
|
||||
mongoObjectFactory.storeRaceLogEventEvent(object);
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -4,6 +4,7 @@ import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent;
|
||||
@@ -60,4 +61,9 @@ public class MongoRegattaLogStoreVisitor implements RegattaLogEventVisitor {
|
||||
public void visit(RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent event) {
|
||||
mongoObjectFactory.storeRegattaLogEvent(regattaLikeIdentifier, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RegattaLogDefineMarkEvent event) {
|
||||
mongoObjectFactory.storeRegattaLogEvent(regattaLikeIdentifier, event);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-12
@@ -14,9 +14,9 @@ import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBCursor;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.QueryBuilder;
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLog;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.DeviceCompetitorMappingFinder;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.DeviceMarkMappingFinder;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceCompetitorMappingFinder;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceMarkMappingFinder;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
@@ -107,9 +107,9 @@ public class MongoGPSFixStoreImpl implements MongoGPSFixStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadCompetitorTrack(DynamicGPSFixTrack<Competitor, GPSFixMoving> track, AbstractLog<?, ?> log, Competitor competitor)
|
||||
public void loadCompetitorTrack(DynamicGPSFixTrack<Competitor, GPSFixMoving> track, RegattaLog log, Competitor competitor)
|
||||
throws NoCorrespondingServiceRegisteredException, TransformationException{
|
||||
List<DeviceMapping<Competitor>> mappings = new DeviceCompetitorMappingFinder<>(log).analyze().get(competitor);
|
||||
List<DeviceMapping<Competitor>> mappings = new RegattaLogDeviceCompetitorMappingFinder(log).analyze().get(competitor);
|
||||
if (mappings != null) {
|
||||
for (DeviceMapping<Competitor> mapping : mappings) {
|
||||
loadTrack(track, mapping.getDevice(), mapping.getTimeRange().from(), mapping.getTimeRange().to(), true /*inclusive*/);
|
||||
@@ -118,9 +118,9 @@ public class MongoGPSFixStoreImpl implements MongoGPSFixStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadMarkTrack(DynamicGPSFixTrack<Mark, GPSFix> track, AbstractLog<?, ?> log, Mark mark)
|
||||
public void loadMarkTrack(DynamicGPSFixTrack<Mark, GPSFix> track, RegattaLog log, Mark mark)
|
||||
throws NoCorrespondingServiceRegisteredException, TransformationException{
|
||||
List<DeviceMapping<Mark>> mappings = new DeviceMarkMappingFinder<>(log).analyze().get(mark);
|
||||
List<DeviceMapping<Mark>> mappings = new RegattaLogDeviceMarkMappingFinder(log).analyze().get(mark);
|
||||
if (mappings != null) {
|
||||
for (DeviceMapping<Mark> mapping : mappings) {
|
||||
loadTrack(track, mapping.getDevice(), mapping.getTimeRange().from(), mapping.getTimeRange().to(), true /*inclusive*/);
|
||||
@@ -192,9 +192,9 @@ public class MongoGPSFixStoreImpl implements MongoGPSFixStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadCompetitorTrack(DynamicGPSFixTrack<Competitor, GPSFixMoving> track, AbstractLog<?, ?> log,
|
||||
public void loadCompetitorTrack(DynamicGPSFixTrack<Competitor, GPSFixMoving> track, RegattaLog log,
|
||||
Competitor competitor, TimePoint start, TimePoint end) throws TransformationException {
|
||||
List<DeviceMapping<Competitor>> mappings = new DeviceCompetitorMappingFinder<>(log).analyze().get(competitor);
|
||||
List<DeviceMapping<Competitor>> mappings = new RegattaLogDeviceCompetitorMappingFinder(log).analyze().get(competitor);
|
||||
if (mappings != null) {
|
||||
for (DeviceMapping<Competitor> mapping : mappings) {
|
||||
final TimePoint from = Util.getLatestOfTimePoints(start, mapping.getTimeRange().from());
|
||||
@@ -211,9 +211,9 @@ public class MongoGPSFixStoreImpl implements MongoGPSFixStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadMarkTrack(DynamicGPSFixTrack<Mark, GPSFix> track, AbstractLog<?, ?> log, Mark mark,
|
||||
public void loadMarkTrack(DynamicGPSFixTrack<Mark, GPSFix> track, RegattaLog log, Mark mark,
|
||||
TimePoint start, TimePoint end) throws TransformationException, NoCorrespondingServiceRegisteredException {
|
||||
List<DeviceMapping<Mark>> mappings = new DeviceMarkMappingFinder<>(log).analyze().get(mark);
|
||||
List<DeviceMapping<Mark>> mappings = new RegattaLogDeviceMarkMappingFinder(log).analyze().get(mark);
|
||||
if (mappings != null) {
|
||||
for (DeviceMapping<Mark> mapping : mappings) {
|
||||
final TimePoint from = Util.getLatestOfTimePoints(start, mapping.getTimeRange().from());
|
||||
@@ -261,5 +261,4 @@ public class MongoGPSFixStoreImpl implements MongoGPSFixStore {
|
||||
}
|
||||
return ((Number) result.get(FieldNames.NUM_FIXES.name())).longValue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+13
-7
@@ -3,6 +3,8 @@ package com.sap.sailing.domain.racelogtracking.test;
|
||||
import static com.sap.sse.common.Util.size;
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
@@ -10,8 +12,10 @@ 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.impl.RaceLogImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceMarkMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceMarkMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.impl.RegattaLogImpl;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
@@ -40,11 +44,12 @@ public class AbstractGPSFixStoreTest {
|
||||
new MockDeviceAndSessionIdentifierWithGPSFixesDeserializer();
|
||||
protected final DeviceIdentifier device = new SmartphoneImeiIdentifier("a");
|
||||
protected RaceLog raceLog;
|
||||
protected RegattaLog regattaLog;
|
||||
protected GPSFixStore store;
|
||||
protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null);
|
||||
protected final Mark mark = DomainFactory.INSTANCE.getOrCreateMark("mark");
|
||||
|
||||
private final AbstractLogEventAuthor author = new LogEventAuthorImpl("author", 0);
|
||||
protected final AbstractLogEventAuthor author = new LogEventAuthorImpl("author", 0);
|
||||
|
||||
protected GPSFixMoving createFix(long millis, double lat, double lng, double knots, double degrees) {
|
||||
return new GPSFixMovingImpl(new DegreePosition(lat, lng),
|
||||
@@ -55,6 +60,7 @@ public class AbstractGPSFixStoreTest {
|
||||
public void setServiceAndRaceLog() {
|
||||
service = new RacingEventServiceImpl(null, null, serviceFinderFactory);
|
||||
raceLog = new RaceLogImpl("racelog");
|
||||
regattaLog = new RegattaLogImpl("regattalog");
|
||||
store = new MongoGPSFixStoreImpl(service.getMongoObjectFactory(), service.getDomainObjectFactory(),
|
||||
serviceFinderFactory);
|
||||
}
|
||||
@@ -66,17 +72,17 @@ public class AbstractGPSFixStoreTest {
|
||||
mongoOF.getGPSFixMetadataCollection().drop();
|
||||
}
|
||||
|
||||
protected void map(RaceLog raceLog, Competitor comp, DeviceIdentifier device, long from, long to) {
|
||||
raceLog.add(new RaceLogDeviceCompetitorMappingEventImpl(MillisecondsTimePoint.now(), author, 0,
|
||||
protected void map(RegattaLog regattaLog, Competitor comp, DeviceIdentifier device, long from, long to) {
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(),
|
||||
comp, device, new MillisecondsTimePoint(from), new MillisecondsTimePoint(to)));
|
||||
}
|
||||
|
||||
protected void map(Competitor comp, DeviceIdentifier device, long from, long to) {
|
||||
map(raceLog, comp, device, from, to);
|
||||
map(regattaLog, comp, device, from, to);
|
||||
}
|
||||
|
||||
protected void map(Mark mark, DeviceIdentifier device, long from, long to) {
|
||||
raceLog.add(new RaceLogDeviceMarkMappingEventImpl(MillisecondsTimePoint.now(), author, 0,
|
||||
regattaLog.add(new RegattaLogDeviceMarkMappingEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(),
|
||||
mark, device, new MillisecondsTimePoint(from), new MillisecondsTimePoint(to)));
|
||||
}
|
||||
|
||||
|
||||
+6
-5
@@ -19,8 +19,8 @@ import org.junit.rules.ExpectedException;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsFromRaceLogEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl;
|
||||
@@ -160,6 +160,7 @@ public class CreateAndTrackWithRaceLogTest {
|
||||
Exception {
|
||||
|
||||
RaceColumn column = leaderboard.getRaceColumnByName(columnName);
|
||||
RegattaLog regattaLog = leaderboard.getRegattaLike().getRegattaLog();
|
||||
RaceLog raceLog = column.getRaceLog(fleet);
|
||||
|
||||
// can denote racelog for tracking
|
||||
@@ -171,10 +172,10 @@ public class CreateAndTrackWithRaceLogTest {
|
||||
Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", null, null, null, null, null,
|
||||
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
|
||||
DeviceIdentifier dev1 = new SmartphoneImeiIdentifier("dev1");
|
||||
raceLog.add(new RaceLogDeviceCompetitorMappingEventImpl(t(), author, 0, comp1, dev1, t(0), t(10)));
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(t(), t(), author, 0, comp1, dev1, t(0), t(10)));
|
||||
addFixes0(dev1);
|
||||
raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(t(), author, t(), UUID.randomUUID(), 0));
|
||||
raceLog.add(new RaceLogRegisterCompetitorEventImpl(t(), author, 0, comp1));
|
||||
|
||||
// start tracking
|
||||
adapter.startTracking(service, leaderboard, column, fleet);
|
||||
|
||||
@@ -182,9 +183,9 @@ public class CreateAndTrackWithRaceLogTest {
|
||||
TrackedRace race = column.getTrackedRace(fleet);
|
||||
assertNotNull(race);
|
||||
|
||||
race.waitForLoadingFromGPSFixStoreToFinishRunning(raceLog);
|
||||
race.waitForLoadingFromGPSFixStoreToFinishRunning(regattaLog);
|
||||
addFixes1(race, comp1, dev1);
|
||||
raceLog.add(new RaceLogDeviceCompetitorMappingEventImpl(t(), author, 0, comp1, dev1, t(11), t(20)));
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(t(), t(), author, 0, comp1, dev1, t(11), t(20)));
|
||||
|
||||
// add another mapping on the fly, other old fixes should be loaded
|
||||
addFixes2(race, comp1, dev1);
|
||||
|
||||
+10
-63
@@ -1,9 +1,6 @@
|
||||
package com.sap.sailing.domain.racelogtracking.test.impl;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.lessThanOrEqualTo;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -11,9 +8,8 @@ import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDefineMarkEventImpl;
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Course;
|
||||
@@ -27,7 +23,6 @@ import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
|
||||
import com.sap.sailing.domain.base.impl.RegattaImpl;
|
||||
import com.sap.sailing.domain.base.impl.WaypointImpl;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore;
|
||||
import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
@@ -35,7 +30,6 @@ import com.sap.sailing.domain.racelogtracking.test.AbstractGPSFixStoreTest;
|
||||
import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
|
||||
import com.sap.sailing.domain.regattalog.impl.EmptyRegattaLogStore;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener;
|
||||
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
|
||||
@@ -46,10 +40,6 @@ import com.sap.sse.common.impl.TimeRangeImpl;
|
||||
public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest {
|
||||
private final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er");
|
||||
|
||||
private int numberOfSwitchesBetweenLoadingRaceLogs = 0;
|
||||
private Integer previouslyLoading = null;
|
||||
private int numFixesReceived = 0;
|
||||
|
||||
@Test
|
||||
public void doesRaceLoadOnlyBetweenStartAndEndOfTracking() throws TransformationException,
|
||||
NoCorrespondingServiceRegisteredException, InterruptedException {
|
||||
@@ -57,6 +47,8 @@ public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest {
|
||||
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
|
||||
Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2");
|
||||
DeviceIdentifier markDevice = new SmartphoneImeiIdentifier("imei2");
|
||||
regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark));
|
||||
regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(2), author, new MillisecondsTimePoint(1), 0, mark2));
|
||||
Course course = new CourseImpl("course", Arrays.asList(new Waypoint[] { new WaypointImpl(mark),
|
||||
new WaypointImpl(mark2) }));
|
||||
RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, Arrays.asList(new Competitor[] { comp, comp2 }));
|
||||
@@ -80,7 +72,8 @@ public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest {
|
||||
trackedRace.setEndOfTrackingReceived(new MillisecondsTimePoint(2000));
|
||||
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
trackedRace.waitForLoadingFromGPSFixStoreToFinishRunning(raceLog);
|
||||
trackedRace.attachRegattaLog(regattaLog);
|
||||
trackedRace.waitForLoadingFromGPSFixStoreToFinishRunning(regattaLog);
|
||||
|
||||
testNumberOfRawFixes(trackedRace.getTrack(comp), 1);
|
||||
testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1);
|
||||
@@ -99,6 +92,8 @@ public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest {
|
||||
Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, null, null,
|
||||
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
|
||||
Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2");
|
||||
regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark));
|
||||
regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(2), author, new MillisecondsTimePoint(1), 0, mark2));
|
||||
DeviceIdentifier device2 = new SmartphoneImeiIdentifier("imei2");
|
||||
DeviceIdentifier device3 = new SmartphoneImeiIdentifier("imei3");
|
||||
Course course = new CourseImpl("course", Arrays.asList(new Waypoint[] { new WaypointImpl(mark),
|
||||
@@ -128,9 +123,10 @@ public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest {
|
||||
DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(regatta, race,
|
||||
Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE, store, 0, 0, 0, /*useMarkPassingCalculator*/ false,
|
||||
OneDesignRankingMetric::new, mock(RaceLogResolver.class));
|
||||
|
||||
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
trackedRace.waitForLoadingFromGPSFixStoreToFinishRunning(raceLog);
|
||||
trackedRace.attachRegattaLog(regattaLog);
|
||||
trackedRace.waitForLoadingFromGPSFixStoreToFinishRunning(regattaLog);
|
||||
|
||||
testNumberOfRawFixes(trackedRace.getTrack(comp), 10002);
|
||||
testNumberOfRawFixes(trackedRace.getTrack(comp2), 1);
|
||||
@@ -151,53 +147,4 @@ public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest {
|
||||
assertEquals(2, store.getNumberOfFixes(device));
|
||||
assertEquals(TimeRangeImpl.create(100, 200), store.getTimeRangeCoveredByFixes(device));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void attachTwoRaceLogsAndSeeIfLoadingIsSerializedNicely() throws TransformationException,
|
||||
NoCorrespondingServiceRegisteredException, InterruptedException {
|
||||
Course course = new CourseImpl("course", Collections.<Waypoint> emptyList());
|
||||
RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass,
|
||||
Arrays.asList(new Competitor[] { comp }));
|
||||
RaceLog raceLog2 = new RaceLogImpl("raceLog 2");
|
||||
|
||||
final int numFixes = 10000;
|
||||
map(comp, device, 0, numFixes / 2);
|
||||
map(raceLog2, comp, device, numFixes / 2 + 1, numFixes);
|
||||
|
||||
for (int i = 0; i < numFixes; i++) {
|
||||
store.storeFix(device, createFix(i, 10, 20, 30, 40));
|
||||
}
|
||||
|
||||
TrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE,
|
||||
EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */
|
||||
null, /* endDate */null, null, null, "a", null));
|
||||
DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(regatta, race,
|
||||
Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE, store, 0, 0, 0, /*useMarkPassingCalculator*/ false,
|
||||
OneDesignRankingMetric::new, mock(RaceLogResolver.class));
|
||||
|
||||
trackedRace.addListener(new AbstractRaceChangeListener() {
|
||||
@Override
|
||||
public void competitorPositionChanged(GPSFixMoving fix, Competitor competitor) {
|
||||
numFixesReceived++;
|
||||
int currentlyLoading = fix.getTimePoint().asMillis() <= numFixes / 2 ? 1 : 2;
|
||||
if (previouslyLoading == null) {
|
||||
previouslyLoading = currentlyLoading;
|
||||
} else if (previouslyLoading != currentlyLoading) {
|
||||
previouslyLoading = currentlyLoading;
|
||||
numberOfSwitchesBetweenLoadingRaceLogs++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
trackedRace.attachRaceLog(raceLog2);
|
||||
|
||||
trackedRace.waitForLoadingFromGPSFixStoreToFinishRunning(raceLog);
|
||||
trackedRace.waitForLoadingFromGPSFixStoreToFinishRunning(raceLog2);
|
||||
|
||||
assertThat("switch at most once between the two race logs while loading",
|
||||
numberOfSwitchesBetweenLoadingRaceLogs, lessThanOrEqualTo(1));
|
||||
assertThat("number of fixes added to race equal to number of fixes in GPSFixStore", numFixesReceived,
|
||||
equalTo(numFixes));
|
||||
}
|
||||
}
|
||||
|
||||
+6
-27
@@ -5,7 +5,6 @@ import java.util.Set;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
@@ -26,6 +25,7 @@ import com.sap.sailing.domain.racelogtracking.impl.RaceLogRaceTracker;
|
||||
import com.sap.sailing.domain.tracking.RaceHandle;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
import com.sap.sse.common.mail.MailException;
|
||||
|
||||
public interface RaceLogTrackingAdapter {
|
||||
@@ -76,27 +76,11 @@ public interface RaceLogTrackingAdapter {
|
||||
throws NotDenotableForRaceLogTrackingException;
|
||||
|
||||
/**
|
||||
* @see #pingMark(RaceLog, Mark, GPSFix, RacingEventService) using a random {@link PingDeviceIdentifier}
|
||||
*/
|
||||
void pingMark(RaceLog raceLogToAddTo, Mark mark, GPSFix gpsFix, RacingEventService service);
|
||||
|
||||
/**
|
||||
* @see #pingMark(RaceLog, Mark, GPSFix, RacingEventService)
|
||||
* Add a fix to the {@link GPSFixStore}, and create a mapping with a virtual device for exactly that time point
|
||||
* in the {@code regattaLogToAddTo}, mapping the virtual device to the {@code mark}.
|
||||
*/
|
||||
void pingMark(RegattaLog regattaLogToAddTo, Mark mark, GPSFix gpsFix, RacingEventService service);
|
||||
|
||||
/**
|
||||
* If not yet registered, register the competitors in {@code competitors}, and unregister all already registered
|
||||
* competitors not in {@code competitors}.
|
||||
*/
|
||||
void registerCompetitors(RacingEventService service, RaceLog raceLog, Set<Competitor> competitors);
|
||||
|
||||
/**
|
||||
* If not yet registered, register the competitors in {@code competitors}, and unregister all already registered
|
||||
* competitors not in {@code competitors}.
|
||||
*/
|
||||
void registerCompetitors(RacingEventService service, RegattaLog regattaLog, Set<Competitor> competitors);
|
||||
|
||||
/**
|
||||
* Invite competitors for tracking via the Tracking App by sending out emails.
|
||||
*
|
||||
@@ -114,16 +98,11 @@ public interface RaceLogTrackingAdapter {
|
||||
String emails, Locale locale) throws MailException;
|
||||
|
||||
/**
|
||||
* Duplicate the course in the newest {@link RaceLogCourseDesignChangedEvent} in {@code from} race log to the
|
||||
* {@code to} race logs. The {@link Mark}s and {@link ControlPoint}s are duplicated and not reused. This also
|
||||
* inserts the necessary {@link RaceLogDefineMarkEvent}s into the {@code to} race logs.
|
||||
* Copy the course in the newest {@link RaceLogCourseDesignChangedEvent} in {@code from} race log to the {@code to}
|
||||
* race logs. The {@link Mark}s and {@link ControlPoint}s are reused and not duplicated.
|
||||
*/
|
||||
void copyCourse(RaceLog fromRaceLog, Set<RaceLog> toRaceLogs, SharedDomainFactory baseDomainFactory,
|
||||
RacingEventService service);
|
||||
|
||||
/**
|
||||
* Duplicate the competitor registrations from the {@code from} race log to the {@code to} race logs.
|
||||
*/
|
||||
void copyCompetitors(RaceLog from, Set<RaceLog> to,
|
||||
RacingEventService service);
|
||||
void copyCompetitors(RaceColumn fromRaceColumn, Fleet fromFleet, Iterable<Pair<RaceColumn, Fleet>> toRaces);
|
||||
}
|
||||
|
||||
+10
@@ -9,12 +9,14 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceInformationFinder;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogTrackingStateAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.base.impl.RegattaImpl;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.DoesNotHaveRegattaLogException;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.RaceNotCreatedException;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
|
||||
@@ -97,6 +99,14 @@ public class RaceLogConnectivityParams implements RaceTrackingConnectivityParame
|
||||
public Leaderboard getLeaderboard() {
|
||||
return leaderboard;
|
||||
}
|
||||
|
||||
public RegattaLog getRegattaLog() throws DoesNotHaveRegattaLogException {
|
||||
if (leaderboard instanceof HasRegattaLike) {
|
||||
return (((HasRegattaLike) leaderboard).getRegattaLike().getRegattaLog());
|
||||
} else {
|
||||
throw new DoesNotHaveRegattaLogException();
|
||||
}
|
||||
}
|
||||
|
||||
public RacingEventService getService() {
|
||||
return service;
|
||||
|
||||
+80
-61
@@ -13,9 +13,6 @@ import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLog;
|
||||
import com.sap.sailing.domain.abstractlog.MultiLogAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.MultiLogAnalyzer.MapWithValueCollectionReducer;
|
||||
import com.sap.sailing.domain.abstractlog.MultiLogAnalyzer.SetReducer;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent;
|
||||
@@ -24,23 +21,18 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastPublishedCourseDesignFinder;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.BaseRaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceInformationFinder;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogTrackingStateAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.impl.BaseRegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.DeviceCompetitorMappingFinder;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.DeviceMarkMappingFinder;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.RegisteredCompetitorsAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.DeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.DeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceCompetitorMappingFinder;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceMarkMappingFinder;
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.ControlPoint;
|
||||
@@ -60,6 +52,7 @@ import com.sap.sailing.domain.common.PassingInstruction;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.TrackedRaceStatusEnum;
|
||||
import com.sap.sailing.domain.common.abstractlog.NotRevokableException;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.DoesNotHaveRegattaLogException;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.RaceLogTrackingState;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.RaceNotCreatedException;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
@@ -75,6 +68,7 @@ import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.RaceHandle;
|
||||
import com.sap.sailing.domain.tracking.RaceTracker;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.WindStore;
|
||||
import com.sap.sailing.domain.tracking.WindTrack;
|
||||
import com.sap.sailing.domain.tracking.impl.TrackedRaceStatusImpl;
|
||||
@@ -128,21 +122,6 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener {
|
||||
for (AbstractLog<?, ?> log : params.getLogHierarchy()) {
|
||||
if (log instanceof RaceLog) {
|
||||
RaceLogEventVisitor visitor = new BaseRaceLogEventVisitor() {
|
||||
@Override
|
||||
public void visit(RaceLogDeviceCompetitorMappingEvent event) {
|
||||
RaceLogRaceTracker.this.onDeviceCompetitorMappingEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogDeviceMarkMappingEvent event) {
|
||||
RaceLogRaceTracker.this.onDeviceMarkMappingEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogDefineMarkEvent event) {
|
||||
RaceLogRaceTracker.this.onDefineMarkEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogStartTrackingEvent event) {
|
||||
RaceLogRaceTracker.this.onStartTrackingEvent(event);
|
||||
@@ -174,6 +153,11 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener {
|
||||
public void visit(RegattaLogDeviceMarkMappingEvent event) {
|
||||
RaceLogRaceTracker.this.onDeviceMarkMappingEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RegattaLogDefineMarkEvent event) {
|
||||
RaceLogRaceTracker.this.onDefineMarkEvent(event);
|
||||
}
|
||||
};
|
||||
visitors.put(log, visitor);
|
||||
((RegattaLog) log).addListener(visitor);
|
||||
@@ -247,14 +231,12 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener {
|
||||
return params.getRaceLog().getId();
|
||||
}
|
||||
|
||||
private Map<Competitor, List<DeviceMapping<Competitor>>> getNewCompetitorMappings() {
|
||||
return new MultiLogAnalyzer<>(new DeviceCompetitorMappingFinder.Factory(),
|
||||
new MapWithValueCollectionReducer<>(), params.getLogHierarchy()).analyze();
|
||||
private Map<Competitor, List<DeviceMapping<Competitor>>> getNewCompetitorMappings() throws DoesNotHaveRegattaLogException {
|
||||
return new RegattaLogDeviceCompetitorMappingFinder(params.getRegattaLog()).analyze();
|
||||
}
|
||||
|
||||
private Map<Mark, List<DeviceMapping<Mark>>> getNewMarkMappings() {
|
||||
return new MultiLogAnalyzer<>(new DeviceMarkMappingFinder.Factory(), new MapWithValueCollectionReducer<>(),
|
||||
params.getLogHierarchy()).analyze();
|
||||
private Map<Mark, List<DeviceMapping<Mark>>> getNewMarkMappings() throws DoesNotHaveRegattaLogException {
|
||||
return new RegattaLogDeviceMarkMappingFinder(params.getRegattaLog()).analyze();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -266,34 +248,41 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener {
|
||||
if (trackingTimesFromRaceLog == null) {
|
||||
TimePoint earliestMappingStart = new MillisecondsTimePoint(Long.MAX_VALUE);
|
||||
TimePoint latestMappingEnd = new MillisecondsTimePoint(Long.MIN_VALUE);
|
||||
|
||||
for (List<? extends DeviceMapping<?>> list : competitorMappings.values()) {
|
||||
for (DeviceMapping<?> mapping : list) {
|
||||
if (mapping.getTimeRange().from().before(earliestMappingStart)) {
|
||||
earliestMappingStart = mapping.getTimeRange().from();
|
||||
}
|
||||
if (mapping.getTimeRange().to().after(latestMappingEnd)) {
|
||||
latestMappingEnd = mapping.getTimeRange().to();
|
||||
}
|
||||
earliestMappingStart = getUpdatedEarliestMappingStart(earliestMappingStart, mapping.getTimeRange().from());
|
||||
latestMappingEnd = getUpdatedLatestMappingEnd(latestMappingEnd, mapping.getTimeRange().to());
|
||||
}
|
||||
}
|
||||
|
||||
for (List<? extends DeviceMapping<?>> list : markMappings.values()) {
|
||||
for (DeviceMapping<?> mapping : list) {
|
||||
if (mapping.getTimeRange().from().before(earliestMappingStart)) {
|
||||
earliestMappingStart = mapping.getTimeRange().from();
|
||||
}
|
||||
if (mapping.getTimeRange().to().after(latestMappingEnd)) {
|
||||
latestMappingEnd = mapping.getTimeRange().to();
|
||||
}
|
||||
earliestMappingStart = getUpdatedEarliestMappingStart(earliestMappingStart, mapping.getTimeRange().from());
|
||||
latestMappingEnd = getUpdatedLatestMappingEnd(latestMappingEnd, mapping.getTimeRange().to());
|
||||
}
|
||||
}
|
||||
|
||||
trackedRace.setStartOfTrackingReceived(earliestMappingStart);
|
||||
trackedRace.setEndOfTrackingReceived(latestMappingEnd);
|
||||
trackedRace.setStartOfTrackingReceived(earliestMappingStart == null ? TimePoint.BeginningOfTime : earliestMappingStart);
|
||||
trackedRace.setEndOfTrackingReceived(latestMappingEnd == null ? TimePoint.EndOfTime : latestMappingEnd);
|
||||
}
|
||||
}
|
||||
|
||||
private TimePoint getUpdatedEarliestMappingStart(TimePoint earliestMappingStart, final TimePoint from) {
|
||||
if (from == null) {
|
||||
earliestMappingStart = null; // no further updates; one open interval means startOfTracking shall be the beginning of time
|
||||
} else if (earliestMappingStart != null && from.before(earliestMappingStart)) {
|
||||
earliestMappingStart = from;
|
||||
}
|
||||
return earliestMappingStart;
|
||||
}
|
||||
|
||||
private TimePoint getUpdatedLatestMappingEnd(TimePoint latestMappingEnd, final TimePoint to) {
|
||||
if (to == null) {
|
||||
latestMappingEnd = null; // no further updates; one open interval means startOfTracking shall be the beginning of time
|
||||
} else if (latestMappingEnd != null && to.after(latestMappingEnd)) {
|
||||
latestMappingEnd = to;
|
||||
}
|
||||
return latestMappingEnd;
|
||||
}
|
||||
|
||||
private <ItemT extends WithID, FixT extends GPSFix> boolean hasMappingAlreadyBeenLoaded(
|
||||
DeviceMapping<ItemT> newMapping, List<DeviceMapping<ItemT>> oldMappings) {
|
||||
if (oldMappings == null) {
|
||||
@@ -326,7 +315,16 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener {
|
||||
return result;
|
||||
}
|
||||
|
||||
private void updateMarkMappings(boolean loadIfNotCovered) {
|
||||
/**
|
||||
* Adjusts the contents of {@link #markMappings} according to the device mappings for marks found in the regatta
|
||||
* log. Afterwards, the start end end of tracking is {@link #updateStartAndEndOfTracking() updated}.
|
||||
*
|
||||
* @param loadIfNotCovered
|
||||
* If <code>true</code>, for additional time ranges added compared to the previous contents of
|
||||
* {@link #markMappings}, their fixes are loaded from the {@link #gpsFixStore}.
|
||||
* @throws DoesNotHaveRegattaLogException
|
||||
*/
|
||||
private void updateMarkMappings(boolean loadIfNotCovered) throws DoesNotHaveRegattaLogException {
|
||||
assert trackedRace != null;
|
||||
// TODO remove fixes, if mappings have been removed
|
||||
// check if there are new time ranges not covered so far
|
||||
@@ -360,9 +358,13 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener {
|
||||
updateStartAndEndOfTracking();
|
||||
}
|
||||
|
||||
private void onDeviceMarkMappingEvent(DeviceMarkMappingEvent<?> event) {
|
||||
private void onDeviceMarkMappingEvent(RegattaLogDeviceMarkMappingEvent event) {
|
||||
if (trackedRace != null) {
|
||||
updateMarkMappings(true);
|
||||
try {
|
||||
updateMarkMappings(true);
|
||||
} catch (DoesNotHaveRegattaLogException e) {
|
||||
logger.warning("Could not load update mark mappings as RegattaLog couldn't be found");
|
||||
}
|
||||
gpsFixStore.addListener(this, event.getDevice());
|
||||
}
|
||||
}
|
||||
@@ -373,20 +375,35 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener {
|
||||
* {@link RaceLogDefineMarkEvent} is received, the existence of the track for that mark in the {@link TrackedRace}
|
||||
* has to be ensured, also ensuring that the mark will exist in the mark tracks map key set.
|
||||
*/
|
||||
private void onDefineMarkEvent(RaceLogDefineMarkEvent event) {
|
||||
private void onDefineMarkEvent(RegattaLogDefineMarkEvent event) {
|
||||
if (trackedRace != null) {
|
||||
trackedRace.getOrCreateTrack(event.getMark());
|
||||
}
|
||||
}
|
||||
|
||||
private void onDeviceCompetitorMappingEvent(DeviceCompetitorMappingEvent<?> event) {
|
||||
private void onDeviceCompetitorMappingEvent(RegattaLogDeviceCompetitorMappingEvent event) {
|
||||
if (trackedRace != null) {
|
||||
updateCompetitorMappings(true);
|
||||
try {
|
||||
updateCompetitorMappings(true);
|
||||
} catch (DoesNotHaveRegattaLogException e) {
|
||||
logger.warning("Could not load update competitor mappings as RegattaLog couldn't be found");
|
||||
}
|
||||
gpsFixStore.addListener(this, event.getDevice());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCompetitorMappings(boolean loadIfNotCovered) {
|
||||
/**
|
||||
* Adjusts the {@link #competitorMappings} map according to the competitor registrations for the race managed by
|
||||
* this tracked, either from the regatta log or the race log. Then, the {@link TrackedRace}'s start and end of
|
||||
* tracking time frame is {@link #updateStartAndEndOfTracking() updated} from the mapping intervals.
|
||||
*
|
||||
* @param loadIfNotCovered
|
||||
* if <code>true</code>, the GPS fixes for the mappings will be loaded based on a comparison of the
|
||||
* previous mappings from {@link #competitorMappings} and the new mappings.
|
||||
*
|
||||
* @throws DoesNotHaveRegattaLogException
|
||||
*/
|
||||
private void updateCompetitorMappings(boolean loadIfNotCovered) throws DoesNotHaveRegattaLogException {
|
||||
// TODO remove fixes, if mappings have been removed
|
||||
|
||||
// check if there are new time ranges not covered so far
|
||||
@@ -466,9 +483,7 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener {
|
||||
}
|
||||
throw new RaceNotCreatedException(String.format("Race for racelog (%s) has already been created", raceLog));
|
||||
}
|
||||
// check both the racelog and regattalog for registered competitors
|
||||
Set<Competitor> competitors = new MultiLogAnalyzer<>(RegisteredCompetitorsAnalyzer.Factory.INSTANCE,
|
||||
new SetReducer<Competitor>(), params.getLogHierarchy()).analyze();
|
||||
Iterable<Competitor> competitors = raceColumn.getAllCompetitors(params.getFleet());
|
||||
Serializable raceId = denoteEvent.getRaceId();
|
||||
final RaceDefinition raceDef = new RaceDefinitionImpl(raceName, course, boatClass, competitors, raceId);
|
||||
Iterable<Sideline> sidelines = Collections.<Sideline> emptyList();
|
||||
@@ -486,8 +501,12 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener {
|
||||
}
|
||||
}
|
||||
// update the device mappings (without loading the fixes, as the TrackedRace does this itself on startup)
|
||||
updateCompetitorMappings(false);
|
||||
updateMarkMappings(false);
|
||||
try {
|
||||
updateCompetitorMappings(false);
|
||||
updateMarkMappings(false);
|
||||
} catch (DoesNotHaveRegattaLogException e) {
|
||||
logger.warning("Could not load update mark and competitor mappings as RegattaLog couldn't be found");
|
||||
}
|
||||
// add listeners for devices in mappings already present
|
||||
addListeners(competitorMappings);
|
||||
addListeners(markMappings);
|
||||
|
||||
+41
-146
@@ -3,13 +3,12 @@ package com.sap.sailing.domain.racelogtracking.impl;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import javax.activation.DataHandler;
|
||||
import javax.activation.DataSource;
|
||||
@@ -22,33 +21,19 @@ import javax.mail.util.ByteArrayDataSource;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
|
||||
import com.google.zxing.WriterException;
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLog;
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.impl.AllEventsOfTypeFinder;
|
||||
import com.sap.sailing.domain.abstractlog.impl.LastEventOfTypeFinder;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastPublishedCourseDesignFinder;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseDesignChangedEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogTrackingStateAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDefineMarkEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceMarkMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackingEventImpl;
|
||||
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.RegattaLogDeviceMarkMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.RegisteredCompetitorsAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorEvent;
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.CourseBase;
|
||||
@@ -63,6 +48,7 @@ import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.base.impl.CourseDataImpl;
|
||||
import com.sap.sailing.domain.common.RegattaIdentifier;
|
||||
import com.sap.sailing.domain.common.abstractlog.NotRevokableException;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.NotDenotableForRaceLogTrackingException;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.NotDenotedForRaceLogTrackingException;
|
||||
@@ -70,10 +56,8 @@ import com.sap.sailing.domain.common.racelog.tracking.RaceLogRaceTrackerExistsEx
|
||||
import com.sap.sailing.domain.common.racelog.tracking.RaceLogTrackingState;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFix;
|
||||
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.racelogtracking.PingDeviceIdentifierImpl;
|
||||
import com.sap.sailing.domain.racelogtracking.RaceLogTrackingAdapter;
|
||||
import com.sap.sailing.domain.tracking.RaceHandle;
|
||||
@@ -82,6 +66,7 @@ import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
|
||||
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.mail.MailException;
|
||||
import com.sap.sse.mail.MailService;
|
||||
@@ -150,44 +135,44 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
@Override
|
||||
public void denoteRaceForRaceLogTracking(RacingEventService service, Leaderboard leaderboard,
|
||||
RaceColumn raceColumn, Fleet fleet, String raceName) throws NotDenotableForRaceLogTrackingException {
|
||||
|
||||
BoatClass boatClass = null;
|
||||
final BoatClass boatClass;
|
||||
if (leaderboard instanceof RegattaLeaderboard) {
|
||||
RegattaLeaderboard rLeaderboard = (RegattaLeaderboard) leaderboard;
|
||||
boatClass = rLeaderboard.getRegatta().getBoatClass();
|
||||
} else {
|
||||
throw new NotDenotableForRaceLogTrackingException(
|
||||
"Can only denote races in RegattaLeaderboards for RaceLog-tracking");
|
||||
if (!Util.isEmpty(raceColumn.getAllCompetitors(fleet))) {
|
||||
boatClass = findDominatingBoatClass(raceColumn.getAllCompetitors(fleet));
|
||||
} else if (!Util.isEmpty(raceColumn.getAllCompetitors())) {
|
||||
boatClass = findDominatingBoatClass(raceColumn.getAllCompetitors());
|
||||
} else if (!Util.isEmpty(leaderboard.getAllCompetitors())) {
|
||||
boatClass = findDominatingBoatClass(leaderboard.getAllCompetitors());
|
||||
} else {
|
||||
throw new NotDenotableForRaceLogTrackingException("Couldn't infer boat class, no competitors on race and leaderboard");
|
||||
}
|
||||
}
|
||||
|
||||
if (raceName == null) {
|
||||
raceName = leaderboard.getName() + " " + raceColumn.getName() + " " + fleet.getName();
|
||||
}
|
||||
|
||||
RaceLog raceLog = raceColumn.getRaceLog(fleet);
|
||||
assert raceLog != null : new NotDenotableForRaceLogTrackingException("No RaceLog found in place");
|
||||
|
||||
if (new RaceLogTrackingStateAnalyzer(raceLog).analyze().isForTracking()) {
|
||||
throw new NotDenotableForRaceLogTrackingException("Already denoted for tracking");
|
||||
}
|
||||
|
||||
RaceLogEvent event = new RaceLogDenoteForTrackingEventImpl(MillisecondsTimePoint.now(),
|
||||
service.getServerAuthor(), raceLog.getCurrentPassId(), raceName, boatClass, UUID.randomUUID());
|
||||
raceLog.add(event);
|
||||
}
|
||||
|
||||
private BoatClass findDominatingBoatClass(Iterable<Competitor> allCompetitors) {
|
||||
return Util.getDominantObject(()->StreamSupport.stream(allCompetitors.spliterator(), /* parallel */ false).map(c->c.getBoat().getBoatClass()).iterator());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void denoteAllRacesForRaceLogTracking(final RacingEventService service, final Leaderboard leaderboard)
|
||||
throws NotDenotableForRaceLogTrackingException {
|
||||
if (leaderboard instanceof FlexibleLeaderboard) {
|
||||
throw new NotDenotableForRaceLogTrackingException("Can only use regatta leaderboards for RaceLog-tracking");
|
||||
}
|
||||
for (RaceColumn column : leaderboard.getRaceColumns()) {
|
||||
for (Fleet fleet : column.getFleets()) {
|
||||
try {
|
||||
denoteRaceForRaceLogTracking(service, leaderboard, column, fleet, null);
|
||||
} catch (NotDenotableForRaceLogTrackingException e) {
|
||||
}
|
||||
denoteRaceForRaceLogTracking(service, leaderboard, column, fleet, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,18 +187,6 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
return new RaceLogTrackingStateAnalyzer(raceColumn.getRaceLog(fleet)).analyze();
|
||||
}
|
||||
|
||||
private void revokeAlreadyDefinedMarks(RaceLog raceLog, AbstractLogEventAuthor author) {
|
||||
List<RaceLogEvent> markEvents = new AllEventsOfTypeFinder<>(raceLog, /* only unrevoked */true,
|
||||
RaceLogDefineMarkEvent.class).analyze();
|
||||
for (RaceLogEvent event : markEvents) {
|
||||
try {
|
||||
raceLog.revokeEvent(author, event, "removing mark that was already defined");
|
||||
} catch (NotRevokableException e) {
|
||||
logger.log(Level.WARNING, "Could not remove mark that was already defined by adding RevokeEvent", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyCourse(RaceLog fromRaceLog, Set<RaceLog> toRaceLogs, SharedDomainFactory baseDomainFactory,
|
||||
RacingEventService service) {
|
||||
@@ -223,29 +196,16 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
course.getWaypoints().forEach(wp -> Util.addAll(wp.getMarks(), marks));
|
||||
}
|
||||
|
||||
final List<RaceLogEvent> raceLogDeviceMarkMappingEvents = new AllEventsOfTypeFinder<>(fromRaceLog, /*
|
||||
* only
|
||||
* unrevoked
|
||||
*/true,
|
||||
RaceLogDeviceMarkMappingEvent.class).analyze();
|
||||
for (RaceLog toRaceLog : toRaceLogs) {
|
||||
if (new RaceLogTrackingStateAnalyzer(toRaceLog).analyze().isForTracking()) {
|
||||
if (course != null) {
|
||||
CourseBase newCourse = new CourseDataImpl("Copy of \"" + course.getName() + "\"");
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
int i = 0;
|
||||
revokeAlreadyDefinedMarks(toRaceLog, service.getServerAuthor());
|
||||
for (Waypoint oldWaypoint : course.getWaypoints()) {
|
||||
newCourse.addWaypoint(i++, oldWaypoint);
|
||||
}
|
||||
for (Mark mark : marks) {
|
||||
RaceLogEvent event = new RaceLogDefineMarkEventImpl(now, service.getServerAuthor(),
|
||||
toRaceLog.getCurrentPassId(), mark);
|
||||
toRaceLog.add(event);
|
||||
}
|
||||
for (RaceLogEvent raceLogDeviceMarkMappingEvent : raceLogDeviceMarkMappingEvents) {
|
||||
toRaceLog.add(raceLogDeviceMarkMappingEvent);
|
||||
}
|
||||
|
||||
int passId = toRaceLog.getCurrentPassId();
|
||||
RaceLogEvent newCourseEvent = new RaceLogCourseDesignChangedEventImpl(now,
|
||||
service.getServerAuthor(), passId, newCourse);
|
||||
@@ -257,23 +217,31 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyCompetitors(RaceLog fromRaceLog, Set<RaceLog> toRaceLogs, RacingEventService service) {
|
||||
final Set<Competitor> competitors = new RegisteredCompetitorsAnalyzer<>(fromRaceLog).analyze();
|
||||
for (RaceLog toRaceLog : toRaceLogs) {
|
||||
registerCompetitors(service, toRaceLog, competitors);
|
||||
public void copyCompetitors(final RaceColumn fromRaceColumn, final Fleet fromFleet, final Iterable<Pair<RaceColumn, Fleet>> toRaces) {
|
||||
Iterable<Competitor> competitorsToCopy = fromRaceColumn.getAllCompetitors(fromFleet);
|
||||
for (Pair<RaceColumn, Fleet> toRace : toRaces) {
|
||||
final RaceColumn toRaceColumn = toRace.getA();
|
||||
final Fleet toFleet = toRace.getB();
|
||||
try {
|
||||
if (toRaceColumn.isCompetitorRegistrationInRacelogEnabled(toFleet)) {
|
||||
toRaceColumn.registerCompetitors(competitorsToCopy, toFleet);
|
||||
} else {
|
||||
toRaceColumn.enableCompetitorRegistrationOnRaceLog(toFleet);
|
||||
toRaceColumn.registerCompetitors(competitorsToCopy, toFleet);
|
||||
}
|
||||
} catch (CompetitorRegistrationOnRaceLogDisabledException e1) {
|
||||
// cannot happen as we explicitly checked successfully before, or enabled it when the check failed; still produce a log documenting this strangeness:
|
||||
logger.log(Level.WARNING, "Internal error: race column "+toRaceColumn.getName()+" does not accept competitor registration although it should", e1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private static interface DeviceMarkMappingEventFactory<VisitorT, EventT extends AbstractLogEvent<VisitorT>> {
|
||||
EventT createDeviceMarkMapping(DeviceIdentifier device, TimePoint timePoint);
|
||||
}
|
||||
|
||||
private <VisitorT, EventT extends AbstractLogEvent<VisitorT>, LogT extends AbstractLog<EventT, VisitorT>> void pingMark(
|
||||
LogT log, Mark mark, GPSFix gpsFix, RacingEventService service,
|
||||
DeviceMarkMappingEventFactory<VisitorT, EventT> factory, DeviceIdentifier device) {
|
||||
TimePoint time = gpsFix.getTimePoint();
|
||||
EventT mapping = factory.createDeviceMarkMapping(device, time);
|
||||
@Override
|
||||
public void pingMark(RegattaLog log, Mark mark, GPSFix gpsFix, RacingEventService service) {
|
||||
final PingDeviceIdentifierImpl device = new PingDeviceIdentifierImpl();
|
||||
final TimePoint timePoint = gpsFix.getTimePoint();
|
||||
final RegattaLogEvent mapping = new RegattaLogDeviceMarkMappingEventImpl(timePoint,
|
||||
timePoint, service.getServerAuthor(), UUID.randomUUID(), mark, device, timePoint, timePoint);
|
||||
log.add(mapping);
|
||||
try {
|
||||
service.getGPSFixStore().storeFix(device, gpsFix);
|
||||
@@ -282,30 +250,6 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pingMark(RaceLog raceLog, Mark mark, GPSFix gpsFix, RacingEventService service) {
|
||||
DeviceMarkMappingEventFactory<RaceLogEventVisitor, RaceLogEvent> raceLogEventFactory =
|
||||
(DeviceIdentifier dev, TimePoint timePoint) -> new RaceLogDeviceMarkMappingEventImpl(timePoint, service
|
||||
.getServerAuthor(), raceLog.getCurrentPassId(), mark, dev, timePoint, timePoint);
|
||||
pingMark(
|
||||
raceLog,
|
||||
mark,
|
||||
gpsFix,
|
||||
service,
|
||||
raceLogEventFactory,
|
||||
new PingDeviceIdentifierImpl());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pingMark(RegattaLog regattaLog, Mark mark, GPSFix gpsFix, RacingEventService service) {
|
||||
DeviceMarkMappingEventFactory<RegattaLogEventVisitor, RegattaLogEvent> regattaLogEventFactory =
|
||||
(DeviceIdentifier dev, TimePoint timePoint) -> new RegattaLogDeviceMarkMappingEventImpl(timePoint,
|
||||
timePoint, service.getServerAuthor(), UUID.randomUUID(), mark, dev, timePoint, timePoint);
|
||||
pingMark(regattaLog, mark, gpsFix, service,
|
||||
regattaLogEventFactory,
|
||||
new PingDeviceIdentifierImpl());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeDenotationForRaceLogTracking(RacingEventService service, RaceLog raceLog) {
|
||||
RaceLogEvent denoteForTrackingEvent = new LastEventOfTypeFinder<>(raceLog, true,
|
||||
@@ -321,55 +265,6 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
private <LogT extends AbstractLog<EventT, VisitorT>, EventT extends AbstractLogEvent<VisitorT>, VisitorT> void registerCompetitors(
|
||||
AbstractLogEventAuthor author, LogT log, Set<Competitor> competitors,
|
||||
Function<Competitor, EventT> registerEventFactory) {
|
||||
Set<Competitor> alreadyRegistered = new HashSet<Competitor>(new RegisteredCompetitorsAnalyzer<>(log).analyze());
|
||||
Set<Competitor> toBeRegistered = new HashSet<Competitor>();
|
||||
|
||||
for (Competitor c : competitors) {
|
||||
toBeRegistered.add(c);
|
||||
}
|
||||
|
||||
Set<Competitor> toBeRemoved = new HashSet<Competitor>(alreadyRegistered);
|
||||
toBeRemoved.removeAll(toBeRegistered);
|
||||
toBeRegistered.removeAll(alreadyRegistered);
|
||||
|
||||
// register
|
||||
for (Competitor c : toBeRegistered) {
|
||||
log.add(registerEventFactory.apply(c));
|
||||
}
|
||||
|
||||
// unregister
|
||||
for (EventT event : log.getUnrevokedEventsDescending()) {
|
||||
if (event instanceof RegisterCompetitorEvent) {
|
||||
RegisterCompetitorEvent<?> registerEvent = (RegisterCompetitorEvent<?>) event;
|
||||
if (toBeRemoved.contains(registerEvent.getCompetitor())) {
|
||||
try {
|
||||
log.revokeEvent(author, event,
|
||||
"unregistering competitor because no longer selected for registration");
|
||||
} catch (NotRevokableException e) {
|
||||
logger.log(Level.WARNING, "could not unregister competitor by adding RevokeEvent", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCompetitors(RacingEventService service, RaceLog raceLog, Set<Competitor> competitors) {
|
||||
registerCompetitors(service.getServerAuthor(), raceLog, competitors,
|
||||
c -> new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), service.getServerAuthor(),
|
||||
raceLog.getCurrentPassId(), c));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCompetitors(RacingEventService service, RegattaLog regattaLog, Set<Competitor> competitors) {
|
||||
registerCompetitors(service.getServerAuthor(), regattaLog, competitors,
|
||||
c -> new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(),
|
||||
MillisecondsTimePoint.now(), service.getServerAuthor(), UUID.randomUUID(), c));
|
||||
}
|
||||
|
||||
private MailService getMailService() {
|
||||
ServiceReference<MailService> ref = Activator.getContext().getServiceReference(MailService.class);
|
||||
if (ref == null) {
|
||||
|
||||
-115
@@ -1,115 +0,0 @@
|
||||
package com.sap.sailing.domain.racelog.analyzing.test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasItem;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.MultiLogAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.impl.RegattaLogImpl;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.DeviceMappingFinder;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.RegisteredCompetitorsAnalyzer;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.impl.CompetitorImpl;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceMapping;
|
||||
import com.sap.sailing.domain.racelogtracking.impl.SmartphoneUUIDIdentifierImpl;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.WithID;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class MultiLogAnalyzerTest {
|
||||
private static TimePoint now() {
|
||||
return MillisecondsTimePoint.now();
|
||||
}
|
||||
|
||||
private static TimePoint t(long millis) {
|
||||
return new MillisecondsTimePoint(millis);
|
||||
}
|
||||
|
||||
private static UUID uuid() {
|
||||
return UUID.randomUUID();
|
||||
}
|
||||
|
||||
private RaceLog raceLog;
|
||||
private RegattaLog regattaLog;
|
||||
private AbstractLogEventAuthor author;
|
||||
|
||||
private static Competitor createCompetitor(int n) {
|
||||
return new CompetitorImpl(n, n + "", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
|
||||
}
|
||||
|
||||
private static DeviceIdentifier createDevice() {
|
||||
return new SmartphoneUUIDIdentifierImpl(UUID.randomUUID());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
raceLog = new RaceLogImpl(0);
|
||||
regattaLog = new RegattaLogImpl(0);
|
||||
author = new LogEventAuthorImpl("test", 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerCompetitorsInRaceAndRegattaLog() {
|
||||
Competitor c1 = createCompetitor(1);
|
||||
Competitor c2 = createCompetitor(2);
|
||||
Competitor c3 = createCompetitor(3);
|
||||
|
||||
raceLog.add(new RaceLogRegisterCompetitorEventImpl(now(), now(), author, uuid(), 0, c1));
|
||||
regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(now(), now(), author, uuid(), c2));
|
||||
|
||||
raceLog.add(new RaceLogRegisterCompetitorEventImpl(now(), now(), author, uuid(), 0, c3));
|
||||
regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(now(), now(), author, uuid(), c3));
|
||||
|
||||
Set<Competitor> result = new MultiLogAnalyzer<>(
|
||||
RegisteredCompetitorsAnalyzer.Factory.INSTANCE, new MultiLogAnalyzer.SetReducer<Competitor>(), raceLog,
|
||||
regattaLog).analyze();
|
||||
|
||||
assertThat("competitor 1 added", result, hasItem(c1));
|
||||
assertThat("competitor 2 added", result, hasItem(c2));
|
||||
assertThat("competitor 3 added", result, hasItem(c3));
|
||||
assertThat("only three items in total", result.size(), equalTo(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deviceMappingsInRaceAndRegattaLog() {
|
||||
Competitor c1 = createCompetitor(1);
|
||||
Competitor c2 = createCompetitor(2);
|
||||
|
||||
DeviceIdentifier d1 = createDevice();
|
||||
DeviceIdentifier d2 = createDevice();
|
||||
|
||||
raceLog.add(new RaceLogDeviceCompetitorMappingEventImpl(now(), now(), author, 0, 0, c1, d1, t(0), t(10)));
|
||||
raceLog.add(new RaceLogDeviceCompetitorMappingEventImpl(now(), now(), author, 1, 0, c1, d2, t(30), t(40)));
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(now(), now(), author, 2, c2, d2, t(10), t(20)));
|
||||
|
||||
// and one for same item (competitor) in other log
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(now(), now(), author, 3, c1, d1, t(10),
|
||||
t(20)));
|
||||
|
||||
Map<WithID, List<DeviceMapping<WithID>>> result = new MultiLogAnalyzer<>(
|
||||
new DeviceMappingFinder.Factory<>(), new MultiLogAnalyzer.MapWithValueCollectionReducer<>(), raceLog,
|
||||
regattaLog).analyze();
|
||||
|
||||
assertThat("mappings for two competitors", result.size(), equalTo(2));
|
||||
assertThat("three mappings for competitor 1 ", result.get(c1).size(), equalTo(3));
|
||||
assertThat("one mapping for competitor 2", result.get(c2).size(), equalTo(1));
|
||||
}
|
||||
}
|
||||
-27
@@ -16,10 +16,6 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl;
|
||||
import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier;
|
||||
import com.sap.sailing.domain.test.AbstractLeaderboardTest;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
@@ -76,29 +72,6 @@ public class SerializeRaceLogEventsTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRaceLogSerializationWithEventContainingDeviceIdentifier() throws IOException, ClassNotFoundException {
|
||||
RaceLogDeviceCompetitorMappingEvent mappingEvent = new RaceLogDeviceCompetitorMappingEventImpl(
|
||||
MillisecondsTimePoint.now(), new LogEventAuthorImpl("Author Name", /* priority */0), 0,
|
||||
AbstractLeaderboardTest.createCompetitor("Test Competitor"), new SmartphoneImeiIdentifier("1948364938463903"), new MillisecondsTimePoint(0), new MillisecondsTimePoint(10));
|
||||
raceLog.add(mappingEvent);
|
||||
oos.writeObject(raceLog);
|
||||
ObjectInputStream ois = getObjectInputStream();
|
||||
RaceLog rl = (RaceLog) ois.readObject();
|
||||
raceLog.lockForRead();
|
||||
rl.lockForRead();
|
||||
try {
|
||||
RaceLogDeviceCompetitorMappingEvent expected = ((RaceLogDeviceCompetitorMappingEvent) raceLog.getFirstRawFix());
|
||||
RaceLogDeviceCompetitorMappingEvent actual = ((RaceLogDeviceCompetitorMappingEvent) rl.getFirstRawFix());
|
||||
|
||||
assertEquals(Util.size(raceLog.getRawFixes()), Util.size(rl.getRawFixes()));
|
||||
assertEquals(expected.getDevice().getIdentifierType(), actual.getDevice().getIdentifierType());
|
||||
} finally {
|
||||
rl.unlockAfterRead();
|
||||
raceLog.unlockAfterRead();
|
||||
}
|
||||
}
|
||||
|
||||
private ObjectInputStream getObjectInputStream() throws IOException {
|
||||
return new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
|
||||
}
|
||||
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
package com.sap.sailing.domain.racelog.tracking.analyzing.test;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRevokeEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class RevokeEventTest extends AbstractRaceLogTrackingTest {
|
||||
@Test
|
||||
public void revokedEventIsExcluded() {
|
||||
RaceLogEvent event = new RaceLogDeviceCompetitorMappingEventImpl(now, now, author, UUID.randomUUID(), 0, null, null, null, null);
|
||||
RaceLogRevokeEvent revokeEvent = new RaceLogRevokeEventImpl(now.plus(1), now.plus(1), author, UUID.randomUUID(), 0, event.getId(),
|
||||
null, null, null);
|
||||
|
||||
log.add(event);
|
||||
log.add(revokeEvent);
|
||||
|
||||
log.lockForRead();
|
||||
Assert.assertFalse(Util.contains(log.getUnrevokedEvents(), event));
|
||||
log.unlockAfterRead();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eventRevokedByAuthorWithLowerPrioIsNotExcluded() {
|
||||
RaceLogEvent event = new RaceLogDeviceCompetitorMappingEventImpl(now, now, author, UUID.randomUUID(), 0, null, null, null, null);
|
||||
RaceLogRevokeEvent revokeEvent = new RaceLogRevokeEventImpl(now.plus(1), now.plus(1), author1, UUID.randomUUID(), 0, event.getId(),
|
||||
null, null, null);
|
||||
|
||||
log.add(event);
|
||||
log.add(revokeEvent);
|
||||
|
||||
log.lockForRead();
|
||||
Assert.assertTrue(Util.contains(log.getUnrevokedEvents(), event));
|
||||
log.unlockAfterRead();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void revokingRevokeEventIsNotHarmful() {
|
||||
RaceLogEvent event = new RaceLogDeviceCompetitorMappingEventImpl(now, now, author, UUID.randomUUID(), 0, null, null, null, null);
|
||||
RaceLogRevokeEvent revokeEvent = new RaceLogRevokeEventImpl(now.plus(1), now.plus(1), author, UUID.randomUUID(), 0, event.getId(),
|
||||
null, null, null);
|
||||
RaceLogRevokeEvent revokeEvent2 = new RaceLogRevokeEventImpl(now.plus(2), now.plus(2), author, UUID.randomUUID(), 2, revokeEvent.getId(),
|
||||
null, null, null);
|
||||
|
||||
log.add(event);
|
||||
log.add(revokeEvent);
|
||||
|
||||
log.lockForRead();
|
||||
Assert.assertFalse(Util.contains(log.getUnrevokedEvents(), event));
|
||||
Assert.assertFalse(Util.contains(log.getUnrevokedEvents(), revokeEvent));
|
||||
Assert.assertFalse(Util.contains(log.getUnrevokedEvents(), revokeEvent2));
|
||||
log.unlockAfterRead();
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.sap.sailing.domain.regattalog.tracking.analyzing.test;
|
||||
|
||||
import org.junit.Before;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.impl.RegattaLogImpl;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public abstract class AbstractRegattaLogTrackingTest {
|
||||
|
||||
protected RegattaLog log;
|
||||
protected final AbstractLogEventAuthor author = new LogEventAuthorImpl("author0", 0);
|
||||
protected final AbstractLogEventAuthor author1 = new LogEventAuthorImpl("author1", 1);
|
||||
|
||||
protected final TimePoint now = MillisecondsTimePoint.now();
|
||||
|
||||
public AbstractRegattaLogTrackingTest() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
log = new RegattaLogImpl("log");
|
||||
}
|
||||
|
||||
}
|
||||
+9
-9
@@ -1,4 +1,4 @@
|
||||
package com.sap.sailing.domain.racelog.tracking.analyzing.test;
|
||||
package com.sap.sailing.domain.regattalog.tracking.analyzing.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@@ -11,10 +11,10 @@ import junit.framework.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogCloseOpenEndedDeviceMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.DeviceCompetitorMappingFinder;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogCloseOpenEndedDeviceMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceCompetitorMappingFinder;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.impl.CompetitorImpl;
|
||||
import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier;
|
||||
@@ -23,7 +23,7 @@ import com.sap.sailing.domain.racelogtracking.DeviceMapping;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class DeviceMappingFinderTest extends AbstractRaceLogTrackingTest {
|
||||
public class DeviceMappingFinderTest 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);
|
||||
private final DeviceIdentifier device = new SmartphoneImeiIdentifier("imei");
|
||||
@@ -31,7 +31,7 @@ public class DeviceMappingFinderTest extends AbstractRaceLogTrackingTest {
|
||||
private int time = 0;
|
||||
|
||||
private List<DeviceMapping<Competitor>> getMappings() {
|
||||
return new DeviceCompetitorMappingFinder<>(log).analyze().get(competitor);
|
||||
return new RegattaLogDeviceCompetitorMappingFinder(log).analyze().get(competitor);
|
||||
}
|
||||
|
||||
private TimePoint t() {
|
||||
@@ -43,14 +43,14 @@ public class DeviceMappingFinderTest extends AbstractRaceLogTrackingTest {
|
||||
}
|
||||
|
||||
private Serializable addMapping(AbstractLogEventAuthor author, DeviceIdentifier device, Long from, Long to, Competitor item) {
|
||||
RaceLogEvent mapping = new RaceLogDeviceCompetitorMappingEventImpl(t(), t(), author, UUID.randomUUID(), 0, item, device,
|
||||
RegattaLogEvent mapping = new RegattaLogDeviceCompetitorMappingEventImpl(t(), t(), author, UUID.randomUUID(), item, device,
|
||||
t(from), t(to));
|
||||
log.add(mapping);
|
||||
return mapping.getId();
|
||||
}
|
||||
|
||||
private void closeMapping(AbstractLogEventAuthor author, DeviceIdentifier device, Serializable mappingId, long millis) {
|
||||
RaceLogEvent mapping = new RaceLogCloseOpenEndedDeviceMappingEventImpl(t(), t(), author, UUID.randomUUID(), 0, mappingId,
|
||||
RegattaLogEvent mapping = new RegattaLogCloseOpenEndedDeviceMappingEventImpl(t(), author, t(), UUID.randomUUID(), mappingId,
|
||||
new MillisecondsTimePoint(millis));
|
||||
log.add(mapping);
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package com.sap.sailing.domain.regattalog.tracking.analyzing.test;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRevokeEventImpl;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class RevokeEventTest extends AbstractRegattaLogTrackingTest {
|
||||
@Test
|
||||
public void revokedEventIsExcluded() {
|
||||
RegattaLogEvent event = new RegattaLogDeviceCompetitorMappingEventImpl(now, now, author, UUID.randomUUID(), null, null, null, null);
|
||||
RegattaLogRevokeEvent revokeEvent = new RegattaLogRevokeEventImpl(now.plus(1), now.plus(1), author, UUID.randomUUID(), event.getId(),
|
||||
null, null, null);
|
||||
|
||||
log.add(event);
|
||||
log.add(revokeEvent);
|
||||
|
||||
log.lockForRead();
|
||||
Assert.assertFalse(Util.contains(log.getUnrevokedEvents(), event));
|
||||
log.unlockAfterRead();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eventRevokedByAuthorWithLowerPrioIsNotExcluded() {
|
||||
RegattaLogEvent event = new RegattaLogDeviceCompetitorMappingEventImpl(now, now, author, UUID.randomUUID(), null, null, null, null);
|
||||
RegattaLogRevokeEvent revokeEvent = new RegattaLogRevokeEventImpl(now.plus(1), now.plus(1), author1, UUID.randomUUID(), event.getId(),
|
||||
null, null, null);
|
||||
|
||||
log.add(event);
|
||||
log.add(revokeEvent);
|
||||
|
||||
log.lockForRead();
|
||||
Assert.assertTrue(Util.contains(log.getUnrevokedEvents(), event));
|
||||
log.unlockAfterRead();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void revokingRevokeEventIsNotHarmful() {
|
||||
RegattaLogEvent event = new RegattaLogDeviceCompetitorMappingEventImpl(now, now, author, UUID.randomUUID(), null, null, null, null);
|
||||
RegattaLogRevokeEvent revokeEvent = new RegattaLogRevokeEventImpl(now.plus(1), now.plus(1), author, UUID.randomUUID(), event.getId(),
|
||||
null, null, null);
|
||||
RegattaLogRevokeEvent revokeEvent2 = new RegattaLogRevokeEventImpl(now.plus(2), now.plus(2), author, UUID.randomUUID(), revokeEvent.getId(),
|
||||
null, null, null);
|
||||
|
||||
log.add(event);
|
||||
log.add(revokeEvent);
|
||||
|
||||
log.lockForRead();
|
||||
Assert.assertFalse(Util.contains(log.getUnrevokedEvents(), event));
|
||||
Assert.assertFalse(Util.contains(log.getUnrevokedEvents(), revokeEvent));
|
||||
Assert.assertFalse(Util.contains(log.getUnrevokedEvents(), revokeEvent2));
|
||||
log.unlockAfterRead();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -9,8 +9,8 @@ import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer;
|
||||
|
||||
/**
|
||||
* Finds all events in the log which is an {@code instanceof} {@link #ofType}.
|
||||
*
|
||||
* @author Fredrik Teschke
|
||||
*
|
||||
*/
|
||||
public class AllEventsOfTypeFinder<LogT extends AbstractLog<EventT, VisitorT>, EventT extends AbstractLogEvent<VisitorT>,
|
||||
VisitorT> extends BaseLogAnalyzer<LogT, EventT, VisitorT, List<EventT>> {
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.sap.sailing.domain.abstractlog.race;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
/**
|
||||
* holds the competitor ID, the competitor name, the finishing rank, an optional score, the optional {@link MaxPointReason} and
|
||||
* an optional finishing time, important for handicapped races. An optional comment for the competitor's result can also be
|
||||
* provided as a simple {@link String}, such as a reason for a disqualification or a redress given.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public interface CompetitorResult extends Serializable {
|
||||
Serializable getCompetitorId();
|
||||
|
||||
String getCompetitorDisplayName();
|
||||
|
||||
int getOneBasedRank();
|
||||
|
||||
MaxPointsReason getMaxPointsReason();
|
||||
|
||||
Double getScore();
|
||||
|
||||
TimePoint getFinishingTime();
|
||||
|
||||
String getComment();
|
||||
}
|
||||
+4
-9
@@ -1,15 +1,10 @@
|
||||
package com.sap.sailing.domain.abstractlog.race;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
/**
|
||||
* A triple holding the competitor ID, the competitor name and the {@link MaxPointReason} documenting the score for the
|
||||
* competitor
|
||||
* A set of competitor results; order does not tell anything about the finishing order which can be seen from
|
||||
* the {@link CompetitorResult#getRank}.
|
||||
*/
|
||||
public interface CompetitorResults extends List<Util.Triple<Serializable, String, MaxPointsReason>> {
|
||||
|
||||
public interface CompetitorResults extends Iterable<CompetitorResult> {
|
||||
boolean add(CompetitorResult result);
|
||||
}
|
||||
|
||||
+3
-12
@@ -1,13 +1,10 @@
|
||||
package com.sap.sailing.domain.abstractlog.race;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent;
|
||||
|
||||
|
||||
public interface RaceLogEventVisitor {
|
||||
@@ -39,19 +36,11 @@ public interface RaceLogEventVisitor {
|
||||
|
||||
public void visit(RaceLogWindFixEvent event);
|
||||
|
||||
public void visit(RaceLogDeviceCompetitorMappingEvent event);
|
||||
|
||||
public void visit(RaceLogDeviceMarkMappingEvent event);
|
||||
|
||||
public void visit(RaceLogDenoteForTrackingEvent event);
|
||||
|
||||
public void visit(RaceLogStartTrackingEvent event);
|
||||
|
||||
public void visit(RaceLogRegisterCompetitorEvent event);
|
||||
|
||||
public void visit(RaceLogDefineMarkEvent event);
|
||||
|
||||
public void visit(RaceLogCloseOpenEndedDeviceMappingEvent event);
|
||||
|
||||
public void visit(RaceLogAdditionalScoringInformationEvent additionalScoringInformation);
|
||||
|
||||
@@ -64,4 +53,6 @@ public interface RaceLogEventVisitor {
|
||||
public void visit(RaceLogStartOfTrackingEvent event);
|
||||
|
||||
public void visit(RaceLogEndOfTrackingEvent event);
|
||||
|
||||
public void visit(RaceLogUseCompetitorsFromRaceLogEvent event);
|
||||
}
|
||||
|
||||
+4
-4
@@ -2,10 +2,10 @@ package com.sap.sailing.domain.abstractlog.race;
|
||||
|
||||
|
||||
/**
|
||||
* This RaceLog evet type confirms the entered positioning list. Since we do not guarantee the order of incoming events from the app (due to possible
|
||||
* connectivity issues), this event type contains the the confirmed positioning list again. Although this racelog event type contains the same information
|
||||
* such as {@link RaceLogFinishPositioningListChangedEvent} we keep it for backwards compatibility reasons.
|
||||
*
|
||||
* This RaceLog event type confirms the entered positioning list. Since we do not guarantee the order of incoming events
|
||||
* from the app (due to possible connectivity issues), this event type contains the the confirmed positioning list
|
||||
* again. Although this racelog event type contains the same information such as
|
||||
* {@link RaceLogFinishPositioningListChangedEvent} we keep it for backwards compatibility reasons.
|
||||
*/
|
||||
public interface RaceLogFinishPositioningConfirmedEvent extends RaceLogFinishPositioningEvent {
|
||||
|
||||
|
||||
+6
-1
@@ -1,6 +1,11 @@
|
||||
package com.sap.sailing.domain.abstractlog.race;
|
||||
|
||||
|
||||
/**
|
||||
* Captures a temporary race result description. The result is not final yet and needs to be confirmed by
|
||||
* a {@link RaceLogFinishPositioningConfirmedEvent} before it is adopted by other parts of the model. This
|
||||
* type of event can be used to store the interims state of a result editing process before the result
|
||||
* if committed.
|
||||
*/
|
||||
public interface RaceLogFinishPositioningListChangedEvent extends RaceLogFinishPositioningEvent {
|
||||
|
||||
}
|
||||
-1
@@ -19,7 +19,6 @@ public class ConfirmedFinishPositioningListFinder extends RaceLogAnalyzer<Compet
|
||||
return finishPositioningEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
-2
@@ -19,8 +19,6 @@ public class LastPublishedCourseDesignFinder extends RaceLogAnalyzer<CourseBase>
|
||||
return courseDesignEvent.getCourseDesign();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.analyzing.impl;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogUsesOwnCompetitorsAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
|
||||
public class RaceLogRegisteredCompetitorsAnalyzer extends RaceLogAnalyzer<Set<Competitor>> {
|
||||
|
||||
public RaceLogRegisteredCompetitorsAnalyzer(RaceLog raceLog) {
|
||||
super(raceLog);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<Competitor> performAnalysis() {
|
||||
final Set<Competitor> result;
|
||||
if (new RaceLogUsesOwnCompetitorsAnalyzer(getLog()).analyze()){
|
||||
// get Events from RaceLog
|
||||
result = new CompetitorsInLogAnalyzer<>(getLog()).analyze();
|
||||
} else {
|
||||
// as we're explicitly only trying to find those registrations in the RaceLog, we won't
|
||||
// return anything from the regatta log.
|
||||
result = Collections.emptySet();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+6
-24
@@ -22,13 +22,10 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent;
|
||||
|
||||
public abstract class AbstractRaceLogChangedVisitor implements RaceLogEventVisitor {
|
||||
protected abstract void notifyListenerAboutEventAdded(RaceLogEvent event);
|
||||
@@ -92,16 +89,6 @@ public abstract class AbstractRaceLogChangedVisitor implements RaceLogEventVisit
|
||||
notifyListenerAboutEventAdded(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogDeviceCompetitorMappingEvent event) {
|
||||
notifyListenerAboutEventAdded(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogDeviceMarkMappingEvent event) {
|
||||
notifyListenerAboutEventAdded(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogDenoteForTrackingEvent event) {
|
||||
notifyListenerAboutEventAdded(event);
|
||||
@@ -121,16 +108,6 @@ public abstract class AbstractRaceLogChangedVisitor implements RaceLogEventVisit
|
||||
public void visit(RaceLogRegisterCompetitorEvent event) {
|
||||
notifyListenerAboutEventAdded(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogDefineMarkEvent event) {
|
||||
notifyListenerAboutEventAdded(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogCloseOpenEndedDeviceMappingEvent event) {
|
||||
notifyListenerAboutEventAdded(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogAdditionalScoringInformationEvent additionalScoringInformation) {
|
||||
@@ -161,4 +138,9 @@ public abstract class AbstractRaceLogChangedVisitor implements RaceLogEventVisit
|
||||
public void visit(RaceLogEndOfTrackingEvent event) {
|
||||
notifyListenerAboutEventAdded(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) {
|
||||
notifyListenerAboutEventAdded(event);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-24
@@ -21,13 +21,10 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent;
|
||||
|
||||
/**
|
||||
* Base class implementing {@link RaceLogEventVisitor}. Every method is implemented as a no-op.
|
||||
@@ -99,16 +96,6 @@ public abstract class BaseRaceLogEventVisitor implements RaceLogEventVisitor {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogDeviceCompetitorMappingEvent event) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogDeviceMarkMappingEvent event) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogDenoteForTrackingEvent event) {
|
||||
|
||||
@@ -129,16 +116,6 @@ public abstract class BaseRaceLogEventVisitor implements RaceLogEventVisitor {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogDefineMarkEvent event) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogCloseOpenEndedDeviceMappingEvent event) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogAdditionalScoringInformationEvent event) {
|
||||
|
||||
@@ -168,4 +145,9 @@ public abstract class BaseRaceLogEventVisitor implements RaceLogEventVisitor {
|
||||
public void visit(RaceLogStartOfTrackingEvent event) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.CompetitorResult;
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class CompetitorResultImpl implements CompetitorResult {
|
||||
private static final long serialVersionUID = 4928351242700897387L;
|
||||
|
||||
private final Serializable competitorId;
|
||||
|
||||
private final String competitorDisplayName;
|
||||
|
||||
private final int oneBasedRank;
|
||||
|
||||
private final MaxPointsReason maxPointsReason;
|
||||
|
||||
private final Double score;
|
||||
|
||||
private final TimePoint finishingTime;
|
||||
|
||||
private final String comment;
|
||||
|
||||
public CompetitorResultImpl(Serializable competitorId, String competitorDisplayName, int oneBasedRank,
|
||||
MaxPointsReason maxPointsReason, Double score, TimePoint finishingTime, String comment) {
|
||||
super();
|
||||
this.competitorId = competitorId;
|
||||
this.competitorDisplayName = competitorDisplayName;
|
||||
this.oneBasedRank = oneBasedRank;
|
||||
this.maxPointsReason = maxPointsReason;
|
||||
this.score = score;
|
||||
this.finishingTime = finishingTime;
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getCompetitorId() {
|
||||
return competitorId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCompetitorDisplayName() {
|
||||
return competitorDisplayName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOneBasedRank() {
|
||||
return oneBasedRank;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MaxPointsReason getMaxPointsReason() {
|
||||
return maxPointsReason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimePoint getFinishingTime() {
|
||||
return finishingTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((comment == null) ? 0 : comment.hashCode());
|
||||
result = prime * result + ((competitorDisplayName == null) ? 0 : competitorDisplayName.hashCode());
|
||||
result = prime * result + ((competitorId == null) ? 0 : competitorId.hashCode());
|
||||
result = prime * result + ((finishingTime == null) ? 0 : finishingTime.hashCode());
|
||||
result = prime * result + ((maxPointsReason == null) ? 0 : maxPointsReason.hashCode());
|
||||
result = prime * result + oneBasedRank;
|
||||
result = prime * result + ((score == null) ? 0 : score.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
CompetitorResultImpl other = (CompetitorResultImpl) obj;
|
||||
if (comment == null) {
|
||||
if (other.comment != null)
|
||||
return false;
|
||||
} else if (!comment.equals(other.comment))
|
||||
return false;
|
||||
if (competitorDisplayName == null) {
|
||||
if (other.competitorDisplayName != null)
|
||||
return false;
|
||||
} else if (!competitorDisplayName.equals(other.competitorDisplayName))
|
||||
return false;
|
||||
if (competitorId == null) {
|
||||
if (other.competitorId != null)
|
||||
return false;
|
||||
} else if (!competitorId.equals(other.competitorId))
|
||||
return false;
|
||||
if (finishingTime == null) {
|
||||
if (other.finishingTime != null)
|
||||
return false;
|
||||
} else if (!finishingTime.equals(other.finishingTime))
|
||||
return false;
|
||||
if (maxPointsReason != other.maxPointsReason)
|
||||
return false;
|
||||
if (oneBasedRank != other.oneBasedRank)
|
||||
return false;
|
||||
if (score == null) {
|
||||
if (other.score != null)
|
||||
return false;
|
||||
} else if (!score.equals(other.score))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CompetitorResultImpl [competitorId=" + competitorId + ", competitorName=" + competitorDisplayName + ", rank="
|
||||
+ oneBasedRank + ", maxPointsReason=" + maxPointsReason + ", score=" + score + ", finishingTime="
|
||||
+ finishingTime + ", comment=" + comment + "]";
|
||||
}
|
||||
|
||||
}
|
||||
+2
-6
@@ -1,14 +1,10 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.CompetitorResult;
|
||||
import com.sap.sailing.domain.abstractlog.race.CompetitorResults;
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class CompetitorResultsImpl extends ArrayList<Util.Triple<Serializable, String, MaxPointsReason>> implements CompetitorResults {
|
||||
|
||||
public class CompetitorResultsImpl extends ArrayList<CompetitorResult> implements CompetitorResults {
|
||||
private static final long serialVersionUID = 4928351242700897387L;
|
||||
|
||||
}
|
||||
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.tracking;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.CloseOpenEndedDeviceMappingEvent;
|
||||
|
||||
public interface RaceLogCloseOpenEndedDeviceMappingEvent extends RaceLogEvent,
|
||||
CloseOpenEndedDeviceMappingEvent<RaceLogEventVisitor> {
|
||||
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.tracking;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.Revokable;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
|
||||
/**
|
||||
* Defines a mark, that can then be used to build a course.
|
||||
*
|
||||
* @author Fredrik Teschke
|
||||
*
|
||||
*/
|
||||
public interface RaceLogDefineMarkEvent extends RaceLogEvent, Revokable {
|
||||
Mark getMark();
|
||||
}
|
||||
+2
-2
@@ -5,7 +5,7 @@ import java.io.Serializable;
|
||||
import com.sap.sailing.domain.abstractlog.Revokable;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.DeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
|
||||
/**
|
||||
@@ -13,7 +13,7 @@ import com.sap.sailing.domain.base.BoatClass;
|
||||
* for creating this race will be accumulated in this RaceLog. Once it is present, the
|
||||
* actual {@link TrackedRace} can then be created from this information, and fixes for
|
||||
* competitors and marks that arrive on the server, for which a corresponding
|
||||
* {@link DeviceMappingEvent} exists will be added to the race.
|
||||
* {@link RegattaLogDeviceMappingEvent} exists will be added to the race.
|
||||
* @author Fredrik Teschke
|
||||
*
|
||||
*/
|
||||
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.tracking;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.DeviceCompetitorMappingEvent;
|
||||
|
||||
public interface RaceLogDeviceCompetitorMappingEvent extends RaceLogEvent,
|
||||
DeviceCompetitorMappingEvent<RaceLogEventVisitor> {
|
||||
|
||||
}
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.tracking;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.DeviceMarkMappingEvent;
|
||||
|
||||
public interface RaceLogDeviceMarkMappingEvent extends RaceLogEvent,
|
||||
DeviceMarkMappingEvent<RaceLogEventVisitor> {
|
||||
|
||||
}
|
||||
-1
@@ -3,7 +3,6 @@ package com.sap.sailing.domain.abstractlog.race.tracking;
|
||||
import com.sap.sailing.domain.abstractlog.Revokable;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl;
|
||||
|
||||
/**
|
||||
* Closes the phase during which {@link RaceLogDeviceCompetitorMappingEventImpl}s actually result
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.tracking;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.Revokable;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogUsesOwnCompetitorsAnalyzer;
|
||||
|
||||
/**
|
||||
* This is a marker event, which marks a {@link RaceLog} for using it's own competitor registrations. When present,
|
||||
* competitors are not registered on the RegattaLog corresponding to the RaceLog, but on the RaceLog itself. This is for
|
||||
* example used for split fleets.
|
||||
*
|
||||
* See bug2851.
|
||||
*
|
||||
* @see RaceLogUsesOwnCompetitorsAnalyzer
|
||||
* @author Jan Bross (D056848)
|
||||
*
|
||||
*/
|
||||
public interface RaceLogUseCompetitorsFromRaceLogEvent extends RaceLogEvent, Revokable {
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLog;
|
||||
import com.sap.sailing.domain.abstractlog.MultiLogAnalyzer.AnalyzerFactory;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
|
||||
public class RaceLogDefinedMarkFinder extends RaceLogAnalyzer<Collection<Mark>> {
|
||||
public RaceLogDefinedMarkFinder(RaceLog raceLog) {
|
||||
super(raceLog);
|
||||
}
|
||||
|
||||
public static class Factory implements AnalyzerFactory<Collection<Mark>> {
|
||||
@Override
|
||||
public RaceLogAnalyzer<Collection<Mark>> createAnalyzer(AbstractLog<?, ?> log) {
|
||||
return new RaceLogDefinedMarkFinder((RaceLog) log);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Mark> performAnalysis() {
|
||||
List<Mark> result = new ArrayList<Mark>();
|
||||
for (RaceLogEvent event : getLog().getUnrevokedEvents()) {
|
||||
if (event instanceof RaceLogDefineMarkEvent) {
|
||||
RaceLogDefineMarkEvent dME = (RaceLogDefineMarkEvent) event;
|
||||
result.add(dME.getMark());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.LastPingMappingEventFinder;
|
||||
import com.sap.sse.common.WithID;
|
||||
|
||||
public class RaceLogLastPingMappingEventFinder<ItemT extends WithID>
|
||||
extends LastPingMappingEventFinder<RaceLog, RaceLogEvent, RaceLogEventVisitor, ItemT> {
|
||||
|
||||
public RaceLogLastPingMappingEventFinder(RaceLog log, WithID forItem) {
|
||||
super(log, forItem);
|
||||
}
|
||||
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogCloseOpenEndedDeviceMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.OpenEndedDeviceMappingCloser;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceMapping;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class RaceLogOpenEndedDeviceMappingCloser extends
|
||||
OpenEndedDeviceMappingCloser<RaceLog, RaceLogEvent, RaceLogEventVisitor, RaceLogCloseOpenEndedDeviceMappingEvent> {
|
||||
|
||||
public RaceLogOpenEndedDeviceMappingCloser(RaceLog log, DeviceMapping<?> mapping, AbstractLogEventAuthor author,
|
||||
TimePoint closingTimePoint) {
|
||||
super(log, mapping, author, closingTimePoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RaceLogCloseOpenEndedDeviceMappingEvent createCloseEvent(TimePoint logicalTimePoint,
|
||||
Serializable eventToCloseId) {
|
||||
return new RaceLogCloseOpenEndedDeviceMappingEventImpl(
|
||||
logicalTimePoint, author, getLog().getCurrentPassId(), eventToCloseId, closingTimePoint);
|
||||
}
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.impl.AllEventsOfTypeFinder;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent;
|
||||
|
||||
/**
|
||||
* Determines whether the race log claims to authoritatively define the competitors for the race to which it belongs.
|
||||
* This depends on the presence of an unrevoked {@link RaceLogUseCompetitorsFromRaceLogEvent} event in the race log.
|
||||
*
|
||||
* @author Jan Bross
|
||||
*
|
||||
*/
|
||||
public class RaceLogUsesOwnCompetitorsAnalyzer extends RaceLogAnalyzer<Boolean>{
|
||||
public RaceLogUsesOwnCompetitorsAnalyzer(RaceLog raceLog) {
|
||||
super(raceLog);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean performAnalysis() {
|
||||
RaceLog raceLog = getLog();
|
||||
List<RaceLogEvent> event = new AllEventsOfTypeFinder<>(raceLog, /*only unrevoked*/ true, RaceLogUseCompetitorsFromRaceLogEvent.class).analyze();
|
||||
return event.size() >= 1;
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
|
||||
/**
|
||||
* Used to find competitors of a race based on {@link RaceLog} and {@link RegattaLog} contents. Checks whether the
|
||||
* competitors for the given race are registered on the RaceLog via {@link RaceLogUsesOwnCompetitorsAnalyzer} or on the
|
||||
* RegattaLog and fetches the competitors appropriately.
|
||||
*
|
||||
* Should not be used by clients directly. Instead, get the competitor set from the {@code RaceColumn}, using either one
|
||||
* of {@code getAllCompetitors()} and {@code getAllCompetitors(Fleet)}. Those methods automatically check whether a
|
||||
* tracked race is present, which takes precedence over the Race/RegattaLog.
|
||||
*
|
||||
* @author Jan Bross (D056848)
|
||||
*
|
||||
*/
|
||||
public class RegisteredCompetitorsAnalyzer extends RaceLogAnalyzer<Set<Competitor>> {
|
||||
private RegattaLog regattaLog;
|
||||
|
||||
public RegisteredCompetitorsAnalyzer(RaceLog raceLog, RegattaLog regattaLog) {
|
||||
super(raceLog);
|
||||
this.regattaLog = regattaLog;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<Competitor> performAnalysis() {
|
||||
final Set<Competitor> result;
|
||||
if (new RaceLogUsesOwnCompetitorsAnalyzer(getLog()).analyze()) {
|
||||
// get Events from RaceLog
|
||||
result = new CompetitorsInLogAnalyzer<>(getLog()).analyze();
|
||||
} else {
|
||||
// get Events from RegattaLog
|
||||
result = new CompetitorsInLogAnalyzer<>(regattaLog).analyze();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.tracking.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventData;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventDataImpl;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.impl.AbstractDeviceMappingEventImpl;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.WithID;
|
||||
|
||||
public abstract class AbstractRaceLogDeviceMappingEventImpl<ItemT extends WithID>
|
||||
extends AbstractDeviceMappingEventImpl<RaceLogEventVisitor, ItemT> implements RaceLogEvent {
|
||||
private static final long serialVersionUID = -5114645637316367845L;
|
||||
private final RaceLogEventData raceLogEventData;
|
||||
|
||||
public AbstractRaceLogDeviceMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint,
|
||||
AbstractLogEventAuthor author, Serializable id, int passId, ItemT mappedTo, DeviceIdentifier device,
|
||||
TimePoint from, TimePoint to) {
|
||||
super(createdAt, logicalTimePoint, author, id, mappedTo, device, from, to);
|
||||
this.raceLogEventData = new RaceLogEventDataImpl(null, passId);
|
||||
}
|
||||
|
||||
public AbstractRaceLogDeviceMappingEventImpl(TimePoint logicalTimePoint,
|
||||
AbstractLogEventAuthor author, int passId, ItemT mappedTo, DeviceIdentifier device,
|
||||
TimePoint from, TimePoint to) {
|
||||
this(now(), logicalTimePoint, author, randId(), passId, mappedTo, device, from, to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPassId() {
|
||||
return raceLogEventData.getPassId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Competitor> getInvolvedBoats() {
|
||||
return raceLogEventData.getInvolvedBoats();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return raceLogEventData.toString();
|
||||
}
|
||||
}
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.tracking.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventData;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventDataImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.impl.BaseCloseOpenEndedDeviceMappingEventImpl;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class RaceLogCloseOpenEndedDeviceMappingEventImpl extends
|
||||
BaseCloseOpenEndedDeviceMappingEventImpl<RaceLogEventVisitor> implements
|
||||
RaceLogCloseOpenEndedDeviceMappingEvent {
|
||||
private static final long serialVersionUID = -5114645637316367845L;
|
||||
private final RaceLogEventData raceLogEventData;
|
||||
|
||||
public RaceLogCloseOpenEndedDeviceMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint,
|
||||
AbstractLogEventAuthor author, Serializable id, int passId, Serializable deviceMappingEventId,
|
||||
TimePoint closingTimePoint) {
|
||||
super(createdAt, logicalTimePoint, author, id, deviceMappingEventId, closingTimePoint);
|
||||
this.raceLogEventData = new RaceLogEventDataImpl(null, passId);
|
||||
}
|
||||
|
||||
public RaceLogCloseOpenEndedDeviceMappingEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author,
|
||||
int passId, Serializable deviceMappingEventId, TimePoint closingTimePoint) {
|
||||
this(now(), logicalTimePoint, author, randId(), passId, deviceMappingEventId, closingTimePoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPassId() {
|
||||
return raceLogEventData.getPassId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Competitor> getInvolvedBoats() {
|
||||
return raceLogEventData.getInvolvedBoats();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return raceLogEventData.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(RaceLogEventVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.tracking.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class RaceLogDefineMarkEventImpl extends RaceLogEventImpl implements RaceLogDefineMarkEvent {
|
||||
private static final long serialVersionUID = 277007856878002208L;
|
||||
|
||||
private final Mark mark;
|
||||
|
||||
public RaceLogDefineMarkEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author,
|
||||
Serializable pId, int pPassId, Mark mark) {
|
||||
super(createdAt, logicalTimePoint, author, pId, pPassId);
|
||||
this.mark = mark;
|
||||
}
|
||||
|
||||
public RaceLogDefineMarkEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author,
|
||||
int pPassId, Mark mark) {
|
||||
this(now(), logicalTimePoint, author, randId(), pPassId, mark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(RaceLogEventVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mark getMark() {
|
||||
return mark;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortInfo() {
|
||||
return mark.toString();
|
||||
}
|
||||
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.tracking.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class RaceLogDeviceCompetitorMappingEventImpl extends AbstractRaceLogDeviceMappingEventImpl<Competitor>
|
||||
implements RaceLogDeviceCompetitorMappingEvent {
|
||||
public RaceLogDeviceCompetitorMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint,
|
||||
AbstractLogEventAuthor author, Serializable pId, int pPassId, Competitor mappedTo, DeviceIdentifier device,
|
||||
TimePoint from, TimePoint to) {
|
||||
super(createdAt, logicalTimePoint, author, pId, pPassId, mappedTo, device, from, to);
|
||||
}
|
||||
|
||||
public RaceLogDeviceCompetitorMappingEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author,
|
||||
int pPassId, Competitor mappedTo, DeviceIdentifier device, TimePoint from, TimePoint to) {
|
||||
super(logicalTimePoint, author, pPassId, mappedTo, device, from, to);
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = -1494030544804758753L;
|
||||
|
||||
@Override
|
||||
public void accept(RaceLogEventVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.tracking.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class RaceLogDeviceMarkMappingEventImpl extends AbstractRaceLogDeviceMappingEventImpl<Mark> implements
|
||||
RaceLogDeviceMarkMappingEvent {
|
||||
private static final long serialVersionUID = -7223543830755457196L;
|
||||
|
||||
public RaceLogDeviceMarkMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint,
|
||||
AbstractLogEventAuthor author, Serializable pId, int pPassId, Mark mappedTo, DeviceIdentifier device,
|
||||
TimePoint from, TimePoint to) {
|
||||
super(createdAt, logicalTimePoint, author, pId, pPassId, mappedTo, device, from, to);
|
||||
}
|
||||
|
||||
public RaceLogDeviceMarkMappingEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId,
|
||||
Mark mappedTo, DeviceIdentifier device, TimePoint from, TimePoint to) {
|
||||
super(logicalTimePoint, author, pPassId, mappedTo, device, from, to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(RaceLogEventVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.tracking.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class RaceLogUseCompetitorsFromRaceLogEventImpl extends RaceLogEventImpl implements
|
||||
RaceLogUseCompetitorsFromRaceLogEvent {
|
||||
private static final long serialVersionUID = -5114645637316367845L;
|
||||
|
||||
public RaceLogUseCompetitorsFromRaceLogEventImpl(TimePoint createdAt, AbstractLogEventAuthor author,
|
||||
TimePoint logicalTimePoint, Serializable id, int passId)
|
||||
throws IllegalArgumentException {
|
||||
super(createdAt, logicalTimePoint, author, id, null, passId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "This RaceLog uses the competitors registered on the RaceLog instead of the competitors on the RegattaLog";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(RaceLogEventVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
+3
@@ -1,6 +1,7 @@
|
||||
package com.sap.sailing.domain.abstractlog.regatta;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent;
|
||||
@@ -22,4 +23,6 @@ public interface RegattaLogEventVisitor {
|
||||
void visit(RegattaLogSetCompetitorTimeOnTimeFactorEvent event);
|
||||
|
||||
void visit(RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent event);
|
||||
|
||||
void visit(RegattaLogDefineMarkEvent event);
|
||||
}
|
||||
|
||||
+21
-5
@@ -1,10 +1,26 @@
|
||||
package com.sap.sailing.domain.abstractlog.regatta.events;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.Revokable;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.CloseOpenEndedDeviceMappingEvent;
|
||||
|
||||
public interface RegattaLogCloseOpenEndedDeviceMappingEvent extends RegattaLogEvent,
|
||||
CloseOpenEndedDeviceMappingEvent<RegattaLogEventVisitor> {
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
/**
|
||||
* Closes the time range of a {@link RegattaLogDeviceMappingEvent}. This means that the {@link #getClosingTimePoint() timepoint} provided
|
||||
* by this event is substituted for the missing timepoint in the {@code DeviceMappingEvent} it refers to.
|
||||
* @author Fredrik Teschke
|
||||
*
|
||||
*/
|
||||
public interface RegattaLogCloseOpenEndedDeviceMappingEvent extends RegattaLogEvent, Revokable {
|
||||
/**
|
||||
* Returns the timepoint that shall substitute the missing one in the corresponding {@link RegattaLogDeviceMappingEvent}.
|
||||
*/
|
||||
TimePoint getClosingTimePoint();
|
||||
|
||||
/**
|
||||
* Returns the {@code id} of the event for which this event provides the closing timepoint.
|
||||
* @return
|
||||
*/
|
||||
Serializable getDeviceMappingEventId();
|
||||
}
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.sap.sailing.domain.abstractlog.regatta.events;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
|
||||
/**
|
||||
* Defines a mark, that can then be used to build a course.
|
||||
*
|
||||
*/
|
||||
public interface RegattaLogDefineMarkEvent extends RegattaLogEvent {
|
||||
Mark getMark();
|
||||
}
|
||||
+7
-10
@@ -1,10 +1,7 @@
|
||||
package com.sap.sailing.domain.abstractlog.regatta.events;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.DeviceCompetitorMappingEvent;
|
||||
|
||||
public interface RegattaLogDeviceCompetitorMappingEvent extends RegattaLogEvent,
|
||||
DeviceCompetitorMappingEvent<RegattaLogEventVisitor> {
|
||||
|
||||
}
|
||||
package com.sap.sailing.domain.abstractlog.regatta.events;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
|
||||
public interface RegattaLogDeviceCompetitorMappingEvent extends RegattaLogDeviceMappingEvent<Competitor> {
|
||||
|
||||
}
|
||||
|
||||
+6
-6
@@ -1,8 +1,8 @@
|
||||
package com.sap.sailing.domain.abstractlog.shared.events;
|
||||
package com.sap.sailing.domain.abstractlog.regatta.events;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.Revokable;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogDefinedMarkFinder;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDefinedMarkAnalyzer;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
@@ -17,12 +17,12 @@ import com.sap.sse.common.WithID;
|
||||
* as the semantics of somehow later limiting this range would become unclear
|
||||
* <p>
|
||||
* If one end of the time range enclosed by {@link #getFrom()} and {@link #getTo()} is open, this can be closed
|
||||
* by a {@link CloseOpenEndedDeviceMappingEvent}.
|
||||
* by a {@link RegattaLogCloseOpenEndedDeviceMappingEvent}.
|
||||
*
|
||||
* @see RaceLogDefinedMarkFinder for rules by which {@link DeviceMapping}s are derived from these events.
|
||||
* @see RegattaLogDefinedMarkAnalyzer for rules by which {@link DeviceMapping}s are derived from these events.
|
||||
* @author Fredrik Teschke
|
||||
*/
|
||||
public interface DeviceMappingEvent<VisitorT, ItemType extends WithID> extends AbstractLogEvent<VisitorT>, Revokable {
|
||||
public interface RegattaLogDeviceMappingEvent<ItemType extends WithID> extends RegattaLogEvent, Revokable {
|
||||
ItemType getMappedTo();
|
||||
DeviceIdentifier getDevice();
|
||||
|
||||
+6
-6
@@ -1,16 +1,16 @@
|
||||
package com.sap.sailing.domain.abstractlog.shared.events.impl;
|
||||
package com.sap.sailing.domain.abstractlog.regatta.events;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.impl.AbstractLogEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.DeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.WithID;
|
||||
|
||||
public abstract class AbstractDeviceMappingEventImpl<VisitorT, ItemType extends WithID> extends AbstractLogEventImpl<VisitorT> implements
|
||||
DeviceMappingEvent<VisitorT, ItemType> {
|
||||
public abstract class RegattaLogDeviceMappingEventImpl<ItemType extends WithID> extends AbstractLogEventImpl<RegattaLogEventVisitor> implements
|
||||
RegattaLogDeviceMappingEvent<ItemType> {
|
||||
private static final long serialVersionUID = -8439653251231710356L;
|
||||
|
||||
private final ItemType mappedTo;
|
||||
@@ -18,7 +18,7 @@ DeviceMappingEvent<VisitorT, ItemType> {
|
||||
private final TimePoint from;
|
||||
private final TimePoint to;
|
||||
|
||||
public AbstractDeviceMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint,
|
||||
public RegattaLogDeviceMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint,
|
||||
AbstractLogEventAuthor author, Serializable id, ItemType mappedTo,
|
||||
DeviceIdentifier device, TimePoint from, TimePoint to) {
|
||||
super(createdAt, logicalTimePoint, author, id);
|
||||
@@ -28,7 +28,7 @@ DeviceMappingEvent<VisitorT, ItemType> {
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
public AbstractDeviceMappingEventImpl(TimePoint logicalTimePoint,
|
||||
public RegattaLogDeviceMappingEventImpl(TimePoint logicalTimePoint,
|
||||
AbstractLogEventAuthor author, ItemType mappedTo,
|
||||
DeviceIdentifier device, TimePoint from, TimePoint to) {
|
||||
this(now(), logicalTimePoint, author, randId(), mappedTo, device, from, to);
|
||||
+9
-10
@@ -1,10 +1,9 @@
|
||||
package com.sap.sailing.domain.abstractlog.regatta.events;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.DeviceMarkMappingEvent;
|
||||
|
||||
public interface RegattaLogDeviceMarkMappingEvent extends RegattaLogEvent,
|
||||
DeviceMarkMappingEvent<RegattaLogEventVisitor> {
|
||||
|
||||
}
|
||||
package com.sap.sailing.domain.abstractlog.regatta.events;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
|
||||
|
||||
public interface RegattaLogDeviceMarkMappingEvent extends RegattaLogDeviceMappingEvent<Mark>, RegattaLogEvent {
|
||||
|
||||
}
|
||||
|
||||
+31
-13
@@ -3,25 +3,43 @@ package com.sap.sailing.domain.abstractlog.regatta.events.impl;
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.impl.AbstractLogEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.impl.BaseCloseOpenEndedDeviceMappingEventImpl;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class RegattaLogCloseOpenEndedDeviceMappingEventImpl extends BaseCloseOpenEndedDeviceMappingEventImpl<RegattaLogEventVisitor>
|
||||
implements RegattaLogCloseOpenEndedDeviceMappingEvent {
|
||||
public class RegattaLogCloseOpenEndedDeviceMappingEventImpl extends AbstractLogEventImpl<RegattaLogEventVisitor>
|
||||
implements RegattaLogCloseOpenEndedDeviceMappingEvent {
|
||||
private static final long serialVersionUID = -5114645637316367845L;
|
||||
|
||||
public RegattaLogCloseOpenEndedDeviceMappingEventImpl(TimePoint createdAt, AbstractLogEventAuthor author,
|
||||
TimePoint logicalTimePoint, Serializable id, Serializable deviceMappingEventId,
|
||||
TimePoint closingTimePoint) {
|
||||
super(createdAt, logicalTimePoint, author, id, deviceMappingEventId, closingTimePoint);
|
||||
|
||||
private final Serializable deviceMappingEventId;
|
||||
private final TimePoint closingTimePoint;
|
||||
|
||||
public RegattaLogCloseOpenEndedDeviceMappingEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint,
|
||||
Serializable pId, Serializable deviceMappingEventId, TimePoint closingTimePoint) {
|
||||
super(createdAt, logicalTimePoint, author, pId);
|
||||
this.deviceMappingEventId = deviceMappingEventId;
|
||||
this.closingTimePoint = closingTimePoint;
|
||||
}
|
||||
|
||||
public RegattaLogCloseOpenEndedDeviceMappingEventImpl(AbstractLogEventAuthor author,
|
||||
TimePoint logicalTimePoint, Serializable deviceMappingEventId,
|
||||
TimePoint closingTimePoint) {
|
||||
super(logicalTimePoint, author, deviceMappingEventId, closingTimePoint);
|
||||
|
||||
public RegattaLogCloseOpenEndedDeviceMappingEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author,
|
||||
Serializable deviceMappingEventId, TimePoint closingTimePoint) {
|
||||
this( now(), author, logicalTimePoint, randId(), deviceMappingEventId, closingTimePoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getDeviceMappingEventId() {
|
||||
return deviceMappingEventId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimePoint getClosingTimePoint() {
|
||||
return closingTimePoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortInfo() {
|
||||
return "closing mapping (id: " + deviceMappingEventId + ") at " + closingTimePoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.sap.sailing.domain.abstractlog.regatta.events.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.impl.AbstractLogEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class RegattaLogDefineMarkEventImpl extends AbstractLogEventImpl<RegattaLogEventVisitor> implements RegattaLogDefineMarkEvent {
|
||||
private static final long serialVersionUID = -5114645637316367845L;
|
||||
|
||||
protected final Mark mark;
|
||||
|
||||
public RegattaLogDefineMarkEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint,
|
||||
Serializable pId, Mark mark) {
|
||||
super(createdAt, logicalTimePoint, author, pId);
|
||||
this.mark = mark;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(RegattaLogEventVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mark getMark() {
|
||||
return mark;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortInfo() {
|
||||
return "mark: "+mark.toString();
|
||||
}
|
||||
|
||||
}
|
||||
+4
-6
@@ -5,13 +5,12 @@ import java.io.Serializable;
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.impl.AbstractDeviceMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEventImpl;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class RegattaLogDeviceCompetitorMappingEventImpl extends
|
||||
AbstractDeviceMappingEventImpl<RegattaLogEventVisitor, Competitor> implements
|
||||
public class RegattaLogDeviceCompetitorMappingEventImpl extends RegattaLogDeviceMappingEventImpl<Competitor> implements
|
||||
RegattaLogDeviceCompetitorMappingEvent {
|
||||
public RegattaLogDeviceCompetitorMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint,
|
||||
AbstractLogEventAuthor author, Serializable pId, Competitor mappedTo, DeviceIdentifier device,
|
||||
@@ -19,9 +18,8 @@ public class RegattaLogDeviceCompetitorMappingEventImpl extends
|
||||
super(createdAt, logicalTimePoint, author, pId, mappedTo, device, from, to);
|
||||
}
|
||||
|
||||
public RegattaLogDeviceCompetitorMappingEventImpl(TimePoint logicalTimePoint,
|
||||
AbstractLogEventAuthor author, Competitor mappedTo, DeviceIdentifier device,
|
||||
TimePoint from, TimePoint to) {
|
||||
public RegattaLogDeviceCompetitorMappingEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author,
|
||||
Competitor mappedTo, DeviceIdentifier device, TimePoint from, TimePoint to) {
|
||||
super(logicalTimePoint, author, mappedTo, device, from, to);
|
||||
}
|
||||
|
||||
|
||||
+6
-5
@@ -4,18 +4,19 @@ import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.impl.AbstractDeviceMappingEventImpl;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class RegattaLogDeviceMarkMappingEventImpl extends AbstractDeviceMappingEventImpl<RegattaLogEventVisitor, Mark>
|
||||
implements RegattaLogDeviceMarkMappingEvent {
|
||||
public class RegattaLogDeviceMarkMappingEventImpl extends RegattaLogDeviceMappingEventImpl<Mark> implements
|
||||
RegattaLogDeviceMarkMappingEvent {
|
||||
private static final long serialVersionUID = -7223543830755457196L;
|
||||
|
||||
public RegattaLogDeviceMarkMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author,
|
||||
Serializable pId, Mark mappedTo, DeviceIdentifier device, TimePoint from, TimePoint to) {
|
||||
public RegattaLogDeviceMarkMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint,
|
||||
AbstractLogEventAuthor author, Serializable pId, Mark mappedTo, DeviceIdentifier device, TimePoint from,
|
||||
TimePoint to) {
|
||||
super(createdAt, logicalTimePoint, author, pId, mappedTo, device, from, to);
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.abstractlog.regatta.impl;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent;
|
||||
@@ -39,4 +40,7 @@ public class BaseRegattaLogEventVisitor implements RegattaLogEventVisitor {
|
||||
public void visit(RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent event) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RegattaLogDefineMarkEvent event) {
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.abstractlog.regatta.impl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent;
|
||||
@@ -47,4 +48,9 @@ public abstract class RegattaLogEventListener implements RegattaLogEventVisitor
|
||||
public void visit(RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent event) {
|
||||
eventAdded(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RegattaLogDefineMarkEvent event) {
|
||||
eventAdded(event);
|
||||
}
|
||||
}
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
||||
|
||||
public abstract class RegattaLogAnalyzer<ResultType> extends BaseLogAnalyzer
|
||||
<RegattaLog, RegattaLogEvent, RegattaLogEventVisitor, ResultType> {
|
||||
|
||||
public RegattaLogAnalyzer(RegattaLog raceLog) {
|
||||
super(raceLog);
|
||||
}
|
||||
|
||||
protected Iterable<RegattaLogEvent> getPassEvents() {
|
||||
return log.getFixes();
|
||||
}
|
||||
|
||||
protected Iterable<RegattaLogEvent> getPassEventsDescending() {
|
||||
return log.getFixesDescending();
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.impl.AllEventsOfTypeFinder;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
|
||||
public class RegattaLogDefinedMarkAnalyzer extends RegattaLogAnalyzer<Collection<Mark>> {
|
||||
|
||||
public RegattaLogDefinedMarkAnalyzer(RegattaLog log) {
|
||||
super(log);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Mark> performAnalysis() {
|
||||
List<Mark> result = new ArrayList<Mark>();
|
||||
List<RegattaLogEvent> defineMarkEvents = new AllEventsOfTypeFinder<>(log, true, RegattaLogDefineMarkEvent.class)
|
||||
.analyze();
|
||||
|
||||
for (RegattaLogEvent event : defineMarkEvents) {
|
||||
RegattaLogDefineMarkEvent dME = (RegattaLogDefineMarkEvent) event;
|
||||
result.add(dME.getMark());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
|
||||
public class RegattaLogDeviceCompetitorMappingFinder extends RegattaLogDeviceMappingFinder<Competitor> {
|
||||
|
||||
public RegattaLogDeviceCompetitorMappingFinder(RegattaLog log) {
|
||||
super(log);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValidMapping(RegattaLogDeviceMappingEvent<?> mapping) {
|
||||
return mapping instanceof RegattaLogDeviceCompetitorMappingEvent;
|
||||
}
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
package com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
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.events.RegattaLogCloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceMapping;
|
||||
import com.sap.sailing.domain.racelogtracking.impl.DeviceMappingImpl;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.TimeRange;
|
||||
import com.sap.sse.common.WithID;
|
||||
import com.sap.sse.common.impl.TimeRangeImpl;
|
||||
|
||||
/**
|
||||
* Extracts the {@link DeviceMapping}s with the appropriate {@link TimeRange}s from the {@link RaceLog}.
|
||||
* Based on the {@link RegattaLogDeviceMappingEvent}s found in the {@code RaceLog} for the tracked {@code items}
|
||||
* ({@code Competitor}s and {@code Marks}), the actual mappings are created.
|
||||
* <p>
|
||||
* Mappings can be defined with an open-ended time range (e.g. track this from now on), which should then be
|
||||
* closed by a corresponding {@link RegattaLogCloseOpenEndedDeviceMappingEvent}.
|
||||
* <p>
|
||||
* The process of removing conflicts between mappings to ensure that only one mapping was active for
|
||||
* one tracked item has been removed. Instead, every {@code DeviceMappingEvent} now results directly in one
|
||||
* {@code DeviceMapping}, the only changes being introduced by closing open time ranges in cases where an
|
||||
* according {@code CloseOpenEndedDeviceMappingEvent} exists.
|
||||
*/
|
||||
public class RegattaLogDeviceMappingFinder<ItemT extends WithID> extends RegattaLogAnalyzer<Map<ItemT, List<DeviceMapping<ItemT>>>> {
|
||||
private static Logger logger = Logger.getLogger(RegattaLogDeviceMappingFinder.class.getName());
|
||||
|
||||
public RegattaLogDeviceMappingFinder(RegattaLog log) {
|
||||
super(log);
|
||||
}
|
||||
|
||||
protected boolean isValidMapping(RegattaLogDeviceMappingEvent<?> mapping) {
|
||||
return mapping instanceof RegattaLogDeviceMappingEvent;
|
||||
}
|
||||
|
||||
protected DeviceMapping<ItemT> createMapping(DeviceIdentifier device, ItemT item,
|
||||
TimePoint from, TimePoint to, Serializable originalEventId) {
|
||||
return new DeviceMappingImpl<ItemT>(item, device, new TimeRangeImpl(from, to),
|
||||
Collections.singletonList(originalEventId));
|
||||
}
|
||||
|
||||
private <T, U> List<U> getItemSet(Map<T, List<U>> map, T item) {
|
||||
List<U> list = map.get(item);
|
||||
if (list == null) {
|
||||
list = new ArrayList<U>();
|
||||
map.put(item, list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@Override
|
||||
protected Map<ItemT, List<DeviceMapping<ItemT>>> performAnalysis() {
|
||||
Map<ItemT, List<RegattaLogDeviceMappingEvent<ItemT>>> events = new HashMap<ItemT, List<RegattaLogDeviceMappingEvent<ItemT>>>();
|
||||
Map<ItemT, List<DeviceMapping<ItemT>>> mappings = new HashMap<ItemT, List<DeviceMapping<ItemT>>>();
|
||||
Map<Serializable, RegattaLogCloseOpenEndedDeviceMappingEvent> closingEvents = new HashMap<Serializable, RegattaLogCloseOpenEndedDeviceMappingEvent>();
|
||||
|
||||
for (RegattaLogEvent e : getLog().getUnrevokedEvents()) {
|
||||
if (e instanceof RegattaLogDeviceMappingEvent && isValidMapping(((RegattaLogDeviceMappingEvent<?>) e))) {
|
||||
@SuppressWarnings("unchecked")
|
||||
RegattaLogDeviceMappingEvent<ItemT> mappingEvent = (RegattaLogDeviceMappingEvent<ItemT>) e;
|
||||
getItemSet(events, mappingEvent.getMappedTo()).add(mappingEvent);
|
||||
} else if (e instanceof RegattaLogCloseOpenEndedDeviceMappingEvent) {
|
||||
//a higher priority closing events for the same mapping event overwrites the lower priority one
|
||||
RegattaLogCloseOpenEndedDeviceMappingEvent closingEvent = (RegattaLogCloseOpenEndedDeviceMappingEvent) e;
|
||||
closingEvents.put(closingEvent.getDeviceMappingEventId(), closingEvent);
|
||||
}
|
||||
}
|
||||
for (ItemT item : events.keySet()) {
|
||||
mappings.put(item, closeOpenRanges(events.get(item), item, closingEvents));
|
||||
}
|
||||
return mappings;
|
||||
}
|
||||
|
||||
private List<DeviceMapping<ItemT>> closeOpenRanges(List<RegattaLogDeviceMappingEvent<ItemT>> events, ItemT item,
|
||||
Map<Serializable, RegattaLogCloseOpenEndedDeviceMappingEvent> closingEvents) {
|
||||
List<DeviceMapping<ItemT>> result = new ArrayList<DeviceMapping<ItemT>>();
|
||||
for (RegattaLogDeviceMappingEvent<ItemT> event : events) {
|
||||
TimePoint from = event.getFrom();
|
||||
TimePoint to = event.getTo();
|
||||
TimePoint closingTimePoint = closingEvents.containsKey(event.getId()) ? closingEvents.get(event.getId())
|
||||
.getClosingTimePoint() : null;
|
||||
if (from == null) {
|
||||
logger.severe("No start time set for DeviceMappingEvent with ID: " + event.getId());
|
||||
}
|
||||
if (to == null) {
|
||||
to = closingTimePoint;
|
||||
}
|
||||
result.add(createMapping(event.getDevice(), item, from, to, event.getId()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
|
||||
public class RegattaLogDeviceMarkMappingFinder extends RegattaLogDeviceMappingFinder<Mark> {
|
||||
|
||||
public RegattaLogDeviceMarkMappingFinder(RegattaLog log) {
|
||||
super(log);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValidMapping(RegattaLogDeviceMappingEvent<?> mapping) {
|
||||
return mapping instanceof RegattaLogDeviceMarkMappingEvent;
|
||||
}
|
||||
}
|
||||
+37
-11
@@ -1,29 +1,55 @@
|
||||
package com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
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.RegattaLogCloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogCloseOpenEndedDeviceMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.OpenEndedDeviceMappingCloser;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceMapping;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
/**
|
||||
* Generates events that close the events that are responsible for the {@link #mapping} that is passed to the
|
||||
* constructor.
|
||||
*
|
||||
* @author Fredrik Teschke
|
||||
*
|
||||
*/
|
||||
public class RegattaLogOpenEndedDeviceMappingCloser extends
|
||||
OpenEndedDeviceMappingCloser<RegattaLog, RegattaLogEvent, RegattaLogEventVisitor, RegattaLogCloseOpenEndedDeviceMappingEvent> {
|
||||
RegattaLogAnalyzer<List<RegattaLogCloseOpenEndedDeviceMappingEvent>> {
|
||||
private final DeviceMapping<?> mapping;
|
||||
protected final AbstractLogEventAuthor author;
|
||||
protected final TimePoint closingTimePoint;
|
||||
|
||||
public RegattaLogOpenEndedDeviceMappingCloser(RegattaLog log, DeviceMapping<?> mapping, AbstractLogEventAuthor author,
|
||||
TimePoint closingTimePoint) {
|
||||
super(log, mapping, author, closingTimePoint);
|
||||
public RegattaLogOpenEndedDeviceMappingCloser(RegattaLog log, DeviceMapping<?> mapping,
|
||||
AbstractLogEventAuthor author, TimePoint closingTimePoint) {
|
||||
super(log);
|
||||
this.mapping = mapping;
|
||||
this.author = author;
|
||||
this.closingTimePoint = closingTimePoint;
|
||||
}
|
||||
|
||||
protected RegattaLogCloseOpenEndedDeviceMappingEvent createCloseEvent(TimePoint logicalTimePoint,
|
||||
Serializable eventToCloseId) {
|
||||
return new RegattaLogCloseOpenEndedDeviceMappingEventImpl(logicalTimePoint, author, eventToCloseId,
|
||||
closingTimePoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RegattaLogCloseOpenEndedDeviceMappingEvent createCloseEvent(TimePoint logicalTimePoint,
|
||||
Serializable eventToCloseId) {
|
||||
return new RegattaLogCloseOpenEndedDeviceMappingEventImpl(author,
|
||||
logicalTimePoint, eventToCloseId, closingTimePoint);
|
||||
protected List<RegattaLogCloseOpenEndedDeviceMappingEvent> performAnalysis() {
|
||||
List<RegattaLogCloseOpenEndedDeviceMappingEvent> result = new ArrayList<RegattaLogCloseOpenEndedDeviceMappingEvent>();
|
||||
|
||||
for (Serializable eventId : mapping.getOriginalRaceLogEventIds()) {
|
||||
RegattaLogDeviceMappingEvent<?> event = (RegattaLogDeviceMappingEvent<?>) getLog().getEventById(eventId);
|
||||
if (event.getFrom() == null || event.getTo() == null) {
|
||||
result.add(createCloseEvent(MillisecondsTimePoint.now(), event.getId()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.sap.sailing.domain.abstractlog.shared.analyzing;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLog;
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorEvent;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
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.
|
||||
*
|
||||
* @author Jan Broß
|
||||
*
|
||||
*/
|
||||
public class CompetitorDeregistrator<LogT extends AbstractLog<EventT, VisitorT>, EventT extends AbstractLogEvent<VisitorT>, VisitorT>
|
||||
extends BaseLogAnalyzer<LogT, EventT, VisitorT, Void> {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CompetitorDeregistrator.class.getName());
|
||||
protected final Iterable<Competitor> competitorsToDeregister;
|
||||
private AbstractLogEventAuthor eventAuthor;
|
||||
|
||||
public CompetitorDeregistrator(LogT log, Iterable<Competitor> competitorsToDeregister, AbstractLogEventAuthor eventAuthor) {
|
||||
super(log);
|
||||
this.competitorsToDeregister = competitorsToDeregister;
|
||||
this.eventAuthor = eventAuthor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void performAnalysis() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package com.sap.sailing.domain.abstractlog.shared.analyzing;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLog;
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogRegisteredCompetitorsAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RegisteredCompetitorsAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorEvent;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
|
||||
/**
|
||||
* This class searches for RegisterCompetitorEvents in the given log.
|
||||
*
|
||||
* TLDR: It's likely, that you shouldn't use this, but you might want to use {@link RegisteredCompetitorsAnalyzer} or {@link RaceLogRegisteredCompetitorsAnalyzer}
|
||||
*
|
||||
* Note that solemnly analyzing a certain race or RegattaLog my not lead the correct registered competitors for the race
|
||||
* corresponding to the RaceLog/the races corresponding to the RegattaLog.
|
||||
*
|
||||
* This is the case as by default the competitors registered on the RegattaLog are used for each race of the regatta
|
||||
* ignoring the ones in the RaceLog (if present). The RaceLog may override this behavior with the
|
||||
* {@link RaceLogUseCompetitorsFromRaceLogEvent}. Is an event of this type present, the competitors written into the
|
||||
* RaceLog are used instead of the competitors in the RegattaLog.
|
||||
*
|
||||
*/
|
||||
public class CompetitorsInLogAnalyzer<LogT extends AbstractLog<EventT, VisitorT>, EventT extends AbstractLogEvent<VisitorT>, VisitorT>
|
||||
extends BaseLogAnalyzer<LogT, EventT, VisitorT, Set<Competitor>> {
|
||||
|
||||
public CompetitorsInLogAnalyzer(LogT log) {
|
||||
super(log);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<Competitor> performAnalysis() {
|
||||
Set<Competitor> result = new HashSet<Competitor>();
|
||||
|
||||
for (EventT event : getLog().getUnrevokedEvents()) {
|
||||
if (event instanceof RegisterCompetitorEvent) {
|
||||
result.add(((RegisterCompetitorEvent<?>) event).getCompetitor());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.shared.analyzing;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLog;
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.LogAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.MultiLogAnalyzer.AnalyzerFactory;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.DeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.DeviceMappingEvent;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceMapping;
|
||||
|
||||
public class DeviceCompetitorMappingFinder<LogT extends AbstractLog<EventT, VisitorT>, EventT extends AbstractLogEvent<VisitorT>, VisitorT>
|
||||
extends DeviceMappingFinder<LogT, EventT, VisitorT, Competitor> {
|
||||
|
||||
public static class Factory implements AnalyzerFactory<Map<Competitor, List<DeviceMapping<Competitor>>>> {
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Override
|
||||
public LogAnalyzer<Map<Competitor, List<DeviceMapping<Competitor>>>> createAnalyzer(AbstractLog<?, ?> log) {
|
||||
return new DeviceCompetitorMappingFinder(log);
|
||||
}
|
||||
}
|
||||
|
||||
public DeviceCompetitorMappingFinder(LogT log) {
|
||||
super(log);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValidMapping(DeviceMappingEvent<?, ?> mapping) {
|
||||
return mapping instanceof DeviceCompetitorMappingEvent;
|
||||
}
|
||||
}
|
||||
-117
@@ -1,117 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.shared.analyzing;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLog;
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.LogAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.MultiLogAnalyzer.AnalyzerFactory;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.CloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.DeviceMappingEvent;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceMapping;
|
||||
import com.sap.sailing.domain.racelogtracking.impl.DeviceMappingImpl;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.TimeRange;
|
||||
import com.sap.sse.common.WithID;
|
||||
import com.sap.sse.common.impl.TimeRangeImpl;
|
||||
|
||||
/**
|
||||
* Extracts the {@link DeviceMapping}s with the appropriate {@link TimeRange}s from the {@link RaceLog}.
|
||||
* Based on the {@link DeviceMappingEvent}s found in the {@code RaceLog} for the tracked {@code items}
|
||||
* ({@code Competitor}s and {@code Marks}), the actual mappings are created.
|
||||
* <p>
|
||||
* Mappings can be defined with an open-ended time range (e.g. track this from now on), which should then be
|
||||
* closed by a corresponding {@link CloseOpenEndedDeviceMappingEvent}.
|
||||
* <p>
|
||||
* The process of removing conflicts between mappings to ensure that only one mapping was active for
|
||||
* one tracked item has been removed. Instead, every {@code DeviceMappingEvent} now results directly in one
|
||||
* {@code DeviceMapping}, the only changes being introduced by closing open time ranges in cases where an
|
||||
* according {@code CloseOpenEndedDeviceMappingEvent} exists.
|
||||
*/
|
||||
public class DeviceMappingFinder<LogT extends AbstractLog<EventT, VisitorT>, EventT extends AbstractLogEvent<VisitorT>,
|
||||
VisitorT, ItemT extends WithID> extends BaseLogAnalyzer<LogT, EventT, VisitorT, Map<ItemT, List<DeviceMapping<ItemT>>>> {
|
||||
|
||||
public static class Factory<ItemT extends WithID> implements AnalyzerFactory<Map<ItemT, List<DeviceMapping<ItemT>>>> {
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Override
|
||||
public LogAnalyzer<Map<ItemT, List<DeviceMapping<ItemT>>>> createAnalyzer(AbstractLog<?, ?> log) {
|
||||
return new DeviceMappingFinder(log);
|
||||
}
|
||||
}
|
||||
|
||||
private static Logger logger = Logger.getLogger(DeviceMappingFinder.class.getName());
|
||||
|
||||
public DeviceMappingFinder(LogT log) {
|
||||
super(log);
|
||||
}
|
||||
|
||||
protected boolean isValidMapping(DeviceMappingEvent<?, ?> mapping) {
|
||||
return mapping instanceof DeviceMappingEvent;
|
||||
}
|
||||
|
||||
protected DeviceMapping<ItemT> getMapping(DeviceIdentifier device, ItemT item,
|
||||
TimePoint from, TimePoint to, Serializable originalEventId) {
|
||||
return new DeviceMappingImpl<ItemT>(item, device, new TimeRangeImpl(from, to),
|
||||
Collections.singletonList(originalEventId));
|
||||
}
|
||||
|
||||
private <T, U> List<U> getItemSet(Map<T, List<U>> map, T item) {
|
||||
List<U> list = map.get(item);
|
||||
if (list == null) {
|
||||
list = new ArrayList<U>();
|
||||
map.put(item, list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@Override
|
||||
protected Map<ItemT, List<DeviceMapping<ItemT>>> performAnalysis() {
|
||||
Map<ItemT, List<DeviceMappingEvent<?, ItemT>>> events = new HashMap<ItemT, List<DeviceMappingEvent<?, ItemT>>>();
|
||||
Map<ItemT, List<DeviceMapping<ItemT>>> mappings = new HashMap<ItemT, List<DeviceMapping<ItemT>>>();
|
||||
Map<Serializable, CloseOpenEndedDeviceMappingEvent<?>> closingEvents = new HashMap<Serializable, CloseOpenEndedDeviceMappingEvent<?>>();
|
||||
|
||||
for (EventT e : getLog().getUnrevokedEvents()) {
|
||||
if (e instanceof DeviceMappingEvent && isValidMapping(((DeviceMappingEvent<?, ?>) e))) {
|
||||
@SuppressWarnings("unchecked")
|
||||
DeviceMappingEvent<?, ItemT> mappingEvent = (DeviceMappingEvent<?, ItemT>) e;
|
||||
getItemSet(events, mappingEvent.getMappedTo()).add(mappingEvent);
|
||||
} else if (e instanceof CloseOpenEndedDeviceMappingEvent) {
|
||||
//a higher priority closing events for the same mapping event overwrites the lower priority one
|
||||
CloseOpenEndedDeviceMappingEvent<?> closingEvent = (CloseOpenEndedDeviceMappingEvent<?>) e;
|
||||
closingEvents.put(closingEvent.getDeviceMappingEventId(), closingEvent);
|
||||
}
|
||||
}
|
||||
|
||||
for (ItemT item : events.keySet()) {
|
||||
mappings.put(item, closeOpenRanges(events.get(item), item, closingEvents));
|
||||
}
|
||||
|
||||
return mappings;
|
||||
}
|
||||
|
||||
private List<DeviceMapping<ItemT>> closeOpenRanges(List<DeviceMappingEvent<?, ItemT>> events, ItemT item,
|
||||
Map<Serializable, CloseOpenEndedDeviceMappingEvent<?>> closingEvents) {
|
||||
List<DeviceMapping<ItemT>> result = new ArrayList<DeviceMapping<ItemT>>();
|
||||
|
||||
for (DeviceMappingEvent<?, ItemT> event : events) {
|
||||
TimePoint from = event.getFrom();
|
||||
TimePoint to = event.getTo();
|
||||
TimePoint closingTimePoint = closingEvents.containsKey(event.getId()) ?
|
||||
closingEvents.get(event.getId()).getClosingTimePoint() : null;
|
||||
if (from == null) logger.severe("No start time set for DeviceMappingEvent with ID: "+event.getId());
|
||||
if (to == null) to = closingTimePoint;
|
||||
|
||||
result.add(getMapping(event.getDevice(), item, from, to, event.getId()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.shared.analyzing;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLog;
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.LogAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.MultiLogAnalyzer.AnalyzerFactory;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.DeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.DeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceMapping;
|
||||
|
||||
public class DeviceMarkMappingFinder<LogT extends AbstractLog<EventT, VisitorT>, EventT extends AbstractLogEvent<VisitorT>, VisitorT>
|
||||
extends DeviceMappingFinder<LogT, EventT, VisitorT, Mark> {
|
||||
|
||||
public static class Factory implements AnalyzerFactory<Map<Mark, List<DeviceMapping<Mark>>>> {
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Override
|
||||
public LogAnalyzer<Map<Mark, List<DeviceMapping<Mark>>>> createAnalyzer(AbstractLog<?, ?> log) {
|
||||
return new DeviceMarkMappingFinder(log);
|
||||
}
|
||||
}
|
||||
|
||||
public DeviceMarkMappingFinder(LogT log) {
|
||||
super(log);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValidMapping(DeviceMappingEvent<?, ?> mapping) {
|
||||
return mapping instanceof DeviceMarkMappingEvent;
|
||||
}
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.shared.analyzing;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLog;
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.DeviceMappingEvent;
|
||||
import com.sap.sse.common.WithID;
|
||||
|
||||
public class LastPingMappingEventFinder <LogT extends AbstractLog<EventT, VisitorT>,
|
||||
EventT extends AbstractLogEvent<VisitorT>, VisitorT, ItemT extends WithID>
|
||||
extends BaseLogAnalyzer<LogT, EventT, VisitorT, DeviceMappingEvent<VisitorT, ItemT>> {
|
||||
private final WithID item;
|
||||
|
||||
public LastPingMappingEventFinder(LogT log, WithID forItem) {
|
||||
super(log);
|
||||
this.item = forItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DeviceMappingEvent<VisitorT, ItemT> performAnalysis() {
|
||||
for (EventT e : getLog().getUnrevokedEventsDescending()) {
|
||||
if (e instanceof DeviceMappingEvent) {
|
||||
DeviceMappingEvent<?, ?> mappingEvent = (DeviceMappingEvent<?, ?>) e;
|
||||
if (item.equals(mappingEvent.getMappedTo()) && mappingEvent.getFrom() != null &&
|
||||
mappingEvent.getTo() != null && mappingEvent.getFrom().equals(mappingEvent.getTo())) {
|
||||
@SuppressWarnings("unchecked")
|
||||
DeviceMappingEvent<VisitorT, ItemT> cast = (DeviceMappingEvent<VisitorT, ItemT>) mappingEvent;
|
||||
return cast;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.shared.analyzing;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLog;
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.CloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.DeviceMappingEvent;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceMapping;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
/**
|
||||
* Generates events that close the events that are responsible for the {@link #mapping}
|
||||
* that is passed to the constructor.
|
||||
* @author Fredrik Teschke
|
||||
*
|
||||
*/
|
||||
public abstract class OpenEndedDeviceMappingCloser<LogT extends AbstractLog<EventT, VisitorT>,
|
||||
EventT extends AbstractLogEvent<VisitorT>,VisitorT, CloseEventT extends CloseOpenEndedDeviceMappingEvent<VisitorT>>
|
||||
extends BaseLogAnalyzer<LogT, EventT, VisitorT, List<CloseEventT>> {
|
||||
private final DeviceMapping<?> mapping;
|
||||
protected final AbstractLogEventAuthor author;
|
||||
protected final TimePoint closingTimePoint;
|
||||
|
||||
public OpenEndedDeviceMappingCloser(LogT log, DeviceMapping<?> mapping, AbstractLogEventAuthor author,
|
||||
TimePoint closingTimePoint) {
|
||||
super(log);
|
||||
this.mapping = mapping;
|
||||
this.author = author;
|
||||
this.closingTimePoint = closingTimePoint;
|
||||
}
|
||||
|
||||
protected abstract CloseEventT createCloseEvent(TimePoint logicalTimePoint,
|
||||
Serializable eventToCloseId);
|
||||
|
||||
@Override
|
||||
protected List<CloseEventT> performAnalysis() {
|
||||
List<CloseEventT> result = new ArrayList<CloseEventT>();
|
||||
|
||||
for (Serializable eventId : mapping.getOriginalRaceLogEventIds()) {
|
||||
DeviceMappingEvent<?, ?> event = (DeviceMappingEvent<?, ?>) getLog().getEventById(eventId);
|
||||
if (event.getFrom() == null || event.getTo() == null) {
|
||||
result.add(createCloseEvent(MillisecondsTimePoint.now(), event.getId()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.shared.analyzing;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLog;
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.MultiLogAnalyzer.AnalyzerFactory;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorEvent;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
|
||||
/**
|
||||
* Uses the {@link RegisterCompetitorEvent}s in the {@link RaceLog} to determine the competitors registered for this
|
||||
* event.
|
||||
*
|
||||
* @author Fredrik Teschke
|
||||
*
|
||||
*/
|
||||
public class RegisteredCompetitorsAnalyzer<LogT extends AbstractLog<EventT, VisitorT>, EventT extends AbstractLogEvent<VisitorT>, VisitorT>
|
||||
extends BaseLogAnalyzer<LogT, EventT, VisitorT, Set<Competitor>> {
|
||||
|
||||
public static enum Factory implements AnalyzerFactory<Collection<Competitor>> {
|
||||
INSTANCE;
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Override
|
||||
public RegisteredCompetitorsAnalyzer createAnalyzer(AbstractLog<?, ?> log) {
|
||||
return new RegisteredCompetitorsAnalyzer(log);
|
||||
}
|
||||
}
|
||||
|
||||
public RegisteredCompetitorsAnalyzer(LogT log) {
|
||||
super(log);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<Competitor> performAnalysis() {
|
||||
Set<Competitor> result = new HashSet<Competitor>();
|
||||
|
||||
for (EventT event : getLog().getUnrevokedEvents()) {
|
||||
if (event instanceof RegisterCompetitorEvent) {
|
||||
result.add(((RegisterCompetitorEvent<?>) event).getCompetitor());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.shared.events;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.Revokable;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
/**
|
||||
* Closes the time range of a {@link DeviceMappingEvent}. This means that the {@link #getClosingTimePoint() timepoint} provided
|
||||
* by this event is substituted for the missing timepoint in the {@code DeviceMappingEvent} it refers to.
|
||||
* @author Fredrik Teschke
|
||||
*
|
||||
*/
|
||||
public interface CloseOpenEndedDeviceMappingEvent<VisitorT> extends AbstractLogEvent<VisitorT>, Revokable {
|
||||
/**
|
||||
* Returns the timepoint that shall substitute the missing one in the corresponding {@link DeviceMappingEvent}.
|
||||
*/
|
||||
TimePoint getClosingTimePoint();
|
||||
|
||||
/**
|
||||
* Returns the {@code id} of the event for which this event provides the closing timepoint.
|
||||
* @return
|
||||
*/
|
||||
Serializable getDeviceMappingEventId();
|
||||
}
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.shared.events;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
|
||||
public interface DeviceCompetitorMappingEvent<VisitorT> extends DeviceMappingEvent<VisitorT, Competitor> {
|
||||
|
||||
}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.shared.events;
|
||||
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
|
||||
|
||||
public interface DeviceMarkMappingEvent<VisitorT> extends DeviceMappingEvent<VisitorT, Mark> {
|
||||
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
package com.sap.sailing.domain.abstractlog.shared.events.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.impl.AbstractLogEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.CloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public abstract class BaseCloseOpenEndedDeviceMappingEventImpl<VisitorT> extends AbstractLogEventImpl<VisitorT>
|
||||
implements CloseOpenEndedDeviceMappingEvent<VisitorT> {
|
||||
private static final long serialVersionUID = -2401732623610224918L;
|
||||
|
||||
private final Serializable deviceMappingEventId;
|
||||
private final TimePoint closingTimePoint;
|
||||
|
||||
public BaseCloseOpenEndedDeviceMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint,
|
||||
AbstractLogEventAuthor author, Serializable pId, Serializable deviceMappingEventId, TimePoint closingTimePoint) {
|
||||
super(createdAt, logicalTimePoint, author, pId);
|
||||
this.deviceMappingEventId = deviceMappingEventId;
|
||||
this.closingTimePoint = closingTimePoint;
|
||||
}
|
||||
|
||||
public BaseCloseOpenEndedDeviceMappingEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author,
|
||||
Serializable deviceMappingEventId, TimePoint closingTimePoint) {
|
||||
this(now(), logicalTimePoint, author, randId(), deviceMappingEventId, closingTimePoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getDeviceMappingEventId() {
|
||||
return deviceMappingEventId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimePoint getClosingTimePoint() {
|
||||
return closingTimePoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortInfo() {
|
||||
return "closing mapping (id: " + deviceMappingEventId + ") at " + closingTimePoint;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -3,13 +3,13 @@ package com.sap.sailing.domain.racelogtracking;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.DeviceMappingFinder;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceMappingFinder;
|
||||
import com.sap.sse.common.TimeRange;
|
||||
import com.sap.sse.common.Timed;
|
||||
import com.sap.sse.common.WithID;
|
||||
|
||||
/**
|
||||
* @see DeviceMappingFinder {@code DeviceMappings} are derived from {@code DeviceMappingEvents}. The {@link Timed} interface
|
||||
* @see RegattaLogDeviceMappingFinder {@code DeviceMappings} are derived from {@code DeviceMappingEvents}. The {@link Timed} interface
|
||||
* is to be implemented as providing the {@link TimeRange#from()} time point as the answer to {@link Timed#getTimePoint()}.
|
||||
*
|
||||
* @author Fredrik Teschke
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.DeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceMapping;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
@@ -56,7 +56,7 @@ public class DeviceMappingImpl<ItemType extends WithID> implements DeviceMapping
|
||||
return timeRange.from();
|
||||
}
|
||||
|
||||
public static <T extends WithID> DeviceMapping<T> convertToDeviceMapping(DeviceMappingEvent<?, T> event) {
|
||||
public static <T extends WithID> DeviceMapping<T> convertToDeviceMapping(RegattaLogDeviceMappingEvent<T> event) {
|
||||
return new DeviceMappingImpl<T>(event.getMappedTo(), event.getDevice(), new TimeRangeImpl(event.getFrom(), event.getTo()),
|
||||
event.getId());
|
||||
}
|
||||
|
||||
+38
-12
@@ -21,6 +21,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRevokeEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsFromRaceLogEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl;
|
||||
@@ -107,7 +108,8 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard
|
||||
flexibleLeaderboard.addRaceColumn("R1", /* medalRace */ false);
|
||||
RaceLog raceLog = flexibleLeaderboard.getRacelog("R1", LeaderboardNameConstants.DEFAULT_FLEET_NAME);
|
||||
final int passId = 1;
|
||||
final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0);
|
||||
final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0);
|
||||
raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId));
|
||||
final Map<Competitor, RaceLogRegisterCompetitorEvent> competitorOnRaceLogRegistrationEvents = new HashMap<>();
|
||||
for (Competitor c : compLists[0]) {
|
||||
final RaceLogRegisterCompetitorEvent registerCompetitorEvent = new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), author, passId, c);
|
||||
@@ -164,26 +166,45 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleCompetitorListOnOneRaceLogAndRegattaLogInFlexibleLeaderboard() {
|
||||
public void testSimpleCompetitorListOnOneRaceLogAndRegattaLogInFlexibleLeaderboard() throws NotRevokableException {
|
||||
flexibleLeaderboard.addRaceColumn("R1", /* medalRace */ false);
|
||||
RegattaLog regattaLog = flexibleLeaderboard.getRegattaLog();
|
||||
for (Competitor c : compLists[0]) {
|
||||
regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), UUID.randomUUID(), c));
|
||||
}
|
||||
RaceLog raceLog = flexibleLeaderboard.getRacelog("R1", LeaderboardNameConstants.DEFAULT_FLEET_NAME);
|
||||
for (Competitor c : compLists[1]) {
|
||||
raceLog.add(new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), 1, c));
|
||||
final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0);
|
||||
int passId = 1;
|
||||
final RaceLogUseCompetitorsFromRaceLogEventImpl usesCompetitorsFromRaceLogEvent = new RaceLogUseCompetitorsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId);
|
||||
raceLog.add(usesCompetitorsFromRaceLogEvent);
|
||||
for (Competitor c : compLists[1]) {
|
||||
raceLog.add(new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), 1, c));
|
||||
}
|
||||
Set<Competitor> expected = new HashSet<>(compLists[0]);
|
||||
expected.addAll(compLists[1]);
|
||||
//expected are only the competitors in the RaceLog, because only one RaceColumn is
|
||||
//registered, which has the competitors registered in the RaceLog.
|
||||
assertRegattaAndRaceCompetitors(new HashSet<>(compLists[1]));
|
||||
// Now we revoke that the race log provides the competitors for R1; the competitors should then
|
||||
// snap back to those competitors taken from the regatta log for both, the rentire leaderboard
|
||||
// as well as for the race column
|
||||
raceLog.revokeEvent(author, usesCompetitorsFromRaceLogEvent);
|
||||
assertRegattaAndRaceCompetitors(new HashSet<>(compLists[0]));
|
||||
// And now re-introduce per-race competitors and validate again that the cache adjusts properly:
|
||||
raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId));
|
||||
assertRegattaAndRaceCompetitors(new HashSet<>(compLists[1]));
|
||||
}
|
||||
|
||||
private void assertRegattaAndRaceCompetitors(Set<Competitor> expected) {
|
||||
Set<Competitor> actual = new HashSet<>();
|
||||
Util.addAll(competitorProviderFlexibleLeaderboard.getAllCompetitors(), actual);
|
||||
assertEquals(expected, actual);
|
||||
Set<Competitor> actualForRace = new HashSet<>();
|
||||
|
||||
//For the race only the competitors registered on RaceLog as RaceLogUseCompetitorsFromRaceLogEvent is present
|
||||
Set<Competitor> expectedForRace = new HashSet<>(expected);
|
||||
Util.addAll(competitorProviderFlexibleLeaderboard.getAllCompetitors(
|
||||
flexibleLeaderboard.getRaceColumnByName("R1"),
|
||||
flexibleLeaderboard.getFleet(LeaderboardNameConstants.DEFAULT_FLEET_NAME)), actualForRace);
|
||||
assertEquals(expected, actualForRace);
|
||||
assertEquals(expectedForRace, actualForRace);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -251,6 +272,9 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard
|
||||
@Test
|
||||
public void testSimpleCompetitorListOnOneRaceLogInRegattaLeaderboard() {
|
||||
RaceLog raceLog = regattaLeaderboard.getRacelog("R1", "Yellow");
|
||||
final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0);
|
||||
int passId = 1;
|
||||
raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId));
|
||||
for (Competitor c : compLists[0]) {
|
||||
raceLog.add(new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), 1, c));
|
||||
}
|
||||
@@ -307,6 +331,7 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard
|
||||
}
|
||||
final RaceLog raceLog = regattaLeaderboard.getRacelog("R1", "Yellow");
|
||||
final int passId = 1;
|
||||
raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId));
|
||||
final Map<Competitor, RaceLogRegisterCompetitorEvent> competitorOnRaceLogRegistrationEvents = new HashMap<>();
|
||||
for (Competitor c : compLists[passId]) {
|
||||
final RaceLogRegisterCompetitorEvent registerCompetitorEvent = new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), author, passId, c);
|
||||
@@ -325,14 +350,15 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard
|
||||
Util.addAll(regattaLeaderboard.getCompetitors(), actualWithoutSuppressed);
|
||||
assertEquals(expectedWithoutSuppressed, actualWithoutSuppressed);
|
||||
Set<Competitor> actualForRaceYellow = new HashSet<>();
|
||||
Set<Competitor> expectedFoRaceYellow = new HashSet<>(compLists[passId]);
|
||||
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(
|
||||
regattaLeaderboard.getRaceColumnByName("R1"), regattaLeaderboard.getFleet("Yellow")), actualForRaceYellow);
|
||||
assertEquals(expected, actualForRaceYellow);
|
||||
assertEquals(expectedFoRaceYellow, actualForRaceYellow);
|
||||
actualForRaceYellow = new HashSet<>(); // try another time; cache should of course yield an equal result (although
|
||||
// we're not asserting here that the result actually comes from the cache)
|
||||
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(
|
||||
regattaLeaderboard.getRaceColumnByName("R1"), regattaLeaderboard.getFleet("Yellow")), actualForRaceYellow);
|
||||
assertEquals(expected, actualForRaceYellow);
|
||||
assertEquals(expectedFoRaceYellow, actualForRaceYellow);
|
||||
// But now it gets interesting: we're revoking a competitor registration on the race log and assert
|
||||
// that the competitor is gone from the list:
|
||||
final Competitor competitorToRevokeFromRaceLog = compLists[passId].get(2);
|
||||
@@ -341,9 +367,9 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard
|
||||
// we're not asserting here that the result actually comes from the cache)
|
||||
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(
|
||||
regattaLeaderboard.getRaceColumnByName("R1"), regattaLeaderboard.getFleet("Yellow")), actualForRaceYellow);
|
||||
expected.remove(competitorToRevokeFromRaceLog);
|
||||
assertEquals(expected.size(), actualForRaceYellow.size());
|
||||
assertEquals(expected, actualForRaceYellow);
|
||||
expectedFoRaceYellow.remove(competitorToRevokeFromRaceLog);
|
||||
assertEquals(expectedFoRaceYellow.size(), actualForRaceYellow.size());
|
||||
assertEquals(expectedFoRaceYellow, actualForRaceYellow);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
package com.sap.sailing.domain.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.CompetitorResult;
|
||||
import com.sap.sailing.domain.abstractlog.race.CompetitorResults;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultsImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningConfirmedEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPassChangeEventImpl;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.impl.CourseAreaImpl;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
|
||||
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
|
||||
import com.sap.sailing.domain.common.impl.WindImpl;
|
||||
import com.sap.sailing.domain.common.impl.WindSourceImpl;
|
||||
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
|
||||
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
|
||||
import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tractracadapter.ReceiverType;
|
||||
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.tractrac.model.lib.api.event.CreateModelException;
|
||||
import com.tractrac.subscription.lib.api.SubscriberInitializationException;
|
||||
|
||||
/**
|
||||
* Tests the implementation for bug3420: when a {@link RaceLogFinishPositioningConfirmedEvent} is found in a race log
|
||||
* that has a valid {@link CompetitorResult#getFinishingTime()} defined for a competitor, a wrapper mark passing is
|
||||
* expected to be generated with that time point for the finish waypoint. When the event is invalidated, e.g., by
|
||||
* detaching the race log or by starting a new pass or by sending a newer {@link RaceLogFinishPositioningConfirmedEvent}
|
||||
* or one that has higher priority, the finish mark passings need to be updated accordingly. This can mean that entirely
|
||||
* artificial mark passings need to be removed entirely; mark passings that only replaced an original mark passing by
|
||||
* one with a modified finish time need to be reverted back to the original mark passing.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public class MarkPassingUpdateFromRaceLogFinishPositioingListTest extends AbstractManeuverDetectionTestCase {
|
||||
private FlexibleLeaderboard leaderboard;
|
||||
private RaceLog raceLog;
|
||||
private final AbstractLogEventAuthor author;
|
||||
|
||||
public MarkPassingUpdateFromRaceLogFinishPositioingListTest() throws MalformedURLException, URISyntaxException {
|
||||
super();
|
||||
author = new LogEventAuthorImpl("Me", 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getExpectedEventName() {
|
||||
return "ESS Qingdao 2014";
|
||||
}
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws URISyntaxException, IOException, InterruptedException, ParseException, SubscriberInitializationException, CreateModelException {
|
||||
super.setUp();
|
||||
URI storedUri = new URI("file:///"+new File("resources/event_20140429_ESSQingdao-Race_4.mtb").getCanonicalPath().replace('\\', '/'));
|
||||
super.setUp(
|
||||
new URL("file:///" + new File("resources/event_20140429_ESSQingdao-Race_4.txt").getCanonicalPath()),
|
||||
/* liveUri */null, /* storedUri */storedUri, new ReceiverType[] { ReceiverType.MARKPASSINGS,
|
||||
ReceiverType.MARKPOSITIONS, ReceiverType.RACECOURSE, ReceiverType.RAWPOSITIONS });
|
||||
getTrackedRace().recordWind(
|
||||
new WindImpl(/* position */null, new MillisecondsTimePoint(dateFormat.parse("05/01/2014-09:02:00")),
|
||||
new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(269))),
|
||||
new WindSourceImpl(WindSourceType.WEB));
|
||||
leaderboard = new FlexibleLeaderboardImpl("Test", new ThresholdBasedResultDiscardingRuleImpl(new int[0]), new LowPoint(), new CourseAreaImpl("Here", UUID.randomUUID()));
|
||||
final RaceColumn raceColumn = leaderboard.addRace(getTrackedRace(), "R", /* medalRace */ false);
|
||||
raceLog = raceColumn.getRaceLog(raceColumn.getFleets().iterator().next());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the Race 4 for competitor "Alinghi" at a time where the maneuver detection test is likely to compute
|
||||
* a penalty although between the jibe and the tack there is a mark passing
|
||||
*/
|
||||
@Test
|
||||
public void testOriginalFinishMarkPassingTime() throws ParseException, NoWindException {
|
||||
int passId = 0;
|
||||
Competitor alinghi = getCompetitorByName("Alinghi");
|
||||
final MarkPassing alinghiOriginalFinish = getTrackedRace().getMarkPassing(alinghi, getTrackedRace().getRace().getCourse().getLastWaypoint());
|
||||
final TimePoint alinghiOriginalFinishingTime = alinghiOriginalFinish.getTimePoint();
|
||||
assertNotNull(alinghiOriginalFinish.getTimePoint());
|
||||
final TimePoint now = MillisecondsTimePoint.now();
|
||||
final CompetitorResults alinghiFinishesNow = createCompetitorResults(new Util.Pair<>(alinghi, now));
|
||||
raceLog.add(new RaceLogFinishPositioningConfirmedEventImpl(now, author, passId, alinghiFinishesNow));
|
||||
final MarkPassing alinghiCorrectedFinishMarkPassing = getTrackedRace().getMarkPassing(alinghi, getTrackedRace().getRace().getCourse().getLastWaypoint());
|
||||
assertEquals(now, alinghiCorrectedFinishMarkPassing.getTimePoint());
|
||||
raceLog.add(new RaceLogPassChangeEventImpl(now.plus(Duration.ONE_SECOND), author, ++passId)); // this should invalidate the previously edited result
|
||||
assertEquals(alinghiOriginalFinishingTime, getTrackedRace().getMarkPassing(alinghi, getTrackedRace().getRace().getCourse().getLastWaypoint()).getTimePoint());
|
||||
List<MarkPassing> withoutLast = new ArrayList<>();
|
||||
final NavigableSet<MarkPassing> alinghiOriginalMarkPassings = getTrackedRace().getMarkPassings(alinghi);
|
||||
getTrackedRace().lockForRead(alinghiOriginalMarkPassings);
|
||||
try {
|
||||
withoutLast.addAll(alinghiOriginalMarkPassings);
|
||||
} finally {
|
||||
getTrackedRace().unlockAfterRead(alinghiOriginalMarkPassings);
|
||||
}
|
||||
withoutLast.remove(withoutLast.size()-1);
|
||||
getTrackedRace().updateMarkPassings(alinghi, withoutLast);
|
||||
assertNull(getTrackedRace().getMarkPassing(alinghi, getTrackedRace().getRace().getCourse().getLastWaypoint()));
|
||||
raceLog.add(new RaceLogFinishPositioningConfirmedEventImpl(now, author, passId, alinghiFinishesNow));
|
||||
final MarkPassing alinghiSyntheticFinish = getTrackedRace().getMarkPassing(alinghi, getTrackedRace().getRace().getCourse().getLastWaypoint());
|
||||
assertEquals(now, alinghiSyntheticFinish.getTimePoint());
|
||||
assertNull(alinghiSyntheticFinish.getOriginal());
|
||||
// advancing to the next pass is expected to remove the synthetic mark passing again
|
||||
raceLog.add(new RaceLogPassChangeEventImpl(now.plus(Duration.ONE_HOUR), author, ++passId));
|
||||
assertNull(getTrackedRace().getMarkPassing(alinghi, getTrackedRace().getRace().getCourse().getLastWaypoint()));
|
||||
raceLog.add(new RaceLogFinishPositioningConfirmedEventImpl(now, author, passId, alinghiFinishesNow));
|
||||
final MarkPassing alinghiSyntheticFinish2 = getTrackedRace().getMarkPassing(alinghi, getTrackedRace().getRace().getCourse().getLastWaypoint());
|
||||
assertEquals(now, alinghiSyntheticFinish2.getTimePoint());
|
||||
assertNull(alinghiSyntheticFinish2.getOriginal());
|
||||
List<MarkPassing> withLastAgain = new ArrayList<>(withoutLast);
|
||||
withLastAgain.add(alinghiOriginalFinish);
|
||||
getTrackedRace().updateMarkPassings(alinghi, withLastAgain);
|
||||
final MarkPassing alinghiNoLongerSynthetic = getTrackedRace().getMarkPassing(alinghi, getTrackedRace().getRace().getCourse().getLastWaypoint());
|
||||
assertSame(alinghiOriginalFinish, alinghiNoLongerSynthetic.getOriginal());
|
||||
assertTrue(alinghiNoLongerSynthetic.getOriginal() != alinghiNoLongerSynthetic);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
private final CompetitorResults createCompetitorResults(Pair<Competitor, TimePoint>... finishingTimes) {
|
||||
final CompetitorResults results = new CompetitorResultsImpl();
|
||||
int rank = 1;
|
||||
for (Pair<Competitor, TimePoint> finishingTime : finishingTimes) {
|
||||
results.add(new CompetitorResultImpl(finishingTime.getA().getId(), finishingTime.getA().getName(), rank++, /* maxPointsReason */
|
||||
null, /* score */null, finishingTime.getB(), /* comment */null));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
+25
-4
@@ -487,6 +487,27 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
public Iterable<? extends RaceColumn> getRaceColumns() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Competitor> getCompetitorsRegisteredInRegattaLog() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCompetitor(Competitor competitor) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCompetitors(Iterable<Competitor> competitor) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deregisterCompetitor(Competitor competitor) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deregisterCompetitors(Iterable<Competitor> competitor) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -905,10 +926,6 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void waitForLoadingFromGPSFixStoreToFinishRunning(RaceLog forRaceLog) throws InterruptedException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRaceAbortedListener(RaceAbortedListener listener) {
|
||||
}
|
||||
@@ -1008,4 +1025,8 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
public IsManagedByCache<SharedDomainFactory> resolve(SharedDomainFactory domainFactory) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateMarkPassingsAfterRaceLogChanges() {
|
||||
}
|
||||
}
|
||||
|
||||
-4
@@ -554,10 +554,6 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void waitForLoadingFromGPSFixStoreToFinishRunning(RaceLog forRaceLog) throws InterruptedException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRaceAbortedListener(RaceAbortedListener listener) {
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ 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.abstractlog.NotRevokableException;
|
||||
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;
|
||||
@@ -46,6 +48,15 @@ public interface RaceColumn extends Named {
|
||||
*/
|
||||
RaceLog getRaceLog(Fleet fleet);
|
||||
|
||||
/**
|
||||
* Gets the regatta log associated with the regatta-like structure (either a regatta if this is a
|
||||
* {@link RaceColumnInSeries} or a flexible leaderboard). Note that the result may be <code>null</code> particularly
|
||||
* for columns in a {@link MetaLeaderboard}.
|
||||
*
|
||||
* @return the regatta log or <code>null</code> in case this column belongs to a {@link MetaLeaderboard}
|
||||
*/
|
||||
RegattaLog getRegattaLog();
|
||||
|
||||
/**
|
||||
* @return the fleets for each of which this column has a single race and therefore optionally a {@link TrackedRace}, in
|
||||
* ascending order; best fleets first
|
||||
@@ -232,9 +243,9 @@ public interface RaceColumn extends Named {
|
||||
/**
|
||||
* Provides the combined set of competitors from all {@link #getTrackedRace(Fleet) tracked races attached to this
|
||||
* column} or, in case a fleet does not have a tracked race attached, the competitors registered through the
|
||||
* respective {@link RaceLog} {@link #getRaceLog(Fleet) attached to this column for that fleet}. Note that this does
|
||||
* not include competitors registered through any {@link RegattaLog} on the structure owning (directly or
|
||||
* transitively) this column.
|
||||
* respective {@link RaceLog} {@link #getRaceLog(Fleet)} attached to this column for that fleet (if this is
|
||||
* {@link #enableCompetitorRegistrationOnRaceLog(Fleet) enabled) or registered through the {@link #getRegattaLog()
|
||||
* regatta log}.
|
||||
*/
|
||||
Iterable<Competitor> getAllCompetitors();
|
||||
|
||||
@@ -242,4 +253,96 @@ public interface RaceColumn extends Named {
|
||||
* Same as {@link #getAllCompetitors()}, but restricted to the single race identified by the <code>fleet</code> parameter.
|
||||
*/
|
||||
Iterable<Competitor> getAllCompetitors(Fleet fleet);
|
||||
|
||||
/**
|
||||
* Provides the combined set of marks from all {@link #getTrackedRace(Fleet) tracked races attached to this
|
||||
* column} or, in case a fleet does not have a tracked race attached, the marks registered through the
|
||||
* {@link #getRegattaLog() regatta log} for the regatta-like object to which this column belongs (flexible
|
||||
* leaderboard or regatta).
|
||||
*/
|
||||
Iterable<Mark> getAllMarks();
|
||||
|
||||
/**
|
||||
* Same as {@link #getAllMarks()}, but restricted to the single race identified by the <code>fleet</code> parameter.
|
||||
*/
|
||||
Iterable<Mark> getMarks(Fleet fleet);
|
||||
|
||||
/**
|
||||
* Returns the competitor set registered in the race column's race log associated to the passed fleet. If competitor
|
||||
* registration in RaceLog is {@link #disableCompetitorRegistrationOnRaceLog(Fleet) disabled} or in case of a
|
||||
* MetaLeaderboardColumn an empty set is returned.
|
||||
*
|
||||
* @return competitors in RaceLog if registration {@link #enableCompetitorRegistrationOnRaceLog(Fleet) enabled} or
|
||||
* empty set in case registration is {@link #disableCompetitorRegistrationOnRaceLog(Fleet) disabled} or this
|
||||
* column belongs to a {@link MetaLeaderboard}
|
||||
*/
|
||||
Iterable<Competitor> getCompetitorsRegisteredInRacelog(Fleet fleet);
|
||||
|
||||
/**
|
||||
* Checks whether competitor registration on RaceLog is enabled.
|
||||
*
|
||||
* @return boolean if competitor registration on the RaceLog is enabled, false in case this column belongs to a
|
||||
* {@link MetaLeaderboard}
|
||||
*
|
||||
* @see #enableCompetitorRegistrationOnRaceLog(Fleet)
|
||||
* @see #disableCompetitorRegistrationOnRaceLog(Fleet)
|
||||
*/
|
||||
boolean isCompetitorRegistrationInRacelogEnabled(Fleet fleet);
|
||||
|
||||
/**
|
||||
* Activates competitor registration on the race column's race log associated to the passed fleet. As a result,
|
||||
* competitor registrations that were added to the race log before this was disabled by
|
||||
* {@link #disableCompetitorRegistrationOnRaceLog(Fleet)} will again be honored.<p>
|
||||
*
|
||||
* Performs nothing in case this column belongs to a {@link MetaLeaderboard}.
|
||||
*/
|
||||
void enableCompetitorRegistrationOnRaceLog(Fleet fleet);
|
||||
|
||||
/**
|
||||
* Disables competitor registration on the race column's race log associated to the passed fleet. Performs nothing
|
||||
* in case this column belongs to a {@link MetaLeaderboard}. If there are already competitor registrations on the
|
||||
* race log, those will not be removed from the log but they will be ignored, and the regatta log's competitor
|
||||
* registrations will be used instead. Re-{@link #enableCompetitorRegistrationOnRaceLog(Fleet) enabling} competitor
|
||||
* registrations in the race log will cause such existing registrations to be honored again.
|
||||
* <p>
|
||||
*
|
||||
* Performs nothing in case this column belongs to a {@link MetaLeaderboard}.
|
||||
*/
|
||||
void disableCompetitorRegistrationOnRaceLog(Fleet fleet) throws NotRevokableException;
|
||||
|
||||
/**
|
||||
* Registers a competitor on the the race column's race log associated to the passed fleet.
|
||||
*
|
||||
* @throws CompetitorRegistrationOnRaceLogDisabledException
|
||||
* thrown if competitor registration is {@link #disableCompetitorRegistrationOnRaceLog(Fleet) disabled}
|
||||
* on racelog as well as if RaceColumn belongs to a {@link MetaLeaderboard}
|
||||
*/
|
||||
void registerCompetitor(Competitor competitor, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException;
|
||||
|
||||
/**
|
||||
* Registers competitors on the the race column's race log associated to the passed fleet.
|
||||
*
|
||||
* @throws CompetitorRegistrationOnRaceLogDisabledException
|
||||
* thrown if competitor registration is disabled on racelog as well as if RaceColumn belongs to a
|
||||
* {@link MetaLeaderboard}
|
||||
*/
|
||||
void registerCompetitors(Iterable<Competitor> competitor, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException;
|
||||
|
||||
/**
|
||||
* Deregisters a competitor on the the race column's race log associated to the passed fleet.
|
||||
*
|
||||
* @throws CompetitorRegistrationOnRaceLogDisabledException
|
||||
* thrown if competitor registration is disabled on racelog as well as if RaceColumn belongs to a
|
||||
* {@link MetaLeaderboard}
|
||||
*/
|
||||
void deregisterCompetitor(Competitor competitors, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException;
|
||||
|
||||
/**
|
||||
* Deregisters competitors on the the race column's race log associated to the passed fleet.
|
||||
*
|
||||
* @throws CompetitorRegistrationOnRaceLogDisabledException
|
||||
* thrown if competitor registration is disabled on racelog as well as if RaceColumn belongs to a
|
||||
* {@link MetaLeaderboard}
|
||||
*/
|
||||
void deregisterCompetitors(Iterable<Competitor> currentlyRegisteredCompetitors, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException;
|
||||
}
|
||||
|
||||
+164
-28
@@ -2,36 +2,61 @@ package com.sap.sailing.domain.base.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.impl.AllEventsOfTypeFinder;
|
||||
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.RegisteredCompetitorsAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastPublishedCourseDesignFinder;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent;
|
||||
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.race.tracking.impl.RaceLogUseCompetitorsFromRaceLogEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDefinedMarkAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorEvent;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
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.Waypoint;
|
||||
import com.sap.sailing.domain.common.RaceIdentifier;
|
||||
import com.sap.sailing.domain.common.abstractlog.NotRevokableException;
|
||||
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;
|
||||
|
||||
private Map<Fleet, RaceLog> raceLogs;
|
||||
|
||||
|
||||
private transient RaceLogStore raceLogStore;
|
||||
private RegattaLikeIdentifier regattaLikeParent;
|
||||
|
||||
@@ -46,7 +71,7 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
|
||||
this.raceLogStore = raceLogStore;
|
||||
this.regattaLikeParent = regattaLikeParent;
|
||||
for (final Fleet fleet : getFleets()) {
|
||||
reloadRaceLog(fleet);
|
||||
reloadRaceLog(fleet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +81,7 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
|
||||
return raceLogs.get(fleet);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public RaceLogIdentifier getRaceLogIdentifier(Fleet fleet) {
|
||||
return new RaceLogIdentifierImpl(regattaLikeParent, getName(), fleet);
|
||||
@@ -114,13 +139,13 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
|
||||
getRaceColumnListeners().notifyListenersAboutTrackedRaceUnlinked(this, fleet, previouslyLinkedRace);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void removeRaceIdentifier(Fleet fleet) {
|
||||
releaseTrackedRace(fleet);
|
||||
this.raceIdentifiers.remove(fleet);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Fleet getFleetOfCompetitor(Competitor competitor) {
|
||||
for (final Fleet fleet : getFleets()) {
|
||||
@@ -155,7 +180,7 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
@@ -163,9 +188,9 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
|
||||
|
||||
@Override
|
||||
public void reloadRaceLog(Fleet fleet) {
|
||||
synchronized(raceLogs) {
|
||||
synchronized (raceLogs) {
|
||||
RaceLogIdentifier identifier = getRaceLogIdentifier(fleet);
|
||||
RaceLog newOrLoadedRaceLog = raceLogStore.getRaceLog(identifier, /*ignoreCache*/ true);
|
||||
RaceLog newOrLoadedRaceLog = raceLogStore.getRaceLog(identifier, /* ignoreCache */true);
|
||||
RaceLog raceLogAvailable = raceLogs.get(fleet);
|
||||
if (raceLogAvailable == null) {
|
||||
RaceColumnRaceLogReplicator listener = new RaceColumnRaceLogReplicator(this, identifier);
|
||||
@@ -205,7 +230,7 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
|
||||
if (trackedRace != null) {
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
}
|
||||
}, /* prio */ 0);
|
||||
}, /* prio */0);
|
||||
// because this will add the race log to the tracked race's attachedRaceLogs collection again, and
|
||||
// the new DynamicTrackedRaceLogListener that the readObject(...) method had constructed for the
|
||||
// tracked race will be added as a listener to the race log whose listeners collection otherwise would
|
||||
@@ -218,22 +243,11 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
|
||||
trackedRaces.setMasterDataExportOngoingThreadFlag(flagValue);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Iterable<Competitor> getAllCompetitors() {
|
||||
final Set<Competitor> result = new HashSet<>();
|
||||
Set<Competitor> result = new HashSet<>();
|
||||
for (Fleet fleet : getFleets()) {
|
||||
TrackedRace trackedRace = getTrackedRace(fleet);
|
||||
if (trackedRace != null) {
|
||||
Util.addAll(trackedRace.getRace().getCompetitors(), result);
|
||||
} else {
|
||||
// if no tracked race is found, use competitors from race log; 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)).analyze();
|
||||
result.addAll(viaRaceLog);
|
||||
}
|
||||
Util.addAll(getAllCompetitors(fleet), result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -241,17 +255,139 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
|
||||
@Override
|
||||
public Iterable<Competitor> getAllCompetitors(final Fleet fleet) {
|
||||
final Iterable<Competitor> result;
|
||||
final TrackedRace trackedRace = getTrackedRace(fleet);
|
||||
TrackedRace trackedRace = getTrackedRace(fleet);
|
||||
if (trackedRace != null) {
|
||||
result = trackedRace.getRace().getCompetitors();
|
||||
} else {
|
||||
// if no tracked race is found, use competitors from race log; this assumes that if a tracked
|
||||
// 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)).analyze();
|
||||
Set<Competitor> viaRaceLog = new RegisteredCompetitorsAnalyzer(getRaceLog(fleet), getRegattaLog()).analyze();
|
||||
result = viaRaceLog;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCompetitor(Competitor competitor, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException {
|
||||
registerCompetitors(Collections.singleton(competitor), fleet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCompetitors(Iterable<Competitor> competitors, Fleet fleet)
|
||||
throws CompetitorRegistrationOnRaceLogDisabledException {
|
||||
if (!isCompetitorRegistrationInRacelogEnabled(fleet)) {
|
||||
throw new CompetitorRegistrationOnRaceLogDisabledException("Competitor registration not allowed for fleet "+fleet+" in column "+this);
|
||||
}
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
RaceLog raceLog = getRaceLog(fleet);
|
||||
int passId = raceLog.getCurrentPassId();
|
||||
for (Competitor competitor : competitors) {
|
||||
raceLog.add(new RaceLogRegisterCompetitorEventImpl(now, now, raceLogEventAuthorForRaceColumn,
|
||||
UUID.randomUUID(), passId, competitor));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deregisterCompetitor(Competitor competitor, Fleet fleet)
|
||||
throws CompetitorRegistrationOnRaceLogDisabledException {
|
||||
deregisterCompetitors(Collections.singleton(competitor), fleet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deregisterCompetitors(Iterable<Competitor> competitors, Fleet fleet)
|
||||
throws CompetitorRegistrationOnRaceLogDisabledException {
|
||||
if (!isCompetitorRegistrationInRacelogEnabled(fleet)) {
|
||||
throw new CompetitorRegistrationOnRaceLogDisabledException("Competitor registration not allowed for fleet "+fleet+" in column "+this);
|
||||
}
|
||||
HashSet<Competitor> competitorSet = new HashSet<Competitor>();
|
||||
Util.addAll(competitors, competitorSet);
|
||||
RaceLog raceLog = getRaceLog(fleet);
|
||||
for (RaceLogEvent event : raceLog.getUnrevokedEventsDescending()) {
|
||||
if (event instanceof RegisterCompetitorEvent) {
|
||||
RegisterCompetitorEvent<?> registerEvent = (RegisterCompetitorEvent<?>) event;
|
||||
if (competitorSet.contains(registerEvent.getCompetitor())) {
|
||||
try {
|
||||
raceLog.revokeEvent(raceLogEventAuthorForRaceColumn, event,
|
||||
"unregistering competitor because no longer selected for registration");
|
||||
} catch (NotRevokableException e) {
|
||||
logger.log(Level.WARNING, "could not unregister competitor by adding RevokeEvent", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Mark> getAllMarks() {
|
||||
final Set<Mark> result = new HashSet<>();
|
||||
// if the marks from the regatta log are to be used because a slot has no TrackedRace attached,
|
||||
// those regatta log marks only need to be added to the result once
|
||||
boolean regattaLogMarksAlreadyAdded = false;
|
||||
for (Fleet fleet : getFleets()) {
|
||||
TrackedRace trackedRace = getTrackedRace(fleet);
|
||||
if (trackedRace != null) {
|
||||
for (Waypoint waypoint : trackedRace.getRace().getCourse().getWaypoints()) {
|
||||
Util.addAll(waypoint.getMarks(), result);
|
||||
}
|
||||
} else if (!regattaLogMarksAlreadyAdded) {
|
||||
// if no tracked race is found, use marks from regatta log
|
||||
RegattaLog regattaLog = getRegattaLog();
|
||||
Collection<Mark> viaRegattaLog = new RegattaLogDefinedMarkAnalyzer(regattaLog).analyze();
|
||||
result.addAll(viaRegattaLog);
|
||||
regattaLogMarksAlreadyAdded = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Mark> getMarks(Fleet fleet) {
|
||||
final Set<Mark> result = new HashSet<>();
|
||||
final TrackedRace trackedRace = getTrackedRace(fleet);
|
||||
if (trackedRace != null) {
|
||||
for (Waypoint waypoint : trackedRace.getRace().getCourse().getWaypoints()) {
|
||||
Util.addAll(waypoint.getMarks(), result);
|
||||
}
|
||||
} else {
|
||||
// if no tracked race is found, use marks from race course if present in racelog
|
||||
// if not the marks defined in the regatta log
|
||||
LastPublishedCourseDesignFinder courseDesginFinder = new LastPublishedCourseDesignFinder(getRaceLog(fleet));
|
||||
final CourseBase courseBase = courseDesginFinder.analyze();
|
||||
if (courseBase != null) {
|
||||
// TODO why do we collect the marks from the course definition here but not in getAllMarks()?
|
||||
courseBase.getWaypoints().forEach((waypoint) -> Util.addAll(waypoint.getMarks(), result));
|
||||
} else {
|
||||
Util.addAll(new RegattaLogDefinedMarkAnalyzer(getRegattaLog()).analyze(), result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableCompetitorRegistrationOnRaceLog(Fleet fleet) {
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
RaceLog raceLog = getRaceLog(fleet);
|
||||
int passId = raceLog.getCurrentPassId();
|
||||
raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(now, raceLogEventAuthorForRaceColumn, now, UUID.randomUUID(), passId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableCompetitorRegistrationOnRaceLog(Fleet fleet) throws NotRevokableException {
|
||||
RaceLog raceLog = getRaceLog(fleet);
|
||||
List<RaceLogEvent> events = new AllEventsOfTypeFinder<>(raceLog, true, RaceLogUseCompetitorsFromRaceLogEvent.class).analyze();
|
||||
for (RaceLogEvent event : events) {
|
||||
raceLog.lockForRead();
|
||||
try {
|
||||
event = raceLog.getEventById(event.getId());
|
||||
} finally {
|
||||
raceLog.unlockAfterRead();
|
||||
}
|
||||
if (event != null) {
|
||||
raceLog.revokeEvent(raceLogEventAuthorForRaceColumn, event, "revoke triggered by GWT user action");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-1
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.base.impl;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumnInSeries;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
@@ -14,7 +15,7 @@ import com.sap.sailing.domain.tracking.TrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
|
||||
|
||||
/**
|
||||
* Obtains flees and medal information from the {@link Series} to which it is connected at construction time.
|
||||
* Obtains fleets and medal information from the {@link Series} to which it is connected at construction time.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
@@ -131,4 +132,10 @@ public class RaceColumnInSeriesImpl extends AbstractRaceColumn implements RaceCo
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegattaLog getRegattaLog() {
|
||||
Regatta regatta = getRegatta();
|
||||
return regatta.getRegattaLog();
|
||||
}
|
||||
}
|
||||
|
||||
+9
-27
@@ -2,15 +2,15 @@ package com.sap.sailing.domain.base.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogCourseAreaChangedEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningListChangedEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogGateLineOpeningTimeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogPassChangeEvent;
|
||||
@@ -21,16 +21,13 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
|
||||
|
||||
@@ -117,16 +114,6 @@ public class RaceColumnRaceLogReplicator implements RaceLogEventVisitor, Seriali
|
||||
notifyOnAdd(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogDeviceCompetitorMappingEvent event) {
|
||||
notifyOnAdd(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogDeviceMarkMappingEvent event) {
|
||||
notifyOnAdd(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogDenoteForTrackingEvent event) {
|
||||
notifyOnAdd(event);
|
||||
@@ -146,16 +133,6 @@ public class RaceColumnRaceLogReplicator implements RaceLogEventVisitor, Seriali
|
||||
public void visit(RaceLogRegisterCompetitorEvent event) {
|
||||
notifyOnAdd(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogDefineMarkEvent event) {
|
||||
notifyOnAdd(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogCloseOpenEndedDeviceMappingEvent event) {
|
||||
notifyOnAdd(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogFixedMarkPassingEvent event) {
|
||||
@@ -186,4 +163,9 @@ public class RaceColumnRaceLogReplicator implements RaceLogEventVisitor, Seriali
|
||||
public void visit(RaceLogEndOfTrackingEvent event) {
|
||||
notifyOnAdd(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) {
|
||||
notifyOnAdd(event);
|
||||
}
|
||||
}
|
||||
|
||||
+128
-69
@@ -12,13 +12,21 @@ 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.CompetitorDeregistrator;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer;
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.CourseArea;
|
||||
@@ -40,7 +48,9 @@ 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.leaderboard.impl.FlexibleLeaderboardImpl;
|
||||
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
|
||||
import com.sap.sailing.domain.racelog.RaceLogStore;
|
||||
import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore;
|
||||
@@ -61,8 +71,18 @@ 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;
|
||||
|
||||
/**
|
||||
* A regatta with series with race columns and fleets, a scoring scheme and various other data, many of which are relevant
|
||||
* for scoring. A regatta has a single boat class. It implements the {@link IsRegattaLike} interface and for this uses a
|
||||
* delegate pattern with the {@link BaseRegattaLikeImpl} which it shares with {@link FlexibleLeaderboardImpl}. That
|
||||
* delegate provides the {@link RegattaLog} for this regatta.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListener {
|
||||
|
||||
/**
|
||||
@@ -93,48 +113,44 @@ 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, RankingMetricConstructor rankingMetricConstructor) {
|
||||
this(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, name, boatClass, startDate, endDate, series,
|
||||
persistent, scoringScheme, id, courseArea, /* useStartTimeInference */true, rankingMetricConstructor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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)}
|
||||
@@ -142,9 +158,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);
|
||||
}
|
||||
@@ -162,12 +178,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,9 +193,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;
|
||||
@@ -241,19 +260,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();
|
||||
@@ -266,17 +285,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()) {
|
||||
@@ -288,7 +306,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
} else {
|
||||
logger.warning("Race Columns were null during deserialization. This should not happen.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -301,7 +319,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Series getSeriesByName(String name) {
|
||||
for (Series s : getSeries()) {
|
||||
@@ -316,12 +334,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());
|
||||
@@ -331,12 +349,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) {
|
||||
@@ -345,10 +364,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) {
|
||||
@@ -400,25 +419,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
|
||||
@@ -457,7 +479,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);
|
||||
}
|
||||
|
||||
@@ -480,7 +503,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;
|
||||
@@ -515,17 +538,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;
|
||||
@@ -533,8 +556,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() {
|
||||
@@ -545,7 +568,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
return getId() + " " + getName() + " " + getScoringScheme().getType().name();
|
||||
}
|
||||
@@ -594,7 +617,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
}
|
||||
this.series = newSeriesList;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -621,7 +644,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);
|
||||
@@ -649,7 +672,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;
|
||||
|
||||
@@ -677,8 +700,8 @@ 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
|
||||
// will be thrown. We catch and log it here and try again.
|
||||
// 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);
|
||||
concurrentlyModified = true;
|
||||
@@ -726,4 +749,40 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Competitor> getCompetitorsRegisteredInRegattaLog() {
|
||||
RegattaLog regattaLog = getRegattaLog();
|
||||
CompetitorsInLogAnalyzer<RegattaLog, RegattaLogEvent, RegattaLogEventVisitor> analyzer = new CompetitorsInLogAnalyzer<>(
|
||||
regattaLog);
|
||||
return analyzer.analyze();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCompetitor(Competitor competitor) {
|
||||
registerCompetitors(Collections.singleton(competitor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCompetitors(Iterable<Competitor> competitors) {
|
||||
RegattaLog regattaLog = getRegattaLike().getRegattaLog();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
|
||||
for (Competitor competitor : competitors) {
|
||||
regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(now, now, regattaLogEventAuthorForRegatta,
|
||||
UUID.randomUUID(), competitor));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deregisterCompetitor(Competitor competitor) {
|
||||
deregisterCompetitors(Collections.singleton(competitor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deregisterCompetitors(Iterable<Competitor> competitors) {
|
||||
RegattaLog regattaLog = getRegattaLike().getRegattaLog();
|
||||
CompetitorDeregistrator<RegattaLog, RegattaLogEvent, RegattaLogEventVisitor> deregisterer = new CompetitorDeregistrator<>(regattaLog, competitors, regattaLogEventAuthorForRegatta);
|
||||
deregisterer.analyze();
|
||||
}
|
||||
}
|
||||
|
||||
+27
-1
@@ -1,5 +1,10 @@
|
||||
package com.sap.sailing.domain.base.impl;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogRegisteredCompetitorsAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogUsesOwnCompetitorsAnalyzer;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
@@ -114,5 +119,26 @@ public abstract class SimpleAbstractRaceColumn implements RaceColumn {
|
||||
public boolean hasSplitFleets() {
|
||||
return Util.size(getFleets()) > 1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Iterable<Competitor> getCompetitorsRegisteredInRacelog(final Fleet fleet) {
|
||||
RaceLog raceLog = getRaceLog(fleet);
|
||||
if (raceLog == null) {
|
||||
return Collections.emptySet();
|
||||
} else {
|
||||
RaceLogRegisteredCompetitorsAnalyzer analyzer = new RaceLogRegisteredCompetitorsAnalyzer(raceLog);
|
||||
return analyzer.analyze();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompetitorRegistrationInRacelogEnabled(final Fleet fleet) {
|
||||
RaceLog raceLog = getRaceLog(fleet);
|
||||
if (raceLog == null) {
|
||||
return false;
|
||||
} else {
|
||||
RaceLogUsesOwnCompetitorsAnalyzer analyzer = new RaceLogUsesOwnCompetitorsAnalyzer(raceLog);
|
||||
return analyzer.analyze();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -1,8 +1,10 @@
|
||||
package com.sap.sailing.domain.leaderboard;
|
||||
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.regattalike.IsRegattaLike;
|
||||
|
||||
public interface FlexibleRaceColumn extends RaceColumn {
|
||||
void setName(String newName);
|
||||
void setIsMedalRace(boolean isMedalRace);
|
||||
void setRegattaLikeHelper(IsRegattaLike regattaLikeHelper);
|
||||
}
|
||||
|
||||
+73
-19
@@ -5,8 +5,17 @@ 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.CompetitorDeregistrator;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
@@ -17,34 +26,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 regattaLogEventAuthorForAbstractLeaderboard = 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()) {
|
||||
@@ -79,7 +95,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);
|
||||
@@ -106,8 +122,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,9 +151,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++;
|
||||
@@ -156,7 +174,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();
|
||||
}
|
||||
}
|
||||
@@ -164,12 +183,47 @@ 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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Competitor> getCompetitorsRegisteredInRegattaLog() {
|
||||
RegattaLog regattaLog = getRegattaLike().getRegattaLog();
|
||||
CompetitorsInLogAnalyzer<RegattaLog, RegattaLogEvent, RegattaLogEventVisitor> analyzer = new CompetitorsInLogAnalyzer<>(
|
||||
regattaLog);
|
||||
return analyzer.analyze();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCompetitor(Competitor competitor) {
|
||||
registerCompetitors(Collections.singleton(competitor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCompetitors(Iterable<Competitor> competitors) {
|
||||
RegattaLog regattaLog = getRegattaLike().getRegattaLog();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
|
||||
for (Competitor competitor : competitors) {
|
||||
regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(now, now, regattaLogEventAuthorForAbstractLeaderboard,
|
||||
UUID.randomUUID(), competitor));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deregisterCompetitor(Competitor competitor) {
|
||||
deregisterCompetitors(Collections.singleton(competitor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deregisterCompetitors(Iterable<Competitor> competitors) {
|
||||
RegattaLog regattaLog = getRegattaLike().getRegattaLog();
|
||||
CompetitorDeregistrator<RegattaLog, RegattaLogEvent, RegattaLogEventVisitor> deregisterer = new CompetitorDeregistrator<>(regattaLog, competitors, regattaLogEventAuthorForAbstractLeaderboard);
|
||||
deregisterer.analyze();
|
||||
}
|
||||
}
|
||||
|
||||
+55
-37
@@ -11,12 +11,12 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.BaseRaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.impl.BaseRegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.shared.analyzing.RegisteredCompetitorsAnalyzer;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
@@ -29,30 +29,36 @@ import com.sap.sse.common.Util.Pair;
|
||||
|
||||
/**
|
||||
* A caching provider of a competitor set, based on the tracked races and {@link RaceLog}s of the {@link RaceColumn}s of
|
||||
* a {@link HasRaceColumnsAndRegattaLike} and the {@link RegattaLog} of the same object. After an answer has been provided,
|
||||
* it is cached. The cache is invalidated when one of the following events occurs:
|
||||
* a {@link HasRaceColumnsAndRegattaLike} and the {@link RegattaLog} of the same object. After an answer has been
|
||||
* provided, it is cached. The cache is invalidated when one of the following events occurs:
|
||||
* <ul>
|
||||
* <li>a competitor is registered with or unregistered from a race log of any of the race columns or the regatta log</li>
|
||||
* <li>a race column is added or removed</li>
|
||||
* <li>a tracked race is linked to or unlinked from any of the race columns</li>
|
||||
* <li>the racelog is marked as providing it's own competitors via the {@link RaceLogUseCompetitorsFromRaceLogEvent}</li>
|
||||
* <li>the racelog is marked as no longer providing it's own competitors by revoking an event of type {@link RaceLogUseCompetitorsFromRaceLogEvent}</li>
|
||||
* </ul>
|
||||
*
|
||||
* Note that objects of this type are not serializable. Classes using such objects shall not assign them to non-transient
|
||||
* fields if they want to be serializable themselves.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class CompetitorProviderFromRaceColumnsAndRegattaLike {
|
||||
private static final Logger logger = Logger.getLogger(CompetitorProviderFromRaceColumnsAndRegattaLike.class.getName());
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CompetitorProviderFromRaceColumnsAndRegattaLike.class
|
||||
.getName());
|
||||
|
||||
private final HasRaceColumnsAndRegattaLike provider;
|
||||
|
||||
private final RegattaLogEventVisitor regattaLogCompetitorsCacheInvalidationListener;
|
||||
|
||||
private final RaceLogEventVisitor raceLogCompetitorsCacheInvalidationListener;
|
||||
|
||||
|
||||
private final RaceColumnListener raceColumnListener;
|
||||
|
||||
private Iterable<Competitor> allCompetitorsCache;
|
||||
|
||||
|
||||
private final ConcurrentHashMap<Pair<RaceColumn, Fleet>, Iterable<Competitor>> allCompetitorsCacheByRace;
|
||||
|
||||
public CompetitorProviderFromRaceColumnsAndRegattaLike(HasRaceColumnsAndRegattaLike provider) {
|
||||
@@ -75,11 +81,13 @@ public class CompetitorProviderFromRaceColumnsAndRegattaLike {
|
||||
@Override
|
||||
public void visit(RegattaLogRevokeEvent event) {
|
||||
try {
|
||||
if (RegattaLogRegisterCompetitorEvent.class.isAssignableFrom(Class.forName(event.getRevokedEventType()))) {
|
||||
if (RegattaLogRegisterCompetitorEvent.class.isAssignableFrom(Class.forName(event
|
||||
.getRevokedEventType()))) {
|
||||
invalidateAllCompetitorsCaches();
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
logger.log(Level.WARNING, "Problem occurred trying to resolve revoked event class "+event.getRevokedEventType(), e);
|
||||
logger.log(Level.WARNING,
|
||||
"Problem occurred trying to resolve revoked event class " + event.getRevokedEventType(), e);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -89,14 +97,23 @@ public class CompetitorProviderFromRaceColumnsAndRegattaLike {
|
||||
invalidateAllCompetitorsCaches();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) {
|
||||
invalidateAllCompetitorsCaches();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogRevokeEvent event) {
|
||||
try {
|
||||
if (RaceLogRegisterCompetitorEvent.class.isAssignableFrom(Class.forName(event.getRevokedEventType()))) {
|
||||
final Class<?> revokedEventClass = Class.forName(event.getRevokedEventType());
|
||||
//
|
||||
if (RaceLogRegisterCompetitorEvent.class.isAssignableFrom(revokedEventClass) ||
|
||||
RaceLogUseCompetitorsFromRaceLogEvent.class.isAssignableFrom(revokedEventClass)) {
|
||||
invalidateAllCompetitorsCaches();
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
logger.log(Level.WARNING, "Problem occurred trying to resolve revoked event class "+event.getRevokedEventType(), e);
|
||||
logger.log(Level.WARNING,
|
||||
"Problem occurred trying to resolve revoked event class " + event.getRevokedEventType(), e);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -104,7 +121,8 @@ public class CompetitorProviderFromRaceColumnsAndRegattaLike {
|
||||
private static final long serialVersionUID = -8678230058730043052L;
|
||||
|
||||
@Override
|
||||
public void defaultAction() {}
|
||||
public void defaultAction() {
|
||||
}
|
||||
|
||||
/**
|
||||
* As the entire provider object is considered transient, its listeners are so, too.
|
||||
@@ -135,7 +153,7 @@ public class CompetitorProviderFromRaceColumnsAndRegattaLike {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public Iterable<Competitor> getAllCompetitors() {
|
||||
if (allCompetitorsCache == null) {
|
||||
final Set<Competitor> result = new HashSet<>();
|
||||
@@ -145,59 +163,59 @@ public class CompetitorProviderFromRaceColumnsAndRegattaLike {
|
||||
rc.getRaceLog(fleet).addListener(raceLogCompetitorsCacheInvalidationListener);
|
||||
}
|
||||
}
|
||||
// note: adding listeners is idempotent; at most one occurrence of this listener exists in the race/regatta log's
|
||||
// listeners set
|
||||
provider.addRaceColumnListener(raceColumnListener);
|
||||
// consider {@link RegattaLog}
|
||||
Set<Competitor> viaLog = getCompetitorsFromRegattaLogAndRegisterAsRegattaLogListener();
|
||||
result.addAll(viaLog);
|
||||
// consider {@link RegattaLog} competitor changes because the RaceColumns may have added the competitors from there
|
||||
provider.getRegattaLike().getRegattaLog().addListener(regattaLogCompetitorsCacheInvalidationListener);
|
||||
allCompetitorsCache = result;
|
||||
}
|
||||
return allCompetitorsCache;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtains competitors from the regatta log and adds those from the tracked race for the
|
||||
* raceColumn/fleet combination or the race log, if no tracked race is attached for this
|
||||
* combination. Does <em>not</em> eliminate suppressed competitors.
|
||||
* Obtains competitors from the regatta log and adds those from the tracked race for the raceColumn/fleet
|
||||
* combination or the race log, if no tracked race is attached for this combination. Does <em>not</em> eliminate
|
||||
* suppressed competitors.
|
||||
*/
|
||||
public Iterable<Competitor> getAllCompetitors(final RaceColumn raceColumn, final Fleet fleet) {
|
||||
Pair<RaceColumn, Fleet> key = new Pair<>(raceColumn, fleet);
|
||||
Iterable<Competitor> result = allCompetitorsCacheByRace.get(key);
|
||||
if (result == null) {
|
||||
final Set<Competitor> resultSet = new HashSet<>();
|
||||
final Set<Competitor> resultSet = new HashSet<>();
|
||||
//raceColumn already considers trackedRace, RaceLog and RegattaLog
|
||||
Util.addAll(raceColumn.getAllCompetitors(fleet), resultSet);
|
||||
// note: adding listeners is idempotent; at most one occurrence of this listener exists in the race log's listeners set
|
||||
// note: adding listeners is idempotent; at most one occurrence of this listener exists in the race/regatta log's
|
||||
// listeners set
|
||||
raceColumn.getRaceLog(fleet).addListener(raceLogCompetitorsCacheInvalidationListener);
|
||||
provider.addRaceColumnListener(raceColumnListener);
|
||||
// consider {@link RegattaLog}
|
||||
Set<Competitor> viaLog = getCompetitorsFromRegattaLogAndRegisterAsRegattaLogListener();
|
||||
resultSet.addAll(viaLog);
|
||||
// consider {@link RegattaLog} competitor changes because the RaceColumns may have added the competitors from there
|
||||
provider.getRegattaLike().getRegattaLog().addListener(regattaLogCompetitorsCacheInvalidationListener);
|
||||
result = resultSet;
|
||||
allCompetitorsCacheByRace.put(key, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Set<Competitor> getCompetitorsFromRegattaLogAndRegisterAsRegattaLogListener() {
|
||||
Set<Competitor> viaLog = new RegisteredCompetitorsAnalyzer<>(provider.getRegattaLike().getRegattaLog()).analyze();
|
||||
// note: adding listeners is idempotent; at most one occurrence of this listener exists in the regatta log's listeners set
|
||||
provider.getRegattaLike().getRegattaLog().addListener(regattaLogCompetitorsCacheInvalidationListener);
|
||||
return viaLog;
|
||||
}
|
||||
|
||||
private void invalidateAllCompetitorsCaches() {
|
||||
allCompetitorsCache = null;
|
||||
// note: adding listeners was idempotent; at most one occurrence of this listener exists in the regatta log's listeners set
|
||||
// note: adding listeners was idempotent; at most one occurrence of this listener exists in the regatta log's
|
||||
// listeners set
|
||||
provider.getRegattaLike().getRegattaLog().removeListener(regattaLogCompetitorsCacheInvalidationListener);
|
||||
for (final RaceColumn rc : provider.getRaceColumns()) {
|
||||
for (final Fleet fleet : rc.getFleets()) {
|
||||
// note: adding listeners was idempotent; at most one occurrence of this listener exists in the race log's listeners set
|
||||
// note: adding listeners was idempotent; at most one occurrence of this listener exists in the race
|
||||
// log's listeners set
|
||||
rc.getRaceLog(fleet).removeListener(raceLogCompetitorsCacheInvalidationListener);
|
||||
}
|
||||
}
|
||||
// note: adding listeners was idempotent; at most one occurrence of this listener exists in the race column listeners set
|
||||
// note: adding listeners was idempotent; at most one occurrence of this listener exists in the race column
|
||||
// listeners set
|
||||
provider.removeRaceColumnListener(raceColumnListener);
|
||||
allCompetitorsCacheByRace.clear(); // this is a little coarse-grained; but given the typical access patterns it should be good enough.
|
||||
// The change frequency of competitors lists on individual races is much lower than the access frequency to this structure.
|
||||
allCompetitorsCacheByRace.clear(); // this is a little coarse-grained; but given the typical access patterns it
|
||||
// should be good enough.
|
||||
// The change frequency of competitors lists on individual races is much lower than the access frequency to this
|
||||
// structure.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user