mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-22 13:45:42 +00:00
Merge remote-tracking branch 'ExternalGit/master' into raceboard-simulation
This commit is contained in:
+1
-1
@@ -35,7 +35,7 @@ import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class BarbadosResultImportTest {
|
||||
private static final MillisecondsTimePoint NOW = MillisecondsTimePoint.now();
|
||||
private static final TimePoint NOW = MillisecondsTimePoint.now();
|
||||
private static final String SAMPLE_INPUT_NAME_EMPTY_RESULTS = "RESULTS-505Barbados.xlsx";
|
||||
private static final String SAMPLE_INPUT_NAME_SOME_RESULTS = "RESULTS2.xlsx";
|
||||
private static final String RESOURCES = "resources/";
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package com.sap.sailing.datamining.test.util;
|
||||
|
||||
import com.sap.sse.datamining.AdditionalResultDataBuilder;
|
||||
import com.sap.sse.datamining.components.AdditionalResultDataBuilder;
|
||||
import com.sap.sse.datamining.impl.components.AbstractProcessor;
|
||||
|
||||
public class NullProcessor<InputType, ResultType> extends AbstractProcessor<InputType, ResultType> {
|
||||
|
||||
+13
-1
@@ -20,6 +20,7 @@ LegSailingDomainRetrieverChain=Segel-Dom
|
||||
GPSFixSailingDomainRetrieverChain=Segel-Domänen GPS-Fix-Beschaffer
|
||||
MarkPassingSailingDomainRetrieverChain=Segel-Domänen Tonnenrundungs-Beschaffer
|
||||
RaceResultSailingDomainRetrieverChain=Segel-Domänen Rennergebnis-Beschaffer
|
||||
RaceOfCompetitorSailingDomainRetrieverChain=Rennen eines Teilnehmers-Beschaffer
|
||||
LeaderboardGroup=Ranglisten Gruppe
|
||||
Leaderboard=Rangliste
|
||||
Leg=Schenkel
|
||||
@@ -44,4 +45,15 @@ Bft10=schwerer Sturm
|
||||
Bft11=orkanartiger Sturm
|
||||
Bft12=Orkan
|
||||
RelativeScoreInRace=Relative Wertung im Rennen (0 am besten; 1 am schlechtesten)
|
||||
WindSpeedInBeaufort=Windgeschwindigkeit in Bft.
|
||||
WindSpeedInBeaufort=Windgeschwindigkeit in Bft.
|
||||
DistanceAtStart=Distanz zur Startlinie zum Startzeitpunkt
|
||||
SpeedAtStart=Geschwindigkeit zum Startzeitpunkt
|
||||
SpeedTenSecondsBeforeStart=Geschwindigkeit 10s vor dem Startzeitpunkt
|
||||
RankAtFirstMark=Position beim ersten Wegpunkt
|
||||
NumberOfTacks=Anzahl der Wenden
|
||||
NumberOfJibes=Anzahl der Halsen
|
||||
NumberOfPenaltyCircles=Anzahl der Straf-Kreise
|
||||
RankGainsOrLosses=Positions-Verluste oder -Gewinne
|
||||
DistanceToStarboardSideAtStart=Distanz zur Steuerbordseite (% der Länge)
|
||||
NumberOfPodiumFinish=Azahl der Podium-Siege
|
||||
NumberOfWins=Anzahl der Siege
|
||||
+13
-1
@@ -22,6 +22,7 @@ LegSailingDomainRetrieverChain=Sailing Domain Leg Retriever
|
||||
GPSFixSailingDomainRetrieverChain=Sailing Domain GPS Fix Retriever
|
||||
MarkPassingSailingDomainRetrieverChain=Sailing Domain Mark Passing Retriever
|
||||
RaceResultSailingDomainRetrieverChain=Sailing Domain Race Result Retriever
|
||||
RaceOfCompetitorSailingDomainRetrieverChain=Race of Competitor Retriever
|
||||
LeaderboardGroup=Leaderboard Group
|
||||
Leaderboard=Leaderboard
|
||||
Leg=Leg
|
||||
@@ -44,4 +45,15 @@ Bft10=Storm
|
||||
Bft11=Violent storm
|
||||
Bft12=Hurricane
|
||||
RelativeScoreInRace=Relative score in race (0 best; 1 worst)
|
||||
WindSpeedInBeaufort=Wind speed in Bft
|
||||
WindSpeedInBeaufort=Wind speed in Bft
|
||||
DistanceAtStart=Distance to start at start
|
||||
SpeedAtStart=Speed at start
|
||||
SpeedTenSecondsBeforeStart=Speed 10s before start
|
||||
RankAtFirstMark=Rank at First Mark
|
||||
NumberOfTacks=Number of Tacks
|
||||
NumberOfJibes=Number of Jibes
|
||||
NumberOfPenaltyCircles=Number of Penalty Circles
|
||||
RankGainsOrLosses=Rank Gains or Losses
|
||||
DistanceToStarboardSideAtStart=Distance to Starboard Side (% of Length)
|
||||
NumberOfPodiumFinish=Number of Podium Finishes
|
||||
NumberOfWins=Number of Wins
|
||||
@@ -6,16 +6,19 @@ import java.util.Set;
|
||||
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
import com.sap.sailing.datamining.data.HasRaceResultOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.data.HasGPSFixContext;
|
||||
import com.sap.sailing.datamining.data.HasMarkPassingContext;
|
||||
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.data.HasRaceResultOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedLegContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedRaceContext;
|
||||
import com.sap.sailing.datamining.impl.components.aggregators.ParallelTrueSumAggregationProcessor;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sse.datamining.DataMiningBundleService;
|
||||
import com.sap.sse.datamining.DataRetrieverChainDefinition;
|
||||
import com.sap.sse.datamining.DataSourceProvider;
|
||||
import com.sap.sse.datamining.components.AggregationProcessorDefinition;
|
||||
import com.sap.sse.datamining.components.DataRetrieverChainDefinition;
|
||||
import com.sap.sse.datamining.data.ClusterGroup;
|
||||
import com.sap.sse.datamining.impl.AbstractDataMiningActivator;
|
||||
import com.sap.sse.i18n.ResourceBundleStringMessages;
|
||||
@@ -74,6 +77,7 @@ public class Activator extends AbstractDataMiningActivator implements DataMining
|
||||
internalClasses.add(HasTrackedLegOfCompetitorContext.class);
|
||||
internalClasses.add(HasGPSFixContext.class);
|
||||
internalClasses.add(HasMarkPassingContext.class);
|
||||
internalClasses.add(HasRaceOfCompetitorContext.class);
|
||||
return internalClasses;
|
||||
}
|
||||
|
||||
@@ -91,6 +95,13 @@ public class Activator extends AbstractDataMiningActivator implements DataMining
|
||||
return dataSourceProviders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<AggregationProcessorDefinition<?, ?>> getAggregationProcessorDefinitions() {
|
||||
HashSet<AggregationProcessorDefinition<?, ?>> aggregators = new HashSet<>();
|
||||
aggregators.add(ParallelTrueSumAggregationProcessor.getDefinition());
|
||||
return aggregators;
|
||||
}
|
||||
|
||||
private void initializeDataSourceProviders() {
|
||||
dataSourceProviders = new HashSet<>();
|
||||
dataSourceProviders.add(new RacingEventServiceProvider(context));
|
||||
|
||||
+9
-2
@@ -6,6 +6,7 @@ import java.util.Collection;
|
||||
import com.sap.sailing.datamining.data.HasGPSFixContext;
|
||||
import com.sap.sailing.datamining.data.HasLeaderboardContext;
|
||||
import com.sap.sailing.datamining.data.HasMarkPassingContext;
|
||||
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.data.HasRaceResultOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedLegContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
|
||||
@@ -15,13 +16,14 @@ import com.sap.sailing.datamining.impl.components.GPSFixRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.LeaderboardGroupRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.LeaderboardRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.MarkPassingRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.RaceOfCompetitorRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.TrackedLegOfCompetitorRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.TrackedLegRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.TrackedRaceRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.data.LeaderboardGroupWithContext;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sse.datamining.DataRetrieverChainDefinition;
|
||||
import com.sap.sse.datamining.impl.SimpleDataRetrieverChainDefinition;
|
||||
import com.sap.sse.datamining.components.DataRetrieverChainDefinition;
|
||||
import com.sap.sse.datamining.impl.components.SimpleDataRetrieverChainDefinition;
|
||||
|
||||
public class SailingDataRetrievalChainDefinitions {
|
||||
|
||||
@@ -50,6 +52,11 @@ public class SailingDataRetrievalChainDefinitions {
|
||||
trackedRaceRetrieverChainDefinition, HasMarkPassingContext.class, "MarkPassingSailingDomainRetrieverChain");
|
||||
markPassingRetrieverChainDefinition.endWith(TrackedRaceRetrievalProcessor.class, MarkPassingRetrievalProcessor.class, HasMarkPassingContext.class, "MarkPassing");
|
||||
dataRetrieverChainDefinitions.add(markPassingRetrieverChainDefinition);
|
||||
|
||||
final DataRetrieverChainDefinition<RacingEventService, HasRaceOfCompetitorContext> raceOfCompetitorRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
|
||||
trackedRaceRetrieverChainDefinition, HasRaceOfCompetitorContext.class, "RaceOfCompetitorSailingDomainRetrieverChain");
|
||||
raceOfCompetitorRetrieverChainDefinition.endWith(TrackedRaceRetrievalProcessor.class, RaceOfCompetitorRetrievalProcessor.class, HasRaceOfCompetitorContext.class, "Competitor");
|
||||
dataRetrieverChainDefinitions.add(raceOfCompetitorRetrieverChainDefinition);
|
||||
|
||||
final DataRetrieverChainDefinition<RacingEventService, HasTrackedLegOfCompetitorContext> legOfCompetitorRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
|
||||
trackedRaceRetrieverChainDefinition, HasTrackedLegOfCompetitorContext.class, "LegSailingDomainRetrieverChain");
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.sap.sailing.datamining.data;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sse.datamining.shared.annotations.Connector;
|
||||
import com.sap.sse.datamining.shared.annotations.Statistic;
|
||||
import com.sap.sse.datamining.shared.data.Unit;
|
||||
|
||||
public interface HasRaceOfCompetitorContext {
|
||||
|
||||
@Connector(scanForStatistics=false)
|
||||
public HasTrackedRaceContext getTrackedRaceContext();
|
||||
|
||||
@Connector(messageKey="Competitor")
|
||||
public Competitor getCompetitor();
|
||||
|
||||
@Statistic(messageKey="DistanceAtStart", resultUnit=Unit.Meters, resultDecimals=0, ordinal=0)
|
||||
public double getDistanceToStartLineAtStart();
|
||||
|
||||
@Statistic(messageKey="DistanceToStarboardSideAtStart", resultDecimals=2, ordinal=1)
|
||||
public Double getNormalizedDistanceToStarboardSideAtStart();
|
||||
|
||||
@Connector(messageKey="SpeedAtStart", ordinal=2)
|
||||
public Speed getSpeedAtStart();
|
||||
|
||||
@Connector(messageKey="SpeedTenSecondsBeforeStart", ordinal=3)
|
||||
public Speed getSpeedTenSecondsBeforeStart();
|
||||
|
||||
@Statistic(messageKey="RankAtFirstMark", resultDecimals=2, ordinal=4)
|
||||
public Double getRankAtFirstMark();
|
||||
|
||||
@Statistic(messageKey="NumberOfTacks", resultDecimals=2, ordinal=5)
|
||||
public Double getNumberOfTacks();
|
||||
|
||||
@Statistic(messageKey="NumberOfJibes", resultDecimals=2, ordinal=6)
|
||||
public Double getNumberOfJibes();
|
||||
|
||||
@Statistic(messageKey="NumberOfPenaltyCircles", resultDecimals=2, ordinal=7)
|
||||
public Double getNumberOfPenaltyCircles();
|
||||
|
||||
@Statistic(messageKey="RankGainsOrLosses", resultDecimals=2, ordinal=8)
|
||||
public Double getRankGainsOrLosses();
|
||||
|
||||
}
|
||||
+7
-1
@@ -16,7 +16,7 @@ public interface HasRaceResultOfCompetitorContext {
|
||||
/**
|
||||
* 0 means the competitor won the race, 1 means the competitor ranked last
|
||||
*/
|
||||
@Statistic(messageKey="RelativeScoreInRace", ordinal=3, resultDecimals=2)
|
||||
@Statistic(messageKey="RelativeScoreInRace", ordinal=1, resultDecimals=2)
|
||||
public double getRelativeRank();
|
||||
|
||||
@Dimension(messageKey="WindSpeedInBeaufort")
|
||||
@@ -24,4 +24,10 @@ public interface HasRaceResultOfCompetitorContext {
|
||||
|
||||
@Dimension(messageKey="Regatta")
|
||||
String getRegattaName();
|
||||
|
||||
@Statistic(messageKey="NumberOfPodiumFinish", ordinal=2)
|
||||
public Boolean isPodiumFinish();
|
||||
|
||||
@Statistic(messageKey="NumberOfWins", ordinal=3)
|
||||
public Boolean isWin();
|
||||
}
|
||||
|
||||
+3
@@ -18,5 +18,8 @@ public interface HasTrackedLegOfCompetitorContext {
|
||||
|
||||
@Statistic(messageKey="DistanceTraveled", resultUnit=Unit.Meters, resultDecimals=0, ordinal=0)
|
||||
public Double getDistanceTraveled();
|
||||
|
||||
@Statistic(messageKey="RankGainsOrLosses", resultDecimals=2, ordinal=1)
|
||||
public Double getRankGainsOrLosses();
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.sap.sailing.datamining.impl.components;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedRaceContext;
|
||||
import com.sap.sailing.datamining.impl.data.RaceOfCompetitorWithContext;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sse.datamining.components.Processor;
|
||||
import com.sap.sse.datamining.impl.components.AbstractRetrievalProcessor;
|
||||
|
||||
public class RaceOfCompetitorRetrievalProcessor extends AbstractRetrievalProcessor<HasTrackedRaceContext, HasRaceOfCompetitorContext> {
|
||||
|
||||
public RaceOfCompetitorRetrievalProcessor(ExecutorService executor,
|
||||
Collection<Processor<HasRaceOfCompetitorContext, ?>> resultReceivers, int retrievalLevel) {
|
||||
super(HasTrackedRaceContext.class, HasRaceOfCompetitorContext.class, executor, resultReceivers, retrievalLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<HasRaceOfCompetitorContext> retrieveData(HasTrackedRaceContext element) {
|
||||
Collection<HasRaceOfCompetitorContext> raceOfCompetitorsWithContext = new ArrayList<>();
|
||||
for (Competitor competitor : element.getTrackedRace().getRace().getCompetitors()) {
|
||||
HasRaceOfCompetitorContext raceOfCompetitorWithContext = new RaceOfCompetitorWithContext(element, competitor);
|
||||
raceOfCompetitorsWithContext.add(raceOfCompetitorWithContext);
|
||||
}
|
||||
return raceOfCompetitorsWithContext;
|
||||
}
|
||||
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package com.sap.sailing.datamining.impl.components.aggregators;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import com.sap.sse.datamining.components.AggregationProcessorDefinition;
|
||||
import com.sap.sse.datamining.components.Processor;
|
||||
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
|
||||
import com.sap.sse.datamining.impl.components.SimpleAggregationProcessorDefinition;
|
||||
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelGroupedDataStoringAggregationProcessor;
|
||||
import com.sap.sse.datamining.shared.GroupKey;
|
||||
|
||||
public class ParallelTrueSumAggregationProcessor
|
||||
extends AbstractParallelGroupedDataStoringAggregationProcessor<Boolean, Double> {
|
||||
|
||||
private static final AggregationProcessorDefinition<Boolean, Double> DEFINITION =
|
||||
new SimpleAggregationProcessorDefinition<>(Boolean.class, Double.class, "Sum", ParallelTrueSumAggregationProcessor.class);
|
||||
|
||||
public static AggregationProcessorDefinition<Boolean, Double> getDefinition() {
|
||||
return DEFINITION;
|
||||
}
|
||||
|
||||
private Map<GroupKey, Double> result;
|
||||
|
||||
public ParallelTrueSumAggregationProcessor(ExecutorService executor,
|
||||
Collection<Processor<Map<GroupKey, Double>, ?>> resultReceivers) {
|
||||
super(executor, resultReceivers, "Sum");
|
||||
result = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void storeElement(GroupedDataEntry<Boolean> element) {
|
||||
GroupKey key = element.getKey();
|
||||
if (!result.containsKey(key)) {
|
||||
result.put(key, 0.0);
|
||||
}
|
||||
Double currentAmount = result.get(key);
|
||||
if (element.getDataEntry()) {
|
||||
result.put(key, currentAmount + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<GroupKey, Double> aggregateResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
package com.sap.sailing.datamining.impl.data;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedRaceContext;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Course;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.common.ManeuverType;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext {
|
||||
|
||||
private final HasTrackedRaceContext trackedRaceContext;
|
||||
private final Competitor competitor;
|
||||
|
||||
public RaceOfCompetitorWithContext(HasTrackedRaceContext trackedRaceContext, Competitor competitor) {
|
||||
this.trackedRaceContext = trackedRaceContext;
|
||||
this.competitor = competitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HasTrackedRaceContext getTrackedRaceContext() {
|
||||
return trackedRaceContext;
|
||||
}
|
||||
|
||||
private TrackedRace getTrackedRace() {
|
||||
return getTrackedRaceContext().getTrackedRace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Competitor getCompetitor() {
|
||||
return competitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDistanceToStartLineAtStart() {
|
||||
return getTrackedRace().getDistanceToStartLine(getCompetitor(), 0).getMeters();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Speed getSpeedAtStart() {
|
||||
return getTrackedRace().getSpeed(getCompetitor(), 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Speed getSpeedTenSecondsBeforeStart() {
|
||||
return getTrackedRace().getSpeed(getCompetitor(), TimeUnit.SECONDS.toMillis(10));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getRankAtFirstMark() {
|
||||
Course course = getTrackedRace().getRace().getCourse();
|
||||
Waypoint firstMark = course.getFirstLeg().getTo();
|
||||
Competitor competitor = getCompetitor();
|
||||
return Double.valueOf(getTrackedRace().getRank(competitor, getTrackedRace().getMarkPassing(competitor, firstMark).getTimePoint()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getNumberOfTacks() {
|
||||
return getNumberOf(ManeuverType.TACK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getNumberOfJibes() {
|
||||
return getNumberOf(ManeuverType.JIBE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getNumberOfPenaltyCircles() {
|
||||
return getNumberOf(ManeuverType.PENALTY_CIRCLE);
|
||||
}
|
||||
|
||||
private Double getNumberOf(ManeuverType maneuverType) {
|
||||
TrackedRace trackedRace = getTrackedRace();
|
||||
double number = 0;
|
||||
for (Maneuver maneuver : trackedRace.getManeuvers(getCompetitor(), trackedRace.getStartOfRace(), trackedRace.getEndOfTracking(), false)) {
|
||||
if (maneuver.getType() == maneuverType) {
|
||||
number++;
|
||||
}
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getRankGainsOrLosses() {
|
||||
Double rankAtFirstMark = getRankAtFirstMark();
|
||||
Double rankAtFinish = getRankAtFinish();
|
||||
return rankAtFirstMark - rankAtFinish;
|
||||
}
|
||||
|
||||
private Double getRankAtFinish() {
|
||||
return Double.valueOf(getTrackedRace().getRank(getCompetitor(), getTrackedRace().getEndOfTracking()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getNormalizedDistanceToStarboardSideAtStart() {
|
||||
TrackedRace trackedRace = getTrackedRace();
|
||||
TrackedLegOfCompetitor firstTrackedLegOfCompetitor = trackedRace.getTrackedLeg(competitor, trackedRace.getRace().getCourse().getFirstLeg());
|
||||
TimePoint competitorStartTime = firstTrackedLegOfCompetitor.getStartTime();
|
||||
Double distance = trackedRace.getDistanceFromStarboardSideOfStartLine(getCompetitor(), competitorStartTime).getMeters();
|
||||
Double length = trackedRace.getStartLine(competitorStartTime).getLength().getMeters();
|
||||
return distance / length;
|
||||
}
|
||||
|
||||
}
|
||||
+33
-3
@@ -52,6 +52,10 @@ public class RaceResultOfCompetitorWithContext implements HasRaceResultOfCompeti
|
||||
return leaderboardWithContext;
|
||||
}
|
||||
|
||||
private Leaderboard getLeaderboard() {
|
||||
return getLeaderboardContext().getLeaderboard();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Competitor getCompetitor() {
|
||||
return competitor;
|
||||
@@ -59,8 +63,8 @@ public class RaceResultOfCompetitorWithContext implements HasRaceResultOfCompeti
|
||||
|
||||
@Override
|
||||
public double getRelativeRank() {
|
||||
Leaderboard leaderboard = getLeaderboardContext().getLeaderboard();
|
||||
final MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
Leaderboard leaderboard = getLeaderboard();
|
||||
final TimePoint now = MillisecondsTimePoint.now();
|
||||
double competitorCount = Util.size(leaderboard.getCompetitors());
|
||||
double points = leaderboard.getNetPoints(competitor, raceColumn, now);
|
||||
double relativeLowPoints = leaderboard.getScoringScheme().isHigherBetter() ?
|
||||
@@ -154,9 +158,35 @@ public class RaceResultOfCompetitorWithContext implements HasRaceResultOfCompeti
|
||||
|
||||
@Override
|
||||
public String getRegattaName() {
|
||||
Leaderboard leaderboard = getLeaderboardContext().getLeaderboard();;
|
||||
Leaderboard leaderboard = getLeaderboard();;
|
||||
final String result = leaderboard.getName();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isPodiumFinish() {
|
||||
Leaderboard leaderboard = getLeaderboard();
|
||||
final TimePoint now = MillisecondsTimePoint.now();
|
||||
double points = leaderboard.getNetPoints(competitor, raceColumn, now);
|
||||
if (leaderboard.getScoringScheme().isHigherBetter()) {
|
||||
double competitorCount = Util.size(leaderboard.getCompetitors());
|
||||
return points >= (competitorCount - 2.05);
|
||||
} else {
|
||||
return points <= 3.05;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isWin() {
|
||||
Leaderboard leaderboard = getLeaderboard();
|
||||
final TimePoint now = MillisecondsTimePoint.now();
|
||||
double points = leaderboard.getNetPoints(competitor, raceColumn, now);
|
||||
if (leaderboard.getScoringScheme().isHigherBetter()) {
|
||||
double competitorCount = Util.size(leaderboard.getCompetitors());
|
||||
return points >= (competitorCount - 0.05);
|
||||
} else {
|
||||
return points <= 1.05;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
@@ -4,6 +4,7 @@ import com.sap.sailing.datamining.data.HasTrackedLegContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class TrackedLegOfCompetitorWithContext implements HasTrackedLegOfCompetitorContext {
|
||||
@@ -39,5 +40,13 @@ public class TrackedLegOfCompetitorWithContext implements HasTrackedLegOfCompeti
|
||||
TimePoint timePoint = getTrackedLegContext().getTrackedRaceContext().getTrackedRace().getEndOfTracking();
|
||||
return getTrackedLegOfCompetitor().getDistanceTraveled(timePoint).getMeters();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getRankGainsOrLosses() {
|
||||
TrackedRace trackedRace = getTrackedLegContext().getTrackedRaceContext().getTrackedRace();
|
||||
Double rankAtStart = Double.valueOf(trackedRace.getRank(getCompetitor(), getTrackedLegOfCompetitor().getStartTime()));
|
||||
Double rankAtFinish = Double.valueOf(trackedRace.getRank(getCompetitor(), getTrackedLegOfCompetitor().getFinishTime()));
|
||||
return rankAtStart - rankAtFinish;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ public enum BoatClassMasterdata {
|
||||
J24 ("J/24", true, 7.32, 2.67, BoatHullType.MONOHULL, true, "J24", "J-24"),
|
||||
J70 ("J/70", true, 6.93, 2.25, BoatHullType.MONOHULL, true, "J70", "J-70"),
|
||||
J80 ("J/80", true, 8.0, 2.51, BoatHullType.MONOHULL, true, "J80", "J-80"),
|
||||
KIELZUGVOGEL ("Kielzugvogel", true, 5.80, 1.88, BoatHullType.MONOHULL, false),
|
||||
KIELZUGVOGEL ("Kielzugvogel", true, 5.80, 1.88, BoatHullType.MONOHULL, false, "KZV"),
|
||||
KITE ("Kite", true, 3.35, 1.52, BoatHullType.MONOHULL, false),
|
||||
LASER_2 ("Laser 2", true, 4.39, 1.42, BoatHullType.MONOHULL, false, "Laser II", "Laser2", "Laser-2", "Laser-II"),
|
||||
LASER_4_7 ("Laser 4.7", true, 4.20, 1.39, BoatHullType.MONOHULL, false, "L4.7"),
|
||||
|
||||
-2
@@ -1,8 +1,6 @@
|
||||
package com.sap.sailing.domain.common;
|
||||
|
||||
public interface LeaderboardNameConstants {
|
||||
static final String DEFAULT_LEADERBOARD_NAME = "Default Leaderboard";
|
||||
|
||||
static final String OVERALL = "Overall";
|
||||
|
||||
static final String DEFAULT_FLEET_NAME = "Default";
|
||||
|
||||
-4
@@ -7,10 +7,6 @@ import com.sap.sse.common.Util.Pair;
|
||||
|
||||
public interface PolarSheetsXYDiagramData extends Serializable {
|
||||
|
||||
List<Pair<Double, Double>> getPointsForAverageSpeedMovingAverage(Tack tack, LegType legType);
|
||||
|
||||
List<Pair<Double, Double>> getPointsForAverageConfidence(Tack tack, LegType legType);
|
||||
|
||||
List<Pair<Double, Double>> getPointsForAverageSpeedRegression(Tack tack, LegType legType);
|
||||
|
||||
}
|
||||
|
||||
+1
-19
@@ -14,30 +14,12 @@ public class PolarSheetsXYDiagramDataImpl implements PolarSheetsXYDiagramData {
|
||||
|
||||
PolarSheetsXYDiagramDataImpl() {
|
||||
}
|
||||
|
||||
private Map<Pair<LegType, Tack>, List<Pair<Double, Double>>> pointsForAverageSpeedMovingAverage;
|
||||
|
||||
private Map<Pair<LegType, Tack>, List<Pair<Double, Double>>> pointsForAverageSpeedRegression;
|
||||
|
||||
private Map<Pair<LegType, Tack>, List<Pair<Double, Double>>> pointsForAverageConfidence;
|
||||
|
||||
public PolarSheetsXYDiagramDataImpl(
|
||||
Map<Pair<LegType, Tack>, List<Pair<Double, Double>>> movingAverageSpeedDataLists,
|
||||
Map<Pair<LegType, Tack>, List<Pair<Double, Double>>> regressionSpeedDataLists,
|
||||
Map<Pair<LegType, Tack>, List<Pair<Double, Double>>> averageConfidenceDataLists) {
|
||||
pointsForAverageSpeedMovingAverage = movingAverageSpeedDataLists;
|
||||
Map<Pair<LegType, Tack>, List<Pair<Double, Double>>> regressionSpeedDataLists) {
|
||||
pointsForAverageSpeedRegression = regressionSpeedDataLists;
|
||||
pointsForAverageConfidence = averageConfidenceDataLists;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Pair<Double, Double>> getPointsForAverageSpeedMovingAverage(Tack tack, LegType legType) {
|
||||
return pointsForAverageSpeedMovingAverage.get(new Pair<LegType, Tack>(legType, tack));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Pair<Double, Double>> getPointsForAverageConfidence(Tack tack, LegType legType) {
|
||||
return pointsForAverageConfidence.get(new Pair<LegType, Tack>(legType, tack));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+13
-3
@@ -8,6 +8,7 @@ import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.impl.AbstractSpeedWithAbstractBearingImpl;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFix;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.AbstractTimePoint;
|
||||
|
||||
/**
|
||||
* A compact representation of a GPS fix which collects all primitive-typed attributes in one object to avoid
|
||||
@@ -41,7 +42,7 @@ public class CompactGPSFixImpl extends AbstractGPSFixImpl {
|
||||
|
||||
private final double latDeg;
|
||||
private final double lngDeg;
|
||||
private final TimePoint timePoint;
|
||||
private final long timePointAsMillis;
|
||||
|
||||
/**
|
||||
* Tells if in the containing {@link DynamicGPSFixTrackImpl} this fix is considered valid. This cache
|
||||
@@ -77,6 +78,15 @@ public class CompactGPSFixImpl extends AbstractGPSFixImpl {
|
||||
}
|
||||
}
|
||||
|
||||
private class CompactTimePoint extends AbstractTimePoint implements TimePoint {
|
||||
private static final long serialVersionUID = -2470922642359937437L;
|
||||
|
||||
@Override
|
||||
public long asMillis() {
|
||||
return timePointAsMillis;
|
||||
}
|
||||
}
|
||||
|
||||
private class CompactEstimatedSpeedBearing extends AbstractBearing {
|
||||
private static final long serialVersionUID = 8549231429037883121L;
|
||||
|
||||
@@ -103,7 +113,7 @@ public class CompactGPSFixImpl extends AbstractGPSFixImpl {
|
||||
public CompactGPSFixImpl(Position position, TimePoint timePoint) {
|
||||
latDeg = position.getLatDeg();
|
||||
lngDeg = position.getLngDeg();
|
||||
this.timePoint = timePoint;
|
||||
timePointAsMillis = timePoint==null?-1:timePoint.asMillis();
|
||||
}
|
||||
|
||||
public CompactGPSFixImpl(GPSFix gpsFix) {
|
||||
@@ -122,7 +132,7 @@ public class CompactGPSFixImpl extends AbstractGPSFixImpl {
|
||||
|
||||
@Override
|
||||
public TimePoint getTimePoint() {
|
||||
return timePoint;
|
||||
return new CompactTimePoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.sap.sailing.domain.common.tracking.impl;
|
||||
|
||||
/**
|
||||
* Used to assemble a compatible JSON string by themselves, using the constants from here.The field identified by this
|
||||
* name tells the fully-qualified class name from which the value of the field identified by {@link #FIELD_ID} has been
|
||||
* created. When deserializing, the ID needs to be re-constructed as an instance of that type.
|
||||
*/
|
||||
public class CompetitorJsonConstants {
|
||||
public static final String FIELD_ID = "id";
|
||||
public static final String FIELD_NAME = "name";
|
||||
public static final String FIELD_SAIL_ID = "sailID";
|
||||
public static final String FIELD_NATIONALITY = "nationality";
|
||||
public static final String FIELD_COUNTRY_CODE = "countryCode";
|
||||
public static final String FIELD_BOAT_CLASS_NAME = "boatClassName";
|
||||
public static final String FIELD_COLOR = "color";
|
||||
public static final String FIELD_FLAG_IMAGE = "flagImage";
|
||||
|
||||
public static final String FIELD_ID_TYPE = "idtype";
|
||||
public static final String FIELD_NATIONALITY_ISO2 = "nationalityISO2";
|
||||
public static final String FIELD_NATIONALITY_ISO3 = "nationalityISO3";
|
||||
public static final String FIELD_TEAM = "team";
|
||||
public static final String FIELD_BOAT = "boat";
|
||||
public static final String FIELD_DISPLAY_COLOR = "displayColor";
|
||||
public static final String FIELD_EMAIL = "email";
|
||||
public static final String FIELD_FLAG_IMAGE_URI = "flagImageUri";
|
||||
public static final String FIELD_TIME_ON_TIME_FACTOR = "timeOnTimeFactor";
|
||||
public static final String FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE = "timeOnDistanceAllowanceInSecondsPerNauticalMile";
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.sap.sailing.server.gateway.serialization.impl;
|
||||
package com.sap.sailing.domain.common.tracking.impl;
|
||||
|
||||
/**
|
||||
* So far only holds the constants required to assemble a JSON object properly. The challenge for this serializer is
|
||||
@@ -15,7 +15,8 @@ Require-Bundle: org.json.simple;bundle-version="1.1.0",
|
||||
com.sap.sailing.domain.shared.android,
|
||||
com.sap.sailing.domain,
|
||||
com.sap.sailing.declination,
|
||||
com.sap.sse.common
|
||||
com.sap.sse.common,
|
||||
com.sap.sse
|
||||
Import-Package: javax.ws.rs;version="1.1.1",
|
||||
javax.ws.rs.core;version="1.1.1",
|
||||
javax.ws.rs.ext;version="1.1.1",
|
||||
|
||||
+2
-1
@@ -20,6 +20,7 @@ import com.sap.sailing.domain.igtimiadapter.persistence.DomainObjectFactory;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.MongoObjectFactory;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.PersistenceFactory;
|
||||
import com.sap.sailing.domain.tracking.WindTrackerFactory;
|
||||
import com.sap.sse.util.impl.ThreadFactoryWithPriority;
|
||||
|
||||
/**
|
||||
* Maintains data about a default {@link Client} that represents this application when interacting with the Igtimi
|
||||
@@ -43,7 +44,7 @@ public class Activator implements BundleActivator {
|
||||
private static final String CLIENT_REDIRECT_URI_PROPERTY_NAME = "igtimi.client.redirecturi";
|
||||
private final Future<IgtimiConnectionFactoryImpl> connectionFactory;
|
||||
private final Future<IgtimiWindTrackerFactory> windTrackerFactory;
|
||||
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
private final ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactoryWithPriority(Thread.NORM_PRIORITY, /* daemon */ true));
|
||||
|
||||
public Activator() throws ClientProtocolException, IllegalStateException, IOException, ParseException {
|
||||
logger.info(getClass().getName()+" constructor");
|
||||
|
||||
+2
-2
@@ -97,7 +97,7 @@ public class DependentStartTimeFinderTest {
|
||||
assertEquals(cAfterB, result.getStartTimeDiff());
|
||||
assertEquals(expectedDependingOnRaces, result.getRacesDependingOn());
|
||||
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
raceLogA.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(5000)));
|
||||
|
||||
finder = new StartTimeFinder(raceLogResolver, raceLogB);
|
||||
@@ -156,7 +156,7 @@ public class DependentStartTimeFinderTest {
|
||||
assertEquals(aAfterC, finder.analyze().getStartTimeDiff());
|
||||
|
||||
// Check that all resolve correctly after changing some element in cycle
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
raceLogB.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(5000)));
|
||||
|
||||
// now A -> C -> B
|
||||
|
||||
+3
-3
@@ -102,7 +102,7 @@ public class DependentRaceStateTest {
|
||||
raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12,
|
||||
new SimpleRaceLogIdentifierImpl("A", "", ""), new MillisecondsDurationImpl(5000)));
|
||||
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
raceLogA.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(5000)));
|
||||
|
||||
verify(listenerC, times(3)).onStartTimeChanged(stateC);
|
||||
@@ -124,7 +124,7 @@ public class DependentRaceStateTest {
|
||||
bTime[0] = state.getStartTime();
|
||||
}
|
||||
});
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
raceLogA.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, now));
|
||||
assertEquals(now.plus(delta), bTime[0]);
|
||||
}
|
||||
@@ -137,7 +137,7 @@ public class DependentRaceStateTest {
|
||||
raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12,
|
||||
new SimpleRaceLogIdentifierImpl("A", "", ""), new MillisecondsDurationImpl(5000)));
|
||||
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
raceLogA.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(5000)));
|
||||
|
||||
raceLogB.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(20000)));
|
||||
|
||||
+1
-1
@@ -432,7 +432,7 @@ public class RaceLogTest {
|
||||
RaceLog raceLog = new RaceLogImpl("RaceLogTest", "test-identifier");
|
||||
UUID client1Id = UUID.randomUUID();
|
||||
UUID client2Id = UUID.randomUUID();
|
||||
final MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
final TimePoint now = MillisecondsTimePoint.now();
|
||||
RaceLogStartTimeEvent startTimeEvent1 = RaceLogEventFactory.INSTANCE.createStartTimeEvent(now, author, 1, now.plus(1));
|
||||
Iterable<RaceLogEvent> empty = raceLog.add(startTimeEvent1, client1Id);
|
||||
assertTrue(Util.isEmpty(empty));
|
||||
|
||||
+3
-2
@@ -8,6 +8,7 @@ import java.util.List;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult.ResolutionFailed;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
@@ -31,13 +32,13 @@ public class DependentStartTimeResolver {
|
||||
|
||||
final StartTimeFinderResult result;
|
||||
if (raceLog == null) {
|
||||
result = new StartTimeFinderResult(dependingOnRaces, null, startTimeDifference);
|
||||
result = new StartTimeFinderResult(dependingOnRaces, startTimeDifference, ResolutionFailed.RACE_LOG_UNRESOLVED);
|
||||
} else {
|
||||
List<SimpleRaceLogIdentifier> extendedDependingOnRaces = new ArrayList<>();
|
||||
Util.addAll(dependingOnRaces, extendedDependingOnRaces);
|
||||
extendedDependingOnRaces.add(identifier);
|
||||
if (containsCycle(extendedDependingOnRaces)) {
|
||||
result = new StartTimeFinderResult(extendedDependingOnRaces, null, null);
|
||||
result = new StartTimeFinderResult(extendedDependingOnRaces, null, ResolutionFailed.CYCLIC_DEPENDENCY);
|
||||
} else {
|
||||
StartTimeFinder dependentStartTimeFinder = new StartTimeFinder(raceLogResolver, raceLog);
|
||||
StartTimeFinderResult resultOfDependentRace = dependentStartTimeFinder.analyze(extendedDependingOnRaces);
|
||||
|
||||
+2
-1
@@ -7,6 +7,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult.ResolutionFailed;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class StartTimeFinder extends RaceLogAnalyzer<StartTimeFinderResult> {
|
||||
@@ -35,7 +36,7 @@ public class StartTimeFinder extends RaceLogAnalyzer<StartTimeFinderResult> {
|
||||
return dependentStartTimeResolver.internalResolve((RaceLogDependentStartTimeEvent) event, dependingOnRaces);
|
||||
}
|
||||
}
|
||||
return new StartTimeFinderResult(dependingOnRaces, null, null);
|
||||
return new StartTimeFinderResult(dependingOnRaces, null, null, ResolutionFailed.NO_START_TIME_SET);
|
||||
} finally {
|
||||
log.unlockAfterRead();
|
||||
}
|
||||
|
||||
+25
@@ -8,20 +8,42 @@ import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class StartTimeFinderResult {
|
||||
public static enum ResolutionFailed { RACE_LOG_UNRESOLVED, CYCLIC_DEPENDENCY, NO_START_TIME_SET };
|
||||
|
||||
private final Iterable<SimpleRaceLogIdentifier> racesDependingOn;
|
||||
private final TimePoint startTime;
|
||||
|
||||
/**
|
||||
* <code>null</code> if resolution worked
|
||||
*/
|
||||
private final ResolutionFailed resolutionFailed;
|
||||
|
||||
private Duration startTimeDiff;
|
||||
|
||||
public StartTimeFinderResult(Iterable<SimpleRaceLogIdentifier> racesDependingOn, TimePoint startTime, Duration startTimeDiff) {
|
||||
this(racesDependingOn, startTime, startTimeDiff, /* resolutionFailed */ null);
|
||||
}
|
||||
|
||||
public StartTimeFinderResult(Iterable<SimpleRaceLogIdentifier> racesDependingOn, Duration startTimeDiff, ResolutionFailed resolutionFailed) {
|
||||
this(racesDependingOn, /* startTime */ null, startTimeDiff, resolutionFailed);
|
||||
}
|
||||
|
||||
public StartTimeFinderResult(Iterable<SimpleRaceLogIdentifier> racesDependingOn, TimePoint startTime, Duration startTimeDiff,
|
||||
ResolutionFailed resolutionFailed) {
|
||||
this.startTime = startTime;
|
||||
this.startTimeDiff = startTimeDiff;
|
||||
this.racesDependingOn = racesDependingOn;
|
||||
this.resolutionFailed = resolutionFailed;
|
||||
}
|
||||
|
||||
public StartTimeFinderResult(TimePoint startTime, Duration startTimeDiff) {
|
||||
this(/* racesDependingOn */ Collections.<SimpleRaceLogIdentifier>emptyList(), startTime, startTimeDiff);
|
||||
}
|
||||
|
||||
public ResolutionFailed getResolutionFailed() {
|
||||
return resolutionFailed;
|
||||
}
|
||||
|
||||
public Iterable<SimpleRaceLogIdentifier> getRacesDependingOn() {
|
||||
return racesDependingOn;
|
||||
}
|
||||
@@ -47,6 +69,7 @@ public class StartTimeFinderResult {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((racesDependingOn == null) ? 0 : racesDependingOn.hashCode());
|
||||
result = prime * result + ((resolutionFailed == null) ? 0 : resolutionFailed.hashCode());
|
||||
result = prime * result + ((startTime == null) ? 0 : startTime.hashCode());
|
||||
result = prime * result + ((startTimeDiff == null) ? 0 : startTimeDiff.hashCode());
|
||||
return result;
|
||||
@@ -66,6 +89,8 @@ public class StartTimeFinderResult {
|
||||
return false;
|
||||
} else if (!racesDependingOn.equals(other.racesDependingOn))
|
||||
return false;
|
||||
if (resolutionFailed != other.resolutionFailed)
|
||||
return false;
|
||||
if (startTime == null) {
|
||||
if (other.startTime != null)
|
||||
return false;
|
||||
|
||||
+6
@@ -145,6 +145,12 @@ public class NoAddingRaceLogWrapper implements RaceLog {
|
||||
return innerRaceLog.getFixesIterator(startingAt, inclusive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<RaceLogEvent> getFixesIterator(TimePoint startingAt, boolean startingAtInclusive,
|
||||
TimePoint endingAt, boolean endingAtInclusive) {
|
||||
return innerRaceLog.getFixesIterator(startingAt, startingAtInclusive, endingAt, endingAtInclusive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<RaceLogEvent> getRawFixesIterator(TimePoint startingAt, boolean inclusive) {
|
||||
return innerRaceLog.getRawFixesIterator(startingAt, inclusive);
|
||||
|
||||
+8
@@ -5,6 +5,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventComparator;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.ReadonlyRacingProcedure;
|
||||
@@ -102,6 +103,12 @@ public interface ReadonlyRaceState extends RaceStateEventProcessor {
|
||||
*/
|
||||
TimePoint getStartTime();
|
||||
|
||||
/**
|
||||
* A more comprehensive answer than {@link #getStartTime()} delivers. The result allows callers to
|
||||
* understand, in particular, why a start time is not known yet.
|
||||
*/
|
||||
StartTimeFinderResult getStartTimeFinderResult();
|
||||
|
||||
/**
|
||||
* If there is a finishing time set for the current pass, returns it. Otherwise <code>null</code>.
|
||||
*/
|
||||
@@ -138,4 +145,5 @@ public interface ReadonlyRaceState extends RaceStateEventProcessor {
|
||||
* If wind has been entered, returns the most recent one. Otherwise <code>null</code>.
|
||||
*/
|
||||
Wind getWindFix();
|
||||
|
||||
}
|
||||
|
||||
+5
@@ -308,6 +308,11 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
|
||||
public TimePoint getStartTime() {
|
||||
return cachedStartTimeFinderResult.getStartTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public StartTimeFinderResult getStartTimeFinderResult() {
|
||||
return cachedStartTimeFinderResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimePoint getFinishingTime() {
|
||||
|
||||
+17
-1
@@ -126,7 +126,23 @@ public interface Track<FixType extends Timed> extends Serializable {
|
||||
* will be thrown in case the caller has failed to do so.
|
||||
*/
|
||||
Iterator<FixType> getFixesIterator(TimePoint startingAt, boolean inclusive);
|
||||
|
||||
|
||||
/**
|
||||
* Returns an iterator starting at the first fix after <code>startingAt</code> (or "at or after" in case
|
||||
* <code>inclusive</code> is <code>true</code>) and that ends at the <code>endingAt</code> time point or just before
|
||||
* in case <code>endingAtIncluive</code> is false. The fixes returned by the iterator are the smoothened fixes (see
|
||||
* also {@link #getFixes()}, without any smoothening or dampening applied.
|
||||
*
|
||||
* Callers must have called {@link #lockForRead()} before calling this method. This will be checked, and an
|
||||
* exception will be thrown in case the caller has failed to do so.
|
||||
*
|
||||
* @param startingAt
|
||||
* if <code>null</code>, starts with the first fix available
|
||||
* @param endingAt
|
||||
* if <code>null</code>., ends with the last fix available
|
||||
*/
|
||||
Iterator<FixType> getFixesIterator(TimePoint startingAt, boolean startingAtInclusive, TimePoint endingAt, boolean endingAtInclusive);
|
||||
|
||||
/**
|
||||
* Returns an iterator starting at the first raw fix after <code>startingAt</code> (or "at or after" in case
|
||||
* <code>inclusive</code> is <code>true</code>). The fixes returned by the iterator are the raw fixes (see also
|
||||
|
||||
+16
@@ -259,6 +259,22 @@ public class TrackImpl<FixType extends Timed> implements Track<FixType> {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<FixType> getFixesIterator(TimePoint startingAt, boolean startingAtInclusive, TimePoint endingAt,
|
||||
boolean endingAtInclusive) {
|
||||
assertReadLock();
|
||||
NavigableSet<FixType> set = getInternalFixes();
|
||||
if (startingAt != null && endingAt != null) {
|
||||
set = set.subSet(getDummyFix(startingAt), startingAtInclusive, getDummyFix(endingAt), endingAtInclusive);
|
||||
} else if (endingAt != null) {
|
||||
set = set.headSet(getDummyFix(endingAt), endingAtInclusive);
|
||||
} else if (startingAt != null) {
|
||||
set = set.tailSet(getDummyFix(startingAt), startingAtInclusive);
|
||||
}
|
||||
Iterator<FixType> result = set.iterator();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<FixType> getFixesDescendingIterator(TimePoint startingAt, boolean inclusive) {
|
||||
assertReadLock();
|
||||
|
||||
+3
-4
@@ -336,10 +336,9 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
Regatta regatta = raceIDToRegattaCache.get(raceID);
|
||||
if (regatta != null) {
|
||||
Set<RaceDefinition> toRemove = new HashSet<RaceDefinition>();
|
||||
for (RaceDefinition race : regatta.getAllRaces()) {
|
||||
if (race.getName().equals(raceID)) {
|
||||
toRemove.add(race);
|
||||
}
|
||||
RaceDefinition race = regatta.getRaceByName(raceID);
|
||||
if (race != null) {
|
||||
toRemove.add(race);
|
||||
}
|
||||
for (RaceDefinition raceToRemove : toRemove) {
|
||||
regatta.removeRace(raceToRemove);
|
||||
|
||||
+2
-1
@@ -13,12 +13,13 @@ import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCalculationReuseCache;
|
||||
import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class LeaderboardDTOCalculationReuseCacheTest {
|
||||
@Test
|
||||
public void testNullWindCaching() {
|
||||
final MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
final TimePoint now = MillisecondsTimePoint.now();
|
||||
final LeaderboardDTOCalculationReuseCache cache = new LeaderboardDTOCalculationReuseCache(now);
|
||||
final Competitor competitor = mock(Competitor.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
+2
-1
@@ -25,6 +25,7 @@ import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
|
||||
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
|
||||
import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl;
|
||||
import com.sap.sailing.domain.tractracadapter.ReceiverType;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.tractrac.model.lib.api.event.CreateModelException;
|
||||
@@ -43,7 +44,7 @@ public class LeaderboardForKielWeekTest extends OnlineTracTracBasedTest {
|
||||
public void leaderboardWithOneRaceTest() throws URISyntaxException, NoWindException, IOException, InterruptedException, SubscriberInitializationException, CreateModelException {
|
||||
leaderboard = new FlexibleLeaderboardImpl("Kiel Week 2011 505s", new ThresholdBasedResultDiscardingRuleImpl(new int[] { 3, 6 }),
|
||||
new LowPoint(), null);
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
loadRace("event_20110609_KielerWoch-505_Race_2.txt", "event_20110609_KielerWoch-505_Race_2.mtb"); // 505 Race 2
|
||||
Competitor kevin = getCompetitorByName("Kevin");
|
||||
RaceColumn column = leaderboard.addRace(getTrackedRace(), "Test Race 1", /* medalRace */false);
|
||||
|
||||
+1
-1
@@ -120,7 +120,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest {
|
||||
leaderboard.addRaceColumn(columnName, /* medalRace */ true);
|
||||
leaderboard.addRace(testRaces.iterator().next(), columnName, /* medalRace */false);
|
||||
final Set<String> emptySet = Collections.emptySet();
|
||||
final MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
final TimePoint now = MillisecondsTimePoint.now();
|
||||
final TrackedRegattaRegistry trackedRegattaRegistry = new TrackedRegattaRegistry() {
|
||||
@Override
|
||||
public DynamicTrackedRegatta getOrCreateTrackedRegatta(Regatta regatta) {
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class LineAnalysisTest extends TrackBasedTest {
|
||||
private MillisecondsTimePoint now;
|
||||
private TimePoint now;
|
||||
private DynamicTrackedRace trackedRace;
|
||||
|
||||
@Before
|
||||
|
||||
+62
-1
@@ -34,6 +34,7 @@ import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
|
||||
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
|
||||
import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl;
|
||||
import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.RaceExecutionOrderProvider;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
|
||||
@@ -49,6 +50,7 @@ import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
* was <code>null</code> when {@link RaceColumn} was linked to {@link TrackedRace}.
|
||||
*
|
||||
* @author Alexander Ries (D062114)
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest {
|
||||
@@ -69,7 +71,7 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest
|
||||
private final String RACECOLUMN_FLEXIBLELEADERBOARD = "TestFlexibleLeaderboardRaceColumn";
|
||||
|
||||
@Test
|
||||
public void testRaceExecutionOrderProviderAttachDetachWithRaceCollumn() {
|
||||
public void testRaceExecutionOrderProviderAttachDetachWithRaceColumn() {
|
||||
trackedRace = createTestTrackedRace(REGATTA, RACE, BOATCLASS, Collections.<Competitor> emptyList(),
|
||||
MillisecondsTimePoint.now());
|
||||
flexibleLeaderboard = new FlexibleLeaderboardImpl(FLEXIBLELEADERBOARD,
|
||||
@@ -215,4 +217,63 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest
|
||||
/* startDate */null, /* endDate */null, seriesSet, false, scoringScheme, UUID.randomUUID(), null,
|
||||
OneDesignRankingMetric::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* See bug 3173. When a race is linked more than once to a fleet in a series, the "previous race"
|
||||
* definition's transitive closure may become cyclic, and a race may be considered its own
|
||||
* direct or transitive predecessor. This can lead to endless recursion in the {@link TrackedRace#takesWindFix(Wind)}
|
||||
* implementation which traverses a race's predecessors recursively.
|
||||
*/
|
||||
@Test
|
||||
public void testCyclicPreviousRacesSequence() {
|
||||
createTestSetupWithRegattaAndSeries(/* linkSeriesToRegatta */ true);
|
||||
final RaceColumnInSeries r1 = series.addRaceColumn("R1", /* trackedRegattaRegistry */ null);
|
||||
final RaceColumnInSeries r2 = series.addRaceColumn("R2", /* trackedRegattaRegistry */ null);
|
||||
final RaceColumnInSeries r3 = series.addRaceColumn("R2", /* trackedRegattaRegistry */ null);
|
||||
final RaceColumnInSeries r4 = series.addRaceColumn("R2", /* trackedRegattaRegistry */ null);
|
||||
final TimePoint startOfFirstRace = MillisecondsTimePoint.now();
|
||||
final TimePoint endOfFirstRace = startOfFirstRace.plus(Duration.ONE_MINUTE);
|
||||
final TimePoint startOfSecondRace = endOfFirstRace.plus(Duration.ONE_MINUTE);
|
||||
final TimePoint endOfSecondRace = startOfSecondRace.plus(Duration.ONE_MINUTE);
|
||||
final TimePoint startOfThirdRace = endOfSecondRace.plus(Duration.ONE_MINUTE);
|
||||
final TimePoint endOfThirdRace = startOfThirdRace.plus(Duration.ONE_MINUTE);
|
||||
final TrackedRace tr1 = createTrackedRace("FirstRace", startOfFirstRace, endOfFirstRace);
|
||||
final TrackedRace tr2 = createTrackedRace("SecondRace", startOfSecondRace, endOfSecondRace);
|
||||
final TrackedRace tr3 = createTrackedRace("ThirdRace", startOfThirdRace, endOfThirdRace);
|
||||
r1.setTrackedRace(fleet, tr3);
|
||||
r2.setTrackedRace(fleet, tr1);
|
||||
r3.setTrackedRace(fleet, tr2);
|
||||
r4.setTrackedRace(fleet, tr3); // produce a cycle because now transitively tr1 has itself as a predecessor
|
||||
assertTrue(tr3.takesWindFix(new WindImpl(new DegreePosition(12, 13),
|
||||
startOfThirdRace.minus(TrackedRaceImpl.EXTRA_LONG_TIME_BEFORE_START_TO_TRACK_WIND_MILLIS.divide(2)),
|
||||
new KnotSpeedWithBearingImpl(/* speedInKnots */18, new DegreeBearingImpl(185)))));
|
||||
}
|
||||
|
||||
/**
|
||||
* See bug 3173. When a race is linked more than once to a fleet in a series, the "previous race"
|
||||
* definition's transitive closure may become cyclic, and a race may be considered its own
|
||||
* direct or transitive predecessor. This can lead to endless recursion in the {@link TrackedRace#takesWindFix(Wind)}
|
||||
* implementation which traverses a race's predecessors recursively.
|
||||
*/
|
||||
@Test
|
||||
public void testCyclicPreviousRacesSequenceUsingSingleRace() {
|
||||
createTestSetupWithRegattaAndSeries(/* linkSeriesToRegatta */ true);
|
||||
final RaceColumnInSeries r1 = series.addRaceColumn("R1", /* trackedRegattaRegistry */ null);
|
||||
final RaceColumnInSeries r2 = series.addRaceColumn("R2", /* trackedRegattaRegistry */ null);
|
||||
final TimePoint startOfFirstRace = MillisecondsTimePoint.now();
|
||||
final TimePoint endOfFirstRace = startOfFirstRace.plus(Duration.ONE_MINUTE);
|
||||
final TrackedRace tr1 = createTrackedRace("FirstRace", startOfFirstRace, endOfFirstRace);
|
||||
r1.setTrackedRace(fleet, tr1);
|
||||
r2.setTrackedRace(fleet, tr1);
|
||||
assertTrue(tr1.takesWindFix(new WindImpl(new DegreePosition(12, 13),
|
||||
startOfFirstRace.minus(TrackedRaceImpl.EXTRA_LONG_TIME_BEFORE_START_TO_TRACK_WIND_MILLIS.divide(2)),
|
||||
new KnotSpeedWithBearingImpl(/* speedInKnots */18, new DegreeBearingImpl(185)))));
|
||||
}
|
||||
|
||||
private DynamicTrackedRace createTrackedRace(final String name, final TimePoint startOfRace, final TimePoint endOfRace) {
|
||||
DynamicTrackedRace trackedRace = createTestTrackedRace(REGATTA, name, BOATCLASS, Collections.<Competitor> emptyList(), startOfRace);
|
||||
trackedRace.setStartOfTrackingReceived(startOfRace);
|
||||
trackedRace.setEndOfTrackingReceived(endOfRace);
|
||||
return trackedRace;
|
||||
}
|
||||
}
|
||||
|
||||
+35
@@ -3,7 +3,9 @@ package com.sap.sailing.domain.test;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
@@ -11,12 +13,15 @@ import java.util.Set;
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.Timeout;
|
||||
|
||||
import com.sap.sse.util.SmartFutureCache;
|
||||
import com.sap.sse.util.SmartFutureCache.CacheUpdater;
|
||||
@@ -24,6 +29,8 @@ import com.sap.sse.util.SmartFutureCache.EmptyUpdateInterval;
|
||||
import com.sap.sse.util.SmartFutureCache.UpdateInterval;
|
||||
|
||||
public class SmartFutureCacheTest {
|
||||
@Rule public Timeout AbstractTracTracLiveTestTimeout = new Timeout(2 * 60 * 1000);
|
||||
|
||||
@Test
|
||||
public void testPerformanceOfGetAndCall() {
|
||||
SmartFutureCache<String, String, EmptyUpdateInterval> sfc = new SmartFutureCache<String, String, SmartFutureCache.EmptyUpdateInterval>(
|
||||
@@ -42,6 +49,34 @@ public class SmartFutureCacheTest {
|
||||
}
|
||||
System.out.println("testPerformanceOfGetAndCall took "+(System.currentTimeMillis()-start)+"ms");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExceptionInComputeCacheUpdate() {
|
||||
final boolean[] throwException = new boolean[1];
|
||||
throwException[0] = true;
|
||||
SmartFutureCache<String, String, EmptyUpdateInterval> sfc = new SmartFutureCache<String, String, SmartFutureCache.EmptyUpdateInterval>(
|
||||
new SmartFutureCache.AbstractCacheUpdater<String, String, SmartFutureCache.EmptyUpdateInterval>() {
|
||||
@Override
|
||||
public String computeCacheUpdate(String key, EmptyUpdateInterval updateInterval) {
|
||||
if (throwException[0]) {
|
||||
throw new NullPointerException("Humba");
|
||||
} else {
|
||||
return "Humba";
|
||||
}
|
||||
}
|
||||
}, "SmartFutureCacheTest.testExceptionInComputeCacheUpdate");
|
||||
sfc.triggerUpdate("humba", /* update interval */ null);
|
||||
try {
|
||||
// during the first call, expecting exception
|
||||
sfc.get("humba", /* waitForLatest */ true);
|
||||
fail("Expected RuntimeException because computeCacheUpdate threw one");
|
||||
} catch (RuntimeException expected) {
|
||||
assertSame(ExecutionException.class, expected.getCause().getClass());
|
||||
}
|
||||
throwException[0] = false;
|
||||
sfc.triggerUpdate("humba", /* update interval */ null);
|
||||
assertEquals("Humba", sfc.get("humba", /* waitForLatest */ true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuspendAndResume() {
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class StarbordSideOfStartLineRecognitionTest {
|
||||
private MillisecondsTimePoint now;
|
||||
private TimePoint now;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl;
|
||||
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
|
||||
import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
|
||||
@@ -56,7 +57,7 @@ public class TackTest extends StoredTrackBasedTestWithTrackedRace {
|
||||
@Test
|
||||
public void testStarboardTack() throws NoWindException {
|
||||
DynamicGPSFixTrack<Competitor, GPSFixMoving> hassosTrack = getTrackedRace().getTrack(competitor);
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
hassosTrack.addGPSFix(new GPSFixMovingImpl(new DegreePosition(54.4680424, 10.234451), now,
|
||||
new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(45))));
|
||||
assertEquals(Tack.PORT, getTrackedRace().getTack(competitor, now));
|
||||
@@ -65,7 +66,7 @@ public class TackTest extends StoredTrackBasedTestWithTrackedRace {
|
||||
@Test
|
||||
public void testPortTack() throws NoWindException {
|
||||
DynamicGPSFixTrack<Competitor, GPSFixMoving> hassosTrack = getTrackedRace().getTrack(competitor);
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
hassosTrack.addGPSFix(new GPSFixMovingImpl(new DegreePosition(54.4680424, 10.234451), now,
|
||||
new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(270))));
|
||||
assertEquals(Tack.STARBOARD, getTrackedRace().getTack(competitor, now));
|
||||
@@ -74,7 +75,7 @@ public class TackTest extends StoredTrackBasedTestWithTrackedRace {
|
||||
@Test
|
||||
public void testStarboardTackForZeroDifference() throws NoWindException {
|
||||
DynamicGPSFixTrack<Competitor, GPSFixMoving> hassosTrack = getTrackedRace().getTrack(competitor);
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
hassosTrack.addGPSFix(new GPSFixMovingImpl(new DegreePosition(54.4680424, 10.234451), now,
|
||||
new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(180))));
|
||||
assertEquals(Tack.PORT, getTrackedRace().getTack(competitor, now));
|
||||
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
package com.sap.sailing.domain.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.tractracadapter.TracTracRaceTracker;
|
||||
import com.sap.sailing.domain.tractracadapter.impl.TracTracRaceTrackerImpl;
|
||||
|
||||
/**
|
||||
* See bug 3174: the addition of the "random" element in the params_url around summer 2015 has killed our
|
||||
* comparison of {@link TracTracRaceTracker#getID()} objects. Although two URLs differ in this "random" parameter,
|
||||
* they still refer to the same race.<p>
|
||||
*
|
||||
* This test asserts that two TracTrac race tracker IDs differing only in the "random" URL parameter are still considered
|
||||
* equal.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class TracTracIgnoreRandomInParamsURLTest {
|
||||
@Test
|
||||
public void testEqualRaceTrackerIDsThatOnlyDifferInRandomParam() throws MalformedURLException, URISyntaxException {
|
||||
Object id1 = TracTracRaceTrackerImpl.createID(new URL("http://event.tractrac.com/events/event_20150707_erEuropean/clientparams.php?event=event_20150707_erEuropean&race=777b1420-07c1-0133-0cec-60a44ce903c3&random=769909699"),
|
||||
new URI("tcp://event.tractrac.com:4400"), new URI("tcp://event.tractrac.com:4401"));
|
||||
Object id2 = TracTracRaceTrackerImpl.createID(new URL("http://event.tractrac.com/events/event_20150707_erEuropean/clientparams.php?event=event_20150707_erEuropean&race=777b1420-07c1-0133-0cec-60a44ce903c3&random=1794448899"),
|
||||
new URI("tcp://event.tractrac.com:4400"), new URI("tcp://event.tractrac.com:4401"));
|
||||
assertEquals(id1, id2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualRaceTrackerIDsThatOnlyDifferInRandomParamAndNotLastParameter() throws MalformedURLException, URISyntaxException {
|
||||
Object id1 = TracTracRaceTrackerImpl.createID(new URL("http://event.tractrac.com/events/event_20150707_erEuropean/clientparams.php?event=event_20150707_erEuropean&race=777b1420-07c1-0133-0cec-60a44ce903c3&random=769909699&a=b"),
|
||||
new URI("tcp://event.tractrac.com:4400"), new URI("tcp://event.tractrac.com:4401"));
|
||||
Object id2 = TracTracRaceTrackerImpl.createID(new URL("http://event.tractrac.com/events/event_20150707_erEuropean/clientparams.php?event=event_20150707_erEuropean&race=777b1420-07c1-0133-0cec-60a44ce903c3&random=1794448899&a=b"),
|
||||
new URI("tcp://event.tractrac.com:4400"), new URI("tcp://event.tractrac.com:4401"));
|
||||
assertEquals(id1, id2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualRaceTrackerIDsThatOnlyDifferInRandomParamWithFragment() throws MalformedURLException, URISyntaxException {
|
||||
Object id1 = TracTracRaceTrackerImpl.createID(new URL("http://event.tractrac.com/events/event_20150707_erEuropean/clientparams.php?event=event_20150707_erEuropean&race=777b1420-07c1-0133-0cec-60a44ce903c3&random=769909699&a=b#HumbaHumba"),
|
||||
new URI("tcp://event.tractrac.com:4400"), new URI("tcp://event.tractrac.com:4401"));
|
||||
Object id2 = TracTracRaceTrackerImpl.createID(new URL("http://event.tractrac.com/events/event_20150707_erEuropean/clientparams.php?event=event_20150707_erEuropean&race=777b1420-07c1-0133-0cec-60a44ce903c3&random=1794448899&a=b#HumbaHumba"),
|
||||
new URI("tcp://event.tractrac.com:4400"), new URI("tcp://event.tractrac.com:4401"));
|
||||
assertEquals(id1, id2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualRaceTrackerIDsThatOnlyDifferInRandomParamAndFragment() throws MalformedURLException, URISyntaxException {
|
||||
Object id1 = TracTracRaceTrackerImpl.createID(new URL("http://event.tractrac.com/events/event_20150707_erEuropean/clientparams.php?event=event_20150707_erEuropean&race=777b1420-07c1-0133-0cec-60a44ce903c3&random=769909699&a=b#HumbaTrala"),
|
||||
new URI("tcp://event.tractrac.com:4400"), new URI("tcp://event.tractrac.com:4401"));
|
||||
Object id2 = TracTracRaceTrackerImpl.createID(new URL("http://event.tractrac.com/events/event_20150707_erEuropean/clientparams.php?event=event_20150707_erEuropean&race=777b1420-07c1-0133-0cec-60a44ce903c3&random=1794448899&a=b#HumbaHumba"),
|
||||
new URI("tcp://event.tractrac.com:4400"), new URI("tcp://event.tractrac.com:4401"));
|
||||
assertFalse(id1.equals(id2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualRaceTrackerIDsThatDifferInRaceIDAndRandomParam() throws MalformedURLException, URISyntaxException {
|
||||
Object id1 = TracTracRaceTrackerImpl.createID(new URL("http://event.tractrac.com/events/event_20150707_erEuropean/clientparams.php?event=event_20150707_erEuropean&race=777b1420-07c1-0132-0cec-60a44ce903c3&random=769909699"),
|
||||
new URI("tcp://event.tractrac.com:4400"), new URI("tcp://event.tractrac.com:4401"));
|
||||
Object id2 = TracTracRaceTrackerImpl.createID(new URL("http://event.tractrac.com/events/event_20150707_erEuropean/clientparams.php?event=event_20150707_erEuropean&race=777b1420-07c1-0133-0cec-60a44ce903c3&random=1794448899"),
|
||||
new URI("tcp://event.tractrac.com:4400"), new URI("tcp://event.tractrac.com:4401"));
|
||||
assertFalse(id1.equals(id2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualRaceTrackerIDsThatDifferInLiveURI() throws MalformedURLException, URISyntaxException {
|
||||
Object id1 = TracTracRaceTrackerImpl.createID(new URL("http://event.tractrac.com/events/event_20150707_erEuropean/clientparams.php?event=event_20150707_erEuropean&race=777b1420-07c1-0132-0cec-60a44ce903c3&random=769909699"),
|
||||
new URI("tcp://event.tractrac.com:4400"), new URI("tcp://event.tractrac.com:4401"));
|
||||
Object id2 = TracTracRaceTrackerImpl.createID(new URL("http://event.tractrac.com/events/event_20150707_erEuropean/clientparams.php?event=event_20150707_erEuropean&race=777b1420-07c1-0132-0cec-60a44ce903c3&random=769909699"),
|
||||
new URI("tcp://event.tractrac.com:4412"), new URI("tcp://event.tractrac.com:4413"));
|
||||
assertFalse(id1.equals(id2));
|
||||
}
|
||||
}
|
||||
@@ -758,7 +758,7 @@ public class TrackTest {
|
||||
Bearing bearing = new DegreeBearingImpl(123);
|
||||
Speed speed = new KnotSpeedImpl(7);
|
||||
Position p = new DegreePosition(0, 0);
|
||||
final MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
final TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint start = now;
|
||||
final int steps = 10;
|
||||
TimePoint next = null;
|
||||
@@ -858,7 +858,7 @@ public class TrackTest {
|
||||
Bearing bearing = new DegreeBearingImpl(123);
|
||||
Speed speed = new KnotSpeedImpl(7);
|
||||
Position p = new DegreePosition(0, 0);
|
||||
final MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
final TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint start = now;
|
||||
final int steps = 10;
|
||||
TimePoint next = null;
|
||||
@@ -916,7 +916,7 @@ public class TrackTest {
|
||||
Bearing bearing = new DegreeBearingImpl(123);
|
||||
Speed speed = new KnotSpeedImpl(7);
|
||||
Position p = new DegreePosition(0, 0);
|
||||
final MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
final TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint start = now;
|
||||
final int steps = 10;
|
||||
TimePoint next = null;
|
||||
|
||||
+2
-2
@@ -67,7 +67,7 @@ public class TrackedRaceCenterTest {
|
||||
|
||||
@Test
|
||||
public void testSimpleAverage() {
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
Position mark1Pos = new DegreePosition(10, 10);
|
||||
mark1Track.add(new GPSFixImpl(mark1Pos, now));
|
||||
Position mark2Pos = new DegreePosition(20, 10);
|
||||
@@ -85,7 +85,7 @@ public class TrackedRaceCenterTest {
|
||||
DynamicGPSFixTrackImpl<Mark> mark3Track = new DynamicGPSFixTrackImpl<Mark>(mark3, /* millisecondsOverWhichToAverage */ 10);
|
||||
when(trackedRace.getOrCreateTrack(mark3)).thenReturn(mark3Track);
|
||||
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
Position mark1Pos = new DegreePosition(0, 0);
|
||||
mark1Track.add(new GPSFixImpl(mark1Pos, now));
|
||||
Position mark2Pos = new DegreePosition(0, 10);
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ public class WindEstimationLockingUnderLoadTest {
|
||||
} else {
|
||||
double directionInDegrees = 360*Math.random();
|
||||
double confidence = Math.random();
|
||||
final MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
final TimePoint now = MillisecondsTimePoint.now();
|
||||
result = new WindWithConfidenceImpl<TimePoint>(new WindImpl(new DegreePosition(49, 8), now, new KnotSpeedWithBearingImpl(speedInKnots, new DegreeBearingImpl(directionInDegrees))),
|
||||
confidence, now, /* useSpeed */ true);
|
||||
}
|
||||
|
||||
+8
-8
@@ -137,7 +137,7 @@ public class WindEstimationOnConstructedTracksTest extends StoredTrackBasedTest
|
||||
@Test
|
||||
public void testCombinedWindTrack() throws NoWindException {
|
||||
initRace(4, new int[] { 1, 1, 2, 2 }, new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23).getTime()));
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
setBearingForCompetitor(competitors.get(0), now, 315);
|
||||
setBearingForCompetitor(competitors.get(1), now, 45); // on the same tack, should give no read-out
|
||||
setBearingForCompetitor(competitors.get(2), now, 135);
|
||||
@@ -253,7 +253,7 @@ public class WindEstimationOnConstructedTracksTest extends StoredTrackBasedTest
|
||||
@Test
|
||||
public void testWindEstimationForSimpleTracks() throws NoWindException {
|
||||
initRace(2, new int[] { 1, 1 }, new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23).getTime()));
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
setBearingForCompetitor(competitors.get(0), now, 320);
|
||||
setBearingForCompetitor(competitors.get(1), now, 50);
|
||||
Wind estimatedWindDirection = getTrackedRace().getEstimatedWindDirection(now);
|
||||
@@ -263,7 +263,7 @@ public class WindEstimationOnConstructedTracksTest extends StoredTrackBasedTest
|
||||
@Test
|
||||
public void testWindEstimationForSimpleTracksWithOneAncientFixToBeSuppressedByLowConfidence() throws NoWindException {
|
||||
initRace(3, new int[] { 1, 1, 1 }, new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23).getTime()));
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
setBearingForCompetitor(competitors.get(0), now, 320);
|
||||
setBearingForCompetitor(competitors.get(1), now, 50);
|
||||
setBearingForCompetitor(competitors.get(2), new MillisecondsTimePoint(0), 100); // this shouldn't disturb the estimation because it's too old
|
||||
@@ -275,7 +275,7 @@ public class WindEstimationOnConstructedTracksTest extends StoredTrackBasedTest
|
||||
public void testWindEstimationForSimpleTracksWithOneFixNearMarkPassingToBeSuppressedByLowConfidence() throws NoWindException {
|
||||
TimePoint markPassingTimePoint = new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23).getTime());
|
||||
initRace(3, new int[] { 1, 1, 1 }, markPassingTimePoint);
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
setBearingForCompetitor(competitors.get(0), now, 320);
|
||||
setBearingForCompetitor(competitors.get(1), now, 50);
|
||||
setBearingForCompetitor(competitors.get(2), markPassingTimePoint, 100); // this shouldn't disturb the estimation because it's too old
|
||||
@@ -286,7 +286,7 @@ public class WindEstimationOnConstructedTracksTest extends StoredTrackBasedTest
|
||||
@Test
|
||||
public void testWindEstimationForTwoBoatsOnSameTack() throws NoWindException {
|
||||
initRace(2, new int[] { 1, 1 }, new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23).getTime()));
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
setBearingForCompetitor(competitors.get(0), now, 320);
|
||||
setBearingForCompetitor(competitors.get(1), now, 330); // on the same tack, should give no read-out
|
||||
Wind nullWind = getTrackedRace().getEstimatedWindDirection(now);
|
||||
@@ -298,7 +298,7 @@ public class WindEstimationOnConstructedTracksTest extends StoredTrackBasedTest
|
||||
@Test
|
||||
public void testWindEstimationForFourBoatsOnSameTack() throws NoWindException {
|
||||
initRace(4, new int[] { 1, 1, 2, 2 }, new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23).getTime()));
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
setBearingForCompetitor(competitors.get(0), now, 320);
|
||||
setBearingForCompetitor(competitors.get(1), now, 330); // on the same tack, should give no read-out
|
||||
setBearingForCompetitor(competitors.get(2), now, 135);
|
||||
@@ -312,7 +312,7 @@ public class WindEstimationOnConstructedTracksTest extends StoredTrackBasedTest
|
||||
@Test
|
||||
public void testWindEstimationForFourBoatsWithUpwindOnSameTack() throws NoWindException {
|
||||
initRace(4, new int[] { 1, 1, 2, 2 }, new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23).getTime()));
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
setBearingForCompetitor(competitors.get(0), now, 320);
|
||||
setBearingForCompetitor(competitors.get(1), now, 330); // on the same tack, should give no read-out
|
||||
setBearingForCompetitor(competitors.get(2), now, 135);
|
||||
@@ -324,7 +324,7 @@ public class WindEstimationOnConstructedTracksTest extends StoredTrackBasedTest
|
||||
@Test
|
||||
public void testWindEstimationForFourBoats() throws NoWindException {
|
||||
initRace(4, new int[] { 1, 1, 2, 2 }, new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23).getTime()));
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
setBearingForCompetitor(competitors.get(0), now, 315);
|
||||
setBearingForCompetitor(competitors.get(1), now, 45); // on the same tack, should give no read-out
|
||||
setBearingForCompetitor(competitors.get(2), now, 135);
|
||||
|
||||
-9
@@ -1,15 +1,6 @@
|
||||
package com.sap.sailing.domain.tractracadapter;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
|
||||
import com.sap.sailing.domain.tracking.RaceTracker;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public interface TracTracRaceTracker extends RaceTracker {
|
||||
/**
|
||||
* returns the paramURL, liveURI and storedURI for the TracTrac connection maintained by this tracker
|
||||
*/
|
||||
Util.Triple<URL, URI, URI> getID();
|
||||
|
||||
}
|
||||
|
||||
+11
-10
@@ -16,6 +16,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -122,7 +123,7 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
* Maps from the TracTrac race UUIDs to the domain model's {@link RaceDefinition} objects that represent the race
|
||||
* identified by that UUID
|
||||
*/
|
||||
private final Map<UUID, RaceDefinition> raceCache = new HashMap<>();
|
||||
private final ConcurrentHashMap<UUID, RaceDefinition> raceCache = new ConcurrentHashMap<>();
|
||||
|
||||
private final MetadataParser metadataParser;
|
||||
|
||||
@@ -328,11 +329,11 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
@Override
|
||||
public RaceDefinition getAndWaitForRaceDefinition(UUID raceId, long timeoutInMilliseconds) {
|
||||
long start = System.currentTimeMillis();
|
||||
synchronized (raceCache) {
|
||||
RaceDefinition result = raceCache.get(raceId);
|
||||
boolean interrupted = false;
|
||||
while ((timeoutInMilliseconds == -1 || System.currentTimeMillis()-start < timeoutInMilliseconds) && !interrupted && result == null) {
|
||||
try {
|
||||
RaceDefinition result = raceCache.get(raceId);
|
||||
boolean interrupted = false;
|
||||
while ((timeoutInMilliseconds == -1 || System.currentTimeMillis()-start < timeoutInMilliseconds) && !interrupted && result == null) {
|
||||
try {
|
||||
synchronized (raceCache) {
|
||||
if (timeoutInMilliseconds == -1) {
|
||||
raceCache.wait();
|
||||
} else {
|
||||
@@ -341,13 +342,13 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
raceCache.wait(timeToWait);
|
||||
}
|
||||
}
|
||||
result = raceCache.get(raceId);
|
||||
} catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
}
|
||||
result = raceCache.get(raceId);
|
||||
} catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -84,7 +84,7 @@ public class RaceTrackingConnectivityParametersImpl implements RaceTrackingConne
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.sap.sse.common.Util.Triple<URL, URI, URI> getTrackerID() {
|
||||
public Object getTrackerID() {
|
||||
return TracTracRaceTrackerImpl.createID(paramURL, liveURI, storedURI);
|
||||
}
|
||||
|
||||
|
||||
+46
-9
@@ -12,7 +12,9 @@ import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
@@ -194,12 +196,12 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
|
||||
private final Set<RaceDefinition> races;
|
||||
private final DynamicTrackedRegatta trackedRegatta;
|
||||
private TrackedRaceStatus lastStatus;
|
||||
private HashMap<Util.Triple<URL, URI, URI>, Util.Pair<Integer, Float>> lastProgressPerID;
|
||||
private Map<Object, Util.Pair<Integer, Float>> lastProgressPerID;
|
||||
|
||||
/**
|
||||
* paramURL, liveURI and storedURI for TracTrac connection
|
||||
* paramURL, liveURI and storedURI for TracTrac connection, voided of "random" part
|
||||
*/
|
||||
private final Util.Triple<URL, URI, URI> urls;
|
||||
private final Object id;
|
||||
|
||||
/**
|
||||
* Tells if this tracker was created with a valid live URI. If not, the tracker will stop and unregister itself
|
||||
@@ -315,12 +317,12 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
|
||||
this.trackedRegattaRegistry = trackedRegattaRegistry;
|
||||
this.tractracRace = tractracRace;
|
||||
this.tractracEvent = tractracRace.getEvent();
|
||||
urls = createID(paramURL, liveURI, storedURI);
|
||||
this.id = createID(paramURL, liveURI, storedURI);
|
||||
isLiveTracking = liveURI != null;
|
||||
this.races = new HashSet<RaceDefinition>();
|
||||
this.gpsFixStore = gpsFixStore;
|
||||
this.domainFactory = domainFactory;
|
||||
this.lastProgressPerID = new HashMap<Util.Triple<URL, URI, URI>, Util.Pair<Integer, Float>>();
|
||||
this.lastProgressPerID = new HashMap<>();
|
||||
if (simulateWithStartTimeNow) {
|
||||
simulator = new Simulator(windStore);
|
||||
// don't write the transformed wind fixes into the DB again... see also bug 1974
|
||||
@@ -461,13 +463,48 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
|
||||
return trackedRegatta;
|
||||
}
|
||||
|
||||
static Util.Triple<URL, URI, URI> createID(URL paramURL, URI liveURI, URI storedURI) {
|
||||
return new Util.Triple<URL, URI, URI>(paramURL, liveURI, storedURI);
|
||||
public static Object createID(URL paramURL, URI liveURI, URI storedURI) {
|
||||
URL paramURLStrippedOfRandomParam;
|
||||
if (paramURL == null) {
|
||||
paramURLStrippedOfRandomParam = null;
|
||||
} else {
|
||||
final String query = paramURL.getQuery();
|
||||
if (query == null) {
|
||||
paramURLStrippedOfRandomParam = paramURL;
|
||||
} else {
|
||||
final StringJoiner stringJoiner = new StringJoiner("&", "?", "");
|
||||
stringJoiner.setEmptyValue("");
|
||||
String[] queryParams = query.split("&");
|
||||
for (String queryParam : queryParams) {
|
||||
String[] nameValue = queryParam.split("=");
|
||||
if (!"random".equalsIgnoreCase(nameValue[0])) {
|
||||
final StringBuilder param = new StringBuilder();
|
||||
param.append(nameValue[0]);
|
||||
if (nameValue.length > 1) {
|
||||
param.append('=');
|
||||
param.append(nameValue[1]);
|
||||
}
|
||||
stringJoiner.add(param.toString());
|
||||
}
|
||||
}
|
||||
try {
|
||||
paramURLStrippedOfRandomParam = new URL(paramURL.getProtocol(), paramURL.getHost(), paramURL.getPort(),
|
||||
paramURL.getPath()+stringJoiner.toString()+(paramURL.getRef() == null || paramURL.getRef().isEmpty() ?
|
||||
"" : ("#"+paramURL.getRef())));
|
||||
} catch (MalformedURLException e) {
|
||||
// this is pretty strange as we only removed one parameter; log and continue with original URL as a default
|
||||
logger.log(Level.SEVERE, "Error trying to strip the \"random\" parameter from the TracTrac params_url "+
|
||||
paramURL, e);
|
||||
paramURLStrippedOfRandomParam = paramURL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Util.Triple<URL, URI, URI>(paramURLStrippedOfRandomParam, liveURI, storedURI);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Util.Triple<URL, URI, URI> getID() {
|
||||
return urls;
|
||||
public Object getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
@@ -5,6 +5,7 @@ import java.io.ObjectInputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
@@ -20,6 +21,8 @@ import com.sap.sse.common.Util;
|
||||
|
||||
public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implements RaceColumn {
|
||||
private static final long serialVersionUID = -7801617988982540470L;
|
||||
|
||||
private static final Logger logger = Logger.getLogger(AbstractRaceColumn.class.getName());
|
||||
|
||||
private TrackedRaces trackedRaces;
|
||||
private Map<Fleet, RaceIdentifier> raceIdentifiers;
|
||||
@@ -70,6 +73,8 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
|
||||
if (trackedRace != null) {
|
||||
this.trackedRaces.put(fleet, trackedRace);
|
||||
this.setRaceIdentifier(fleet, trackedRace.getRaceIdentifier());
|
||||
logger.info(String.format("Linked race column %s with tracked race %s.", this.getName(),
|
||||
trackedRace.getRace() == null ? "null" : trackedRace.getRace().getName()));
|
||||
}
|
||||
}
|
||||
if (trackedRace != null) {
|
||||
|
||||
@@ -6,11 +6,14 @@ import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
@@ -77,7 +80,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
|
||||
private static final Logger logger = Logger.getLogger(RegattaImpl.class.getName());
|
||||
private static final long serialVersionUID = 6509564189552478869L;
|
||||
private Set<RaceDefinition> races;
|
||||
private ConcurrentHashMap<String, RaceDefinition> races;
|
||||
private final BoatClass boatClass;
|
||||
private transient Set<RegattaListener> regattaListeners;
|
||||
private List<? extends Series> series;
|
||||
@@ -178,7 +181,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
this.useStartTimeInference = useStartTimeInference;
|
||||
this.id = id;
|
||||
this.raceLogStore = raceLogStore;
|
||||
races = new HashSet<RaceDefinition>();
|
||||
races = new ConcurrentHashMap<>();
|
||||
regattaListeners = new HashSet<RegattaListener>();
|
||||
raceColumnListeners = new RaceColumnListeners();
|
||||
this.boatClass = boatClass;
|
||||
@@ -256,7 +259,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
MasterDataImportInformation masterDataImportInformation = ongoingMasterDataImportInformation.get();
|
||||
if (masterDataImportInformation != null) {
|
||||
raceLogStore = masterDataImportInformation.getRaceLogStore();
|
||||
races = new HashSet<RaceDefinition>();
|
||||
races = new ConcurrentHashMap<>();
|
||||
} else {
|
||||
raceLogStore = EmptyRaceLogStore.INSTANCE;
|
||||
}
|
||||
@@ -309,9 +312,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
|
||||
@Override
|
||||
public Iterable<RaceDefinition> getAllRaces() {
|
||||
synchronized (races) {
|
||||
return new ArrayList<RaceDefinition>(races);
|
||||
}
|
||||
return races.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -326,12 +327,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
|
||||
@Override
|
||||
public RaceDefinition getRaceByName(String raceName) {
|
||||
for (RaceDefinition r : getAllRaces()) {
|
||||
if (r.getName().equals(raceName)) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return races.get(raceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -340,9 +336,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
if (getBoatClass() != null && race.getBoatClass() != getBoatClass()) {
|
||||
throw new IllegalArgumentException("Boat class "+race.getBoatClass()+" doesn't match regatta's boat class "+getBoatClass());
|
||||
}
|
||||
synchronized (races) {
|
||||
races.add(race);
|
||||
}
|
||||
races.put(race.getName(), race);
|
||||
synchronized (regattaListeners) {
|
||||
for (RegattaListener l : regattaListeners) {
|
||||
l.raceAdded(this, race);
|
||||
@@ -352,10 +346,8 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
|
||||
@Override
|
||||
public void removeRace(RaceDefinition race) {
|
||||
synchronized (races) {
|
||||
logger.info("Removing race "+race.getName()+" from regatta "+getName()+" ("+hashCode()+")");
|
||||
races.remove(race);
|
||||
}
|
||||
logger.info("Removing race "+race.getName()+" from regatta "+getName()+" ("+hashCode()+")");
|
||||
races.remove(race.getName());
|
||||
synchronized (regattaListeners) {
|
||||
for (RegattaListener l : regattaListeners) {
|
||||
l.raceRemoved(this, race);
|
||||
@@ -678,15 +670,27 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
final Map<Fleet, Iterable<? extends RaceColumn>> result = new HashMap<>();
|
||||
final Iterable<? extends Series> mySeries = getSeries();
|
||||
if (mySeries != null) {
|
||||
for (Series currentSeries : mySeries) {
|
||||
if (currentSeries.getFleets() != null) {
|
||||
for (Fleet fleet : currentSeries.getFleets()) {
|
||||
if (currentSeries.getRaceColumns() != null) {
|
||||
result.put(fleet, currentSeries.getRaceColumns());
|
||||
boolean concurrentlyModified = false;
|
||||
do {
|
||||
try {
|
||||
for (Series currentSeries : mySeries) {
|
||||
if (currentSeries.getFleets() != null) {
|
||||
for (Fleet fleet : currentSeries.getFleets()) {
|
||||
if (currentSeries.getRaceColumns() != null) {
|
||||
result.put(fleet, currentSeries.getRaceColumns());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ConcurrentModificationException e) {
|
||||
// getSeries() returns a live collection, and Series.getRaceColumns() does so, too.
|
||||
// In the unlikely event of a modification is applied to either of these structures while iterating, an exception
|
||||
// will be thrown. We catch and log it here and try again.
|
||||
logger.log(Level.INFO,
|
||||
"Got a ConcurrentModificationException while trying to update the RaceExecutionOrderCache", e);
|
||||
concurrentlyModified = true;
|
||||
}
|
||||
}
|
||||
} while (concurrentlyModified);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@ public class LeaderboardDTOCache implements LeaderboardCache {
|
||||
private static final Executor computeLeadearboardByNameExecutor = new ThreadPoolExecutor(/* corePoolSize */ THREAD_POOL_SIZE,
|
||||
/* maximumPoolSize */ THREAD_POOL_SIZE,
|
||||
/* keepAliveTime */ 60, TimeUnit.SECONDS,
|
||||
/* workQueue */ new LinkedBlockingQueue<Runnable>(), new ThreadFactoryWithPriority(Thread.NORM_PRIORITY-1));
|
||||
/* workQueue */ new LinkedBlockingQueue<Runnable>(), new ThreadFactoryWithPriority(Thread.NORM_PRIORITY-1, /* daemon */ true));
|
||||
|
||||
private final LeaderboardCacheManager leaderboardCacheManager;
|
||||
|
||||
|
||||
+1
-1
@@ -279,7 +279,7 @@ public class LiveLeaderboardUpdater implements Runnable {
|
||||
+ leaderboard.getName());
|
||||
// interrupt the current thread if not producing a single result within the overall timeout
|
||||
while (true) {
|
||||
MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
final Long delayToLiveInMillis = getLeaderboard().getDelayToLiveInMillis();
|
||||
TimePoint timePoint = delayToLiveInMillis == null ? now : now.minus(delayToLiveInMillis);
|
||||
synchronized (this) {
|
||||
|
||||
+2
-2
@@ -341,7 +341,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
|
||||
executor = new ThreadPoolExecutor(/* corePoolSize */ THREAD_POOL_SIZE,
|
||||
/* maximumPoolSize */ THREAD_POOL_SIZE,
|
||||
/* keepAliveTime */ 60, TimeUnit.SECONDS,
|
||||
/* workQueue */ new LinkedBlockingQueue<Runnable>(), new ThreadFactoryWithPriority(Thread.NORM_PRIORITY-1));
|
||||
/* workQueue */ new LinkedBlockingQueue<Runnable>(), new ThreadFactoryWithPriority(Thread.NORM_PRIORITY-1, /* daemon */ true));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1148,7 +1148,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
|
||||
|
||||
@Override
|
||||
public TimePoint getNowMinusDelay() {
|
||||
final MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
final TimePoint now = MillisecondsTimePoint.now();
|
||||
final Long delayToLiveInMillis = getDelayToLiveInMillis();
|
||||
TimePoint timePoint = delayToLiveInMillis == null ? now : now.minus(delayToLiveInMillis);
|
||||
return timePoint;
|
||||
|
||||
+1
-1
@@ -145,7 +145,7 @@ public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements
|
||||
private FlexibleRaceColumn addRaceColumn(String name, boolean medalRace, boolean logAlreadyExistingColumn) {
|
||||
FlexibleRaceColumn column = getRaceColumnByName(name);
|
||||
if (column != null) {
|
||||
final String msg = "Trying to create race column with duplicate name "+name+" in leaderboard +"+getName();
|
||||
final String msg = "Trying to create race column with duplicate name "+name+" in leaderboard "+getName();
|
||||
logger.severe(msg);
|
||||
} else {
|
||||
column = createRaceColumn(name, medalRace);
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ public class MarkPassingCalculator {
|
||||
.getRuntime().availableProcessors() - 1, 3),
|
||||
/* maximumPoolSize */Math.max(Runtime.getRuntime().availableProcessors() - 1, 3),
|
||||
/* keepAliveTime */60, TimeUnit.SECONDS,
|
||||
/* workQueue */new LinkedBlockingQueue<Runnable>(), new ThreadFactoryWithPriority(Thread.NORM_PRIORITY - 1));
|
||||
/* workQueue */new LinkedBlockingQueue<Runnable>(), new ThreadFactoryWithPriority(Thread.NORM_PRIORITY - 1, /* daemon */ true));
|
||||
|
||||
private boolean suspended = false;
|
||||
|
||||
|
||||
+9
-1
@@ -23,6 +23,8 @@ import com.sap.sailing.domain.base.Event;
|
||||
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.configuration.DeviceConfiguration;
|
||||
import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher;
|
||||
import com.sap.sailing.domain.common.RaceIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaIdentifier;
|
||||
@@ -62,10 +64,11 @@ public class TopLevelMasterData implements Serializable {
|
||||
private final Set<WindTrackMasterData> windTrackMasterData;
|
||||
private final Map<LeaderboardGroup, Set<Event>> eventForLeaderboardGroup;
|
||||
private final Map<DeviceIdentifier, Set<GPSFix>> raceLogTrackingFixes;
|
||||
private final Map<DeviceConfigurationMatcher, DeviceConfiguration> deviceConfigurations;
|
||||
|
||||
public TopLevelMasterData(final Set<LeaderboardGroup> groupsToExport, final Iterable<Event> allEvents,
|
||||
final Map<String, Regatta> regattaForRaceIdString, final Collection<MediaTrack> allMediaTracks,
|
||||
GPSFixStore gpsFixStore, boolean exportWind) {
|
||||
GPSFixStore gpsFixStore, boolean exportWind, Map<DeviceConfigurationMatcher, DeviceConfiguration> deviceConfigurations) {
|
||||
this.raceIdStringsForRegatta = convertToRaceIdStringsForRegattaMap(regattaForRaceIdString);
|
||||
this.leaderboardGroups = groupsToExport;
|
||||
this.raceLogTrackingFixes = getAllRelevantRaceLogTrackingFixes(gpsFixStore);
|
||||
@@ -74,6 +77,7 @@ public class TopLevelMasterData implements Serializable {
|
||||
} else {
|
||||
this.windTrackMasterData = new HashSet<WindTrackMasterData>();
|
||||
}
|
||||
this.deviceConfigurations = deviceConfigurations;
|
||||
this.eventForLeaderboardGroup = createEventMap(groupsToExport, allEvents);
|
||||
this.filteredMediaTracks = new HashSet<MediaTrack>();
|
||||
filterMediaTracks(allMediaTracks, this.filteredMediaTracks);
|
||||
@@ -344,4 +348,8 @@ public class TopLevelMasterData implements Serializable {
|
||||
public Map<DeviceIdentifier, Set<GPSFix>> getRaceLogTrackingFixes() {
|
||||
return raceLogTrackingFixes;
|
||||
}
|
||||
|
||||
public Map<DeviceConfigurationMatcher, DeviceConfiguration> getDeviceConfigurations() {
|
||||
return deviceConfigurations;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-30
@@ -8,6 +8,7 @@ import org.apache.commons.math.analysis.polynomials.PolynomialFunction;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
import com.sap.sailing.domain.base.SpeedWithBearingWithConfidence;
|
||||
import com.sap.sailing.domain.base.SpeedWithConfidence;
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
@@ -51,36 +52,6 @@ public interface PolarDataService {
|
||||
SpeedWithConfidence<Void> getSpeed(BoatClass boatClass, Speed windSpeed, Bearing trueWindAngle)
|
||||
throws NotEnoughDataHasBeenAddedException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param boatClass
|
||||
* @param windSpeed
|
||||
* @param legType
|
||||
* Should be {@link LegType#UPWIND} or {@link LegType#DOWNWIND}, there is no information for other
|
||||
* courses yet. Use getSpeed for the desired angle to get rawer information on other courses for now.
|
||||
* @param tack
|
||||
* Polar data can vary depending on the tack the boat is on.
|
||||
* @param useRegressionForSpeed TODO
|
||||
* @return The estimated average speed of a boat for the supplied parameters with the estimated average bearing to
|
||||
* the true wind and a confidence which consists of the confidences of the wind speed, and boat speed sources (50%)
|
||||
* and a confidence calculated using the amount of underlying fixes (50%). 0 <= confidence < 1<br/>
|
||||
* A value with zero confidence doesn't have any significance!<br/>
|
||||
* <br/>
|
||||
*
|
||||
* The bearing is somewhere between -179 to +180<br/>
|
||||
* <br/>
|
||||
*
|
||||
* Get the speed using returnValue.getObject()<br/>
|
||||
* <br/>
|
||||
*
|
||||
* Returns null if the leg type is not up or downwind.
|
||||
*
|
||||
* @throws NotEnoughDataHasBeenAddedException
|
||||
* If there is not enough data to supply a value with some kind of significance.
|
||||
*/
|
||||
SpeedWithBearingWithConfidence<Void> getAverageSpeedWithBearing(BoatClass boatClass, Speed windSpeed,
|
||||
LegType legType, Tack tack, boolean useRegressionForSpeed) throws NotEnoughDataHasBeenAddedException;
|
||||
|
||||
|
||||
/**
|
||||
* Generates a polar sheet for given races and settings using the provided executor for the worker threads. This
|
||||
@@ -242,5 +213,9 @@ public interface PolarDataService {
|
||||
*/
|
||||
void unregisterListener(BoatClass boatClass, PolarsChangedListener listener);
|
||||
|
||||
void registerDomainFactory(DomainFactory domainFactory);
|
||||
|
||||
void unregisterDomainFactory(DomainFactory domainFactory);
|
||||
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -471,7 +471,7 @@ public abstract class AbstractRankingMetric implements RankingMetric {
|
||||
* started at <code>timePoint</code> yet, or <code>who</code>'s tracked leg for the last leg if <code>who</code> has
|
||||
* already finished the race at <code>timePoint</code>.
|
||||
*/
|
||||
private TrackedLegOfCompetitor getCurrentLegOrLastLegIfAlreadyFinished(Competitor who, TimePoint timePoint) {
|
||||
protected TrackedLegOfCompetitor getCurrentLegOrLastLegIfAlreadyFinished(Competitor who, TimePoint timePoint) {
|
||||
TrackedLegOfCompetitor currentLegWho = getTrackedRace().getCurrentLeg(who, timePoint);
|
||||
if (currentLegWho == null) { // already finished or not yet started; if already finished, use last leg
|
||||
final Waypoint lastWaypoint = getTrackedRace().getRace().getCourse().getLastWaypoint();
|
||||
|
||||
+60
-1
@@ -42,7 +42,66 @@ public class OneDesignRankingMetric extends AbstractRankingMetric {
|
||||
|
||||
@Override
|
||||
public Duration getGapToLeaderInOwnTime(RankingMetric.RankingInfo rankingInfo, Competitor competitor, WindLegTypeAndLegBearingCache cache) {
|
||||
return rankingInfo.getCompetitorRankingInfo().apply(competitor).getEstimatedActualDurationFromTimePointToCompetitorFarthestAhead();
|
||||
// When the competitor is in the same leg as the leader (which in this ranking metric is always the boat
|
||||
// farthest ahead) then the competitor's duration to reach the current leader's position is estimated based on the
|
||||
// competitor's average VMG on the current leg.
|
||||
// If the leader has already finished the competitor's current leg, the time when the competitor will probably
|
||||
// finish the leg is compared to the time when the leader finished the leg.
|
||||
// When the competitor has already finished the current leg this can only mean the competitor finished the race
|
||||
// because otherwise the competitor would not be considered in this leg anymore. In this case, the mark passing
|
||||
// times for finishing the leg are compared between competitor and leader.
|
||||
final Duration result;
|
||||
final TrackedLegOfCompetitor currentLegWho = getCurrentLegOrLastLegIfAlreadyFinished(competitor,
|
||||
rankingInfo.getTimePoint());
|
||||
final Competitor to = rankingInfo.getCompetitorFarthestAhead();
|
||||
final TrackedLegOfCompetitor currentLegTo = getCurrentLegOrLastLegIfAlreadyFinished(to, rankingInfo.getTimePoint());
|
||||
if (currentLegTo == null) {
|
||||
result = null;
|
||||
} else {
|
||||
final TimePoint tosLegFinishingTime = currentLegTo.getFinishTime();
|
||||
// If who is on the last leg, to will also be considered on the last leg, even if to already finished that leg.
|
||||
// If to finished the last leg and who is on the last leg, getEstimatedActualDurationFromTimePointToCompetitorFarthestAhead will
|
||||
// not work properly because it considers both on the same leg and therefore doesn't restrict the time to when to finished
|
||||
// the leg and looks at the excess time.
|
||||
final Waypoint lastWaypoint = getTrackedRace().getRace().getCourse().getLastWaypoint();
|
||||
if (tosLegFinishingTime != null && !tosLegFinishingTime.after(rankingInfo.getTimePoint()) &&
|
||||
currentLegTo.getTrackedLeg().getLeg().getTo() == lastWaypoint) {
|
||||
// to has finished the race
|
||||
if (currentLegWho == null) {
|
||||
result = null;
|
||||
} else {
|
||||
final TimePoint whosLegFinishingTime = currentLegWho.getFinishTime();
|
||||
if (whosLegFinishingTime != null && !whosLegFinishingTime.after(rankingInfo.getTimePoint())) {
|
||||
// both have finished their leg; this means both have finished the race because otherwise this wouldn't be
|
||||
// who's current leg
|
||||
result = tosLegFinishingTime.until(whosLegFinishingTime);
|
||||
} else {
|
||||
final Duration etaNextMark = currentLegWho.getEstimatedTimeToNextMark(rankingInfo.getTimePoint(), WindPositionMode.EXACT);
|
||||
if (etaNextMark == null) {
|
||||
result = null;
|
||||
} else {
|
||||
final Duration timeToTookToFinishRaceStartingAtNextMark;
|
||||
final Waypoint whosNextMark = currentLegWho.getTrackedLeg().getLeg().getTo();
|
||||
if (whosNextMark == lastWaypoint) {
|
||||
// who is in the last leg; the ETA to who's next mark is the solution
|
||||
timeToTookToFinishRaceStartingAtNextMark = Duration.NULL;
|
||||
} else {
|
||||
// after passing the next mark, who still needs to travel about the same time that to
|
||||
// traveled after passing the next mark until finishing the race
|
||||
timeToTookToFinishRaceStartingAtNextMark =
|
||||
getTrackedRace().getMarkPassing(to, whosNextMark).getTimePoint().
|
||||
until(tosLegFinishingTime);
|
||||
}
|
||||
final TimePoint etaAtFinish = rankingInfo.getTimePoint().plus(etaNextMark.plus(timeToTookToFinishRaceStartingAtNextMark));
|
||||
result = tosLegFinishingTime.until(etaAtFinish);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = rankingInfo.getCompetitorRankingInfo().apply(competitor).getEstimatedActualDurationFromTimePointToCompetitorFarthestAhead();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.TrackedRaceStatusEnum;
|
||||
import com.sap.sailing.domain.common.confidence.Weigher;
|
||||
import com.sap.sailing.domain.common.impl.KnotSpeedImpl;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFix;
|
||||
@@ -151,4 +152,19 @@ public interface GPSFixTrack<ItemType, FixType extends GPSFix> extends Track<Fix
|
||||
*/
|
||||
Iterator<Position> getEstimatedPositions(Iterable<Timed> timeds, boolean extrapolate);
|
||||
|
||||
/**
|
||||
* When a {@link TrackedRace} moves into state {@link TrackedRaceStatusEnum#LOADING}, it shall call
|
||||
* this method on all its tracks to allow them to skip validity cache updates which, when done at massive
|
||||
* scale, are too expensive because they keep invalidating neighbors' validity and need some time to
|
||||
* find those neighbors. When leading state LOADING, {@link #resumeValidityCaching()} must be called.
|
||||
*/
|
||||
void suspendValidityCaching();
|
||||
|
||||
/**
|
||||
* When a {@link TrackedRace} moves out of state {@link TrackedRaceStatusEnum#LOADING}, it shall call
|
||||
* this method on all its tracks to allow them to invalidate all validity caching so far in order to
|
||||
* have everything re-calculated when needed.
|
||||
*/
|
||||
void resumeValidityCaching();
|
||||
|
||||
}
|
||||
|
||||
@@ -302,6 +302,10 @@ public interface TrackedRace extends Serializable, IsManagedByCache<SharedDomain
|
||||
return true;
|
||||
}
|
||||
|
||||
default boolean takesWindFixRecursively(Wind wind, Set<TrackedRace> visited) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #getWind(Position, TimePoint, Set) getWind(p, at, Collections.emptyList())}
|
||||
*/
|
||||
@@ -859,4 +863,5 @@ public interface TrackedRace extends Serializable, IsManagedByCache<SharedDomain
|
||||
default RaceLogResolver getRaceLogResolver() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
@@ -474,10 +474,13 @@ public class CrossTrackErrorCache extends AbstractRaceChangeListener {
|
||||
}
|
||||
|
||||
public void suspend() {
|
||||
owner.removeListener(this);
|
||||
cachePerCompetitor.suspend();
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
owner.addListener(this);
|
||||
invalidate();
|
||||
cachePerCompetitor.resume();
|
||||
}
|
||||
}
|
||||
|
||||
-5
@@ -560,11 +560,6 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<MarkPassing> getMarkPassingsInOrder(Waypoint waypoint) {
|
||||
return (NavigableSet<MarkPassing>) super.getMarkPassingsInOrder(waypoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lockForRead(Iterable<MarkPassing> markPassings) {
|
||||
getRace().getCourse().lockForRead();
|
||||
|
||||
+31
-3
@@ -26,6 +26,7 @@ import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.TrackedRaceStatusEnum;
|
||||
import com.sap.sailing.domain.common.confidence.BearingWithConfidence;
|
||||
import com.sap.sailing.domain.common.confidence.BearingWithConfidenceCluster;
|
||||
import com.sap.sailing.domain.common.confidence.ConfidenceBasedAverager;
|
||||
@@ -40,6 +41,7 @@ import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.common.tracking.WithValidityCache;
|
||||
import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.GPSTrackListener;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.TimeRange;
|
||||
import com.sap.sse.common.Timed;
|
||||
@@ -58,7 +60,12 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
|
||||
|
||||
private final GPSTrackListeners<ItemType, FixType> listeners;
|
||||
|
||||
|
||||
/**
|
||||
* When the owning {@link TrackedRace} is still {@link TrackedRaceStatusEnum#LOADING loading}, validity cache updates are
|
||||
* suspended.
|
||||
*/
|
||||
private boolean validityCachingSuspended;
|
||||
|
||||
private static class GPSTrackListeners<I, F extends GPSFix> implements Serializable {
|
||||
private static final long serialVersionUID = -7117842092078781722L;
|
||||
private Set<GPSTrackListener<I, F>> listeners;
|
||||
@@ -186,6 +193,25 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
|
||||
this.listeners = new GPSTrackListeners<ItemType, FixType>();
|
||||
this.distanceCache = new DistanceCache(trackedItem==null?"null":trackedItem.toString());
|
||||
this.maxSpeedCache = createMaxSpeedCache();
|
||||
this.validityCachingSuspended = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suspendValidityCaching() {
|
||||
validityCachingSuspended = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resumeValidityCaching() {
|
||||
lockForWrite();
|
||||
try {
|
||||
this.validityCachingSuspended = false;
|
||||
for (FixType fix : getRawFixes()) {
|
||||
fix.invalidateCache();
|
||||
}
|
||||
} finally {
|
||||
unlockAfterWrite();
|
||||
}
|
||||
}
|
||||
|
||||
protected MaxSpeedCache<ItemType, FixType> createMaxSpeedCache() {
|
||||
@@ -958,7 +984,7 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
|
||||
* of the <code>gpsFix</code> "upwards." However, if the adjacent earlier fixes have changed their validity by the addition
|
||||
* of <code>gpsFix</code>, the distance cache must be invalidated starting with the first fix whose validity changed.
|
||||
*/
|
||||
protected void invalidateValidityAndEstimatedSpeedAndDistanceCaches(FixType gpsFix) {
|
||||
private void invalidateValidityAndEstimatedSpeedAndDistanceCaches(FixType gpsFix) {
|
||||
assertWriteLock();
|
||||
TimePoint distanceCacheInvalidationStart = gpsFix.getTimePoint();
|
||||
// see also bug 968: cache entries for intervals ending after the last fix need to be removed because they are
|
||||
@@ -1058,7 +1084,9 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
|
||||
try {
|
||||
firstFixInTrack = getRawFixes().isEmpty();
|
||||
result = addWithoutLocking(fix);
|
||||
invalidateValidityAndEstimatedSpeedAndDistanceCaches(fix);
|
||||
if (!validityCachingSuspended) {
|
||||
invalidateValidityAndEstimatedSpeedAndDistanceCaches(fix);
|
||||
}
|
||||
} finally {
|
||||
unlockAfterWrite();
|
||||
}
|
||||
|
||||
+1
-1
@@ -105,7 +105,7 @@ public class ShortTimeWindCache {
|
||||
*/
|
||||
private void ensureTimerIsRunning() {
|
||||
if (timer == null) {
|
||||
timer = new Timer(getClass().getSimpleName()+" for "+trackedRace.getRace().getName());
|
||||
timer = new Timer(getClass().getSimpleName()+" for "+trackedRace.getRace().getName(), /* isDaemon */ true);
|
||||
timer.scheduleAtFixedRate(new CacheInvalidator(), /* delay */ preserveHowManyMilliseconds, preserveHowManyMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
Executable → Regular
+63
-35
@@ -590,6 +590,17 @@ public class TrackBasedEstimationWindTrackImpl extends VirtualWindTrackImpl {
|
||||
*/
|
||||
private class CacheInvalidationRaceChangeListener extends AbstractRaceChangeListener implements Serializable {
|
||||
private static final long serialVersionUID = -6623310087193133466L;
|
||||
|
||||
private boolean suspended;
|
||||
|
||||
public CacheInvalidationRaceChangeListener() {
|
||||
if (getTrackedRace().getStatus().getStatus() == TrackedRaceStatusEnum.LOADING) {
|
||||
suspended = true;
|
||||
clearCache();
|
||||
} else {
|
||||
suspended = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void defaultAction() {
|
||||
@@ -598,7 +609,9 @@ public class TrackBasedEstimationWindTrackImpl extends VirtualWindTrackImpl {
|
||||
|
||||
@Override
|
||||
public void windDataReceived(Wind wind, WindSource windSource) {
|
||||
invalidateForNewWind(wind, windSource);
|
||||
if (!suspended) {
|
||||
invalidateForNewWind(wind, windSource);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -654,48 +667,61 @@ public class TrackBasedEstimationWindTrackImpl extends VirtualWindTrackImpl {
|
||||
|
||||
@Override
|
||||
public void windDataRemoved(Wind wind, WindSource windSource) {
|
||||
invalidateForNewWind(wind, windSource);
|
||||
if (!suspended) {
|
||||
invalidateForNewWind(wind, windSource);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void competitorPositionChanged(GPSFixMoving fix, Competitor competitor) {
|
||||
long averagingInterval = getTrackedRace().getMillisecondsOverWhichToAverageSpeed();
|
||||
WindWithConfidence<TimePoint> startOfInvalidation = getDummyFixWithConfidence(new MillisecondsTimePoint(fix
|
||||
.getTimePoint().asMillis() - averagingInterval));
|
||||
TimePoint endOfInvalidation = new MillisecondsTimePoint(fix.getTimePoint().asMillis() + averagingInterval);
|
||||
scheduleCacheRefresh(startOfInvalidation, endOfInvalidation);
|
||||
if (!suspended) {
|
||||
long averagingInterval = getTrackedRace().getMillisecondsOverWhichToAverageSpeed();
|
||||
WindWithConfidence<TimePoint> startOfInvalidation = getDummyFixWithConfidence(new MillisecondsTimePoint(fix
|
||||
.getTimePoint().asMillis() - averagingInterval));
|
||||
TimePoint endOfInvalidation = new MillisecondsTimePoint(fix.getTimePoint().asMillis() + averagingInterval);
|
||||
scheduleCacheRefresh(startOfInvalidation, endOfInvalidation);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void statusChanged(TrackedRaceStatus newStatus, TrackedRaceStatus oldStatus) {
|
||||
if (oldStatus.getStatus() == TrackedRaceStatusEnum.LOADING) {
|
||||
if (newStatus.getStatus() != TrackedRaceStatusEnum.LOADING) {
|
||||
suspended = false;
|
||||
}
|
||||
} else if (newStatus.getStatus() == TrackedRaceStatusEnum.LOADING) {
|
||||
suspended = true;
|
||||
clearCache();
|
||||
}
|
||||
// This virtual wind track's cache can cope with an empty cache after the LOADING phase and populates the
|
||||
// cache
|
||||
// upon request. Invalidation happens also during the LOADING phase, preserving the cache's invariant.
|
||||
// cache upon request. Invalidation during the LOADING phase happens by clearing the entire cache.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markPassingReceived(Competitor competitor, Map<Waypoint, MarkPassing> oldMarkPassings,
|
||||
Iterable<MarkPassing> markPassings) {
|
||||
long averagingInterval = getTrackedRace().getMillisecondsOverWhichToAverageSpeed();
|
||||
WindWithConfidence<TimePoint> startOfInvalidation;
|
||||
TimePoint endOfInvalidation;
|
||||
for (MarkPassing markPassing : markPassings) {
|
||||
MarkPassing oldMarkPassing = oldMarkPassings.get(markPassing.getWaypoint());
|
||||
if (oldMarkPassing != markPassing) {
|
||||
if (oldMarkPassing == null) {
|
||||
startOfInvalidation = getDummyFixWithConfidence(new MillisecondsTimePoint(markPassing
|
||||
.getTimePoint().asMillis() - averagingInterval));
|
||||
endOfInvalidation = new MillisecondsTimePoint(markPassing.getTimePoint().asMillis()
|
||||
+ averagingInterval);
|
||||
} else {
|
||||
TimePoint[] interval = new TimePoint[] { oldMarkPassing.getTimePoint(),
|
||||
markPassing.getTimePoint() };
|
||||
Arrays.sort(interval);
|
||||
startOfInvalidation = getDummyFixWithConfidence(new MillisecondsTimePoint(
|
||||
interval[0].asMillis() - averagingInterval));
|
||||
endOfInvalidation = new MillisecondsTimePoint(interval[1].asMillis() + averagingInterval);
|
||||
if (!suspended) {
|
||||
long averagingInterval = getTrackedRace().getMillisecondsOverWhichToAverageSpeed();
|
||||
WindWithConfidence<TimePoint> startOfInvalidation;
|
||||
TimePoint endOfInvalidation;
|
||||
for (MarkPassing markPassing : markPassings) {
|
||||
MarkPassing oldMarkPassing = oldMarkPassings.get(markPassing.getWaypoint());
|
||||
if (oldMarkPassing != markPassing) {
|
||||
if (oldMarkPassing == null) {
|
||||
startOfInvalidation = getDummyFixWithConfidence(new MillisecondsTimePoint(markPassing
|
||||
.getTimePoint().asMillis() - averagingInterval));
|
||||
endOfInvalidation = new MillisecondsTimePoint(markPassing.getTimePoint().asMillis()
|
||||
+ averagingInterval);
|
||||
} else {
|
||||
TimePoint[] interval = new TimePoint[] { oldMarkPassing.getTimePoint(),
|
||||
markPassing.getTimePoint() };
|
||||
Arrays.sort(interval);
|
||||
startOfInvalidation = getDummyFixWithConfidence(new MillisecondsTimePoint(
|
||||
interval[0].asMillis() - averagingInterval));
|
||||
endOfInvalidation = new MillisecondsTimePoint(interval[1].asMillis() + averagingInterval);
|
||||
}
|
||||
scheduleCacheRefresh(startOfInvalidation, endOfInvalidation);
|
||||
}
|
||||
scheduleCacheRefresh(startOfInvalidation, endOfInvalidation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -703,13 +729,15 @@ public class TrackBasedEstimationWindTrackImpl extends VirtualWindTrackImpl {
|
||||
@Override
|
||||
public void markPositionChanged(GPSFix fix, Mark mark, boolean firstInTrack) {
|
||||
assert fix != null && fix.getTimePoint() != null;
|
||||
// A mark position change can mean a leg type change. The interval over which the wind estimation is
|
||||
// affected
|
||||
// depends on how the GPS track computes the estimated mark position. Ask it:
|
||||
TimeRange interval = getTrackedRace().getOrCreateTrack(mark).getEstimatedPositionTimePeriodAffectedBy(fix);
|
||||
WindWithConfidence<TimePoint> startOfInvalidation = getDummyFixWithConfidence(interval.from());
|
||||
TimePoint endOfInvalidation = interval.to();
|
||||
scheduleCacheRefresh(startOfInvalidation, endOfInvalidation);
|
||||
if (!suspended) {
|
||||
// A mark position change can mean a leg type change. The interval over which the wind estimation is
|
||||
// affected
|
||||
// depends on how the GPS track computes the estimated mark position. Ask it:
|
||||
TimeRange interval = getTrackedRace().getOrCreateTrack(mark).getEstimatedPositionTimePeriodAffectedBy(fix);
|
||||
WindWithConfidence<TimePoint> startOfInvalidation = getDummyFixWithConfidence(interval.from());
|
||||
TimePoint endOfInvalidation = interval.to();
|
||||
scheduleCacheRefresh(startOfInvalidation, endOfInvalidation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.tracking.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -17,6 +18,7 @@ import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Course;
|
||||
import com.sap.sailing.domain.base.Leg;
|
||||
import com.sap.sailing.domain.base.SpeedWithBearingWithConfidence;
|
||||
import com.sap.sailing.domain.base.SpeedWithConfidence;
|
||||
@@ -77,6 +79,16 @@ public class TrackedLegImpl implements TrackedLeg {
|
||||
competitorTracksOrderedByRank = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream oos) throws IOException {
|
||||
final Course course = trackedRace.getRace().getCourse();
|
||||
course.lockForRead();
|
||||
try {
|
||||
oos.defaultWriteObject();
|
||||
} finally {
|
||||
course.unlockAfterRead();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Leg getLeg() {
|
||||
return leg;
|
||||
|
||||
+1
-1
@@ -350,7 +350,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor {
|
||||
if (startPos != null) {
|
||||
Distance d = getTrackedLeg().getAbsoluteWindwardDistance(startPos, endPos, to,
|
||||
WindPositionMode.EXACT, cache);
|
||||
result = d.inTime(to.asMillis() - start.getTimePoint().asMillis());
|
||||
result = d == null ? null : d.inTime(to.asMillis() - start.getTimePoint().asMillis());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+79
-30
@@ -273,6 +273,17 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
|
||||
private transient Timer cacheInvalidationTimer;
|
||||
private transient Object cacheInvalidationTimerLock;
|
||||
|
||||
/**
|
||||
* handled by {@link #suspendAllCachesNotUpdatingWhileLoading()} and {@link #resumeAllCachesNotUpdatingWhileLoading()}.
|
||||
*/
|
||||
private boolean cachesSuspended;
|
||||
|
||||
/**
|
||||
* Whether during {@link #cachesSuspended suspended caches mode} the maneuver re-calculation was triggered; will lead
|
||||
* to triggering the maneuver re-calculation when caches are {@link #resumeAllCachesNotUpdatingWhileLoading() resumed}.
|
||||
*/
|
||||
private boolean triggerManeuverCacheInvalidationForAllCompetitors;
|
||||
|
||||
/**
|
||||
* Keys are the {@link RaceLog#getId() IDs} of the race logs that are stored as values.
|
||||
@@ -605,11 +616,11 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
crossTrackErrorCache = new CrossTrackErrorCache(this);
|
||||
crossTrackErrorCache.invalidate();
|
||||
maneuverCache = createManeuverCache();
|
||||
triggerManeuverCacheRecalculationForAllCompetitors();
|
||||
logger.info("Deserialized race " + getRace().getName());
|
||||
// considering the unlikely possibility that the course and this tracked race's internal structures
|
||||
// may be inconsistent, e.g., due to non-atomic serialization of course and tracked race; see bug 2223
|
||||
adjustStructureToCourse();
|
||||
triggerManeuverCacheRecalculationForAllCompetitors();
|
||||
logger.info("Deserialized race " + getRace().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -625,6 +636,10 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
private void adjustStructureToCourse() throws PatchFailedException {
|
||||
final TrackedRaceAsWaypointList trackedRaceAsWaypointList = new TrackedRaceAsWaypointList(this);
|
||||
Patch<Waypoint> diff = DiffUtils.diff(trackedRaceAsWaypointList, getRace().getCourse().getWaypoints());
|
||||
if (!diff.isEmpty()) {
|
||||
logger.warning("Found inconsistency between race's course ("+getRace().getCourse()+
|
||||
") and TrackedRace's structures in "+this+"; fixing");
|
||||
}
|
||||
diff.applyToInPlace(trackedRaceAsWaypointList);
|
||||
}
|
||||
|
||||
@@ -684,7 +699,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<MarkPassing> getMarkPassingsInOrder(Waypoint waypoint) {
|
||||
public NavigableSet<MarkPassing> getMarkPassingsInOrder(Waypoint waypoint) {
|
||||
return getMarkPassingsInOrderAsNavigableSet(waypoint);
|
||||
}
|
||||
|
||||
@@ -798,12 +813,13 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
TimePoint passingTime = null;
|
||||
final Waypoint lastWaypoint = getRace().getCourse().getLastWaypoint();
|
||||
if (lastWaypoint != null) {
|
||||
Iterable<MarkPassing> markPassingsInOrder = getMarkPassingsInOrder(lastWaypoint);
|
||||
NavigableSet<MarkPassing> markPassingsInOrder = getMarkPassingsInOrder(lastWaypoint);
|
||||
if (markPassingsInOrder != null) {
|
||||
lockForRead(markPassingsInOrder);
|
||||
try {
|
||||
for (MarkPassing passingFinishLine : markPassingsInOrder) {
|
||||
passingTime = passingFinishLine.getTimePoint();
|
||||
final MarkPassing last = markPassingsInOrder.isEmpty() ? null : markPassingsInOrder.last();
|
||||
if (last != null) {
|
||||
passingTime = last.getTimePoint();
|
||||
}
|
||||
} finally {
|
||||
unlockAfterRead(markPassingsInOrder);
|
||||
@@ -1525,6 +1541,18 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
*/
|
||||
@Override
|
||||
public boolean takesWindFix(Wind wind) {
|
||||
final Set<TrackedRace> visited = new HashSet<>();
|
||||
visited.add(this);
|
||||
return takesWindFixRecursively(wind, visited);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param visited
|
||||
* used to avoid endless recursion if cyclic predecessor relations are delivered by a
|
||||
* {@link RaceExecutionOrderProvider}
|
||||
*/
|
||||
@Override
|
||||
public boolean takesWindFixRecursively(Wind wind, Set<TrackedRace> visited) {
|
||||
final boolean result;
|
||||
final TimePoint earliestStartTimePoint = Util.getEarliestOfTimePoints(getStartOfRace(), getStartOfTracking());
|
||||
final TimePoint latestEndTimePoint = Util.getLatestOfTimePoints(getEndOfRace(), getEndOfTracking());
|
||||
@@ -1546,7 +1574,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
// the fix is in the critical interval between EXTRA_LONG_TIME_BEFORE_START_TO_TRACK_WIND_MILLIS and
|
||||
// TIME_BEFORE_START_TO_TRACK_WIND_MILLIS before the earliestStartTimePoint; the fix shall only be accepted
|
||||
// if no previous race exists that accepts it
|
||||
result = noPreviousRaceTakesWind(wind);
|
||||
result = noPreviousRaceTakesWind(wind, visited);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1558,10 +1586,11 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean noPreviousRaceTakesWind(Wind wind) {
|
||||
private boolean noPreviousRaceTakesWind(Wind wind, Set<TrackedRace> visited) {
|
||||
final boolean result;
|
||||
Set<TrackedRace> previousRacesInExecutionOrder = getPreviousRacesFromAttachedRaceExecutionOrderProviders();
|
||||
if (previousRacesInExecutionOrder == null || !previousRacesInExecutionOrder.stream().filter(tr -> tr.takesWindFix(wind) == true).findAny().isPresent()) {
|
||||
if (previousRacesInExecutionOrder == null || !previousRacesInExecutionOrder.stream().filter(tr ->
|
||||
visited.add(tr) && tr.takesWindFixRecursively(wind, visited)).findAny().isPresent()) {
|
||||
result = true;
|
||||
} else {
|
||||
result = false;
|
||||
@@ -2332,18 +2361,26 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
}
|
||||
|
||||
protected void triggerManeuverCacheRecalculationForAllCompetitors() {
|
||||
final List<Competitor> shuffledCompetitors = new ArrayList<>();
|
||||
for (Competitor competitor : (getRace().getCompetitors())) {
|
||||
shuffledCompetitors.add(competitor);
|
||||
}
|
||||
Collections.shuffle(shuffledCompetitors);
|
||||
for (Competitor competitor : shuffledCompetitors) {
|
||||
triggerManeuverCacheRecalculation(competitor);
|
||||
if (cachesSuspended) {
|
||||
triggerManeuverCacheInvalidationForAllCompetitors = true;
|
||||
} else {
|
||||
final List<Competitor> shuffledCompetitors = new ArrayList<>();
|
||||
for (Competitor competitor : (getRace().getCompetitors())) {
|
||||
shuffledCompetitors.add(competitor);
|
||||
}
|
||||
Collections.shuffle(shuffledCompetitors);
|
||||
for (Competitor competitor : shuffledCompetitors) {
|
||||
triggerManeuverCacheRecalculation(competitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void triggerManeuverCacheRecalculation(final Competitor competitor) {
|
||||
maneuverCache.triggerUpdate(competitor, /* updateInterval */null);
|
||||
if (cachesSuspended) {
|
||||
triggerManeuverCacheInvalidationForAllCompetitors = true;
|
||||
} else {
|
||||
maneuverCache.triggerUpdate(competitor, /* updateInterval */null);
|
||||
}
|
||||
}
|
||||
|
||||
private com.sap.sse.common.Util.Triple<TimePoint, TimePoint, List<Maneuver>> computeManeuvers(Competitor competitor) throws NoWindException {
|
||||
@@ -3018,6 +3055,13 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
}
|
||||
|
||||
private void suspendAllCachesNotUpdatingWhileLoading() {
|
||||
cachesSuspended = true;
|
||||
for (GPSFixTrack<Competitor, GPSFixMoving> competitorTrack : tracks.values()) {
|
||||
competitorTrack.suspendValidityCaching();
|
||||
}
|
||||
for (GPSFixTrack<Mark, GPSFix> markTrack : markTracks.values()) {
|
||||
markTrack.suspendValidityCaching();
|
||||
}
|
||||
if (markPassingCalculator != null) {
|
||||
markPassingCalculator.suspend();
|
||||
}
|
||||
@@ -3026,10 +3070,20 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
}
|
||||
|
||||
private void resumeAllCachesNotUpdatingWhileLoading() {
|
||||
cachesSuspended = false;
|
||||
for (GPSFixTrack<Competitor, GPSFixMoving> competitorTrack : tracks.values()) {
|
||||
competitorTrack.resumeValidityCaching();
|
||||
}
|
||||
for (GPSFixTrack<Mark, GPSFix> markTrack : markTracks.values()) {
|
||||
markTrack.resumeValidityCaching();
|
||||
}
|
||||
if (markPassingCalculator != null) {
|
||||
markPassingCalculator.resume();
|
||||
}
|
||||
crossTrackErrorCache.resume();
|
||||
if (triggerManeuverCacheInvalidationForAllCompetitors) {
|
||||
triggerManeuverCacheRecalculationForAllCompetitors();
|
||||
}
|
||||
maneuverCache.resume();
|
||||
}
|
||||
|
||||
@@ -3365,10 +3419,8 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
final TrackedLeg legDeterminingDirection = getLegDeterminingDirectionInWhichToPassWaypoint(waypoint);
|
||||
final Mark portMarkWhileApproachingLine = marksAndPositions.getPortMarkWhileApproachingLine();
|
||||
final Mark starboardMarkWhileApproachingLine = marksAndPositions.getStarboardMarkWhileApproachingLine();
|
||||
final Position portMarkPositionWhileApproachingLine = marksAndPositions
|
||||
.getPortMarkPositionWhileApproachingLine();
|
||||
final Position starboardMarkPositionWhileApproachingLine = marksAndPositions
|
||||
.getStarboardMarkPositionWhileApproachingLine();
|
||||
final Position portMarkPositionWhileApproachingLine = marksAndPositions.getPortMarkPositionWhileApproachingLine();
|
||||
final Position starboardMarkPositionWhileApproachingLine = marksAndPositions.getStarboardMarkPositionWhileApproachingLine();
|
||||
final Bearing differenceToCombinedWind;
|
||||
final NauticalSide advantageousSideWhileApproachingLine;
|
||||
final Distance distanceAdvantage;
|
||||
@@ -3425,14 +3477,13 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
*/
|
||||
private LineMarksWithPositions getLineMarksAndPositions(TimePoint timePoint, Waypoint waypoint) {
|
||||
final LineMarksWithPositions result;
|
||||
List<Position> markPositions = new ArrayList<Position>();
|
||||
List<Position> markPositions = new ArrayList<>();
|
||||
int numberOfMarks = 0;
|
||||
boolean allMarksHavePositions = true;
|
||||
if (waypoint != null) {
|
||||
for (Mark lineMark : waypoint.getMarks()) {
|
||||
numberOfMarks++;
|
||||
final Position estimatedMarkPosition = getOrCreateTrack(lineMark).getEstimatedPosition(timePoint, /* extrapolate */
|
||||
false);
|
||||
final Position estimatedMarkPosition = getOrCreateTrack(lineMark).getEstimatedPosition(timePoint, /* extrapolate */ false);
|
||||
if (estimatedMarkPosition != null) {
|
||||
markPositions.add(estimatedMarkPosition);
|
||||
} else {
|
||||
@@ -3482,12 +3533,10 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
|
||||
private TrackedLeg getLegDeterminingDirectionInWhichToPassWaypoint(Waypoint waypoint) {
|
||||
final TrackedLeg legDeterminingDirection;
|
||||
{
|
||||
final int indexOfWaypoint2 = getRace().getCourse().getIndexOfWaypoint(waypoint);
|
||||
final boolean isStartLine2 = indexOfWaypoint2 == 0;
|
||||
legDeterminingDirection = getTrackedLeg(getRace().getCourse().getLegs().get(isStartLine2 ? 0
|
||||
: indexOfWaypoint2 - 1));
|
||||
}
|
||||
final int indexOfWaypoint = getRace().getCourse().getIndexOfWaypoint(waypoint);
|
||||
final boolean isStartLine = indexOfWaypoint == 0;
|
||||
legDeterminingDirection = getTrackedLeg(getRace().getCourse().getLegs().get(isStartLine ? 0
|
||||
: indexOfWaypoint - 1));
|
||||
return legDeterminingDirection;
|
||||
}
|
||||
|
||||
|
||||
@@ -110,4 +110,11 @@
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="lz4-java"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
</feature>
|
||||
|
||||
@@ -28,9 +28,7 @@ Computes leaderboard information for sailing races and offers RESTful APIs to al
|
||||
<import plugin="com.google.gwt.osgi" version="2.7.0" match="greaterOrEqual"/>
|
||||
<import plugin="org.json.simple" version="1.1.0" match="greaterOrEqual"/>
|
||||
<import plugin="org.moxieapps.gwt.highcharts" version="1.6.0" match="greaterOrEqual"/>
|
||||
<import plugin="org.apache.geronimo.specs.geronimo-jms_1.1_spec"/>
|
||||
<import plugin="com.rabbitmq.client"/>
|
||||
<import plugin="org.apache.geronimo.specs.geronimo-j2ee-management_1.1_spec"/>
|
||||
</requires>
|
||||
|
||||
<plugin
|
||||
|
||||
@@ -17,7 +17,6 @@ Require-Bundle: com.sap.sailing.server,
|
||||
com.sap.sse.filestorage
|
||||
Bundle-ClassPath: .
|
||||
Import-Package: com.sap.sailing.domain.racelogtracking.impl,
|
||||
javax.jms;version="1.1.0",
|
||||
javax.servlet;version="2.6.0",
|
||||
javax.servlet.http;version="2.6.0",
|
||||
junit.framework;version="4.8.1",
|
||||
|
||||
@@ -11,6 +11,6 @@
|
||||
</listAttribute>
|
||||
<stringAttribute key="projectName" value="com.sap.sailing.gwt.ui"/>
|
||||
<booleanAttribute key="showLaunchOutput" value="false"/>
|
||||
<stringAttribute key="url" value="http://127.0.0.1:8888/gwt/AdminConsole.html"/>
|
||||
<stringAttribute key="url" value="http://127.0.0.1:8888/gwt/Home.html"/>
|
||||
<stringAttribute key="urlQueryParams" value=""/>
|
||||
</launchConfiguration>
|
||||
|
||||
@@ -51,8 +51,7 @@ Require-Bundle: com.sap.sailing.domain,
|
||||
com.sap.sailing.news
|
||||
Bundle-Activator: com.sap.sailing.gwt.ui.server.Activator
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Import-Package: javax.jms;version="1.1.0",
|
||||
javax.servlet;version="3.1.0",
|
||||
Import-Package: javax.servlet;version="3.1.0",
|
||||
javax.servlet.descriptor;version="3.1.0",
|
||||
javax.servlet.http;version="3.1.0",
|
||||
org.apache.http.client;version="4.2.5",
|
||||
|
||||
@@ -1,76 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="com.google.gdt.eclipse.suite.webapp">
|
||||
<booleanAttribute key="com.google.gdt.eclipse.core.RUN_SERVER" value="false"/>
|
||||
<stringAttribute key="com.google.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.GWTShell"/>
|
||||
<booleanAttribute key="com.google.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/>
|
||||
<booleanAttribute key="com.google.gwt.eclipse.core.CODE_SERVER_PORT_AUTO" value="true"/>
|
||||
<listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES">
|
||||
<listEntry value="com.sap.sailing.gwt.ui.RaceBoard"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.DataMining"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.LeaderboardEditing"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.Spectator"/>
|
||||
<listEntry value="com.sap.sailing.gwt.regattaoverview.RegattaOverview"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.PolarSheets"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.Leaderboard"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.Simulator"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.YoutubePopup"/>
|
||||
<listEntry value="com.sap.sailing.gwt.AutoPlay"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.AdminConsole"/>
|
||||
<listEntry value="com.sap.sailing.gwt.home.Home"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.VideoPopup"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="com.google.gwt.eclipse.core.URL" value="/gwt/Home.html"/>
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
||||
<listEntry value="/com.sap.sailing.gwt.ui"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
||||
<listEntry value="4"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
|
||||
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
|
||||
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
|
||||
</listAttribute>
|
||||
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="false"/>
|
||||
<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6" javaProject="com.sap.sailing.gwt.ui" path="1" type="4"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.gwt.ui/src/main/resources" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.gwt.ui/src/main/java" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.gwt.theme/src/main/java" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.googlecode.java-diff-utils/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain.common/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/org.json.simple/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.server/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain.tractracadapter/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.expeditionconnector/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.declination/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.declination/resources" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.udpconnector/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.mongodb/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain.swisstimingadapter/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain.persistence/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain.swisstimingadapter.persistence/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.operationaltransformation/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.replication/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain.tractracadapter.persistence/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/org.moxieapps.gwt.highcharts/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.geocoding/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.datamining.shared/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.common/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.datamining.shared/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.gwt/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.google.gwt.osgi/lib/gwt-user.jar" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry id="org.eclipse.jdt.launching.classpathentry.defaultClasspath"> <memento exportedEntriesOnly="false" project="com.sap.sailing.gwt.ui"/> </runtimeClasspathEntry> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.security/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.security.ui/src/main/java" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.gwt.adminconsole/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.security.common/src" path="3" type="2"/> "/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/>
|
||||
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -incremental -war "${project_loc:com.sap.sailing.gwt.ui}" -noserver -remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -logLevel INFO -codeServerPort auto -startupUrl /gwt/Home.html com.sap.sailing.gwt.home.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.regattaoverview.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup com.sap.sailing.gwt.home.Home com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.ui.PolarSheets com.sap.sailing.gwt.regattaoverview.RegattaOverview com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.DataMining com.sap.sailing.gwt.ui.RaceBoard"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m -Dgwt-usearchives=false -Dgwt.persistentunitcache=false"/>
|
||||
</launchConfiguration>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="com.google.gdt.eclipse.suite.webapp">
|
||||
<booleanAttribute key="com.google.gdt.eclipse.core.RUN_SERVER" value="false"/>
|
||||
<stringAttribute key="com.google.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.GWTShell"/>
|
||||
<booleanAttribute key="com.google.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/>
|
||||
<booleanAttribute key="com.google.gwt.eclipse.core.CODE_SERVER_PORT_AUTO" value="true"/>
|
||||
<listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES">
|
||||
<listEntry value="com.sap.sailing.gwt.ui.RaceBoard"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.DataMining"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.LeaderboardEditing"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.Spectator"/>
|
||||
<listEntry value="com.sap.sailing.gwt.regattaoverview.RegattaOverview"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.PolarSheets"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.Leaderboard"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.Simulator"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.YoutubePopup"/>
|
||||
<listEntry value="com.sap.sailing.gwt.AutoPlay"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.AdminConsole"/>
|
||||
<listEntry value="com.sap.sailing.gwt.home.Home"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.VideoPopup"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="com.google.gwt.eclipse.core.URL" value="/gwt/Home.html"/>
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
||||
<listEntry value="/com.sap.sailing.gwt.ui"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
||||
<listEntry value="4"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
|
||||
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
|
||||
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
|
||||
</listAttribute>
|
||||
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="false"/>
|
||||
<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6" javaProject="com.sap.sailing.gwt.ui" path="1" type="4"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.gwt.ui/src/main/resources" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.gwt.ui/src/main/java" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.gwt.theme/src/main/java" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.googlecode.java-diff-utils/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain.common/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/org.json.simple/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.server/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain.tractracadapter/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.expeditionconnector/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.declination/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.declination/resources" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.udpconnector/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.mongodb/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain.swisstimingadapter/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain.persistence/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain.swisstimingadapter.persistence/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.operationaltransformation/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.replication/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain.tractracadapter.persistence/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/org.moxieapps.gwt.highcharts/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.geocoding/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.datamining.shared/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.common/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.datamining.shared/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.gwt/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.google.gwt.osgi/lib/gwt-user.jar" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry id="org.eclipse.jdt.launching.classpathentry.defaultClasspath"> <memento exportedEntriesOnly="false" project="com.sap.sailing.gwt.ui"/> </runtimeClasspathEntry> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.security/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.security.ui/src/main/java" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.gwt.adminconsole/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.security.common/src" path="3" type="2"/> "/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/>
|
||||
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -incremental -war "${project_loc:com.sap.sailing.gwt.ui}" -noserver -remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -logLevel INFO -codeServerPort auto -startupUrl /gwt/Home.html com.sap.sailing.gwt.home.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.regattaoverview.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup com.sap.sailing.gwt.home.Home com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.ui.PolarSheets com.sap.sailing.gwt.regattaoverview.RegattaOverview com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.DataMining com.sap.sailing.gwt.ui.RaceBoard"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m -Dgwt-usearchives=false -Dgwt.persistentunitcache=false"/>
|
||||
</launchConfiguration>
|
||||
|
||||
+8
-10
@@ -133,12 +133,6 @@ public abstract class AbstractEventActivity<PLACE extends AbstractEventPlace> ex
|
||||
return getRaceViewerURL(leaderboard.name, raceIdentifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRaceViewerURL(String regattaName, String trackedRaceName) {
|
||||
return EntryPointLinkFactory
|
||||
.createRaceBoardLink(createRaceBoardLinkParameters(regattaName, regattaName, trackedRaceName));
|
||||
}
|
||||
|
||||
public String getRaceViewerURL(String leaderboardName, RegattaAndRaceIdentifier raceIdentifier) {
|
||||
return EntryPointLinkFactory
|
||||
.createRaceBoardLink(createRaceBoardLinkParameters(leaderboardName, raceIdentifier.getRegattaName(), raceIdentifier.getRaceName()));
|
||||
@@ -314,7 +308,14 @@ public abstract class AbstractEventActivity<PLACE extends AbstractEventPlace> ex
|
||||
String url = "RegattaOverview.html?ignoreLocalSettings=true&onlyrunningraces=false&event=" + getCtx().getEventId();
|
||||
url += "&onlyracesofsameday=" + getCtx().getEventDTO().isRunning();
|
||||
if(showRegattaMetadata()) {
|
||||
url += "®atta=" + getCtx().getRegattaId();
|
||||
if(getRegattaMetadata().isFlexibleLeaderboard()) {
|
||||
String defaultCourseAreaId = getRegattaMetadata().getDefaultCourseAreaId();
|
||||
if(defaultCourseAreaId != null && !defaultCourseAreaId.isEmpty()) {
|
||||
url += "&coursearea=" + defaultCourseAreaId;
|
||||
}
|
||||
} else {
|
||||
url += "®atta=" + getCtx().getRegattaId();
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
@@ -325,9 +326,6 @@ public abstract class AbstractEventActivity<PLACE extends AbstractEventPlace> ex
|
||||
if(ctx.getRegatta().getState() == RegattaState.RUNNING) {
|
||||
return true;
|
||||
}
|
||||
if(ctx.getRegatta().getState() != RegattaState.UNKNOWN) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return ctx.getEventDTO().getState() == EventState.RUNNING;
|
||||
}
|
||||
|
||||
+2
-1
@@ -6,6 +6,7 @@ import com.google.gwt.place.shared.Place;
|
||||
import com.google.gwt.safehtml.shared.SafeUri;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.IsWidget;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.dto.RaceDTO;
|
||||
import com.sap.sailing.gwt.common.client.controls.tabbar.TabView;
|
||||
import com.sap.sailing.gwt.home.client.place.event.regatta.AbstractEventRegattaPlace;
|
||||
@@ -56,7 +57,7 @@ public interface EventView<PLACE extends AbstractEventPlace, PRES extends EventV
|
||||
|
||||
String getRaceViewerURL(StrippedLeaderboardDTO leaderboard, RaceDTO race);
|
||||
|
||||
String getRaceViewerURL(String regattaName, String trackedRaceName);
|
||||
String getRaceViewerURL(String leaderboardName, RegattaAndRaceIdentifier raceIdentifier);
|
||||
|
||||
PlaceNavigation<RegattaRacesPlace> getRegattaRacesNavigation(String regattaName);
|
||||
PlaceNavigation<AbstractEventRegattaPlace> getRegattaNavigation(String regattaName);
|
||||
|
||||
+2
-2
@@ -157,8 +157,8 @@ public class MultiregattaOverviewTabView extends Composite implements Multiregat
|
||||
private class MultiregattaOverviewRegattasTabViewRegattaFilterList implements
|
||||
DropdownFilterList<String>, RefreshableWidget<SortedSetResult<RegattaWithProgressDTO>> {
|
||||
@Override
|
||||
public void setData(SortedSetResult<RegattaWithProgressDTO> data, long nextUpdate, int updateNo) {
|
||||
regattaListUi.setData(data, nextUpdate, updateNo);
|
||||
public void setData(SortedSetResult<RegattaWithProgressDTO> data) {
|
||||
regattaListUi.setData(data);
|
||||
boatCategoryFilterUi.updateFilterValues();
|
||||
}
|
||||
@Override
|
||||
|
||||
+3
-3
@@ -155,8 +155,8 @@ public class MultiregattaRegattasTabView extends Composite implements Multiregat
|
||||
DropdownFilterList<String>, RefreshableWidget<SortedSetResult<RegattaWithProgressDTO>> {
|
||||
|
||||
@Override
|
||||
public void setData(SortedSetResult<RegattaWithProgressDTO> data, long nextUpdate, int updateNo) {
|
||||
regattaListUi.setData(data, nextUpdate, updateNo);
|
||||
public void setData(SortedSetResult<RegattaWithProgressDTO> data) {
|
||||
regattaListUi.setData(data);
|
||||
boatCategoryFilterUi.updateFilterValues();
|
||||
}
|
||||
|
||||
@@ -172,4 +172,4 @@ public class MultiregattaRegattasTabView extends Composite implements Multiregat
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -33,13 +33,13 @@ public class EventOverviewStage extends Composite {
|
||||
|
||||
private final RefreshableWidget<EventOverviewStageDTO> refreshable = new RefreshableWidget<EventOverviewStageDTO>() {
|
||||
@Override
|
||||
public void setData(EventOverviewStageDTO data, long nextUpdate, int updateNo) {
|
||||
public void setData(EventOverviewStageDTO data) {
|
||||
setStageData(data);
|
||||
}
|
||||
};
|
||||
private final RefreshableWidget<ListResult<NewsEntryDTO>> newsRefreshable = new RefreshableWidget<ListResult<NewsEntryDTO>>() {
|
||||
@Override
|
||||
public void setData(ListResult<NewsEntryDTO> data, long nextUpdate, int updateNo) {
|
||||
public void setData(ListResult<NewsEntryDTO> data) {
|
||||
setNews(data.getValues());
|
||||
}
|
||||
};
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ public class MultiRegattaList extends Composite implements RefreshableWidget<Sor
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(SortedSetResult<RegattaWithProgressDTO> data, long nextUpdate, int updateNo) {
|
||||
public void setData(SortedSetResult<RegattaWithProgressDTO> data) {
|
||||
this.setListData(data == null ? Collections.<RegattaWithProgressDTO>emptySet() : data.getValues());
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -21,15 +21,15 @@ public class MultiRegattaListItem extends Composite {
|
||||
@UiField(provided = true) MultiRegattaListSteps regattaStepsUi;
|
||||
private final RegattaWithProgressDTO regattaWithProgress;
|
||||
|
||||
public MultiRegattaListItem(RegattaWithProgressDTO regattaWithProgress) {
|
||||
public MultiRegattaListItem(RegattaWithProgressDTO regattaWithProgress, boolean showStateMarker) {
|
||||
this.regattaWithProgress = regattaWithProgress;
|
||||
regattaHeaderUi = new RegattaHeader(regattaWithProgress);
|
||||
regattaHeaderUi = new RegattaHeader(regattaWithProgress, showStateMarker);
|
||||
regattaStepsUi = new MultiRegattaListSteps(regattaWithProgress.getProgress());
|
||||
initWidget(uiBinder.createAndBindUi(this));
|
||||
}
|
||||
|
||||
public MultiRegattaListItem(RegattaWithProgressDTO regattaWithProgress, Presenter presenter) {
|
||||
this(regattaWithProgress);
|
||||
this(regattaWithProgress, presenter.getCtx().getEventDTO().isRunning());
|
||||
regattaHeaderUi.setRegattaNavigation(presenter.getRegattaNavigation(regattaWithProgress.getId()));
|
||||
PlaceNavigation<?> leaderboardNavigation = presenter.getRegattaLeaderboardNavigation(regattaWithProgress.getId());
|
||||
regattaStepsUi.setLeaderboardNavigation(regattaWithProgress.getState(), leaderboardNavigation);
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ public class RegattaCompetitionSeries extends Composite {
|
||||
RegattaCompetitionFleet competitionFleet = new RegattaCompetitionFleet(fleet);
|
||||
for (RaceListRaceDTO race : fleet.getRaces()) {
|
||||
boolean tracked = race.getTrackingState() == RaceTrackingState.TRACKED_VALID_DATA;
|
||||
String raceViewerUrl = tracked ? presenter.getRaceViewerURL(race.getRegattaName(), race.getTrackedRaceName()) : null;
|
||||
String raceViewerUrl = tracked ? presenter.getRaceViewerURL(race.getRegattaName(), race.getRegattaAndRaceIdentifier()) : null;
|
||||
competitionFleet.addRace(race, raceViewerUrl);
|
||||
}
|
||||
containerUi.add(competitionFleet);
|
||||
|
||||
+25
-5
@@ -72,20 +72,31 @@
|
||||
min-width: 13.333333333333334em;
|
||||
max-width: 16.666666666666668em;
|
||||
}
|
||||
.race_item_flag {
|
||||
max-width: 1.6em;
|
||||
max-height: 1.6em;
|
||||
img.race_item_flag {
|
||||
vertical-align: middle;
|
||||
height: 1em;
|
||||
width: auto;
|
||||
}
|
||||
.race_item_position {
|
||||
margin-right: 0.333333333333333em;
|
||||
}
|
||||
.race_item_winner {
|
||||
.race_item_sailid {
|
||||
margin-left: 5px;
|
||||
vertical-align: middle;
|
||||
font-weight: bold;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.race_item_winner {
|
||||
vertical-align: middle;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.race_itemwinner {
|
||||
padding: 0.733333333333333em 1.333333333333333em;
|
||||
padding: 0 1.333333333333333em;
|
||||
}
|
||||
.race_itemwinner > div {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.race_itemcenter {
|
||||
text-align: center;
|
||||
@@ -211,4 +222,13 @@
|
||||
.racesListIcon > div {
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
}
|
||||
.racesListHideColumn {
|
||||
width: 0 !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
border: medium none !important;
|
||||
}
|
||||
.racesListHideColumn > * {
|
||||
display: none !important;
|
||||
}
|
||||
+2
@@ -24,6 +24,7 @@ public interface RacesListLiveResources extends ClientBundle {
|
||||
String race_itemwinner();
|
||||
String race_item_flag();
|
||||
String race_item_position();
|
||||
String race_item_sailid();
|
||||
String race_item_winner();
|
||||
String race_itemcenter();
|
||||
String race_itemright();
|
||||
@@ -49,5 +50,6 @@ public interface RacesListLiveResources extends ClientBundle {
|
||||
String raceslistlive();
|
||||
|
||||
String racesListIcon();
|
||||
String racesListHideColumn();
|
||||
}
|
||||
}
|
||||
|
||||
+53
-32
@@ -1,6 +1,9 @@
|
||||
package com.sap.sailing.gwt.home.client.place.event.partials.racelist;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.user.cellview.client.Column;
|
||||
import com.google.gwt.user.cellview.client.ColumnSortList;
|
||||
@@ -33,33 +36,23 @@ public abstract class AbstractRaceList<T extends RaceMetadataDTO<? extends Abstr
|
||||
protected final SortableRaceListColumn<T, ?> windDirectionColumn = RaceListColumnFactory.getWindDirectionColumn();
|
||||
protected final SortableRaceListColumn<T, ?> raceViewerButtonColumn;
|
||||
|
||||
private SortedCellTable<T> cellTable;
|
||||
private SortedCellTable<T> cellTable = new SortedCellTable<T>(0, CleanCellTableResources.INSTANCE);
|
||||
private boolean tableColumnsInitialized = false;
|
||||
|
||||
protected AbstractRaceList(EventView.Presenter presenter) {
|
||||
CSS.ensureInjected();
|
||||
this.raceViewerButtonColumn = RaceListColumnFactory.getRaceViewerButtonColumn(presenter);
|
||||
this.cellTableContainer.setWidget(this.cellTable);
|
||||
this.initTableStyle();
|
||||
this.initWidget(cellTableContainer);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void setTableData(Collection<T> data) {
|
||||
ColumnSortList sortList = this.cellTable == null ? null : this.cellTable.getColumnSortList();
|
||||
this.cellTable = new SortedCellTable<T>(data.size(), CleanCellTableResources.INSTANCE);
|
||||
this.cellTableContainer.setWidget(this.cellTable);
|
||||
this.initTableStyle();
|
||||
this.initTableColumns();
|
||||
this.ensureInitTableColumns();
|
||||
this.updateColumnVisibility();
|
||||
this.cellTable.setPageSize(data.size());
|
||||
this.cellTable.setList(data);
|
||||
if (sortList != null && sortList.size() > 0) {
|
||||
for (int i = sortList.size() - 1; i >= 0; i--) {
|
||||
ColumnSortInfo sortInfo = sortList.get(i);
|
||||
Column<T, ?> column = (Column<T, ?>) sortInfo.getColumn();
|
||||
if(this.cellTable.getColumnIndex(column) >= 0) {
|
||||
this.cellTable.sortColumn(column, sortInfo.isAscending());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.cellTable.sortColumn(startTimeColumn);
|
||||
}
|
||||
this.restoreColumnSortInfos();
|
||||
}
|
||||
|
||||
private void initTableStyle() {
|
||||
@@ -73,24 +66,52 @@ public abstract class AbstractRaceList<T extends RaceMetadataDTO<? extends Abstr
|
||||
});
|
||||
}
|
||||
|
||||
private void ensureInitTableColumns() {
|
||||
if (tableColumnsInitialized) return;
|
||||
tableColumnsInitialized = true;
|
||||
this.initTableColumns();
|
||||
}
|
||||
|
||||
protected abstract void initTableColumns();
|
||||
|
||||
protected void add(SortableRaceListColumn<T, ?> column) {
|
||||
if (column.isShowDetails()) {
|
||||
if (column.getColumnStyle() != null) {
|
||||
column.setCellStyleNames(column.getColumnStyle());
|
||||
}
|
||||
|
||||
private void updateColumnVisibility() {
|
||||
for (int i = 0; i < this.cellTable.getColumnCount(); i++) {
|
||||
SortableRaceListColumn<T, ?> column = (SortableRaceListColumn<T, ?>) this.cellTable.getColumn(i);
|
||||
Header<?> header = column.getHeader();
|
||||
if (header != null && column.getHeaderStyle() != null) {
|
||||
header.setHeaderStyleNames(column.getHeaderStyle());
|
||||
if (header != null) {
|
||||
header.setHeaderStyleNames(column.getCurrentHeaderStyle());
|
||||
}
|
||||
boolean ascending = column.getPreferredSortingOrder().isAscending();
|
||||
InvertibleComparator<T> comperator = column.getComparator();
|
||||
if (comperator != null) {
|
||||
comperator.setAscending(ascending);
|
||||
}
|
||||
this.cellTable.addColumn(column, header, comperator, ascending);
|
||||
column.setCellStyleNames(column.getCurrentColumnStyle());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void restoreColumnSortInfos() {
|
||||
ColumnSortList sortList = this.cellTable.getColumnSortList();
|
||||
List<ColumnSortInfo> oldSortInfos;
|
||||
if (sortList.size() == 0) {
|
||||
boolean ascending = startTimeColumn.getPreferredSortingOrder().isAscending();
|
||||
oldSortInfos = Collections.singletonList(new ColumnSortInfo(startTimeColumn, ascending));
|
||||
} else {
|
||||
oldSortInfos = new ArrayList<ColumnSortList.ColumnSortInfo>(sortList.size());
|
||||
for (int i = sortList.size() - 1; i >= 0; i--) {
|
||||
oldSortInfos.add(sortList.get(i));
|
||||
}
|
||||
}
|
||||
for (ColumnSortInfo sortInfo : oldSortInfos) {
|
||||
Column<T, ?> column = (Column<T, ?>) sortInfo.getColumn();
|
||||
this.cellTable.sortColumn(column);
|
||||
}
|
||||
}
|
||||
|
||||
protected void add(SortableRaceListColumn<T, ?> column) {
|
||||
Header<?> header = column.getHeader();
|
||||
boolean ascending = column.getPreferredSortingOrder().isAscending();
|
||||
InvertibleComparator<T> comperator = column.getComparator();
|
||||
if (comperator != null) {
|
||||
comperator.setAscending(ascending);
|
||||
}
|
||||
this.cellTable.addColumn(column, header, comperator, ascending);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-4
@@ -76,8 +76,8 @@ public class RaceListColumnFactory {
|
||||
@Template("<a href=\"{2}\" class=\"{0}\" target=\"_blank\">{1}</a>")
|
||||
SafeHtml raceViewerLinkButton(String styleNames, String text, String link);
|
||||
|
||||
@Template("<img src=\"{2}\" class=\"{0}\" /><span class=\"{1}\">{3}</span>")
|
||||
SafeHtml winner(String styleNamesFlag, String styleNamesText, SafeUri flagImageURL, String name);
|
||||
@Template("<img src=\"{3}\" class=\"{0}\" /><span class=\"{1}\">{4}</span><div class=\"{2}\" title=\"{5}\">{5}</div>")
|
||||
SafeHtml winner(String styleNamesFlag, String styleNamesSailId, String styleNamesText, SafeUri flagImageURL, String sailId, String name);
|
||||
|
||||
@Template("<img src=\"{1}\" class=\"{0}\" />")
|
||||
SafeHtml imageHeader(String styleNames, SafeUri imageURL);
|
||||
@@ -470,7 +470,8 @@ public class RaceListColumnFactory {
|
||||
public void render(Context context, SimpleCompetitorDTO value, SafeHtmlBuilder sb) {
|
||||
if (value != null) {
|
||||
SafeUri flagImageUri = FlagImageResolver.getFlagImageUri(value.getFlagImageURL(), value.getTwoLetterIsoCountryCode());
|
||||
sb.append(TEMPLATE.winner(CSS.race_item_flag(), CSS.race_item_winner(), flagImageUri, value.getName()));
|
||||
String flagStyle = CSS.race_item_flag(), sailIdStyle = CSS.race_item_sailid(), nameStyle = CSS.race_item_winner();
|
||||
sb.append(TEMPLATE.winner(flagStyle, sailIdStyle, nameStyle, flagImageUri, value.getSailID(), value.getName()));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -514,7 +515,7 @@ public class RaceListColumnFactory {
|
||||
} else {
|
||||
String styleNames = data.getViewState() == RaceViewState.FINISHED ? analyseRaceStyle : watchNowStyle;
|
||||
String text = data.getViewState() == RaceViewState.FINISHED ? I18N.analyseRace() : I18N_UBI.watchNow();
|
||||
String raceViewerURL = presenter.getRaceViewerURL(data.getRegattaName(), data.getTrackedRaceName());
|
||||
String raceViewerURL = presenter.getRaceViewerURL(data.getLeaderboardName(), data.getRegattaAndRaceIdentifier());
|
||||
sb.append(TEMPLATE.raceViewerLinkButton(styleNames, text, raceViewerURL));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ public class RaceListContainer<T extends RaceMetadataDTO<?>> extends Composite i
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(CollectionResult<T> data, long nextUpdate, int updateNo) {
|
||||
public void setData(CollectionResult<T> data) {
|
||||
setRaceListData(data == null ? null : data.getValues());
|
||||
}
|
||||
|
||||
|
||||
+26
-3
@@ -1,10 +1,12 @@
|
||||
package com.sap.sailing.gwt.home.client.place.event.partials.racelist;
|
||||
|
||||
import com.google.gwt.cell.client.Cell;
|
||||
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
|
||||
import com.google.gwt.user.cellview.client.Header;
|
||||
import com.google.gwt.user.cellview.client.TextHeader;
|
||||
import com.google.gwt.user.cellview.client.SafeHtmlHeader;
|
||||
import com.sap.sailing.domain.common.InvertibleComparator;
|
||||
import com.sap.sailing.domain.common.SortingOrder;
|
||||
import com.sap.sailing.gwt.home.client.place.event.partials.raceListLive.RacesListLiveResources;
|
||||
import com.sap.sailing.gwt.ui.client.shared.controls.SortableColumn;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
@@ -16,11 +18,11 @@ public abstract class SortableRaceListColumn<T, C> extends SortableColumn<T, C>
|
||||
private boolean showDetails = true;
|
||||
|
||||
protected SortableRaceListColumn(String headerText, Cell<C> cell, InvertibleComparator<T> comparator) {
|
||||
this(new TextHeader(headerText), cell, comparator);
|
||||
this(new WrappedTextHeader(headerText), cell, comparator);
|
||||
}
|
||||
|
||||
protected SortableRaceListColumn(String headerText, Cell<C> cell, InvertibleComparator<T> comparator, SortingOrder preferredSortingOrder) {
|
||||
this(new TextHeader(headerText), cell, comparator, preferredSortingOrder);
|
||||
this(new WrappedTextHeader(headerText), cell, comparator, preferredSortingOrder);
|
||||
}
|
||||
|
||||
protected SortableRaceListColumn(Header<?> header, Cell<C> cell, InvertibleComparator<T> comparator) {
|
||||
@@ -54,4 +56,25 @@ public abstract class SortableRaceListColumn<T, C> extends SortableColumn<T, C>
|
||||
protected final String getStyleNamesString(String... styleNames) {
|
||||
return Util.join(" ", styleNames);
|
||||
}
|
||||
|
||||
private static final String COLUMN_HIDDEN_STYLE = RacesListLiveResources.INSTANCE.css().racesListHideColumn();
|
||||
|
||||
protected final String getCurrentHeaderStyle() {
|
||||
return getShowOrHiddenStyle(getHeaderStyle());
|
||||
}
|
||||
|
||||
protected final String getCurrentColumnStyle() {
|
||||
return getShowOrHiddenStyle(getColumnStyle());
|
||||
}
|
||||
|
||||
private String getShowOrHiddenStyle(String showStyle) {
|
||||
showStyle = showStyle == null ? "" : showStyle;
|
||||
return showDetails ? showStyle : getStyleNamesString(showStyle, COLUMN_HIDDEN_STYLE);
|
||||
}
|
||||
|
||||
private static class WrappedTextHeader extends SafeHtmlHeader {
|
||||
public WrappedTextHeader(String headerText) {
|
||||
super(SafeHtmlUtils.fromTrustedString("<div>" + headerText + "</div>"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -19,9 +19,9 @@ public class RegattaHeader extends Composite {
|
||||
@UiField AnchorElement headerBodyUi;
|
||||
@UiField AnchorElement headerArrowUi;
|
||||
|
||||
public RegattaHeader(RegattaMetadataDTO regattaMetadata) {
|
||||
public RegattaHeader(RegattaMetadataDTO regattaMetadata, boolean showStateMarker) {
|
||||
initWidget(uiBinder.createAndBindUi(this));
|
||||
headerBodyUi.appendChild(new RegattaHeaderBody(regattaMetadata).getElement());
|
||||
headerBodyUi.appendChild(new RegattaHeaderBody(regattaMetadata, showStateMarker).getElement());
|
||||
}
|
||||
|
||||
public void setRegattaNavigation(PlaceNavigation<?> placeNavigation) {
|
||||
|
||||
+5
-2
@@ -12,7 +12,9 @@ import com.google.gwt.user.client.ui.UIObject;
|
||||
import com.sap.sailing.gwt.common.client.BoatClassImageResolver;
|
||||
import com.sap.sailing.gwt.home.client.shared.LabelTypeUtil;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.eventview.HasRegattaMetadata.RegattaState;
|
||||
import com.sap.sailing.gwt.ui.shared.eventview.RegattaMetadataDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.general.LabelType;
|
||||
|
||||
public class RegattaHeaderBody extends UIObject {
|
||||
|
||||
@@ -27,13 +29,14 @@ public class RegattaHeaderBody extends UIObject {
|
||||
@UiField protected DivElement labelUi;
|
||||
@UiField protected DivElement detailsItemContainerUi;
|
||||
|
||||
public RegattaHeaderBody(RegattaMetadataDTO regattaMetadata) {
|
||||
public RegattaHeaderBody(RegattaMetadataDTO regattaMetadata, boolean showStateMarker) {
|
||||
RegattaHeaderResources.INSTANCE.css().ensureInjected();
|
||||
setElement(uiBinder.createAndBindUi(this));
|
||||
ImageResource logo = BoatClassImageResolver.getBoatClassIconResource(regattaMetadata.getBoatClass());
|
||||
logoUi.getStyle().setBackgroundImage("url('" + logo.getSafeUri().asString() + "')");
|
||||
nameUi.setInnerText(regattaMetadata.getDisplayName());
|
||||
LabelTypeUtil.renderLabelTypeOrHide(labelUi, regattaMetadata.getState().getStateMarker());
|
||||
RegattaState state = regattaMetadata.getState();
|
||||
LabelTypeUtil.renderLabelTypeOrHide(labelUi, showStateMarker ? state.getStateMarker() : LabelType.NONE);
|
||||
addDetailsItem(regattaMetadata.getCompetitorsCount(), I18N.competitorsCount(regattaMetadata.getCompetitorsCount()));
|
||||
addDetailsItem(regattaMetadata.getRaceCount(), I18N.racesCount(regattaMetadata.getRaceCount()));
|
||||
String defaultCourseAreaName = regattaMetadata.getDefaultCourseAreaName();
|
||||
|
||||
+2
-2
@@ -75,8 +75,8 @@ public class UpdatesBoxItem extends Widget {
|
||||
placeNavigation = presenter.getRegattaLeaderboardNavigation(((LeaderboardNewsEntryDTO) entry).getLeaderboardName());
|
||||
} else if(entry instanceof AbstractRaceNewsEntryDTO) {
|
||||
AbstractRaceNewsEntryDTO raceEntry = (AbstractRaceNewsEntryDTO) entry;
|
||||
if(raceEntry.getTrackedRaceName() != null) {
|
||||
directLink = presenter.getRaceViewerURL(raceEntry.getRegattaName(), raceEntry.getTrackedRaceName());
|
||||
if(raceEntry.getRegattaAndRaceIdentfier() != null) {
|
||||
directLink = presenter.getRaceViewerURL(raceEntry.getLeaderboardName(), raceEntry.getRegattaAndRaceIdentfier());
|
||||
}
|
||||
}
|
||||
if(placeNavigation != null) {
|
||||
|
||||
+2
-2
@@ -132,8 +132,8 @@ public class RegattaRacesTabView extends Composite implements RegattaTabView<Reg
|
||||
refreshManager.add(liveRacesListUi.getRefreshable(), new GetLiveRacesForRegattaAction(myPlace.getCtx().getEventDTO().getId(), myPlace.getRegattaId()));
|
||||
refreshManager.add(new RefreshableWidget<RegattaWithProgressDTO>() {
|
||||
@Override
|
||||
public void setData(RegattaWithProgressDTO data, long nextUpdate, int updateNo) {
|
||||
regattaInfoContainerUi.setWidget(new MultiRegattaListItem(data));
|
||||
public void setData(RegattaWithProgressDTO data) {
|
||||
regattaInfoContainerUi.setWidget(new MultiRegattaListItem(data, true));
|
||||
}
|
||||
}, new GetRegattaWithProgressAction(myPlace.getCtx().getEventDTO().getId(), myPlace.getRegattaId()));
|
||||
refreshManager.add(raceListContainerUi, new GetFinishedRacesAction(myPlace.getCtx().getEventDTO().getId(), myPlace.getRegattaId()));
|
||||
|
||||
+10
-5
@@ -2,6 +2,8 @@ package com.sap.sailing.gwt.home.client.place.event.regatta.tabs.reload;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.google.gwt.core.client.Scheduler;
|
||||
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
|
||||
@@ -17,6 +19,7 @@ import com.sap.sailing.gwt.ui.shared.dispatch.DTO;
|
||||
import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL;
|
||||
|
||||
public class RefreshManager {
|
||||
private static final Logger LOG = Logger.getLogger(RefreshManager.class.getName());
|
||||
|
||||
private static final long PAUSE_ON_ERROR = 1000 * 30;
|
||||
private List<RefreshHolder<DTO, Action<ResultWithTTL<DTO>>>> refreshables = new ArrayList<>();
|
||||
@@ -47,16 +50,14 @@ public class RefreshManager {
|
||||
});
|
||||
}
|
||||
|
||||
private int updateNo;
|
||||
|
||||
private void update() {
|
||||
updateNo++;
|
||||
for (final RefreshHolder<DTO, Action<ResultWithTTL<DTO>>> refreshable : refreshables) {
|
||||
// Everything that needs refresh within the next 5000ms will be refreshed now.
|
||||
// This makes it possible to use batching resulting in less requests.
|
||||
if (!refreshable.callRunning && refreshable.timeout < System.currentTimeMillis() + 5000) {
|
||||
refreshable.callRunning = true;
|
||||
actionExecutor.execute(refreshable.provider.getAction(), new AsyncCallback<ResultWithTTL<DTO>>() {
|
||||
final Action<ResultWithTTL<DTO>> action = refreshable.provider.getAction();
|
||||
actionExecutor.execute(action, new AsyncCallback<ResultWithTTL<DTO>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
refreshable.callRunning = false;
|
||||
@@ -68,7 +69,11 @@ public class RefreshManager {
|
||||
public void onSuccess(ResultWithTTL<DTO> result) {
|
||||
refreshable.callRunning = false;
|
||||
refreshable.timeout = System.currentTimeMillis() + result.getTtl();
|
||||
refreshable.widget.setData(result.getDto(), refreshable.timeout, updateNo);
|
||||
try {
|
||||
refreshable.widget.setData(result.getDto());
|
||||
} catch(Throwable error) {
|
||||
LOG.log(Level.SEVERE, "Error while refreshing content with action " + action.getClass().getName(), error);
|
||||
}
|
||||
reschedule();
|
||||
}
|
||||
});
|
||||
|
||||
+1
-1
@@ -3,5 +3,5 @@ package com.sap.sailing.gwt.home.client.place.event.regatta.tabs.reload;
|
||||
import com.sap.sailing.gwt.ui.shared.dispatch.DTO;
|
||||
|
||||
public interface RefreshableWidget<D extends DTO> {
|
||||
void setData(D data, long nextUpdate, int updateNo);
|
||||
void setData(D data);
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package com.sap.sailing.gwt.home.client.shared.media;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gwt.dom.client.Style.Overflow;
|
||||
import com.google.gwt.event.dom.client.KeyCodes;
|
||||
@@ -27,7 +27,7 @@ public class SailingFullscreenViewer implements FullscreenViewer<SailingImageDTO
|
||||
};
|
||||
};
|
||||
|
||||
public void show(SailingImageDTO selected, List<SailingImageDTO> images) {
|
||||
public void show(SailingImageDTO selected, Collection<SailingImageDTO> images) {
|
||||
final SailingGalleryPlayer viewer = new SailingGalleryPlayer(selected, images);
|
||||
|
||||
Window.addResizeHandler(new ResizeHandler() {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user