mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-15 14:56:41 +00:00
Implemented range dimensions for the distance to starboard side at start and relative score for races of competitors
This commit is contained in:
1 parent
9ada894373
commit
2072e3f624
5 files changed
+201
-4
No files matched your search
+82
@@ -0,0 +1,82 @@
|
||||
package com.sap.sailing.datamining.impl.data;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sse.datamining.data.Cluster;
|
||||
import com.sap.sse.datamining.data.ClusterGroup;
|
||||
import com.sap.sse.datamining.impl.data.ClusterWithLowerAndUpperBoundaries;
|
||||
import com.sap.sse.datamining.impl.data.ComparableClusterBoundary;
|
||||
import com.sap.sse.datamining.impl.data.ComparisonStrategy;
|
||||
|
||||
// TODO Move to sse bundle, after 49er analysis
|
||||
public class TestLinearDoubleClusterGroup {
|
||||
|
||||
private ClusterGroup<Double> hardPercentageClusterGroup;
|
||||
private ClusterGroup<Double> softLinearClusterGroup;
|
||||
|
||||
@Before
|
||||
public void initialize() {
|
||||
hardPercentageClusterGroup = new LinearDoubleClusterGroup(0.0, 1.0, 0.1, true);
|
||||
softLinearClusterGroup = new LinearDoubleClusterGroup(0, 100, 10, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetClusterForValueOutOfBounds() {
|
||||
Cluster<Double> cluster = hardPercentageClusterGroup.getClusterFor(-0.01);
|
||||
assertThat(cluster, nullValue());
|
||||
|
||||
cluster = hardPercentageClusterGroup.getClusterFor(1.01);
|
||||
assertThat(cluster, nullValue());
|
||||
|
||||
cluster = softLinearClusterGroup.getClusterFor(-0.1);
|
||||
Cluster<Double> expectedCluster = createCluster(0, 0, 10);
|
||||
assertThat(cluster, is(expectedCluster));
|
||||
|
||||
cluster = softLinearClusterGroup.getClusterFor(100.1);
|
||||
expectedCluster = createCluster(9, 0, 10);
|
||||
assertThat(cluster, is(expectedCluster));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetClusterForBoundaryValues() {
|
||||
Cluster<Double> cluster = hardPercentageClusterGroup.getClusterFor(0.0);
|
||||
Cluster<Double> expectedCluster = createCluster(0, 0, 0.1);
|
||||
assertThat(cluster, is(expectedCluster));
|
||||
|
||||
cluster = hardPercentageClusterGroup.getClusterFor(1.0);
|
||||
expectedCluster = createCluster(9, 0, 0.1);
|
||||
assertThat(cluster, is(expectedCluster));
|
||||
|
||||
cluster = softLinearClusterGroup.getClusterFor(0.0);
|
||||
expectedCluster = createCluster(0, 0, 10);
|
||||
assertThat(cluster, is(expectedCluster));
|
||||
|
||||
cluster = softLinearClusterGroup.getClusterFor(100.0);
|
||||
expectedCluster = createCluster(9, 0, 10);
|
||||
assertThat(cluster, is(expectedCluster));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetClusterFor() {
|
||||
double value = -0.05;
|
||||
double stepSize = 0.1;
|
||||
for (int index = 0; index < 10; index++) {
|
||||
value += stepSize;
|
||||
Cluster<Double> cluster = hardPercentageClusterGroup.getClusterFor(value);
|
||||
Cluster<Double> expectedCluster = createCluster(index, 0, stepSize);
|
||||
assertThat(cluster, is(expectedCluster));
|
||||
}
|
||||
}
|
||||
|
||||
private Cluster<Double> createCluster(int index, double lowerBoundValue, double stepSize) {
|
||||
ComparableClusterBoundary<Double> lowerBound = new ComparableClusterBoundary<Double>(lowerBoundValue + stepSize * index, ComparisonStrategy.GREATER_EQUALS_THAN);
|
||||
ComparableClusterBoundary<Double> upperBound = new ComparableClusterBoundary<Double>(lowerBoundValue + stepSize * (index + 1), ComparisonStrategy.LOWER_THAN);
|
||||
return new ClusterWithLowerAndUpperBoundaries<>(lowerBound, upperBound);
|
||||
}
|
||||
|
||||
}
|
||||
+12
-4
@@ -3,6 +3,7 @@ package com.sap.sailing.datamining;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.sap.sailing.datamining.impl.data.LinearDoubleClusterGroup;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.impl.KnotSpeedImpl;
|
||||
import com.sap.sse.datamining.data.Cluster;
|
||||
@@ -17,7 +18,8 @@ import com.sap.sse.datamining.impl.data.LocalizedCluster;
|
||||
|
||||
public class SailingClusterGroups {
|
||||
|
||||
private final ClusterGroup<Speed> windStrengthInBeaufortCluster;
|
||||
private final ClusterGroup<Speed> windStrengthInBeaufortClusterGroup;
|
||||
private final ClusterGroup<Double> percentageClusterGroup;
|
||||
|
||||
public SailingClusterGroups() {
|
||||
Collection<Cluster<Speed>> clusters = new ArrayList<>();
|
||||
@@ -98,11 +100,17 @@ public class SailingClusterGroups {
|
||||
lowerBound = new ComparableClusterBoundary<Speed>(lowerBoundWindSpeed, ComparisonStrategy.GREATER_EQUALS_THAN);
|
||||
clusters.add(new LocalizedCluster<Speed>("Bft12", new ClusterWithSingleBoundary<Speed>(lowerBound)));
|
||||
|
||||
windStrengthInBeaufortCluster = new FixClusterGroup<Speed>(clusters);
|
||||
windStrengthInBeaufortClusterGroup = new FixClusterGroup<Speed>(clusters);
|
||||
|
||||
percentageClusterGroup = new LinearDoubleClusterGroup(0.0, 1.0, 0.1, true);
|
||||
}
|
||||
|
||||
public ClusterGroup<Speed> getWindStrengthInBeaufortCluster() {
|
||||
return windStrengthInBeaufortCluster;
|
||||
public ClusterGroup<Speed> getWindStrengthInBeaufortClusterGroup() {
|
||||
return windStrengthInBeaufortClusterGroup;
|
||||
}
|
||||
|
||||
public ClusterGroup<Double> getPercentageClusterGroup() {
|
||||
return percentageClusterGroup;
|
||||
}
|
||||
|
||||
}
|
||||
+7
@@ -8,6 +8,7 @@ import com.sap.sailing.domain.common.Tack;
|
||||
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 HasRaceOfCompetitorContext {
|
||||
|
||||
@@ -23,6 +24,12 @@ public interface HasRaceOfCompetitorContext {
|
||||
@Dimension(messageKey="TackAtStart", ordinal=12)
|
||||
public Tack getTackAtStart() throws NoWindException;
|
||||
|
||||
@Dimension(messageKey="DistanceToStarboardSideAtStart", ordinal=13)
|
||||
public ClusterDTO getPercentageClusterForDistanceToStarboardSideAtStart();
|
||||
|
||||
@Dimension(messageKey="RelativeScore", ordinal=14)
|
||||
public ClusterDTO getPercentageClusterForRelativeScore();
|
||||
|
||||
@Statistic(messageKey="DistanceAtStart", resultDecimals=2, ordinal=0)
|
||||
public Distance getDistanceToStartLineAtStart();
|
||||
|
||||
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package com.sap.sailing.datamining.impl.data;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sap.sse.datamining.data.Cluster;
|
||||
import com.sap.sse.datamining.data.ClusterGroup;
|
||||
import com.sap.sse.datamining.impl.data.ClusterWithLowerAndUpperBoundaries;
|
||||
import com.sap.sse.datamining.impl.data.ComparableClusterBoundary;
|
||||
import com.sap.sse.datamining.impl.data.ComparisonStrategy;
|
||||
|
||||
// TODO: Improve and move to com.sap.sse.datamining
|
||||
public class LinearDoubleClusterGroup implements ClusterGroup<Double> {
|
||||
private static final long serialVersionUID = 1559316450183865115L;
|
||||
|
||||
private final double lowerBound;
|
||||
private final double upperBound;
|
||||
private final double stepSize;
|
||||
private final boolean hardBounds;
|
||||
|
||||
private final transient Map<Integer, Cluster<Double>> clusterCache;
|
||||
|
||||
public LinearDoubleClusterGroup(double lowerBound, double upperBound, double stepSize, boolean hardBounds) {
|
||||
this.lowerBound = lowerBound;
|
||||
this.upperBound = upperBound;
|
||||
this.stepSize = stepSize;
|
||||
this.hardBounds = hardBounds;
|
||||
|
||||
clusterCache = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cluster<Double> getClusterFor(Double valueObject) {
|
||||
double value = valueObject.doubleValue();
|
||||
if (value < lowerBound) {
|
||||
return hardBounds ? null : getCluster(0);
|
||||
}
|
||||
if (value > upperBound) {
|
||||
return hardBounds ? null : getCluster(getLastClusterIndex());
|
||||
}
|
||||
|
||||
if (Math.abs(upperBound - value) < 0.0001) {
|
||||
return getCluster(getLastClusterIndex());
|
||||
}
|
||||
return getCluster((int) (value / stepSize));
|
||||
}
|
||||
|
||||
private Cluster<Double> getCluster(int index) {
|
||||
if (!clusterCache.containsKey(index)) {
|
||||
ComparableClusterBoundary<Double> lowerBound = new ComparableClusterBoundary<Double>(this.lowerBound + stepSize * index, ComparisonStrategy.GREATER_EQUALS_THAN);
|
||||
ComparableClusterBoundary<Double> upperBound = new ComparableClusterBoundary<Double>(this.lowerBound + stepSize * (index + 1), ComparisonStrategy.LOWER_THAN);
|
||||
Cluster<Double> cluster = new ClusterWithLowerAndUpperBoundaries<>(lowerBound, upperBound);
|
||||
clusterCache.put(index, cluster);
|
||||
}
|
||||
return clusterCache.get(index);
|
||||
}
|
||||
|
||||
private int getLastClusterIndex() {
|
||||
double doubleIndex = upperBound / stepSize;
|
||||
int index = (int) doubleIndex;
|
||||
double fractionalPart = doubleIndex - index;
|
||||
if (fractionalPart <= 0.0001) {
|
||||
index--;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Double> getClusterElementsType() {
|
||||
return Double.class;
|
||||
}
|
||||
|
||||
}
|
||||
+27
@@ -2,6 +2,7 @@ package com.sap.sailing.datamining.impl.data;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.sap.sailing.datamining.Activator;
|
||||
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedRaceContext;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
@@ -16,6 +17,9 @@ import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.datamining.data.Cluster;
|
||||
import com.sap.sse.datamining.shared.impl.dto.ClusterDTO;
|
||||
|
||||
public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext {
|
||||
|
||||
@@ -52,6 +56,17 @@ public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext {
|
||||
return startOfRace == null ? null : getTrackedRace().getTack(getCompetitor(), startOfRace);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClusterDTO getPercentageClusterForDistanceToStarboardSideAtStart() {
|
||||
Double normalizedDistance = getNormalizedDistanceToStarboardSideAtStart();
|
||||
if (normalizedDistance == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Cluster<Double> cluster = Activator.getClusterGroups().getPercentageClusterGroup().getClusterFor(normalizedDistance);
|
||||
return new ClusterDTO(cluster.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getDistanceToStartLineAtStart() {
|
||||
return getTrackedRace().getDistanceToStartLine(getCompetitor(), 0);
|
||||
@@ -71,6 +86,18 @@ public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext {
|
||||
return distance / length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClusterDTO getPercentageClusterForRelativeScore() {
|
||||
Double rankAtFinish = getRankAtFinish();
|
||||
if (rankAtFinish == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int competitorCount = Util.size(getTrackedRace().getRace().getCompetitors());
|
||||
Cluster<Double> cluster = Activator.getClusterGroups().getPercentageClusterGroup().getClusterFor(rankAtFinish / competitorCount);
|
||||
return new ClusterDTO(cluster.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Speed getSpeedWhenStarting() {
|
||||
return getTrackedRace().getSpeedWhenCrossingStartLine(getCompetitor());
|
||||
|
||||
Reference in new issue
Block a user