mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-25 05:23:51 +00:00
merged with master
This commit is contained in:
commit
45483c8a5b
62 files changed
+1366
-486
No files matched your search
+2
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.datamining.shared;
|
||||
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.LegType;
|
||||
import com.sap.sailing.domain.common.ManeuverType;
|
||||
@@ -16,6 +17,7 @@ public final class SailingDataMiningSerializationDummy implements SerializationD
|
||||
|
||||
private LegType legType;
|
||||
private Distance distance;
|
||||
private Bearing bearing;
|
||||
private CentralAngleDistance centralAngleDistance;
|
||||
private MeterDistance meterDistance;
|
||||
private NauticalMileDistance nauticalMileDistance;
|
||||
|
||||
+19
-2
@@ -23,6 +23,7 @@ LegSailingDomainRetrieverChain=Legs
|
||||
GPSFixSailingDomainRetrieverChain=GPS Fixes
|
||||
BravoFixSailingDomainRetrieverChain=Bravo Fixes
|
||||
BravoFixTrackSailingDomainRetrieverChain=Bravo Tracks
|
||||
FoilingSegmentsSailingDomainRetrieverChain=Foiled Segments
|
||||
WindFixSailingDomainRetrieverChain=Wind Fixes
|
||||
MarkPassingSailingDomainRetrieverChain=Mark Passings
|
||||
RaceResultSailingDomainRetrieverChain=Race Results
|
||||
@@ -96,7 +97,7 @@ WindSourceName=Wind Source Name
|
||||
windFrom=True Wind Direction (TWD)
|
||||
windSpeedKnots=True Wind Speed (kts)
|
||||
speedInKnots=Speed (kts)
|
||||
bearing=Course over Ground (°T)
|
||||
bearing=Direction (°T)
|
||||
WindTrack=Wind Track
|
||||
timeSpentFoiling=Time spent foiling
|
||||
yaw=Yaw
|
||||
@@ -105,4 +106,20 @@ roll=Heel
|
||||
rideHeight=Ride Height
|
||||
rideHeightPort=Ride Height Port Hull
|
||||
rideHeightStarboard=Ride Height Starboard Hull
|
||||
IsFoiling=Is Foiling
|
||||
IsFoiling=Is Foiling
|
||||
FoilingDuration=Foiling Duration
|
||||
FoilingDistance=Distance Foiled
|
||||
TakeoffSpeedInKnotsInKnots=Takeoff speed in knots
|
||||
LandingSpeedInKnots=Landing speed in knots
|
||||
AbsoluteTrueWindAngleAtTakeoff=Absolute true wind angle (TWA) at takeoff
|
||||
AbsoluteTrueWindAngleAtLanding=Absolute true wind angle (TWA) at landing
|
||||
WindStrengthInBeaufortAtTakeoff=Wind strength in beaufort at takeoff
|
||||
WindStrengthInBeaufortAtLanding=Wind strength in beaufort at landing
|
||||
WindAtTakeoff=Wind at takeoff
|
||||
WindAtLanding=Wind at landing
|
||||
StartsOnLegType=Type of leg at takeoff
|
||||
EndsOnLegType=Type of leg at landing
|
||||
FoilingSegments=Foiled Segments
|
||||
AverageAbsoluteTrueWindAngle=Average absolute true wind angle
|
||||
AbsoluteTrueWindAngle=Absolute true wind angle (TWA)
|
||||
Wind=Wind
|
||||
+19
-2
@@ -21,6 +21,7 @@ LegSailingDomainRetrieverChain=Schenkel
|
||||
GPSFixSailingDomainRetrieverChain=GPS-Fixes
|
||||
BravoFixSailingDomainRetrieverChain=Bravo-Fixes
|
||||
BravoFixTrackSailingDomainRetrieverChain=Bravo Messreihen
|
||||
FoilingSegmentsSailingDomainRetrieverChain=Gefoilte Abschnitte
|
||||
WindFixSailingDomainRetrieverChain=Windmessungen
|
||||
MarkPassingSailingDomainRetrieverChain=Tonnenrundungen
|
||||
RaceResultSailingDomainRetrieverChain=Rennergebnisse
|
||||
@@ -96,7 +97,7 @@ WindSourceName=Name der Windmessreihe
|
||||
windFrom=Wind aus Richtung (TWD)
|
||||
windSpeedKnots=Wahre Windgeschwindigkeit (kn)
|
||||
speedInKnots=Fahrt (kn)
|
||||
bearing=Kurs über Grund (°)
|
||||
bearing=Richtung (°)
|
||||
WindTrack=Windmessreihe
|
||||
timeSpentFoiling=Zeit auf Foils
|
||||
yaw=Gierung
|
||||
@@ -105,4 +106,20 @@ roll=Kr
|
||||
rideHeight=Foiling-Höhe
|
||||
rideHeightPort=Foiling-Höhe Backbord-Rumpf
|
||||
rideHeightStarboard=Foiling-Höhe Steuerbord-Rumpf
|
||||
IsFoiling=Foilt
|
||||
IsFoiling=Foilt
|
||||
FoilingDuration=Foilingdauer
|
||||
FoilingDistance=Gefoilte Distanz
|
||||
TakeoffSpeedInKnotsInKnots=Abhebegeschwindigkeit in Knoten
|
||||
LandingSpeedInKnots=Landegeschwindigkeit in Knoten
|
||||
AbsoluteTrueWindAngleAtTakeoff=Absoluter Winkel zum wahren Wind (TWA) beim Abheben
|
||||
AbsoluteTrueWindAngleAtLanding=Absoluter Winkel zum wahren Wind (TWA) beim Landen
|
||||
WindStrengthInBeaufortAtTakeoff=Windstärke beim Abheben in Beaufort
|
||||
WindStrengthInBeaufortAtLanding=Windstärke beim Landen in Beaufort
|
||||
WindAtTakeoff=Wind beim Abheben
|
||||
WindAtLanding=Wind beim Landen
|
||||
StartsOnLegType=Bahnschnenkeltyp beim Abheben
|
||||
EndsOnLegType=Bahnschenkeltyp beim Landen
|
||||
FoilingSegments=Gefoilte Abschnitte
|
||||
AverageAbsoluteTrueWindAngle=Durchschnittlicher absoluter Winkel zum wahren Wind (TWA)
|
||||
AbsoluteTrueWindAngle=Absoluter Winkel zum wahren Wind (TWA)
|
||||
Wind=Wind
|
||||
@@ -9,6 +9,7 @@ import org.osgi.framework.BundleContext;
|
||||
|
||||
import com.sap.sailing.datamining.data.HasBravoFixContext;
|
||||
import com.sap.sailing.datamining.data.HasBravoFixTrackContext;
|
||||
import com.sap.sailing.datamining.data.HasFoilingSegmentContext;
|
||||
import com.sap.sailing.datamining.data.HasGPSFixContext;
|
||||
import com.sap.sailing.datamining.data.HasLeaderboardContext;
|
||||
import com.sap.sailing.datamining.data.HasLeaderboardGroupContext;
|
||||
@@ -22,6 +23,8 @@ import com.sap.sailing.datamining.data.HasTrackedRaceContext;
|
||||
import com.sap.sailing.datamining.data.HasWindFixContext;
|
||||
import com.sap.sailing.datamining.data.HasWindTrackContext;
|
||||
import com.sap.sailing.datamining.impl.components.aggregators.ParallelBearingAverageDegreesAggregationProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.aggregators.ParallelBearingMaxAggregationProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.aggregators.ParallelBearingMinAggregationProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.aggregators.ParallelBoolSumAggregationProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.aggregators.ParallelDistanceAverageAggregationProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.aggregators.ParallelDistanceMaxAggregationProcessor;
|
||||
@@ -95,6 +98,7 @@ public class Activator extends AbstractDataMiningActivatorWithPredefinedQueries
|
||||
internalClasses.add(HasWindFixContext.class);
|
||||
internalClasses.add(HasBravoFixContext.class);
|
||||
internalClasses.add(HasBravoFixTrackContext.class);
|
||||
internalClasses.add(HasFoilingSegmentContext.class);
|
||||
internalClasses.add(HasManeuverContext.class);
|
||||
internalClasses.add(HasMarkPassingContext.class);
|
||||
internalClasses.add(HasRaceOfCompetitorContext.class);
|
||||
@@ -131,6 +135,8 @@ public class Activator extends AbstractDataMiningActivatorWithPredefinedQueries
|
||||
aggregators.add(ParallelDurationMaxAggregationProcessor.getDefinition());
|
||||
aggregators.add(ParallelDurationMinAggregationProcessor.getDefinition());
|
||||
aggregators.add(ParallelBearingAverageDegreesAggregationProcessor.getDefinition());
|
||||
aggregators.add(ParallelBearingMaxAggregationProcessor.getDefinition());
|
||||
aggregators.add(ParallelBearingMinAggregationProcessor.getDefinition());
|
||||
return aggregators;
|
||||
}
|
||||
|
||||
|
||||
+8
@@ -5,6 +5,7 @@ import java.util.Collection;
|
||||
|
||||
import com.sap.sailing.datamining.data.HasBravoFixContext;
|
||||
import com.sap.sailing.datamining.data.HasBravoFixTrackContext;
|
||||
import com.sap.sailing.datamining.data.HasFoilingSegmentContext;
|
||||
import com.sap.sailing.datamining.data.HasGPSFixContext;
|
||||
import com.sap.sailing.datamining.data.HasLeaderboardContext;
|
||||
import com.sap.sailing.datamining.data.HasManeuverContext;
|
||||
@@ -19,6 +20,7 @@ import com.sap.sailing.datamining.data.HasWindTrackContext;
|
||||
import com.sap.sailing.datamining.impl.components.BravoFixRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.BravoFixTrackRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.CompetitorOfRaceInLeaderboardRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.FoilingSegmentRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.GPSFixRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.LeaderboardGroupRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.LeaderboardRetrievalProcessor;
|
||||
@@ -70,6 +72,12 @@ public class SailingDataRetrievalChainDefinitions {
|
||||
HasBravoFixTrackContext.class, "BravoFixTrack");
|
||||
dataRetrieverChainDefinitions.add(bravoFixTrackRetrieverChainDefinition);
|
||||
|
||||
final DataRetrieverChainDefinition<RacingEventService, HasFoilingSegmentContext> foilingSegmentsRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
|
||||
raceOfCompetitorRetrieverChainDefinition, HasFoilingSegmentContext.class, "FoilingSegmentsSailingDomainRetrieverChain");
|
||||
foilingSegmentsRetrieverChainDefinition.endWith(RaceOfCompetitorRetrievalProcessor.class, FoilingSegmentRetrievalProcessor.class,
|
||||
HasFoilingSegmentContext.class, "FoilingSegments");
|
||||
dataRetrieverChainDefinitions.add(foilingSegmentsRetrieverChainDefinition);
|
||||
|
||||
final DataRetrieverChainDefinition<RacingEventService, HasTrackedLegOfCompetitorContext> legOfCompetitorRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
|
||||
trackedRaceRetrieverChainDefinition, HasTrackedLegOfCompetitorContext.class, "LegSailingDomainRetrieverChain");
|
||||
legOfCompetitorRetrieverChainDefinition.addAfter(TrackedRaceRetrievalProcessor.class, TrackedLegRetrievalProcessor.class, HasTrackedLegContext.class, "Leg");
|
||||
|
||||
+14
@@ -1,8 +1,13 @@
|
||||
package com.sap.sailing.datamining.data;
|
||||
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.tracking.BravoFix;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.datamining.annotations.Connector;
|
||||
import com.sap.sse.datamining.annotations.Statistic;
|
||||
|
||||
public interface HasBravoFixContext extends HasWindOnTrackedLeg {
|
||||
@Connector(scanForStatistics=false)
|
||||
@@ -10,6 +15,15 @@ public interface HasBravoFixContext extends HasWindOnTrackedLeg {
|
||||
|
||||
@Connector(ordinal=1)
|
||||
BravoFix getBravoFix();
|
||||
|
||||
@Connector(messageKey="Speed")
|
||||
SpeedWithBearing getSpeed();
|
||||
|
||||
@Connector(messageKey="Wind")
|
||||
Wind getWind();
|
||||
|
||||
@Statistic(messageKey="AbsoluteTrueWindAngle")
|
||||
Bearing getAbsoluteTrueWindAngle() throws NoWindException;
|
||||
|
||||
@Override
|
||||
default TimePoint getTimePoint() {
|
||||
|
||||
Executable
+64
@@ -0,0 +1,64 @@
|
||||
package com.sap.sailing.datamining.data;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.LegType;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.datamining.annotations.Connector;
|
||||
import com.sap.sse.datamining.annotations.Dimension;
|
||||
import com.sap.sse.datamining.annotations.Statistic;
|
||||
import com.sap.sse.datamining.shared.impl.dto.ClusterDTO;
|
||||
import com.sap.sse.i18n.ResourceBundleStringMessages;
|
||||
|
||||
public interface HasFoilingSegmentContext {
|
||||
@Connector(scanForStatistics=false)
|
||||
HasBravoFixTrackContext getBravoFixTrackContext();
|
||||
|
||||
TimePoint getStartOfFoilingSegment();
|
||||
|
||||
TimePoint getEndOfFoilingSegment();
|
||||
|
||||
@Statistic(messageKey="FoilingDuration")
|
||||
Duration getDuration();
|
||||
|
||||
@Statistic(messageKey="FoilingDistance")
|
||||
Distance getDistance();
|
||||
|
||||
@Statistic(messageKey="TakeoffSpeedInKnotsInKnots", resultDecimals=1)
|
||||
Double getTakeoffSpeedInKnots();
|
||||
|
||||
@Statistic(messageKey="LandingSpeedInKnots", resultDecimals=1)
|
||||
Double getLandingSpeedInKnots();
|
||||
|
||||
@Statistic(messageKey="AbsoluteTrueWindAngleAtTakeoff", resultDecimals=1)
|
||||
Bearing getAbsoluteTrueWindAngleAtTakeoffInDegrees() throws NoWindException;
|
||||
|
||||
@Statistic(messageKey="AbsoluteTrueWindAngleAtLanding", resultDecimals=1)
|
||||
Bearing getAbsoluteTrueWindAngleAtLandingInDegrees() throws NoWindException;
|
||||
|
||||
@Statistic(messageKey="AverageAbsoluteTrueWindAngle", resultDecimals=1)
|
||||
Bearing getAverageAbsoluteTrueWindAngle() throws NoWindException;
|
||||
|
||||
@Dimension(messageKey="WindStrengthInBeaufortAtTakeoff")
|
||||
ClusterDTO getWindStrengthAsBeaufortClusterAtTakeoff(Locale locale, ResourceBundleStringMessages stringMessages);
|
||||
|
||||
@Dimension(messageKey="WindStrengthInBeaufortAtLanding")
|
||||
ClusterDTO getWindStrengthAsBeaufortClusterAtLanding(Locale locale, ResourceBundleStringMessages stringMessages);
|
||||
|
||||
@Connector(messageKey="WindAtTakeoff")
|
||||
Wind getWindAtTakeoff();
|
||||
|
||||
@Connector(messageKey="WindAtLanding")
|
||||
Wind getWindAtLanding();
|
||||
|
||||
@Dimension(messageKey="StartsOnLegType")
|
||||
LegType getStartsOnLegType() throws NoWindException;
|
||||
|
||||
@Dimension(messageKey="EndsOnLegType")
|
||||
LegType getEndsOnLegType() throws NoWindException;
|
||||
}
|
||||
+1
-1
@@ -9,6 +9,6 @@ public interface HasLeaderboardContext {
|
||||
|
||||
PolarDataService getPolarDataService();
|
||||
|
||||
@Dimension(messageKey="Leaderboard")
|
||||
@Dimension(messageKey="Leaderboard", ordinal=1)
|
||||
String getName();
|
||||
}
|
||||
+5
-6
@@ -20,6 +20,9 @@ public interface HasManeuverContext extends HasWindOnTrackedLeg, HasManeuver, Ha
|
||||
|
||||
@Dimension(messageKey="Tack", ordinal=13)
|
||||
Tack getTack();
|
||||
|
||||
@Dimension(messageKey="ToSide")
|
||||
NauticalSide getToSide();
|
||||
|
||||
@Connector(messageKey="SpeedBefore", ordinal=0)
|
||||
SpeedWithBearing getSpeedBefore();
|
||||
@@ -28,14 +31,10 @@ public interface HasManeuverContext extends HasWindOnTrackedLeg, HasManeuver, Ha
|
||||
|
||||
@Statistic(messageKey="DirectionChange", resultDecimals=2, ordinal=2)
|
||||
Double getDirectionChangeInDegrees();
|
||||
|
||||
@Statistic(messageKey="AbsoluteDirectionChange", resultDecimals=2, ordinal=2)
|
||||
@Statistic(messageKey="AbsoluteDirectionChange", resultDecimals=2, ordinal=3)
|
||||
Double getAbsoluteDirectionChangeInDegrees();
|
||||
|
||||
@Dimension(messageKey="ToSide")
|
||||
NauticalSide getToSide();
|
||||
|
||||
@Statistic(messageKey="ManeuverLoss", resultDecimals=0, ordinal=3)
|
||||
@Statistic(messageKey="ManeuverLoss", resultDecimals=0, ordinal=4)
|
||||
Distance getManeuverLoss();
|
||||
|
||||
}
|
||||
+9
-5
@@ -5,25 +5,29 @@ import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sse.datamining.annotations.Connector;
|
||||
import com.sap.sse.datamining.annotations.Dimension;
|
||||
import com.sap.sse.datamining.annotations.Statistic;
|
||||
import com.sap.sse.datamining.shared.impl.dto.ClusterDTO;
|
||||
|
||||
public interface HasRaceResultOfCompetitorContext {
|
||||
|
||||
@Connector(scanForStatistics=false)
|
||||
public HasLeaderboardContext getLeaderboardContext();
|
||||
|
||||
@Connector(messageKey="Competitor")
|
||||
@Connector(messageKey="Competitor", ordinal=2)
|
||||
public Competitor getCompetitor();
|
||||
|
||||
@Connector(messageKey="BoatClass")
|
||||
@Connector(messageKey="BoatClass", ordinal=3)
|
||||
BoatClass getBoatClass();
|
||||
|
||||
@Dimension(messageKey="Regatta")
|
||||
@Dimension(messageKey="Regatta", ordinal=4)
|
||||
String getRegattaName();
|
||||
|
||||
@Dimension(messageKey="CompetitorSearchTag", ordinal=11) // TODO Clean me: Move Dimension to Competitor when possible
|
||||
@Dimension(messageKey="CompetitorSearchTag", ordinal=5) // TODO Clean me: Move Dimension to Competitor when possible
|
||||
public String getCompetitorSearchTag();
|
||||
|
||||
@Dimension(messageKey="RelativeScoreInPercent", ordinal=6)
|
||||
public ClusterDTO getPercentageClusterForRelativeScore();
|
||||
|
||||
@Dimension(messageKey="WindSpeedInBeaufort")
|
||||
@Dimension(messageKey="WindSpeedInBeaufort", ordinal=7)
|
||||
int getAverageWindSpeedInRoundedBeaufort();
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@ public interface HasWind extends Positioned, Timed {
|
||||
@Dimension(messageKey="WindStrengthInBeaufort", ordinal=11)
|
||||
default ClusterDTO getWindStrengthAsBeaufortCluster(Locale locale, ResourceBundleStringMessages stringMessages) {
|
||||
Wind wind = getWind();
|
||||
Cluster<?> cluster = Activator.getClusterGroups().getWindStrengthInBeaufortClusterGroup().getClusterFor(wind);
|
||||
return new ClusterDTO(cluster.asLocalizedString(locale, stringMessages));
|
||||
final Cluster<?> cluster = Activator.getClusterGroups().getWindStrengthInBeaufortClusterGroup().getClusterFor(wind);
|
||||
return new ClusterDTO(cluster.toString(), ()->cluster.asLocalizedString(locale, stringMessages));
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -11,13 +11,13 @@ public interface HasWindFixContext extends HasWind {
|
||||
@Connector(scanForStatistics=false)
|
||||
public HasTrackedRaceContext getTrackedRaceContext();
|
||||
|
||||
@Statistic(messageKey="")
|
||||
@Statistic(messageKey="", ordinal=0)
|
||||
public Wind getWind();
|
||||
|
||||
@Statistic(messageKey="windFrom", resultDecimals=1)
|
||||
@Statistic(messageKey="windFrom", resultDecimals=1, ordinal=1)
|
||||
double getWindFromDegrees();
|
||||
|
||||
@Statistic(messageKey="windSpeedKnots", resultDecimals=1)
|
||||
@Statistic(messageKey="windSpeedKnots", resultDecimals=1, ordinal=2)
|
||||
double getWindSpeedInKnots();
|
||||
|
||||
@Override
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ import java.util.concurrent.ExecutorService;
|
||||
|
||||
import com.sap.sailing.datamining.data.HasBravoFixTrackContext;
|
||||
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.impl.data.BravoTrackWithContext;
|
||||
import com.sap.sailing.datamining.impl.data.BravoFixTrackWithContext;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.tracking.BravoFixTrack;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
@@ -32,7 +32,7 @@ public class BravoFixTrackRetrievalProcessor extends AbstractRetrievalProcessor<
|
||||
final TrackedRace trackedRace = element.getTrackedRaceContext().getTrackedRace();
|
||||
final BravoFixTrack<Competitor> bravoFixTrack = trackedRace.getSensorTrack(element.getCompetitor(), BravoFixTrack.TRACK_NAME);
|
||||
if (bravoFixTrack != null) {
|
||||
bravoTracksWithContext.add(new BravoTrackWithContext(element, bravoFixTrack));
|
||||
bravoTracksWithContext.add(new BravoFixTrackWithContext(element, bravoFixTrack));
|
||||
}
|
||||
return bravoTracksWithContext;
|
||||
}
|
||||
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
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.HasFoilingSegmentContext;
|
||||
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.impl.data.BravoFixTrackWithContext;
|
||||
import com.sap.sailing.datamining.impl.data.FoilingSegmentWithContext;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.tracking.BravoFix;
|
||||
import com.sap.sailing.domain.tracking.BravoFixTrack;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.datamining.components.Processor;
|
||||
import com.sap.sse.datamining.impl.components.AbstractRetrievalProcessor;
|
||||
|
||||
public class FoilingSegmentRetrievalProcessor extends AbstractRetrievalProcessor<HasRaceOfCompetitorContext, HasFoilingSegmentContext> {
|
||||
|
||||
public FoilingSegmentRetrievalProcessor(ExecutorService executor, Collection<Processor<HasFoilingSegmentContext, ?>> resultReceivers, int retrievalLevel) {
|
||||
super(HasRaceOfCompetitorContext.class, HasFoilingSegmentContext.class, executor, resultReceivers, retrievalLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<HasFoilingSegmentContext> retrieveData(HasRaceOfCompetitorContext element) {
|
||||
Collection<HasFoilingSegmentContext> foilingSegments = new ArrayList<>();
|
||||
final TrackedRace trackedRace = element.getTrackedRaceContext().getTrackedRace();
|
||||
final TimePoint startOfRace = element.getTrackedRaceContext().getTrackedRace().getStartOfRace();
|
||||
if (startOfRace != null) {
|
||||
final TimePoint endOfRace = element.getTrackedRaceContext().getTrackedRace().getEndOfRace();
|
||||
final TimePoint end;
|
||||
if (endOfRace == null) {
|
||||
final TimePoint endOfTracking = element.getTrackedRaceContext().getTrackedRace().getEndOfTracking();
|
||||
end = endOfTracking == null ? MillisecondsTimePoint.now() : endOfTracking;
|
||||
} else {
|
||||
end = endOfRace;
|
||||
}
|
||||
final BravoFixTrack<Competitor> bravoFixTrack = trackedRace.getSensorTrack(element.getCompetitor(), BravoFixTrack.TRACK_NAME);
|
||||
if (bravoFixTrack != null) {
|
||||
boolean isFoiling = false;
|
||||
TimePoint startOfSegment = null;
|
||||
bravoFixTrack.lockForRead();
|
||||
try {
|
||||
for (final BravoFix bravoFix : bravoFixTrack.getFixes(startOfRace, /* fromInclusive */ true, end, /* toInclusive */ false)) {
|
||||
if (isFoiling) {
|
||||
if (!bravoFix.isFoiling()) {
|
||||
isFoiling = false;
|
||||
foilingSegments.add(createFoilingSegment(startOfSegment, bravoFix.getTimePoint(), element, bravoFixTrack));
|
||||
startOfSegment = null;
|
||||
}
|
||||
} else {
|
||||
if (bravoFix.isFoiling()) {
|
||||
isFoiling = true;
|
||||
startOfSegment = bravoFix.getTimePoint();
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
bravoFixTrack.unlockAfterRead();
|
||||
}
|
||||
if (isFoiling) {
|
||||
foilingSegments.add(createFoilingSegment(startOfSegment, end, element, bravoFixTrack));
|
||||
}
|
||||
}
|
||||
}
|
||||
return foilingSegments;
|
||||
}
|
||||
|
||||
private HasFoilingSegmentContext createFoilingSegment(TimePoint startOfSegment, TimePoint endOfSegment,
|
||||
HasRaceOfCompetitorContext raceOfCompetitorContext, BravoFixTrack<Competitor> bravoFixTrack) {
|
||||
return new FoilingSegmentWithContext(new BravoFixTrackWithContext(raceOfCompetitorContext, bravoFixTrack), startOfSegment, endOfSegment);
|
||||
}
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.sap.sailing.datamining.impl.components.aggregators;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sse.datamining.components.AggregationProcessorDefinition;
|
||||
import com.sap.sse.datamining.components.Processor;
|
||||
import com.sap.sse.datamining.impl.components.SimpleAggregationProcessorDefinition;
|
||||
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelComparableMaxAggregationProcessor;
|
||||
import com.sap.sse.datamining.shared.GroupKey;
|
||||
|
||||
public class ParallelBearingMaxAggregationProcessor extends
|
||||
AbstractParallelComparableMaxAggregationProcessor<Bearing> {
|
||||
|
||||
private static final AggregationProcessorDefinition<Bearing, Bearing> DEFINITION =
|
||||
new SimpleAggregationProcessorDefinition<>(Bearing.class, Bearing.class, "Maximum", ParallelBearingMaxAggregationProcessor.class);
|
||||
|
||||
public static AggregationProcessorDefinition<Bearing, Bearing> getDefinition() {
|
||||
return DEFINITION;
|
||||
}
|
||||
|
||||
|
||||
public ParallelBearingMaxAggregationProcessor(ExecutorService executor,
|
||||
Collection<Processor<Map<GroupKey, Bearing>, ?>> resultReceivers) {
|
||||
super(executor, resultReceivers);
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.sap.sailing.datamining.impl.components.aggregators;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sse.datamining.components.AggregationProcessorDefinition;
|
||||
import com.sap.sse.datamining.components.Processor;
|
||||
import com.sap.sse.datamining.impl.components.SimpleAggregationProcessorDefinition;
|
||||
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelComparableMaxAggregationProcessor;
|
||||
import com.sap.sse.datamining.shared.GroupKey;
|
||||
|
||||
public class ParallelBearingMinAggregationProcessor extends
|
||||
AbstractParallelComparableMaxAggregationProcessor<Bearing> {
|
||||
|
||||
private static final AggregationProcessorDefinition<Bearing, Bearing> DEFINITION =
|
||||
new SimpleAggregationProcessorDefinition<>(Bearing.class, Bearing.class, "Minimum", ParallelBearingMinAggregationProcessor.class);
|
||||
|
||||
public static AggregationProcessorDefinition<Bearing, Bearing> getDefinition() {
|
||||
return DEFINITION;
|
||||
}
|
||||
|
||||
|
||||
public ParallelBearingMinAggregationProcessor(ExecutorService executor,
|
||||
Collection<Processor<Map<GroupKey, Bearing>, ?>> resultReceivers) {
|
||||
super(executor, resultReceivers);
|
||||
}
|
||||
}
|
||||
+3
-10
@@ -8,11 +8,11 @@ import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sse.datamining.components.AggregationProcessorDefinition;
|
||||
import com.sap.sse.datamining.components.Processor;
|
||||
import com.sap.sse.datamining.impl.components.SimpleAggregationProcessorDefinition;
|
||||
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelSingleGroupedValueAggregationProcessor;
|
||||
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelComparableMaxAggregationProcessor;
|
||||
import com.sap.sse.datamining.shared.GroupKey;
|
||||
|
||||
public class ParallelDistanceMaxAggregationProcessor extends
|
||||
AbstractParallelSingleGroupedValueAggregationProcessor<Distance> {
|
||||
AbstractParallelComparableMaxAggregationProcessor<Distance> {
|
||||
|
||||
private static final AggregationProcessorDefinition<Distance, Distance> DEFINITION =
|
||||
new SimpleAggregationProcessorDefinition<>(Distance.class, Distance.class, "Maximum", ParallelDistanceMaxAggregationProcessor.class);
|
||||
@@ -20,16 +20,9 @@ public class ParallelDistanceMaxAggregationProcessor extends
|
||||
public static AggregationProcessorDefinition<Distance, Distance> getDefinition() {
|
||||
return DEFINITION;
|
||||
}
|
||||
|
||||
|
||||
public ParallelDistanceMaxAggregationProcessor(ExecutorService executor,
|
||||
Collection<Processor<Map<GroupKey, Distance>, ?>> resultReceivers) {
|
||||
super(executor, resultReceivers, "Maximum");
|
||||
super(executor, resultReceivers);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Distance compareValuesAndReturnNewResult(Distance currentResult, Distance newValue) {
|
||||
return currentResult.getMeters() >= newValue.getMeters() ? currentResult : newValue;
|
||||
}
|
||||
|
||||
}
|
||||
+3
-9
@@ -8,11 +8,11 @@ import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sse.datamining.components.AggregationProcessorDefinition;
|
||||
import com.sap.sse.datamining.components.Processor;
|
||||
import com.sap.sse.datamining.impl.components.SimpleAggregationProcessorDefinition;
|
||||
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelSingleGroupedValueAggregationProcessor;
|
||||
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelComparableMinAggregationProcessor;
|
||||
import com.sap.sse.datamining.shared.GroupKey;
|
||||
|
||||
public class ParallelDistanceMinAggregationProcessor extends
|
||||
AbstractParallelSingleGroupedValueAggregationProcessor<Distance> {
|
||||
AbstractParallelComparableMinAggregationProcessor<Distance> {
|
||||
|
||||
private static final AggregationProcessorDefinition<Distance, Distance> DEFINITION =
|
||||
new SimpleAggregationProcessorDefinition<>(Distance.class, Distance.class, "Minimum", ParallelDistanceMinAggregationProcessor.class);
|
||||
@@ -24,12 +24,6 @@ public class ParallelDistanceMinAggregationProcessor extends
|
||||
|
||||
public ParallelDistanceMinAggregationProcessor(ExecutorService executor,
|
||||
Collection<Processor<Map<GroupKey, Distance>, ?>> resultReceivers) {
|
||||
super(executor, resultReceivers, "Minimum");
|
||||
super(executor, resultReceivers);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Distance compareValuesAndReturnNewResult(Distance currentResult, Distance newValue) {
|
||||
return currentResult.getMeters() <= newValue.getMeters() ? currentResult : newValue;
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -8,13 +8,13 @@ import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class BravoTrackWithContext implements HasBravoFixTrackContext {
|
||||
public class BravoFixTrackWithContext implements HasBravoFixTrackContext {
|
||||
|
||||
private final HasRaceOfCompetitorContext raceOfCompetitorContext;
|
||||
|
||||
private final BravoFixTrack<Competitor> bravoFixTrack;
|
||||
|
||||
public BravoTrackWithContext(HasRaceOfCompetitorContext raceOfCompetitorContext, BravoFixTrack<Competitor> bravoFixTrack) {
|
||||
public BravoFixTrackWithContext(HasRaceOfCompetitorContext raceOfCompetitorContext, BravoFixTrack<Competitor> bravoFixTrack) {
|
||||
this.raceOfCompetitorContext = raceOfCompetitorContext;
|
||||
this.bravoFixTrack = bravoFixTrack;
|
||||
}
|
||||
+35
-3
@@ -2,9 +2,16 @@ package com.sap.sailing.datamining.impl.data;
|
||||
|
||||
import com.sap.sailing.datamining.data.HasBravoFixContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.tracking.BravoFix;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
|
||||
public class BravoFixWithContext implements HasBravoFixContext {
|
||||
private static final long serialVersionUID = -4537126043228674949L;
|
||||
@@ -39,10 +46,35 @@ public class BravoFixWithContext implements HasBravoFixContext {
|
||||
this.wind = wind;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpeedWithBearing getSpeed() {
|
||||
return getGpsFixTrack().getEstimatedSpeed(getTimePoint());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Wind getWind() {
|
||||
return getTrackedRace().getWind(getGpsFixTrack().getEstimatedPosition(getTimePoint(), /* extrapolate */ true), getTimePoint());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bearing getAbsoluteTrueWindAngle() throws NoWindException {
|
||||
return getTrackedRace().getTrackedLeg(getCompetitor(), getTimePoint()).getBeatAngle(getTimePoint()).abs();
|
||||
}
|
||||
|
||||
private Competitor getCompetitor() {
|
||||
return getTrackedLegOfCompetitorContext().getCompetitor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return getTrackedLegOfCompetitorContext().getTrackedLegOfCompetitor().getTrackedLeg().getTrackedRace()
|
||||
.getTrack(getTrackedLegOfCompetitorContext().getCompetitor())
|
||||
.getEstimatedPosition(getTimePoint(), /* extrapolate */ true);
|
||||
return getGpsFixTrack().getEstimatedPosition(getTimePoint(), /* extrapolate */ true);
|
||||
}
|
||||
|
||||
private GPSFixTrack<Competitor, GPSFixMoving> getGpsFixTrack() {
|
||||
return getTrackedRace().getTrack(getTrackedLegOfCompetitorContext().getCompetitor());
|
||||
}
|
||||
|
||||
private TrackedRace getTrackedRace() {
|
||||
return getTrackedLegOfCompetitorContext().getTrackedLegOfCompetitor().getTrackedLeg().getTrackedRace();
|
||||
}
|
||||
}
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
package com.sap.sailing.datamining.impl.data;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import com.sap.sailing.datamining.Activator;
|
||||
import com.sap.sailing.datamining.data.HasBravoFixTrackContext;
|
||||
import com.sap.sailing.datamining.data.HasFoilingSegmentContext;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.BearingCluster;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.LegType;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.tracking.BravoFix;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.tracking.BravoFixTrack;
|
||||
import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.datamining.data.Cluster;
|
||||
import com.sap.sse.datamining.shared.impl.dto.ClusterDTO;
|
||||
import com.sap.sse.i18n.ResourceBundleStringMessages;
|
||||
|
||||
public class FoilingSegmentWithContext implements HasFoilingSegmentContext {
|
||||
private final HasBravoFixTrackContext bravoFixTrackContext;
|
||||
private final TimePoint startOfFoilingSegment;
|
||||
private final TimePoint endOfFoilingSegment;
|
||||
|
||||
public FoilingSegmentWithContext(HasBravoFixTrackContext bravoFixTrackContext, TimePoint startOfFoilingSegment,
|
||||
TimePoint endOfFoilingSegment) {
|
||||
super();
|
||||
this.bravoFixTrackContext = bravoFixTrackContext;
|
||||
this.startOfFoilingSegment = startOfFoilingSegment;
|
||||
this.endOfFoilingSegment = endOfFoilingSegment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HasBravoFixTrackContext getBravoFixTrackContext() {
|
||||
return bravoFixTrackContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimePoint getStartOfFoilingSegment() {
|
||||
return startOfFoilingSegment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimePoint getEndOfFoilingSegment() {
|
||||
return endOfFoilingSegment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Duration getDuration() {
|
||||
return getStartOfFoilingSegment().until(getEndOfFoilingSegment());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getDistance() {
|
||||
return getGpsFixTrack().
|
||||
getDistanceTraveled(getStartOfFoilingSegment(), getEndOfFoilingSegment());
|
||||
}
|
||||
|
||||
private GPSFixTrack<Competitor, GPSFixMoving> getGpsFixTrack() {
|
||||
return getTrackedRace().getTrack(getCompetitor());
|
||||
}
|
||||
|
||||
private Competitor getCompetitor() {
|
||||
return getBravoFixTrackContext().getRaceOfCompetitorContext().getCompetitor();
|
||||
}
|
||||
|
||||
private TrackedRace getTrackedRace() {
|
||||
return getBravoFixTrackContext().getRaceOfCompetitorContext().getTrackedRaceContext().getTrackedRace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getTakeoffSpeedInKnots() {
|
||||
final SpeedWithBearing estimatedSpeed = getGpsFixTrack().getEstimatedSpeed(getStartOfFoilingSegment());
|
||||
return estimatedSpeed==null?null:estimatedSpeed.getKnots();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getLandingSpeedInKnots() {
|
||||
final SpeedWithBearing estimatedSpeed = getGpsFixTrack().getEstimatedSpeed(getEndOfFoilingSegment());
|
||||
return estimatedSpeed==null?null:estimatedSpeed.getKnots();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bearing getAbsoluteTrueWindAngleAtTakeoffInDegrees() throws NoWindException {
|
||||
return getAbsoluteTrueWindAngle(getStartOfFoilingSegment());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bearing getAbsoluteTrueWindAngleAtLandingInDegrees() throws NoWindException {
|
||||
final TimePoint timePoint = getEndOfFoilingSegment();
|
||||
return getAbsoluteTrueWindAngle(timePoint);
|
||||
}
|
||||
|
||||
private Bearing getAbsoluteTrueWindAngle(final TimePoint timePoint) throws NoWindException {
|
||||
return getTrackedRace().getTrackedLeg(getCompetitor(), timePoint).getBeatAngle(timePoint).abs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bearing getAverageAbsoluteTrueWindAngle() throws NoWindException {
|
||||
final BearingCluster bearingCluster = new BearingCluster();
|
||||
final BravoFixTrack<Competitor> bravoFixTrack = getBravoFixTrackContext().getBravoFixTrack();
|
||||
bravoFixTrack.lockForRead();
|
||||
try {
|
||||
for (final BravoFix bravoFix : bravoFixTrack.getFixes(getStartOfFoilingSegment(), /* fromInclusive */ true, getEndOfFoilingSegment(), /* toInclusive */ false)) {
|
||||
bearingCluster.add(getAbsoluteTrueWindAngle(bravoFix.getTimePoint()));
|
||||
}
|
||||
} finally {
|
||||
bravoFixTrack.unlockAfterRead();
|
||||
}
|
||||
return bearingCluster.getAverage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClusterDTO getWindStrengthAsBeaufortClusterAtTakeoff(Locale locale,
|
||||
ResourceBundleStringMessages stringMessages) {
|
||||
return getWindStrengthAsBeaufortCluster(locale, stringMessages, getWindAtTakeoff());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClusterDTO getWindStrengthAsBeaufortClusterAtLanding(Locale locale,
|
||||
ResourceBundleStringMessages stringMessages) {
|
||||
return getWindStrengthAsBeaufortCluster(locale, stringMessages, getWindAtLanding());
|
||||
}
|
||||
|
||||
private Wind getWind(TimePoint timePoint) {
|
||||
return getTrackedRace().getWind(getGpsFixTrack().getEstimatedPosition(timePoint, /* extrapolate */ true), timePoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Wind getWindAtTakeoff() {
|
||||
return getWind(getStartOfFoilingSegment());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Wind getWindAtLanding() {
|
||||
return getWind(getEndOfFoilingSegment());
|
||||
}
|
||||
|
||||
private ClusterDTO getWindStrengthAsBeaufortCluster(Locale locale, ResourceBundleStringMessages stringMessages, Wind wind) {
|
||||
Cluster<?> cluster = Activator.getClusterGroups().getWindStrengthInBeaufortClusterGroup().getClusterFor(wind);
|
||||
return new ClusterDTO(cluster.toString(), ()->cluster.asLocalizedString(locale, stringMessages));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LegType getStartsOnLegType() throws NoWindException {
|
||||
return getLegType(getStartOfFoilingSegment());
|
||||
}
|
||||
|
||||
private LegType getLegType(final TimePoint timePoint) throws NoWindException {
|
||||
return getTrackedRace().getTrackedLeg(getCompetitor(), timePoint).getTrackedLeg().getLegType(timePoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LegType getEndsOnLegType() throws NoWindException {
|
||||
return getLegType(getEndOfFoilingSegment());
|
||||
}
|
||||
}
|
||||
+16
@@ -5,6 +5,8 @@ import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.datamining.Activator;
|
||||
import com.sap.sailing.datamining.SailingClusterGroups;
|
||||
import com.sap.sailing.datamining.data.HasLeaderboardContext;
|
||||
import com.sap.sailing.datamining.data.HasRaceResultOfCompetitorContext;
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
@@ -31,6 +33,8 @@ import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.datamining.data.Cluster;
|
||||
import com.sap.sse.datamining.shared.impl.dto.ClusterDTO;
|
||||
|
||||
public class RaceResultOfCompetitorWithContext implements HasRaceResultOfCompetitorContext {
|
||||
private final static Logger logger = Logger.getLogger(RaceResultOfCompetitorWithContext.class.getName());
|
||||
@@ -78,6 +82,18 @@ public class RaceResultOfCompetitorWithContext implements HasRaceResultOfCompeti
|
||||
public String getCompetitorSearchTag() {
|
||||
return getCompetitor().getSearchTag();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClusterDTO getPercentageClusterForRelativeScore() {
|
||||
Double relativeScore = getRelativeRank();
|
||||
if (relativeScore == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
SailingClusterGroups clusterGroups = Activator.getClusterGroups();
|
||||
Cluster<Double> cluster = clusterGroups.getPercentageClusterGroup().getClusterFor(relativeScore);
|
||||
return new ClusterDTO(clusterGroups.getPercentageClusterFormatter().format(cluster));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAverageWindSpeedInRoundedBeaufort() {
|
||||
|
||||
+9
-1
@@ -5,6 +5,11 @@ import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
|
||||
public abstract class AbstractBearing implements Bearing {
|
||||
private static final long serialVersionUID = 1968420344627864784L;
|
||||
|
||||
@Override
|
||||
public int compareTo(Bearing o) {
|
||||
return this==o?0:getDegrees() > o.getDegrees() ? 1 : getDegrees()==o.getDegrees()?0:-1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bearing reverse() {
|
||||
if (getDegrees() >= 180) {
|
||||
@@ -69,5 +74,8 @@ public abstract class AbstractBearing implements Bearing {
|
||||
return getDegrees() / 180. * Math.PI;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Bearing abs() {
|
||||
return getDegrees()>=0?this:new DegreeBearingImpl(-getDegrees());
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
|
||||
|
||||
public interface Bearing extends Serializable {
|
||||
public interface Bearing extends Serializable, Comparable<Bearing> {
|
||||
Bearing NORTH = new DegreeBearingImpl(0);
|
||||
Bearing EAST = new DegreeBearingImpl(90);
|
||||
Bearing SOUTH = new DegreeBearingImpl(180);
|
||||
@@ -42,4 +42,9 @@ public interface Bearing extends Serializable {
|
||||
*/
|
||||
Bearing middle(Bearing other);
|
||||
|
||||
/**
|
||||
* If this bearing has a negative signum, reverts the signum. For example, {@code new DegreeBearingImpl(-10).abs().equals(new DegreeBearingImpl(10)}.
|
||||
*/
|
||||
Bearing abs();
|
||||
|
||||
}
|
||||
+1
-1
@@ -11,7 +11,7 @@ import com.sap.sse.datamining.annotations.Statistic;
|
||||
* <p><b>NOTE:</b> This fix type is currently used to track ESS foiling data, only.</p>
|
||||
*/
|
||||
public interface BravoFix extends SensorFix {
|
||||
static final Distance MIN_FOILING_HEIGHT_THRESHOLD = new MeterDistance(0.2);
|
||||
static final Distance MIN_FOILING_HEIGHT_THRESHOLD = new MeterDistance(0.1);
|
||||
|
||||
/**
|
||||
* Gets the ride height (foiling) for this fix.
|
||||
|
||||
+2
-2
@@ -36,7 +36,7 @@ public class BravoFixImpl implements BravoFix {
|
||||
|
||||
@Override
|
||||
public Distance getRideHeight() {
|
||||
return new MeterDistance(fix.get(BravoSensorDataMetadata.INSTANCE.rideHeightColumn));
|
||||
return Util.min(getRideHeightPortHull(), getRideHeightStarboardHull());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,7 +51,7 @@ public class BravoFixImpl implements BravoFix {
|
||||
|
||||
@Override
|
||||
public boolean isFoiling() {
|
||||
return Util.min(getRideHeightPortHull(), getRideHeightStarboardHull()).compareTo(MIN_FOILING_HEIGHT_THRESHOLD) >= 0;
|
||||
return getRideHeight().compareTo(MIN_FOILING_HEIGHT_THRESHOLD) >= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
@@ -515,6 +515,9 @@ public class SensorFixStoreAndLoadTest {
|
||||
private DoubleVectorFix createBravoDoubleVectorFixWithRideHeight(long timestamp, double rideHeight) {
|
||||
double[] fixData = new double[BravoSensorDataMetadata.INSTANCE.columnCount];
|
||||
fixData[BravoSensorDataMetadata.INSTANCE.rideHeightColumn] = rideHeight;
|
||||
// fill the port/starboard columns as well because their minimum defines the true ride height
|
||||
fixData[BravoSensorDataMetadata.INSTANCE.rideHeightPortHullColumn] = rideHeight;
|
||||
fixData[BravoSensorDataMetadata.INSTANCE.rideHeightStarboardHullColumn] = rideHeight;
|
||||
return new DoubleVectorFixImpl(new MillisecondsTimePoint(timestamp), fixData);
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -118,6 +118,9 @@ public class BravoFixTrackSerializationTest {
|
||||
private void addOrReplaceBravoFixToTrack(boolean replace) {
|
||||
double[] fixData = new double[BravoSensorDataMetadata.INSTANCE.columnCount];
|
||||
fixData[BravoSensorDataMetadata.INSTANCE.rideHeightColumn] = rideHeight;
|
||||
// fill the port/starboard columns as well because their minimum defines the true ride height
|
||||
fixData[BravoSensorDataMetadata.INSTANCE.rideHeightPortHullColumn] = rideHeight;
|
||||
fixData[BravoSensorDataMetadata.INSTANCE.rideHeightStarboardHullColumn] = rideHeight;
|
||||
track.add(new BravoFixImpl(new DoubleVectorFixImpl(timePoint, fixData)), replace);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
<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="-incremental -workDir "${project_loc:com.sap.sailing.gwt.ui}/.tmp/gwt-work" -war "${project_loc:com.sap.sailing.gwt.ui}" -noserver -remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -logLevel INFO -codeServerPort 9876 -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/EmbeddedMapAndWindChart com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -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 -startupUrl /gwt/AutoPlay.html com.sap.sailing.gwt.AutoPlay 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.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 com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-incremental -workDir "${project_loc:com.sap.sailing.gwt.ui}/.tmp/gwt-work" -war "${project_loc:com.sap.sailing.gwt.ui}" -noserver -remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -logLevel INFO -codeServerPort 9876 -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/EmbeddedMapAndWindChart com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -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 -startupUrl /gwt/AutoPlay.html com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.AutoPlay"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms1024m -Xmx3072m -Dgwt.watchFileChanges=false"/>
|
||||
</launchConfiguration>
|
||||
@@ -69,7 +69,7 @@
|
||||
<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/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 -startupUrl /gwt/AutoPlay.html com.sap.sailing.gwt.AutoPlay 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.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.PROGRAM_ARGUMENTS" value="-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/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 -startupUrl /gwt/AutoPlay.html com.sap.sailing.gwt.AutoPlay 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.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 -Dgwt.watchFileChanges=false"/>
|
||||
</launchConfiguration>
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package com.google.gwt.user.client.rpc.core.com.sap.sailing.domain.common.impl;
|
||||
|
||||
import com.google.gwt.user.client.rpc.CustomFieldSerializer;
|
||||
import com.google.gwt.user.client.rpc.SerializationException;
|
||||
import com.google.gwt.user.client.rpc.SerializationStreamReader;
|
||||
import com.google.gwt.user.client.rpc.SerializationStreamWriter;
|
||||
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
|
||||
|
||||
public class DegreeBearingImpl_CustomFieldSerializer extends CustomFieldSerializer<DegreeBearingImpl> {
|
||||
|
||||
@Override
|
||||
public void serializeInstance(SerializationStreamWriter streamWriter, DegreeBearingImpl instance)
|
||||
throws SerializationException {
|
||||
serialize(streamWriter, instance);
|
||||
}
|
||||
|
||||
public static void serialize(SerializationStreamWriter streamWriter, DegreeBearingImpl instance)
|
||||
throws SerializationException {
|
||||
streamWriter.writeDouble(instance.getDegrees());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCustomInstantiateInstance() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DegreeBearingImpl instantiateInstance(SerializationStreamReader streamReader)
|
||||
throws SerializationException {
|
||||
return instantiate(streamReader);
|
||||
}
|
||||
|
||||
public static DegreeBearingImpl instantiate(SerializationStreamReader streamReader)
|
||||
throws SerializationException {
|
||||
return new DegreeBearingImpl(streamReader.readDouble());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeInstance(SerializationStreamReader streamReader, DegreeBearingImpl instance)
|
||||
throws SerializationException {
|
||||
deserialize(streamReader, instance);
|
||||
}
|
||||
|
||||
public static void deserialize(SerializationStreamReader streamReader, DegreeBearingImpl instance) {
|
||||
// Done by instantiateInstance
|
||||
}
|
||||
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package com.google.gwt.user.client.rpc.core.com.sap.sailing.domain.common.impl;
|
||||
|
||||
import com.google.gwt.user.client.rpc.CustomFieldSerializer;
|
||||
import com.google.gwt.user.client.rpc.SerializationException;
|
||||
import com.google.gwt.user.client.rpc.SerializationStreamReader;
|
||||
import com.google.gwt.user.client.rpc.SerializationStreamWriter;
|
||||
import com.sap.sailing.domain.common.impl.RadianBearingImpl;
|
||||
|
||||
public class RadianBearingImpl_CustomFieldSerializer extends CustomFieldSerializer<RadianBearingImpl> {
|
||||
|
||||
@Override
|
||||
public void serializeInstance(SerializationStreamWriter streamWriter, RadianBearingImpl instance)
|
||||
throws SerializationException {
|
||||
serialize(streamWriter, instance);
|
||||
}
|
||||
|
||||
public static void serialize(SerializationStreamWriter streamWriter, RadianBearingImpl instance)
|
||||
throws SerializationException {
|
||||
streamWriter.writeDouble(instance.getRadians());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCustomInstantiateInstance() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RadianBearingImpl instantiateInstance(SerializationStreamReader streamReader)
|
||||
throws SerializationException {
|
||||
return instantiate(streamReader);
|
||||
}
|
||||
|
||||
public static RadianBearingImpl instantiate(SerializationStreamReader streamReader)
|
||||
throws SerializationException {
|
||||
return new RadianBearingImpl(streamReader.readDouble());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeInstance(SerializationStreamReader streamReader, RadianBearingImpl instance)
|
||||
throws SerializationException {
|
||||
deserialize(streamReader, instance);
|
||||
}
|
||||
|
||||
public static void deserialize(SerializationStreamReader streamReader, RadianBearingImpl instance) {
|
||||
// Done by instantiateInstance
|
||||
}
|
||||
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.google.gwt.user.client.rpc.core.com.sap.sse.datamining.shared.impl.dto;
|
||||
|
||||
import com.google.gwt.user.client.rpc.CustomFieldSerializer;
|
||||
import com.google.gwt.user.client.rpc.SerializationException;
|
||||
import com.google.gwt.user.client.rpc.SerializationStreamReader;
|
||||
import com.google.gwt.user.client.rpc.SerializationStreamWriter;
|
||||
import com.sap.sse.datamining.shared.impl.dto.ClusterDTO;
|
||||
|
||||
/**
|
||||
* Ensures that the {@link ClusterDTO#getLocalizedName() localizedName} field is serialized by
|
||||
* really evaluating it eagerly now; this way, an optional lazy evaluation function does not need
|
||||
* to be serialized.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class ClusterDTO_CustomFieldSerializer extends CustomFieldSerializer<ClusterDTO> {
|
||||
|
||||
@Override
|
||||
public void serializeInstance(SerializationStreamWriter streamWriter, ClusterDTO instance)
|
||||
throws SerializationException {
|
||||
serialize(streamWriter, instance);
|
||||
}
|
||||
|
||||
public static void serialize(SerializationStreamWriter streamWriter, ClusterDTO instance)
|
||||
throws SerializationException {
|
||||
streamWriter.writeString(instance.getSignifier());
|
||||
streamWriter.writeString(instance.getLocalizedName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCustomInstantiateInstance() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClusterDTO instantiateInstance(SerializationStreamReader streamReader)
|
||||
throws SerializationException {
|
||||
return instantiate(streamReader);
|
||||
}
|
||||
|
||||
public static ClusterDTO instantiate(SerializationStreamReader streamReader)
|
||||
throws SerializationException {
|
||||
return new ClusterDTO(streamReader.readString(), streamReader.readString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeInstance(SerializationStreamReader streamReader, ClusterDTO instance)
|
||||
throws SerializationException {
|
||||
deserialize(streamReader, instance);
|
||||
}
|
||||
|
||||
public static void deserialize(SerializationStreamReader streamReader, ClusterDTO instance) {
|
||||
// Done by instantiateInstance
|
||||
}
|
||||
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package com.google.gwt.user.client.rpc.core.com.sap.sse.datamining.shared.impl.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.user.client.rpc.CustomFieldSerializer;
|
||||
import com.google.gwt.user.client.rpc.SerializationException;
|
||||
import com.google.gwt.user.client.rpc.SerializationStreamReader;
|
||||
import com.google.gwt.user.client.rpc.SerializationStreamWriter;
|
||||
import com.sap.sse.datamining.shared.impl.dto.FunctionDTO;
|
||||
|
||||
/**
|
||||
* Ensures that the {@link FunctionDTO#getLocalizedName() localizedName} field is serialized by
|
||||
* really evaluating it eagerly now; this way, an optional lazy evaluation function does not need
|
||||
* to be serialized.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class FunctionDTO_CustomFieldSerializer extends CustomFieldSerializer<FunctionDTO> {
|
||||
|
||||
@Override
|
||||
public void serializeInstance(SerializationStreamWriter streamWriter, FunctionDTO instance)
|
||||
throws SerializationException {
|
||||
serialize(streamWriter, instance);
|
||||
}
|
||||
|
||||
public static void serialize(SerializationStreamWriter streamWriter, FunctionDTO instance)
|
||||
throws SerializationException {
|
||||
streamWriter.writeBoolean(instance.isDimension());
|
||||
streamWriter.writeString(instance.getFunctionName());
|
||||
streamWriter.writeString(instance.getSourceTypeName());
|
||||
streamWriter.writeString(instance.getReturnTypeName());
|
||||
streamWriter.writeObject(instance.getParameterTypeNames());
|
||||
streamWriter.writeString(instance.getDisplayName());
|
||||
streamWriter.writeInt(instance.getOrdinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCustomInstantiateInstance() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionDTO instantiateInstance(SerializationStreamReader streamReader)
|
||||
throws SerializationException {
|
||||
return instantiate(streamReader);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // the cast to List<String> is the problem here
|
||||
public static FunctionDTO instantiate(SerializationStreamReader streamReader)
|
||||
throws SerializationException {
|
||||
return new FunctionDTO(/* isDimension */ streamReader.readBoolean(), /* function name */ streamReader.readString(),
|
||||
/* source type name */ streamReader.readString(), /* return type name */ streamReader.readString(),
|
||||
/* parameter type names */ (List<String>) streamReader.readObject(), /* display name */ streamReader.readString(),
|
||||
/* ordinal */ streamReader.readInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeInstance(SerializationStreamReader streamReader, FunctionDTO instance)
|
||||
throws SerializationException {
|
||||
deserialize(streamReader, instance);
|
||||
}
|
||||
|
||||
public static void deserialize(SerializationStreamReader streamReader, FunctionDTO instance) {
|
||||
// Done by instantiateInstance
|
||||
}
|
||||
|
||||
}
|
||||
+9
-5
@@ -16,7 +16,7 @@ import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint;
|
||||
import com.sap.sailing.gwt.ui.client.RemoteServiceMappingConstants;
|
||||
import com.sap.sailing.gwt.ui.datamining.execution.SimpleQueryRunner;
|
||||
import com.sap.sailing.gwt.ui.datamining.presentation.TabbedResultsPresenter;
|
||||
import com.sap.sailing.gwt.ui.datamining.selection.BufferingQueryDefinitionProviderWithControls;
|
||||
import com.sap.sailing.gwt.ui.datamining.selection.QueryDefinitionProviderWithControls;
|
||||
import com.sap.sse.datamining.shared.DataMiningSession;
|
||||
import com.sap.sse.datamining.shared.impl.UUIDDataMiningSession;
|
||||
import com.sap.sse.gwt.client.EntryPointHelper;
|
||||
@@ -58,8 +58,8 @@ public class DataMiningEntryPoint extends AbstractSailingEntryPoint {
|
||||
ResultsPresenter<?> resultsPresenter = new TabbedResultsPresenter(null, null, getStringMessages());
|
||||
|
||||
DockLayoutPanel selectionDockPanel = new DockLayoutPanel(Unit.PX);
|
||||
BufferingQueryDefinitionProviderWithControls queryDefinitionProviderWithControls =
|
||||
new BufferingQueryDefinitionProviderWithControls(null, null, session, getStringMessages(),
|
||||
QueryDefinitionProviderWithControls queryDefinitionProviderWithControls =
|
||||
new QueryDefinitionProviderWithControls(null, null, session, getStringMessages(),
|
||||
dataMiningService, DataMiningEntryPoint.this, settingsControl, resultsPresenter);
|
||||
queryDefinitionProviderWithControls.getEntryWidget().addStyleName("dataMiningPanel");
|
||||
selectionDockPanel.add(queryDefinitionProviderWithControls.getEntryWidget());
|
||||
@@ -68,7 +68,11 @@ public class DataMiningEntryPoint extends AbstractSailingEntryPoint {
|
||||
dataMiningService,
|
||||
DataMiningEntryPoint.this, queryDefinitionProviderWithControls, resultsPresenter);
|
||||
queryDefinitionProviderWithControls.addControl(queryRunner.getEntryWidget());
|
||||
settingsControl.addSettingsComponent(queryRunner);
|
||||
/* Running queries automatically when they've been changed is currently unnecessary, if not even counterproductive.
|
||||
* This removes the query runner settings to prevent that the user can enable the automatic execution of queries.
|
||||
* Re-enable this, when this functionality is desired again.
|
||||
*/
|
||||
// settingsControl.addSettingsComponent(queryRunner);
|
||||
|
||||
SplitLayoutPanel splitPanel = new SplitLayoutPanel(15);
|
||||
splitPanel.addSouth(resultsPresenter.getEntryWidget(), 350);
|
||||
@@ -84,4 +88,4 @@ public class DataMiningEntryPoint extends AbstractSailingEntryPoint {
|
||||
rootPanel.add(panel);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -26,8 +26,8 @@ public interface DataMiningService extends RemoteService {
|
||||
HashSet<FunctionDTO> getStatisticsFor(DataRetrieverChainDefinitionDTO retrieverChainDefinition, String localeInfoName);
|
||||
|
||||
HashSet<AggregationProcessorDefinitionDTO> getAggregatorDefinitionsFor(FunctionDTO extractionFunction, String localeInfoName);
|
||||
|
||||
HashSet<FunctionDTO> getDimensionsFor(FunctionDTO statisticToCalculate, String localeInfoName);
|
||||
|
||||
HashSet<FunctionDTO> getDimensionsFor(DataRetrieverChainDefinitionDTO dataRetrieverChainDefinitionDTO, String localeInfoName);
|
||||
HashMap<DataRetrieverLevelDTO, HashSet<FunctionDTO>> getDimensionsMappedByLevelFor(
|
||||
DataRetrieverChainDefinitionDTO dataRetrieverChainDefinitionDTO, String localeInfoName);
|
||||
HashMap<DataRetrieverLevelDTO, HashSet<FunctionDTO>> getReducedDimensionsMappedByLevelFor(
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ public interface DataMiningServiceAsync {
|
||||
void getAggregatorDefinitionsFor(FunctionDTO extractionFunction, String localeInfoName,
|
||||
AsyncCallback<HashSet<AggregationProcessorDefinitionDTO>> asyncCallback);
|
||||
|
||||
void getDimensionsFor(FunctionDTO statisticToCalculate, String localeInfoName, AsyncCallback<HashSet<FunctionDTO>> callback);
|
||||
void getDimensionsFor(DataRetrieverChainDefinitionDTO dataRetrieverChainDefinitionDTO, String localeInfoName, AsyncCallback<HashSet<FunctionDTO>> callback);
|
||||
void getDimensionsMappedByLevelFor(DataRetrieverChainDefinitionDTO dataRetrieverChainDefinitionDTO, String localeInfoName,
|
||||
AsyncCallback<HashMap<DataRetrieverLevelDTO, HashSet<FunctionDTO>>> callback);
|
||||
public void getReducedDimensionsMappedByLevelFor(DataRetrieverChainDefinitionDTO dataRetrieverChainDefinitionDTO, String localeInfoName,
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import com.sap.sse.common.settings.SerializableSettings;
|
||||
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
|
||||
import com.sap.sse.datamining.shared.impl.dto.FunctionDTO;
|
||||
|
||||
public interface GroupingProvider extends DataMiningComponentProvider<SerializableSettings>, StatisticChangedListener{
|
||||
public interface GroupingProvider extends DataMiningComponentProvider<SerializableSettings>, DataRetrieverChainDefinitionChangedListener {
|
||||
|
||||
public Collection<FunctionDTO> getDimensionsToGroupBy();
|
||||
public String getCustomGrouperScriptText();
|
||||
|
||||
+29
-3
@@ -2,9 +2,11 @@ package com.sap.sailing.gwt.ui.datamining.execution;
|
||||
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.user.client.Timer;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.datamining.DataMiningService;
|
||||
import com.sap.sailing.gwt.ui.datamining.DataMiningServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.datamining.ManagedDataMiningQueriesCounter;
|
||||
import com.sap.sailing.gwt.ui.datamining.QueryDefinitionProvider;
|
||||
@@ -23,12 +25,29 @@ import com.sap.sse.gwt.client.shared.perspective.ComponentContext;
|
||||
|
||||
public class SimpleQueryRunner extends AbstractComponent<QueryRunnerSettings> implements QueryRunner {
|
||||
|
||||
/**
|
||||
* The delay before a query is sent to the {@link DataMiningService}.
|
||||
*
|
||||
* @see #queryReleaseTimer
|
||||
*/
|
||||
private static final int queryBufferTimeInMillis = 200;
|
||||
|
||||
private final DataMiningSession session;
|
||||
private final StringMessages stringMessages;
|
||||
private final DataMiningServiceAsync dataMiningService;
|
||||
private final ErrorReporter errorReporter;
|
||||
private final ManagedDataMiningQueriesCounter counter;
|
||||
|
||||
|
||||
/**
|
||||
* Timer to prevent the execution of unnecessary queries, when they're run
|
||||
* automatically (see {@link QueryRunnerSettings}). This can be caused by
|
||||
* a change of the used data type, that then causes a change of the
|
||||
* dimension to group by and the data retriever chain. Or caused by quick
|
||||
* changes of the filter selection.
|
||||
*
|
||||
* @see #queryBufferTimeInMillis
|
||||
*/
|
||||
private final Timer queryReleaseTimer;
|
||||
private QueryRunnerSettings settings;
|
||||
private final QueryDefinitionProvider<?> queryDefinitionProvider;
|
||||
private final ResultsPresenter<?> resultsPresenter;
|
||||
@@ -56,7 +75,13 @@ public class SimpleQueryRunner extends AbstractComponent<QueryRunnerSettings> im
|
||||
run(SimpleQueryRunner.this.queryDefinitionProvider.getQueryDefinition());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
queryReleaseTimer = new Timer() {
|
||||
@Override
|
||||
public void run() {
|
||||
SimpleQueryRunner.this.run(queryDefinitionProvider.getQueryDefinition());
|
||||
}
|
||||
};
|
||||
if (this.settings.isRunAutomatically()) {
|
||||
queryDefinitionProvider.addQueryDefinitionChangedListener(this);
|
||||
}
|
||||
@@ -98,7 +123,8 @@ public class SimpleQueryRunner extends AbstractComponent<QueryRunnerSettings> im
|
||||
|
||||
@Override
|
||||
public void queryDefinitionChanged(StatisticQueryDefinitionDTO newQueryDefinition) {
|
||||
run(newQueryDefinition);
|
||||
// See javadoc of queryReleaseTimer
|
||||
queryReleaseTimer.schedule(queryBufferTimeInMillis);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
@@ -7,9 +7,11 @@ import java.util.Map;
|
||||
|
||||
import com.google.gwt.core.client.Scheduler;
|
||||
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.datamining.presentation.dataproviders.AbstractResultDataProvider;
|
||||
import com.sap.sailing.gwt.ui.datamining.presentation.dataproviders.BearingDataProvider;
|
||||
import com.sap.sailing.gwt.ui.datamining.presentation.dataproviders.DistanceDataProvider;
|
||||
import com.sap.sailing.gwt.ui.datamining.presentation.dataproviders.DurationDataProvider;
|
||||
import com.sap.sailing.gwt.ui.datamining.presentation.dataproviders.NumberDataProvider;
|
||||
@@ -35,6 +37,8 @@ public abstract class AbstractResultsPresenterWithDataProviders<SettingsType ext
|
||||
dataProviders.put(distanceDataProvider.getResultType().getName(), distanceDataProvider);
|
||||
AbstractResultDataProvider<Duration> durationDataProvider = new DurationDataProvider();
|
||||
dataProviders.put(durationDataProvider.getResultType().getName(), durationDataProvider);
|
||||
AbstractResultDataProvider<Bearing> bearingDataProvider = new BearingDataProvider();
|
||||
dataProviders.put(bearingDataProvider.getResultType().getName(), bearingDataProvider);
|
||||
}
|
||||
|
||||
protected void internalShowResults(QueryResultDTO<?> result) {
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.sap.sailing.gwt.ui.datamining.presentation.dataproviders;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
|
||||
|
||||
public class BearingDataProvider extends AbstractDataProvider<Bearing> {
|
||||
|
||||
private static final String DEGREES = "Angle in Degrees";
|
||||
private static final String RADIANS = "Angle in Radians";
|
||||
|
||||
public BearingDataProvider() {
|
||||
super(Bearing.class, getMappings());
|
||||
}
|
||||
|
||||
private static LinkedHashMap<String, Function<Bearing, Number>> getMappings() {
|
||||
LinkedHashMap<String, Function<Bearing, Number>> mappings = new LinkedHashMap<>();
|
||||
mappings.put(DEGREES, bearing->bearing.getDegrees());
|
||||
mappings.put(RADIANS, bearing->bearing.getRadians());
|
||||
return mappings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultDataKeyFor(QueryResultDTO<?> result) {
|
||||
return DEGREES;
|
||||
}
|
||||
}
|
||||
+21
-7
@@ -4,22 +4,36 @@ import java.util.LinkedHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
|
||||
|
||||
public class DistanceDataProvider extends AbstractDataProvider<Distance> {
|
||||
|
||||
private static final String CENTRAL_ANGLE_RADIAN = "Central Angle Radian";
|
||||
private static final String CENTRAL_ANGLE_DEGREE = "Central Angle Degree";
|
||||
private static final String KILOMETERS = "Kilometers";
|
||||
private static final String METERS = "Meters";
|
||||
private static final String NAUTICAL_MILES = "Nautical Miles";
|
||||
private static final String SEA_MILES = "Sea Miles";
|
||||
private static final String GEOGRAPHICAL_MILES = "Geographical Miles";
|
||||
|
||||
public DistanceDataProvider() {
|
||||
super(Distance.class, getMappings());
|
||||
}
|
||||
|
||||
private static LinkedHashMap<String, Function<Distance, Number>> getMappings() {
|
||||
LinkedHashMap<String, Function<Distance, Number>> mappings = new LinkedHashMap<>();
|
||||
mappings.put("Geographical Miles", distance->distance.getGeographicalMiles());
|
||||
mappings.put("Sea Miles", distance->distance.getSeaMiles());
|
||||
mappings.put("Nautical Miles", distance->distance.getNauticalMiles());
|
||||
mappings.put("Meters", distance->distance.getMeters());
|
||||
mappings.put("Kilometers", distance->distance.getKilometers());
|
||||
mappings.put("Central Angle Degree", distance->distance.getCentralAngleDeg());
|
||||
mappings.put("Central Angle Radian", distance->distance.getCentralAngleRad());
|
||||
mappings.put(GEOGRAPHICAL_MILES, distance->distance.getGeographicalMiles());
|
||||
mappings.put(SEA_MILES, distance->distance.getSeaMiles());
|
||||
mappings.put(NAUTICAL_MILES, distance->distance.getNauticalMiles());
|
||||
mappings.put(METERS, distance->distance.getMeters());
|
||||
mappings.put(KILOMETERS, distance->distance.getKilometers());
|
||||
mappings.put(CENTRAL_ANGLE_DEGREE, distance->distance.getCentralAngleDeg());
|
||||
mappings.put(CENTRAL_ANGLE_RADIAN, distance->distance.getCentralAngleRad());
|
||||
return mappings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultDataKeyFor(QueryResultDTO<?> result) {
|
||||
return METERS;
|
||||
}
|
||||
}
|
||||
+279
-280
@@ -1,280 +1,279 @@
|
||||
package com.sap.sailing.gwt.ui.datamining.selection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.gwt.event.logical.shared.ValueChangeEvent;
|
||||
import com.google.gwt.event.logical.shared.ValueChangeHandler;
|
||||
import com.google.gwt.i18n.client.LocaleInfo;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.ValueListBox;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.client.shared.controls.AbstractObjectRenderer;
|
||||
import com.sap.sailing.gwt.ui.datamining.DataMiningServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.datamining.GroupingChangedListener;
|
||||
import com.sap.sailing.gwt.ui.datamining.GroupingProvider;
|
||||
import com.sap.sailing.gwt.ui.datamining.StatisticProvider;
|
||||
import com.sap.sse.common.settings.SerializableSettings;
|
||||
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
|
||||
import com.sap.sse.datamining.shared.impl.dto.AggregationProcessorDefinitionDTO;
|
||||
import com.sap.sse.datamining.shared.impl.dto.FunctionDTO;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.shared.components.AbstractComponent;
|
||||
import com.sap.sse.gwt.client.shared.components.Component;
|
||||
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
|
||||
import com.sap.sse.gwt.client.shared.perspective.ComponentContext;
|
||||
|
||||
public class MultiDimensionalGroupingProvider extends AbstractComponent<SerializableSettings> implements GroupingProvider {
|
||||
|
||||
private static final String GROUPING_PROVIDER_ELEMENT_STYLE = "groupingProviderElement";
|
||||
|
||||
private final StringMessages stringMessages;
|
||||
private final DataMiningServiceAsync dataMiningService;
|
||||
private final ErrorReporter errorReporter;
|
||||
private final Set<GroupingChangedListener> listeners;
|
||||
|
||||
private final FlowPanel mainPanel;
|
||||
private final List<ValueListBox<FunctionDTO>> dimensionToGroupByBoxes;
|
||||
|
||||
private boolean isAwaitingReload;
|
||||
private FunctionDTO currentStatisticToCalculate;
|
||||
private final List<FunctionDTO> availableDimensions;
|
||||
|
||||
public MultiDimensionalGroupingProvider(Component<?> parent, ComponentContext<?, ?> context,
|
||||
StringMessages stringMessages,
|
||||
DataMiningServiceAsync dataMiningService, ErrorReporter errorReporter,
|
||||
StatisticProvider statisticProvider) {
|
||||
super(parent, context);
|
||||
this.stringMessages = stringMessages;
|
||||
this.dataMiningService = dataMiningService;
|
||||
this.errorReporter = errorReporter;
|
||||
listeners = new HashSet<GroupingChangedListener>();
|
||||
currentStatisticToCalculate = null;
|
||||
availableDimensions = new ArrayList<>();
|
||||
isAwaitingReload = false;
|
||||
dimensionToGroupByBoxes = new ArrayList<ValueListBox<FunctionDTO>>();
|
||||
|
||||
mainPanel = new FlowPanel();
|
||||
Label groupByLabel = new Label(this.stringMessages.groupBy());
|
||||
groupByLabel.addStyleName(GROUPING_PROVIDER_ELEMENT_STYLE);
|
||||
mainPanel.add(groupByLabel);
|
||||
|
||||
ValueListBox<FunctionDTO> firstDimensionToGroupByBox = createDimensionToGroupByBox();
|
||||
addDimensionToGroupByBoxAndUpdateAcceptableValues(firstDimensionToGroupByBox);
|
||||
statisticProvider.addStatisticChangedListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void awaitReloadComponents() {
|
||||
isAwaitingReload = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAwatingReload() {
|
||||
return isAwaitingReload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reloadComponents() {
|
||||
isAwaitingReload = false;
|
||||
updateAvailableDimensions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void statisticChanged(FunctionDTO newStatisticToCalculate, AggregationProcessorDefinitionDTO newAggregatorDefinition) {
|
||||
if (!Objects.equals(currentStatisticToCalculate, newStatisticToCalculate)) {
|
||||
currentStatisticToCalculate = newStatisticToCalculate;
|
||||
if (!isAwaitingReload) {
|
||||
updateAvailableDimensions();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAvailableDimensions() {
|
||||
if (currentStatisticToCalculate != null) {
|
||||
dataMiningService.getDimensionsFor(currentStatisticToCalculate, LocaleInfo.getCurrentLocale()
|
||||
.getLocaleName(), new AsyncCallback<HashSet<FunctionDTO>>() {
|
||||
@Override
|
||||
public void onSuccess(HashSet<FunctionDTO> dimensions) {
|
||||
clearAvailableDimensionsAndGroupByBoxes();
|
||||
for (FunctionDTO dimension : dimensions) {
|
||||
availableDimensions.add(dimension);
|
||||
}
|
||||
ValueListBox<FunctionDTO> firstDimensionToGroupByBox = createDimensionToGroupByBox();
|
||||
addDimensionToGroupByBoxAndUpdateAcceptableValues(firstDimensionToGroupByBox);
|
||||
if (!availableDimensions.isEmpty()) {
|
||||
Collections.sort(availableDimensions);
|
||||
firstDimensionToGroupByBox.setValue(availableDimensions.iterator().next(), true);
|
||||
} else {
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Error fetching the dimensions from the server: " + caught.getMessage());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
clearAvailableDimensionsAndGroupByBoxes();
|
||||
ValueListBox<FunctionDTO> firstDimensionToGroupByBox = createDimensionToGroupByBox();
|
||||
addDimensionToGroupByBoxAndUpdateAcceptableValues(firstDimensionToGroupByBox);
|
||||
}
|
||||
}
|
||||
|
||||
private void clearAvailableDimensionsAndGroupByBoxes() {
|
||||
for (ValueListBox<FunctionDTO> dimensionToGroupByBox : dimensionToGroupByBoxes) {
|
||||
mainPanel.remove(dimensionToGroupByBox);
|
||||
}
|
||||
dimensionToGroupByBoxes.clear();
|
||||
availableDimensions.clear();
|
||||
}
|
||||
|
||||
private ValueListBox<FunctionDTO> createDimensionToGroupByBox() {
|
||||
ValueListBox<FunctionDTO> dimensionToGroupByBox = new ValueListBox<FunctionDTO>(new AbstractObjectRenderer<FunctionDTO>() {
|
||||
@Override
|
||||
protected String convertObjectToString(FunctionDTO function) {
|
||||
return function.getDisplayName();
|
||||
}
|
||||
|
||||
});
|
||||
dimensionToGroupByBox.addStyleName(GROUPING_PROVIDER_ELEMENT_STYLE);
|
||||
dimensionToGroupByBox.addValueChangeHandler(new ValueChangeHandler<FunctionDTO>() {
|
||||
private boolean firstChange = true;
|
||||
|
||||
@Override
|
||||
public void onValueChange(ValueChangeEvent<FunctionDTO> event) {
|
||||
if (firstChange && event.getValue() != null) {
|
||||
ValueListBox<FunctionDTO> newDimensionToGroupByBox = createDimensionToGroupByBox();
|
||||
addDimensionToGroupByBox(newDimensionToGroupByBox);
|
||||
firstChange = false;
|
||||
} else if (event.getValue() == null) {
|
||||
Widget changedDimensionToGroupByBox = (Widget) event.getSource();
|
||||
mainPanel.remove(changedDimensionToGroupByBox);
|
||||
dimensionToGroupByBoxes.remove(changedDimensionToGroupByBox);
|
||||
}
|
||||
updateAcceptableValues();
|
||||
notifyListeners();
|
||||
}
|
||||
});
|
||||
return dimensionToGroupByBox;
|
||||
}
|
||||
|
||||
private void addDimensionToGroupByBoxAndUpdateAcceptableValues(ValueListBox<FunctionDTO> dimensionToGroupByBox) {
|
||||
addDimensionToGroupByBox(dimensionToGroupByBox);
|
||||
updateAcceptableValues();
|
||||
}
|
||||
|
||||
private void addDimensionToGroupByBox(ValueListBox<FunctionDTO> dimensionToGroupByBox) {
|
||||
mainPanel.add(dimensionToGroupByBox);
|
||||
dimensionToGroupByBoxes.add(dimensionToGroupByBox);
|
||||
}
|
||||
|
||||
private void updateAcceptableValues() {
|
||||
for (ValueListBox<FunctionDTO> dimensionToGroupByBox : dimensionToGroupByBoxes) {
|
||||
List<FunctionDTO> acceptableValues = new ArrayList<FunctionDTO>(availableDimensions);
|
||||
acceptableValues.removeAll(getDimensionsToGroupBy());
|
||||
if (dimensionToGroupByBox.getValue() != null) {
|
||||
acceptableValues.add(dimensionToGroupByBox.getValue());
|
||||
}
|
||||
Collections.sort(acceptableValues);
|
||||
acceptableValues.add(null);
|
||||
dimensionToGroupByBox.setAcceptableValues(acceptableValues);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FunctionDTO> getDimensionsToGroupBy() {
|
||||
Collection<FunctionDTO> dimensionsToGroupBy = new ArrayList<FunctionDTO>();
|
||||
for (ValueListBox<FunctionDTO> dimensionListBox : dimensionToGroupByBoxes) {
|
||||
if (dimensionListBox.getValue() != null) {
|
||||
dimensionsToGroupBy.add(dimensionListBox.getValue());
|
||||
}
|
||||
}
|
||||
return dimensionsToGroupBy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCustomGrouperScriptText() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyQueryDefinition(StatisticQueryDefinitionDTO queryDefinition) {
|
||||
int index = 0;
|
||||
for (FunctionDTO dimension : queryDefinition.getDimensionsToGroupBy()) {
|
||||
dimensionToGroupByBoxes.get(index).setValue(dimension, true);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addGroupingChangedListener(GroupingChangedListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
private void notifyListeners() {
|
||||
for (GroupingChangedListener listener : listeners) {
|
||||
listener.groupingChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocalizedShortName() {
|
||||
return stringMessages.groupingProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Widget getEntryWidget() {
|
||||
return mainPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return mainPanel.isVisible();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean visibility) {
|
||||
mainPanel.setVisible(visibility);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSettings() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SettingsDialogComponent<SerializableSettings> getSettingsDialogComponent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSettings(SerializableSettings newSettings) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDependentCssClassName() {
|
||||
return "multiDimensionalGroupingProvider";
|
||||
}
|
||||
|
||||
@Override
|
||||
public SerializableSettings getSettings() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "MultiDimensionalGroupingProvider";
|
||||
}
|
||||
|
||||
}
|
||||
package com.sap.sailing.gwt.ui.datamining.selection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.gwt.event.logical.shared.ValueChangeEvent;
|
||||
import com.google.gwt.event.logical.shared.ValueChangeHandler;
|
||||
import com.google.gwt.i18n.client.LocaleInfo;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.ValueListBox;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.client.shared.controls.AbstractObjectRenderer;
|
||||
import com.sap.sailing.gwt.ui.datamining.DataMiningServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.datamining.DataRetrieverChainDefinitionProvider;
|
||||
import com.sap.sailing.gwt.ui.datamining.GroupingChangedListener;
|
||||
import com.sap.sailing.gwt.ui.datamining.GroupingProvider;
|
||||
import com.sap.sse.common.settings.SerializableSettings;
|
||||
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
|
||||
import com.sap.sse.datamining.shared.impl.dto.DataRetrieverChainDefinitionDTO;
|
||||
import com.sap.sse.datamining.shared.impl.dto.FunctionDTO;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.shared.components.AbstractComponent;
|
||||
import com.sap.sse.gwt.client.shared.components.Component;
|
||||
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
|
||||
import com.sap.sse.gwt.client.shared.perspective.ComponentContext;
|
||||
|
||||
public class MultiDimensionalGroupingProvider extends AbstractComponent<SerializableSettings>
|
||||
implements GroupingProvider {
|
||||
|
||||
private static final String GROUPING_PROVIDER_ELEMENT_STYLE = "groupingProviderElement";
|
||||
|
||||
private final StringMessages stringMessages;
|
||||
private final DataMiningServiceAsync dataMiningService;
|
||||
private final ErrorReporter errorReporter;
|
||||
private final Set<GroupingChangedListener> listeners;
|
||||
|
||||
private final FlowPanel mainPanel;
|
||||
private final List<ValueListBox<FunctionDTO>> dimensionToGroupByBoxes;
|
||||
|
||||
private boolean isAwaitingReload;
|
||||
private DataRetrieverChainDefinitionDTO currentRetrieverChainDefinition;
|
||||
private final List<FunctionDTO> availableDimensions;
|
||||
|
||||
public MultiDimensionalGroupingProvider(Component<?> parent, ComponentContext<?, ?> context,StringMessages stringMessages, DataMiningServiceAsync dataMiningService, ErrorReporter errorReporter,
|
||||
DataRetrieverChainDefinitionProvider retrieverChainProvider) {
|
||||
super(parent, context);
|
||||
this.stringMessages = stringMessages;
|
||||
this.dataMiningService = dataMiningService;
|
||||
this.errorReporter = errorReporter;
|
||||
listeners = new HashSet<GroupingChangedListener>();
|
||||
currentRetrieverChainDefinition = null;
|
||||
availableDimensions = new ArrayList<>();
|
||||
isAwaitingReload = false;
|
||||
dimensionToGroupByBoxes = new ArrayList<ValueListBox<FunctionDTO>>();
|
||||
|
||||
mainPanel = new FlowPanel();
|
||||
Label groupByLabel = new Label(this.stringMessages.groupBy());
|
||||
groupByLabel.addStyleName(GROUPING_PROVIDER_ELEMENT_STYLE);
|
||||
mainPanel.add(groupByLabel);
|
||||
|
||||
ValueListBox<FunctionDTO> firstDimensionToGroupByBox = createDimensionToGroupByBox();
|
||||
addDimensionToGroupByBoxAndUpdateAcceptableValues(firstDimensionToGroupByBox);
|
||||
retrieverChainProvider.addDataRetrieverChainDefinitionChangedListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void awaitReloadComponents() {
|
||||
isAwaitingReload = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAwatingReload() {
|
||||
return isAwaitingReload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reloadComponents() {
|
||||
isAwaitingReload = false;
|
||||
updateAvailableDimensions();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void dataRetrieverChainDefinitionChanged(DataRetrieverChainDefinitionDTO newRetrieverChainDefinition) {
|
||||
if (!Objects.equals(currentRetrieverChainDefinition, newRetrieverChainDefinition)) {
|
||||
currentRetrieverChainDefinition = newRetrieverChainDefinition;
|
||||
if (!isAwaitingReload) {
|
||||
updateAvailableDimensions();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAvailableDimensions() {
|
||||
if (currentRetrieverChainDefinition != null) {
|
||||
dataMiningService.getDimensionsFor(currentRetrieverChainDefinition, LocaleInfo.getCurrentLocale()
|
||||
.getLocaleName(), new AsyncCallback<HashSet<FunctionDTO>>() {
|
||||
@Override
|
||||
public void onSuccess(HashSet<FunctionDTO> dimensions) {
|
||||
clearAvailableDimensionsAndGroupByBoxes();
|
||||
for (FunctionDTO dimension : dimensions) {
|
||||
availableDimensions.add(dimension);
|
||||
}
|
||||
ValueListBox<FunctionDTO> firstDimensionToGroupByBox = createDimensionToGroupByBox();
|
||||
addDimensionToGroupByBoxAndUpdateAcceptableValues(firstDimensionToGroupByBox);
|
||||
if (!availableDimensions.isEmpty()) {
|
||||
Collections.sort(availableDimensions);
|
||||
firstDimensionToGroupByBox.setValue(availableDimensions.iterator().next(), true);
|
||||
} else {
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Error fetching the dimensions from the server: " + caught.getMessage());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
clearAvailableDimensionsAndGroupByBoxes();
|
||||
ValueListBox<FunctionDTO> firstDimensionToGroupByBox = createDimensionToGroupByBox();
|
||||
addDimensionToGroupByBoxAndUpdateAcceptableValues(firstDimensionToGroupByBox);
|
||||
}
|
||||
}
|
||||
|
||||
private void clearAvailableDimensionsAndGroupByBoxes() {
|
||||
for (ValueListBox<FunctionDTO> dimensionToGroupByBox : dimensionToGroupByBoxes) {
|
||||
mainPanel.remove(dimensionToGroupByBox);
|
||||
}
|
||||
dimensionToGroupByBoxes.clear();
|
||||
availableDimensions.clear();
|
||||
}
|
||||
|
||||
private ValueListBox<FunctionDTO> createDimensionToGroupByBox() {
|
||||
ValueListBox<FunctionDTO> dimensionToGroupByBox = new ValueListBox<FunctionDTO>(new AbstractObjectRenderer<FunctionDTO>() {
|
||||
@Override
|
||||
protected String convertObjectToString(FunctionDTO function) {
|
||||
return function.getDisplayName();
|
||||
}
|
||||
|
||||
});
|
||||
dimensionToGroupByBox.addStyleName(GROUPING_PROVIDER_ELEMENT_STYLE);
|
||||
dimensionToGroupByBox.addValueChangeHandler(new ValueChangeHandler<FunctionDTO>() {
|
||||
private boolean firstChange = true;
|
||||
|
||||
@Override
|
||||
public void onValueChange(ValueChangeEvent<FunctionDTO> event) {
|
||||
if (firstChange && event.getValue() != null) {
|
||||
ValueListBox<FunctionDTO> newDimensionToGroupByBox = createDimensionToGroupByBox();
|
||||
addDimensionToGroupByBox(newDimensionToGroupByBox);
|
||||
firstChange = false;
|
||||
} else if (event.getValue() == null) {
|
||||
Widget changedDimensionToGroupByBox = (Widget) event.getSource();
|
||||
mainPanel.remove(changedDimensionToGroupByBox);
|
||||
dimensionToGroupByBoxes.remove(changedDimensionToGroupByBox);
|
||||
}
|
||||
updateAcceptableValues();
|
||||
notifyListeners();
|
||||
}
|
||||
});
|
||||
return dimensionToGroupByBox;
|
||||
}
|
||||
|
||||
private void addDimensionToGroupByBoxAndUpdateAcceptableValues(ValueListBox<FunctionDTO> dimensionToGroupByBox) {
|
||||
addDimensionToGroupByBox(dimensionToGroupByBox);
|
||||
updateAcceptableValues();
|
||||
}
|
||||
|
||||
private void addDimensionToGroupByBox(ValueListBox<FunctionDTO> dimensionToGroupByBox) {
|
||||
mainPanel.add(dimensionToGroupByBox);
|
||||
dimensionToGroupByBoxes.add(dimensionToGroupByBox);
|
||||
}
|
||||
|
||||
private void updateAcceptableValues() {
|
||||
for (ValueListBox<FunctionDTO> dimensionToGroupByBox : dimensionToGroupByBoxes) {
|
||||
List<FunctionDTO> acceptableValues = new ArrayList<FunctionDTO>(availableDimensions);
|
||||
acceptableValues.removeAll(getDimensionsToGroupBy());
|
||||
if (dimensionToGroupByBox.getValue() != null) {
|
||||
acceptableValues.add(dimensionToGroupByBox.getValue());
|
||||
}
|
||||
Collections.sort(acceptableValues);
|
||||
acceptableValues.add(null);
|
||||
dimensionToGroupByBox.setAcceptableValues(acceptableValues);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FunctionDTO> getDimensionsToGroupBy() {
|
||||
Collection<FunctionDTO> dimensionsToGroupBy = new ArrayList<FunctionDTO>();
|
||||
for (ValueListBox<FunctionDTO> dimensionListBox : dimensionToGroupByBoxes) {
|
||||
if (dimensionListBox.getValue() != null) {
|
||||
dimensionsToGroupBy.add(dimensionListBox.getValue());
|
||||
}
|
||||
}
|
||||
return dimensionsToGroupBy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCustomGrouperScriptText() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyQueryDefinition(StatisticQueryDefinitionDTO queryDefinition) {
|
||||
int index = 0;
|
||||
for (FunctionDTO dimension : queryDefinition.getDimensionsToGroupBy()) {
|
||||
dimensionToGroupByBoxes.get(index).setValue(dimension, true);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addGroupingChangedListener(GroupingChangedListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
private void notifyListeners() {
|
||||
for (GroupingChangedListener listener : listeners) {
|
||||
listener.groupingChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocalizedShortName() {
|
||||
return stringMessages.groupingProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Widget getEntryWidget() {
|
||||
return mainPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return mainPanel.isVisible();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean visibility) {
|
||||
mainPanel.setVisible(visibility);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSettings() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SettingsDialogComponent<SerializableSettings> getSettingsDialogComponent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSettings(SerializableSettings newSettings) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDependentCssClassName() {
|
||||
return "multiDimensionalGroupingProvider";
|
||||
}
|
||||
|
||||
@Override
|
||||
public SerializableSettings getSettings() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "MultiDimensionalGroupingProvider";
|
||||
}
|
||||
}
|
||||
+30
-49
@@ -11,7 +11,6 @@ import com.google.gwt.dom.client.Style.Unit;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.i18n.client.LocaleInfo;
|
||||
import com.google.gwt.user.client.Timer;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.DockLayoutPanel;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
@@ -51,21 +50,11 @@ import com.sap.sse.gwt.client.shared.components.Component;
|
||||
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
|
||||
import com.sap.sse.gwt.client.shared.perspective.ComponentContext;
|
||||
|
||||
public class BufferingQueryDefinitionProviderWithControls extends AbstractQueryDefinitionProvider<AdvancedDataMiningSettings> implements WithControls {
|
||||
|
||||
/**
|
||||
* The delay before a changed query definition is submitted to the listeners.
|
||||
* This prevents unnecessary queries caused by a change of the used data type, that then causes
|
||||
* a change of the dimension to group by and the data retriever chain.
|
||||
* Or caused by quick changes of the filter selection.
|
||||
*/
|
||||
private static final int queryBufferTimeInMillis = 200;
|
||||
public class QueryDefinitionProviderWithControls extends AbstractQueryDefinitionProvider<AdvancedDataMiningSettings> implements WithControls {
|
||||
|
||||
private static final double headerPanelHeight = 45;
|
||||
private static final double footerPanelHeight = 50;
|
||||
|
||||
private final Timer queryDefinitionReleaseTimer;
|
||||
|
||||
private final DockLayoutPanel mainPanel;
|
||||
private final FlowPanel controlsPanel;
|
||||
private final ToggleButton queryDefinitionViewerToggleButton;
|
||||
@@ -82,19 +71,12 @@ public class BufferingQueryDefinitionProviderWithControls extends AbstractQueryD
|
||||
private final SplitLayoutPanel filterSplitPanel;
|
||||
private final FilterSelectionProvider filterSelectionProvider;
|
||||
|
||||
public BufferingQueryDefinitionProviderWithControls(Component<?> parent, ComponentContext<?, ?> context,
|
||||
DataMiningSession session,
|
||||
StringMessages stringMessages,
|
||||
public QueryDefinitionProviderWithControls(Component<?> parent, ComponentContext<?, ?> context,
|
||||
DataMiningSession session, StringMessages stringMessages,
|
||||
DataMiningServiceAsync dataMiningService, ErrorReporter errorReporter, DataMiningSettingsControl settingsControl,
|
||||
ResultsPresenter<?> resultsPresenter) {
|
||||
super(parent, context, stringMessages, dataMiningService, errorReporter);
|
||||
providerListener = new ProviderListener();
|
||||
queryDefinitionReleaseTimer = new Timer() {
|
||||
@Override
|
||||
public void run() {
|
||||
notifyQueryDefinitionChanged();
|
||||
}
|
||||
};
|
||||
|
||||
// Creating the header panel, that contains the retriever chain provider and the controls
|
||||
controlsPanel = new FlowPanel();
|
||||
@@ -111,11 +93,10 @@ public class BufferingQueryDefinitionProviderWithControls extends AbstractQueryD
|
||||
filterSplitPanel.setWidgetHidden(queryDefinitionViewer.getEntryWidget(), !queryDefinitionViewerToggleButton.getValue());
|
||||
}
|
||||
});
|
||||
queryDefinitionViewer = new QueryDefinitionViewer(this, context, getStringMessages());
|
||||
queryDefinitionViewer = new QueryDefinitionViewer(parent, context, getStringMessages());
|
||||
addQueryDefinitionChangedListener(queryDefinitionViewer);
|
||||
predefinedQueryRunner = new PredefinedQueryRunner(this, context, session, getStringMessages(),
|
||||
dataMiningService,
|
||||
errorReporter, resultsPresenter);
|
||||
predefinedQueryRunner = new PredefinedQueryRunner(parent, context, session, getStringMessages(),
|
||||
dataMiningService, errorReporter, resultsPresenter);
|
||||
|
||||
Button clearSelectionButton = new Button(this.getStringMessages().clearSelection());
|
||||
clearSelectionButton.addClickHandler(new ClickHandler() {
|
||||
@@ -140,7 +121,7 @@ public class BufferingQueryDefinitionProviderWithControls extends AbstractQueryD
|
||||
addControl(predefinedQueryRunner.getEntryWidget());
|
||||
}
|
||||
|
||||
retrieverChainProvider = new SimpleDataRetrieverChainDefinitionProvider(this, context, getStringMessages(),
|
||||
retrieverChainProvider = new SimpleDataRetrieverChainDefinitionProvider(parent, context, getStringMessages(),
|
||||
getDataMiningService(), getErrorReporter(), settingsControl);
|
||||
retrieverChainProvider.addDataRetrieverChainDefinitionChangedListener(providerListener);
|
||||
|
||||
@@ -149,13 +130,12 @@ public class BufferingQueryDefinitionProviderWithControls extends AbstractQueryD
|
||||
headerPanel.add(controlsPanel);
|
||||
|
||||
// Creating the footer panel, that contains the statistic provider and the grouping provider
|
||||
statisticProvider = new SimpleStatisticProvider(this, context, getStringMessages(), getDataMiningService(),
|
||||
statisticProvider = new SimpleStatisticProvider(parent, context, getStringMessages(), getDataMiningService(),
|
||||
getErrorReporter(), retrieverChainProvider);
|
||||
statisticProvider.addStatisticChangedListener(providerListener);
|
||||
|
||||
groupingProvider = new MultiDimensionalGroupingProvider(this, context, getStringMessages(),
|
||||
getDataMiningService(),
|
||||
getErrorReporter(), statisticProvider);
|
||||
groupingProvider = new MultiDimensionalGroupingProvider(parent, context, getStringMessages(),
|
||||
getDataMiningService(), getErrorReporter(), retrieverChainProvider);
|
||||
groupingProvider.addGroupingChangedListener(providerListener);
|
||||
|
||||
SplitLayoutPanel footerPanel = new SplitLayoutPanel(15);
|
||||
@@ -167,8 +147,8 @@ public class BufferingQueryDefinitionProviderWithControls extends AbstractQueryD
|
||||
filterSplitPanel.addSouth(footerPanel, footerPanelHeight);
|
||||
filterSplitPanel.addEast(queryDefinitionViewer.getEntryWidget(), 600);
|
||||
filterSplitPanel.setWidgetHidden(queryDefinitionViewer.getEntryWidget(), true);
|
||||
filterSelectionProvider = new ListRetrieverChainFilterSelectionProvider(this, context, session, stringMessages,
|
||||
dataMiningService, errorReporter, retrieverChainProvider);
|
||||
filterSelectionProvider = new ListRetrieverChainFilterSelectionProvider(parent, context, session,
|
||||
stringMessages, dataMiningService, errorReporter, retrieverChainProvider);
|
||||
filterSelectionProvider.addSelectionChangedListener(providerListener);
|
||||
filterSplitPanel.add(filterSelectionProvider.getEntryWidget());
|
||||
|
||||
@@ -182,10 +162,9 @@ public class BufferingQueryDefinitionProviderWithControls extends AbstractQueryD
|
||||
providers.add(statisticProvider);
|
||||
providers.add(groupingProvider);
|
||||
providers.add(filterSelectionProvider);
|
||||
}
|
||||
|
||||
private void scheduleQueryDefinitionChanged() {
|
||||
queryDefinitionReleaseTimer.schedule(queryBufferTimeInMillis);
|
||||
|
||||
// Set await reload flag to initialize the components, when the retriever chains have been loaded
|
||||
providers.forEach(provider -> provider.awaitReloadComponents());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -241,7 +220,7 @@ public class BufferingQueryDefinitionProviderWithControls extends AbstractQueryD
|
||||
filterSelectionProvider.applySelection(queryDefinition);
|
||||
setBlockChangeNotification(false);
|
||||
|
||||
scheduleQueryDefinitionChanged();
|
||||
notifyQueryDefinitionChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -316,38 +295,40 @@ public class BufferingQueryDefinitionProviderWithControls extends AbstractQueryD
|
||||
|
||||
@Override
|
||||
public void statisticChanged(FunctionDTO newStatisticToCalculate, AggregationProcessorDefinitionDTO newAggregatorDefinition) {
|
||||
if (isAwatingReload()) {
|
||||
groupingProvider.statisticChanged(statisticProvider.getStatisticToCalculate(), statisticProvider.getAggregatorDefinition());
|
||||
groupingProvider.reloadComponents();
|
||||
} else {
|
||||
scheduleQueryDefinitionChanged();
|
||||
if (!isAwatingReload()) {
|
||||
notifyQueryDefinitionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void groupingChanged() {
|
||||
if (!isAwatingReload()) {
|
||||
scheduleQueryDefinitionChanged();
|
||||
notifyQueryDefinitionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataRetrieverChainDefinitionChanged(DataRetrieverChainDefinitionDTO newDataRetrieverChainDefinition) {
|
||||
if (isAwatingReload()) {
|
||||
statisticProvider.dataRetrieverChainDefinitionChanged(retrieverChainProvider.getDataRetrieverChainDefinition());
|
||||
statisticProvider.reloadComponents();
|
||||
DataRetrieverChainDefinitionDTO retrieverChainDefinition = retrieverChainProvider.getDataRetrieverChainDefinition();
|
||||
|
||||
filterSelectionProvider.dataRetrieverChainDefinitionChanged(retrieverChainProvider.getDataRetrieverChainDefinition());
|
||||
groupingProvider.dataRetrieverChainDefinitionChanged(retrieverChainDefinition);
|
||||
groupingProvider.reloadComponents();
|
||||
|
||||
filterSelectionProvider.dataRetrieverChainDefinitionChanged(retrieverChainDefinition);
|
||||
filterSelectionProvider.reloadComponents();
|
||||
|
||||
statisticProvider.dataRetrieverChainDefinitionChanged(retrieverChainDefinition);
|
||||
statisticProvider.reloadComponents();
|
||||
} else {
|
||||
scheduleQueryDefinitionChanged();
|
||||
notifyQueryDefinitionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectionChanged() {
|
||||
if (!isAwatingReload()) {
|
||||
scheduleQueryDefinitionChanged();
|
||||
notifyQueryDefinitionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,7 +336,7 @@ public class BufferingQueryDefinitionProviderWithControls extends AbstractQueryD
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "BufferingQueryDefinitionProviderWithControls";
|
||||
return "QueryDefinitionProviderWithControls";
|
||||
}
|
||||
|
||||
}
|
||||
-2
@@ -131,8 +131,6 @@ public class ListRetrieverChainFilterSelectionProvider extends AbstractComponent
|
||||
} else if (!isAwaitingReload) {
|
||||
clearContent();
|
||||
}
|
||||
} else if (retrieverChain != null && !isAwaitingReload) {
|
||||
updateRetrievalLevels();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-6
@@ -4,6 +4,8 @@ import java.util.Comparator;
|
||||
|
||||
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
|
||||
import com.sap.sailing.domain.common.dto.LeaderboardRowDTO;
|
||||
import com.sap.sailing.domain.common.impl.MeterDistance;
|
||||
import com.sap.sailing.domain.common.tracking.BravoFix;
|
||||
|
||||
public class RideHeightQualityMinMaxRender extends MinMaxRenderer {
|
||||
|
||||
@@ -12,19 +14,23 @@ public class RideHeightQualityMinMaxRender extends MinMaxRenderer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the value of a {@link LeaderboardRowDTO}. Values greater than 1.26 are considered good,
|
||||
* values lower than 0.74 are considered bad; anything in between is "OK".
|
||||
* Renders the value of a {@link LeaderboardRowDTO}. Values greater than
|
||||
* {@link BravoFix#MIN_FOILING_HEIGHT_THRESHOLD} are considered OK, values greater than that plus 0.2m are considered good,
|
||||
* values below {@link BravoFix#MIN_FOILING_HEIGHT_THRESHOLD} are considered bad.
|
||||
*/
|
||||
@Override
|
||||
protected void render(LeaderboardRowDTO row, String nullSafeValue, String nullSafeTitle, SafeHtmlBuilder sb) {
|
||||
Double doubleValue = getValueProvider().getDoubleValue(row);
|
||||
if (doubleValue != null) {
|
||||
final String barStyle;
|
||||
if (doubleValue > 1.26) barStyle = BACKGROUND_BAR_STYLE_GOOD;
|
||||
else if (doubleValue >= 0.74) barStyle = BACKGROUND_BAR_STYLE_OK;
|
||||
else barStyle = BACKGROUND_BAR_STYLE_BAD;
|
||||
if (doubleValue > BravoFix.MIN_FOILING_HEIGHT_THRESHOLD.add(new MeterDistance(0.2)).getMeters()) {
|
||||
barStyle = BACKGROUND_BAR_STYLE_GOOD;
|
||||
} else if (doubleValue >= BravoFix.MIN_FOILING_HEIGHT_THRESHOLD.getMeters()) {
|
||||
barStyle = BACKGROUND_BAR_STYLE_OK;
|
||||
} else {
|
||||
barStyle = BACKGROUND_BAR_STYLE_BAD;
|
||||
}
|
||||
sb.append(TEMPLATES.render(nullSafeValue, barStyle, nullSafeTitle, 100));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+45
-14
@@ -2,10 +2,13 @@ package com.sap.sailing.gwt.ui.server;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -26,13 +29,18 @@ import com.sap.sse.datamining.Query;
|
||||
import com.sap.sse.datamining.StatisticQueryDefinition;
|
||||
import com.sap.sse.datamining.components.AggregationProcessorDefinition;
|
||||
import com.sap.sse.datamining.components.DataRetrieverChainDefinition;
|
||||
import com.sap.sse.datamining.data.ExtensibleQueryResult;
|
||||
import com.sap.sse.datamining.data.QueryResult;
|
||||
import com.sap.sse.datamining.factories.DataMiningDTOFactory;
|
||||
import com.sap.sse.datamining.functions.Function;
|
||||
import com.sap.sse.datamining.impl.components.DataRetrieverLevel;
|
||||
import com.sap.sse.datamining.impl.data.QueryResultImpl;
|
||||
import com.sap.sse.datamining.shared.DataMiningSession;
|
||||
import com.sap.sse.datamining.shared.GroupKey;
|
||||
import com.sap.sse.datamining.shared.SerializationDummy;
|
||||
import com.sap.sse.datamining.shared.data.QueryResultState;
|
||||
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
|
||||
import com.sap.sse.datamining.shared.impl.GenericGroupKey;
|
||||
import com.sap.sse.datamining.shared.impl.PredefinedQueryIdentifier;
|
||||
import com.sap.sse.datamining.shared.impl.dto.AggregationProcessorDefinitionDTO;
|
||||
import com.sap.sse.datamining.shared.impl.dto.DataRetrieverChainDefinitionDTO;
|
||||
@@ -117,17 +125,12 @@ public class DataMiningServiceImpl extends RemoteServiceServlet implements DataM
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<FunctionDTO> getDimensionsFor(FunctionDTO statisticToCalculate, String localeInfoName) {
|
||||
SecurityUtils.getSubject().checkPermission(Permission.DATA_MINING.getStringPermissionForObjects(Mode.READ, statisticToCalculate.getFunctionName()));
|
||||
Class<?> baseDataType = getBaseDataType(statisticToCalculate);
|
||||
Iterable<Function<?>> dimensions = getDataMiningServer().getDimensionsFor(baseDataType);
|
||||
public HashSet<FunctionDTO> getDimensionsFor(DataRetrieverChainDefinitionDTO dataRetrieverChainDefinitionDTO, String localeInfoName) {
|
||||
SecurityUtils.getSubject().checkPermission(Permission.DATA_MINING.getStringPermissionForObjects(Mode.READ, dataRetrieverChainDefinitionDTO.getName()));
|
||||
Class<?> retrievedType = getDataMiningServer().getDataRetrieverChainDefinitionForDTO(dataRetrieverChainDefinitionDTO).getRetrievedDataType();
|
||||
Iterable<Function<?>> dimensions = getDataMiningServer().getDimensionsFor(retrievedType);
|
||||
return functionsAsDTOs(dimensions, localeInfoName);
|
||||
}
|
||||
|
||||
private Class<?> getBaseDataType(FunctionDTO statisticToCalculate) {
|
||||
Function<?> function = getDataMiningServer().getFunctionForDTO(statisticToCalculate);
|
||||
return function.getDeclaringType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<DataRetrieverLevelDTO, HashSet<FunctionDTO>> getDimensionsMappedByLevelFor(DataRetrieverChainDefinitionDTO dataRetrieverChainDefinitionDTO, String localeInfoName) {
|
||||
@@ -186,6 +189,11 @@ public class DataMiningServiceImpl extends RemoteServiceServlet implements DataM
|
||||
Iterable<DataRetrieverChainDefinition<?, ?>> dataRetrieverChainDefinitions = (Iterable<DataRetrieverChainDefinition<?, ?>>)(Iterable<?>) getDataMiningServer().getDataRetrieverChainDefinitionsByDataType(baseDataType);
|
||||
return dataRetrieverChainDefinitionsAsDTOs(dataRetrieverChainDefinitions, localeInfoName);
|
||||
}
|
||||
|
||||
private Class<?> getBaseDataType(FunctionDTO statisticToCalculate) {
|
||||
Function<?> function = getDataMiningServer().getFunctionForDTO(statisticToCalculate);
|
||||
return function.getDeclaringType();
|
||||
}
|
||||
|
||||
private ArrayList<DataRetrieverChainDefinitionDTO> dataRetrieverChainDefinitionsAsDTOs(
|
||||
Iterable<DataRetrieverChainDefinition<?, ?>> dataRetrieverChainDefinitions, String localeInfoName) {
|
||||
@@ -209,11 +217,34 @@ public class DataMiningServiceImpl extends RemoteServiceServlet implements DataM
|
||||
DataRetrieverChainDefinition<RacingEventService, ?> retrieverChainDefinition = dataMiningServer.getDataRetrieverChainDefinitionForDTO(dataRetrieverChainDefinitionDTO);
|
||||
DataRetrieverLevel<?, ?> retrieverLevel = retrieverChainDefinition.getDataRetrieverLevel(retrieverLevelDTO.getLevel());
|
||||
Iterable<Function<?>> dimensions = functionDTOsAsFunctions(dimensionDTOs);
|
||||
Map<DataRetrieverLevel<?, ?>, SerializableSettings> retrieverSettings = retrieverSettingsDTOAsRetrieverSettings(retrieverSettingsDTO, retrieverChainDefinition);
|
||||
Map<DataRetrieverLevel<?, ?>, Map<Function<?>, Collection<?>>> filterSelection = filterSelectionDTOAsFilterSelection(filterSelectionDTO, retrieverChainDefinition);
|
||||
Locale locale = ResourceBundleStringMessages.Util.getLocaleFor(localeInfoName);
|
||||
Query<HashSet<Object>> dimensionValuesQuery = dataMiningServer.createDimensionValuesQuery(retrieverChainDefinition, retrieverLevel, dimensions, retrieverSettings, filterSelection, locale);
|
||||
QueryResult<HashSet<Object>> result = dataMiningServer.runNewQueryAndAbortPreviousQueries(session, dimensionValuesQuery);
|
||||
// split up between boolean/enum dimensions and others; for the bool/enums we'll
|
||||
// simply enumerate all values instead of retrieving all objects
|
||||
List<Function<?>> nonBoolNonEnumResultDimensions = new ArrayList<>();
|
||||
LinkedHashMap<Function<?>, List<?>> boolOrEnumResultDimensionsWithValues = new LinkedHashMap<>();
|
||||
for (final Function<?> dimensionFunction : dimensions) {
|
||||
if (dimensionFunction.getReturnType() == boolean.class || dimensionFunction.getReturnType() == Boolean.class) {
|
||||
boolOrEnumResultDimensionsWithValues.put(dimensionFunction, Arrays.asList(true, false));
|
||||
} else if (dimensionFunction.getReturnType().isEnum()) {
|
||||
boolOrEnumResultDimensionsWithValues.put(dimensionFunction, Arrays.asList(dimensionFunction.getReturnType().getEnumConstants()));
|
||||
} else {
|
||||
nonBoolNonEnumResultDimensions.add(dimensionFunction);
|
||||
}
|
||||
}
|
||||
final ExtensibleQueryResult<HashSet<Object>> result;
|
||||
final Locale locale = ResourceBundleStringMessages.Util.getLocaleFor(localeInfoName);
|
||||
if (!nonBoolNonEnumResultDimensions.isEmpty()) {
|
||||
Map<DataRetrieverLevel<?, ?>, SerializableSettings> retrieverSettings = retrieverSettingsDTOAsRetrieverSettings(retrieverSettingsDTO, retrieverChainDefinition);
|
||||
Map<DataRetrieverLevel<?, ?>, Map<Function<?>, Collection<?>>> filterSelection = filterSelectionDTOAsFilterSelection(filterSelectionDTO, retrieverChainDefinition);
|
||||
Query<HashSet<Object>> dimensionValuesQuery = dataMiningServer.createDimensionValuesQuery(retrieverChainDefinition, retrieverLevel, nonBoolNonEnumResultDimensions, retrieverSettings, filterSelection, locale);
|
||||
result = (ExtensibleQueryResult<HashSet<Object>>) dataMiningServer.runNewQueryAndAbortPreviousQueries(session, dimensionValuesQuery);
|
||||
} else {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Class<HashSet<Object>> clazz = (Class<HashSet<Object>>) new HashSet<Object>().getClass();
|
||||
result = new QueryResultImpl<HashSet<Object>>(QueryResultState.NORMAL, clazz, new HashMap<GroupKey, HashSet<Object>>());
|
||||
}
|
||||
for (final Entry<Function<?>, List<?>> e : boolOrEnumResultDimensionsWithValues.entrySet()) {
|
||||
result.addResult(new GenericGroupKey<>(dtoFactory.createFunctionDTO(e.getKey(), getDataMiningServer().getStringMessages(), locale)), new LinkedHashSet<>(e.getValue()));
|
||||
}
|
||||
return dtoFactory.createResultDTO(result);
|
||||
}
|
||||
|
||||
|
||||
+9
@@ -4,6 +4,15 @@
|
||||
<div id="mainContent">
|
||||
<h4 class="articleHeadline">What's New - SAP Sailing Analytics</h4>
|
||||
<div class="innerContent">
|
||||
<h5 class="articleSubheadline">February 2017</h5>
|
||||
<ul class="bulletList">
|
||||
<li>The definition of "ride height" for foiling sensors has been changed. Instead of showing
|
||||
the ride height calculated by the sensor we are now showing the minimum of the port and
|
||||
starboard ride heights. Therefore, this new definition of ride height can be seen as the
|
||||
distance of lowest hull part from the water.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h5 class="articleSubheadline">January 2017</h5>
|
||||
<ul class="bulletList">
|
||||
<li>An issue with wind-up map rotation which sometimes left the map centered over the African continent has been fixed.
|
||||
|
||||
+5
-3
@@ -60,7 +60,9 @@ public class BravoDataImportTest {
|
||||
}
|
||||
|
||||
private enum ImportData {
|
||||
FILE_UNDEFINED_RACE_BRAVO(870, 0.77176) {
|
||||
// find out the number of fixes using the following bash line:
|
||||
// tail -n +5 Undefined\ Race\ -\ BRAVO.txt | awk '{if ($5<$6) print v=$5; else v=$6; sum+=v; count++; } END {print "Sum: ", sum, "Count: ", count, "Average:", sum/count;}'
|
||||
FILE_UNDEFINED_RACE_BRAVO(870, 0.661037) {
|
||||
@Override
|
||||
protected InputStream getInputStream() {
|
||||
return getClass().getResourceAsStream("/Undefined Race - BRAVO.txt");
|
||||
@@ -72,13 +74,13 @@ public class BravoDataImportTest {
|
||||
return new ByteArrayInputStream(HEADER_ORDER_DEFAULT.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
},
|
||||
DUMMY_DEAFULT_HEADER_ONE_LINE(1, 0.77151) {
|
||||
DUMMY_DEAFULT_HEADER_ONE_LINE(1, 0.661044) {
|
||||
@Override
|
||||
protected InputStream getInputStream() {
|
||||
return new ByteArrayInputStream((HEADER_ORDER_DEFAULT + DUMMY_CONTENT).getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
},
|
||||
DUMMY_RANDOM_HAEDER_ONE_LINE(1, 0.01346) {
|
||||
DUMMY_RANDOM_HAEDER_ONE_LINE(1, 0.092727) {
|
||||
@Override
|
||||
protected InputStream getInputStream() {
|
||||
return new ByteArrayInputStream((HEADER_ORDER_RANDOM + DUMMY_CONTENT).getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
+1
-5
@@ -104,10 +104,6 @@ public class BravoDataImporterImpl implements DoubleVectorFixImporter {
|
||||
|
||||
/**
|
||||
* Parses the CSV line and reads the double data values in the order defined by the col enums.
|
||||
*
|
||||
* @param line
|
||||
* @param colIndices
|
||||
* @return
|
||||
*/
|
||||
private DoubleVectorFixImpl parseLine(long lineNr, String filename, String line, Map<String, Integer> colIndices) {
|
||||
try {
|
||||
@@ -119,7 +115,7 @@ public class BravoDataImporterImpl implements DoubleVectorFixImporter {
|
||||
long epoch = Long.parseLong(epochColValue);
|
||||
fixTp = new MillisecondsTimePoint(epoch);
|
||||
} else {
|
||||
String jjLDATE = contentTokens[0].substring(0, 9);
|
||||
String jjLDATE = contentTokens[0].substring(0, contentTokens[0].indexOf("."));
|
||||
StringBuilder dtb = new StringBuilder(jjLDATE);
|
||||
String jjlTIME = contentTokens[1];
|
||||
int offset = 6 - jjlTIME.indexOf(".");
|
||||
|
||||
@@ -27,5 +27,5 @@
|
||||
<booleanAttribute key="tracing" value="false"/>
|
||||
<booleanAttribute key="useCustomFeatures" value="false"/>
|
||||
<booleanAttribute key="useDefaultConfigArea" value="true"/>
|
||||
<stringAttribute key="workspace_bundles" value="com.google.gwt.servlet@default:default,com.googlecode.java-diff-utils@default:default,com.googlecode.mgwt@default:default,com.sap.sailing.barbados.resultimport@default:default,com.sap.sailing.competitorimport@default:default,com.sap.sailing.dashboards.gwt@5:true,com.sap.sailing.datamining.shared@default:default,com.sap.sailing.datamining@default:default,com.sap.sailing.declination@default:default,com.sap.sailing.domain.common@default:default,com.sap.sailing.domain.deckmanadapter@4:true,com.sap.sailing.domain.igtimiadapter.persistence@default:default,com.sap.sailing.domain.igtimiadapter@default:default,com.sap.sailing.domain.persistence@default:default,com.sap.sailing.domain.racelogtrackingadapter@3:default,com.sap.sailing.domain.shared.android@default:default,com.sap.sailing.domain.swisstimingadapter.persistence@default:default,com.sap.sailing.domain.swisstimingadapter@4:true,com.sap.sailing.domain.swisstimingreplayadapter@4:true,com.sap.sailing.domain.tractracadapter.persistence@default:default,com.sap.sailing.domain.tractracadapter@4:true,com.sap.sailing.domain@default:default,com.sap.sailing.ess40.resultimport@default:default,com.sap.sailing.expeditionconnector@default:default,com.sap.sailing.freg.resultimport@default:default,com.sap.sailing.geocoding@default:default,com.sap.sailing.gwt.ui@5:true,com.sap.sailing.kiworesultimport@default:default,com.sap.sailing.manage2sail.resultimport@default:default,com.sap.sailing.manage2sail@default:default,com.sap.sailing.news@default:default,com.sap.sailing.polars.datamining.shared@default:default,com.sap.sailing.polars.datamining@default:default,com.sap.sailing.polars@4:true,com.sap.sailing.resultimport@default:default,com.sap.sailing.sailwave.resultimport@default:default,com.sap.sailing.server.gateway.serialization.shared.android@default:default,com.sap.sailing.server.gateway.serialization@default:default,com.sap.sailing.server.gateway@5:true,com.sap.sailing.server.trackfiles@default:default,com.sap.sailing.server@default:default,com.sap.sailing.simulator@default:default,com.sap.sailing.udpconnector@default:default,com.sap.sailing.velum.resultimport@default:default,com.sap.sailing.www@4:true,com.sap.sailing.xrr.resultimport@default:default,com.sap.sailing.xrr.schema@default:default,com.sap.sailing.xrr.structureimport@default:default,com.sap.sailing.yachtscoring.resultimport@default:default,com.sap.sse.common@default:default,com.sap.sse.datamining.annotations@default:default,com.sap.sse.datamining.shared@default:default,com.sap.sse.datamining@default:default,com.sap.sse.filestorage@default:default,com.sap.sse.gwt.adminconsole@default:default,com.sap.sse.gwt@default:default,com.sap.sse.mail@4:true,com.sap.sse.mongodb@default:default,com.sap.sse.operationaltransformation@default:default,com.sap.sse.replication@4:true,com.sap.sse.security.common@default:default,com.sap.sse.security.ui@6:true,com.sap.sse.security.userstore.mongodb@4:true,com.sap.sse.security@5:true,com.sap.sse.shared.android@default:default,com.sap.sse@default:default,com.tractrac.clientmodule@default:default,org.json.simple@default:default,org.moxieapps.gwt.highcharts@default:default"/>
|
||||
<stringAttribute key="workspace_bundles" value="com.google.gwt.servlet@default:default,com.googlecode.java-diff-utils@default:default,com.googlecode.mgwt@default:default,com.sap.sailing.barbados.resultimport@default:default,com.sap.sailing.competitorimport@default:default,com.sap.sailing.dashboards.gwt@5:true,com.sap.sailing.datamining.provider@default:default,com.sap.sailing.datamining.shared@default:default,com.sap.sailing.datamining@default:default,com.sap.sailing.declination@default:default,com.sap.sailing.domain.common@default:default,com.sap.sailing.domain.deckmanadapter@4:true,com.sap.sailing.domain.igtimiadapter.persistence@default:default,com.sap.sailing.domain.igtimiadapter@default:default,com.sap.sailing.domain.persistence@default:default,com.sap.sailing.domain.racelogtrackingadapter@3:default,com.sap.sailing.domain.shared.android@default:default,com.sap.sailing.domain.swisstimingadapter.persistence@default:default,com.sap.sailing.domain.swisstimingadapter@4:true,com.sap.sailing.domain.swisstimingreplayadapter@4:true,com.sap.sailing.domain.tractracadapter.persistence@default:default,com.sap.sailing.domain.tractracadapter@4:true,com.sap.sailing.domain@default:default,com.sap.sailing.ess40.resultimport@default:default,com.sap.sailing.expeditionconnector@default:default,com.sap.sailing.freg.resultimport@default:default,com.sap.sailing.geocoding@default:default,com.sap.sailing.gwt.ui@5:true,com.sap.sailing.kiworesultimport@default:default,com.sap.sailing.manage2sail.resultimport@default:default,com.sap.sailing.manage2sail@default:default,com.sap.sailing.news@default:default,com.sap.sailing.polars.datamining.shared@default:default,com.sap.sailing.polars.datamining@default:default,com.sap.sailing.polars@4:true,com.sap.sailing.resultimport@default:default,com.sap.sailing.sailwave.resultimport@default:default,com.sap.sailing.server.gateway.serialization.shared.android@default:default,com.sap.sailing.server.gateway.serialization@default:default,com.sap.sailing.server.gateway@5:true,com.sap.sailing.server.trackfiles@default:default,com.sap.sailing.server@default:default,com.sap.sailing.simulator@default:default,com.sap.sailing.udpconnector@default:default,com.sap.sailing.velum.resultimport@default:default,com.sap.sailing.www@4:true,com.sap.sailing.xrr.resultimport@default:default,com.sap.sailing.xrr.schema@default:default,com.sap.sailing.xrr.structureimport@default:default,com.sap.sailing.yachtscoring.resultimport@default:default,com.sap.sse.common@default:default,com.sap.sse.datamining.annotations@default:default,com.sap.sse.datamining.shared@default:default,com.sap.sse.datamining@default:default,com.sap.sse.filestorage@default:default,com.sap.sse.gwt.adminconsole@default:default,com.sap.sse.gwt@default:default,com.sap.sse.mail@4:true,com.sap.sse.mongodb@default:default,com.sap.sse.operationaltransformation@default:default,com.sap.sse.replication@4:true,com.sap.sse.security.common@default:default,com.sap.sse.security.ui@6:true,com.sap.sse.security.userstore.mongodb@4:true,com.sap.sse.security@5:true,com.sap.sse.shared.android@default:default,com.sap.sse@default:default,com.tractrac.clientmodule@default:default,org.json.simple@default:default,org.moxieapps.gwt.highcharts@default:default"/>
|
||||
</launchConfiguration>
|
||||
+9
-7
@@ -666,9 +666,11 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
|
||||
private void restoreTrackedRaces() {
|
||||
final ScheduledExecutorService backgroundExecutor = ThreadPoolUtil.INSTANCE.getDefaultBackgroundTaskThreadPoolExecutor();
|
||||
try {
|
||||
numberOfTrackedRacesToRestore = getDomainObjectFactory().loadConnectivityParametersForRacesToRestore(params -> {
|
||||
backgroundExecutor.execute(()->{
|
||||
// restore the races by calling addRace one by one, but in a background thread, therefore concurrent to any remaining
|
||||
// server startup activities happening
|
||||
backgroundExecutor.execute(()->{
|
||||
try {
|
||||
numberOfTrackedRacesToRestore = getDomainObjectFactory().loadConnectivityParametersForRacesToRestore(params -> {
|
||||
try {
|
||||
addRace(/* addToRegatta==null means "default regatta" */ null, params, /* no timeout during mass loading */ -1);
|
||||
numberOfTrackedRacesRestored.incrementAndGet();
|
||||
@@ -676,10 +678,10 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
logger.log(Level.SEVERE, "Exception trying to restore race"+params, e);
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (MalformedURLException | URISyntaxException e) {
|
||||
logger.log(Level.SEVERE, "Exception trying to obtain connectivity parameters for restoring tracked races", e);
|
||||
}
|
||||
} catch (MalformedURLException | URISyntaxException e) {
|
||||
logger.log(Level.SEVERE, "Exception trying to obtain connectivity parameters for restoring tracked races", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+62
-10
@@ -2,19 +2,64 @@ package com.sap.sse.datamining.shared.impl.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* The {@link #signifier} is relevant for the {@link #equals(Object)} and {@link #hashCode()} implementations.
|
||||
* Optionally, a {@link #localizedName} can be provided at construction time, e.g., as a localized, human-readable
|
||||
* version of the {@link #signifier}. If not, the {@link #localizedName} will be assigned from the {@link #signifier}.
|
||||
* <p>
|
||||
*
|
||||
* The {@link #signifier} must be set explicitly at construction time. The {@link #localizedName} can optionally
|
||||
* be provided as a {@link LocalizedNameProvider} through which it will be evaluated lazily, particularly during
|
||||
* serialization with the custom field serializer.
|
||||
*
|
||||
* @author Lennart Hensler
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class ClusterDTO implements Serializable {
|
||||
private static final long serialVersionUID = -2962035066215989018L;
|
||||
|
||||
private String signifier;
|
||||
|
||||
private final String signifier;
|
||||
|
||||
/**
|
||||
* <b>Constructor for the GWT-Serialization. Don't use this!</b>
|
||||
* If {@code null}, the {@link #signifier} will be returned by {@link #toString} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
ClusterDTO() { }
|
||||
private String localizedName;
|
||||
|
||||
/**
|
||||
* Upon serialization the {@link #signifier} must be obtained from a {@link #localizedNameProvider} and
|
||||
* cached in the object serialized.
|
||||
*/
|
||||
private transient LocalizedNameProvider localizedNameProvider;
|
||||
|
||||
public ClusterDTO(String signifier) {
|
||||
this(signifier, signifier);
|
||||
}
|
||||
|
||||
public ClusterDTO(String signifier, String localizedName) {
|
||||
this.signifier = signifier;
|
||||
this.localizedName = localizedName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used for lazy initialization of objects of this type. As long as the {@link ClusterDTO}
|
||||
* object is only passed around and not treated with {@link #hashCode} or {@link #equals} or the
|
||||
* {@link #getLocalizedName()} method is called explicitly then the signifier string is not calculated.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public static interface LocalizedNameProvider {
|
||||
String getLocalizedName();
|
||||
}
|
||||
|
||||
/**
|
||||
* A possibility to initialize the {@link #getSignifier() signifier} lazily so that the providing function is
|
||||
* called only when the signifier is really asked for.
|
||||
*/
|
||||
public ClusterDTO(String signifier, LocalizedNameProvider localizedNameProvider) {
|
||||
this(signifier, /* toStringResult */ (String) null);
|
||||
this.localizedNameProvider = localizedNameProvider;
|
||||
}
|
||||
|
||||
public String getSignifier() {
|
||||
@@ -23,14 +68,21 @@ public class ClusterDTO implements Serializable {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getSignifier();
|
||||
return getLocalizedName();
|
||||
}
|
||||
|
||||
public String getLocalizedName() {
|
||||
if (localizedName == null && localizedNameProvider != null) {
|
||||
localizedName = localizedNameProvider.getLocalizedName();
|
||||
}
|
||||
return localizedName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((signifier == null) ? 0 : signifier.hashCode());
|
||||
result = prime * result + ((getSignifier() == null) ? 0 : getSignifier().hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -43,10 +95,10 @@ public class ClusterDTO implements Serializable {
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ClusterDTO other = (ClusterDTO) obj;
|
||||
if (signifier == null) {
|
||||
if (other.signifier != null)
|
||||
if (getSignifier() == null) {
|
||||
if (other.getSignifier() != null)
|
||||
return false;
|
||||
} else if (!signifier.equals(other.signifier))
|
||||
} else if (!getSignifier().equals(other.getSignifier()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
+24
-11
@@ -7,20 +7,30 @@ import java.util.List;
|
||||
public class FunctionDTO implements Serializable, Comparable<FunctionDTO> {
|
||||
private static final long serialVersionUID = 4587389541910498505L;
|
||||
|
||||
private boolean isDimension;
|
||||
private String functionName;
|
||||
private String sourceTypeName;
|
||||
private String returnTypeName;
|
||||
private List<String> parameterTypeNames;
|
||||
|
||||
private final boolean isDimension;
|
||||
private final String functionName;
|
||||
private final String sourceTypeName;
|
||||
private final String returnTypeName;
|
||||
private final List<String> parameterTypeNames;
|
||||
private final int ordinal;
|
||||
private String displayName;
|
||||
private int ordinal;
|
||||
|
||||
/**
|
||||
* Constructor for the GWT-Serialization. Don't use this!
|
||||
* If the {@link #displayName} is not set and this provider is valid, the {@F
|
||||
*/
|
||||
@Deprecated
|
||||
FunctionDTO() {
|
||||
private transient DisplayNameProvider displayNameProvider;
|
||||
|
||||
public static interface DisplayNameProvider {
|
||||
String getDisplayName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the construction of the {@link #displayName} lazy, using the {@code displayNameProvider}.
|
||||
*/
|
||||
public FunctionDTO(boolean isDimension, String functionName, String sourceTypeName, String returnTypeName,
|
||||
List<String> parameterTypeNames, DisplayNameProvider displayNameProvider, int ordinal) {
|
||||
this(isDimension, functionName, sourceTypeName, returnTypeName, parameterTypeNames,
|
||||
/* displayName is constructed lazily using the displayNameProvider */ (String) null, ordinal);
|
||||
this.displayNameProvider = displayNameProvider;
|
||||
}
|
||||
|
||||
public FunctionDTO(boolean isDimension, String functionName, String sourceTypeName, String returnTypeName,
|
||||
@@ -52,6 +62,9 @@ public class FunctionDTO implements Serializable, Comparable<FunctionDTO> {
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
if (displayName == null && displayNameProvider != null) {
|
||||
displayName = displayNameProvider.getDisplayName();
|
||||
}
|
||||
return displayName;
|
||||
}
|
||||
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.sap.sse.datamining.data;
|
||||
|
||||
import com.sap.sse.datamining.shared.GroupKey;
|
||||
|
||||
public interface ExtensibleQueryResult<ResultType> extends QueryResult<ResultType> {
|
||||
void addResult(GroupKey key, ResultType result);
|
||||
}
|
||||
+5
-4
@@ -26,7 +26,7 @@ public class DataMiningDTOFactory {
|
||||
* The display name of the resulting DTO is the {@link Function#getSimpleName() simple name} of the given function.
|
||||
*/
|
||||
public FunctionDTO createFunctionDTO(Function<?> function) {
|
||||
return createFunctionDTO(function, function.getSimpleName());
|
||||
return createFunctionDTO(function, ()->function.getSimpleName());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,15 +36,16 @@ public class DataMiningDTOFactory {
|
||||
* If the function has no message key, the function name is used as display name.
|
||||
*/
|
||||
public FunctionDTO createFunctionDTO(Function<?> function, ResourceBundleStringMessages stringMessages, Locale locale) {
|
||||
return createFunctionDTO(function, function.getLocalizedName(locale, stringMessages));
|
||||
return createFunctionDTO(function, ()->function.getLocalizedName(locale, stringMessages));
|
||||
}
|
||||
|
||||
private FunctionDTO createFunctionDTO(Function<?> function, String displayName) {
|
||||
private FunctionDTO createFunctionDTO(Function<?> function, FunctionDTO.DisplayNameProvider displayNameProvider) {
|
||||
String functionName = function.getSimpleName();
|
||||
String sourceTypeName = function.getDeclaringType().getName();
|
||||
String returnTypeName = function.getReturnType().getName();
|
||||
List<String> parameterTypeNames = getParameterTypeNames(function);
|
||||
return new FunctionDTO(function.isDimension(), functionName, sourceTypeName, returnTypeName, parameterTypeNames, displayName, function.getOrdinal());
|
||||
return new FunctionDTO(function.isDimension(), functionName, sourceTypeName, returnTypeName, parameterTypeNames,
|
||||
displayNameProvider, function.getOrdinal());
|
||||
}
|
||||
|
||||
private List<String> getParameterTypeNames(Function<?> function) {
|
||||
|
||||
@@ -121,14 +121,11 @@ public class QueryFactory {
|
||||
@Override
|
||||
protected Processor<DataSourceType, ?> createChainAndReturnFirstProcessor(Processor<Map<GroupKey, HashSet<Object>>, Void> resultReceiver) {
|
||||
ProcessorFactory processorFactory = new ProcessorFactory(executor);
|
||||
|
||||
Processor<GroupedDataEntry<Object>, Map<GroupKey, HashSet<Object>>> valueCollector = processorFactory.createGroupedDataCollectingAsSetProcessor(/*query*/ this);
|
||||
|
||||
Map<DataRetrieverLevel<?, ?>, FilterCriterion<?>> criteriaMappedByRetrieverLevel = createFilterCriteria(filterSelection);
|
||||
DataRetrieverChainBuilder<DataSourceType> chainBuilder = dataRetrieverChainDefinition.startBuilding(executor);
|
||||
while (!chainBuilder.hasBeenInitialized() || chainBuilder.getCurrentRetrieverLevel().getLevel() < retrieverLevel.getLevel()) {
|
||||
chainBuilder.stepFurther();
|
||||
|
||||
DataRetrieverLevel<?, ?> currentLevel = chainBuilder.getCurrentRetrieverLevel();
|
||||
if (settings.containsKey(currentLevel)) {
|
||||
chainBuilder.setSettings(settings.get(currentLevel));
|
||||
@@ -141,7 +138,6 @@ public class QueryFactory {
|
||||
chainBuilder.getCurrentRetrievedDataType(), valueCollector, getParameterProvidersFor(dimensions, stringMessages, locale), stringMessages, locale)) {
|
||||
chainBuilder.addResultReceiver(groupingExtractor);
|
||||
}
|
||||
|
||||
return chainBuilder.build();
|
||||
}
|
||||
};
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ public abstract class AbstractParallelAggregationProcessor<InputType, Aggregated
|
||||
|
||||
|
||||
/**
|
||||
* Method to handle the element. This method is only called in a way, that is thread safe, so
|
||||
* Method to handle the element. This method is only called in a way that is thread safe so
|
||||
* that multiple threads can't corrupt the data.
|
||||
*/
|
||||
protected abstract void handleElement(InputType element);
|
||||
|
||||
+11
-4
@@ -30,13 +30,20 @@ public abstract class AbstractParallelSingleGroupedValueAggregationProcessor<Val
|
||||
protected void handleElement(GroupedDataEntry<ValueType> element) {
|
||||
GroupKey key = element.getKey();
|
||||
ValueType value = element.getDataEntry();
|
||||
if (!valueMap.containsKey(key)) {
|
||||
valueMap.put(key, value);
|
||||
} else {
|
||||
valueMap.put(key, compareValuesAndReturnNewResult(valueMap.get(key), value));
|
||||
if (value != null) {
|
||||
if (!valueMap.containsKey(key)) {
|
||||
valueMap.put(key, value);
|
||||
} else {
|
||||
valueMap.put(key, compareValuesAndReturnNewResult(valueMap.get(key), value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param currentResult not {@code null}
|
||||
* @param newValue not {@code null}
|
||||
* @return not {@code null}
|
||||
*/
|
||||
protected abstract ValueType compareValuesAndReturnNewResult(ValueType currentResult, ValueType newValue);
|
||||
|
||||
@Override
|
||||
|
||||
+9
-7
@@ -36,13 +36,15 @@ public class ParallelGroupedNumberDataAverageAggregationProcessor
|
||||
|
||||
@Override
|
||||
protected void storeElement(GroupedDataEntry<Number> element) {
|
||||
incrementElementAmount(element);
|
||||
DoubleHolder aggregate = sumPerKey.get(element.getKey());
|
||||
if (aggregate == null) {
|
||||
aggregate = new DoubleHolder(element.getDataEntry().doubleValue());
|
||||
sumPerKey.put(element.getKey(), aggregate);
|
||||
} else {
|
||||
aggregate.value += element.getDataEntry().doubleValue();
|
||||
if (element.getDataEntry() != null) {
|
||||
incrementElementAmount(element);
|
||||
DoubleHolder aggregate = sumPerKey.get(element.getKey());
|
||||
if (aggregate == null) {
|
||||
aggregate = new DoubleHolder(element.getDataEntry().doubleValue());
|
||||
sumPerKey.put(element.getKey(), aggregate);
|
||||
} else {
|
||||
aggregate.value += element.getDataEntry().doubleValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-2
@@ -19,13 +19,11 @@ public class ParallelGroupedNumberDataMinAggregationProcessor
|
||||
return DEFINITION;
|
||||
}
|
||||
|
||||
|
||||
public ParallelGroupedNumberDataMinAggregationProcessor(ExecutorService executor,
|
||||
Collection<Processor<Map<GroupKey, Number>, ?>> resultReceivers) {
|
||||
super(executor, resultReceivers, "Minimum");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Number compareValuesAndReturnNewResult(Number currentResult, Number newValue) {
|
||||
return currentResult.doubleValue() <= newValue.doubleValue() ? currentResult : newValue;
|
||||
|
||||
+2
-3
@@ -2,14 +2,14 @@ package com.sap.sse.datamining.impl.data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.sap.sse.datamining.data.QueryResult;
|
||||
import com.sap.sse.datamining.data.ExtensibleQueryResult;
|
||||
import com.sap.sse.datamining.shared.AdditionalResultData;
|
||||
import com.sap.sse.datamining.shared.GroupKey;
|
||||
import com.sap.sse.datamining.shared.data.QueryResultState;
|
||||
import com.sap.sse.datamining.shared.impl.NullAdditionalResultData;
|
||||
import com.sap.sse.datamining.shared.impl.QueryResultBaseImpl;
|
||||
|
||||
public class QueryResultImpl<ResultType> extends QueryResultBaseImpl<ResultType> implements QueryResult<ResultType> {
|
||||
public class QueryResultImpl<ResultType> extends QueryResultBaseImpl<ResultType> implements ExtensibleQueryResult<ResultType> {
|
||||
private static final long serialVersionUID = 5173796619174827696L;
|
||||
|
||||
private Class<ResultType> resultType;
|
||||
@@ -40,5 +40,4 @@ public class QueryResultImpl<ResultType> extends QueryResultBaseImpl<ResultType>
|
||||
public AdditionalResultData getAdditionalData() {
|
||||
return super.getAdditionalData();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user