From 38f5a6caf632f6c5f18b07e3fa75dd5d0f220164 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Thu, 23 Jun 2022 17:39:31 +0200 Subject: [PATCH] bug5752: fixed discarding and display of discarded results in columns with factors != 1 --- .../LeaderboardScoringAndRankingTestBase.java | 2 +- .../domain/leaderboard/Leaderboard.java | 6 ++-- .../leaderboard/ResultDiscardingRule.java | 11 +++--- .../domain/leaderboard/ScoringScheme.java | 4 +-- .../impl/AbstractLeaderboardWithCache.java | 2 +- .../impl/AbstractSimpleLeaderboardImpl.java | 27 +++++++------- .../impl/LeaderboardTotalRankComparator.java | 2 +- .../PerSeriesResultDiscardingRuleImpl.java | 11 +++--- ...hresholdBasedResultDiscardingRuleImpl.java | 12 ++++--- .../resources/SailingAnalyticsNotes.html | 4 +++ .../impl/MarkPassingsJsonSerializer.java | 2 +- .../test/LeaderboardDiscardingRulesTest.java | 35 +++++++++++++++++++ 12 files changed, 84 insertions(+), 34 deletions(-) diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTestBase.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTestBase.java index df9b65a3bf2..056b76fa58f 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTestBase.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTestBase.java @@ -55,7 +55,7 @@ public class LeaderboardScoringAndRankingTestBase extends AbstractLeaderboardTes double[][] scoresAfterNRaces, TimePoint timePoint, Competitor[] competitors) throws NoWindException { for (int competitorIndex=0; competitorIndex discardedRaceColumns = leaderboard.getResultDiscardingRule() - .getDiscardedRaceColumns(competitors[competitorIndex], leaderboard, raceColumnsToConsider, timePoint); + .getDiscardedRaceColumns(competitors[competitorIndex], leaderboard, raceColumnsToConsider, timePoint, leaderboard.getScoringScheme()); for (int raceColumnIndex=0; raceColumnIndex 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, diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/ResultDiscardingRule.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/ResultDiscardingRule.java index 8552673467d..1a426d60a5d 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/ResultDiscardingRule.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/ResultDiscardingRule.java @@ -21,19 +21,20 @@ public interface ResultDiscardingRule extends Serializable { /** * @param raceColumnsToConsider if a column is not 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 getDiscardedRaceColumns(Competitor competitor, Leaderboard leaderboard, - Iterable raceColumnsToConsider, TimePoint timePoint); + Iterable raceColumnsToConsider, TimePoint timePoint, ScoringScheme scoringScheme); default Set getDiscardedRaceColumns(Competitor competitor, Leaderboard leaderboard, Iterable 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 getDiscardedRaceColumns(Competitor competitor, Leaderboard leaderboard, Iterable raceColumnsToConsider, TimePoint timePoint, - Function totalPointsSupplier, - WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); + ScoringScheme scoringScheme, + Function totalPointsSupplier, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); } 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 546e4464f58..66f10586dbc 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 @@ -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 { *

* * "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); 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 a4276256db7..c0696fec8c6 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 @@ -509,7 +509,7 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard { addOverallDetailsToRow(timePoint, competitor, row); } result.competitors.add(competitorDTO); - final Set discardedRaceColumns = getResultDiscardingRule().getDiscardedRaceColumns(competitor, this, getRaceColumns(), timePoint); + final Set 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) { 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 064579543d5..30ca039ad0e 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 @@ -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 raceColumnsToConsider, TimePoint timePoint) { final Set 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 raceColumnsToConsider, TimePoint timePoint) { final Set 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 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 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 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), entry); } 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 de64c9cfc7e..b0ed671fc65 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 @@ -93,7 +93,7 @@ public class LeaderboardTotalRankComparator implements Comparator { discardedRaceColumnsPerCompetitor = new HashMap<>(); for (Competitor competitor : leaderboard.getCompetitors()) { Set discardedRaceColumns = leaderboard.getResultDiscardingRule().getDiscardedRaceColumns( - competitor, leaderboard, raceColumnsToConsider, timePoint); + competitor, leaderboard, raceColumnsToConsider, timePoint, leaderboard.getScoringScheme()); this.discardedRaceColumnsPerCompetitor.put(competitor, discardedRaceColumns); for (RaceColumn raceColumn : raceColumnsToConsider) { Pair key = new Util.Pair(competitor, raceColumn); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/PerSeriesResultDiscardingRuleImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/PerSeriesResultDiscardingRuleImpl.java index 6f4abbe0c14..8aed687cfec 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/PerSeriesResultDiscardingRuleImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/PerSeriesResultDiscardingRuleImpl.java @@ -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 getDiscardedRaceColumns(Competitor competitor, Leaderboard leaderboard, - Iterable raceColumnsToConsider, TimePoint timePoint) { - return getDiscardedRaceColumns(competitor, leaderboard, raceColumnsToConsider, timePoint, new LeaderboardDTOCalculationReuseCache(timePoint)); + Iterable raceColumnsToConsider, TimePoint timePoint, ScoringScheme scoringScheme) { + return getDiscardedRaceColumns(competitor, leaderboard, raceColumnsToConsider, timePoint, scoringScheme, new LeaderboardDTOCalculationReuseCache(timePoint)); } @Override public Set getDiscardedRaceColumns(Competitor competitor, Leaderboard leaderboard, Iterable raceColumnsToConsider, TimePoint timePoint, - Function totalPointsSupplier, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { + ScoringScheme scoringScheme, Function totalPointsSupplier, + WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Set result = new HashSet<>(); for (final Series s : regatta.getSeries()) { if (s.getResultDiscardingRule() != null) { final Iterable 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; 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 f24a7ef7691..89dce680cc6 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 @@ -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 getDiscardedRaceColumns(final Competitor competitor, final Leaderboard leaderboard, - Iterable raceColumnsToConsider, final TimePoint timePoint) { - return getDiscardedRaceColumns(competitor, leaderboard, raceColumnsToConsider, timePoint, new LeaderboardDTOCalculationReuseCache(timePoint)); + Iterable raceColumnsToConsider, final TimePoint timePoint, ScoringScheme scoringScheme) { + return getDiscardedRaceColumns(competitor, leaderboard, raceColumnsToConsider, timePoint, scoringScheme, new LeaderboardDTOCalculationReuseCache(timePoint)); } @Override public Set getDiscardedRaceColumns(final Competitor competitor, final Leaderboard leaderboard, Iterable raceColumnsToConsider, final TimePoint timePoint, - Function totalPointsSupplier, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { + ScoringScheme scoringScheme, Function totalPointsSupplier, + WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { int resultsToDiscard = getNumberOfResultsToDiscard(competitor, raceColumnsToConsider, leaderboard, timePoint); final Set 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(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/SailingAnalyticsNotes.html b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/SailingAnalyticsNotes.html index d88ee2d3ace..870d0bd44fb 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/SailingAnalyticsNotes.html +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/SailingAnalyticsNotes.html @@ -11,6 +11,10 @@ did not properly grant its permissions to requests.

  • Fixed a regression regarding the availability of /sailingserver/api/v1/regattas/{regatta-name}/datamining/... requests; a refactoring attempt accidentally introduced this problem which has now been resolved.
  • +
  • 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.
  • May 2022
      diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java index 9114ecf4da0..df71016dedb 100755 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java @@ -141,7 +141,7 @@ public class MarkPassingsJsonSerializer extends AbstractTrackedRaceDataJsonSeria return totalPointsForRaceColumn; }; final Set 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); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardDiscardingRulesTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardDiscardingRulesTest.java index e2126162931..9b32ae9759a 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardDiscardingRulesTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardDiscardingRulesTest.java @@ -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