mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-10 14:20:55 +00:00
Merge remote-tracking branch 'origin/master' into mark-rounding-inference
Conflicts: java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties
This commit is contained in:
commit
6f89b80167
215 files changed
+8139
-361
No files matched your search
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/bin
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>com.sap.sailing.datamining.shared</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.pde.PluginNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
<nature>com.google.gwt.eclipse.core.gwtNature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||||
|
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||||
|
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||||
|
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.6
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
pluginProject.extensions=false
|
||||||
|
resolve.requirebundle=false
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Bundle-ManifestVersion: 2
|
||||||
|
Bundle-Name: Datamining-Shared
|
||||||
|
Bundle-SymbolicName: com.sap.sailing.datamining.shared
|
||||||
|
Bundle-Version: 1.0.0.qualifier
|
||||||
|
Bundle-Vendor: SAP
|
||||||
|
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||||
|
Bundle-ActivationPolicy: lazy
|
||||||
|
Bundle-ClassPath: .
|
||||||
|
Export-Package: com.sap.sailing.datamining.shared
|
||||||
|
Import-Package: com.google.gwt.i18n.client
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
source.. = src/
|
||||||
|
output.. = bin/
|
||||||
|
bin.includes = META-INF/,\
|
||||||
|
.,\
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<artifactId>root</artifactId>
|
||||||
|
<groupId>com.sap.sailing</groupId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>com.sap.sailing.datamining.shared</artifactId>
|
||||||
|
<packaging>eclipse-plugin</packaging>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.eclipse.tycho</groupId>
|
||||||
|
<artifactId>tycho-source-plugin</artifactId>
|
||||||
|
<version>${tycho-version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>plugin-source</id>
|
||||||
|
<phase>generate-sources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>plugin-source</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt-module.dtd">
|
||||||
|
<module>
|
||||||
|
<source path='shared'/>
|
||||||
|
</module>
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package com.sap.sailing.datamining.shared;
|
||||||
|
|
||||||
|
|
||||||
|
public abstract class AbstractGroupKey implements GroupKey {
|
||||||
|
private static final long serialVersionUID = 183947887066745315L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Enforce hash code and equals in all subclasses
|
||||||
|
@Override
|
||||||
|
public abstract boolean equals(Object other);
|
||||||
|
@Override
|
||||||
|
public abstract int hashCode();
|
||||||
|
|
||||||
|
}
|
||||||
+84
@@ -0,0 +1,84 @@
|
|||||||
|
package com.sap.sailing.datamining.shared;
|
||||||
|
|
||||||
|
|
||||||
|
public final class Components {
|
||||||
|
|
||||||
|
public enum GrouperType {
|
||||||
|
Dimensions
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum AggregatorType {
|
||||||
|
Sum, Average, Median;
|
||||||
|
|
||||||
|
public Message getNameMessage() {
|
||||||
|
switch (this) {
|
||||||
|
case Average:
|
||||||
|
return Message.Average;
|
||||||
|
case Median:
|
||||||
|
return Message.Median;
|
||||||
|
case Sum:
|
||||||
|
return Message.Sum;
|
||||||
|
};
|
||||||
|
throw new IllegalArgumentException("No message available for the aggregator type '" + this + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum ValueType {
|
||||||
|
Integer, Double
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum StatisticType {
|
||||||
|
|
||||||
|
Speed(ValueType.Double, Unit.Knots, 2),
|
||||||
|
Distance(ValueType.Double, Unit.Meters, 2);
|
||||||
|
|
||||||
|
private final ValueType valueType;
|
||||||
|
private final Unit unit;
|
||||||
|
private final int valueDecimals;
|
||||||
|
|
||||||
|
private StatisticType(ValueType valueType, Unit unit, int valueDecimals) {
|
||||||
|
this.valueType = valueType;
|
||||||
|
this.unit = unit;
|
||||||
|
this.valueDecimals = valueDecimals;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueType getValueType() {
|
||||||
|
return valueType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Message getSignifierMessage() {
|
||||||
|
switch (this) {
|
||||||
|
case Distance:
|
||||||
|
return Message.Distance;
|
||||||
|
case Speed:
|
||||||
|
return Message.Speed;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("No message available for the statistic type '" + this + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Unit getUnit() {
|
||||||
|
return unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Message getUnitMessage() {
|
||||||
|
switch (unit) {
|
||||||
|
case Knots:
|
||||||
|
return Message.Knots;
|
||||||
|
case Meters:
|
||||||
|
return Message.Meters;
|
||||||
|
case None:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("No message available for the unit '" + unit + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValueDecimals() {
|
||||||
|
return valueDecimals;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Components() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+82
@@ -0,0 +1,82 @@
|
|||||||
|
package com.sap.sailing.datamining.shared;
|
||||||
|
|
||||||
|
|
||||||
|
public class CompoundGroupKey extends AbstractGroupKey {
|
||||||
|
private static final long serialVersionUID = -7902450253393172550L;
|
||||||
|
|
||||||
|
private GroupKey mainKey;
|
||||||
|
private GroupKey subKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the GWT-Serialization. Don't use this!
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
CompoundGroupKey() { }
|
||||||
|
|
||||||
|
public CompoundGroupKey(GroupKey mainKey) {
|
||||||
|
this(mainKey, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompoundGroupKey(GroupKey mainKey, GroupKey subKey) {
|
||||||
|
this.mainKey = mainKey;
|
||||||
|
this.subKey = subKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String asString() {
|
||||||
|
return mainKey.asString() + " (" + subKey.asString() + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSubKey() {
|
||||||
|
return subKey != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GroupKey getMainKey() {
|
||||||
|
return mainKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GroupKey getSubKey() {
|
||||||
|
return subKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubKey(GroupKey subKey) {
|
||||||
|
this.subKey = subKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((mainKey == null) ? 0 : mainKey.hashCode());
|
||||||
|
result = prime * result + ((subKey == null) ? 0 : subKey.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
CompoundGroupKey other = (CompoundGroupKey) obj;
|
||||||
|
if (mainKey == null) {
|
||||||
|
if (other.mainKey != null)
|
||||||
|
return false;
|
||||||
|
} else if (!mainKey.equals(other.mainKey))
|
||||||
|
return false;
|
||||||
|
if (subKey == null) {
|
||||||
|
if (other.subKey != null)
|
||||||
|
return false;
|
||||||
|
} else if (!subKey.equals(other.subKey))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
package com.sap.sailing.datamining.shared;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public final class DataMiningSerializationDummy implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private GenericGroupKey<String> groupKey;
|
||||||
|
|
||||||
|
private DataMiningSerializationDummy() { }
|
||||||
|
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package com.sap.sailing.datamining.shared;
|
||||||
|
|
||||||
|
public enum DataTypes {
|
||||||
|
|
||||||
|
GPSFix, TrackedLegOfCompetitor
|
||||||
|
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
package com.sap.sailing.datamining.shared;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public enum DimensionIdentifier {
|
||||||
|
RegattaName, BoatClassName, CourseAreaName, FleetName, RaceName, LegType, LegNumber, Nationality, CompetitorName, SailID, WindStrength, Year;
|
||||||
|
|
||||||
|
public static class OrdinalComparator implements Comparator<DimensionIdentifier> {
|
||||||
|
private static final List<DimensionIdentifier> dimensions = Arrays.asList(DimensionIdentifier.values());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(DimensionIdentifier dimension1, DimensionIdentifier dimension2) {
|
||||||
|
Integer ordinal1 = dimensions.indexOf(dimension1);
|
||||||
|
Integer ordinal2 = dimensions.indexOf(dimension2);
|
||||||
|
return ordinal1.compareTo(ordinal2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+64
@@ -0,0 +1,64 @@
|
|||||||
|
package com.sap.sailing.datamining.shared;
|
||||||
|
|
||||||
|
|
||||||
|
public class GenericGroupKey<T> extends AbstractGroupKey {
|
||||||
|
private static final long serialVersionUID = -3838535617341226965L;
|
||||||
|
|
||||||
|
private T value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the GWT-Serialization. Don't use this!
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
GenericGroupKey() { }
|
||||||
|
|
||||||
|
public GenericGroupKey(T value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSubKey() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GroupKey getMainKey() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GroupKey getSubKey() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String asString() {
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((value == null) ? 0 : value.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
GenericGroupKey<?> other = (GenericGroupKey<?>) obj;
|
||||||
|
if (value == null) {
|
||||||
|
if (other.value != null)
|
||||||
|
return false;
|
||||||
|
} else if (!value.equals(other.value))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
package com.sap.sailing.datamining.shared;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
|
||||||
|
public interface GroupKey extends Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a string representation of this group key.
|
||||||
|
*/
|
||||||
|
public String asString();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this group key has a sub key. For example if the data was grouped primary by competitor and secondary by leg type.
|
||||||
|
* @return true, if this group key has a sub key
|
||||||
|
*/
|
||||||
|
public boolean hasSubKey();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the main key, if there is one. Otherwise it returns <code>this</code>.
|
||||||
|
*/
|
||||||
|
public GroupKey getMainKey();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the sub key or null, if there's none.
|
||||||
|
*/
|
||||||
|
public GroupKey getSubKey();
|
||||||
|
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
package com.sap.sailing.datamining.shared;
|
||||||
|
|
||||||
|
public enum Message {
|
||||||
|
Average, Median, Sum, Distance, Speed, Knots, Meters, ResultSignifier, SignifierInUnit
|
||||||
|
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
package com.sap.sailing.datamining.shared;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.shared.Components.AggregatorType;
|
||||||
|
import com.sap.sailing.datamining.shared.Components.GrouperType;
|
||||||
|
import com.sap.sailing.datamining.shared.Components.StatisticType;
|
||||||
|
|
||||||
|
public interface QueryDefinition extends Serializable {
|
||||||
|
|
||||||
|
public String getLocaleName();
|
||||||
|
|
||||||
|
public GrouperType getGrouperType();
|
||||||
|
|
||||||
|
public StatisticType getStatisticType();
|
||||||
|
|
||||||
|
public AggregatorType getAggregatorType();
|
||||||
|
|
||||||
|
public DataTypes getDataType();
|
||||||
|
|
||||||
|
public List<DimensionIdentifier> getDimensionsToGroupBy();
|
||||||
|
|
||||||
|
public Map<DimensionIdentifier, Iterable<?>> getSelection();
|
||||||
|
|
||||||
|
}
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
package com.sap.sailing.datamining.shared;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface QueryResult<AggregatedType> extends Serializable {
|
||||||
|
|
||||||
|
int getRetrievedDataAmount();
|
||||||
|
public int getFilteredDataAmount();
|
||||||
|
public double getCalculationTimeInSeconds();
|
||||||
|
public boolean isEmpty();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a description what kind of results are contained.
|
||||||
|
*/
|
||||||
|
public String getResultSignifier();
|
||||||
|
public Unit getUnit();
|
||||||
|
public int getValueDecimals();
|
||||||
|
|
||||||
|
public Map<GroupKey, AggregatedType> getResults();
|
||||||
|
|
||||||
|
}
|
||||||
+82
@@ -0,0 +1,82 @@
|
|||||||
|
package com.sap.sailing.datamining.shared;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class QueryResultImpl<AggregatedType> implements QueryResult<AggregatedType> {
|
||||||
|
private static final long serialVersionUID = -8347731622150585715L;
|
||||||
|
|
||||||
|
private int retrievedDataAmount;
|
||||||
|
private int filteredDataAmount;
|
||||||
|
private long calculationTimeInNanos;
|
||||||
|
|
||||||
|
private String resultSignifier;
|
||||||
|
private Unit unit;
|
||||||
|
private int valueDecimals;
|
||||||
|
|
||||||
|
private Map<GroupKey, AggregatedType> results;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the GWT-Serialization. Don't use this!
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
QueryResultImpl() { }
|
||||||
|
|
||||||
|
public QueryResultImpl(int retrievedDataAmount, int filteredDataAmount, String resultSiginifier, Unit unit, int valueDecimals) {
|
||||||
|
this.retrievedDataAmount = retrievedDataAmount;
|
||||||
|
this.filteredDataAmount = filteredDataAmount;
|
||||||
|
results = new HashMap<GroupKey, AggregatedType>();
|
||||||
|
this.resultSignifier = resultSiginifier;
|
||||||
|
this.unit = unit;
|
||||||
|
this.valueDecimals = valueDecimals;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRetrievedDataAmount() {
|
||||||
|
return retrievedDataAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getFilteredDataAmount() {
|
||||||
|
return filteredDataAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getCalculationTimeInSeconds() {
|
||||||
|
return calculationTimeInNanos / 1000000000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCalculationTimeInNanos(long calculationTimeInNanos) {
|
||||||
|
this.calculationTimeInNanos = calculationTimeInNanos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return results.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getResultSignifier() {
|
||||||
|
return resultSignifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Unit getUnit() {
|
||||||
|
return unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getValueDecimals() {
|
||||||
|
return valueDecimals;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<GroupKey, AggregatedType> getResults() {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addResult(GroupKey key, AggregatedType value) {
|
||||||
|
results.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+87
@@ -0,0 +1,87 @@
|
|||||||
|
package com.sap.sailing.datamining.shared;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.gwt.i18n.client.LocaleInfo;
|
||||||
|
import com.sap.sailing.datamining.shared.Components.AggregatorType;
|
||||||
|
import com.sap.sailing.datamining.shared.Components.GrouperType;
|
||||||
|
import com.sap.sailing.datamining.shared.Components.StatisticType;
|
||||||
|
|
||||||
|
public class SimpleQueryDefinition implements QueryDefinition {
|
||||||
|
private static final long serialVersionUID = 3476324726640558091L;
|
||||||
|
|
||||||
|
private String localeName;
|
||||||
|
|
||||||
|
private GrouperType grouperType;
|
||||||
|
private StatisticType statisticType;
|
||||||
|
private AggregatorType aggregatorType;
|
||||||
|
private DataTypes dataType;
|
||||||
|
|
||||||
|
private List<DimensionIdentifier> dimensionsToGroupBy;
|
||||||
|
private Map<DimensionIdentifier, Iterable<?>> selectionMappedByDimension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the GWT-Serialization. Don't use this!
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
SimpleQueryDefinition() { }
|
||||||
|
|
||||||
|
public SimpleQueryDefinition(LocaleInfo localeInfo, GrouperType grouperType, StatisticType statisticType, AggregatorType aggregatorType, DataTypes dataType) {
|
||||||
|
this.localeName = localeInfo.getLocaleName();
|
||||||
|
this.grouperType = grouperType;
|
||||||
|
this.statisticType = statisticType;
|
||||||
|
this.aggregatorType = aggregatorType;
|
||||||
|
this.dataType = dataType;
|
||||||
|
|
||||||
|
dimensionsToGroupBy = new ArrayList<DimensionIdentifier>();
|
||||||
|
selectionMappedByDimension = new HashMap<DimensionIdentifier, Iterable<?>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLocaleName() {
|
||||||
|
return localeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GrouperType getGrouperType() {
|
||||||
|
return grouperType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StatisticType getStatisticType() {
|
||||||
|
return statisticType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AggregatorType getAggregatorType() {
|
||||||
|
return aggregatorType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataTypes getDataType() {
|
||||||
|
return dataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DimensionIdentifier> getDimensionsToGroupBy() {
|
||||||
|
return dimensionsToGroupBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<DimensionIdentifier, Iterable<?>> getSelection() {
|
||||||
|
return selectionMappedByDimension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void appendDimensionToGroupBy(DimensionIdentifier dimension) {
|
||||||
|
dimensionsToGroupBy.add(dimension);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectionFor(DimensionIdentifier dimension, Collection<?> selection) {
|
||||||
|
selectionMappedByDimension.put(dimension, selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.sap.sailing.datamining.shared;
|
||||||
|
|
||||||
|
public enum Unit {
|
||||||
|
|
||||||
|
None, Knots, Meters
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||||
|
<classpathentry kind="con" path="com.google.gwt.eclipse.core.GWT_CONTAINER"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/bin
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>com.sap.sailing.datamining.test</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.pde.PluginNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||||
|
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.7
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Bundle-ManifestVersion: 2
|
||||||
|
Bundle-Name: Test
|
||||||
|
Bundle-SymbolicName: com.sap.sailing.datamining.test
|
||||||
|
Bundle-Version: 1.0.0.qualifier
|
||||||
|
Bundle-Vendor: SAP
|
||||||
|
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||||
|
Fragment-Host: com.sap.sailing.datamining
|
||||||
|
Import-Package: junit.framework;version="4.8.2",
|
||||||
|
org.junit;version="4.8.2"
|
||||||
|
Require-Bundle: org.mockito.mockito-core;bundle-version="1.9.5",
|
||||||
|
org.hamcrest;bundle-version="1.1.0"
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
source.. = src/
|
||||||
|
output.. = bin/
|
||||||
|
bin.includes = META-INF/,\
|
||||||
|
.
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<artifactId>root</artifactId>
|
||||||
|
<groupId>com.sap.sailing</groupId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>com.sap.sailing.datamining.test</artifactId>
|
||||||
|
<packaging>eclipse-test-plugin</packaging>
|
||||||
|
</project>
|
||||||
+78
@@ -0,0 +1,78 @@
|
|||||||
|
package com.sap.sailing.datamining.test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.AggregationWorker;
|
||||||
|
import com.sap.sailing.datamining.WorkReceiver;
|
||||||
|
import com.sap.sailing.datamining.impl.aggregators.SimpleIntegerArithmeticAverageAggregationWorker;
|
||||||
|
import com.sap.sailing.datamining.impl.aggregators.SumAggregationWorker;
|
||||||
|
import com.sap.sailing.datamining.impl.aggregators.helpers.SimpleIntegerSumAggregator;
|
||||||
|
import com.sap.sailing.datamining.shared.GenericGroupKey;
|
||||||
|
import com.sap.sailing.datamining.shared.GroupKey;
|
||||||
|
|
||||||
|
public class TestAggregators {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSumAggregator() {
|
||||||
|
AggregationWorker<Integer, Integer> sumAggregator = new SumAggregationWorker<Integer, Integer>(new SimpleIntegerSumAggregator());
|
||||||
|
Map<GroupKey, Collection<Integer>> data = asDataToAggregate(1, 7, 6, 3);
|
||||||
|
sumAggregator.setDataToAggregate(data);
|
||||||
|
DataReceiver receiver = new DataReceiver();
|
||||||
|
sumAggregator.setReceiver(receiver);
|
||||||
|
|
||||||
|
sumAggregator.run();
|
||||||
|
Map<GroupKey, Integer> expectedAggregation = asAggregatedData(17);
|
||||||
|
assertEquals(expectedAggregation, receiver.result);
|
||||||
|
|
||||||
|
data = asDataToAggregate(7);
|
||||||
|
sumAggregator.setDataToAggregate(data);
|
||||||
|
sumAggregator.run();
|
||||||
|
expectedAggregation = asAggregatedData(7);
|
||||||
|
assertEquals(expectedAggregation, receiver.result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAverageAggregator() {
|
||||||
|
AggregationWorker<Integer, Integer> averageAggregator = new SimpleIntegerArithmeticAverageAggregationWorker();
|
||||||
|
Map<GroupKey, Collection<Integer>> data = asDataToAggregate(1, 7, 6, 3);
|
||||||
|
averageAggregator.setDataToAggregate(data);
|
||||||
|
DataReceiver receiver = new DataReceiver();
|
||||||
|
averageAggregator.setReceiver(receiver);
|
||||||
|
|
||||||
|
averageAggregator.run();
|
||||||
|
Map<GroupKey, Integer> expectedAggregation = asAggregatedData(4);
|
||||||
|
assertEquals(expectedAggregation, receiver.result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<GroupKey, Collection<Integer>> asDataToAggregate(Integer... values) {
|
||||||
|
Collection<Integer> dataEntries = Arrays.asList(values);
|
||||||
|
Map<GroupKey, Collection<Integer>> data = new HashMap<GroupKey, Collection<Integer>>();
|
||||||
|
data.put(new GenericGroupKey<Integer>(100), dataEntries);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<GroupKey, Integer> asAggregatedData(Integer value) {
|
||||||
|
Map<GroupKey,Integer> data = new HashMap<GroupKey, Integer>();
|
||||||
|
data.put(new GenericGroupKey<Integer>(100), value);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DataReceiver implements WorkReceiver<Map<GroupKey, Integer>> {
|
||||||
|
|
||||||
|
public Map<GroupKey, Integer> result;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void receiveWork(Map<GroupKey, Integer> result) {
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
package com.sap.sailing.datamining.test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.ClusterOfComparable;
|
||||||
|
import com.sap.sailing.datamining.Clusters;
|
||||||
|
import com.sap.sailing.datamining.impl.ClusterOfComparableImpl;
|
||||||
|
|
||||||
|
public class TestClusters {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClusterOfComparable() {
|
||||||
|
ClusterOfComparable<Integer> cluster = new ClusterOfComparableImpl<Integer>("Test", 3, 1);
|
||||||
|
|
||||||
|
assertTrue(cluster.isInRange(1));
|
||||||
|
assertTrue(cluster.isInRange(2));
|
||||||
|
assertTrue(cluster.isInRange(3));
|
||||||
|
|
||||||
|
assertFalse(cluster.isInRange(null));
|
||||||
|
assertFalse(cluster.isInRange(0));
|
||||||
|
assertFalse(cluster.isInRange(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWindStrengthClusters() {
|
||||||
|
assertNull(Clusters.WindStrength.getClusterFor(15, Clusters.WindStrength.StandardClusters));
|
||||||
|
assertEquals(Clusters.WindStrength.VeryLight, Clusters.WindStrength.getClusterFor(1, Clusters.WindStrength.StandardClusters));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
package com.sap.sailing.datamining.test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.ExtractionWorker;
|
||||||
|
import com.sap.sailing.datamining.WorkReceiver;
|
||||||
|
import com.sap.sailing.datamining.impl.AbstractExtractionWorker;
|
||||||
|
import com.sap.sailing.datamining.shared.GenericGroupKey;
|
||||||
|
import com.sap.sailing.datamining.shared.GroupKey;
|
||||||
|
|
||||||
|
public class TestExtractors {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAbstractExtractor() {
|
||||||
|
ExtractionWorker<String, Integer> lengthExtractor = new LengthExtractor();
|
||||||
|
DataReceiver receiver = new DataReceiver();
|
||||||
|
lengthExtractor.setReceiver(receiver);
|
||||||
|
|
||||||
|
Collection<String> dataEntries = Arrays.asList("Fu", "Bar", "Blub");
|
||||||
|
Map<GroupKey, Collection<String>> data = new HashMap<GroupKey, Collection<String>>();
|
||||||
|
data.put(new GenericGroupKey<Integer>(100), dataEntries);
|
||||||
|
lengthExtractor.setDataToExtractFrom(data);
|
||||||
|
|
||||||
|
|
||||||
|
Collection<Integer> expectedExtractedDataEntries = Arrays.asList(2, 3, 4);
|
||||||
|
Map<GroupKey, Collection<Integer>> expectedExtractedData = new HashMap<GroupKey, Collection<Integer>>();
|
||||||
|
expectedExtractedData.put(new GenericGroupKey<Integer>(100), expectedExtractedDataEntries);
|
||||||
|
lengthExtractor.run();
|
||||||
|
assertEquals(expectedExtractedData, receiver.result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LengthExtractor extends AbstractExtractionWorker<String, Integer> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer extract(String dataEntry) {
|
||||||
|
return dataEntry.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DataReceiver implements WorkReceiver<Map<GroupKey, Collection<Integer>>> {
|
||||||
|
|
||||||
|
public Map<GroupKey, Collection<Integer>> result;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void receiveWork(Map<GroupKey, Collection<Integer>> result) {
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+87
@@ -0,0 +1,87 @@
|
|||||||
|
package com.sap.sailing.datamining.test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.ClusterOfComparable;
|
||||||
|
import com.sap.sailing.datamining.ConcurrentFilterCriteria;
|
||||||
|
import com.sap.sailing.datamining.impl.ClusterOfComparableImpl;
|
||||||
|
import com.sap.sailing.datamining.impl.criterias.AndCompoundFilterCriteria;
|
||||||
|
import com.sap.sailing.datamining.impl.criterias.CompoundFilterCriteria;
|
||||||
|
import com.sap.sailing.datamining.impl.criterias.OrCompoundFilterCriteria;
|
||||||
|
import com.sap.sailing.datamining.impl.criterias.RegexFilterCriteria;
|
||||||
|
import com.sap.sailing.datamining.impl.criterias.SimpleRangeFilterCriteria;
|
||||||
|
|
||||||
|
public class TestFilterCriterias {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRegexFilterCriteria() {
|
||||||
|
ConcurrentFilterCriteria<String> regexFilterCriteria = new StringRegexFilterCriteria(".*");
|
||||||
|
assertTrue(regexFilterCriteria.matches("some Random stuff"));
|
||||||
|
assertFalse(regexFilterCriteria.matches(null));
|
||||||
|
|
||||||
|
String[] stringsToMatch = new String[] {"Regatta", "Other Regatta", "Third Regatta"};
|
||||||
|
|
||||||
|
regexFilterCriteria = new StringRegexFilterCriteria(stringsToMatch[0] + "|" + stringsToMatch[1] + "|" + stringsToMatch[2]);
|
||||||
|
for (String stringToMatch : stringsToMatch) {
|
||||||
|
assertTrue("Failed to match " + stringToMatch, regexFilterCriteria.matches(stringToMatch));
|
||||||
|
}
|
||||||
|
assertFalse("'Fourth Regatta' shouldn't be matched", regexFilterCriteria.matches("Fourth Regatta"));
|
||||||
|
|
||||||
|
regexFilterCriteria = new StringRegexFilterCriteria(".*Regatta");
|
||||||
|
for (String stringToMatch : stringsToMatch) {
|
||||||
|
assertTrue("Failed to match " + stringToMatch, regexFilterCriteria.matches(stringToMatch));
|
||||||
|
}
|
||||||
|
assertFalse("'Regatta (29ER)' shouldn't be matched", regexFilterCriteria.matches("Regatta (29ER)"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRangeFilterCriteria() {
|
||||||
|
ClusterOfComparable<Integer> cluster = new ClusterOfComparableImpl<Integer>("Test", 3, 1);
|
||||||
|
ConcurrentFilterCriteria<Integer> rangeFilterCriteria = new SimpleRangeFilterCriteria<Integer>(cluster);
|
||||||
|
|
||||||
|
assertTrue(rangeFilterCriteria.matches(1));
|
||||||
|
assertTrue(rangeFilterCriteria.matches(2));
|
||||||
|
assertTrue(rangeFilterCriteria.matches(3));
|
||||||
|
|
||||||
|
assertFalse(rangeFilterCriteria.matches(0));
|
||||||
|
assertFalse(rangeFilterCriteria.matches(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCompoundFilterCriterias() {
|
||||||
|
StringRegexFilterCriteria startsWithBar = new StringRegexFilterCriteria("Bar.*");
|
||||||
|
StringRegexFilterCriteria endWithFoo = new StringRegexFilterCriteria(".*Foo");
|
||||||
|
|
||||||
|
CompoundFilterCriteria<String> compoundCriteria = new AndCompoundFilterCriteria<String>();
|
||||||
|
compoundCriteria.addCriteria(startsWithBar);
|
||||||
|
compoundCriteria.addCriteria(endWithFoo);
|
||||||
|
|
||||||
|
assertTrue(compoundCriteria.matches("BarAndFoo"));
|
||||||
|
assertFalse(compoundCriteria.matches("BarFo"));
|
||||||
|
|
||||||
|
compoundCriteria = new OrCompoundFilterCriteria<String>();
|
||||||
|
compoundCriteria.addCriteria(startsWithBar);
|
||||||
|
compoundCriteria.addCriteria(endWithFoo);
|
||||||
|
|
||||||
|
assertTrue(compoundCriteria.matches("BarF"));
|
||||||
|
assertTrue(compoundCriteria.matches("BraFoo"));
|
||||||
|
assertFalse(compoundCriteria.matches("Nothing"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StringRegexFilterCriteria extends RegexFilterCriteria<String> {
|
||||||
|
|
||||||
|
public StringRegexFilterCriteria(String regex) {
|
||||||
|
super(regex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getValueToMatch(String data) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
package com.sap.sailing.datamining.test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.ClusterOfComparable;
|
||||||
|
import com.sap.sailing.datamining.ConcurrentFilterCriteria;
|
||||||
|
import com.sap.sailing.datamining.FiltrationWorker;
|
||||||
|
import com.sap.sailing.datamining.WorkReceiver;
|
||||||
|
import com.sap.sailing.datamining.impl.ClusterOfComparableImpl;
|
||||||
|
import com.sap.sailing.datamining.impl.CriteriaFiltrationWorker;
|
||||||
|
import com.sap.sailing.datamining.impl.criterias.SimpleRangeFilterCriteria;
|
||||||
|
|
||||||
|
public class TestFilters {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFilterByCriteria() {
|
||||||
|
List<Integer> data = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
|
||||||
|
|
||||||
|
ClusterOfComparable<Integer> cluster = new ClusterOfComparableImpl<Integer>("Test", 5, 1);
|
||||||
|
ConcurrentFilterCriteria<Integer> criteria = new SimpleRangeFilterCriteria<Integer>(cluster);
|
||||||
|
FiltrationWorker<Integer> filter = new CriteriaFiltrationWorker<Integer>(criteria);
|
||||||
|
filter.setDataToFilter(data);
|
||||||
|
|
||||||
|
Receiver receiver = new Receiver();
|
||||||
|
filter.setReceiver(receiver);
|
||||||
|
|
||||||
|
filter.run();
|
||||||
|
Collection<Integer> expectedFilteredData = Arrays.asList(1, 2, 3, 4, 5);
|
||||||
|
assertEquals(expectedFilteredData, receiver.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Receiver implements WorkReceiver<Collection<Integer>> {
|
||||||
|
|
||||||
|
public Collection<Integer> data;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void receiveWork(Collection<Integer> data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+69
@@ -0,0 +1,69 @@
|
|||||||
|
package com.sap.sailing.datamining.test;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.i18n.DataMiningResourceBundleManager;
|
||||||
|
|
||||||
|
public class TestI18N {
|
||||||
|
|
||||||
|
private static final String SIMPLE_TEST_MESSAGE_KEY = "SimpleTestMessage";
|
||||||
|
private static final String TEST_MESSAGE_WITH_PARAMETERS = "TestMessageWithParameters";
|
||||||
|
|
||||||
|
private OpenResourceBundleManager bundleManager;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void initializeBundleManager() {
|
||||||
|
bundleManager = new OpenResourceBundleManager(Locale.ENGLISH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGettingASimpleMessage() {
|
||||||
|
assertThat(bundleManager.get("default", SIMPLE_TEST_MESSAGE_KEY), is("English"));
|
||||||
|
assertThat(bundleManager.get("en", SIMPLE_TEST_MESSAGE_KEY), is("English"));
|
||||||
|
assertThat(bundleManager.get("de", SIMPLE_TEST_MESSAGE_KEY), is("Deutsch"));
|
||||||
|
|
||||||
|
assertThat(bundleManager.get(Locale.ENGLISH, SIMPLE_TEST_MESSAGE_KEY), is("English"));
|
||||||
|
assertThat(bundleManager.get(Locale.GERMAN, SIMPLE_TEST_MESSAGE_KEY), is("Deutsch"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGettingAMessageWithParameters() {
|
||||||
|
assertThat(bundleManager.get("default", TEST_MESSAGE_WITH_PARAMETERS, "Param0", "Param1"), is("English Param0 - Param1"));
|
||||||
|
assertThat(bundleManager.get("en", TEST_MESSAGE_WITH_PARAMETERS, "Param0", "Param1"), is("English Param0 - Param1"));
|
||||||
|
assertThat(bundleManager.get("de", TEST_MESSAGE_WITH_PARAMETERS, "Param0", "Param1"), is("Deutsch Param0 - Param1"));
|
||||||
|
|
||||||
|
assertThat(bundleManager.get(Locale.ENGLISH, TEST_MESSAGE_WITH_PARAMETERS, "Param0", "Param1"), is("English Param0 - Param1"));
|
||||||
|
assertThat(bundleManager.get(Locale.GERMAN, TEST_MESSAGE_WITH_PARAMETERS, "Param0", "Param1"), is("Deutsch Param0 - Param1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private class OpenResourceBundleManager extends DataMiningResourceBundleManager {
|
||||||
|
|
||||||
|
public OpenResourceBundleManager(Locale defaultLocale) {
|
||||||
|
super(defaultLocale);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get(Locale locale, String message, String... parameters) {
|
||||||
|
return super.get(locale, message, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get(Locale locale, String message) {
|
||||||
|
return super.get(locale, message, new String[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get(String localeName, String message, String... parameters) {
|
||||||
|
return this.get(getLocaleFrom(localeName), message, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get(String localeName, String message) {
|
||||||
|
return this.get(getLocaleFrom(localeName), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+172
@@ -0,0 +1,172 @@
|
|||||||
|
package com.sap.sailing.datamining.test.groupers;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.Dimension;
|
||||||
|
import com.sap.sailing.datamining.GroupingWorker;
|
||||||
|
import com.sap.sailing.datamining.WorkReceiver;
|
||||||
|
import com.sap.sailing.datamining.impl.AbstractDimension;
|
||||||
|
import com.sap.sailing.datamining.impl.MultiDimensionalGroupingWorker;
|
||||||
|
import com.sap.sailing.datamining.shared.CompoundGroupKey;
|
||||||
|
import com.sap.sailing.datamining.shared.GenericGroupKey;
|
||||||
|
import com.sap.sailing.datamining.shared.GroupKey;
|
||||||
|
|
||||||
|
public class TestDimensionGroupers {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGroupByDimension() {
|
||||||
|
Dimension<Integer, String> crossSum = createCrossSumDimension();
|
||||||
|
GroupingWorker<Integer> groupByDimension = new OpenGrouper<Integer>(Arrays.asList(crossSum));
|
||||||
|
|
||||||
|
DataReceiver receiver = new DataReceiver();
|
||||||
|
groupByDimension.setReceiver(receiver);
|
||||||
|
|
||||||
|
Collection<Integer> data = Arrays.asList(11, 2, 13, 4, 22, 3, 21, 111);
|
||||||
|
groupByDimension.setDataToGroup(data);
|
||||||
|
|
||||||
|
Map<GroupKey, Collection<Integer>> expectedGroups = new HashMap<GroupKey, Collection<Integer>>();
|
||||||
|
Collection<Integer> group = new ArrayList<Integer>();
|
||||||
|
group.add(11);
|
||||||
|
group.add(2);
|
||||||
|
expectedGroups.put(new GenericGroupKey<String>("2"), group);
|
||||||
|
group = new ArrayList<Integer>();
|
||||||
|
group.add(3);
|
||||||
|
group.add(21);
|
||||||
|
group.add(111);
|
||||||
|
expectedGroups.put(new GenericGroupKey<String>("3"), group);
|
||||||
|
group = new ArrayList<Integer>();
|
||||||
|
group.add(13);
|
||||||
|
group.add(4);
|
||||||
|
group.add(22);
|
||||||
|
expectedGroups.put(new GenericGroupKey<String>("4"), group);
|
||||||
|
|
||||||
|
groupByDimension.run();
|
||||||
|
assertEquals(expectedGroups, receiver.groupedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGroupKeyGeneration() {
|
||||||
|
Dimension<Integer, String> first = new AbstractDimension<Integer, String>("First") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(Integer data) {
|
||||||
|
return "First";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Dimension<Integer, String> second = new AbstractDimension<Integer, String>("Second") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(Integer data) {
|
||||||
|
return "Second";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Dimension<Integer, String> third = new AbstractDimension<Integer, String>("Third") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(Integer data) {
|
||||||
|
return "Third";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
OpenGrouper<Integer> grouper = new OpenGrouper<Integer>(Arrays.asList(first, second, third));
|
||||||
|
GroupKey expectedGroupKey = new CompoundGroupKey(new GenericGroupKey<String>("First"), new CompoundGroupKey(new GenericGroupKey<String>("Second"), new GenericGroupKey<String>("Third")));
|
||||||
|
assertEquals(expectedGroupKey, grouper.getGroupKey(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGroupByMultipleDimensions() {
|
||||||
|
Dimension<Integer, String> crossSum = createCrossSumDimension();
|
||||||
|
Dimension<Integer, String> signum = createSignumDimension();
|
||||||
|
GroupingWorker<Integer> groupByDimensions = new OpenGrouper<Integer>(Arrays.asList(crossSum, signum));
|
||||||
|
|
||||||
|
DataReceiver receiver = new DataReceiver();
|
||||||
|
groupByDimensions.setReceiver(receiver);
|
||||||
|
|
||||||
|
Collection<Integer> data = Arrays.asList(13, -4, 22, -3, 21, -111);
|
||||||
|
groupByDimensions.setDataToGroup(data);
|
||||||
|
|
||||||
|
Map<GroupKey, Collection<Integer>> expectedGroups = new HashMap<GroupKey, Collection<Integer>>();
|
||||||
|
Collection<Integer> expectedGroup = new ArrayList<Integer>();
|
||||||
|
expectedGroup.add(-3);
|
||||||
|
expectedGroup.add(-111);
|
||||||
|
expectedGroups.put(new CompoundGroupKey(new GenericGroupKey<String>("3"), new GenericGroupKey<String>("-1")), expectedGroup);
|
||||||
|
expectedGroup = new ArrayList<Integer>();
|
||||||
|
expectedGroup.add(13);
|
||||||
|
expectedGroup.add(22);
|
||||||
|
expectedGroups.put(new CompoundGroupKey(new GenericGroupKey<String>("4"), new GenericGroupKey<String>("1")), expectedGroup);
|
||||||
|
expectedGroup = new ArrayList<Integer>();
|
||||||
|
expectedGroup.add(21);
|
||||||
|
expectedGroups.put(new CompoundGroupKey(new GenericGroupKey<String>("3"), new GenericGroupKey<String>("1")), expectedGroup);
|
||||||
|
expectedGroup = new ArrayList<Integer>();
|
||||||
|
expectedGroup.add(-4);
|
||||||
|
expectedGroups.put(new CompoundGroupKey(new GenericGroupKey<String>("4"), new GenericGroupKey<String>("-1")), expectedGroup);
|
||||||
|
|
||||||
|
groupByDimensions.run();
|
||||||
|
Map<GroupKey, Collection<Integer>> groups = receiver.groupedData;
|
||||||
|
for (Entry<GroupKey, Collection<Integer>> expectedGroupEntry : expectedGroups.entrySet()) {
|
||||||
|
Collection<Integer> group = groups.get(expectedGroupEntry.getKey());
|
||||||
|
assertNotNull("No group for key: " + expectedGroupEntry.getKey().asString(), group);
|
||||||
|
assertEquals(expectedGroupEntry.getValue(), group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dimension<Integer, String> createCrossSumDimension() {
|
||||||
|
return new AbstractDimension<Integer, String>("Cross Sum") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(Integer data) {
|
||||||
|
int crossSum = 0;
|
||||||
|
int value = Math.abs(data);
|
||||||
|
while (value > 0) {
|
||||||
|
crossSum += value % 10;
|
||||||
|
value /= 10;
|
||||||
|
}
|
||||||
|
return crossSum + "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private AbstractDimension<Integer, String> createSignumDimension() {
|
||||||
|
return new AbstractDimension<Integer, String>("Signum") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(Integer data) {
|
||||||
|
return ((int) Math.signum(data)) + "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class OpenGrouper<DataType> extends MultiDimensionalGroupingWorker<DataType, String> {
|
||||||
|
|
||||||
|
public OpenGrouper(Collection<Dimension<DataType, String>> dimensions) {
|
||||||
|
super(dimensions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GroupKey createGroupKeyFor(DataType dataEntry, Dimension<DataType, String> dimension) {
|
||||||
|
return new GenericGroupKey<String>(dimension.getDimensionValueFrom(dataEntry));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupKey getGroupKey(DataType dataEntry) {
|
||||||
|
return getGroupKeyFor(dataEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DataReceiver implements WorkReceiver<Map<GroupKey, Collection<Integer>>> {
|
||||||
|
|
||||||
|
public Map<GroupKey, Collection<Integer>> groupedData;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void receiveWork(Map<GroupKey, Collection<Integer>> result) {
|
||||||
|
groupedData = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="con" path="com.google.gwt.eclipse.core.GWT_CONTAINER"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="src" path="resources"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/bin
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>com.sap.sailing.datamining</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand> </buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.pde.PluginNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
<nature>com.google.gwt.eclipse.core.gwtNature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||||
|
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||||
|
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||||
|
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||||
|
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.7
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
pluginProject.extensions=false
|
||||||
|
resolve.requirebundle=false
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Bundle-ManifestVersion: 2
|
||||||
|
Bundle-Name: Datamining
|
||||||
|
Bundle-SymbolicName: com.sap.sailing.datamining
|
||||||
|
Bundle-Version: 1.0.0.qualifier
|
||||||
|
Bundle-Vendor: SAP
|
||||||
|
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||||
|
Bundle-ActivationPolicy: lazy
|
||||||
|
Import-Package: com.google.gwt.i18n.client,
|
||||||
|
com.sap.sailing.server
|
||||||
|
Export-Package: com.sap.sailing.datamining
|
||||||
|
Require-Bundle: com.sap.sailing.domain;bundle-version="1.0.0",
|
||||||
|
com.sap.sailing.domain.common,
|
||||||
|
com.sap.sailing.datamining.shared;bundle-version="1.0.0"
|
||||||
|
Bundle-ClassPath: .
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
source.. = src/,\
|
||||||
|
resources/
|
||||||
|
output.. = bin/
|
||||||
|
bin.includes = META-INF/,\
|
||||||
|
.
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<artifactId>root</artifactId>
|
||||||
|
<groupId>com.sap.sailing</groupId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>com.sap.sailing.datamining</artifactId>
|
||||||
|
<packaging>eclipse-plugin</packaging>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
SimpleTestMessage=Deutsch
|
||||||
|
TestMessageWithParameters=Deutsch {0} - {1}
|
||||||
|
Average=Durchschnitt
|
||||||
|
Median=Median
|
||||||
|
Sum=Summe
|
||||||
|
Distance=Distanz
|
||||||
|
Speed=Geschwindigkeit
|
||||||
|
Meters=Metern
|
||||||
|
Knots=Knoten
|
||||||
|
ResultSignifier={0} ({1})
|
||||||
|
SignifierInUnit={0} in {1}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
SimpleTestMessage=English
|
||||||
|
TestMessageWithParameters=English {0} - {1}
|
||||||
|
Average=Average
|
||||||
|
Median=Median
|
||||||
|
Sum=Sum
|
||||||
|
Distance=Distance
|
||||||
|
Speed=Speed
|
||||||
|
Meters=meters
|
||||||
|
Knots=knots
|
||||||
|
ResultSignifier={0} ({1})
|
||||||
|
SignifierInUnit={0} in {1}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.shared.GroupKey;
|
||||||
|
|
||||||
|
public interface AggregationWorker<ExtractedType, AggregatedType> extends ComponentWorker<Map<GroupKey, AggregatedType>> {
|
||||||
|
|
||||||
|
public void setDataToAggregate(Map<GroupKey, Collection<ExtractedType>> data);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
public interface Cluster<ValueType> {
|
||||||
|
|
||||||
|
public String getName();
|
||||||
|
public ValueType getUpperRange();
|
||||||
|
public ValueType getLowerRange();
|
||||||
|
|
||||||
|
public boolean isInRange(ValueType value, Comparator<ValueType> comparator);
|
||||||
|
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
public interface ClusterOfComparable<ValueType extends Comparable<ValueType>> extends Cluster<ValueType> {
|
||||||
|
|
||||||
|
public boolean isInRange(ValueType value);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.impl.WindStrengthClusterImpl;
|
||||||
|
|
||||||
|
public class Clusters {
|
||||||
|
|
||||||
|
private Clusters() { }
|
||||||
|
|
||||||
|
public static class WindStrength {
|
||||||
|
|
||||||
|
public static WindStrengthCluster VeryLight = new WindStrengthClusterImpl("Very Light", 0.0, 2.5);
|
||||||
|
public static WindStrengthCluster Light = new WindStrengthClusterImpl("Very Light", 2.5, 5.0);
|
||||||
|
public static WindStrengthCluster Medium = new WindStrengthClusterImpl("Very Light", 5.0, 7.5);
|
||||||
|
public static WindStrengthCluster Strong = new WindStrengthClusterImpl("Very Light", 7.5, 10.0);
|
||||||
|
public static WindStrengthCluster VeryStrong = new WindStrengthClusterImpl("Very Light", 10.0, 12.0);
|
||||||
|
public static Collection<WindStrengthCluster> StandardClusters = Arrays.asList(VeryLight, Light, Medium, Strong, VeryStrong);
|
||||||
|
|
||||||
|
private WindStrength() { }
|
||||||
|
|
||||||
|
public static WindStrengthCluster getClusterFor(double windStrengthInBeafort, Collection<WindStrengthCluster> clusters) {
|
||||||
|
List<WindStrengthCluster> sortedClusters = new ArrayList<WindStrengthCluster>(clusters);
|
||||||
|
Collections.sort(sortedClusters, new Comparator<WindStrengthCluster>() {
|
||||||
|
@Override
|
||||||
|
public int compare(WindStrengthCluster cluster1, WindStrengthCluster cluster2) {
|
||||||
|
return cluster1.getUpperRange().compareTo(cluster2.getUpperRange());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (WindStrengthCluster cluster : sortedClusters) {
|
||||||
|
if (cluster.isInRange(windStrengthInBeafort)) {
|
||||||
|
return cluster;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
|
||||||
|
public interface ComponentWorker<ResultType> extends Runnable {
|
||||||
|
|
||||||
|
public void setReceiver(WorkReceiver<ResultType> receiver);
|
||||||
|
|
||||||
|
public boolean isDone();
|
||||||
|
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
public interface ConcurrentFilterCriteria<DataType> {
|
||||||
|
|
||||||
|
public boolean matches(DataType dataEntry);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.factories.AggregatorFactory;
|
||||||
|
import com.sap.sailing.datamining.factories.DataRetrieverFactory;
|
||||||
|
import com.sap.sailing.datamining.factories.ExtractorFactory;
|
||||||
|
import com.sap.sailing.datamining.factories.FilterFactory;
|
||||||
|
import com.sap.sailing.datamining.factories.GrouperFactory;
|
||||||
|
import com.sap.sailing.datamining.i18n.DataMiningResourceBundleManager;
|
||||||
|
import com.sap.sailing.datamining.impl.QueryImpl;
|
||||||
|
import com.sap.sailing.datamining.shared.QueryDefinition;
|
||||||
|
|
||||||
|
public final class DataMiningFactory {
|
||||||
|
|
||||||
|
private static final int THREAD_POOL_SIZE = Math.max(Runtime.getRuntime().availableProcessors(), 3);
|
||||||
|
private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(THREAD_POOL_SIZE, THREAD_POOL_SIZE, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
|
||||||
|
|
||||||
|
private static final DataMiningStringMessages stringMessages = new DataMiningResourceBundleManager(Locale.ENGLISH);
|
||||||
|
|
||||||
|
private DataMiningFactory() { }
|
||||||
|
|
||||||
|
public static <DataType, AggregatedType extends Number> Query<DataType, AggregatedType> createQuery(QueryDefinition queryDefinition) {
|
||||||
|
Locale locale = stringMessages.getLocaleFrom(queryDefinition.getLocaleName());
|
||||||
|
|
||||||
|
ParallelDataRetriever<DataType> retriever = DataRetrieverFactory.createDataRetriever(queryDefinition.getDataType(), executor);
|
||||||
|
|
||||||
|
ParallelFilter<DataType> filter = createFilter(queryDefinition);
|
||||||
|
|
||||||
|
ParallelGrouper<DataType> grouper = GrouperFactory.createGrouper(queryDefinition, executor);
|
||||||
|
ParallelExtractor<DataType, AggregatedType> extractor = ExtractorFactory.createExtractor(stringMessages, locale, queryDefinition.getStatisticType(), executor);
|
||||||
|
ParallelAggregator<AggregatedType, AggregatedType> aggregator = AggregatorFactory.createAggregator(stringMessages, locale, queryDefinition.getStatisticType().getValueType(),
|
||||||
|
queryDefinition.getAggregatorType(), executor);
|
||||||
|
|
||||||
|
return new QueryImpl<DataType, AggregatedType, AggregatedType>(stringMessages, locale, retriever, filter, grouper, extractor, aggregator);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <DataType> ParallelFilter<DataType> createFilter(QueryDefinition queryDefinition) {
|
||||||
|
if (queryDefinition.getSelection().isEmpty()) {
|
||||||
|
return FilterFactory.createNonFilteringFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkerBuilder<FiltrationWorker<DataType>> workerBuilder = FilterFactory.createDimensionFilterBuilder(queryDefinition.getDataType(), queryDefinition.getSelection());
|
||||||
|
return FilterFactory.createParallelFilter(workerBuilder, executor);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.shared.Message;
|
||||||
|
|
||||||
|
public interface DataMiningStringMessages {
|
||||||
|
|
||||||
|
Locale getLocaleFrom(String localeName);
|
||||||
|
|
||||||
|
public String get(String localeName, Message message);
|
||||||
|
public String get(String localeName, Message message, String... parameters);
|
||||||
|
public String get(String localeName, Message message, Message... parameters);
|
||||||
|
|
||||||
|
public String get(Locale locale, Message message);
|
||||||
|
public String get(Locale locale, Message message, String... parameters);
|
||||||
|
public String get(Locale locale, Message message, Message... parameters);
|
||||||
|
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
|
||||||
|
|
||||||
|
public interface DataRetrievalWorker<DataType> extends ComponentWorker<Collection<DataType>> {
|
||||||
|
|
||||||
|
public void setGroup(LeaderboardGroup group);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
|
||||||
|
public interface Dimension<DataType, ValueType> {
|
||||||
|
|
||||||
|
public String getName();
|
||||||
|
|
||||||
|
public ValueType getDimensionValueFrom(DataType dataEntry);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.shared.GroupKey;
|
||||||
|
|
||||||
|
public interface ExtractionWorker<DataType, ExtractedType> extends ComponentWorker<Map<GroupKey, Collection<ExtractedType>>> {
|
||||||
|
|
||||||
|
public void setDataToExtractFrom(Map<GroupKey, Collection<DataType>> data);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public interface FiltrationWorker<DataType> extends ComponentWorker<Collection<DataType>> {
|
||||||
|
|
||||||
|
public void setDataToFilter(Collection<DataType> data);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.shared.GroupKey;
|
||||||
|
|
||||||
|
public interface GroupingWorker<DataType> extends ComponentWorker<Map<GroupKey, Collection<DataType>>> {
|
||||||
|
|
||||||
|
public void setDataToGroup(Collection<DataType> data);
|
||||||
|
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.impl.ParallelComponent;
|
||||||
|
import com.sap.sailing.datamining.shared.GroupKey;
|
||||||
|
|
||||||
|
public interface ParallelAggregator<ExtractedType, AggregatedType> extends ParallelComponent<Map<GroupKey, Collection<ExtractedType>>,
|
||||||
|
Map<GroupKey, AggregatedType>> {
|
||||||
|
|
||||||
|
public String getName();
|
||||||
|
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.impl.ParallelComponent;
|
||||||
|
import com.sap.sailing.server.RacingEventService;
|
||||||
|
|
||||||
|
public interface ParallelDataRetriever<DataType> extends ParallelComponent<RacingEventService, Collection<DataType>> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.impl.ParallelComponent;
|
||||||
|
import com.sap.sailing.datamining.shared.GroupKey;
|
||||||
|
import com.sap.sailing.datamining.shared.Unit;
|
||||||
|
|
||||||
|
public interface ParallelExtractor<DataType, ExtractedType> extends ParallelComponent<Map<GroupKey, Collection<DataType>>,
|
||||||
|
Map<GroupKey, Collection<ExtractedType>>> {
|
||||||
|
|
||||||
|
public Unit getUnit();
|
||||||
|
|
||||||
|
public int getValueDecimals();
|
||||||
|
|
||||||
|
public String getSignifier();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.impl.ParallelComponent;
|
||||||
|
|
||||||
|
public interface ParallelFilter<DataType> extends ParallelComponent<Collection<DataType>, Collection<DataType>> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.impl.ParallelComponent;
|
||||||
|
import com.sap.sailing.datamining.shared.GroupKey;
|
||||||
|
|
||||||
|
public interface ParallelGrouper<DataType> extends ParallelComponent<Collection<DataType>, Map<GroupKey, Collection<DataType>>> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.shared.QueryResult;
|
||||||
|
import com.sap.sailing.server.RacingEventService;
|
||||||
|
|
||||||
|
public interface Query<DataType, AggregatedType> {
|
||||||
|
|
||||||
|
public QueryResult<AggregatedType> run(RacingEventService racingEventService) throws InterruptedException, ExecutionException;
|
||||||
|
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
public interface WindStrengthCluster extends ClusterOfComparable<Double> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
public interface WorkReceiver<ResultType> {
|
||||||
|
|
||||||
|
public void receiveWork(ResultType result);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.sap.sailing.datamining;
|
||||||
|
|
||||||
|
|
||||||
|
public interface WorkerBuilder<WorkerType> {
|
||||||
|
|
||||||
|
public WorkerType build();
|
||||||
|
|
||||||
|
}
|
||||||
+64
@@ -0,0 +1,64 @@
|
|||||||
|
package com.sap.sailing.datamining.builders;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.AggregationWorker;
|
||||||
|
import com.sap.sailing.datamining.WorkerBuilder;
|
||||||
|
import com.sap.sailing.datamining.impl.aggregators.SimpleDoubleArithmeticAverageAggregationWorker;
|
||||||
|
import com.sap.sailing.datamining.impl.aggregators.SimpleDoubleMedianAggregationWorker;
|
||||||
|
import com.sap.sailing.datamining.impl.aggregators.SimpleIntegerArithmeticAverageAggregationWorker;
|
||||||
|
import com.sap.sailing.datamining.impl.aggregators.SimpleIntegerMedianAggregationWorker;
|
||||||
|
import com.sap.sailing.datamining.impl.aggregators.SumAggregationWorker;
|
||||||
|
import com.sap.sailing.datamining.impl.aggregators.helpers.SimpleDoubleSumAggregator;
|
||||||
|
import com.sap.sailing.datamining.impl.aggregators.helpers.SimpleIntegerSumAggregator;
|
||||||
|
import com.sap.sailing.datamining.shared.Components.AggregatorType;
|
||||||
|
import com.sap.sailing.datamining.shared.Components.ValueType;
|
||||||
|
|
||||||
|
public class AggregationWorkerBuilder<ExtractedType, AggregatedType> implements WorkerBuilder<AggregationWorker<ExtractedType, AggregatedType>> {
|
||||||
|
|
||||||
|
private ValueType valueType;
|
||||||
|
private AggregatorType aggregatorType;
|
||||||
|
|
||||||
|
public AggregationWorkerBuilder(ValueType valueType, AggregatorType aggregatorType) {
|
||||||
|
this.valueType = valueType;
|
||||||
|
this.aggregatorType = aggregatorType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public AggregationWorker<ExtractedType, AggregatedType> build() {
|
||||||
|
switch (valueType) {
|
||||||
|
case Double:
|
||||||
|
return (AggregationWorker<ExtractedType, AggregatedType>) createDoubleAggregationWorker(aggregatorType);
|
||||||
|
case Integer:
|
||||||
|
return (AggregationWorker<ExtractedType, AggregatedType>) createIntegerAggregationWorker(aggregatorType);
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Not yet implemented for the given statistics value type: "
|
||||||
|
+ valueType.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AggregationWorker<Integer, Integer> createIntegerAggregationWorker(AggregatorType aggregatorType) {
|
||||||
|
switch (aggregatorType) {
|
||||||
|
case Average:
|
||||||
|
return new SimpleIntegerArithmeticAverageAggregationWorker();
|
||||||
|
case Sum:
|
||||||
|
return new SumAggregationWorker<Integer, Integer>(new SimpleIntegerSumAggregator());
|
||||||
|
case Median:
|
||||||
|
return new SimpleIntegerMedianAggregationWorker();
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Not yet implemented for the given aggregator type: "
|
||||||
|
+ aggregatorType.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AggregationWorker<Double, Double> createDoubleAggregationWorker(AggregatorType aggregatorType) {
|
||||||
|
switch (aggregatorType) {
|
||||||
|
case Average:
|
||||||
|
return new SimpleDoubleArithmeticAverageAggregationWorker();
|
||||||
|
case Sum:
|
||||||
|
return new SumAggregationWorker<Double, Double>(new SimpleDoubleSumAggregator());
|
||||||
|
case Median:
|
||||||
|
return new SimpleDoubleMedianAggregationWorker();
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Not yet implemented for the given aggregator type: "
|
||||||
|
+ aggregatorType.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
package com.sap.sailing.datamining.builders;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.DataRetrievalWorker;
|
||||||
|
import com.sap.sailing.datamining.WorkerBuilder;
|
||||||
|
import com.sap.sailing.datamining.impl.gps_fix.GPSFixLeaderboardGroupDataRetrievalWorker;
|
||||||
|
import com.sap.sailing.datamining.impl.tracked_leg_of_competitor.TrackedLegOfCompetitorLeaderboardGroupDataRetrievalWorker;
|
||||||
|
import com.sap.sailing.datamining.shared.DataTypes;
|
||||||
|
|
||||||
|
public class DataRetrieverWorkerBuilder<DataType> implements WorkerBuilder<DataRetrievalWorker<DataType>> {
|
||||||
|
|
||||||
|
private final DataTypes dataType;
|
||||||
|
|
||||||
|
public DataRetrieverWorkerBuilder(DataTypes dataType) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public DataRetrievalWorker<DataType> build() {
|
||||||
|
switch (dataType) {
|
||||||
|
case GPSFix:
|
||||||
|
return (DataRetrievalWorker<DataType>) new GPSFixLeaderboardGroupDataRetrievalWorker();
|
||||||
|
case TrackedLegOfCompetitor:
|
||||||
|
return (DataRetrievalWorker<DataType>) new TrackedLegOfCompetitorLeaderboardGroupDataRetrievalWorker();
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Not yet implemented for the given data type: " + dataType.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
package com.sap.sailing.datamining.builders;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.ExtractionWorker;
|
||||||
|
import com.sap.sailing.datamining.WorkerBuilder;
|
||||||
|
import com.sap.sailing.datamining.impl.SpeedInKnotsExtractionWorker;
|
||||||
|
import com.sap.sailing.datamining.impl.tracked_leg_of_competitor.DistanceTraveledExtractionWorker;
|
||||||
|
import com.sap.sailing.datamining.shared.Components.StatisticType;
|
||||||
|
|
||||||
|
public class ExtractionWorkerBuilder<DataType, ExtractedType> implements WorkerBuilder<ExtractionWorker<DataType, ExtractedType>> {
|
||||||
|
|
||||||
|
private StatisticType statisticType;
|
||||||
|
|
||||||
|
public ExtractionWorkerBuilder(StatisticType statisticType) {
|
||||||
|
this.statisticType = statisticType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public ExtractionWorker<DataType, ExtractedType> build() {
|
||||||
|
switch (statisticType) {
|
||||||
|
case Speed:
|
||||||
|
return (ExtractionWorker<DataType, ExtractedType>) new SpeedInKnotsExtractionWorker();
|
||||||
|
case Distance:
|
||||||
|
return (ExtractionWorker<DataType, ExtractedType>) new DistanceTraveledExtractionWorker();
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Not yet implemented for the given statistic type: "
|
||||||
|
+ statisticType.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
package com.sap.sailing.datamining.builders;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.ConcurrentFilterCriteria;
|
||||||
|
import com.sap.sailing.datamining.FiltrationWorker;
|
||||||
|
import com.sap.sailing.datamining.WorkerBuilder;
|
||||||
|
import com.sap.sailing.datamining.impl.CriteriaFiltrationWorker;
|
||||||
|
|
||||||
|
public class FilterByCriteriaBuilder<DataType> implements WorkerBuilder<FiltrationWorker<DataType>> {
|
||||||
|
|
||||||
|
private ConcurrentFilterCriteria<DataType> criteria;
|
||||||
|
|
||||||
|
public FilterByCriteriaBuilder(ConcurrentFilterCriteria<DataType> criteria) {
|
||||||
|
this.criteria = criteria;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FiltrationWorker<DataType> build() {
|
||||||
|
return new CriteriaFiltrationWorker<DataType>(criteria);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
package com.sap.sailing.datamining.builders;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.Dimension;
|
||||||
|
import com.sap.sailing.datamining.GroupingWorker;
|
||||||
|
import com.sap.sailing.datamining.WorkerBuilder;
|
||||||
|
import com.sap.sailing.datamining.impl.MultiDimensionalGroupingWorker;
|
||||||
|
|
||||||
|
public class MultiDimensionalGroupingWorkerBuilder<DataType, ValueType> implements WorkerBuilder<GroupingWorker<DataType>> {
|
||||||
|
|
||||||
|
private Collection<Dimension<DataType, ValueType>> dimensions;
|
||||||
|
|
||||||
|
public MultiDimensionalGroupingWorkerBuilder(Collection<Dimension<DataType, ValueType>> dimensions) {
|
||||||
|
this.dimensions = dimensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GroupingWorker<DataType> build() {
|
||||||
|
return new MultiDimensionalGroupingWorker<DataType, ValueType>(dimensions);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.sap.sailing.datamining.data;
|
||||||
|
|
||||||
|
public interface GPSFixContext extends TrackedLegOfCompetitorContext {
|
||||||
|
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
package com.sap.sailing.datamining.data;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.WindStrengthCluster;
|
||||||
|
import com.sap.sailing.domain.common.LegType;
|
||||||
|
import com.sap.sailing.domain.tracking.GPSFixMoving;
|
||||||
|
|
||||||
|
public interface GPSFixWithContext extends GPSFixMoving {
|
||||||
|
|
||||||
|
public String getRegattaName();
|
||||||
|
public String getRaceName();
|
||||||
|
public int getLegNumber();
|
||||||
|
public String getCourseAreaName();
|
||||||
|
public String getFleetName();
|
||||||
|
public String getBoatClassName();
|
||||||
|
/**
|
||||||
|
* The year of the start of the race.
|
||||||
|
*/
|
||||||
|
public Integer getYear();
|
||||||
|
/**
|
||||||
|
* The leg type of the leg, which contains this gps fix. Can be <code>null</code> if there's no wind in the race.
|
||||||
|
*/
|
||||||
|
public LegType getLegType();
|
||||||
|
public String getCompetitorName();
|
||||||
|
public String getCompetitorSailID();
|
||||||
|
public String getCompetitorNationality();
|
||||||
|
public WindStrengthCluster getWindStrength();
|
||||||
|
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
package com.sap.sailing.datamining.data;
|
||||||
|
|
||||||
|
import com.sap.sailing.domain.base.CourseArea;
|
||||||
|
import com.sap.sailing.domain.base.Fleet;
|
||||||
|
import com.sap.sailing.domain.common.LegType;
|
||||||
|
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||||
|
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
|
||||||
|
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||||
|
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||||
|
|
||||||
|
public interface TrackedLegContext {
|
||||||
|
|
||||||
|
public LeaderboardGroup getLeaderboardGroup();
|
||||||
|
public Leaderboard getLeaderboard();
|
||||||
|
public CourseArea getCourseArea();
|
||||||
|
public Fleet getFleet();
|
||||||
|
public TrackedRace getTrackedRace();
|
||||||
|
public TrackedLeg getTrackedLeg();
|
||||||
|
public LegType getLegType();
|
||||||
|
public int getLegNumber();
|
||||||
|
public Integer getYear();
|
||||||
|
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package com.sap.sailing.datamining.data;
|
||||||
|
|
||||||
|
import com.sap.sailing.domain.base.Competitor;
|
||||||
|
|
||||||
|
public interface TrackedLegOfCompetitorContext extends TrackedLegContext {
|
||||||
|
|
||||||
|
public Competitor getCompetitor();
|
||||||
|
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package com.sap.sailing.datamining.data;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.WindStrengthCluster;
|
||||||
|
import com.sap.sailing.domain.common.Distance;
|
||||||
|
import com.sap.sailing.domain.common.LegType;
|
||||||
|
|
||||||
|
public interface TrackedLegOfCompetitorWithContext {
|
||||||
|
|
||||||
|
public String getRegattaName();
|
||||||
|
public String getRaceName();
|
||||||
|
public int getLegNumber();
|
||||||
|
public String getCourseAreaName();
|
||||||
|
public String getFleetName();
|
||||||
|
public String getBoatClassName();
|
||||||
|
/**
|
||||||
|
* The year of the start of the race.
|
||||||
|
*/
|
||||||
|
public Integer getYear();
|
||||||
|
public LegType getLegType();
|
||||||
|
public String getCompetitorName();
|
||||||
|
public String getCompetitorSailID();
|
||||||
|
public String getCompetitorNationality();
|
||||||
|
public WindStrengthCluster getWindStrength();
|
||||||
|
public Distance getDistanceTraveled();
|
||||||
|
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package com.sap.sailing.datamining.data.impl;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.data.GPSFixContext;
|
||||||
|
import com.sap.sailing.datamining.data.TrackedLegOfCompetitorContext;
|
||||||
|
import com.sap.sailing.domain.base.Competitor;
|
||||||
|
import com.sap.sailing.domain.base.CourseArea;
|
||||||
|
import com.sap.sailing.domain.base.Fleet;
|
||||||
|
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||||
|
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
|
||||||
|
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||||
|
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||||
|
|
||||||
|
public class GPSFixContextImpl extends TrackedLegOfCompetitorContextImpl implements GPSFixContext {
|
||||||
|
|
||||||
|
public GPSFixContextImpl(LeaderboardGroup leaderboardGroup, Leaderboard leaderboard, CourseArea courseArea,
|
||||||
|
Fleet fleet, TrackedRace trackedRace, TrackedLeg trackedLeg, int legNumber, Competitor competitor) {
|
||||||
|
super(leaderboardGroup, leaderboard, courseArea, fleet, trackedRace, trackedLeg, legNumber, competitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GPSFixContextImpl(TrackedLegOfCompetitorContext baseContext) {
|
||||||
|
this(baseContext.getLeaderboardGroup(), baseContext.getLeaderboard(), baseContext.getCourseArea(), baseContext.getFleet(),
|
||||||
|
baseContext.getTrackedRace(), baseContext.getTrackedLeg(), baseContext.getLegNumber(),
|
||||||
|
baseContext.getCompetitor());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+128
@@ -0,0 +1,128 @@
|
|||||||
|
package com.sap.sailing.datamining.data.impl;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.data.TrackedLegContext;
|
||||||
|
import com.sap.sailing.domain.base.CourseArea;
|
||||||
|
import com.sap.sailing.domain.base.Fleet;
|
||||||
|
import com.sap.sailing.domain.common.LegType;
|
||||||
|
import com.sap.sailing.domain.common.NoWindException;
|
||||||
|
import com.sap.sailing.domain.common.TimePoint;
|
||||||
|
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
|
||||||
|
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||||
|
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
|
||||||
|
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||||
|
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||||
|
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||||
|
|
||||||
|
public class TrackedLegContextImpl implements TrackedLegContext {
|
||||||
|
|
||||||
|
private LeaderboardGroup leaderboardGroup;
|
||||||
|
private Leaderboard leaderboard;
|
||||||
|
private CourseArea courseArea;
|
||||||
|
private Fleet fleet;
|
||||||
|
private TrackedRace trackedRace;
|
||||||
|
private TrackedLeg trackedLeg;
|
||||||
|
private LegType legType;
|
||||||
|
private int legNumber;
|
||||||
|
private Integer year;
|
||||||
|
|
||||||
|
private boolean legTypeHasBeenInitialized;
|
||||||
|
private boolean yearHasBeenInitialized;
|
||||||
|
|
||||||
|
public TrackedLegContextImpl(LeaderboardGroup leaderboardGroup, Leaderboard leaderboard, CourseArea courseArea, Fleet fleet,
|
||||||
|
TrackedRace trackedRace, TrackedLeg trackedLeg, int legNumber) {
|
||||||
|
this.leaderboardGroup = leaderboardGroup;
|
||||||
|
this.leaderboard = leaderboard;
|
||||||
|
this.courseArea = courseArea;
|
||||||
|
this.fleet = fleet;
|
||||||
|
this.trackedRace = trackedRace;
|
||||||
|
this.trackedLeg = trackedLeg;
|
||||||
|
this.legNumber = legNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LeaderboardGroup getLeaderboardGroup() {
|
||||||
|
return leaderboardGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Leaderboard getLeaderboard() {
|
||||||
|
return leaderboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CourseArea getCourseArea() {
|
||||||
|
return courseArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fleet getFleet() {
|
||||||
|
return fleet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TrackedRace getTrackedRace() {
|
||||||
|
return trackedRace;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TrackedLeg getTrackedLeg() {
|
||||||
|
return trackedLeg;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LegType getLegType() {
|
||||||
|
if (!legTypeHasBeenInitialized) {
|
||||||
|
initializeLegType();
|
||||||
|
}
|
||||||
|
return legType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLegNumber() {
|
||||||
|
return legNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getYear() {
|
||||||
|
if (!yearHasBeenInitialized) {
|
||||||
|
initializeYear();
|
||||||
|
}
|
||||||
|
return year;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeLegType() {
|
||||||
|
try {
|
||||||
|
legType = getTrackedLeg() == null ? null : getTrackedLeg().getLegType(getTimePointForLegType());
|
||||||
|
} catch (NoWindException e) {
|
||||||
|
legType = null;
|
||||||
|
}
|
||||||
|
legTypeHasBeenInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TimePoint getTimePointForLegType() {
|
||||||
|
TimePoint at = null;
|
||||||
|
for (TrackedLegOfCompetitor trackedLegOfCompetitor : getTrackedLeg().getTrackedLegsOfCompetitors()) {
|
||||||
|
TimePoint start = trackedLegOfCompetitor.getStartTime();
|
||||||
|
TimePoint finish = trackedLegOfCompetitor.getFinishTime();
|
||||||
|
if (start != null && finish != null) {
|
||||||
|
at = new MillisecondsTimePoint((start.asMillis() + finish.asMillis()) / 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return at;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeYear() {
|
||||||
|
TimePoint time = getTrackedRace().getStartOfRace() != null ? getTrackedRace().getStartOfRace() : getTrackedRace().getStartOfTracking();
|
||||||
|
if (time == null) {
|
||||||
|
year = 0;
|
||||||
|
}
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.setTime(time.asDate());
|
||||||
|
year = calendar.get(Calendar.YEAR);
|
||||||
|
yearHasBeenInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
package com.sap.sailing.datamining.data.impl;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.data.TrackedLegContext;
|
||||||
|
import com.sap.sailing.datamining.data.TrackedLegOfCompetitorContext;
|
||||||
|
import com.sap.sailing.domain.base.Competitor;
|
||||||
|
import com.sap.sailing.domain.base.CourseArea;
|
||||||
|
import com.sap.sailing.domain.base.Fleet;
|
||||||
|
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||||
|
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
|
||||||
|
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||||
|
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||||
|
|
||||||
|
public class TrackedLegOfCompetitorContextImpl extends TrackedLegContextImpl implements TrackedLegOfCompetitorContext {
|
||||||
|
|
||||||
|
private Competitor competitor;
|
||||||
|
|
||||||
|
public TrackedLegOfCompetitorContextImpl(LeaderboardGroup leaderboardGroup, Leaderboard leaderboard,
|
||||||
|
CourseArea courseArea, Fleet fleet, TrackedRace trackedRace, TrackedLeg trackedLeg, int legNumber, Competitor competitor) {
|
||||||
|
super(leaderboardGroup, leaderboard, courseArea, fleet, trackedRace, trackedLeg, legNumber);
|
||||||
|
this.competitor = competitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackedLegOfCompetitorContextImpl(TrackedLegContext trackedLegContext, Competitor competitor) {
|
||||||
|
this(trackedLegContext.getLeaderboardGroup(), trackedLegContext.getLeaderboard(), trackedLegContext.getCourseArea(),
|
||||||
|
trackedLegContext.getFleet(), trackedLegContext.getTrackedRace(), trackedLegContext.getTrackedLeg(), trackedLegContext.getLegNumber(),
|
||||||
|
competitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Competitor getCompetitor() {
|
||||||
|
return competitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package com.sap.sailing.datamining.dimensions;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.Dimension;
|
||||||
|
import com.sap.sailing.datamining.shared.DimensionIdentifier;
|
||||||
|
|
||||||
|
public interface DimensionManager<DataType> {
|
||||||
|
|
||||||
|
public Dimension<DataType, ?> getDimensionFor(DimensionIdentifier sharedDimension);
|
||||||
|
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package com.sap.sailing.datamining.dimensions;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.data.GPSFixWithContext;
|
||||||
|
import com.sap.sailing.datamining.data.TrackedLegOfCompetitorWithContext;
|
||||||
|
import com.sap.sailing.datamining.shared.DataTypes;
|
||||||
|
|
||||||
|
public final class DimensionManagerProvider {
|
||||||
|
|
||||||
|
private DimensionManagerProvider() { }
|
||||||
|
|
||||||
|
private static final DimensionManager<GPSFixWithContext> GPSFixDimensionManager = new GPSFixDimensionManager();
|
||||||
|
private static final DimensionManager<TrackedLegOfCompetitorWithContext> TrackedLegOfCompetitorDimensionManager = new TrackedLegOfCompetitorDimensionManager();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <DataType> DimensionManager<DataType> getDimensionManagerFor(DataTypes dataType) {
|
||||||
|
switch (dataType) {
|
||||||
|
case GPSFix:
|
||||||
|
return (DimensionManager<DataType>) GPSFixDimensionManager;
|
||||||
|
case TrackedLegOfCompetitor:
|
||||||
|
return (DimensionManager<DataType>) TrackedLegOfCompetitorDimensionManager;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Not yet implemented for the given data type: "
|
||||||
|
+ dataType.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+133
@@ -0,0 +1,133 @@
|
|||||||
|
package com.sap.sailing.datamining.dimensions;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.Dimension;
|
||||||
|
import com.sap.sailing.datamining.data.GPSFixWithContext;
|
||||||
|
import com.sap.sailing.datamining.impl.AbstractDimension;
|
||||||
|
import com.sap.sailing.datamining.shared.DimensionIdentifier;
|
||||||
|
import com.sap.sailing.domain.common.LegType;
|
||||||
|
|
||||||
|
public final class GPSFixDimensionManager implements DimensionManager<GPSFixWithContext> {
|
||||||
|
|
||||||
|
public GPSFixDimensionManager() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The dimension for the given dimension type. Throws an exception, if the used <code>ValueType</code> doesn't match the <code>ValueType</code> of the returning dimension.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Dimension<GPSFixWithContext, ?> getDimensionFor(DimensionIdentifier dimension) {
|
||||||
|
switch (dimension) {
|
||||||
|
case BoatClassName:
|
||||||
|
return BoatClassNameDimension;
|
||||||
|
case CompetitorName:
|
||||||
|
return CompetitorNameDimension;
|
||||||
|
case CourseAreaName:
|
||||||
|
return CourseAreaNameDimension;
|
||||||
|
case FleetName:
|
||||||
|
return FleetNameDimension;
|
||||||
|
case LegNumber:
|
||||||
|
return LegNumberDimension;
|
||||||
|
case LegType:
|
||||||
|
return LegTypeDimension;
|
||||||
|
case Nationality:
|
||||||
|
return NationalityDimension;
|
||||||
|
case RaceName:
|
||||||
|
return RaceNameDimension;
|
||||||
|
case RegattaName:
|
||||||
|
return RegattaNameDimension;
|
||||||
|
case SailID:
|
||||||
|
return SailIDDimension;
|
||||||
|
case WindStrength:
|
||||||
|
return WindStrengthDimension;
|
||||||
|
case Year:
|
||||||
|
return YearDimension;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Not yet implemented for the given dimension: "
|
||||||
|
+ dimension.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static Dimension<GPSFixWithContext, String> RegattaNameDimension = new AbstractDimension<GPSFixWithContext, String>("Regatta") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(GPSFixWithContext data) {
|
||||||
|
return data.getRegattaName();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<GPSFixWithContext, String> RaceNameDimension = new AbstractDimension<GPSFixWithContext, String>("Race") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(GPSFixWithContext data) {
|
||||||
|
return data.getRaceName();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<GPSFixWithContext, Integer> LegNumberDimension = new AbstractDimension<GPSFixWithContext, Integer>("Leg Number") {
|
||||||
|
@Override
|
||||||
|
public Integer getDimensionValueFrom(GPSFixWithContext data) {
|
||||||
|
return data.getLegNumber();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<GPSFixWithContext, String> CourseAreaNameDimension = new AbstractDimension<GPSFixWithContext, String>("Course Area") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(GPSFixWithContext data) {
|
||||||
|
return data.getCourseAreaName();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<GPSFixWithContext, String> FleetNameDimension = new AbstractDimension<GPSFixWithContext, String>("Fleet") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(GPSFixWithContext data) {
|
||||||
|
return data.getFleetName();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<GPSFixWithContext, String> BoatClassNameDimension = new AbstractDimension<GPSFixWithContext, String>("Boat Class") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(GPSFixWithContext data) {
|
||||||
|
return data.getBoatClassName();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<GPSFixWithContext, Integer> YearDimension = new AbstractDimension<GPSFixWithContext, Integer>("Year") {
|
||||||
|
@Override
|
||||||
|
public Integer getDimensionValueFrom(GPSFixWithContext data) {
|
||||||
|
return data.getYear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<GPSFixWithContext, LegType> LegTypeDimension = new AbstractDimension<GPSFixWithContext, LegType>("Leg Type") {
|
||||||
|
@Override
|
||||||
|
public LegType getDimensionValueFrom(GPSFixWithContext data) {
|
||||||
|
return data.getLegType();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<GPSFixWithContext, String> CompetitorNameDimension = new AbstractDimension<GPSFixWithContext, String>("Competitor") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(GPSFixWithContext data) {
|
||||||
|
return data.getCompetitorName();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<GPSFixWithContext, String> SailIDDimension = new AbstractDimension<GPSFixWithContext, String>("Sail ID") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(GPSFixWithContext data) {
|
||||||
|
return data.getCompetitorSailID();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<GPSFixWithContext, String> NationalityDimension = new AbstractDimension<GPSFixWithContext, String>("Nationality") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(GPSFixWithContext data) {
|
||||||
|
return data.getCompetitorNationality();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//TODO after new clusters
|
||||||
|
public final static Dimension<GPSFixWithContext, String> WindStrengthDimension = new AbstractDimension<GPSFixWithContext, String>("Wind Strength") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(GPSFixWithContext data) {
|
||||||
|
return data.getWindStrength().getName();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
+132
@@ -0,0 +1,132 @@
|
|||||||
|
package com.sap.sailing.datamining.dimensions;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.Dimension;
|
||||||
|
import com.sap.sailing.datamining.data.TrackedLegOfCompetitorWithContext;
|
||||||
|
import com.sap.sailing.datamining.impl.AbstractDimension;
|
||||||
|
import com.sap.sailing.datamining.shared.DimensionIdentifier;
|
||||||
|
import com.sap.sailing.domain.common.LegType;
|
||||||
|
|
||||||
|
public final class TrackedLegOfCompetitorDimensionManager implements DimensionManager<TrackedLegOfCompetitorWithContext> {
|
||||||
|
|
||||||
|
public TrackedLegOfCompetitorDimensionManager() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The dimension for the given dimension type. Throws an exception, if the used <code>ValueType</code> doesn't match the <code>ValueType</code> of the returning dimension.
|
||||||
|
*/
|
||||||
|
public Dimension<TrackedLegOfCompetitorWithContext, ?> getDimensionFor(DimensionIdentifier dimension) {
|
||||||
|
switch (dimension) {
|
||||||
|
case BoatClassName:
|
||||||
|
return BoatClassNameDimension;
|
||||||
|
case CompetitorName:
|
||||||
|
return CompetitorNameDimension;
|
||||||
|
case CourseAreaName:
|
||||||
|
return CourseAreaNameDimension;
|
||||||
|
case FleetName:
|
||||||
|
return FleetNameDimension;
|
||||||
|
case LegNumber:
|
||||||
|
return LegNumberDimension;
|
||||||
|
case LegType:
|
||||||
|
return LegTypeDimension;
|
||||||
|
case Nationality:
|
||||||
|
return NationalityDimension;
|
||||||
|
case RaceName:
|
||||||
|
return RaceNameDimension;
|
||||||
|
case RegattaName:
|
||||||
|
return RegattaNameDimension;
|
||||||
|
case SailID:
|
||||||
|
return SailIDDimension;
|
||||||
|
case WindStrength:
|
||||||
|
return WindStrengthDimension;
|
||||||
|
case Year:
|
||||||
|
return YearDimension;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Not yet implemented for the given dimension: "
|
||||||
|
+ dimension.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static Dimension<TrackedLegOfCompetitorWithContext, String> RegattaNameDimension = new AbstractDimension<TrackedLegOfCompetitorWithContext, String>("Regatta") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(TrackedLegOfCompetitorWithContext data) {
|
||||||
|
return data.getRegattaName();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<TrackedLegOfCompetitorWithContext, String> RaceNameDimension = new AbstractDimension<TrackedLegOfCompetitorWithContext, String>("Race") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(TrackedLegOfCompetitorWithContext data) {
|
||||||
|
return data.getRaceName();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<TrackedLegOfCompetitorWithContext, Integer> LegNumberDimension = new AbstractDimension<TrackedLegOfCompetitorWithContext, Integer>("Leg Number") {
|
||||||
|
@Override
|
||||||
|
public Integer getDimensionValueFrom(TrackedLegOfCompetitorWithContext data) {
|
||||||
|
return data.getLegNumber();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<TrackedLegOfCompetitorWithContext, String> CourseAreaNameDimension = new AbstractDimension<TrackedLegOfCompetitorWithContext, String>("Course Area") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(TrackedLegOfCompetitorWithContext data) {
|
||||||
|
return data.getCourseAreaName();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<TrackedLegOfCompetitorWithContext, String> FleetNameDimension = new AbstractDimension<TrackedLegOfCompetitorWithContext, String>("Fleet") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(TrackedLegOfCompetitorWithContext data) {
|
||||||
|
return data.getFleetName();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<TrackedLegOfCompetitorWithContext, String> BoatClassNameDimension = new AbstractDimension<TrackedLegOfCompetitorWithContext, String>("Boat Class") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(TrackedLegOfCompetitorWithContext data) {
|
||||||
|
return data.getBoatClassName();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<TrackedLegOfCompetitorWithContext, Integer> YearDimension = new AbstractDimension<TrackedLegOfCompetitorWithContext, Integer>("Year") {
|
||||||
|
@Override
|
||||||
|
public Integer getDimensionValueFrom(TrackedLegOfCompetitorWithContext data) {
|
||||||
|
return data.getYear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<TrackedLegOfCompetitorWithContext, LegType> LegTypeDimension = new AbstractDimension<TrackedLegOfCompetitorWithContext, LegType>("Leg Type") {
|
||||||
|
@Override
|
||||||
|
public LegType getDimensionValueFrom(TrackedLegOfCompetitorWithContext data) {
|
||||||
|
return data.getLegType();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<TrackedLegOfCompetitorWithContext, String> CompetitorNameDimension = new AbstractDimension<TrackedLegOfCompetitorWithContext, String>("Competitor") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(TrackedLegOfCompetitorWithContext data) {
|
||||||
|
return data.getCompetitorName();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<TrackedLegOfCompetitorWithContext, String> SailIDDimension = new AbstractDimension<TrackedLegOfCompetitorWithContext, String>("Sail ID") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(TrackedLegOfCompetitorWithContext data) {
|
||||||
|
return data.getCompetitorSailID();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final static Dimension<TrackedLegOfCompetitorWithContext, String> NationalityDimension = new AbstractDimension<TrackedLegOfCompetitorWithContext, String>("Nationality") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(TrackedLegOfCompetitorWithContext data) {
|
||||||
|
return data.getCompetitorNationality();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//TODO after new clusters
|
||||||
|
public final static Dimension<TrackedLegOfCompetitorWithContext, String> WindStrengthDimension = new AbstractDimension<TrackedLegOfCompetitorWithContext, String>("Wind Strength") {
|
||||||
|
@Override
|
||||||
|
public String getDimensionValueFrom(TrackedLegOfCompetitorWithContext data) {
|
||||||
|
return data.getWindStrength().getName();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package com.sap.sailing.datamining.factories;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.AggregationWorker;
|
||||||
|
import com.sap.sailing.datamining.DataMiningStringMessages;
|
||||||
|
import com.sap.sailing.datamining.ParallelAggregator;
|
||||||
|
import com.sap.sailing.datamining.WorkerBuilder;
|
||||||
|
import com.sap.sailing.datamining.builders.AggregationWorkerBuilder;
|
||||||
|
import com.sap.sailing.datamining.impl.GroupDividingParallelAggregator;
|
||||||
|
import com.sap.sailing.datamining.shared.Components.AggregatorType;
|
||||||
|
import com.sap.sailing.datamining.shared.Components.ValueType;
|
||||||
|
|
||||||
|
public final class AggregatorFactory {
|
||||||
|
|
||||||
|
private AggregatorFactory() { }
|
||||||
|
|
||||||
|
public static <ExtractedType, AggregatedType> ParallelAggregator<ExtractedType, AggregatedType> createAggregator(DataMiningStringMessages stringMessages,
|
||||||
|
Locale locale,
|
||||||
|
ValueType valueType, AggregatorType aggregatorType, ThreadPoolExecutor executor) {
|
||||||
|
WorkerBuilder<AggregationWorker<ExtractedType, AggregatedType>> workerBuilder = new AggregationWorkerBuilder<ExtractedType, AggregatedType>(valueType, aggregatorType);
|
||||||
|
return new GroupDividingParallelAggregator<ExtractedType, AggregatedType>(stringMessages.get(locale, aggregatorType.getNameMessage()), workerBuilder, executor);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
package com.sap.sailing.datamining.factories;
|
||||||
|
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.ParallelDataRetriever;
|
||||||
|
import com.sap.sailing.datamining.DataRetrievalWorker;
|
||||||
|
import com.sap.sailing.datamining.WorkerBuilder;
|
||||||
|
import com.sap.sailing.datamining.builders.DataRetrieverWorkerBuilder;
|
||||||
|
import com.sap.sailing.datamining.impl.GroupDividingParallelDataRetriever;
|
||||||
|
import com.sap.sailing.datamining.shared.DataTypes;
|
||||||
|
|
||||||
|
public final class DataRetrieverFactory {
|
||||||
|
|
||||||
|
private DataRetrieverFactory() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a retriever for the given data type. Throws an exception, if the used <code>DataType</code> doesn't match
|
||||||
|
* the <code>DataType</code> of the returning retriever.
|
||||||
|
* @param racingService
|
||||||
|
*/
|
||||||
|
public static <DataType> ParallelDataRetriever<DataType> createDataRetriever(DataTypes dataType, ThreadPoolExecutor executor) {
|
||||||
|
WorkerBuilder<DataRetrievalWorker<DataType>> workerBuilder = new DataRetrieverWorkerBuilder<DataType>(dataType);
|
||||||
|
return new GroupDividingParallelDataRetriever<DataType>(workerBuilder, executor);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
package com.sap.sailing.datamining.factories;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.DataMiningStringMessages;
|
||||||
|
import com.sap.sailing.datamining.ExtractionWorker;
|
||||||
|
import com.sap.sailing.datamining.ParallelExtractor;
|
||||||
|
import com.sap.sailing.datamining.WorkerBuilder;
|
||||||
|
import com.sap.sailing.datamining.builders.ExtractionWorkerBuilder;
|
||||||
|
import com.sap.sailing.datamining.impl.GroupDividingParallelExtractor;
|
||||||
|
import com.sap.sailing.datamining.shared.Message;
|
||||||
|
import com.sap.sailing.datamining.shared.Unit;
|
||||||
|
import com.sap.sailing.datamining.shared.Components.StatisticType;
|
||||||
|
|
||||||
|
public final class ExtractorFactory {
|
||||||
|
|
||||||
|
private ExtractorFactory() { }
|
||||||
|
|
||||||
|
public static <DataType, ExtractedType extends Number> ParallelExtractor<DataType, ExtractedType> createExtractor(DataMiningStringMessages stringMessages, Locale locale,
|
||||||
|
StatisticType statisticType, ThreadPoolExecutor executor) {
|
||||||
|
WorkerBuilder<ExtractionWorker<DataType, ExtractedType>> workerBuilder = new ExtractionWorkerBuilder<DataType, ExtractedType>(statisticType);
|
||||||
|
String signifier = statisticType.getUnit() == Unit.None ? stringMessages.get(locale, statisticType.getSignifierMessage()) :
|
||||||
|
stringMessages.get(locale, Message.SignifierInUnit, statisticType.getSignifierMessage(), statisticType.getUnitMessage());
|
||||||
|
return new GroupDividingParallelExtractor<DataType, ExtractedType>(signifier, statisticType.getUnit(), statisticType.getValueDecimals(),
|
||||||
|
workerBuilder, executor);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+64
@@ -0,0 +1,64 @@
|
|||||||
|
package com.sap.sailing.datamining.factories;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.Dimension;
|
||||||
|
import com.sap.sailing.datamining.ParallelFilter;
|
||||||
|
import com.sap.sailing.datamining.ConcurrentFilterCriteria;
|
||||||
|
import com.sap.sailing.datamining.FiltrationWorker;
|
||||||
|
import com.sap.sailing.datamining.WorkerBuilder;
|
||||||
|
import com.sap.sailing.datamining.builders.FilterByCriteriaBuilder;
|
||||||
|
import com.sap.sailing.datamining.dimensions.DimensionManager;
|
||||||
|
import com.sap.sailing.datamining.dimensions.DimensionManagerProvider;
|
||||||
|
import com.sap.sailing.datamining.impl.NonFilteringFilter;
|
||||||
|
import com.sap.sailing.datamining.impl.PartitioningParallelFilter;
|
||||||
|
import com.sap.sailing.datamining.impl.criterias.AndCompoundFilterCriteria;
|
||||||
|
import com.sap.sailing.datamining.impl.criterias.CompoundFilterCriteria;
|
||||||
|
import com.sap.sailing.datamining.impl.criterias.DimensionValuesFilterCriteria;
|
||||||
|
import com.sap.sailing.datamining.shared.DataTypes;
|
||||||
|
import com.sap.sailing.datamining.shared.DimensionIdentifier;
|
||||||
|
|
||||||
|
public final class FilterFactory {
|
||||||
|
|
||||||
|
private FilterFactory() { }
|
||||||
|
|
||||||
|
public static <DataType> ParallelFilter<DataType> createParallelFilter(WorkerBuilder<FiltrationWorker<DataType>> workerBuilder, ThreadPoolExecutor executor) {
|
||||||
|
return new PartitioningParallelFilter<DataType>(workerBuilder, executor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <DataType> WorkerBuilder<FiltrationWorker<DataType>> createDimensionFilterBuilder(DataTypes dataType, Map<DimensionIdentifier, Iterable<?>> selection) {
|
||||||
|
ConcurrentFilterCriteria<DataType> criteria = createAndCompoundDimensionFilterCritera(dataType, selection);
|
||||||
|
WorkerBuilder<FiltrationWorker<DataType>> builder = new FilterByCriteriaBuilder<DataType>(criteria);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A filter that filters nothing. So the returning collection is the same as the given one.
|
||||||
|
*/
|
||||||
|
public static <DataType> ParallelFilter<DataType> createNonFilteringFilter() {
|
||||||
|
return new NonFilteringFilter<DataType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <DataType> ConcurrentFilterCriteria<DataType> createAndCompoundDimensionFilterCritera(DataTypes dataType, Map<DimensionIdentifier, Iterable<?>> selection) {
|
||||||
|
DimensionManager<DataType> dimensionManager = DimensionManagerProvider.getDimensionManagerFor(dataType);
|
||||||
|
CompoundFilterCriteria<DataType> compoundCriteria = new AndCompoundFilterCriteria<DataType>();
|
||||||
|
|
||||||
|
for (Entry<DimensionIdentifier, Iterable<?>> entry : selection.entrySet()) {
|
||||||
|
Dimension<DataType, ?> dimension = dimensionManager.getDimensionFor(entry.getKey());
|
||||||
|
if (dimension != null) {
|
||||||
|
ConcurrentFilterCriteria<DataType> criteria = createDimensionFilterCriteria(dimension, entry.getValue());
|
||||||
|
compoundCriteria.addCriteria(criteria);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return compoundCriteria;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static <DataType, ValueType> ConcurrentFilterCriteria<DataType> createDimensionFilterCriteria(Dimension<DataType, ValueType> dimension, Iterable<?> values) {
|
||||||
|
return new DimensionValuesFilterCriteria<DataType, ValueType>(dimension, (Collection<ValueType>) values);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
package com.sap.sailing.datamining.factories;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.Dimension;
|
||||||
|
import com.sap.sailing.datamining.GroupingWorker;
|
||||||
|
import com.sap.sailing.datamining.ParallelGrouper;
|
||||||
|
import com.sap.sailing.datamining.WorkerBuilder;
|
||||||
|
import com.sap.sailing.datamining.builders.MultiDimensionalGroupingWorkerBuilder;
|
||||||
|
import com.sap.sailing.datamining.dimensions.DimensionManager;
|
||||||
|
import com.sap.sailing.datamining.dimensions.DimensionManagerProvider;
|
||||||
|
import com.sap.sailing.datamining.impl.PartitioningParallelGrouper;
|
||||||
|
import com.sap.sailing.datamining.shared.DataTypes;
|
||||||
|
import com.sap.sailing.datamining.shared.DimensionIdentifier;
|
||||||
|
import com.sap.sailing.datamining.shared.QueryDefinition;
|
||||||
|
|
||||||
|
public final class GrouperFactory {
|
||||||
|
|
||||||
|
private GrouperFactory() { }
|
||||||
|
|
||||||
|
public static <DataType> ParallelGrouper<DataType> createGrouper(QueryDefinition queryDefinition, ThreadPoolExecutor executor) {
|
||||||
|
WorkerBuilder<GroupingWorker<DataType>> workerBuilder = createGroupingWorkerBuilder(queryDefinition);
|
||||||
|
return new PartitioningParallelGrouper<DataType>(workerBuilder, executor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <DataType> WorkerBuilder<GroupingWorker<DataType>> createGroupingWorkerBuilder(QueryDefinition queryDefinition) {
|
||||||
|
switch (queryDefinition.getGrouperType()) {
|
||||||
|
case Dimensions:
|
||||||
|
return createMultiDimensionalGroupingWorkerBuilder(queryDefinition.getDataType(), queryDefinition.getDimensionsToGroupBy());
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Not yet implemented for the given grouper type: "
|
||||||
|
+ queryDefinition.getGrouperType().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static <DataType, ValueType> WorkerBuilder<GroupingWorker<DataType>> createMultiDimensionalGroupingWorkerBuilder(DataTypes dataType, List<DimensionIdentifier> dimensionsToGroupBy) {
|
||||||
|
DimensionManager<DataType> dimensionManager = DimensionManagerProvider.getDimensionManagerFor(dataType);
|
||||||
|
Collection<Dimension<DataType, ValueType>> dimensions = new LinkedHashSet<Dimension<DataType, ValueType>>();
|
||||||
|
for (DimensionIdentifier sharedDimension : dimensionsToGroupBy) {
|
||||||
|
Dimension<DataType, ValueType> dimension = (Dimension<DataType, ValueType>) dimensionManager.getDimensionFor(sharedDimension);
|
||||||
|
dimensions.add(dimension);
|
||||||
|
}
|
||||||
|
return new MultiDimensionalGroupingWorkerBuilder<DataType, ValueType>(dimensions);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+91
@@ -0,0 +1,91 @@
|
|||||||
|
package com.sap.sailing.datamining.i18n;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.DataMiningStringMessages;
|
||||||
|
import com.sap.sailing.datamining.shared.Message;
|
||||||
|
|
||||||
|
public class DataMiningResourceBundleManager implements DataMiningStringMessages {
|
||||||
|
|
||||||
|
private static final String DEFAULT_LOCALE_NAME = "default";
|
||||||
|
private static final String STRING_MESSAGES_BASE_NAME = "stringmessages/StringMessages";
|
||||||
|
private static final String MESSAGE_PARAMETER_START = "\\{";
|
||||||
|
private static final String MESSAGE_PARAMETER_END = "\\}";
|
||||||
|
|
||||||
|
private Map<String, Locale> supportedLocalesMappedByLocaleInfo;
|
||||||
|
private Map<Locale, ResourceBundle> messagesMappedByLocale;
|
||||||
|
|
||||||
|
public DataMiningResourceBundleManager(Locale defaultLocale) {
|
||||||
|
supportedLocalesMappedByLocaleInfo = new HashMap<>();
|
||||||
|
messagesMappedByLocale = new HashMap<>();
|
||||||
|
|
||||||
|
initializeSupportedLocales(defaultLocale);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String get(Locale locale, String message, String... parameters) {
|
||||||
|
String result = getResourceBundle(locale).getString(message);
|
||||||
|
|
||||||
|
for (int i = 0; i < parameters.length; i++) {
|
||||||
|
String replacementRegex = MESSAGE_PARAMETER_START + i + MESSAGE_PARAMETER_END;
|
||||||
|
result = result.replaceAll(replacementRegex, parameters[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get(Locale locale, Message message, String... parameters) {
|
||||||
|
return get(locale, message.toString(), parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get(Locale locale, Message message, Message... parameters) {
|
||||||
|
String[] parametersAsString = new String[parameters.length];
|
||||||
|
for (int i = 0; i < parameters.length; i++) {
|
||||||
|
parametersAsString[i] = get(locale, parameters[i]);
|
||||||
|
}
|
||||||
|
return get(locale, message, parametersAsString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get(Locale locale, Message message) {
|
||||||
|
return get(locale, message, new String[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get(String localeName, Message message, String... parameters) {
|
||||||
|
return get(getLocaleFrom(localeName), message, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get(String localeName, Message message, Message... parameters) {
|
||||||
|
return get(getLocaleFrom(localeName), message, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get(String localeName, Message message) {
|
||||||
|
return get(getLocaleFrom(localeName), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Locale getLocaleFrom(String localeName) {
|
||||||
|
Locale locale = supportedLocalesMappedByLocaleInfo.get(localeName);
|
||||||
|
return locale != null ? locale : supportedLocalesMappedByLocaleInfo.get(DEFAULT_LOCALE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResourceBundle getResourceBundle(Locale locale) {
|
||||||
|
if (!messagesMappedByLocale.containsKey(locale)) {
|
||||||
|
messagesMappedByLocale.put(locale, ResourceBundle.getBundle(STRING_MESSAGES_BASE_NAME, locale));
|
||||||
|
}
|
||||||
|
return messagesMappedByLocale.get(locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeSupportedLocales(Locale defaultLocale) {
|
||||||
|
supportedLocalesMappedByLocaleInfo.put(DEFAULT_LOCALE_NAME, defaultLocale);
|
||||||
|
supportedLocalesMappedByLocaleInfo.put("en", Locale.ENGLISH);
|
||||||
|
supportedLocalesMappedByLocaleInfo.put("de", Locale.GERMAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
package com.sap.sailing.datamining.impl;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.ComponentWorker;
|
||||||
|
import com.sap.sailing.datamining.WorkReceiver;
|
||||||
|
|
||||||
|
public abstract class AbstractComponentWorker<ResultType> implements ComponentWorker<ResultType> {
|
||||||
|
|
||||||
|
private WorkReceiver<ResultType> receiver;
|
||||||
|
private boolean done;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
receiver.receiveWork(doWork());
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract ResultType doWork();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setReceiver(WorkReceiver<ResultType> receiver) {
|
||||||
|
this.receiver = receiver;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDone() {
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected WorkReceiver<ResultType> getReceiver() {
|
||||||
|
return receiver;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
package com.sap.sailing.datamining.impl;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.Dimension;
|
||||||
|
|
||||||
|
public abstract class AbstractDimension<DataType, ValueType> implements Dimension<DataType, ValueType> {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public AbstractDimension(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
AbstractDimension<?, ?> other = (AbstractDimension<?, ?>) obj;
|
||||||
|
if (name == null) {
|
||||||
|
if (other.name != null)
|
||||||
|
return false;
|
||||||
|
} else if (!name.equals(other.name))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
package com.sap.sailing.datamining.impl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.ExtractionWorker;
|
||||||
|
import com.sap.sailing.datamining.shared.GroupKey;
|
||||||
|
|
||||||
|
public abstract class AbstractExtractionWorker<DataType, ExtractedType> extends AbstractComponentWorker<Map<GroupKey, Collection<ExtractedType>>>
|
||||||
|
implements ExtractionWorker<DataType, ExtractedType> {
|
||||||
|
|
||||||
|
private Map<GroupKey, Collection<DataType>> data;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDataToExtractFrom(Map<GroupKey, Collection<DataType>> data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<GroupKey, Collection<ExtractedType>> doWork() {
|
||||||
|
Map<GroupKey, Collection<ExtractedType>> extractedData = new HashMap<GroupKey, Collection<ExtractedType>>();
|
||||||
|
for (Entry<GroupKey, Collection<DataType>> dataEntry : data.entrySet()) {
|
||||||
|
GroupKey key = dataEntry.getKey();
|
||||||
|
if (!extractedData.containsKey(key)) {
|
||||||
|
extractedData.put(key, new ArrayList<ExtractedType>());
|
||||||
|
};
|
||||||
|
|
||||||
|
for (DataType dateElement : dataEntry.getValue()) {
|
||||||
|
ExtractedType extractedDataElement = extract(dateElement);
|
||||||
|
if (extractedDataElement != null) {
|
||||||
|
extractedData.get(key).add(extractedDataElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return extractedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract ExtractedType extract(DataType dataEntry);
|
||||||
|
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
package com.sap.sailing.datamining.impl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.FiltrationWorker;
|
||||||
|
|
||||||
|
public abstract class AbstractFiltrationWorker<DataType> extends AbstractComponentWorker<Collection<DataType>>
|
||||||
|
implements FiltrationWorker<DataType> {
|
||||||
|
|
||||||
|
private Collection<DataType> data;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<DataType> doWork() {
|
||||||
|
Collection<DataType> filteredData = new ArrayList<DataType>();
|
||||||
|
for (DataType dataEntry : data) {
|
||||||
|
if (matches(dataEntry)) {
|
||||||
|
filteredData.add(dataEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filteredData;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract boolean matches(DataType dataEntry);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDataToFilter(Collection<DataType> data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
package com.sap.sailing.datamining.impl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.GroupingWorker;
|
||||||
|
import com.sap.sailing.datamining.shared.GroupKey;
|
||||||
|
|
||||||
|
public abstract class AbstractGroupingWorker<DataType> extends AbstractComponentWorker<Map<GroupKey, Collection<DataType>>>
|
||||||
|
implements GroupingWorker<DataType> {
|
||||||
|
|
||||||
|
private Collection<DataType> data;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDataToGroup(Collection<DataType> data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<GroupKey, Collection<DataType>> doWork() {
|
||||||
|
Map<GroupKey, Collection<DataType>> groupedData = new HashMap<GroupKey, Collection<DataType>>();
|
||||||
|
for (DataType dataEntry : data) {
|
||||||
|
GroupKey key = getGroupKeyFor(dataEntry);
|
||||||
|
if (key != null) {
|
||||||
|
if (!groupedData.containsKey(key)) {
|
||||||
|
groupedData.put(key, new ArrayList<DataType>());
|
||||||
|
}
|
||||||
|
groupedData.get(key).add(dataEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return groupedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract GroupKey getGroupKeyFor(DataType dataEntry);
|
||||||
|
|
||||||
|
}
|
||||||
+79
@@ -0,0 +1,79 @@
|
|||||||
|
package com.sap.sailing.datamining.impl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.DataRetrievalWorker;
|
||||||
|
import com.sap.sailing.datamining.data.TrackedLegContext;
|
||||||
|
import com.sap.sailing.datamining.data.TrackedLegOfCompetitorContext;
|
||||||
|
import com.sap.sailing.datamining.data.impl.TrackedLegContextImpl;
|
||||||
|
import com.sap.sailing.datamining.data.impl.TrackedLegOfCompetitorContextImpl;
|
||||||
|
import com.sap.sailing.domain.base.Competitor;
|
||||||
|
import com.sap.sailing.domain.base.CourseArea;
|
||||||
|
import com.sap.sailing.domain.base.Fleet;
|
||||||
|
import com.sap.sailing.domain.base.Leg;
|
||||||
|
import com.sap.sailing.domain.base.RaceColumn;
|
||||||
|
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||||
|
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||||
|
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
|
||||||
|
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||||
|
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||||
|
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||||
|
|
||||||
|
public abstract class AbstractLeaderboardGroupDataRetrievalWorker<DataType> extends AbstractComponentWorker<Collection<DataType>> implements DataRetrievalWorker<DataType> {
|
||||||
|
|
||||||
|
private LeaderboardGroup group;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setGroup(LeaderboardGroup group) {
|
||||||
|
this.group = group;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected LeaderboardGroup getGroup() {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Collection<Pair<TrackedLeg, TrackedLegContext>> retrieveDataTillTrackedLeg(LeaderboardGroup group) {
|
||||||
|
Collection<Pair<TrackedLeg, TrackedLegContext>> data = new ArrayList<Pair<TrackedLeg, TrackedLegContext>>();
|
||||||
|
for (Leaderboard leaderboard : group.getLeaderboards()) {
|
||||||
|
CourseArea courseArea = leaderboard.getDefaultCourseArea();
|
||||||
|
for (RaceColumn raceColumn : leaderboard.getRaceColumns()) {
|
||||||
|
for (Fleet fleet : raceColumn.getFleets()) {
|
||||||
|
TrackedRace trackedRace = raceColumn.getTrackedRace(fleet);
|
||||||
|
if (trackedRace != null) {
|
||||||
|
int legNumber = 1;
|
||||||
|
for (Leg leg : trackedRace.getRace().getCourse().getLegs()) {
|
||||||
|
TrackedLeg trackedLeg = trackedRace.getTrackedLeg(leg);
|
||||||
|
if (trackedLeg != null) {
|
||||||
|
TrackedLegContext dataContext = new TrackedLegContextImpl(group, leaderboard,
|
||||||
|
courseArea, fleet, trackedRace, trackedLeg, legNumber);
|
||||||
|
data.add(new Pair<TrackedLeg, TrackedLegContext>(trackedLeg, dataContext));
|
||||||
|
legNumber++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Collection<Pair<TrackedLegOfCompetitor, TrackedLegOfCompetitorContext>> retrieveDataTillTrackedLegOfCompetitor(
|
||||||
|
LeaderboardGroup group) {
|
||||||
|
Collection<Pair<TrackedLegOfCompetitor, TrackedLegOfCompetitorContext>> data = new ArrayList<Pair<TrackedLegOfCompetitor, TrackedLegOfCompetitorContext>>();
|
||||||
|
Collection<Pair<TrackedLeg, TrackedLegContext>> baseData = retrieveDataTillTrackedLeg(group);
|
||||||
|
for (Pair<TrackedLeg, TrackedLegContext> baseDataEntry : baseData) {
|
||||||
|
TrackedLeg trackedLeg = baseDataEntry.getA();
|
||||||
|
TrackedLegContext trackedLegContext = baseDataEntry.getB();
|
||||||
|
for (Competitor competitor : trackedLegContext.getTrackedRace().getRace().getCompetitors()) {
|
||||||
|
TrackedLegOfCompetitor trackedLegOfCompetitor = trackedLeg.getTrackedLeg(competitor);
|
||||||
|
TrackedLegOfCompetitorContext dataContext = new TrackedLegOfCompetitorContextImpl(trackedLegContext,
|
||||||
|
competitor);
|
||||||
|
data.add(new Pair<TrackedLegOfCompetitor, TrackedLegOfCompetitorContext>(trackedLegOfCompetitor,
|
||||||
|
dataContext));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+102
@@ -0,0 +1,102 @@
|
|||||||
|
package com.sap.sailing.datamining.impl;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.ComponentWorker;
|
||||||
|
import com.sap.sailing.datamining.WorkReceiver;
|
||||||
|
|
||||||
|
public abstract class AbstractParallelComponent<WorkingType, ResultType> implements ParallelComponent<WorkingType, ResultType>,
|
||||||
|
WorkReceiver<ResultType> {
|
||||||
|
|
||||||
|
private ThreadPoolExecutor executor;
|
||||||
|
private Collection<ComponentWorker<ResultType>> workers;
|
||||||
|
private Set<ResultType> results;
|
||||||
|
|
||||||
|
public AbstractParallelComponent(ThreadPoolExecutor executor) {
|
||||||
|
this.executor = executor;
|
||||||
|
workers = new HashSet<ComponentWorker<ResultType>>();
|
||||||
|
results = Collections.newSetFromMap(new ConcurrentHashMap<ResultType, Boolean>());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParallelComponent<WorkingType, ResultType> start(WorkingType data) {
|
||||||
|
setUpWorkersFor(data);
|
||||||
|
for (ComponentWorker<ResultType> worker : workers) {
|
||||||
|
executor.execute(worker);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void setUpWorkersFor(WorkingType data);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void receiveWork(ResultType result) {
|
||||||
|
results.add(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Collection<ResultType> getResults() {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultType get() throws InterruptedException, ExecutionException {
|
||||||
|
while (!isDone()) {
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
return finalizeData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultType get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException,
|
||||||
|
TimeoutException {
|
||||||
|
long timeRun = 0;
|
||||||
|
long timeoutInMillis = unit.toMillis(timeout);
|
||||||
|
while (!isDone() && timeRun < timeoutInMillis) {
|
||||||
|
Thread.sleep(100);
|
||||||
|
timeRun = timeRun + 100;
|
||||||
|
}
|
||||||
|
if (timeRun >= timeoutInMillis) {
|
||||||
|
throw new TimeoutException();
|
||||||
|
}
|
||||||
|
return finalizeData();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract ResultType finalizeData();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDone() {
|
||||||
|
for (ComponentWorker<ResultType> worker : workers) {
|
||||||
|
if (!worker.isDone()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ThreadPoolExecutor getExecutor() {
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addWorker(ComponentWorker<ResultType> worker) {
|
||||||
|
workers.add(worker);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.sap.sailing.datamining.impl;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import com.sap.sailing.datamining.Cluster;
|
||||||
|
|
||||||
|
public class ClusterImpl<ValueType> implements Cluster<ValueType> {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private ValueType upperRange;
|
||||||
|
private ValueType lowerRange;
|
||||||
|
|
||||||
|
public ClusterImpl(String name, ValueType upperRange, ValueType lowerRange) {
|
||||||
|
this.name = name;
|
||||||
|
this.upperRange = upperRange;
|
||||||
|
this.lowerRange = lowerRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueType getUpperRange() {
|
||||||
|
return upperRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueType getLowerRange() {
|
||||||
|
return lowerRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInRange(ValueType value, Comparator<ValueType> comparator) {
|
||||||
|
return comparator.compare(value, getLowerRange()) >= 0 && comparator.compare(value, getUpperRange()) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loaded 100 of 215 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user