mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-13 22:15:26 +00:00
Merge branch 'bug4661'
This commit is contained in:
commit
0d20ca2bec
26 files changed
+1160
-75
No files matched your search
+1
-8
@@ -209,15 +209,8 @@ public class RaceResultOfCompetitorWithContext implements HasRaceResultOfCompeti
|
||||
|
||||
@Override
|
||||
public Boolean isWin() {
|
||||
Leaderboard leaderboard = getLeaderboard();
|
||||
final TimePoint now = MillisecondsTimePoint.now();
|
||||
double points = leaderboard.getTotalPoints(competitor, raceColumn, now);
|
||||
if (leaderboard.getScoringScheme().isHigherBetter()) {
|
||||
double competitorCount = Util.size(leaderboard.getCompetitors());
|
||||
return points >= (competitorCount - 0.05);
|
||||
} else {
|
||||
return points <= 1.05;
|
||||
}
|
||||
return getLeaderboard().isWin(competitor, raceColumn, now);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -5,5 +5,5 @@ 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_LEAGUE_OVERALL, HIGH_POINT_MATCH_RACING, LOW_POINT_TIE_BREAK_BASED_ON_LAST_SERIES_ONLY, LOW_POINT_FIRST_TO_WIN_TWO_RACES
|
||||
}
|
||||
+900
@@ -0,0 +1,900 @@
|
||||
package com.sap.sailing.domain.test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.base.Series;
|
||||
import com.sap.sailing.domain.base.impl.FleetImpl;
|
||||
import com.sap.sailing.domain.base.impl.RegattaImpl;
|
||||
import com.sap.sailing.domain.base.impl.SeriesImpl;
|
||||
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;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
/**
|
||||
* This class contains several tests for the {@link LowPointFirstToWinTwoRaces} scoring rule defined by
|
||||
* {@link ScoringSchemeType#LOW_POINT_FIRST_TO_WIN_TWO_RACES}. It tests that the carry is correctly applied and that the
|
||||
* ordering is as expected. Furthermore it contains several negative tests, that validate, that the normal low point
|
||||
* behavior is not changed and still works for those same cases in case the {@link ScoringSchemeType#LOW_POINT} scoring
|
||||
* scheme is used.
|
||||
*/
|
||||
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<Competitor> yellow, List<Competitor> blue, TimePoint now) {
|
||||
RaceColumn qColumn = series.get(0).getRaceColumnByName("Q");
|
||||
TrackedRace qYellow = new MockedTrackedRaceWithStartTimeAndRanks(now, yellow);
|
||||
qColumn.setTrackedRace(qColumn.getFleetByName("Yellow"), qYellow);
|
||||
TrackedRace qBlue = new MockedTrackedRaceWithStartTimeAndRanks(now, blue);
|
||||
qColumn.setTrackedRace(qColumn.getFleetByName("Blue"), qBlue);
|
||||
}
|
||||
|
||||
private void manuallyTransferCarry(Leaderboard leaderboard, List<Competitor> medalCompetitors) {
|
||||
int carryScore = 1;
|
||||
for (Competitor medalCompetitor : medalCompetitors) {
|
||||
leaderboard.getScoreCorrection().correctScore(medalCompetitor, leaderboard.getRaceColumnByName("Carry"), carryScore++);
|
||||
}
|
||||
}
|
||||
|
||||
private Regatta setupRegatta(boolean useFirstTwoWins) {
|
||||
final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true);
|
||||
Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass,
|
||||
false, /* startDate */ null, /* endDate */ null, series, /* persistent */false,
|
||||
DomainFactory.INSTANCE
|
||||
.createScoringScheme(useFirstTwoWins ? ScoringSchemeType.LOW_POINT_FIRST_TO_WIN_TWO_RACES
|
||||
: ScoringSchemeType.LOW_POINT),
|
||||
"123", /* course area */null, OneDesignRankingMetric::new);
|
||||
return regatta;
|
||||
}
|
||||
|
||||
private void setupMedalSeriesWithCarryOverAndFourRaceColumns() {
|
||||
Set<? extends Fleet> medalFleets = Collections.singleton(new FleetImpl("Default"));
|
||||
List<String> medalRaceColumnNames = new ArrayList<String>();
|
||||
medalRaceColumnNames.add("Carry");
|
||||
medalRaceColumnNames.add("M1");
|
||||
medalRaceColumnNames.add("M2");
|
||||
medalRaceColumnNames.add("M3");
|
||||
medalRaceColumnNames.add("M4");
|
||||
Series medalSeries = new SeriesImpl("Medal", /* isMedal */true, /* isFleetsCanRunInParallel */ true,
|
||||
medalFleets, medalRaceColumnNames, /* trackedRegattaRegistry */ null);
|
||||
medalSeries.setFirstColumnIsNonDiscardableCarryForward(true);
|
||||
medalSeries.setStartsWithZeroScore(true);
|
||||
series.add(medalSeries);
|
||||
}
|
||||
|
||||
private void setupQualificationSeriesWithOneRaceColumn() {
|
||||
List<Fleet> qualificationFleets = new ArrayList<Fleet>();
|
||||
for (String qualificationFleetName : new String[] { "Yellow", "Blue" }) {
|
||||
qualificationFleets.add(new FleetImpl(qualificationFleetName));
|
||||
}
|
||||
List<String> qualificationRaceColumnNames = new ArrayList<String>();
|
||||
qualificationRaceColumnNames.add("Q");
|
||||
Series qualificationSeries = new SeriesImpl("Qualification", /* isMedal */false,
|
||||
/* isFleetsCanRunInParallel */ true, qualificationFleets, qualificationRaceColumnNames,
|
||||
/* trackedRegattaRegistry */ null);
|
||||
series.add(qualificationSeries);
|
||||
}
|
||||
|
||||
private List<Pair<Competitor, Double>> createCompetitorResultForTimestamp(TimePoint time, Leaderboard leaderboard) {
|
||||
List<Pair<Competitor, Double>> list = new ArrayList<>();
|
||||
for (Competitor competitor : leaderboard.getCompetitorsFromBestToWorst(time)) {
|
||||
list.add(new Pair<Competitor, Double>(competitor, leaderboard.getNetPoints(competitor, time)));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private void assertNonFinalistsAreBehindFinalistsAndNotChanged(
|
||||
List<Pair<Competitor, Double>> preSeriesScoreRankResult, List<Pair<Competitor, Double>> afterFinalResults) {
|
||||
List<Pair<Competitor, Double>> nonFinalistsPreScore = preSeriesScoreRankResult.subList(4,
|
||||
preSeriesScoreRankResult.size());
|
||||
List<Pair<Competitor, Double>> nonFinalistsAfterScore = afterFinalResults.subList(4, afterFinalResults.size());
|
||||
Assert.assertEquals(nonFinalistsPreScore, nonFinalistsAfterScore);
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test the preseries winner will win the first race, and should get a score of 2, all other finalists
|
||||
* should be scored with Low_Points restarting at 0 for the medal series. The non finalists score should not change
|
||||
* during the medalseries.
|
||||
*/
|
||||
@Test
|
||||
public void testFirstPreseriesWinsAgain() throws NoWindException {
|
||||
series = new ArrayList<Series>();
|
||||
setupQualificationSeriesWithOneRaceColumn();
|
||||
|
||||
setupMedalSeriesWithCarryOverAndFourRaceColumns();
|
||||
Regatta regatta = setupRegatta(true);
|
||||
List<Competitor> competitors = createCompetitors(12);
|
||||
List<Competitor> yellow = new ArrayList<>(competitors.subList(0, 6));
|
||||
List<Competitor> blue = new ArrayList<>(competitors);
|
||||
blue.removeAll(yellow);
|
||||
Collections.shuffle(yellow);
|
||||
Collections.shuffle(blue);
|
||||
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis() + 1000);
|
||||
executePreSeries(yellow, blue, now);
|
||||
|
||||
List<Competitor> preSeriesRankResult = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
List<Competitor> medalCompetitorsBestToWorst = preSeriesRankResult.subList(0, 4);
|
||||
List<Pair<Competitor, Double>> preSeriesScoreRankResult = createCompetitorResultForTimestamp(later,
|
||||
leaderboard);
|
||||
|
||||
manuallyTransferCarry(leaderboard, medalCompetitorsBestToWorst);
|
||||
|
||||
Competitor preFirst = medalCompetitorsBestToWorst.get(0);
|
||||
Competitor preSecond = medalCompetitorsBestToWorst.get(1);
|
||||
Competitor preThird = medalCompetitorsBestToWorst.get(2);
|
||||
Competitor preFourth = medalCompetitorsBestToWorst.get(3);
|
||||
|
||||
RaceColumn m1 = leaderboard.getRaceColumnByName("M1");
|
||||
|
||||
ArrayList<Competitor> m1Results = new ArrayList<>();
|
||||
m1Results.add(preFirst);
|
||||
m1Results.add(preSecond);
|
||||
m1Results.add(preThird);
|
||||
m1Results.add(preFourth);
|
||||
|
||||
TrackedRace mDefault = new MockedTrackedRaceWithStartTimeAndRanks(now, m1Results);
|
||||
m1.setTrackedRace(m1.getFleetByName("Default"), mDefault);
|
||||
|
||||
Assert.assertEquals(2.0, leaderboard.getNetPoints(preFirst, later), EPSILON);
|
||||
Assert.assertEquals(4, leaderboard.getNetPoints(preSecond, later), EPSILON);
|
||||
Assert.assertEquals(6, leaderboard.getNetPoints(preThird, later), EPSILON);
|
||||
Assert.assertEquals(8, leaderboard.getNetPoints(preFourth, later), EPSILON);
|
||||
|
||||
List<Pair<Competitor, Double>> afterFinalResults = createCompetitorResultForTimestamp(later, leaderboard);
|
||||
assertNonFinalistsAreBehindFinalistsAndNotChanged(preSeriesScoreRankResult, afterFinalResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test the second best in the preseries wins the first two medal races, and should get a score of 2, all
|
||||
* other finalists should be scored with Low_Points restarting at 0 for the medal series. The non finalists score
|
||||
* should not change during the medalseries.
|
||||
*/
|
||||
@Test
|
||||
public void testSecondPreSeriesWinsTwice() throws NoWindException {
|
||||
series = new ArrayList<Series>();
|
||||
// -------- qualification series ------------
|
||||
setupQualificationSeriesWithOneRaceColumn();
|
||||
setupMedalSeriesWithCarryOverAndFourRaceColumns();
|
||||
Regatta regatta = setupRegatta(true);
|
||||
List<Competitor> competitors = createCompetitors(12);
|
||||
List<Competitor> yellow = new ArrayList<>(competitors.subList(0, 6));
|
||||
List<Competitor> blue = new ArrayList<>(competitors);
|
||||
blue.removeAll(yellow);
|
||||
Collections.shuffle(yellow);
|
||||
Collections.shuffle(blue);
|
||||
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis() + 1000);
|
||||
executePreSeries(yellow, blue, now);
|
||||
|
||||
List<Competitor> preSeriesRankResult = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
List<Competitor> medalCompetitorsBestToWorst = preSeriesRankResult.subList(0, 4);
|
||||
List<Pair<Competitor, Double>> preSeriesScoreRankResult = createCompetitorResultForTimestamp(later,
|
||||
leaderboard);
|
||||
manuallyTransferCarry(leaderboard, medalCompetitorsBestToWorst);
|
||||
|
||||
Competitor preFirst = medalCompetitorsBestToWorst.get(0);
|
||||
Competitor preSecond = medalCompetitorsBestToWorst.get(1);
|
||||
Competitor preThird = medalCompetitorsBestToWorst.get(2);
|
||||
Competitor preFourth = medalCompetitorsBestToWorst.get(3);
|
||||
|
||||
RaceColumn m1 = leaderboard.getRaceColumnByName("M1");
|
||||
|
||||
ArrayList<Competitor> m1Results = new ArrayList<>();
|
||||
m1Results.add(preSecond);
|
||||
m1Results.add(preFirst);
|
||||
m1Results.add(preThird);
|
||||
m1Results.add(preFourth);
|
||||
|
||||
TimePoint m1now = new MillisecondsTimePoint(later.asMillis() + 1000);
|
||||
TimePoint m1later = new MillisecondsTimePoint(m1now.asMillis() + 1000);
|
||||
|
||||
TrackedRace m1Default = new MockedTrackedRaceWithStartTimeAndRanks(now, m1Results);
|
||||
m1.setTrackedRace(m1.getFleetByName("Default"), m1Default);
|
||||
|
||||
Assert.assertEquals(3, leaderboard.getNetPoints(preSecond, later), EPSILON);
|
||||
Assert.assertEquals(3, leaderboard.getNetPoints(preFirst, later), EPSILON);
|
||||
Assert.assertEquals(6, leaderboard.getNetPoints(preThird, later), EPSILON);
|
||||
Assert.assertEquals(8, leaderboard.getNetPoints(preFourth, later), EPSILON);
|
||||
|
||||
List<Competitor> res = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
Assert.assertEquals(res.get(0), preFirst);
|
||||
Assert.assertEquals(res.get(1), preSecond);
|
||||
|
||||
RaceColumn m2 = leaderboard.getRaceColumnByName("M2");
|
||||
|
||||
ArrayList<Competitor> m2Results = new ArrayList<>();
|
||||
m2Results.add(preSecond);
|
||||
m2Results.add(preFirst);
|
||||
m2Results.add(preThird);
|
||||
m2Results.add(preFourth);
|
||||
|
||||
TimePoint m2now = new MillisecondsTimePoint(m1later.asMillis() + 1000);
|
||||
TimePoint m2later = new MillisecondsTimePoint(m2now.asMillis() + 1000);
|
||||
TrackedRace m2Default = new MockedTrackedRaceWithStartTimeAndRanks(m2now, m2Results);
|
||||
m2.setTrackedRace(m1.getFleetByName("Default"), m2Default);
|
||||
|
||||
Assert.assertEquals(4.0, leaderboard.getNetPoints(preSecond, m2later), EPSILON);
|
||||
Assert.assertEquals(5.0, leaderboard.getNetPoints(preFirst, m2later), EPSILON);
|
||||
Assert.assertEquals(9, leaderboard.getNetPoints(preThird, m2later), EPSILON);
|
||||
Assert.assertEquals(12, leaderboard.getNetPoints(preFourth, m2later), EPSILON);
|
||||
|
||||
List<Competitor> res2 = leaderboard.getCompetitorsFromBestToWorst(m2later);
|
||||
Assert.assertEquals(res2.get(0), preSecond);
|
||||
Assert.assertEquals(res2.get(1), preFirst);
|
||||
Assert.assertEquals(res2.get(2), preThird);
|
||||
Assert.assertEquals(res2.get(3), preFourth);
|
||||
|
||||
List<Pair<Competitor, Double>> afterFinalResults = createCompetitorResultForTimestamp(m2later, leaderboard);
|
||||
assertNonFinalistsAreBehindFinalistsAndNotChanged(preSeriesScoreRankResult, afterFinalResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test the best in the preseries wins the second medal race, and should get a score of 2, all other
|
||||
* finalists should be scored with Low_Points restarting at 0 for the medal series. The non finalists score should
|
||||
* not change during the medalseries. Also asserts that during tie-breaking the pre-series carry score takes
|
||||
* precedence.
|
||||
*/
|
||||
@Test
|
||||
public void testFirstWinsSecondRace() throws NoWindException {
|
||||
series = new ArrayList<Series>();
|
||||
// -------- qualification series ------------
|
||||
setupQualificationSeriesWithOneRaceColumn();
|
||||
setupMedalSeriesWithCarryOverAndFourRaceColumns();
|
||||
Regatta regatta = setupRegatta(true);
|
||||
List<Competitor> competitors = createCompetitors(12);
|
||||
List<Competitor> yellow = new ArrayList<>(competitors.subList(0, 6));
|
||||
List<Competitor> blue = new ArrayList<>(competitors);
|
||||
blue.removeAll(yellow);
|
||||
Collections.shuffle(yellow);
|
||||
Collections.shuffle(blue);
|
||||
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis() + 1000);
|
||||
executePreSeries(yellow, blue, now);
|
||||
|
||||
List<Competitor> preSeriesRankResult = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
List<Competitor> medalCompetitorsBestToWorst = preSeriesRankResult.subList(0, 4);
|
||||
List<Pair<Competitor, Double>> preSeriesScoreRankResult = createCompetitorResultForTimestamp(later,
|
||||
leaderboard);
|
||||
manuallyTransferCarry(leaderboard, medalCompetitorsBestToWorst);
|
||||
|
||||
Competitor preFirst = medalCompetitorsBestToWorst.get(0);
|
||||
Competitor preSecond = medalCompetitorsBestToWorst.get(1);
|
||||
Competitor preThird = medalCompetitorsBestToWorst.get(2);
|
||||
Competitor preFourth = medalCompetitorsBestToWorst.get(3);
|
||||
|
||||
RaceColumn m1 = leaderboard.getRaceColumnByName("M1");
|
||||
|
||||
ArrayList<Competitor> m1Results = new ArrayList<>();
|
||||
m1Results.add(preSecond);
|
||||
m1Results.add(preFirst);
|
||||
m1Results.add(preThird);
|
||||
m1Results.add(preFourth);
|
||||
|
||||
TimePoint m1now = new MillisecondsTimePoint(later.asMillis() + 1000);
|
||||
TimePoint m1later = new MillisecondsTimePoint(m1now.asMillis() + 1000);
|
||||
|
||||
TrackedRace m1Default = new MockedTrackedRaceWithStartTimeAndRanks(now, m1Results);
|
||||
m1.setTrackedRace(m1.getFleetByName("Default"), m1Default);
|
||||
|
||||
Assert.assertEquals(3, leaderboard.getNetPoints(preSecond, later), EPSILON);
|
||||
Assert.assertEquals(3, leaderboard.getNetPoints(preFirst, later), EPSILON);
|
||||
Assert.assertEquals(6, leaderboard.getNetPoints(preThird, later), EPSILON);
|
||||
Assert.assertEquals(8, leaderboard.getNetPoints(preFourth, later), EPSILON);
|
||||
// assert that during tie-breaking the pre-series carry score takes precedence
|
||||
List<Competitor> res = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
Assert.assertEquals(res.get(0), preFirst);
|
||||
Assert.assertEquals(res.get(1), preSecond);
|
||||
|
||||
RaceColumn m2 = leaderboard.getRaceColumnByName("M2");
|
||||
|
||||
ArrayList<Competitor> m2Results = new ArrayList<>();
|
||||
m2Results.add(preFirst);
|
||||
m2Results.add(preSecond);
|
||||
m2Results.add(preThird);
|
||||
m2Results.add(preFourth);
|
||||
|
||||
TimePoint m2now = new MillisecondsTimePoint(m1later.asMillis() + 1000);
|
||||
TimePoint m2later = new MillisecondsTimePoint(m2now.asMillis() + 1000);
|
||||
TrackedRace m2Default = new MockedTrackedRaceWithStartTimeAndRanks(m2now, m2Results);
|
||||
m2.setTrackedRace(m1.getFleetByName("Default"), m2Default);
|
||||
|
||||
Assert.assertEquals(4, leaderboard.getNetPoints(preFirst, m2later), EPSILON);
|
||||
Assert.assertEquals(5, leaderboard.getNetPoints(preSecond, m2later), EPSILON);
|
||||
Assert.assertEquals(9, leaderboard.getNetPoints(preThird, m2later), EPSILON);
|
||||
Assert.assertEquals(12, leaderboard.getNetPoints(preFourth, m2later), EPSILON);
|
||||
|
||||
List<Competitor> res2 = leaderboard.getCompetitorsFromBestToWorst(m2later);
|
||||
Assert.assertEquals(res2.get(0), preFirst);
|
||||
Assert.assertEquals(res2.get(1), preSecond);
|
||||
Assert.assertEquals(res2.get(2), preThird);
|
||||
Assert.assertEquals(res2.get(3), preFourth);
|
||||
|
||||
List<Pair<Competitor, Double>> afterFinalResults = createCompetitorResultForTimestamp(m2later, leaderboard);
|
||||
assertNonFinalistsAreBehindFinalistsAndNotChanged(preSeriesScoreRankResult, afterFinalResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test the worst finalist of the qualification wins the first and second medal races, and should get a
|
||||
* score of 2, all other finalists should be scored with Low_Points restarting at 0 for the medal series. The non
|
||||
* finalists score should not change during the medalseries
|
||||
*/
|
||||
@Test
|
||||
public void testLastWinsTwoRaces() throws NoWindException {
|
||||
series = new ArrayList<Series>();
|
||||
// -------- qualification series ------------
|
||||
setupQualificationSeriesWithOneRaceColumn();
|
||||
setupMedalSeriesWithCarryOverAndFourRaceColumns();
|
||||
Regatta regatta = setupRegatta(true);
|
||||
List<Competitor> competitors = createCompetitors(12);
|
||||
List<Competitor> yellow = new ArrayList<>(competitors.subList(0, 6));
|
||||
List<Competitor> blue = new ArrayList<>(competitors);
|
||||
blue.removeAll(yellow);
|
||||
Collections.shuffle(yellow);
|
||||
Collections.shuffle(blue);
|
||||
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis() + 1000);
|
||||
executePreSeries(yellow, blue, now);
|
||||
|
||||
List<Competitor> preSeriesRankResult = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
List<Competitor> medalCompetitorsBestToWorst = preSeriesRankResult.subList(0, 4);
|
||||
List<Pair<Competitor, Double>> preSeriesScoreRankResult = createCompetitorResultForTimestamp(later,
|
||||
leaderboard);
|
||||
manuallyTransferCarry(leaderboard, medalCompetitorsBestToWorst);
|
||||
|
||||
Competitor preFirst = medalCompetitorsBestToWorst.get(0);
|
||||
Competitor preSecond = medalCompetitorsBestToWorst.get(1);
|
||||
Competitor preThird = medalCompetitorsBestToWorst.get(2);
|
||||
Competitor preFourth = medalCompetitorsBestToWorst.get(3);
|
||||
|
||||
RaceColumn m1 = leaderboard.getRaceColumnByName("M1");
|
||||
|
||||
ArrayList<Competitor> m1Results = new ArrayList<>();
|
||||
m1Results.add(preFourth);
|
||||
m1Results.add(preFirst);
|
||||
m1Results.add(preSecond);
|
||||
m1Results.add(preThird);
|
||||
|
||||
TimePoint m1now = new MillisecondsTimePoint(later.asMillis() + 1000);
|
||||
TimePoint m1later = new MillisecondsTimePoint(m1now.asMillis() + 1000);
|
||||
|
||||
TrackedRace m1Default = new MockedTrackedRaceWithStartTimeAndRanks(now, m1Results);
|
||||
m1.setTrackedRace(m1.getFleetByName("Default"), m1Default);
|
||||
|
||||
Assert.assertEquals(5, leaderboard.getNetPoints(preFourth, later), EPSILON);
|
||||
Assert.assertEquals(3.0, leaderboard.getNetPoints(preFirst, later), EPSILON);
|
||||
Assert.assertEquals(5, leaderboard.getNetPoints(preSecond, later), EPSILON);
|
||||
Assert.assertEquals(7, leaderboard.getNetPoints(preThird, later), EPSILON);
|
||||
|
||||
List<Competitor> res = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
Assert.assertEquals(res.get(0), preFirst);
|
||||
Assert.assertEquals(res.get(1), preSecond);
|
||||
Assert.assertEquals(res.get(2), preFourth);
|
||||
|
||||
RaceColumn m2 = leaderboard.getRaceColumnByName("M2");
|
||||
|
||||
ArrayList<Competitor> m2Results = new ArrayList<>();
|
||||
m2Results.add(preFourth);
|
||||
m2Results.add(preFirst);
|
||||
m2Results.add(preSecond);
|
||||
m2Results.add(preThird);
|
||||
|
||||
TimePoint m2now = new MillisecondsTimePoint(m1later.asMillis() + 1000);
|
||||
TimePoint m2later = new MillisecondsTimePoint(m2now.asMillis() + 1000);
|
||||
TrackedRace m2Default = new MockedTrackedRaceWithStartTimeAndRanks(m2now, m2Results);
|
||||
m2.setTrackedRace(m1.getFleetByName("Default"), m2Default);
|
||||
|
||||
Assert.assertEquals(6.0, leaderboard.getNetPoints(preFourth, m2later), EPSILON);
|
||||
Assert.assertEquals(5.0, leaderboard.getNetPoints(preFirst, m2later), EPSILON);
|
||||
Assert.assertEquals(8, leaderboard.getNetPoints(preSecond, m2later), EPSILON);
|
||||
Assert.assertEquals(11, leaderboard.getNetPoints(preThird, m2later), EPSILON);
|
||||
|
||||
List<Competitor> res2 = leaderboard.getCompetitorsFromBestToWorst(m2later);
|
||||
Assert.assertEquals(res2.get(0), preFourth);
|
||||
Assert.assertEquals(res2.get(1), preFirst);
|
||||
Assert.assertEquals(res2.get(2), preSecond);
|
||||
Assert.assertEquals(res2.get(3), preThird);
|
||||
|
||||
List<Pair<Competitor, Double>> afterFinalResults = createCompetitorResultForTimestamp(m2later, leaderboard);
|
||||
assertNonFinalistsAreBehindFinalistsAndNotChanged(preSeriesScoreRankResult, afterFinalResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test no finalist reaches two wins before terminating (eg. due to bad weather) all finalists should be
|
||||
* scored with Low_Points restarting at 0 for the medal series. The non finalists score should not change during the
|
||||
* medalseries.
|
||||
*/
|
||||
@Test
|
||||
public void noTwoWinsAbortAfterTwoRacesAndTieBreaker() throws NoWindException {
|
||||
series = new ArrayList<Series>();
|
||||
// -------- qualification series ------------
|
||||
setupQualificationSeriesWithOneRaceColumn();
|
||||
setupMedalSeriesWithCarryOverAndFourRaceColumns();
|
||||
Regatta regatta = setupRegatta(true);
|
||||
List<Competitor> competitors = createCompetitors(12);
|
||||
List<Competitor> yellow = new ArrayList<>(competitors.subList(0, 6));
|
||||
List<Competitor> blue = new ArrayList<>(competitors);
|
||||
blue.removeAll(yellow);
|
||||
Collections.shuffle(yellow);
|
||||
Collections.shuffle(blue);
|
||||
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis() + 1000);
|
||||
executePreSeries(yellow, blue, now);
|
||||
|
||||
List<Competitor> preSeriesRankResult = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
List<Competitor> medalCompetitorsBestToWorst = preSeriesRankResult.subList(0, 4);
|
||||
List<Pair<Competitor, Double>> preSeriesScoreRankResult = createCompetitorResultForTimestamp(later,
|
||||
leaderboard);
|
||||
manuallyTransferCarry(leaderboard, medalCompetitorsBestToWorst);
|
||||
|
||||
Competitor preFirst = medalCompetitorsBestToWorst.get(0);
|
||||
Competitor preSecond = medalCompetitorsBestToWorst.get(1);
|
||||
Competitor preThird = medalCompetitorsBestToWorst.get(2);
|
||||
Competitor preFourth = medalCompetitorsBestToWorst.get(3);
|
||||
|
||||
RaceColumn m1 = leaderboard.getRaceColumnByName("M1");
|
||||
|
||||
ArrayList<Competitor> m1Results = new ArrayList<>();
|
||||
m1Results.add(preFourth);
|
||||
m1Results.add(preFirst);
|
||||
m1Results.add(preSecond);
|
||||
m1Results.add(preThird);
|
||||
|
||||
TimePoint m1now = new MillisecondsTimePoint(later.asMillis() + 1000);
|
||||
TimePoint m1later = new MillisecondsTimePoint(m1now.asMillis() + 1000);
|
||||
|
||||
TrackedRace m1Default = new MockedTrackedRaceWithStartTimeAndRanks(now, m1Results);
|
||||
m1.setTrackedRace(m1.getFleetByName("Default"), m1Default);
|
||||
|
||||
Assert.assertEquals(5, leaderboard.getNetPoints(preFourth, later), EPSILON);
|
||||
Assert.assertEquals(3.0, leaderboard.getNetPoints(preFirst, later), EPSILON);
|
||||
Assert.assertEquals(5, leaderboard.getNetPoints(preSecond, later), EPSILON);
|
||||
Assert.assertEquals(7, leaderboard.getNetPoints(preThird, later), EPSILON);
|
||||
|
||||
|
||||
List<Competitor> res = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
Assert.assertEquals(res.get(0), preFirst);
|
||||
Assert.assertEquals(res.get(1), preSecond);
|
||||
Assert.assertEquals(res.get(2), preFourth);
|
||||
|
||||
RaceColumn m2 = leaderboard.getRaceColumnByName("M2");
|
||||
|
||||
ArrayList<Competitor> m2Results = new ArrayList<>();
|
||||
m2Results.add(preThird);
|
||||
m2Results.add(preFirst);
|
||||
m2Results.add(preSecond);
|
||||
m2Results.add(preFourth);
|
||||
|
||||
TimePoint m2now = new MillisecondsTimePoint(m1later.asMillis() + 1000);
|
||||
TimePoint m2later = new MillisecondsTimePoint(m2now.asMillis() + 1000);
|
||||
TrackedRace m2Default = new MockedTrackedRaceWithStartTimeAndRanks(m2now, m2Results);
|
||||
m2.setTrackedRace(m1.getFleetByName("Default"), m2Default);
|
||||
|
||||
Assert.assertEquals(9, leaderboard.getNetPoints(preFourth, m2later), EPSILON);
|
||||
Assert.assertEquals(5.0, leaderboard.getNetPoints(preFirst, m2later), EPSILON);
|
||||
Assert.assertEquals(8, leaderboard.getNetPoints(preSecond, m2later), EPSILON);
|
||||
Assert.assertEquals(8, leaderboard.getNetPoints(preThird, m2later), EPSILON);
|
||||
|
||||
List<Pair<Competitor, Double>> afterFinalResults = createCompetitorResultForTimestamp(m2later, leaderboard);
|
||||
assertNonFinalistsAreBehindFinalistsAndNotChanged(preSeriesScoreRankResult, afterFinalResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Using normal lowpoints, being the best in the preseries and having an additional win in the medals, should not
|
||||
* make you the overall winner in case another finalist has a better score.
|
||||
*/
|
||||
@Test
|
||||
public void negativeTestFirstPreseriesWinsAgain() throws NoWindException {
|
||||
series = new ArrayList<Series>();
|
||||
setupQualificationSeriesWithOneRaceColumn();
|
||||
|
||||
setupMedalSeriesWithCarryOverAndFourRaceColumns();
|
||||
Regatta regatta = setupRegatta(false);
|
||||
List<Competitor> competitors = createCompetitors(12);
|
||||
List<Competitor> yellow = new ArrayList<>(competitors.subList(0, 6));
|
||||
List<Competitor> blue = new ArrayList<>(competitors);
|
||||
blue.removeAll(yellow);
|
||||
Collections.shuffle(yellow);
|
||||
Collections.shuffle(blue);
|
||||
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis() + 1000);
|
||||
executePreSeries(yellow, blue, now);
|
||||
|
||||
List<Competitor> preSeriesRankResult = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
List<Pair<Competitor, Double>> preSeriesScoreRankResult = createCompetitorResultForTimestamp(later,
|
||||
leaderboard);
|
||||
List<Competitor> medalCompetitors = preSeriesRankResult.subList(0, 4);
|
||||
|
||||
manuallyTransferCarry(leaderboard, medalCompetitors);
|
||||
|
||||
Competitor preFirst = medalCompetitors.get(0);
|
||||
Competitor preSecond = medalCompetitors.get(1);
|
||||
Competitor preThird = medalCompetitors.get(2);
|
||||
Competitor preFourth = medalCompetitors.get(3);
|
||||
|
||||
RaceColumn m1 = leaderboard.getRaceColumnByName("M1");
|
||||
|
||||
ArrayList<Competitor> m1Results = new ArrayList<>();
|
||||
m1Results.add(preFirst);
|
||||
m1Results.add(preSecond);
|
||||
m1Results.add(preThird);
|
||||
m1Results.add(preFourth);
|
||||
|
||||
TrackedRace mDefault = new MockedTrackedRaceWithStartTimeAndRanks(now, m1Results);
|
||||
m1.setTrackedRace(m1.getFleetByName("Default"), mDefault);
|
||||
|
||||
Assert.assertEquals(4, leaderboard.getNetPoints(preFirst, later), EPSILON);
|
||||
Assert.assertEquals(8, leaderboard.getNetPoints(preSecond, later), EPSILON);
|
||||
Assert.assertEquals(12, leaderboard.getNetPoints(preThird, later), EPSILON);
|
||||
Assert.assertEquals(16, leaderboard.getNetPoints(preFourth, later), EPSILON);
|
||||
Assert.assertEquals(1, leaderboard.getTotalRankOfCompetitor(preFirst, later));
|
||||
Assert.assertEquals(2, leaderboard.getTotalRankOfCompetitor(preSecond, later));
|
||||
Assert.assertEquals(3, leaderboard.getTotalRankOfCompetitor(preThird, later));
|
||||
Assert.assertEquals(4, leaderboard.getTotalRankOfCompetitor(preFourth, later));
|
||||
|
||||
List<Pair<Competitor, Double>> afterFinalResults = createCompetitorResultForTimestamp(later, leaderboard);
|
||||
assertNonFinalistsAreBehindFinalistsAndNotChanged(preSeriesScoreRankResult, afterFinalResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Using normal lowpoints, having two wins should not matter, also the racecolum factor is expected to be 2 instead
|
||||
* of 1.
|
||||
*/
|
||||
@Test
|
||||
public void negativeTestSecondPreSeriesWinsTwice() throws NoWindException {
|
||||
series = new ArrayList<Series>();
|
||||
// -------- qualification series ------------
|
||||
setupQualificationSeriesWithOneRaceColumn();
|
||||
setupMedalSeriesWithCarryOverAndFourRaceColumns();
|
||||
Regatta regatta = setupRegatta(false);
|
||||
List<Competitor> competitors = createCompetitors(12);
|
||||
List<Competitor> yellow = new ArrayList<>(competitors.subList(0, 6));
|
||||
List<Competitor> blue = new ArrayList<>(competitors);
|
||||
blue.removeAll(yellow);
|
||||
Collections.shuffle(yellow);
|
||||
Collections.shuffle(blue);
|
||||
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis() + 1000);
|
||||
executePreSeries(yellow, blue, now);
|
||||
|
||||
List<Competitor> preSeriesRankResult = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
List<Competitor> medalCompetitorsBestToWorst = preSeriesRankResult.subList(0, 4);
|
||||
List<Pair<Competitor, Double>> preSeriesScoreRankResult = createCompetitorResultForTimestamp(later,
|
||||
leaderboard);
|
||||
manuallyTransferCarry(leaderboard, medalCompetitorsBestToWorst);
|
||||
|
||||
Competitor preFirst = medalCompetitorsBestToWorst.get(0);
|
||||
Competitor preSecond = medalCompetitorsBestToWorst.get(1);
|
||||
Competitor preThird = medalCompetitorsBestToWorst.get(2);
|
||||
Competitor preFourth = medalCompetitorsBestToWorst.get(3);
|
||||
|
||||
RaceColumn m1 = leaderboard.getRaceColumnByName("M1");
|
||||
|
||||
ArrayList<Competitor> m1Results = new ArrayList<>();
|
||||
m1Results.add(preSecond);
|
||||
m1Results.add(preFirst);
|
||||
m1Results.add(preThird);
|
||||
m1Results.add(preFourth);
|
||||
|
||||
TimePoint m1now = new MillisecondsTimePoint(later.asMillis() + 1000);
|
||||
TimePoint m1later = new MillisecondsTimePoint(m1now.asMillis() + 1000);
|
||||
|
||||
TrackedRace m1Default = new MockedTrackedRaceWithStartTimeAndRanks(now, m1Results);
|
||||
m1.setTrackedRace(m1.getFleetByName("Default"), m1Default);
|
||||
|
||||
Assert.assertEquals(6, leaderboard.getNetPoints(preSecond, later), EPSILON);
|
||||
Assert.assertEquals(6.0, leaderboard.getNetPoints(preFirst, later), EPSILON);
|
||||
Assert.assertEquals(12, leaderboard.getNetPoints(preThird, later), EPSILON);
|
||||
Assert.assertEquals(16, leaderboard.getNetPoints(preFourth, later), EPSILON);
|
||||
|
||||
RaceColumn m2 = leaderboard.getRaceColumnByName("M2");
|
||||
|
||||
ArrayList<Competitor> m2Results = new ArrayList<>();
|
||||
m2Results.add(preSecond);
|
||||
m2Results.add(preFirst);
|
||||
m2Results.add(preThird);
|
||||
m2Results.add(preFourth);
|
||||
|
||||
TimePoint m2now = new MillisecondsTimePoint(m1later.asMillis() + 1000);
|
||||
TimePoint m2later = new MillisecondsTimePoint(m2now.asMillis() + 1000);
|
||||
TrackedRace m2Default = new MockedTrackedRaceWithStartTimeAndRanks(m2now, m2Results);
|
||||
m2.setTrackedRace(m1.getFleetByName("Default"), m2Default);
|
||||
|
||||
Assert.assertEquals(8, leaderboard.getNetPoints(preSecond, m2later), EPSILON);
|
||||
Assert.assertEquals(10.0, leaderboard.getNetPoints(preFirst, m2later), EPSILON);
|
||||
Assert.assertEquals(18, leaderboard.getNetPoints(preThird, m2later), EPSILON);
|
||||
Assert.assertEquals(24, leaderboard.getNetPoints(preFourth, m2later), EPSILON);
|
||||
Assert.assertEquals(1, leaderboard.getTotalRankOfCompetitor(preSecond, m2later));
|
||||
Assert.assertEquals(2, leaderboard.getTotalRankOfCompetitor(preFirst, m2later));
|
||||
Assert.assertEquals(3, leaderboard.getTotalRankOfCompetitor(preThird, m2later));
|
||||
Assert.assertEquals(4, leaderboard.getTotalRankOfCompetitor(preFourth, m2later));
|
||||
List<Pair<Competitor, Double>> afterFinalResults = createCompetitorResultForTimestamp(m2later, leaderboard);
|
||||
assertNonFinalistsAreBehindFinalistsAndNotChanged(preSeriesScoreRankResult, afterFinalResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Using normal lowpoints, having two wins should not matter, also the racecolum factor is expected to be 2 instead
|
||||
* of 1.
|
||||
*/
|
||||
@Test
|
||||
public void negativeTestFirstWinsSecondRace() throws NoWindException {
|
||||
series = new ArrayList<Series>();
|
||||
// -------- qualification series ------------
|
||||
setupQualificationSeriesWithOneRaceColumn();
|
||||
setupMedalSeriesWithCarryOverAndFourRaceColumns();
|
||||
Regatta regatta = setupRegatta(false);
|
||||
List<Competitor> competitors = createCompetitors(12);
|
||||
List<Competitor> yellow = new ArrayList<>(competitors.subList(0, 6));
|
||||
List<Competitor> blue = new ArrayList<>(competitors);
|
||||
blue.removeAll(yellow);
|
||||
Collections.shuffle(yellow);
|
||||
Collections.shuffle(blue);
|
||||
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis() + 1000);
|
||||
executePreSeries(yellow, blue, now);
|
||||
|
||||
List<Competitor> preSeriesRankResult = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
List<Competitor> medalCompetitorsBestToWorst = preSeriesRankResult.subList(0, 4);
|
||||
List<Pair<Competitor, Double>> preSeriesScoreRankResult = createCompetitorResultForTimestamp(later,
|
||||
leaderboard);
|
||||
manuallyTransferCarry(leaderboard, medalCompetitorsBestToWorst);
|
||||
|
||||
Competitor preFirst = medalCompetitorsBestToWorst.get(0);
|
||||
Competitor preSecond = medalCompetitorsBestToWorst.get(1);
|
||||
Competitor preThird = medalCompetitorsBestToWorst.get(2);
|
||||
Competitor preFourth = medalCompetitorsBestToWorst.get(3);
|
||||
|
||||
RaceColumn m1 = leaderboard.getRaceColumnByName("M1");
|
||||
|
||||
ArrayList<Competitor> m1Results = new ArrayList<>();
|
||||
m1Results.add(preSecond);
|
||||
m1Results.add(preFirst);
|
||||
m1Results.add(preThird);
|
||||
m1Results.add(preFourth);
|
||||
|
||||
TimePoint m1now = new MillisecondsTimePoint(later.asMillis() + 1000);
|
||||
TimePoint m1later = new MillisecondsTimePoint(m1now.asMillis() + 1000);
|
||||
|
||||
TrackedRace m1Default = new MockedTrackedRaceWithStartTimeAndRanks(now, m1Results);
|
||||
m1.setTrackedRace(m1.getFleetByName("Default"), m1Default);
|
||||
|
||||
Assert.assertEquals(6, leaderboard.getNetPoints(preSecond, later), EPSILON);
|
||||
Assert.assertEquals(6, leaderboard.getNetPoints(preFirst, later), EPSILON);
|
||||
Assert.assertEquals(12, leaderboard.getNetPoints(preThird, later), EPSILON);
|
||||
Assert.assertEquals(16, leaderboard.getNetPoints(preFourth, later), EPSILON);
|
||||
|
||||
|
||||
List<Competitor> res = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
Assert.assertEquals(res.get(0), preSecond);
|
||||
Assert.assertEquals(res.get(1), preFirst);
|
||||
|
||||
RaceColumn m2 = leaderboard.getRaceColumnByName("M2");
|
||||
|
||||
ArrayList<Competitor> m2Results = new ArrayList<>();
|
||||
m2Results.add(preFirst);
|
||||
m2Results.add(preSecond);
|
||||
m2Results.add(preThird);
|
||||
m2Results.add(preFourth);
|
||||
|
||||
TimePoint m2now = new MillisecondsTimePoint(m1later.asMillis() + 1000);
|
||||
TimePoint m2later = new MillisecondsTimePoint(m2now.asMillis() + 1000);
|
||||
TrackedRace m2Default = new MockedTrackedRaceWithStartTimeAndRanks(m2now, m2Results);
|
||||
m2.setTrackedRace(m1.getFleetByName("Default"), m2Default);
|
||||
|
||||
Assert.assertEquals(8, leaderboard.getNetPoints(preFirst, m2later), EPSILON);
|
||||
Assert.assertEquals(10, leaderboard.getNetPoints(preSecond, m2later), EPSILON);
|
||||
Assert.assertEquals(18, leaderboard.getNetPoints(preThird, m2later), EPSILON);
|
||||
Assert.assertEquals(24, leaderboard.getNetPoints(preFourth, m2later), EPSILON);
|
||||
|
||||
List<Pair<Competitor, Double>> afterFinalResults = createCompetitorResultForTimestamp(m2later, leaderboard);
|
||||
assertNonFinalistsAreBehindFinalistsAndNotChanged(preSeriesScoreRankResult, afterFinalResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Using normal lowpoints, the racecolum factor is expected to be 2 instead of 1.
|
||||
*/
|
||||
@Test
|
||||
public void negativeTestLastWinsTwoRaces() throws NoWindException {
|
||||
series = new ArrayList<Series>();
|
||||
// -------- qualification series ------------
|
||||
setupQualificationSeriesWithOneRaceColumn();
|
||||
setupMedalSeriesWithCarryOverAndFourRaceColumns();
|
||||
Regatta regatta = setupRegatta(false);
|
||||
List<Competitor> competitors = createCompetitors(12);
|
||||
List<Competitor> yellow = new ArrayList<>(competitors.subList(0, 6));
|
||||
List<Competitor> blue = new ArrayList<>(competitors);
|
||||
blue.removeAll(yellow);
|
||||
Collections.shuffle(yellow);
|
||||
Collections.shuffle(blue);
|
||||
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis() + 1000);
|
||||
executePreSeries(yellow, blue, now);
|
||||
|
||||
List<Competitor> preSeriesRankResult = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
List<Competitor> medalCompetitorsBestToWorst = preSeriesRankResult.subList(0, 4);
|
||||
List<Pair<Competitor, Double>> preSeriesScoreRankResult = createCompetitorResultForTimestamp(later,
|
||||
leaderboard);
|
||||
|
||||
manuallyTransferCarry(leaderboard, medalCompetitorsBestToWorst);
|
||||
|
||||
Competitor preFirst = medalCompetitorsBestToWorst.get(0);
|
||||
Competitor preSecond = medalCompetitorsBestToWorst.get(1);
|
||||
Competitor preThird = medalCompetitorsBestToWorst.get(2);
|
||||
Competitor preFourth = medalCompetitorsBestToWorst.get(3);
|
||||
|
||||
RaceColumn m1 = leaderboard.getRaceColumnByName("M1");
|
||||
|
||||
ArrayList<Competitor> m1Results = new ArrayList<>();
|
||||
m1Results.add(preFourth);
|
||||
m1Results.add(preFirst);
|
||||
m1Results.add(preSecond);
|
||||
m1Results.add(preThird);
|
||||
|
||||
TimePoint m1now = new MillisecondsTimePoint(later.asMillis() + 1000);
|
||||
TimePoint m1later = new MillisecondsTimePoint(m1now.asMillis() + 1000);
|
||||
|
||||
TrackedRace m1Default = new MockedTrackedRaceWithStartTimeAndRanks(now, m1Results);
|
||||
m1.setTrackedRace(m1.getFleetByName("Default"), m1Default);
|
||||
|
||||
Assert.assertEquals(10, leaderboard.getNetPoints(preFourth, later), EPSILON);
|
||||
Assert.assertEquals(6.0, leaderboard.getNetPoints(preFirst, later), EPSILON);
|
||||
Assert.assertEquals(10, leaderboard.getNetPoints(preSecond, later), EPSILON);
|
||||
Assert.assertEquals(14, leaderboard.getNetPoints(preThird, later), EPSILON);
|
||||
|
||||
List<Competitor> res = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
Assert.assertEquals(res.get(0), preFirst);
|
||||
Assert.assertEquals(res.get(1), preFourth);
|
||||
Assert.assertEquals(res.get(2), preSecond);
|
||||
|
||||
RaceColumn m2 = leaderboard.getRaceColumnByName("M2");
|
||||
|
||||
ArrayList<Competitor> m2Results = new ArrayList<>();
|
||||
m2Results.add(preFourth);
|
||||
m2Results.add(preFirst);
|
||||
m2Results.add(preSecond);
|
||||
m2Results.add(preThird);
|
||||
|
||||
TimePoint m2now = new MillisecondsTimePoint(m1later.asMillis() + 1000);
|
||||
TimePoint m2later = new MillisecondsTimePoint(m2now.asMillis() + 1000);
|
||||
TrackedRace m2Default = new MockedTrackedRaceWithStartTimeAndRanks(m2now, m2Results);
|
||||
m2.setTrackedRace(m1.getFleetByName("Default"), m2Default);
|
||||
|
||||
Assert.assertEquals(12, leaderboard.getNetPoints(preFourth, m2later), EPSILON);
|
||||
Assert.assertEquals(10, leaderboard.getNetPoints(preFirst, m2later), EPSILON);
|
||||
Assert.assertEquals(16, leaderboard.getNetPoints(preSecond, m2later), EPSILON);
|
||||
Assert.assertEquals(22, leaderboard.getNetPoints(preThird, m2later), EPSILON);
|
||||
|
||||
List<Pair<Competitor, Double>> afterFinalResults = createCompetitorResultForTimestamp(m2later, leaderboard);
|
||||
assertNonFinalistsAreBehindFinalistsAndNotChanged(preSeriesScoreRankResult, afterFinalResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Using normal lowpoints, tie braking is done with manual carry decimals.
|
||||
*/
|
||||
@Test
|
||||
public void negativeNoTwoWinsAbortAfterTwoRacesAndTieBreaker() throws NoWindException {
|
||||
series = new ArrayList<Series>();
|
||||
// -------- qualification series ------------
|
||||
setupQualificationSeriesWithOneRaceColumn();
|
||||
setupMedalSeriesWithCarryOverAndFourRaceColumns();
|
||||
Regatta regatta = setupRegatta(false);
|
||||
List<Competitor> competitors = createCompetitors(12);
|
||||
List<Competitor> yellow = new ArrayList<>(competitors.subList(0, 6));
|
||||
List<Competitor> blue = new ArrayList<>(competitors);
|
||||
blue.removeAll(yellow);
|
||||
Collections.shuffle(yellow);
|
||||
Collections.shuffle(blue);
|
||||
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis() + 1000);
|
||||
executePreSeries(yellow, blue, now);
|
||||
|
||||
List<Competitor> preSeriesRankResult = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
List<Competitor> medalCompetitorsBestToWorst = preSeriesRankResult.subList(0, 4);
|
||||
List<Pair<Competitor, Double>> preSeriesScoreRankResult = createCompetitorResultForTimestamp(later,
|
||||
leaderboard);
|
||||
manuallyTransferCarry(leaderboard, medalCompetitorsBestToWorst);
|
||||
|
||||
Competitor preFirst = medalCompetitorsBestToWorst.get(0);
|
||||
Competitor preSecond = medalCompetitorsBestToWorst.get(1);
|
||||
Competitor preThird = medalCompetitorsBestToWorst.get(2);
|
||||
Competitor preFourth = medalCompetitorsBestToWorst.get(3);
|
||||
|
||||
RaceColumn m1 = leaderboard.getRaceColumnByName("M1");
|
||||
|
||||
ArrayList<Competitor> m1Results = new ArrayList<>();
|
||||
m1Results.add(preFourth);
|
||||
m1Results.add(preFirst);
|
||||
m1Results.add(preSecond);
|
||||
m1Results.add(preThird);
|
||||
|
||||
TimePoint m1now = new MillisecondsTimePoint(later.asMillis() + 1000);
|
||||
TimePoint m1later = new MillisecondsTimePoint(m1now.asMillis() + 1000);
|
||||
|
||||
TrackedRace m1Default = new MockedTrackedRaceWithStartTimeAndRanks(now, m1Results);
|
||||
m1.setTrackedRace(m1.getFleetByName("Default"), m1Default);
|
||||
|
||||
Assert.assertEquals(10, leaderboard.getNetPoints(preFourth, later), EPSILON);
|
||||
Assert.assertEquals(6.0, leaderboard.getNetPoints(preFirst, later), EPSILON);
|
||||
Assert.assertEquals(10, leaderboard.getNetPoints(preSecond, later), EPSILON);
|
||||
Assert.assertEquals(14, leaderboard.getNetPoints(preThird, later), EPSILON);
|
||||
|
||||
List<Competitor> res = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
Assert.assertEquals(res.get(0), preFirst);
|
||||
Assert.assertEquals(res.get(1), preFourth);
|
||||
Assert.assertEquals(res.get(2), preSecond);
|
||||
|
||||
RaceColumn m2 = leaderboard.getRaceColumnByName("M2");
|
||||
|
||||
ArrayList<Competitor> m2Results = new ArrayList<>();
|
||||
m2Results.add(preThird);
|
||||
m2Results.add(preFirst);
|
||||
m2Results.add(preSecond);
|
||||
m2Results.add(preFourth);
|
||||
|
||||
TimePoint m2now = new MillisecondsTimePoint(m1later.asMillis() + 1000);
|
||||
TimePoint m2later = new MillisecondsTimePoint(m2now.asMillis() + 1000);
|
||||
TrackedRace m2Default = new MockedTrackedRaceWithStartTimeAndRanks(m2now, m2Results);
|
||||
m2.setTrackedRace(m1.getFleetByName("Default"), m2Default);
|
||||
|
||||
Assert.assertEquals(18, leaderboard.getNetPoints(preFourth, m2later), EPSILON);
|
||||
Assert.assertEquals(10, leaderboard.getNetPoints(preFirst, m2later), EPSILON);
|
||||
Assert.assertEquals(16, leaderboard.getNetPoints(preSecond, m2later), EPSILON);
|
||||
Assert.assertEquals(16, leaderboard.getNetPoints(preThird, m2later), EPSILON);
|
||||
|
||||
List<Competitor> res2 = leaderboard.getCompetitorsFromBestToWorst(m2later);
|
||||
Assert.assertEquals(res2.get(0), preFirst);
|
||||
Assert.assertEquals(res2.get(1), preThird);
|
||||
Assert.assertEquals(res2.get(2), preSecond);
|
||||
Assert.assertEquals(res2.get(3), preFourth);
|
||||
|
||||
List<Pair<Competitor, Double>> afterFinalResults = createCompetitorResultForTimestamp(m2later, leaderboard);
|
||||
assertNonFinalistsAreBehindFinalistsAndNotChanged(preSeriesScoreRankResult, afterFinalResults);
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -137,8 +137,8 @@ public class OfflineSerializationTest extends AbstractSerializationTest {
|
||||
|
||||
DomainFactory receiverDomainFactory = new DomainFactoryImpl((srlid)->null);
|
||||
LeaderboardGroup clone = cloneBySerialization(leaderboardGroup, receiverDomainFactory);
|
||||
assertEquals(FACTOR, overallLeaderboard.getRaceColumnByName("Test Leaderboard").getFactor(), 0.00000001);
|
||||
assertEquals(FACTOR, clone.getOverallLeaderboard().getRaceColumnByName("Test Leaderboard").getFactor(), 0.00000001);
|
||||
assertEquals(FACTOR, overallLeaderboard.getScoringScheme().getScoreFactor(overallLeaderboard.getRaceColumnByName("Test Leaderboard")), 0.00000001);
|
||||
assertEquals(FACTOR, clone.getOverallLeaderboard().getScoringScheme().getScoreFactor(clone.getOverallLeaderboard().getRaceColumnByName("Test Leaderboard")), 0.00000001);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -162,14 +162,6 @@ public interface RaceColumn extends Named {
|
||||
*/
|
||||
void releaseTrackedRace(Fleet fleet);
|
||||
|
||||
/**
|
||||
* Usually, the scores in each leaderboard column count as they are for the overall score. However, if a column is
|
||||
* a medal race column it usually counts double. Under certain circumstances, columns may also count with factors different
|
||||
* from 1 or 2. For example, we've seen cases in the Extreme Sailing Series where the race committee defined that in the
|
||||
* overall series leaderboard the last two columns each count 1.5 times their scores.
|
||||
*/
|
||||
double getFactor();
|
||||
|
||||
/**
|
||||
* By default, a competitor's total score is computed by summing up the non-discarded total points of each race
|
||||
* across the leaderboard, considering the {@link RaceColumn#getFactor() column factors}. Some race columns,
|
||||
|
||||
+5
@@ -58,6 +58,7 @@ import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsEightAndInterp
|
||||
import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsFive;
|
||||
import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsSix;
|
||||
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
|
||||
import com.sap.sailing.domain.leaderboard.impl.LowPointFirstToWinTwoRaces;
|
||||
import com.sap.sailing.domain.leaderboard.impl.LowPointForLeagueOverallLeaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.impl.LowPointTieBreakBasedOnLastSeriesOnly;
|
||||
import com.sap.sailing.domain.leaderboard.impl.LowPointWinnerGetsZero;
|
||||
@@ -144,6 +145,10 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain
|
||||
return new LowPointTieBreakBasedOnLastSeriesOnly();
|
||||
case LOW_POINT_WITH_AUTOMATIC_RDG:
|
||||
return new LowPointWithAutomaticRDG();
|
||||
case LOW_POINT_FIRST_TO_WIN_TWO_RACES:
|
||||
return new LowPointFirstToWinTwoRaces();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
throw new RuntimeException("Unknown scoring scheme type "+scoringSchemeType.name());
|
||||
}
|
||||
|
||||
-12
@@ -20,13 +20,6 @@ public abstract class SimpleAbstractRaceColumn implements RaceColumn {
|
||||
private static final long serialVersionUID = -3590156714385187908L;
|
||||
private final RaceColumnListeners raceColumnListeners;
|
||||
|
||||
/**
|
||||
* The factor by which a medal race score is multiplied by default in the overall point scheme.
|
||||
*
|
||||
* @see #getFactor()
|
||||
*/
|
||||
private static final double DEFAULT_MEDAL_RACE_FACTOR = 2.0;
|
||||
|
||||
/**
|
||||
* If <code>null</code>, 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.
|
||||
@@ -66,11 +59,6 @@ public abstract class SimpleAbstractRaceColumn implements RaceColumn {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFactor() {
|
||||
return explicitFactor == null ? (isMedalRace() ? DEFAULT_MEDAL_RACE_FACTOR : 1.) : explicitFactor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFactor(Double factor) {
|
||||
Double oldExplicitFactor = getExplicitFactor();
|
||||
|
||||
+19
-1
@@ -604,4 +604,22 @@ public interface Leaderboard extends LeaderboardBase, HasRaceColumns {
|
||||
* leaderboard.
|
||||
*/
|
||||
boolean hasScores(Competitor competitor, TimePoint timePoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a racecolumn evaluates to be a win for the given competitor at the given timepoint.
|
||||
* If the competitor is not scored for this race, false is returned
|
||||
*/
|
||||
default boolean isWin(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint) {
|
||||
final Double points = getTotalPoints(competitor, raceColumn, timePoint);
|
||||
final boolean result;
|
||||
if (points == null) {
|
||||
result = false;
|
||||
} else if (getScoringScheme().isHigherBetter()) {
|
||||
double competitorCount = Util.size(getCompetitors());
|
||||
result = points >= (competitorCount - 0.05);
|
||||
} else {
|
||||
result = points <= 1.05;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import java.util.concurrent.Callable;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.base.Series;
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.ScoringSchemeType;
|
||||
@@ -25,6 +26,13 @@ import com.sap.sse.common.Util;
|
||||
*
|
||||
*/
|
||||
public interface ScoringScheme extends Serializable {
|
||||
/**
|
||||
* The factor by which a medal race score is multiplied by default in the overall point scheme.
|
||||
*
|
||||
* @see #getFactor()
|
||||
*/
|
||||
static final double DEFAULT_MEDAL_RACE_FACTOR = 2.0;
|
||||
|
||||
/**
|
||||
* If this returns <code>true</code>, a higher score is better. For example, the Extreme Sailing Series uses this
|
||||
* scoring scheme, as opposed to the olympic sailing classes which use a low-point system.
|
||||
@@ -119,4 +127,51 @@ public interface ScoringScheme extends Serializable {
|
||||
* @throws NoWindException
|
||||
*/
|
||||
int compareByLatestRegattaInMetaLeaderboard(Leaderboard leaderboard, Competitor o1, Competitor o2, TimePoint timePoint);
|
||||
|
||||
/**
|
||||
* Returning {@code true} makes the number of wins in a medal series the primary ranking criteria.
|
||||
* The number of wins that makes a competitor the overall winner must be returned by {@link #getTargetAmountOfMedalRaceWins()}.
|
||||
*/
|
||||
default boolean isMedalWinAmountCriteria() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returning {@code true} makes the {@link RaceColumn#isCarryForward() carry forward score} in a
|
||||
* {@link Series#isMedal() medal series} a secondary ranking criteria for competitors that have an equal overall
|
||||
* score.
|
||||
*/
|
||||
default boolean isCarryForwardInMedalsCriteria() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returning {@code true} makes the last medal race (having valid scores) a secondary ranking criteria for
|
||||
* competitors that have an equal overall score.
|
||||
*/
|
||||
default boolean isLastMedalRaceCriteria() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* If {@link #isMedalWinAmountCriteria()} returns {@code true}, this will be the amount of races that must be won,
|
||||
* in order to win the medal series instantly
|
||||
*/
|
||||
default int getTargetAmountOfMedalRaceWins() {
|
||||
throw new IllegalStateException("This call is not valid for this scoringSheme");
|
||||
}
|
||||
|
||||
/**
|
||||
* Usually, the scores in each leaderboard column count as they are for the overall score. However, if a column is a
|
||||
* medal race column it usually counts double. Under certain circumstances, columns may also count with factors
|
||||
* different from 1 or 2. For example, we've seen cases in the Extreme Sailing Series where the race committee
|
||||
* defined that in the overall series leaderboard the last two columns each count 1.5 times their scores.
|
||||
*/
|
||||
default double getScoreFactor(RaceColumn raceColumn) {
|
||||
Double factor = raceColumn.getExplicitFactor();
|
||||
if (factor == null) {
|
||||
factor = raceColumn.isMedalRace() ? DEFAULT_MEDAL_RACE_FACTOR : 1.0;
|
||||
}
|
||||
return factor;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -72,7 +72,7 @@ public abstract class AbstractHighPointExtremeSailingSeriesOverall extends HighP
|
||||
private int getWins(List<com.sap.sse.common.Util.Pair<RaceColumn, Double>> scores) {
|
||||
int wins = 0;
|
||||
for (com.sap.sse.common.Util.Pair<RaceColumn, Double> score : scores) {
|
||||
if (Math.abs(score.getB() - maxPoints * score.getA().getFactor()) < 0.0000001) {
|
||||
if (Math.abs(score.getB() - maxPoints * getScoreFactor(score.getA())) < 0.0000001) {
|
||||
wins++;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -46,8 +46,8 @@ public abstract class AbstractHighPointFirstGetsFixedOr8AndLastBreaksTie extends
|
||||
private double getHighestScore(List<com.sap.sse.common.Util.Pair<RaceColumn, Double>> scores) {
|
||||
double highestScore = 0;
|
||||
for (com.sap.sse.common.Util.Pair<RaceColumn, Double> score : scores) {
|
||||
if ((score.getB() * score.getA().getFactor()) > highestScore) {
|
||||
highestScore = score.getB() * score.getA().getFactor();
|
||||
if ((score.getB() * getScoreFactor(score.getA())) > highestScore) {
|
||||
highestScore = score.getB() * getScoreFactor(score.getA());
|
||||
}
|
||||
}
|
||||
return highestScore;
|
||||
|
||||
java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java
Executable → Regular
+1
-1
@@ -281,5 +281,5 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI
|
||||
RegattaLogBoatDeregistrator<RegattaLog, RegattaLogEvent, RegattaLogEventVisitor> deregisterer = new RegattaLogBoatDeregistrator<>(regattaLog, boats, regattaLogEventAuthorForAbstractLeaderboard);
|
||||
deregisterer.deregister(deregisterer.analyze());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+1
-1
@@ -406,7 +406,7 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard {
|
||||
}
|
||||
// Note: the RaceColumnDTO won't be created by the following addRace call because it has been created
|
||||
// above by the result.createEmptyRaceColumn call
|
||||
result.addRace(raceColumn.getName(), raceColumn.getExplicitFactor(), raceColumn.getFactor(),
|
||||
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);
|
||||
|
||||
+2
-2
@@ -129,11 +129,11 @@ public abstract class AbstractScoringSchemeImpl implements ScoringScheme {
|
||||
// needs to compare net points; therefore, divide the total points by the column factor for comparison:
|
||||
List<Double> o1NetScores = new ArrayList<>();
|
||||
for (com.sap.sse.common.Util.Pair<RaceColumn, Double> o1ColumnAndScore : o1Scores) {
|
||||
o1NetScores.add(o1ColumnAndScore.getB()/o1ColumnAndScore.getA().getFactor());
|
||||
o1NetScores.add(o1ColumnAndScore.getB() / getScoreFactor(o1ColumnAndScore.getA()));
|
||||
}
|
||||
List<Double> o2NetScores = new ArrayList<>();
|
||||
for (com.sap.sse.common.Util.Pair<RaceColumn, Double> o2ColumnAndScore : o2Scores) {
|
||||
o2NetScores.add(o2ColumnAndScore.getB()/o2ColumnAndScore.getA().getFactor());
|
||||
o2NetScores.add(o2ColumnAndScore.getB() / getScoreFactor(o2ColumnAndScore.getA()));
|
||||
}
|
||||
Collections.sort(o1NetScores, pureScoreComparator);
|
||||
Collections.sort(o2NetScores, pureScoreComparator);
|
||||
|
||||
+5
-3
@@ -475,7 +475,7 @@ public abstract class AbstractSimpleLeaderboardImpl extends AbstractLeaderboardW
|
||||
if (totalPoints == null) {
|
||||
result = null;
|
||||
} else {
|
||||
result = raceColumn.getFactor() * totalPoints;
|
||||
result = getScoringScheme().getScoreFactor(raceColumn) * totalPoints;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -663,7 +663,7 @@ public abstract class AbstractSimpleLeaderboardImpl extends AbstractLeaderboardW
|
||||
return new EntryImpl(trackedRankProvider, correctedScore, () -> correctedResults.getUncorrectedScore(),
|
||||
correctedResults.isCorrected(),
|
||||
discarded ? DOUBLE_0
|
||||
: correctedScore == null ? null : Double.valueOf(correctedScore * race.getFactor()),
|
||||
: correctedScore == null ? null : Double.valueOf(correctedScore * getScoringScheme().getScoreFactor(race)),
|
||||
correctedResults.getMaxPointsReason(), discarded, race.getFleetOfCompetitor(competitor));
|
||||
}
|
||||
|
||||
@@ -738,7 +738,7 @@ public abstract class AbstractSimpleLeaderboardImpl extends AbstractLeaderboardW
|
||||
() -> correctedResults.getUncorrectedScore(), correctedResults.isCorrected(),
|
||||
discarded ? DOUBLE_0
|
||||
: (correctedScore == null ? null
|
||||
: Double.valueOf((correctedScore * raceColumn.getFactor()))),
|
||||
: Double.valueOf((correctedScore * getScoringScheme().getScoreFactor(raceColumn)))),
|
||||
correctedResults.getMaxPointsReason(), discarded, raceColumn.getFleetOfCompetitor(competitor));
|
||||
result.put(new com.sap.sse.common.Util.Pair<Competitor, RaceColumn>(competitor, raceColumn), entry);
|
||||
}
|
||||
@@ -959,5 +959,7 @@ public abstract class AbstractSimpleLeaderboardImpl extends AbstractLeaderboardW
|
||||
return Util.getDominantObject(StreamSupport.stream(allBoats.spliterator(), /* parallel */ false)
|
||||
.map(b -> b.getBoatClass()).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Executable → Regular
+72
-9
@@ -111,6 +111,10 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
|
||||
double o2ScoreSum = getLeaderboard().getCarriedPoints(o2);
|
||||
Double o1MedalRaceScore = 0.0;
|
||||
Double o2MedalRaceScore = 0.0;
|
||||
Double o1CarryForwardScoreInMedals = null;
|
||||
Double o2CarryForwardScoreInMedals = null;
|
||||
Double o1LastMedalScore = null;
|
||||
Double o2LastMedalScore = null;
|
||||
// When a column has isStartsWithZeroScore, the competitor's score only need to be reset to zero if from there on
|
||||
// the competitor scored in this or any subsequent columns
|
||||
boolean needToResetO1ScoreUponNextValidResult = false;
|
||||
@@ -124,6 +128,8 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
|
||||
// it is guaranteed to have equal ordering as all fleets that the competitor is assigned to within the key series.
|
||||
final Map<Series, Map<Competitor, Fleet>> fleetWithCorrectOrderingForCompetitorBySeries = new HashMap<>();
|
||||
int defaultFleetBasedComparisonResult = 0; // relevant if no authoritative fleet-based comparison result was determined; based on extreme fleet vs. no fleet comparison
|
||||
int numberOfMedalRacesWonO1 = 0;
|
||||
int numberOfMedalRacesWonO2 = 0;
|
||||
for (RaceColumn raceColumn : getLeaderboard().getRaceColumns()) {
|
||||
needToResetO1ScoreUponNextValidResult = raceColumn.isStartsWithZeroScore();
|
||||
needToResetO2ScoreUponNextValidResult = raceColumn.isStartsWithZeroScore();
|
||||
@@ -178,10 +184,21 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
|
||||
if (o2Score != null) {
|
||||
o2MedalRaceScore += o2Score;
|
||||
}
|
||||
if (o1Score != null || o2Score != null) {
|
||||
o1LastMedalScore = o1Score;
|
||||
o2LastMedalScore = o2Score;
|
||||
}
|
||||
} else {
|
||||
o1CarryForwardScoreInMedals = o1Score;
|
||||
o2CarryForwardScoreInMedals = o2Score;
|
||||
}
|
||||
// similar to compareByFleet, however, tracking is not required; having medal race column points
|
||||
// (tracked or manual) is sufficient
|
||||
preemptiveColumnResult = compareByMedalRaceParticipation(o1Score, o2Score);
|
||||
if (scoringScheme.isMedalWinAmountCriteria()) {
|
||||
numberOfMedalRacesWonO1 += leaderboard.isWin(o1, raceColumn, timePoint) ? 1 : 0;
|
||||
numberOfMedalRacesWonO2 += leaderboard.isWin(o2, raceColumn, timePoint) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
if (preemptiveColumnResult == 0 && raceColumn.isTotalOrderDefinedByFleet()) {
|
||||
final FleetComparisonResult compareByFleetResult = compareByFleet(raceColumn, o1, o2, fleetWithCorrectOrderingForCompetitorBySeries);
|
||||
@@ -205,18 +222,35 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
|
||||
// break tie by sorting scores and looking for the first score difference.
|
||||
int result = compareByNumberOfRacesScored(o1Scores.size(), o2Scores.size());
|
||||
if (result == 0) {
|
||||
result = compareByScoreSum(o1ScoreSum, o2ScoreSum);
|
||||
if (scoringScheme.isMedalWinAmountCriteria()) {
|
||||
// if one reaches the target amount of races won then this has priority, else proceed with normal low
|
||||
// points scoring (e.g., not enough races yet)
|
||||
result = compareByMedalRacesWon(numberOfMedalRacesWonO1, numberOfMedalRacesWonO2);
|
||||
}
|
||||
if (result == 0) {
|
||||
result = compareByMedalRaceScore(o1MedalRaceScore, o2MedalRaceScore);
|
||||
result = compareByScoreSum(o1ScoreSum, o2ScoreSum);
|
||||
if (result == 0) {
|
||||
result = compareByBetterScore(o1, Collections.unmodifiableList(o1Scores), o2, Collections.unmodifiableList(o2Scores), timePoint);
|
||||
if (scoringScheme.isCarryForwardInMedalsCriteria()) {
|
||||
result = compareBySingleRaceColumnScore(o1CarryForwardScoreInMedals, o2CarryForwardScoreInMedals);
|
||||
}
|
||||
if (result == 0) {
|
||||
// compare by last race:
|
||||
result = scoringScheme.compareByLastRace(o1TotalPoints, o2TotalPoints, nullScoresAreBetter, o1, o2);
|
||||
if (scoringScheme.isLastMedalRaceCriteria()) {
|
||||
result = compareBySingleRaceColumnScore(o1LastMedalScore, o2LastMedalScore);
|
||||
}
|
||||
if (result == 0) {
|
||||
result = scoringScheme.compareByLatestRegattaInMetaLeaderboard(getLeaderboard(), o1, o2, timePoint);
|
||||
result = compareByMedalRaceScore(o1MedalRaceScore, o2MedalRaceScore);
|
||||
if (result == 0) {
|
||||
result = compareByArbitraryButStableCriteria(o1, o2);
|
||||
result = compareByBetterScore(o1, Collections.unmodifiableList(o1Scores), o2, Collections.unmodifiableList(o2Scores), timePoint);
|
||||
if (result == 0) {
|
||||
// compare by last race:
|
||||
result = scoringScheme.compareByLastRace(o1TotalPoints, o2TotalPoints, nullScoresAreBetter, o1, o2);
|
||||
if (result == 0) {
|
||||
result = scoringScheme.compareByLatestRegattaInMetaLeaderboard(getLeaderboard(), o1, o2, timePoint);
|
||||
if (result == 0) {
|
||||
result = compareByArbitraryButStableCriteria(o1, o2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -226,6 +260,33 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares by the number of races won in the medal series. If one of the competitors reached the target of races
|
||||
* won (defined by {@link ScoringScheme#getTargetAmountOfMedalRaceWins()} it is ranked better than the other. If
|
||||
* none of the competitors reached the target, they are ranked equally even if one has more wins. This is because
|
||||
* only reaching the exact number of wins counts for this criteria but not the general comparison by the number of
|
||||
* wins. If both competitors exactly reached the target, they are also ranked equally (this can e.g. occur while
|
||||
* entering score corrections).
|
||||
*/
|
||||
private int compareByMedalRacesWon(int numberOfMedalRacesWonO1, int numberOfMedalRacesWonO2) {
|
||||
final int result;
|
||||
final int targetAmount = scoringScheme.getTargetAmountOfMedalRaceWins();
|
||||
if (numberOfMedalRacesWonO1 >= targetAmount || numberOfMedalRacesWonO2 >= targetAmount) {
|
||||
result = Integer.compare(numberOfMedalRacesWonO2, numberOfMedalRacesWonO1);
|
||||
} else {
|
||||
result = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares by the scores of a single race column. If only one of the competitors has a result this competitor is
|
||||
* ranked better than the other one.
|
||||
*/
|
||||
private int compareBySingleRaceColumnScore(Double o1Score, Double o2Score) {
|
||||
return Comparator.nullsLast((Double o1s, Double o2s)->getScoreComparator().compare(o1s, o2s)).compare(o1Score, o2Score);
|
||||
}
|
||||
|
||||
private int compareByArbitraryButStableCriteria(Competitor o1, Competitor o2) {
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
@@ -236,11 +297,13 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
|
||||
*/
|
||||
private int compareByMedalRaceScore(Double o1MedalRaceScore, Double o2MedalRaceScore) {
|
||||
assert o1MedalRaceScore != null || o2MedalRaceScore == null;
|
||||
final int result;
|
||||
if (o1MedalRaceScore != null) {
|
||||
return getScoreComparator().compare(o1MedalRaceScore, o2MedalRaceScore);
|
||||
result = getScoreComparator().compare(o1MedalRaceScore, o2MedalRaceScore);
|
||||
} else {
|
||||
return 0;
|
||||
result = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class FleetComparisonResult {
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.sap.sailing.domain.leaderboard.impl;
|
||||
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.common.ScoringSchemeType;
|
||||
|
||||
/**
|
||||
* This class is a derivation of the LowPointScoring scheme. The following additional rules apply:
|
||||
* <ol>
|
||||
* <li>The first participant in the medal series, that wins two races is ranked as the first.</li>
|
||||
* <li>Having 1 point in the carry forward column of the medal series explicitly counts as an additional win which
|
||||
* requires the winner of the qualification to only need one additional win in the medals.</li>
|
||||
* <li>If none of the participants in the medal series reached the target amount of 2 wins yet, the ranking is done
|
||||
* based on the points only.</li>
|
||||
* <li>If there is a carry forward column in the medal series, the carry forward points are used as the primary tie
|
||||
* breaking criteria in case two participants in the medal series have the same overall score.</li>
|
||||
* <li>If there is no carry forward column in the medal series or the carry forward score is not sufficient, the points
|
||||
* of the last medal race are used as a secondary tie breaking criteria.</li>
|
||||
* <li>This Scheme will change the default scoring factor for medal races to 1, usually 2 is used</li>
|
||||
* <ol>
|
||||
*/
|
||||
public class LowPointFirstToWinTwoRaces extends LowPoint {
|
||||
private static final long serialVersionUID = 7072175334160798617L;
|
||||
|
||||
@Override
|
||||
public ScoringSchemeType getType() {
|
||||
return ScoringSchemeType.LOW_POINT_FIRST_TO_WIN_TWO_RACES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMedalWinAmountCriteria() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCarryForwardInMedalsCriteria() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLastMedalRaceCriteria() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTargetAmountOfMedalRaceWins() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getScoreFactor(RaceColumn raceColumn) {
|
||||
Double factor = raceColumn.getExplicitFactor();
|
||||
if (factor == null) {
|
||||
factor = 1.0;
|
||||
}
|
||||
return factor;
|
||||
}
|
||||
}
|
||||
+2
@@ -434,6 +434,8 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
|
||||
String insertWaypointAfterSelected();
|
||||
String addGate();
|
||||
String scoringSchemeLowPointSystem();
|
||||
String scoringSchemeLowPointSystemFirstTwoWins();
|
||||
String scoringSchemeLowPointSystemFirstTwoWinsDescription();
|
||||
String scoringSchemeHighPointSystem();
|
||||
String scoringSchemeLowPointWinnerGetsZero();
|
||||
String scoringSchemeWinnerGetsFive();
|
||||
|
||||
+2
@@ -484,6 +484,8 @@ scoringSchemeHighPointFirstGetsTwelveOrEight=High Point, winner gets 12 points (
|
||||
scoringSchemeHighPointFirstGetsTwelveOrEightDescription=Score in points. Winner scores 12 points, 2nd - 11 points, .... A tie is broken in favour of the competitor with the highest score, if tie remains then tie is broken by the rank in the last race scored.
|
||||
scoringSchemeHighPointFirstGetsTwelveOrEight2017=High Point ESS 2017, winner gets 12 points (or 8)
|
||||
scoringSchemeHighPointFirstGetsTwelveOrEight2017Description=Score in points. Winner scores 12 points, 2nd - 11 points, .... A tie is broken in favour of the competitor with the highest score, if tie remains then tie is broken by the rank in the last race scored.
|
||||
scoringSchemeLowPointSystemFirstTwoWins=Low Point System, First with two wins in medals is winner
|
||||
scoringSchemeLowPointSystemFirstTwoWinsDescription=Low Point System. The first in the medal series to win two races wins the medal series. Being the best in the pre medal series counts as one win for this.
|
||||
scoringSystem=Scoring system
|
||||
createFlexibleLeaderboard=Create flexible leaderboard
|
||||
createRegattaLeaderboard=Create regatta leaderboard
|
||||
|
||||
+2
@@ -474,6 +474,8 @@ scoringSchemeLowPointForLeagueOverallLeaderboardDescription=Bei Punktegleichstan
|
||||
scoringSchemeLowPointTieBreakBasedOnLastSeriesOnly=Low Point System, bei Punktegleichstand zählt letzten Serie
|
||||
scoringSchemeLowPointTieBreakBasedOnLastSeriesOnlyDescription=Bei Punktegleichstand entscheidet die Punktesumme aller (auch der gestrichenen) Wettfahrten der letzten Serie
|
||||
scoringSchemeLowPointWithAutomaticRdg=Low Point System, RDG erhält Durchschnitt aller nicht-RDG-Wertungen als Vorschlag
|
||||
scoringSchemeLowPointSystemFirstTwoWins=Low Point System, Erster mit zwei Siegen in Medaillen-Rennen gewinnt
|
||||
scoringSchemeLowPointSystemFirstTwoWinsDescription=Low Point System. Der Erste, der zwei Rennen in den Medaillen-Rennen gewinnt, zählt als Sieger der Medaillen-Serie. Der Beste der Vorserien bekommt einen zusätzlichen Sieg angerechnet.
|
||||
scoringSystem=Bepunktungssystem
|
||||
createFlexibleLeaderboard=Flexible Rangliste anlegen
|
||||
createRegattaLeaderboard=Rangliste für Regatta anlegen
|
||||
|
||||
+4
@@ -46,6 +46,8 @@ public class ScoringSchemeTypeFormatter {
|
||||
return stringMessages.scoringSchemeLowPointTieBreakBasedOnLastSeriesOnly();
|
||||
case LOW_POINT_WITH_AUTOMATIC_RDG:
|
||||
return stringMessages.scoringSchemeLowPointWithAutomaticRdg();
|
||||
case LOW_POINT_FIRST_TO_WIN_TWO_RACES:
|
||||
return stringMessages.scoringSchemeLowPointSystemFirstTwoWins();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -72,6 +74,8 @@ public class ScoringSchemeTypeFormatter {
|
||||
return stringMessages.scoringSchemeHighPointMatchRacingDescription();
|
||||
case LOW_POINT_TIE_BREAK_BASED_ON_LAST_SERIES_ONLY:
|
||||
return stringMessages.scoringSchemeLowPointTieBreakBasedOnLastSeriesOnlyDescription();
|
||||
case LOW_POINT_FIRST_TO_WIN_TWO_RACES:
|
||||
return stringMessages.scoringSchemeLowPointSystemFirstTwoWinsDescription();
|
||||
default:
|
||||
return format(scoringSchemeType, stringMessages);
|
||||
}
|
||||
|
||||
+2
-1
@@ -2603,7 +2603,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
}
|
||||
}
|
||||
final FleetDTO fleetDTO = baseDomainFactory.convertToFleetDTO(fleet);
|
||||
RaceColumnDTO raceColumnDTO = leaderboardDTO.addRace(raceColumn.getName(), raceColumn.getExplicitFactor(), raceColumn.getFactor(),
|
||||
RaceColumnDTO raceColumnDTO = leaderboardDTO.addRace(raceColumn.getName(),
|
||||
raceColumn.getExplicitFactor(), leaderboard.getScoringScheme().getScoreFactor(raceColumn),
|
||||
raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getRegatta().getName() : null,
|
||||
raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getSeries().getName() : null,
|
||||
fleetDTO, raceColumn.isMedalRace(), raceIdentifier, raceDTO, raceColumn instanceof MetaLeaderboardColumn);
|
||||
|
||||
+3
-3
@@ -68,9 +68,9 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest {
|
||||
r3.setFactor(2.5);
|
||||
new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard);
|
||||
Leaderboard loadedLeaderboard = new DomainObjectFactoryImpl(db, DomainFactory.INSTANCE).loadLeaderboard(leaderboardName, /* regattaRegistry */ null, /* leaderboardRegistry */ null);
|
||||
assertEquals(1.0, loadedLeaderboard.getRaceColumnByName("R1").getFactor(), 0.000000001);
|
||||
assertEquals(1.5, loadedLeaderboard.getRaceColumnByName("R2").getFactor(), 0.000000001);
|
||||
assertEquals(2.5, loadedLeaderboard.getRaceColumnByName("R3").getFactor(), 0.000000001);
|
||||
assertEquals(1.0, loadedLeaderboard.getScoringScheme().getScoreFactor(loadedLeaderboard.getRaceColumnByName("R1")), 0.000000001);
|
||||
assertEquals(1.5, loadedLeaderboard.getScoringScheme().getScoreFactor(loadedLeaderboard.getRaceColumnByName("R2")), 0.000000001);
|
||||
assertEquals(2.5, loadedLeaderboard.getScoringScheme().getScoreFactor(loadedLeaderboard.getRaceColumnByName("R3")), 0.000000001);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+12
-7
@@ -31,6 +31,7 @@ import com.sap.sailing.domain.common.TargetTimeInfo;
|
||||
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.ScoringScheme;
|
||||
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
@@ -74,8 +75,9 @@ public class RaceGroupFactory {
|
||||
Map<Series, List<RaceColumn>> seriesToRaceColumns = getSeriesToRaceColumns(leaderboard);
|
||||
Collection<SeriesWithRows> seriesWithRows = new ArrayList<>();
|
||||
for (Series series : getSeriesIterable(leaderboard, seriesToRaceColumns)) {
|
||||
seriesWithRows.add(new SeriesWithRowsImpl(series.getName(), series.isMedal(), series.isFleetsCanRunInParallel(), getRows(series,
|
||||
seriesToRaceColumns.get(series))));
|
||||
seriesWithRows
|
||||
.add(new SeriesWithRowsImpl(series.getName(), series.isMedal(), series.isFleetsCanRunInParallel(),
|
||||
getRows(series, seriesToRaceColumns.get(series), leaderboard.getScoringScheme())));
|
||||
}
|
||||
return seriesWithRows;
|
||||
}
|
||||
@@ -89,14 +91,16 @@ public class RaceGroupFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param raceColumns must be provided in the same order in which they appear in the series / leaderboard
|
||||
* @param raceColumns
|
||||
* must be provided in the same order in which they appear in the series / leaderboard
|
||||
*/
|
||||
private Collection<RaceRow> getRows(Series series, List<RaceColumn> raceColumns) {
|
||||
private Collection<RaceRow> getRows(Series series, List<RaceColumn> raceColumns, ScoringScheme scoringScheme) {
|
||||
Collection<RaceRow> rows = new ArrayList<>();
|
||||
for (Fleet fleet : series.getFleets()) {
|
||||
// We are taking the fleet name because there might be several "default fleet"
|
||||
// objects when TrackedRaces are linked onto this Leaderboard
|
||||
rows.add(new RaceRowImpl(fleet, getCells(fleet.getName(), raceColumns, isFirstRaceColumnVirtual(series))));
|
||||
rows.add(new RaceRowImpl(fleet,
|
||||
getCells(fleet.getName(), raceColumns, isFirstRaceColumnVirtual(series), scoringScheme)));
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
@@ -111,7 +115,7 @@ public class RaceGroupFactory {
|
||||
* {@link TrackedRace#getEstimatedTimeToComplete(TimePoint) estimation} for the current point in time, when the
|
||||
* request is being made, using this time point to determine the wind speed and direction for each leg.
|
||||
*/
|
||||
private List<RaceCell> getCells(String fleetName, List<RaceColumn> raceColumns, boolean isFirstRaceColumnVirtual) {
|
||||
private List<RaceCell> getCells(String fleetName, List<RaceColumn> raceColumns, boolean isFirstRaceColumnVirtual, ScoringScheme scoringScheme) {
|
||||
boolean skippedFirst = false;
|
||||
List<RaceCell> cells = new ArrayList<>();
|
||||
if (raceColumns != null) {
|
||||
@@ -131,7 +135,8 @@ public class RaceGroupFactory {
|
||||
targetTime = null;
|
||||
}
|
||||
cells.add(new RaceCellImpl(raceColumn.getName(), raceColumn.getRaceLog(fleet),
|
||||
raceColumn.getFactor(), raceColumn.getExplicitFactor(), zeroBasedIndexOfRaceInFleet++, targetTime));
|
||||
scoringScheme.getScoreFactor(raceColumn), raceColumn.getExplicitFactor(),
|
||||
zeroBasedIndexOfRaceInFleet++, targetTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1200,7 +1200,7 @@ public class LeaderboardsResource extends AbstractLeaderboardsResource {
|
||||
raceColumnsAsJson.add(raceColumnAsJson);
|
||||
raceColumnAsJson.put(RaceColumnConstants.RACE_COLUMN_NAME, rc.getName());
|
||||
raceColumnAsJson.put(RaceColumnConstants.EXPLICIT_FACTOR, rc.getExplicitFactor());
|
||||
raceColumnAsJson.put(RaceColumnConstants.FACTOR, rc.getFactor());
|
||||
raceColumnAsJson.put(RaceColumnConstants.FACTOR, leaderboard.getScoringScheme().getScoreFactor(rc));
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
+8
-12
@@ -411,7 +411,7 @@ public class MasterDataImportTest {
|
||||
|
||||
raceColumnOnTarget.setTrackedRace(fleet1OnTarget, trackedRaceForTarget);
|
||||
|
||||
Assert.assertEquals(factor, raceColumnOnTarget.getFactor());
|
||||
Assert.assertEquals(factor, leaderboard.getScoringScheme().getScoreFactor(raceColumnOnTarget));
|
||||
|
||||
Iterable<Competitor> competitorsOnTarget = leaderboardOnTarget.getAllCompetitors();
|
||||
Iterator<Competitor> competitorIterator = competitorsOnTarget.iterator();
|
||||
@@ -423,10 +423,8 @@ public class MasterDataImportTest {
|
||||
scoreCorrection,
|
||||
leaderboardOnTarget.getScoreCorrection().getExplicitScoreCorrection(competitorOnTarget,
|
||||
raceColumnOnTarget));
|
||||
Assert.assertEquals(
|
||||
maxPointsReason,
|
||||
leaderboardOnTarget.getScoreCorrection().getMaxPointsReason(competitorOnTarget, raceColumnOnTarget,
|
||||
MillisecondsTimePoint.now()));
|
||||
Assert.assertEquals(maxPointsReason, leaderboardOnTarget.getScoreCorrection()
|
||||
.getMaxPointsReason(competitorOnTarget, raceColumnOnTarget, MillisecondsTimePoint.now()));
|
||||
|
||||
// Check for carried points
|
||||
Assert.assertEquals(carriedPoints, leaderboardOnTarget.getCarriedPoints(competitorOnTarget));
|
||||
@@ -2093,7 +2091,7 @@ public class MasterDataImportTest {
|
||||
|
||||
RaceColumn metaColumn = metaColumns.iterator().next();
|
||||
Assert.assertNotNull(metaColumn);
|
||||
Assert.assertEquals(factor, metaColumn.getFactor());
|
||||
Assert.assertEquals(factor, overallLeaderboard.getScoringScheme().getScoreFactor(metaColumn));
|
||||
|
||||
// Verify that overall leaderboard data has been persisted
|
||||
RacingEventService persistenceVerifier = new RacingEventServiceImplMock(){};
|
||||
@@ -2115,7 +2113,7 @@ public class MasterDataImportTest {
|
||||
|
||||
metaColumn = metaColumns.iterator().next();
|
||||
Assert.assertNotNull(metaColumn);
|
||||
Assert.assertEquals(factor, metaColumn.getFactor());
|
||||
Assert.assertEquals(factor, overallLeaderboard.getScoringScheme().getScoreFactor(metaColumn));
|
||||
|
||||
}
|
||||
|
||||
@@ -2289,17 +2287,15 @@ public class MasterDataImportTest {
|
||||
|
||||
raceColumnOnTarget.setTrackedRace(defaultFleetOnTarget, trackedRaceForTarget);
|
||||
|
||||
Assert.assertEquals(factor, raceColumnOnTarget.getFactor());
|
||||
Assert.assertEquals(factor, leaderboardOnTarget.getScoringScheme().getScoreFactor(raceColumnOnTarget));
|
||||
|
||||
// Check for score corrections
|
||||
Assert.assertEquals(
|
||||
scoreCorrection,
|
||||
leaderboardOnTarget.getScoreCorrection().getExplicitScoreCorrection(competitorOnTarget,
|
||||
raceColumnOnTarget));
|
||||
Assert.assertEquals(
|
||||
maxPointsReason,
|
||||
leaderboardOnTarget.getScoreCorrection().getMaxPointsReason(competitorOnTarget, raceColumnOnTarget,
|
||||
MillisecondsTimePoint.now()));
|
||||
Assert.assertEquals(maxPointsReason, leaderboardOnTarget.getScoreCorrection()
|
||||
.getMaxPointsReason(competitorOnTarget, raceColumnOnTarget, MillisecondsTimePoint.now()));
|
||||
|
||||
// Check for carried points
|
||||
Assert.assertEquals(carriedPoints, leaderboardOnTarget.getCarriedPoints(competitorOnTarget));
|
||||
|
||||
Reference in new issue
Block a user