mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-21 11:40:01 +00:00
Merge branch 'non-integer-scores'
This commit is contained in:
commit
37e1271c71
36 files changed
+395
-217
No files matched your search
+13
-13
@@ -32,16 +32,16 @@ import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
*/
|
||||
public class DelayedLeaderboardCorrectionsImpl implements DelayedLeaderboardCorrections {
|
||||
private static final long serialVersionUID = 8824782847677232275L;
|
||||
private final Map<String, Integer> carriedPointsByCompetitorName;
|
||||
private final Map<String, Double> carriedPointsByCompetitorName;
|
||||
private final Map<String, Map<RaceColumn, MaxPointsReason>> maxPointsReasonsByCompetitorName;
|
||||
private final Map<String, Map<RaceColumn, Integer>> correctedScoresByCompetitorName;
|
||||
private final Map<String, Map<RaceColumn, Double>> correctedScoresByCompetitorName;
|
||||
private final Map<String, String> displayNamesByCompetitorName;
|
||||
private final Leaderboard leaderboard;
|
||||
|
||||
public DelayedLeaderboardCorrectionsImpl(Leaderboard leaderboard) {
|
||||
carriedPointsByCompetitorName = new HashMap<String, Integer>();
|
||||
carriedPointsByCompetitorName = new HashMap<String, Double>();
|
||||
maxPointsReasonsByCompetitorName = new HashMap<String, Map<RaceColumn,MaxPointsReason>>();
|
||||
correctedScoresByCompetitorName = new HashMap<String, Map<RaceColumn,Integer>>();
|
||||
correctedScoresByCompetitorName = new HashMap<String, Map<RaceColumn, Double>>();
|
||||
displayNamesByCompetitorName = new HashMap<String, String>();
|
||||
this.leaderboard = leaderboard;
|
||||
leaderboard.addRaceColumnListener(this);
|
||||
@@ -61,7 +61,7 @@ public class DelayedLeaderboardCorrectionsImpl implements DelayedLeaderboardCorr
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCarriedPoints(String competitorName, int carriedPoints) {
|
||||
public void setCarriedPoints(String competitorName, double carriedPoints) {
|
||||
assertNoTrackedRaceAssociatedYet();
|
||||
carriedPointsByCompetitorName.put(competitorName, carriedPoints);
|
||||
}
|
||||
@@ -78,11 +78,11 @@ public class DelayedLeaderboardCorrectionsImpl implements DelayedLeaderboardCorr
|
||||
}
|
||||
|
||||
@Override
|
||||
public void correctScore(String competitorName, RaceColumn raceColumn, int correctedScore) {
|
||||
public void correctScore(String competitorName, RaceColumn raceColumn, double correctedScore) {
|
||||
assertNoTrackedRaceAssociatedYet();
|
||||
Map<RaceColumn, Integer> map = correctedScoresByCompetitorName.get(competitorName);
|
||||
Map<RaceColumn, Double> map = correctedScoresByCompetitorName.get(competitorName);
|
||||
if (map == null) {
|
||||
map = new HashMap<RaceColumn, Integer>();
|
||||
map = new HashMap<RaceColumn, Double>();
|
||||
correctedScoresByCompetitorName.put(competitorName, map);
|
||||
}
|
||||
map.put(raceColumn, correctedScore);
|
||||
@@ -101,8 +101,8 @@ public class DelayedLeaderboardCorrectionsImpl implements DelayedLeaderboardCorr
|
||||
for (Competitor competitor : race.getRace().getCompetitors()) {
|
||||
competitorsByName.put(competitor.getName(), competitor);
|
||||
}
|
||||
for (Iterator<Map.Entry<String, Integer>> carryEntryIter = carriedPointsByCompetitorName.entrySet().iterator(); carryEntryIter.hasNext(); ) {
|
||||
Map.Entry<String, Integer> carryEntry = carryEntryIter.next();
|
||||
for (Iterator<Map.Entry<String, Double>> carryEntryIter = carriedPointsByCompetitorName.entrySet().iterator(); carryEntryIter.hasNext(); ) {
|
||||
Map.Entry<String, Double> carryEntry = carryEntryIter.next();
|
||||
if (competitorsByName.containsKey(carryEntry.getKey())) {
|
||||
leaderboard.setCarriedPoints(competitorsByName.get(carryEntry.getKey()), carryEntry.getValue());
|
||||
carryEntryIter.remove();
|
||||
@@ -119,11 +119,11 @@ public class DelayedLeaderboardCorrectionsImpl implements DelayedLeaderboardCorr
|
||||
maxPointsReasonsEntryIter.remove();
|
||||
}
|
||||
}
|
||||
for (Iterator<java.util.Map.Entry<String, Map<RaceColumn, Integer>>> correctedScoresEntryIter =
|
||||
for (Iterator<java.util.Map.Entry<String, Map<RaceColumn, Double>>> correctedScoresEntryIter =
|
||||
correctedScoresByCompetitorName.entrySet().iterator(); correctedScoresEntryIter.hasNext();) {
|
||||
java.util.Map.Entry<String, Map<RaceColumn, Integer>> correctedScoresEntries = correctedScoresEntryIter.next();
|
||||
java.util.Map.Entry<String, Map<RaceColumn, Double>> correctedScoresEntries = correctedScoresEntryIter.next();
|
||||
if (competitorsByName.containsKey(correctedScoresEntries.getKey())) {
|
||||
for (java.util.Map.Entry<RaceColumn, Integer> correctedScoreEntry : correctedScoresEntries.getValue().entrySet()) {
|
||||
for (java.util.Map.Entry<RaceColumn, Double> correctedScoreEntry : correctedScoresEntries.getValue().entrySet()) {
|
||||
leaderboard.getScoreCorrection().correctScore(competitorsByName.get(correctedScoresEntries.getKey()),
|
||||
correctedScoreEntry.getKey(), correctedScoreEntry.getValue());
|
||||
}
|
||||
|
||||
+16
-5
@@ -199,7 +199,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
}
|
||||
if (result != null) {
|
||||
DelayedLeaderboardCorrections loadedLeaderboardCorrections = new DelayedLeaderboardCorrectionsImpl(result);
|
||||
loadLeaderboardCorrections(dbLeaderboard, loadedLeaderboardCorrections);
|
||||
loadLeaderboardCorrections(dbLeaderboard, loadedLeaderboardCorrections, scoreCorrection);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -262,17 +262,27 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
return result;
|
||||
}
|
||||
|
||||
private void loadLeaderboardCorrections(DBObject dbLeaderboard, DelayedLeaderboardCorrections correctionsToUpdate) {
|
||||
private void loadLeaderboardCorrections(DBObject dbLeaderboard, DelayedLeaderboardCorrections correctionsToUpdate,
|
||||
SettableScoreCorrection scoreCorrectionToUpdate) {
|
||||
DBObject carriedPoints = (DBObject) dbLeaderboard.get(FieldNames.LEADERBOARD_CARRIED_POINTS.name());
|
||||
if (carriedPoints != null) {
|
||||
for (String competitorName : carriedPoints.keySet()) {
|
||||
Integer carriedPointsForCompetitor = (Integer) carriedPoints.get(competitorName);
|
||||
Double carriedPointsForCompetitor = ((Number) carriedPoints.get(competitorName)).doubleValue();
|
||||
if (carriedPointsForCompetitor != null) {
|
||||
correctionsToUpdate.setCarriedPoints(MongoUtils.unescapeDollarAndDot(competitorName), carriedPointsForCompetitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
DBObject dbScoreCorrection = (DBObject) dbLeaderboard.get(FieldNames.LEADERBOARD_SCORE_CORRECTIONS.name());
|
||||
if (dbScoreCorrection.containsField(FieldNames.LEADERBOARD_SCORE_CORRECTION_TIMESTAMP.name())) {
|
||||
scoreCorrectionToUpdate.setTimePointOfLastCorrectionsValidity(
|
||||
new MillisecondsTimePoint((Long) dbScoreCorrection.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_TIMESTAMP.name())));
|
||||
dbScoreCorrection.removeField(FieldNames.LEADERBOARD_SCORE_CORRECTION_TIMESTAMP.name());
|
||||
}
|
||||
if (dbScoreCorrection.containsField(FieldNames.LEADERBOARD_SCORE_CORRECTION_COMMENT.name())) {
|
||||
scoreCorrectionToUpdate.setComment((String) dbScoreCorrection.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_COMMENT.name()));
|
||||
dbScoreCorrection.removeField(FieldNames.LEADERBOARD_SCORE_CORRECTION_COMMENT.name());
|
||||
}
|
||||
for (String raceName : dbScoreCorrection.keySet()) {
|
||||
DBObject dbScoreCorrectionForRace = (DBObject) dbScoreCorrection.get(raceName);
|
||||
for (String competitorName : dbScoreCorrectionForRace.keySet()) {
|
||||
@@ -284,8 +294,9 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON.name())));
|
||||
}
|
||||
if (dbScoreCorrectionForCompetitorInRace.containsField(FieldNames.LEADERBOARD_CORRECTED_SCORE.name())) {
|
||||
correctionsToUpdate.correctScore(MongoUtils.unescapeDollarAndDot(competitorName), raceColumn, (Integer) dbScoreCorrectionForCompetitorInRace
|
||||
.get(FieldNames.LEADERBOARD_CORRECTED_SCORE.name()));
|
||||
final Double leaderboardCorrectedScore = ((Number) dbScoreCorrectionForCompetitorInRace
|
||||
.get(FieldNames.LEADERBOARD_CORRECTED_SCORE.name())).doubleValue();
|
||||
correctionsToUpdate.correctScore(MongoUtils.unescapeDollarAndDot(competitorName), raceColumn, (Double) leaderboardCorrectedScore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -41,11 +41,12 @@ public enum FieldNames {
|
||||
|
||||
// leaderboard:
|
||||
LEADERBOARD_NAME, LEADERBOARD_COLUMNS, LEADERBOARD_COLUMN_NAME, LEADERBOARD_COMPETITOR_DISPLAY_NAMES, LEADERBOARD_IS_MEDAL_RACE_COLUMN,
|
||||
LEADERBOARD_CARRIED_POINTS, LEADERBOARD_SCORE_CORRECTIONS, LEADERBOARD_DISCARDING_THRESHOLDS, LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON, LEADERBOARD_CORRECTED_SCORE,
|
||||
LEADERBOARD_CARRIED_POINTS, LEADERBOARD_SCORE_CORRECTIONS, LEADERBOARD_DISCARDING_THRESHOLDS, LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON,
|
||||
LEADERBOARD_CORRECTED_SCORE, LEADERBOARD_SCORE_CORRECTION_TIMESTAMP, LEADERBOARD_SCORE_CORRECTION_COMMENT,
|
||||
|
||||
// leaderboard group
|
||||
LEADERBOARD_GROUP_NAME, LEADERBOARD_GROUP_DESCRIPTION, LEADERBOARD_GROUP_LEADERBOARDS,
|
||||
|
||||
// race ID to regatta name
|
||||
RACE_ID_AS_STRING
|
||||
RACE_ID_AS_STRING;
|
||||
}
|
||||
+9
-1
@@ -25,6 +25,7 @@ import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.common.RaceIdentifier;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.impl.Util.Triple;
|
||||
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
|
||||
@@ -205,7 +206,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
dbCorrectionForCompetitor.put(FieldNames.LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON.name(),
|
||||
maxPointsReason.name());
|
||||
}
|
||||
Integer explicitScoreCorrection = scoreCorrection
|
||||
Double explicitScoreCorrection = scoreCorrection
|
||||
.getExplicitScoreCorrection(competitor, raceColumn);
|
||||
if (explicitScoreCorrection != null) {
|
||||
dbCorrectionForCompetitor.put(FieldNames.LEADERBOARD_CORRECTED_SCORE.name(),
|
||||
@@ -218,6 +219,13 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
dbScoreCorrections.put(raceColumn.getName(), dbCorrectionForRace);
|
||||
}
|
||||
}
|
||||
final TimePoint timePointOfLastCorrectionsValidity = scoreCorrection.getTimePointOfLastCorrectionsValidity();
|
||||
if (timePointOfLastCorrectionsValidity != null) {
|
||||
dbScoreCorrections.put(FieldNames.LEADERBOARD_SCORE_CORRECTION_TIMESTAMP.name(), timePointOfLastCorrectionsValidity.asMillis());
|
||||
}
|
||||
if (scoreCorrection.getComment() != null) {
|
||||
dbScoreCorrections.put(FieldNames.LEADERBOARD_SCORE_CORRECTION_COMMENT.name(), scoreCorrection.getComment());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+9
-9
@@ -43,24 +43,24 @@ public class LeaderboardForKielWeekTest extends OnlineTracTracBasedTest {
|
||||
loadRace("357c700a-9d9a-11e0-85be-406186cbf87c"); // 505 Race 2
|
||||
Competitor hasso = getCompetitorByName("Dr.Plattner");
|
||||
RaceColumn column = leaderboard.addRace(getTrackedRace(), "Test Race 1", /* medalRace */ false, defaultFleet);
|
||||
assertEquals(21, leaderboard.getTotalPoints(hasso, now));
|
||||
assertEquals(21, leaderboard.getTotalPoints(hasso, now), 0.000000001);
|
||||
Pair<Competitor, RaceColumn> key = new Pair<Competitor, RaceColumn>(hasso, column);
|
||||
assertEquals(21, leaderboard.getContent(now).get(key).getTotalPoints());
|
||||
assertEquals(21, leaderboard.getEntry(hasso, column, now).getTotalPoints());
|
||||
assertEquals(21, leaderboard.getContent(now).get(key).getTotalPoints(), 0.000000001);
|
||||
assertEquals(21, leaderboard.getEntry(hasso, column, now).getTotalPoints(), 0.000000001);
|
||||
loadRace("e876c3a0-9da8-11e0-85be-406186cbf87c"); // 505 Race 3
|
||||
column = leaderboard.addRace(getTrackedRace(), "Test Race 2", /* medalRace */ false, defaultFleet);
|
||||
key = new Pair<Competitor, RaceColumn>(hasso, column);
|
||||
// In Race 3, Hasso ranked 31st
|
||||
assertEquals(52, leaderboard.getTotalPoints(hasso, now));
|
||||
assertEquals(31, leaderboard.getContent(now).get(key).getTotalPoints());
|
||||
assertEquals(31, leaderboard.getEntry(hasso, column, now).getTotalPoints());
|
||||
assertEquals(52, leaderboard.getTotalPoints(hasso, now), 0.000000001);
|
||||
assertEquals(31, leaderboard.getContent(now).get(key).getTotalPoints(), 0.000000001);
|
||||
assertEquals(31, leaderboard.getEntry(hasso, column, now).getTotalPoints(), 0.000000001);
|
||||
loadRace("7c666e50-9dde-11e0-85be-406186cbf87c"); // 505 Race 4
|
||||
column = leaderboard.addRace(getTrackedRace(), "Test Race 3", /* medalRace */ false, defaultFleet);
|
||||
key = new Pair<Competitor, RaceColumn>(hasso, column);
|
||||
// now the second race is discarded because Hasso ranked worst compared to the other two; in race 4 he ranked 11th
|
||||
assertEquals(32, leaderboard.getTotalPoints(hasso, now));
|
||||
assertEquals(11, leaderboard.getContent(now).get(key).getTotalPoints());
|
||||
assertEquals(11, leaderboard.getEntry(hasso, column, now).getTotalPoints());
|
||||
assertEquals(32, leaderboard.getTotalPoints(hasso, now), 0.000000001);
|
||||
assertEquals(11, leaderboard.getContent(now).get(key).getTotalPoints(), 0.000000001);
|
||||
assertEquals(11, leaderboard.getEntry(hasso, column, now).getTotalPoints(), 0.000000001);
|
||||
}
|
||||
|
||||
private void loadRace(String raceId) throws MalformedURLException, IOException, InterruptedException,
|
||||
|
||||
+14
-14
@@ -126,9 +126,9 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest {
|
||||
scoreCorrection.setMaxPointsReason(competitor, bestScoringRaceColumn, MaxPointsReason.DSQ);
|
||||
// assert that best scoring but now disqualified race gets max net points because of disqualification:
|
||||
assertEquals(Util.size(bestScoringRaceColumn.getTrackedRace(defaultFleet).getRace().getCompetitors())+1,
|
||||
leaderboard.getEntry(competitor, bestScoringRaceColumn, MillisecondsTimePoint.now()).getNetPoints());
|
||||
leaderboard.getEntry(competitor, bestScoringRaceColumn, MillisecondsTimePoint.now()).getNetPoints(), 0.000000001);
|
||||
// now assert that it gets discarded because due to disqualification it scores worse than all others:
|
||||
assertEquals(0, leaderboard.getEntry(competitor, bestScoringRaceColumn, MillisecondsTimePoint.now()).getTotalPoints());
|
||||
assertEquals(0, leaderboard.getEntry(competitor, bestScoringRaceColumn, MillisecondsTimePoint.now()).getTotalPoints(), 0.000000001);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -162,10 +162,10 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest {
|
||||
scoreCorrection.setMaxPointsReason(competitor, bestScoringRaceColumn, MaxPointsReason.DND);
|
||||
// assert that best scoring but now disqualified race gets max net points because of disqualification:
|
||||
assertEquals(Util.size(bestScoringRaceColumn.getTrackedRace(defaultFleet).getRace().getCompetitors())+1,
|
||||
leaderboard.getEntry(competitor, bestScoringRaceColumn, MillisecondsTimePoint.now()).getNetPoints());
|
||||
leaderboard.getEntry(competitor, bestScoringRaceColumn, MillisecondsTimePoint.now()).getNetPoints(), 0.000000001);
|
||||
// now assert that it does not get discarded because it's a DND
|
||||
assertEquals(Util.size(bestScoringRaceColumn.getTrackedRace(defaultFleet).getRace().getCompetitors())+1,
|
||||
leaderboard.getEntry(competitor, bestScoringRaceColumn, MillisecondsTimePoint.now()).getTotalPoints());
|
||||
leaderboard.getEntry(competitor, bestScoringRaceColumn, MillisecondsTimePoint.now()).getTotalPoints(), 0.000000001);
|
||||
}
|
||||
|
||||
protected void testLeaderboard(int numberOfStartedRaces, int numberOfNotStartedRaces, int firstDiscardingThreshold,
|
||||
@@ -208,30 +208,30 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest {
|
||||
assertEquals(rank, leaderboard.getTrackedRank(competitor, raceColumn, now));
|
||||
assertEquals(rank, leaderboard.getContent(now).get(key).getTrackedPoints());
|
||||
assertEquals(rank, leaderboard.getEntry(competitor, raceColumn, now).getTrackedPoints());
|
||||
assertEquals(rank, leaderboard.getNetPoints(competitor, raceColumn, now));
|
||||
assertEquals(rank, leaderboard.getContent(now).get(key).getNetPoints());
|
||||
assertEquals(rank, leaderboard.getEntry(competitor, raceColumn, now).getNetPoints());
|
||||
assertEquals(rank, leaderboard.getNetPoints(competitor, raceColumn, now), 0.000000001);
|
||||
assertEquals(rank, leaderboard.getContent(now).get(key).getNetPoints(), 0.000000001);
|
||||
assertEquals(rank, leaderboard.getEntry(competitor, raceColumn, now).getNetPoints(), 0.000000001);
|
||||
// One race is discarded because four races were started, and for [3-6) one race can be discarded.
|
||||
// The discarded race is the worst of those started, so the one with rank 4.
|
||||
int expectedNumberOfDiscardedRaces =
|
||||
numberOfRacesFromWhichToDiscard < firstDiscardingThreshold ? 0 : numberOfRacesFromWhichToDiscard < secondDiscardingThreshold ? 1 : 2;
|
||||
boolean discarded = ranksOfNonMedalStartedRaces.indexOf(rank) >= ranksOfNonMedalStartedRaces.size()-expectedNumberOfDiscardedRaces;
|
||||
int expected = discarded ? 0 : rank==medalRacePoints?2*rank:rank;
|
||||
assertEquals(expected, leaderboard.getTotalPoints(competitor, raceColumn, now));
|
||||
assertEquals(expected, leaderboard.getContent(now).get(key).getTotalPoints());
|
||||
assertEquals(expected, leaderboard.getEntry(competitor, raceColumn, now).getTotalPoints());
|
||||
assertEquals(expected, leaderboard.getTotalPoints(competitor, raceColumn, now), 0.000000001);
|
||||
assertEquals(expected, leaderboard.getContent(now).get(key).getTotalPoints(), 0.000000001);
|
||||
assertEquals(expected, leaderboard.getEntry(competitor, raceColumn, now).getTotalPoints(), 0.000000001);
|
||||
totalPoints += leaderboard.getContent(now).get(key).getTotalPoints();
|
||||
} else {
|
||||
assertEquals(0, leaderboard.getTrackedRank(competitor, raceColumn, now));
|
||||
assertEquals(0, leaderboard.getNetPoints(competitor, raceColumn, now));
|
||||
assertEquals(0, leaderboard.getNetPoints(competitor, raceColumn, now), 0.000000001);
|
||||
assertEquals(0, leaderboard.getContent(now).get(key).getTrackedPoints());
|
||||
assertEquals(0, leaderboard.getContent(now).get(key).getNetPoints());
|
||||
assertEquals(0, leaderboard.getContent(now).get(key).getNetPoints(), 0.000000001);
|
||||
assertEquals(0, leaderboard.getEntry(competitor, raceColumn, now).getTrackedPoints());
|
||||
assertEquals(0, leaderboard.getEntry(competitor, raceColumn, now).getNetPoints());
|
||||
assertEquals(0, leaderboard.getEntry(competitor, raceColumn, now).getNetPoints(), 0.000000001);
|
||||
// no increment on totalPoints
|
||||
}
|
||||
}
|
||||
assertEquals(totalPoints, leaderboard.getTotalPoints(competitor, now));
|
||||
assertEquals(totalPoints, leaderboard.getTotalPoints(competitor, now), 0.000000001);
|
||||
}
|
||||
|
||||
private int getMedalRacePoints(Competitor competitor, TimePoint at, Fleet fleet) throws NoWindException {
|
||||
|
||||
+7
-7
@@ -87,12 +87,12 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest {
|
||||
assertEquals(competitors.get(5), rankedCompetitors.get(9));
|
||||
|
||||
// Now test the total points and make sure the other competitors advanced by one, too
|
||||
assertEquals(11, leaderboard.getTotalPoints(competitors.get(5), f1Column, now));
|
||||
assertEquals(11, leaderboard.getTotalPoints(competitors.get(5), f1Column, now), 0.000000001);
|
||||
for (int i=0; i<5; i++) {
|
||||
assertEquals(i+1, leaderboard.getTotalPoints(competitors.get(i), f1Column, now));
|
||||
assertEquals(i+1, leaderboard.getTotalPoints(competitors.get(i), f1Column, now), 0.000000001);
|
||||
}
|
||||
for (int i=6; i<10; i++) {
|
||||
assertEquals(i, leaderboard.getTotalPoints(competitors.get(i), f1Column, now));
|
||||
assertEquals(i, leaderboard.getTotalPoints(competitors.get(i), f1Column, now), 0.000000001);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest {
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
TimePoint later = createAndAttachTrackedRaces(series.get(1), "Default", f1, f2, f3);
|
||||
List<Competitor> rankedCompetitors = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
assertEquals(leaderboard.getTotalPoints(c[0], later), leaderboard.getTotalPoints(c[1], later));
|
||||
assertEquals(leaderboard.getTotalPoints(c[0], later), leaderboard.getTotalPoints(c[1], later), 0.000000001);
|
||||
assertEquals(Arrays.asList(new Competitor[] { c[0], c[1], c[2] }), rankedCompetitors);
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest {
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
TimePoint later = createAndAttachTrackedRaces(series.get(1), "Default", f1, f2, f3, f4, f5, f6);
|
||||
List<Competitor> rankedCompetitors = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
assertEquals(leaderboard.getTotalPoints(c[0], later), leaderboard.getTotalPoints(c[1], later));
|
||||
assertEquals(leaderboard.getTotalPoints(c[0], later), leaderboard.getTotalPoints(c[1], later), 0.000000001);
|
||||
assertTrue(rankedCompetitors.indexOf(c[0]) == rankedCompetitors.indexOf(c[1])-1);
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest {
|
||||
createAndAttachTrackedRaces(series.get(2), "Medal", m1);
|
||||
List<Competitor> rankedCompetitors = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
// assert that both have equal score
|
||||
assertEquals(leaderboard.getTotalPoints(c[0], later), leaderboard.getTotalPoints(c[1], later));
|
||||
assertEquals(leaderboard.getTotalPoints(c[0], later), leaderboard.getTotalPoints(c[1], later), 0.000000001);
|
||||
// assert that c[0] ranks better than c[1] (reason: c[0] ranked better in medal race)
|
||||
assertEquals(rankedCompetitors.indexOf(c[0]), rankedCompetitors.indexOf(c[1])-1);
|
||||
}
|
||||
@@ -255,7 +255,7 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest {
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
TimePoint later = createAndAttachTrackedRaces(series.get(1), "Default", f1, f2, f3, f4, f5, f6);
|
||||
List<Competitor> rankedCompetitors = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
assertEquals(leaderboard.getTotalPoints(c[0], later), leaderboard.getTotalPoints(c[1], later));
|
||||
assertEquals(leaderboard.getTotalPoints(c[0], later), leaderboard.getTotalPoints(c[1], later), 0.000000001);
|
||||
assertEquals(rankedCompetitors.indexOf(c[0]), rankedCompetitors.indexOf(c[1])-1);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -19,9 +19,9 @@ import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
*
|
||||
*/
|
||||
public interface DelayedLeaderboardCorrections extends RaceColumnListener, Serializable {
|
||||
void correctScore(String competitorName, RaceColumn raceColumn, int correctedScore);
|
||||
void correctScore(String competitorName, RaceColumn raceColumn, double correctedScore);
|
||||
|
||||
void setCarriedPoints(String competitorName, int carriedPoints);
|
||||
void setCarriedPoints(String competitorName, double carriedPoints);
|
||||
|
||||
void setMaxPointsReason(String competitorName, RaceColumn raceColumn, MaxPointsReason maxPointsReason);
|
||||
|
||||
|
||||
@@ -40,8 +40,8 @@ public interface Leaderboard extends Named {
|
||||
*/
|
||||
public interface Entry {
|
||||
int getTrackedPoints();
|
||||
int getNetPoints() throws NoWindException;
|
||||
int getTotalPoints() throws NoWindException;
|
||||
double getNetPoints() throws NoWindException;
|
||||
double getTotalPoints() throws NoWindException;
|
||||
MaxPointsReason getMaxPointsReason();
|
||||
boolean isDiscarded() throws NoWindException;
|
||||
/**
|
||||
@@ -77,7 +77,7 @@ public interface Leaderboard extends Named {
|
||||
* the <code>competitor</code>. Returns <code>0</code> if there is no carried points definition for
|
||||
* <code>competitor</code>.
|
||||
*/
|
||||
int getCarriedPoints(Competitor competitor);
|
||||
double getCarriedPoints(Competitor competitor);
|
||||
|
||||
/**
|
||||
* Shorthand for {@link TrackedRace#getRank(Competitor, com.sap.sailing.domain.common.TimePoint)} with the
|
||||
@@ -106,7 +106,7 @@ public interface Leaderboard extends Named {
|
||||
* @param race
|
||||
* a race that is contained in the {@link #getRaceColumns()} result
|
||||
*/
|
||||
int getNetPoints(Competitor competitor, RaceColumn race, TimePoint timePoint) throws NoWindException;
|
||||
double getNetPoints(Competitor competitor, RaceColumn race, TimePoint timePoint) throws NoWindException;
|
||||
|
||||
/**
|
||||
* Tells if and why a competitor received "penalty" points for a race (however the scoring rules define the
|
||||
@@ -125,7 +125,7 @@ public interface Leaderboard extends Named {
|
||||
* @param race
|
||||
* a race that is contained in the {@link #getRaceColumns()} result
|
||||
*/
|
||||
int getTotalPoints(Competitor competitor, RaceColumn race, TimePoint timePoint) throws NoWindException;
|
||||
double getTotalPoints(Competitor competitor, RaceColumn race, TimePoint timePoint) throws NoWindException;
|
||||
|
||||
/**
|
||||
* Tells whether the contribution of <code>raceColumn</code> is discarded in the current leaderboard's standings for
|
||||
@@ -139,7 +139,7 @@ public interface Leaderboard extends Named {
|
||||
* Sums up the {@link #getTotalPoints(Competitor, TrackedRace, TimePoint) total points} of <code>competitor</code>
|
||||
* across all races tracked by this leaderboard.
|
||||
*/
|
||||
int getTotalPoints(Competitor competitor, TimePoint timePoint) throws NoWindException;
|
||||
double getTotalPoints(Competitor competitor, TimePoint timePoint) throws NoWindException;
|
||||
|
||||
/**
|
||||
* Sorts the competitors according to their ranking in the race column specified. Only competitors who have a score
|
||||
@@ -191,7 +191,7 @@ public interface Leaderboard extends Named {
|
||||
* simply added to the scores tracked by this leaderboard in the {@link #getTotalPoints(Competitor, TimePoint)}
|
||||
* method.
|
||||
*/
|
||||
void setCarriedPoints(Competitor competitor, int carriedPoints);
|
||||
void setCarriedPoints(Competitor competitor, double carriedPoints);
|
||||
|
||||
/**
|
||||
* Reverses the effect of {@link #setCarriedPoints(Competitor, int)}, i.e., afterwards, asking {@link #getCarriedPoints(Competitor)}
|
||||
|
||||
+15
-1
@@ -21,7 +21,7 @@ import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
*/
|
||||
public interface ScoreCorrection extends Serializable {
|
||||
public interface Result {
|
||||
int getCorrectedScore();
|
||||
double getCorrectedScore();
|
||||
MaxPointsReason getMaxPointsReason();
|
||||
boolean isCorrected();
|
||||
}
|
||||
@@ -51,4 +51,18 @@ public interface ScoreCorrection extends Serializable {
|
||||
*/
|
||||
boolean isScoreCorrected(Competitor competitor, RaceColumn raceColumn);
|
||||
|
||||
/**
|
||||
* Tells when the score correction was last updated. This should usually be the "validity time" and not the
|
||||
* "transaction time." In other words, if scores provided by the race committee are updated to this score correction
|
||||
* at time X, and the race committee's scores are tagged with time Y, then this method should return Y, not X. If
|
||||
* Y is not available for some reason, X may be used as a default.
|
||||
*/
|
||||
TimePoint getTimePointOfLastCorrectionsValidity();
|
||||
|
||||
/**
|
||||
* A free-form comment to display to the viewers of the leaderboard that has these score corrections. It should make
|
||||
* crystal clear if the scores are preliminary or not yet jury-finalized. If <code>null</code> is returned, this
|
||||
* always has to be interpreted as "preliminary" because then no comment as to the correctness have been made.
|
||||
*/
|
||||
String getComment();
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.sap.sailing.domain.leaderboard;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
|
||||
/**
|
||||
* Tells how ranks and disqualifications of a {@link TrackedRace} are converted into points in the scope
|
||||
* of a {@link Regatta}, also considering rules for discarding results. Different implementations may, e.g.,
|
||||
* distinguish between low-point and high-point scoring schemes, schemes where a winner's score is further
|
||||
* improved as well as different discarding thresholds.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public interface ScoringRules {
|
||||
/**
|
||||
* Note that scores can be fractional numbers, e.g., if the scoring rule determines that the winner's rank
|
||||
* is divided by two to obtain their score.
|
||||
*/
|
||||
BigDecimal getScore(TrackedRace trackedRace, Competitor competitor, TimePoint timePoint);
|
||||
}
|
||||
+6
-2
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.leaderboard;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
|
||||
public interface SettableScoreCorrection extends ScoreCorrection {
|
||||
|
||||
@@ -17,7 +18,7 @@ public interface SettableScoreCorrection extends ScoreCorrection {
|
||||
|
||||
MaxPointsReason getMaxPointsReason(Competitor competitor, RaceColumn raceColumn);
|
||||
|
||||
void correctScore(Competitor competitor, RaceColumn raceColumn, int points);
|
||||
void correctScore(Competitor competitor, RaceColumn raceColumn, double points);
|
||||
|
||||
/**
|
||||
* Removes a score correction which makes the competitor's score for <code>raceColumn</code> to fall back to the score
|
||||
@@ -29,8 +30,11 @@ public interface SettableScoreCorrection extends ScoreCorrection {
|
||||
* @return <code>null</code> if not set for the competitor, e.g., because no correction was made or an explicit
|
||||
* {@link MaxPointsReason} was provided for the competitor.
|
||||
*/
|
||||
Integer getExplicitScoreCorrection(Competitor competitor, RaceColumn raceColumn);
|
||||
Double getExplicitScoreCorrection(Competitor competitor, RaceColumn raceColumn);
|
||||
|
||||
boolean hasCorrectionFor(RaceColumn raceInLeaderboard);
|
||||
|
||||
void setTimePointOfLastCorrectionsValidity(TimePoint timePointOfLastCorrectionsValidity);
|
||||
|
||||
void setComment(String scoreCorrectionComment);
|
||||
}
|
||||
+26
-24
@@ -43,7 +43,7 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard, RaceColumn
|
||||
/**
|
||||
* The factor by which a medal race score is multiplied in the overall point scheme
|
||||
*/
|
||||
private static final int MEDAL_RACE_FACTOR = 2;
|
||||
private static final double MEDAL_RACE_FACTOR = 2.0;
|
||||
|
||||
private final SettableScoreCorrection scoreCorrection;
|
||||
private ThresholdBasedResultDiscardingRule resultDiscardingRule;
|
||||
@@ -59,9 +59,9 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard, RaceColumn
|
||||
* with aggregated results of races not tracked / displayed by this leaderboard in detail. The points
|
||||
* provided by this map are considered by {@link #getTotalPoints(Competitor, TimePoint)}.
|
||||
*/
|
||||
private final Map<Competitor, Integer> carriedPoints;
|
||||
private final Map<Competitor, Double> carriedPoints;
|
||||
|
||||
private final Comparator<Integer> scoreComparator;
|
||||
private final Comparator<Double> scoreComparator;
|
||||
|
||||
private Set<RaceColumnListener> raceColumnListeners;
|
||||
|
||||
@@ -79,14 +79,14 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard, RaceColumn
|
||||
*/
|
||||
private class EntryImpl implements Entry {
|
||||
private final Callable<Integer> trackedPoints;
|
||||
private final int netPoints;
|
||||
private final double netPoints;
|
||||
private final boolean isNetPointsCorrected;
|
||||
private final int totalPoints;
|
||||
private final double totalPoints;
|
||||
private final MaxPointsReason maxPointsReason;
|
||||
private final boolean discarded;
|
||||
private final Fleet fleet;
|
||||
|
||||
private EntryImpl(Callable<Integer> trackedPoints, int netPoints, boolean isNetPointsCorrected, int totalPoints,
|
||||
private EntryImpl(Callable<Integer> trackedPoints, double netPoints, boolean isNetPointsCorrected, double totalPoints,
|
||||
MaxPointsReason maxPointsReason, boolean discarded, Fleet fleet) {
|
||||
super();
|
||||
this.trackedPoints = trackedPoints;
|
||||
@@ -106,7 +106,7 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard, RaceColumn
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public int getNetPoints() {
|
||||
public double getNetPoints() {
|
||||
return netPoints;
|
||||
}
|
||||
@Override
|
||||
@@ -114,7 +114,7 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard, RaceColumn
|
||||
return isNetPointsCorrected;
|
||||
}
|
||||
@Override
|
||||
public int getTotalPoints() {
|
||||
public double getTotalPoints() {
|
||||
return totalPoints;
|
||||
}
|
||||
@Override
|
||||
@@ -132,12 +132,14 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard, RaceColumn
|
||||
}
|
||||
|
||||
/**
|
||||
* @param scoreCorrection must not be <code>null</code>
|
||||
* @param scoreComparator the comparator to use to compare basic scores, such as net points
|
||||
* @param name must not be <code>null</code>
|
||||
*/
|
||||
public AbstractLeaderboardImpl(SettableScoreCorrection scoreCorrection,
|
||||
ThresholdBasedResultDiscardingRule resultDiscardingRule, Comparator<Integer> scoreComparator) {
|
||||
this.carriedPoints = new HashMap<Competitor, Integer>();
|
||||
ThresholdBasedResultDiscardingRule resultDiscardingRule, Comparator<Double> scoreComparator) {
|
||||
assert scoreCorrection != null;
|
||||
this.carriedPoints = new HashMap<Competitor, Double>();
|
||||
this.scoreCorrection = scoreCorrection;
|
||||
this.displayNames = new HashMap<Competitor, String>();
|
||||
this.resultDiscardingRule = resultDiscardingRule;
|
||||
@@ -264,7 +266,7 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard, RaceColumn
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNetPoints(final Competitor competitor, final RaceColumn raceColumn, final TimePoint timePoint) throws NoWindException {
|
||||
public double getNetPoints(final Competitor competitor, final RaceColumn raceColumn, final TimePoint timePoint) throws NoWindException {
|
||||
return getScoreCorrection().getCorrectedScore(
|
||||
new Callable<Integer>() {
|
||||
public Integer call() throws NoWindException {
|
||||
@@ -288,15 +290,15 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard, RaceColumn
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalPoints(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint) throws NoWindException {
|
||||
public double getTotalPoints(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint) throws NoWindException {
|
||||
return isDiscarded(competitor, raceColumn, timePoint) ?
|
||||
0 :
|
||||
(raceColumn.isMedalRace() ? MEDAL_RACE_FACTOR : 1) * getNetPoints(competitor, raceColumn, timePoint);
|
||||
0.0 :
|
||||
(raceColumn.isMedalRace() ? MEDAL_RACE_FACTOR : 1.0) * getNetPoints(competitor, raceColumn, timePoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalPoints(Competitor competitor, TimePoint timePoint) throws NoWindException {
|
||||
int result = getCarriedPoints(competitor);
|
||||
public double getTotalPoints(Competitor competitor, TimePoint timePoint) throws NoWindException {
|
||||
double result = getCarriedPoints(competitor);
|
||||
for (RaceColumn r : getRaceColumns()) {
|
||||
result += getTotalPoints(competitor, r, timePoint);
|
||||
}
|
||||
@@ -315,7 +317,7 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard, RaceColumn
|
||||
boolean discarded = isDiscarded(competitor, race, timePoint);
|
||||
return new EntryImpl(trackedPoints, correctedResults.getCorrectedScore(), correctedResults.isCorrected(),
|
||||
discarded ? 0
|
||||
: correctedResults.getCorrectedScore() * (race.isMedalRace() ? MEDAL_RACE_FACTOR : 1),
|
||||
: correctedResults.getCorrectedScore() * (race.isMedalRace() ? MEDAL_RACE_FACTOR : 1.0),
|
||||
correctedResults.getMaxPointsReason(), discarded, race.getFleetOfCompetitor(competitor));
|
||||
}
|
||||
|
||||
@@ -348,7 +350,7 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard, RaceColumn
|
||||
boolean discarded = discardedRacesForCompetitor.contains(raceColumn);
|
||||
Entry entry = new EntryImpl(trackedPoints, correctedResults.getCorrectedScore(),
|
||||
correctedResults.isCorrected(), discarded ? 0 : correctedResults.getCorrectedScore()
|
||||
* (raceColumn.isMedalRace() ? MEDAL_RACE_FACTOR : 1), correctedResults.getMaxPointsReason(), discarded,
|
||||
* (raceColumn.isMedalRace() ? MEDAL_RACE_FACTOR : 1.0), correctedResults.getMaxPointsReason(), discarded,
|
||||
raceColumn.getFleetOfCompetitor(competitor));
|
||||
result.put(new Pair<Competitor, RaceColumn>(competitor, raceColumn), entry);
|
||||
}
|
||||
@@ -357,13 +359,13 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard, RaceColumn
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCarriedPoints(Competitor competitor, int carriedPoints) {
|
||||
public void setCarriedPoints(Competitor competitor, double carriedPoints) {
|
||||
this.carriedPoints.put(competitor, carriedPoints);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCarriedPoints(Competitor competitor) {
|
||||
Integer result = carriedPoints.get(competitor);
|
||||
public double getCarriedPoints(Competitor competitor) {
|
||||
Double result = carriedPoints.get(competitor);
|
||||
return result == null ? 0 : result;
|
||||
}
|
||||
|
||||
@@ -418,11 +420,11 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard, RaceColumn
|
||||
*/
|
||||
@Override
|
||||
public List<Competitor> getCompetitorsFromBestToWorst(final RaceColumn raceColumn, TimePoint timePoint) throws NoWindException {
|
||||
final Map<Competitor, Pair<Integer, Fleet>> netPointsAndFleet = new HashMap<Competitor, Pair<Integer, Fleet>>();
|
||||
final Map<Competitor, Pair<Double, Fleet>> netPointsAndFleet = new HashMap<Competitor, Pair<Double, Fleet>>();
|
||||
for (Competitor competitor : getCompetitors()) {
|
||||
int netPoints = getNetPoints(competitor, raceColumn, timePoint);
|
||||
double netPoints = getNetPoints(competitor, raceColumn, timePoint);
|
||||
if (netPoints != 0) {
|
||||
netPointsAndFleet.put(competitor, new Pair<Integer, Fleet>(netPoints, raceColumn.getFleetOfCompetitor(competitor)));
|
||||
netPointsAndFleet.put(competitor, new Pair<Double, Fleet>(netPoints, raceColumn.getFleetOfCompetitor(competitor)));
|
||||
}
|
||||
}
|
||||
List<Competitor> result = new ArrayList<Competitor>(netPointsAndFleet.keySet());
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements
|
||||
private String name;
|
||||
|
||||
public FlexibleLeaderboardImpl(String name, SettableScoreCorrection scoreCorrection,
|
||||
ThresholdBasedResultDiscardingRule resultDiscardingRule, Comparator<Integer> scoreComparator) {
|
||||
ThresholdBasedResultDiscardingRule resultDiscardingRule, Comparator<Double> scoreComparator) {
|
||||
super(scoreCorrection, resultDiscardingRule, scoreComparator);
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("A leaderboard's name must not be null");
|
||||
|
||||
+18
-18
@@ -47,14 +47,14 @@ import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
*/
|
||||
public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
|
||||
private final Leaderboard leaderboard;
|
||||
private final Comparator<Integer> scoreComparator;
|
||||
private final Map<Pair<Competitor, RaceColumn>, Integer> totalPointsCache;
|
||||
private final Comparator<Double> scoreComparator;
|
||||
private final Map<Pair<Competitor, RaceColumn>, Double> totalPointsCache;
|
||||
|
||||
public LeaderboardTotalRankComparator(Leaderboard leaderboard, TimePoint timePoint, Comparator<Integer> scoreComparator) throws NoWindException {
|
||||
public LeaderboardTotalRankComparator(Leaderboard leaderboard, TimePoint timePoint, Comparator<Double> scoreComparator) throws NoWindException {
|
||||
super();
|
||||
this.leaderboard = leaderboard;
|
||||
this.scoreComparator = scoreComparator;
|
||||
totalPointsCache = new HashMap<Pair<Competitor, RaceColumn>, Integer>();
|
||||
totalPointsCache = new HashMap<Pair<Competitor, RaceColumn>, Double>();
|
||||
for (Competitor competitor : leaderboard.getCompetitors()) {
|
||||
for (RaceColumn raceColumn : leaderboard.getRaceColumns()) {
|
||||
totalPointsCache.put(new Pair<Competitor, RaceColumn>(competitor, raceColumn),
|
||||
@@ -69,20 +69,20 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
|
||||
|
||||
@Override
|
||||
public int compare(Competitor o1, Competitor o2) {
|
||||
List<Integer> o1Scores = new ArrayList<Integer>();
|
||||
List<Integer> o2Scores = new ArrayList<Integer>();
|
||||
List<Double> o1Scores = new ArrayList<Double>();
|
||||
List<Double> o2Scores = new ArrayList<Double>();
|
||||
int o1ScoreSum = 0;
|
||||
int o2ScoreSum = 0;
|
||||
int o1MedalRaceScore = 0;
|
||||
int o2MedalRaceScore = 0;
|
||||
double o1MedalRaceScore = 0;
|
||||
double o2MedalRaceScore = 0;
|
||||
for (RaceColumn raceColumn : getLeaderboard().getRaceColumns()) {
|
||||
int preemptiveColumnResult = 0;
|
||||
final int o1Score = totalPointsCache.get(new Pair<Competitor, RaceColumn>(o1, raceColumn));
|
||||
final double o1Score = totalPointsCache.get(new Pair<Competitor, RaceColumn>(o1, raceColumn));
|
||||
if (o1Score != 0) {
|
||||
o1Scores.add(o1Score);
|
||||
o1ScoreSum += o1Score;
|
||||
}
|
||||
final int o2Score = totalPointsCache.get(new Pair<Competitor, RaceColumn>(o2, raceColumn));
|
||||
final double o2Score = totalPointsCache.get(new Pair<Competitor, RaceColumn>(o2, raceColumn));
|
||||
if (o2Score != 0) {
|
||||
o2Scores.add(o2Score);
|
||||
o2ScoreSum += o2Score;
|
||||
@@ -123,7 +123,7 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
|
||||
* Precondition: either both scored in medal race or both didn't. If both scored, the better score wins.
|
||||
* This is to be applied only if the total score of both competitors are equal to each other.
|
||||
*/
|
||||
private int compareByMedalRaceScore(int o1MedalRaceScore, int o2MedalRaceScore) {
|
||||
private int compareByMedalRaceScore(double o1MedalRaceScore, double o2MedalRaceScore) {
|
||||
assert o1MedalRaceScore != 0 || o2MedalRaceScore == 0;
|
||||
if (o1MedalRaceScore != 0) {
|
||||
return getScoreComparator().compare(o1MedalRaceScore, o2MedalRaceScore);
|
||||
@@ -185,7 +185,7 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
|
||||
return result;
|
||||
}
|
||||
|
||||
private int compareByMedalRaceParticipation(int o1Score, int o2Score) {
|
||||
private int compareByMedalRaceParticipation(double o1Score, double o2Score) {
|
||||
// if only one scored in medal race, this decides the order and returns immediately
|
||||
if (o1Score == 0) {
|
||||
if (o2Score != 0) {
|
||||
@@ -207,14 +207,14 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
|
||||
* @param o2Scores
|
||||
* @return
|
||||
*/
|
||||
protected int compareByBetterScore(List<Integer> o1Scores, List<Integer> o2Scores) {
|
||||
protected int compareByBetterScore(List<Double> o1Scores, List<Double> o2Scores) {
|
||||
assert o1Scores.size() == o2Scores.size();
|
||||
Comparator<Integer> scoreComparator = getScoreComparator();
|
||||
Comparator<Double> scoreComparator = getScoreComparator();
|
||||
Collections.sort(o1Scores, scoreComparator);
|
||||
Collections.sort(o2Scores, scoreComparator);
|
||||
// now both lists are sorted from best to worst score
|
||||
Iterator<Integer> o1Iter = o1Scores.iterator();
|
||||
Iterator<Integer> o2Iter = o2Scores.iterator();
|
||||
Iterator<Double> o1Iter = o1Scores.iterator();
|
||||
Iterator<Double> o2Iter = o2Scores.iterator();
|
||||
int result = 0;
|
||||
while (result == 0 && o1Iter.hasNext() && o2Iter.hasNext()) {
|
||||
result = scoreComparator.compare(o1Iter.next(), o2Iter.next());
|
||||
@@ -227,14 +227,14 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
|
||||
* scheme where lesser scores compare "better" which again means "lesser." Therefore, the comparator retunred compares
|
||||
* the integer numbers by their natural ordering.
|
||||
*/
|
||||
protected Comparator<Integer> getScoreComparator() {
|
||||
protected Comparator<Double> getScoreComparator() {
|
||||
return scoreComparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation ranks a competitor better (lesser) if it has the lower score sum
|
||||
*/
|
||||
protected int compareByScoreSum(int o1ScoreSum, int o2ScoreSum) {
|
||||
protected int compareByScoreSum(double o1ScoreSum, double o2ScoreSum) {
|
||||
return getScoreComparator().compare(o1ScoreSum, o2ScoreSum);
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -9,12 +9,12 @@ import java.util.Comparator;
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public class LowerScoreIsBetter implements Comparator<Integer>, Serializable {
|
||||
public class LowerScoreIsBetter implements Comparator<Double>, Serializable {
|
||||
private static final long serialVersionUID = -2767385186133743330L;
|
||||
|
||||
@Override
|
||||
public int compare(Integer o1, Integer o2) {
|
||||
return o1-o2;
|
||||
public int compare(Double o1, Double o2) {
|
||||
return Double.valueOf(o1).compareTo(Double.valueOf(o2));
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -29,7 +29,7 @@ public class RegattaLeaderboardImpl extends AbstractLeaderboardImpl implements R
|
||||
private final Regatta regatta;
|
||||
|
||||
public RegattaLeaderboardImpl(Regatta regatta, SettableScoreCorrection scoreCorrection,
|
||||
ThresholdBasedResultDiscardingRule resultDiscardingRule, Comparator<Integer> scoreComparator) {
|
||||
ThresholdBasedResultDiscardingRule resultDiscardingRule, Comparator<Double> scoreComparator) {
|
||||
super(scoreCorrection, resultDiscardingRule, scoreComparator);
|
||||
this.regatta = regatta;
|
||||
regatta.addRaceColumnListener(this);
|
||||
|
||||
+2
-1
@@ -57,7 +57,8 @@ public class ResultDiscardingRuleImpl implements ThresholdBasedResultDiscardingR
|
||||
@Override
|
||||
public int compare(RaceColumn o1, RaceColumn o2) {
|
||||
try {
|
||||
return leaderboard.getNetPoints(competitor, o1, timePoint) - leaderboard.getNetPoints(competitor, o2, timePoint);
|
||||
return Double.valueOf(leaderboard.getNetPoints(competitor, o1, timePoint)).compareTo(
|
||||
Double.valueOf(leaderboard.getNetPoints(competitor, o2, timePoint)));
|
||||
} catch (NoWindException e) {
|
||||
throw new NoWindError(e);
|
||||
}
|
||||
|
||||
+44
-10
@@ -33,11 +33,25 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
|
||||
/**
|
||||
* If no score correction is provided here, the uncorrected points are the default.
|
||||
*/
|
||||
private final Map<Pair<Competitor, RaceColumn>, Integer> correctedScores;
|
||||
private final Map<Pair<Competitor, RaceColumn>, Double> correctedScores;
|
||||
|
||||
/**
|
||||
* If <code>null</code>, despite a non-<code>null</code> {@link #timePointOfLastCorrectionsValidity} value the result have to be assumed
|
||||
* to be preliminary and need to be displayed with a corresponding hint.
|
||||
*/
|
||||
private String comment;
|
||||
|
||||
/**
|
||||
* Tells when the score correction was last updated. This should usually be the "validity time" and not the
|
||||
* "transaction time." In other words, if scores provided by the race committee are updated to this score correction
|
||||
* at time X, and the race committee's scores are tagged with time Y, then this method should return Y, not X. If
|
||||
* Y is not available for some reason, X may be used as a default.
|
||||
*/
|
||||
private TimePoint timePointOfLastCorrectionsValidity;
|
||||
|
||||
public ScoreCorrectionImpl() {
|
||||
this.maxPointsReasons = new HashMap<Util.Pair<Competitor,RaceColumn>, MaxPointsReason>();
|
||||
this.correctedScores = new HashMap<Util.Pair<Competitor,RaceColumn>, Integer>();
|
||||
this.correctedScores = new HashMap<Util.Pair<Competitor,RaceColumn>, Double>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,7 +65,7 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void correctScore(Competitor competitor, RaceColumn raceColumn, int points) {
|
||||
public void correctScore(Competitor competitor, RaceColumn raceColumn, double points) {
|
||||
correctedScores.put(raceColumn.getKey(competitor), points);
|
||||
}
|
||||
|
||||
@@ -85,21 +99,21 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
|
||||
@Override
|
||||
public Result getCorrectedScore(Callable<Integer> uncorrectedScore, final Competitor competitor, final RaceColumn raceColumn,
|
||||
TimePoint timePoint, int numberOfCompetitorsInLeaderboard) {
|
||||
int result;
|
||||
double result;
|
||||
final MaxPointsReason maxPointsReason = getMaxPointsReason(competitor, raceColumn);
|
||||
if (maxPointsReason == MaxPointsReason.NONE) {
|
||||
result = getCorrectedNonMaxedScore(competitor, raceColumn, uncorrectedScore);
|
||||
} 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(raceColumn.getKey(competitor));
|
||||
Double correctedNonMaxedScore = correctedScores.get(raceColumn.getKey(competitor));
|
||||
if (correctedNonMaxedScore == null) {
|
||||
result = getMaxPoints(raceColumn.getTrackedRace(competitor), numberOfCompetitorsInLeaderboard);
|
||||
} else {
|
||||
result = correctedNonMaxedScore;
|
||||
}
|
||||
}
|
||||
final int correctedScore = result;
|
||||
final double correctedScore = result;
|
||||
return new Result() {
|
||||
@Override
|
||||
public MaxPointsReason getMaxPointsReason() {
|
||||
@@ -107,7 +121,7 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCorrectedScore() {
|
||||
public double getCorrectedScore() {
|
||||
return correctedScore;
|
||||
}
|
||||
|
||||
@@ -123,8 +137,8 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
|
||||
* reasons, computes the corrected score. If {@link #correctedScores} contains an entry for the <code>competitor</code>'s key,
|
||||
* it is used. Otherwise, the <code>uncorrectedScore</code> is returned.
|
||||
*/
|
||||
protected int getCorrectedNonMaxedScore(Competitor competitor, RaceColumn raceColumn, Callable<Integer> uncorrectedScore) {
|
||||
Integer correctedNonMaxedScore = correctedScores.get(raceColumn.getKey(competitor));
|
||||
protected double getCorrectedNonMaxedScore(Competitor competitor, RaceColumn raceColumn, Callable<Integer> uncorrectedScore) {
|
||||
Double correctedNonMaxedScore = correctedScores.get(raceColumn.getKey(competitor));
|
||||
if (correctedNonMaxedScore == null) {
|
||||
try {
|
||||
return uncorrectedScore.call();
|
||||
@@ -141,7 +155,7 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getExplicitScoreCorrection(Competitor competitor, RaceColumn raceColumn) {
|
||||
public Double getExplicitScoreCorrection(Competitor competitor, RaceColumn raceColumn) {
|
||||
return correctedScores.get(raceColumn.getKey(competitor));
|
||||
}
|
||||
|
||||
@@ -160,4 +174,24 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimePoint getTimePointOfLastCorrectionsValidity() {
|
||||
return timePointOfLastCorrectionsValidity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTimePointOfLastCorrectionsValidity(TimePoint timePointOfLastCorrectionsValidity) {
|
||||
this.timePointOfLastCorrectionsValidity = timePointOfLastCorrectionsValidity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComment(String scoreCorrectionComment) {
|
||||
this.comment = scoreCorrectionComment;
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -51,7 +51,7 @@ public class TestColumnSwapping {
|
||||
leaderboardCreationDate = new Date();
|
||||
try {
|
||||
// get Leaderboard with name and current date
|
||||
leaderboardOriginalDTO = new LeaderboardDTO();
|
||||
leaderboardOriginalDTO = new LeaderboardDTO(null, null);
|
||||
leaderboardOriginalDTO.addRace("Race1", DEFAULT_FLEET, true, null, null);
|
||||
leaderboardOriginalDTO.addRace("Race3", DEFAULT_FLEET, true, null, null);
|
||||
leaderboardOriginalDTO.addRace("Race2", DEFAULT_FLEET, true, null, null);
|
||||
@@ -101,7 +101,7 @@ public class TestColumnSwapping {
|
||||
|
||||
@Test
|
||||
public void testLeaderBoardDTOMethods() {
|
||||
lb = new LeaderboardDTO();
|
||||
lb = new LeaderboardDTO(null, null);
|
||||
assertNotNull("Leaderboard != NULL", lb);
|
||||
lb.addRace("1", DEFAULT_FLEET, false, null, null);
|
||||
lb.addRace("2", DEFAULT_FLEET, false, null, null);
|
||||
|
||||
+7
-4
@@ -162,17 +162,17 @@ public interface SailingService extends RemoteService {
|
||||
|
||||
Map<String, RegattaAndRaceIdentifier> getRegattaAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(String leaderboardName, String raceColumnName);
|
||||
|
||||
void updateLeaderboardCarryValue(String leaderboardName, String competitorIdAsString, Integer carriedPoints);
|
||||
void updateLeaderboardCarryValue(String leaderboardName, String competitorIdAsString, Double carriedPoints);
|
||||
|
||||
/**
|
||||
* @return the new net points in {@link Pair#getA()} and the new total points in {@link Pair#getB()} for time point
|
||||
* <code>date</code> after the max points reason has been updated to <code>maxPointsReasonAsString</code>.
|
||||
*/
|
||||
Triple<Integer, Integer, Boolean> updateLeaderboardMaxPointsReason(String leaderboardName, String competitorIdAsString,
|
||||
Triple<Double, Double, Boolean> updateLeaderboardMaxPointsReason(String leaderboardName, String competitorIdAsString,
|
||||
String raceColumnName, MaxPointsReason maxPointsReason, Date date) throws NoWindException;
|
||||
|
||||
Triple<Integer, Integer, Boolean> updateLeaderboardScoreCorrection(String leaderboardName, String competitorIdAsString,
|
||||
String columnName, Integer correctedScore, Date date) throws NoWindException;
|
||||
Triple<Double, Double, Boolean> updateLeaderboardScoreCorrection(String leaderboardName, String competitorIdAsString,
|
||||
String columnName, Double correctedScore, Date date) throws NoWindException;
|
||||
|
||||
void updateCompetitorDisplayNameInLeaderboard(String leaderboardName, String competitorIdAsString, String displayName);
|
||||
|
||||
@@ -252,4 +252,7 @@ public interface SailingService extends RemoteService {
|
||||
void removeFregURLs(Set<String> toRemove) throws Exception;
|
||||
|
||||
void addFragUrl(String result) throws Exception;
|
||||
|
||||
Void updateLeaderboardScoreCorrectionMetadata(String leaderboardName, Date timePointOfLastCorrectionValidity,
|
||||
String comment);
|
||||
}
|
||||
+6
-3
@@ -226,13 +226,16 @@ public interface SailingServiceAsync {
|
||||
void disconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String raceColumnName, String fleetName,
|
||||
AsyncCallback<Void> callback);
|
||||
|
||||
void updateLeaderboardCarryValue(String leaderboardName, String competitorIdAsString, Integer carriedPoints, AsyncCallback<Void> callback);
|
||||
void updateLeaderboardCarryValue(String leaderboardName, String competitorIdAsString, Double carriedPoints, AsyncCallback<Void> callback);
|
||||
|
||||
void updateLeaderboardMaxPointsReason(String leaderboardName, String competitorIdAsString, String raceColumnName,
|
||||
MaxPointsReason maxPointsReason, Date date, AsyncCallback<Triple<Integer, Integer, Boolean>> asyncCallback);
|
||||
MaxPointsReason maxPointsReason, Date date, AsyncCallback<Triple<Double, Double, Boolean>> asyncCallback);
|
||||
|
||||
void updateLeaderboardScoreCorrection(String leaderboardName, String competitorIdAsString, String columnName,
|
||||
Integer correctedScore, Date date, AsyncCallback<Triple<Integer, Integer, Boolean>> asyncCallback);
|
||||
Double correctedScore, Date date, AsyncCallback<Triple<Double, Double, Boolean>> asyncCallback);
|
||||
|
||||
void updateLeaderboardScoreCorrectionMetadata(String leaderboardName, Date timePointOfLastCorrectionValidity,
|
||||
String comment, AsyncCallback<Void> callback);
|
||||
|
||||
void updateLeaderboardScoreCorrectionsAndMaxPointsReasons(BulkScoreCorrectionDTO updates,
|
||||
AsyncCallback<Void> callback);
|
||||
|
||||
+23
-11
@@ -19,6 +19,7 @@ import com.google.gwt.cell.client.TextCell;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.i18n.client.NumberFormat;
|
||||
import com.google.gwt.resources.client.ImageResource;
|
||||
import com.google.gwt.safehtml.shared.SafeHtml;
|
||||
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
|
||||
@@ -92,6 +93,8 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
|
||||
private static final int SAIL_ID_COLUMN_INDEX = 1;
|
||||
|
||||
private static final int CARRY_COLUMN_INDEX = 3;
|
||||
|
||||
protected static final NumberFormat scoreFormat = NumberFormat.getFormat("0.00");
|
||||
|
||||
private final SailingServiceAsync sailingService;
|
||||
|
||||
@@ -489,15 +492,16 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
|
||||
if (entry.reasonForMaxPoints == null || entry.reasonForMaxPoints == MaxPointsReason.NONE) {
|
||||
if (!entry.discarded) {
|
||||
html.appendHtmlConstant("<span style=\"font-weight: bold;\">");
|
||||
html.appendHtmlConstant(entry.totalPoints == 0 ? "" : ""+entry.totalPoints);
|
||||
html.appendHtmlConstant(entry.totalPoints == 0 ? "" : scoreFormat.format(entry.totalPoints));
|
||||
html.appendHtmlConstant("</span>");
|
||||
} else {
|
||||
html.appendHtmlConstant(" <span style=\"opacity: 0.5;\"><del>");
|
||||
html.appendHtmlConstant(entry.netPoints == 0 ? "" : ""+entry.netPoints);
|
||||
html.appendHtmlConstant(entry.netPoints == 0 ? "" : scoreFormat.format(entry.netPoints));
|
||||
html.appendHtmlConstant("</del></span>");
|
||||
}
|
||||
} else {
|
||||
html.appendHtmlConstant(" <span title=\""+entry.netPoints+"/"+entry.totalPoints+"\" style=\"opacity: 0.5;\">");
|
||||
html.appendHtmlConstant(" <span title=\""+scoreFormat.format(entry.netPoints)+"/"+
|
||||
scoreFormat.format(entry.totalPoints)+"\" style=\"opacity: 0.5;\">");
|
||||
if (entry.discarded) {
|
||||
html.appendHtmlConstant("<del>");
|
||||
}
|
||||
@@ -562,10 +566,11 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
|
||||
legColumns = new ArrayList<LegColumn>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue(LeaderboardRowDTO object) {
|
||||
final int totalPoints = object.fieldsByRaceColumnName.get(getRaceColumnName()).totalPoints;
|
||||
return "" + (totalPoints == 0 ? "" : totalPoints);
|
||||
// The following code exists only for robustness. This method should never be called because
|
||||
// RaceColumn implements its own render(...) method which doesn't make use of getValue(...)
|
||||
final double totalPoints = object.fieldsByRaceColumnName.get(getRaceColumnName()).totalPoints;
|
||||
return "" + (totalPoints == 0 ? "" : scoreFormat.format(totalPoints));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -835,8 +840,8 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
|
||||
|
||||
@Override
|
||||
public String getValue(LeaderboardRowDTO object) {
|
||||
int totalPoints = getLeaderboard().getTotalPoints(object);
|
||||
return "" + (totalPoints==0 ? "" : totalPoints);
|
||||
double totalPoints = getLeaderboard().getTotalPoints(object);
|
||||
return "" + (totalPoints==0 ? "" : scoreFormat.format(totalPoints));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -880,7 +885,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
|
||||
|
||||
@Override
|
||||
public String getValue(LeaderboardRowDTO object) {
|
||||
return object.carriedPoints == null ? "" : "" + object.carriedPoints;
|
||||
return object.carriedPoints == null ? "" : scoreFormat.format(object.carriedPoints);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -888,8 +893,15 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
|
||||
return new Comparator<LeaderboardRowDTO>() {
|
||||
@Override
|
||||
public int compare(LeaderboardRowDTO o1, LeaderboardRowDTO o2) {
|
||||
return (o1.carriedPoints == null ? 0 : o1.carriedPoints)
|
||||
- (o2.carriedPoints == null ? 0 : o2.carriedPoints);
|
||||
Double o1CarriedPoints = o1.carriedPoints;
|
||||
if (o1CarriedPoints == null) {
|
||||
o1CarriedPoints = 0.0;
|
||||
}
|
||||
Double o2CarriedPoints = o2.carriedPoints;
|
||||
if (o2CarriedPoints == null) {
|
||||
o2CarriedPoints = 0.0;
|
||||
}
|
||||
return o1CarriedPoints.compareTo(o2CarriedPoints);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
+9
-9
@@ -63,7 +63,7 @@ public class EditableLeaderboardPanel extends LeaderboardPanel {
|
||||
@Override
|
||||
public void update(final int rowIndex, final LeaderboardRowDTO row, final String value) {
|
||||
getSailingService().updateLeaderboardCarryValue(getLeaderboardName(), row.competitor.id,
|
||||
value == null || value.length() == 0 ? null : Integer.valueOf(value.trim()),
|
||||
value == null || value.length() == 0 ? null : Double.valueOf(value.trim()),
|
||||
new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
@@ -74,7 +74,7 @@ public class EditableLeaderboardPanel extends LeaderboardPanel {
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void v) {
|
||||
row.carriedPoints = value==null||value.length()==0 ? null : Integer.valueOf(value.trim());
|
||||
row.carriedPoints = value==null||value.length()==0 ? null : Double.valueOf(value.trim());
|
||||
EditableLeaderboardPanel.this.getData().getList().set(rowIndex, row);
|
||||
}
|
||||
});
|
||||
@@ -227,7 +227,7 @@ public class EditableLeaderboardPanel extends LeaderboardPanel {
|
||||
getBusyIndicator().setBusy(true);
|
||||
getSailingService().updateLeaderboardMaxPointsReason(getLeaderboardName(), row.competitor.id,
|
||||
raceColumnName, value == null || value.trim().length() == 0 ? null : MaxPointsReason.valueOf(value.trim()),
|
||||
getLeaderboardDisplayDate(), new AsyncCallback<Triple<Integer, Integer, Boolean>>() {
|
||||
getLeaderboardDisplayDate(), new AsyncCallback<Triple<Double, Double, Boolean>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
getBusyIndicator().setBusy(false);
|
||||
@@ -238,7 +238,7 @@ public class EditableLeaderboardPanel extends LeaderboardPanel {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Triple<Integer, Integer, Boolean> newNetAndTotalPointsAndIsCorrected) {
|
||||
public void onSuccess(Triple<Double, Double, Boolean> newNetAndTotalPointsAndIsCorrected) {
|
||||
getBusyIndicator().setBusy(false);
|
||||
row.fieldsByRaceColumnName.get(raceColumnName).reasonForMaxPoints = value == null
|
||||
|| value.length() == 0 ? null : MaxPointsReason.valueOf(value.trim());
|
||||
@@ -322,8 +322,8 @@ public class EditableLeaderboardPanel extends LeaderboardPanel {
|
||||
getWhiteboardOwner().whiteboardProduced(whiteboard);
|
||||
getBusyIndicator().setBusy(true);
|
||||
getSailingService().updateLeaderboardScoreCorrection(getLeaderboardName(), row.competitor.id, raceName,
|
||||
value == null || value.trim().length() == 0 ? null : Integer.valueOf(value.trim()), getLeaderboardDisplayDate(),
|
||||
new AsyncCallback<Triple<Integer, Integer, Boolean>>() {
|
||||
value == null || value.trim().length() == 0 ? null : Double.valueOf(value.trim()), getLeaderboardDisplayDate(),
|
||||
new AsyncCallback<Triple<Double, Double, Boolean>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
getBusyIndicator().setBusy(false);
|
||||
@@ -334,11 +334,11 @@ public class EditableLeaderboardPanel extends LeaderboardPanel {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Triple<Integer, Integer, Boolean> newNetAndTotalPointsAndIsCorrected) {
|
||||
public void onSuccess(Triple<Double, Double, Boolean> newNetAndTotalPointsAndIsCorrected) {
|
||||
getBusyIndicator().setBusy(false);
|
||||
final LeaderboardEntryDTO leaderboardEntryDTO = row.fieldsByRaceColumnName.get(raceName);
|
||||
leaderboardEntryDTO.netPoints = value == null || value.length() == 0 ? newNetAndTotalPointsAndIsCorrected
|
||||
.getA() : Integer.valueOf(value.trim());
|
||||
.getA() : Double.valueOf(value.trim());
|
||||
leaderboardEntryDTO.totalPoints = newNetAndTotalPointsAndIsCorrected.getB();
|
||||
leaderboardEntryDTO.netPointsCorrected = newNetAndTotalPointsAndIsCorrected.getC();
|
||||
getCell().setViewData(row, null); // ensure that getValue() is called again
|
||||
@@ -354,7 +354,7 @@ public class EditableLeaderboardPanel extends LeaderboardPanel {
|
||||
LeaderboardEntryDTO leaderboardEntryDTO = object.fieldsByRaceColumnName.get(raceName);
|
||||
String result = "";
|
||||
if (leaderboardEntryDTO != null) {
|
||||
result = result+leaderboardEntryDTO.netPoints;
|
||||
result = scoreFormat.format(leaderboardEntryDTO.netPoints);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+1
-1
@@ -258,7 +258,7 @@ public class MatchAndApplyScoreCorrectionsDialog extends DataEntryDialog<BulkSco
|
||||
if (officialCorrectionEntry.getScore() != null) {
|
||||
double officialTotalPoints = officialCorrectionEntry.getScore().doubleValue();
|
||||
double officialNetPoints = raceColumn.isMedalRace() ? officialTotalPoints / MEDAL_RACE_FACTOR : officialTotalPoints;
|
||||
result.addScoreUpdate(competitor, raceColumn, (int) Math.round(officialNetPoints));
|
||||
result.addScoreUpdate(competitor, raceColumn, officialNetPoints);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+16
-7
@@ -206,6 +206,7 @@ import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardCarryVa
|
||||
import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardGroup;
|
||||
import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardMaxPointsReason;
|
||||
import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardScoreCorrection;
|
||||
import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardScoreCorrectionMetadata;
|
||||
import com.sap.sailing.server.operationaltransformation.UpdateRaceDelayToLive;
|
||||
import com.sap.sailing.server.replication.ReplicaDescriptor;
|
||||
import com.sap.sailing.server.replication.ReplicationFactory;
|
||||
@@ -418,7 +419,9 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
LeaderboardDTO result = null;
|
||||
final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName);
|
||||
if (leaderboard != null) {
|
||||
result = new LeaderboardDTO();
|
||||
result = new LeaderboardDTO(leaderboard.getScoreCorrection().getTimePointOfLastCorrectionsValidity()==null ?
|
||||
null : leaderboard.getScoreCorrection().getTimePointOfLastCorrectionsValidity().asDate(),
|
||||
leaderboard.getScoreCorrection()==null?null:leaderboard.getScoreCorrection().getComment());
|
||||
final TimePoint timePoint = new MillisecondsTimePoint(date);
|
||||
result.competitors = new ArrayList<CompetitorDTO>();
|
||||
result.name = leaderboard.getName();
|
||||
@@ -1945,12 +1948,12 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLeaderboardCarryValue(String leaderboardName, String competitorIdAsString, Integer carriedPoints) {
|
||||
public void updateLeaderboardCarryValue(String leaderboardName, String competitorIdAsString, Double carriedPoints) {
|
||||
getService().apply(new UpdateLeaderboardCarryValue(leaderboardName, competitorIdAsString, carriedPoints));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Triple<Integer, Integer, Boolean> updateLeaderboardMaxPointsReason(String leaderboardName, String competitorIdAsString, String raceColumnName,
|
||||
public Triple<Double, Double, Boolean> updateLeaderboardMaxPointsReason(String leaderboardName, String competitorIdAsString, String raceColumnName,
|
||||
MaxPointsReason maxPointsReason, Date date) throws NoWindException {
|
||||
return getService().apply(
|
||||
new UpdateLeaderboardMaxPointsReason(leaderboardName, raceColumnName, competitorIdAsString,
|
||||
@@ -1958,18 +1961,24 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
}
|
||||
|
||||
@Override
|
||||
public Triple<Integer, Integer, Boolean> updateLeaderboardScoreCorrection(String leaderboardName,
|
||||
String competitorIdAsString, String columnName, Integer correctedScore, Date date) throws NoWindException {
|
||||
public Triple<Double, Double, Boolean> updateLeaderboardScoreCorrection(String leaderboardName,
|
||||
String competitorIdAsString, String columnName, Double correctedScore, Date date) throws NoWindException {
|
||||
return getService().apply(
|
||||
new UpdateLeaderboardScoreCorrection(leaderboardName, columnName, competitorIdAsString, correctedScore,
|
||||
new MillisecondsTimePoint(date)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void updateLeaderboardScoreCorrectionMetadata(String leaderboardName, Date timePointOfLastCorrectionValidity, String comment) {
|
||||
return getService().apply(
|
||||
new UpdateLeaderboardScoreCorrectionMetadata(leaderboardName, new MillisecondsTimePoint(timePointOfLastCorrectionValidity), comment));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLeaderboardScoreCorrectionsAndMaxPointsReasons(BulkScoreCorrectionDTO updates) throws NoWindException {
|
||||
Date dateForResults = new Date(); // we don't care about the result date/time here; use current date as default
|
||||
for (Map.Entry<String, Map<String, Integer>> e : updates.getScoreUpdatesForRaceColumnByCompetitorIdAsString().entrySet()) {
|
||||
for (Map.Entry<String, Integer> raceColumnNameAndCorrectedScore : e.getValue().entrySet()) {
|
||||
for (Map.Entry<String, Map<String, Double>> e : updates.getScoreUpdatesForRaceColumnByCompetitorIdAsString().entrySet()) {
|
||||
for (Map.Entry<String, Double> raceColumnNameAndCorrectedScore : e.getValue().entrySet()) {
|
||||
updateLeaderboardScoreCorrection(updates.getLeaderboardName(), e.getKey(),
|
||||
raceColumnNameAndCorrectedScore.getKey(), raceColumnNameAndCorrectedScore.getValue(), dateForResults);
|
||||
}
|
||||
|
||||
+4
-4
@@ -69,16 +69,16 @@ public abstract class AbstractLeaderboardDTO implements IsSerializable {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getTotalPoints(LeaderboardRowDTO object) {
|
||||
int totalPoints = object.carriedPoints == null ? 0 : object.carriedPoints;
|
||||
public double getTotalPoints(LeaderboardRowDTO object) {
|
||||
double totalPoints = object.carriedPoints == null ? 0 : object.carriedPoints;
|
||||
for (LeaderboardEntryDTO e : object.fieldsByRaceColumnName.values()) {
|
||||
totalPoints += e.totalPoints;
|
||||
}
|
||||
return totalPoints;
|
||||
}
|
||||
|
||||
public int getNetPoints(CompetitorDTO competitor, String nameOfLastRaceSoFar) {
|
||||
int result = 0;
|
||||
public double getNetPoints(CompetitorDTO competitor, String nameOfLastRaceSoFar) {
|
||||
double result = 0;
|
||||
LeaderboardRowDTO row = rows.get(competitor);
|
||||
if (row != null) {
|
||||
LeaderboardEntryDTO field = row.fieldsByRaceColumnName.get(nameOfLastRaceSoFar);
|
||||
|
||||
+6
-6
@@ -16,20 +16,20 @@ import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
public class BulkScoreCorrectionDTO implements IsSerializable {
|
||||
private String leaderboardName;
|
||||
private Map<String, Map<String, MaxPointsReason>> maxPointsUpdatesForRaceColumnByCompetitorIdAsString;
|
||||
private Map<String, Map<String, Integer>> scoreUpdatesForRaceColumnByCompetitorIdAsString;
|
||||
private Map<String, Map<String, Double>> scoreUpdatesForRaceColumnByCompetitorIdAsString;
|
||||
|
||||
public BulkScoreCorrectionDTO() {}
|
||||
|
||||
public BulkScoreCorrectionDTO(String leaderboardName) {
|
||||
this.leaderboardName = leaderboardName;
|
||||
maxPointsUpdatesForRaceColumnByCompetitorIdAsString = new HashMap<String, Map<String,MaxPointsReason>>();
|
||||
scoreUpdatesForRaceColumnByCompetitorIdAsString = new HashMap<String, Map<String,Integer>>();
|
||||
scoreUpdatesForRaceColumnByCompetitorIdAsString = new HashMap<String, Map<String, Double>>();
|
||||
}
|
||||
|
||||
public void addScoreUpdate(CompetitorDTO competitor, RaceColumnDTO raceColumn, int newScore) {
|
||||
Map<String, Integer> map = scoreUpdatesForRaceColumnByCompetitorIdAsString.get(competitor.id);
|
||||
public void addScoreUpdate(CompetitorDTO competitor, RaceColumnDTO raceColumn, double newScore) {
|
||||
Map<String, Double> map = scoreUpdatesForRaceColumnByCompetitorIdAsString.get(competitor.id);
|
||||
if (map == null) {
|
||||
map = new HashMap<String, Integer>();
|
||||
map = new HashMap<String, Double>();
|
||||
scoreUpdatesForRaceColumnByCompetitorIdAsString.put(competitor.id, map);
|
||||
}
|
||||
map.put(raceColumn.name, newScore);
|
||||
@@ -48,7 +48,7 @@ public class BulkScoreCorrectionDTO implements IsSerializable {
|
||||
return maxPointsUpdatesForRaceColumnByCompetitorIdAsString;
|
||||
}
|
||||
|
||||
public Map<String, Map<String, Integer>> getScoreUpdatesForRaceColumnByCompetitorIdAsString() {
|
||||
public Map<String, Map<String, Double>> getScoreUpdatesForRaceColumnByCompetitorIdAsString() {
|
||||
return scoreUpdatesForRaceColumnByCompetitorIdAsString;
|
||||
}
|
||||
|
||||
|
||||
+29
-1
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.gwt.ui.shared;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -21,8 +22,16 @@ public class LeaderboardDTO extends AbstractLeaderboardDTO implements IsSerializ
|
||||
public List<CompetitorDTO> competitors;
|
||||
|
||||
private Map<RaceColumnDTO, List<CompetitorDTO>> competitorOrderingPerRace;
|
||||
|
||||
private Date timePointOfLastCorrectionsValidity;
|
||||
|
||||
private String comment;
|
||||
|
||||
LeaderboardDTO() {} // for serialization
|
||||
|
||||
public LeaderboardDTO() {
|
||||
public LeaderboardDTO(Date timePointOfLastCorrectionsValidity, String comment) {
|
||||
this.timePointOfLastCorrectionsValidity = timePointOfLastCorrectionsValidity;
|
||||
this.comment = comment;
|
||||
competitorOrderingPerRace = new HashMap<RaceColumnDTO, List<CompetitorDTO>>();
|
||||
}
|
||||
|
||||
@@ -38,6 +47,25 @@ public class LeaderboardDTO extends AbstractLeaderboardDTO implements IsSerializ
|
||||
return competitors.indexOf(competitor) + 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* A free-form comment to display to the viewers of the leaderboard that has these score corrections. It should make
|
||||
* crystal clear if the scores are preliminary or not yet jury-finalized. If <code>null</code> is returned, this
|
||||
* always has to be interpreted as "preliminary" because then no comment as to the correctness have been made.
|
||||
*/
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells when the score correction was last updated. This should usually be the "validity time" and not the
|
||||
* "transaction time." In other words, if scores provided by the race committee are updated to this score correction
|
||||
* at time X, and the race committee's scores are tagged with time Y, then this method should return Y, not X. If
|
||||
* Y is not available for some reason, X may be used as a default.
|
||||
*/
|
||||
public Date getTimePointOfLastCorrectionsValidity() {
|
||||
return timePointOfLastCorrectionsValidity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode() ^ ((competitors == null) ? 0 : competitors.hashCode());
|
||||
|
||||
+4
-4
@@ -26,14 +26,14 @@ public class LeaderboardEntryDTO implements IsSerializable {
|
||||
*/
|
||||
public MaxPointsReason reasonForMaxPoints;
|
||||
|
||||
public int netPoints;
|
||||
public double netPoints;
|
||||
|
||||
/**
|
||||
* Tells if the net points have been overridden by a score correction. Can be used to render differently in editing environment.
|
||||
*/
|
||||
public boolean netPointsCorrected;
|
||||
|
||||
public int totalPoints;
|
||||
public double totalPoints;
|
||||
|
||||
public boolean discarded;
|
||||
|
||||
@@ -63,11 +63,11 @@ public class LeaderboardEntryDTO implements IsSerializable {
|
||||
int result = 1;
|
||||
result = prime * result + (discarded ? 1231 : 1237);
|
||||
result = prime * result + ((legDetails == null) ? 0 : legDetails.hashCode());
|
||||
result = prime * result + netPoints;
|
||||
result = prime * result + (int) netPoints;
|
||||
result = prime * result + ((averageCrossTrackErrorInMeters == null) ? 0 : averageCrossTrackErrorInMeters.hashCode());
|
||||
result = prime * result + ((reasonForMaxPoints == null) ? 0 : reasonForMaxPoints.hashCode());
|
||||
result = prime * result + ((windwardDistanceToOverallLeaderInMeters == null) ? 0 : windwardDistanceToOverallLeaderInMeters.hashCode());
|
||||
result = prime * result + totalPoints;
|
||||
result = prime * result + (int) totalPoints;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import com.google.gwt.user.client.rpc.IsSerializable;
|
||||
public class LeaderboardRowDTO implements IsSerializable {
|
||||
public CompetitorDTO competitor;
|
||||
public Map<String, LeaderboardEntryDTO> fieldsByRaceColumnName;
|
||||
public Integer carriedPoints;
|
||||
public Double carriedPoints;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
+24
-6
@@ -14,6 +14,7 @@ import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.impl.BoatClassImpl;
|
||||
import com.sap.sailing.domain.base.impl.BoatImpl;
|
||||
import com.sap.sailing.domain.base.impl.CompetitorImpl;
|
||||
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.domain.base.impl.NationalityImpl;
|
||||
import com.sap.sailing.domain.base.impl.PersonImpl;
|
||||
import com.sap.sailing.domain.base.impl.TeamImpl;
|
||||
@@ -21,6 +22,7 @@ import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.common.impl.Util;
|
||||
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.SettableScoreCorrection;
|
||||
import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
|
||||
import com.sap.sailing.domain.leaderboard.impl.LowerScoreIsBetter;
|
||||
import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl;
|
||||
@@ -31,6 +33,22 @@ import com.sap.sailing.domain.test.MockedTrackedRaceWithFixedRank;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
|
||||
public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest {
|
||||
@Test
|
||||
public void testStoreAndRetrieveLeaderboardWithCommentedScoreCorrection() {
|
||||
final String leaderboardName = "TestLeaderboard";
|
||||
final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 };
|
||||
SettableScoreCorrection scoreCorrection = new ScoreCorrectionImpl();
|
||||
FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, scoreCorrection,
|
||||
new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowerScoreIsBetter());
|
||||
scoreCorrection.setComment("Humba");
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
scoreCorrection.setTimePointOfLastCorrectionsValidity(now);
|
||||
new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard);
|
||||
Leaderboard loadedLeaderboard = new DomainObjectFactoryImpl(db).loadLeaderboard(leaderboardName, /* regattaRegistry */ null);
|
||||
assertEquals("Humba", loadedLeaderboard.getScoreCorrection().getComment());
|
||||
assertEquals(now, loadedLeaderboard.getScoreCorrection().getTimePointOfLastCorrectionsValidity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStoreAndRetrieveSimpleLeaderboard() {
|
||||
final String leaderboardName = "TestLeaderboard";
|
||||
@@ -48,7 +66,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest {
|
||||
public void testStoreAndRetrieveLeaderboardWithCarryColumn() {
|
||||
final String leaderboardName = "TestLeaderboard";
|
||||
final String raceColumnName = "My First Race";
|
||||
final int carriedPointsForWolfgangHunger = 3;
|
||||
final double carriedPointsForWolfgangHunger = 3.7;
|
||||
final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 };
|
||||
FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(),
|
||||
new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowerScoreIsBetter());
|
||||
@@ -65,7 +83,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest {
|
||||
.getDiscardIndexResultsStartingWithHowManyRaces()));
|
||||
assertEquals(1, Util.size(loadedLeaderboard.getCompetitors()));
|
||||
assertEquals(competitor, loadedLeaderboard.getCompetitors().iterator().next());
|
||||
assertEquals(carriedPointsForWolfgangHunger, loadedLeaderboard.getCarriedPoints(competitor));
|
||||
assertEquals(carriedPointsForWolfgangHunger, loadedLeaderboard.getCarriedPoints(competitor), 0.000000001);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -73,7 +91,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest {
|
||||
final String leaderboardName = "TestLeaderboard";
|
||||
final String raceColumnName1 = "My First Race 1";
|
||||
final String raceColumnName2 = "My First Race 2";
|
||||
final int correctedPoints = 2;
|
||||
final double correctedPoints = 2.75;
|
||||
final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 };
|
||||
FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(),
|
||||
new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowerScoreIsBetter());
|
||||
@@ -90,7 +108,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest {
|
||||
RaceColumn loadedColumn2 = loadedLeaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace, ignored */ false, leaderboard.getFleet(null));
|
||||
assertEquals(leaderboardName, loadedLeaderboard.getName());
|
||||
assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn1));
|
||||
assertEquals(correctedPoints, (int) loadedLeaderboard.getScoreCorrection().getExplicitScoreCorrection(competitor, loadedColumn1));
|
||||
assertEquals(correctedPoints, (double) loadedLeaderboard.getScoreCorrection().getExplicitScoreCorrection(competitor, loadedColumn1), 0.00000001);
|
||||
assertFalse(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn2));
|
||||
}
|
||||
|
||||
@@ -125,7 +143,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest {
|
||||
final String leaderboardName = "TestLeaderboard";
|
||||
final String raceColumnName1 = "My First Race 1";
|
||||
final String raceColumnName2 = "My First Race 2";
|
||||
final int correctedPoints = 2;
|
||||
final double correctedPoints = 2.55;
|
||||
final MaxPointsReason maxPointsReason = MaxPointsReason.DNF;
|
||||
final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 };
|
||||
FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(),
|
||||
@@ -144,7 +162,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest {
|
||||
RaceColumn loadedColumn2 = loadedLeaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace, ignored */ false, leaderboard.getFleet(null));
|
||||
assertEquals(leaderboardName, loadedLeaderboard.getName());
|
||||
assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn1));
|
||||
assertEquals(correctedPoints, (int) loadedLeaderboard.getScoreCorrection().getExplicitScoreCorrection(competitor, loadedColumn1));
|
||||
assertEquals(correctedPoints, (double) loadedLeaderboard.getScoreCorrection().getExplicitScoreCorrection(competitor, loadedColumn1), 0.000000001);
|
||||
assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn2));
|
||||
assertEquals(maxPointsReason, loadedLeaderboard.getScoreCorrection().getMaxPointsReason(competitor, loadedColumn2));
|
||||
}
|
||||
|
||||
+2
-2
@@ -8,9 +8,9 @@ import com.sap.sailing.server.RacingEventServiceOperation;
|
||||
public class UpdateLeaderboardCarryValue extends AbstractLeaderboardOperation<Void> {
|
||||
private static final long serialVersionUID = 5467731814788887426L;
|
||||
private final String competitorIdAsString;
|
||||
private final Integer newCarriedValue;
|
||||
private final Double newCarriedValue;
|
||||
|
||||
public UpdateLeaderboardCarryValue(String leaderboardName, String competitorIdAsString, Integer newCarriedValue) {
|
||||
public UpdateLeaderboardCarryValue(String leaderboardName, String competitorIdAsString, Double newCarriedValue) {
|
||||
super(leaderboardName);
|
||||
this.competitorIdAsString = competitorIdAsString;
|
||||
this.newCarriedValue = newCarriedValue;
|
||||
|
||||
+3
-3
@@ -11,7 +11,7 @@ import com.sap.sailing.domain.leaderboard.Leaderboard.Entry;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sailing.server.RacingEventServiceOperation;
|
||||
|
||||
public class UpdateLeaderboardMaxPointsReason extends AbstractLeaderboardColumnOperation<Triple<Integer, Integer, Boolean>> {
|
||||
public class UpdateLeaderboardMaxPointsReason extends AbstractLeaderboardColumnOperation<Triple<Double, Double, Boolean>> {
|
||||
private static final long serialVersionUID = -492130952256848047L;
|
||||
private final String competitorIdAsString;
|
||||
private final MaxPointsReason newMaxPointsReason;
|
||||
@@ -38,7 +38,7 @@ public class UpdateLeaderboardMaxPointsReason extends AbstractLeaderboardColumnO
|
||||
}
|
||||
|
||||
@Override
|
||||
public Triple<Integer, Integer, Boolean> internalApplyTo(RacingEventService toState) throws NoWindException {
|
||||
public Triple<Double, Double, Boolean> internalApplyTo(RacingEventService toState) throws NoWindException {
|
||||
Leaderboard leaderboard = toState.getLeaderboardByName(getLeaderboardName());
|
||||
if (leaderboard != null) {
|
||||
Competitor competitor = leaderboard.getCompetitorByIdAsString(competitorIdAsString);
|
||||
@@ -51,7 +51,7 @@ public class UpdateLeaderboardMaxPointsReason extends AbstractLeaderboardColumnO
|
||||
updateStoredLeaderboard(toState, leaderboard);
|
||||
Entry updatedEntry = leaderboard.getEntry(competitor, raceColumn, timePoint);
|
||||
boolean isScoreCorrected = leaderboard.getScoreCorrection().isScoreCorrected(competitor, raceColumn);
|
||||
return new Triple<Integer, Integer, Boolean>(updatedEntry.getNetPoints(), updatedEntry.getTotalPoints(), isScoreCorrected);
|
||||
return new Triple<Double, Double, Boolean>(updatedEntry.getNetPoints(), updatedEntry.getTotalPoints(), isScoreCorrected);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Didn't find competitor with ID "+competitorIdAsString+" in leaderboard "+getLeaderboardName());
|
||||
}
|
||||
|
||||
+7
-7
@@ -9,17 +9,17 @@ import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sailing.server.RacingEventServiceOperation;
|
||||
|
||||
public class UpdateLeaderboardScoreCorrection extends AbstractLeaderboardColumnOperation<Triple<Integer, Integer, Boolean>> {
|
||||
public class UpdateLeaderboardScoreCorrection extends AbstractLeaderboardColumnOperation<Triple<Double, Double, Boolean>> {
|
||||
private static final long serialVersionUID = -977025759476022993L;
|
||||
private final String competitorIdAsString;
|
||||
private final Integer correctedScore;
|
||||
private final Double correctedScore;
|
||||
private final TimePoint timePoint;
|
||||
|
||||
/**
|
||||
* @param timePoint the time point for which to deliver leaderboard results as the result of this operation
|
||||
*/
|
||||
public UpdateLeaderboardScoreCorrection(String leaderboardName, String columnName, String competitorIdAsString,
|
||||
Integer correctedScore, TimePoint timePoint) {
|
||||
Double correctedScore, TimePoint timePoint) {
|
||||
super(leaderboardName, columnName);
|
||||
this.competitorIdAsString = competitorIdAsString;
|
||||
this.correctedScore = correctedScore;
|
||||
@@ -39,10 +39,10 @@ public class UpdateLeaderboardScoreCorrection extends AbstractLeaderboardColumnO
|
||||
}
|
||||
|
||||
@Override
|
||||
public Triple<Integer, Integer, Boolean> internalApplyTo(RacingEventService toState) throws NoWindException {
|
||||
public Triple<Double, Double, Boolean> internalApplyTo(RacingEventService toState) throws NoWindException {
|
||||
Leaderboard leaderboard = toState.getLeaderboardByName(getLeaderboardName());
|
||||
int newNetPoints;
|
||||
int newTotalPoints;
|
||||
double newNetPoints;
|
||||
double newTotalPoints;
|
||||
boolean isScoreCorrected;
|
||||
if (leaderboard != null) {
|
||||
Competitor competitor = leaderboard.getCompetitorByIdAsString(competitorIdAsString);
|
||||
@@ -64,7 +64,7 @@ public class UpdateLeaderboardScoreCorrection extends AbstractLeaderboardColumnO
|
||||
throw new IllegalArgumentException("Didn't find leaderboard "+getLeaderboardName());
|
||||
}
|
||||
updateStoredLeaderboard(toState, leaderboard);
|
||||
return new Triple<Integer, Integer, Boolean>(newNetPoints, newTotalPoints, isScoreCorrected);
|
||||
return new Triple<Double, Double, Boolean>(newNetPoints, newTotalPoints, isScoreCorrected);
|
||||
}
|
||||
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package com.sap.sailing.server.operationaltransformation;
|
||||
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.SettableScoreCorrection;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sailing.server.RacingEventServiceOperation;
|
||||
|
||||
public class UpdateLeaderboardScoreCorrectionMetadata extends AbstractLeaderboardOperation<Void> {
|
||||
private static final long serialVersionUID = -977025759476022993L;
|
||||
private final TimePoint timePointOfLastCorrectionValidity;
|
||||
private final String comment;
|
||||
|
||||
/**
|
||||
* @param timePoint the time point for which to deliver leaderboard results as the result of this operation
|
||||
*/
|
||||
public UpdateLeaderboardScoreCorrectionMetadata(String leaderboardName, TimePoint timePointOfLastCorrectionValidity, String comment) {
|
||||
super(leaderboardName);
|
||||
this.timePointOfLastCorrectionValidity = timePointOfLastCorrectionValidity;
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation<?> transformClientOp(RacingEventServiceOperation<?> serverOp) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation<?> transformServerOp(RacingEventServiceOperation<?> clientOp) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void internalApplyTo(RacingEventService toState) throws NoWindException {
|
||||
Leaderboard leaderboard = toState.getLeaderboardByName(getLeaderboardName());
|
||||
if (leaderboard != null) {
|
||||
SettableScoreCorrection scoreCorrection = leaderboard.getScoreCorrection();
|
||||
if (scoreCorrection != null) {
|
||||
scoreCorrection.setComment(comment);
|
||||
scoreCorrection.setTimePointOfLastCorrectionsValidity(timePointOfLastCorrectionValidity);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Leaderboard "+getLeaderboardName()+" has no score corrections to which to apply metadata "+
|
||||
timePointOfLastCorrectionValidity+"/"+comment);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Didn't find leaderboard "+getLeaderboardName());
|
||||
}
|
||||
updateStoredLeaderboard(toState, leaderboard);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user