mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-23 22:19:13 +00:00
Merge branch 'master' into bug5741
This commit is contained in:
+4
-2
@@ -34,6 +34,7 @@ import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.dto.LeaderboardDTO;
|
||||
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.ScoringScheme;
|
||||
import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
|
||||
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
|
||||
import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl;
|
||||
@@ -334,6 +335,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest {
|
||||
Collections.sort(ranksOfNonMedalStartedRaces);
|
||||
int carryInt = (carry == null ? 0 : carry);
|
||||
int netPoints = carryInt;
|
||||
final ScoringScheme scoringScheme = leaderboard.getScoringScheme();
|
||||
int medalRacePoints = getMedalRacePoints(competitorWithBoat, now, defaultFleet);
|
||||
for (TrackedRace race : testRaces) {
|
||||
RaceColumn raceColumn = raceColumnsInLeaderboard.get(race);
|
||||
@@ -344,8 +346,8 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest {
|
||||
assertEquals(rank, leaderboard.getContent(now).get(key).getTrackedRank());
|
||||
assertEquals(rank, leaderboard.getEntry(competitorWithBoat, raceColumn, now).getTrackedRank());
|
||||
assertEquals(rank, leaderboard.getTotalPoints(competitorWithBoat, raceColumn, now), 0.000000001);
|
||||
assertEquals(rank, leaderboard.getContent(now).get(key).getTotalPoints(), 0.000000001);
|
||||
assertEquals(rank, leaderboard.getEntry(competitorWithBoat, raceColumn, now).getTotalPoints(), 0.000000001);
|
||||
assertEquals(rank*scoringScheme.getScoreFactor(raceColumn), leaderboard.getContent(now).get(key).getTotalPoints(), 0.000000001);
|
||||
assertEquals(rank*scoringScheme.getScoreFactor(raceColumn), leaderboard.getEntry(competitorWithBoat, raceColumn, now).getTotalPoints(), 0.000000001);
|
||||
// One race is discarded because four races were started, and for [3-6) one race can be discarded.
|
||||
// The discarded race is the worst of those started, so the one with rank 4.
|
||||
int expectedNumberOfDiscardedRaces =
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ public class LeaderboardScoringAndRankingTestBase extends AbstractLeaderboardTes
|
||||
double[][] scoresAfterNRaces, TimePoint timePoint, Competitor[] competitors) throws NoWindException {
|
||||
for (int competitorIndex=0; competitorIndex<scoresAfterNRaces.length; competitorIndex++) {
|
||||
final Set<RaceColumn> discardedRaceColumns = leaderboard.getResultDiscardingRule()
|
||||
.getDiscardedRaceColumns(competitors[competitorIndex], leaderboard, raceColumnsToConsider, timePoint);
|
||||
.getDiscardedRaceColumns(competitors[competitorIndex], leaderboard, raceColumnsToConsider, timePoint, leaderboard.getScoringScheme());
|
||||
for (int raceColumnIndex=0; raceColumnIndex<raceColumnsToConsider.size(); raceColumnIndex++) {
|
||||
assertEquals(scoresAfterNRaces[competitorIndex][raceColumnIndex],
|
||||
leaderboard.getNetPoints(competitors[competitorIndex], raceColumnsToConsider.get(raceColumnIndex),
|
||||
|
||||
@@ -178,7 +178,7 @@ public interface Leaderboard extends LeaderboardBase, HasRaceColumns {
|
||||
*
|
||||
* @param discardedRaceColumns
|
||||
* expected to be the result of what we would get if we called {@link #getResultDiscardingRule()}.
|
||||
* {@link ResultDiscardingRule#getDiscardedRaceColumns(Competitor, Leaderboard, Iterable, TimePoint)
|
||||
* {@link ResultDiscardingRule#getDiscardedRaceColumns(Competitor, Leaderboard, Iterable, TimePoint, ScoringScheme)
|
||||
* getDiscardedRaceColumns(competitor, this, raceColumnsToConsider, timePoint)}.
|
||||
*/
|
||||
Entry getEntry(Competitor competitor, RaceColumn race, TimePoint timePoint, Set<RaceColumn> discardedRaceColumns) throws NoWindException;
|
||||
@@ -439,7 +439,7 @@ public interface Leaderboard extends LeaderboardBase, HasRaceColumns {
|
||||
* Fetches all entries for all competitors of all races tracked by this leaderboard in one sweep. This saves some
|
||||
* computational effort compared to fetching all entries separately, particularly because all
|
||||
* {@link #isDiscarded(Competitor, RaceColumn, TimePoint) discarded races} of a competitor are computed in one
|
||||
* sweep using {@link ResultDiscardingRule#getDiscardedRaceColumns(Competitor, Leaderboard, Iterable, TimePoint)} only once.
|
||||
* sweep using {@link ResultDiscardingRule#getDiscardedRaceColumns(Competitor, Leaderboard, Iterable, TimePoint, ScoringScheme)} only once.
|
||||
* Note that in order to get the {@link #getNetPoints(Competitor, TimePoint) total points} for a competitor
|
||||
* for the entire leaderboard, the {@link #getCarriedPoints(Competitor) carried-over points} need to be added.
|
||||
*/
|
||||
@@ -630,7 +630,7 @@ public interface Leaderboard extends LeaderboardBase, HasRaceColumns {
|
||||
*
|
||||
* @param discardedRaceColumns
|
||||
* expected to be the result of what we would get if we called {@link #getResultDiscardingRule()}.
|
||||
* {@link ResultDiscardingRule#getDiscardedRaceColumns(Competitor, Leaderboard, Iterable, TimePoint)
|
||||
* {@link ResultDiscardingRule#getDiscardedRaceColumns(Competitor, Leaderboard, Iterable, TimePoint, ScoringScheme)
|
||||
* getDiscardedRaceColumns(competitor, this, raceColumnsToConsider, timePoint)}.
|
||||
*/
|
||||
Double getNetPoints(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint,
|
||||
|
||||
+6
-5
@@ -21,19 +21,20 @@ public interface ResultDiscardingRule extends Serializable {
|
||||
/**
|
||||
* @param raceColumnsToConsider if a column is <code>not</code> contained, its existence will be ignored for determining the
|
||||
* columns to discard. It affects the count of races. Only columns contained can be part of the result.
|
||||
* @param scoringScheme TODO
|
||||
*/
|
||||
Set<RaceColumn> getDiscardedRaceColumns(Competitor competitor, Leaderboard leaderboard,
|
||||
Iterable<RaceColumn> raceColumnsToConsider, TimePoint timePoint);
|
||||
Iterable<RaceColumn> raceColumnsToConsider, TimePoint timePoint, ScoringScheme scoringScheme);
|
||||
|
||||
default Set<RaceColumn> getDiscardedRaceColumns(Competitor competitor, Leaderboard leaderboard,
|
||||
Iterable<RaceColumn> raceColumnsToConsider, TimePoint timePoint,
|
||||
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) {
|
||||
ScoringScheme scoringScheme, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) {
|
||||
return getDiscardedRaceColumns(competitor, leaderboard, raceColumnsToConsider, timePoint,
|
||||
raceColumn->leaderboard.getTotalPoints(competitor, raceColumn, timePoint, cache), cache);
|
||||
scoringScheme, raceColumn->leaderboard.getTotalPoints(competitor, raceColumn, timePoint, cache), cache);
|
||||
}
|
||||
|
||||
Set<RaceColumn> getDiscardedRaceColumns(Competitor competitor, Leaderboard leaderboard,
|
||||
Iterable<RaceColumn> raceColumnsToConsider, TimePoint timePoint,
|
||||
Function<RaceColumn, Double> totalPointsSupplier,
|
||||
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache);
|
||||
ScoringScheme scoringScheme,
|
||||
Function<RaceColumn, Double> totalPointsSupplier, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache);
|
||||
}
|
||||
|
||||
+2
-2
@@ -94,7 +94,7 @@ public interface ScoringScheme extends Serializable {
|
||||
* scores of the second competitor, in the order of race columns in the leaderboard
|
||||
* @param discardedRaceColumnsPerCompetitor
|
||||
* for each competitor holds the result of {@link Leaderboard#getResultDiscardingRule()
|
||||
* Leaderborad.getResultDiscardingRule()}{@code .}{@link ResultDiscardingRule#getDiscardedRaceColumns(Competitor, Leaderboard, Iterable, TimePoint)
|
||||
* Leaderborad.getResultDiscardingRule()}{@code .}{@link ResultDiscardingRule#getDiscardedRaceColumns(Competitor, Leaderboard, Iterable, TimePoint, ScoringScheme)
|
||||
* getDiscardedRaceColumns(...)}. This accelerates things considerable because we do not have to make this expensive calculation
|
||||
* for each competitor again.
|
||||
*/
|
||||
@@ -117,7 +117,7 @@ public interface ScoringScheme extends Serializable {
|
||||
* <p>
|
||||
*
|
||||
* <em>"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."</em>
|
||||
*/
|
||||
int compareByLastRace(List<Util.Pair<RaceColumn, Double>> o1Scores, List<Util.Pair<RaceColumn, Double>> o2Scores, boolean nullScoresAreBetter, Competitor o1, Competitor o2);
|
||||
|
||||
+1
-1
@@ -509,7 +509,7 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard {
|
||||
addOverallDetailsToRow(timePoint, competitor, row);
|
||||
}
|
||||
result.competitors.add(competitorDTO);
|
||||
final Set<RaceColumn> discardedRaceColumns = getResultDiscardingRule().getDiscardedRaceColumns(competitor, this, getRaceColumns(), timePoint);
|
||||
final Set<RaceColumn> discardedRaceColumns = getResultDiscardingRule().getDiscardedRaceColumns(competitor, this, getRaceColumns(), timePoint, getScoringScheme());
|
||||
for (final RaceColumn raceColumn : this.getRaceColumns()) {
|
||||
// in case boats can't change set the also the boat on the row to simplify access
|
||||
if (result.canBoatsOfCompetitorsChangePerRace == false && row.boat == null) {
|
||||
|
||||
+15
-12
@@ -34,6 +34,7 @@ import com.sap.sailing.domain.leaderboard.NumberOfCompetitorsInLeaderboardFetche
|
||||
import com.sap.sailing.domain.leaderboard.ResultDiscardingRule;
|
||||
import com.sap.sailing.domain.leaderboard.ScoreCorrection.Result;
|
||||
import com.sap.sailing.domain.leaderboard.ScoreCorrectionListener;
|
||||
import com.sap.sailing.domain.leaderboard.ScoringScheme;
|
||||
import com.sap.sailing.domain.leaderboard.SettableScoreCorrection;
|
||||
import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
|
||||
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
|
||||
@@ -426,7 +427,7 @@ public abstract class AbstractSimpleLeaderboardImpl extends AbstractLeaderboardW
|
||||
private boolean isDiscarded(Competitor competitor, RaceColumn raceColumn,
|
||||
Iterable<RaceColumn> raceColumnsToConsider, TimePoint timePoint) {
|
||||
final Set<RaceColumn> discardedRaceColumns = getResultDiscardingRule().getDiscardedRaceColumns(competitor, this,
|
||||
raceColumnsToConsider, timePoint);
|
||||
raceColumnsToConsider, timePoint, getScoringScheme());
|
||||
return isDiscarded(competitor, raceColumn, timePoint, discardedRaceColumns);
|
||||
}
|
||||
|
||||
@@ -438,7 +439,7 @@ public abstract class AbstractSimpleLeaderboardImpl extends AbstractLeaderboardW
|
||||
*
|
||||
* @param discardedRaceColumns
|
||||
* expected to be the result of what we would get if we called {@link #getResultDiscardingRule()}.
|
||||
* {@link ResultDiscardingRule#getDiscardedRaceColumns(Competitor, Leaderboard, Iterable, TimePoint)
|
||||
* {@link ResultDiscardingRule#getDiscardedRaceColumns(Competitor, Leaderboard, Iterable, TimePoint, ScoringScheme)
|
||||
* getDiscardedRaceColumns(competitor, this, raceColumnsToConsider, timePoint)}.
|
||||
*/
|
||||
private boolean isDiscarded(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint,
|
||||
@@ -456,7 +457,7 @@ public abstract class AbstractSimpleLeaderboardImpl extends AbstractLeaderboardW
|
||||
public Double getNetPoints(Competitor competitor, RaceColumn raceColumn, Iterable<RaceColumn> raceColumnsToConsider,
|
||||
TimePoint timePoint) {
|
||||
final Set<RaceColumn> discardedRaceColumns = getResultDiscardingRule().getDiscardedRaceColumns(competitor, this,
|
||||
raceColumnsToConsider, timePoint);
|
||||
raceColumnsToConsider, timePoint, getScoringScheme());
|
||||
return getNetPoints(competitor, raceColumn, timePoint, discardedRaceColumns);
|
||||
}
|
||||
|
||||
@@ -468,7 +469,7 @@ public abstract class AbstractSimpleLeaderboardImpl extends AbstractLeaderboardW
|
||||
*
|
||||
* @param discardedRaceColumns
|
||||
* expected to be the result of what we would get if we called {@link #getResultDiscardingRule()}.
|
||||
* {@link ResultDiscardingRule#getDiscardedRaceColumns(Competitor, Leaderboard, Iterable, TimePoint)
|
||||
* {@link ResultDiscardingRule#getDiscardedRaceColumns(Competitor, Leaderboard, Iterable, TimePoint, ScoringScheme)
|
||||
* getDiscardedRaceColumns(competitor, this, raceColumnsToConsider, timePoint)}.
|
||||
*/
|
||||
@Override
|
||||
@@ -508,7 +509,7 @@ public abstract class AbstractSimpleLeaderboardImpl extends AbstractLeaderboardW
|
||||
boolean needToResetScoreUponNextNonEmptyEntry = false;
|
||||
double result = getCarriedPoints(competitor);
|
||||
final Set<RaceColumn> discardedRaceColumns = getResultDiscardingRule().getDiscardedRaceColumns(competitor, this,
|
||||
raceColumnsToConsider, timePoint);
|
||||
raceColumnsToConsider, timePoint, getScoringScheme());
|
||||
for (RaceColumn raceColumn : raceColumnsToConsider) {
|
||||
if (raceColumn.isStartsWithZeroScore()) {
|
||||
needToResetScoreUponNextNonEmptyEntry = true;
|
||||
@@ -662,7 +663,7 @@ public abstract class AbstractSimpleLeaderboardImpl extends AbstractLeaderboardW
|
||||
public Entry getEntry(final Competitor competitor, final RaceColumn race, final TimePoint timePoint)
|
||||
throws NoWindException {
|
||||
final Set<RaceColumn> discardedRaceColumns = getResultDiscardingRule().getDiscardedRaceColumns(competitor, this,
|
||||
getRaceColumns(), timePoint);
|
||||
getRaceColumns(), timePoint, getScoringScheme());
|
||||
return getEntry(competitor, race, timePoint, discardedRaceColumns);
|
||||
}
|
||||
|
||||
@@ -674,7 +675,9 @@ public abstract class AbstractSimpleLeaderboardImpl extends AbstractLeaderboardW
|
||||
this, timePoint, new NumberOfCompetitorsFetcherImpl(), getScoringScheme());
|
||||
boolean discarded = isDiscarded(competitor, race, timePoint, discardedRaceColumns);
|
||||
final Double correctedScore = correctedResults.getCorrectedScore();
|
||||
return new EntryImpl(trackedRankProvider, correctedScore, () -> correctedResults.getUncorrectedScore(),
|
||||
final Double correctedScoreScaledByColumnFactor = correctedScore == null ? null
|
||||
: Double.valueOf((correctedScore * getScoringScheme().getScoreFactor(race)));
|
||||
return new EntryImpl(trackedRankProvider, correctedScoreScaledByColumnFactor, () -> correctedResults.getUncorrectedScore(),
|
||||
correctedResults.isCorrected(),
|
||||
discarded ? DOUBLE_0
|
||||
: correctedScore == null ? null : Double.valueOf(correctedScore * getScoringScheme().getScoreFactor(race)),
|
||||
@@ -743,16 +746,16 @@ public abstract class AbstractSimpleLeaderboardImpl extends AbstractLeaderboardW
|
||||
Set<RaceColumn> discardedRacesForCompetitor = discardedRaces.get(competitor);
|
||||
if (discardedRacesForCompetitor == null) {
|
||||
discardedRacesForCompetitor = getResultDiscardingRule().getDiscardedRaceColumns(competitor, this,
|
||||
getRaceColumns(), timePoint);
|
||||
getRaceColumns(), timePoint, getScoringScheme());
|
||||
discardedRaces.put(competitor, discardedRacesForCompetitor);
|
||||
}
|
||||
boolean discarded = discardedRacesForCompetitor.contains(raceColumn);
|
||||
final Double correctedScore = correctedResults.getCorrectedScore();
|
||||
Entry entry = new EntryImpl(trackedRankProvider, correctedScore,
|
||||
final Double correctedScoreScaledByColumnFactor = correctedScore == null ? null
|
||||
: Double.valueOf((correctedScore * getScoringScheme().getScoreFactor(raceColumn)));
|
||||
Entry entry = new EntryImpl(trackedRankProvider, correctedScoreScaledByColumnFactor,
|
||||
() -> correctedResults.getUncorrectedScore(), correctedResults.isCorrected(),
|
||||
discarded ? DOUBLE_0
|
||||
: (correctedScore == null ? null
|
||||
: Double.valueOf((correctedScore * getScoringScheme().getScoreFactor(raceColumn)))),
|
||||
discarded ? DOUBLE_0 : correctedScoreScaledByColumnFactor,
|
||||
correctedResults.getMaxPointsReason(), discarded, raceColumn.getFleetOfCompetitor(competitor));
|
||||
result.put(new com.sap.sse.common.Util.Pair<Competitor, RaceColumn>(competitor, raceColumn), entry);
|
||||
}
|
||||
|
||||
+1
-1
@@ -93,7 +93,7 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
|
||||
discardedRaceColumnsPerCompetitor = new HashMap<>();
|
||||
for (Competitor competitor : leaderboard.getCompetitors()) {
|
||||
Set<RaceColumn> discardedRaceColumns = leaderboard.getResultDiscardingRule().getDiscardedRaceColumns(
|
||||
competitor, leaderboard, raceColumnsToConsider, timePoint);
|
||||
competitor, leaderboard, raceColumnsToConsider, timePoint, leaderboard.getScoringScheme());
|
||||
this.discardedRaceColumnsPerCompetitor.put(competitor, discardedRaceColumns);
|
||||
for (RaceColumn raceColumn : raceColumnsToConsider) {
|
||||
Pair<Competitor, RaceColumn> key = new Util.Pair<Competitor, RaceColumn>(competitor, raceColumn);
|
||||
|
||||
+7
-4
@@ -11,6 +11,7 @@ import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.base.Series;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.ResultDiscardingRule;
|
||||
import com.sap.sailing.domain.leaderboard.ScoringScheme;
|
||||
import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCalculationReuseCache;
|
||||
import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
@@ -35,19 +36,21 @@ public class PerSeriesResultDiscardingRuleImpl implements ResultDiscardingRule {
|
||||
|
||||
@Override
|
||||
public Set<RaceColumn> getDiscardedRaceColumns(Competitor competitor, Leaderboard leaderboard,
|
||||
Iterable<RaceColumn> raceColumnsToConsider, TimePoint timePoint) {
|
||||
return getDiscardedRaceColumns(competitor, leaderboard, raceColumnsToConsider, timePoint, new LeaderboardDTOCalculationReuseCache(timePoint));
|
||||
Iterable<RaceColumn> raceColumnsToConsider, TimePoint timePoint, ScoringScheme scoringScheme) {
|
||||
return getDiscardedRaceColumns(competitor, leaderboard, raceColumnsToConsider, timePoint, scoringScheme, new LeaderboardDTOCalculationReuseCache(timePoint));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RaceColumn> getDiscardedRaceColumns(Competitor competitor, Leaderboard leaderboard,
|
||||
Iterable<RaceColumn> raceColumnsToConsider, TimePoint timePoint,
|
||||
Function<RaceColumn, Double> totalPointsSupplier, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) {
|
||||
ScoringScheme scoringScheme, Function<RaceColumn, Double> totalPointsSupplier,
|
||||
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) {
|
||||
final Set<RaceColumn> result = new HashSet<>();
|
||||
for (final Series s : regatta.getSeries()) {
|
||||
if (s.getResultDiscardingRule() != null) {
|
||||
final Iterable<RaceColumn> columnsToConsiderInSeries = getColumnsToConsiderInSeries(s, raceColumnsToConsider);
|
||||
result.addAll(s.getResultDiscardingRule().getDiscardedRaceColumns(competitor, leaderboard, columnsToConsiderInSeries, timePoint, totalPointsSupplier, cache));
|
||||
result.addAll(s.getResultDiscardingRule().getDiscardedRaceColumns(competitor, leaderboard, columnsToConsiderInSeries,
|
||||
timePoint, scoringScheme, totalPointsSupplier, cache));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
+8
-4
@@ -21,6 +21,7 @@ import com.sap.sailing.domain.base.RaceColumnInSeries;
|
||||
import com.sap.sailing.domain.base.Series;
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.ScoringScheme;
|
||||
import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
|
||||
import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCalculationReuseCache;
|
||||
import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache;
|
||||
@@ -80,14 +81,15 @@ public class ThresholdBasedResultDiscardingRuleImpl implements ThresholdBasedRes
|
||||
|
||||
@Override
|
||||
public Set<RaceColumn> getDiscardedRaceColumns(final Competitor competitor, final Leaderboard leaderboard,
|
||||
Iterable<RaceColumn> raceColumnsToConsider, final TimePoint timePoint) {
|
||||
return getDiscardedRaceColumns(competitor, leaderboard, raceColumnsToConsider, timePoint, new LeaderboardDTOCalculationReuseCache(timePoint));
|
||||
Iterable<RaceColumn> raceColumnsToConsider, final TimePoint timePoint, ScoringScheme scoringScheme) {
|
||||
return getDiscardedRaceColumns(competitor, leaderboard, raceColumnsToConsider, timePoint, scoringScheme, new LeaderboardDTOCalculationReuseCache(timePoint));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RaceColumn> getDiscardedRaceColumns(final Competitor competitor, final Leaderboard leaderboard,
|
||||
Iterable<RaceColumn> raceColumnsToConsider, final TimePoint timePoint,
|
||||
Function<RaceColumn, Double> totalPointsSupplier, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) {
|
||||
ScoringScheme scoringScheme, Function<RaceColumn, Double> totalPointsSupplier,
|
||||
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) {
|
||||
int resultsToDiscard = getNumberOfResultsToDiscard(competitor, raceColumnsToConsider, leaderboard, timePoint);
|
||||
final Set<RaceColumn> result;
|
||||
if (resultsToDiscard > 0) {
|
||||
@@ -96,7 +98,9 @@ public class ThresholdBasedResultDiscardingRuleImpl implements ThresholdBasedRes
|
||||
for (final RaceColumn raceColumn : raceColumnsToConsider) {
|
||||
if (raceColumn.isDiscardable()) {
|
||||
sortedRaces.add(raceColumn);
|
||||
totalPointsForCompetitorPerColumn.put(raceColumn, totalPointsSupplier.apply(raceColumn));
|
||||
final Double totalPoints = totalPointsSupplier.apply(raceColumn);
|
||||
totalPointsForCompetitorPerColumn.put(raceColumn,
|
||||
totalPoints == null ? null : (totalPoints * scoringScheme.getScoreFactor(raceColumn)));
|
||||
}
|
||||
}
|
||||
result = new HashSet<RaceColumn>();
|
||||
|
||||
+4
@@ -11,6 +11,10 @@
|
||||
did not properly grant its permissions to requests.</li>
|
||||
<li>Fixed a regression regarding the availability of <tt>/sailingserver/api/v1/regattas/{regatta-name}/datamining/...</tt>
|
||||
requests; a refactoring attempt accidentally introduced this problem which has now been resolved.</li>
|
||||
<li>Fixed an issue with column factors other than 1 in combination with excluding worst scores; previously,
|
||||
the points before multiplication by the column factor were compared for discarding.
|
||||
With this, the display of those discards has also been fixed such that the scaled number is displayed
|
||||
with a strike-through.</li>
|
||||
</ul>
|
||||
<h5 class="articleSubheadline">May 2022</h5>
|
||||
<ul class="bulletList">
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@ public class MarkPassingsJsonSerializer extends AbstractTrackedRaceDataJsonSeria
|
||||
return totalPointsForRaceColumn;
|
||||
};
|
||||
final Set<RaceColumn> discardedRaceColumns = leaderboard.getResultDiscardingRule().getDiscardedRaceColumns(competitor, leaderboard,
|
||||
leaderboard.getRaceColumns(), markPassing.getTimePoint(), totalPointsSupplier, cache);
|
||||
leaderboard.getRaceColumns(), markPassing.getTimePoint(), leaderboard.getScoringScheme(), totalPointsSupplier, cache);
|
||||
final Double netPoints = leaderboard.getNetPoints(competitor, raceColumnAndFleet.getA(),
|
||||
markPassing.getTimePoint(), discardedRaceColumns, ()->totalPoints);
|
||||
markPassingJson.put(POINTS_BASED_ON_PASSING_ORDER, totalPoints);
|
||||
|
||||
+35
@@ -94,6 +94,41 @@ public class LeaderboardDiscardingRulesTest {
|
||||
assertEquals(123.+123., netPointsHasso, 0.000000001);
|
||||
}
|
||||
|
||||
/**
|
||||
* See bug 892: If a competitor has two or more equally-scored races of which the to-be-discarded number
|
||||
* has to be discarded, ensure that not only one but all of them are discarded and that the sailor isn't awarded
|
||||
* more races sailed than the competition
|
||||
*/
|
||||
@Test
|
||||
public void testDiscardingRulesWithColumnFactor() throws NoWindException {
|
||||
racingEventService.removeLeaderboard(LEADERBOARDNAME);
|
||||
racingEventService.addFlexibleLeaderboard(LEADERBOARDNAME, null, new int[] { 2 }, new LowPoint(), Collections.emptySet());
|
||||
FlexibleLeaderboard leaderboard = (FlexibleLeaderboard) racingEventService.getLeaderboardByName(LEADERBOARDNAME);
|
||||
assertNotNull(leaderboard);
|
||||
BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("505", /* typicallyStartsUpwind */ true);
|
||||
CompetitorWithBoat hasso = AbstractLeaderboardTest.createCompetitorWithBoat("Dr. Hasso Plattner");
|
||||
final TrackedRace race1 = new MockedTrackedRaceWithFixedRank(hasso, /* rank */ 5, /* started */ true, boatClass);
|
||||
leaderboard.addRace(race1, "R1", /* medalRace */false).setFactor(2.0); // results in score 10
|
||||
final TrackedRace race2 = new MockedTrackedRaceWithFixedRank(hasso, /* rank */ 9, /* started */ true, boatClass);
|
||||
leaderboard.addRace(race2, "R2", /* medalRace */false);
|
||||
CompetitorWithBoat wolfgang = AbstractLeaderboardTest.createCompetitorWithBoat("Wolfgang Hunger");
|
||||
final TrackedRace race3 = new MockedTrackedRaceWithFixedRank(wolfgang, /* rank */ 123, /* started */ true, boatClass);
|
||||
leaderboard.addRace(race3, "R3", /* medalRace */false);
|
||||
final TrackedRace race4 = new MockedTrackedRaceWithFixedRank(wolfgang, /* rank */ 124, /* started */ true, boatClass);
|
||||
leaderboard.addRace(race4, "R4", /* medalRace */false);
|
||||
leaderboard.getScoreCorrection().correctScore(hasso, leaderboard.getRaceColumnByName("R3"), 6.);
|
||||
leaderboard.getScoreCorrection().correctScore(hasso, leaderboard.getRaceColumnByName("R4"), 3.);
|
||||
leaderboard.getScoreCorrection().correctScore(wolfgang, leaderboard.getRaceColumnByName("R1"), 1.); // results in score 2.0
|
||||
leaderboard.getScoreCorrection().correctScore(wolfgang, leaderboard.getRaceColumnByName("R2"), 2.);
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
// Hunger scores better than Plattner in this case because Hunger's two discards are 123/124, keeping 122/122
|
||||
// whereas Plattner is to discard two of the four 123 results, keeping 123/123, being two points worse than Hunger:
|
||||
double netPointsHasso = leaderboard.getNetPoints(hasso, now);
|
||||
double netPointsWolfgang = leaderboard.getNetPoints(wolfgang, now);
|
||||
assertEquals(123. + 2. + 2., netPointsWolfgang, 0.0000000001); // discards the 124.0 in R4
|
||||
assertEquals(9. + 6. + 3., netPointsHasso, 0.000000001);
|
||||
}
|
||||
|
||||
/**
|
||||
* See bug 892: If a competitor has two or more equally-scored races of which the to-be-discarded number
|
||||
* has to be discarded, ensure that not only one but all of them are discarded and that the sailor isn't awarded
|
||||
|
||||
Reference in New Issue
Block a user