diff --git a/configuration/buildAndUpdateProduct.sh b/configuration/buildAndUpdateProduct.sh index 2058454dc23..f5c35a32a88 100755 --- a/configuration/buildAndUpdateProduct.sh +++ b/configuration/buildAndUpdateProduct.sh @@ -61,16 +61,19 @@ HAS_OVERWRITTEN_TARGET=0 TARGET_SERVER_NAME=$active_branch gwtcompile=1 +onegwtpermutationonly=0 testing=1 clean="clean" offline=0 proxy=0 +no_confirmation=1 extra='' if [ $# -eq 0 ]; then - echo "buildAndUpdateProduct [-g -t -o -c -m -n -l ] [build|install|all|hot-deploy|remote-deploy]" + echo "buildAndUpdateProduct [-b -u -g -t -o -c -m -n -l ] [build|install|all|hot-deploy|remote-deploy]" 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 "-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)" @@ -81,10 +84,11 @@ if [ $# -eq 0 ]; then echo "-l Telnet port the OSGi server is running. Optional but enables fully automatic hot-deploy." echo "-s Name of server you want to use as target for install, hot-deploy or remote-reploy. This overrides default behaviour." echo "-w Target for remote-deploy. Must comply with the following format: user@server." + echo "-u Run without confirmation messages. Use with extreme care." echo "" echo "build: builds the server code using Maven to $PROJECT_HOME (log to $START_DIR/build.log)" echo "install: installs product and configuration to $SERVERS_HOME/$active_branch. Overwrites any configuration by using config from branch." - echo "all: calls build and then install" + echo "all: invokes build and then install" echo "" echo "hot-deploy: performs hot deployment of named bundle into OSGi server" echo "Example: $0 -n com.sap.sailing.www -l 14888 hot-deploy" @@ -104,12 +108,13 @@ echo PROJECT_HOME is $PROJECT_HOME echo SERVERS_HOME is $SERVERS_HOME echo BRANCH is $active_branch -options=':gtocpm:n:l:s:w:' +options=':bgtocpm:n:l:s:w:u' while getopts $options option do case $option in g) gwtcompile=0;; t) testing=0;; + b) onegwtpermutationonly=1;; o) offline=1;; c) clean="";; p) proxy=1;; @@ -119,6 +124,7 @@ do s) TARGET_SERVER_NAME=$OPTARG HAS_OVERWRITTEN_TARGET=1;; w) REMOTE_SERVER_LOGIN=$OPTARG;; + u) no_confirmation=1;; \?) echo "Invalid option" exit 4;; esac @@ -179,12 +185,14 @@ if [[ "$@" == "hot-deploy" ]]; then echo "WARNING: Bundle versions do not differ. Update not needed." fi - read -s -n1 -p "Do you really want to hot-deploy bundle $OSGI_BUNDLE_NAME to $SERVERS_HOME/$active_branch? (y/N): " answer - case $answer in - "Y" | "y") echo "Continuing";; - *) echo "Aborting..." - exit;; - esac + if [ $no_confirmation -eq 0 ]; then + read -s -n1 -p "Do you really want to hot-deploy bundle $OSGI_BUNDLE_NAME to $SERVERS_HOME/$active_branch? (y/N): " answer + case $answer in + "Y" | "y") echo "Continuing";; + *) echo "Aborting..." + exit;; + esac + fi # deploy new bundle physically mkdir -p $SERVERS_HOME/$active_branch/plugins/deploy @@ -223,12 +231,15 @@ if [[ "$@" == "hot-deploy" ]]; then BUNDLE_ID=`echo $OLD_BUNDLE_INFORMATION | cut -d " " -f 1` OLD_ACTIVATED_NAME=`echo $OLD_BUNDLE_INFORMATION | cut -d " " -f 3` echo "Could identify bundle-id $BUNDLE_ID for $OLD_ACTIVATED_NAME" - read -s -n1 -p "I will now stop and reinstall the bundle mentioned in the line above. Is this right? (y/N): " answer - case $answer in - "Y" | "y") echo "Continuing";; - *) echo "Aborting..." - exit;; - esac + + if [ $no_confirmation -eq 0 ]; then + read -s -n1 -p "I will now stop and reinstall the bundle mentioned in the line above. Is this right? (y/N): " answer + case $answer in + "Y" | "y") echo "Continuing";; + *) echo "Aborting..." + exit;; + esac + fi # stop and uninstall echo -n stop $BUNDLE_ID | $NC_CMD > /dev/null @@ -270,6 +281,24 @@ if [[ "$@" == "build" ]] || [[ "$@" == "all" ]]; then if [ $gwtcompile -eq 1 ]; then echo "INFO: Compiling GWT (rm -rf com.sap.sailing.gwt.ui/com.sap.sailing.*)" rm -rf com.sap.sailing.gwt.ui/com.sap.sailing.* + if [ $onegwtpermutationonly -eq 1 ]; then + echo "INFO: Patching .gwt.xml files such that only one GWT permutation needs to be compiled" + for i in com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/*.gwt.xml; do + echo "INFO: Patching $i files such that only one GWT permutation needs to be compiled" + cp $i $i.bak + cat $i | sed -e 's/^[ ]*/ /' >$i.sed + mv $i.sed $i + done + else + echo "INFO: Patching .gwt.xml files such that all GWT permutations are compiled" + for i in com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/*.gwt.xml; do + echo "INFO: Patching $i files such that all GWT permutations are compiled" + cp $i $i.bak + cat $i | sed -e 's/ //' >$i.sed + mv $i.sed $i + done + fi + else echo "INFO: GWT Compilation disabled" extra="-Pdebug.no-gwt-compile" @@ -298,17 +327,27 @@ if [[ "$@" == "build" ]] || [[ "$@" == "all" ]]; then echo "Using following command: mvn $extra -fae -s $MAVEN_SETTINGS $clean install" mvn $extra -fae -s $MAVEN_SETTINGS $clean install 2>&1 | tee $START_DIR/build.log + 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" + for i in com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/*.gwt.xml; do + mv -v $i.bak $i + done + fi + echo "Build complete. Do not forget to install product..." fi if [[ "$@" == "install" ]] || [[ "$@" == "all" ]]; then - read -s -n1 -p "Currently branch $active_branch is active and I will deploy to $ACDIR. Do you want to proceed with $@ (y/N): " answer - case $answer in - "Y" | "y") echo "Continuing";; - *) echo "Aborting..." - exit;; - esac + if [ $no_confirmation -eq 0 ]; then + read -s -n1 -p "Currently branch $active_branch is active and I will deploy to $ACDIR. Do you want to proceed with $@ (y/N): " answer + case $answer in + "Y" | "y") echo "Continuing";; + *) echo "Aborting..." + exit;; + esac + fi if [ ! -d $ACDIR ]; then echo "Could not find directory $ACDIR - perhaps you are on a wrong branch?" @@ -427,12 +466,14 @@ if [[ "$@" == "remote-deploy" ]]; then REMOTE_HOME=`ssh $REMOTE_SERVER_LOGIN 'echo $HOME/servers'` REMOTE_SERVER="$REMOTE_HOME/$SERVER" - read -s -n1 -p "I will deploy the current GIT branch to $REMOTE_SERVER_LOGIN:$REMOTE_SERVER. Is this correct (y/n)? " answer - case $answer in - "Y" | "y") OK=1;; - *) echo "Aborting... nothing has been changed on remote server!" - exit;; - esac + if [ $no_confirmation -eq 0 ]; then + read -s -n1 -p "I will deploy the current GIT branch to $REMOTE_SERVER_LOGIN:$REMOTE_SERVER. Is this correct (y/n)? " answer + case $answer in + "Y" | "y") OK=1;; + *) echo "Aborting... nothing has been changed on remote server!" + exit;; + esac + fi $SSH_CMD "test -d $REMOTE_SERVER/plugins" if [[ $? -eq 1 ]]; then @@ -474,18 +515,20 @@ if [[ "$@" == "remote-deploy" ]]; then echo "Deployed successfully. I did NOT change any configuration (no env.sh or config.ini or jetty.xml adaption), only code!" - read -s -n1 -p "Do you want me to restart the remote server (y/n)? " answer - case $answer in - "Y" | "y") OK=1;; - *) echo "Aborting... deployment should be ready by now!" - exit;; - esac + if [ $no_confirmation -eq 0 ]; then + read -s -n1 -p "Do you want me to restart the remote server (y/n)? " answer + case $answer in + "Y" | "y") OK=1;; + *) echo "Aborting... deployment should be ready by now!" + exit;; + esac - echo "" - $SSH_CMD "cd $REMOTE_SERVER && bash -l -c $REMOTE_SERVER/stop" - $SSH_CMD "cd $REMOTE_SERVER && bash -l -c $REMOTE_SERVER/start" + echo "" + $SSH_CMD "cd $REMOTE_SERVER && bash -l -c $REMOTE_SERVER/stop" + $SSH_CMD "cd $REMOTE_SERVER && bash -l -c $REMOTE_SERVER/start" - echo "Restarted remote server. Please check." + echo "Restarted remote server. Please check." + fi fi if [[ "$@" == "deploy-startpage" ]]; then diff --git a/doc/RaceCommittee Feature List.xlsx b/doc/RaceCommittee Feature List.xlsx new file mode 100644 index 00000000000..1a1a1fd521b Binary files /dev/null and b/doc/RaceCommittee Feature List.xlsx differ diff --git a/doc/Swiss Timing Race Committee App.docx b/doc/Swiss Timing Race Committee App.docx new file mode 100644 index 00000000000..4cb663e44a1 Binary files /dev/null and b/doc/Swiss Timing Race Committee App.docx differ diff --git a/doc/theses/20130913_Bross_Tracking_Sailing_Races_with_Mobile_Devices.pdf b/doc/theses/20130913_Bross_Tracking_Sailing_Races_with_Mobile_Devices.pdf new file mode 100755 index 00000000000..9895bf632d4 Binary files /dev/null and b/doc/theses/20130913_Bross_Tracking_Sailing_Races_with_Mobile_Devices.pdf differ diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index a4a06acaee3..1163b1637c0 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -82,7 +82,6 @@ import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; import com.sap.sailing.domain.leaderboard.impl.RegattaLeaderboardImpl; -import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard; import com.sap.sailing.domain.persistence.DomainObjectFactory; @@ -238,16 +237,15 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { result = leaderboardRegistry.getLeaderboardByName(leaderboardName); } if (result == null) { - SettableScoreCorrection scoreCorrection = new ScoreCorrectionImpl(); ThresholdBasedResultDiscardingRule resultDiscardingRule = loadResultDiscardingRule(dbLeaderboard, FieldNames.LEADERBOARD_DISCARDING_THRESHOLDS); String regattaName = (String) dbLeaderboard.get(FieldNames.REGATTA_NAME.name()); if (groupForMetaLeaderboard != null) { result = new LeaderboardGroupMetaLeaderboard(groupForMetaLeaderboard, loadScoringScheme(dbLeaderboard), resultDiscardingRule); groupForMetaLeaderboard.setOverallLeaderboard(result); } else if (regattaName == null) { - result = loadFlexibleLeaderboard(dbLeaderboard, scoreCorrection, resultDiscardingRule); + result = loadFlexibleLeaderboard(dbLeaderboard, resultDiscardingRule); } else { - result = loadRegattaLeaderboard(leaderboardName, regattaName, dbLeaderboard, scoreCorrection, resultDiscardingRule, regattaRegistry); + result = loadRegattaLeaderboard(leaderboardName, regattaName, dbLeaderboard, resultDiscardingRule, regattaRegistry); } if (result != null) { final Leaderboard finalResult = result; @@ -263,7 +261,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } } }); - needsMigration[0] = loadLeaderboardCorrections(dbLeaderboard, loadedLeaderboardCorrections, scoreCorrection) || needsMigration[0]; + needsMigration[0] = loadLeaderboardCorrections(dbLeaderboard, loadedLeaderboardCorrections, result.getScoreCorrection()) || needsMigration[0]; needsMigration[0] = loadSuppressedCompetitors(dbLeaderboard, loadedLeaderboardCorrections) || needsMigration[0]; loadColumnFactors(dbLeaderboard, result); // add the leaderboard to the registry @@ -338,20 +336,20 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { * @return null if the regatta cannot be resolved; otherwise the leaderboard for the regatta specified */ private RegattaLeaderboard loadRegattaLeaderboard(String leaderboardName, String regattaName, DBObject dbLeaderboard, - SettableScoreCorrection scoreCorrection, ThresholdBasedResultDiscardingRule resultDiscardingRule, RegattaRegistry regattaRegistry) { + ThresholdBasedResultDiscardingRule resultDiscardingRule, RegattaRegistry regattaRegistry) { RegattaLeaderboard result = null; Regatta regatta = regattaRegistry.getRegatta(new RegattaName(regattaName)); if (regatta == null) { logger.info("Couldn't find regatta "+regattaName+" for corresponding regatta leaderboard. Not loading regatta leaderboard."); } else { - result = new RegattaLeaderboardImpl(regatta, scoreCorrection, resultDiscardingRule); + result = new RegattaLeaderboardImpl(regatta, resultDiscardingRule); result.setName(leaderboardName); } return result; } private FlexibleLeaderboard loadFlexibleLeaderboard(DBObject dbLeaderboard, - SettableScoreCorrection scoreCorrection, ThresholdBasedResultDiscardingRule resultDiscardingRule) { + ThresholdBasedResultDiscardingRule resultDiscardingRule) { final FlexibleLeaderboardImpl result; BasicDBList dbRaceColumns = (BasicDBList) dbLeaderboard.get(FieldNames.LEADERBOARD_COLUMNS.name()); if (dbRaceColumns == null) { @@ -372,7 +370,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } result = new FlexibleLeaderboardImpl(raceLogStore, (String) dbLeaderboard.get(FieldNames.LEADERBOARD_NAME - .name()), scoreCorrection, resultDiscardingRule, scoringScheme, courseArea); + .name()), resultDiscardingRule, scoringScheme, courseArea); // For a FlexibleLeaderboard, fleets are owned by the leaderboard's RaceColumn objects. We need to manage // them here: Map fleetsByName = new HashMap(); @@ -1025,7 +1023,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { for (DBObject o : raceLog.find(query)) { RaceLogEvent raceLogEvent = loadRaceLogEvent((DBObject) o.get(FieldNames.RACE_LOG_EVENT.name())); if (raceLogEvent != null) { - result.add(raceLogEvent); + result.load(raceLogEvent); } } } diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index 540da2d9cee..09ba9c0748e 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -36,6 +36,7 @@ import com.sap.sailing.domain.common.Speed; 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.Triple; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard; @@ -280,14 +281,16 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { } private void storeScoreCorrections(Leaderboard leaderboard, BasicDBObject dbScoreCorrections) { + TimePoint now = MillisecondsTimePoint.now(); SettableScoreCorrection scoreCorrection = leaderboard.getScoreCorrection(); for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { BasicDBList dbCorrectionForRace = new BasicDBList(); for (Competitor competitor : leaderboard.getCompetitors()) { - if (scoreCorrection.isScoreCorrected(competitor, raceColumn)) { + // TODO bug 655: make score corrections time dependent + if (scoreCorrection.isScoreCorrected(competitor, raceColumn, now)) { BasicDBObject dbCorrectionForCompetitor = new BasicDBObject(); dbCorrectionForCompetitor.put(FieldNames.COMPETITOR_ID.name(), competitor.getId()); - MaxPointsReason maxPointsReason = scoreCorrection.getMaxPointsReason(competitor, raceColumn); + MaxPointsReason maxPointsReason = scoreCorrection.getMaxPointsReason(competitor, raceColumn, now); if (maxPointsReason != MaxPointsReason.NONE) { dbCorrectionForCompetitor.put(FieldNames.LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON.name(), maxPointsReason.name()); @@ -751,7 +754,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogFinishPositioningListChangedEvent.class.getSimpleName()); - result.put(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name(), storePositionedCompetitors(finishPositioningListChangedEvent.getPositionedCompetitors())); + result.put(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name(), storePositionedCompetitors(finishPositioningListChangedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons())); return result; } @@ -762,7 +765,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogFinishPositioningConfirmedEvent.class.getSimpleName()); - result.put(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name(), storePositionedCompetitors(finishPositioningConfirmedEvent.getPositionedCompetitors())); + result.put(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name(), storePositionedCompetitors(finishPositioningConfirmedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons())); return result; } diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/ConfirmedFinishPositioningListFinderTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/ConfirmedFinishPositioningListFinderTest.java index fbc3b5dbe9c..e77d1e645cd 100644 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/ConfirmedFinishPositioningListFinderTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/ConfirmedFinishPositioningListFinderTest.java @@ -29,9 +29,9 @@ public class ConfirmedFinishPositioningListFinderTest extends @Override protected List> setupTargetEventsForPassAwareTests(int passId) { RaceLogFinishPositioningConfirmedEvent event = createEvent(RaceLogFinishPositioningConfirmedEvent.class, 1, passId); - when(event.getPositionedCompetitors()).thenReturn(mock(List.class)); + when(event.getPositionedCompetitorsIDsNamesMaxPointsReasons()).thenReturn(mock(List.class)); raceLog.add(event); - return event.getPositionedCompetitors(); + return event.getPositionedCompetitorsIDsNamesMaxPointsReasons(); } @Test @@ -45,11 +45,11 @@ public class ConfirmedFinishPositioningListFinderTest extends public void testMostRecent() { RaceLogFinishPositioningConfirmedEvent event1 = createEvent(RaceLogFinishPositioningConfirmedEvent.class, 1); RaceLogFinishPositioningConfirmedEvent event2 = createEvent(RaceLogFinishPositioningConfirmedEvent.class, 2); - when(event2.getPositionedCompetitors()).thenReturn(mock(List.class)); + when(event2.getPositionedCompetitorsIDsNamesMaxPointsReasons()).thenReturn(mock(List.class)); raceLog.add(event1); raceLog.add(event2); - assertEquals(event2.getPositionedCompetitors(), analyzer.analyze()); + assertEquals(event2.getPositionedCompetitorsIDsNamesMaxPointsReasons(), analyzer.analyze()); } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLog.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLog.java index bef4dd32eda..379133b2f19 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLog.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLog.java @@ -66,4 +66,13 @@ public interface RaceLog extends Track, WithID { void addAllListeners(HashSet listeners); Iterable getAllListeners(); + + /** + * 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. + * + * @return true if the event was actually added which is the case if there was no equal event contained + * in this race log yet + */ + boolean load(RaceLogEvent event); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogFinishPositioningEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogFinishPositioningEvent.java index 5c92d3e9a9b..cfc2d0af9dd 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogFinishPositioningEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogFinishPositioningEvent.java @@ -8,5 +8,9 @@ import com.sap.sailing.domain.common.impl.Util.Triple; public abstract interface RaceLogFinishPositioningEvent extends RaceLogEvent { - List> getPositionedCompetitors(); + /** + * @return a triple holding the competitor ID, the competitor name and the {@link MaxPointReason} documenting the + * score for the competitor + */ + List> getPositionedCompetitorsIDsNamesMaxPointsReasons(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/AbortingFlagFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/AbortingFlagFinder.java index c3e606f939f..9c615632204 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/AbortingFlagFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/AbortingFlagFinder.java @@ -12,7 +12,7 @@ public class AbortingFlagFinder extends RaceLogAnalyzer { } @Override - protected RaceLogFlagEvent performAnalyzation() { + protected RaceLogFlagEvent performAnalysis() { if (raceLog.getCurrentPassId() <= RaceLog.DefaultPassId) { return null; } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/ConfirmedFinishPositioningListFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/ConfirmedFinishPositioningListFinder.java index 7784ec86be3..d11a7ca45e1 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/ConfirmedFinishPositioningListFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/ConfirmedFinishPositioningListFinder.java @@ -16,11 +16,11 @@ public class ConfirmedFinishPositioningListFinder extends RaceLogAnalyzer> performAnalyzation() { + protected List> performAnalysis() { for (RaceLogEvent event : getPassEventsDescending()) { if (event instanceof RaceLogFinishPositioningConfirmedEvent) { RaceLogFinishPositioningConfirmedEvent finishPositioningEvent = (RaceLogFinishPositioningConfirmedEvent) event; - return finishPositioningEvent.getPositionedCompetitors(); + return finishPositioningEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons(); } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishPositioningListFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishPositioningListFinder.java index 62d0d9c67cb..545e0607875 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishPositioningListFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishPositioningListFinder.java @@ -16,11 +16,11 @@ public class FinishPositioningListFinder extends RaceLogAnalyzer> performAnalyzation() { + protected List> performAnalysis() { for (RaceLogEvent event : getPassEventsDescending()) { if (event instanceof RaceLogFinishPositioningListChangedEvent) { RaceLogFinishPositioningListChangedEvent finishPositioningEvent = (RaceLogFinishPositioningListChangedEvent) event; - return finishPositioningEvent.getPositionedCompetitors(); + return finishPositioningEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons(); } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishedTimeFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishedTimeFinder.java index 0181fca9421..a75f215fb3f 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishedTimeFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishedTimeFinder.java @@ -13,7 +13,7 @@ public class FinishedTimeFinder extends RaceLogAnalyzer { } @Override - protected TimePoint performAnalyzation() { + protected TimePoint performAnalysis() { for (RaceLogEvent event : getPassEventsDescending()) { if (event instanceof RaceLogRaceStatusEvent) { RaceLogRaceStatusEvent statusEvent = (RaceLogRaceStatusEvent) event; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishingTimeFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishingTimeFinder.java index e535008b5e7..76f683bf0b4 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishingTimeFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishingTimeFinder.java @@ -13,7 +13,7 @@ public class FinishingTimeFinder extends RaceLogAnalyzer { } @Override - protected TimePoint performAnalyzation() { + protected TimePoint performAnalysis() { for (RaceLogEvent event : getPassEventsDescending()) { if (event instanceof RaceLogRaceStatusEvent) { RaceLogRaceStatusEvent statusEvent = (RaceLogRaceStatusEvent) event; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/GateLineOpeningTimeFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/GateLineOpeningTimeFinder.java index 864a3cf2cba..0b7399a2606 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/GateLineOpeningTimeFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/GateLineOpeningTimeFinder.java @@ -11,7 +11,7 @@ public class GateLineOpeningTimeFinder extends RaceLogAnalyzer { } @Override - protected Long performAnalyzation() { + protected Long performAnalysis() { for (RaceLogEvent event : getPassEvents()) { if (event instanceof RaceLogGateLineOpeningTimeEvent) { return ((RaceLogGateLineOpeningTimeEvent) event).getGateLineOpeningTime(); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/IndividualRecallFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/IndividualRecallFinder.java index a9d1a7fc1fd..61a5f97a31c 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/IndividualRecallFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/IndividualRecallFinder.java @@ -14,7 +14,7 @@ public abstract class IndividualRecallFinder extends RaceLogAnalyzer protected abstract boolean isRelevant(RaceLogFlagEvent flagEvent); @Override - protected TimePoint performAnalyzation() { + protected TimePoint performAnalysis() { for (RaceLogEvent event : getPassEvents()) { if (event instanceof RaceLogFlagEvent) { RaceLogFlagEvent flagEvent = (RaceLogFlagEvent) event; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastFlagsFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastFlagsFinder.java index 30748e187a1..475ab27f806 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastFlagsFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastFlagsFinder.java @@ -25,7 +25,7 @@ public class LastFlagsFinder extends RaceLogAnalyzer> { } @Override - protected List performAnalyzation() { + protected List performAnalysis() { Iterator iterator = getPassEventsDescending().iterator(); RaceLogFlagEvent flagEvent = getNextFlagEvent(iterator); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastPublishedCourseDesignFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastPublishedCourseDesignFinder.java index e67fbfa26ba..c700b59c17a 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastPublishedCourseDesignFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastPublishedCourseDesignFinder.java @@ -13,7 +13,7 @@ public class LastPublishedCourseDesignFinder extends RaceLogAnalyzer } @Override - protected CourseBase performAnalyzation() { + protected CourseBase performAnalysis() { for (RaceLogEvent event : getAllEventsDescending()) { if (event instanceof RaceLogCourseDesignChangedEvent) { RaceLogCourseDesignChangedEvent courseDesignEvent = (RaceLogCourseDesignChangedEvent) event; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastWindFixFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastWindFixFinder.java index 996c0c0effa..9cbf1c716bf 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastWindFixFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastWindFixFinder.java @@ -12,7 +12,7 @@ public class LastWindFixFinder extends RaceLogAnalyzer { } @Override - protected Wind performAnalyzation() { + protected Wind performAnalysis() { for (RaceLogEvent event : getAllEventsDescending()) { if (event instanceof RaceLogWindFixEvent) { RaceLogWindFixEvent windFixEvent = (RaceLogWindFixEvent) event; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/PathfinderFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/PathfinderFinder.java index d0849327c6c..a885ab5e5f0 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/PathfinderFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/PathfinderFinder.java @@ -11,7 +11,7 @@ public class PathfinderFinder extends RaceLogAnalyzer { } @Override - protected String performAnalyzation() { + protected String performAnalysis() { for (RaceLogEvent event : getPassEventsDescending()) { if (event instanceof RaceLogPathfinderEvent) { return ((RaceLogPathfinderEvent) event).getPathfinderId(); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/ProtestStartTimeFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/ProtestStartTimeFinder.java index 38a3aa48248..18fb9bb852c 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/ProtestStartTimeFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/ProtestStartTimeFinder.java @@ -12,7 +12,7 @@ public class ProtestStartTimeFinder extends RaceLogAnalyzer { } @Override - protected TimePoint performAnalyzation() { + protected TimePoint performAnalysis() { for (RaceLogEvent event : getPassEventsDescending()) { if (event instanceof RaceLogProtestStartTimeEvent) { return ((RaceLogProtestStartTimeEvent) event).getProtestStartTime(); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RRS26StartModeFlagFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RRS26StartModeFlagFinder.java index a018ee4f96a..2837c899871 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RRS26StartModeFlagFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RRS26StartModeFlagFinder.java @@ -30,7 +30,7 @@ public class RRS26StartModeFlagFinder extends RaceLogAnalyzer { } @Override - protected Flags performAnalyzation() { + protected Flags performAnalysis() { StartProcedureType type = procedureAnalyzer.analyze(); if (StartProcedureType.RRS26.equals(type)) { for (RaceLogEvent event : getPassEventsDescending()) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RaceLogAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RaceLogAnalyzer.java index aaf96731ae3..11ec94bebc8 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RaceLogAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RaceLogAnalyzer.java @@ -24,13 +24,13 @@ public abstract class RaceLogAnalyzer { public ResultType analyze() { raceLog.lockForRead(); try { - return performAnalyzation(); + return performAnalysis(); } finally { raceLog.unlockAfterRead(); } } - protected abstract ResultType performAnalyzation(); + protected abstract ResultType performAnalysis(); protected Iterable getPassEvents() { return raceLog.getFixes(); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RaceStatusAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RaceStatusAnalyzer.java index a351e5440c7..7ca600b5125 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RaceStatusAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RaceStatusAnalyzer.java @@ -12,7 +12,7 @@ public class RaceStatusAnalyzer extends RaceLogAnalyzer { } @Override - protected RaceLogRaceStatus performAnalyzation() { + protected RaceLogRaceStatus performAnalysis() { for (RaceLogEvent event : getPassEventsDescending()) { if (event instanceof RaceLogRaceStatusEvent) { RaceLogRaceStatusEvent statusEvent = (RaceLogRaceStatusEvent) event; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/StartProcedureTypeAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/StartProcedureTypeAnalyzer.java index 1ccee75cd93..8d6bfc7db5a 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/StartProcedureTypeAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/StartProcedureTypeAnalyzer.java @@ -12,7 +12,7 @@ public class StartProcedureTypeAnalyzer extends RaceLogAnalyzer { } @Override - protected TimePoint performAnalyzation() { + protected TimePoint performAnalysis() { for (RaceLogEvent event : getPassEventsDescending()) { if (event instanceof RaceLogStartTimeEvent) { return ((RaceLogStartTimeEvent) event).getStartTime(); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/WindFixesFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/WindFixesFinder.java index 218bfd2c42e..0c94fc329c6 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/WindFixesFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/WindFixesFinder.java @@ -15,7 +15,7 @@ public class WindFixesFinder extends RaceLogAnalyzer> { } @Override - protected List performAnalyzation() { + protected List performAnalysis() { final List windFixes = new ArrayList(); for (RaceLogEvent event : getAllEventsDescending()) { if (event instanceof RaceLogWindFixEvent) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFinishPositioningEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFinishPositioningEventImpl.java index cb7e21d9453..c80cef23f40 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFinishPositioningEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFinishPositioningEventImpl.java @@ -22,7 +22,7 @@ public abstract class RaceLogFinishPositioningEventImpl extends RaceLogEventImpl } @Override - public List> getPositionedCompetitors() { + public List> getPositionedCompetitorsIDsNamesMaxPointsReasons() { return positionedCompetitors; } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogImpl.java index 49dee9c8a51..9813741b651 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogImpl.java @@ -88,6 +88,24 @@ public class RaceLogImpl extends TrackImpl implements RaceLog { } return isAdded; } + + @Override + public boolean load(RaceLogEvent event) { + boolean isAdded = false; + lockForWrite(); + try { + isAdded = getInternalRawFixes().add(event); + } finally { + unlockAfterWrite(); + } + if (isAdded) { + logger.finer(String.format("%s (%s) was loaded into log.", event, event.getClass().getName())); + setCurrentPassId(Math.max(event.getPassId(), this.currentPassId)); + } else { + logger.warning(String.format("%s (%s) was not loaded into log. Ignoring", event, event.getClass().getName())); + } + return isAdded; + } protected void notifyListenersAboutReceive(RaceLogEvent event) { synchronized (listeners) { diff --git a/java/com.sap.sailing.domain.swisstimingadapter/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.swisstimingadapter/META-INF/MANIFEST.MF index 80cd6d3e589..d00c4a9387a 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.swisstimingadapter/META-INF/MANIFEST.MF @@ -10,4 +10,5 @@ Require-Bundle: com.sap.sailing.domain, com.sap.sailing.udpconnector, com.googlecode.java-diff-utils;bundle-version="1.3.0", com.sap.sailing.domain.common -Export-Package: com.sap.sailing.domain.swisstimingadapter +Export-Package: com.sap.sailing.domain.swisstimingadapter, + com.sap.sailing.domain.swisstimingadapter.impl;x-friends:="com.sap.sailing.server.test" diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardForKielWeekTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardForKielWeekTest.java index cd97487b2e7..9abe5d413eb 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardForKielWeekTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardForKielWeekTest.java @@ -23,7 +23,6 @@ import com.sap.sailing.domain.common.impl.WindSourceImpl; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.LowPoint; import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; -import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.tracking.impl.WindImpl; import com.sap.sailing.domain.tractracadapter.ReceiverType; @@ -38,8 +37,8 @@ public class LeaderboardForKielWeekTest extends OnlineTracTracBasedTest { @Test public void leaderboardWithOneRaceTest() throws URISyntaxException, NoWindException, IOException, InterruptedException { - leaderboard = new FlexibleLeaderboardImpl("Kiel Week 2011 505s", new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(new int[] { 3, 6 }), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl("Kiel Week 2011 505s", new ThresholdBasedResultDiscardingRuleImpl(new int[] { 3, 6 }), + new LowPoint(), null); Fleet defaultFleet = leaderboard.getFleet(null); MillisecondsTimePoint now = MillisecondsTimePoint.now(); loadRace("357c700a-9d9a-11e0-85be-406186cbf87c"); // 505 Race 2 diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java index 9081815008e..4df7ca3ee3b 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java @@ -40,7 +40,6 @@ import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.LowPoint; import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; -import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithFixedRank; import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithFixedRankAndManyCompetitors; import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; @@ -102,7 +101,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { @Test public void ensureMedalRaceParamIsIgnoredIfRaceColumnAlreadyExists() { - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ScoreCorrectionImpl(), new ThresholdBasedResultDiscardingRuleImpl( + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ThresholdBasedResultDiscardingRuleImpl( new int[] { 5, 8 }), new LowPoint(), null); Fleet defaultFleet = leaderboard.getFleet(null); final String columnName = "abc"; @@ -115,7 +114,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { @Test public void testRepeatedLeaderboardDTOCacheInvalidation() throws NoWindException, InterruptedException, ExecutionException { - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ScoreCorrectionImpl(), new ThresholdBasedResultDiscardingRuleImpl( + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ThresholdBasedResultDiscardingRuleImpl( new int[] { 5, 8 }), new LowPoint(), null); Fleet defaultFleet = leaderboard.getFleet(null); final String columnName = "abc"; @@ -174,8 +173,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { r.addCompetitor(c3); // this makes maxPoints==4 testRaces.add(r); // hash set should take care of more or less randomly permuting the races } - ScoreCorrectionImpl scoreCorrection = new ScoreCorrectionImpl(); - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", scoreCorrection, new ThresholdBasedResultDiscardingRuleImpl( + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ThresholdBasedResultDiscardingRuleImpl( new int[] { 1 }), new LowPoint(), null); Fleet defaultFleet = leaderboard.getFleet(null); int i=0; @@ -190,7 +188,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { bestScoringRaceColumn = raceColumn; } } - scoreCorrection.setMaxPointsReason(competitor, bestScoringRaceColumn, MaxPointsReason.DSQ); + leaderboard.getScoreCorrection().setMaxPointsReason(competitor, bestScoringRaceColumn, MaxPointsReason.DSQ); // assert that best scoring but now disqualified race gets max net points because of disqualification: assertEquals(Util.size(bestScoringRaceColumn.getTrackedRace(defaultFleet).getRace().getCompetitors())+1, leaderboard.getEntry(competitor, bestScoringRaceColumn, MillisecondsTimePoint.now()).getNetPoints(), 0.000000001); @@ -208,8 +206,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { competitor, /* rank */ 1, /* started */true); testRace.addCompetitor(c2); testRace.addCompetitor(c3); // this makes maxPoints==4 - ScoreCorrectionImpl scoreCorrection = new ScoreCorrectionImpl(); - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", scoreCorrection, new ThresholdBasedResultDiscardingRuleImpl( + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ThresholdBasedResultDiscardingRuleImpl( new int[] { 2 }), new LowPoint(), null); Fleet defaultFleet = leaderboard.getFleet(null); leaderboard.addRace(testRace, "R1", /* medalRace */ false, defaultFleet); @@ -237,14 +234,13 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { competitor, /* rank */ 1, /* started */true); testRace.addCompetitor(c2); testRace.addCompetitor(c3); // this makes maxPoints==4 - ScoreCorrectionImpl scoreCorrection = new ScoreCorrectionImpl(); - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", scoreCorrection, new ThresholdBasedResultDiscardingRuleImpl( + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ThresholdBasedResultDiscardingRuleImpl( new int[] { 2 }), new LowPoint(), null); Fleet defaultFleet = leaderboard.getFleet(null); RaceColumn r1 = leaderboard.addRace(testRace, "R1", /* medalRace */ false, defaultFleet); raceColumnsInLeaderboard.put(testRace, r1); RaceColumn r2 = leaderboard.addRaceColumn("R2", /* medalRace */ false, defaultFleet); - scoreCorrection.setMaxPointsReason(competitor, r2, MaxPointsReason.DND); // non-discardable disqualification + leaderboard.getScoreCorrection().setMaxPointsReason(competitor, r2, MaxPointsReason.DND); // non-discardable disqualification // assert that max points were given before discarding... assertEquals(4.0, leaderboard.getEntry(competitor, r2, MillisecondsTimePoint.now()).getNetPoints(), 0.000000001); // ...and after... @@ -265,8 +261,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { r.addCompetitor(c3); // this makes maxPoints==4 testRaces.add(r); // hash set should take care of more or less randomly permuting the races } - ScoreCorrectionImpl scoreCorrection = new ScoreCorrectionImpl(); - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", scoreCorrection, new ThresholdBasedResultDiscardingRuleImpl( + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ThresholdBasedResultDiscardingRuleImpl( new int[] { 1 }), new LowPoint(), null); Fleet defaultFleet = leaderboard.getFleet(null); int i=0; @@ -281,7 +276,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { bestScoringRaceColumn = raceColumn; } } - scoreCorrection.setMaxPointsReason(competitor, bestScoringRaceColumn, MaxPointsReason.DND); + leaderboard.getScoreCorrection().setMaxPointsReason(competitor, bestScoringRaceColumn, MaxPointsReason.DND); // assert that best scoring but now disqualified race gets max net points because of disqualification: assertEquals(Util.size(bestScoringRaceColumn.getTrackedRace(defaultFleet).getRace().getCompetitors())+1, leaderboard.getEntry(competitor, bestScoringRaceColumn, MillisecondsTimePoint.now()).getNetPoints(), 0.000000001); @@ -293,7 +288,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { protected void testLeaderboard(int numberOfStartedRaces, int numberOfNotStartedRaces, int firstDiscardingThreshold, int secondDiscardingThreshold, Integer carry, boolean addOneMedalRace, int numberOfUntrackedRaces) throws NoWindException { setupRaces(numberOfStartedRaces, numberOfNotStartedRaces); - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ScoreCorrectionImpl(), new ThresholdBasedResultDiscardingRuleImpl( + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ThresholdBasedResultDiscardingRuleImpl( new int[] { firstDiscardingThreshold, secondDiscardingThreshold }), new LowPoint(), null); Fleet defaultFleet = leaderboard.getFleet(null); int i=0; diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java index 7578c7a5f94..df2a4c7c104 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java @@ -44,9 +44,9 @@ import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.HighPoint; import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOverall; import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; +import com.sap.sailing.domain.leaderboard.impl.LowPoint; import com.sap.sailing.domain.leaderboard.impl.RegattaLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; -import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard; import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithStartTimeAndRanks; import com.sap.sailing.domain.tracking.MarkPassing; @@ -59,9 +59,8 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest { private ArrayList series; private Leaderboard createLeaderboard(Regatta regatta, int[] discardingThresholds) { - ScoreCorrectionImpl scoreCorrections = new ScoreCorrectionImpl(); ThresholdBasedResultDiscardingRuleImpl discardingRules = new ThresholdBasedResultDiscardingRuleImpl(discardingThresholds); - return new RegattaLeaderboardImpl(regatta, scoreCorrections, discardingRules); + return new RegattaLeaderboardImpl(regatta, discardingRules); } @Test @@ -800,24 +799,24 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest { Competitor[] f6 = new Competitor[] { c[3], c[0] }; TimePoint now = MillisecondsTimePoint.now(); TimePoint later = new MillisecondsTimePoint(now.asMillis()+1000); - FlexibleLeaderboard leaderboard1 = new FlexibleLeaderboardImpl("Leaderboard 1", new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(/* discarding thresholds */ new int[0]), new HighPoint(), null); + FlexibleLeaderboard leaderboard1 = new FlexibleLeaderboardImpl("Leaderboard 1", new ThresholdBasedResultDiscardingRuleImpl(/* discarding thresholds */ new int[0]), + new HighPoint(), null); leaderboard1.addRace(new MockedTrackedRaceWithStartTimeAndRanks(now, Arrays.asList(f1)), "R1", /* medalRace */ false, leaderboard1.getFleet(null)); leaderboard1.addRace(new MockedTrackedRaceWithStartTimeAndRanks(now, Arrays.asList(f2)), "R2", /* medalRace */ false, leaderboard1.getFleet(null)); assertTrue(leaderboard1.getScoringScheme().getScoreComparator(/* nullScoresAreBetter */ false).compare( leaderboard1.getTotalPoints(c[0], later), leaderboard1.getTotalPoints(c[3], later)) < 0); // c0 better than c3 - FlexibleLeaderboard leaderboard2 = new FlexibleLeaderboardImpl("Leaderboard 3", new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(/* discarding thresholds */ new int[0]), new HighPoint(), null); + FlexibleLeaderboard leaderboard2 = new FlexibleLeaderboardImpl("Leaderboard 3", new ThresholdBasedResultDiscardingRuleImpl(/* discarding thresholds */ new int[0]), + new HighPoint(), null); leaderboard2.addRace(new MockedTrackedRaceWithStartTimeAndRanks(now, Arrays.asList(f3)), "R1", /* medalRace */ false, leaderboard1.getFleet(null)); leaderboard2.addRace(new MockedTrackedRaceWithStartTimeAndRanks(now, Arrays.asList(f4)), "R2", /* medalRace */ false, leaderboard1.getFleet(null)); assertTrue(leaderboard2.getScoringScheme().getScoreComparator(/* nullScoresAreBetter */ false).compare( leaderboard2.getTotalPoints(c[3], later), leaderboard2.getTotalPoints(c[0], later)) < 0); // c3 better than c0 - FlexibleLeaderboard leaderboard3 = new FlexibleLeaderboardImpl("Leaderboard 3", new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(/* discarding thresholds */ new int[0]), new HighPoint(), null); + FlexibleLeaderboard leaderboard3 = new FlexibleLeaderboardImpl("Leaderboard 3", new ThresholdBasedResultDiscardingRuleImpl(/* discarding thresholds */ new int[0]), + new HighPoint(), null); leaderboard3.addRace(new MockedTrackedRaceWithStartTimeAndRanks(now, Arrays.asList(f5)), "R1", /* medalRace */ false, leaderboard1.getFleet(null)); leaderboard3.addRace(new MockedTrackedRaceWithStartTimeAndRanks(now, Arrays.asList(f6)), "R2", /* medalRace */ false, @@ -838,6 +837,100 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest { assertEquals(29 /* two wins, one second */, leaderboardGroup.getOverallLeaderboard().getTotalPoints(c[3], later), 0.000000001); } + @Test + public void testApplicationOfScoreCorrectionsInRacesWithNoTrackedRaceAfterLastTrackedRaceWithoutMarkPassings() throws NoWindException { + // Let c0 lead the series, c3 trail it, c1 and c2 are one-time competitors which are then suppressed in the + // overall leaderboard, expecting c3 to rank second overall, after c0 ranking first, with c1 and c2 not appearing + // in the overall leaderboard's sorted competitor list + Competitor[] c = createCompetitors(4).toArray(new Competitor[0]); + Competitor[] f1 = new Competitor[] { c[2], c[0], c[1], c[3] }; + final TimePoint endOfR1 = MillisecondsTimePoint.now(); + final TimePoint withinR1 = endOfR1.minus(1000); + final TimePoint startOfR1 = withinR1.minus(10000); + final TimePoint beforeStartOfR1 = startOfR1.minus(10000); + final TimePoint afterEndOfR1 = endOfR1.plus(1000); + FlexibleLeaderboard leaderboard1 = new FlexibleLeaderboardImpl("Leaderboard 1", new ThresholdBasedResultDiscardingRuleImpl(/* discarding thresholds */ new int[0]), + new LowPoint(), null); + leaderboard1.addRace(new MockedTrackedRaceWithStartTimeAndRanks(startOfR1, Arrays.asList(f1)) { + private static final long serialVersionUID = 8705622361027154428L; + public TimePoint getEndOfRace() { + return endOfR1; + } + }, "R1", /* medalRace */ false, + leaderboard1.getFleet(null)); + RaceColumn r2 = leaderboard1.addRaceColumn("R2", /* medalRace */ false, new Fleet[] { new FleetImpl("Default Fleet") }); + leaderboard1.getScoreCorrection().correctScore(c[0], r2, 123.); + assertEquals(2. + 123., leaderboard1.getTotalPoints(c[0], afterEndOfR1), 0.00000001); // correction expected to apply after end of last tracked race before the corrected column + assertEquals(2. + 0., leaderboard1.getTotalPoints(c[0], withinR1), 0.00000001); // correction expected NOT to apply before end of last tracked race before the corrected column + assertEquals(0., leaderboard1.getTotalPoints(c[0], beforeStartOfR1), 0.00000001); // not even the R1 scores apply before the start time of R1 + } + + @Test + public void testApplicationOfScoreCorrectionsInRacesWithNoTrackedRaceAfterLastTrackedRaceWithMarkPassings() throws NoWindException { + // Let c0 lead the series, c3 trail it, c1 and c2 are one-time competitors which are then suppressed in the + // overall leaderboard, expecting c3 to rank second overall, after c0 ranking first, with c1 and c2 not appearing + // in the overall leaderboard's sorted competitor list + Competitor[] c = createCompetitors(4).toArray(new Competitor[0]); + Competitor[] f1 = new Competitor[] { c[2], c[0], c[1], c[3] }; + final TimePoint endOfR1 = MillisecondsTimePoint.now(); + final TimePoint withinR1 = endOfR1.minus(1000); + final TimePoint startOfR1 = withinR1.minus(10000); + final TimePoint beforeStartOfR1 = startOfR1.minus(10000); + final TimePoint afterEndOfR1 = endOfR1.plus(1000); + final Waypoint start = new WaypointImpl(new GateImpl(new MarkImpl("Start Pin End"), new MarkImpl("Start Committee Boat"), "Start")); + final Waypoint finish = new WaypointImpl(new GateImpl(new MarkImpl("Finish Pin End"), new MarkImpl("Finish Committee Boat"), "Finish")); + FlexibleLeaderboard leaderboard1 = new FlexibleLeaderboardImpl("Leaderboard 1", new ThresholdBasedResultDiscardingRuleImpl(/* discarding thresholds */ new int[0]), + new LowPoint(), null); + final MockedTrackedRaceWithStartTimeAndRanks trackedRace = new MockedTrackedRaceWithStartTimeAndRanks(startOfR1, Arrays.asList(f1)) { + private static final long serialVersionUID = 8705622361027154428L; + @Override + public TimePoint getEndOfRace() { + return endOfR1; + } + @Override + public NavigableSet getMarkPassings(Competitor competitor) { + ArrayListNavigableSet result = new ArrayListNavigableSet(new TimedComparator()); + result.add(new MarkPassingImpl(startOfR1, start, competitor)); + result.add(new MarkPassingImpl(endOfR1, finish, competitor)); + return result; + } + }; + trackedRace.getRace().getCourse().addWaypoint(0, start); + trackedRace.getRace().getCourse().addWaypoint(1, finish); + RaceColumn r1 = leaderboard1.addRace(trackedRace, "R1", /* medalRace */ false, leaderboard1.getFleet(null)); + RaceColumn r2 = leaderboard1.addRaceColumn("R2", /* medalRace */ false, new Fleet[] { new FleetImpl("Default Fleet") }); + leaderboard1.getScoreCorrection().correctScore(c[0], r2, 123.); + assertEquals(2. + 123., leaderboard1.getTotalPoints(c[0], afterEndOfR1), 0.00000001); // correction expected to apply after end of last tracked race before the corrected column + assertEquals(2. + 0., leaderboard1.getTotalPoints(c[0], withinR1), 0.00000001); // correction expected NOT to apply before end of last tracked race before the corrected column + assertEquals(0., leaderboard1.getTotalPoints(c[0], beforeStartOfR1), 0.00000001); // not even the R1 scores apply before the start time of R1 + + leaderboard1.getScoreCorrection().setMaxPointsReason(c[1], r2, MaxPointsReason.DNS); + assertEquals(3. + 5., leaderboard1.getTotalPoints(c[1], afterEndOfR1), 0.00000001); // DNS is applied at race start (not known), so at least after the end of R1 + assertEquals(3. + 0., leaderboard1.getTotalPoints(c[1], withinR1), 0.00000001); // correction expected NOT to apply before end of last tracked race before the corrected column + assertEquals(0., leaderboard1.getTotalPoints(c[1], beforeStartOfR1), 0.00000001); // not even the R1 scores apply before the start time of R1 + + leaderboard1.getScoreCorrection().setMaxPointsReason(c[2], r2, MaxPointsReason.DNF); + assertEquals(1. + 5., leaderboard1.getTotalPoints(c[2], afterEndOfR1), 0.00000001); // DNF is applied after R2 finish (not known), so at least after the end of R1 + assertEquals(1. + 0., leaderboard1.getTotalPoints(c[2], withinR1), 0.00000001); // correction expected NOT to apply before end of last tracked race before the corrected column + assertEquals(0., leaderboard1.getTotalPoints(c[2], beforeStartOfR1), 0.00000001); // not even the R1 scores apply before the start time of R1 + + leaderboard1.getScoreCorrection().setMaxPointsReason(c[3], r1, MaxPointsReason.DNF); + assertEquals(0., leaderboard1.getTotalPoints(c[3], beforeStartOfR1), 0.00000001); // DNF does not apply before the start + assertEquals(4., leaderboard1.getTotalPoints(c[3], withinR1), 0.00000001); // correction expected NOT to apply before end of race + assertEquals(5., leaderboard1.getTotalPoints(c[3], afterEndOfR1), 0.00000001); // after race is finished, DNF applies + + leaderboard1.getScoreCorrection().setMaxPointsReason(c[3], r1, MaxPointsReason.DNS); + assertEquals(0., leaderboard1.getTotalPoints(c[3], beforeStartOfR1), 0.00000001); // DNS does not apply before the start + assertEquals(5., leaderboard1.getTotalPoints(c[3], withinR1), 0.00000001); // correction expected to apply after the start + assertEquals(5., leaderboard1.getTotalPoints(c[3], afterEndOfR1), 0.00000001); // not even the R1 scores apply before the start time of R1 + + leaderboard1.getScoreCorrection().setMaxPointsReason(c[3], r1, null); + leaderboard1.getScoreCorrection().correctScore(c[3], r1, 123.); + assertEquals(4., leaderboard1.getTotalPoints(c[3], withinR1), 0.00000001); // correction expected NOT to apply before end of last tracked race before the corrected column + assertEquals(123., leaderboard1.getTotalPoints(c[3], afterEndOfR1), 0.00000001); // correction is applied after R1 finish + assertEquals(0., leaderboard1.getTotalPoints(c[3], beforeStartOfR1), 0.00000001); // not even the R1 scores apply before the start time of R1 + } + private TimePoint createAndAttachTrackedRaces(Series theSeries, String fleetName, Competitor[]... competitorLists) { TimePoint now = MillisecondsTimePoint.now(); TimePoint later = new MillisecondsTimePoint(now.asMillis()+1000); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceLogAttachOnTrackedRaceTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceLogAttachOnTrackedRaceTest.java index 80eb691ef57..78e7d9383fa 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceLogAttachOnTrackedRaceTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceLogAttachOnTrackedRaceTest.java @@ -16,7 +16,6 @@ import com.sap.sailing.domain.common.impl.Util; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.LowPoint; -import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.test.mock.MockedTrackedRace; import com.sap.sailing.domain.tracking.TrackedRace; @@ -48,8 +47,7 @@ public class RaceLogAttachOnTrackedRaceTest { @Before public void setUp() { - ScoreCorrectionImpl scoreCorrection = new ScoreCorrectionImpl(); - leaderboard = new FlexibleLeaderboardImpl("", scoreCorrection, null, new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl("", null, new LowPoint(), null); } @Test diff --git a/java/com.sap.sailing.domain.tractracadapter/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.tractracadapter/META-INF/MANIFEST.MF index 55a083f5ccb..5457b5a986b 100755 --- a/java/com.sap.sailing.domain.tractracadapter/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.tractracadapter/META-INF/MANIFEST.MF @@ -11,7 +11,7 @@ Require-Bundle: com.sap.sailing.domain, com.sap.sailing.domain.common, com.sap.sailing.server.gateway.serialization;bundle-version="1.0.0" Export-Package: com.sap.sailing.domain.tractracadapter, - com.sap.sailing.domain.tractracadapter.impl;x-friends:="com.sap.sailing.domain.test,com.sap.sailing.domain.swisstimingadapter.test" + com.sap.sailing.domain.tractracadapter.impl;x-friends:="com.sap.sailing.domain.test,com.sap.sailing.domain.swisstimingadapter.test,com.sap.sailing.server.test" Bundle-ActivationPolicy: lazy Import-Package: org.json.simple, org.json.simple.parser diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java index feb63fd7a2f..b5ce0b7c4a0 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java @@ -526,6 +526,8 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements } else { logger.info("Joined TracTrac IO thread for race(s) "+getRaces()); } + lastStatus = new TrackedRaceStatusImpl(TrackedRaceStatusEnum.FINISHED, /* will be ignored */ 1.0); + updateStatusOfTrackedRaces(); } protected DataController getController() { @@ -551,6 +553,11 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements // we have seen many more fixes been transmitted after having received stopped() } + /** + * Propagates {@link #lastStatus} to all tracked races to which this tracker writes. + * + * @see #updateStatusOfTrackedRace(DynamicTrackedRace) + */ private void updateStatusOfTrackedRaces() { for (RaceDefinition race : getRaces()) { DynamicTrackedRace trackedRace = getTrackedRegatta().getExistingTrackedRace(race); @@ -560,10 +567,24 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements } } + /** + * Propagates {@link #lastStatus} to trackedRace's {@link TrackedRace#getStatus() status}. If + * {@link #lastStatus} is a {@link TrackedRaceStatusEnum#FINISHED FINISHED} status, the progress value is taken from + * the tracked race's current status instead of overwriting it with the progress indicated by + * {@link #lastStatus}. + */ private void updateStatusOfTrackedRace(DynamicTrackedRace trackedRace) { // can't update a race status once it has been set to FINISHED if (lastStatus != null && trackedRace.getStatus() != null && trackedRace.getStatus().getStatus() != TrackedRaceStatusEnum.FINISHED) { - trackedRace.setStatus(lastStatus); + final TrackedRaceStatus status; + if (lastStatus.getStatus() == TrackedRaceStatusEnum.FINISHED) { + // in this case use the tracked race's progress value: + status = new TrackedRaceStatusImpl(lastStatus.getStatus(), trackedRace.getStatus() == null ? 0.0 + : trackedRace.getStatus().getLoadingProgress()); + } else { + status = lastStatus; + } + trackedRace.setStatus(status); } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/ScoreCorrection.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/ScoreCorrection.java index f8e9926b2fc..38c8ef1d754 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/ScoreCorrection.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/ScoreCorrection.java @@ -20,6 +20,12 @@ import com.sap.sailing.domain.tracking.TrackedRace; * */ public interface ScoreCorrection extends Serializable { + /** + * A score correction as valid at the time point specified with the query that produced this object. + * + * @author Axel Uhl (d043530) + * + */ public interface Result { /** * @return null in case there is no score attributed to the competitor for the race column in @@ -31,6 +37,11 @@ public interface ScoreCorrection extends Serializable { MaxPointsReason getMaxPointsReason(); boolean isCorrected(); + + /** + * @return the time point for which this result is valid + */ + TimePoint getTimePoint(); } /** @@ -39,26 +50,51 @@ public interface ScoreCorrection extends Serializable { * and {@link MaxPointsReason#NONE} will be listed as the {@link Result#getMaxPointsReason() correction reason}. * Note, though, that {@link MaxPointsReason#NONE} can also be the reason for an explicit score correction, e.g., if * the tracking results were overruled by the jury. Clients may use - * {@link #isScoreCorrected(Competitor, TrackedRace)} to detect the difference. + * {@link #isScoreCorrected(Competitor, TrackedRace, TimePoint)} to detect the difference. + * + * @param trackedRankProvider + * can provide the tracked rank if needed; will only be called if there is no score correction for the + * timePoint specified. + * @param timePoint + * the time point for which to get the corrected score; score corrections have a validity time interval. + * Only the last score correction valid at timePoint is considered. * * @param numberOfCompetitorsFetcher * can determine the number of competitors to use as the basis for penalty score calculation * ("max points") if needed */ - Result getCorrectedScore(Callable trackedRank, Competitor competitor, RaceColumn raceColumn, + Result getCorrectedScore(Callable trackedRankProvider, Competitor competitor, RaceColumn raceColumn, TimePoint timePoint, NumberOfCompetitorsInLeaderboardFetcher numberOfCompetitorsFetcher, ScoringScheme scoringScheme); + /** + * @param timePoint + * the time point at which the max points reason is to be valid + * + * @return a non-null result + */ + MaxPointsReason getMaxPointsReason(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint); + /** * Note the difference between what this method does and a more naive comparison of uncorrected and corrected score. * Should, for some reason, the uncorrected score change later, an existing score correction would still remain in * place whereas if no score correction exists for the competitor/race combination, the resulting score after - * "correction" will still be the uncorrected value.

+ * "correction" will still be the uncorrected value. + *

+ * + * @param timePoint + * the time point for which to check whether the competitor's score was corrected at that time point; in + * other words, this method checks if there is a score correction for competitor in column + * raceColumn that is valid at timePoint. * * @return if an explicit score correction was made for the combination of competitor and * raceColumn */ - boolean isScoreCorrected(Competitor competitor, RaceColumn raceColumn); + boolean isScoreCorrected(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint); + /** + * Checks if this score correction object has any score corrections for any competitor valid at any time point for + * the race column specified by raceInLeaderboard. + */ boolean hasCorrectionFor(RaceColumn raceInLeaderboard); /** diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/SettableScoreCorrection.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/SettableScoreCorrection.java index 736250540fe..732bf75467d 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/SettableScoreCorrection.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/SettableScoreCorrection.java @@ -13,17 +13,12 @@ public interface SettableScoreCorrection extends ScoreCorrection { /** * @param reason * if null, any existing max-points reason is removed; while - * {@link #getMaxPointsReason(Competitor, RaceColumn)} will return {@link MaxPointsReason#NONE}, a - * call to {@link #isScoreCorrected(Competitor, RaceColumn)} will return false if no + * {@link #getMaxPointsReason(Competitor, RaceColumn, TimePoint)} will return {@link MaxPointsReason#NONE}, a + * call to {@link #isScoreCorrected(Competitor, RaceColumn, TimePoint)} will return false if no * other explicit score correction was made for the competitor. */ void setMaxPointsReason(Competitor competitor, RaceColumn raceColumn, MaxPointsReason reason); - /** - * @return a non-null result - */ - MaxPointsReason getMaxPointsReason(Competitor competitor, RaceColumn raceColumn); - void correctScore(Competitor competitor, RaceColumn raceColumn, double points); /** diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java index 224a9e21d1c..59114f0d9a6 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java @@ -14,7 +14,6 @@ import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.NoWindException; import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.leaderboard.ScoreCorrection; -import com.sap.sailing.domain.leaderboard.SettableScoreCorrection; import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; import com.sap.sailing.domain.tracking.TrackedRace; @@ -38,14 +37,11 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI private transient Iterable allCompetitorsCache; /** - * @param scoreCorrection must not be null * @param scoreComparator the comparator to use to compare basic scores, such as net points * @param name must not be null */ - public AbstractLeaderboardImpl(SettableScoreCorrection scoreCorrection, - ThresholdBasedResultDiscardingRule resultDiscardingRule) { - super(scoreCorrection, resultDiscardingRule); - assert scoreCorrection != null; + public AbstractLeaderboardImpl(ThresholdBasedResultDiscardingRule resultDiscardingRule) { + super(resultDiscardingRule); } @Override @@ -133,7 +129,7 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI Iterator ci = competitorsFromBestToWorst.iterator(); while (betterCompetitorRank < rank && ci.hasNext()) { Competitor betterTrackedCompetitor = ci.next(); - MaxPointsReason maxPointsReasonForBetterCompetitor = getScoreCorrection().getMaxPointsReason(betterTrackedCompetitor, raceColumn); + MaxPointsReason maxPointsReasonForBetterCompetitor = getScoreCorrection().getMaxPointsReason(betterTrackedCompetitor, raceColumn, timePoint); if (maxPointsReasonForBetterCompetitor != null && maxPointsReasonForBetterCompetitor != MaxPointsReason.NONE && maxPointsReasonForBetterCompetitor.isAdvanceCompetitorsTrackedWorse()) { correctedRank--; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java index dcc1ccbd896..24e7c7b2108 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java @@ -342,9 +342,9 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race } } - public AbstractSimpleLeaderboardImpl(SettableScoreCorrection scoreCorrection, ThresholdBasedResultDiscardingRule resultDiscardingRule) { + public AbstractSimpleLeaderboardImpl(ThresholdBasedResultDiscardingRule resultDiscardingRule) { this.carriedPoints = new HashMap(); - this.scoreCorrection = scoreCorrection; + this.scoreCorrection = createScoreCorrection(); this.displayNames = new HashMap(); this.crossLeaderboardResultDiscardingRule = resultDiscardingRule; this.suppressedCompetitors = new HashSet(); @@ -354,6 +354,15 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race initTransientFields(); } + /** + * Produces the score correction object to use in this leaderboard. Used by the constructor. Subclasses may override + * this method to create a more specific type of score correction. This implementation produces an object of type + * {@link ScoreCorrectionImpl}. + */ + protected SettableScoreCorrection createScoreCorrection() { + return new ScoreCorrectionImpl(this); + } + private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { ois.defaultReadObject(); initTransientFields(); @@ -459,7 +468,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race @Override public MaxPointsReason getMaxPointsReason(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint) { - return getScoreCorrection().getMaxPointsReason(competitor, raceColumn); + return getScoreCorrection().getMaxPointsReason(competitor, raceColumn, timePoint); } @Override @@ -615,7 +624,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race public boolean countRaceForComparisonWithDiscardingThresholds(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint) { TrackedRace trackedRaceForCompetitorInColumn; return getScoringScheme().isValidInTotalScore(this, raceColumn, timePoint) && - (getScoreCorrection().isScoreCorrected(competitor, raceColumn) || + (getScoreCorrection().isScoreCorrected(competitor, raceColumn, timePoint) || ((trackedRaceForCompetitorInColumn=raceColumn.getTrackedRace(competitor)) != null && trackedRaceForCompetitorInColumn.hasStarted(timePoint))); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java index c78ae8d18bc..609fb016488 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java @@ -18,7 +18,6 @@ import com.sap.sailing.domain.common.LeaderboardNameConstants; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.FlexibleRaceColumn; import com.sap.sailing.domain.leaderboard.ScoringScheme; -import com.sap.sailing.domain.leaderboard.SettableScoreCorrection; import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; import com.sap.sailing.domain.racelog.RaceLogStore; import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore; @@ -47,14 +46,14 @@ public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements private transient RaceLogStore raceLogStore; private CourseArea courseArea; - public FlexibleLeaderboardImpl(String name, SettableScoreCorrection scoreCorrection, - ThresholdBasedResultDiscardingRule resultDiscardingRule, ScoringScheme scoringScheme, CourseArea courseArea) { - this(EmptyRaceLogStore.INSTANCE, name, scoreCorrection, resultDiscardingRule, scoringScheme, courseArea); + public FlexibleLeaderboardImpl(String name, ThresholdBasedResultDiscardingRule resultDiscardingRule, + ScoringScheme scoringScheme, CourseArea courseArea) { + this(EmptyRaceLogStore.INSTANCE, name, resultDiscardingRule, scoringScheme, courseArea); } - public FlexibleLeaderboardImpl(RaceLogStore raceLogStore, String name, SettableScoreCorrection scoreCorrection, - ThresholdBasedResultDiscardingRule resultDiscardingRule, ScoringScheme scoringScheme, CourseArea courseArea) { - super(scoreCorrection, resultDiscardingRule); + public FlexibleLeaderboardImpl(RaceLogStore raceLogStore, String name, ThresholdBasedResultDiscardingRule resultDiscardingRule, + ScoringScheme scoringScheme, CourseArea courseArea) { + super(resultDiscardingRule); this.scoringScheme = scoringScheme; if (name == null) { throw new IllegalArgumentException("A leaderboard's name must not be null"); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java index 02439785dd1..8d224a533d6 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java @@ -14,7 +14,6 @@ import com.sap.sailing.domain.base.impl.RaceColumnInSeriesImpl; import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; import com.sap.sailing.domain.leaderboard.ScoringScheme; -import com.sap.sailing.domain.leaderboard.SettableScoreCorrection; import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; import com.sap.sailing.domain.tracking.TrackedRace; @@ -31,9 +30,8 @@ public class RegattaLeaderboardImpl extends AbstractLeaderboardImpl implements R private static final long serialVersionUID = 2370461218294770084L; private final Regatta regatta; - public RegattaLeaderboardImpl(Regatta regatta, SettableScoreCorrection scoreCorrection, - ThresholdBasedResultDiscardingRule resultDiscardingRule) { - super(scoreCorrection, resultDiscardingRule); + public RegattaLeaderboardImpl(Regatta regatta, ThresholdBasedResultDiscardingRule resultDiscardingRule) { + super(resultDiscardingRule); this.regatta = regatta; regatta.addRaceColumnListener(this); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/ScoreCorrectionImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/ScoreCorrectionImpl.java index 2b434fac0b1..5d8aadb4a91 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/ScoreCorrectionImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/ScoreCorrectionImpl.java @@ -5,6 +5,7 @@ import java.io.ObjectInputStream; import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.NavigableSet; import java.util.Set; import java.util.concurrent.Callable; @@ -14,10 +15,12 @@ import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.impl.Util; import com.sap.sailing.domain.common.impl.Util.Pair; +import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.NumberOfCompetitorsInLeaderboardFetcher; import com.sap.sailing.domain.leaderboard.ScoreCorrectionListener; import com.sap.sailing.domain.leaderboard.ScoringScheme; import com.sap.sailing.domain.leaderboard.SettableScoreCorrection; +import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.TrackedRace; /** @@ -57,8 +60,11 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection { private TimePoint timePointOfLastCorrectionsValidity; private transient Set scoreCorrectionListeners; + + private final Leaderboard leaderboard; - public ScoreCorrectionImpl() { + public ScoreCorrectionImpl(Leaderboard leaderboard) { + this.leaderboard = leaderboard; this.maxPointsReasons = new HashMap, MaxPointsReason>(); this.correctedScores = new HashMap, Double>(); this.scoreCorrectionListeners = new HashSet(); @@ -135,9 +141,10 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection { } @Override - public boolean isScoreCorrected(Competitor competitor, RaceColumn raceColumn) { + public boolean isScoreCorrected(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint) { Pair key = raceColumn.getKey(competitor); - return correctedScores.containsKey(key) || maxPointsReasons.containsKey(key); + return (correctedScores.containsKey(key) && !isCertainlyBeforeRaceFinish(timePoint, raceColumn, competitor)) + || (maxPointsReasons.containsKey(key) && isMaxPointsReasonApplicable(maxPointsReasons.get(key), timePoint, raceColumn, competitor)); } @Override @@ -145,31 +152,199 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection { Double oldScore = correctedScores.remove(raceColumn.getKey(competitor)); notifyListeners(competitor, raceColumn, oldScore, null); } + + /** + * Based on the order of the {@link Leaderboard#getRaceColumns() race columns} in the {@link #getLeaderboard() + * leaderboard to which this score correction object belongs}, tries to determine whether the timePoint + * is before the start of competitor's race in the race column specified by raceColumn. If + * there is a {@link RaceColumn#getTrackedRace(Competitor) tracked race for the competitor associated with the race + * column}, that race's start time is used for the calculation. Otherwise, if there is a tracked race column prior + * to raceColumn in the leaderboard in which competitor competes, and the competitor + * hasn't finished that race at timePoint, we also know that this must be before the start of + * competitor's race in raceColumn because we assume that the same competitor can only + * compete in one race at a time within a single leaderboard. + *

+ * + * In all other cases, false is returned which can either mean that timePoint is certainly + * known to be after the race start of competitor in the race for raceColumn, or we just + * can't tell, e.g., because competitor's race for raceColumn is not tracked, and + * timePoint is after all prior race column's finishing time for competitor. + *

+ * + * This method can be used to decide whether to apply a {@link MaxPointsReason#DNC}, {@link MaxPointsReason#DNS} or + * {@link MaxPointsReason#OCS} correction for competitor at timePoint in the race for + * raceColumn, because the correction can be applied at race start but should not be applied any + * earlier than that because it would incorrectly influence the total scores displayed for the competitor during + * earlier races. + */ + private boolean isCertainlyBeforeRaceStart(TimePoint timePoint, RaceColumn raceColumn, Competitor competitor) { + final boolean result; + TrackedRace trackedRace = raceColumn.getTrackedRace(competitor); + final TimePoint startOfRace; + if (trackedRace != null && (startOfRace = trackedRace.getStartOfRace()) != null) { + result = timePoint.before(startOfRace); + } else { + boolean preResult = false; + for (RaceColumn rc : getLeaderboard().getRaceColumns()) { + if (rc == raceColumn) { + break; + } + TrackedRace rcTrackedRace = rc.getTrackedRace(competitor); + if (rcTrackedRace != null) { + NavigableSet markPassings = rcTrackedRace.getMarkPassings(competitor); + if (markPassings != null && !markPassings.isEmpty()) { + MarkPassing lastMarkPassing = markPassings.last(); + if (timePoint.before(lastMarkPassing.getTimePoint())) { + preResult = true; + break; + } + } else { + // if available, use the end of the race as indicator for how long competitor may have been in the race + TimePoint endOfRace = rcTrackedRace.getEndOfRace(); + if (endOfRace != null && timePoint.before(endOfRace)) { + preResult = true; + break; + } + } + } + } + result = preResult; + } + return result; + } + + /** + * Based on the order of the {@link Leaderboard#getRaceColumns() race columns} in the {@link #getLeaderboard() + * leaderboard to which this score correction object belongs}, tries to determine whether the timePoint + * is before the finish or abandoning of competitor's race in the race column specified by + * raceColumn. If there is a {@link RaceColumn#getTrackedRace(Competitor) tracked race for the + * competitor associated with the race column}, that race's finish time for competitor (if defined) or + * the {@link TrackedRace#getEndOfRace() end of the race} is used for the calculation. Otherwise, if there is a + * tracked race column prior to raceColumn in the leaderboard in which competitor + * competes, and the competitor has finished that race after timePoint, we also know that this must be + * before the end of competitor's race in raceColumn because we assume that the same + * competitor can only compete in one race at a time within a single leaderboard. + *

+ * + * In all other cases, false is returned which can either mean that timePoint is certainly + * known to be after the race finish of competitor in the race for raceColumn, or we just + * can't tell, e.g., because competitor's race for raceColumn is not tracked, and + * timePoint is after all prior race column's finishing time for competitor. + *

+ * + * This method can be used to decide whether to apply a score correction for competitor at + * timePoint in the race for raceColumn, because the correction should not be applied + * before race end because it would incorrectly influence the total scores displayed for the competitor during + * earlier races. + */ + private boolean isCertainlyBeforeRaceFinish(TimePoint timePoint, RaceColumn raceColumn, Competitor competitor) { + final boolean result; + TrackedRace trackedRace = raceColumn.getTrackedRace(competitor); + final TimePoint endOfRace; + // endOfRace != null means we at least will have a fallback result even if there are no mark passings for the competitor + if (trackedRace != null && (endOfRace = trackedRace.getEndOfRace()) != null) { + NavigableSet markPassings = trackedRace.getMarkPassings(competitor); + final MarkPassing lastMarkPassing; + // count race as finished for the competitor if the finish mark passing exists or the time is after the end of race + if (markPassings != null && !markPassings.isEmpty() && + (lastMarkPassing = markPassings.last()).getWaypoint() == trackedRace.getRace().getCourse().getLastWaypoint()) { + result = timePoint.before(lastMarkPassing.getTimePoint()); + } else { + // if available, use the end of the race as indicator for how long competitor may have been in the race + result = timePoint.before(endOfRace); + } + } else { + boolean preResult = false; + for (RaceColumn rc : getLeaderboard().getRaceColumns()) { + if (rc == raceColumn) { + break; + } + TrackedRace rcTrackedRace = rc.getTrackedRace(competitor); + if (rcTrackedRace != null) { + NavigableSet markPassings = rcTrackedRace.getMarkPassings(competitor); + if (markPassings != null && !markPassings.isEmpty()) { + MarkPassing lastMarkPassing = markPassings.last(); + if (timePoint.before(lastMarkPassing.getTimePoint())) { + preResult = true; + break; + } + } else { + // if available, use the end of the race as indicator for how long competitor may have been in the race + TimePoint rcEndOfRace = rcTrackedRace.getEndOfRace(); + if (rcEndOfRace != null) { + if (timePoint.before(rcEndOfRace)) { + preResult = true; + break; + } + } else { + TimePoint rcStartOfRace = rcTrackedRace.getStartOfRace(); + if (rcStartOfRace != null && timePoint.before(rcStartOfRace)) { + preResult = true; + break; + } + } + } + } + } + result = preResult; + } + return result; + } + + private boolean appliesAtStartOfRace(MaxPointsReason maxPointsReason) { + final boolean result; + switch (maxPointsReason) { + case DNS: + case DNC: + case OCS: + result = true; + break; + default: + result = false; + } + return result; + } @Override - public MaxPointsReason getMaxPointsReason(Competitor competitor, RaceColumn raceColumn) { + public MaxPointsReason getMaxPointsReason(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint) { MaxPointsReason result = maxPointsReasons.get(raceColumn.getKey(competitor)); - if (result == null) { + if (result == null || !isMaxPointsReasonApplicable(result, timePoint, raceColumn, competitor)) { result = MaxPointsReason.NONE; } return result; } + private boolean isMaxPointsReasonApplicable(MaxPointsReason maxPointsReason, TimePoint timePoint, RaceColumn raceColumn, Competitor competitor) { + return (appliesAtStartOfRace(maxPointsReason) && !isCertainlyBeforeRaceStart(timePoint, raceColumn, competitor)) + || !isCertainlyBeforeRaceFinish(timePoint, raceColumn, competitor); + } + /** - * If the {@link #getMaxPointsReason(Competitor, TrackedRace)} for the competitor for the + * If the {@link #getMaxPointsReason(Competitor, TrackedRace, TimePoint)} for the competitor for the * raceColumn's tracked race is not {@link MaxPointsReason#NONE}, the * {@link #getMaxPoints(TrackedRace) maximum score} is computed for the competitor. Otherwise, the * uncorrectedScore is returned. *

+ * + * The current implementation considers timePoint by comparing it to the competitor's + * times for the tracked race associated for that competitor in raceColumn. If there is no such tracked + * race, any score correction available will be applied unchanged. If a tracked race is attached to the column for + * the competitor's fleet, the score correction is applied if timePoint is after the competitor + * finished or aborted the race. If the timePoint is after the {@link TrackedRace#getStartOfRace() race + * start time}, a score correction for the competitor for that race is considered if it is a + * {@link MaxPointsReason#DNS}, {@link MaxPointsReason#DNC} or {@link MaxPointsReason#OCS} code. Those penalties + * apply already from the start of the race and will cause the penalty score to be applied already during the race + * time interval, so the competitor will be sorted to the end of the leaderboard already during replay. + *

*/ @Override public Result getCorrectedScore(Callable trackedRankProvider, final Competitor competitor, - final RaceColumn raceColumn, TimePoint timePoint, NumberOfCompetitorsInLeaderboardFetcher numberOfCompetitorsInLeaderboardFetcher, + final RaceColumn raceColumn, final TimePoint timePoint, NumberOfCompetitorsInLeaderboardFetcher numberOfCompetitorsInLeaderboardFetcher, ScoringScheme scoringScheme) { Double result; - final MaxPointsReason maxPointsReason = getMaxPointsReason(competitor, raceColumn); + final MaxPointsReason maxPointsReason = getMaxPointsReason(competitor, raceColumn, timePoint); if (maxPointsReason == MaxPointsReason.NONE) { - result = getCorrectedNonMaxedScore(competitor, raceColumn, trackedRankProvider, scoringScheme, numberOfCompetitorsInLeaderboardFetcher); + result = getCorrectedNonMaxedScore(competitor, raceColumn, trackedRankProvider, scoringScheme, numberOfCompetitorsInLeaderboardFetcher, timePoint); } else { // allow explicit override even when max points reason is specified; calculation may be wrong, // e.g., in case we have an untracked race and the number of competitors is estimated incorrectly @@ -196,7 +371,12 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection { @Override public boolean isCorrected() { - return isScoreCorrected(competitor, raceColumn); + return isScoreCorrected(competitor, raceColumn, getTimePoint()); + } + + @Override + public TimePoint getTimePoint() { + return timePoint; } }; } @@ -216,21 +396,21 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection { * Under the assumption that the competitor is not assigned the maximum score due to disqualification or other * reasons, computes the corrected score. If {@link #correctedScores} contains an entry for the * competitor's key, it is used. Otherwise, the uncorrectedScore is returned. + * * @param scoringScheme * used to transform the tracked rank into a score if there is no score correction applied - * * @return null in case the competitor has no score assigned in that race which is the - * case if the score is not corrected by these score corrections, and the trackedRankProvider delivers 0 - * as the rank, or if the score is not corrected and the scoring scheme cannot find the competitor in any tracked race - * of the raceColumn, meaning there cannot be a tracked rank for the competitor regardless what - * trackedRankProvider delivers. + * case if the score is not corrected by these score corrections, and the trackedRankProvider + * delivers 0 as the rank, or if the score is not corrected and the scoring scheme cannot find the + * competitor in any tracked race of the raceColumn, meaning there cannot be a tracked rank for + * the competitor regardless what trackedRankProvider delivers. */ - protected Double getCorrectedNonMaxedScore(final Competitor competitor, final RaceColumn raceColumn, + private Double getCorrectedNonMaxedScore(final Competitor competitor, final RaceColumn raceColumn, Callable trackedRankProvider, ScoringScheme scoringScheme, - final NumberOfCompetitorsInLeaderboardFetcher numberOfCompetitorsInLeaderboardFetcher) { + final NumberOfCompetitorsInLeaderboardFetcher numberOfCompetitorsInLeaderboardFetcher, TimePoint timePoint) { Double correctedNonMaxedScore = correctedScores.get(raceColumn.getKey(competitor)); Double result; - if (correctedNonMaxedScore == null) { + if (correctedNonMaxedScore == null || isCertainlyBeforeRaceFinish(timePoint, raceColumn, competitor)) { try { int trackedRank = trackedRankProvider.call(); result = scoringScheme.getScoreForRank(raceColumn, competitor, trackedRank, @@ -289,4 +469,8 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection { this.comment = scoreCorrectionComment; } + protected Leaderboard getLeaderboard() { + return leaderboard; + } + } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/AbstractMetaLeaderboard.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/AbstractMetaLeaderboard.java index 9673b67fcc3..aeb39a751b8 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/AbstractMetaLeaderboard.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/AbstractMetaLeaderboard.java @@ -20,6 +20,7 @@ import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.MetaLeaderboard; import com.sap.sailing.domain.leaderboard.ScoreCorrectionListener; import com.sap.sailing.domain.leaderboard.ScoringScheme; +import com.sap.sailing.domain.leaderboard.SettableScoreCorrection; import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; import com.sap.sailing.domain.leaderboard.impl.AbstractSimpleLeaderboardImpl; import com.sap.sailing.domain.tracking.TrackedRace; @@ -74,8 +75,7 @@ public abstract class AbstractMetaLeaderboard extends AbstractSimpleLeaderboardI } public AbstractMetaLeaderboard(String name, ScoringScheme scoringScheme, ThresholdBasedResultDiscardingRule resultDiscardingRule) { - super(new MetaLeaderboardScoreCorrection(), resultDiscardingRule); - getScoreCorrection().setMetaLeaderboard(this); + super(resultDiscardingRule); metaFleet = new FleetImpl("MetaFleet"); this.scoringScheme = scoringScheme; this.name = name; @@ -83,6 +83,13 @@ public abstract class AbstractMetaLeaderboard extends AbstractSimpleLeaderboardI scoreCorrectionChangeForwardersByLeaderboard = new WeakHashMap(); } + @Override + protected SettableScoreCorrection createScoreCorrection() { + return new MetaLeaderboardScoreCorrection(this); + } + + + private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { ois.defaultReadObject(); columnsForLeaderboards = new WeakHashMap<>(); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardScoreCorrection.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardScoreCorrection.java index 2d4e49e5f49..8109435276c 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardScoreCorrection.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardScoreCorrection.java @@ -6,18 +6,15 @@ import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.impl.Util; import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.MetaLeaderboard; import com.sap.sailing.domain.leaderboard.NumberOfCompetitorsInLeaderboardFetcher; import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; public class MetaLeaderboardScoreCorrection extends ScoreCorrectionImpl { private static final long serialVersionUID = 3773423384260065869L; - private AbstractMetaLeaderboard metaLeaderboard; - public MetaLeaderboardScoreCorrection() { - } - - protected void setMetaLeaderboard(AbstractMetaLeaderboard metaLeaderboard) { - this.metaLeaderboard = metaLeaderboard; + public MetaLeaderboardScoreCorrection(MetaLeaderboard leaderboard) { + super(leaderboard); } @Override @@ -43,11 +40,16 @@ public class MetaLeaderboardScoreCorrection extends ScoreCorrectionImpl { MaxPointsReason newMaxPointsReason) { super.notifyListeners(competitor, oldMaxPointsReason, newMaxPointsReason); } + + @Override + protected MetaLeaderboard getLeaderboard() { + return (MetaLeaderboard) super.getLeaderboard(); + } @Override public TimePoint getTimePointOfLastCorrectionsValidity() { TimePoint result = super.getTimePointOfLastCorrectionsValidity(); - for (Leaderboard leaderboard : metaLeaderboard.getLeaderboards()) { + for (Leaderboard leaderboard : getLeaderboard().getLeaderboards()) { TimePoint leaderboardLastCorrectionTimePoint = leaderboard.getScoreCorrection().getTimePointOfLastCorrectionsValidity(); if (result == null || (leaderboardLastCorrectionTimePoint != null && leaderboardLastCorrectionTimePoint.after(result))) { result = leaderboardLastCorrectionTimePoint; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/masterdataimport/FlexibleLeaderboardMasterData.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/masterdataimport/FlexibleLeaderboardMasterData.java index c0c06e2c852..9e2ce14093c 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/masterdataimport/FlexibleLeaderboardMasterData.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/masterdataimport/FlexibleLeaderboardMasterData.java @@ -9,7 +9,6 @@ import com.sap.sailing.domain.base.LeaderboardMasterData; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.ScoringScheme; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; -import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.racelog.RaceLogEvent; public class FlexibleLeaderboardMasterData extends LeaderboardMasterData { @@ -48,8 +47,8 @@ public class FlexibleLeaderboardMasterData extends LeaderboardMasterData { @Override public Leaderboard getLeaderboard() { - return new FlexibleLeaderboardImpl(getName(), new ScoreCorrectionImpl(), getResultDiscardingRule(), - scoringScheme, courseArea); + return new FlexibleLeaderboardImpl(getName(), getResultDiscardingRule(), scoringScheme, + courseArea); } public List getRaceColumns() { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/masterdataimport/RegattaLeaderboardMasterData.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/masterdataimport/RegattaLeaderboardMasterData.java index 689bbb30a75..8abeee6471a 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/masterdataimport/RegattaLeaderboardMasterData.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/masterdataimport/RegattaLeaderboardMasterData.java @@ -10,7 +10,6 @@ import com.sap.sailing.domain.common.RegattaIdentifier; import com.sap.sailing.domain.common.RegattaName; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.impl.RegattaLeaderboardImpl; -import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.racelog.RaceLogEvent; public class RegattaLeaderboardMasterData extends LeaderboardMasterData { @@ -40,7 +39,7 @@ public class RegattaLeaderboardMasterData extends LeaderboardMasterData { if (regatta == null) { return null; } - return new RegattaLeaderboardImpl(regatta, new ScoreCorrectionImpl(), getResultDiscardingRule()); + return new RegattaLeaderboardImpl(regatta, getResultDiscardingRule()); } } diff --git a/java/com.sap.sailing.gwt.ui/pom.xml b/java/com.sap.sailing.gwt.ui/pom.xml index c7e27b25caf..c9df309c469 100644 --- a/java/com.sap.sailing.gwt.ui/pom.xml +++ b/java/com.sap.sailing.gwt.ui/pom.xml @@ -48,7 +48,8 @@ - -Dgwt.persistentunitcache=false + -Dgwt.persistentunitcache=false + chrome com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.ui.Leaderboard diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java index 5223c642de0..35321662f18 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java @@ -224,7 +224,7 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest trackedRegatta[0] = new DynamicTrackedRegattaImpl(loadedRegatta); resForLoading.apply(new ConnectTrackedRaceToLeaderboardColumn(loadedLeaderboard.getName(), loadedQ2.getName(), loadedYellow .getName(), q2YellowTrackedRace.getRaceIdentifier())); - MaxPointsReason hassosLoadedMaxPointsReason = loadedLeaderboard.getScoreCorrection().getMaxPointsReason(hasso, loadedQ2); + MaxPointsReason hassosLoadedMaxPointsReason = loadedLeaderboard.getScoreCorrection().getMaxPointsReason(hasso, loadedQ2, MillisecondsTimePoint.now()); assertEquals(MaxPointsReason.DNF, hassosLoadedMaxPointsReason); } diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java index 0e71b7b8415..be053083ef2 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java @@ -40,7 +40,6 @@ import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOver import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; import com.sap.sailing.domain.leaderboard.impl.LowPoint; import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; -import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard; import com.sap.sailing.domain.persistence.DomainObjectFactory; import com.sap.sailing.domain.persistence.MongoObjectFactory; @@ -76,17 +75,17 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe final String groupDescription = "A leaderboard group"; final ArrayList leaderboards = new ArrayList<>(); - Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards.add(leaderboard); final LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl(groupName, groupDescription, false, leaderboards); @@ -124,19 +123,19 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe final String groupName = "Leaderboard Group"; final String groupDescription = "A leaderboard group"; - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); racingEventService.addLeaderboard(leaderboard); leaderboard.addRace(raceWithTwoCompetitors, raceColumnName1, /* medalRace */ false, leaderboard.getFleet(null)); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); racingEventService.addLeaderboard(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); racingEventService.addLeaderboard(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); racingEventService.addLeaderboard(leaderboard); LeaderboardGroup leaderboardGroup = racingEventService.addLeaderboardGroup(groupName, groupDescription, false, Arrays.asList(leaderboardNames), new int[0], @@ -181,19 +180,19 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe final String groupDescription = "A leaderboard group"; final ArrayList leaderboards = new ArrayList<>(); - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards.add(leaderboard); leaderboard.addRace(raceWithTwoCompetitors, raceColumnName1, /* medalRace */ false, leaderboard.getFleet(null)); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards.add(leaderboard); final LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl(groupName, groupDescription, false, leaderboards); @@ -238,19 +237,19 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe final String groupDescription = "A leaderboard group"; final ArrayList leaderboards = new ArrayList<>(); - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards.add(leaderboard); leaderboard.addRace(raceWithTwoCompetitors, raceColumnName1, /* medalRace */ false, leaderboard.getFleet(null)); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards.add(leaderboard); final LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl(groupName, groupDescription, false, leaderboards); @@ -286,14 +285,14 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe final String groupName1 = "Leaderboard Group 1"; final String groupDescription1 = "A leaderboard group 1"; final ArrayList leaderboards1 = new ArrayList<>(); - Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards1.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards1.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards1.add(leaderboard); final LeaderboardGroup leaderboardGroup1 = new LeaderboardGroupImpl(groupName1, groupDescription1, false, leaderboards1); mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup1); @@ -301,11 +300,11 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe final String groupName2 = "Leaderboard Group 2"; final String groupDescription2= "A leaderboard group 2"; final ArrayList leaderboards2 = new ArrayList<>(); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards2.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards2.add(leaderboard); final LeaderboardGroup leaderboardGroup2 = new LeaderboardGroupImpl(groupName2, groupDescription2, false, leaderboards2); mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup2); @@ -331,17 +330,17 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe final String groupDescription = "A leaderboard group"; final ArrayList leaderboards = new ArrayList<>(); - Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards.add(leaderboard); final LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl(groupName, groupDescription, false, leaderboards); @@ -369,11 +368,11 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe final String groupDescription = "A leaderboard group"; final ArrayList leaderboards = new ArrayList<>(); - Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboards.add(leaderboard); final LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl(groupName, groupDescription, false, leaderboards); @@ -382,12 +381,12 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe final String[] ungroupedLeaderboardNames = {"Ungrouped Leaderboard 0", "Ungrouped Leaderboard 1", "Ungrouped Leaderboard 2"}; final FlexibleLeaderboard[] ungroupedLeaderboards = { - new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[0], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null), - new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[1], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null), - new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[2], new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null) }; + new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null), + new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null), + new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null) }; mongoObjectFactory.storeLeaderboard(ungroupedLeaderboards[0]); mongoObjectFactory.storeLeaderboard(ungroupedLeaderboards[1]); mongoObjectFactory.storeLeaderboard(ungroupedLeaderboards[2]); @@ -424,7 +423,7 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe final String groupDescription = "A leaderboard group"; final ArrayList leaderboards = new ArrayList<>(); - final FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + final FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); final Fleet fleet = leaderboard.getFleet(null); final RaceColumn race = leaderboard.addRaceColumn(columnName, false, fleet); leaderboards.add(leaderboard); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java index 7a9c5ba94ed..baf2b19dd4e 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java @@ -26,13 +26,11 @@ import com.sap.sailing.domain.common.impl.MillisecondsTimePoint; import com.sap.sailing.domain.common.impl.Util; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard; -import com.sap.sailing.domain.leaderboard.SettableScoreCorrection; import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.HighPoint; import com.sap.sailing.domain.leaderboard.impl.LowPoint; import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; -import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.persistence.impl.DomainObjectFactoryImpl; import com.sap.sailing.domain.persistence.impl.MongoObjectFactoryImpl; import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithFixedRank; @@ -48,8 +46,8 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { public void testStoreAndRetrieveSimpleLeaderboardWithSpecificColumnFactors() { final String leaderboardName = "TestLeaderboard"; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); leaderboard.addRaceColumn("R1", /* medalRace */ false); RaceColumn r2 = leaderboard.addRaceColumn("R2", /* medalRace */ false); r2.setFactor(1.5); @@ -66,8 +64,8 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { public void testStoreAndRetrieveLeaderboardWithSuppressedCompetitors() { final String leaderboardName = "TestLeaderboard"; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); Competitor wolfgang = createCompetitor(); Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", new TeamImpl("STG", Collections.singleton( new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), @@ -94,12 +92,11 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { public void testStoreAndRetrieveLeaderboardWithCommentedScoreCorrection() { final String leaderboardName = "TestLeaderboard"; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - SettableScoreCorrection scoreCorrection = new ScoreCorrectionImpl(); - FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, scoreCorrection, - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - scoreCorrection.setComment("Humba"); + FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboard.getScoreCorrection().setComment("Humba"); MillisecondsTimePoint now = MillisecondsTimePoint.now(); - scoreCorrection.setTimePointOfLastCorrectionsValidity(now); + leaderboard.getScoreCorrection().setTimePointOfLastCorrectionsValidity(now); new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard); Leaderboard loadedLeaderboard = new DomainObjectFactoryImpl(db).loadLeaderboard(leaderboardName, /* regattaRegistry */ null); assertEquals("Humba", loadedLeaderboard.getScoreCorrection().getComment()); @@ -110,9 +107,8 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { public void testStoreAndRetrieveLeaderboardWithDisplayNameSet() { final String leaderboardName = "TestLeaderboard"; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - SettableScoreCorrection scoreCorrection = new ScoreCorrectionImpl(); - FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, scoreCorrection, - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); Competitor competitor = createCompetitor(); TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); final String raceColumnName1 = "My First Race 1"; @@ -132,8 +128,8 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { public void testStoreAndRetrieveSimpleLeaderboard() { final String leaderboardName = "TestLeaderboard"; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard); Leaderboard loadedLeaderboard = new DomainObjectFactoryImpl(db).loadLeaderboard(leaderboardName, /* regattaRegistry */ null); assertEquals(leaderboardName, loadedLeaderboard.getName()); @@ -145,8 +141,8 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { public void testStoreAndRetrieveSimpleLeaderboardWithHighPointScoringScheme() { final String leaderboardName = "TestLeaderboard"; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new HighPoint(), null); + FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new HighPoint(), null); new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard); Leaderboard loadedLeaderboard = new DomainObjectFactoryImpl(db).loadLeaderboard(leaderboardName, /* regattaRegistry */ null); assertSame(HighPoint.class, loadedLeaderboard.getScoringScheme().getClass()); @@ -159,8 +155,8 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final String raceColumnName = "My First Race"; final double carriedPointsForWolfgangHunger = 3.7; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); Competitor competitor = createCompetitor(); TrackedRace raceWithOneCompetitor = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); leaderboard.addRace(raceWithOneCompetitor, raceColumnName, /* medalRace */ false, leaderboard.getFleet(null)); @@ -184,8 +180,8 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final String raceColumnName2 = "My First Race 2"; final double correctedPoints = 2.75; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); Competitor competitor = createCompetitor(); TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true); @@ -200,9 +196,9 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { RaceColumn loadedColumn2 = loadedLeaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace, ignored */ false, leaderboard.getFleet(null)); assertEquals(leaderboardName, loadedLeaderboard.getName()); - assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn1)); + assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn1, MillisecondsTimePoint.now())); assertEquals(correctedPoints, (double) loadedLeaderboard.getScoreCorrection().getExplicitScoreCorrection(competitor, loadedColumn1), 0.00000001); - assertFalse(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn2)); + assertFalse(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn2, MillisecondsTimePoint.now())); } @Test @@ -212,8 +208,8 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final String raceColumnName2 = "My.First$Race$2"; final double correctedPoints = 2.75; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); Competitor competitor = createCompetitor(); TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true); @@ -226,9 +222,9 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { RaceColumn loadedColumn1 = loadedLeaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace, ignored */ false, leaderboard.getFleet(null)); RaceColumn loadedColumn2 = loadedLeaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace, ignored */ false, leaderboard.getFleet(null)); assertEquals(leaderboardName, loadedLeaderboard.getName()); - assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn1)); + assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn1, MillisecondsTimePoint.now())); assertEquals(correctedPoints, (double) loadedLeaderboard.getScoreCorrection().getExplicitScoreCorrection(competitor, loadedColumn1), 0.00000001); - assertFalse(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn2)); + assertFalse(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn2, MillisecondsTimePoint.now())); } @Test @@ -238,8 +234,8 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final String raceColumnName2 = "My First Race 2"; final MaxPointsReason maxPointsReason = MaxPointsReason.DNF; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); Competitor competitor = createCompetitor(); TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true); @@ -254,9 +250,9 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { RaceColumn loadedColumn2 = loadedLeaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace, ignored */ false, leaderboard.getFleet(null)); assertEquals(leaderboardName, loadedLeaderboard.getName()); - assertFalse(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn1)); - assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn2)); - assertEquals(maxPointsReason, loadedLeaderboard.getScoreCorrection().getMaxPointsReason(competitor, loadedColumn2)); + assertFalse(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn1, MillisecondsTimePoint.now())); + assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn2, MillisecondsTimePoint.now())); + assertEquals(maxPointsReason, loadedLeaderboard.getScoreCorrection().getMaxPointsReason(competitor, loadedColumn2, MillisecondsTimePoint.now())); } @Test @@ -267,8 +263,8 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final double correctedPoints = 2.55; final MaxPointsReason maxPointsReason = MaxPointsReason.DNF; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); Competitor competitor = createCompetitor(); TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true); @@ -286,10 +282,10 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { RaceColumn loadedColumn2 = loadedLeaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace, ignored */ false, leaderboard.getFleet(null)); assertEquals(leaderboardName, loadedLeaderboard.getName()); - assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn1)); + assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn1, MillisecondsTimePoint.now())); assertEquals(correctedPoints, (double) loadedLeaderboard.getScoreCorrection().getExplicitScoreCorrection(competitor, loadedColumn1), 0.000000001); - assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn2)); - assertEquals(maxPointsReason, loadedLeaderboard.getScoreCorrection().getMaxPointsReason(competitor, loadedColumn2)); + assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn2, MillisecondsTimePoint.now())); + assertEquals(maxPointsReason, loadedLeaderboard.getScoreCorrection().getMaxPointsReason(competitor, loadedColumn2, MillisecondsTimePoint.now())); } private Competitor createCompetitor() { diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java index a1e19a65f7d..b24d5353232 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java @@ -32,7 +32,6 @@ import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.LowPoint; -import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; import com.sap.sailing.domain.persistence.MongoFactory; import com.sap.sailing.domain.persistence.MongoRaceLogStoreFactory; @@ -77,8 +76,8 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD RaceLogStore raceLogStore = MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStore(mongoObjectFactory, domainObjectFactory); - leaderboard = new FlexibleLeaderboardImpl(raceLogStore, leaderboardName, new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + leaderboard = new FlexibleLeaderboardImpl(raceLogStore, leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); Fleet defaultFleet = leaderboard.getFleet(null); leaderboard.addRaceColumn(raceColumnName, /* medalRace */ false, defaultFleet); @@ -248,8 +247,8 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD assertEquals(now, loadedConfirmedEvent.getTimePoint()); assertEquals(0, loadedConfirmedEvent.getPassId()); assertEquals(0, loadedConfirmedEvent.getInvolvedBoats().size()); - assertNull(event.getPositionedCompetitors()); - assertNull(loadedConfirmedEvent.getPositionedCompetitors()); + assertNull(event.getPositionedCompetitorsIDsNamesMaxPointsReasons()); + assertNull(loadedConfirmedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertEquals(1, Util.size(loadedRaceLog.getFixes())); } finally { loadedRaceLog.unlockAfterRead(); @@ -297,10 +296,10 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD assertEquals(event.getPassId(), loadedPositioningEvent.getPassId()); assertEquals(event.getId(), loadedPositioningEvent.getId()); assertEquals(event.getInvolvedBoats().size(), loadedPositioningEvent.getInvolvedBoats().size()); - assertEquals(event.getPositionedCompetitors().size(), loadedPositioningEvent.getPositionedCompetitors().size()); - assertEquals(event.getPositionedCompetitors().get(0).getA(), loadedPositioningEvent.getPositionedCompetitors().get(0).getA()); - assertEquals(event.getPositionedCompetitors().get(0).getB(), loadedPositioningEvent.getPositionedCompetitors().get(0).getB()); - assertEquals(event.getPositionedCompetitors().get(0).getC().name(), loadedPositioningEvent.getPositionedCompetitors().get(0).getC().name()); + assertEquals(event.getPositionedCompetitorsIDsNamesMaxPointsReasons().size(), loadedPositioningEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons().size()); + assertEquals(event.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getA(), loadedPositioningEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getA()); + assertEquals(event.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getB(), loadedPositioningEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getB()); + assertEquals(event.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getC().name(), loadedPositioningEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getC().name()); assertEquals(1, Util.size(loadedRaceLog.getFixes())); } finally { loadedRaceLog.unlockAfterRead(); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java index 6a610148cd9..c5ad19d801e 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java @@ -259,10 +259,10 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends RaceLogMongoDBTest assertEquals(event.getPassId(), loadedPositioningEvent.getPassId()); assertEquals(event.getId(), loadedPositioningEvent.getId()); assertEquals(event.getInvolvedBoats().size(), loadedPositioningEvent.getInvolvedBoats().size()); - assertEquals(event.getPositionedCompetitors().size(), loadedPositioningEvent.getPositionedCompetitors().size()); - assertEquals(event.getPositionedCompetitors().get(0).getA(), loadedPositioningEvent.getPositionedCompetitors().get(0).getA()); - assertEquals(event.getPositionedCompetitors().get(0).getB(), loadedPositioningEvent.getPositionedCompetitors().get(0).getB()); - assertEquals(event.getPositionedCompetitors().get(0).getC().name(), loadedPositioningEvent.getPositionedCompetitors().get(0).getC().name()); + assertEquals(event.getPositionedCompetitorsIDsNamesMaxPointsReasons().size(), loadedPositioningEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons().size()); + assertEquals(event.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getA(), loadedPositioningEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getA()); + assertEquals(event.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getB(), loadedPositioningEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getB()); + assertEquals(event.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getC().name(), loadedPositioningEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getC().name()); assertEquals(1, Util.size(loadedRaceLog.getFixes())); } finally { loadedRaceLog.unlockAfterRead(); @@ -289,10 +289,10 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends RaceLogMongoDBTest assertEquals(event.getPassId(), loadedConfirmedEvent.getPassId()); assertEquals(event.getId(), loadedConfirmedEvent.getId()); assertEquals(event.getInvolvedBoats().size(), loadedConfirmedEvent.getInvolvedBoats().size()); - assertEquals(event.getPositionedCompetitors().size(), loadedConfirmedEvent.getPositionedCompetitors().size()); - assertEquals(event.getPositionedCompetitors().get(0).getA(), loadedConfirmedEvent.getPositionedCompetitors().get(0).getA()); - assertEquals(event.getPositionedCompetitors().get(0).getB(), loadedConfirmedEvent.getPositionedCompetitors().get(0).getB()); - assertEquals(event.getPositionedCompetitors().get(0).getC().name(), loadedConfirmedEvent.getPositionedCompetitors().get(0).getC().name()); + assertEquals(event.getPositionedCompetitorsIDsNamesMaxPointsReasons().size(), loadedConfirmedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons().size()); + assertEquals(event.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getA(), loadedConfirmedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getA()); + assertEquals(event.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getB(), loadedConfirmedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getB()); + assertEquals(event.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getC().name(), loadedConfirmedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getC().name()); assertEquals(1, Util.size(loadedRaceLog.getFixes())); } finally { loadedRaceLog.unlockAfterRead(); @@ -314,8 +314,8 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends RaceLogMongoDBTest assertEquals(now, loadedConfirmedEvent.getTimePoint()); assertEquals(0, loadedConfirmedEvent.getPassId()); assertEquals(0, loadedConfirmedEvent.getInvolvedBoats().size()); - assertNull(event.getPositionedCompetitors()); - assertNull(loadedConfirmedEvent.getPositionedCompetitors()); + assertNull(event.getPositionedCompetitorsIDsNamesMaxPointsReasons()); + assertNull(loadedConfirmedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertEquals(1, Util.size(loadedRaceLog.getFixes())); } finally { loadedRaceLog.unlockAfterRead(); diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java index 8eba39304e5..38135dbdda6 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java @@ -64,15 +64,15 @@ public class RaceLogFinishPositioningConfirmedEventSerializerTest { assertEquals(event.getTimePoint(), deserializedEvent.getTimePoint()); assertEquals(0, Util.size(event.getInvolvedBoats())); assertEquals(0, Util.size(deserializedEvent.getInvolvedBoats())); - assertNotNull(event.getPositionedCompetitors()); - assertNotNull(deserializedEvent.getPositionedCompetitors()); - assertEquals(1, event.getPositionedCompetitors().size()); - assertEquals(1, deserializedEvent.getPositionedCompetitors().size()); - assertEquals(event.getPositionedCompetitors().get(0).getA(), deserializedEvent.getPositionedCompetitors() + assertNotNull(event.getPositionedCompetitorsIDsNamesMaxPointsReasons()); + assertNotNull(deserializedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); + assertEquals(1, event.getPositionedCompetitorsIDsNamesMaxPointsReasons().size()); + assertEquals(1, deserializedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons().size()); + assertEquals(event.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getA(), deserializedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons() .get(0).getA()); - assertEquals(event.getPositionedCompetitors().get(0).getB(), deserializedEvent.getPositionedCompetitors() + assertEquals(event.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getB(), deserializedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons() .get(0).getB()); - assertEquals(event.getPositionedCompetitors().get(0).getC(), deserializedEvent.getPositionedCompetitors() + assertEquals(event.getPositionedCompetitorsIDsNamesMaxPointsReasons().get(0).getC(), deserializedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons() .get(0).getC()); } @@ -89,9 +89,9 @@ public class RaceLogFinishPositioningConfirmedEventSerializerTest { assertEquals(event.getTimePoint(), deserializedEvent.getTimePoint()); assertEquals(0, Util.size(event.getInvolvedBoats())); assertEquals(0, Util.size(deserializedEvent.getInvolvedBoats())); - assertNull(event.getPositionedCompetitors()); - assertNotNull(deserializedEvent.getPositionedCompetitors()); - assertEquals(0, deserializedEvent.getPositionedCompetitors().size()); + assertNull(event.getPositionedCompetitorsIDsNamesMaxPointsReasons()); + assertNotNull(deserializedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); + assertEquals(0, deserializedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons().size()); } @Test @@ -107,10 +107,10 @@ public class RaceLogFinishPositioningConfirmedEventSerializerTest { assertEquals(event.getTimePoint(), deserializedEvent.getTimePoint()); assertEquals(0, Util.size(event.getInvolvedBoats())); assertEquals(0, Util.size(deserializedEvent.getInvolvedBoats())); - assertNotNull(event.getPositionedCompetitors()); - assertNotNull(deserializedEvent.getPositionedCompetitors()); - assertEquals(0, event.getPositionedCompetitors().size()); - assertEquals(0, deserializedEvent.getPositionedCompetitors().size()); + assertNotNull(event.getPositionedCompetitorsIDsNamesMaxPointsReasons()); + assertNotNull(deserializedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); + assertEquals(0, event.getPositionedCompetitorsIDsNamesMaxPointsReasons().size()); + assertEquals(0, deserializedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons().size()); } } diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/masterdata/impl/LeaderboardMasterDataJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/masterdata/impl/LeaderboardMasterDataJsonSerializer.java index e62a45885fa..2ac3f15a576 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/masterdata/impl/LeaderboardMasterDataJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/masterdata/impl/LeaderboardMasterDataJsonSerializer.java @@ -11,6 +11,7 @@ import com.sap.sailing.domain.base.CourseArea; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.common.impl.MillisecondsTimePoint; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; @@ -272,12 +273,14 @@ public class LeaderboardMasterDataJsonSerializer implements JsonSerializer> positionedCompetitors = new ArrayList>(); + positionedCompetitors.add(new Triple(competitor.getId(), competitor.getName(), MaxPointsReason.BFD)); + positionedCompetitors.add(new Triple(competitor2.getId(), competitor2.getName(), MaxPointsReason.NONE)); + RaceLogFinishPositioningConfirmedEvent finishPositioningConfirmedEvent = factory.createFinishPositioningConfirmedEvent(logTimePoint2, 1, positionedCompetitors); + raceColumn.getRaceLog(testFleet1).add(finishPositioningConfirmedEvent); + storedLogUUIDs.add(finishPositioningConfirmedEvent.getId()); // Set score correction double scoreCorrection = 12.0; @@ -392,7 +406,7 @@ public class MasterDataImportTest { // Deserialization copied from doPost in MasterDataByLeaderboardGroupJsonPostServlet RacingEventService destService = new RacingEventServiceImplMock(); - DomainFactory domainFactory = DomainFactory.INSTANCE; + DomainFactory domainFactory = new DomainFactoryImpl(); // create a new, empty domain factory to ensure all competitors are removed MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); MasterDataImportObjectCreationCount creationCount = importer.importMasterData( masterDataOverallObject.toString(), false); @@ -433,11 +447,154 @@ public class MasterDataImportTest { leaderboardOnTarget.getScoreCorrection().getExplicitScoreCorrection(competitorOnTarget, raceColumnOnTarget)); Assert.assertEquals(maxPointsReason, - leaderboardOnTarget.getScoreCorrection().getMaxPointsReason(competitorOnTarget, raceColumnOnTarget)); + leaderboardOnTarget.getScoreCorrection().getMaxPointsReason(competitorOnTarget, raceColumnOnTarget, MillisecondsTimePoint.now())); // Checks if score correction was not set if not set on source Assert.assertFalse(leaderboardOnTarget.getScoreCorrection().isScoreCorrected(competitorOnTarget2, - raceColumnOnTarget)); + raceColumnOnTarget, MillisecondsTimePoint.now())); + } + + /** + * When a race log entry references a competitor, e.g., by its UUID, these cannot be resolved when the TrackedRace isn't + * connected to the race column / leaderboard yet. Such a resolution would occur if importing the race log event triggered + * a listener which would try to resolve the competitor ID. This test ensures that the import does not fail due to such a + * look-up. + */ + @Test + public void testMasterDataImportForRaceLogEventsReferencingCompetitors() throws MalformedURLException, IOException, + InterruptedException { + // Setup source service + DomainFactory sourceDomainFactory = new DomainFactoryImpl(); + RacingEventService sourceService = new RacingEventServiceImpl(MongoDBService.INSTANCE, + SwissTimingFactory.INSTANCE, new com.sap.sailing.domain.swisstimingadapter.impl.DomainFactoryImpl( + sourceDomainFactory), new com.sap.sailing.domain.tractracadapter.impl.DomainFactoryImpl( + sourceDomainFactory), MediaDBFactory.INSTANCE.getDefaultMediaDB()); + Event event = sourceService.addEvent(TEST_EVENT_NAME, "testVenue", "", false, eventUUID, + new ArrayList()); + UUID courseAreaUUID = UUID.randomUUID(); + CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); + event.getVenue().addCourseArea(courseArea); + + List raceColumnNames = new ArrayList(); + String raceColumnName = "T1"; + raceColumnNames.add(raceColumnName); + raceColumnNames.add("T2"); + final List emptyRaceColumnNamesList = Collections.emptyList(); + + List series = new ArrayList(); + List fleets = new ArrayList(); + FleetImpl testFleet1 = new FleetImpl("testFleet1"); + fleets.add(testFleet1); + fleets.add(new FleetImpl("testFleet2")); + series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); + UUID regattaUUID = UUID.randomUUID(); + Regatta regatta = sourceService.createRegatta("testRegatta", "29er", regattaUUID, series, true, new LowPoint(), + courseAreaUUID); + event.addRegatta(regatta); + for (String name : raceColumnNames) { + series.get(0).addRaceColumn(name, sourceService); + } + + int[] discardRule = { 1, 2, 3, 4 }; + Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), + "testDisplayName", discardRule); + List leaderboardNames = new ArrayList(); + leaderboardNames.add(leaderboard.getName()); + sourceService.addLeaderboardGroup(TEST_GROUP_NAME, "testGroupDesc", false, leaderboardNames, null, null); + + // Set tracked Race with competitors + Set competitors = new HashSet(); + UUID competitorUUID = UUID.randomUUID(); + Set sailors = new HashSet(); + sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), + "Oberhoschy")); + Person coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), + "Der Lennart halt"); + Team team = new TeamImpl("Pros", sailors, coach); + BoatClass boatClass = new BoatClassImpl("H16", true); + Boat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + Competitor competitor = sourceDomainFactory.getOrCreateCompetitor(competitorUUID, "Froderik", team, boat); + competitors.add(competitor); + UUID competitor2UUID = UUID.randomUUID(); + Set sailors2 = new HashSet(); + sailors2.add(new PersonImpl("Test Mustermann", new NationalityImpl("GER"), new Date(645487200000L), "desc")); + Person coach2 = new PersonImpl("Max Test", new NationalityImpl("GER"), new Date(645487200000L), "desc"); + Team team2 = new TeamImpl("Pros2", sailors2, coach2); + Boat boat2 = new BoatImpl("FastBoat", boatClass, "GER70133"); + Competitor competitor2 = sourceDomainFactory.getOrCreateCompetitor(competitor2UUID, "Froderik", team2, boat2); + competitors.add(competitor2); + TrackedRace trackedRace = new DummyTrackedRace(competitors, regatta); + + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + raceColumn.setTrackedRace(testFleet1, trackedRace); + + // Set log event + RaceLogEventFactory factory = new RaceLogEventFactoryImpl(); + TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); + RaceLogStartTimeEvent logEvent = factory.createStartTimeEvent(logTimePoint, 1, logTimePoint); + raceColumn.getRaceLog(testFleet1).add(logEvent); + storedLogUUIDs.add(logEvent.getId()); + + // Add a competitor-related race log event to ensure that no competitor resolution is attempted while receiving + TimePoint logTimePoint2 = logTimePoint.plus(10); + List> positionedCompetitors = new ArrayList>(); + positionedCompetitors.add(new Triple(competitor.getId(), competitor.getName(), MaxPointsReason.DNS)); + positionedCompetitors.add(new Triple(competitor2.getId(), competitor2.getName(), MaxPointsReason.NONE)); + RaceLogFinishPositioningConfirmedEvent finishPositioningConfirmedEvent = factory.createFinishPositioningConfirmedEvent(logTimePoint2, 1, positionedCompetitors); + raceColumn.getRaceLog(testFleet1).add(finishPositioningConfirmedEvent); + storedLogUUIDs.add(finishPositioningConfirmedEvent.getId()); + + // Serialize + TopLevelMasterDataSerializer serializer = new TopLevelMasterDataSerializer( + sourceService.getLeaderboardGroups(), sourceService.getAllEvents(), + sourceService.getPersistentRegattasForRaceIDs(), sourceService.getAllMediaTracks()); + Set names = new HashSet(); + names.add(TEST_GROUP_NAME); + JSONObject masterDataOverallObject = serializer.serialize(names); + Assert.assertNotNull(masterDataOverallObject); + + // Delete all data above from the database, to allow recreating all of it on target server + deleteCreatedDataFromDatabase(); + + // Deserialization copied from doPost in MasterDataByLeaderboardGroupJsonPostServlet + RacingEventService destService = new RacingEventServiceImplMock(); + DomainFactory domainFactory = new DomainFactoryImpl(); // create a new, empty domain factory to ensure all competitors are removed + MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); + MasterDataImportObjectCreationCount creationCount = importer.importMasterData( + masterDataOverallObject.toString(), false); + + Assert.assertNotNull(creationCount); + Event eventOnTarget = destService.getEvent(eventUUID); + Assert.assertNotNull(eventOnTarget); + LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); + Assert.assertNotNull(leaderboardGroupOnTarget); + Leaderboard leaderboardOnTarget = destService.getLeaderboardByName(TEST_LEADERBOARD_NAME); + Assert.assertNotNull(leaderboardOnTarget); + Regatta regattaOnTarget = destService.getRegattaByName(TEST_LEADERBOARD_NAME); + Assert.assertNotNull(regattaOnTarget); + + Assert.assertEquals(courseAreaUUID, eventOnTarget.getVenue().getCourseAreas().iterator().next().getId()); + + RaceColumn raceColumnOnTarget = leaderboardOnTarget.getRaceColumnByName(raceColumnName); + Assert.assertNotNull(raceColumnOnTarget); + + Assert.assertTrue(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget)); + Competitor competitorOnTarget = domainFactory.getExistingCompetitorById(competitorUUID); + Set competitorsCreatedOnTarget = new HashSet(); + competitorsCreatedOnTarget.add(competitorOnTarget); + + TrackedRace trackedRaceForTarget = new DummyTrackedRace(competitorsCreatedOnTarget, regattaOnTarget); + Fleet fleet1OnTarget = raceColumnOnTarget.getFleetByName(testFleet1.getName()); + raceColumnOnTarget.setTrackedRace(fleet1OnTarget, trackedRaceForTarget); + + Iterable competitorsOnTarget = leaderboardOnTarget.getAllCompetitors(); + Iterator competitorIterator = competitorsOnTarget.iterator(); + Assert.assertTrue(competitorIterator.hasNext()); + Assert.assertEquals(competitorOnTarget, competitorIterator.next()); + + // Check for score corrections + Assert.assertEquals(MaxPointsReason.DNS, + leaderboardOnTarget.getScoreCorrection().getMaxPointsReason(competitorOnTarget, raceColumnOnTarget, MillisecondsTimePoint.now())); } @Test diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch index 85f0272fc18..77e917122fc 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch @@ -22,10 +22,10 @@ - + - + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Monitoring).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Monitoring).launch index d60f3c63dcd..871a4c361dc 100644 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Monitoring).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Monitoring).launch @@ -22,10 +22,10 @@ - + - + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, No Tests).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, No Tests).launch index 13e52b39586..74b58322c07 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, No Tests).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, No Tests).launch @@ -21,9 +21,9 @@ - + - + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch index 58461c8453b..0e310c59ce8 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch @@ -21,9 +21,9 @@ - + - + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy).launch b/java/com.sap.sailing.server/SailingServer (Proxy).launch index c075c4faa3a..fd283c15bd2 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy).launch @@ -26,6 +26,6 @@ - + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch b/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch index a61dd35df96..69d27d3bf3b 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch @@ -22,10 +22,10 @@ - + - + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy, Remote Debug SAP VM).launch b/java/com.sap.sailing.server/SailingServer (Proxy, Remote Debug SAP VM).launch index 83ac437bcd7..5939146639d 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy, Remote Debug SAP VM).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy, Remote Debug SAP VM).launch @@ -22,9 +22,9 @@ - + - + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy, SwissTiming Live Simulation).launch b/java/com.sap.sailing.server/SailingServer (Proxy, SwissTiming Live Simulation).launch index ddf44c6a321..4b7a4e1035d 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy, SwissTiming Live Simulation).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy, SwissTiming Live Simulation).launch @@ -21,9 +21,9 @@ - + - + diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RaceLogScoringReplicator.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RaceLogScoringReplicator.java index ec40af24cc7..21386648ecc 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RaceLogScoringReplicator.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RaceLogScoringReplicator.java @@ -5,7 +5,6 @@ import java.util.List; import java.util.concurrent.Callable; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.RaceColumnListener; @@ -111,12 +110,14 @@ public class RaceLogScoringReplicator implements RaceColumnListener { } /** - * Retrieves the last RaceLogFinishPositioningListChangedEvent from the racelog and compares the ranks and disqualifications - * entered by the race committee with the tracked ranks. When a tracked rank for a competitor is not the same as the rank of the race committee, - * a score correction is issued. - * The positioning list contains a list of competitors sorted by the positioning order when finishing. Additionally a MaxPointsReason might be entered by the - * Race Committee. - * @param timePoint the TimePoint at which the race committee confirmed their last rank list entered in the app. + * Retrieves the last RaceLogFinishPositioningListChangedEvent from the racelog and compares the ranks and + * disqualifications entered by the race committee with the tracked ranks. When a tracked rank for a competitor is + * not the same as the rank of the race committee, a score correction is issued. The positioning list contains a + * list of competitors sorted by the positioning order when finishing. Additionally a MaxPointsReason might be + * entered by the Race Committee. + * + * @param timePoint + * the TimePoint at which the race committee confirmed their last rank list entered in the app. */ private void checkNeedForScoreCorrectionByResultsOfRaceCommittee(Leaderboard leaderboard, RaceColumn raceColumn, Fleet fleet, RaceLog raceLog, TimePoint timePoint) { @@ -138,7 +139,7 @@ public class RaceLogScoringReplicator implements RaceColumnListener { if (positioningList != null) { for (Triple positionedCompetitor : positioningList) { - Competitor competitor = DomainFactory.INSTANCE.getExistingCompetitorById(positionedCompetitor.getA()); + Competitor competitor = service.getBaseDomainFactory().getExistingCompetitorById(positionedCompetitor.getA()); if (positionedCompetitor.getC().equals(MaxPointsReason.NONE)) { try { diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java index 154acd334ea..8c16475a91d 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java @@ -73,7 +73,6 @@ import com.sap.sailing.domain.leaderboard.ScoringScheme; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; import com.sap.sailing.domain.leaderboard.impl.RegattaLeaderboardImpl; -import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard; import com.sap.sailing.domain.persistence.DomainObjectFactory; @@ -377,8 +376,8 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen domainObjectFactory); CourseArea courseArea = getCourseArea(courseAreaId); FlexibleLeaderboard result = new FlexibleLeaderboardImpl(raceLogStore, leaderboardName, - new ScoreCorrectionImpl(), new ThresholdBasedResultDiscardingRuleImpl(discardThresholds), - scoringScheme, courseArea); + new ThresholdBasedResultDiscardingRuleImpl(discardThresholds), scoringScheme, + courseArea); result.setDisplayName(leaderboardDisplayName); synchronized (leaderboardsByName) { if (getLeaderboardByName(leaderboardName) != null) { @@ -410,8 +409,7 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen + (regatta == null ? "null" : (regatta.getName() + " (" + regatta.hashCode() + ")")) + " to " + this); RegattaLeaderboard result = null; if (regatta != null) { - result = new RegattaLeaderboardImpl(regatta, new ScoreCorrectionImpl(), - new ThresholdBasedResultDiscardingRuleImpl(discardThresholds)); + result = new RegattaLeaderboardImpl(regatta, new ThresholdBasedResultDiscardingRuleImpl(discardThresholds)); result.setDisplayName(leaderboardDisplayName); synchronized (leaderboardsByName) { if (getLeaderboardByName(result.getName()) != null) { diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/ImportMasterDataOperation.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/ImportMasterDataOperation.java index 5b71da06724..a7bfcfd31f2 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/ImportMasterDataOperation.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/ImportMasterDataOperation.java @@ -170,7 +170,7 @@ public class ImportMasterDataOperation extends List logEvents = fleetEntry.getValue(); RaceLog raceLog = raceColumn.getRaceLog(fleet); for (RaceLogEvent singleEvent : logEvents) { - raceLog.add(singleEvent); + raceLog.load(singleEvent); } } } diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateLeaderboardMaxPointsReason.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateLeaderboardMaxPointsReason.java index d6c5673e81c..2a1cce83097 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateLeaderboardMaxPointsReason.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateLeaderboardMaxPointsReason.java @@ -50,7 +50,7 @@ public class UpdateLeaderboardMaxPointsReason extends AbstractLeaderboardColumnO leaderboard.getScoreCorrection().setMaxPointsReason(competitor, raceColumn, newMaxPointsReason); updateStoredLeaderboard(toState, leaderboard); Entry updatedEntry = leaderboard.getEntry(competitor, raceColumn, timePoint); - boolean isScoreCorrected = leaderboard.getScoreCorrection().isScoreCorrected(competitor, raceColumn); + boolean isScoreCorrected = leaderboard.getScoreCorrection().isScoreCorrected(competitor, raceColumn, timePoint); return new Triple(updatedEntry.getNetPoints(), updatedEntry.getTotalPoints(), isScoreCorrected); } else { throw new IllegalArgumentException("Didn't find competitor with ID "+competitorIdAsString+" in leaderboard "+getLeaderboardName()); diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateLeaderboardScoreCorrection.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateLeaderboardScoreCorrection.java index 7319800c250..31c073f27e0 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateLeaderboardScoreCorrection.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateLeaderboardScoreCorrection.java @@ -56,7 +56,7 @@ public class UpdateLeaderboardScoreCorrection extends AbstractLeaderboardColumnO newNetPoints = correctedScore; } newTotalPoints = leaderboard.getEntry(competitor, raceColumn, timePoint).getTotalPoints(); - isScoreCorrected = leaderboard.getScoreCorrection().isScoreCorrected(competitor, raceColumn); + isScoreCorrected = leaderboard.getScoreCorrection().isScoreCorrected(competitor, raceColumn, timePoint); } else { throw new IllegalArgumentException("Didn't find competitor with ID "+competitorIdAsString+" in leaderboard "+getLeaderboardName()); } diff --git a/java/com.sap.sailing.www.events/ess40/mobile.html b/java/com.sap.sailing.www.events/ess40/mobile.html index b1592476ea7..7c4b627b278 100644 --- a/java/com.sap.sailing.www.events/ess40/mobile.html +++ b/java/com.sap.sailing.www.events/ess40/mobile.html @@ -23,7 +23,7 @@ Act 7 - Nice, France

- September 2th - 6th + October 2th - 6th