caching competitor results in leaderboard competitor so that for one time point all scores only need to be computed once

This commit is contained in:
Axel Uhl committed 2012-06-18 12:50:51 +02:00
1 parent fc41de7a51
commit 957cb5738a
4 files changed
+65 -61

No files matched your search

@@ -42,7 +42,7 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest {
}
@Test
public void testOneStartedRaceWithDifferentScores() {
public void testOneStartedRaceWithDifferentScores() throws NoWindException {
List<Competitor> competitors = createCompetitors(10);
Regatta regatta = createRegatta(/* qualifying */0, new String[] { "Default" }, /* final */1,
new String[] { "Default" },
@@ -97,7 +97,7 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest {
}
@Test
public void testDistributionAcrossQualifyingFleetsWithDifferentScores() {
public void testDistributionAcrossQualifyingFleetsWithDifferentScores() throws NoWindException {
List<Competitor> competitors = createCompetitors(10);
List<Competitor> yellow = new ArrayList<Competitor>();
List<Competitor> blue = new ArrayList<Competitor>();
@@ -127,7 +127,7 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest {
}
@Test
public void testDistributionAcrossFinalFleetsWithDifferentScores() {
public void testDistributionAcrossFinalFleetsWithDifferentScores() throws NoWindException {
List<Competitor> competitors = createCompetitors(10);
List<Competitor> gold = new ArrayList<Competitor>();
List<Competitor> silver = new ArrayList<Competitor>();
@@ -155,7 +155,7 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest {
}
@Test
public void testMedalTakesPrecedence() {
public void testMedalTakesPrecedence() throws NoWindException {
final int firstMedalCompetitorIndex = 3;
List<Competitor> competitors = createCompetitors(20);
List<Competitor> medal = competitors.subList(firstMedalCompetitorIndex, firstMedalCompetitorIndex+10);
@@ -159,8 +159,9 @@ public interface Leaderboard extends Named {
/**
* Sorts the competitors according to the overall regatta standings, considering the sorting rules for
* {@link Series}, {@link Fleet}s, medal races, discarding rules and score corrections.
* @throws NoWindException
*/
List<Competitor> getCompetitorsFromBestToWorst(TimePoint timePoint);
List<Competitor> getCompetitorsFromBestToWorst(TimePoint timePoint) throws NoWindException;
/**
* Fetches all entries for all competitors of all races tracked by this leaderboard in one sweep. This saves some
@@ -459,7 +459,7 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard, RaceColumn
}
@Override
public List<Competitor> getCompetitorsFromBestToWorst(TimePoint timePoint) {
public List<Competitor> getCompetitorsFromBestToWorst(TimePoint timePoint) throws NoWindException {
List<Competitor> result = new ArrayList<Competitor>();
for (Competitor competitor : getCompetitors()) {
result.add(competitor);
@@ -468,7 +468,7 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard, RaceColumn
return result;
}
protected Comparator<? super Competitor> getTotalRankComparator(TimePoint timePoint) {
protected Comparator<? super Competitor> getTotalRankComparator(TimePoint timePoint) throws NoWindException {
return new LeaderboardTotalRankComparator(this, timePoint, scoreComparator);
}
@@ -3,15 +3,17 @@ package com.sap.sailing.domain.leaderboard.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
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.common.NoWindError;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.leaderboard.Leaderboard;
/**
@@ -45,75 +47,76 @@ import com.sap.sailing.domain.leaderboard.Leaderboard;
*/
public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
private final Leaderboard leaderboard;
private final TimePoint timePoint;
private final Comparator<Integer> scoreComparator;
private final Map<Pair<Competitor, RaceColumn>, Integer> totalPointsCache;
public LeaderboardTotalRankComparator(Leaderboard leaderboard, TimePoint timePoint, Comparator<Integer> scoreComparator) {
public LeaderboardTotalRankComparator(Leaderboard leaderboard, TimePoint timePoint, Comparator<Integer> scoreComparator) throws NoWindException {
super();
this.leaderboard = leaderboard;
this.timePoint = timePoint;
this.scoreComparator = scoreComparator;
totalPointsCache = new HashMap<Pair<Competitor, RaceColumn>, Integer>();
for (Competitor competitor : leaderboard.getCompetitors()) {
for (RaceColumn raceColumn : leaderboard.getRaceColumns()) {
totalPointsCache.put(new Pair<Competitor, RaceColumn>(competitor, raceColumn),
leaderboard.getTotalPoints(competitor, raceColumn, timePoint));
}
}
}
protected Leaderboard getLeaderboard() {
return leaderboard;
}
protected TimePoint getTimePoint() {
return timePoint;
}
@Override
public int compare(Competitor o1, Competitor o2) {
try {
List<Integer> o1Scores = new ArrayList<Integer>();
List<Integer> o2Scores = new ArrayList<Integer>();
int o1ScoreSum = 0;
int o2ScoreSum = 0;
int o1MedalRaceScore = 0;
int o2MedalRaceScore = 0;
for (RaceColumn raceColumn : getLeaderboard().getRaceColumns()) {
int preemptiveColumnResult = 0;
final int o1Score = getLeaderboard().getTotalPoints(o1, raceColumn, timePoint);
if (o1Score != 0) {
o1Scores.add(o1Score);
o1ScoreSum += o1Score;
}
final int o2Score = getLeaderboard().getTotalPoints(o2, raceColumn, timePoint);
if (o2Score != 0) {
o2Scores.add(o2Score);
o2ScoreSum += o2Score;
}
if (raceColumn.isMedalRace()) {
o1MedalRaceScore = o1Score;
o2MedalRaceScore = o2Score;
// similar to compareByFleet, however, tracking is not required; having medal race column points (tracked or manual) is sufficient
preemptiveColumnResult = compareByMedalRaceParticipation(o1Score, o2Score);
}
if (preemptiveColumnResult == 0) {
preemptiveColumnResult = compareByFleet(raceColumn, o1, o2);
}
if (preemptiveColumnResult != 0) {
return preemptiveColumnResult;
}
List<Integer> o1Scores = new ArrayList<Integer>();
List<Integer> o2Scores = new ArrayList<Integer>();
int o1ScoreSum = 0;
int o2ScoreSum = 0;
int o1MedalRaceScore = 0;
int o2MedalRaceScore = 0;
for (RaceColumn raceColumn : getLeaderboard().getRaceColumns()) {
int preemptiveColumnResult = 0;
final int o1Score = totalPointsCache.get(new Pair<Competitor, RaceColumn>(o1, raceColumn));
if (o1Score != 0) {
o1Scores.add(o1Score);
o1ScoreSum += o1Score;
}
// now count the races in which they scored; if they scored in a different number of races, prefer the competitor
// who scored more often; otherwise, prefer the competitor who has a better score sum; if score sums are equal, 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 (result == 0) {
result = compareByMedalRaceScore(o1MedalRaceScore, o2MedalRaceScore);
if (result == 0) {
result = compareByBetterScore(o1Scores, o2Scores);
}
}
final int o2Score = totalPointsCache.get(new Pair<Competitor, RaceColumn>(o2, raceColumn));
if (o2Score != 0) {
o2Scores.add(o2Score);
o2ScoreSum += o2Score;
}
if (raceColumn.isMedalRace()) {
o1MedalRaceScore = o1Score;
o2MedalRaceScore = o2Score;
// similar to compareByFleet, however, tracking is not required; having medal race column points
// (tracked or manual) is sufficient
preemptiveColumnResult = compareByMedalRaceParticipation(o1Score, o2Score);
}
if (preemptiveColumnResult == 0) {
preemptiveColumnResult = compareByFleet(raceColumn, o1, o2);
}
if (preemptiveColumnResult != 0) {
return preemptiveColumnResult;
}
return result;
} catch (NoWindException e) {
throw new NoWindError(e);
}
// now count the races in which they scored; if they scored in a different number of races, prefer the
// competitor
// who scored more often; otherwise, prefer the competitor who has a better score sum; if score sums are equal,
// 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 (result == 0) {
result = compareByMedalRaceScore(o1MedalRaceScore, o2MedalRaceScore);
if (result == 0) {
result = compareByBetterScore(o1Scores, o2Scores);
}
}
}
return result;
}
/**