mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-06 12:23:55 +00:00
Merge branch 'master' into bug3938
This commit is contained in:
commit
34386899e7
20 files changed
+508
-138
No files matched your search
+4
@@ -2,6 +2,8 @@ package com.sap.sailing.datamining.shared;
|
||||
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.LegType;
|
||||
import com.sap.sailing.domain.common.ManeuverType;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.common.impl.CentralAngleDistance;
|
||||
import com.sap.sailing.domain.common.impl.MeterDistance;
|
||||
import com.sap.sailing.domain.common.impl.NauticalMileDistance;
|
||||
@@ -16,6 +18,8 @@ public final class SailingDataMiningSerializationDummy implements SerializationD
|
||||
private CentralAngleDistance centralAngleDistance;
|
||||
private MeterDistance meterDistance;
|
||||
private NauticalMileDistance nauticalMileDistance;
|
||||
private ManeuverType maneuverType;
|
||||
private Tack tack;
|
||||
|
||||
private SailingDataMiningSerializationDummy() { }
|
||||
|
||||
|
||||
+13
-2
@@ -16,6 +16,7 @@ Race=Race
|
||||
Competitor=Competitor
|
||||
Boat=Boat
|
||||
Team=Team
|
||||
CompetitorSearchTag=Competitor Search Tag
|
||||
LeaderboardSailingDomainRetrieverChain=Leaderboards
|
||||
RaceSailingDomainRetrieverChain=Races
|
||||
LegSailingDomainRetrieverChain=Legs
|
||||
@@ -23,12 +24,14 @@ GPSFixSailingDomainRetrieverChain=GPS-Fixes
|
||||
MarkPassingSailingDomainRetrieverChain=Mark Passings
|
||||
RaceResultSailingDomainRetrieverChain=Race Results
|
||||
RaceOfCompetitorSailingDomainRetrieverChain=Races of Competitors
|
||||
ManeuverSailingDomainRetrieverChain=Maneuver
|
||||
LeaderboardGroup=Leaderboard Group
|
||||
Leaderboard=Leaderboard
|
||||
Leg=Leg
|
||||
MarkPassing=Mark Passing
|
||||
LegOfCompetitor=Leg of competitor
|
||||
GpsFix=GPS-Fix
|
||||
Maneuver=Maneuver
|
||||
WindStrengthInBeaufort=Wind Strength in Beaufort
|
||||
Bft0=Calm
|
||||
Bft1=Light air
|
||||
@@ -43,7 +46,8 @@ Bft9=Strong gale
|
||||
Bft10=Storm
|
||||
Bft11=Violent storm
|
||||
Bft12=Hurricane
|
||||
RelativeScoreInRace=Relative score in race (0 best; 1 worst)
|
||||
RelativeScore=Relative Score (0 best; 1 worst)
|
||||
AbsoluteRank=Absolute Rank
|
||||
WindSpeedInBeaufort=Wind speed in Bft
|
||||
DistanceAtStart=Distance to start at start
|
||||
SpeedWhenStarting=Speed when starting
|
||||
@@ -60,4 +64,11 @@ NumberOfWins=Number of Wins
|
||||
RankGainsOrLossesBetweenFirstMarkAndFinish=Rank Gains or Losses (1st Mark -> Finish)
|
||||
IsTracked=Is Tracked
|
||||
NumberOfCompetitorFixes=Number of Competitor Fixes
|
||||
NumberOfMarkFixes=Number of Mark Fixes
|
||||
NumberOfMarkFixes=Number of Mark Fixes
|
||||
ManeuverType=Maneuver Type
|
||||
Tack=Tack
|
||||
SpeedBefore=Speed Before Maneuver
|
||||
SpeedAfter=Speed After Maneuver
|
||||
DirectionChange=Direction Change in Degrees
|
||||
ManeuverLoss=Maneuver Loss
|
||||
Waypoint=Waypoint
|
||||
+13
-2
@@ -3,6 +3,7 @@ DistanceTraveled=zur
|
||||
Boat=Boot
|
||||
Team=Team
|
||||
Name=Name
|
||||
CompetitorSearchTag=Teilnehmer Such-Tag
|
||||
Nationality=Nationalitäts
|
||||
Acronym=Abkürzung
|
||||
SailID=Segelnummer
|
||||
@@ -21,12 +22,14 @@ GPSFixSailingDomainRetrieverChain=GPS-Fixes
|
||||
MarkPassingSailingDomainRetrieverChain=Tonnenrundungen
|
||||
RaceResultSailingDomainRetrieverChain=Rennergebnisse
|
||||
RaceOfCompetitorSailingDomainRetrieverChain=Rennen eines Teilnehmers
|
||||
ManeuverSailingDomainRetrieverChain=Manöver
|
||||
LeaderboardGroup=Ranglisten Gruppe
|
||||
Leaderboard=Rangliste
|
||||
Leg=Schenkel
|
||||
MarkPassing=Tonnenrundung
|
||||
LegOfCompetitor=Schenkel eines Teilnehmers
|
||||
GpsFix=GPS-Fix
|
||||
Maneuver=Manöver
|
||||
Speed=Geschwindigkeit
|
||||
SpeedTenSecondsBefore=Geschwindigkeit 10s vorher
|
||||
WindStrengthInBeaufort=Windstärke in Beaufort
|
||||
@@ -43,7 +46,8 @@ Bft9=Sturm
|
||||
Bft10=schwerer Sturm
|
||||
Bft11=orkanartiger Sturm
|
||||
Bft12=Orkan
|
||||
RelativeScoreInRace=Relative Wertung im Rennen (0 am besten; 1 am schlechtesten)
|
||||
RelativeScore=Relative Wertung (0 am besten; 1 am schlechtesten)
|
||||
AbsoluteRank=Absolute Platzierung
|
||||
WindSpeedInBeaufort=Windgeschwindigkeit in Bft.
|
||||
DistanceAtStart=Distanz zur Startlinie zum Startzeitpunkt
|
||||
SpeedWhenStarting=Geschwindigkeit beim Überqueren der Startlinie
|
||||
@@ -60,4 +64,11 @@ NumberOfWins=Anzahl der Siege
|
||||
RankGainsOrLossesBetweenFirstMarkAndFinish=Positions-Verluste oder -Gewinne (1ter Wegpunkt -> Ziel)
|
||||
IsTracked=Ist getracked
|
||||
NumberOfCompetitorFixes=Anzahl der Teilnehmer-Fixes
|
||||
NumberOfMarkFixes=Anzahl der Tonnen-Fixes
|
||||
NumberOfMarkFixes=Anzahl der Tonnen-Fixes
|
||||
ManeuverType=Art des Manövers
|
||||
Tack=Seite
|
||||
SpeedBefore=Geschwindigkeit bevor dem Manöver
|
||||
SpeedAfter=Geschwindigkeit nach dem Manöver
|
||||
DirectionChange=Richtungsänderung in Grad
|
||||
ManeuverLoss=Manöververlust
|
||||
Waypoint=Wegpunkt
|
||||
@@ -10,6 +10,7 @@ import org.osgi.framework.BundleContext;
|
||||
import com.sap.sailing.datamining.data.HasGPSFixContext;
|
||||
import com.sap.sailing.datamining.data.HasLeaderboardContext;
|
||||
import com.sap.sailing.datamining.data.HasLeaderboardGroupContext;
|
||||
import com.sap.sailing.datamining.data.HasManeuverContext;
|
||||
import com.sap.sailing.datamining.data.HasMarkPassingContext;
|
||||
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.data.HasRaceResultOfCompetitorContext;
|
||||
@@ -82,6 +83,7 @@ public class Activator extends AbstractDataMiningActivatorWithPredefinedQueries
|
||||
internalClasses.add(HasTrackedLegContext.class);
|
||||
internalClasses.add(HasTrackedLegOfCompetitorContext.class);
|
||||
internalClasses.add(HasGPSFixContext.class);
|
||||
internalClasses.add(HasManeuverContext.class);
|
||||
internalClasses.add(HasMarkPassingContext.class);
|
||||
internalClasses.add(HasRaceOfCompetitorContext.class);
|
||||
internalClasses.add(HasLeaderboardGroupContext.class);
|
||||
|
||||
+13
-5
@@ -5,6 +5,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.HasManeuverContext;
|
||||
import com.sap.sailing.datamining.data.HasMarkPassingContext;
|
||||
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.data.HasRaceResultOfCompetitorContext;
|
||||
@@ -15,6 +16,7 @@ import com.sap.sailing.datamining.impl.components.CompetitorOfRaceInLeaderboardR
|
||||
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.ManeuverRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.MarkPassingRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.RaceOfCompetitorRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.TrackedLegOfCompetitorRetrievalProcessor;
|
||||
@@ -48,11 +50,6 @@ public class SailingDataRetrievalChainDefinitions {
|
||||
trackedRaceRetrieverChainDefinition.endWith(LeaderboardRetrievalProcessor.class, TrackedRaceRetrievalProcessor.class,
|
||||
HasTrackedRaceContext.class, "Race");
|
||||
dataRetrieverChainDefinitions.add(trackedRaceRetrieverChainDefinition);
|
||||
|
||||
final DataRetrieverChainDefinition<RacingEventService, HasMarkPassingContext> markPassingRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
|
||||
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");
|
||||
@@ -71,6 +68,17 @@ public class SailingDataRetrievalChainDefinitions {
|
||||
gpsFixRetrieverChainDefinition.endWith(TrackedLegOfCompetitorRetrievalProcessor.class, GPSFixRetrievalProcessor.class,
|
||||
HasGPSFixContext.class, "GpsFix");
|
||||
dataRetrieverChainDefinitions.add(gpsFixRetrieverChainDefinition);
|
||||
|
||||
final DataRetrieverChainDefinition<RacingEventService, HasManeuverContext> maneuverRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
|
||||
legOfCompetitorRetrieverChainDefinition, HasManeuverContext.class, "ManeuverSailingDomainRetrieverChain");
|
||||
maneuverRetrieverChainDefinition.endWith(TrackedLegOfCompetitorRetrievalProcessor.class, ManeuverRetrievalProcessor.class,
|
||||
HasManeuverContext.class, "Maneuver");
|
||||
dataRetrieverChainDefinitions.add(maneuverRetrieverChainDefinition);
|
||||
|
||||
final DataRetrieverChainDefinition<RacingEventService, HasMarkPassingContext> markPassingRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
|
||||
legOfCompetitorRetrieverChainDefinition, HasMarkPassingContext.class, "MarkPassingSailingDomainRetrieverChain");
|
||||
markPassingRetrieverChainDefinition.endWith(TrackedLegOfCompetitorRetrievalProcessor.class, MarkPassingRetrievalProcessor.class, HasMarkPassingContext.class, "MarkPassing");
|
||||
dataRetrieverChainDefinitions.add(markPassingRetrieverChainDefinition);
|
||||
}
|
||||
|
||||
public Iterable<DataRetrieverChainDefinition<?, ?>> get() {
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.sap.sailing.datamining.data;
|
||||
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.ManeuverType;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sse.datamining.annotations.Connector;
|
||||
import com.sap.sse.datamining.annotations.Dimension;
|
||||
import com.sap.sse.datamining.annotations.Statistic;
|
||||
|
||||
public interface HasManeuverContext {
|
||||
|
||||
@Connector(scanForStatistics=false)
|
||||
HasTrackedLegOfCompetitorContext getTrackedLegOfCompetitorContext();
|
||||
|
||||
Maneuver getManeuver();
|
||||
|
||||
//TODO Clean-Up:
|
||||
// Move Dimensions and Statistics to Maneuver and connect to it
|
||||
@Dimension(messageKey="ManeuverType", ordinal=12)
|
||||
ManeuverType getManeuverType();
|
||||
|
||||
@Dimension(messageKey="Tack", ordinal=13)
|
||||
Tack getTack();
|
||||
|
||||
@Connector(messageKey="SpeedBefore", ordinal=0)
|
||||
SpeedWithBearing getSpeedBefore();
|
||||
@Connector(messageKey="SpeedAfter", ordinal=1)
|
||||
SpeedWithBearing getSpeedAfter();
|
||||
|
||||
@Statistic(messageKey="DirectionChange", resultDecimals=2, ordinal=2)
|
||||
Double getDirectionChangeInDegrees();
|
||||
|
||||
@Statistic(messageKey="ManeuverLoss", resultDecimals=0, ordinal=3)
|
||||
Distance getManeuverLoss();
|
||||
|
||||
}
|
||||
+28
-16
@@ -1,29 +1,41 @@
|
||||
package com.sap.sailing.datamining.data;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.tracking.MarkPassingManeuver;
|
||||
import com.sap.sse.datamining.annotations.Connector;
|
||||
import com.sap.sse.datamining.annotations.Dimension;
|
||||
import com.sap.sse.datamining.annotations.Statistic;
|
||||
|
||||
public interface HasMarkPassingContext {
|
||||
|
||||
@Connector
|
||||
HasTrackedRaceContext getTrackedRaceContext();
|
||||
@Connector(scanForStatistics=false)
|
||||
HasTrackedLegOfCompetitorContext getTrackedLegOfCompetitorContext();
|
||||
|
||||
MarkPassingManeuver getManeuver();
|
||||
|
||||
//TODO Clean-Up:
|
||||
// Move Dimensions and Statistics to Maneuver/MarkPassingManeuver and connect to it
|
||||
// Find a way to implement HasManeuverContext and HasMarkPassingManeuver with a base class
|
||||
@Dimension(messageKey="Tack", ordinal=12)
|
||||
Tack getTack();
|
||||
|
||||
@Connector(messageKey="Waypoint", ordinal=13)
|
||||
Waypoint getWaypoint();
|
||||
|
||||
@Connector
|
||||
MarkPassing getMarkPassing();
|
||||
@Connector(messageKey="SpeedBefore", ordinal=0)
|
||||
SpeedWithBearing getSpeedBefore();
|
||||
@Connector(messageKey="SpeedAfter", ordinal=1)
|
||||
SpeedWithBearing getSpeedAfter();
|
||||
|
||||
@Connector(messageKey="Competitor")
|
||||
Competitor getCompetitor();
|
||||
@Statistic(messageKey="DirectionChange", resultDecimals=2, ordinal=2)
|
||||
Double getDirectionChangeInDegrees();
|
||||
|
||||
@Connector(messageKey="Speed", ordinal=1)
|
||||
Speed getSpeed();
|
||||
@Statistic(messageKey="RelativeScore", ordinal=3, resultDecimals=2)
|
||||
Double getRelativeRank();
|
||||
|
||||
@Connector(messageKey="SpeedTenSecondsBefore", ordinal=2)
|
||||
Speed getSpeedTenSecondsBefore();
|
||||
@Statistic(messageKey="AbsoluteRank", ordinal=4, resultDecimals=2)
|
||||
Double getAbsoluteRank();
|
||||
|
||||
@Dimension(messageKey="LegType", ordinal=6)
|
||||
String getPreviousLegTypeSignifier() throws NoWindException;
|
||||
}
|
||||
+4
@@ -4,6 +4,7 @@ import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sse.datamining.annotations.Connector;
|
||||
import com.sap.sse.datamining.annotations.Dimension;
|
||||
import com.sap.sse.datamining.annotations.Statistic;
|
||||
|
||||
public interface HasRaceOfCompetitorContext {
|
||||
@@ -14,6 +15,9 @@ public interface HasRaceOfCompetitorContext {
|
||||
@Connector(messageKey="Competitor")
|
||||
public Competitor getCompetitor();
|
||||
|
||||
@Dimension(messageKey="CompetitorSearchTag", ordinal=11) // TODO Clean me: Move Dimension to Competitor when possible
|
||||
public String getCompetitorSearchTag();
|
||||
|
||||
@Statistic(messageKey="DistanceAtStart", resultDecimals=2, ordinal=0)
|
||||
public Distance getDistanceToStartLineAtStart();
|
||||
|
||||
|
||||
+17
-11
@@ -12,22 +12,28 @@ public interface HasRaceResultOfCompetitorContext {
|
||||
|
||||
@Connector(messageKey="Competitor")
|
||||
public Competitor getCompetitor();
|
||||
|
||||
/**
|
||||
* 0 means the competitor won the race, 1 means the competitor ranked last
|
||||
*/
|
||||
@Statistic(messageKey="RelativeScoreInRace", ordinal=1, resultDecimals=2)
|
||||
public double getRelativeRank();
|
||||
|
||||
@Dimension(messageKey="WindSpeedInBeaufort")
|
||||
int getAverageWindSpeedInRoundedBeaufort();
|
||||
|
||||
@Dimension(messageKey="Regatta")
|
||||
String getRegattaName();
|
||||
|
||||
@Statistic(messageKey="NumberOfPodiumFinish", ordinal=2)
|
||||
@Dimension(messageKey="CompetitorSearchTag", ordinal=11) // TODO Clean me: Move Dimension to Competitor when possible
|
||||
public String getCompetitorSearchTag();
|
||||
|
||||
@Dimension(messageKey="WindSpeedInBeaufort")
|
||||
int getAverageWindSpeedInRoundedBeaufort();
|
||||
|
||||
/**
|
||||
* 0 means the competitor won the race, 1 means the competitor ranked last
|
||||
*/
|
||||
@Statistic(messageKey="RelativeScore", ordinal=1, resultDecimals=2)
|
||||
public Double getRelativeRank();
|
||||
|
||||
@Statistic(messageKey="AbsoluteRank", ordinal=2, resultDecimals=2)
|
||||
public Double getAbsoluteRank();
|
||||
|
||||
@Statistic(messageKey="NumberOfPodiumFinish", ordinal=3)
|
||||
public Boolean isPodiumFinish();
|
||||
|
||||
@Statistic(messageKey="NumberOfWins", ordinal=3)
|
||||
@Statistic(messageKey="NumberOfWins", ordinal=4)
|
||||
public Boolean isWin();
|
||||
}
|
||||
+10
@@ -4,6 +4,7 @@ import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||
import com.sap.sse.datamining.annotations.Connector;
|
||||
import com.sap.sse.datamining.annotations.Dimension;
|
||||
import com.sap.sse.datamining.annotations.Statistic;
|
||||
|
||||
public interface HasTrackedLegOfCompetitorContext {
|
||||
@@ -12,6 +13,9 @@ public interface HasTrackedLegOfCompetitorContext {
|
||||
public HasTrackedLegContext getTrackedLegContext();
|
||||
|
||||
public TrackedLegOfCompetitor getTrackedLegOfCompetitor();
|
||||
|
||||
@Dimension(messageKey="CompetitorSearchTag", ordinal=11) // TODO Clean me: Move Dimension to Competitor when possible
|
||||
public String getCompetitorSearchTag();
|
||||
|
||||
@Connector(messageKey="Competitor")
|
||||
public Competitor getCompetitor();
|
||||
@@ -21,5 +25,11 @@ public interface HasTrackedLegOfCompetitorContext {
|
||||
|
||||
@Statistic(messageKey="RankGainsOrLosses", resultDecimals=2, ordinal=1)
|
||||
public Double getRankGainsOrLosses();
|
||||
|
||||
@Statistic(messageKey="RelativeScore", resultDecimals=2, ordinal=2)
|
||||
public Double getRelativeRank();
|
||||
|
||||
@Statistic(messageKey="AbsoluteRank", resultDecimals=2, ordinal=3)
|
||||
public Double getAbsoluteRank();
|
||||
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.sap.sailing.datamining.impl.components;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import com.sap.sailing.datamining.data.HasManeuverContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.impl.data.ManeuverWithContext;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.datamining.components.Processor;
|
||||
import com.sap.sse.datamining.impl.components.AbstractRetrievalProcessor;
|
||||
|
||||
public class ManeuverRetrievalProcessor extends AbstractRetrievalProcessor<HasTrackedLegOfCompetitorContext, HasManeuverContext> {
|
||||
|
||||
public ManeuverRetrievalProcessor(ExecutorService executor, Collection<Processor<HasManeuverContext, ?>> resultReceivers, int retrievalLevel) {
|
||||
super(HasTrackedLegOfCompetitorContext.class, HasManeuverContext.class, executor, resultReceivers, retrievalLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<HasManeuverContext> retrieveData(HasTrackedLegOfCompetitorContext element) {
|
||||
Collection<HasManeuverContext> maneuversWithContext = new ArrayList<>();
|
||||
TimePoint finishTime = element.getTrackedLegOfCompetitor().getFinishTime();
|
||||
if (finishTime != null) {
|
||||
try {
|
||||
List<Maneuver> maneuvers = element.getTrackedLegOfCompetitor().getManeuvers(finishTime, false);
|
||||
for (Maneuver maneuver : maneuvers) {
|
||||
maneuversWithContext.add(new ManeuverWithContext(element, maneuver));
|
||||
}
|
||||
} catch (NoWindException e) {
|
||||
throw new IllegalStateException("No wind retrieving the maneuvers", e);
|
||||
}
|
||||
}
|
||||
return maneuversWithContext;
|
||||
}
|
||||
|
||||
}
|
||||
+23
-24
@@ -1,46 +1,45 @@
|
||||
package com.sap.sailing.datamining.impl.components;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import com.sap.sailing.datamining.data.HasMarkPassingContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedRaceContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.impl.data.MarkPassingWithContext;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.common.ManeuverType;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sailing.domain.tracking.MarkPassingManeuver;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.datamining.components.Processor;
|
||||
import com.sap.sse.datamining.impl.components.AbstractRetrievalProcessor;
|
||||
|
||||
public class MarkPassingRetrievalProcessor extends AbstractRetrievalProcessor<HasTrackedRaceContext, HasMarkPassingContext> {
|
||||
public class MarkPassingRetrievalProcessor extends AbstractRetrievalProcessor<HasTrackedLegOfCompetitorContext, HasMarkPassingContext> {
|
||||
|
||||
public MarkPassingRetrievalProcessor(ExecutorService executor,
|
||||
Collection<Processor<HasMarkPassingContext, ?>> resultReceivers, int retrievalLevel) {
|
||||
super(HasTrackedRaceContext.class, HasMarkPassingContext.class, executor, resultReceivers, retrievalLevel);
|
||||
super(HasTrackedLegOfCompetitorContext.class, HasMarkPassingContext.class, executor, resultReceivers, retrievalLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<HasMarkPassingContext> retrieveData(HasTrackedRaceContext element) {
|
||||
TrackedRace trackedRace = element.getTrackedRace();
|
||||
Set<HasMarkPassingContext> result = new HashSet<>();
|
||||
trackedRace.getRace().getCourse().lockForRead();
|
||||
try {
|
||||
for (Competitor competitor : trackedRace.getRace().getCompetitors()) {
|
||||
NavigableSet<MarkPassing> markPassingsForCompetitor = trackedRace.getMarkPassings(competitor);
|
||||
trackedRace.lockForRead(markPassingsForCompetitor);
|
||||
try {
|
||||
markPassingsForCompetitor.stream().forEach(mp->result.add(new MarkPassingWithContext(element, mp)));
|
||||
} finally {
|
||||
trackedRace.unlockAfterRead(markPassingsForCompetitor);
|
||||
protected Iterable<HasMarkPassingContext> retrieveData(HasTrackedLegOfCompetitorContext element) {
|
||||
Collection<HasMarkPassingContext> maneuversWithContext = new ArrayList<>();
|
||||
TimePoint finishTime = element.getTrackedLegOfCompetitor().getFinishTime();
|
||||
if (finishTime != null) {
|
||||
try {
|
||||
List<Maneuver> maneuvers = element.getTrackedLegOfCompetitor().getManeuvers(finishTime, false);
|
||||
for (Maneuver maneuver : maneuvers) {
|
||||
if (maneuver.getType() == ManeuverType.MARK_PASSING) {
|
||||
maneuversWithContext.add(new MarkPassingWithContext(element, (MarkPassingManeuver) maneuver));
|
||||
}
|
||||
}
|
||||
} catch (NoWindException e) {
|
||||
throw new IllegalStateException("No wind retrieving the mark passings", e);
|
||||
}
|
||||
} finally {
|
||||
trackedRace.getRace().getCourse().unlockAfterRead();
|
||||
}
|
||||
return result;
|
||||
return maneuversWithContext;
|
||||
}
|
||||
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package com.sap.sailing.datamining.impl.data;
|
||||
|
||||
import com.sap.sailing.datamining.data.HasManeuverContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.ManeuverType;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
|
||||
public class ManeuverWithContext implements HasManeuverContext {
|
||||
|
||||
private final HasTrackedLegOfCompetitorContext trackedLegOfCompetitor;
|
||||
private final Maneuver maneuver;
|
||||
|
||||
public ManeuverWithContext(HasTrackedLegOfCompetitorContext trackedLegOfCompetitor, Maneuver maneuver) {
|
||||
this.trackedLegOfCompetitor = trackedLegOfCompetitor;
|
||||
this.maneuver = maneuver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HasTrackedLegOfCompetitorContext getTrackedLegOfCompetitorContext() {
|
||||
return trackedLegOfCompetitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Maneuver getManeuver() {
|
||||
return maneuver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManeuverType getManeuverType() {
|
||||
return getManeuver().getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tack getTack() {
|
||||
return getManeuver().getNewTack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpeedWithBearing getSpeedBefore() {
|
||||
return getManeuver().getSpeedWithBearingBefore();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpeedWithBearing getSpeedAfter() {
|
||||
return getManeuver().getSpeedWithBearingAfter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getDirectionChangeInDegrees() {
|
||||
return getManeuver().getDirectionChangeInDegrees();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getManeuverLoss() {
|
||||
return getManeuver().getManeuverLoss();
|
||||
}
|
||||
|
||||
}
|
||||
+56
-49
@@ -1,74 +1,81 @@
|
||||
package com.sap.sailing.datamining.impl.data;
|
||||
|
||||
import com.sap.sailing.datamining.data.HasMarkPassingContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedRaceContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.tracking.MarkPassingManeuver;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class MarkPassingWithContext implements HasMarkPassingContext {
|
||||
private final HasTrackedRaceContext trackedRaceContext;
|
||||
private final MarkPassing markPassing;
|
||||
|
||||
public MarkPassingWithContext(HasTrackedRaceContext trackedRaceContext, MarkPassing markPassing) {
|
||||
super();
|
||||
this.trackedRaceContext = trackedRaceContext;
|
||||
this.markPassing = markPassing;
|
||||
private final HasTrackedLegOfCompetitorContext trackedLegOfCompetitor;
|
||||
private final MarkPassingManeuver maneuver;
|
||||
|
||||
private Double absoluteRank;
|
||||
private boolean rankHasBeenInitialized;
|
||||
|
||||
public MarkPassingWithContext(HasTrackedLegOfCompetitorContext trackedLegOfCompetitor, MarkPassingManeuver maneuver) {
|
||||
this.trackedLegOfCompetitor = trackedLegOfCompetitor;
|
||||
this.maneuver = maneuver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HasTrackedRaceContext getTrackedRaceContext() {
|
||||
return trackedRaceContext;
|
||||
public HasTrackedLegOfCompetitorContext getTrackedLegOfCompetitorContext() {
|
||||
return trackedLegOfCompetitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkPassing getMarkPassing() {
|
||||
return markPassing;
|
||||
public MarkPassingManeuver getManeuver() {
|
||||
return maneuver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Competitor getCompetitor() {
|
||||
return markPassing.getCompetitor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Speed getSpeed() {
|
||||
return getTrackedRace().getTrack(getCompetitor()).getEstimatedSpeed(getMarkPassing().getTimePoint());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Speed getSpeedTenSecondsBefore() {
|
||||
return getTrackedRace().getTrack(getCompetitor()).getEstimatedSpeed(getMarkPassing().getTimePoint().minus(10000 /* ms */));
|
||||
}
|
||||
|
||||
private TrackedRace getTrackedRace() {
|
||||
return trackedRaceContext.getTrackedRace();
|
||||
public Tack getTack() {
|
||||
return getManeuver().getNewTack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreviousLegTypeSignifier() throws NoWindException {
|
||||
final String result;
|
||||
TrackedLeg previousLeg = getPreviousLeg();
|
||||
if (previousLeg == null) {
|
||||
result = "Start";
|
||||
} else {
|
||||
result = previousLeg.getLegType(getMarkPassing().getTimePoint()).toString();
|
||||
}
|
||||
return result;
|
||||
public Waypoint getWaypoint() {
|
||||
return getManeuver().getWaypointPassed();
|
||||
}
|
||||
|
||||
private TrackedLeg getPreviousLeg() {
|
||||
final TrackedLeg result;
|
||||
Waypoint waypoint = markPassing.getWaypoint();
|
||||
if (waypoint == getTrackedRace().getRace().getCourse().getFirstWaypoint()) {
|
||||
result = null;
|
||||
} else {
|
||||
result = getTrackedRace().getTrackedLegFinishingAt(waypoint);
|
||||
}
|
||||
return result;
|
||||
@Override
|
||||
public SpeedWithBearing getSpeedBefore() {
|
||||
return getManeuver().getSpeedWithBearingBefore();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpeedWithBearing getSpeedAfter() {
|
||||
return getManeuver().getSpeedWithBearingAfter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getDirectionChangeInDegrees() {
|
||||
return getManeuver().getDirectionChangeInDegrees();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getRelativeRank() {
|
||||
Leaderboard leaderboard = getTrackedLegOfCompetitorContext().getTrackedLegContext().getTrackedRaceContext().getLeaderboardContext().getLeaderboard();
|
||||
double competitorCount = Util.size(leaderboard.getCompetitors());
|
||||
return getAbsoluteRank() == null ? null : getAbsoluteRank() / competitorCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getAbsoluteRank() {
|
||||
if (!rankHasBeenInitialized) {
|
||||
TrackedRace trackedRace = getTrackedLegOfCompetitorContext().getTrackedLegContext().getTrackedRaceContext().getTrackedRace();
|
||||
Competitor competitor = getTrackedLegOfCompetitorContext().getCompetitor();
|
||||
int rank = trackedRace.getRank(competitor, getManeuver().getTimePoint());
|
||||
absoluteRank = rank == 0 ? null : Double.valueOf(rank);
|
||||
rankHasBeenInitialized = true;
|
||||
}
|
||||
return absoluteRank;
|
||||
}
|
||||
|
||||
}
|
||||
+10
-3
@@ -38,6 +38,11 @@ public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext {
|
||||
public Competitor getCompetitor() {
|
||||
return competitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCompetitorSearchTag() {
|
||||
return getCompetitor().getSearchTag();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getDistanceToStartLineAtStart() {
|
||||
@@ -59,7 +64,8 @@ public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext {
|
||||
Course course = getTrackedRace().getRace().getCourse();
|
||||
Waypoint firstMark = course.getFirstLeg().getTo();
|
||||
Competitor competitor = getCompetitor();
|
||||
return Double.valueOf(getTrackedRace().getRank(competitor, getTrackedRace().getMarkPassing(competitor, firstMark).getTimePoint()));
|
||||
int rank = getTrackedRace().getRank(competitor, getTrackedRace().getMarkPassing(competitor, firstMark).getTimePoint());
|
||||
return rank == 0 ? null : Double.valueOf(rank);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -97,11 +103,12 @@ public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext {
|
||||
public Double getRankGainsOrLossesBetweenFirstMarkAndFinish() {
|
||||
Double rankAtFirstMark = getRankAtFirstMark();
|
||||
Double rankAtFinish = getRankAtFinish();
|
||||
return rankAtFirstMark - rankAtFinish;
|
||||
return rankAtFirstMark != null && rankAtFinish != null ? rankAtFirstMark - rankAtFinish : null;
|
||||
}
|
||||
|
||||
private Double getRankAtFinish() {
|
||||
return Double.valueOf(getTrackedRace().getRank(getCompetitor(), getTrackedRace().getEndOfTracking()));
|
||||
int rank = getTrackedRace().getRank(getCompetitor(), getTrackedRace().getEndOfTracking());
|
||||
return rank == 0 ? null : Double.valueOf(rank);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+25
-12
@@ -62,17 +62,17 @@ public class RaceResultOfCompetitorWithContext implements HasRaceResultOfCompeti
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getRelativeRank() {
|
||||
Leaderboard leaderboard = getLeaderboard();
|
||||
final TimePoint now = MillisecondsTimePoint.now();
|
||||
double competitorCount = Util.size(leaderboard.getCompetitors());
|
||||
double points = leaderboard.getTotalPoints(competitor, raceColumn, now);
|
||||
double relativeLowPoints = leaderboard.getScoringScheme().isHigherBetter() ?
|
||||
competitorCount - points : points;
|
||||
final double result = relativeLowPoints / competitorCount;
|
||||
public String getRegattaName() {
|
||||
Leaderboard leaderboard = getLeaderboard();;
|
||||
final String result = leaderboard.getName();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCompetitorSearchTag() {
|
||||
return getCompetitor().getSearchTag();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAverageWindSpeedInRoundedBeaufort() {
|
||||
Speed exactResult = getAverageWindSpeed();
|
||||
@@ -157,10 +157,23 @@ public class RaceResultOfCompetitorWithContext implements HasRaceResultOfCompeti
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRegattaName() {
|
||||
Leaderboard leaderboard = getLeaderboard();;
|
||||
final String result = leaderboard.getName();
|
||||
return result;
|
||||
public Double getRelativeRank() {
|
||||
Leaderboard leaderboard = getLeaderboard();
|
||||
final TimePoint now = MillisecondsTimePoint.now();
|
||||
double competitorCount = Util.size(leaderboard.getCompetitors());
|
||||
Double points = leaderboard.getTotalPoints(competitor, raceColumn, now);
|
||||
if (points != null) {
|
||||
double relativeLowPoints = leaderboard.getScoringScheme().isHigherBetter() ? competitorCount - points
|
||||
: points;
|
||||
final double result = relativeLowPoints / competitorCount;
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getAbsoluteRank() {
|
||||
return getLeaderboard().getTotalPoints(competitor, raceColumn, MillisecondsTimePoint.now());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+48
-4
@@ -4,9 +4,11 @@ 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.common.Distance;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class TrackedLegOfCompetitorWithContext implements HasTrackedLegOfCompetitorContext {
|
||||
|
||||
@@ -15,6 +17,11 @@ public class TrackedLegOfCompetitorWithContext implements HasTrackedLegOfCompeti
|
||||
private final TrackedLegOfCompetitor trackedLegOfCompetitor;
|
||||
private final Competitor competitor;
|
||||
|
||||
private Double rankAtStart;
|
||||
private boolean isRankAtStartInitialized;
|
||||
private Double rankAtFinish;
|
||||
private boolean isRankAtFinishInitialized;
|
||||
|
||||
public TrackedLegOfCompetitorWithContext(HasTrackedLegContext trackedLegContext, TrackedLegOfCompetitor trackedLegOfCompetitor) {
|
||||
this.trackedLegContext = trackedLegContext;
|
||||
this.trackedLegOfCompetitor = trackedLegOfCompetitor;
|
||||
@@ -35,6 +42,11 @@ public class TrackedLegOfCompetitorWithContext implements HasTrackedLegOfCompeti
|
||||
public Competitor getCompetitor() {
|
||||
return competitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCompetitorSearchTag() {
|
||||
return getCompetitor().getSearchTag();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getDistanceTraveled() {
|
||||
@@ -44,10 +56,42 @@ public class TrackedLegOfCompetitorWithContext implements HasTrackedLegOfCompeti
|
||||
|
||||
@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;
|
||||
Double rankAtStart = getRankAtStart();
|
||||
Double rankAtFinish = getRankAtFinish();
|
||||
return rankAtStart != null && rankAtFinish != null ? rankAtStart - rankAtFinish : null;
|
||||
}
|
||||
|
||||
private Double getRankAtStart() {
|
||||
if (!isRankAtStartInitialized) {
|
||||
TrackedRace trackedRace = getTrackedLegContext().getTrackedRaceContext().getTrackedRace();
|
||||
int rank = trackedRace.getRank(getCompetitor(), getTrackedLegOfCompetitor().getStartTime());
|
||||
rankAtStart = rank == 0 ? null : Double.valueOf(rank);
|
||||
isRankAtStartInitialized = true;
|
||||
}
|
||||
return rankAtStart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getRelativeRank() {
|
||||
Leaderboard leaderboard = getTrackedLegContext().getTrackedRaceContext().getLeaderboardContext().getLeaderboard();
|
||||
double competitorCount = Util.size(leaderboard.getCompetitors());
|
||||
Double rankAtFinish = getRankAtFinish();
|
||||
return rankAtFinish == null ? null : rankAtFinish / competitorCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getAbsoluteRank() {
|
||||
return getRankAtFinish();
|
||||
}
|
||||
|
||||
private Double getRankAtFinish() {
|
||||
if (!isRankAtFinishInitialized) {
|
||||
TrackedRace trackedRace = getTrackedLegContext().getTrackedRaceContext().getTrackedRace();
|
||||
int rank = trackedRace.getRank(getCompetitor(), getTrackedLegOfCompetitor().getFinishTime());
|
||||
rankAtFinish = rank == 0 ? null : Double.valueOf(rank);
|
||||
isRankAtFinishInitialized = true;
|
||||
}
|
||||
return rankAtFinish;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,14 +10,14 @@ Require-Bundle: org.eclipse.osgi;bundle-version="3.10.1",
|
||||
com.sap.sse.datamining;bundle-version="1.0.0",
|
||||
com.sap.sse.datamining.annotations;bundle-version="1.0.0",
|
||||
com.sap.sse.datamining.shared;bundle-version="1.0.0",
|
||||
com.sap.sailing.datamining,
|
||||
com.sap.sailing.server;bundle-version="1.0.0",
|
||||
com.sap.sse.common;bundle-version="1.0.0",
|
||||
com.sap.sailing.domain;bundle-version="1.0.0",
|
||||
com.sap.sailing.domain.shared.android,
|
||||
com.sap.sailing.domain.common;bundle-version="1.0.0",
|
||||
com.sap.sailing.polars.datamining.shared,
|
||||
org.apache.commons.math
|
||||
org.apache.commons.math,
|
||||
com.sap.sailing.datamining
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Export-Package: com.sap.sailing.polars.datamining.data,
|
||||
|
||||
+90
-5
@@ -1,6 +1,7 @@
|
||||
package com.sap.sailing.server.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -8,6 +9,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -96,16 +98,99 @@ public class ApplyScoresFromRaceLogTest extends LeaderboardScoringAndRankingTest
|
||||
final List<Competitor> rankedCompetitorsBeforeApplying = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
assertEquals(competitors, rankedCompetitorsBeforeApplying); // no effects of preliminary results list yet
|
||||
f1RaceState.setFinishPositioningConfirmed(now);
|
||||
final Function<Competitor, Double> expectedPoints = (c)->scores.get(c)==null?(mprs.get(c) == null || mprs.get(c) == MaxPointsReason.NONE ? competitors.indexOf(c)+1 : competitors.size()+1):scores.get(c);
|
||||
for (final Competitor c : competitors) {
|
||||
assertEquals(scores.get(c)==null?competitors.indexOf(c)+1:scores.get(c), leaderboard.getTotalPoints(c, f1Column, now), 0.00000001);
|
||||
assertEquals(expectedPoints.apply(c), leaderboard.getTotalPoints(c, f1Column, now), 0.00000001);
|
||||
}
|
||||
final List<Competitor> expectedNewOrder = new ArrayList<>(competitors);
|
||||
expectedNewOrder.sort((c1, c2)->
|
||||
new Double(scores.get(c1)==null?competitors.indexOf(c1)+1:scores.get(c1)).compareTo(
|
||||
new Double(scores.get(c2)==null?competitors.indexOf(c2)+1:scores.get(c2))));
|
||||
expectedNewOrder.sort((c1, c2)->new Double(expectedPoints.apply(c1)).compareTo(new Double(expectedPoints.apply(c1))));
|
||||
final List<Competitor> rankedCompetitorsAfterApplying = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
assertEquals(expectedNewOrder, rankedCompetitorsAfterApplying);
|
||||
double lastScore = 0;
|
||||
for (final Competitor c : rankedCompetitorsAfterApplying) {
|
||||
assertEquals(expectedPoints.apply(c), leaderboard.getTotalPoints(c, f1Column, later));
|
||||
assertTrue(leaderboard.getTotalPoints(c, f1Column, later) >= lastScore);
|
||||
lastScore = leaderboard.getTotalPoints(c, f1Column, later);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See also bug 3955: when for a competitor no score is explicitly provided but a {@link MaxPointsReason} has been set, don't
|
||||
* correct the score in the leaderboard's score correction but only set the {@link MaxPointsReason}. This will let the scoring
|
||||
* scheme select the score, as it used to be before the fix for bug 3794, commit 830e64842a39fb137446887c5177f7de34bd5b5a.
|
||||
*/
|
||||
@Test
|
||||
public void testScoresFromRaceLogOnlyAppliedIfExplicitOrNoMaxPointsReason() throws NoWindException {
|
||||
final RacingEventService service = new RacingEventServiceImpl();
|
||||
final List<Competitor> competitors = new ArrayList<>();
|
||||
for (int i=0; i<8; i++) {
|
||||
final String competitorName = "C"+i;
|
||||
competitors.add(service.getBaseDomainFactory().getCompetitorStore().getOrCreateCompetitor(UUID.randomUUID(),
|
||||
competitorName, /* displayColor */ Color.RED, /* email */ null, /* flagImageURI */ null,
|
||||
new TeamImpl("STG", Collections.singleton(
|
||||
new PersonImpl(competitorName, new NationalityImpl("GER"),
|
||||
/* dateOfBirth */ null, "This is famous "+competitorName)),
|
||||
new PersonImpl("Rigo van Maas", new NationalityImpl("NED"),
|
||||
/* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat",
|
||||
new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null),
|
||||
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null));
|
||||
}
|
||||
final Regatta regatta = createRegatta(/* qualifying */0, new String[] { "Default" }, /* final */1,
|
||||
new String[] { "Default" },
|
||||
/* medal */false, /* medal */ 0, "testOneStartedRaceWithDifferentScores",
|
||||
DomainFactory.INSTANCE.getOrCreateBoatClass("49er", /* typicallyStartsUpwind */true), DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.HIGH_POINT_FIRST_GETS_TEN_OR_EIGHT));
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis()+1000);
|
||||
TrackedRace f1 = new MockedTrackedRaceWithStartTimeAndRanks(now, competitors);
|
||||
RaceColumn f1Column = series.get(1).getRaceColumnByName("F1");
|
||||
f1Column.setTrackedRace(f1Column.getFleets().iterator().next(), f1);
|
||||
final Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
|
||||
service.addLeaderboard(leaderboard); // should add a RaceLogScoringReplicator as listener to the leaderboard
|
||||
service.addRegattaWithoutReplication(regatta);
|
||||
int oneBasedRank = 1;
|
||||
final CompetitorResults results = new CompetitorResultsImpl();
|
||||
|
||||
setResultForCompetitor(competitors.get(0), oneBasedRank++, results, MaxPointsReason.DNF, /* explicit score */ null);
|
||||
setResultForCompetitor(competitors.get(1), oneBasedRank++, results, MaxPointsReason.OCS, /* explicit score */ null);
|
||||
setResultForCompetitor(competitors.get(2), oneBasedRank++, results, MaxPointsReason.DNF, /* explicit score */ 0.1);
|
||||
setResultForCompetitor(competitors.get(3), oneBasedRank++, results, MaxPointsReason.OCS, /* explicit score */ 0.2);
|
||||
setResultForCompetitor(competitors.get(4), oneBasedRank++, results, /* maxPointsReason */ null, /* explicit score */ null);
|
||||
setResultForCompetitor(competitors.get(5), oneBasedRank++, results, /* maxPointsReason */ null, /* explicit score */ 2.4);
|
||||
setResultForCompetitor(competitors.get(6), oneBasedRank++, results, MaxPointsReason.NONE, /* explicit score */ null);
|
||||
setResultForCompetitor(competitors.get(7), oneBasedRank++, results, MaxPointsReason.NONE, /* explicit score */ 3.3);
|
||||
|
||||
final RaceLog f1RaceLog = f1Column.getRaceLog(f1Column.getFleets().iterator().next());
|
||||
final LogEventAuthorImpl author = new LogEventAuthorImpl("Axel", 0);
|
||||
final RaceState f1RaceState = new RaceStateImpl(service, f1RaceLog, author,
|
||||
new RacingProcedureFactoryImpl(author, new EmptyRegattaConfiguration()));
|
||||
f1RaceState.setFinishPositioningListChanged(now, results);
|
||||
final List<Competitor> rankedCompetitorsBeforeApplying = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
assertEquals(competitors, rankedCompetitorsBeforeApplying); // no effects of preliminary results list yet
|
||||
f1RaceState.setFinishPositioningConfirmed(now);
|
||||
|
||||
assertScoreCorrections(leaderboard, f1Column, competitors.get(0), MaxPointsReason.DNF, 0, /* score is corrected */ false, later);
|
||||
assertScoreCorrections(leaderboard, f1Column, competitors.get(1), MaxPointsReason.OCS, 0, /* score is corrected */ false, later);
|
||||
assertScoreCorrections(leaderboard, f1Column, competitors.get(2), MaxPointsReason.DNF, 0.1, /* score is corrected */ true, later);
|
||||
assertScoreCorrections(leaderboard, f1Column, competitors.get(3), MaxPointsReason.OCS, 0.2, /* score is corrected */ true, later);
|
||||
assertScoreCorrections(leaderboard, f1Column, competitors.get(4), MaxPointsReason.NONE, 6, /* score is corrected */ true, later); // score corrected based on rank because no MaxPointsReason set
|
||||
assertScoreCorrections(leaderboard, f1Column, competitors.get(5), MaxPointsReason.NONE, 2.4, /* score is corrected */ true, later); // score corrected based on explicit score
|
||||
assertScoreCorrections(leaderboard, f1Column, competitors.get(6), MaxPointsReason.NONE, 4, /* score is corrected */ true, later); // score corrected based on rank because MaxPointsReason.NONE set
|
||||
assertScoreCorrections(leaderboard, f1Column, competitors.get(7), MaxPointsReason.NONE, 3.3, /* score is corrected */ true, later); // score corrected based on explicit score
|
||||
}
|
||||
|
||||
private void assertScoreCorrections(Leaderboard leaderboard, RaceColumn raceColumn, Competitor competitor,
|
||||
MaxPointsReason expectedMaxPointsReason, double expectedScore, boolean expectedIsScoreCorrected,
|
||||
TimePoint timePoint) {
|
||||
assertEquals(expectedIsScoreCorrected, leaderboard.getScoreCorrection().getExplicitScoreCorrection(competitor, raceColumn) != null);
|
||||
assertEquals(expectedMaxPointsReason, leaderboard.getScoreCorrection().getMaxPointsReason(competitor, raceColumn, timePoint));
|
||||
assertEquals(expectedScore, leaderboard.getTotalPoints(competitor, raceColumn, timePoint), 0.000001);
|
||||
}
|
||||
|
||||
private void setResultForCompetitor(final Competitor competitor, int oneBasedRank,
|
||||
final CompetitorResults results, MaxPointsReason maxPointsReason, Double explicitScore) {
|
||||
results.add(new CompetitorResultImpl(competitor.getId(), competitor.getName(), oneBasedRank++, maxPointsReason, explicitScore, /* finishingTime */ null, /* comment */ null));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+11
-3
@@ -143,9 +143,17 @@ public class RaceLogScoringReplicator implements RaceColumnListener {
|
||||
if (positioningList != null) {
|
||||
for (CompetitorResult positionedCompetitor : positioningList) {
|
||||
Competitor competitor = service.getBaseDomainFactory().getExistingCompetitorById(positionedCompetitor.getCompetitorId());
|
||||
int rankByRaceCommittee = getRankInPositioningListByRaceCommittee(positionedCompetitor);
|
||||
correctScoreInLeaderboard(leaderboard, raceColumn, timePoint, numberOfCompetitorsInRace,
|
||||
competitor, rankByRaceCommittee, positionedCompetitor.getScore());
|
||||
// The score is updated when explicitly provided or when no penalty was set;
|
||||
// in turn, this means that when a penalty is set and no score is explicitly provided,
|
||||
// it is up to the scoring scheme to infer a penalty score for the MaxPointsReason.
|
||||
// See also bug 3955.
|
||||
if (positionedCompetitor.getScore() != null
|
||||
|| positionedCompetitor.getMaxPointsReason() == null
|
||||
|| positionedCompetitor.getMaxPointsReason().equals(MaxPointsReason.NONE)) {
|
||||
int rankByRaceCommittee = getRankInPositioningListByRaceCommittee(positionedCompetitor);
|
||||
correctScoreInLeaderboard(leaderboard, raceColumn, timePoint, numberOfCompetitorsInRace, competitor,
|
||||
rankByRaceCommittee, positionedCompetitor.getScore());
|
||||
}
|
||||
setMaxPointsReasonInLeaderboardIfNecessary(leaderboard, raceColumn, timePoint, positionedCompetitor.getMaxPointsReason(), competitor);
|
||||
}
|
||||
// Since the metadata update is used by the Sailing suite to determine the final state of a race, it has to
|
||||
|
||||
Reference in new issue
Block a user