diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/BoatClassMasterdata.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/BoatClassMasterdata.java
index 9eff04e2a83..cad0de6a069 100755
--- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/BoatClassMasterdata.java
+++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/BoatClassMasterdata.java
@@ -30,6 +30,8 @@ public enum BoatClassMasterdata {
BAVARIA_CRUISER_45 ("Bavaria Cruiser 45", true, 14.27, 4.35, BoatHullType.MONOHULL, true, "B45", "B 45", "BAVARIACRUISER45"),
BAVARIA_CRUISER_46 ("Bavaria Cruiser 46", true, 14.27, 4.35, BoatHullType.MONOHULL, true, "B46", "B 46", "BAVARIACRUISER46"),
BB10M ("BB 10m", true, 10.00, 2.30, BoatHullType.MONOHULL, true, "Dansk BB10M klub"),
+ BENETEAU_FIRST_35 ("Benetau First 35", true, 10.66, 3.636, BoatHullType.MONOHULL, true, "First 35"),
+ BENETEAU_FIRST_45 ("Benetau First 45", true, 13.68, 4.202, BoatHullType.MONOHULL, true, "First 45"),
BRASSFAHRT_I ("Brassfahrt I", true, 12.00, 3.50, BoatHullType.MONOHULL, true, "Brassfahrt 1"),
BRASSFAHRT_II ("Brassfahrt II", true, 12.00, 3.50, BoatHullType.MONOHULL, true, "Brassfahrt 2"),
BRASSFAHRT_III ("Brassfahrt III", true, 12.00, 3.50, BoatHullType.MONOHULL, true, "Brassfahrt 3"),
@@ -70,7 +72,7 @@ public enum BoatClassMasterdata {
HOBIE_TIGER ("Hobie Tiger", true, 5.51, 2.60, BoatHullType.CATAMARAN, true),
HOBIE_WILD_CAT ("Hobie Wild Cat", true, 5.49, 2.59, BoatHullType.CATAMARAN, true, "Hobie Wild Cat F18"),
INTERNATIONAL_14("International 14", true, 4.27, 1.83, BoatHullType.MONOHULL, true, "I14", "Int.14", "Int14"),
- IQFOIL_MEN("iQFOil Men", true, 2.20, 0.95, BoatHullType.SURFERBOARD, false, "iQFOil 95 Men"),
+ IQFOIL_MEN("iQFOil Men", true, 2.20, 0.95, BoatHullType.SURFERBOARD, false, "iQFOil 95 Men", "iQF95"),
IQFOIL_WOMEN("iQFOil Women", true, 2.20, 0.95, BoatHullType.SURFERBOARD, false, "iQFOil 95 Women"),
IQFOIL_YOUTH("iQFOil Youth", true, 2.15, 0.85, BoatHullType.SURFERBOARD, false, "iQFOil 85 Youth"),
IRC("IRC", true, 15.00, 4.00, BoatHullType.MONOHULL, false),
diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/LeaderboardType.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/LeaderboardType.java
index 1d987b76b6a..665cb929e5f 100644
--- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/LeaderboardType.java
+++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/LeaderboardType.java
@@ -1,9 +1,12 @@
package com.sap.sailing.domain.common;
public enum LeaderboardType {
- RegattaLeaderboard(false, true), RegattaMetaLeaderboard(true, true),
+ RegattaLeaderboard(false, true),
+ RegattaMetaLeaderboard(true, true),
RegattaLeaderboardWithEliminations(false, true),
- FlexibleLeaderboard(false, false), FlexibleMetaLeaderboard(true, false);
+ RegattaLeaderboardWithOtherTieBreakingLeaderboard(false, true),
+ FlexibleLeaderboard(false, false),
+ FlexibleMetaLeaderboard(true, false);
boolean isRegattaLeaderboard;
boolean isMetaLeaderboard;
diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ScoringSchemeType.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ScoringSchemeType.java
index 0b2c8f26219..1b522e26b8f 100755
--- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ScoringSchemeType.java
+++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ScoringSchemeType.java
@@ -5,5 +5,14 @@ public enum ScoringSchemeType {
LOW_POINT, LOW_POINT_WITH_AUTOMATIC_RDG, HIGH_POINT, HIGH_POINT_ESS_OVERALL,HIGH_POINT_ESS_OVERALL_12, HIGH_POINT_LAST_BREAKS_TIE, HIGH_POINT_FIRST_GETS_TEN,
HIGH_POINT_FIRST_GETS_ONE, LOW_POINT_WINNER_GETS_ZERO, HIGH_POINT_WINNER_GETS_SIX, HIGH_POINT_WINNER_GETS_FIVE, HIGH_POINT_WINNER_GETS_EIGHT,
HIGH_POINT_WINNER_GETS_EIGHT_AND_INTERPOLATION, HIGH_POINT_FIRST_GETS_TEN_OR_EIGHT, HIGH_POINT_FIRST_GETS_TWELVE_OR_EIGHT, HIGH_POINT_FIRST_GETS_TWELVE_OR_EIGHT_2017, LOW_POINT_WITH_ELIMINATIONS_AND_ROUNDS_WINNER_GETS_07,
- LOW_POINT_LEAGUE_OVERALL, HIGH_POINT_MATCH_RACING, LOW_POINT_TIE_BREAK_BASED_ON_LAST_SERIES_ONLY, LOW_POINT_FIRST_TO_WIN_TWO_RACES, LOW_POINT_FIRST_TO_WIN_THREE_RACES
+ LOW_POINT_LEAGUE_OVERALL, HIGH_POINT_MATCH_RACING, LOW_POINT_TIE_BREAK_BASED_ON_LAST_SERIES_ONLY, LOW_POINT_FIRST_TO_WIN_TWO_RACES, LOW_POINT_FIRST_TO_WIN_THREE_RACES,
+ HIGH_POINT_BY_WINS_TIES_LASTLY_BROKEN_BY_OTHER_LEADERBOARD;
+
+ public static double getScaledScore(double columnFactor, double unscaledScore, boolean oneAlwaysStaysOne) {
+ return unscaledScore * columnFactor - (oneAlwaysStaysOne ? columnFactor-1 : 0);
+ }
+
+ public static double getUnscaledScore(double columnFactor, double scaledScore, boolean oneAlwaysStaysOne) {
+ return (scaledScore + (oneAlwaysStaysOne ? columnFactor - 1 : 0)) / columnFactor;
+ }
}
diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java
index 0ab3cfecb31..59955995146 100755
--- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java
+++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java
@@ -36,6 +36,10 @@ public abstract class AbstractLeaderboardDTO extends NamedDTO implements Secured
* Set to the non-null regatta name if this DTO represents a RegattaLeaderboard.
*/
public String regattaName;
+ /**
+ * Set if this DTO represents a {@code RegattaLeaderboardWithOtherTieBreakingLeaderboard}
+ */
+ private String otherTieBreakingLeaderboardName;
public String displayName;
public List courseAreas;
public ScoringSchemeType scoringScheme;
@@ -111,6 +115,14 @@ public abstract class AbstractLeaderboardDTO extends NamedDTO implements Secured
return competitorDisplayNames.get(competitor);
}
}
+
+ public String getOtherTieBreakingLeaderboardName() {
+ return otherTieBreakingLeaderboardName;
+ }
+
+ public void setOtherTieBreakingLeaderboardName(String otherTieBreakingLeaderboardName) {
+ this.otherTieBreakingLeaderboardName = otherTieBreakingLeaderboardName;
+ }
/**
* If the race column whose name is specified in raceColumnName has at least one competitor who has valid
@@ -196,7 +208,6 @@ public abstract class AbstractLeaderboardDTO extends NamedDTO implements Secured
* ensures that a fleet named fleetName is present. If it's not present yet, it's added to the race
* column's fleet name list. The trackedRaceIdentifier and race are associated with the
* column for the fleet identified by fleetName.
- *
* @param explicitFactor
* factor by which to multiply the race column's points for the overall score; if null, the
* default will be determined by whether or not the column is marked as medal race
@@ -212,15 +223,16 @@ public abstract class AbstractLeaderboardDTO extends NamedDTO implements Secured
* {@link RaceColumnInSeriesDTO}
* @param fleetDTO
* must not be null
+ * @param oneAlwaysStaysOne TODO
*/
public RaceColumnDTO addRace(String raceColumnName, Double explicitFactor, double effectiveFactor,
String regattaName, String seriesName, FleetDTO fleetDTO, boolean medalRace,
- RegattaAndRaceIdentifier trackedRaceIdentifier, RaceDTO race, boolean isMetaLeaderboardColumn) {
+ RegattaAndRaceIdentifier trackedRaceIdentifier, RaceDTO race, boolean isMetaLeaderboardColumn, boolean oneAlwaysStaysOne) {
assert fleetDTO != null;
RaceColumnDTO raceColumnDTO = getRaceColumnByName(raceColumnName);
if (raceColumnDTO == null) {
raceColumnDTO = RaceColumnDTOFactory.INSTANCE.createRaceColumnDTO(raceColumnName, medalRace,
- explicitFactor, regattaName, seriesName, isMetaLeaderboardColumn);
+ explicitFactor, regattaName, seriesName, isMetaLeaderboardColumn, oneAlwaysStaysOne);
races.add(raceColumnDTO);
}
raceColumnDTO.setEffectiveFactor(effectiveFactor);
@@ -240,9 +252,9 @@ public abstract class AbstractLeaderboardDTO extends NamedDTO implements Secured
}
public RaceColumnDTO createEmptyRaceColumn(String raceColumnName, boolean medalRace, String regattaName,
- String seriesName, boolean isMetaLeaderboardColumn) {
+ String seriesName, boolean isMetaLeaderboardColumn, boolean oneAlwaysStaysOne) {
final RaceColumnDTO raceColumn = RaceColumnDTOFactory.INSTANCE.createRaceColumnDTO(raceColumnName,
- medalRace, /* explicit factor */ null, regattaName, seriesName, isMetaLeaderboardColumn);
+ medalRace, /* explicit factor */ null, regattaName, seriesName, isMetaLeaderboardColumn, oneAlwaysStaysOne);
races.add(raceColumn);
return raceColumn;
}
@@ -437,6 +449,11 @@ public abstract class AbstractLeaderboardDTO extends NamedDTO implements Secured
return false;
} else if (!getName().equals(other.getName()))
return false;
+ if (getOtherTieBreakingLeaderboardName() == null) {
+ if (other.getOtherTieBreakingLeaderboardName() != null)
+ return false;
+ } else if (!getOtherTieBreakingLeaderboardName().equals(other.getOtherTieBreakingLeaderboardName()))
+ return false;
if (races == null) {
if (other.races != null)
return false;
diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/MetaLeaderboardRaceColumnDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/MetaLeaderboardRaceColumnDTO.java
index 11dab2ba77b..4a14f3d7739 100644
--- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/MetaLeaderboardRaceColumnDTO.java
+++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/MetaLeaderboardRaceColumnDTO.java
@@ -7,7 +7,7 @@ public class MetaLeaderboardRaceColumnDTO extends RaceColumnDTO {
MetaLeaderboardRaceColumnDTO() {} // for GWT RPC serialization only
public MetaLeaderboardRaceColumnDTO(String name) {
- super(name);
+ super(name, /* oneAlwaysStaysOne */ false);
}
private static final long serialVersionUID = 6152752963316150432L;
diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTO.java
index dc0db35bd45..f6209459bce 100755
--- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTO.java
+++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTO.java
@@ -23,6 +23,7 @@ public class RaceColumnDTO extends NamedDTO implements Serializable {
private Map racesPerFleet;
private Double explicitFactor;
private double effectiveFactor;
+ private boolean oneAlwaysStaysOne;
private Map raceLogTrackingInfos;
public enum RaceColumnLiveState { NOT_TRACKED, TRACKED, TRACKED_AND_LIVE };
@@ -30,12 +31,18 @@ public class RaceColumnDTO extends NamedDTO implements Serializable {
@Deprecated
RaceColumnDTO() {} // for GWT RPC serialization only
- public RaceColumnDTO(String name) {
+ /**
+ * @param oneAlwaysStaysOne
+ * tells whether when scaling results with the {@link #getEffectiveFactor() effective column factor}, the
+ * 1.0 score shall always remain 1.0.
+ */
+ public RaceColumnDTO(String name, boolean oneAlwaysStaysOne) {
super(name);
trackedRaceIdentifiersPerFleet = new HashMap();
raceLogTrackingInfos = new HashMap();
racesPerFleet = new HashMap();
fleets = new ArrayList();
+ this.oneAlwaysStaysOne = oneAlwaysStaysOne;
}
public RaceColumnLiveState getLiveState(long serverTimePointAsMillis) {
@@ -59,6 +66,10 @@ public class RaceColumnDTO extends NamedDTO implements Serializable {
public void setExplicitFactor(Double explicitFactor) {
this.explicitFactor = explicitFactor;
}
+
+ public boolean isOneAlwaysStaysOne() {
+ return oneAlwaysStaysOne;
+ }
public boolean hasTrackedRace(RaceIdentifier raceIdentifier) {
return trackedRaceIdentifiersPerFleet.values().contains(raceIdentifier);
diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTOFactory.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTOFactory.java
index 47df2bbce1c..0b8136bd748 100755
--- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTOFactory.java
+++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTOFactory.java
@@ -10,14 +10,21 @@ public class RaceColumnDTOFactory {
* when null, a regular {@link RaceColumnDTO} or {@link MetaLeaderboardRaceColumnDTO} will
* be produced (depending on isMetaLeaderboardColumn) and initialized from the properties
* passed; otherwise, a {@link RaceColumnInSeriesDTO} will be created.
+ * @param oneAlwaysStaysOne
+ * When scores in this column are scaled by some factor, either based on the {@link #getExplicitFactor()
+ * explicit factor} set for this column, or implicitly, e.g., because the {@link ScoringScheme} mandates
+ * the doubling of medal race scores and this column {@link #isMedalRace() represents a medal race}, then
+ * some configurations still want the 1.0 score still to be 1.0. For example, with a column factor of 2.0
+ * scores 1, 2, 3 would end up as 1, 3, 5; or with a column factor of 3.0 scores 1, 2, 3 would end up as
+ * 1, 4, 7. This method tells whether this column shall apply such a scheme.
*/
public RaceColumnDTO createRaceColumnDTO(String columnName, boolean isMedal, Double explicitFactor,
- String regattaName, String seriesName, boolean isMetaLeaderboardColumn) {
+ String regattaName, String seriesName, boolean isMetaLeaderboardColumn, boolean oneAlwaysStaysOne) {
final RaceColumnDTO raceColumnDTO;
if (seriesName != null) {
- raceColumnDTO = new RaceColumnInSeriesDTO(columnName, seriesName, regattaName);
+ raceColumnDTO = new RaceColumnInSeriesDTO(columnName, seriesName, regattaName, oneAlwaysStaysOne);
} else {
- raceColumnDTO = isMetaLeaderboardColumn ? new MetaLeaderboardRaceColumnDTO(columnName) : new RaceColumnDTO(columnName);
+ raceColumnDTO = isMetaLeaderboardColumn ? new MetaLeaderboardRaceColumnDTO(columnName) : new RaceColumnDTO(columnName, oneAlwaysStaysOne);
}
fillRaceColumnDTO(raceColumnDTO, isMedal, explicitFactor);
return raceColumnDTO;
diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnInSeriesDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnInSeriesDTO.java
index bdd6720bde7..fb269d1b7aa 100644
--- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnInSeriesDTO.java
+++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnInSeriesDTO.java
@@ -8,8 +8,8 @@ public class RaceColumnInSeriesDTO extends RaceColumnDTO {
@Deprecated
RaceColumnInSeriesDTO() {} // for GWT serialization
- public RaceColumnInSeriesDTO(String name, String seriesName, String regattaName) {
- super(name);
+ public RaceColumnInSeriesDTO(String name, String seriesName, String regattaName, boolean oneAlwaysStaysOne) {
+ super(name, oneAlwaysStaysOne);
this.seriesName = seriesName;
this.regattaName = regattaName;
}
diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/SeriesCreationParametersDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/SeriesCreationParametersDTO.java
index e3e761c4d2f..9c4c0a179a9 100755
--- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/SeriesCreationParametersDTO.java
+++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/SeriesCreationParametersDTO.java
@@ -24,10 +24,12 @@ public class SeriesCreationParametersDTO implements Serializable {
private Integer maximumNumberOfDiscards;
+ private boolean oneAlwaysStaysOne;
+
SeriesCreationParametersDTO() {}
public SeriesCreationParametersDTO(List fleets, boolean isMedal, boolean isFleetsCanRunInParallel, boolean isStartsWithZeroScore, boolean firstColumnIsNonDiscardableCarryForward,
- int[] discardingThresholds, boolean hasSplitFleetContiguousScoring, boolean hasCrossFleetMergedRanking, Integer maximumNumberOfDiscards) {
+ int[] discardingThresholds, boolean hasSplitFleetContiguousScoring, boolean hasCrossFleetMergedRanking, Integer maximumNumberOfDiscards, boolean oneAlwaysStaysOne) {
super();
this.fleets = fleets;
this.isMedal = isMedal;
@@ -38,6 +40,7 @@ public class SeriesCreationParametersDTO implements Serializable {
this.firstColumnIsNonDiscardableCarryForward = firstColumnIsNonDiscardableCarryForward;
this.discardingThresholds = discardingThresholds;
this.maximumNumberOfDiscards = maximumNumberOfDiscards;
+ this.oneAlwaysStaysOne = oneAlwaysStaysOne;
}
public List getFleets() {
@@ -75,4 +78,8 @@ public class SeriesCreationParametersDTO implements Serializable {
public Integer getMaximumNumberOfDiscards() {
return maximumNumberOfDiscards;
}
+
+ public boolean isOneAlwaysStaysOne() {
+ return oneAlwaysStaysOne;
+ }
}
diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/FieldNames.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/FieldNames.java
index 3f55109099f..75fae49f4c7 100644
--- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/FieldNames.java
+++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/FieldNames.java
@@ -50,6 +50,7 @@ public enum FieldNames {
SERIES_HAS_SPLIT_FLEET_CONTIGUOUS_SCORING,
SERIES_HAS_CROSS_FLEET_MERGED_RANKING,
SERIES_STARTS_WITH_NON_DISCARDABLE_CARRY_FORWARD,
+ SERIES_ONE_ALWAYS_STAYS_ONE,
SERIES_FLEETS,
SERIES_RACE_COLUMNS,
SERIES_DISCARDING_THRESHOLDS,
@@ -88,7 +89,7 @@ public enum FieldNames {
LEADERBOARD_SCORE_CORRECTIONS, LEADERBOARD_DISCARDING_THRESHOLDS,
LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON, LEADERBOARD_CORRECTED_SCORE, LEADERBOARD_SCORE_CORRECTION_TIMESTAMP,
LEADERBOARD_RANK, LEADERBOARD_SCORE_CORRECTION_COMMENT, LEADERBOARD_SCORE_CORRECTION_MERGE_STATE,
- LEADERBOARD_COLUMN_FACTORS, WRAPPED_REGATTA_LEADERBOARD_NAME,
+ LEADERBOARD_COLUMN_FACTORS, WRAPPED_REGATTA_LEADERBOARD_NAME, OTHER_TIEBREAKING_LEADERBOARD_NAME,
ELMINATED_COMPETITORS,
// leaderboard group
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 d22e3dfd8a7..d57538834b2 100644
--- 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
@@ -233,6 +233,7 @@ import com.sap.sailing.domain.leaderboard.impl.DelegatingRegattaLeaderboardWithC
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.RegattaLeaderboardWithOtherTieBreakingLeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl;
import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
@@ -491,7 +492,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
result = leaderboardRegistry.getLeaderboardByName(leaderboardName);
}
if (result == null) {
- String wrappedRegattaLeaderboardName = (String) dbLeaderboard
+ final String wrappedRegattaLeaderboardName = (String) dbLeaderboard
.get(FieldNames.WRAPPED_REGATTA_LEADERBOARD_NAME.name());
if (wrappedRegattaLeaderboardName != null) {
result = loadRegattaLeaderboardWithEliminations(dbLeaderboard, leaderboardName,
@@ -510,7 +511,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
result = loadFlexibleLeaderboard(dbLeaderboard, resultDiscardingRule);
} else {
result = loadRegattaLeaderboard(leaderboardName, regattaName, dbLeaderboard,
- resultDiscardingRule, regattaRegistry);
+ resultDiscardingRule, regattaRegistry, leaderboardRegistry);
}
}
if (result != null) {
@@ -590,14 +591,21 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
*/
private RegattaLeaderboard loadRegattaLeaderboard(String leaderboardName, String regattaName,
Document dbLeaderboard, ThresholdBasedResultDiscardingRule resultDiscardingRule,
- RegattaRegistry regattaRegistry) {
- RegattaLeaderboard result = null;
+ RegattaRegistry regattaRegistry, LeaderboardRegistry leaderboardRegistry) {
+ final RegattaLeaderboard result;
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.");
+ result = null;
} else {
- result = new RegattaLeaderboardImpl(regatta, resultDiscardingRule);
+ final String otherTieBreakingLeaderboardName = (String) dbLeaderboard.get(FieldNames.OTHER_TIEBREAKING_LEADERBOARD_NAME.name());
+ if (otherTieBreakingLeaderboardName == null) {
+ result = new RegattaLeaderboardImpl(regatta, resultDiscardingRule);
+ } else {
+ result = new RegattaLeaderboardWithOtherTieBreakingLeaderboardImpl(regatta, resultDiscardingRule,
+ () -> (RegattaLeaderboard) leaderboardRegistry.getLeaderboardByName(otherTieBreakingLeaderboardName));
+ }
}
return result;
}
@@ -1426,13 +1434,15 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
final Number maximumNumberOfDiscardsAsObject = (Number) dbSeries
.get(FieldNames.SERIES_MAXIMUM_NUMBER_OF_DISCARDS.name());
final Integer maximumNumberOfDiscards = maximumNumberOfDiscardsAsObject == null ? null : maximumNumberOfDiscardsAsObject.intValue();
- Boolean startsWithZeroScore = (Boolean) dbSeries.get(FieldNames.SERIES_STARTS_WITH_ZERO_SCORE.name());
- Boolean hasSplitFleetContiguousScoring = (Boolean) dbSeries
+ final Boolean startsWithZeroScore = (Boolean) dbSeries.get(FieldNames.SERIES_STARTS_WITH_ZERO_SCORE.name());
+ final Boolean hasSplitFleetContiguousScoring = (Boolean) dbSeries
.get(FieldNames.SERIES_HAS_SPLIT_FLEET_CONTIGUOUS_SCORING.name());
- Boolean hasCrossFleetMergedRankingObject = (Boolean) dbSeries
+
+ final Boolean hasCrossFleetMergedRankingObject = (Boolean) dbSeries
.get(FieldNames.SERIES_HAS_CROSS_FLEET_MERGED_RANKING.name());
- Boolean firstColumnIsNonDiscardableCarryForward = (Boolean) dbSeries
+ final Boolean firstColumnIsNonDiscardableCarryForward = (Boolean) dbSeries
.get(FieldNames.SERIES_STARTS_WITH_NON_DISCARDABLE_CARRY_FORWARD.name());
+ final Boolean oneAlwaysStaysOne = (Boolean) dbSeries.get(FieldNames.SERIES_ONE_ALWAYS_STAYS_ONE.name());
@SuppressWarnings("unchecked")
final Iterable dbFleets = (Iterable) dbSeries.get(FieldNames.SERIES_FLEETS.name());
List fleets = loadFleets(dbFleets);
@@ -1459,6 +1469,9 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
if (firstColumnIsNonDiscardableCarryForward != null) {
series.setFirstColumnIsNonDiscardableCarryForward(firstColumnIsNonDiscardableCarryForward);
}
+ if (oneAlwaysStaysOne != null) {
+ series.setOneAlwaysStaysOne(oneAlwaysStaysOne);
+ }
loadRaceColumnRaceLinks(dbRaceColumns, series);
return series;
}
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 ec681e0709d..cab59630d56 100644
--- 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
@@ -122,6 +122,7 @@ import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
import com.sap.sailing.domain.leaderboard.RegattaLeaderboardWithEliminations;
+import com.sap.sailing.domain.leaderboard.RegattaLeaderboardWithOtherTieBreakingLeaderboard;
import com.sap.sailing.domain.leaderboard.ResultDiscardingRule;
import com.sap.sailing.domain.leaderboard.SettableScoreCorrection;
import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
@@ -399,6 +400,10 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
private void storeRegattaLeaderboard(RegattaLeaderboard leaderboard, Document dbLeaderboard) {
dbLeaderboard.put(FieldNames.REGATTA_NAME.name(), leaderboard.getRegatta().getName());
+ if (leaderboard instanceof RegattaLeaderboardWithOtherTieBreakingLeaderboard) {
+ dbLeaderboard.put(FieldNames.OTHER_TIEBREAKING_LEADERBOARD_NAME.name(),
+ ((RegattaLeaderboardWithOtherTieBreakingLeaderboard) leaderboard).getOtherTieBreakingLeaderboard().getName());
+ }
}
private void storeFlexibleLeaderboard(FlexibleLeaderboard leaderboard, Document dbLeaderboard) {
@@ -799,6 +804,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
dbSeries.put(FieldNames.SERIES_HAS_CROSS_FLEET_MERGED_RANKING.name(), s.hasCrossFleetMergedRanking());
dbSeries.put(FieldNames.SERIES_STARTS_WITH_ZERO_SCORE.name(), s.isStartsWithZeroScore());
dbSeries.put(FieldNames.SERIES_STARTS_WITH_NON_DISCARDABLE_CARRY_FORWARD.name(), s.isFirstColumnIsNonDiscardableCarryForward());
+ dbSeries.put(FieldNames.SERIES_ONE_ALWAYS_STAYS_ONE.name(), s.isOneAlwaysStaysOne());
BasicDBList dbFleets = new BasicDBList();
for (Fleet fleet : s.getFleets()) {
dbFleets.add(storeFleet(fleet));
diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java
index 5f5db19d233..c63aecd6d25 100755
--- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java
+++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java
@@ -410,7 +410,7 @@ public class LeaderboardDTODiffingTest {
public void testPartialRaceColumnDTOCompaction() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
// create a modified R9 RaceDTO clone in newVersion to make sure that even changing a property in the RaceDTO will keep the RaceColumnDTO from being omitted
RaceColumnDTO r9 = newVersion.getRaceColumnByName("R9");
- RaceColumnDTO clonedR9 = new RaceColumnDTO("R9");
+ RaceColumnDTO clonedR9 = new RaceColumnDTO("R9", /* oneAlwaysStaysOne */ false);
cloner.clone(r9, clonedR9);
// also clone the racesPerFleet map, or else we'd be modifying the previous version's one too
final Field racesPerFleetField = clonedR9.getClass().getDeclaredField("racesPerFleet");
diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/ScoringSchemeTypeScoreScalingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/ScoringSchemeTypeScoreScalingTest.java
new file mode 100644
index 00000000000..f0f1be0f04e
--- /dev/null
+++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/ScoringSchemeTypeScoreScalingTest.java
@@ -0,0 +1,49 @@
+package com.sap.sailing.domain.common.test;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import com.sap.sailing.domain.common.ScoringSchemeType;
+
+public class ScoringSchemeTypeScoreScalingTest {
+ private static final double DELTA = 0.0000001;
+
+ @Test
+ public void testScalingThreeWithThree() {
+ testScalingAndUnscaling(/* unscaled */ 3, /* factor */ 3, /* scaled */ 9, /* oneAlwaysStaysOne */ false);
+ }
+
+ @Test
+ public void testScalingOneWithThree() {
+ testScalingAndUnscaling(/* unscaled */ 1, /* factor */ 3, /* scaled */ 3, /* oneAlwaysStaysOne */ false);
+ }
+
+ @Test
+ public void testScalingThreeWithTwo() {
+ testScalingAndUnscaling(/* unscaled */ 3, /* factor */ 2, /* scaled */ 6, /* oneAlwaysStaysOne */ false);
+ }
+
+ @Test
+ public void testScalingOneWithTwo() {
+ testScalingAndUnscaling(/* unscaled */ 1, /* factor */ 2, /* scaled */ 2, /* oneAlwaysStaysOne */ false);
+ }
+
+ @Test
+ public void testScalingWithThreeWithOneStaysOne() {
+ testScalingAndUnscaling(/* unscaled */ 3, /* factor */ 3, /* scaled */ 7, /* oneAlwaysStaysOne */ true);
+ testScalingAndUnscaling(/* unscaled */ 1, /* factor */ 3, /* scaled */ 1, /* oneAlwaysStaysOne */ true);
+ }
+
+ @Test
+ public void testScalingWithTwoWithOneStaysOne() {
+ testScalingAndUnscaling(/* unscaled */ 3, /* factor */ 2, /* scaled */ 5, /* oneAlwaysStaysOne */ true);
+ testScalingAndUnscaling(/* unscaled */ 1, /* factor */ 2, /* scaled */ 1, /* oneAlwaysStaysOne */ true);
+ }
+
+ private void testScalingAndUnscaling(final double unscaled, final double factor, final double scaled,
+ final boolean oneAlwaysStaysOne) {
+ assertEquals(scaled, ScoringSchemeType.getScaledScore(factor, unscaled, oneAlwaysStaysOne), DELTA);
+ assertEquals(unscaled, ScoringSchemeType.getUnscaledScore(factor, scaled, oneAlwaysStaysOne), DELTA);
+ }
+}
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 847e90fc4d4..5b72025e4e2 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
@@ -59,7 +59,6 @@ import com.sap.sailing.domain.common.dto.LeaderboardDTO;
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
-import com.sap.sailing.domain.leaderboard.impl.DelegatingRegattaLeaderboardWithCompetitorElimination;
import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.HighPoint;
import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOverall;
@@ -87,11 +86,6 @@ import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.shared.util.impl.ArrayListNavigableSet;
public class LeaderboardScoringAndRankingTest extends LeaderboardScoringAndRankingTestBase {
- protected DelegatingRegattaLeaderboardWithCompetitorElimination createDelegatingRegattaLeaderboardWithCompetitorElimination(
- Regatta regatta, String leaderboardName, int[] discardingThresholds) {
- return new DelegatingRegattaLeaderboardWithCompetitorElimination(()->createLeaderboard(regatta, discardingThresholds), leaderboardName);
- }
-
@Test
public void testOneStartedRaceWithDifferentScores() throws NoWindException {
List competitors = createCompetitors(10);
diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTestForLowPoints.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTestForLowPoints.java
index d28c45afd9b..22829e179f9 100644
--- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTestForLowPoints.java
+++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTestForLowPoints.java
@@ -23,7 +23,6 @@ import com.sap.sailing.domain.common.CompetitorRegistrationType;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.ScoringSchemeType;
import com.sap.sailing.domain.leaderboard.Leaderboard;
-import com.sap.sailing.domain.leaderboard.impl.DelegatingRegattaLeaderboardWithCompetitorElimination;
import com.sap.sailing.domain.leaderboard.impl.LowPointFirstToWinTwoRaces;
import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithStartTimeAndRanks;
@@ -42,12 +41,6 @@ import com.sap.sse.common.impl.MillisecondsTimePoint;
public class LeaderboardScoringAndRankingTestForLowPoints extends LeaderboardScoringAndRankingTestBase {
private static final double EPSILON = 0.000001;
- protected DelegatingRegattaLeaderboardWithCompetitorElimination createDelegatingRegattaLeaderboardWithCompetitorElimination(
- Regatta regatta, String leaderboardName, int[] discardingThresholds) {
- return new DelegatingRegattaLeaderboardWithCompetitorElimination(
- () -> createLeaderboard(regatta, discardingThresholds), leaderboardName);
- }
-
private void executePreSeries(List yellow, List blue, TimePoint now) {
RaceColumn qColumn = series.get(0).getRaceColumnByName("Q");
TrackedRace qYellow = new MockedTrackedRaceWithStartTimeAndRanks(now, yellow);
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java
index 0db1b5f6e63..3b89d7e728b 100644
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java
@@ -11,6 +11,7 @@ import com.sap.sailing.domain.common.abstractlog.NotRevokableException;
import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.MetaLeaderboard;
+import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
import com.sap.sailing.domain.racelog.RaceLogStore;
import com.sap.sailing.domain.regattalike.RegattaLikeIdentifier;
@@ -195,10 +196,20 @@ public interface RaceColumn extends Named {
void setFactor(Double factor);
/**
- * If null, the {@link #getFactor() factor} defaults to 1 for non-medal and {@link #DEFAULT_MEDAL_RACE_FACTOR} for
- * medal races. Otherwise, the explicit factor is used.
+ * {@link ScoringScheme}s shall prefer this explicit factor, if not null, and otherwise determine a default
+ * based on the rules of the scoring scheme, e.g., defaulting to 1 for non-medal and {@link #DEFAULT_MEDAL_RACE_FACTOR} for
+ * medal races, or similar.
*/
Double getExplicitFactor();
+
+ /**
+ * When scores in this column are scaled by some factor, either based on the {@link #getExplicitFactor() explicit factor}
+ * set for this column, or implicitly, e.g., because the {@link ScoringScheme} mandates the doubling of medal race scores
+ * and this column {@link #isMedalRace() represents a medal race}, then some configurations still want the 1.0 score still
+ * to be 1.0. For example, with a column factor of 2.0 scores 1, 2, 3 would end up as 1, 3, 5; or with a column factor of
+ * 3.0 scores 1, 2, 3 would end up as 1, 4, 7. This method tells whether this column shall apply such a scheme.
+ */
+ boolean isOneAlwaysStaysOne();
/**
* Returns the race log identifier associated with this fleet and race log
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumnListener.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumnListener.java
index 8c93db7610e..aac3c7f17f0 100755
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumnListener.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumnListener.java
@@ -25,6 +25,8 @@ public interface RaceColumnListener extends Serializable {
void hasCrossFleetMergedRankingChanged(RaceColumn raceColumn, boolean hasCrossFleetMergedRanking);
+ void oneAlwaysStaysOneChanged(RaceColumn raceColumn, boolean oneAlwaysStaysOne);
+
default boolean canAddRaceColumnToContainer(RaceColumn raceColumn) {
return true;
}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Series.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Series.java
index cdff73ba048..68fa98a8147 100755
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Series.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Series.java
@@ -1,5 +1,6 @@
package com.sap.sailing.domain.base;
+import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.TrackedRegatta;
@@ -108,6 +109,9 @@ public interface Series extends SeriesBase {
*/
boolean isStartsWithZeroScore();
+ /**
+ * @see #isStartsWithZeroScore()
+ */
void setStartsWithZeroScore(boolean startsWithZeroScore);
boolean isFirstColumnIsNonDiscardableCarryForward();
@@ -122,6 +126,9 @@ public interface Series extends SeriesBase {
*/
boolean hasSplitFleetContiguousScoring();
+ /**
+ * @see #hasSplitFleetContiguousScoring()
+ */
void setSplitFleetContiguousScoring(boolean hasSplitFleetScore);
/**
@@ -135,4 +142,18 @@ public interface Series extends SeriesBase {
void setCrossFleetMergedRanking(boolean hasCrossFleetMergedRanking);
+ /**
+ * When scores in this series are scaled by some factor, either based on an {@link RaceColumn#getExplicitFactor()
+ * explicit column factor}, or implicitly, e.g., because the {@link ScoringScheme} mandates the
+ * doubling of medal race scores and this series {@link #isMedal() represents a medal series}, then some
+ * configurations still want the 1.0 score still to be 1.0. For example, with a column factor of 2.0 scores 1, 2, 3
+ * would end up as 1, 3, 5; or with a column factor of 3.0 scores 1, 2, 3 would end up as 1, 4, 7. This method tells
+ * whether this column shall apply such a scheme.
+ */
+ boolean isOneAlwaysStaysOne();
+
+ /**
+ * @see #isOneAlwaysStaysOne()
+ */
+ void setOneAlwaysStaysOne(boolean oneAlwaysStaysOne);
}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java
index 3576fa1110c..6b3f43e23da 100755
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java
@@ -42,6 +42,7 @@ import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.leaderboard.impl.HighPoint;
+import com.sap.sailing.domain.leaderboard.impl.HighPointByWinsTiesLastlyBrokenByOtherLeaderboard;
import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOverall;
import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOverall12PointsMax;
import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets10LastBreaksTie;
@@ -155,6 +156,8 @@ public class DomainFactoryImpl extends SharedDomainFactoryImplfalse which is also the default.
*/
private boolean hasSplitFleetContiguousScoring;
-
+
/**
* When a column has more than one fleet there are two different options for scoring it when the fleets are of the
* same rank. Either the scoring scheme is applied to both fleets at the same time and competitors compete across
@@ -79,8 +80,8 @@ public class SeriesImpl extends RenamableImpl implements Series, RaceColumnListe
* the column as many times as there are fleets in the column. For the latter case, this field is false
* which is also the default.
*/
- private boolean hasCrossFleetMergedRanking;
-
+ private boolean hasCrossFleetMergedRanking;
+
/**
* @param fleets
* must be non-empty
@@ -106,7 +107,7 @@ public class SeriesImpl extends RenamableImpl implements Series, RaceColumnListe
Collections.sort(fleetsInAscendingOrder);
this.raceColumns = new ArrayList();
this.isMedal = isMedal;
- this.isFleetsCanRunInParallel = isFleetsCanRunInParallel;
+ this.isFleetsCanRunInParallel = isFleetsCanRunInParallel;
this.raceColumnListeners = new RaceColumnListeners();
for (String raceColumnName : raceColumnNames) {
addRaceColumn(raceColumnName, trackedRegattaRegistry);
@@ -122,7 +123,7 @@ public class SeriesImpl extends RenamableImpl implements Series, RaceColumnListe
public void removeRaceColumnListener(RaceColumnListener listener) {
raceColumnListeners.removeRaceColumnListener(listener);
}
-
+
@Override
public Regatta getRegatta() {
return regatta;
@@ -167,7 +168,7 @@ public class SeriesImpl extends RenamableImpl implements Series, RaceColumnListe
public RaceColumnInSeries addRaceColumn(String raceColumnName, TrackedRegattaRegistry trackedRegattaRegistry) {
return addRaceColumn(raceColumns.size(), raceColumnName, trackedRegattaRegistry);
}
-
+
@Override
public RaceColumnInSeries addRaceColumn(int insertIndex, String raceColumnName, TrackedRegattaRegistry trackedRegattaRegistry) {
RaceColumnInSeriesImpl result = createRaceColumn(raceColumnName, trackedRegattaRegistry);
@@ -191,11 +192,11 @@ public class SeriesImpl extends RenamableImpl implements Series, RaceColumnListe
*/
private RaceColumnInSeriesImpl createRaceColumn(String raceColumnName, TrackedRegattaRegistry trackedRegattaRegistry) {
return new RaceColumnInSeriesImpl(
- raceColumnName,
- this,
+ raceColumnName,
+ this,
trackedRegattaRegistry);
}
-
+
private void attachRaceExecutionOrderProviderToTrackedRacesInRaceColumns() {
for (RaceColumnInSeries raceColumnInSeries : raceColumns) {
for (Fleet fleet : raceColumnInSeries.getFleets()) {
@@ -206,7 +207,7 @@ public class SeriesImpl extends RenamableImpl implements Series, RaceColumnListe
}
}
}
-
+
private void detachRaceExecutionOrderProviderFromTrackedRacesInRaceColumns() {
for (RaceColumnInSeries raceColumnInSeries : raceColumns) {
for (Fleet fleet : raceColumnInSeries.getFleets()) {
@@ -334,6 +335,11 @@ public class SeriesImpl extends RenamableImpl implements Series, RaceColumnListe
raceColumnListeners.notifyListenersAboutFactorChanged(raceColumn, oldFactor, newFactor);
}
+ @Override
+ public void oneAlwaysStaysOneChanged(RaceColumn raceColumn, boolean oneAlwaysStaysOne) {
+ raceColumnListeners.notifyListenersAboutOneAlwaysStaysOneChanged(raceColumn, oneAlwaysStaysOne);
+ }
+
@Override
public void competitorDisplayNameChanged(Competitor competitor, String oldDisplayName, String displayName) {
raceColumnListeners.notifyListenersAboutCompetitorDisplayNameChanged(competitor, oldDisplayName, displayName);
@@ -409,13 +415,13 @@ public class SeriesImpl extends RenamableImpl implements Series, RaceColumnListe
}
return result;
}
-
+
@Override
public void setStartsWithZeroScore(boolean startsWithZeroScore) {
boolean oldStartsWithZeroScore = this.startsWithZeroScore;
if (oldStartsWithZeroScore != startsWithZeroScore) {
this.startsWithZeroScore = startsWithZeroScore;
- RaceColumn firstRaceColumnInSeries = getFirstRaceColumn();
+ final RaceColumn firstRaceColumnInSeries = getFirstRaceColumn();
if (firstRaceColumnInSeries != null) {
raceColumnListeners.notifyListenersAboutIsStartsWithZeroScoreChanged(firstRaceColumnInSeries, startsWithZeroScore);
}
@@ -441,7 +447,7 @@ public class SeriesImpl extends RenamableImpl implements Series, RaceColumnListe
}
}
}
-
+
@Override
public boolean isFirstColumnIsNonDiscardableCarryForward() {
return firstColumnIsNonDiscardableCarryForward;
@@ -452,7 +458,7 @@ public class SeriesImpl extends RenamableImpl implements Series, RaceColumnListe
boolean oldFirstColumnIsNonDiscardableCarryForward = this.firstColumnIsNonDiscardableCarryForward;
if (oldFirstColumnIsNonDiscardableCarryForward != firstColumnIsNonDiscardableCarryForward) {
this.firstColumnIsNonDiscardableCarryForward = firstColumnIsNonDiscardableCarryForward;
- RaceColumn firstRaceColumnInSeries = getFirstRaceColumn();
+ final RaceColumn firstRaceColumnInSeries = getFirstRaceColumn();
if (firstRaceColumnInSeries != null) {
raceColumnListeners.notifyListenersAboutIsFirstColumnIsNonDiscardableCarryForwardChanged(firstRaceColumnInSeries, firstColumnIsNonDiscardableCarryForward);
}
@@ -469,4 +475,20 @@ public class SeriesImpl extends RenamableImpl implements Series, RaceColumnListe
public boolean hasCrossFleetMergedRanking() {
return hasCrossFleetMergedRanking;
}
+
+ @Override
+ public boolean isOneAlwaysStaysOne() {
+ return oneAlwaysStaysOne;
+ }
+
+ @Override
+ public void setOneAlwaysStaysOne(boolean oneAlwaysStaysOne) {
+ boolean oldOneAlwaysStaysOne = this.oneAlwaysStaysOne;
+ if (oldOneAlwaysStaysOne != oneAlwaysStaysOne) {
+ this.oneAlwaysStaysOne = oneAlwaysStaysOne;
+ for (RaceColumn raceColumn : getRaceColumns()) {
+ raceColumnListeners.notifyListenersAboutOneAlwaysStaysOneChanged(raceColumn, oneAlwaysStaysOne);
+ }
+ }
+ }
}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/AbstractScoreCorrectionListenerWithDefaultAction.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/AbstractScoreCorrectionListenerWithDefaultAction.java
new file mode 100644
index 00000000000..109bc3ae9aa
--- /dev/null
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/AbstractScoreCorrectionListenerWithDefaultAction.java
@@ -0,0 +1,44 @@
+package com.sap.sailing.domain.leaderboard;
+
+import com.sap.sailing.domain.base.Competitor;
+import com.sap.sailing.domain.base.RaceColumn;
+import com.sap.sailing.domain.common.MaxPointsReason;
+import com.sap.sse.common.TimePoint;
+
+public abstract class AbstractScoreCorrectionListenerWithDefaultAction implements ScoreCorrectionListener {
+
+ @Override
+ public void correctedScoreChanged(Competitor competitor, RaceColumn raceColumn, Double oldCorrectedScore,
+ Double newCorrectedScore) {
+ defaultAction();
+ }
+
+ @Override
+ public void maxPointsReasonChanged(Competitor competitor, RaceColumn raceColumn, MaxPointsReason oldMaxPointsReason,
+ MaxPointsReason newMaxPointsReason) {
+ defaultAction();
+ }
+
+ @Override
+ public void carriedPointsChanged(Competitor competitor, Double oldCarriedPoints, Double newCarriedPoints) {
+ defaultAction();
+ }
+
+ @Override
+ public void isSuppressedChanged(Competitor competitor, boolean newIsSuppressed) {
+ defaultAction();
+ }
+
+ @Override
+ public void timePointOfLastCorrectionsValidityChanged(TimePoint oldTimePointOfLastCorrectionsValidity,
+ TimePoint newTimePointOfLastCorrectionsValidity) {
+ defaultAction();
+ }
+
+ @Override
+ public void commentChanged(String oldComment, String newComment) {
+ defaultAction();
+ }
+
+ abstract protected void defaultAction();
+}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/FlexibleRaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/FlexibleRaceColumn.java
index 5bd22ab3b8b..7e80866dc2e 100755
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/FlexibleRaceColumn.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/FlexibleRaceColumn.java
@@ -6,5 +6,14 @@ import com.sap.sse.common.Renamable;
public interface FlexibleRaceColumn extends RaceColumn, Renamable {
void setIsMedalRace(boolean isMedalRace);
+
void setRegattaLikeHelper(IsRegattaLike regattaLikeHelper);
+
+ /**
+ * Flexible race columns always apply scoring factors linearly and regularly.
+ */
+ @Override
+ default boolean isOneAlwaysStaysOne() {
+ return false;
+ }
}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java
index 79bb92e3ec0..e603e9a9240 100644
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java
@@ -465,7 +465,7 @@ public interface Leaderboard extends LeaderboardBase, HasRaceColumns {
* Returns the total rank of the given competitor or {@code 0} if no rank can be determined for
* the {@code competitor} in this leaderboard.
*/
- int getTotalRankOfCompetitor(Competitor competitor, TimePoint timePoint) throws NoWindException;
+ int getTotalRankOfCompetitor(Competitor competitor, TimePoint timePoint);
/**
* Fetches all entries for all competitors of all races tracked by this leaderboard in one sweep. This saves some
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java
index eed2da720d6..f3c9813ad16 100755
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java
@@ -20,21 +20,19 @@ import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnListener;
import com.sap.sailing.domain.base.WithNationality;
import com.sap.sailing.domain.base.impl.RaceColumnListenerWithDefaultAction;
-import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.leaderboard.caching.LeaderboardCache;
import com.sap.sailing.domain.tracking.RaceChangeListener;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
-import com.sap.sse.common.TimePoint;
import com.sap.sse.concurrent.ConcurrentWeakHashMap;
import com.sap.sse.concurrent.LockUtil;
import com.sap.sse.concurrent.NamedReentrantReadWriteLock;
/**
* Manages a {@link LeaderboardCache}. When a {@link Leaderboard} is {@link LeaderboardCache#add added} to the cache, it
- * start observing the leaderboard for changes through the linked {@link TrackedRace}s as a {@link RaceChangeListener}
+ * starts observing the leaderboard for changes through the linked {@link TrackedRace}s as a {@link RaceChangeListener}
* and through the race columns as a {@link RaceColumnListener}. When changes affecting a leaderboard occur, the
* {@link LeaderboardCache#removeFromCache(Leaderboard)} method is called on the leaderboard cache.
*
@@ -200,7 +198,7 @@ public class LeaderboardCacheManager {
}
}
- private class CacheInvalidationUponScoreCorrectionListener implements ScoreCorrectionListener {
+ private class CacheInvalidationUponScoreCorrectionListener extends AbstractScoreCorrectionListenerWithDefaultAction {
private final Leaderboard leaderboard;
public CacheInvalidationUponScoreCorrectionListener(Leaderboard leaderboard) {
@@ -208,34 +206,7 @@ public class LeaderboardCacheManager {
}
@Override
- public void correctedScoreChanged(Competitor competitor, RaceColumn raceColumn, Double oldCorrectedScore, Double newCorrectedScore) {
- removeFromCache(leaderboard);
- }
-
- @Override
- public void maxPointsReasonChanged(Competitor competitor, RaceColumn raceColumn,
- MaxPointsReason oldMaxPointsReason, MaxPointsReason newMaxPointsReason) {
- removeFromCache(leaderboard);
- }
-
- @Override
- public void carriedPointsChanged(Competitor competitor, Double oldCarriedPoints, Double newCarriedPoints) {
- removeFromCache(leaderboard);
- }
-
- @Override
- public void isSuppressedChanged(Competitor competitor, boolean newIsSuppressed) {
- removeFromCache(leaderboard);
- }
-
- @Override
- public void timePointOfLastCorrectionsValidityChanged(TimePoint oldTimePointOfLastCorrectionsValidity,
- TimePoint newTimePointOfLastCorrectionsValidity) {
- removeFromCache(leaderboard);
- }
-
- @Override
- public void commentChanged(String oldComment, String newComment) {
+ public void defaultAction() {
removeFromCache(leaderboard);
}
}
@@ -374,12 +345,12 @@ public class LeaderboardCacheManager {
trackedRace.addListener(listener);
invalidationListeners = invalidationListenersPerLeaderboard.get(leaderboard);
if (invalidationListeners == null) {
- invalidationListeners = new ConcurrentHashMap>();
+ invalidationListeners = new ConcurrentHashMap<>();
invalidationListenersPerLeaderboard.put(leaderboard, invalidationListeners);
}
Set listeners = invalidationListeners.get(trackedRace);
if (listeners == null) {
- listeners = Collections.synchronizedSet(new HashSet());
+ listeners = Collections.synchronizedSet(new HashSet<>());
invalidationListeners.put(trackedRace, listeners);
}
listeners.add(listener);
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/RegattaLeaderboardWithOtherTieBreakingLeaderboard.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/RegattaLeaderboardWithOtherTieBreakingLeaderboard.java
new file mode 100644
index 00000000000..b21d85f94ba
--- /dev/null
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/RegattaLeaderboardWithOtherTieBreakingLeaderboard.java
@@ -0,0 +1,21 @@
+package com.sap.sailing.domain.leaderboard;
+
+/**
+ * A regatta leaderboard that may have to resort to the competitor standings in another leaderboard
+ * for breaking specific ties. This {@link #getOtherTieBreakingLeaderboard() other leaderboard} can,
+ * e.g., be obtained by a {@link ScoringScheme} which then looks up scores or ranks in that leaderboard
+ * for tie-breaking purposes.
+ *
+ * Changes in the tie-breaking leaderboard may lead to tie-breaking changes in this leaderboard. However,
+ * this leaderboard assumes that by and large the tie-breaking leaderboard is complete and has no running
+ * races anymore. An exception to this assumption are score corrections applied to the tie-breaking
+ * leaderboard, e.g., by importing official results after the races in this leaderboard have started
+ * already. Therefore, this leaderboard acts as a {@link ScoreCorrectionListener} on the
+ * tie-breaking leaderboard and will forward those changes.
+ *
+ * @author Axel Uhl (d043530)
+ *
+ */
+public interface RegattaLeaderboardWithOtherTieBreakingLeaderboard extends RegattaLeaderboard {
+ RegattaLeaderboard getOtherTieBreakingLeaderboard();
+}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/ScoringScheme.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/ScoringScheme.java
index 66f10586dbc..bd879bc2f95 100755
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/ScoringScheme.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/ScoringScheme.java
@@ -117,7 +117,7 @@ public interface ScoringScheme extends Serializable {
*
*
* "A8.2 If a tie remains between two or more boats, they shall be ranked in order of their scores in the last
- * race. Any remaining ties shall be broken by using the tied boats� scores in the next-to-last race and so on until
+ * race. Any remaining ties shall be broken by using the tied boats' scores in the next-to-last race and so on until
* all ties are broken. These scores shall be used even if some of them are excluded scores."
*/
int compareByLastRace(List> o1Scores, List> o2Scores, boolean nullScoresAreBetter, Competitor o1, Competitor o2);
@@ -140,6 +140,8 @@ public interface ScoringScheme extends Serializable {
* @throws NoWindException
*/
int compareByLatestRegattaInMetaLeaderboard(Leaderboard leaderboard, Competitor o1, Competitor o2, TimePoint timePoint);
+
+ int compareByOtherTieBreakingLeaderboard(RegattaLeaderboardWithOtherTieBreakingLeaderboard leaderboard, Competitor o1, Competitor o2, TimePoint timePoint);
/**
* Returning {@code true} makes the number of wins in a medal series the primary ranking criteria.
@@ -187,4 +189,27 @@ public interface ScoringScheme extends Serializable {
}
return factor;
}
+
+ /**
+ * Computes a score corrected by a {@link #getScoreFactor(RaceColumn) column factor} and potentially other
+ * column-specific rules, such as that despite multiplying, the original score 1 is to map to 1 again.
+ * Respects {@link RaceColumn#isOneAlwaysStaysOne()} on the {@code raceColumn}.
+ *
+ * @see #getOriginalScoreFromScoreScaledByFactor(RaceColumn, double)
+ * @see ScoringSchemeType#getScaledScore(double, double, boolean)
+ */
+ default double getScoreScaledByFactor(RaceColumn raceColumn, double originalScore) {
+ return ScoringSchemeType.getScaledScore(getScoreFactor(raceColumn), originalScore, raceColumn.isOneAlwaysStaysOne());
+ }
+
+ /**
+ * "Un-scales" a score; the inverse of {@link #getScoreScaledByFactor(RaceColumn, double)}. Respects
+ * {@link RaceColumn#isOneAlwaysStaysOne()} on the {@code raceColumn}.
+ *
+ * @see #getScoreScaledByFactor(RaceColumn, double)
+ * @see ScoringSchemeType#getUnscaledScore(double, double, boolean)
+ */
+ default double getOriginalScoreFromScoreScaledByFactor(RaceColumn raceColumn, double scaledScore) {
+ return ScoringSchemeType.getUnscaledScore(getScoreFactor(raceColumn), scaledScore, raceColumn.isOneAlwaysStaysOne());
+ }
}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractHighPointExtremeSailingSeriesOverall.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractHighPointExtremeSailingSeriesOverall.java
index 9cdfd4edc82..8cbcb4a7db2 100644
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractHighPointExtremeSailingSeriesOverall.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractHighPointExtremeSailingSeriesOverall.java
@@ -9,7 +9,6 @@ import java.util.concurrent.Callable;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.RaceColumn;
-import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.MetaLeaderboard;
import com.sap.sailing.domain.leaderboard.NumberOfCompetitorsInLeaderboardFetcher;
@@ -74,7 +73,7 @@ public abstract class AbstractHighPointExtremeSailingSeriesOverall extends HighP
private int getWins(List> scores) {
int wins = 0;
for (com.sap.sse.common.Util.Pair score : scores) {
- if (Math.abs(score.getB() - maxPoints * getScoreFactor(score.getA())) < 0.0000001) {
+ if (Math.abs(score.getB() - getScoreScaledByFactor(score.getA(), maxPoints)) < 0.0000001) {
wins++;
}
}
@@ -109,7 +108,6 @@ public abstract class AbstractHighPointExtremeSailingSeriesOverall extends HighP
/**
* Notice of Race (NOR) section 13.5 specifies for the series score: "If a tie still remains, it shall be broken in
* favor of the boat that had the better place at the last Regatta sailed."
- * @throws NoWindException
*/
@Override
public int compareByLatestRegattaInMetaLeaderboard(Leaderboard leaderboard, Competitor o1, Competitor o2, TimePoint timePoint) {
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractHighPointFirstGetsFixedOr8AndLastBreaksTie.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractHighPointFirstGetsFixedOr8AndLastBreaksTie.java
index 5b62ef9bedf..b781c3ed0d8 100644
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractHighPointFirstGetsFixedOr8AndLastBreaksTie.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractHighPointFirstGetsFixedOr8AndLastBreaksTie.java
@@ -48,8 +48,9 @@ public abstract class AbstractHighPointFirstGetsFixedOr8AndLastBreaksTie extends
private double getHighestScore(List> scores) {
double highestScore = 0;
for (com.sap.sse.common.Util.Pair score : scores) {
- if ((score.getB() * getScoreFactor(score.getA())) > highestScore) {
- highestScore = score.getB() * getScoreFactor(score.getA());
+ final double scoreScaledByFactor = getScoreScaledByFactor(score.getA(), score.getB());
+ if (scoreScaledByFactor > highestScore) {
+ highestScore = scoreScaledByFactor;
}
}
return highestScore;
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java
index c0696fec8c6..73102c15bee 100755
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java
@@ -419,7 +419,7 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard {
RaceColumnDTO raceColumnDTO = result.createEmptyRaceColumn(raceColumn.getName(), raceColumn.isMedalRace(),
raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getRegatta().getName() : null,
raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getSeries().getName() : null,
- isMetaLeaderboardColumn);
+ isMetaLeaderboardColumn, raceColumn.isOneAlwaysStaysOne());
if (isMetaLeaderboardColumn && raceColumnDTO instanceof MetaLeaderboardRaceColumnDTO) {
calculateRacesMetadata((MetaLeaderboardColumn) raceColumn, (MetaLeaderboardRaceColumnDTO) raceColumnDTO, baseDomainFactory);
}
@@ -438,7 +438,7 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard {
result.addRace(raceColumn.getName(), raceColumn.getExplicitFactor(), getScoringScheme().getScoreFactor(raceColumn),
raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getRegatta().getName() : null,
raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getSeries().getName() : null,
- fleetDTO, raceColumn.isMedalRace(), raceIdentifier, race, isMetaLeaderboardColumn);
+ fleetDTO, raceColumn.isMedalRace(), raceIdentifier, race, isMetaLeaderboardColumn, raceColumn.isOneAlwaysStaysOne());
}
Future> task = executor.submit(
() -> baseDomainFactory.getCompetitorDTOList(AbstractLeaderboardWithCache.this.getCompetitorsFromBestToWorst(
@@ -845,7 +845,7 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard {
row.totalDurationFoiledInSeconds = totalDurationFoiled==null?null:totalDurationFoiled.asSeconds();
}
- private LeaderboardDTOCache getLeaderboardDTOCache() {
+ protected LeaderboardDTOCache getLeaderboardDTOCache() {
LeaderboardDTOCache result = this.leaderboardDTOCache;
if (result == null) {
synchronized (this) {
@@ -1183,7 +1183,7 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard {
}
@Override
- public int getTotalRankOfCompetitor(Competitor competitor, TimePoint timePoint) throws NoWindException {
+ public int getTotalRankOfCompetitor(Competitor competitor, TimePoint timePoint) {
return getCompetitorsFromBestToWorst(timePoint).indexOf(competitor) + 1;
}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractScoringSchemeImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractScoringSchemeImpl.java
index 800dd6bdf08..7309efb5c8e 100755
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractScoringSchemeImpl.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractScoringSchemeImpl.java
@@ -15,6 +15,7 @@ import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.leaderboard.Leaderboard;
+import com.sap.sailing.domain.leaderboard.RegattaLeaderboardWithOtherTieBreakingLeaderboard;
import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.TimePoint;
@@ -151,7 +152,7 @@ public abstract class AbstractScoringSchemeImpl implements ScoringScheme {
* Assuming both competitors scored in the same number of races, compares the sorted scores based on World Sailing's
* Racing Rules of Sailing (RRS) addendum A8.1:
*
- * "A8.1 If there is a series-score tie between two or more boats, each boat’s race scores shall be listed in
+ * "A8.1 If there is a series-score tie between two or more boats, each boat's race scores shall be listed in
* order of best to worst, and at the first point(s) where there is a difference the tie shall be broken in favour
* of the boat(s) with the best score(s). No excluded scores shall be used."
*/
@@ -166,14 +167,14 @@ public abstract class AbstractScoringSchemeImpl implements ScoringScheme {
final Set o1Discards = discardedRaceColumnsPerCompetitor.get(o1);
for (com.sap.sse.common.Util.Pair o1ColumnAndScore : o1Scores) {
if (includeDiscardedResults || !o1Discards.contains(o1ColumnAndScore.getA())) {
- o1NetScores.add(new Pair<>(o1ColumnAndScore.getA(), o1ColumnAndScore.getB() / getScoreFactor(o1ColumnAndScore.getA())));
+ o1NetScores.add(new Pair<>(o1ColumnAndScore.getA(), getOriginalScoreFromScoreScaledByFactor(o1ColumnAndScore.getA(), o1ColumnAndScore.getB())));
}
}
List> o2NetScores = new ArrayList<>();
final Set o2Discards = discardedRaceColumnsPerCompetitor.get(o2);
for (com.sap.sse.common.Util.Pair o2ColumnAndScore : o2Scores) {
if (includeDiscardedResults || !o2Discards.contains(o2ColumnAndScore.getA())) {
- o2NetScores.add(new Pair<>(o2ColumnAndScore.getA(), o2ColumnAndScore.getB() / getScoreFactor(o2ColumnAndScore.getA())));
+ o2NetScores.add(new Pair<>(o2ColumnAndScore.getA(), getOriginalScoreFromScoreScaledByFactor(o2ColumnAndScore.getA(), o2ColumnAndScore.getB())));
}
}
Collections.sort(o1NetScores, ruleA8_1ScoreComparator);
@@ -228,7 +229,7 @@ public abstract class AbstractScoringSchemeImpl implements ScoringScheme {
*
*
* "A8.2 If a tie remains between two or more boats, they shall be ranked in order of their scores in the last race.
- * Any remaining ties shall be broken by using the tied boats’ scores in the next-to-last race and so on until all
+ * Any remaining ties shall be broken by using the tied boats' scores in the next-to-last race and so on until all
* ties are broken. These scores shall be used even if some of them are excluded scores."
*
* @param o1ScoresIncludingDiscarded
@@ -270,4 +271,9 @@ public abstract class AbstractScoringSchemeImpl implements ScoringScheme {
public int compareByLatestRegattaInMetaLeaderboard(Leaderboard leaderboard, Competitor o1, Competitor o2, TimePoint timePoint) {
return 0;
}
+
+ @Override
+ public int compareByOtherTieBreakingLeaderboard(RegattaLeaderboardWithOtherTieBreakingLeaderboard leaderboard, Competitor o1, Competitor o2, TimePoint timePoint) {
+ return 0;
+ }
}
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 2549398e1b5..967ae91e312 100644
--- 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
@@ -271,6 +271,11 @@ public abstract class AbstractSimpleLeaderboardImpl extends AbstractLeaderboardW
hasSplitFleetContiguousScoring);
}
+ @Override
+ public void oneAlwaysStaysOneChanged(RaceColumn raceColumn, boolean oneAlwaysStaysOne) {
+ getRaceColumnListeners().notifyListenersAboutOneAlwaysStaysOneChanged(raceColumn, oneAlwaysStaysOne);
+ }
+
@Override
public void hasCrossFleetMergedRankingChanged(RaceColumn raceColumn, boolean hasCrossFleetMergedRanking) {
getRaceColumnListeners().notifyListenersAboutHasCrossFleetMergedRankingChanged(raceColumn, hasCrossFleetMergedRanking);
@@ -495,7 +500,7 @@ public abstract class AbstractSimpleLeaderboardImpl extends AbstractLeaderboardW
if (totalPoints == null) {
result = null;
} else {
- result = getScoringScheme().getScoreFactor(raceColumn) * totalPoints;
+ result = getScoringScheme().getScoreScaledByFactor(raceColumn, totalPoints);
}
}
return result;
@@ -681,11 +686,10 @@ public abstract class AbstractSimpleLeaderboardImpl extends AbstractLeaderboardW
boolean discarded = isDiscarded(competitor, race, timePoint, discardedRaceColumns);
final Double correctedScore = correctedResults.getCorrectedScore();
final Double correctedScoreScaledByColumnFactor = correctedScore == null ? null
- : Double.valueOf((correctedScore * getScoringScheme().getScoreFactor(race)));
+ : Double.valueOf(getScoringScheme().getScoreScaledByFactor(race, correctedScore));
return new EntryImpl(trackedRankProvider, correctedScoreScaledByColumnFactor, () -> correctedResults.getUncorrectedScore(),
correctedResults.isCorrected(),
- discarded ? DOUBLE_0
- : correctedScore == null ? null : Double.valueOf(correctedScore * getScoringScheme().getScoreFactor(race)),
+ discarded ? DOUBLE_0 : correctedScoreScaledByColumnFactor,
correctedResults.getMaxPointsReason(), discarded, race.getFleetOfCompetitor(competitor));
}
@@ -757,7 +761,7 @@ public abstract class AbstractSimpleLeaderboardImpl extends AbstractLeaderboardW
boolean discarded = discardedRacesForCompetitor.contains(raceColumn);
final Double correctedScore = correctedResults.getCorrectedScore();
final Double correctedScoreScaledByColumnFactor = correctedScore == null ? null
- : Double.valueOf((correctedScore * getScoringScheme().getScoreFactor(raceColumn)));
+ : Double.valueOf(getScoringScheme().getScoreScaledByFactor(raceColumn, correctedScore));
Entry entry = new EntryImpl(trackedRankProvider, correctedScoreScaledByColumnFactor,
() -> correctedResults.getUncorrectedScore(), correctedResults.isCorrected(),
discarded ? DOUBLE_0 : correctedScoreScaledByColumnFactor,
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegateLeaderboard.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegateLeaderboard.java
new file mode 100644
index 00000000000..d2f8b2e22bd
--- /dev/null
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegateLeaderboard.java
@@ -0,0 +1,66 @@
+package com.sap.sailing.domain.leaderboard.impl;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
+
+public class DelegateLeaderboard implements Serializable {
+ private static final long serialVersionUID = -1764036951368356044L;
+
+ private RegattaLeaderboard delegateLeaderboard;
+
+ private transient final Supplier delegateLeaderboardSupplier;
+
+ /**
+ * The particular use case for which this field is introduced is registering score correction
+ * listeners at a point in time when the full leaderboard hasn't been resolved yet. Instead of
+ * letting this listener registration attempt the resolution without success the request can
+ * be queued here, and each time the {@link #getDelegateLeaderboard()} successfully resolves a
+ * leaderboard, all consumers in this set will be triggered.
+ */
+ private final ConcurrentHashMap, Boolean> triggerWhenDelegateLeaderboardIsResolved;
+
+ public DelegateLeaderboard(Supplier delegateLeaderboardSupplier) {
+ this.delegateLeaderboardSupplier = delegateLeaderboardSupplier;
+ this.triggerWhenDelegateLeaderboardIsResolved = new ConcurrentHashMap<>();
+ }
+
+ public RegattaLeaderboard getDelegateLeaderboard() {
+ // TODO make thread-safe; if multiple threads call concurrently, triggers from triggerWhenFullLeaderboardIsResolved may fire several times
+ if (delegateLeaderboard == null) {
+ if (delegateLeaderboardSupplier == null) {
+ throw new NullPointerException("Internal error: Regatta leaderboard supplier is null; this can only happen upon premature serialization");
+ }
+ delegateLeaderboard = delegateLeaderboardSupplier.get();
+ if (delegateLeaderboard != null) {
+ for (Iterator> i=triggerWhenDelegateLeaderboardIsResolved.keySet().iterator(); i.hasNext(); ) {
+ final Consumer toTrigger = i.next();
+ toTrigger.accept(delegateLeaderboard);
+ i.remove();
+ }
+ }
+ }
+ return delegateLeaderboard;
+ }
+
+ public void scheduleLeaderboardConsumer(final Consumer consumer) {
+ triggerWhenDelegateLeaderboardIsResolved.put(consumer, true);
+ }
+
+ /**
+ * If the {@link #getDelegateLeaderboard() delegate leaderboard} is already available, the {@code action} is
+ * run with it right away; otherwise it is scheduled and run the next time that {@link #getDelegateLeaderboard()}
+ * is invoked such that it returns a valid leaderboard.
+ */
+ public void runOrSchedule(final Consumer action) {
+ if (getDelegateLeaderboard() != null) {
+ action.accept(getDelegateLeaderboard());
+ } else {
+ scheduleLeaderboardConsumer(action);
+ }
+ }
+}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java
index aac0b0e0f4d..9aa2f70ee89 100755
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java
@@ -6,12 +6,10 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.Consumer;
import java.util.function.Supplier;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
@@ -66,18 +64,7 @@ import com.sap.sse.common.Util.Pair;
public class DelegatingRegattaLeaderboardWithCompetitorElimination extends AbstractLeaderboardWithCache implements RegattaLeaderboardWithEliminations {
private static final long serialVersionUID = 8331154893189722924L;
private final String name;
- private RegattaLeaderboard fullLeaderboard;
-
- private transient final Supplier fullLeaderboardSupplier;
-
- /**
- * The particular use case for which this field is introduced is registering score correction
- * listeners at a point in time when the full leaderboard hasn't been resolved yet. Instead of
- * letting this listener registration attempt the resolution without success the request can
- * be queued here, and each time the {@link #getFullLeaderboard()} successfully resolves a
- * leaderboard, all consumers in this set will be triggered.
- */
- private final ConcurrentHashMap, Boolean> triggerWhenFullLeaderboardIsResolved;
+ private final DelegateLeaderboard fullLeaderboard;
/**
* Competitors eliminated from this leaderboard for regatta ranking; those competitors are not part of
@@ -93,12 +80,10 @@ public class DelegatingRegattaLeaderboardWithCompetitorElimination extends Abstr
/**
* The leaderboard wrapper starts out with an empty set of eliminated competitors
*/
- public DelegatingRegattaLeaderboardWithCompetitorElimination(Supplier fullLeaderboardSupplier,
- String name) {
+ public DelegatingRegattaLeaderboardWithCompetitorElimination(Supplier fullLeaderboardSupplier, String name) {
this.name = name;
- this.fullLeaderboardSupplier = fullLeaderboardSupplier;
this.eliminatedCompetitors = new ConcurrentHashMap<>();
- this.triggerWhenFullLeaderboardIsResolved = new ConcurrentHashMap<>();
+ fullLeaderboard = new DelegateLeaderboard(fullLeaderboardSupplier);
}
@Override
@@ -106,9 +91,13 @@ public class DelegatingRegattaLeaderboardWithCompetitorElimination extends Abstr
return name;
}
+ private RegattaLeaderboard getDelegateLeaderboard() {
+ return fullLeaderboard.getDelegateLeaderboard();
+ }
+
@Override
public Iterable getCompetitors() {
- return new ObscuringIterable<>(getFullLeaderboard().getCompetitors(), eliminatedCompetitors.keySet());
+ return new ObscuringIterable<>(getDelegateLeaderboard().getCompetitors(), eliminatedCompetitors.keySet());
}
@Override
@@ -118,6 +107,7 @@ public class DelegatingRegattaLeaderboardWithCompetitorElimination extends Abstr
} else {
eliminatedCompetitors.remove(competitor);
}
+ getLeaderboardDTOCache().invalidate(this);
}
@Override
@@ -133,7 +123,7 @@ public class DelegatingRegattaLeaderboardWithCompetitorElimination extends Abstr
@Override
public Map> getRankedCompetitorsFromBestToWorstAfterEachRaceColumn(TimePoint timePoint,
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws NoWindException {
- Map> preResult = getFullLeaderboard().getRankedCompetitorsFromBestToWorstAfterEachRaceColumn(timePoint, cache);
+ Map> preResult = getDelegateLeaderboard().getRankedCompetitorsFromBestToWorstAfterEachRaceColumn(timePoint, cache);
for (final List e : preResult.values()) {
e.removeAll(eliminatedCompetitors.keySet());
}
@@ -143,7 +133,7 @@ public class DelegatingRegattaLeaderboardWithCompetitorElimination extends Abstr
@Override
public Map getCompetitorsForWhichThereAreCarriedPoints() {
final Map result = new HashMap<>();
- for (final java.util.Map.Entry e : getFullLeaderboard().getCompetitorsForWhichThereAreCarriedPoints().entrySet()) {
+ for (final java.util.Map.Entry e : getDelegateLeaderboard().getCompetitorsForWhichThereAreCarriedPoints().entrySet()) {
if (!isEliminated(e.getKey())) {
result.put(e.getKey(), e.getValue());
}
@@ -154,13 +144,13 @@ public class DelegatingRegattaLeaderboardWithCompetitorElimination extends Abstr
@Override
public Iterable getCompetitorsFromBestToWorst(RaceColumn raceColumn, TimePoint timePoint,
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws NoWindException {
- return new ObscuringIterable<>(getFullLeaderboard().getCompetitorsFromBestToWorst(raceColumn, timePoint, cache), eliminatedCompetitors.keySet());
+ return new ObscuringIterable<>(getDelegateLeaderboard().getCompetitorsFromBestToWorst(raceColumn, timePoint, cache), eliminatedCompetitors.keySet());
}
@Override
public List getCompetitorsFromBestToWorst(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) {
final List result = new ArrayList<>();
- for (final Competitor c : getFullLeaderboard().getCompetitorsFromBestToWorst(timePoint, cache)) {
+ for (final Competitor c : getDelegateLeaderboard().getCompetitorsFromBestToWorst(timePoint, cache)) {
if (!isEliminated(c)) {
result.add(c);
}
@@ -171,7 +161,7 @@ public class DelegatingRegattaLeaderboardWithCompetitorElimination extends Abstr
@Override
public Map, Entry> getContent(TimePoint timePoint) throws NoWindException {
final Map, Entry> result = new HashMap<>();
- for (final java.util.Map.Entry, Entry> e : getFullLeaderboard().getContent(timePoint).entrySet()) {
+ for (final java.util.Map.Entry, Entry> e : getDelegateLeaderboard().getContent(timePoint).entrySet()) {
if (!isEliminated(e.getKey().getA())) {
result.put(e.getKey(), e.getValue());
}
@@ -187,384 +177,359 @@ public class DelegatingRegattaLeaderboardWithCompetitorElimination extends Abstr
// --------------------- Delegate Pattern Implementation ----------------------
@Override
public CompetitorProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider() {
- return getFullLeaderboard().getOrCreateCompetitorsProvider();
+ return getDelegateLeaderboard().getOrCreateCompetitorsProvider();
}
@Override
public Regatta getRegatta() {
- return getFullLeaderboard().getRegatta();
+ return getDelegateLeaderboard().getRegatta();
}
@Override
public Iterable getCompetitorsRegisteredInRegattaLog() {
- return getFullLeaderboard().getCompetitorsRegisteredInRegattaLog();
+ return getDelegateLeaderboard().getCompetitorsRegisteredInRegattaLog();
}
@Override
public IsRegattaLike getRegattaLike() {
- return getFullLeaderboard().getRegattaLike();
+ return getDelegateLeaderboard().getRegattaLike();
}
@Override
public RaceLog getRacelog(String raceColumnName, String fleetName) {
- return getFullLeaderboard().getRacelog(raceColumnName, fleetName);
+ return getDelegateLeaderboard().getRacelog(raceColumnName, fleetName);
}
@Override
public void registerCompetitor(Competitor competitor) {
- getFullLeaderboard().registerCompetitor(competitor);
+ getDelegateLeaderboard().registerCompetitor(competitor);
}
@Override
public void registerCompetitors(Iterable competitors) {
- getFullLeaderboard().registerCompetitors(competitors);
+ getDelegateLeaderboard().registerCompetitors(competitors);
}
@Override
public void deregisterCompetitor(Competitor competitor) {
- getFullLeaderboard().deregisterCompetitor(competitor);
+ getDelegateLeaderboard().deregisterCompetitor(competitor);
}
@Override
public void deregisterCompetitors(Iterable competitor) {
- getFullLeaderboard().deregisterCompetitors(competitor);
+ getDelegateLeaderboard().deregisterCompetitors(competitor);
}
@Override
public Iterable getAllCompetitors() {
- return getFullLeaderboard().getAllCompetitors();
+ return getDelegateLeaderboard().getAllCompetitors();
}
@Override
public Pair, Iterable> getAllCompetitorsWithRaceDefinitionsConsidered() {
- return getFullLeaderboard().getAllCompetitorsWithRaceDefinitionsConsidered();
+ return getDelegateLeaderboard().getAllCompetitorsWithRaceDefinitionsConsidered();
}
@Override
public Iterable getAllCompetitors(RaceColumn raceColumn, Fleet fleet) {
- return getFullLeaderboard().getAllCompetitors(raceColumn, fleet);
+ return getDelegateLeaderboard().getAllCompetitors(raceColumn, fleet);
}
@Override
public Iterable getCompetitors(RaceColumn raceColumn, Fleet fleet) {
- return getFullLeaderboard().getCompetitors(raceColumn, fleet);
+ return getDelegateLeaderboard().getCompetitors(raceColumn, fleet);
}
@Override
public Iterable getSuppressedCompetitors() {
- return getFullLeaderboard().getSuppressedCompetitors();
+ return getDelegateLeaderboard().getSuppressedCompetitors();
}
@Override
public boolean isSuppressed(Competitor competitor) {
- return getFullLeaderboard().isSuppressed(competitor);
+ return getDelegateLeaderboard().isSuppressed(competitor);
}
@Override
public void setSuppressed(Competitor competitor, boolean suppressed) {
- getFullLeaderboard().setSuppressed(competitor, suppressed);
+ getDelegateLeaderboard().setSuppressed(competitor, suppressed);
}
@Override
public Fleet getFleet(String fleetName) {
- return getFullLeaderboard().getFleet(fleetName);
+ return getDelegateLeaderboard().getFleet(fleetName);
}
@Override
public Entry getEntry(Competitor competitor, RaceColumn race, TimePoint timePoint) throws NoWindException {
- return getFullLeaderboard().getEntry(competitor, race, timePoint);
+ return getDelegateLeaderboard().getEntry(competitor, race, timePoint);
}
@Override
public Entry getEntry(Competitor competitor, RaceColumn race, TimePoint timePoint,
Set discardedRaceColumns) throws NoWindException {
- return getFullLeaderboard().getEntry(competitor, race, timePoint, discardedRaceColumns);
+ return getDelegateLeaderboard().getEntry(competitor, race, timePoint, discardedRaceColumns);
}
@Override
public Map> getNetPointsSumAfterRaceColumn(TimePoint timePoint)
throws NoWindException {
- return getFullLeaderboard().getNetPointsSumAfterRaceColumn(timePoint);
+ return getDelegateLeaderboard().getNetPointsSumAfterRaceColumn(timePoint);
}
@Override
public double getCarriedPoints(Competitor competitor) {
- return getFullLeaderboard().getCarriedPoints(competitor);
+ return getDelegateLeaderboard().getCarriedPoints(competitor);
}
@Override
public int getTrackedRank(Competitor competitor, RaceColumn race, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) {
- return getFullLeaderboard().getTrackedRank(competitor, race, timePoint, cache);
+ return getDelegateLeaderboard().getTrackedRank(competitor, race, timePoint, cache);
}
@Override
public Double getTotalPoints(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) {
- return getFullLeaderboard().getTotalPoints(competitor, raceColumn, timePoint, cache);
+ return getDelegateLeaderboard().getTotalPoints(competitor, raceColumn, timePoint, cache);
}
@Override
public MaxPointsReason getMaxPointsReason(Competitor competitor, RaceColumn race, TimePoint timePoint) {
- return getFullLeaderboard().getMaxPointsReason(competitor, race, timePoint);
+ return getDelegateLeaderboard().getMaxPointsReason(competitor, race, timePoint);
}
@Override
public Double getNetPoints(Competitor competitor, RaceColumn race, TimePoint timePoint) {
- return getFullLeaderboard().getNetPoints(competitor, race, timePoint);
+ return getDelegateLeaderboard().getNetPoints(competitor, race, timePoint);
}
@Override
public boolean isDiscarded(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint) {
- return getFullLeaderboard().isDiscarded(competitor, raceColumn, timePoint);
+ return getDelegateLeaderboard().isDiscarded(competitor, raceColumn, timePoint);
}
@Override
public Double getNetPoints(Competitor competitor, TimePoint timePoint) {
- return getFullLeaderboard().getNetPoints(competitor, timePoint);
+ return getDelegateLeaderboard().getNetPoints(competitor, timePoint);
}
@Override
public Double getNetPoints(Competitor competitor, Iterable raceColumnsToConsider, TimePoint timePoint)
throws NoWindException {
- return getFullLeaderboard().getNetPoints(competitor, raceColumnsToConsider, timePoint);
+ return getDelegateLeaderboard().getNetPoints(competitor, raceColumnsToConsider, timePoint);
}
@Override
public Iterable getRaceColumns() {
- final RegattaLeaderboard theFullLeaderboard = getFullLeaderboard();
+ final RegattaLeaderboard theFullLeaderboard = getDelegateLeaderboard();
return theFullLeaderboard == null ? Collections.emptySet() : theFullLeaderboard.getRaceColumns();
}
@Override
public RaceColumn getRaceColumnByName(String name) {
- return getFullLeaderboard().getRaceColumnByName(name);
+ return getDelegateLeaderboard().getRaceColumnByName(name);
}
@Override
public void setCarriedPoints(Competitor competitor, double carriedPoints) {
- getFullLeaderboard().setCarriedPoints(competitor, carriedPoints);
+ getDelegateLeaderboard().setCarriedPoints(competitor, carriedPoints);
}
@Override
public void unsetCarriedPoints(Competitor competitor) {
- getFullLeaderboard().unsetCarriedPoints(competitor);
+ getDelegateLeaderboard().unsetCarriedPoints(competitor);
}
@Override
public boolean hasCarriedPoints() {
- return getFullLeaderboard().hasCarriedPoints();
+ return getDelegateLeaderboard().hasCarriedPoints();
}
@Override
public boolean hasCarriedPoints(Competitor competitor) {
- return getFullLeaderboard().hasCarriedPoints(competitor);
+ return getDelegateLeaderboard().hasCarriedPoints(competitor);
}
@Override
public SettableScoreCorrection getScoreCorrection() {
- return getFullLeaderboard().getScoreCorrection();
+ return getDelegateLeaderboard().getScoreCorrection();
}
@Override
public void addScoreCorrectionListener(ScoreCorrectionListener listener) {
- if (getFullLeaderboard() != null) {
- getFullLeaderboard().addScoreCorrectionListener(listener);
- } else {
- triggerWhenFullLeaderboardIsResolved.put(leaderboard->leaderboard.addScoreCorrectionListener(listener), true);
- }
+ fullLeaderboard.runOrSchedule(leaderboard->leaderboard.addScoreCorrectionListener(listener));
}
@Override
public void removeScoreCorrectionListener(ScoreCorrectionListener listener) {
- if (getFullLeaderboard() != null) {
- getFullLeaderboard().removeScoreCorrectionListener(listener);
- } else {
- triggerWhenFullLeaderboardIsResolved.put(leaderboard->leaderboard.removeScoreCorrectionListener(listener), true);
- }
+ fullLeaderboard.runOrSchedule(leaderboard->leaderboard.removeScoreCorrectionListener(listener));
}
@Override
public Competitor getCompetitorByName(String competitorName) {
- return getFullLeaderboard().getCompetitorByName(competitorName);
+ return getDelegateLeaderboard().getCompetitorByName(competitorName);
}
public void setDisplayName(Competitor competitor, String displayName) {
- getFullLeaderboard().setDisplayName(competitor, displayName);
+ getDelegateLeaderboard().setDisplayName(competitor, displayName);
}
@Override
public String getDisplayName(Competitor competitor) {
- return getFullLeaderboard().getDisplayName(competitor);
+ return getDelegateLeaderboard().getDisplayName(competitor);
}
@Override
public boolean countRaceForComparisonWithDiscardingThresholds(Competitor competitor, RaceColumn raceColumn,
TimePoint timePoint) {
- return getFullLeaderboard().countRaceForComparisonWithDiscardingThresholds(competitor, raceColumn, timePoint);
+ return getDelegateLeaderboard().countRaceForComparisonWithDiscardingThresholds(competitor, raceColumn, timePoint);
}
@Override
public ResultDiscardingRule getResultDiscardingRule() {
- return getFullLeaderboard().getResultDiscardingRule();
+ return getDelegateLeaderboard().getResultDiscardingRule();
}
@Override
public void setCrossLeaderboardResultDiscardingRule(ThresholdBasedResultDiscardingRule discardingRule) {
- getFullLeaderboard().setCrossLeaderboardResultDiscardingRule(discardingRule);
+ getDelegateLeaderboard().setCrossLeaderboardResultDiscardingRule(discardingRule);
}
@Override
public Competitor getCompetitorByIdAsString(String idAsString) {
- return getFullLeaderboard().getCompetitorByIdAsString(idAsString);
+ return getDelegateLeaderboard().getCompetitorByIdAsString(idAsString);
}
@Override
public void addRaceColumnListener(RaceColumnListener listener) {
- getFullLeaderboard().addRaceColumnListener(listener);
+ getDelegateLeaderboard().addRaceColumnListener(listener);
}
@Override
public void removeRaceColumnListener(RaceColumnListener listener) {
- getFullLeaderboard().removeRaceColumnListener(listener);
+ getDelegateLeaderboard().removeRaceColumnListener(listener);
}
@Override
public Long getDelayToLiveInMillis() {
- return getFullLeaderboard().getDelayToLiveInMillis();
+ return getDelegateLeaderboard().getDelayToLiveInMillis();
}
@Override
public Iterable getTrackedRaces() {
- return getFullLeaderboard().getTrackedRaces();
+ return getDelegateLeaderboard().getTrackedRaces();
}
@Override
public ScoringScheme getScoringScheme() {
- return getFullLeaderboard().getScoringScheme();
+ return getDelegateLeaderboard().getScoringScheme();
}
@Override
public TimePoint getTimePointOfLatestModification() {
- return getFullLeaderboard().getTimePointOfLatestModification();
+ return getDelegateLeaderboard().getTimePointOfLatestModification();
}
@Override
public Pair getMaximumSpeedOverGround(Competitor competitor, TimePoint timePoint) {
- return getFullLeaderboard().getMaximumSpeedOverGround(competitor, timePoint);
+ return getDelegateLeaderboard().getMaximumSpeedOverGround(competitor, timePoint);
}
@Override
public Speed getAverageSpeedOverGround(Competitor competitor, TimePoint timePoint) {
- return getFullLeaderboard().getAverageSpeedOverGround(competitor, timePoint);
+ return getDelegateLeaderboard().getAverageSpeedOverGround(competitor, timePoint);
}
@Override
public Double getNetPoints(Competitor competitor, RaceColumn raceColumn, Iterable raceColumnsToConsider,
TimePoint timePoint) throws NoWindException {
- return getFullLeaderboard().getNetPoints(competitor, raceColumn, raceColumnsToConsider, timePoint);
+ return getDelegateLeaderboard().getNetPoints(competitor, raceColumn, raceColumnsToConsider, timePoint);
}
@Override
public Double getNetPoints(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint,
Set discardedRaceColumns) {
- return getFullLeaderboard().getNetPoints(competitor, raceColumn, timePoint, discardedRaceColumns);
+ return getDelegateLeaderboard().getNetPoints(competitor, raceColumn, timePoint, discardedRaceColumns);
}
@Override
public TimePoint getNowMinusDelay() {
- return getFullLeaderboard().getNowMinusDelay();
+ return getDelegateLeaderboard().getNowMinusDelay();
}
@Override
public Iterable getCourseAreas() {
- return getFullLeaderboard().getCourseAreas();
+ return getDelegateLeaderboard().getCourseAreas();
}
@Override
public NumberOfCompetitorsInLeaderboardFetcher getNumberOfCompetitorsInLeaderboardFetcher() {
- return getFullLeaderboard().getNumberOfCompetitorsInLeaderboardFetcher();
+ return getDelegateLeaderboard().getNumberOfCompetitorsInLeaderboardFetcher();
}
@Override
public Pair getRaceColumnAndFleet(TrackedRace trackedRace) {
- return getFullLeaderboard().getRaceColumnAndFleet(trackedRace);
+ return getDelegateLeaderboard().getRaceColumnAndFleet(trackedRace);
}
@Override
public BoatClass getBoatClass() {
- return getFullLeaderboard().getBoatClass();
+ return getDelegateLeaderboard().getBoatClass();
}
@Override
public Boat getBoatOfCompetitor(Competitor competitor, RaceColumn raceColumn, Fleet fleet) {
- return getFullLeaderboard().getBoatOfCompetitor(competitor, raceColumn, fleet);
- }
-
- private RegattaLeaderboard getFullLeaderboard() {
- if (fullLeaderboard == null) {
- if (fullLeaderboardSupplier == null) {
- throw new NullPointerException("Internal error: Regatta leaderboard supplier is null; this can only happen upon premature serialization");
- }
- fullLeaderboard = fullLeaderboardSupplier.get();
- if (fullLeaderboard != null) {
- for (Iterator> i=triggerWhenFullLeaderboardIsResolved.keySet().iterator(); i.hasNext(); ) {
- final Consumer toTrigger = i.next();
- toTrigger.accept(fullLeaderboard);
- i.remove();
- }
- }
- }
- return fullLeaderboard;
+ return getDelegateLeaderboard().getBoatOfCompetitor(competitor, raceColumn, fleet);
}
/**
- * Before being serialized, ensure that the leaderboard supplier has been used to tru
+ * Before being serialized, ensure that the leaderboard supplier has been used
* to resolve the leaderboard.
* @throws IOException
*/
private void writeObject(ObjectOutputStream oos) throws IOException {
- getFullLeaderboard();
+ getDelegateLeaderboard();
oos.defaultWriteObject();
}
@Override
public Iterable getBoatsRegisteredInRegattaLog() {
- return getFullLeaderboard().getBoatsRegisteredInRegattaLog();
+ return getDelegateLeaderboard().getBoatsRegisteredInRegattaLog();
}
@Override
public Iterable getAllBoats() {
- return getFullLeaderboard().getAllBoats();
+ return getDelegateLeaderboard().getAllBoats();
}
@Override
public void registerBoat(Boat boat) {
- getFullLeaderboard().registerBoat(boat);
+ getDelegateLeaderboard().registerBoat(boat);
}
@Override
public void registerBoats(Iterable boats) {
- getFullLeaderboard().registerBoats(boats);
+ getDelegateLeaderboard().registerBoats(boats);
}
@Override
public void deregisterBoat(Boat boat) {
- getFullLeaderboard().deregisterBoat(boat);
+ getDelegateLeaderboard().deregisterBoat(boat);
}
@Override
public void deregisterBoats(Iterable boats) {
- getFullLeaderboard().deregisterBoats(boats);
+ getDelegateLeaderboard().deregisterBoats(boats);
}
@Override
public Double getNetPoints(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint,
Set discardedRaceColumns, Supplier totalPointsProvider) {
- return getFullLeaderboard().getNetPoints(competitor, raceColumn, timePoint, discardedRaceColumns,
+ return getDelegateLeaderboard().getNetPoints(competitor, raceColumn, timePoint, discardedRaceColumns,
totalPointsProvider);
}
@Override
public boolean isResultsAreOfficial(RaceColumn raceColumn, Fleet fleet) {
- return getFullLeaderboard().isResultsAreOfficial(raceColumn, fleet);
+ return getDelegateLeaderboard().isResultsAreOfficial(raceColumn, fleet);
}
}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointByWinsTiesLastlyBrokenByOtherLeaderboard.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointByWinsTiesLastlyBrokenByOtherLeaderboard.java
new file mode 100644
index 00000000000..a1acf8191f7
--- /dev/null
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointByWinsTiesLastlyBrokenByOtherLeaderboard.java
@@ -0,0 +1,35 @@
+package com.sap.sailing.domain.leaderboard.impl;
+
+import com.sap.sailing.domain.base.Competitor;
+import com.sap.sailing.domain.common.ScoringSchemeType;
+import com.sap.sailing.domain.leaderboard.RegattaLeaderboardWithOtherTieBreakingLeaderboard;
+import com.sap.sse.common.TimePoint;
+
+public class HighPointByWinsTiesLastlyBrokenByOtherLeaderboard extends HighPointMatchRacing {
+ private static final long serialVersionUID = -2930982687072741643L;
+
+ @Override
+ public ScoringSchemeType getType() {
+ return ScoringSchemeType.HIGH_POINT_BY_WINS_TIES_LASTLY_BROKEN_BY_OTHER_LEADERBOARD;
+ }
+
+ @Override
+ public int compareByOtherTieBreakingLeaderboard(RegattaLeaderboardWithOtherTieBreakingLeaderboard leaderboard,
+ Competitor o1, Competitor o2, TimePoint timePoint) {
+ final int result;
+ final int o1RankInOtherTieBreakingLeaderboard = leaderboard.getOtherTieBreakingLeaderboard().getTotalRankOfCompetitor(o1, timePoint);
+ final int o2RankInOtherTieBreakingLeaderboard = leaderboard.getOtherTieBreakingLeaderboard().getTotalRankOfCompetitor(o2, timePoint);
+ if (o1RankInOtherTieBreakingLeaderboard == o2RankInOtherTieBreakingLeaderboard) {
+ result = 0;
+ } else {
+ if (o1RankInOtherTieBreakingLeaderboard == 0) {
+ result = 1; // o1 has no rank; this is worse ("greater") than any valid rank
+ } else if (o2RankInOtherTieBreakingLeaderboard == 0) {
+ result = -1;
+ } else {
+ result = Integer.compare(o1RankInOtherTieBreakingLeaderboard, o2RankInOtherTieBreakingLeaderboard);
+ }
+ }
+ return result;
+ }
+}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointMatchRacing.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointMatchRacing.java
index ca85336eb8b..81bee87beb2 100644
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointMatchRacing.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointMatchRacing.java
@@ -32,5 +32,4 @@ public class HighPointMatchRacing extends HighPoint {
Callable numberOfCompetitorsInRaceFetcher, NumberOfCompetitorsInLeaderboardFetcher numberOfCompetitorsInLeaderboardFetcher, TimePoint timePoint) {
return rank == 0 ? null : rank == 1 ? 1.0 : 0.0;
}
-
}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java
index b0ed671fc65..306a986cce2 100644
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java
@@ -16,6 +16,7 @@ import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.leaderboard.Leaderboard;
+import com.sap.sailing.domain.leaderboard.RegattaLeaderboardWithOtherTieBreakingLeaderboard;
import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache;
import com.sap.sse.common.TimePoint;
@@ -255,7 +256,13 @@ public class LeaderboardTotalRankComparator implements Comparator {
if (result == 0) {
result = scoringScheme.compareByLatestRegattaInMetaLeaderboard(getLeaderboard(), o1, o2, timePoint);
if (result == 0) {
- result = compareByArbitraryButStableCriteria(o1, o2);
+ if (getLeaderboard() instanceof RegattaLeaderboardWithOtherTieBreakingLeaderboard) {
+ result = scoringScheme.compareByOtherTieBreakingLeaderboard(
+ (RegattaLeaderboardWithOtherTieBreakingLeaderboard) getLeaderboard(), o1, o2, timePoint);
+ }
+ if (result == 0) {
+ result = compareByArbitraryButStableCriteria(o1, o2);
+ }
}
}
}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardWithOtherTieBreakingLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardWithOtherTieBreakingLeaderboardImpl.java
new file mode 100644
index 00000000000..9a0a1cc990e
--- /dev/null
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardWithOtherTieBreakingLeaderboardImpl.java
@@ -0,0 +1,48 @@
+package com.sap.sailing.domain.leaderboard.impl;
+
+import java.util.function.Supplier;
+
+import com.sap.sailing.domain.base.Regatta;
+import com.sap.sailing.domain.common.LeaderboardType;
+import com.sap.sailing.domain.leaderboard.AbstractScoreCorrectionListenerWithDefaultAction;
+import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
+import com.sap.sailing.domain.leaderboard.RegattaLeaderboardWithOtherTieBreakingLeaderboard;
+import com.sap.sailing.domain.leaderboard.ScoreCorrectionListener;
+import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
+
+/**
+ * Upon construction accepts a supplier for another {@link RegattaLeaderboard} and schedules the registration
+ * of a {@link ScoreCorrectionListener} on that leaderboard. When score corrections change on that other
+ * leaderboard, this leaderboard's cache contents are invalidated.
+ *
+ * @author Axel Uhl (d043530)
+ *
+ */
+public class RegattaLeaderboardWithOtherTieBreakingLeaderboardImpl extends RegattaLeaderboardImpl
+ implements RegattaLeaderboardWithOtherTieBreakingLeaderboard {
+ private static final long serialVersionUID = -4859656155952136210L;
+ private final DelegateLeaderboard otherTieBreakingLeaderboardProvider;
+
+ public RegattaLeaderboardWithOtherTieBreakingLeaderboardImpl(Regatta regatta,
+ ThresholdBasedResultDiscardingRule resultDiscardingRule, Supplier otherTieBreakingLeaderboardProvider) {
+ super(regatta, resultDiscardingRule);
+ this.otherTieBreakingLeaderboardProvider = new DelegateLeaderboard(otherTieBreakingLeaderboardProvider);
+ this.otherTieBreakingLeaderboardProvider.runOrSchedule(otherTieBreakingLeaderboard->otherTieBreakingLeaderboard.addScoreCorrectionListener(
+ new AbstractScoreCorrectionListenerWithDefaultAction() {
+ @Override
+ protected void defaultAction() {
+ getLeaderboardDTOCache().invalidate(RegattaLeaderboardWithOtherTieBreakingLeaderboardImpl.this);
+ }
+ }));
+ }
+
+ @Override
+ public RegattaLeaderboard getOtherTieBreakingLeaderboard() {
+ return otherTieBreakingLeaderboardProvider.getDelegateLeaderboard();
+ }
+
+ @Override
+ public LeaderboardType getLeaderboardType() {
+ return LeaderboardType.RegattaLeaderboardWithOtherTieBreakingLeaderboard;
+ }
+}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/ThresholdBasedResultDiscardingRuleImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/ThresholdBasedResultDiscardingRuleImpl.java
index 89dce680cc6..58a55566c1f 100755
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/ThresholdBasedResultDiscardingRuleImpl.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/ThresholdBasedResultDiscardingRuleImpl.java
@@ -100,7 +100,7 @@ public class ThresholdBasedResultDiscardingRuleImpl implements ThresholdBasedRes
sortedRaces.add(raceColumn);
final Double totalPoints = totalPointsSupplier.apply(raceColumn);
totalPointsForCompetitorPerColumn.put(raceColumn,
- totalPoints == null ? null : (totalPoints * scoringScheme.getScoreFactor(raceColumn)));
+ totalPoints == null ? null : scoringScheme.getScoreScaledByFactor(raceColumn, totalPoints));
}
}
result = new HashSet();
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java
index 7b5d77e6d2a..f1d3565a229 100755
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java
@@ -109,6 +109,11 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R
return false;
}
+ @Override
+ public boolean isOneAlwaysStaysOne() {
+ return false;
+ }
+
@Override
public void releaseTrackedRace(Fleet fleet) {
}
@@ -153,6 +158,11 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R
getRaceColumnListeners().notifyListenersAboutHasCrossFleetMergedRankingChanged(raceColumn, hasCrossFleetMergedRanking);
}
+ @Override
+ public void oneAlwaysStaysOneChanged(RaceColumn raceColumn, boolean oneAlwaysStaysOne) {
+ getRaceColumnListeners().notifyListenersAboutOneAlwaysStaysOneChanged(raceColumn, oneAlwaysStaysOne);
+ }
+
@Override
public boolean canAddRaceColumnToContainer(RaceColumn raceColumn) {
return getRaceColumnListeners().canAddRaceColumnToContainer(raceColumn);
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/util/impl/RaceColumnListeners.java b/java/com.sap.sailing.domain/src/com/sap/sailing/util/impl/RaceColumnListeners.java
index 7371f62c466..9219f71c4d0 100755
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/util/impl/RaceColumnListeners.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/util/impl/RaceColumnListeners.java
@@ -187,4 +187,10 @@ public class RaceColumnListeners implements Serializable {
listener.regattaLogEventAdded(event);
}
}
+
+ public void notifyListenersAboutOneAlwaysStaysOneChanged(RaceColumn raceColumn, boolean oneAlwaysStaysOne) {
+ for (RaceColumnListener listener : getRaceColumnListeners()) {
+ listener.oneAlwaysStaysOneChanged(raceColumn, oneAlwaysStaysOne);
+ }
+ }
}
diff --git a/java/com.sap.sailing.geocoding/src/com/sap/sailing/geocoding/impl/ReverseGeocoderImpl.java b/java/com.sap.sailing.geocoding/src/com/sap/sailing/geocoding/impl/ReverseGeocoderImpl.java
index 71c59f213ba..98fe1eb78d7 100644
--- a/java/com.sap.sailing.geocoding/src/com/sap/sailing/geocoding/impl/ReverseGeocoderImpl.java
+++ b/java/com.sap.sailing.geocoding/src/com/sap/sailing/geocoding/impl/ReverseGeocoderImpl.java
@@ -14,6 +14,8 @@ import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
@@ -44,10 +46,12 @@ public class ReverseGeocoderImpl implements ReverseGeocoder {
private final int XKM_RADIUS = 5;
private final int ROWS_PER_XKM_RADIUS = 15;
- private final int MAX_ROW_NUMBER = 1000;
+ private final int MAX_ROW_NUMBER = 500;
private final int MAX_RADIUS = 300;
private QuadTree>> cache = new QuadTree>>();;
+
+ private static final Logger logger = Logger.getLogger(ReverseGeocoderImpl.class.getName());
@Override
public Placemark getPlacemarkNearest(Position position) throws IOException, ParseException {
@@ -71,14 +75,13 @@ public class ReverseGeocoderImpl implements ReverseGeocoder {
@Override
public List getPlacemarksNear(Position position, double radius) throws IOException, ParseException {
- List placemarks = null;
- Util.Triple> cachedPlacemarks = checkCache(position);
+ final List placemarks;
+ final Util.Triple> cachedPlacemarks = checkCache(position);
// Calculating the search radius and the maximum number of returning Placemarks
double limitedRadius = Math.min(radius, MAX_RADIUS);
- int radiusInt = (int) limitedRadius;
- int xKmRadius = radiusInt / XKM_RADIUS;
- int maxRows = (int) (ROWS_PER_XKM_RADIUS * Math.pow(2, xKmRadius));
- maxRows = Math.min(maxRows, MAX_ROW_NUMBER);
+ final int radiusInt = (int) limitedRadius;
+ final int xKmRadius = radiusInt / XKM_RADIUS;
+ final int maxRows = (int) Math.min(ROWS_PER_XKM_RADIUS * Math.pow(2, xKmRadius), MAX_ROW_NUMBER);
if (cachedPlacemarks != null && cachedPlacemarks.getB() >= limitedRadius) {
if (cachedPlacemarks.getC().size() > maxRows) {
placemarks = cachedPlacemarks.getC().subList(0, maxRows);
@@ -95,23 +98,29 @@ public class ReverseGeocoderImpl implements ReverseGeocoder {
} else {
searchPosition = position;
}
- JSONArray geonames = callNearbyService(searchPosition, limitedRadius, maxRows);
+ final JSONArray geonames = callNearbyService(searchPosition, limitedRadius, maxRows);
if (geonames != null) {
Iterator