fixing bug in ScoreCorrectionImpl regarding the delayed application of MaxPointsReason and scores; added test case; use live time point for winner determination

Change-Id: I15606fe99c52b32580bf9191e1a592828642c346
This commit is contained in:
Axel Uhl committed 2016-04-29 17:34:02 +02:00
1 parent 3ffb2be543
commit fc6d0b3e24
3 files changed
+128 -29

No files matched your search

@@ -324,11 +324,39 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
@Override
public MaxPointsReason getMaxPointsReason(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint) {
MaxPointsReason result = maxPointsReasons.get(raceColumn.getKey(competitor));
if (result == null || !isMaxPointsReasonApplicable(result, timePoint, raceColumn, competitor)) {
result = MaxPointsReason.NONE;
return getAnnotatedMaxPointsReason(competitor, raceColumn, timePoint).getMaxPointsReason();
}
private static class AnnotatedMaxPointsReason {
private final MaxPointsReason maxPointsReason;
private final boolean maxPointsReasonExistsButIsNotApplicableForTimePoint;
public AnnotatedMaxPointsReason(MaxPointsReason maxPointsReason,
boolean maxPointsReasonExistsButIsNotApplicableForTimePoint) {
super();
this.maxPointsReason = maxPointsReason;
this.maxPointsReasonExistsButIsNotApplicableForTimePoint = maxPointsReasonExistsButIsNotApplicableForTimePoint;
}
return result;
public MaxPointsReason getMaxPointsReason() {
return maxPointsReason;
}
public boolean isMaxPointsReasonExistsButIsNotApplicableForTimePoint() {
return maxPointsReasonExistsButIsNotApplicableForTimePoint;
}
}
private AnnotatedMaxPointsReason getAnnotatedMaxPointsReason(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint) {
MaxPointsReason maxPointsReason = maxPointsReasons.get(raceColumn.getKey(competitor));
boolean maxPointsReasonExistsButIsNotApplicableForTimePoint;
if (maxPointsReason == null) {
maxPointsReason = MaxPointsReason.NONE;
maxPointsReasonExistsButIsNotApplicableForTimePoint = false;
} else if (!isMaxPointsReasonApplicable(maxPointsReason, timePoint, raceColumn, competitor)) {
maxPointsReason = MaxPointsReason.NONE;
maxPointsReasonExistsButIsNotApplicableForTimePoint = true;
} else {
maxPointsReasonExistsButIsNotApplicableForTimePoint = false;
}
return new AnnotatedMaxPointsReason(maxPointsReason, maxPointsReasonExistsButIsNotApplicableForTimePoint);
}
private boolean isMaxPointsReasonApplicable(MaxPointsReason maxPointsReason, TimePoint timePoint, RaceColumn raceColumn, Competitor competitor) {
@@ -360,15 +388,21 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
final NumberOfCompetitorsInLeaderboardFetcher numberOfCompetitorsInLeaderboardFetcher,
final ScoringScheme scoringScheme) {
Double result;
final MaxPointsReason maxPointsReason = getMaxPointsReason(competitor, raceColumn, timePoint);
if (maxPointsReason == MaxPointsReason.NONE) {
result = getCorrectedNonMaxedScore(competitor, raceColumn, trackedRankProvider, scoringScheme, numberOfCompetitorsInLeaderboardFetcher, timePoint);
final AnnotatedMaxPointsReason maxPointsReason = getAnnotatedMaxPointsReason(competitor, raceColumn, timePoint);
if (maxPointsReason.getMaxPointsReason() == MaxPointsReason.NONE) {
// could be that there is a MaxPointsReason that just doesn't apply yet at timePoint; in this
// case ignore the score correction and deliver the uncorrected result
if (maxPointsReason.isMaxPointsReasonExistsButIsNotApplicableForTimePoint()) {
result = getUncorrectedScore(competitor, raceColumn, trackedRankProvider, scoringScheme, numberOfCompetitorsInLeaderboardFetcher, timePoint);
} else {
result = getCorrectedNonMaxedScore(competitor, raceColumn, trackedRankProvider, scoringScheme, numberOfCompetitorsInLeaderboardFetcher, timePoint);
}
} else {
// allow explicit override even when max points reason is specified; calculation may be wrong,
// e.g., in case we have an untracked race and the number of competitors is estimated incorrectly
Double correctedNonMaxedScore = correctedScores.get(raceColumn.getKey(competitor));
if (correctedNonMaxedScore == null) {
result = scoringScheme.getPenaltyScore(raceColumn, competitor, maxPointsReason,
result = scoringScheme.getPenaltyScore(raceColumn, competitor, maxPointsReason.getMaxPointsReason(),
getNumberOfCompetitorsInRace(raceColumn, competitor, numberOfCompetitorsInLeaderboardFetcher),
numberOfCompetitorsInLeaderboardFetcher);
} else {
@@ -379,7 +413,7 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
return new Result() {
@Override
public MaxPointsReason getMaxPointsReason() {
return maxPointsReason;
return maxPointsReason.getMaxPointsReason();
}
@Override
@@ -446,25 +480,34 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
Double correctedNonMaxedScore = correctedScores.get(raceColumn.getKey(competitor));
Double result;
if (correctedNonMaxedScore == null || isCertainlyBeforeRaceFinish(timePoint, raceColumn, competitor)) {
try {
int trackedRank = trackedRankProvider.call();
result = scoringScheme.getScoreForRank(leaderboard, raceColumn, competitor,
trackedRank, new Callable<Integer>() {
@Override
public Integer call() {
return getNumberOfCompetitorsInRace(raceColumn, competitor, numberOfCompetitorsInLeaderboardFetcher);
}
}, numberOfCompetitorsInLeaderboardFetcher, timePoint);
} catch (Exception e) {
logger.log(Level.SEVERE, "Exception while computing corrected non maxed score", e);
throw new RuntimeException(e);
}
result = getUncorrectedScore(competitor, raceColumn, trackedRankProvider, scoringScheme,
numberOfCompetitorsInLeaderboardFetcher, timePoint);
} else {
result = correctedNonMaxedScore;
}
return result;
}
private Double getUncorrectedScore(final Competitor competitor, final RaceColumn raceColumn,
Callable<Integer> trackedRankProvider, ScoringScheme scoringScheme,
final NumberOfCompetitorsInLeaderboardFetcher numberOfCompetitorsInLeaderboardFetcher, TimePoint timePoint) {
final Double result;
try {
int trackedRank = trackedRankProvider.call();
result = scoringScheme.getScoreForRank(leaderboard, raceColumn, competitor,
trackedRank, new Callable<Integer>() {
@Override
public Integer call() {
return getNumberOfCompetitorsInRace(raceColumn, competitor, numberOfCompetitorsInLeaderboardFetcher);
}
}, numberOfCompetitorsInLeaderboardFetcher, timePoint);
} catch (Exception e) {
logger.log(Level.SEVERE, "Exception while computing uncorrected score", e);
throw new RuntimeException(e);
}
return result;
}
@Override
public Double getExplicitScoreCorrection(Competitor competitor, RaceColumn raceColumn) {
return correctedScores.get(raceColumn.getKey(competitor));