mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-08 13:20:57 +00:00
Merge branch 'master' into bug3785
This commit is contained in:
commit
1dd5db458b
8 files changed
+386
-248
No files matched your search
+11
-11
@@ -287,7 +287,7 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
for (Competitor competitor : competitors) {
|
||||
final String toAddress = competitor.getEmail();
|
||||
if (toAddress != null) {
|
||||
String leaderboardName = leaderboard.getName();
|
||||
String leaderboardName = leaderboard.getDisplayName() == null ? leaderboard.getName() : leaderboard.getDisplayName();
|
||||
String competitorName = competitor.getName();
|
||||
String url = DeviceMappingConstants.getDeviceMappingForRegattaLogUrl(serverUrlWithoutTrailingSlash,
|
||||
event.getId().toString(), leaderboardName, DeviceMappingConstants.URL_COMPETITOR_ID_AS_STRING,
|
||||
@@ -299,8 +299,8 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
}
|
||||
try {
|
||||
final ResourceBundleStringMessages B = RaceLogTrackingI18n.STRING_MESSAGES;
|
||||
sendInvitationEmail(locale, toAddress, leaderboardName, competitorName, url, B.get(locale, "sailInSightAppName"),
|
||||
iOSAppUrl, androidAppUrl, logoUrl);
|
||||
sendInvitationEmail(locale, toAddress, leaderboardName, event.getName(), competitorName, url,
|
||||
B.get(locale, "sailInSightAppName"), iOSAppUrl, androidAppUrl, logoUrl);
|
||||
} catch (MailException e) {
|
||||
occuredExceptions.append(e.getMessage() + "\r\n");
|
||||
}
|
||||
@@ -311,8 +311,8 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
private void sendInvitationEmail(Locale locale, final String toAddress, String leaderboardName, String invitee,
|
||||
String url, String appName, String iOSAppUrl, String androidAppUrl, String logoUrl) throws MailException {
|
||||
private void sendInvitationEmail(Locale locale, final String toAddress, String leaderboardName, String eventName,
|
||||
String invitee, String url, String appName, String iOSAppUrl, String androidAppUrl, String logoUrl) throws MailException {
|
||||
final ResourceBundleStringMessages B = RaceLogTrackingI18n.STRING_MESSAGES;
|
||||
String subject = String.format("%s %s", B.get(locale, "trackingInvitationFor"), invitee);
|
||||
|
||||
@@ -325,8 +325,8 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
StringBuilder htmlText = new StringBuilder();
|
||||
htmlText.append("<!doctype html>\n");
|
||||
htmlText.append("<html>");
|
||||
htmlText.append("<head><title>");
|
||||
htmlText.append(B.get(locale, "welcomeTo")).append(" ").append(leaderboardName).append("</title>");
|
||||
final String welcomeText = B.get(locale, "welcomeTo")+" "+eventName+", "+leaderboardName;
|
||||
htmlText.append("<head><title>").append(welcomeText).append("</title>");
|
||||
htmlText.append("<style type=\"text/css\">\n");
|
||||
htmlText.append(".b,.b:active,.b:visited {padding:15px;margin:10px;width:200px;display:inline-block;background-color:#337ab7;border-radius:4px;color:#ffffff;border:1px solid #2e6da4;text-decoration:none;}\n");
|
||||
htmlText.append(".b:hover {background-color:#2b618e;border:1px solid #204d74;}\n");
|
||||
@@ -338,7 +338,7 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
if (hasLogoUrl) {
|
||||
htmlText.append("<p><img src=\"").append(logoUrl).append("\" /></p> ");
|
||||
}
|
||||
htmlText.append("<h1>").append(B.get(locale, "welcomeTo")).append(" ").append(leaderboardName).append("</h1> ");
|
||||
htmlText.append("<h1>").append(welcomeText).append("</h1> ");
|
||||
htmlText.append("<p>").append(B.get(locale, "scanQRCodeOrVisitUrlToRegisterAs", appName)).append(" <b>").append(invitee)
|
||||
.append("</b></p> ");
|
||||
htmlText.append("<p class=\"qr\"><img src=\"cid:image\" title=\"").append(url).append("\" /></p> ");
|
||||
@@ -392,7 +392,7 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
String emails, String iOSAppUrl, String androidAppUrl, Locale locale) throws MailException {
|
||||
StringBuilder occuredExceptions = new StringBuilder();
|
||||
String[] emailArray = emails.split(",");
|
||||
String leaderboardName = leaderboard.getName();
|
||||
String leaderboardName = leaderboard.getDisplayName() == null ? leaderboard.getName() : leaderboard.getDisplayName();
|
||||
String eventId = event.getId().toString();
|
||||
String logoUrl = null;
|
||||
List<ImageDescriptor> imagesWithTag = event.findImagesWithTag(MediaTagConstants.LOGO);
|
||||
@@ -406,8 +406,8 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
try {
|
||||
final ResourceBundleStringMessages B = RaceLogTrackingI18n.STRING_MESSAGES;
|
||||
sendInvitationEmail(locale, toAddress, leaderboardName,
|
||||
RaceLogTrackingI18n.STRING_MESSAGES.get(locale, "buoyTender"), url, B.get(locale, "buoyPingerAppName"), iOSAppUrl,
|
||||
androidAppUrl, logoUrl);
|
||||
event.getName(), RaceLogTrackingI18n.STRING_MESSAGES.get(locale, "buoyTender"), url, B.get(locale, "buoyPingerAppName"),
|
||||
iOSAppUrl, androidAppUrl, logoUrl);
|
||||
} catch (MailException e) {
|
||||
occuredExceptions.append(e.getMessage() + "\r\n");
|
||||
}
|
||||
|
||||
+2
-190
@@ -55,7 +55,6 @@ import com.sap.sailing.domain.common.dto.LeaderboardDTO;
|
||||
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
|
||||
import com.sap.sailing.domain.leaderboard.ScoringScheme;
|
||||
import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
|
||||
import com.sap.sailing.domain.leaderboard.impl.HighPoint;
|
||||
import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOverall;
|
||||
@@ -70,7 +69,6 @@ import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore;
|
||||
import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
|
||||
import com.sap.sailing.domain.regattalog.impl.EmptyRegattaLogStore;
|
||||
import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithStartTimeAndRanks;
|
||||
import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithStartTimeAndZeroRanks;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
|
||||
@@ -82,10 +80,8 @@ import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.util.impl.ArrayListNavigableSet;
|
||||
|
||||
public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest {
|
||||
private ArrayList<Series> series;
|
||||
|
||||
private Leaderboard createLeaderboard(Regatta regatta, int[] discardingThresholds) {
|
||||
public class LeaderboardScoringAndRankingTest extends LeaderboardScoringAndRankingTestBase {
|
||||
protected Leaderboard createLeaderboard(Regatta regatta, int[] discardingThresholds) {
|
||||
ThresholdBasedResultDiscardingRuleImpl discardingRules = new ThresholdBasedResultDiscardingRuleImpl(discardingThresholds);
|
||||
return new RegattaLeaderboardImpl(regatta, discardingRules);
|
||||
}
|
||||
@@ -1250,19 +1246,6 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest {
|
||||
checkScoresAfterSomeRaces(leaderboard, raceColumnsToConsider, scoresAfter6Races, later, c);
|
||||
}
|
||||
|
||||
private void checkScoresAfterSomeRaces(Leaderboard leaderboard, List<RaceColumn> raceColumnsToConsider,
|
||||
double[][] scoresAfterNRaces, TimePoint timePoint, Competitor[] competitors) throws NoWindException {
|
||||
for (int competitorIndex=0; competitorIndex<scoresAfterNRaces.length; competitorIndex++) {
|
||||
final Set<RaceColumn> discardedRaceColumns = leaderboard.getResultDiscardingRule()
|
||||
.getDiscardedRaceColumns(competitors[competitorIndex], leaderboard, raceColumnsToConsider, timePoint);
|
||||
for (int raceColumnIndex=0; raceColumnIndex<raceColumnsToConsider.size(); raceColumnIndex++) {
|
||||
assertEquals(scoresAfterNRaces[competitorIndex][raceColumnIndex],
|
||||
leaderboard.getNetPoints(competitors[competitorIndex], raceColumnsToConsider.get(raceColumnIndex),
|
||||
timePoint, discardedRaceColumns), 0.00000001);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTieBreakByMedalRaceScoreOnlyIfEqualNetScore() throws NoWindException {
|
||||
Competitor[] c = createCompetitors(2).toArray(new Competitor[0]);
|
||||
@@ -1863,177 +1846,6 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest {
|
||||
assertEquals(0., leaderboard1.getNetPoints(c[3], beforeStartOfR1), 0.00000001); // not even the R1 scores apply before the start time of R1
|
||||
}
|
||||
|
||||
private TimePoint createAndAttachTrackedRaces(Series theSeries, String fleetName, boolean withScores, Competitor[]... competitorLists) {
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis()+1000);
|
||||
Iterator<? extends RaceColumn> columnIter = theSeries.getRaceColumns().iterator();
|
||||
for (Competitor[] competitorList : competitorLists) {
|
||||
RaceColumn raceColumn = columnIter.next();
|
||||
final TrackedRace trackedRace;
|
||||
if (withScores) {
|
||||
trackedRace = new MockedTrackedRaceWithStartTimeAndRanks(now, Arrays.asList(competitorList));
|
||||
} else {
|
||||
trackedRace = new MockedTrackedRaceWithStartTimeAndZeroRanks(now, Arrays.asList(competitorList));
|
||||
}
|
||||
raceColumn.setTrackedRace(raceColumn.getFleetByName(fleetName), trackedRace);
|
||||
}
|
||||
return later;
|
||||
}
|
||||
|
||||
private void createAndAttachTrackedRacesWithStartTimeAndLastMarkPassingTimes(
|
||||
Series theSeries, String fleetName, Competitor[][] competitorLists, TimePoint[] startTimes,
|
||||
Map<Competitor, TimePoint>[] lastMarkPassingTimesForCompetitors) {
|
||||
Iterator<? extends RaceColumn> columnIter = theSeries.getRaceColumns().iterator();
|
||||
int i=0;
|
||||
for (Competitor[] competitorList : competitorLists) {
|
||||
RaceColumn raceColumn = columnIter.next();
|
||||
final Map<Competitor, TimePoint> lastMarkPassingTimes = lastMarkPassingTimesForCompetitors[i];
|
||||
final Waypoint start = new WaypointImpl(new ControlPointWithTwoMarksImpl(new MarkImpl("Left StartBuoy"), new MarkImpl("Right StartBuoy"), "Start"));
|
||||
final Waypoint finish = new WaypointImpl(new MarkImpl("FinishBuoy"));
|
||||
TrackedRace trackedRace = new MockedTrackedRaceWithStartTimeAndRanks(startTimes[i], Arrays.asList(competitorList)) {
|
||||
private static final long serialVersionUID = 1L;
|
||||
@Override
|
||||
public NavigableSet<MarkPassing> getMarkPassings(Competitor competitor) {
|
||||
ArrayListNavigableSet<MarkPassing> result = new ArrayListNavigableSet<>(new TimedComparator());
|
||||
result.add(new MarkPassingImpl(lastMarkPassingTimes.get(competitor), finish, competitor));
|
||||
return result;
|
||||
}
|
||||
};
|
||||
trackedRace.getRace().getCourse().addWaypoint(0, start);
|
||||
trackedRace.getRace().getCourse().addWaypoint(1, finish);
|
||||
raceColumn.setTrackedRace(raceColumn.getFleetByName(fleetName), trackedRace);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
private List<Competitor> createCompetitors(int numberOfCompetitorsToCreate) {
|
||||
List<Competitor> result = new ArrayList<Competitor>();
|
||||
for (int i=1; i<=numberOfCompetitorsToCreate; i++) {
|
||||
result.add(createCompetitor("C"+i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Regatta createSimpleRegatta(final int numberOfRaces, final String regattaName, BoatClass boatClass, ScoringScheme scoringScheme) {
|
||||
series = new ArrayList<Series>();
|
||||
List<Fleet> fleets = new ArrayList<Fleet>();
|
||||
fleets.add(new FleetImpl("Default"));
|
||||
|
||||
List<String> raceColumnNames = new ArrayList<String>();
|
||||
for (int i = 1; i <= numberOfRaces; i++) {
|
||||
raceColumnNames.add("R" + i);
|
||||
}
|
||||
Series defaultSeries = new SeriesImpl("Default", /* isMedal */false, /* isFleetsCanRunInParallel */true,
|
||||
fleets, raceColumnNames, /* trackedRegattaRegistry */null);
|
||||
series.add(defaultSeries);
|
||||
|
||||
Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName(regattaName, boatClass.getName()), boatClass,
|
||||
/* startDate */null, /* endDate */null, series, /* persistent */false, scoringScheme, "123", null,
|
||||
OneDesignRankingMetric::new);
|
||||
return regatta;
|
||||
}
|
||||
|
||||
private Regatta createRegatta(final int numberOfQualifyingRaces, String[] qualifyingFleetNames, final int numberOfFinalRaces,
|
||||
String[] finalFleetNames, boolean medalRaceAndSeries, final int numberOfMedalRaces, final String regattaBaseName, BoatClass boatClass, ScoringScheme scoringScheme) {
|
||||
series = new ArrayList<Series>();
|
||||
|
||||
// -------- qualifying series ------------
|
||||
if (qualifyingFleetNames != null && qualifyingFleetNames.length > 0) {
|
||||
List<Fleet> qualifyingFleets = new ArrayList<Fleet>();
|
||||
for (String qualifyingFleetName : qualifyingFleetNames) {
|
||||
qualifyingFleets.add(new FleetImpl(qualifyingFleetName));
|
||||
}
|
||||
List<String> qualifyingRaceColumnNames = new ArrayList<String>();
|
||||
for (int i = 1; i <= numberOfQualifyingRaces; i++) {
|
||||
qualifyingRaceColumnNames.add("Q" + i);
|
||||
}
|
||||
Series qualifyingSeries = new SeriesImpl("Qualifying", /* isMedal */false, /* isFleetsCanRunInParallel */ true, qualifyingFleets,
|
||||
qualifyingRaceColumnNames, /* trackedRegattaRegistry */null);
|
||||
series.add(qualifyingSeries);
|
||||
}
|
||||
|
||||
// -------- final series ------------
|
||||
if (finalFleetNames != null && finalFleetNames.length > 0) {
|
||||
List<Fleet> finalFleets = new ArrayList<Fleet>();
|
||||
int fleetOrdering = 1;
|
||||
for (String finalFleetName : finalFleetNames) {
|
||||
finalFleets.add(new FleetImpl(finalFleetName, fleetOrdering++));
|
||||
}
|
||||
List<String> finalRaceColumnNames = new ArrayList<String>();
|
||||
for (int i = 1; i <= numberOfFinalRaces; i++) {
|
||||
finalRaceColumnNames.add("F" + i);
|
||||
}
|
||||
Series finalSeries = new SeriesImpl("Final", /* isMedal */false, /* isFleetsCanRunInParallel */ true, finalFleets, finalRaceColumnNames, /* trackedRegattaRegistry */ null);
|
||||
series.add(finalSeries);
|
||||
}
|
||||
|
||||
if (medalRaceAndSeries) {
|
||||
// ------------ medal --------------
|
||||
List<Fleet> medalFleets = new ArrayList<Fleet>();
|
||||
medalFleets.add(new FleetImpl("Medal"));
|
||||
List<String> medalRaceColumnNames = new ArrayList<String>();
|
||||
if(numberOfMedalRaces == 1) {
|
||||
medalRaceColumnNames.add("M");
|
||||
} else if(numberOfMedalRaces > 1) {
|
||||
for (int i = 1; i <= numberOfMedalRaces; i++) {
|
||||
medalRaceColumnNames.add("M" + i);
|
||||
}
|
||||
}
|
||||
Series medalSeries = new SeriesImpl("Medal", /* isMedal */true, /* isFleetsCanRunInParallel */ true, medalFleets, medalRaceColumnNames, /* trackedRegattaRegistry */ null);
|
||||
series.add(medalSeries);
|
||||
}
|
||||
|
||||
Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), boatClass,
|
||||
/*startDate*/ null, /*endDate*/ null, series, /* persistent */ false, scoringScheme, "123", null, OneDesignRankingMetric::new);
|
||||
return regatta;
|
||||
}
|
||||
|
||||
private Regatta createRegattaWithEliminations(final int numberOfEliminations, final int[] numbersOfHeatsPerRound,
|
||||
final String regattaBaseName, BoatClass boatClass, ScoringScheme scoringScheme) {
|
||||
series = new ArrayList<Series>();
|
||||
// example for numbersOfHeatsPerRound: [8, 4, 2, 2]
|
||||
for (int elimination=1; elimination<=numberOfEliminations; elimination++) {
|
||||
int heatNumber = 1;
|
||||
// create one elimination consisting of a number of rounds, each consisting of a number of heats
|
||||
int roundNumber = 1;
|
||||
for (int numberOfHeatsPerRound : numbersOfHeatsPerRound) {
|
||||
final boolean isFinalRound = roundNumber == numbersOfHeatsPerRound.length;
|
||||
// create one round as a series that has one fleet per heat
|
||||
List<Fleet> fleetsInRound = new ArrayList<Fleet>();
|
||||
for (int heatInRound=1; heatInRound<=numberOfHeatsPerRound; heatInRound++) {
|
||||
final int ordering = numbersOfHeatsPerRound.length-roundNumber+1+
|
||||
// in final round distinguish Final and Losers Final
|
||||
(isFinalRound ? heatInRound-1 : 1);
|
||||
fleetsInRound.add(new FleetImpl("Heat "+(heatNumber++), ordering));
|
||||
}
|
||||
List<String> raceColumnNameForRound = new ArrayList<String>();
|
||||
raceColumnNameForRound.add("E"+elimination+"R"+roundNumber);
|
||||
final String roundName;
|
||||
if (numbersOfHeatsPerRound.length-roundNumber == 2) {
|
||||
roundName = "Quarter-Final";
|
||||
} else if (numbersOfHeatsPerRound.length-roundNumber == 1) {
|
||||
roundName = "Semi-Final";
|
||||
} else if (numbersOfHeatsPerRound.length-roundNumber == 0) {
|
||||
roundName = "Final";
|
||||
} else {
|
||||
roundName = "Round "+roundNumber;
|
||||
}
|
||||
Series seriesForRound = new SeriesImpl("E"+elimination+" "+roundName, /* isMedal */ false, /* isFleetsCanRunInParallel */ true, fleetsInRound,
|
||||
raceColumnNameForRound, /* trackedRegattaRegistry */null);
|
||||
if (isFinalRound) {
|
||||
// last "Final" round; here, the fleets are contiguously scored
|
||||
seriesForRound.setSplitFleetContiguousScoring(true);
|
||||
}
|
||||
series.add(seriesForRound);
|
||||
roundNumber++;
|
||||
}
|
||||
}
|
||||
Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), boatClass,
|
||||
/*startDate*/ null, /*endDate*/ null, series, /* persistent */ false, scoringScheme,
|
||||
/* ID */ "123", /* course area */ null, OneDesignRankingMetric::new);
|
||||
return regatta;
|
||||
}
|
||||
|
||||
/**
|
||||
* See bug 1260. There must be a possibility to have ordered fleets that are scored such that the winner of the race of the best fleet
|
||||
* gets the best score in that column; and the winner of the second-best fleet gets the n-th best score in the column with n being the
|
||||
|
||||
+233
@@ -0,0 +1,233 @@
|
||||
package com.sap.sailing.domain.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.base.Series;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.base.impl.ControlPointWithTwoMarksImpl;
|
||||
import com.sap.sailing.domain.base.impl.FleetImpl;
|
||||
import com.sap.sailing.domain.base.impl.MarkImpl;
|
||||
import com.sap.sailing.domain.base.impl.RegattaImpl;
|
||||
import com.sap.sailing.domain.base.impl.SeriesImpl;
|
||||
import com.sap.sailing.domain.base.impl.WaypointImpl;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.ScoringScheme;
|
||||
import com.sap.sailing.domain.leaderboard.impl.RegattaLeaderboardImpl;
|
||||
import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl;
|
||||
import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
|
||||
import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithStartTimeAndRanks;
|
||||
import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithStartTimeAndZeroRanks;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.impl.MarkPassingImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.TimedComparator;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.util.impl.ArrayListNavigableSet;
|
||||
|
||||
public class LeaderboardScoringAndRankingTestBase extends AbstractLeaderboardTest {
|
||||
protected ArrayList<Series> series;
|
||||
|
||||
protected Leaderboard createLeaderboard(Regatta regatta, int[] discardingThresholds) {
|
||||
ThresholdBasedResultDiscardingRuleImpl discardingRules = new ThresholdBasedResultDiscardingRuleImpl(discardingThresholds);
|
||||
return new RegattaLeaderboardImpl(regatta, discardingRules);
|
||||
}
|
||||
|
||||
protected void checkScoresAfterSomeRaces(Leaderboard leaderboard, List<RaceColumn> raceColumnsToConsider,
|
||||
double[][] scoresAfterNRaces, TimePoint timePoint, Competitor[] competitors) throws NoWindException {
|
||||
for (int competitorIndex=0; competitorIndex<scoresAfterNRaces.length; competitorIndex++) {
|
||||
final Set<RaceColumn> discardedRaceColumns = leaderboard.getResultDiscardingRule()
|
||||
.getDiscardedRaceColumns(competitors[competitorIndex], leaderboard, raceColumnsToConsider, timePoint);
|
||||
for (int raceColumnIndex=0; raceColumnIndex<raceColumnsToConsider.size(); raceColumnIndex++) {
|
||||
assertEquals(scoresAfterNRaces[competitorIndex][raceColumnIndex],
|
||||
leaderboard.getNetPoints(competitors[competitorIndex], raceColumnsToConsider.get(raceColumnIndex),
|
||||
timePoint, discardedRaceColumns), 0.00000001);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected TimePoint createAndAttachTrackedRaces(Series theSeries, String fleetName, boolean withScores, Competitor[]... competitorLists) {
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis()+1000);
|
||||
Iterator<? extends RaceColumn> columnIter = theSeries.getRaceColumns().iterator();
|
||||
for (Competitor[] competitorList : competitorLists) {
|
||||
RaceColumn raceColumn = columnIter.next();
|
||||
final TrackedRace trackedRace;
|
||||
if (withScores) {
|
||||
trackedRace = new MockedTrackedRaceWithStartTimeAndRanks(now, Arrays.asList(competitorList));
|
||||
} else {
|
||||
trackedRace = new MockedTrackedRaceWithStartTimeAndZeroRanks(now, Arrays.asList(competitorList));
|
||||
}
|
||||
raceColumn.setTrackedRace(raceColumn.getFleetByName(fleetName), trackedRace);
|
||||
}
|
||||
return later;
|
||||
}
|
||||
|
||||
protected void createAndAttachTrackedRacesWithStartTimeAndLastMarkPassingTimes(
|
||||
Series theSeries, String fleetName, Competitor[][] competitorLists, TimePoint[] startTimes,
|
||||
Map<Competitor, TimePoint>[] lastMarkPassingTimesForCompetitors) {
|
||||
Iterator<? extends RaceColumn> columnIter = theSeries.getRaceColumns().iterator();
|
||||
int i=0;
|
||||
for (Competitor[] competitorList : competitorLists) {
|
||||
RaceColumn raceColumn = columnIter.next();
|
||||
final Map<Competitor, TimePoint> lastMarkPassingTimes = lastMarkPassingTimesForCompetitors[i];
|
||||
final Waypoint start = new WaypointImpl(new ControlPointWithTwoMarksImpl(new MarkImpl("Left StartBuoy"), new MarkImpl("Right StartBuoy"), "Start"));
|
||||
final Waypoint finish = new WaypointImpl(new MarkImpl("FinishBuoy"));
|
||||
TrackedRace trackedRace = new MockedTrackedRaceWithStartTimeAndRanks(startTimes[i], Arrays.asList(competitorList)) {
|
||||
private static final long serialVersionUID = 1L;
|
||||
@Override
|
||||
public NavigableSet<MarkPassing> getMarkPassings(Competitor competitor) {
|
||||
ArrayListNavigableSet<MarkPassing> result = new ArrayListNavigableSet<>(new TimedComparator());
|
||||
result.add(new MarkPassingImpl(lastMarkPassingTimes.get(competitor), finish, competitor));
|
||||
return result;
|
||||
}
|
||||
};
|
||||
trackedRace.getRace().getCourse().addWaypoint(0, start);
|
||||
trackedRace.getRace().getCourse().addWaypoint(1, finish);
|
||||
raceColumn.setTrackedRace(raceColumn.getFleetByName(fleetName), trackedRace);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Competitor> createCompetitors(int numberOfCompetitorsToCreate) {
|
||||
List<Competitor> result = new ArrayList<Competitor>();
|
||||
for (int i=1; i<=numberOfCompetitorsToCreate; i++) {
|
||||
result.add(createCompetitor("C"+i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Regatta createSimpleRegatta(final int numberOfRaces, final String regattaName, BoatClass boatClass, ScoringScheme scoringScheme) {
|
||||
series = new ArrayList<Series>();
|
||||
List<Fleet> fleets = new ArrayList<Fleet>();
|
||||
fleets.add(new FleetImpl("Default"));
|
||||
|
||||
List<String> raceColumnNames = new ArrayList<String>();
|
||||
for (int i = 1; i <= numberOfRaces; i++) {
|
||||
raceColumnNames.add("R" + i);
|
||||
}
|
||||
Series defaultSeries = new SeriesImpl("Default", /* isMedal */false, /* isFleetsCanRunInParallel */true,
|
||||
fleets, raceColumnNames, /* trackedRegattaRegistry */null);
|
||||
series.add(defaultSeries);
|
||||
|
||||
Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName(regattaName, boatClass.getName()), boatClass,
|
||||
/* startDate */null, /* endDate */null, series, /* persistent */false, scoringScheme, "123", null,
|
||||
OneDesignRankingMetric::new);
|
||||
return regatta;
|
||||
}
|
||||
|
||||
protected Regatta createRegatta(final int numberOfQualifyingRaces, String[] qualifyingFleetNames, final int numberOfFinalRaces,
|
||||
String[] finalFleetNames, boolean medalRaceAndSeries, final int numberOfMedalRaces, final String regattaBaseName, BoatClass boatClass, ScoringScheme scoringScheme) {
|
||||
series = new ArrayList<Series>();
|
||||
|
||||
// -------- qualifying series ------------
|
||||
if (qualifyingFleetNames != null && qualifyingFleetNames.length > 0) {
|
||||
List<Fleet> qualifyingFleets = new ArrayList<Fleet>();
|
||||
for (String qualifyingFleetName : qualifyingFleetNames) {
|
||||
qualifyingFleets.add(new FleetImpl(qualifyingFleetName));
|
||||
}
|
||||
List<String> qualifyingRaceColumnNames = new ArrayList<String>();
|
||||
for (int i = 1; i <= numberOfQualifyingRaces; i++) {
|
||||
qualifyingRaceColumnNames.add("Q" + i);
|
||||
}
|
||||
Series qualifyingSeries = new SeriesImpl("Qualifying", /* isMedal */false, /* isFleetsCanRunInParallel */ true, qualifyingFleets,
|
||||
qualifyingRaceColumnNames, /* trackedRegattaRegistry */null);
|
||||
series.add(qualifyingSeries);
|
||||
}
|
||||
|
||||
// -------- final series ------------
|
||||
if (finalFleetNames != null && finalFleetNames.length > 0) {
|
||||
List<Fleet> finalFleets = new ArrayList<Fleet>();
|
||||
int fleetOrdering = 1;
|
||||
for (String finalFleetName : finalFleetNames) {
|
||||
finalFleets.add(new FleetImpl(finalFleetName, fleetOrdering++));
|
||||
}
|
||||
List<String> finalRaceColumnNames = new ArrayList<String>();
|
||||
for (int i = 1; i <= numberOfFinalRaces; i++) {
|
||||
finalRaceColumnNames.add("F" + i);
|
||||
}
|
||||
Series finalSeries = new SeriesImpl("Final", /* isMedal */false, /* isFleetsCanRunInParallel */ true, finalFleets, finalRaceColumnNames, /* trackedRegattaRegistry */ null);
|
||||
series.add(finalSeries);
|
||||
}
|
||||
|
||||
if (medalRaceAndSeries) {
|
||||
// ------------ medal --------------
|
||||
List<Fleet> medalFleets = new ArrayList<Fleet>();
|
||||
medalFleets.add(new FleetImpl("Medal"));
|
||||
List<String> medalRaceColumnNames = new ArrayList<String>();
|
||||
if(numberOfMedalRaces == 1) {
|
||||
medalRaceColumnNames.add("M");
|
||||
} else if(numberOfMedalRaces > 1) {
|
||||
for (int i = 1; i <= numberOfMedalRaces; i++) {
|
||||
medalRaceColumnNames.add("M" + i);
|
||||
}
|
||||
}
|
||||
Series medalSeries = new SeriesImpl("Medal", /* isMedal */true, /* isFleetsCanRunInParallel */ true, medalFleets, medalRaceColumnNames, /* trackedRegattaRegistry */ null);
|
||||
series.add(medalSeries);
|
||||
}
|
||||
|
||||
Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), boatClass,
|
||||
/*startDate*/ null, /*endDate*/ null, series, /* persistent */ false, scoringScheme, "123", null, OneDesignRankingMetric::new);
|
||||
return regatta;
|
||||
}
|
||||
|
||||
protected Regatta createRegattaWithEliminations(final int numberOfEliminations, final int[] numbersOfHeatsPerRound,
|
||||
final String regattaBaseName, BoatClass boatClass, ScoringScheme scoringScheme) {
|
||||
series = new ArrayList<Series>();
|
||||
// example for numbersOfHeatsPerRound: [8, 4, 2, 2]
|
||||
for (int elimination=1; elimination<=numberOfEliminations; elimination++) {
|
||||
int heatNumber = 1;
|
||||
// create one elimination consisting of a number of rounds, each consisting of a number of heats
|
||||
int roundNumber = 1;
|
||||
for (int numberOfHeatsPerRound : numbersOfHeatsPerRound) {
|
||||
final boolean isFinalRound = roundNumber == numbersOfHeatsPerRound.length;
|
||||
// create one round as a series that has one fleet per heat
|
||||
List<Fleet> fleetsInRound = new ArrayList<Fleet>();
|
||||
for (int heatInRound=1; heatInRound<=numberOfHeatsPerRound; heatInRound++) {
|
||||
final int ordering = numbersOfHeatsPerRound.length-roundNumber+1+
|
||||
// in final round distinguish Final and Losers Final
|
||||
(isFinalRound ? heatInRound-1 : 1);
|
||||
fleetsInRound.add(new FleetImpl("Heat "+(heatNumber++), ordering));
|
||||
}
|
||||
List<String> raceColumnNameForRound = new ArrayList<String>();
|
||||
raceColumnNameForRound.add("E"+elimination+"R"+roundNumber);
|
||||
final String roundName;
|
||||
if (numbersOfHeatsPerRound.length-roundNumber == 2) {
|
||||
roundName = "Quarter-Final";
|
||||
} else if (numbersOfHeatsPerRound.length-roundNumber == 1) {
|
||||
roundName = "Semi-Final";
|
||||
} else if (numbersOfHeatsPerRound.length-roundNumber == 0) {
|
||||
roundName = "Final";
|
||||
} else {
|
||||
roundName = "Round "+roundNumber;
|
||||
}
|
||||
Series seriesForRound = new SeriesImpl("E"+elimination+" "+roundName, /* isMedal */ false, /* isFleetsCanRunInParallel */ true, fleetsInRound,
|
||||
raceColumnNameForRound, /* trackedRegattaRegistry */null);
|
||||
if (isFinalRound) {
|
||||
// last "Final" round; here, the fleets are contiguously scored
|
||||
seriesForRound.setSplitFleetContiguousScoring(true);
|
||||
}
|
||||
series.add(seriesForRound);
|
||||
roundNumber++;
|
||||
}
|
||||
}
|
||||
Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), boatClass,
|
||||
/*startDate*/ null, /*endDate*/ null, series, /* persistent */ false, scoringScheme,
|
||||
/* ID */ "123", /* course area */ null, OneDesignRankingMetric::new);
|
||||
return regatta;
|
||||
}
|
||||
}
|
||||
Executable → Regular
+14
-9
@@ -166,16 +166,21 @@ public abstract class ExpandableSortableColumn<C> extends LeaderboardSortableCol
|
||||
setExpanded(!isExpanded());
|
||||
ensureExpansionDataIsLoaded(new Runnable() {
|
||||
public void run() {
|
||||
int insertIndex = table.getColumnIndex(ExpandableSortableColumn.this);
|
||||
// The check "insertIndex != -1" is necessary, because the child-columns might be deleted asynchronously
|
||||
// while toggling the columns.
|
||||
if (insertIndex != -1) {
|
||||
insertIndex++;
|
||||
for (AbstractSortableColumnWithMinMax<LeaderboardRowDTO, ?> column : getAllVisibleChildren()) {
|
||||
column.updateMinMax();
|
||||
getLeaderboardPanel().insertColumn(insertIndex++, column);
|
||||
// column may have been collapsed meanwhile, so that the columns must not be added to the table right now
|
||||
if (isExpanded()) {
|
||||
int insertIndex = table.getColumnIndex(ExpandableSortableColumn.this);
|
||||
// The check "insertIndex != -1" is necessary, because the child-columns might be deleted
|
||||
// asynchronously while toggling the columns.
|
||||
if (insertIndex != -1) {
|
||||
insertIndex++;
|
||||
for (AbstractSortableColumnWithMinMax<LeaderboardRowDTO, ?> column : getAllVisibleChildren()) {
|
||||
column.updateMinMax();
|
||||
if (table.getColumnIndex(column) < 0) {
|
||||
getLeaderboardPanel().insertColumn(insertIndex++, column);
|
||||
}
|
||||
}
|
||||
getLeaderboardPanel().getLeaderboardTable().redraw();
|
||||
}
|
||||
getLeaderboardPanel().getLeaderboardTable().redraw();
|
||||
}
|
||||
getLeaderboardPanel().setBusyState(oldBusyState);
|
||||
setTogglingInProcess(false);
|
||||
|
||||
+1
-1
@@ -2484,7 +2484,7 @@ public class LeaderboardPanel extends SimplePanel implements Component<Leaderboa
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Due to a course change, a race may change its number of legs. All expanded race columns that show leg columns and
|
||||
* whose leg count changed need to be collapsed before the leaderboard is replaced, and expanded afterwards again.
|
||||
* Race columns whose toggling is {@link ExpandableSortableColumn#isTogglingInProcess() currently in progress} are
|
||||
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
package com.sap.sailing.server.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.CompetitorResults;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultsImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.RaceState;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.impl.RacingProcedureFactoryImpl;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.base.configuration.impl.EmptyRegattaConfiguration;
|
||||
import com.sap.sailing.domain.base.impl.BoatClassImpl;
|
||||
import com.sap.sailing.domain.base.impl.BoatImpl;
|
||||
import com.sap.sailing.domain.base.impl.NationalityImpl;
|
||||
import com.sap.sailing.domain.base.impl.PersonImpl;
|
||||
import com.sap.sailing.domain.base.impl.TeamImpl;
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.ScoringSchemeType;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.test.LeaderboardScoringAndRankingTestBase;
|
||||
import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithStartTimeAndRanks;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sailing.server.impl.RacingEventServiceImpl;
|
||||
import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class ApplyScoresFromRaceLogTest extends LeaderboardScoringAndRankingTestBase {
|
||||
/**
|
||||
* See also bug 3794: make sure that different variants of scores and max points reasons / penalties are applied to the
|
||||
* leaderboard.
|
||||
*/
|
||||
@Test
|
||||
public void testApplicationOfScoresFromRaceLog() throws NoWindException {
|
||||
final RacingEventService service = new RacingEventServiceImpl();
|
||||
final List<Competitor> competitors = new ArrayList<>();
|
||||
for (int i=0; i<20; i++) {
|
||||
final String competitorName = "C"+i;
|
||||
competitors.add(service.getBaseDomainFactory().getCompetitorStore().getOrCreateCompetitor(UUID.randomUUID(),
|
||||
competitorName, /* displayColor */ Color.RED, /* email */ null, /* flagImageURI */ null,
|
||||
new TeamImpl("STG", Collections.singleton(
|
||||
new PersonImpl(competitorName, new NationalityImpl("GER"),
|
||||
/* dateOfBirth */ null, "This is famous "+competitorName)),
|
||||
new PersonImpl("Rigo van Maas", new NationalityImpl("NED"),
|
||||
/* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat",
|
||||
new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null),
|
||||
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null));
|
||||
}
|
||||
final Regatta regatta = createRegatta(/* qualifying */0, new String[] { "Default" }, /* final */1,
|
||||
new String[] { "Default" },
|
||||
/* medal */false, /* medal */ 0, "testOneStartedRaceWithDifferentScores",
|
||||
DomainFactory.INSTANCE.getOrCreateBoatClass("49er", /* typicallyStartsUpwind */true), DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT));
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis()+1000);
|
||||
TrackedRace f1 = new MockedTrackedRaceWithStartTimeAndRanks(now, competitors);
|
||||
RaceColumn f1Column = series.get(1).getRaceColumnByName("F1");
|
||||
f1Column.setTrackedRace(f1Column.getFleets().iterator().next(), f1);
|
||||
final Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
|
||||
service.addLeaderboard(leaderboard); // should add a RaceLogScoringReplicator as listener to the leaderboard
|
||||
service.addRegattaWithoutReplication(regatta);
|
||||
final Map<Competitor, Double> scores = new HashMap<>();
|
||||
final Map<Competitor, MaxPointsReason> mprs = new HashMap<>();
|
||||
int oneBasedRank = 1;
|
||||
final CompetitorResults results = new CompetitorResultsImpl();
|
||||
for (final Competitor c : competitors) {
|
||||
final MaxPointsReason mpr = new MaxPointsReason[] { null, MaxPointsReason.NONE, MaxPointsReason.DNF, MaxPointsReason.OCS }[oneBasedRank%4];
|
||||
final Double score = oneBasedRank%5 == 0 ? null : 20*Math.random();
|
||||
scores.put(c, score);
|
||||
mprs.put(c, mpr);
|
||||
results.add(new CompetitorResultImpl(c.getId(), c.getName(),
|
||||
oneBasedRank++, mpr, score, /* finishingTime */ null, /* comment */ null));
|
||||
}
|
||||
final RaceLog f1RaceLog = f1Column.getRaceLog(f1Column.getFleets().iterator().next());
|
||||
final LogEventAuthorImpl author = new LogEventAuthorImpl("Axel", 0);
|
||||
final RaceState f1RaceState = new RaceStateImpl(service, f1RaceLog, author,
|
||||
new RacingProcedureFactoryImpl(author, new EmptyRegattaConfiguration()));
|
||||
f1RaceState.setFinishPositioningListChanged(now, results);
|
||||
final List<Competitor> rankedCompetitorsBeforeApplying = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
assertEquals(competitors, rankedCompetitorsBeforeApplying); // no effects of preliminary results list yet
|
||||
f1RaceState.setFinishPositioningConfirmed(now);
|
||||
for (final Competitor c : competitors) {
|
||||
assertEquals(scores.get(c)==null?competitors.indexOf(c)+1:scores.get(c), leaderboard.getTotalPoints(c, f1Column, now), 0.00000001);
|
||||
}
|
||||
final List<Competitor> expectedNewOrder = new ArrayList<>(competitors);
|
||||
expectedNewOrder.sort((c1, c2)->
|
||||
new Double(scores.get(c1)==null?competitors.indexOf(c1)+1:scores.get(c1)).compareTo(
|
||||
new Double(scores.get(c2)==null?competitors.indexOf(c2)+1:scores.get(c2))));
|
||||
final List<Competitor> rankedCompetitorsAfterApplying = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
assertEquals(expectedNewOrder, rankedCompetitorsAfterApplying);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+10
-35
@@ -1,7 +1,5 @@
|
||||
package com.sap.sailing.server.impl;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.CompetitorResult;
|
||||
import com.sap.sailing.domain.abstractlog.race.CompetitorResults;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
@@ -15,7 +13,6 @@ import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.RaceColumnListener;
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.ResultDiscardingRule;
|
||||
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
|
||||
@@ -148,21 +145,13 @@ public class RaceLogScoringReplicator implements RaceColumnListener {
|
||||
if (positioningList != null) {
|
||||
for (CompetitorResult positionedCompetitor : positioningList) {
|
||||
Competitor competitor = service.getBaseDomainFactory().getExistingCompetitorById(positionedCompetitor.getCompetitorId());
|
||||
if (positionedCompetitor.getMaxPointsReason().equals(MaxPointsReason.NONE)) {
|
||||
try {
|
||||
resetMaxPointsReasonIfNecessary(leaderboard, raceColumn, timePoint, competitor);
|
||||
int rankByRaceCommittee = getRankInPositioningListByRaceCommittee(positionedCompetitor);
|
||||
correctScoreInLeaderboard(leaderboard, raceColumn, timePoint, numberOfCompetitorsInRace,
|
||||
competitor, rankByRaceCommittee, positionedCompetitor.getScore());
|
||||
} catch (NoWindException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
setMaxPointsReasonInLeaderboardIfNecessary(leaderboard, raceColumn, timePoint, positionedCompetitor, competitor);
|
||||
}
|
||||
int rankByRaceCommittee = getRankInPositioningListByRaceCommittee(positionedCompetitor);
|
||||
correctScoreInLeaderboard(leaderboard, raceColumn, timePoint, numberOfCompetitorsInRace,
|
||||
competitor, rankByRaceCommittee, positionedCompetitor.getScore());
|
||||
setMaxPointsReasonInLeaderboardIfNecessary(leaderboard, raceColumn, timePoint, positionedCompetitor, competitor);
|
||||
}
|
||||
//Since the metadata update is used by the Sailing suite to determine the final state of a race, it has to be triggered, even though
|
||||
//no score correction was performed
|
||||
// Since the metadata update is used by the Sailing suite to determine the final state of a race, it has to
|
||||
// be triggered, even though no score correction may have been performed
|
||||
applyMetadataUpdate(leaderboard, timePoint, COMMENT_TEXT_ON_SCORE_CORRECTION);
|
||||
}
|
||||
}
|
||||
@@ -170,9 +159,9 @@ public class RaceLogScoringReplicator implements RaceColumnListener {
|
||||
private boolean setMaxPointsReasonInLeaderboardIfNecessary(Leaderboard leaderboard, RaceColumn raceColumn,
|
||||
TimePoint timePoint, CompetitorResult positionedCompetitor, Competitor competitor) {
|
||||
boolean scoreHasBeenCorrected = false;
|
||||
MaxPointsReason trackedMaxPointsReason = leaderboard.getMaxPointsReason(competitor, raceColumn, timePoint);
|
||||
MaxPointsReason oldMaxPointsReason = leaderboard.getMaxPointsReason(competitor, raceColumn, timePoint);
|
||||
MaxPointsReason maxPointsReasonByRaceCommittee = positionedCompetitor.getMaxPointsReason();
|
||||
if (!maxPointsReasonByRaceCommittee.equals(trackedMaxPointsReason)) {
|
||||
if (!Util.equalsWithNull(maxPointsReasonByRaceCommittee, oldMaxPointsReason)) {
|
||||
applyMaxPointsReasonOperation(leaderboard, raceColumn, competitor, maxPointsReasonByRaceCommittee, timePoint);
|
||||
scoreHasBeenCorrected = true;
|
||||
}
|
||||
@@ -181,16 +170,11 @@ public class RaceLogScoringReplicator implements RaceColumnListener {
|
||||
|
||||
private void correctScoreInLeaderboard(Leaderboard leaderboard, RaceColumn raceColumn, TimePoint timePoint,
|
||||
final int numberOfCompetitorsInRace,
|
||||
Competitor competitor, int rankByRaceCommittee, Double optionalExplicitScore) throws NoWindException {
|
||||
Competitor competitor, int rankByRaceCommittee, Double optionalExplicitScore) {
|
||||
final Double scoreByRaceCommittee;
|
||||
if (optionalExplicitScore == null) {
|
||||
scoreByRaceCommittee = leaderboard.getScoringScheme().getScoreForRank(leaderboard, raceColumn, competitor,
|
||||
rankByRaceCommittee, new Callable<Integer>() {
|
||||
@Override
|
||||
public Integer call() {
|
||||
return numberOfCompetitorsInRace;
|
||||
}
|
||||
}, leaderboard.getNumberOfCompetitorsInLeaderboardFetcher(), timePoint);
|
||||
rankByRaceCommittee, ()->numberOfCompetitorsInRace, leaderboard.getNumberOfCompetitorsInLeaderboardFetcher(), timePoint);
|
||||
} else {
|
||||
scoreByRaceCommittee = optionalExplicitScore;
|
||||
}
|
||||
@@ -198,15 +182,6 @@ public class RaceLogScoringReplicator implements RaceColumnListener {
|
||||
applyScoreCorrectionOperation(leaderboard, raceColumn, competitor, scoreByRaceCommittee, timePoint);
|
||||
}
|
||||
|
||||
private boolean resetMaxPointsReasonIfNecessary(Leaderboard leaderboard, RaceColumn raceColumn, TimePoint timePoint, Competitor competitor) {
|
||||
boolean scoreHasBeenCorrected = false;
|
||||
if (!leaderboard.getMaxPointsReason(competitor, raceColumn, timePoint).equals(MaxPointsReason.NONE)) {
|
||||
applyMaxPointsReasonOperation(leaderboard, raceColumn, competitor, MaxPointsReason.NONE, timePoint);
|
||||
scoreHasBeenCorrected = true;
|
||||
}
|
||||
return scoreHasBeenCorrected;
|
||||
}
|
||||
|
||||
private void applyScoreCorrectionOperation(Leaderboard leaderboard, RaceColumn raceColumn, Competitor competitor, Double correctedScore, TimePoint timePoint) {
|
||||
RacingEventServiceOperation<?> operation = new UpdateLeaderboardScoreCorrection(leaderboard.getName(), raceColumn.getName(), competitor.getId().toString(), correctedScore, timePoint);
|
||||
service.apply(operation);
|
||||
|
||||
@@ -22,8 +22,9 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:ellipsize="middle"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/toolbar_text_color"
|
||||
android:textSize="16sp" />
|
||||
|
||||
@@ -32,8 +33,9 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:ellipsize="middle"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/toolbar_text_color"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
Reference in new issue
Block a user