Merge branch 'master' into bug4254

This commit is contained in:
Axel Uhl committed 2017-08-01 13:10:40 +02:00
commit 4feec8c1fe
19 files changed
+164 -27

No files matched your search

@@ -18,7 +18,6 @@ import com.sap.sailing.datamining.data.HasTrackedRaceContext;
import com.sap.sailing.datamining.test.util.OpenFunctionManager;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.base.Team;
import com.sap.sailing.domain.common.Moving;
import com.sap.sailing.domain.common.Speed;
import com.sap.sse.common.Named;
@@ -61,13 +60,11 @@ public class TestSailingFunctionsRegistration {
Method getCompetitorMethod = HasTrackedLegOfCompetitorContext.class.getMethod("getCompetitor", new Class<?>[0]);
Function<?> getCompetitor = functionFactory.createMethodWrappingFunction(getCompetitorMethod);
Method getTeamMethod = Competitor.class.getMethod("getTeam", new Class<?>[0]);
Function<?> getTeam = functionFactory.createMethodWrappingFunction(getTeamMethod);
Method getNationalityMethod = Team.class.getMethod("getNationality", new Class<?>[0]);
Method getNationalityMethod = Competitor.class.getMethod("getNationality", new Class<?>[0]);
Function<?> getNationality = functionFactory.createMethodWrappingFunction(getNationalityMethod);
Method getAcronymMethod = Nationality.class.getMethod("getThreeLetterIOCAcronym", new Class<?>[0]);
Function<?> getAcronym = functionFactory.createMethodWrappingFunction(getAcronymMethod);
expectedDimensions.add(functionFactory.createCompoundFunction(Arrays.asList(getCompetitor, getTeam, getNationality, getAcronym)));
expectedDimensions.add(functionFactory.createCompoundFunction(Arrays.asList(getCompetitor, getNationality, getAcronym)));
return expectedDimensions;
}
@@ -12,6 +12,7 @@ Regatta=Regatta
CourseArea=Course Area
BoatClass=Boat Class
Fleet=Fleet
RaceColumn=Race Column
Race=Race
Competitor=Competitor
Boat=Boat
@@ -14,6 +14,7 @@ Regatta=Regatta
CourseArea=Regattabahn
BoatClass=Bootsklasse
Fleet=Flotte
RaceColumn=Rennspalte
Race=Rennen
LeaderboardSailingDomainRetrieverChain=Leaderboards
RaceSailingDomainRetrieverChain=Rennen
@@ -1,6 +1,7 @@
package com.sap.sailing.datamining.data;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.tracking.BravoFixTrack;
import com.sap.sse.common.Duration;
import com.sap.sse.datamining.annotations.Connector;
@@ -14,4 +15,7 @@ public interface HasBravoFixTrackContext {
@Statistic(messageKey="timeSpentFoiling", resultDecimals=1)
Duration getTimeSpentFoiling();
@Statistic(messageKey="FoilingDistance", resultDecimals=1)
Distance getDistanceSpentFoiling();
}
@@ -5,6 +5,7 @@ import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.Tack;
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
import com.sap.sse.common.Duration;
import com.sap.sse.datamining.annotations.Connector;
import com.sap.sse.datamining.annotations.Dimension;
import com.sap.sse.datamining.annotations.Statistic;
@@ -42,4 +43,10 @@ public interface HasTrackedLegOfCompetitorContext extends HasWindOnTrackedLeg {
return getTrackedLegContext().getTrackedRaceContext().getTrackedRace().getTack(
getTrackedLegOfCompetitorContext().getCompetitor(), getTimePoint());
}
@Statistic(messageKey="timeSpentFoiling", resultDecimals=1)
Duration getTimeSpentFoiling();
@Statistic(messageKey="FoilingDistance", resultDecimals=1)
Distance getDistanceSpentFoiling();
}
@@ -3,6 +3,7 @@ package com.sap.sailing.datamining.data;
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.RaceColumn;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.NauticalSide;
@@ -23,23 +24,26 @@ public interface HasTrackedRaceContext {
@Connector(messageKey="CourseArea", ordinal=3)
public CourseArea getCourseArea();
@Connector(messageKey="Fleet", ordinal=4)
@Connector(messageKey="RaceColumn", ordinal=4)
public RaceColumn getRaceColumn();
@Connector(messageKey="Fleet", ordinal=5)
public Fleet getFleet();
@Connector(messageKey="Race", ordinal=5)
@Connector(messageKey="Race", ordinal=6)
public RaceDefinition getRace();
@Dimension(messageKey="Year", ordinal=2)
public Integer getYear();
@Dimension(messageKey="AdvantageousEndOfLine", ordinal=6)
@Dimension(messageKey="AdvantageousEndOfLine", ordinal=7)
public NauticalSide getAdvantageousEndOfLine();
@Dimension(messageKey="MedalRace", ordinal=7)
@Dimension(messageKey="MedalRace", ordinal=8)
public Boolean isMedalRace();
@Dimension(messageKey="IsTracked", ordinal=7)
@Dimension(messageKey="IsTracked", ordinal=9)
public Boolean isTracked();
@Statistic(messageKey="NumberOfCompetitorFixes", resultDecimals=0, ordinal=0)
@@ -40,6 +40,7 @@ public class FoilingSegmentRetrievalProcessor extends AbstractRetrievalProcessor
final BravoFixTrack<Competitor> bravoFixTrack = trackedRace.getSensorTrack(element.getCompetitor(), BravoFixTrack.TRACK_NAME);
if (bravoFixTrack != null) {
boolean isFoiling = false;
TimePoint last = null;
TimePoint startOfSegment = null;
bravoFixTrack.lockForRead();
try {
@@ -47,7 +48,9 @@ public class FoilingSegmentRetrievalProcessor extends AbstractRetrievalProcessor
if (isFoiling) {
if (!bravoFix.isFoiling()) {
isFoiling = false;
foilingSegments.add(createFoilingSegment(startOfSegment, bravoFix.getTimePoint(), element, bravoFixTrack));
foilingSegments.add(createFoilingSegment(startOfSegment,
last /* don't include the last interval ending at the non-foiling fix */,
element, bravoFixTrack));
startOfSegment = null;
}
} else {
@@ -56,6 +59,7 @@ public class FoilingSegmentRetrievalProcessor extends AbstractRetrievalProcessor
startOfSegment = bravoFix.getTimePoint();
}
}
last = bravoFix.getTimePoint();
}
} finally {
bravoFixTrack.unlockAfterRead();
@@ -29,7 +29,7 @@ public class TrackedRaceRetrievalProcessor extends AbstractRetrievalProcessor<Ha
TrackedRace trackedRace = raceColumn.getTrackedRace(fleet);
if (trackedRace != null) {
Regatta regatta = trackedRace.getTrackedRegatta().getRegatta();
HasTrackedRaceContext trackedRaceWithContext = new TrackedRaceWithContext(element, regatta, fleet, trackedRace);
HasTrackedRaceContext trackedRaceWithContext = new TrackedRaceWithContext(element, regatta, raceColumn, fleet, trackedRace);
trackedRacesWithContext.add(trackedRaceWithContext);
}
}
@@ -3,6 +3,7 @@ package com.sap.sailing.datamining.impl.data;
import com.sap.sailing.datamining.data.HasBravoFixTrackContext;
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.tracking.BravoFixTrack;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
@@ -43,4 +44,19 @@ public class BravoFixTrackWithContext implements HasBravoFixTrackContext {
return bravoFixTrack.getTimeSpentFoiling(startOfRace, end);
}
@Override
public Distance getDistanceSpentFoiling() {
final TimePoint endOfRace = getRaceOfCompetitorContext().getTrackedRaceContext().getTrackedRace().getEndOfRace();
final TimePoint startOfRace = getRaceOfCompetitorContext().getTrackedRaceContext().getTrackedRace().getStartOfRace();
final TimePoint end;
if (endOfRace == null) {
final TimePoint endOfTracking = getRaceOfCompetitorContext().getTrackedRaceContext().getTrackedRace().getEndOfTracking();
end = endOfTracking == null ? MillisecondsTimePoint.now() : endOfTracking;
} else {
end = endOfRace;
}
return bravoFixTrack.getDistanceSpentFoiling(
getRaceOfCompetitorContext().getTrackedRaceContext().getTrackedRace().getTrack(getRaceOfCompetitorContext().getCompetitor()),
startOfRace, end);
}
}
@@ -21,6 +21,7 @@ import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.LineDetails;
import com.sap.sailing.domain.tracking.Maneuver;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.TrackedLeg;
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
import com.sap.sailing.domain.tracking.TrackedRace;
@@ -181,7 +182,8 @@ public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext {
Course course = getTrackedRace().getRace().getCourse();
Waypoint firstMark = course.getFirstLeg().getTo();
Competitor competitor = getCompetitor();
int rank = getTrackedRace().getRank(competitor, getTrackedRace().getMarkPassing(competitor, firstMark).getTimePoint());
final MarkPassing markPassing = getTrackedRace().getMarkPassing(competitor, firstMark);
int rank = markPassing == null ? 0 : getTrackedRace().getRank(competitor, markPassing.getTimePoint());
return rank == 0 ? null : Double.valueOf(rank);
}
@@ -1,5 +1,7 @@
package com.sap.sailing.datamining.impl.data;
import java.util.function.BiFunction;
import com.sap.sailing.datamining.Activator;
import com.sap.sailing.datamining.SailingClusterGroups;
import com.sap.sailing.datamining.data.HasTrackedLegContext;
@@ -9,11 +11,14 @@ import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.Wind;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.tracking.BravoFixTrack;
import com.sap.sailing.domain.tracking.TrackedLeg;
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.datamining.data.Cluster;
import com.sap.sse.datamining.shared.impl.dto.ClusterDTO;
@@ -64,6 +69,37 @@ public class TrackedLegOfCompetitorWithContext implements HasTrackedLegOfCompeti
return new ClusterDTO(clusterGroups.getPercentageClusterFormatter().format(cluster));
}
private <R> R getSomethingForLegTrackingInterval(BiFunction<TimePoint, TimePoint, R> resultSupplier) {
final TimePoint startTime = getTrackedLegOfCompetitor().getStartTime();
final TimePoint finishTime = getTrackedLegOfCompetitor().getFinishTime();
final R result;
if (startTime != null) {
final TrackedRace trackedRace = getTrackedLegContext().getTrackedLeg().getTrackedRace();
final TimePoint effectiveEndOfInterval = finishTime != null ? finishTime :
trackedRace.getEndOfTracking() != null ? trackedRace.getEndOfTracking() : MillisecondsTimePoint.now();
result = resultSupplier.apply(startTime, effectiveEndOfInterval);
} else {
result = null;
}
return result;
}
@Override
public Duration getTimeSpentFoiling() {
return getSomethingForLegTrackingInterval((start, end) -> {
BravoFixTrack<Competitor> bravoFixTrack = getTrackedLegContext().getTrackedLeg().getTrackedRace().getSensorTrack(getCompetitor(), BravoFixTrack.TRACK_NAME);
return bravoFixTrack.getTimeSpentFoiling(start, end);
});
}
@Override
public Distance getDistanceSpentFoiling() {
return getSomethingForLegTrackingInterval((start, end) -> {
BravoFixTrack<Competitor> bravoFixTrack = getTrackedLegContext().getTrackedLeg().getTrackedRace().getSensorTrack(getCompetitor(), BravoFixTrack.TRACK_NAME);
return bravoFixTrack.getDistanceSpentFoiling(getTrackedLegContext().getTrackedLeg().getTrackedRace().getTrack(getCompetitor()), start, end);
});
}
@Override
public Distance getDistanceTraveled() {
TimePoint timePoint = getTrackedLegContext().getTrackedRaceContext().getTrackedRace().getEndOfTracking();
@@ -114,11 +150,13 @@ public class TrackedLegOfCompetitorWithContext implements HasTrackedLegOfCompeti
public Long getTimeTakenInSeconds() {
TimePoint startTime = getTrackedLegOfCompetitor().getStartTime();
TimePoint finishTime = getTrackedLegOfCompetitor().getFinishTime();
final Long result;
if (startTime == null || finishTime == null) {
return null;
result = null;
} else {
result = (finishTime.asMillis() - startTime.asMillis()) / 1000;
}
return (finishTime.asMillis() - startTime.asMillis()) / 1000;
return result;
}
@Override
@@ -8,6 +8,7 @@ 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.Mark;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.NauticalSide;
@@ -24,15 +25,17 @@ public class TrackedRaceWithContext implements HasTrackedRaceContext {
private final HasLeaderboardContext leaderboardContext;
private final Regatta regatta;
private final RaceColumn raceColumn;
private final Fleet fleet;
private final TrackedRace trackedRace;
private Integer year;
private boolean yearHasBeenInitialized;
public TrackedRaceWithContext(HasLeaderboardContext leaderboardContext, Regatta regatta, Fleet fleet, TrackedRace trackedRace) {
public TrackedRaceWithContext(HasLeaderboardContext leaderboardContext, Regatta regatta, RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) {
this.leaderboardContext = leaderboardContext;
this.regatta = regatta;
this.raceColumn = raceColumn;
this.fleet = fleet;
this.trackedRace = trackedRace;
}
@@ -57,6 +60,11 @@ public class TrackedRaceWithContext implements HasTrackedRaceContext {
return trackedRace;
}
@Override
public RaceColumn getRaceColumn() {
return raceColumn;
}
@Override
public Fleet getFleet() {
return fleet;
@@ -138,11 +146,17 @@ public class TrackedRaceWithContext implements HasTrackedRaceContext {
// Convenience methods for race dependent calculation to avoid code duplication
public Double getRelativeScoreForCompetitor(Competitor competitor) {
Double rankAtFinish = getRankAtFinishForCompetitor(competitor);
if (rankAtFinish == null) {
return null;
final TimePoint now = MillisecondsTimePoint.now();
Double maxTotalPoints = 1.0; // avoid division by zero
Double totalPointsOfCompetitor = 0.0;
for (final Competitor c : getLeaderboardContext().getLeaderboard().getCompetitors()) {
final Double totalPoints = getLeaderboardContext().getLeaderboard().getTotalPoints(c, getRaceColumn(), now);
maxTotalPoints = Math.max(maxTotalPoints, totalPoints);
if (c == competitor) {
totalPointsOfCompetitor = totalPoints;
}
}
return rankAtFinish / Util.size(getTrackedRace().getRace().getCompetitors());
return totalPointsOfCompetitor / maxTotalPoints;
}
@Override
@@ -231,12 +231,13 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
public DBCollection getGPSFixCollection() {
DBCollection gpsFixCollection = database.getCollection(CollectionNames.GPS_FIXES.name());
// Removes an old index not needed anymore
// Removes old indexes not needed anymore
dropIndexSafe(gpsFixCollection, "DEVICE_ID.DEVICE_TYPE_SPECIFIC_ID_1_GPSFIX.TIME_AS_MILLIS_1");
dropIndexSafe(gpsFixCollection, "DEVICE_ID_1_GPSFIX.TIME_AS_MILLIS_1");
DBObject index = new BasicDBObject();
index.put(FieldNames.DEVICE_ID.name(), 1);
index.put(FieldNames.GPSFIX.name()+"."+FieldNames.TIME_AS_MILLIS.name(), 1);
index.put(FieldNames.TIME_AS_MILLIS.name(), 1);
gpsFixCollection.createIndex(index);
return gpsFixCollection;
}
@@ -48,10 +48,10 @@ public class DoubleVectorFixMongoHandlerImpl implements FixMongoHandler<DoubleVe
private double[] fromDBObject(DBObject dbObject) {
@SuppressWarnings("unchecked")
List<Double> dbValues = (List<Double>) dbObject;
List<Number> dbValues = (List<Number>) dbObject;
double[] result = new double[dbValues.size()];
for(int i = 0 ; i < dbValues.size() ; i++) {
result[i] = dbValues.get(i);
result[i] = dbValues.get(i).doubleValue();
}
return result;
}
@@ -11,8 +11,13 @@ import com.sap.sse.datamining.annotations.Connector;
import com.sap.sse.datamining.annotations.Dimension;
public interface Competitor extends NamedWithID, IsManagedByCache<SharedDomainFactory> {
@Connector(messageKey="Team", ordinal=9)
Team getTeam();
/**
* Short for {@link #getTeam()}.{@link Team#getNationality() getNationality()}.
*/
@Connector(messageKey="Nationality", ordinal=9)
Nationality getNationality();
@Connector(messageKey="Boat", ordinal=10)
Boat getBoat();
@@ -9,6 +9,7 @@ import java.util.Set;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorChangeListener;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.base.SharedDomainFactory;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
@@ -78,6 +79,11 @@ public class CompetitorImpl implements DynamicCompetitor {
return team;
}
@Override
public Nationality getNationality() {
return getTeam() == null ? null : getTeam().getNationality();
}
@Override
public DynamicBoat getBoat() {
return boat;
@@ -2,9 +2,11 @@ package com.sap.sailing.domain.tracking;
import java.io.Serializable;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.Bearing;
import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.tracking.BravoFix;
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.WithID;
@@ -66,4 +68,9 @@ public interface BravoFixTrack<ItemType extends WithID & Serializable> extends S
* The time spent foiling during the time range provided
*/
Duration getTimeSpentFoiling(TimePoint from, TimePoint to);
/**
* The distance sailed foiling during the time range provided
*/
Distance getDistanceSpentFoiling(GPSFixTrack<Competitor, GPSFixMoving> gpsFixTrack, TimePoint from, TimePoint to);
}
@@ -2,11 +2,14 @@ package com.sap.sailing.domain.tracking.impl;
import java.io.Serializable;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.Bearing;
import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.tracking.BravoFix;
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.BravoFixTrack;
import com.sap.sailing.domain.tracking.DynamicBravoFixTrack;
import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
@@ -143,4 +146,25 @@ public class BravoFixTrackImpl<ItemType extends WithID & Serializable> extends S
}
return result;
}
@Override
public Distance getDistanceSpentFoiling(GPSFixTrack<Competitor, GPSFixMoving> gpsFixTrack, TimePoint from, TimePoint to) {
Distance result = Distance.NULL;
lockForRead();
try {
TimePoint last = from;
boolean isFoiling = false;
for (final BravoFix fix : getFixes(from, true, to, true)) {
final boolean fixFoils = isFoiling(fix);
if (isFoiling && fixFoils) {
result = result.add(gpsFixTrack.getDistanceTraveled(last, fix.getTimePoint()));
}
last = fix.getTimePoint();
isFoiling = fixFoils;
}
} finally {
unlockAfterRead();
}
return result;
}
}
@@ -5,6 +5,7 @@ import java.net.URI;
import com.sap.sailing.domain.base.Boat;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorChangeListener;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.base.SharedDomainFactory;
import com.sap.sailing.domain.base.Team;
import com.sap.sailing.domain.base.Waypoint;
@@ -53,6 +54,11 @@ public class DummyMarkPassingWithTimePointOnly implements MarkPassing {
return null;
}
@Override
public Nationality getNationality() {
return null;
}
@Override
public Boat getBoat() {
return null;