mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-28 00:16:46 +00:00
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:
@@ -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
|
||||
|
||||
+7
@@ -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
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+8
-8
@@ -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
@@ -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
|
||||
|
||||
+84
@@ -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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user