Implemented range dimensions for the distance to starboard side at start and relative score for races of competitors

This commit is contained in:
Lennart Hensler committed 2016-10-21 14:28:39 +02:00
1 parent 9ada894373
commit 2072e3f624
5 files changed
+201 -4

No files matched your search

@@ -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);
}
}
@@ -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;
}
}
@@ -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();
@@ -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;
}
}
@@ -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());