Merge remote-tracking branch 'origin/bug3752'

This commit is contained in:
Axel Uhl committed 2016-08-08 23:40:25 +02:00
commit bc5868453a
3 files changed
+103 -11

No files matched your search

@@ -42,7 +42,7 @@
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -incremental -war &quot;${project_loc:com.sap.sailing.dashboards.gwt}&quot; -startupUrl /dashboards/RibDashboard.html -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9998 com.sap.sailing.dashboards.gwt.RibDashboard"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -incremental -war &quot;${project_loc:com.sap.sailing.dashboards.gwt}&quot; -startupUrl /dashboards/RibDashboard.html -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort auto com.sap.sailing.dashboards.gwt.RibDashboard"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.dashboards.gwt"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m"/>
</launchConfiguration>
@@ -2103,6 +2103,92 @@ public class LeaderboardScoringAndRankingTest extends LeaderboardScoringAndRanki
}
}
/**
* See bug 3752 comment #6: when in an earlier race a competitor does not have a fleet assigned and the other one does, but in
* a later race in the same series both competitors are assigned to the same fleet, the authoritative answer based on the fleets
* must be that they compare equal; an earlier default based on "extreme fleet" considerations must be discarded if fleet equality
* is definitely established.
*/
@Test
public void testTotalRankComparatorForOrderedSplitFleetsWithUnknownFleetInPreviousRaceAndSameFleetInLaterRace() throws NoWindException {
series = new ArrayList<Series>();
// -------- qualification series ------------
{
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);
// discard the one and only qualification race; it doesn't score
qualificationSeries.setResultDiscardingRule(new ThresholdBasedResultDiscardingRuleImpl(new int[] { 1 }));
series.add(qualificationSeries);
}
// -------- final series ------------
{
List<Fleet> finalFleets = new ArrayList<Fleet>();
int fleetOrdering = 1;
for (String finalFleetName : new String[] { "Gold", "Silver" }) {
finalFleets.add(new FleetImpl(finalFleetName, fleetOrdering++));
}
List<String> finalRaceColumnNames = Arrays.asList("F1", "F2");
Series finalSeries = new SeriesImpl("Final", /* isMedal */false, /* isFleetsCanRunInParallel */ true, finalFleets, finalRaceColumnNames, /* trackedRegattaRegistry */ null);
series.add(finalSeries);
}
final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true);
Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass, /*startDate*/ null, /*endDate*/ null,
series, /* persistent */false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), "123", /* course area */null, OneDesignRankingMetric::new);
List<Competitor> competitors = createCompetitors(12);
final int firstYellowCompetitorIndex = 3;
List<Competitor> yellow = new ArrayList<>(competitors.subList(firstYellowCompetitorIndex, firstYellowCompetitorIndex+6));
List<Competitor> blue = new ArrayList<>(competitors);
blue.removeAll(yellow);
Collections.shuffle(yellow);
Collections.shuffle(blue);
final int firstGoldCompetitorIndex = 5;
List<Competitor> gold = new ArrayList<>(competitors.subList(firstGoldCompetitorIndex, firstGoldCompetitorIndex+6));
List<Competitor> silver = new ArrayList<>(competitors);
silver.removeAll(gold);
Collections.shuffle(gold);
Collections.shuffle(silver);
List<Competitor> lastRaceSilver = new ArrayList<>(silver);
final Competitor theUntrackedCompetitorInLastRace = lastRaceSilver.get(lastRaceSilver.size()-1);
lastRaceSilver.remove(theUntrackedCompetitorInLastRace); // one participant accidentally not tracked; expected to end up between silver and gold
List<Competitor> medal = new ArrayList<>(gold.subList(0, 2)); // take two gold race participants as medal race participants
List<Competitor> lastRaceGold = new ArrayList<>(gold);
lastRaceGold.removeAll(medal); // no medal race participant participates in the last race's gold fleet
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
TimePoint now = MillisecondsTimePoint.now();
TimePoint later = new MillisecondsTimePoint(now.asMillis()+1000);
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);
RaceColumn f1Column = series.get(1).getRaceColumnByName("F1");
TrackedRace f1Gold = new MockedTrackedRaceWithStartTimeAndRanks(now, gold);
f1Column.setTrackedRace(f1Column.getFleetByName("Gold"), f1Gold);
final List<Competitor> f1SilverWithOneMissing = new ArrayList<>(silver);
final Competitor missing = silver.get(silver.size()-1); // this competitor is not assigned to a fleet for F1, but for F2
f1SilverWithOneMissing.remove(missing);
TrackedRace f1Silver = new MockedTrackedRaceWithStartTimeAndRanks(now, f1SilverWithOneMissing);
f1Column.setTrackedRace(f1Column.getFleetByName("Silver"), f1Silver);
leaderboard.getScoreCorrection().correctScore(missing, f1Column, silver.size()); // set score to what it would have been
RaceColumn f2Column = series.get(1).getRaceColumnByName("F2");
TrackedRace f2Gold = new MockedTrackedRaceWithStartTimeAndRanks(now, gold);
f2Column.setTrackedRace(f2Column.getFleetByName("Gold"), f2Gold);
TrackedRace f2Silver = new MockedTrackedRaceWithStartTimeAndRanks(now, silver);
f2Column.setTrackedRace(f2Column.getFleetByName("Silver"), f2Silver);
List<Competitor> rankedCompetitors = leaderboard.getCompetitorsFromBestToWorst(later);
// the competitor missing from F1 Silver has worst score in both Silver fleet races and must rank last;
// with the bug still present, she would have ranked between Gold and Silver
assertEquals(missing, rankedCompetitors.get(rankedCompetitors.size()-1));
}
/**
* See bug 3798: special discarding rule that limits the number of discards for the final series; configured
* by {@link Series#getMaximumNumberOfDiscards()}.
@@ -185,8 +185,10 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
}
if (preemptiveColumnResult == 0 && raceColumn.isTotalOrderDefinedByFleet()) {
final FleetComparisonResult compareByFleetResult = compareByFleet(raceColumn, o1, o2, fleetWithCorrectOrderingForCompetitorBySeries);
preemptiveColumnResult = compareByFleetResult.getAuthoritativeFleetComparisonResult();
if (defaultFleetBasedComparisonResult == 0) {
if (compareByFleetResult.getAuthoritativeFleetComparisonResult() != null) {
preemptiveColumnResult = compareByFleetResult.getAuthoritativeFleetComparisonResult();
defaultFleetBasedComparisonResult = 0;
} else if (defaultFleetBasedComparisonResult == 0) {
defaultFleetBasedComparisonResult = compareByFleetResult.getDefaultFleetComparisonResultBasedOnUnknownFleetAssignment();
}
}
@@ -241,10 +243,14 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
private static class FleetComparisonResult {
/**
* Is non-{@code 0} if the two competitors have been identified as having raced in different fleets in
* {@code raceColumn} with those fleets having different {@link Fleet#getOrdering() orderings}.
* Evaluation of further comparison criteria is not necessary in this case.
* {@code raceColumn} with those fleets having different {@link Fleet#getOrdering() orderings}, or {@code 0}
* if the two competitors have been identified authoritatively having raced in the same fleet in
* {@code raceColumn}. Remains {@code null} if at least one competitor's fleet couldn't be identified.
* Evaluation of further comparison criteria is not necessary only if an authoritative non-{@code 0}
* answer was found. If fleet comparison has been calculated for all columns and no authoritative answer
* was found, the {@link #defaultFleetComparisonResultBasedOnUnknownFleetAssignment} result can be used.
*/
private final int authoritativeFleetComparisonResult;
private final Integer authoritativeFleetComparisonResult;
/**
* When for one of the two competitors compared the fleet in which she raced in a race column
@@ -258,14 +264,14 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
*/
private final int defaultFleetComparisonResultBasedOnUnknownFleetAssignment;
public FleetComparisonResult(int authoritativeFleetComparisonResult,
public FleetComparisonResult(Integer authoritativeFleetComparisonResult,
int defaultFleetComparisonResultBasedOnUnknownFleetAssignment) {
super();
this.authoritativeFleetComparisonResult = authoritativeFleetComparisonResult;
this.defaultFleetComparisonResultBasedOnUnknownFleetAssignment = defaultFleetComparisonResultBasedOnUnknownFleetAssignment;
}
public int getAuthoritativeFleetComparisonResult() {
public Integer getAuthoritativeFleetComparisonResult() {
return authoritativeFleetComparisonResult;
}
@@ -288,14 +294,14 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
} else {
// check if o1's fleet is best or worst in column; in that case, o1's membership in this fleet and the fact
// that o2 is not part of that fleet determines the result
result = new FleetComparisonResult(0, extremeFleetComparison(raceColumn, o1f));
result = new FleetComparisonResult(null, extremeFleetComparison(raceColumn, o1f));
}
} else if (o2f != null) {
// check if o2's fleet is best or worst in column; in that case, o2's membership in this fleet and the fact
// that o1 is not part of that fleet determines the result
result = new FleetComparisonResult(0, -extremeFleetComparison(raceColumn, o2f));
result = new FleetComparisonResult(null, -extremeFleetComparison(raceColumn, o2f));
} else {
result = new FleetComparisonResult(0, 0);
result = new FleetComparisonResult(null, 0);
}
return result;
}