Merge branch 'master' into mark-rounding-inference

Conflicts:
	java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java
	java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SharedDomainFactory.java
	java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java
	java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java
	java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java
	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
	mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/domain/impl/DomainFactoryImpl.java
	mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/coursedesign/CourseElementListAdapter.java
	mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/coursedesign/DraggableCourseElementListAdapter.java
	mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/dialogs/coursedesign/ESSCourseDesignDialog.java
This commit is contained in:
Nick Klose committed 2013-12-09 13:22:09 +01:00
commit 96075f5cc1
784 files changed
+22102 -12039

No files matched your search

+1 -1
View File
@@ -1,5 +1,6 @@
/target
build.log
reporting.log
.metadata
*.class
*.swp
@@ -28,4 +29,3 @@ java/com.sap.sailing.simulator/bin/com/sap/sailing/simulator/Simulator.gwt.xml
/mobile/com.sap.sailing.racecommittee.app/res/values/keys.xml
/mobile/google-play-services_lib/gen/*
/mobile/google-play-services_lib/gen/com/google/android/gms/BuildConfig.java
+46 -2
View File
@@ -1,6 +1,7 @@
#!/bin/bash
set -o functrace
find_project_home ()
{
if [[ $1 == '/' ]] || [[ $1 == "" ]]; then
@@ -76,15 +77,19 @@ testing=1
clean="clean"
offline=0
proxy=0
android=1
reporting=0
suppress_confirmation=0
extra=''
if [ $# -eq 0 ]; then
echo "buildAndUpdateProduct [-b -u -g -t -o -c -m <config> -n <package> -l <port>] [build|install|all|hot-deploy|remote-deploy|release]"
echo "buildAndUpdateProduct [-b -u -g -t -a -o -c -m <config> -n <package> -l <port>] [build|install|all|hot-deploy|remote-deploy|release]"
echo ""
echo "-g Disable GWT compile, no gwt files will be generated, old ones will be preserved."
echo "-b Build GWT permutation only for one browser and English language."
echo "-t Disable tests"
echo "-a Disable mobile projects (RaceCommittee App)"
echo "-r Enable generating surefire test reports"
echo "-o Enable offline mode (does not work for tycho surefire plugin)"
echo "-c Disable cleaning (use only if you are sure that no java file has changed)"
echo "-p Enable proxy mode (overwrites file specified by -m)"
@@ -126,7 +131,7 @@ echo SERVERS_HOME is $SERVERS_HOME
echo BRANCH is $active_branch
echo VERSION is $VERSION_INFO
options=':bgtocpm:n:l:s:w:u'
options=':bgtocparm:n:l:s:w:u'
while getopts $options option
do
case $option in
@@ -136,6 +141,8 @@ do
o) offline=1;;
c) clean="";;
p) proxy=1;;
a) android=0;;
r) reporting=1;;
m) MAVEN_SETTINGS=$OPTARG;;
n) OSGI_BUNDLE_NAME=$OPTARG;;
l) OSGI_TELNET_PORT=$OPTARG;;
@@ -417,6 +424,9 @@ if [[ "$@" == "build" ]] || [[ "$@" == "all" ]]; then
extra="-Pdebug.no-gwt-compile"
fi
# back to root!
cd $PROJECT_HOME
if [ $testing -eq 0 ]; then
echo "INFO: Skipping tests"
extra="$extra -Dmaven.test.skip=true -DskipTests=true"
@@ -437,6 +447,30 @@ if [[ "$@" == "build" ]] || [[ "$@" == "all" ]]; then
extra="$extra -P no-debug.without-proxy"
fi
if [ $android -eq 1 ]; then
if [[ $ANDROID_HOME == "" ]]; then
echo "Environment variable ANDROID_HOME not found. Aborting."
echo "Deactivate mobile build with parameter -a."
exit
fi
echo "ANDROID_HOME=$ANDROID_HOME"
PATH=$PATH:$ANDROID_HOME/tools
PATH=$PATH:$ANDROID_HOME/platform-tools
RC_APP_VERSION=`grep "android:versionCode=" mobile/com.sap.sailing.racecommittee.app/AndroidManifest.xml | cut -d "\"" -f 2`
echo "RC_APPVERSION=$RC_APP_VERSION"
extra="$extra -Drc-app-api-version=$RC_APP_VERSION"
else
echo "INFO: Deactivating mobile modules"
extra="$extra -P !with-mobile"
fi
if [ $reporting -eq 1 ]; then
echo "INFO: Activating reporting"
extra="$extra -Dreportsdirectory=$PROJECT_HOME/target/surefire-reports"
fi
# make sure to honour the service configuration
# needed to make sure that tests use the right servers
APP_PARAMETERS="-Dmongo.host=$MONGODB_HOST -Dmongo.port=$MONGODB_PORT -Dexpedition.udp.port=$EXPEDITION_PORT -Dreplication.exchangeHost=$REPLICATION_HOST -Dreplication.exchangeName=$REPLICATION_CHANNEL"
@@ -445,6 +479,16 @@ if [[ "$@" == "build" ]] || [[ "$@" == "all" ]]; then
echo "Maven version used: `mvn --version`"
mvn $extra -DargLine="$APP_PARAMETERS" -fae -s $MAVEN_SETTINGS $clean install 2>&1 | tee $START_DIR/build.log
if [ $reporting -eq 1 ]; then
echo "INFO: Generating reports"
echo "Using following command: mvn $extra -DargLine=\"$APP_PARAMETERS\" -fae -s $MAVEN_SETTINGS surefire-report:report-only"
mvn $extra -DargLine="$APP_PARAMETERS" -fae -s $MAVEN_SETTINGS surefire-report:report-only 2>&1 | tee $START_DIR/reporting.log
tar -xzf configuration/surefire-reports-resources.tar.gz
echo "INFO: Reports generated in $PROJECT_HOME/target/site/surefire-report.html"
echo "INFO: Be sure to check the result of the actual BUILD run!"
fi
cd $PROJECT_HOME/java
if [ $gwtcompile -eq 1 ]; then
# Now move back the backup .gwt.xml files before they were (maybe) patched
echo "INFO: restoring backup copies of .gwt.xml files after they has been patched before"
Binary file not shown.
@@ -7,6 +7,8 @@ Bundle-Vendor: SAP
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Export-Package: com.sap.sailing.domain.common,
com.sap.sailing.domain.common.configuration,
com.sap.sailing.domain.common.dto,
com.sap.sailing.domain.common.filter,
com.sap.sailing.domain.common.impl,
com.sap.sailing.domain.common.media,
@@ -14,5 +16,4 @@ Export-Package: com.sap.sailing.domain.common,
com.sap.sailing.domain.common.quadtree.impl;x-friends:="com.sap.sailing.domain.test",
com.sap.sailing.domain.common.racelog,
com.sap.sailing.domain.common.racelog.utils,
com.sap.sailing.domain.common.dto,
com.sap.sailing.domain.common.trackfiles
@@ -0,0 +1,37 @@
package com.sap.sailing.domain.common;
import java.util.ArrayList;
import java.util.List;
/**
* Used to decided which Course Designer to pick.
*
* When modifying these values also check res/preferences.xml of racecommittee.app!
*/
public enum CourseDesignerMode {
UNKNOWN("Unknown"),
BY_NAME("By-Name Course Designer"), // O2, O3, I2,...
BY_MAP("By-Map Course Designer"), // Map-based Course Designer
BY_MARKS("By-Marks Course Designer"); // ESS
private String displayName;
private CourseDesignerMode(String displayName) {
this.displayName = displayName;
}
@Override
public String toString() {
return displayName;
}
public static CourseDesignerMode[] validValues() {
List<CourseDesignerMode> validValues = new ArrayList<CourseDesignerMode>();
for (CourseDesignerMode type : values()) {
if (type != UNKNOWN) {
validValues.add(type);
}
}
return validValues.toArray(new CourseDesignerMode[0]);
}
}
@@ -0,0 +1,16 @@
package com.sap.sailing.domain.common.configuration;
public enum DeviceConfigurationMatcherType {
SINGLE(1), MULTI(2);
private int matchingRank;
private DeviceConfigurationMatcherType(int rank) {
this.matchingRank = rank;
}
public int getRank() {
return matchingRank;
}
}
@@ -0,0 +1,31 @@
package com.sap.sailing.domain.common.impl;
import com.sap.sailing.domain.common.impl.Util.Pair;
public class QRCodeUtils {
private static final String fragmentKey = "identifier";
public static String composeQRContent(String deviceIdentifier, String apkUrl) {
// poor man's uri fragment encoding: ' ' as '%20'
String encodedIdentifier = deviceIdentifier.replaceAll(" ", "%20");
return apkUrl + "#" + fragmentKey + "=" + encodedIdentifier;
}
public static Pair<String, String> splitQRContent(String qrCodeContent) {
int fragmentIndex = qrCodeContent.lastIndexOf('#');
if (fragmentIndex == -1 || fragmentIndex == 0 || qrCodeContent.length() == fragmentIndex + 1) {
throw new IllegalArgumentException("There is no server or identifier.");
}
String deviceIdentifier = qrCodeContent.substring(fragmentIndex + 1, qrCodeContent.length());
if (!deviceIdentifier.startsWith(fragmentKey + "=")) {
throw new IllegalArgumentException("The identifier is malformed");
}
deviceIdentifier = deviceIdentifier.substring((fragmentKey + "=").length());
deviceIdentifier = deviceIdentifier.replaceAll("%20", " ");
String apkUrl = qrCodeContent.substring(0, fragmentIndex);
return new Pair<String, String>(deviceIdentifier, apkUrl);
}
}
@@ -0,0 +1,37 @@
package com.sap.sailing.domain.common.racelog;
public class FlagPole {
private final Flags upperFlag;
private final Flags lowerFlag;
private final boolean isDisplayed;
public FlagPole(Flags flag, boolean isDisplayed) {
this(flag, Flags.NONE, isDisplayed);
}
public FlagPole(Flags upperFlag, Flags lowerFlag, boolean isDisplayed) {
this.upperFlag = upperFlag;
this.lowerFlag = lowerFlag;
this.isDisplayed = isDisplayed;
}
public Flags getUpperFlag() {
return upperFlag;
}
public Flags getLowerFlag() {
return lowerFlag;
}
public boolean isDisplayed() {
return isDisplayed;
}
public boolean describesSame(FlagPole otherPole) {
return this.upperFlag == otherPole.upperFlag &&
this.lowerFlag == otherPole.lowerFlag &&
this.isDisplayed == otherPole.isDisplayed;
}
}
@@ -1,5 +1,8 @@
package com.sap.sailing.domain.common.racelog;
import java.util.ArrayList;
import java.util.List;
public enum Flags {
NONE,
ALPHA,
@@ -20,5 +23,15 @@ public enum Flags {
AP,
ESSONE,
ESSTWO,
ESSTHREE
ESSTHREE;
public static Flags[] validValues() {
List<Flags> validValues = new ArrayList<Flags>();
for (Flags flag : values()) {
if (flag != NONE) {
validValues.add(flag);
}
}
return validValues.toArray(new Flags[validValues.size()]);
}
}
@@ -0,0 +1,38 @@
package com.sap.sailing.domain.common.racelog;
import java.util.ArrayList;
import java.util.List;
/**
* Used to identify a RacingProcedure's type.
*
* When modifying these values also check res/preferences.xml of racecommittee.app!
*/
public enum RacingProcedureType {
UNKNOWN("Unknown"),
RRS26("Fix Line Start (RRS26)"),
GateStart("Gate Start"),
ESS("\"Extreme Sailing Series\"-Start"),
BASIC("Basic Countdown Start");
private String displayName;
private RacingProcedureType(String displayName) {
this.displayName = displayName;
}
@Override
public String toString() {
return displayName;
}
public static RacingProcedureType[] validValues() {
List<RacingProcedureType> validValues = new ArrayList<RacingProcedureType>();
for (RacingProcedureType type : values()) {
if (type != UNKNOWN) {
validValues.add(type);
}
}
return validValues.toArray(new RacingProcedureType[0]);
}
}
@@ -1,18 +0,0 @@
package com.sap.sailing.domain.common.racelog;
public enum StartProcedureType {
RRS26("Fix Line Start (RRS26)"),
GateStart("Gate Start"),
ESS("\"Extreme Sailing Series\"-Start");
private String displayName;
private StartProcedureType(String displayName) {
this.displayName = displayName;
}
@Override
public String toString() {
return displayName;
}
}
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.persistence;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import com.mongodb.DBObject;
import com.sap.sailing.domain.base.Competitor;
@@ -10,6 +11,8 @@ import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.RegattaRegistry;
import com.sap.sailing.domain.base.configuration.DeviceConfiguration;
import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.leaderboard.Leaderboard;
@@ -97,4 +100,6 @@ public interface DomainObjectFactory {
Collection<Competitor> loadAllCompetitors();
DomainFactory getBaseDomainFactory();
Iterable<Entry<DeviceConfigurationMatcher, DeviceConfiguration>> loadAllDeviceConfigurations();
}
@@ -9,6 +9,8 @@ import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.configuration.DeviceConfiguration;
import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
@@ -102,4 +104,8 @@ public interface MongoObjectFactory {
DB getDatabase();
void storeDeviceConfiguration(DeviceConfigurationMatcher matcher, DeviceConfiguration configuration);
void removeDeviceConfiguration(DeviceConfigurationMatcher matcher);
}
@@ -51,10 +51,16 @@ public enum CollectionNames {
/**
* Stores the race log events for a tracked race.
*/
RACE_LOGS,
/**
* Stores competitors for smartphone tracking.
*/
COMPETITORS,
RACE_LOGS,
/**
* Stores configurations for mobile devices.
*/
CONFIGURATIONS;
}
@@ -7,6 +7,7 @@ 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;
@@ -15,6 +16,7 @@ import java.util.logging.Logger;
import org.bson.types.ObjectId;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
@@ -41,6 +43,11 @@ import com.sap.sailing.domain.base.RegattaRegistry;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.Venue;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.configuration.DeviceConfiguration;
import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher;
import com.sap.sailing.domain.base.configuration.RegattaConfiguration;
import com.sap.sailing.domain.base.configuration.impl.DeviceConfigurationImpl;
import com.sap.sailing.domain.base.configuration.impl.RegattaConfigurationImpl;
import com.sap.sailing.domain.base.impl.CourseDataImpl;
import com.sap.sailing.domain.base.impl.EventImpl;
import com.sap.sailing.domain.base.impl.FleetImpl;
@@ -61,6 +68,7 @@ import com.sap.sailing.domain.common.SpeedWithBearing;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.WindSourceType;
import com.sap.sailing.domain.common.configuration.DeviceConfigurationMatcherType;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.domain.common.impl.DegreePosition;
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
@@ -72,7 +80,7 @@ import com.sap.sailing.domain.common.impl.WindSourceImpl;
import com.sap.sailing.domain.common.impl.WindSourceWithAdditionalID;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.domain.common.racelog.StartProcedureType;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
import com.sap.sailing.domain.leaderboard.DelayedLeaderboardCorrections;
import com.sap.sailing.domain.leaderboard.DelayedLeaderboardCorrections.LeaderboardCorrectionsResolvedListener;
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
@@ -90,10 +98,12 @@ import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRul
import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
import com.sap.sailing.domain.persistence.MongoRaceLogStoreFactory;
import com.sap.sailing.domain.racelog.CompetitorResults;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogCourseAreaChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogCourseDesignChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogEventRestoreFactory;
import com.sap.sailing.domain.racelog.RaceLogFinishPositioningConfirmedEvent;
import com.sap.sailing.domain.racelog.RaceLogFinishPositioningListChangedEvent;
@@ -108,14 +118,20 @@ import com.sap.sailing.domain.racelog.RaceLogStartProcedureChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent;
import com.sap.sailing.domain.racelog.RaceLogStore;
import com.sap.sailing.domain.racelog.RaceLogWindFixEvent;
import com.sap.sailing.domain.racelog.impl.CompetitorResultsImpl;
import com.sap.sailing.domain.racelog.impl.RaceLogEventAuthorImpl;
import com.sap.sailing.domain.racelog.impl.RaceLogImpl;
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
import com.sap.sailing.domain.tracking.Wind;
import com.sap.sailing.domain.tracking.WindTrack;
import com.sap.sailing.domain.tracking.impl.WindImpl;
import com.sap.sailing.domain.tracking.impl.WindTrackImpl;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.DeviceConfigurationJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.Helpers;
import com.sap.sailing.server.gateway.deserialization.impl.RegattaConfigurationJsonDeserializer;
public class DomainObjectFactoryImpl implements DomainObjectFactory {
private static final Logger logger = Logger.getLogger(DomainObjectFactoryImpl.class.getName());
@@ -839,7 +855,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
private CourseArea loadCourseArea(DBObject courseAreaDBObject) {
String name = (String) courseAreaDBObject.get(FieldNames.COURSE_AREA_NAME.name());
Serializable id = (Serializable) courseAreaDBObject.get(FieldNames.COURSE_AREA_ID.name());
UUID id = (UUID) courseAreaDBObject.get(FieldNames.COURSE_AREA_ID.name());
return baseDomainFactory.getOrCreateCourseArea(id, name);
}
@@ -890,7 +906,18 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
courseArea = baseDomainFactory.getExistingCourseAreaById(courseAreaUuid);
}
RegattaConfiguration configuration = null;
if (dbRegatta.containsField(FieldNames.REGATTA_REGATTA_CONFIGURATION.name())) {
try {
JSONObject json = Helpers.toJSONObjectSafe(new JSONParser().parse(JSON.serialize(dbRegatta.get(FieldNames.REGATTA_REGATTA_CONFIGURATION.name()))));
configuration = RegattaConfigurationJsonDeserializer.create().deserialize(json);
} catch (JsonDeserializationException|ParseException e) {
logger.log(Level.WARNING, "Error loading racing procedure configration for regatta.", e);
}
}
result = new RegattaImpl(raceLogStore, baseName, boatClass, series, /* persistent */ true, loadScoringScheme(dbRegatta), id, courseArea);
result.setRegattaConfiguration(configuration);
}
return result;
}
@@ -1022,9 +1049,19 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
query.put(FieldNames.RACE_LOG_IDENTIFIER.name(), TripleSerializer.serialize(identifier.getIdentifier()));
loadRaceLogEvents(result, query);
// query for events with deprecated identifier format
// query for events with deprecated identifier format...
query.put(FieldNames.RACE_LOG_IDENTIFIER.name(), MongoUtils.escapeDollarAndDot(identifier.getDeprecatedIdentifier()));
loadRaceLogEvents(result, query);
List<RaceLogEvent> eventsToMigrate = loadRaceLogEvents(result, query);
if (!eventsToMigrate.isEmpty()) {
// ... migrate them...
MongoRaceLogStoreVisitor storeVisitor = new MongoRaceLogStoreVisitor(identifier, new MongoObjectFactoryImpl(database));
for (RaceLogEvent event : eventsToMigrate) {
event.accept(storeVisitor);
}
// ... and delete the old ones...
database.getCollection(CollectionNames.RACE_LOGS.name()).remove(query);
}
} catch (Throwable t) {
// something went wrong during DB access; report, then use empty new race log
logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load recorded race log data. Check MongoDB settings.");
@@ -1033,126 +1070,141 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
return result;
}
private void loadRaceLogEvents(RaceLog result, BasicDBObject query) {
private List<RaceLogEvent> loadRaceLogEvents(RaceLog targetRaceLog, BasicDBObject query) {
List<RaceLogEvent> result = new ArrayList<>();
DBCollection raceLog = database.getCollection(CollectionNames.RACE_LOGS.name());
for (DBObject o : raceLog.find(query)) {
RaceLogEvent raceLogEvent = loadRaceLogEvent((DBObject) o.get(FieldNames.RACE_LOG_EVENT.name()));
if (raceLogEvent != null) {
result.load(raceLogEvent);
targetRaceLog.load(raceLogEvent);
result.add(raceLogEvent);
}
}
return result;
}
public RaceLogEvent loadRaceLogEvent(DBObject dbObject) {
TimePoint timePoint = loadTimePoint(dbObject);
TimePoint logicalTimePoint = loadTimePoint(dbObject);
TimePoint createdAt = loadTimePoint(dbObject, FieldNames.RACE_LOG_EVENT_CREATED_AT);
Serializable id = (Serializable) dbObject.get(FieldNames.RACE_LOG_EVENT_ID.name());
Integer passId = (Integer) dbObject.get(FieldNames.RACE_LOG_EVENT_PASS_ID.name());
BasicDBList dbCompetitors = (BasicDBList) dbObject.get(FieldNames.RACE_LOG_EVENT_INVOLVED_BOATS.name());
List<Competitor> competitors = loadCompetitorsForRaceLogEvent(dbCompetitors);
final RaceLogEventAuthor author;
String authorName = (String) dbObject.get(FieldNames.RACE_LOG_EVENT_AUTHOR_NAME.name());
Number authorPriority = (Number) dbObject.get(FieldNames.RACE_LOG_EVENT_AUTHOR_PRIORITY.name());
if (authorName != null && authorPriority != null) {
author = new RaceLogEventAuthorImpl(authorName, authorPriority.intValue());
} else {
author = RaceLogEventAuthorImpl.createCompatibilityAuthor();
}
String eventClass = (String) dbObject.get(FieldNames.RACE_LOG_EVENT_CLASS.name());
if (eventClass.equals(RaceLogStartTimeEvent.class.getSimpleName())) {
return loadRaceLogStartTimeEvent(createdAt, timePoint, id, passId, competitors, dbObject);
return loadRaceLogStartTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(RaceLogRaceStatusEvent.class.getSimpleName())) {
return loadRaceLogRaceStatusEvent(createdAt, timePoint, id, passId, competitors, dbObject);
return loadRaceLogRaceStatusEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(RaceLogFlagEvent.class.getSimpleName())) {
return loadRaceLogFlagEvent(createdAt, timePoint, id, passId, competitors, dbObject);
return loadRaceLogFlagEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(RaceLogPassChangeEvent.class.getSimpleName())) {
return loadRaceLogPassChangeEvent(createdAt, timePoint, id, passId, competitors);
return loadRaceLogPassChangeEvent(createdAt, author, logicalTimePoint, id, passId, competitors);
} else if (eventClass.equals(RaceLogCourseAreaChangedEvent.class.getSimpleName())) {
return loadRaceLogCourseAreaChangedEvent(createdAt, timePoint, id, passId, competitors, dbObject);
return loadRaceLogCourseAreaChangedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(RaceLogCourseDesignChangedEvent.class.getSimpleName())) {
return loadRaceLogCourseDesignChangedEvent(createdAt, timePoint, id, passId, competitors, dbObject);
return loadRaceLogCourseDesignChangedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(RaceLogFinishPositioningListChangedEvent.class.getSimpleName())) {
return loadRaceLogFinishPositioningListChangedEvent(createdAt, timePoint, id, passId, competitors, dbObject);
return loadRaceLogFinishPositioningListChangedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(RaceLogFinishPositioningConfirmedEvent.class.getSimpleName())) {
return loadRaceLogFinishPositioningConfirmedEvent(createdAt, timePoint, id, passId, competitors, dbObject);
return loadRaceLogFinishPositioningConfirmedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(RaceLogPathfinderEvent.class.getSimpleName())) {
return loadRaceLogPathfinderEvent(createdAt, timePoint, id, passId, competitors, dbObject);
return loadRaceLogPathfinderEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(RaceLogGateLineOpeningTimeEvent.class.getSimpleName())) {
return loadRaceLogGateLineOpeningTimeEvent(createdAt, timePoint, id, passId, competitors, dbObject);
return loadRaceLogGateLineOpeningTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(RaceLogStartProcedureChangedEvent.class.getSimpleName())) {
return loadRaceLogStartProcedureChangedEvent(createdAt, timePoint, id, passId, competitors, dbObject);
return loadRaceLogStartProcedureChangedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(RaceLogProtestStartTimeEvent.class.getSimpleName())) {
return loadRaceLogRaceLogProtestStartTimeEvent(createdAt, timePoint, id, passId, competitors, dbObject);
return loadRaceLogRaceLogProtestStartTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(RaceLogWindFixEvent.class.getSimpleName())) {
return loadRaceLogRaceLogWindFixEvent(createdAt, timePoint, id, passId, competitors, dbObject);
return loadRaceLogRaceLogWindFixEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
}
throw new IllegalStateException(String.format("Unknown RaceLogEvent type %s", eventClass));
}
private RaceLogEvent loadRaceLogRaceLogWindFixEvent(TimePoint createdAt, TimePoint timePoint, Serializable id,
Integer passId, List<Competitor> competitors, DBObject dbObject) {
private RaceLogEvent loadRaceLogRaceLogWindFixEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
Wind wind = loadWind((DBObject) dbObject.get(FieldNames.WIND.name()));
return raceLogEventFactory.createWindFixEvent(createdAt, timePoint, id, competitors, passId, wind);
return raceLogEventFactory.createWindFixEvent(createdAt, author, logicalTimePoint, id, competitors, passId, wind);
}
private RaceLogEvent loadRaceLogRaceLogProtestStartTimeEvent(TimePoint createdAt, TimePoint timePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
private RaceLogEvent loadRaceLogRaceLogProtestStartTimeEvent(TimePoint createdAt, RaceLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
TimePoint protestStartTime = loadTimePoint(dbObject, FieldNames.RACE_LOG_PROTEST_START_TIME);
return raceLogEventFactory.createProtestStartTimeEvent(createdAt, timePoint, id, competitors, passId, protestStartTime);
return raceLogEventFactory.createProtestStartTimeEvent(createdAt, author, logicalTimePoint, id, competitors, passId, protestStartTime);
}
private RaceLogEvent loadRaceLogStartProcedureChangedEvent(TimePoint createdAt, TimePoint timePoint,
private RaceLogEvent loadRaceLogStartProcedureChangedEvent(TimePoint createdAt, RaceLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
RacingProcedureType type = RacingProcedureType.valueOf(dbObject.get(FieldNames.RACE_LOG_START_PROCEDURE_TYPE.name()).toString());
return raceLogEventFactory.createStartProcedureChangedEvent(createdAt, author, logicalTimePoint, id, competitors, passId, type);
}
private RaceLogEvent loadRaceLogGateLineOpeningTimeEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
StartProcedureType type = StartProcedureType.valueOf(dbObject.get(FieldNames.RACE_LOG_START_PROCEDURE_TYPE.name()).toString());
return raceLogEventFactory.createStartProcedureChangedEvent(createdAt, timePoint, id, competitors, passId, type);
}
private RaceLogEvent loadRaceLogGateLineOpeningTimeEvent(TimePoint createdAt, TimePoint timePoint, Serializable id,
Integer passId, List<Competitor> competitors, DBObject dbObject) {
Number gateLineOpeningTime = (Number) dbObject.get(FieldNames.RACE_LOG_GATE_LINE_OPENING_TIME.name());
return raceLogEventFactory.createGateLineOpeningTimeEvent(createdAt, timePoint, id, competitors, passId,
gateLineOpeningTime == null ? null : gateLineOpeningTime.longValue());
Number gateLaunchStopTime = (Number) dbObject.get(FieldNames.RACE_LOG_GATE_LINE_OPENING_TIME.name());
Number golfDownTime = 0;
if (dbObject.containsField(FieldNames.RACE_LOG_GOLF_DOWN_TIME.name())) {
golfDownTime = (Number) dbObject.get(FieldNames.RACE_LOG_GOLF_DOWN_TIME.name());
}
return raceLogEventFactory.createGateLineOpeningTimeEvent(createdAt, author, logicalTimePoint, id, competitors,
passId, gateLaunchStopTime == null ? null : gateLaunchStopTime.longValue(), golfDownTime.longValue());
}
private RaceLogEvent loadRaceLogPathfinderEvent(TimePoint createdAt, TimePoint timePoint, Serializable id,
Integer passId, List<Competitor> competitors, DBObject dbObject) {
private RaceLogEvent loadRaceLogPathfinderEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
String pathfinderId = dbObject.get(FieldNames.RACE_LOG_PATHFINDER_ID.name()).toString();
return raceLogEventFactory.createPathfinderEvent(createdAt, timePoint, id, competitors, passId, pathfinderId);
return raceLogEventFactory.createPathfinderEvent(createdAt, author, logicalTimePoint, id, competitors, passId, pathfinderId);
}
private RaceLogEvent loadRaceLogFinishPositioningConfirmedEvent(TimePoint createdAt, TimePoint timePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
private RaceLogEvent loadRaceLogFinishPositioningConfirmedEvent(TimePoint createdAt, RaceLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
BasicDBList dbPositionedCompetitorList = (BasicDBList) dbObject.get(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name());
List<Triple<Serializable, String, MaxPointsReason>> positionedCompetitors = null;
CompetitorResults positionedCompetitors = null;
//When a confirmation event is loaded that does not contain the positioned competitors (this is the case for the ESS events in
//Singapore and Quingdao) then null should be set for the positionedCompetitors, which is evaluated later on.
if (dbPositionedCompetitorList != null) {
positionedCompetitors = loadPositionedCompetitors(dbPositionedCompetitorList);
}
return raceLogEventFactory.createFinishPositioningConfirmedEvent(createdAt, timePoint, id, competitors, passId, positionedCompetitors);
return raceLogEventFactory.createFinishPositioningConfirmedEvent(createdAt, author, logicalTimePoint, id, competitors, passId, positionedCompetitors);
}
private RaceLogEvent loadRaceLogFinishPositioningListChangedEvent(TimePoint createdAt, TimePoint timePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
private RaceLogEvent loadRaceLogFinishPositioningListChangedEvent(TimePoint createdAt, RaceLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
BasicDBList dbPositionedCompetitorList = (BasicDBList) dbObject.get(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name());
List<Triple<Serializable, String, MaxPointsReason>> positionedCompetitors = loadPositionedCompetitors(dbPositionedCompetitorList);
CompetitorResults positionedCompetitors = loadPositionedCompetitors(dbPositionedCompetitorList);
return raceLogEventFactory.createFinishPositioningListChangedEvent(createdAt, timePoint, id, competitors, passId, positionedCompetitors);
return raceLogEventFactory.createFinishPositioningListChangedEvent(createdAt, author, logicalTimePoint, id, competitors, passId, positionedCompetitors);
}
private RaceLogEvent loadRaceLogPassChangeEvent(TimePoint createdAt, TimePoint timePoint, Serializable id,
Integer passId, List<Competitor> competitors) {
return raceLogEventFactory.createPassChangeEvent(createdAt, timePoint, id, competitors, passId);
private RaceLogEvent loadRaceLogPassChangeEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors) {
return raceLogEventFactory.createPassChangeEvent(createdAt, author, logicalTimePoint, id, competitors, passId);
}
private RaceLogCourseDesignChangedEvent loadRaceLogCourseDesignChangedEvent(TimePoint createdAt, TimePoint timePoint, Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
private RaceLogCourseDesignChangedEvent loadRaceLogCourseDesignChangedEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
String courseName = (String) dbObject.get(FieldNames.RACE_LOG_COURSE_DESIGN_NAME.name());
CourseBase courseData = loadCourseData((BasicDBList) dbObject.get(FieldNames.RACE_LOG_COURSE_DESIGN.name()), courseName);
return raceLogEventFactory.createCourseDesignChangedEvent(createdAt, timePoint, id, competitors, passId, courseData);
return raceLogEventFactory.createCourseDesignChangedEvent(createdAt, author, logicalTimePoint, id, competitors, passId, courseData);
}
private RaceLogCourseAreaChangedEvent loadRaceLogCourseAreaChangedEvent(TimePoint createdAt, TimePoint timePoint, Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
private RaceLogCourseAreaChangedEvent loadRaceLogCourseAreaChangedEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
Serializable courseAreaId = (Serializable) dbObject.get(FieldNames.COURSE_AREA_ID.name());
return raceLogEventFactory.createCourseAreaChangedEvent(createdAt, timePoint, id, competitors, passId, courseAreaId);
return raceLogEventFactory.createCourseAreaChangedEvent(createdAt, author, logicalTimePoint, id, competitors, passId, courseAreaId);
}
private List<Triple<Serializable, String, MaxPointsReason>> loadPositionedCompetitors(BasicDBList dbPositionedCompetitorList) {
List<Triple<Serializable, String, MaxPointsReason>> positionedCompetitors = new ArrayList<Triple<Serializable, String, MaxPointsReason>>();
private CompetitorResults loadPositionedCompetitors(BasicDBList dbPositionedCompetitorList) {
CompetitorResults positionedCompetitors = new CompetitorResultsImpl();
for (Object object : dbPositionedCompetitorList) {
DBObject dbObject = (DBObject) object;
@@ -1181,13 +1233,13 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
List<Competitor> competitors = new ArrayList<Competitor>();
for (Object object : dbCompetitorList) {
Serializable competitorId = (Serializable) object;
Competitor competitor = baseDomainFactory.getExistingCompetitorById(competitorId);
Competitor competitor = baseDomainFactory.getCompetitorStore().getExistingCompetitorById(competitorId);
competitors.add(competitor);
}
return competitors;
}
private RaceLogFlagEvent loadRaceLogFlagEvent(TimePoint createdAt, TimePoint timePoint, Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
private RaceLogFlagEvent loadRaceLogFlagEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
Flags upperFlag = Flags.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_FLAG_UPPER.name()));
Flags lowerFlag = Flags.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_FLAG_LOWER.name()));
Boolean displayed = Boolean.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_FLAG_DISPLAYED.name()));
@@ -1196,17 +1248,17 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
return null;
}
return raceLogEventFactory.createFlagEvent(createdAt, timePoint, id, competitors, passId, upperFlag, lowerFlag, displayed);
return raceLogEventFactory.createFlagEvent(createdAt, author, logicalTimePoint, id, competitors, passId, upperFlag, lowerFlag, displayed);
}
private RaceLogStartTimeEvent loadRaceLogStartTimeEvent(TimePoint createdAt, TimePoint timePoint, Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
private RaceLogStartTimeEvent loadRaceLogStartTimeEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
TimePoint startTime = loadTimePoint(dbObject, FieldNames.RACE_LOG_EVENT_START_TIME);
return raceLogEventFactory.createStartTimeEvent(createdAt, timePoint, id, competitors, passId, startTime);
return raceLogEventFactory.createStartTimeEvent(createdAt, author, logicalTimePoint, id, competitors, passId, startTime);
}
private RaceLogRaceStatusEvent loadRaceLogRaceStatusEvent(TimePoint createdAt, TimePoint timePoint, Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
private RaceLogRaceStatusEvent loadRaceLogRaceStatusEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
RaceLogRaceStatus nextStatus = RaceLogRaceStatus.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name()));
return raceLogEventFactory.createRaceStatusEvent(createdAt, timePoint, id, competitors, passId, nextStatus);
return raceLogEventFactory.createRaceStatusEvent(createdAt, author, logicalTimePoint, id, competitors, passId, nextStatus);
}
private CourseBase loadCourseData(BasicDBList dbCourseList, String courseName) {
@@ -1288,4 +1340,56 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
}
return result;
}
@Override
public Iterable<Entry<DeviceConfigurationMatcher, DeviceConfiguration>> loadAllDeviceConfigurations() {
Map<DeviceConfigurationMatcher, DeviceConfiguration> result = new HashMap<>();
DBCollection configurationCollection = database.getCollection(CollectionNames.CONFIGURATIONS.name());
try {
for (DBObject dbObject : configurationCollection.find()) {
Pair<DeviceConfigurationMatcher, DeviceConfiguration> entry = loadConfigurationEntry(dbObject);
result.put(entry.getA(), entry.getB());
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load configurations.");
logger.log(Level.SEVERE, "loadAllDeviceConfigurations", e);
}
return result.entrySet();
}
private Pair<DeviceConfigurationMatcher, DeviceConfiguration> loadConfigurationEntry(DBObject dbObject) {
DBObject matcherObject = (DBObject) dbObject.get(FieldNames.CONFIGURATION_MATCHER.name());
DBObject configObject = (DBObject) dbObject.get(FieldNames.CONFIGURATION_CONFIG.name());
return new Pair<DeviceConfigurationMatcher, DeviceConfiguration>(loadConfigurationMatcher(matcherObject),
loadConfiguration(configObject));
}
private DeviceConfigurationMatcher loadConfigurationMatcher(DBObject matcherObject) {
DeviceConfigurationMatcherType type = DeviceConfigurationMatcherType.valueOf(
matcherObject.get(FieldNames.CONFIGURATION_MATCHER_TYPE.name()).toString());
List<String> clientIdentifiers = new ArrayList<String>();
BasicDBList clientIdentifiersObject = (BasicDBList) matcherObject.get(FieldNames.CONFIGURATION_MATCHER_CLIENTS.name());
if (clientIdentifiersObject != null) {
for (Object clientIdentifier : clientIdentifiersObject) {
clientIdentifiers.add(clientIdentifier.toString());
}
}
return baseDomainFactory.getOrCreateDeviceConfigurationMatcher(type, clientIdentifiers);
}
private DeviceConfiguration loadConfiguration(DBObject configObject) {
DeviceConfiguration configuration = null;
try {
JsonDeserializer<DeviceConfiguration> deserializer = DeviceConfigurationJsonDeserializer.create();
JSONObject json = Helpers.toJSONObjectSafe(new JSONParser().parse(JSON.serialize(configObject)));
configuration = deserializer.deserialize(json);
} catch (JsonDeserializationException | ParseException e) {
logger.log(Level.SEVERE, "Error parsing configuration object from MongoDB, falling back to empty configuration.");
logger.log(Level.SEVERE, "loadConfiguration", e);
configuration = new DeviceConfigurationImpl(new RegattaConfigurationImpl());
}
return configuration;
}
}
@@ -18,6 +18,7 @@ public enum FieldNames {
REGATTA_ID,
REGATTA_BASE_NAME,
REGATTA_SERIES,
REGATTA_REGATTA_CONFIGURATION,
SERIES_NAME,
SERIES_IS_MEDAL,
SERIES_STARTS_WITH_ZERO_SCORE,
@@ -69,9 +70,16 @@ public enum FieldNames {
// race log
RACE_LOG_IDENTIFIER,
RACE_LOG_EVENT, RACE_LOG_EVENT_PASS_ID, RACE_LOG_EVENT_ID, RACE_LOG_EVENT_CREATED_AT, RACE_LOG_EVENT_INVOLVED_BOATS, RACE_LOG_EVENT_FLAG_UPPER, RACE_LOG_EVENT_FLAG_LOWER,
RACE_LOG_EVENT, RACE_LOG_EVENT_PASS_ID, RACE_LOG_EVENT_ID, RACE_LOG_EVENT_CREATED_AT, RACE_LOG_EVENT_AUTHOR_NAME, RACE_LOG_EVENT_AUTHOR_PRIORITY,
RACE_LOG_EVENT_INVOLVED_BOATS, RACE_LOG_EVENT_FLAG_UPPER, RACE_LOG_EVENT_FLAG_LOWER,
RACE_LOG_EVENT_FLAG_DISPLAYED, RACE_LOG_EVENT_START_TIME, RACE_LOG_EVENT_CLASS, RACE_LOG_EVENT_NEXT_STATUS, RACE_LOG_COURSE_DESIGN, WAYPOINT_ID,
WAYPOINT_NAME, WAYPOINT_PASSINGINSTRUCTION, CONTROLPOINT, CONTROLPOINT_CLASS, MARK_ID, MARK_COLOR, MARK_NAME, MARK_PATTERN, MARK_SHAPE, MARK_TYPE,
CONTROLPOINT_VALUE, GATE_ID, GATE_NAME, GATE_LEFT, GATE_RIGHT, RACE_LOG_POSITIONED_COMPETITORS, RACE_LOG_PATHFINDER_ID, RACE_LOG_GATE_LINE_OPENING_TIME,
RACE_LOG_START_PROCEDURE_TYPE, RACE_LOG_PROTEST_START_TIME, RACE_LOG_COURSE_DESIGN_NAME;
CONTROLPOINT_VALUE, GATE_ID, GATE_NAME, GATE_LEFT, GATE_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,
// configurations
CONFIGURATION_MATCHER, CONFIGURATION_CONFIG, CONFIGURATION_MATCHER_ID, CONFIGURATION_MATCHER_TYPE, CONFIGURATION_MATCHER_CLIENTS,
CONFIGURATION_CONFIG_ALLOWED_COURSE_AREA_NAMES, CONFIGURATION_CONFIG_MIN_ROUNDS, CONFIGURATION_CONFIG_MAX_ROUNDS, CONFIGURATION_CONFIG_RESULTS_MAIL,
CONFIGURATION_CONFIG_PROCEDURES;
}
@@ -29,6 +29,11 @@ import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.Timed;
import com.sap.sailing.domain.base.Venue;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.configuration.DeviceConfiguration;
import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher;
import com.sap.sailing.domain.base.configuration.RegattaConfiguration;
import com.sap.sailing.domain.base.configuration.impl.DeviceConfigurationMatcherMulti;
import com.sap.sailing.domain.base.configuration.impl.DeviceConfigurationMatcherSingle;
import com.sap.sailing.domain.base.impl.FleetImpl;
import com.sap.sailing.domain.common.Bearing;
import com.sap.sailing.domain.common.MaxPointsReason;
@@ -39,6 +44,7 @@ import com.sap.sailing.domain.common.SpeedWithBearing;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
import com.sap.sailing.domain.leaderboard.Leaderboard;
@@ -51,6 +57,7 @@ import com.sap.sailing.domain.persistence.MongoObjectFactory;
import com.sap.sailing.domain.racelog.RaceLogCourseAreaChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogCourseDesignChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogFinishPositioningConfirmedEvent;
import com.sap.sailing.domain.racelog.RaceLogFinishPositioningListChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogFlagEvent;
@@ -68,7 +75,10 @@ import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.Wind;
import com.sap.sailing.domain.tracking.WindTrack;
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer;
import com.sap.sailing.server.gateway.serialization.impl.DeviceConfigurationJsonSerializer;
import com.sap.sailing.server.gateway.serialization.impl.RegattaConfigurationJsonSerializer;
public class MongoObjectFactoryImpl implements MongoObjectFactory {
private static Logger logger = Logger.getLogger(MongoObjectFactoryImpl.class.getName());
@@ -467,6 +477,12 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
} else {
dbRegatta.put(FieldNames.COURSE_AREA_ID.name(), null);
}
if (regatta.getRegattaConfiguration() != null) {
JsonSerializer<RegattaConfiguration> serializer = RegattaConfigurationJsonSerializer.create();
JSONObject json = serializer.serialize(regatta.getRegattaConfiguration());
DBObject configurationObject = (DBObject) JSON.parse(json.toString());
dbRegatta.put(FieldNames.REGATTA_REGATTA_CONFIGURATION.name(), configurationObject);
}
regattasCollection.update(query, dbRegatta, /* upsrt */ true, /* multi */ false);
}
@@ -545,6 +561,13 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
result.ensureIndex(new BasicDBObject(FieldNames.RACE_LOG_IDENTIFIER.name(), null));
return result;
}
private void storeRaceLogEventAuthor(DBObject dbObject, RaceLogEventAuthor author) {
if (author != null) {
dbObject.put(FieldNames.RACE_LOG_EVENT_AUTHOR_NAME.name(), author.getName());
dbObject.put(FieldNames.RACE_LOG_EVENT_AUTHOR_PRIORITY.name(), author.getPriority());
}
}
public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogFlagEvent flagEvent) {
BasicDBObject result = new BasicDBObject();
@@ -702,11 +725,13 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
}
private void storeRaceLogEventProperties(RaceLogEvent event, DBObject result) {
storeTimed(event, result);
// for compatibility reasons we reuse the field name of Timed
storeTimePoint(event.getLogicalTimePoint(), result, FieldNames.TIME_AS_MILLIS);
storeTimePoint(event.getCreatedAt(), result, FieldNames.RACE_LOG_EVENT_CREATED_AT);
result.put(FieldNames.RACE_LOG_EVENT_ID.name(), event.getId());
result.put(FieldNames.RACE_LOG_EVENT_PASS_ID.name(), event.getPassId());
result.put(FieldNames.RACE_LOG_EVENT_INVOLVED_BOATS.name(), storeInvolvedBoatsForRaceLogEvent(event.getInvolvedBoats()));
storeRaceLogEventAuthor(result, event.getAuthor());
}
@@ -785,7 +810,8 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogGateLineOpeningTimeEvent.class.getSimpleName());
result.put(FieldNames.RACE_LOG_GATE_LINE_OPENING_TIME.name(), gateLineOpeningTimeEvent.getGateLineOpeningTime());
result.put(FieldNames.RACE_LOG_GATE_LINE_OPENING_TIME.name(), gateLineOpeningTimeEvent.getGateLineOpeningTimes().getGateLaunchStopTime());
result.put(FieldNames.RACE_LOG_GOLF_DOWN_TIME.name(), gateLineOpeningTimeEvent.getGateLineOpeningTimes().getGolfDownTime());
return result;
}
@@ -873,7 +899,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
public void storeCompetitor(Competitor competitor) {
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name());
JSONObject json = competitorSerializer.serialize(competitor);
BasicDBObject query = new BasicDBObject(CompetitorJsonSerializer.FIELD_ID, competitor.getId());
DBObject query = (DBObject) JSON.parse(competitorSerializer.getCompetitorIdQuery(competitor).toString());
DBObject entry = (DBObject) JSON.parse(json.toString());
collection.update(query, entry, /* upsrt */true, /* multi */false);
}
@@ -892,4 +918,49 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
BasicDBObject query = new BasicDBObject(CompetitorJsonSerializer.FIELD_ID, competitor.getId().toString());
collection.remove(query);
}
@Override
public void storeDeviceConfiguration(DeviceConfigurationMatcher matcher, DeviceConfiguration configuration) {
DBCollection configurationsCollections = database.getCollection(CollectionNames.CONFIGURATIONS.name());
DBObject query = new BasicDBObject();
query.put(FieldNames.CONFIGURATION_MATCHER_ID.name(), matcher.getMatcherIdentifier());
DBObject entryObject = new BasicDBObject();
entryObject.put(FieldNames.CONFIGURATION_MATCHER_ID.name(), matcher.getMatcherIdentifier());
entryObject.put(FieldNames.CONFIGURATION_MATCHER.name(), createDeviceConfigurationMatcherObject(matcher));
entryObject.put(FieldNames.CONFIGURATION_CONFIG.name(), createDeviceConfigurationObject(configuration));
configurationsCollections.update(query, entryObject, /* upsrt */ true, /* multi */ false);
}
private DBObject createDeviceConfigurationMatcherObject(DeviceConfigurationMatcher matcher) {
DBObject matcherObject = new BasicDBObject();
matcherObject.put(FieldNames.CONFIGURATION_MATCHER_TYPE.name(), matcher.getMatcherType().name());
if (matcher instanceof DeviceConfigurationMatcherSingle) {
BasicDBList client = new BasicDBList();
client.add(((DeviceConfigurationMatcherSingle)matcher).getClientIdentifier());
matcherObject.put(FieldNames.CONFIGURATION_MATCHER_CLIENTS.name(), client);
} else if (matcher instanceof DeviceConfigurationMatcherMulti) {
BasicDBList clients = new BasicDBList();
Util.addAll(((DeviceConfigurationMatcherMulti)matcher).getClientIdentifiers(), clients);
matcherObject.put(FieldNames.CONFIGURATION_MATCHER_CLIENTS.name(), clients);
}
return matcherObject;
}
private DBObject createDeviceConfigurationObject(DeviceConfiguration configuration) {
JsonSerializer<DeviceConfiguration> serializer = DeviceConfigurationJsonSerializer.create();
JSONObject json = serializer.serialize(configuration);
DBObject entry = (DBObject) JSON.parse(json.toString());
return entry;
}
@Override
public void removeDeviceConfiguration(DeviceConfigurationMatcher matcher) {
DBCollection configurationsCollections = database.getCollection(CollectionNames.CONFIGURATIONS.name());
DBObject query = new BasicDBObject();
query.put(FieldNames.CONFIGURATION_MATCHER_ID.name(), matcher.getMatcherIdentifier());
configurationsCollections.remove(query);
}
}
@@ -15,25 +15,27 @@ public class MongoRaceLogStoreImpl implements RaceLogStore {
private final MongoObjectFactory mongoObjectFactory;
private final DomainObjectFactory domainObjectFactory;
private final Map<RaceLogIdentifier, RaceLog> raceLogCache;
private final WeakHashMap<RaceLog, MongoRaceLogListener> listeners;
private final WeakHashMap<RaceLog, MongoRaceLogStoreVisitor> listeners;
public MongoRaceLogStoreImpl(MongoObjectFactory mongoObjectFactory, DomainObjectFactory domainObjectFactory) {
this.mongoObjectFactory = mongoObjectFactory;
this.domainObjectFactory = domainObjectFactory;
this.raceLogCache = new HashMap<>();
this.listeners = new WeakHashMap<RaceLog, MongoRaceLogListener>();
this.listeners = new WeakHashMap<RaceLog, MongoRaceLogStoreVisitor>();
}
@Override
public RaceLog getRaceLog(RaceLogIdentifier identifier, boolean ignoreCache) {
final RaceLog result;
if (!ignoreCache && raceLogCache.containsKey(identifier)) {
return raceLogCache.get(identifier);
result = raceLogCache.get(identifier);
} else {
result = domainObjectFactory.loadRaceLog(identifier);
MongoRaceLogStoreVisitor listener = new MongoRaceLogStoreVisitor(identifier, mongoObjectFactory);
listeners.put(result, listener);
result.addListener(listener);
raceLogCache.put(identifier, result);
}
RaceLog result = domainObjectFactory.loadRaceLog(identifier);
MongoRaceLogListener listener = new MongoRaceLogListener(identifier, mongoObjectFactory);
listeners.put(result, listener);
result.addListener(listener);
raceLogCache.put(identifier, result);
return result;
}
@@ -21,15 +21,15 @@ import com.sap.sailing.domain.racelog.RaceLogStartProcedureChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent;
import com.sap.sailing.domain.racelog.RaceLogWindFixEvent;
public class MongoRaceLogListener implements RaceLogEventVisitor {
public class MongoRaceLogStoreVisitor implements RaceLogEventVisitor {
private final RaceLogIdentifier raceLogIdentifier;
private final MongoObjectFactoryImpl mongoObjectFactory;
private final DBCollection raceLogsCollection;
private final static Logger logger = Logger.getLogger(MongoRaceLogListener.class.getName());
private final static Logger logger = Logger.getLogger(MongoRaceLogStoreVisitor.class.getName());
public MongoRaceLogListener(RaceLogIdentifier identifier, MongoObjectFactory mongoObjectFactory) {
public MongoRaceLogStoreVisitor(RaceLogIdentifier identifier, MongoObjectFactory mongoObjectFactory) {
super();
this.raceLogIdentifier = identifier;
this.mongoObjectFactory = (MongoObjectFactoryImpl) mongoObjectFactory;
@@ -5,21 +5,19 @@ import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.Serializable;
import java.util.List;
import java.util.Arrays;
import org.junit.Test;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.racelog.CompetitorResults;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogFinishPositioningConfirmedEvent;
import com.sap.sailing.domain.racelog.analyzing.impl.ConfirmedFinishPositioningListFinder;
@SuppressWarnings("unchecked")
public class ConfirmedFinishPositioningListFinderTest extends
PassAwareRaceLogAnalyzerTest<ConfirmedFinishPositioningListFinder, List<Triple<Serializable, String, MaxPointsReason>>> {
PassAwareRaceLogAnalyzerTest<ConfirmedFinishPositioningListFinder, CompetitorResults> {
@Override
protected ConfirmedFinishPositioningListFinder createAnalyzer(RaceLog raceLog) {
@@ -27,11 +25,10 @@ public class ConfirmedFinishPositioningListFinderTest extends
}
@Override
protected List<Triple<Serializable, String, MaxPointsReason>> setupTargetEventsForPassAwareTests(int passId) {
RaceLogFinishPositioningConfirmedEvent event = createEvent(RaceLogFinishPositioningConfirmedEvent.class, 1, passId);
when(event.getPositionedCompetitorsIDsNamesMaxPointsReasons()).thenReturn(mock(List.class));
raceLog.add(event);
return event.getPositionedCompetitorsIDsNamesMaxPointsReasons();
protected TargetPair getTargetEventsAndResultForPassAwareTests(int passId, RaceLogEventAuthor author) {
RaceLogFinishPositioningConfirmedEvent event = createEvent(RaceLogFinishPositioningConfirmedEvent.class, 1, passId, author);
when(event.getPositionedCompetitorsIDsNamesMaxPointsReasons()).thenReturn(mock(CompetitorResults.class));
return new TargetPair(Arrays.asList(event), event.getPositionedCompetitorsIDsNamesMaxPointsReasons());
}
@Test
@@ -45,7 +42,7 @@ public class ConfirmedFinishPositioningListFinderTest extends
public void testMostRecent() {
RaceLogFinishPositioningConfirmedEvent event1 = createEvent(RaceLogFinishPositioningConfirmedEvent.class, 1);
RaceLogFinishPositioningConfirmedEvent event2 = createEvent(RaceLogFinishPositioningConfirmedEvent.class, 2);
when(event2.getPositionedCompetitorsIDsNamesMaxPointsReasons()).thenReturn(mock(List.class));
when(event2.getPositionedCompetitorsIDsNamesMaxPointsReasons()).thenReturn(mock(CompetitorResults.class));
raceLog.add(event1);
raceLog.add(event2);
@@ -4,12 +4,15 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import org.junit.Test;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent;
import com.sap.sailing.domain.racelog.analyzing.impl.FinishedTimeFinder;
@@ -19,13 +22,12 @@ public class FinishedTimeFinderTest extends PassAwareRaceLogAnalyzerTest<Finishe
protected FinishedTimeFinder createAnalyzer(RaceLog raceLog) {
return new FinishedTimeFinder(raceLog);
}
@Override
protected TimePoint setupTargetEventsForPassAwareTests(int passId) {
RaceLogRaceStatusEvent event = createEvent(RaceLogRaceStatusEvent.class, 1, passId);
protected TargetPair getTargetEventsAndResultForPassAwareTests(int passId, RaceLogEventAuthor author) {
RaceLogRaceStatusEvent event = createEvent(RaceLogRaceStatusEvent.class, 1, passId, author);
when(event.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHED);
raceLog.add(event);
return event.getTimePoint();
return new TargetPair(Arrays.asList(event), event.getLogicalTimePoint());
}
@Test
@@ -45,7 +47,7 @@ public class FinishedTimeFinderTest extends PassAwareRaceLogAnalyzerTest<Finishe
raceLog.add(event1);
raceLog.add(event2);
assertEquals(event2.getTimePoint(), analyzer.analyze());
assertEquals(event2.getLogicalTimePoint(), analyzer.analyze());
}
@Test
@@ -58,6 +60,6 @@ public class FinishedTimeFinderTest extends PassAwareRaceLogAnalyzerTest<Finishe
raceLog.add(event1);
raceLog.add(event2);
assertEquals(event1.getTimePoint(), analyzer.analyze());
assertEquals(event1.getLogicalTimePoint(), analyzer.analyze());
}
}
@@ -1,15 +1,18 @@
package com.sap.sailing.domain.racelog.analyzing.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import org.junit.Test;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent;
import com.sap.sailing.domain.racelog.analyzing.impl.FinishingTimeFinder;
@@ -19,13 +22,12 @@ public class FinishingTimeFinderTest extends PassAwareRaceLogAnalyzerTest<Finish
protected FinishingTimeFinder createAnalyzer(RaceLog raceLog) {
return new FinishingTimeFinder(raceLog);
}
@Override
protected TimePoint setupTargetEventsForPassAwareTests(int passId) {
RaceLogRaceStatusEvent event = createEvent(RaceLogRaceStatusEvent.class, 1, passId);
protected TargetPair getTargetEventsAndResultForPassAwareTests(int passId, RaceLogEventAuthor author) {
RaceLogRaceStatusEvent event = createEvent(RaceLogRaceStatusEvent.class, 1, passId, author);
when(event.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHING);
raceLog.add(event);
return event.getTimePoint();
return new TargetPair(Arrays.asList(event), event.getLogicalTimePoint());
}
@Test
@@ -45,7 +47,7 @@ public class FinishingTimeFinderTest extends PassAwareRaceLogAnalyzerTest<Finish
raceLog.add(event1);
raceLog.add(event2);
assertEquals(event2.getTimePoint(), analyzer.analyze());
assertSame(event2.getLogicalTimePoint(), analyzer.analyze());
}
@Test
@@ -58,6 +60,6 @@ public class FinishingTimeFinderTest extends PassAwareRaceLogAnalyzerTest<Finish
raceLog.add(event1);
raceLog.add(event2);
assertEquals(event1.getTimePoint(), analyzer.analyze());
assertSame(event1.getLogicalTimePoint(), analyzer.analyze());
}
}
@@ -0,0 +1,51 @@
package com.sap.sailing.domain.racelog.analyzing.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import org.junit.Test;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogGateLineOpeningTimeEvent;
import com.sap.sailing.domain.racelog.RaceLogGateLineOpeningTimeEvent.GateLineOpeningTimes;
import com.sap.sailing.domain.racelog.analyzing.impl.GateLineOpeningTimeFinder;
public class GateLineOpeningTimeFinderTest extends PassAwareRaceLogAnalyzerTest<GateLineOpeningTimeFinder, GateLineOpeningTimes> {
@Override
protected GateLineOpeningTimeFinder createAnalyzer(RaceLog raceLog) {
return new GateLineOpeningTimeFinder(raceLog);
}
@Override
protected TargetPair getTargetEventsAndResultForPassAwareTests(int passId, RaceLogEventAuthor author) {
RaceLogGateLineOpeningTimeEvent event = createEvent(RaceLogGateLineOpeningTimeEvent.class, 1, passId, author);
when(event.getGateLineOpeningTimes()).thenReturn(new GateLineOpeningTimes(2, 3));
return new TargetPair(Arrays.asList(event), new GateLineOpeningTimes(2, 3));
}
@Test
public void testNullForNone() {
RaceLogEvent event1 = createEvent(RaceLogEvent.class, 1);
raceLog.add(event1);
assertNull(analyzer.analyze());
}
@Test
public void testMostRecent() {
RaceLogGateLineOpeningTimeEvent event1 = createEvent(RaceLogGateLineOpeningTimeEvent.class, 1);
when(event1.getGateLineOpeningTimes()).thenReturn(new GateLineOpeningTimes(1, 2));
RaceLogGateLineOpeningTimeEvent event2 = createEvent(RaceLogGateLineOpeningTimeEvent.class, 2);
when(event2.getGateLineOpeningTimes()).thenReturn(new GateLineOpeningTimes(2, 3));
raceLog.add(event1);
raceLog.add(event2);
assertEquals(event2.getGateLineOpeningTimes(), analyzer.analyze());
}
}
@@ -0,0 +1,62 @@
package com.sap.sailing.domain.racelog.analyzing.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import org.junit.Test;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogFlagEvent;
import com.sap.sailing.domain.racelog.analyzing.impl.IndividualRecallFinder;
public class IndividualRecallFinderTest extends PassAwareRaceLogAnalyzerTest<IndividualRecallFinder, TimePoint> {
@Override
protected TargetPair getTargetEventsAndResultForPassAwareTests(
int passId, RaceLogEventAuthor author) {
RaceLogFlagEvent event = createEvent(RaceLogFlagEvent.class, 1, passId, author);
when(event.getUpperFlag()).thenReturn(Flags.XRAY);
when(event.isDisplayed()).thenReturn(true);
return new TargetPair(Arrays.asList(event), event.getLogicalTimePoint());
}
@Override
protected IndividualRecallFinder createAnalyzer(RaceLog raceLog) {
return new IndividualRecallFinder(raceLog) {
@Override
protected boolean isRelevant(RaceLogFlagEvent flagEvent) {
return flagEvent.getUpperFlag().equals(Flags.XRAY) && flagEvent.isDisplayed();
}
};
}
@Test
public void testNullForNone() {
RaceLogEvent event1 = createEvent(RaceLogEvent.class, 1);
raceLog.add(event1);
assertNull(analyzer.analyze());
}
@Test
public void testMostRecent() {
RaceLogFlagEvent event1 = createEvent(RaceLogFlagEvent.class, 1);
when(event1.getUpperFlag()).thenReturn(Flags.XRAY);
when(event1.isDisplayed()).thenReturn(true);
RaceLogFlagEvent event2 = createEvent(RaceLogFlagEvent.class, 2);
when(event2.getUpperFlag()).thenReturn(Flags.XRAY);
when(event2.isDisplayed()).thenReturn(true);
raceLog.add(event1);
raceLog.add(event2);
assertEquals(event2.getLogicalTimePoint(), analyzer.analyze());
}
}
@@ -1,36 +1,113 @@
package com.sap.sailing.domain.racelog.analyzing.test;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Collection;
import java.util.UUID;
import org.junit.Test;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.analyzing.impl.RaceLogAnalyzer;
public abstract class PassAwareRaceLogAnalyzerTest<AnalyzerType extends RaceLogAnalyzer<ResultType>, ResultType>
extends RaceLogAnalyzerTest<AnalyzerType> {
protected class TargetPair extends Util.Pair<Collection<? extends RaceLogEvent>, ResultType> {
private static final long serialVersionUID = 7961879340006633439L;
protected abstract ResultType setupTargetEventsForPassAwareTests(int passId);
public TargetPair(Collection<? extends RaceLogEvent> a, ResultType b) {
super(a, b);
}
public void addAll(RaceLog destination) {
for (RaceLogEvent event : getA()) {
destination.add(event);
}
}
}
/**
* Implement in your test to drive some pass- and author-specific tests.
*
* @param passId pass to be used by your events
* @param author author to be used by your events
* @return {@link TargetPair}
*/
protected abstract TargetPair getTargetEventsAndResultForPassAwareTests(int passId, RaceLogEventAuthor author);
/**
* Most of the times you do not need to implement this (only when your ResultType is a primitive).
*/
protected TargetPair getBlockingEventsAndResultForPassAwareTests(int passId, RaceLogEventAuthor author) {
return getTargetEventsAndResultForPassAwareTests(passId, author);
}
@Test
public void testPassAwareWrongPass() {
ResultType nonExpectedResult = setupTargetEventsForPassAwareTests(0);
RaceLogEvent blockingEvent = createEvent(RaceLogEvent.class, 1, 1, UUID.randomUUID());
RaceLogEventAuthor author = mock(RaceLogEventAuthor.class);
TargetPair pair = getTargetEventsAndResultForPassAwareTests(0, author);
ResultType nonExpectedResult = pair.getB();
RaceLogEvent blockingEvent = createEvent(RaceLogEvent.class, 1, 1, UUID.randomUUID(), author);
pair.addAll(raceLog);
raceLog.add(blockingEvent);
assertNotSame(nonExpectedResult, analyzer.analyze());
}
@Test
public void testPassAwareCorrectPass() {
RaceLogEvent minorEvent = createEvent(RaceLogEvent.class, 0, 0, UUID.randomUUID());
ResultType expectedResult = setupTargetEventsForPassAwareTests(1);
RaceLogEventAuthor author = mock(RaceLogEventAuthor.class);
RaceLogEvent minorEvent = createEvent(RaceLogEvent.class, 0, 0, UUID.randomUUID(), author);
TargetPair pair = getTargetEventsAndResultForPassAwareTests(1, author);
ResultType expectedResult = pair.getB();
pair.addAll(raceLog);
raceLog.add(minorEvent);
assertSame(expectedResult, analyzer.analyze());
assertEquals(expectedResult, analyzer.analyze());
}
@Test
public void testPassAwareBlockedByMajorAuthor() {
RaceLogEventAuthor minorAuthor = mock(RaceLogEventAuthor.class);
RaceLogEventAuthor majorAuthor = mock(RaceLogEventAuthor.class);
when(minorAuthor.compareTo(majorAuthor)).thenReturn(-1);
when(majorAuthor.compareTo(minorAuthor)).thenReturn(1);
TargetPair minorPair = getTargetEventsAndResultForPassAwareTests(0, minorAuthor);
minorPair.addAll(raceLog);
TargetPair majorPair = getBlockingEventsAndResultForPassAwareTests(0, majorAuthor);
majorPair.addAll(raceLog);
assertNotSame(minorPair.getB(), analyzer.analyze());
assertEquals(majorPair.getB(), analyzer.analyze());
}
@Test
public void testPassAwareHidingMinorAuthor() {
RaceLogEventAuthor minorAuthor = mock(RaceLogEventAuthor.class);
RaceLogEventAuthor majorAuthor = mock(RaceLogEventAuthor.class);
when(minorAuthor.compareTo(majorAuthor)).thenReturn(-1);
when(majorAuthor.compareTo(minorAuthor)).thenReturn(1);
TargetPair majorPair = getTargetEventsAndResultForPassAwareTests(0, majorAuthor);
majorPair.addAll(raceLog);
TargetPair minorPair = getBlockingEventsAndResultForPassAwareTests(0, minorAuthor);
minorPair.addAll(raceLog);
assertEquals(majorPair.getB(), analyzer.analyze());
assertNotSame(minorPair.getB(), analyzer.analyze());
}
}
@@ -5,11 +5,14 @@ import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import org.junit.Test;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogProtestStartTimeEvent;
import com.sap.sailing.domain.racelog.analyzing.impl.ProtestStartTimeFinder;
@@ -21,11 +24,10 @@ public class ProtestStartTimeFinderTest extends PassAwareRaceLogAnalyzerTest<Pro
}
@Override
protected TimePoint setupTargetEventsForPassAwareTests(int passId) {
RaceLogProtestStartTimeEvent event = createEvent(RaceLogProtestStartTimeEvent.class, 1, passId);
protected TargetPair getTargetEventsAndResultForPassAwareTests(int passId, RaceLogEventAuthor author) {
RaceLogProtestStartTimeEvent event = createEvent(RaceLogProtestStartTimeEvent.class, 1, passId, author);
when(event.getProtestStartTime()).thenReturn(mock(TimePoint.class));
raceLog.add(event);
return event.getProtestStartTime();
return new TargetPair(Arrays.asList(event), event.getProtestStartTime());
}
@Test
@@ -11,6 +11,7 @@ import org.junit.Before;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.analyzing.impl.RaceLogAnalyzer;
import com.sap.sailing.domain.racelog.impl.RaceLogImpl;
@@ -40,9 +41,19 @@ public abstract class RaceLogAnalyzerTest<AnalyzerType extends RaceLogAnalyzer<?
}
protected static <T extends RaceLogEvent> T createEvent(Class<T> type, long milliseconds, int passId, Serializable id) {
return createEvent(type, milliseconds, passId, id, mock(RaceLogEventAuthor.class));
}
protected static <T extends RaceLogEvent> T createEvent(Class<T> type, long milliseconds, int passId, RaceLogEventAuthor author) {
return createEvent(type, milliseconds, passId, UUID.randomUUID(), author);
}
protected static <T extends RaceLogEvent> T createEvent(Class<T> type, long milliseconds, int passId, Serializable id, RaceLogEventAuthor author) {
T event = mock(type);
when(event.getAuthor()).thenReturn(author);
when(event.getPassId()).thenReturn(passId);
when(event.getTimePoint()).thenReturn(new MillisecondsTimePoint(milliseconds));
when(event.getCreatedAt()).thenReturn(new MillisecondsTimePoint(milliseconds));
when(event.getLogicalTimePoint()).thenReturn(new MillisecondsTimePoint(milliseconds));
when(event.getId()).thenReturn(id);
return event;
}
@@ -1,29 +1,53 @@
package com.sap.sailing.domain.racelog.analyzing.test;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.Test;
import java.util.Arrays;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogEventVisitor;
import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent;
import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent;
import com.sap.sailing.domain.racelog.analyzing.impl.RaceStatusAnalyzer;
import com.sap.sailing.domain.racelog.state.racingprocedure.RacingProcedure;
public class RaceStatusAnalyzerTest extends PassAwareRaceLogAnalyzerTest<RaceStatusAnalyzer, RaceLogRaceStatus> {
private RacingProcedure racingProcedure = mock(RacingProcedure.class);
@Override
protected RaceStatusAnalyzer createAnalyzer(RaceLog raceLog) {
return new RaceStatusAnalyzer(raceLog);
return new RaceStatusAnalyzer(raceLog, racingProcedure);
}
@Override
protected TargetPair getTargetEventsAndResultForPassAwareTests(int passId, RaceLogEventAuthor author) {
RaceLogRaceStatusEvent event = createEvent(RaceLogRaceStatusEvent.class, 1, passId, author);
when(event.getNextStatus()).thenReturn(RaceLogRaceStatus.RUNNING);
doAnswer(new StatusVisitorAnswer()).when(event).accept(any(RaceLogEventVisitor.class));
return new TargetPair(Arrays.asList(event), event.getNextStatus());
}
@Override
protected RaceLogRaceStatus setupTargetEventsForPassAwareTests(int passId) {
RaceLogRaceStatusEvent event = createEvent(RaceLogRaceStatusEvent.class, 1, passId);
when(event.getNextStatus()).thenReturn(RaceLogRaceStatus.RUNNING);
raceLog.add(event);
return event.getNextStatus();
protected TargetPair getBlockingEventsAndResultForPassAwareTests(
int passId, RaceLogEventAuthor author) {
RaceLogRaceStatusEvent event = createEvent(RaceLogRaceStatusEvent.class, 1, passId, author);
when(event.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHING);
doAnswer(new StatusVisitorAnswer()).when(event).accept(any(RaceLogEventVisitor.class));
return new TargetPair(Arrays.asList(event), event.getNextStatus());
}
@Test
@@ -36,11 +60,99 @@ public class RaceStatusAnalyzerTest extends PassAwareRaceLogAnalyzerTest<RaceSta
@Test
public void testMostRecent() {
RaceLogRaceStatusEvent event1 = createEvent(RaceLogRaceStatusEvent.class, 1);
when(event1.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHING);
RaceLogRaceStatusEvent event2 = createEvent(RaceLogRaceStatusEvent.class, 2);
when(event2.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHED);
doAnswer(new StatusVisitorAnswer()).when(event2).accept(any(RaceLogEventVisitor.class));
raceLog.add(event1);
raceLog.add(event2);
assertEquals(event2.getNextStatus(), analyzer.analyze());
}
@Test
public void testStartphaseNotYetActive() {
when(racingProcedure.isStartphaseActive(any(TimePoint.class), any(TimePoint.class))).thenReturn(false);
RaceLogStartTimeEvent event = createStartTimeEvent(MillisecondsTimePoint.now().plus(20000).asMillis(), true);
raceLog.add(event);
assertEquals(RaceLogRaceStatus.SCHEDULED, analyzer.analyze());
}
@Test
public void testStartphaseActive() {
when(racingProcedure.isStartphaseActive(any(TimePoint.class), any(TimePoint.class))).thenReturn(true);
RaceLogStartTimeEvent event = createStartTimeEvent(MillisecondsTimePoint.now().plus(20000).asMillis(), true);
raceLog.add(event);
assertEquals(RaceLogRaceStatus.STARTPHASE, analyzer.analyze());
}
@Test
public void testStartTimePassed() {
when(racingProcedure.isStartphaseActive(any(TimePoint.class), any(TimePoint.class))).thenReturn(false);
RaceLogStartTimeEvent event = createStartTimeEvent(0, false);
raceLog.add(event);
assertEquals(RaceLogRaceStatus.RUNNING, analyzer.analyze());
}
@Test
public void testClock() {
final TimePoint startTime = MillisecondsTimePoint.now();
analyzer = new RaceStatusAnalyzer(raceLog, new RaceStatusAnalyzer.Clock() {
@Override
public TimePoint now() {
return startTime.minus(1);
}
}, racingProcedure);
when(racingProcedure.isStartphaseActive(any(TimePoint.class), any(TimePoint.class))).thenReturn(false);
RaceLogStartTimeEvent event = createStartTimeEvent(startTime);
raceLog.add(event);
assertEquals(RaceLogRaceStatus.SCHEDULED, analyzer.analyze());
}
private static RaceLogStartTimeEvent createStartTimeEvent(long startTimeAsMillis, boolean isGreater) {
TimePoint startTime = mock(TimePoint.class);
when(startTime.asMillis()).thenReturn(startTimeAsMillis);
when(startTime.compareTo(any(TimePoint.class))).thenReturn(isGreater ? 1 : -1);
RaceLogStartTimeEvent event = createEvent(RaceLogStartTimeEvent.class, 1);
when(event.getStartTime()).thenReturn(startTime);
doAnswer(new StartTimeVisitorAnswer()).when(event).accept(any(RaceLogEventVisitor.class));
return event;
}
private static RaceLogStartTimeEvent createStartTimeEvent(TimePoint startTime) {
RaceLogStartTimeEvent event = createEvent(RaceLogStartTimeEvent.class, 1);
when(event.getStartTime()).thenReturn(startTime);
doAnswer(new StartTimeVisitorAnswer()).when(event).accept(any(RaceLogEventVisitor.class));
return event;
}
private static class StartTimeVisitorAnswer implements Answer<Void> {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
RaceLogStartTimeEvent event = (RaceLogStartTimeEvent) invocation.getMock();
RaceLogEventVisitor visitor = (RaceLogEventVisitor) invocation.getArguments()[0];
visitor.visit(event);
return null;
}
}
private static class StatusVisitorAnswer implements Answer<Void> {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
RaceLogRaceStatusEvent event = (RaceLogRaceStatusEvent) invocation.getMock();
RaceLogEventVisitor visitor = (RaceLogEventVisitor) invocation.getArguments()[0];
visitor.visit(event);
return null;
}
}
}
@@ -5,11 +5,14 @@ import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import org.junit.Test;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent;
import com.sap.sailing.domain.racelog.analyzing.impl.StartTimeFinder;
@@ -19,13 +22,13 @@ public class StartTimeFinderTest extends PassAwareRaceLogAnalyzerTest<StartTimeF
protected StartTimeFinder createAnalyzer(RaceLog raceLog) {
return new StartTimeFinder(raceLog);
}
@Override
protected TimePoint setupTargetEventsForPassAwareTests(int passId) {
RaceLogStartTimeEvent event = createEvent(RaceLogStartTimeEvent.class, 1, passId);
protected TargetPair getTargetEventsAndResultForPassAwareTests(int passId,
RaceLogEventAuthor author) {
RaceLogStartTimeEvent event = createEvent(RaceLogStartTimeEvent.class, 1, passId, author);
when(event.getStartTime()).thenReturn(mock(TimePoint.class));
raceLog.add(event);
return event.getStartTime();
return new TargetPair(Arrays.asList(event), event.getStartTime());
}
@Test
@@ -0,0 +1,204 @@
package com.sap.sailing.domain.racelog.state.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.base.CourseBase;
import com.sap.sailing.domain.base.configuration.ConfigurationLoader;
import com.sap.sailing.domain.base.configuration.RacingProcedureConfiguration;
import com.sap.sailing.domain.base.configuration.RegattaConfiguration;
import com.sap.sailing.domain.base.configuration.impl.EmptyRegattaConfiguration;
import com.sap.sailing.domain.base.configuration.impl.RegattaConfigurationImpl;
import com.sap.sailing.domain.base.configuration.procedures.ESSConfiguration;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogEventFactory;
import com.sap.sailing.domain.racelog.impl.RaceLogEventAuthorImpl;
import com.sap.sailing.domain.racelog.impl.RaceLogImpl;
import com.sap.sailing.domain.racelog.impl.RaceLogStartProcedureChangedEventImpl;
import com.sap.sailing.domain.racelog.state.RaceState;
import com.sap.sailing.domain.racelog.state.RaceStateChangedListener;
import com.sap.sailing.domain.racelog.state.impl.RaceStateImpl;
import com.sap.sailing.domain.racelog.state.impl.ReadonlyRaceStateImpl;
import com.sap.sailing.domain.racelog.state.racingprocedure.RacingProcedure;
import com.sap.sailing.domain.racelog.state.racingprocedure.gate.GateStartRacingProcedure;
import com.sap.sailing.domain.racelog.state.racingprocedure.impl.RacingProcedureFactoryImpl;
public class RaceStateTest {
private RaceLog raceLog;
private RaceLogEventAuthor author;
private RaceLogEventFactory factory;
private RacingProcedureType defaultRacingProcedureType;
private ConfigurationLoader<RegattaConfiguration> configuration;
private RaceStateChangedListener listener;
private TimePoint nowMock;
private RaceState state;
@Before
public void setUp() {
raceLog = new RaceLogImpl("test-log");
author = new RaceLogEventAuthorImpl("Test", 1);
factory = RaceLogEventFactory.INSTANCE;
defaultRacingProcedureType = RacingProcedureType.RRS26;
configuration = new EmptyRegattaConfiguration();
listener = mock(RaceStateChangedListener.class);
nowMock = mock(TimePoint.class);
state = new RaceStateImpl(raceLog, author, factory, new RacingProcedureFactoryImpl(author, factory, configuration));
}
@Test
public void testStateOnEmptyRaceLog() {
assertNull(state.getCourseDesign());
assertNull(state.getFinishedTime());
assertNull(state.getFinishingTime());
assertNull(state.getFinishPositioningList());
assertNull(state.getProtestTime());
assertNull(state.getStartTime());
assertNotNull(state.getRacingProcedure());
assertEquals(defaultRacingProcedureType, state.getRacingProcedure().getType());
assertEquals(RaceLogRaceStatus.UNSCHEDULED, state.getStatus());
assertNull(state.getConfirmedFinishPositioningList());
}
@Test
public void testInitialProcedureTypeFallback() throws Exception {
assertEquals(ReadonlyRaceStateImpl.fallbackInitialProcedureType, state.getRacingProcedure().getType());
}
@SuppressWarnings("unchecked")
@Test
public void testInitialProcedureTypeConfiguration() throws Exception {
RegattaConfigurationImpl config = new RegattaConfigurationImpl();
config.setDefaultRacingProcedureType(RacingProcedureType.BASIC);
config.setBasicConfiguration(mock(RacingProcedureConfiguration.class));
configuration = mock(ConfigurationLoader.class);
when(configuration.load()).thenReturn(config);
state = new RaceStateImpl(raceLog, author, factory, new RacingProcedureFactoryImpl(author, factory, configuration));
assertEquals(RacingProcedureType.BASIC, state.getRacingProcedure().getType());
}
@SuppressWarnings("unchecked")
@Test
public void testInitialProcedureTypeRaceLog() throws Exception {
RegattaConfigurationImpl config = new RegattaConfigurationImpl();
config.setDefaultRacingProcedureType(RacingProcedureType.BASIC);
config.setBasicConfiguration(mock(RacingProcedureConfiguration.class));
config.setESSConfiguration(mock(ESSConfiguration.class));
configuration = mock(ConfigurationLoader.class);
when(configuration.load()).thenReturn(config);
raceLog.add(new RaceLogStartProcedureChangedEventImpl(nowMock, author, nowMock, "12", null, 0, RacingProcedureType.ESS));
state = new RaceStateImpl(raceLog, author, factory, new RacingProcedureFactoryImpl(author, factory, configuration));
assertEquals(RacingProcedureType.ESS, state.getRacingProcedure().getType());
}
@Test
public void testStartTime() {
state.addChangedListener(listener);
TimePoint startTime = MillisecondsTimePoint.now().plus(60 * 60 * 1000);
state.forceNewStartTime(nowMock, startTime);
assertEquals(startTime, state.getStartTime());
assertEquals(RaceLogRaceStatus.SCHEDULED, state.getStatus());
verify(listener).onStartTimeChanged(state);
verify(listener).onStatusChanged(state);
verifyNoMoreInteractions(listener);
}
@Test
public void testAdvancePass() {
state.addChangedListener(listener);
int oldPassId = raceLog.getCurrentPassId();
state.setAdvancePass(mock(TimePoint.class));
assertEquals(oldPassId + 1, raceLog.getCurrentPassId());
verify(listener).onAdvancePass(state);
verifyNoMoreInteractions(listener);
}
@Test
public void testAbort() {
state.addChangedListener(listener);
state.setAborted(mock(TimePoint.class), false, Flags.NONE);
// TODO: change test when interface is complete
verifyNoMoreInteractions(listener);
}
@Test
public void testGeneralRecall() {
state.addChangedListener(listener);
state.setGeneralRecall(mock(TimePoint.class));
// TODO: change test when interface is complete
verifyNoMoreInteractions(listener);
}
@Test
public void testInvalidateAfterAdvancePass() throws InterruptedException {
state.addChangedListener(listener);
state.forceNewStartTime(nowMock, new MillisecondsTimePoint(1));
Thread.sleep(100);
state.setFinishedTime(new MillisecondsTimePoint(10));
state.setCourseDesign(nowMock, mock(CourseBase.class));
state.setAdvancePass(mock(TimePoint.class));
assertNull(state.getStartTime());
assertEquals(RaceLogRaceStatus.UNSCHEDULED, state.getStatus());
verify(listener, times(1)).onAdvancePass(state);
verify(listener, times(2)).onStartTimeChanged(state);
verify(listener, times(2)).onFinishedTimeChanged(state);
verify(listener, times(3)).onStatusChanged(state);
verify(listener, times(1)).onCourseDesignChanged(state);
verifyNoMoreInteractions(listener);
}
@Test
public void testNewRacingProcedure() throws InterruptedException {
state.addChangedListener(listener);
RacingProcedure oldProcedure = state.getRacingProcedure();
assertEquals(defaultRacingProcedureType, oldProcedure.getType());
state.setRacingProcedure(nowMock, RacingProcedureType.ESS);
RacingProcedure newProcedure = state.getRacingProcedure();
assertEquals(RacingProcedureType.ESS, newProcedure.getType());
assertFalse(oldProcedure.equals(newProcedure));
}
@Test
public void testGetRacingProcedure() throws InterruptedException {
state.setRacingProcedure(nowMock, RacingProcedureType.RRS26);
GateStartRacingProcedure procedure = state.getTypedRacingProcedure(GateStartRacingProcedure.class);
assertNull(procedure);
}
}
@@ -0,0 +1,39 @@
package com.sap.sailing.domain.racelog.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.impl.RaceLogEventAuthorImpl;
public class RaceLogEventAuthorTest {
@Test
public void testCompareToSame() {
RaceLogEventAuthor author = new RaceLogEventAuthorImpl("", 1);
int result = author.compareTo(author);
assertEquals(0, result);
}
@Test
public void testCompareToMinor() {
RaceLogEventAuthor author = new RaceLogEventAuthorImpl("", 1);
RaceLogEventAuthor minor = new RaceLogEventAuthorImpl("", 2);
int result = author.compareTo(minor);
assertTrue(result > 0);
}
@Test
public void testCompareToMajor() {
RaceLogEventAuthor author = new RaceLogEventAuthorImpl("", 3);
RaceLogEventAuthor major = new RaceLogEventAuthorImpl("", 2);
int result = author.compareTo(major);
assertTrue(result < 0);
}
}
@@ -8,14 +8,17 @@ import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.base.Timed;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.impl.RaceLogEventComparator;
public class RaceLogEventComparatorTest {
private RaceLogEvent eventOne;
private RaceLogEvent eventTwo;
private RaceLogEventAuthor author;
private RaceLogEventComparator comparator;
@@ -23,13 +26,15 @@ public class RaceLogEventComparatorTest {
public void setUp() {
eventOne = mock(RaceLogEvent.class);
eventTwo = mock(RaceLogEvent.class);
author = mock(RaceLogEventAuthor.class);
comparator = RaceLogEventComparator.INSTANCE;
}
@Test
public void testEqualsOnSame() {
when(eventOne.getTimePoint()).thenReturn(new MillisecondsTimePoint(1));
when(eventOne.getAuthor()).thenReturn(mock(RaceLogEventAuthor.class));
when(eventOne.getCreatedAt()).thenReturn(new MillisecondsTimePoint(1));
when(eventOne.getId()).thenReturn("a");
int result = comparator.compare(eventOne, eventOne);
@@ -37,12 +42,14 @@ public class RaceLogEventComparatorTest {
}
@Test
public void testSamePassAndSameTimeSameId() {
public void testSamePassAndSameAuthorAndSameTimeAndSameId() {
when(eventOne.getPassId()).thenReturn(0);
when(eventOne.getTimePoint()).thenReturn(new MillisecondsTimePoint(0));
when(eventOne.getAuthor()).thenReturn(author);
when(eventOne.getCreatedAt()).thenReturn(new MillisecondsTimePoint(0));
when(eventOne.getId()).thenReturn("a");
when(eventTwo.getPassId()).thenReturn(0);
when(eventTwo.getTimePoint()).thenReturn(new MillisecondsTimePoint(0));
when(eventTwo.getAuthor()).thenReturn(author);
when(eventTwo.getCreatedAt()).thenReturn(new MillisecondsTimePoint(0));
when(eventTwo.getId()).thenReturn("a");
int result = comparator.compare(eventOne, eventTwo);
@@ -50,12 +57,14 @@ public class RaceLogEventComparatorTest {
}
@Test
public void testSamePassAndSameTimeDifferentId() {
public void testSamePassAndSameAuthorAndSameTimeButDifferentId() {
when(eventOne.getPassId()).thenReturn(0);
when(eventOne.getTimePoint()).thenReturn(new MillisecondsTimePoint(0));
when(eventOne.getAuthor()).thenReturn(author);
when(eventOne.getCreatedAt()).thenReturn(new MillisecondsTimePoint(0));
when(eventOne.getId()).thenReturn("a");
when(eventTwo.getPassId()).thenReturn(0);
when(eventTwo.getTimePoint()).thenReturn(new MillisecondsTimePoint(0));
when(eventTwo.getAuthor()).thenReturn(author);
when(eventTwo.getCreatedAt()).thenReturn(new MillisecondsTimePoint(0));
when(eventTwo.getId()).thenReturn("b");
int result = comparator.compare(eventOne, eventTwo);
@@ -63,22 +72,58 @@ public class RaceLogEventComparatorTest {
}
@Test
public void testSamePassLowerHigherTime() {
public void testSamePassAndSameAuthorButLowerHigherTime() {
when(eventOne.getPassId()).thenReturn(0);
when(eventOne.getTimePoint()).thenReturn(new MillisecondsTimePoint(1));
when(eventOne.getAuthor()).thenReturn(author);
when(eventOne.getCreatedAt()).thenReturn(new MillisecondsTimePoint(1));
when(eventTwo.getPassId()).thenReturn(0);
when(eventTwo.getTimePoint()).thenReturn(new MillisecondsTimePoint(2));
when(eventTwo.getAuthor()).thenReturn(author);
when(eventTwo.getCreatedAt()).thenReturn(new MillisecondsTimePoint(2));
int result = comparator.compare(eventOne, eventTwo);
assertTrue(result < 0);
}
@Test
public void testSamePassHigherLowerTime() {
public void testSamePassAndSameAuthorButHigherLowerTime() {
when(eventOne.getPassId()).thenReturn(0);
when(eventOne.getTimePoint()).thenReturn(new MillisecondsTimePoint(2));
when(eventOne.getAuthor()).thenReturn(author);
when(eventOne.getCreatedAt()).thenReturn(new MillisecondsTimePoint(2));
when(eventTwo.getPassId()).thenReturn(0);
when(eventTwo.getTimePoint()).thenReturn(new MillisecondsTimePoint(1));
when(eventTwo.getAuthor()).thenReturn(author);
when(eventTwo.getCreatedAt()).thenReturn(new MillisecondsTimePoint(1));
int result = comparator.compare(eventOne, eventTwo);
assertTrue(result > 0);
}
@Test
public void testSamePassButLowerHigherAuthor() {
RaceLogEventAuthor minorAuthor = mock(RaceLogEventAuthor.class);
RaceLogEventAuthor majorAuthor = mock(RaceLogEventAuthor.class);
when(minorAuthor.compareTo(majorAuthor)).thenReturn(-1);
when(majorAuthor.compareTo(minorAuthor)).thenReturn(1);
when(eventOne.getPassId()).thenReturn(0);
when(eventOne.getAuthor()).thenReturn(minorAuthor);
when(eventTwo.getPassId()).thenReturn(0);
when(eventTwo.getAuthor()).thenReturn(majorAuthor);
int result = comparator.compare(eventOne, eventTwo);
assertTrue(result < 0);
}
@Test
public void testSamePassButHigherLowerAuthor() {
RaceLogEventAuthor minorAuthor = mock(RaceLogEventAuthor.class);
RaceLogEventAuthor majorAuthor = mock(RaceLogEventAuthor.class);
when(minorAuthor.compareTo(majorAuthor)).thenReturn(-1);
when(majorAuthor.compareTo(minorAuthor)).thenReturn(1);
when(eventOne.getPassId()).thenReturn(0);
when(eventOne.getAuthor()).thenReturn(majorAuthor);
when(eventTwo.getPassId()).thenReturn(0);
when(eventTwo.getAuthor()).thenReturn(minorAuthor);
int result = comparator.compare(eventOne, eventTwo);
assertTrue(result > 0);
@@ -87,9 +132,9 @@ public class RaceLogEventComparatorTest {
@Test
public void testPassLowerHigher() {
when(eventOne.getPassId()).thenReturn(0);
when(eventOne.getTimePoint()).thenReturn(new MillisecondsTimePoint(2));
when(eventOne.getCreatedAt()).thenReturn(new MillisecondsTimePoint(2));
when(eventTwo.getPassId()).thenReturn(1);
when(eventTwo.getTimePoint()).thenReturn(new MillisecondsTimePoint(1));
when(eventTwo.getCreatedAt()).thenReturn(new MillisecondsTimePoint(1));
int result = comparator.compare(eventOne, eventTwo);
assertTrue(result < 0);
@@ -98,12 +143,23 @@ public class RaceLogEventComparatorTest {
@Test
public void testPassHigherLower() {
when(eventOne.getPassId()).thenReturn(1);
when(eventOne.getTimePoint()).thenReturn(new MillisecondsTimePoint(1));
when(eventOne.getCreatedAt()).thenReturn(new MillisecondsTimePoint(1));
when(eventTwo.getPassId()).thenReturn(0);
when(eventTwo.getTimePoint()).thenReturn(new MillisecondsTimePoint(2));
when(eventTwo.getCreatedAt()).thenReturn(new MillisecondsTimePoint(2));
int result = comparator.compare(eventOne, eventTwo);
assertTrue(result > 0);
}
@Test
public void testFallbackForTimed() {
when(eventOne.getPassId()).thenReturn(1);
when(eventOne.getTimePoint()).thenReturn(new MillisecondsTimePoint(1));
Timed timed = mock(Timed.class);
when(timed.getTimePoint()).thenReturn(new MillisecondsTimePoint(2));
int result = comparator.compare(eventOne, timed);
assertTrue(result < 0);
}
}
@@ -0,0 +1,41 @@
package com.sap.sailing.domain.racelog.test;
import static junit.framework.Assert.assertSame;
import static org.mockito.Mockito.mock;
import java.io.Serializable;
import java.util.List;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogEventVisitor;
import com.sap.sailing.domain.racelog.impl.RaceLogEventImpl;
public class RaceLogEventImplTest {
public void testGetTimePointRedirection() {
TimePoint createdAt = mock(TimePoint.class);
TimePoint logicalTimePoint = mock(TimePoint.class);
RaceLogEvent event = new TestRaceLogEvent(createdAt, null, logicalTimePoint, null, null, 0);
assertSame(createdAt, event.getCreatedAt());
assertSame(logicalTimePoint, event.getTimePoint());
assertSame(createdAt, event.getLogicalTimePoint());
}
private static class TestRaceLogEvent extends RaceLogEventImpl {
private static final long serialVersionUID = -5856509136541176818L;
public TestRaceLogEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable pId, List<Competitor> pInvolvedBoats, int pPassId) {
super(createdAt, author, logicalTimePoint, pId, pInvolvedBoats, pPassId);
}
@Override
public void accept(RaceLogEventVisitor visitor) { }
}
}
@@ -2,6 +2,8 @@ package com.sap.sailing.domain.racelog.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
@@ -9,17 +11,24 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.UUID;
import org.junit.Before;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogEventFactory;
import com.sap.sailing.domain.racelog.RaceLogEventVisitor;
import com.sap.sailing.domain.racelog.RaceLogFlagEvent;
import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent;
import com.sap.sailing.domain.racelog.impl.RaceLogEventAuthorImpl;
import com.sap.sailing.domain.racelog.impl.RaceLogImpl;
public class RaceLogTest {
@@ -59,15 +68,17 @@ public class RaceLogTest {
}
@Test
public void testAddEventDifferentPassSameTimePoint() {
public void testAddEventDifferentPassButSameTimePoint() {
RaceLogEvent eventOne = mock(RaceLogEvent.class);
RaceLogEvent eventTwo = mock(RaceLogEvent.class);
when(eventOne.getPassId()).thenReturn(0);
when(eventOne.getTimePoint()).thenReturn(new MillisecondsTimePoint(0));
when(eventOne.getAuthor()).thenReturn(mock(RaceLogEventAuthor.class));
when(eventOne.getCreatedAt()).thenReturn(new MillisecondsTimePoint(0));
when(eventOne.getId()).thenReturn("a");
when(eventTwo.getPassId()).thenReturn(1);
when(eventTwo.getTimePoint()).thenReturn(new MillisecondsTimePoint(0));
when(eventTwo.getAuthor()).thenReturn(mock(RaceLogEventAuthor.class));
when(eventTwo.getCreatedAt()).thenReturn(new MillisecondsTimePoint(0));
when(eventTwo.getId()).thenReturn("b");
assertTrue(raceLog.add(eventOne));
@@ -80,15 +91,18 @@ public class RaceLogTest {
}
@Test
public void testAddEventSamePassSameTimePointDifferentId() {
public void testAddEventSamePassAndSameAuthorAndSameTimePointButDifferentId() {
RaceLogEvent eventOne = mock(RaceLogEvent.class);
RaceLogEvent eventTwo = mock(RaceLogEvent.class);
RaceLogEventAuthor author = mock(RaceLogEventAuthor.class);
when(eventOne.getPassId()).thenReturn(0);
when(eventOne.getTimePoint()).thenReturn(new MillisecondsTimePoint(0));
when(eventOne.getAuthor()).thenReturn(author);
when(eventOne.getCreatedAt()).thenReturn(new MillisecondsTimePoint(0));
when(eventOne.getId()).thenReturn("a");
when(eventTwo.getPassId()).thenReturn(0);
when(eventTwo.getTimePoint()).thenReturn(new MillisecondsTimePoint(0));
when(eventTwo.getAuthor()).thenReturn(author);
when(eventTwo.getCreatedAt()).thenReturn(new MillisecondsTimePoint(0));
when(eventTwo.getId()).thenReturn("b");
assertTrue(raceLog.add(eventOne));
@@ -101,15 +115,18 @@ public class RaceLogTest {
}
@Test
public void testWontAddEventSamePassSameTimePointSameId() {
public void testWontAddEventSamePassAndSameAuthorAndSameTimePointAndSameId() {
RaceLogEvent eventOne = mock(RaceLogEvent.class);
RaceLogEvent eventTwo = mock(RaceLogEvent.class);
RaceLogEventAuthor author = mock(RaceLogEventAuthor.class);
when(eventOne.getPassId()).thenReturn(0);
when(eventOne.getTimePoint()).thenReturn(new MillisecondsTimePoint(0));
when(eventOne.getAuthor()).thenReturn(author);
when(eventOne.getCreatedAt()).thenReturn(new MillisecondsTimePoint(0));
when(eventOne.getId()).thenReturn("a");
when(eventTwo.getPassId()).thenReturn(0);
when(eventTwo.getTimePoint()).thenReturn(new MillisecondsTimePoint(0));
when(eventTwo.getAuthor()).thenReturn(author);
when(eventTwo.getCreatedAt()).thenReturn(new MillisecondsTimePoint(0));
when(eventTwo.getId()).thenReturn("a");
assertTrue(raceLog.add(eventOne));
@@ -146,24 +163,54 @@ public class RaceLogTest {
verify(listener, never()).visit(event);
}
@Test
public void testAddListenerWhileNotifying() {
RaceLogFlagEvent event = mock(RaceLogFlagEvent.class);
RaceLogEventVisitor listener = mock(RaceLogEventVisitor.class);
final RaceLogEventVisitor dynamicListener = mock(RaceLogEventVisitor.class);
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
raceLog.addListener(dynamicListener);
return null;
}
}).when(event).accept(listener);
raceLog.addListener(listener);
raceLog.add(event);
assertEquals(2, Util.size(raceLog.getAllListeners()));
assertTrue(Util.contains(raceLog.getAllListeners(), listener));
assertTrue(Util.contains(raceLog.getAllListeners(), dynamicListener));
verify(event).accept(listener);
verify(event, never()).accept(dynamicListener);
}
@Test
public void testRawFixesDescending() {
RaceLogEvent event1 = mock(RaceLogEvent.class);
RaceLogEvent event2 = mock(RaceLogEvent.class);
RaceLogEvent event3 = mock(RaceLogEvent.class);
RaceLogEventAuthor minorAuthor = mock(RaceLogEventAuthor.class);
RaceLogEventAuthor majorAuthor = mock(RaceLogEventAuthor.class);
when(minorAuthor.compareTo(majorAuthor)).thenReturn(-1);
when(majorAuthor.compareTo(minorAuthor)).thenReturn(1);
when(event1.getTimePoint()).thenReturn(new MillisecondsTimePoint(1));
when(event2.getTimePoint()).thenReturn(new MillisecondsTimePoint(2));
when(event3.getTimePoint()).thenReturn(new MillisecondsTimePoint(3));
when(event1.getAuthor()).thenReturn(majorAuthor);
when(event1.getCreatedAt()).thenReturn(new MillisecondsTimePoint(1));
when(event2.getAuthor()).thenReturn(minorAuthor);
when(event2.getCreatedAt()).thenReturn(new MillisecondsTimePoint(2));
when(event3.getAuthor()).thenReturn(minorAuthor);
when(event3.getCreatedAt()).thenReturn(new MillisecondsTimePoint(3));
raceLog.add(event1);
raceLog.add(event2);
raceLog.add(event3);
raceLog.lockForRead();
assertEquals(event3, Util.get(raceLog.getRawFixesDescending(), 0));
assertEquals(event2, Util.get(raceLog.getRawFixesDescending(), 1));
assertEquals(event1, Util.get(raceLog.getRawFixesDescending(), 2));
assertEquals(event1, Util.get(raceLog.getRawFixesDescending(), 0));
assertEquals(event3, Util.get(raceLog.getRawFixesDescending(), 1));
assertEquals(event2, Util.get(raceLog.getRawFixesDescending(), 2));
raceLog.unlockAfterRead();
}
@@ -172,23 +219,79 @@ public class RaceLogTest {
RaceLogEvent event1 = mock(RaceLogEvent.class);
RaceLogEvent event2 = mock(RaceLogEvent.class);
RaceLogEvent event3 = mock(RaceLogEvent.class);
RaceLogEvent event4 = mock(RaceLogEvent.class);
RaceLogEventAuthor minorAuthor = mock(RaceLogEventAuthor.class);
RaceLogEventAuthor majorAuthor = mock(RaceLogEventAuthor.class);
when(minorAuthor.compareTo(majorAuthor)).thenReturn(-1);
when(majorAuthor.compareTo(minorAuthor)).thenReturn(1);
when(event1.getPassId()).thenReturn(1);
when(event1.getTimePoint()).thenReturn(new MillisecondsTimePoint(1));
when(event1.getAuthor()).thenReturn(majorAuthor);
when(event1.getCreatedAt()).thenReturn(new MillisecondsTimePoint(1));
when(event2.getPassId()).thenReturn(1);
when(event2.getTimePoint()).thenReturn(new MillisecondsTimePoint(2));
when(event3.getPassId()).thenReturn(0);
when(event3.getTimePoint()).thenReturn(new MillisecondsTimePoint(3));
when(event2.getAuthor()).thenReturn(minorAuthor);
when(event2.getCreatedAt()).thenReturn(new MillisecondsTimePoint(2));
when(event3.getPassId()).thenReturn(1);
when(event3.getAuthor()).thenReturn(minorAuthor);
when(event3.getCreatedAt()).thenReturn(new MillisecondsTimePoint(3));
when(event4.getPassId()).thenReturn(0);
when(event4.getAuthor()).thenReturn(majorAuthor);
when(event4.getCreatedAt()).thenReturn(new MillisecondsTimePoint(4));
raceLog.add(event1);
raceLog.add(event2);
raceLog.add(event3);
raceLog.add(event4);
raceLog.lockForRead();
assertEquals(event2, Util.get(raceLog.getFixesDescending(), 0));
assertEquals(event1, Util.get(raceLog.getFixesDescending(), 1));
assertEquals(3, Util.size(raceLog.getFixesDescending()));
assertEquals(event1, Util.get(raceLog.getFixesDescending(), 0));
assertEquals(event3, Util.get(raceLog.getFixesDescending(), 1));
assertEquals(event2, Util.get(raceLog.getFixesDescending(), 2));
raceLog.unlockAfterRead();
}
private RaceLogEventAuthor author = new RaceLogEventAuthorImpl("Test Author", 1);
@Test
public void testAddingEventsFromMultipleClients() {
RaceLog raceLog = new RaceLogImpl("RaceLogTest", "test-identifier");
UUID client1Id = UUID.randomUUID();
UUID client2Id = UUID.randomUUID();
final MillisecondsTimePoint now = MillisecondsTimePoint.now();
RaceLogStartTimeEvent startTimeEvent1 = RaceLogEventFactory.INSTANCE.createStartTimeEvent(now, author, 1, now.plus(1));
Iterable<RaceLogEvent> empty = raceLog.add(startTimeEvent1, client1Id);
assertTrue(Util.isEmpty(empty));
RaceLogStartTimeEvent startTimeEvent2 = RaceLogEventFactory.INSTANCE.createStartTimeEvent(now.plus(2), author, 1, now.plus(3));
Iterable<RaceLogEvent> nonEmpty = raceLog.add(startTimeEvent2, client2Id);
assertEquals(1, Util.size(nonEmpty));
assertSame(startTimeEvent1, nonEmpty.iterator().next());
RaceLogStartTimeEvent startTimeEvent3 = RaceLogEventFactory.INSTANCE.createStartTimeEvent(now.plus(4), author, 1, now.plus(5));
Iterable<RaceLogEvent> nonEmpty2 = raceLog.add(startTimeEvent3, client1Id);
assertEquals(1, Util.size(nonEmpty2));
assertSame(startTimeEvent2, nonEmpty2.iterator().next());
}
@Test()
public void testGetFirstFixAfterNew() {
TimePoint createdAtEventOne = new MillisecondsTimePoint(100);
RaceLogEvent eventOne = mock(RaceLogEvent.class);
when(eventOne.getAuthor()).thenReturn(mock(RaceLogEventAuthor.class));
when(eventOne.getCreatedAt()).thenReturn(createdAtEventOne);
when(eventOne.getTimePoint()).thenReturn(createdAtEventOne);
raceLog.add(eventOne);
TimePoint createdAtEventTwo = new MillisecondsTimePoint(99);
RaceLogEvent eventTwo = mock(RaceLogEvent.class);
when(eventTwo.getAuthor()).thenReturn(mock(RaceLogEventAuthor.class));
when(eventTwo.getCreatedAt()).thenReturn(createdAtEventTwo);
when(eventTwo.getTimePoint()).thenReturn(createdAtEventTwo);
raceLog.add(eventTwo);
assertNull(raceLog.getFirstFixAfter(new MillisecondsTimePoint(100)));
assertEquals(eventOne, raceLog.getFirstFixAfter(new MillisecondsTimePoint(99)));
}
private class VisitFlagEventAnswer implements Answer<Object> {
@Override
File renamed without changes.
@@ -7,12 +7,25 @@ Bundle-Vendor: SAP
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Require-Bundle: com.sap.sailing.domain.common;bundle-version="1.0.0"
Export-Package: com.sap.sailing.domain.base,
com.sap.sailing.domain.base.configuration,
com.sap.sailing.domain.base.configuration.impl,
com.sap.sailing.domain.base.configuration.procedures,
com.sap.sailing.domain.base.impl,
com.sap.sailing.domain.base.racegroup,
com.sap.sailing.domain.base.racegroup.impl,
com.sap.sailing.domain.racelog,
com.sap.sailing.domain.racelog.analyzing.impl,
com.sap.sailing.domain.racelog.impl,
com.sap.sailing.domain.racelog.state,
com.sap.sailing.domain.racelog.state.impl,
com.sap.sailing.domain.racelog.state.racingprocedure,
com.sap.sailing.domain.racelog.state.racingprocedure.ess,
com.sap.sailing.domain.racelog.state.racingprocedure.ess.impl,
com.sap.sailing.domain.racelog.state.racingprocedure.gate,
com.sap.sailing.domain.racelog.state.racingprocedure.gate.impl,
com.sap.sailing.domain.racelog.state.racingprocedure.impl,
com.sap.sailing.domain.racelog.state.racingprocedure.rrs26,
com.sap.sailing.domain.racelog.state.racingprocedure.rrs26.impl,
com.sap.sailing.domain.tracking,
com.sap.sailing.domain.tracking.impl,
com.sap.sailing.util.impl
@@ -0,0 +1,34 @@
package com.sap.sailing.domain.base;
import java.io.Serializable;
import java.util.UUID;
import com.sap.sailing.domain.base.impl.DynamicBoat;
import com.sap.sailing.domain.base.impl.DynamicCompetitor;
import com.sap.sailing.domain.base.impl.DynamicTeam;
/**
* Base interface for classes managing a set of {@link Competitor} objects.
*/
public interface CompetitorFactory {
/**
* If a valid competitor is returned and the caller has information available that could be used to update the competitor,
* the caller must check the result of {@link #isCompetitorToUpdateDuringGetOrCreate(Competitor)}, and if <code>true</code>,
* must call {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} to cause an update of the
* competitor's values.
*/
Competitor getExistingCompetitorById(Serializable competitorId);
/**
* Checks if the <code>competitor</code> shall be updated from the default provided by, e.g., a tracking infrastructure.
* Callers of {@link #getExistingCompetitorById(Serializable)} or {@link #getExistingCompetitorByIdAsString(String)}
* must call this method in case they retrieve a valid competitor by ID and have data available that can be used to update
* the competitor.
*/
boolean isCompetitorToUpdateDuringGetOrCreate(Competitor result);
Competitor getOrCreateCompetitor(Serializable competitorId, String name, DynamicTeam team, DynamicBoat boat);
DynamicCompetitor getOrCreateDynamicCompetitor(UUID fromString, String name, DynamicTeam team, DynamicBoat boat);
}
@@ -13,14 +13,7 @@ import com.sap.sailing.domain.common.dto.CompetitorDTO;
* @author Axel Uhl (d043530)
*
*/
public interface CompetitorStore {
/**
* If a valid competitor is returned and the caller has information available that could be used to update the competitor,
* the caller must check the result of {@link #isCompetitorToUpdateDuringGetOrCreate(Competitor)}, and if <code>true</code>,
* must call {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} to cause an update of the
* competitor's values.
*/
Competitor getExistingCompetitorById(Serializable competitorId);
public interface CompetitorStore extends CompetitorFactory {
/**
* If a valid competitor is returned and the caller has information available that could be used to update the competitor,
@@ -29,16 +22,6 @@ public interface CompetitorStore {
* competitor's values.
*/
Competitor getExistingCompetitorByIdAsString(String idAsString);
/**
* Checks if the <code>competitor</code> shall be updated from the default provided by, e.g., a tracking infrastructure.
* Callers of {@link #getExistingCompetitorById(Serializable)} or {@link #getExistingCompetitorByIdAsString(String)}
* must call this method in case they retrieve a valid competitor by ID and have data available that can be used to update
* the competitor.
*/
boolean isCompetitorToUpdateDuringGetOrCreate(Competitor result);
Competitor getOrCreateCompetitor(Serializable competitorId, String name, DynamicTeam team, DynamicBoat boat);
/**
* When a competitor is queried using {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)}
@@ -1,5 +1,7 @@
package com.sap.sailing.domain.base;
import java.util.UUID;
import com.sap.sailing.domain.common.Named;
import com.sap.sailing.domain.common.WithID;
@@ -11,5 +13,5 @@ import com.sap.sailing.domain.common.WithID;
*
*/
public interface CourseArea extends Named, WithID, IsManagedBySharedDomainFactory {
UUID getId();
}
@@ -1,15 +1,15 @@
package com.sap.sailing.domain.base;
import java.io.Serializable;
import java.util.List;
import java.util.UUID;
import com.sap.sailing.domain.base.impl.DynamicBoat;
import com.sap.sailing.domain.base.impl.DynamicCompetitor;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher;
import com.sap.sailing.domain.common.MarkType;
import com.sap.sailing.domain.common.PassingInstruction;
import com.sap.sailing.domain.common.configuration.DeviceConfigurationMatcherType;
public interface SharedDomainFactory {
public interface SharedDomainFactory extends CompetitorFactory {
/**
* Looks up or, if not found, creates a {@link Nationality} object and re-uses <code>threeLetterIOCCode</code> also as the
@@ -76,33 +76,25 @@ public interface SharedDomainFactory {
BoatClass getOrCreateBoatClass(String name);
/**
* If a valid competitor is returned and the caller has information available that could be used to update the competitor,
* the caller must check the result of {@link #isCompetitorToUpdateDuringGetOrCreate(Competitor)}, and if <code>true</code>,
* must call {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} to cause an update of the
* competitor's values.
* Gets the {@link CompetitorStore} of this {@link SharedDomainFactory}.
*/
Competitor getExistingCompetitorById(Serializable competitorId);
CompetitorStore getCompetitorStore();
/**
* Checks if the <code>competitor</code> shall be updated from the default provided by, e.g., a tracking infrastructure.
* Callers of {@link #getExistingCompetitorById(Serializable)} or {@link #getExistingCompetitorByIdAsString(String)}
* must call this method in case they retrieve a valid competitor by ID and have data available that can be used to update
* the competitor.
* If a {@link CourseArea} with the given id already exists, it is returned. Otherwise a new {@link CourseArea}
* is created.
*/
boolean isCompetitorToUpdateDuringGetOrCreate(Competitor result);
Competitor getOrCreateCompetitor(Serializable competitorId, String name, DynamicTeam team, DynamicBoat boat);
CourseArea getOrCreateCourseArea(UUID id, String name);
/**
* Same as {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} but returns the writable
* specialization of the {@link Competitor} interface. Use with care because the setters offered by the <code>Dynamic...</code>
* subinterfaces don't automatically replicate or store the changes.
* Gets the {@link CourseArea} with passed id; if there is no such {@link CourseArea} <code>null</code> will be returned.
*/
DynamicCompetitor getOrCreateDynamicCompetitor(UUID competitorId, String name, DynamicTeam team, DynamicBoat boat);
CourseArea getOrCreateCourseArea(Serializable courseAreaId, String name);
CourseArea getExistingCourseAreaById(Serializable courseAreaId);
/**
* Hm.
*/
DeviceConfigurationMatcher getOrCreateDeviceConfigurationMatcher(DeviceConfigurationMatcherType type, List<String> clientIdentifiers);
}
@@ -0,0 +1,20 @@
package com.sap.sailing.domain.base.configuration;
/**
* Capable of loading and storing a {@link ConfigurationType}.
*/
public interface ConfigurationLoader<ConfigurationType> {
/**
* Loads the configuration from its database.
* @return A immutable {@link ConfigurationType}.
*/
ConfigurationType load();
/**
* Saves the configuration to its database.
*/
void store();
}
@@ -0,0 +1,35 @@
package com.sap.sailing.domain.base.configuration;
import java.io.Serializable;
import java.util.List;
/**
* Interface holding information about tablet's (RCApp) configuration.
*/
public interface DeviceConfiguration extends Serializable {
/**
* Course area names this tablet is allowed to log on.
*/
List<String> getAllowedCourseAreaNames();
/**
* She is getting the result mails.
*/
String getResultsMailRecipient();
/**
* Course names allowed in the By-Name-Course-Designer
*/
List<String> getByNameCourseDesignerCourseNames();
/**
* Default configuration for all races without a custom {@link RegattaConfiguration}
*/
RegattaConfiguration getRegattaConfiguration();
/**
* Copy me.
*/
DeviceConfiguration copy();
}
@@ -0,0 +1,11 @@
package com.sap.sailing.domain.base.configuration;
import java.io.Serializable;
/**
* Each tablet configuration is bound to a specific client. Use this interface instead of a plain {@link String} to
* enable additions (like event-specific configurations).
*/
public interface DeviceConfigurationIdentifier extends Serializable {
String getClientIdentifier();
}
@@ -0,0 +1,48 @@
package com.sap.sailing.domain.base.configuration;
import java.io.Serializable;
import com.sap.sailing.domain.base.IsManagedBySharedDomainFactory;
import com.sap.sailing.domain.base.configuration.impl.DeviceConfigurationMapImpl;
import com.sap.sailing.domain.common.configuration.DeviceConfigurationMatcherType;
/**
* <p>
* Classes implementing this interface are matching {@link DeviceConfigurationIdentifier}s to associate them with a
* {@link DeviceConfiguration}.
* </p>
*
* <p>The rank (see {@link DeviceConfigurationMatcher#getMatchingRank()}) is used as a priority when multiple matchers
* are matching a {@link DeviceConfigurationIdentifier} (see also {@link DeviceConfigurationMapImpl}) (lower wins).</p>
*/
public interface DeviceConfigurationMatcher extends IsManagedBySharedDomainFactory, Serializable {
/**
* Returns the kind of matching used by this matcher.
*
* @return the {@link Type}.
*/
DeviceConfigurationMatcherType getMatcherType();
/**
* Gets the matcher's rank.
*
* @return the rank.
*/
int getMatchingRank();
/**
* Returns <code>true</code> if this {@link DeviceConfigurationMatcher} matches the given
* {@link DeviceConfigurationIdentifier}; otherwise <code>false</code>.
*
* @param identifier
*/
boolean matches(DeviceConfigurationIdentifier identifier);
/**
* Gets this matcher's identifier.
*
* @return the identifier.
*/
Serializable getMatcherIdentifier();
}
@@ -0,0 +1,31 @@
package com.sap.sailing.domain.base.configuration;
import java.io.Serializable;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.racelog.state.racingprocedure.RacingProcedure;
/**
* Interface holding configuration options common to all {@link RacingProcedure}s.
*/
public interface RacingProcedureConfiguration extends Serializable {
/**
* Gets the class flag to be used by the {@link RacingProcedure}.
*/
Flags getClassFlag();
/**
* Indicates whether the {@link RacingProcedure} should allow individual recall or not.
*/
Boolean hasInidividualRecall();
/**
* Merges this {@link RacingProcedureConfiguration} with the passed configuration, returning a copy with all
* non-null fields of the passed configuration set to the passed configuration's value.
*
* @return a merged copy.
*/
RacingProcedureConfiguration merge(RacingProcedureConfiguration update);
}
@@ -0,0 +1,63 @@
package com.sap.sailing.domain.base.configuration;
import java.io.Serializable;
import com.sap.sailing.domain.base.configuration.procedures.ESSConfiguration;
import com.sap.sailing.domain.base.configuration.procedures.GateStartConfiguration;
import com.sap.sailing.domain.base.configuration.procedures.RRS26Configuration;
import com.sap.sailing.domain.common.CourseDesignerMode;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
import com.sap.sailing.domain.racelog.state.racingprocedure.RacingProcedure;
/**
* Interface holding configuration options for a Regatta, including configurations for
* all types of a {@link RacingProcedure}s.
*/
public interface RegattaConfiguration extends Serializable, Cloneable {
/**
* Gets the default {@link CourseDesignerMode} for races configured.
*/
CourseDesignerMode getDefaultCourseDesignerMode();
/**
* Gets the default {@link RacingProcedureType} for races configured.
*/
RacingProcedureType getDefaultRacingProcedureType();
/**
* Gets the configuration for RRS26 races.
* @return <code>null</code> if there is no configuration.
*/
RRS26Configuration getRRS26Configuration();
/**
* Gets the configuration for Gate Start races.
* @return <code>null</code> if there is no configuration.
*/
GateStartConfiguration getGateStartConfiguration();
/**
* Gets the configuration for ESS races.
* @return <code>null</code> if there is no configuration.
*/
ESSConfiguration getESSConfiguration();
/**
* Gets the configuration for Basic races.
* @return <code>null</code> if there is no configuration.
*/
RacingProcedureConfiguration getBasicConfiguration();
/**
* Copy me.
*/
RegattaConfiguration clone();
/**
* Creates a copied {@link RegattaConfiguration} with all
* non-<code>null</code> fields taken from the passed {@link RegattaConfiguration}.
*/
RegattaConfiguration merge(RegattaConfiguration update);
}
@@ -0,0 +1,25 @@
package com.sap.sailing.domain.base.configuration.impl;
import com.sap.sailing.domain.base.configuration.DeviceConfigurationIdentifier;
public class DeviceConfigurationIdentifierImpl implements DeviceConfigurationIdentifier {
private static final long serialVersionUID = 2785847392322741468L;
private final String clientIdentifier;
public DeviceConfigurationIdentifierImpl(String clientIdentifier) {
this.clientIdentifier = clientIdentifier;
}
@Override
public String getClientIdentifier() {
return clientIdentifier;
}
@Override
public String toString() {
return "DeviceConfigurationIdentifierImpl [clientIdentifier=" + clientIdentifier + "]";
}
}
@@ -0,0 +1,65 @@
package com.sap.sailing.domain.base.configuration.impl;
import java.util.List;
import com.sap.sailing.domain.base.configuration.DeviceConfiguration;
import com.sap.sailing.domain.base.configuration.RegattaConfiguration;
public class DeviceConfigurationImpl implements DeviceConfiguration {
private static final long serialVersionUID = 6084215932610324314L;
private RegattaConfiguration regattaConfiguration;
private List<String> allowedCourseAreaNames;
private String resultsMailRecipient;
private List<String> byNameDesignerCourseNames;
public DeviceConfigurationImpl(RegattaConfiguration regattaConfiguration) {
this.regattaConfiguration = regattaConfiguration;
}
public void setRegattaConfiguration(RegattaConfiguration proceduresConfiguration) {
this.regattaConfiguration = proceduresConfiguration;
}
@Override
public RegattaConfiguration getRegattaConfiguration() {
return regattaConfiguration;
}
@Override
public List<String> getAllowedCourseAreaNames() {
return allowedCourseAreaNames;
}
public void setAllowedCourseAreaNames(List<String> newAllowedCourseAreaNames) {
this.allowedCourseAreaNames = newAllowedCourseAreaNames;
}
@Override
public String getResultsMailRecipient() {
return resultsMailRecipient;
}
public void setResultsMailRecipient(String resultsMailRecipient) {
this.resultsMailRecipient = resultsMailRecipient;
}
@Override
public List<String> getByNameCourseDesignerCourseNames() {
return byNameDesignerCourseNames;
}
public void setByNameDesignerCourseNames(List<String> byNameDesignerCourseNames) {
this.byNameDesignerCourseNames = byNameDesignerCourseNames;
}
public DeviceConfiguration copy() {
DeviceConfigurationImpl copyConfiguration = new DeviceConfigurationImpl(regattaConfiguration.clone());
copyConfiguration.setAllowedCourseAreaNames(allowedCourseAreaNames);
copyConfiguration.setByNameDesignerCourseNames(byNameDesignerCourseNames);
copyConfiguration.setResultsMailRecipient(resultsMailRecipient);
return copyConfiguration;
}
}
@@ -0,0 +1,62 @@
package com.sap.sailing.domain.base.configuration.impl;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.sap.sailing.domain.base.configuration.DeviceConfiguration;
import com.sap.sailing.domain.base.configuration.DeviceConfigurationIdentifier;
import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher;
/**
* <p>
* Helper class providing a {@link Map} of {@link DeviceConfigurationMatcher}s associated with their
* {@link DeviceConfiguration}.
* </p>
*
* <p>
* When searching for a match, the highest ranked {@link DeviceConfigurationMatcher} (i.e. lowest number) wins.
* </p>
*/
public class DeviceConfigurationMapImpl extends ConcurrentHashMap<DeviceConfigurationMatcher, DeviceConfiguration> {
private static final long serialVersionUID = -8009136964737670452L;
private interface Action {
DeviceConfiguration call(DeviceConfigurationMatcher matcher);
}
public DeviceConfiguration getByMatch(DeviceConfigurationIdentifier key) {
return doByMatch(key, new Action() {
@Override
public DeviceConfiguration call(DeviceConfigurationMatcher match) {
return get(match);
}
});
}
public DeviceConfiguration removeByMatch(DeviceConfigurationIdentifier key) {
return doByMatch(key, new Action() {
@Override
public DeviceConfiguration call(DeviceConfigurationMatcher match) {
return remove(match);
}
});
}
private DeviceConfiguration doByMatch(DeviceConfigurationIdentifier key, Action action) {
DeviceConfigurationMatcher match = null;
for (Entry<DeviceConfigurationMatcher, DeviceConfiguration> entry : entrySet()) {
if (entry.getKey().matches(key)) {
if (match == null || match.getMatchingRank() > entry.getKey().getMatchingRank()) {
match = entry.getKey();
}
}
}
if (match != null) {
return action.call(match);
} else {
return null;
}
}
}
@@ -0,0 +1,62 @@
package com.sap.sailing.domain.base.configuration.impl;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.sap.sailing.domain.base.IsManagedBySharedDomainFactory;
import com.sap.sailing.domain.base.SharedDomainFactory;
import com.sap.sailing.domain.base.configuration.DeviceConfigurationIdentifier;
import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher;
import com.sap.sailing.domain.common.configuration.DeviceConfigurationMatcherType;
/**
* Matches a set of {@link DeviceConfigurationIdentifier}s.
*/
public class DeviceConfigurationMatcherMulti implements DeviceConfigurationMatcher {
private static final long serialVersionUID = 2372299957258702516L;
private final List<String> clientIdentifiers;
public DeviceConfigurationMatcherMulti(List<String> matchingClientIdentifiers) {
this.clientIdentifiers = new ArrayList<String>(matchingClientIdentifiers);
Collections.sort(this.clientIdentifiers);
}
@Override
public DeviceConfigurationMatcherType getMatcherType() {
return DeviceConfigurationMatcherType.MULTI;
}
@Override
public int getMatchingRank() {
return getMatcherType().getRank();
}
@Override
public boolean matches(DeviceConfigurationIdentifier identifier) {
return this.clientIdentifiers.contains(identifier.getClientIdentifier());
}
public Iterable<String> getClientIdentifiers() {
return clientIdentifiers;
}
@Override
public Serializable getMatcherIdentifier() {
return String.format("%s%s", DeviceConfigurationMatcherMulti.class.getSimpleName(), clientIdentifiers.toString());
}
@Override
public String toString() {
return "DeviceConfigurationMatcherMulti [clientIdentifiers=" + clientIdentifiers + "]";
}
@Override
public IsManagedBySharedDomainFactory resolve(SharedDomainFactory domainFactory) {
return domainFactory.getOrCreateDeviceConfigurationMatcher(getMatcherType(), clientIdentifiers);
}
}
@@ -0,0 +1,58 @@
package com.sap.sailing.domain.base.configuration.impl;
import java.io.Serializable;
import java.util.Arrays;
import com.sap.sailing.domain.base.IsManagedBySharedDomainFactory;
import com.sap.sailing.domain.base.SharedDomainFactory;
import com.sap.sailing.domain.base.configuration.DeviceConfigurationIdentifier;
import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher;
import com.sap.sailing.domain.common.configuration.DeviceConfigurationMatcherType;
/**
* Matches a single {@link DeviceConfigurationIdentifier}.
*/
public class DeviceConfigurationMatcherSingle implements DeviceConfigurationMatcher {
private static final long serialVersionUID = -3662453614818373801L;
private final String clientIdentifier;
public DeviceConfigurationMatcherSingle(String matchingClientIdentifier) {
this.clientIdentifier = matchingClientIdentifier;
}
@Override
public boolean matches(DeviceConfigurationIdentifier identifier) {
return this.clientIdentifier.equals(identifier.getClientIdentifier());
}
@Override
public DeviceConfigurationMatcherType getMatcherType() {
return DeviceConfigurationMatcherType.SINGLE;
}
@Override
public int getMatchingRank() {
return getMatcherType().getRank();
}
public String getClientIdentifier() {
return clientIdentifier;
}
@Override
public Serializable getMatcherIdentifier() {
return String.format("%s%s", DeviceConfigurationMatcherSingle.class.getSimpleName(), clientIdentifier);
}
@Override
public String toString() {
return "DeviceConfigurationMatcherSingle [clientIdentifier=" + clientIdentifier + "]";
}
@Override
public IsManagedBySharedDomainFactory resolve(SharedDomainFactory domainFactory) {
return domainFactory.getOrCreateDeviceConfigurationMatcher(getMatcherType(), Arrays.asList(clientIdentifier));
}
}
@@ -0,0 +1,21 @@
package com.sap.sailing.domain.base.configuration.impl;
import com.sap.sailing.domain.base.configuration.RacingProcedureConfiguration;
import com.sap.sailing.domain.base.configuration.procedures.ESSConfiguration;
public class ESSConfigurationImpl extends RacingProcedureConfigurationImpl implements ESSConfiguration {
private static final long serialVersionUID = 5406098147408723197L;
protected ESSConfiguration copy() {
ESSConfigurationImpl copy = (ESSConfigurationImpl) super.copy(new ESSConfigurationImpl());
return copy;
}
@Override
public RacingProcedureConfiguration merge(RacingProcedureConfiguration update) {
ESSConfigurationImpl target = (ESSConfigurationImpl) super.merge(update);
return target;
}
}
@@ -0,0 +1,32 @@
package com.sap.sailing.domain.base.configuration.impl;
import com.sap.sailing.domain.base.configuration.RegattaConfiguration;
import com.sap.sailing.domain.base.configuration.ConfigurationLoader;
import com.sap.sailing.domain.common.CourseDesignerMode;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
/**
* Is empty, does nothing on store and load.
*/
public class EmptyRegattaConfiguration extends RegattaConfigurationImpl implements
ConfigurationLoader<RegattaConfiguration> {
private static final long serialVersionUID = -4187341706420504456L;
@Override
public RegattaConfiguration load() {
setDefaultRacingProcedureType(RacingProcedureType.UNKNOWN);
setDefaultCourseDesignerMode(CourseDesignerMode.UNKNOWN);
setRRS26Configuration(new RRS26ConfigurationImpl());
setGateStartConfiguration(new GateStartConfigurationImpl());
setESSConfiguration(new ESSConfigurationImpl());
setBasicConfiguration(new RacingProcedureConfigurationImpl());
return clone();
}
@Override
public void store() {
}
}
@@ -0,0 +1,52 @@
package com.sap.sailing.domain.base.configuration.impl;
import com.sap.sailing.domain.base.configuration.RacingProcedureConfiguration;
import com.sap.sailing.domain.base.configuration.procedures.GateStartConfiguration;
public class GateStartConfigurationImpl extends RacingProcedureConfigurationImpl implements GateStartConfiguration {
private static final long serialVersionUID = 1862408542829215027L;
private Boolean hasPathfinder;
private Boolean hasAdditionalGolfDownTime;
public void setHasPathfinder(Boolean hasPathfinder) {
this.hasPathfinder = hasPathfinder;
}
@Override
public Boolean hasPathfinder() {
return hasPathfinder;
}
public void setHasAdditionalGolfDownTime(Boolean hasAdditionalGolfDownTime) {
this.hasAdditionalGolfDownTime = hasAdditionalGolfDownTime;
}
@Override
public Boolean hasAdditionalGolfDownTime() {
return hasAdditionalGolfDownTime;
}
@Override
public RacingProcedureConfiguration merge(RacingProcedureConfiguration value) {
GateStartConfiguration update = (GateStartConfiguration) value;
GateStartConfigurationImpl target = (GateStartConfigurationImpl) super.merge(update);
if (update.hasPathfinder() != null) {
target.setHasPathfinder(update.hasPathfinder());
}
if (update.hasAdditionalGolfDownTime() != null) {
target.setHasAdditionalGolfDownTime(update.hasAdditionalGolfDownTime());
}
return target;
}
protected GateStartConfiguration copy() {
GateStartConfigurationImpl copy = (GateStartConfigurationImpl) super.copy(new GateStartConfigurationImpl());
copy.setHasPathfinder(hasPathfinder);
copy.setHasAdditionalGolfDownTime(hasAdditionalGolfDownTime);
return copy;
}
}
@@ -0,0 +1,41 @@
package com.sap.sailing.domain.base.configuration.impl;
import java.util.List;
import com.sap.sailing.domain.base.configuration.RacingProcedureConfiguration;
import com.sap.sailing.domain.base.configuration.procedures.RRS26Configuration;
import com.sap.sailing.domain.common.racelog.Flags;
public class RRS26ConfigurationImpl extends RacingProcedureConfigurationImpl implements
RRS26Configuration {
private static final long serialVersionUID = 260941807346644026L;
private List<Flags> startModeFlags;
@Override
public List<Flags> getStartModeFlags() {
return startModeFlags;
}
public void setStartModeFlags(List<Flags> flags) {
this.startModeFlags = flags;
}
@Override
public RacingProcedureConfiguration merge(RacingProcedureConfiguration value) {
RRS26Configuration update = (RRS26Configuration) value;
RRS26ConfigurationImpl target = (RRS26ConfigurationImpl) super.merge(update);
if (update.getStartModeFlags() != null) {
target.setStartModeFlags(update.getStartModeFlags());
}
return target;
}
protected RRS26Configuration copy() {
RRS26ConfigurationImpl copy = (RRS26ConfigurationImpl) super.copy(new RRS26ConfigurationImpl());
copy.setStartModeFlags(startModeFlags);
return copy;
}
}
@@ -0,0 +1,52 @@
package com.sap.sailing.domain.base.configuration.impl;
import com.sap.sailing.domain.base.configuration.RacingProcedureConfiguration;
import com.sap.sailing.domain.common.racelog.Flags;
public class RacingProcedureConfigurationImpl implements RacingProcedureConfiguration {
private static final long serialVersionUID = 8501755084811977792L;
private Flags classFlag;
private Boolean hasInidividualRecall;@Override
public Flags getClassFlag() {
return classFlag;
}
public void setClassFlag(Flags classFlag) {
this.classFlag = classFlag;
}
@Override
public Boolean hasInidividualRecall() {
return hasInidividualRecall;
}
public void setHasInidividualRecall(Boolean hasInidividualRecall) {
this.hasInidividualRecall = hasInidividualRecall;
}
protected RacingProcedureConfiguration copy() {
return copy(new RacingProcedureConfigurationImpl());
}
protected RacingProcedureConfiguration copy(RacingProcedureConfigurationImpl target) {
target.setClassFlag(this.getClassFlag());
target.setHasInidividualRecall(this.hasInidividualRecall());
return target;
}
@Override
public RacingProcedureConfiguration merge(RacingProcedureConfiguration update) {
RacingProcedureConfigurationImpl target = (RacingProcedureConfigurationImpl) this.copy();
if (update.getClassFlag() != null) {
target.setClassFlag(update.getClassFlag());
}
if (update.hasInidividualRecall() != null) {
target.setHasInidividualRecall(update.hasInidividualRecall());
}
return target;
}
}
@@ -0,0 +1,118 @@
package com.sap.sailing.domain.base.configuration.impl;
import com.sap.sailing.domain.base.configuration.RacingProcedureConfiguration;
import com.sap.sailing.domain.base.configuration.RegattaConfiguration;
import com.sap.sailing.domain.base.configuration.procedures.ESSConfiguration;
import com.sap.sailing.domain.base.configuration.procedures.GateStartConfiguration;
import com.sap.sailing.domain.base.configuration.procedures.RRS26Configuration;
import com.sap.sailing.domain.common.CourseDesignerMode;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
public class RegattaConfigurationImpl implements RegattaConfiguration {
private static final long serialVersionUID = 8501755084811977792L;
private RacingProcedureType defaultRacingProcedureType;
private CourseDesignerMode defaultCourseDesignerMode;
private RRS26Configuration rrs26Configuration;
private GateStartConfiguration gateStartConfiguration;
private ESSConfiguration essConfiguration;
private RacingProcedureConfiguration basicConfiguration;
@Override
public RacingProcedureType getDefaultRacingProcedureType() {
return defaultRacingProcedureType;
}
public void setDefaultRacingProcedureType(RacingProcedureType type) {
defaultRacingProcedureType = type;
}
@Override
public CourseDesignerMode getDefaultCourseDesignerMode() {
return defaultCourseDesignerMode;
}
public void setDefaultCourseDesignerMode(CourseDesignerMode mode) {
defaultCourseDesignerMode = mode;
}
@Override
public RRS26Configuration getRRS26Configuration() {
return rrs26Configuration;
}
public void setRRS26Configuration(RRS26Configuration rrs26Configuration) {
this.rrs26Configuration = rrs26Configuration;
}
@Override
public GateStartConfiguration getGateStartConfiguration() {
return gateStartConfiguration;
}
public void setGateStartConfiguration(GateStartConfiguration gateStartConfiguration) {
this.gateStartConfiguration = gateStartConfiguration;
}
@Override
public ESSConfiguration getESSConfiguration() {
return essConfiguration;
}
public void setESSConfiguration(ESSConfiguration essConfiguration) {
this.essConfiguration = essConfiguration;
}
@Override
public RacingProcedureConfiguration getBasicConfiguration() {
return basicConfiguration;
}
public void setBasicConfiguration(RacingProcedureConfiguration basicConfiguration) {
this.basicConfiguration = basicConfiguration;
}
@Override
public RegattaConfiguration clone() {
RegattaConfigurationImpl copy = new RegattaConfigurationImpl();
copy.setDefaultRacingProcedureType(defaultRacingProcedureType);
copy.setDefaultCourseDesignerMode(defaultCourseDesignerMode);
copy.setRRS26Configuration(rrs26Configuration);
copy.setGateStartConfiguration(gateStartConfiguration);
copy.setESSConfiguration(essConfiguration);
copy.setBasicConfiguration(basicConfiguration);
return copy;
}
@Override
public RegattaConfiguration merge(RegattaConfiguration update) {
RegattaConfigurationImpl target = (RegattaConfigurationImpl) this.clone();
if (update.getDefaultCourseDesignerMode() != null) {
target.setDefaultCourseDesignerMode(update.getDefaultCourseDesignerMode());
}
if (update.getDefaultRacingProcedureType() != null) {
target.setDefaultRacingProcedureType(update.getDefaultRacingProcedureType());
}
if (update.getRRS26Configuration() != null) {
target.setRRS26Configuration(
(RRS26Configuration) target.getRRS26Configuration().merge(update.getRRS26Configuration()));
}
if (update.getGateStartConfiguration() != null) {
target.setGateStartConfiguration(
(GateStartConfiguration) target.getGateStartConfiguration().merge(update.getGateStartConfiguration()));
}
if (update.getESSConfiguration() != null) {
target.setESSConfiguration(
(ESSConfiguration) target.getESSConfiguration().merge(update.getESSConfiguration()));
}
if (update.getBasicConfiguration() != null) {
target.setBasicConfiguration(
(RacingProcedureConfiguration) target.getBasicConfiguration().merge(update.getBasicConfiguration()));
}
return target;
}
}
@@ -0,0 +1,7 @@
package com.sap.sailing.domain.base.configuration.procedures;
import com.sap.sailing.domain.base.configuration.RacingProcedureConfiguration;
public interface ESSConfiguration extends RacingProcedureConfiguration {
}
@@ -0,0 +1,10 @@
package com.sap.sailing.domain.base.configuration.procedures;
import com.sap.sailing.domain.base.configuration.RacingProcedureConfiguration;
public interface GateStartConfiguration extends RacingProcedureConfiguration {
Boolean hasPathfinder();
Boolean hasAdditionalGolfDownTime();
}
@@ -0,0 +1,12 @@
package com.sap.sailing.domain.base.configuration.procedures;
import java.util.List;
import com.sap.sailing.domain.base.configuration.RacingProcedureConfiguration;
import com.sap.sailing.domain.common.racelog.Flags;
public interface RRS26Configuration extends RacingProcedureConfiguration {
List<Flags> getStartModeFlags();
}
@@ -1,6 +1,6 @@
package com.sap.sailing.domain.base.impl;
import java.io.Serializable;
import java.util.UUID;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.IsManagedBySharedDomainFactory;
@@ -10,15 +10,15 @@ import com.sap.sailing.domain.common.impl.NamedImpl;
public class CourseAreaImpl extends NamedImpl implements CourseArea {
private static final long serialVersionUID = 5912385360170509150L;
private final Serializable id;
private final UUID id;
public CourseAreaImpl(String name, Serializable id) {
public CourseAreaImpl(String name, UUID id) {
super(name);
this.id = id;
}
@Override
public Serializable getId() {
public UUID getId() {
return id;
}
@@ -0,0 +1,321 @@
package com.sap.sailing.domain.base.impl;
import java.io.Serializable;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.HashMap;
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 com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorStore;
import com.sap.sailing.domain.base.ControlPoint;
import com.sap.sailing.domain.base.ControlPointWithTwoMarks;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.base.SharedDomainFactory;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher;
import com.sap.sailing.domain.base.configuration.impl.DeviceConfigurationMatcherMulti;
import com.sap.sailing.domain.base.configuration.impl.DeviceConfigurationMatcherSingle;
import com.sap.sailing.domain.common.MarkType;
import com.sap.sailing.domain.common.PassingInstruction;
import com.sap.sailing.domain.common.WithID;
import com.sap.sailing.domain.common.configuration.DeviceConfigurationMatcherType;
public class SharedDomainFactoryImpl implements SharedDomainFactory {
/**
* Ensure that the <em>same</em> string is used as key that is also used to set the {@link Nationality}
* object's {@link Nationality#getThreeLetterIOCAcronym() IOC code}.
*/
private final Map<String, Nationality> nationalityCache;
private final Map<Serializable, Mark> markCache;
/**
* For all marks ever created by this factory, the mark {@link WithID#getId() ID}'s string representation
* is mapped here to the actual ID. This allows clients to send only the string representation to the server
* and still be able to identify a mark uniquely this way.
*/
private final Map<String, Serializable> markIdCache;
private final Map<String, BoatClass> boatClassCache;
protected final CompetitorStore competitorStore;
private final Map<Serializable, CourseArea> courseAreaCache;
/**
* Weakly references the waypoints. If a waypoint is no longer strongly referenced, the corresponding reference contained
* as value will have its referred object be <code>null</code>. In this case, the methods reading from this cache will purge
* the record and behave as if the record hadn't existed at the time of the read operation.
*/
private final ConcurrentHashMap<Serializable, WeakWaypointReference> waypointCache;
private final ReferenceQueue<Waypoint> waypointCacheReferenceQueue;
private final Map<Serializable, DeviceConfigurationMatcher> configurationMatcherCache;
/**
* Weak references to {@link Waypoint} objects of this type are registered with
* {@link DomainFactoryImpl#waypointCacheReferenceQueue} upon construction so that when their referents are no
* longer strongly referenced and the reference was nulled, they are entered into that queue.
* Methods managing the {@link #waypointCache} can poll the queue and then remove cache entries based on
* the {@link #id} stored in the reference.
*
* @author Axel Uhl (D043530)
*
*/
private class WeakWaypointReference extends WeakReference<Waypoint> {
private final Serializable id;
public WeakWaypointReference(Waypoint waypoint) {
super(waypoint, waypointCacheReferenceQueue);
this.id = waypoint.getId();
}
public void removeCacheEntry() {
waypointCache.remove(id);
}
}
private final Set<String> mayStartWithNoUpwindLeg;
/**
* Uses a transient competitor store
*/
public SharedDomainFactoryImpl() {
this(new TransientCompetitorStoreImpl());
}
public SharedDomainFactoryImpl(CompetitorStore competitorStore) {
waypointCacheReferenceQueue = new ReferenceQueue<Waypoint>();
nationalityCache = new HashMap<String, Nationality>();
markCache = new HashMap<Serializable, Mark>();
markIdCache = new HashMap<String, Serializable>();
boatClassCache = new HashMap<String, BoatClass>();
this.competitorStore = competitorStore;
waypointCache = new ConcurrentHashMap<Serializable, WeakWaypointReference>();
mayStartWithNoUpwindLeg = new HashSet<String>(Arrays.asList(new String[] { "extreme40", "ess", "ess40" }));
courseAreaCache = new HashMap<Serializable, CourseArea>();
configurationMatcherCache = new HashMap<Serializable, DeviceConfigurationMatcher>();
}
@Override
public Nationality getOrCreateNationality(String threeLetterIOCCode) {
synchronized (nationalityCache) {
Nationality result = nationalityCache.get(threeLetterIOCCode);
if (result == null) {
result = new NationalityImpl(threeLetterIOCCode);
nationalityCache.put(threeLetterIOCCode, result);
}
return result;
}
}
@Override
public Mark getOrCreateMark(String name) {
return getOrCreateMark(name, name);
}
@Override
public Mark getOrCreateMark(Serializable id, String name) {
Mark result = markCache.get(id);
if (result == null) {
result = new MarkImpl(id, name);
cacheMark(id, result);
}
return result;
}
@Override
public Mark getOrCreateMark(String toStringRepresentationOfID, String name) {
final Mark result;
if (markIdCache.containsKey(toStringRepresentationOfID)) {
Serializable id = markIdCache.get(toStringRepresentationOfID);
result = getOrCreateMark(id, name);
} else {
result = new MarkImpl(toStringRepresentationOfID, name);
cacheMark(toStringRepresentationOfID, result);
}
return result;
}
private void cacheMark(Serializable id, Mark result) {
markCache.put(id, result);
markIdCache.put(id.toString(), id);
}
@Override
public Mark getOrCreateMark(Serializable id, String name, MarkType type, String color, String shape, String pattern) {
Mark result = markCache.get(id);
if (result == null) {
result = new MarkImpl(id, name, type, color, shape, pattern);
cacheMark(id, result);
}
return result;
}
@Override
public ControlPointWithTwoMarks createControlPointWithTwoMarks(Mark left, Mark right, String name) {
return new ControlPointWithTwoMarksImpl(left, right, name);
}
@Override
public ControlPointWithTwoMarks createControlPointWithTwoMarks(Serializable id, Mark left, Mark right, String name) {
return new ControlPointWithTwoMarksImpl(id, left, right, name);
}
@Override
public Waypoint createWaypoint(ControlPoint controlPoint, PassingInstruction passingInstruction) {
synchronized (waypointCache) {
expungeStaleWaypointCacheEntries();
Waypoint result = new WaypointImpl(controlPoint, passingInstruction);
waypointCache.put(result.getId(), new WeakWaypointReference(result));
return result;
}
}
@Override
public Waypoint getExistingWaypointById(Waypoint waypointPrototype) {
synchronized (waypointCache) {
expungeStaleWaypointCacheEntries();
Waypoint result = null;
Reference<Waypoint> ref = waypointCache.get(waypointPrototype.getId());
if (ref != null) {
result = ref.get();
if (result == null) {
// waypoint was finalized; remove entry from cache
waypointCache.remove(waypointPrototype.getId());
}
}
return result;
}
}
@Override
public Waypoint getExistingWaypointByIdOrCache(Waypoint waypoint) {
synchronized (waypointCache) {
expungeStaleWaypointCacheEntries();
Waypoint result = null;
Reference<Waypoint> ref = waypointCache.get(waypoint.getId());
if (ref != null) {
result = ref.get();
if (result == null) {
// waypoint was finalized; remove entry from cache and add anew
result = waypoint;
waypointCache.put(waypoint.getId(), new WeakWaypointReference(waypoint));
} // else, result is the waypoint found in the cache; return it
} else {
// No entry found in the cache; not even a stale, finalized one. Create a new entry:
result = waypoint;
waypointCache.put(waypoint.getId(), new WeakWaypointReference(waypoint));
}
return result;
}
}
private void expungeStaleWaypointCacheEntries() {
Reference<? extends Waypoint> ref;
while ((ref=waypointCacheReferenceQueue.poll()) != null) {
((WeakWaypointReference) ref).removeCacheEntry();
}
}
@Override
public BoatClass getOrCreateBoatClass(String name, boolean typicallyStartsUpwind) {
synchronized (boatClassCache) {
BoatClass result = boatClassCache.get(name);
if (result == null) {
result = new BoatClassImpl(name, typicallyStartsUpwind);
boatClassCache.put(name, result);
}
return result;
}
}
@Override
public BoatClass getOrCreateBoatClass(String name) {
return getOrCreateBoatClass(name, /* typicallyStartsUpwind */!mayStartWithNoUpwindLeg.contains(name.toLowerCase()));
}
@Override
public CourseArea getOrCreateCourseArea(UUID courseAreaId, String name) {
CourseArea result = getExistingCourseAreaById(courseAreaId);
if (result == null) {
result = new CourseAreaImpl(name, courseAreaId);
courseAreaCache.put(courseAreaId, result);
}
return result;
}
@Override
public CourseArea getExistingCourseAreaById(Serializable courseAreaId) {
return courseAreaCache.get(courseAreaId);
}
@Override
public CompetitorStore getCompetitorStore() {
return competitorStore;
}
@Override
public Competitor getExistingCompetitorById(Serializable competitorId) {
return getCompetitorStore().getExistingCompetitorById(competitorId);
}
@Override
public boolean isCompetitorToUpdateDuringGetOrCreate(Competitor result) {
return getCompetitorStore().isCompetitorToUpdateDuringGetOrCreate(result);
}
@Override
public Competitor getOrCreateCompetitor(Serializable competitorId, String name, DynamicTeam team, DynamicBoat boat) {
return getCompetitorStore().getOrCreateCompetitor(competitorId, name, team, boat);
}
@Override
public DynamicCompetitor getOrCreateDynamicCompetitor(UUID competitorId, String name, DynamicTeam team,
DynamicBoat boat) {
return getCompetitorStore().getOrCreateDynamicCompetitor(competitorId, name, team, boat);
}
@Override
public DeviceConfigurationMatcher getOrCreateDeviceConfigurationMatcher(DeviceConfigurationMatcherType type,
List<String> clientIdentifiers) {
DeviceConfigurationMatcher probe = createMatcher(type, clientIdentifiers);
DeviceConfigurationMatcher matcher = configurationMatcherCache.get(probe.getMatcherIdentifier());
if (matcher == null) {
configurationMatcherCache.put(probe.getMatcherIdentifier(), probe);
matcher = probe;
}
return matcher;
}
private DeviceConfigurationMatcher createMatcher(DeviceConfigurationMatcherType type, List<String> clientIdentifiers) {
DeviceConfigurationMatcher matcher = null;
switch (type) {
case SINGLE:
matcher = new DeviceConfigurationMatcherSingle(clientIdentifiers.get(0));
break;
case MULTI:
matcher = new DeviceConfigurationMatcherMulti(clientIdentifiers);
break;
default:
throw new IllegalArgumentException("Unknown matcher type: " + type);
}
return matcher;
}
}
@@ -8,6 +8,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.WeakHashMap;
import com.sap.sailing.domain.base.Competitor;
@@ -38,15 +39,15 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab
public TransientCompetitorStoreImpl() {
lock = new NamedReentrantReadWriteLock("CompetitorStore", /* fair */ false);
competitorCache = new HashMap<>();
competitorsByIdAsString = new HashMap<>();
competitorsToUpdateDuringGetOrCreate = new HashSet<>();
weakCompetitorDTOCache = new WeakHashMap<>();
competitorCache = new HashMap<Serializable, Competitor>();
competitorsByIdAsString = new HashMap<String, Competitor>();
competitorsToUpdateDuringGetOrCreate = new HashSet<Competitor>();
weakCompetitorDTOCache = new WeakHashMap<Competitor, CompetitorDTO>();
}
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
weakCompetitorDTOCache = new WeakHashMap<>();
weakCompetitorDTOCache = new WeakHashMap<Competitor, CompetitorDTO>();
}
private Competitor createCompetitor(Serializable id, String name, DynamicTeam team, DynamicBoat boat) {
@@ -89,6 +90,11 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab
}
return result;
}
@Override
public DynamicCompetitor getOrCreateDynamicCompetitor(UUID fromString, String name, DynamicTeam team, DynamicBoat boat) {
return (DynamicCompetitor) getOrCreateCompetitor(fromString, name, team, boat);
}
private void competitorNoLongerToUpdateDuringGetOrCreate(Competitor result) {
competitorsToUpdateDuringGetOrCreate.remove(result);
@@ -3,7 +3,9 @@ package com.sap.sailing.domain.base.racegroup;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.configuration.RegattaConfiguration;
import com.sap.sailing.domain.common.Named;
import com.sap.sailing.domain.racelog.state.racingprocedure.RacingProcedure;
/**
* A {@link RaceGroup} is an abstract representation of a set of races managed in fleets and series.
@@ -40,4 +42,9 @@ public interface RaceGroup extends Named {
* Gets the collection of series.
*/
public Iterable<SeriesWithRows> getSeries();
/**
* Gets configuration objects for {@link RacingProcedure}s of this {@link RaceGroup}'s races.
*/
public RegattaConfiguration getRegattaConfiguration();
}
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.base.racegroup.impl;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.configuration.RegattaConfiguration;
import com.sap.sailing.domain.base.racegroup.RaceGroup;
import com.sap.sailing.domain.base.racegroup.SeriesWithRows;
import com.sap.sailing.domain.common.impl.NamedImpl;
@@ -13,16 +14,15 @@ public class RaceGroupImpl extends NamedImpl implements RaceGroup {
private final BoatClass boatClass;
private final CourseArea courseArea;
private final Iterable<SeriesWithRows> series;
private final RegattaConfiguration regattaConfiguration;
public RaceGroupImpl(
String name,
BoatClass boatClass,
CourseArea courseArea,
Iterable<SeriesWithRows> series) {
public RaceGroupImpl(String name, BoatClass boatClass, CourseArea courseArea, Iterable<SeriesWithRows> series,
RegattaConfiguration regattaConfiguration) {
super(name);
this.boatClass = boatClass;
this.courseArea = courseArea;
this.series = series;
this.regattaConfiguration = regattaConfiguration;
}
public CourseArea getDefaultCourseArea() {
@@ -37,4 +37,9 @@ public class RaceGroupImpl extends NamedImpl implements RaceGroup {
return boatClass;
}
@Override
public RegattaConfiguration getRegattaConfiguration() {
return regattaConfiguration;
}
}
@@ -0,0 +1,11 @@
package com.sap.sailing.domain.racelog;
import java.io.Serializable;
import java.util.List;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.impl.Util.Triple;
public interface CompetitorResults extends List<Triple<Serializable, String, MaxPointsReason>> {
}
@@ -1,6 +1,7 @@
package com.sap.sailing.domain.racelog;
import java.util.HashSet;
import java.util.UUID;
import com.sap.sailing.domain.common.WithID;
import com.sap.sailing.domain.racelog.impl.RaceLogEventComparator;
@@ -67,6 +68,23 @@ public interface RaceLog extends Track<RaceLogEvent>, WithID {
Iterable<RaceLogEventVisitor> getAllListeners();
/**
* Adds an event to this race log and returns a superset of all race log events (excluding the new
* <code>event</code>) that were added to this race log but not yet returned to the client with ID
* <code>clientId</code> by this method. In general, the list returned is not a true superset but
* equals exactly those events not yet delivered to the client. However, if the server was re-started
* since the client last called this method, and since the underlying data structures are not durably
* stored, the entire set of all race log events would be delivered to the client once.
*/
Iterable<RaceLogEvent> add(RaceLogEvent event, UUID clientId);
/**
* Returns all {@link #getRawFixes() raw fixes} and marks them as delivered to the client identified by <code>clientId</code>
* so that when that ID appears in a subsequent call to {@link #add(RaceLogEvent, UUID)}, the fixes returned by this call
* are already considered delivered to the client identified by <code>clientId</code>.
*/
Iterable<RaceLogEvent> getRawFixes(UUID clientId);
/**
* Like {@link #add(RaceLogEvent)}, only that no events are triggered. Use this method only when loading a race log,
* e.g., from a replication or master data import or when loading from the database.
@@ -0,0 +1,10 @@
package com.sap.sailing.domain.racelog;
public interface RaceLogChangedListener {
/**
* Called when an event is added to the {@link RaceLog}.
* @param event that was added
*/
public void eventAdded(RaceLogEvent event);
}
@@ -1,5 +1,6 @@
package com.sap.sailing.domain.racelog;
import java.io.Serializable;
import java.util.List;
import com.sap.sailing.domain.base.Competitor;
@@ -28,24 +29,40 @@ import com.sap.sailing.domain.common.WithID;
*
* The timestamp received with {@link RaceLogEvent#getCreatedAt()} denotes the point in time the event was created.
*
* The timestamp received with {@link RaceLogEvent#getTimePoint()} denotes the logical point in time the event has
* occurred (sometimes called 'event time'). This timestamp might be different from {@link RaceLogEvent#getCreatedAt()}.
* For example setting the start time of race to a point in time in the past, results in a {@link RaceLogEvent}
* returning "now" on {@link RaceLogEvent#getCreatedAt()} and such a point in time that a complete startphase could have
* occured on {@link RaceLogEvent#getTimePoint()}.
* The timestamp received with {@link RaceLogEvent#getLogicalTimePoint()} denotes the logical point in time the event
* has occurred (sometimes called 'event time'). This timestamp might be different from
* {@link RaceLogEvent#getCreatedAt()}. For example setting the start time of race to a point in time in the past,
* results in a {@link RaceLogEvent} returning "now" on {@link RaceLogEvent#getCreatedAt()} and such a point in time
* that a complete startphase could have occured on {@link RaceLogEvent#getTimePoint()}.
*
* To ensure an ordering there should be no two {@link RaceLogEvent}s returning the same point in time on
* {@link RaceLogEvent#getTimePoint()} <b>per pass</b>.
* {@link RaceLogEvent#getCreatedAt()} <b>per pass</b>.
*
* The {@link RaceLogEvent}'s {@link Timed} interface redirects to {@link RaceLogEvent#getCreatedAt()} (was
* {@link RaceLogEvent#getLogicalTimePoint()}!).
* </p>
*
* <p>
* Race log events have an author that has a name and a priority assigned. This can be used to represent multiple
* concurrent race log authors such as a device used on a starting vessel, another device used at the finish line and
* yet another device used on shore. In case more than one device make a statement about something, such as the start
* time or the start procedure, the statement from the device with the highest priority needs to take precedence.
* </p>
*/
public interface RaceLogEvent extends Timed, WithID {
public interface RaceLogEvent extends Timed, WithID, Serializable {
/**
* Gets the {@link TimePoint} this event was created at.
*/
TimePoint getCreatedAt();
/**
* Gets the event's logical timestamp.
*
* @return
*/
TimePoint getLogicalTimePoint();
/**
* Gets the event's pass identifier.
*
@@ -68,4 +85,6 @@ public interface RaceLogEvent extends Timed, WithID {
* Visitor pattern to implement certain {@link RaceLogEvent} subclass specific behavior.
*/
void accept(RaceLogEventVisitor visitor);
RaceLogEventAuthor getAuthor();
}
@@ -0,0 +1,29 @@
package com.sap.sailing.domain.racelog;
import com.sap.sailing.domain.common.Named;
/**
* Multiple devices may concurrently post to a single {@link RaceLog}. In this case it is important to understand
* who posted what. The "who" is described by instances of this class. In particular, an author has a name and a
* priority which is then used to arbitrate between different posts on the same subject, such as a race's start time
* or transitions from one race phase to another.
*
* @author Axel Uhl (d043530)
*
*/
public interface RaceLogEventAuthor extends Named, Comparable<RaceLogEventAuthor> {
public static final int PRIORITY_COMPATIBILITY = 16;
public static final String NAME_COMPATIBILITY = "Compatibility";
/**
* A lesser number represents a higher priority. Suggested priority levels:
* <ol>
* <li>Start Vessel</li>
* <li>Finish Vessel</li>
* <li>Shore Control</li>
* <li>Compatibility priority for old events</li>
* </ol>
*/
int getPriority();
}
@@ -5,89 +5,87 @@ import java.util.List;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CourseBase;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.domain.common.racelog.StartProcedureType;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
import com.sap.sailing.domain.racelog.impl.RaceLogEventFactoryImpl;
import com.sap.sailing.domain.tracking.Wind;
public interface RaceLogEventFactory {
RaceLogEventFactory INSTANCE = new RaceLogEventFactoryImpl();
RaceLogFlagEvent createFlagEvent(TimePoint timePoint, Serializable id, List<Competitor> involvedBoats, int passId,
Flags upperFlag, Flags lowerFlag, boolean isDisplayed);
RaceLogFlagEvent createFlagEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, Serializable id, List<Competitor> involvedBoats,
int passId, Flags upperFlag, Flags lowerFlag, boolean isDisplayed);
RaceLogFlagEvent createFlagEvent(TimePoint timePoint, int passId, Flags upperFlag, Flags lowerFlag,
boolean isDisplayed);
RaceLogFlagEvent createFlagEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, int passId, Flags upperFlag,
Flags lowerFlag, boolean isDisplayed);
RaceLogStartTimeEvent createStartTimeEvent(TimePoint timePoint, Serializable id, List<Competitor> involvedBoats,
int passId, TimePoint startTime);
RaceLogStartTimeEvent createStartTimeEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, Serializable id,
List<Competitor> involvedBoats, int passId, TimePoint startTime);
RaceLogStartTimeEvent createStartTimeEvent(TimePoint timePoint, int passId, TimePoint startTime);
RaceLogStartTimeEvent createStartTimeEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, int passId, TimePoint startTime);
RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint timePoint, Serializable id, List<Competitor> competitors,
int passId, RaceLogRaceStatus nextStatus);
RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, Serializable id,
List<Competitor> competitors, int passId, RaceLogRaceStatus nextStatus);
RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint timePoint, int passId, RaceLogRaceStatus nextStatus);
RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, int passId, RaceLogRaceStatus nextStatus);
RaceLogPassChangeEvent createPassChangeEvent(TimePoint timePoint, Serializable id, List<Competitor> competitors,
int passId);
RaceLogPassChangeEvent createPassChangeEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, Serializable id,
List<Competitor> competitors, int passId);
RaceLogPassChangeEvent createPassChangeEvent(TimePoint timePoint, int passId);
RaceLogPassChangeEvent createPassChangeEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, int passId);
RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint timePoint, Serializable id,
List<Competitor> competitors, int passId, Serializable courseAreaId);
RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
Serializable id, List<Competitor> competitors, int passId, Serializable courseAreaId);
RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint timePoint, int passId,
Serializable courseAreaId);
RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
int passId, Serializable courseAreaId);
RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint timePoint, Serializable id,
List<Competitor> competitors, int passId, CourseBase courseData);
RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
Serializable id, List<Competitor> competitors, int passId, CourseBase courseData);
RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint timePoint, int passId,
CourseBase courseData);
RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
int passId, CourseBase courseData);
RaceLogFinishPositioningListChangedEvent createFinishPositioningListChangedEvent(TimePoint timePoint,
Serializable id, List<Competitor> competitors, int passId,
List<Triple<Serializable, String, MaxPointsReason>> positionedCompetitors);
RaceLogFinishPositioningListChangedEvent createFinishPositioningListChangedEvent(TimePoint logicalTimePoint,
RaceLogEventAuthor author, Serializable id, List<Competitor> competitors,
int passId, CompetitorResults positionedCompetitors);
RaceLogFinishPositioningListChangedEvent createFinishPositioningListChangedEvent(TimePoint timePoint, int passId,
List<Triple<Serializable, String, MaxPointsReason>> positionedCompetitors);
RaceLogFinishPositioningListChangedEvent createFinishPositioningListChangedEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
int passId, CompetitorResults positionedCompetitors);
RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint timePoint, Serializable id,
List<Competitor> competitors, int passId, List<Triple<Serializable, String, MaxPointsReason>> positionedCompetitors);
RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
Serializable id, List<Competitor> competitors, int passId, CompetitorResults positionedCompetitors);
RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint timePoint, int passId,
List<Triple<Serializable, String, MaxPointsReason>> positionedCompetitors);
RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
int passId, CompetitorResults positionedCompetitors);
RaceLogPathfinderEvent createPathfinderEvent(TimePoint timePoint, Serializable id, List<Competitor> competitors,
int passId, String pathfinderId);
RaceLogPathfinderEvent createPathfinderEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, Serializable id,
List<Competitor> competitors, int passId, String pathfinderId);
RaceLogPathfinderEvent createPathfinderEvent(TimePoint timePoint, int passId, String pathfinderId);
RaceLogPathfinderEvent createPathfinderEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, int passId, String pathfinderId);
RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint timePoint, Serializable id,
List<Competitor> competitors, int passId, Long gateLineOpeningTimeInMillis);
RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
Serializable id, List<Competitor> competitors, int passId, Long gateLaunchStopTime, Long golfDownTime);
RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint timePoint, int passId,
Long gateLineOpeningTimeInMillis);
RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
int passId, Long gateLaunchStopTime, Long golfDownTime);
RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint timePoint, Serializable id,
List<Competitor> competitors, int passId, StartProcedureType type);
RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
Serializable id, List<Competitor> competitors, int passId, RacingProcedureType type);
RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint timePoint, int passId,
StartProcedureType type);
RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
int passId, RacingProcedureType type);
RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint timePoint, Serializable id,
List<Competitor> competitors, int passId, TimePoint protestStartTime);
RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
Serializable id, List<Competitor> competitors, int passId, TimePoint protestStartTime);
RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint timePoint, int passId, TimePoint protestStartTime);
RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, int passId, TimePoint protestStartTime);
RaceLogWindFixEvent createWindFixEvent(TimePoint eventTime, int currentPassId, Wind wind);
RaceLogWindFixEvent createWindFixEvent(TimePoint eventTime, RaceLogEventAuthor author, int currentPassId, Wind wind);
RaceLogWindFixEvent createWindFixEvent(TimePoint timePoint, Serializable id,
List<Competitor> competitors, int passId, Wind wind);
RaceLogWindFixEvent createWindFixEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
Serializable id, List<Competitor> competitors, int passId, Wind wind);
}
@@ -5,56 +5,55 @@ import java.util.List;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CourseBase;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.domain.common.racelog.StartProcedureType;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
import com.sap.sailing.domain.racelog.impl.RaceLogEventRestoreFactoryImpl;
import com.sap.sailing.domain.tracking.Wind;
public interface RaceLogEventRestoreFactory extends RaceLogEventFactory {
RaceLogEventRestoreFactory INSTANCE = new RaceLogEventRestoreFactoryImpl();
RaceLogFlagEvent createFlagEvent(TimePoint createdAt, TimePoint logicalTimePoint, Serializable id,
List<Competitor> involvedBoats, int passId, Flags upperFlag, Flags lowerFlag, boolean isDisplayed);
RaceLogFlagEvent createFlagEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, List<Competitor> involvedBoats, int passId, Flags upperFlag, Flags lowerFlag, boolean isDisplayed);
RaceLogStartTimeEvent createStartTimeEvent(TimePoint createdAt, TimePoint logicalTimePoint, Serializable id,
List<Competitor> involvedBoats, int passId, TimePoint startTime);
RaceLogStartTimeEvent createStartTimeEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, List<Competitor> involvedBoats, int passId, TimePoint startTime);
RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint createdAt, TimePoint logicalTimePoint, Serializable id,
List<Competitor> competitors, int passId, RaceLogRaceStatus nextStatus);
RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, List<Competitor> competitors, int passId, RaceLogRaceStatus nextStatus);
RaceLogPassChangeEvent createPassChangeEvent(TimePoint createdAt, TimePoint logicalTimePoint, Serializable id,
List<Competitor> competitors, int passId);
RaceLogPassChangeEvent createPassChangeEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, List<Competitor> competitors, int passId);
RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint createdAt, TimePoint logicalTimePoint,
Serializable id, List<Competitor> competitors, int passId, Serializable courseAreaId);
RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint createdAt, RaceLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId, Serializable courseAreaId);
RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint createdAt, TimePoint logicalTimePoint,
Serializable id, List<Competitor> competitors, int passId, CourseBase courseData);
RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint createdAt, RaceLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId, CourseBase courseData);
RaceLogFinishPositioningListChangedEvent createFinishPositioningListChangedEvent(TimePoint createdAt,
TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId,
List<Triple<Serializable, String, MaxPointsReason>> positionedCompetitors);
RaceLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors,
int passId, CompetitorResults positionedCompetitors);
RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint createdAt,
TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId,
List<Triple<Serializable, String, MaxPointsReason>> positionedCompetitors);
RaceLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors,
int passId, CompetitorResults positionedCompetitors);
RaceLogPathfinderEvent createPathfinderEvent(TimePoint createdAt, TimePoint logicalTimePoint, Serializable id,
List<Competitor> competitors, int passId, String pathfinderId);
RaceLogPathfinderEvent createPathfinderEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, List<Competitor> competitors, int passId, String pathfinderId);
RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint createdAt, TimePoint logicalTimePoint,
Serializable id, List<Competitor> competitors, int passId, Long gateLineOpeningTime);
RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint createdAt, RaceLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId, Long gateLaunchStopTime,
Long golfDownTime);
RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint createdAt, TimePoint timePoint,
Serializable id, List<Competitor> competitors, int passId, StartProcedureType type);
RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint createdAt, RaceLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId, RacingProcedureType type);
RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint createdAt, TimePoint timePoint,
Serializable id, List<Competitor> competitors, int passId, TimePoint protestStartTime);
RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint createdAt, RaceLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId, TimePoint protestStartTime);
RaceLogWindFixEvent createWindFixEvent(TimePoint createdAt, TimePoint timePoint, Serializable id,
List<Competitor> competitors, Integer passId, Wind wind);
RaceLogWindFixEvent createWindFixEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, List<Competitor> competitors, Integer passId, Wind wind);
}
@@ -1,10 +1,5 @@
package com.sap.sailing.domain.racelog;
import java.io.Serializable;
import java.util.List;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.impl.Util.Triple;
public abstract interface RaceLogFinishPositioningEvent extends RaceLogEvent {
@@ -12,5 +7,5 @@ public abstract interface RaceLogFinishPositioningEvent extends RaceLogEvent {
* @return a triple holding the competitor ID, the competitor name and the {@link MaxPointReason} documenting the
* score for the competitor
*/
List<Triple<Serializable, String, MaxPointsReason>> getPositionedCompetitorsIDsNamesMaxPointsReasons();
CompetitorResults getPositionedCompetitorsIDsNamesMaxPointsReasons();
}
@@ -1,6 +1,20 @@
package com.sap.sailing.domain.racelog;
import com.sap.sailing.domain.common.impl.Util.Pair;
public interface RaceLogGateLineOpeningTimeEvent extends RaceLogEvent {
Long getGateLineOpeningTime();
public class GateLineOpeningTimes extends Pair<Long, Long> {
private static final long serialVersionUID = -3262303047719105275L;
public GateLineOpeningTimes(long gateLaunchStopTime, long golfDownTime) {
super(gateLaunchStopTime, golfDownTime);
}
public final long getGateLaunchStopTime() { return this.getA(); }
public final long getGolfDownTime() { return this.getB(); }
}
GateLineOpeningTimes getGateLineOpeningTimes();
}
@@ -0,0 +1,15 @@
package com.sap.sailing.domain.racelog;
/**
* Constants shared across race committee app and servlet implementation
*
* @author Axel Uhl (d043530)
*
*/
public interface RaceLogServletConstants {
static final String PARAMS_LEADERBOARD_NAME = "leaderboard";
static final String PARAMS_RACE_COLUMN_NAME = "raceColumn";
static final String PARAMS_RACE_FLEET_NAME = "fleet";
static final String PARAMS_CLIENT_UUID = "clientuuid";
static final String PARAM_COURSE_AREA_FILTER = "courseArea";
}
@@ -1,9 +1,10 @@
package com.sap.sailing.domain.racelog;
import com.sap.sailing.domain.common.racelog.StartProcedureType;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
public interface RaceLogStartProcedureChangedEvent extends RaceLogEvent {
StartProcedureType getStartProcedureType();
RacingProcedureType getStartProcedureType();
}
@@ -1,22 +1,18 @@
package com.sap.sailing.domain.racelog.analyzing.impl;
import java.io.Serializable;
import java.util.List;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.racelog.CompetitorResults;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogFinishPositioningConfirmedEvent;
public class ConfirmedFinishPositioningListFinder extends RaceLogAnalyzer<List<Triple<Serializable, String, MaxPointsReason>>> {
public class ConfirmedFinishPositioningListFinder extends RaceLogAnalyzer<CompetitorResults> {
public ConfirmedFinishPositioningListFinder(RaceLog raceLog) {
super(raceLog);
}
@Override
protected List<Triple<Serializable, String, MaxPointsReason>> performAnalysis() {
protected CompetitorResults performAnalysis() {
for (RaceLogEvent event : getPassEventsDescending()) {
if (event instanceof RaceLogFinishPositioningConfirmedEvent) {
RaceLogFinishPositioningConfirmedEvent finishPositioningEvent = (RaceLogFinishPositioningConfirmedEvent) event;
@@ -1,22 +1,18 @@
package com.sap.sailing.domain.racelog.analyzing.impl;
import java.io.Serializable;
import java.util.List;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.racelog.CompetitorResults;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogFinishPositioningListChangedEvent;
public class FinishPositioningListFinder extends RaceLogAnalyzer<List<Triple<Serializable, String, MaxPointsReason>>> {
public class FinishPositioningListFinder extends RaceLogAnalyzer<CompetitorResults> {
public FinishPositioningListFinder(RaceLog raceLog) {
super(raceLog);
}
@Override
protected List<Triple<Serializable, String, MaxPointsReason>> performAnalysis() {
protected CompetitorResults performAnalysis() {
for (RaceLogEvent event : getPassEventsDescending()) {
if (event instanceof RaceLogFinishPositioningListChangedEvent) {
RaceLogFinishPositioningListChangedEvent finishPositioningEvent = (RaceLogFinishPositioningListChangedEvent) event;
@@ -18,7 +18,7 @@ public class FinishedTimeFinder extends RaceLogAnalyzer<TimePoint> {
if (event instanceof RaceLogRaceStatusEvent) {
RaceLogRaceStatusEvent statusEvent = (RaceLogRaceStatusEvent) event;
if (statusEvent.getNextStatus().equals(RaceLogRaceStatus.FINISHED)) {
return statusEvent.getTimePoint();
return statusEvent.getLogicalTimePoint();
}
}
}
@@ -18,7 +18,7 @@ public class FinishingTimeFinder extends RaceLogAnalyzer<TimePoint> {
if (event instanceof RaceLogRaceStatusEvent) {
RaceLogRaceStatusEvent statusEvent = (RaceLogRaceStatusEvent) event;
if (statusEvent.getNextStatus().equals(RaceLogRaceStatus.FINISHING)) {
return statusEvent.getTimePoint();
return statusEvent.getLogicalTimePoint();
}
}
}
@@ -3,18 +3,19 @@ package com.sap.sailing.domain.racelog.analyzing.impl;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogGateLineOpeningTimeEvent;
import com.sap.sailing.domain.racelog.RaceLogGateLineOpeningTimeEvent.GateLineOpeningTimes;
public class GateLineOpeningTimeFinder extends RaceLogAnalyzer<Long> {
public class GateLineOpeningTimeFinder extends RaceLogAnalyzer<GateLineOpeningTimes> {
public GateLineOpeningTimeFinder(RaceLog raceLog) {
super(raceLog);
}
@Override
protected Long performAnalysis() {
for (RaceLogEvent event : getPassEvents()) {
protected GateLineOpeningTimes performAnalysis() {
for (RaceLogEvent event : getPassEventsDescending()) {
if (event instanceof RaceLogGateLineOpeningTimeEvent) {
return ((RaceLogGateLineOpeningTimeEvent) event).getGateLineOpeningTime();
return ((RaceLogGateLineOpeningTimeEvent) event).getGateLineOpeningTimes();
}
}
@@ -15,11 +15,11 @@ public abstract class IndividualRecallFinder extends RaceLogAnalyzer<TimePoint>
@Override
protected TimePoint performAnalysis() {
for (RaceLogEvent event : getPassEvents()) {
for (RaceLogEvent event : getPassEventsDescending()) {
if (event instanceof RaceLogFlagEvent) {
RaceLogFlagEvent flagEvent = (RaceLogFlagEvent) event;
if (isRelevant(flagEvent)) {
return flagEvent.getTimePoint();
return flagEvent.getLogicalTimePoint();
}
}
}
@@ -0,0 +1,34 @@
package com.sap.sailing.domain.racelog.analyzing.impl;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.racelog.RaceLog;
public class IsIndividualRecallDisplayedAnalyzer extends RaceLogAnalyzer<Boolean> {
private final IndividualRecallFinder displayedFinder;
private final IndividualRecallFinder removedFinder;
public IsIndividualRecallDisplayedAnalyzer(RaceLog raceLog) {
this(raceLog, new IndividualRecallDisplayedFinder(raceLog), new IndividualRecallRemovedFinder(raceLog));
}
public IsIndividualRecallDisplayedAnalyzer(RaceLog raceLog, IndividualRecallDisplayedFinder displayedFinder,
IndividualRecallRemovedFinder removedFinder) {
super(raceLog);
this.displayedFinder = displayedFinder;
this.removedFinder = removedFinder;
}
@Override
protected Boolean performAnalysis() {
TimePoint displayedAt = displayedFinder.analyze();
TimePoint removedAt = removedFinder.analyze();
if (displayedAt != null) {
if (removedAt == null || displayedAt.after(removedAt)) {
return true;
}
}
return false;
}
}
@@ -12,10 +12,12 @@ import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogFlagEvent;
/**
* Analyzation returns the most recent {@link RaceLogFlagEvent}s.
* Analysis returns the most recent {@link RaceLogFlagEvent}s.
* <p>
*
* If there is no {@link RaceLogFlagEvent} in the current pass, <code>null</code> is returned. Otherwise a {@link List}
* of {@link RaceLogFlagEvent} is returned containing all {@link RaceLogEvent}s with the most recent {@link TimePoint}.
* of {@link RaceLogFlagEvent} is returned containing all {@link RaceLogEvent}s with the most recent (logical)
* {@link TimePoint}.
*
*/
public class LastFlagsFinder extends RaceLogAnalyzer<List<RaceLogFlagEvent>> {
@@ -38,9 +40,9 @@ public class LastFlagsFinder extends RaceLogAnalyzer<List<RaceLogFlagEvent>> {
private List<RaceLogFlagEvent> collectAllWithSameTimePoint(Iterator<RaceLogEvent> iterator,
RaceLogFlagEvent flagEvent) {
List<RaceLogFlagEvent> result = new ArrayList<RaceLogFlagEvent>();
TimePoint lastFlagsTime = flagEvent.getTimePoint();
TimePoint logicalTime = flagEvent.getLogicalTimePoint();
while (flagEvent.getTimePoint().equals(lastFlagsTime)) {
while (flagEvent.getLogicalTimePoint().equals(logicalTime)) {
result.add(flagEvent);
flagEvent = getNextFlagEvent(iterator);
if (flagEvent == null) {
@@ -62,11 +64,11 @@ public class LastFlagsFinder extends RaceLogAnalyzer<List<RaceLogFlagEvent>> {
}
/**
* Use this method the obtain the most "interesting" {@link RaceLogFlagEvent} of the {@link LastFlagsFinder}'s
* analyzation result.
* Use this method to obtain the most "interesting" {@link RaceLogFlagEvent} of the {@link LastFlagsFinder}'s
* analysis result.
*
* If an empty list or <code>null</code> is passed, this method returns <code>null</code>. Otherwise the (most
* recent) {@link RaceLogFlagEvent} with the highest ID is returned favoring events with
* recent by logical timestamp) {@link RaceLogFlagEvent} with the highest ID is returned favoring events with
* {@link RaceLogFlagEvent#isDisplayed()} returning <code>true</code>.
*
* @param events
@@ -82,7 +84,7 @@ public class LastFlagsFinder extends RaceLogAnalyzer<List<RaceLogFlagEvent>> {
Collections.sort(sortedEvents, new Comparator<RaceLogFlagEvent>() {
@Override
public int compare(RaceLogFlagEvent left, RaceLogFlagEvent right) {
int result = right.getTimePoint().compareTo(left.getTimePoint());
int result = right.getLogicalTimePoint().compareTo(left.getLogicalTimePoint());
if (result == 0) {
result = Boolean.valueOf(right.isDisplayed()).compareTo(left.isDisplayed());
if (result == 0) {
@@ -4,15 +4,17 @@ import java.util.List;
import java.util.Arrays;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.common.racelog.StartProcedureType;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogFlagEvent;
public class RRS26StartModeFlagFinder extends RaceLogAnalyzer<Flags> {
private final List<Flags> startModeFlags = Arrays.asList(Flags.PAPA, Flags.ZULU, Flags.BLACK, Flags.INDIA);
private StartProcedureTypeAnalyzer procedureAnalyzer;
private final static List<Flags> defaultStartModeFlags = Arrays.asList(Flags.PAPA, Flags.ZULU, Flags.BLACK, Flags.INDIA);
private final RacingProcedureTypeAnalyzer procedureAnalyzer;
private final List<Flags> startModeFlags;
/**
* Searches for the start mode flag of a RRS26 race.
@@ -21,24 +23,31 @@ public class RRS26StartModeFlagFinder extends RaceLogAnalyzer<Flags> {
* to be used to ensure a RRS26 race. Must operate on the same race log. Otherwise a
* {@link IllegalArgumentException} is thrown.
*/
public RRS26StartModeFlagFinder(StartProcedureTypeAnalyzer procedureAnalyzer, RaceLog raceLog) {
public RRS26StartModeFlagFinder(RacingProcedureTypeAnalyzer procedureAnalyzer, RaceLog raceLog) {
this(procedureAnalyzer, raceLog, defaultStartModeFlags);
}
public RRS26StartModeFlagFinder(RacingProcedureTypeAnalyzer procedureAnalyzer, RaceLog raceLog, List<Flags> startModeFlags) {
super(raceLog);
if (raceLog != procedureAnalyzer.getRaceLog()) {
throw new IllegalArgumentException("Both analyzers must operate on the same race log.");
}
this.procedureAnalyzer = procedureAnalyzer;
this.startModeFlags = startModeFlags;
}
@Override
protected Flags performAnalysis() {
StartProcedureType type = procedureAnalyzer.analyze();
if (StartProcedureType.RRS26.equals(type)) {
for (RaceLogEvent event : getPassEventsDescending()) {
if (event instanceof RaceLogFlagEvent) {
RaceLogFlagEvent flagEvent = (RaceLogFlagEvent) event;
if (isStartModeFlagEvent(flagEvent)) {
return flagEvent.getUpperFlag();
}
RacingProcedureType type = procedureAnalyzer.analyze();
if (!RacingProcedureType.RRS26.equals(type)) {
return null;
}
for (RaceLogEvent event : getPassEventsDescending()) {
if (event instanceof RaceLogFlagEvent) {
RaceLogFlagEvent flagEvent = (RaceLogFlagEvent) event;
if (isStartModeFlagEvent(flagEvent)) {
return flagEvent.getUpperFlag();
}
}
}
@@ -1,14 +1,39 @@
package com.sap.sailing.domain.racelog.analyzing.impl;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent;
import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent;
import com.sap.sailing.domain.racelog.impl.BaseRaceLogEventVisitor;
import com.sap.sailing.domain.racelog.state.racingprocedure.ReadonlyRacingProcedure;
public class RaceStatusAnalyzer extends RaceLogAnalyzer<RaceLogRaceStatus> {
public RaceStatusAnalyzer(RaceLog raceLog) {
public interface Clock {
TimePoint now();
}
public final static class StandardClock implements Clock {
@Override
public TimePoint now() {
return MillisecondsTimePoint.now();
}
}
private final EventDispatcher eventDispatcher;
public RaceStatusAnalyzer(RaceLog raceLog, ReadonlyRacingProcedure racingProcedure) {
super(raceLog);
this.eventDispatcher = new EventDispatcher(new StandardClock(), racingProcedure);
}
public RaceStatusAnalyzer(RaceLog raceLog, Clock clock, ReadonlyRacingProcedure racingProcedure) {
super(raceLog);
this.eventDispatcher = new EventDispatcher(clock, racingProcedure);
}
@Override
@@ -16,11 +41,43 @@ public class RaceStatusAnalyzer extends RaceLogAnalyzer<RaceLogRaceStatus> {
for (RaceLogEvent event : getPassEventsDescending()) {
if (event instanceof RaceLogRaceStatusEvent) {
RaceLogRaceStatusEvent statusEvent = (RaceLogRaceStatusEvent) event;
return statusEvent.getNextStatus();
statusEvent.accept(eventDispatcher);
return eventDispatcher.nextStatus;
}
}
return RaceLogRaceStatus.UNSCHEDULED;
}
private class EventDispatcher extends BaseRaceLogEventVisitor {
private final Clock clock;
private final ReadonlyRacingProcedure racingProcedure;
public RaceLogRaceStatus nextStatus;
public EventDispatcher(Clock clock, ReadonlyRacingProcedure racingProcedure) {
this.clock = clock;
this.racingProcedure = racingProcedure;
this.nextStatus = RaceLogRaceStatus.UNKNOWN;
}
@Override
public void visit(RaceLogStartTimeEvent event) {
TimePoint now = clock.now();
if (racingProcedure.isStartphaseActive(event.getStartTime(), now)) {
nextStatus = RaceLogRaceStatus.STARTPHASE;
} else if (now.before(event.getStartTime())) {
nextStatus = RaceLogRaceStatus.SCHEDULED;
} else {
nextStatus = RaceLogRaceStatus.RUNNING;
}
};
@Override
public void visit(RaceLogRaceStatusEvent event) {
nextStatus = event.getNextStatus();
};
};
}
@@ -1,25 +1,25 @@
package com.sap.sailing.domain.racelog.analyzing.impl;
import com.sap.sailing.domain.common.racelog.StartProcedureType;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogStartProcedureChangedEvent;
public class StartProcedureTypeAnalyzer extends RaceLogAnalyzer<StartProcedureType> {
public class RacingProcedureTypeAnalyzer extends RaceLogAnalyzer<RacingProcedureType> {
public StartProcedureTypeAnalyzer(RaceLog raceLog) {
public RacingProcedureTypeAnalyzer(RaceLog raceLog) {
super(raceLog);
}
@Override
protected StartProcedureType performAnalysis() {
protected RacingProcedureType performAnalysis() {
for (RaceLogEvent event : getAllEventsDescending()) {
if (event instanceof RaceLogStartProcedureChangedEvent) {
RaceLogStartProcedureChangedEvent startProcedureEvent = (RaceLogStartProcedureChangedEvent) event;
return startProcedureEvent.getStartProcedureType();
}
}
return null;
return RacingProcedureType.UNKNOWN;
}
}
@@ -0,0 +1,88 @@
package com.sap.sailing.domain.racelog.impl;
import com.sap.sailing.domain.racelog.RaceLogCourseAreaChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogCourseDesignChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogEventVisitor;
import com.sap.sailing.domain.racelog.RaceLogFinishPositioningConfirmedEvent;
import com.sap.sailing.domain.racelog.RaceLogFinishPositioningListChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogFlagEvent;
import com.sap.sailing.domain.racelog.RaceLogGateLineOpeningTimeEvent;
import com.sap.sailing.domain.racelog.RaceLogPassChangeEvent;
import com.sap.sailing.domain.racelog.RaceLogPathfinderEvent;
import com.sap.sailing.domain.racelog.RaceLogProtestStartTimeEvent;
import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent;
import com.sap.sailing.domain.racelog.RaceLogStartProcedureChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent;
import com.sap.sailing.domain.racelog.RaceLogWindFixEvent;
/**
* Base class implementing {@link RaceLogEventVisitor}. Every method is implemented as a no-op.
*/
public abstract class BaseRaceLogEventVisitor implements RaceLogEventVisitor {
@Override
public void visit(RaceLogFlagEvent event) {
}
@Override
public void visit(RaceLogPassChangeEvent event) {
}
@Override
public void visit(RaceLogRaceStatusEvent event) {
}
@Override
public void visit(RaceLogStartTimeEvent event) {
}
@Override
public void visit(RaceLogCourseAreaChangedEvent event) {
}
@Override
public void visit(RaceLogCourseDesignChangedEvent event) {
}
@Override
public void visit(RaceLogFinishPositioningListChangedEvent event) {
}
@Override
public void visit(RaceLogFinishPositioningConfirmedEvent event) {
}
@Override
public void visit(RaceLogPathfinderEvent event) {
}
@Override
public void visit(RaceLogGateLineOpeningTimeEvent event) {
}
@Override
public void visit(RaceLogStartProcedureChangedEvent event) {
}
@Override
public void visit(RaceLogProtestStartTimeEvent event) {
}
@Override
public void visit(RaceLogWindFixEvent event) {
}
}
@@ -0,0 +1,14 @@
package com.sap.sailing.domain.racelog.impl;
import java.io.Serializable;
import java.util.ArrayList;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.racelog.CompetitorResults;
public class CompetitorResultsImpl extends ArrayList<Triple<Serializable, String, MaxPointsReason>> implements CompetitorResults {
private static final long serialVersionUID = 4928351242700897387L;
}
@@ -0,0 +1,192 @@
package com.sap.sailing.domain.racelog.impl;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventVisitor;
/**
* Wrapper for a {@link RaceLog} which will ignore all calls trying to add an {@link RaceLogEvent}. All other
* functionality redirects to the wrapper {@link RaceLog}.
*/
public class NoAddingRaceLogWrapper implements RaceLog {
private static final long serialVersionUID = -5145744179072564993L;
private static final Logger logger = Logger.getLogger(NoAddingRaceLogWrapper.class.getSimpleName());
private final RaceLog innerRaceLog;
public NoAddingRaceLogWrapper(RaceLog innerRaceLog) {
this.innerRaceLog = innerRaceLog;
}
@Override
public boolean add(RaceLogEvent event) {
logger.log(Level.FINEST, "add() called; event will not be added.");
return false;
}
@Override
public Iterable<RaceLogEvent> add(RaceLogEvent event, UUID clientId) {
logger.log(Level.FINEST, "add() called; event will not be added.");
return Collections.emptyList();
}
@Override
public void addListener(RaceLogEventVisitor listener) {
innerRaceLog.addListener(listener);
}
@Override
public void removeListener(RaceLogEventVisitor listener) {
innerRaceLog.removeListener(listener);
}
@Override
public void addAllListeners(HashSet<RaceLogEventVisitor> listeners) {
innerRaceLog.addAllListeners(listeners);
}
@Override
public HashSet<RaceLogEventVisitor> removeAllListeners() {
return innerRaceLog.removeAllListeners();
}
@Override
public Iterable<RaceLogEventVisitor> getAllListeners() {
return innerRaceLog.getAllListeners();
}
@Override
public void lockForRead() {
innerRaceLog.lockForRead();
}
@Override
public void unlockAfterRead() {
innerRaceLog.unlockAfterRead();
}
@Override
public Iterable<RaceLogEvent> getFixes() {
return innerRaceLog.getFixes();
}
@Override
public Iterable<RaceLogEvent> getRawFixes() {
return innerRaceLog.getRawFixes();
}
@Override
public RaceLogEvent getLastFixAtOrBefore(TimePoint timePoint) {
return innerRaceLog.getLastFixAtOrBefore(timePoint);
}
@Override
public RaceLogEvent getLastFixBefore(TimePoint timePoint) {
return innerRaceLog.getLastFixBefore(timePoint);
}
@Override
public RaceLogEvent getLastRawFixAtOrBefore(TimePoint timePoint) {
return innerRaceLog.getLastRawFixAtOrBefore(timePoint);
}
@Override
public RaceLogEvent getFirstFixAtOrAfter(TimePoint timePoint) {
return innerRaceLog.getFirstFixAtOrAfter(timePoint);
}
@Override
public RaceLogEvent getFirstRawFixAtOrAfter(TimePoint timePoint) {
return innerRaceLog.getFirstRawFixAtOrAfter(timePoint);
}
@Override
public RaceLogEvent getLastRawFixBefore(TimePoint timePoint) {
return innerRaceLog.getLastRawFixBefore(timePoint);
}
@Override
public RaceLogEvent getFirstRawFixAfter(TimePoint timePoint) {
return innerRaceLog.getFirstRawFixAfter(timePoint);
}
@Override
public RaceLogEvent getFirstFixAfter(TimePoint timePoint) {
return innerRaceLog.getFirstFixAfter(timePoint);
}
@Override
public RaceLogEvent getFirstRawFix() {
return innerRaceLog.getFirstRawFix();
}
@Override
public RaceLogEvent getLastRawFix() {
return innerRaceLog.getLastRawFix();
}
@Override
public Iterator<RaceLogEvent> getFixesIterator(TimePoint startingAt, boolean inclusive) {
return innerRaceLog.getFixesIterator(startingAt, inclusive);
}
@Override
public Iterator<RaceLogEvent> getRawFixesIterator(TimePoint startingAt, boolean inclusive) {
return innerRaceLog.getRawFixesIterator(startingAt, inclusive);
}
@Override
public Serializable getId() {
return innerRaceLog;
}
@Override
public int getCurrentPassId() {
return innerRaceLog.getCurrentPassId();
}
@Override
public boolean isEmpty() {
return innerRaceLog.isEmpty();
}
@Override
public Iterable<RaceLogEvent> getRawFixesDescending() {
return innerRaceLog.getRawFixesDescending();
}
@Override
public Iterable<RaceLogEvent> getFixesDescending() {
return innerRaceLog.getFixesDescending();
}
@Override
public Iterable<RaceLogEvent> getRawFixes(UUID clientId) {
return innerRaceLog.getRawFixes(clientId);
}
@Override
public boolean load(RaceLogEvent event) {
return innerRaceLog.load(event);
}
@Override
public Iterator<RaceLogEvent> getFixesDescendingIterator(TimePoint startingAt, boolean inclusive) {
return innerRaceLog.getFixesDescendingIterator(startingAt, inclusive);
}
@Override
public Iterator<RaceLogEvent> getRawFixesDescendingIterator(TimePoint startingAt, boolean inclusive) {
return innerRaceLog.getRawFixesDescendingIterator(startingAt, inclusive);
}
}
@@ -1,5 +1,6 @@
package com.sap.sailing.racecommittee.app.domain.racelog.impl;
package com.sap.sailing.domain.racelog.impl;
import com.sap.sailing.domain.racelog.RaceLogChangedListener;
import com.sap.sailing.domain.racelog.RaceLogCourseAreaChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogCourseDesignChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogEventVisitor;
@@ -14,7 +15,6 @@ import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent;
import com.sap.sailing.domain.racelog.RaceLogStartProcedureChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent;
import com.sap.sailing.domain.racelog.RaceLogWindFixEvent;
import com.sap.sailing.racecommittee.app.domain.racelog.RaceLogChangedListener;
public class RaceLogChangedVisitor implements RaceLogEventVisitor {
@@ -6,17 +6,18 @@ import java.util.List;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.racelog.RaceLogCourseAreaChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogEventVisitor;
public class RaceLogCourseAreaChangeEventImpl extends RaceLogEventImpl implements
RaceLogCourseAreaChangedEvent {
private static final long serialVersionUID = -3943108136024977860L;
private Serializable courseAreaId;
private final Serializable courseAreaId;
public RaceLogCourseAreaChangeEventImpl(TimePoint createdAt,
TimePoint pTimePoint, Serializable pId, List<Competitor> pInvolvedBoats, int pPassId, Serializable courseAreaId) {
super(createdAt, pTimePoint, pId, pInvolvedBoats, pPassId);
RaceLogEventAuthor author, TimePoint pTimePoint, Serializable pId, List<Competitor> pInvolvedBoats, int pPassId, Serializable courseAreaId) {
super(createdAt, author, pTimePoint, pId, pInvolvedBoats, pPassId);
this.courseAreaId = courseAreaId;
}
@@ -7,16 +7,17 @@ import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CourseBase;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.racelog.RaceLogCourseDesignChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogEventVisitor;
public class RaceLogCourseDesignChangedEventImpl extends RaceLogEventImpl implements RaceLogCourseDesignChangedEvent {
private static final long serialVersionUID = 1565936170747420547L;
private CourseBase courseDesign;
private final CourseBase courseDesign;
public RaceLogCourseDesignChangedEventImpl(TimePoint createdAt,
TimePoint pTimePoint, Serializable pId, List<Competitor> pInvolvedBoats, int pPassId, CourseBase courseDesign) {
super(createdAt, pTimePoint, pId, pInvolvedBoats, pPassId);
RaceLogEventAuthor author, TimePoint pTimePoint, Serializable pId, List<Competitor> pInvolvedBoats, int pPassId, CourseBase courseDesign) {
super(createdAt, author, pTimePoint, pId, pInvolvedBoats, pPassId);
this.courseDesign = courseDesign;
}
@@ -0,0 +1,33 @@
package com.sap.sailing.domain.racelog.impl;
import com.sap.sailing.domain.common.impl.NamedImpl;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
public class RaceLogEventAuthorImpl extends NamedImpl implements RaceLogEventAuthor {
private static final long serialVersionUID = -5602802911563685812L;
private final int priority;
public static RaceLogEventAuthor createCompatibilityAuthor() {
return new RaceLogEventAuthorImpl(NAME_COMPATIBILITY, PRIORITY_COMPATIBILITY);
}
public RaceLogEventAuthorImpl(String name, int priority) {
super(name);
this.priority = priority;
}
@Override
public int getPriority() {
return priority;
}
@Override
public int compareTo(RaceLogEventAuthor other) {
return new Integer(other.getPriority()).compareTo(getPriority());
}
@Override
public String toString() {
return super.toString()+" with priority "+getPriority();
}
}
@@ -5,38 +5,50 @@ import java.util.Comparator;
import com.sap.sailing.domain.base.Timed;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.tracking.impl.TimedComparator;
/**
* Comparator sorting by pass, then by {@link RaceLogEventAuthor}, then by {@link RaceLogEvent#getCreatedAt()}
* timestamp.
*
* If one of the passed objects is not a {@link RaceLogEvent}, sorting is done by {@link Timed#getTimePoint()}.
*/
public enum RaceLogEventComparator implements Comparator<Timed>, Serializable {
INSTANCE;
private Comparator<Timed> timedComparator;
private RaceLogEventComparator() {
this.timedComparator = TimedComparator.INSTANCE;
}
@Override
public int compare(Timed o1, Timed o2) {
if (o1 instanceof RaceLogEvent && o2 instanceof RaceLogEvent) {
return compareEvents((RaceLogEvent)o1, (RaceLogEvent)o2);
return compareEvents((RaceLogEvent) o1, (RaceLogEvent) o2);
}
// fallback to timed comparison
return timedComparator.compare(o1, o2);
}
private int compareEvents(RaceLogEvent e1, RaceLogEvent e2) {
int result = comparePasses(e1, e2);
return result == 0 ? compareTimes(e1, e2) : result;
return result == 0 ? compareAuthorPriorities(e1, e2) : result;
}
private int comparePasses(RaceLogEvent e1, RaceLogEvent e2) {
return e1.getPassId() - e2.getPassId();
}
private int compareTimes(RaceLogEvent e1, RaceLogEvent e2) {
int result = timedComparator.compare(e1, e2);
private int compareAuthorPriorities(RaceLogEvent e1, RaceLogEvent e2) {
int result = e1.getAuthor().compareTo(e2.getAuthor());
return result == 0 ? compareCreatedAtTimes(e1, e2) : result;
}
private int compareCreatedAtTimes(RaceLogEvent e1, RaceLogEvent e2) {
int result = e1.getCreatedAt().compareTo(e2.getCreatedAt());
return result == 0 ? compareIds(e1, e2) : result;
}
@@ -7,15 +7,15 @@ import java.util.UUID;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CourseBase;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.domain.common.racelog.StartProcedureType;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
import com.sap.sailing.domain.racelog.CompetitorResults;
import com.sap.sailing.domain.racelog.RaceLogCourseAreaChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogCourseDesignChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogEventFactory;
import com.sap.sailing.domain.racelog.RaceLogFinishPositioningConfirmedEvent;
import com.sap.sailing.domain.racelog.RaceLogFlagEvent;
@@ -32,172 +32,172 @@ import com.sap.sailing.domain.tracking.Wind;
public class RaceLogEventFactoryImpl implements RaceLogEventFactory {
@Override
public RaceLogFlagEvent createFlagEvent(TimePoint timePoint, Serializable id, List<Competitor> involvedBoats,
int passId, Flags upperFlag, Flags lowerFlag, boolean isDisplayed) {
return new RaceLogFlagEventImpl(MillisecondsTimePoint.now(), timePoint, id, involvedBoats, passId, upperFlag,
public RaceLogFlagEvent createFlagEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, Serializable id,
List<Competitor> involvedBoats, int passId, Flags upperFlag, Flags lowerFlag, boolean isDisplayed) {
return new RaceLogFlagEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, involvedBoats, passId,
upperFlag, lowerFlag, isDisplayed);
}
@Override
public RaceLogFlagEvent createFlagEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, int passId, Flags upperFlag,
Flags lowerFlag, boolean isDisplayed) {
return createFlagEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList<Competitor>(), passId, upperFlag,
lowerFlag, isDisplayed);
}
@Override
public RaceLogFlagEvent createFlagEvent(TimePoint timePoint, int passId, Flags upperFlag, Flags lowerFlag,
boolean isDisplayed) {
return createFlagEvent(timePoint, UUID.randomUUID(), new ArrayList<Competitor>(), passId, upperFlag, lowerFlag,
isDisplayed);
public RaceLogStartTimeEvent createStartTimeEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
Serializable id, List<Competitor> involvedBoats, int passId, TimePoint startTime) {
return new RaceLogStartTimeEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, involvedBoats,
passId, startTime);
}
@Override
public RaceLogStartTimeEvent createStartTimeEvent(TimePoint timePoint, Serializable id,
List<Competitor> involvedBoats, int passId, TimePoint startTime) {
return new RaceLogStartTimeEventImpl(MillisecondsTimePoint.now(), timePoint, id, involvedBoats, passId,
startTime);
public RaceLogStartTimeEvent createStartTimeEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, int passId, TimePoint startTime) {
return createStartTimeEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList<Competitor>(), passId, startTime);
}
@Override
public RaceLogStartTimeEvent createStartTimeEvent(TimePoint timePoint, int passId, TimePoint startTime) {
return createStartTimeEvent(timePoint, UUID.randomUUID(), new ArrayList<Competitor>(), passId, startTime);
public RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
Serializable id, List<Competitor> competitors, int passId, RaceLogRaceStatus nextStatus) {
return new RaceLogRaceStatusEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, competitors,
passId, nextStatus);
}
@Override
public RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint timePoint, Serializable id,
List<Competitor> competitors, int passId, RaceLogRaceStatus nextStatus) {
return new RaceLogRaceStatusEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId,
nextStatus);
public RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, int passId, RaceLogRaceStatus nextStatus) {
return createRaceStatusEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList<Competitor>(), passId, nextStatus);
}
@Override
public RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint timePoint, int passId, RaceLogRaceStatus nextStatus) {
return createRaceStatusEvent(timePoint, UUID.randomUUID(), new ArrayList<Competitor>(), passId, nextStatus);
public RaceLogPassChangeEvent createPassChangeEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
Serializable id, List<Competitor> competitors, int passId) {
return new RaceLogPassChangeEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, competitors, passId);
}
@Override
public RaceLogPassChangeEvent createPassChangeEvent(TimePoint timePoint, Serializable id,
List<Competitor> competitors, int passId) {
return new RaceLogPassChangeEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId);
public RaceLogPassChangeEvent createPassChangeEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, int passId) {
return createPassChangeEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList<Competitor>(), passId);
}
@Override
public RaceLogPassChangeEvent createPassChangeEvent(TimePoint timePoint, int passId) {
return createPassChangeEvent(timePoint, UUID.randomUUID(), new ArrayList<Competitor>(), passId);
public RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
Serializable id, List<Competitor> competitors, int passId, Serializable courseAreaId) {
return new RaceLogCourseAreaChangeEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, competitors,
passId, courseAreaId);
}
@Override
public RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint timePoint, Serializable id,
List<Competitor> competitors, int passId, Serializable courseAreaId) {
return new RaceLogCourseAreaChangeEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId,
courseAreaId);
public RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
int passId, Serializable courseAreaId) {
return createCourseAreaChangedEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList<Competitor>(),
passId, courseAreaId);
}
@Override
public RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint timePoint, int passId,
Serializable courseAreaId) {
return createCourseAreaChangedEvent(timePoint, UUID.randomUUID(), new ArrayList<Competitor>(), passId,
courseAreaId);
public RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
Serializable id, List<Competitor> competitors, int passId, CourseBase courseData) {
return new RaceLogCourseDesignChangedEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, competitors,
passId, courseData);
}
@Override
public RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint timePoint, Serializable id,
List<Competitor> competitors, int passId, CourseBase courseData) {
return new RaceLogCourseDesignChangedEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId,
courseData);
public RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
int passId, CourseBase courseData) {
return createCourseDesignChangedEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList<Competitor>(),
passId, courseData);
}
@Override
public RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint timePoint, int passId,
CourseBase courseData) {
return createCourseDesignChangedEvent(timePoint, UUID.randomUUID(), new ArrayList<Competitor>(), passId,
courseData);
public RaceLogFinishPositioningListChangedEventImpl createFinishPositioningListChangedEvent(TimePoint logicalTimePoint,
RaceLogEventAuthor author, Serializable id, List<Competitor> competitors,
int passId, CompetitorResults positionedCompetitors) {
return new RaceLogFinishPositioningListChangedEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint,
id, competitors, passId, positionedCompetitors);
}
@Override
public RaceLogFinishPositioningListChangedEventImpl createFinishPositioningListChangedEvent(TimePoint timePoint,
Serializable id, List<Competitor> competitors, int passId,
List<Triple<Serializable, String, MaxPointsReason>> positionedCompetitors) {
return new RaceLogFinishPositioningListChangedEventImpl(MillisecondsTimePoint.now(), timePoint, id,
public RaceLogFinishPositioningListChangedEventImpl createFinishPositioningListChangedEvent(TimePoint logicalTimePoint,
RaceLogEventAuthor author, int passId, CompetitorResults positionedCompetitors) {
return createFinishPositioningListChangedEvent(logicalTimePoint, author, UUID.randomUUID(),
new ArrayList<Competitor>(), passId, positionedCompetitors);
}
@Override
public RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint logicalTimePoint,
RaceLogEventAuthor author, Serializable id, List<Competitor> competitors, int passId, CompetitorResults positionedCompetitors) {
return new RaceLogFinishPositioningConfirmedEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id,
competitors, passId, positionedCompetitors);
}
@Override
public RaceLogFinishPositioningListChangedEventImpl createFinishPositioningListChangedEvent(TimePoint timePoint,
int passId, List<Triple<Serializable, String, MaxPointsReason>> positionedCompetitors) {
return createFinishPositioningListChangedEvent(timePoint, UUID.randomUUID(), new ArrayList<Competitor>(),
passId, positionedCompetitors);
public RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
int passId, CompetitorResults positionedCompetitors) {
return createFinishPositioningConfirmedEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList<Competitor>(), passId, positionedCompetitors);
}
@Override
public RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint timePoint,
Serializable id, List<Competitor> competitors, int passId, List<Triple<Serializable, String, MaxPointsReason>> positionedCompetitors) {
return new RaceLogFinishPositioningConfirmedEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors,
passId, positionedCompetitors);
public RaceLogPathfinderEvent createPathfinderEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
Serializable id, List<Competitor> competitors, int passId, String pathfinderId) {
return new RaceLogPathfinderEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, competitors,
passId, pathfinderId);
}
@Override
public RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint timePoint, int passId,
List<Triple<Serializable, String, MaxPointsReason>> positionedCompetitors) {
return createFinishPositioningConfirmedEvent(timePoint, UUID.randomUUID(), new ArrayList<Competitor>(), passId, positionedCompetitors);
public RaceLogPathfinderEvent createPathfinderEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, int passId, String pathfinderId) {
return createPathfinderEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList<Competitor>(), passId, pathfinderId);
}
@Override
public RaceLogPathfinderEvent createPathfinderEvent(TimePoint timePoint, Serializable id,
List<Competitor> competitors, int passId, String pathfinderId) {
return new RaceLogPathfinderEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId,
pathfinderId);
public RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
Serializable id, List<Competitor> competitors, int passId, Long gateLaunchStopTime, Long golfDownTime) {
return new RaceLogGateLineOpeningTimeEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, competitors,
passId, gateLaunchStopTime, golfDownTime);
}
@Override
public RaceLogPathfinderEvent createPathfinderEvent(TimePoint timePoint, int passId, String pathfinderId) {
return createPathfinderEvent(timePoint, UUID.randomUUID(), new ArrayList<Competitor>(), passId, pathfinderId);
public RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
int passId, Long gateLaunchStopTime, Long golfDownTime) {
return createGateLineOpeningTimeEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList<Competitor>(),
passId, gateLaunchStopTime, golfDownTime);
}
@Override
public RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint timePoint, Serializable id,
List<Competitor> competitors, int passId, Long gateLineOpeningTimeInMillis) {
return new RaceLogGateLineOpeningTimeEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId,
gateLineOpeningTimeInMillis);
public RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
Serializable id, List<Competitor> competitors, int passId, RacingProcedureType type) {
return new RaceLogStartProcedureChangedEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id,
competitors, passId, type);
}
@Override
public RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint timePoint, int passId,
Long gateLineOpeningTimeInMillis) {
return createGateLineOpeningTimeEvent(timePoint, UUID.randomUUID(), new ArrayList<Competitor>(), passId,
gateLineOpeningTimeInMillis);
public RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
int passId, RacingProcedureType type) {
return createStartProcedureChangedEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList<Competitor>(), passId, type);
}
@Override
public RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint timePoint, Serializable id,
List<Competitor> competitors, int passId, StartProcedureType type) {
return new RaceLogStartProcedureChangedEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors,
passId, type);
public RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
Serializable id, List<Competitor> competitors, int passId, TimePoint protestStartTime) {
return new RaceLogProtestStartTimeEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id,
competitors, passId, protestStartTime);
}
@Override
public RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint timePoint, int passId,
StartProcedureType type) {
return createStartProcedureChangedEvent(timePoint, UUID.randomUUID(), new ArrayList<Competitor>(), passId, type);
}
@Override
public RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint timePoint, Serializable id,
List<Competitor> competitors, int passId, TimePoint protestStartTime) {
return new RaceLogProtestStartTimeEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors,
public RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author,
int passId, TimePoint protestStartTime) {
return createProtestStartTimeEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList<Competitor>(),
passId, protestStartTime);
}
@Override
public RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint timePoint, int passId,
TimePoint protestStartTime) {
return createProtestStartTimeEvent(timePoint, UUID.randomUUID(), new ArrayList<Competitor>(), passId,
protestStartTime);
public RaceLogWindFixEvent createWindFixEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, int passId, Wind wind) {
return createWindFixEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList<Competitor>(), passId, wind);
}
@Override
public RaceLogWindFixEvent createWindFixEvent(TimePoint timePoint, int passId, Wind wind) {
return createWindFixEvent(timePoint, UUID.randomUUID(), new ArrayList<Competitor>(), passId, wind);
}
@Override
public RaceLogWindFixEvent createWindFixEvent(TimePoint timePoint, Serializable id, List<Competitor> competitors,
int passId, Wind wind) {
return new RaceLogWindFixEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId, wind);
public RaceLogWindFixEvent createWindFixEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, Serializable id,
List<Competitor> competitors, int passId, Wind wind) {
return new RaceLogWindFixEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, competitors, passId, wind);
}
}
@@ -6,21 +6,24 @@ import java.util.List;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
public abstract class RaceLogEventImpl implements RaceLogEvent {
private static final long serialVersionUID = -5810258278984777732L;
private TimePoint createdAt;
private TimePoint logicalTimePoint;
private Serializable id;
private List<Competitor> involvedBoats;
private int passId;
private final TimePoint createdAt;
private final TimePoint logicalTimePoint;
private final Serializable id;
private final List<Competitor> involvedBoats;
private final int passId;
private final RaceLogEventAuthor author;
public RaceLogEventImpl(TimePoint createdAt, TimePoint pTimePoint, Serializable pId,
List<Competitor> pInvolvedBoats, int pPassId) {
public RaceLogEventImpl(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable pId, List<Competitor> pInvolvedBoats, int pPassId) {
this.createdAt = createdAt;
this.logicalTimePoint = pTimePoint;
this.author = author;
this.logicalTimePoint = logicalTimePoint;
this.id = pId;
this.involvedBoats = pInvolvedBoats;
this.passId = pPassId;
@@ -31,8 +34,16 @@ public abstract class RaceLogEventImpl implements RaceLogEvent {
return createdAt;
}
/*
* Redirects to getCreatedAt()
*/
@Override
public TimePoint getTimePoint() {
return getCreatedAt();
}
@Override
public TimePoint getLogicalTimePoint() {
return logicalTimePoint;
}
@@ -50,5 +61,16 @@ public abstract class RaceLogEventImpl implements RaceLogEvent {
public int getPassId() {
return passId;
}
@Override
public RaceLogEventAuthor getAuthor() {
return author;
}
@Override
public String toString() {
return getClass().getName() + ": createdAt: " + getCreatedAt() + ", logicalTimePoint: " + getLogicalTimePoint()
+ ", id: " + getId() + ", involvedBoats: " + getInvolvedBoats() + ", passId: " + getPassId() +
", author: "+ getAuthor();
}
}
@@ -5,14 +5,14 @@ import java.util.List;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CourseBase;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.domain.common.racelog.StartProcedureType;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
import com.sap.sailing.domain.racelog.CompetitorResults;
import com.sap.sailing.domain.racelog.RaceLogCourseAreaChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogCourseDesignChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogEventRestoreFactory;
import com.sap.sailing.domain.racelog.RaceLogFinishPositioningConfirmedEvent;
import com.sap.sailing.domain.racelog.RaceLogFinishPositioningListChangedEvent;
@@ -30,81 +30,83 @@ import com.sap.sailing.domain.tracking.Wind;
public class RaceLogEventRestoreFactoryImpl extends RaceLogEventFactoryImpl implements RaceLogEventRestoreFactory {
@Override
public RaceLogFlagEvent createFlagEvent(TimePoint createdAt, TimePoint logicalTimePoint, Serializable id,
List<Competitor> involvedBoats, int passId, Flags upperFlag, Flags lowerFlag, boolean isDisplayed) {
return new RaceLogFlagEventImpl(createdAt, logicalTimePoint, id, involvedBoats, passId, upperFlag, lowerFlag, isDisplayed);
public RaceLogFlagEvent createFlagEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, List<Competitor> involvedBoats, int passId, Flags upperFlag, Flags lowerFlag, boolean isDisplayed) {
return new RaceLogFlagEventImpl(createdAt, author, logicalTimePoint, id, involvedBoats, passId, upperFlag, lowerFlag, isDisplayed);
}
@Override
public RaceLogStartTimeEvent createStartTimeEvent(TimePoint createdAt, TimePoint logicalTimePoint, Serializable id,
List<Competitor> involvedBoats, int passId, TimePoint startTime) {
return new RaceLogStartTimeEventImpl(createdAt, logicalTimePoint, id, involvedBoats, passId, startTime);
public RaceLogStartTimeEvent createStartTimeEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, List<Competitor> involvedBoats, int passId, TimePoint startTime) {
return new RaceLogStartTimeEventImpl(createdAt, author, logicalTimePoint, id, involvedBoats, passId, startTime);
}
@Override
public RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint createdAt, TimePoint logicalTimePoint,
Serializable id, List<Competitor> competitors, int passId, RaceLogRaceStatus nextStatus) {
return new RaceLogRaceStatusEventImpl(createdAt, logicalTimePoint, id, competitors, passId, nextStatus);
public RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint createdAt, RaceLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId, RaceLogRaceStatus nextStatus) {
return new RaceLogRaceStatusEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, nextStatus);
}
@Override
public RaceLogPassChangeEvent createPassChangeEvent(TimePoint createdAt, TimePoint logicalTimePoint,
Serializable id, List<Competitor> competitors, int passId) {
return new RaceLogPassChangeEventImpl(createdAt, logicalTimePoint, id, competitors, passId);
public RaceLogPassChangeEvent createPassChangeEvent(TimePoint createdAt, RaceLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId) {
return new RaceLogPassChangeEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId);
}
@Override
public RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint createdAt, TimePoint logicalTimePoint,
Serializable id, List<Competitor> competitors, int passId, Serializable courseAreaId) {
return new RaceLogCourseAreaChangeEventImpl(createdAt, logicalTimePoint, id, competitors, passId, courseAreaId);
public RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint createdAt, RaceLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId, Serializable courseAreaId) {
return new RaceLogCourseAreaChangeEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, courseAreaId);
}
@Override
public RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint createdAt,
TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId, CourseBase courseData) {
return new RaceLogCourseDesignChangedEventImpl(createdAt, logicalTimePoint, id, competitors, passId, courseData);
RaceLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId, CourseBase courseData) {
return new RaceLogCourseDesignChangedEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, courseData);
}
@Override
public RaceLogFinishPositioningListChangedEvent createFinishPositioningListChangedEvent(TimePoint createdAt,
TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId, List<Triple<Serializable, String, MaxPointsReason>> positionedCompetitors) {
return new RaceLogFinishPositioningListChangedEventImpl(createdAt, logicalTimePoint, id, competitors, passId, positionedCompetitors);
RaceLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId, CompetitorResults positionedCompetitors) {
return new RaceLogFinishPositioningListChangedEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, positionedCompetitors);
}
@Override
public RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint createdAt,
TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId, List<Triple<Serializable, String, MaxPointsReason>> positionedCompetitors) {
return new RaceLogFinishPositioningConfirmedEventImpl(createdAt, logicalTimePoint, id, competitors, passId, positionedCompetitors);
RaceLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId, CompetitorResults positionedCompetitors) {
return new RaceLogFinishPositioningConfirmedEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, positionedCompetitors);
}
@Override
public RaceLogPathfinderEvent createPathfinderEvent(TimePoint createdAt, TimePoint logicalTimePoint,
Serializable id, List<Competitor> competitors, int passId, String pathfinderId) {
return new RaceLogPathfinderEventImpl(createdAt, logicalTimePoint, id, competitors, passId, pathfinderId);
public RaceLogPathfinderEvent createPathfinderEvent(TimePoint createdAt, RaceLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId, String pathfinderId) {
return new RaceLogPathfinderEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, pathfinderId);
}
@Override
public RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint createdAt, TimePoint logicalTimePoint,
Serializable id, List<Competitor> competitors, int passId, Long gateLineOpeningTime) {
return new RaceLogGateLineOpeningTimeEventImpl(createdAt, logicalTimePoint, id, competitors, passId, gateLineOpeningTime);
public RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint createdAt, RaceLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId, Long gateLaunchStopTime,
Long golfDownTime) {
return new RaceLogGateLineOpeningTimeEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, gateLaunchStopTime,
golfDownTime);
}
@Override
public RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint createdAt, TimePoint timePoint,
Serializable id, List<Competitor> competitors, int passId, StartProcedureType type) {
return new RaceLogStartProcedureChangedEventImpl(createdAt, timePoint, id, competitors, passId, type);
public RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint createdAt, RaceLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId, RacingProcedureType type) {
return new RaceLogStartProcedureChangedEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, type);
}
@Override
public RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint createdAt, TimePoint timePoint,
Serializable id, List<Competitor> competitors, int passId, TimePoint protestStartTime) {
return new RaceLogProtestStartTimeEventImpl(createdAt, timePoint, id, competitors, passId, protestStartTime);
public RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint createdAt, RaceLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, List<Competitor> competitors, int passId, TimePoint protestStartTime) {
return new RaceLogProtestStartTimeEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, protestStartTime);
}
@Override
public RaceLogWindFixEvent createWindFixEvent(TimePoint createdAt, TimePoint timePoint, Serializable id,
List<Competitor> competitors, Integer passId, Wind wind) {
return new RaceLogWindFixEventImpl(createdAt, timePoint, id, competitors, passId, wind);
public RaceLogWindFixEvent createWindFixEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, List<Competitor> competitors, Integer passId, Wind wind) {
return new RaceLogWindFixEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, wind);
}
@@ -4,9 +4,9 @@ import java.io.Serializable;
import java.util.List;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.racelog.CompetitorResults;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogEventVisitor;
import com.sap.sailing.domain.racelog.RaceLogFinishPositioningConfirmedEvent;
@@ -15,8 +15,8 @@ public class RaceLogFinishPositioningConfirmedEventImpl extends RaceLogFinishPos
private static final long serialVersionUID = 5028181339200048499L;
public RaceLogFinishPositioningConfirmedEventImpl(TimePoint createdAt,
TimePoint pTimePoint, Serializable pId, List<Competitor> pCompetitors, int pPassId, List<Triple<Serializable, String, MaxPointsReason>> positionedCompetitors) {
super(createdAt, pTimePoint, pId, pCompetitors, pPassId, positionedCompetitors);
RaceLogEventAuthor author, TimePoint pTimePoint, Serializable pId, List<Competitor> pCompetitors, int pPassId, CompetitorResults positionedCompetitors) {
super(createdAt, author, pTimePoint, pId, pCompetitors, pPassId, positionedCompetitors);
}
@Override
@@ -4,25 +4,25 @@ import java.io.Serializable;
import java.util.List;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.racelog.CompetitorResults;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogFinishPositioningEvent;
public abstract class RaceLogFinishPositioningEventImpl extends RaceLogEventImpl implements RaceLogFinishPositioningEvent {
private static final long serialVersionUID = -8168584588697908309L;
protected List<Triple<Serializable, String, MaxPointsReason>> positionedCompetitors;
private final CompetitorResults positionedCompetitors;
public RaceLogFinishPositioningEventImpl(TimePoint createdAt, TimePoint pTimePoint, Serializable pId,
List<Competitor> pInvolvedBoats, int pPassId, List<Triple<Serializable, String, MaxPointsReason>> positionedCompetitors) {
super(createdAt, pTimePoint, pId, pInvolvedBoats, pPassId);
public RaceLogFinishPositioningEventImpl(TimePoint createdAt, RaceLogEventAuthor author, TimePoint pTimePoint,
Serializable pId, List<Competitor> pInvolvedBoats, int pPassId, CompetitorResults positionedCompetitors) {
super(createdAt, author, pTimePoint, pId, pInvolvedBoats, pPassId);
this.positionedCompetitors = positionedCompetitors;
}
@Override
public List<Triple<Serializable, String, MaxPointsReason>> getPositionedCompetitorsIDsNamesMaxPointsReasons() {
public CompetitorResults getPositionedCompetitorsIDsNamesMaxPointsReasons() {
return positionedCompetitors;
}
Loaded 100 of 784 files, more files were not shown because too many files have changed in this diff. Show more