Merge remote-tracking branch 'origin/bug3838'

This commit is contained in:
Axel Uhl
2016-07-28 20:48:40 +02:00
6 changed files with 91 additions and 5 deletions
@@ -44,6 +44,7 @@ import com.sap.sailing.domain.common.tracking.GPSFix;
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.common.tracking.SensorFix;
import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike;
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
import com.sap.sailing.domain.polars.PolarDataService;
import com.sap.sailing.domain.ranking.RankingMetric;
@@ -522,6 +523,11 @@ public class MockedTrackedRace implements DynamicTrackedRace {
@Override
public void deregisterCompetitors(Iterable<Competitor> competitor) {
}
@Override
public CompetitorProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider() {
return null;
}
};
}
@@ -386,6 +386,14 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
return boatClass;
}
@Override
public CompetitorProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider() {
if (competitorsProvider == null) {
competitorsProvider = new CompetitorProviderFromRaceColumnsAndRegattaLike(this);
}
return competitorsProvider;
}
@Override
public Iterable<Competitor> getAllCompetitors() {
Set<Competitor> result = new HashSet<Competitor>();
@@ -1,7 +1,10 @@
package com.sap.sailing.domain.leaderboard;
import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike;
import com.sap.sailing.domain.regattalike.HasRegattaLike;
public interface HasRaceColumnsAndRegattaLike extends HasRegattaLike, HasRaceColumns {
CompetitorProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider();
}
@@ -101,7 +101,8 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI
return getOrCreateCompetitorsProvider().getAllCompetitors(raceColumn, fleet);
}
private CompetitorProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider() {
@Override
public CompetitorProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider() {
if (competitorsProvider == null) {
competitorsProvider = new CompetitorProviderFromRaceColumnsAndRegattaLike(this);
}
@@ -11,6 +11,8 @@ import java.util.Set;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnInSeries;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.common.NoWindError;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.leaderboard.Leaderboard;
@@ -113,6 +115,14 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
// the competitor scored in this or any subsequent columns
boolean needToResetO1ScoreUponNextValidResult = false;
boolean needToResetO2ScoreUponNextValidResult = false;
// Once we have established the fleet of a competitor in a series the fleet ordering for that competitor in that series
// cannot change anymore; if assigned to an ordered fleet, the ordering will have to remain unchanged throughout the fleet,
// and if assigned to an unordered fleet (ordering==0) the only change may be a re-assignment to a different unordered
// fleet but not to an ordered fleet. Therefore, once we know the fleet ordering for a competitor in a series for sure,
// we don't have to bother computing it again. It can be cached. See also bug 3838.
// The fleet stored here may not be the same fleet for the competitor for all columns in that series but
// 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
for (RaceColumn raceColumn : getLeaderboard().getRaceColumns()) {
needToResetO1ScoreUponNextValidResult = raceColumn.isStartsWithZeroScore();
@@ -174,7 +184,7 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
preemptiveColumnResult = compareByMedalRaceParticipation(o1Score, o2Score);
}
if (preemptiveColumnResult == 0 && raceColumn.isTotalOrderDefinedByFleet()) {
final FleetComparisonResult compareByFleetResult = compareByFleet(raceColumn, o1, o2);
final FleetComparisonResult compareByFleetResult = compareByFleet(raceColumn, o1, o2, fleetWithCorrectOrderingForCompetitorBySeries);
preemptiveColumnResult = compareByFleetResult.getAuthoritativeFleetComparisonResult();
if (defaultFleetBasedComparisonResult == 0) {
defaultFleetBasedComparisonResult = compareByFleetResult.getDefaultFleetComparisonResultBasedOnUnknownFleetAssignment();
@@ -264,9 +274,10 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
}
}
private FleetComparisonResult compareByFleet(RaceColumn raceColumn, Competitor o1, Competitor o2) {
Fleet o1f = raceColumn.getFleetOfCompetitor(o1);
Fleet o2f = raceColumn.getFleetOfCompetitor(o2);
private FleetComparisonResult compareByFleet(final RaceColumn raceColumn, final Competitor o1, final Competitor o2,
final Map<Series, Map<Competitor, Fleet>> fleetWithCorrectOrderingForCompetitorBySeries) {
final Fleet o1f = getAFleetWithCorrectOrderingOfCompetitorFromCacheOrRaceColumnAndCache(raceColumn, o1, fleetWithCorrectOrderingForCompetitorBySeries);
final Fleet o2f = getAFleetWithCorrectOrderingOfCompetitorFromCacheOrRaceColumnAndCache(raceColumn, o2, fleetWithCorrectOrderingForCompetitorBySeries);
// if the fleet for both was identified because both were tracked in this column, then if the fleets
// don't compare equal, return the fleet comparison as result immediately. Example: o1 competed in Gold fleet,
// o2 in Silver fleet; Gold compares better to Silver, so o1 is compared better to o2.
@@ -289,6 +300,58 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
return result;
}
/**
* Tries to find a fleet assignment for the {@code competitor} in the {@code fleetWithCorrectOrderingForCompetitorBySeries} cache for
* the {@link Series} corresponding with {@code RaceColumn} ({@code null} in case the column is not part of a {@link Regatta}).
* If found, that fleet is returned, although it may not be the exact fleet assignment for the competitor in that column, but
* at least it has the correct ordering which suffices for fleet comparisons.<p>
*
* If a fleet assignment is not found in the cache, the race column is {@link RaceColumn#getFleetOfCompetitor(Competitor) asked}
* for the competitor's fleet assignment. If a result is found, it is added to the {@code fleetWithCorrectOrderingForCompetitorBySeries}
* cache.
*/
private Fleet getAFleetWithCorrectOrderingOfCompetitorFromCacheOrRaceColumnAndCache(final RaceColumn raceColumn, final Competitor competitor,
final Map<Series, Map<Competitor, Fleet>> fleetWithCorrectOrderingForCompetitorBySeries) {
Fleet fleetWithCorrectOrdering = null;
final Series series;
if (raceColumn instanceof RaceColumnInSeries) {
series = ((RaceColumnInSeries) raceColumn).getSeries();
} else {
series = null;
}
Map<Competitor, Fleet> fleetForCompetitorInSeries = fleetWithCorrectOrderingForCompetitorBySeries.get(series);
if (fleetForCompetitorInSeries != null && fleetForCompetitorInSeries.containsKey(competitor)) {
fleetWithCorrectOrdering = fleetForCompetitorInSeries.get(competitor);
}
if (fleetWithCorrectOrdering == null) {
fleetWithCorrectOrdering = getFleetOfCompetitorFromRaceColumnAndCache(raceColumn, competitor,
fleetWithCorrectOrderingForCompetitorBySeries, series, fleetForCompetitorInSeries);
}
return fleetWithCorrectOrdering;
}
private Fleet getFleetOfCompetitorInRaceColumn(final RaceColumn raceColumn, final Competitor competitor) {
for (final Fleet fleet : raceColumn.getFleets()) {
if (Util.contains(getLeaderboard().getAllCompetitors(raceColumn, fleet), competitor)) {
return fleet;
}
}
return null;
}
private Fleet getFleetOfCompetitorFromRaceColumnAndCache(final RaceColumn raceColumn, final Competitor competitor,
final Map<Series, Map<Competitor, Fleet>> orderedFleetsForCompetitorsBySeries, final Series series,
Map<Competitor, Fleet> fleetForCompetitorInSeries) {
final Fleet fleetWithCorrectOrdering = getFleetOfCompetitorInRaceColumn(raceColumn, competitor);
if (fleetWithCorrectOrdering != null) {
if (fleetForCompetitorInSeries == null) {
fleetForCompetitorInSeries = new HashMap<>();
orderedFleetsForCompetitorsBySeries.put(series, fleetForCompetitorInSeries);
}
fleetForCompetitorInSeries.put(competitor, fleetWithCorrectOrdering);
}
return fleetWithCorrectOrdering;
}
/**
* If the race column only has one fleet, no decision is made and 0 is returned. Otherwise, if <code>fleet</code> is the
* best fleet with others in the column being worse, return "better" (lesser; -1). If <code>fleet</code> is the worst fleet
@@ -130,4 +130,9 @@ public class RegattaLeaderboardImpl extends AbstractLeaderboardImpl implements R
public BoatClass getBoatClass() {
return getRegatta().getBoatClass();
}
@Override
public CompetitorProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider() {
return getRegatta().getOrCreateCompetitorsProvider();
}
}