fixed serious bugs regarding storage of score corrections/max points reasons

One problem was the proper escaping of + characters which during URLDecoder.decode were
replaced by space. Another issue was that when directly calling setTrackedRace on a
RaceInLeaderboard column, the left-overs were not properly assigned. I fixed this using
a delegate pattern with a wrapper around the RaceInLeaderboard objects returned from
the leaderboard with delayed score correction / max points data. This, however, led to
a follow-up problem when constructing the keys used for the score correction / max points
maps: the wrappers were neither identical nor equal to the delegate. I now delegate the
key construction to the RaceInLeaderboard instance which gives the wrapper a chance to
use its delegate in the key constructed.
This commit is contained in:
Axel Uhl
2011-10-02 02:40:15 +02:00
parent 36eed1f770
commit 77079015d4
7 changed files with 110 additions and 15 deletions
+2
View File
@@ -4,6 +4,8 @@ Axel
- add test cases for leaderboard columns with untracked races in conjunction with max points
and score overriding
- add test cases for leaderboard storage regarding proper escaping of + signs
- Use wind estimator to feed another wind track
- make manuevering time a parameter coming from the boat class and use it in hasDirectionChange to
@@ -1,6 +1,8 @@
package com.sap.sailing.domain.leaderboard;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.util.Util.Pair;
/**
* A column in a {@link Leaderboard} that represents the data of a race. Over the life time of this object it can be
@@ -21,4 +23,9 @@ public interface RaceInLeaderboard extends LeaderboardColumn {
boolean isMedalRace();
void setName(String newName);
/**
* Constructs a key for maps storing corrections such as score corrections and max points reasons.
*/
Pair<Competitor, RaceInLeaderboard> getKey(Competitor competitor);
}
@@ -6,6 +6,7 @@ import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.RaceInLeaderboard;
import com.sap.sailing.domain.tracking.NoWindException;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.util.Util.Pair;
public class RaceInLeaderboardImpl implements RaceInLeaderboard {
private TrackedRace trackedRace;
@@ -18,7 +19,7 @@ public class RaceInLeaderboardImpl implements RaceInLeaderboard {
this.leaderboard = leaderboard;
this.medalRace = medalRace;
}
@Override
public int getTotalPoints(Competitor competitor, TimePoint timePoint) throws NoWindException {
if (getTrackedRace() != null) {
@@ -53,4 +54,8 @@ public class RaceInLeaderboardImpl implements RaceInLeaderboard {
this.name = newName;
}
@Override
public Pair<Competitor, RaceInLeaderboard> getKey(Competitor competitor) {
return new Pair<Competitor, RaceInLeaderboard>(competitor, this);
}
}
@@ -39,7 +39,7 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
@Override
public void setMaxPointsReason(Competitor competitor, RaceInLeaderboard raceColumn, MaxPointsReason reason) {
Pair<Competitor, RaceInLeaderboard> key = new Pair<Competitor, RaceInLeaderboard>(competitor, raceColumn);
Pair<Competitor, RaceInLeaderboard> key = raceColumn.getKey(competitor);
if (reason == null) {
maxPointsReasons.remove(key);
} else {
@@ -49,23 +49,23 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
@Override
public void correctScore(Competitor competitor, RaceInLeaderboard raceColumn, int points) {
correctedScores.put(new Pair<Competitor, RaceInLeaderboard>(competitor, raceColumn), points);
correctedScores.put(raceColumn.getKey(competitor), points);
}
@Override
public boolean isScoreCorrected(Competitor competitor, RaceInLeaderboard raceColumn) {
Pair<Competitor, RaceInLeaderboard> key = new Pair<Competitor, RaceInLeaderboard>(competitor, raceColumn);
Pair<Competitor, RaceInLeaderboard> key = raceColumn.getKey(competitor);
return correctedScores.containsKey(key) || maxPointsReasons.containsKey(key);
}
@Override
public void uncorrectScore(Competitor competitor, RaceInLeaderboard raceColumn) {
correctedScores.remove(new Pair<Competitor, RaceInLeaderboard>(competitor, raceColumn));
correctedScores.remove(raceColumn.getKey(competitor));
}
@Override
public MaxPointsReason getMaxPointsReason(Competitor competitor, RaceInLeaderboard raceColumn) {
MaxPointsReason result = maxPointsReasons.get(new Pair<Competitor, RaceInLeaderboard>(competitor, raceColumn));
MaxPointsReason result = maxPointsReasons.get(raceColumn.getKey(competitor));
if (result == null) {
result = MaxPointsReason.NONE;
}
@@ -89,7 +89,7 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
} 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
Integer correctedNonMaxedScore = correctedScores.get(new Pair<Competitor, RaceInLeaderboard>(competitor, raceColumn));
Integer correctedNonMaxedScore = correctedScores.get(raceColumn.getKey(competitor));
if (correctedNonMaxedScore == null) {
result = getMaxPoints(raceColumn.getTrackedRace(), numberOfCompetitorsInLeaderboard);
} else {
@@ -117,7 +117,7 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
* differences between what the tracking results suggest and what the jury or race committee decided.
*/
protected int getCorrectedNonMaxedScore(Competitor competitor, RaceInLeaderboard raceColumn, int uncorrectedScore) {
Integer correctedNonMaxedScore = correctedScores.get(new Pair<Competitor, RaceInLeaderboard>(competitor, raceColumn));
Integer correctedNonMaxedScore = correctedScores.get(raceColumn.getKey(competitor));
if (correctedNonMaxedScore == null) {
return uncorrectedScore;
} else {
@@ -131,7 +131,7 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
@Override
public Integer getExplicitScoreCorrection(Competitor competitor, RaceInLeaderboard raceColumn) {
return correctedScores.get(new Pair<Competitor, RaceInLeaderboard>(competitor, raceColumn));
return correctedScores.get(raceColumn.getKey(competitor));
}
}
@@ -1,3 +1,2 @@
# Module com.sap.sailing.gwt.ui.AdminConsole
# RPC service class, partial path of RPC policy file
com.sap.sailing.gwt.ui.client.SailingService, 11DA6BC91685E39664B32FD397B4B352.gwt.rpc
@@ -1,16 +1,21 @@
package com.sap.sailing.mongodb.impl;
import java.util.ArrayList;
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.TimePoint;
import com.sap.sailing.domain.leaderboard.RaceInLeaderboard;
import com.sap.sailing.domain.leaderboard.ScoreCorrection.MaxPointsReason;
import com.sap.sailing.domain.leaderboard.SettableScoreCorrection;
import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
import com.sap.sailing.domain.leaderboard.impl.LeaderboardImpl;
import com.sap.sailing.domain.tracking.NoWindException;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.util.Util.Pair;
/**
* Keeps a record of carried points and score corrections to be applied, keyed by the competitor names to which they
@@ -26,6 +31,56 @@ public class LeaderboardImplWithDelayedCarriedPoints extends LeaderboardImpl {
private final Map<String, Integer> carriedPointsByCompetitorName;
private final Map<String, Map<RaceInLeaderboard, MaxPointsReason>> maxPointsReasonsByCompetitorName;
private final Map<String, Map<RaceInLeaderboard, Integer>> correctedScoresByCompetitorName;
/**
* A wrapper for {@link RaceInLeaderboard} that, when its {@link #setTrackedRace(TrackedRace)} method is called,
* additionally calls {@link LeaderboardImplWithDelayedCarriedPoints#assignLeftOvers(TrackedRace)}.
*
* @author Axel Uhl (D043530)
*/
private class RaceInLeaderboardForDelayedCarriedPoints implements RaceInLeaderboard {
private final RaceInLeaderboard delegate;
public RaceInLeaderboardForDelayedCarriedPoints(RaceInLeaderboard delegate) {
this.delegate = delegate;
}
@Override
public void setTrackedRace(TrackedRace trackedRace) {
delegate.setTrackedRace(trackedRace);
assignLeftOvers(trackedRace);
}
@Override
public int getTotalPoints(Competitor competitor, TimePoint timePoint) throws NoWindException {
return delegate.getTotalPoints(competitor, timePoint);
}
@Override
public String getName() {
return delegate.getName();
}
@Override
public TrackedRace getTrackedRace() {
return delegate.getTrackedRace();
}
@Override
public boolean isMedalRace() {
return delegate.isMedalRace();
}
@Override
public void setName(String newName) {
delegate.setName(newName);
}
@Override
public Pair<Competitor, RaceInLeaderboard> getKey(Competitor competitor) {
return new Pair<Competitor, RaceInLeaderboard>(competitor, delegate);
}
}
public LeaderboardImplWithDelayedCarriedPoints(String name, SettableScoreCorrection scoreCorrection,
ThresholdBasedResultDiscardingRule resultDiscardingRule) {
@@ -69,6 +124,35 @@ public class LeaderboardImplWithDelayedCarriedPoints extends LeaderboardImpl {
return result;
}
/**
* As {@link RaceInLeaderboard} offers {@link RaceInLeaderboard#setTrackedRace(TrackedRace)}, wrapper objects
* are returned by this redefinition which, when that method is called, will additionally call
* {@link #assignLeftOvers(TrackedRace)}.
*
* @see RaceInLeaderboardForDelayedCarriedPoints
*/
@Override
public Iterable<RaceInLeaderboard> getRaceColumns() {
List<RaceInLeaderboard> result = new ArrayList<RaceInLeaderboard>();
for (RaceInLeaderboard ril : super.getRaceColumns()) {
result.add(new RaceInLeaderboardForDelayedCarriedPoints(ril));
}
return result;
}
/**
* As {@link RaceInLeaderboard} offers {@link RaceInLeaderboard#setTrackedRace(TrackedRace)}, a wrapper object
* is returned by this redefinition which, when that method is called, will additionally call
* {@link #assignLeftOvers(TrackedRace)}.
*
* @see RaceInLeaderboardForDelayedCarriedPoints
*/
@Override
public RaceInLeaderboard getRaceColumnByName(String columnName) {
RaceInLeaderboard raceColumn = super.getRaceColumnByName(columnName);
return raceColumn == null ? null : new RaceInLeaderboardForDelayedCarriedPoints(raceColumn);
}
/**
* Checks if there are any carried points, max points reasons or corrected scores left over that may now receive
* their competitor record. If so, {@link #setCarriedPoints(com.sap.sailing.domain.base.Competitor, int)},
@@ -14,11 +14,9 @@ public class MongoUtils {
* {@link #unescapeDollarAndDot(String)}.
*/
public static String escapeDollarAndDot(String key) {
String result = key.replace("%", "%25");
if (key.length() > 0 && key.charAt(0) == '$') {
result = "%24"+key.substring(1);
} else {
result = key;
String result = key.replace("%", "%25").replace("+", "%2B");
if (result.length() > 0 && result.charAt(0) == '$') {
result = "%24"+result.substring(1);
}
return result.replace(".", "%2E");
}