mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-13 15:50:59 +00:00
Merge branch 'master' into igtimi
This commit is contained in:
commit
dab2cfd2a9
17 files changed
+242
-45
No files matched your search
@@ -25,6 +25,8 @@ Like businesses, sailors need the latest information to make strategic decisions
|
||||
* [[Development Environment|wiki/development-environment]]
|
||||
* [[Working with GWT Locally|wiki/local-gwt]]
|
||||
* [[Mobile Development|wiki/mobile-development]]
|
||||
* Information for Webdesigners
|
||||
* [[Layout repository|wiki/webdesign]]
|
||||
* General Information
|
||||
* [[Architecture and Infrastructure|wiki/architecture-and-infrastructure]]
|
||||
* [[Sailing Domain Algorithms|wiki/sailing-domain-algorithms]]
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package com.sap.sailing.domain.common;
|
||||
|
||||
public enum TrackedRaceStatusEnum { PREPARED(0), LOADING(1), TRACKING(2), FINISHED(3);
|
||||
public enum TrackedRaceStatusEnum { PREPARED(0), LOADING(1), TRACKING(2), FINISHED(3), ERROR(4);
|
||||
|
||||
private final int order;
|
||||
|
||||
|
||||
@@ -16,5 +16,5 @@
|
||||
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.domain.test"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080 -XX:+UseParallelGC -Dtractrac.tunnel=true -Dtractrac.tunnel.host=10.18.22.156 -ea -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080 -XX:+UseParallelGC -Dtractrac.tunnel=true -Dtractrac.tunnel.host=localhost -ea -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties"/>
|
||||
</launchConfiguration>
|
||||
+24
-1
@@ -14,18 +14,25 @@ import java.util.Set;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sailing.domain.base.Nationality;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.base.impl.BoatImpl;
|
||||
import com.sap.sailing.domain.base.impl.CompetitorImpl;
|
||||
import com.sap.sailing.domain.base.impl.CourseAreaImpl;
|
||||
import com.sap.sailing.domain.base.impl.DomainFactoryImpl;
|
||||
import com.sap.sailing.domain.base.impl.PersonImpl;
|
||||
import com.sap.sailing.domain.base.impl.TeamImpl;
|
||||
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.leaderboard.impl.FlexibleLeaderboardImpl;
|
||||
import com.sap.sailing.domain.leaderboard.impl.HighPoint;
|
||||
import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl;
|
||||
import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl;
|
||||
import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard;
|
||||
|
||||
public class OfflineSerializationTest extends AbstractSerializationTest {
|
||||
/**
|
||||
@@ -87,6 +94,22 @@ public class OfflineSerializationTest extends AbstractSerializationTest {
|
||||
clone.getDiscardIndexResultsStartingWithHowManyRaces()));
|
||||
}
|
||||
|
||||
// see bug 1605
|
||||
@Test
|
||||
public void testSerializingOverallLeaderboardWithFactorOnColumn() throws ClassNotFoundException, IOException {
|
||||
Leaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ThresholdBasedResultDiscardingRuleImpl(new int[] { 3, 5 }), new HighPoint(), new CourseAreaImpl("Alpha", "Alpha"));
|
||||
LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl("LeaderboardGroup", "Test Leaderboard Group", /* displayGroupsInReverseOrder */ false, Arrays.asList(new Leaderboard[] { leaderboard }));
|
||||
final LeaderboardGroupMetaLeaderboard overallLeaderboard = new LeaderboardGroupMetaLeaderboard(leaderboardGroup, new HighPoint(), new ThresholdBasedResultDiscardingRuleImpl(new int[0]));
|
||||
leaderboardGroup.setOverallLeaderboard(overallLeaderboard);
|
||||
final double FACTOR = 2.0;
|
||||
overallLeaderboard.getRaceColumnByName("Test Leaderboard").setFactor(FACTOR);
|
||||
|
||||
DomainFactory receiverDomainFactory = new DomainFactoryImpl();
|
||||
LeaderboardGroup clone = cloneBySerialization(leaderboardGroup, receiverDomainFactory);
|
||||
assertEquals(FACTOR, overallLeaderboard.getRaceColumnByName("Test Leaderboard").getFactor(), 0.00000001);
|
||||
assertEquals(FACTOR, clone.getOverallLeaderboard().getRaceColumnByName("Test Leaderboard").getFactor(), 0.00000001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdentityStabilityOfMarkSerialization() throws ClassNotFoundException, IOException {
|
||||
DomainFactory senderDomainFactory = new DomainFactoryImpl();
|
||||
|
||||
+31
-3
@@ -14,6 +14,7 @@ import java.net.URL;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -81,6 +82,13 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
|
||||
* with static position information otherwise not available through {@link MarkPassingReceiver}'s events.
|
||||
*/
|
||||
static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||
|
||||
/**
|
||||
* This value indicated how many stored data packets we allow that are not in the right sequence
|
||||
* Background: It can happen that the progress for storedData hops around and delivers a progress
|
||||
* that is lower than one received before. This can happen but only at a maximum of times this constant describes.
|
||||
*/
|
||||
static final Integer MAX_STORED_PACKET_HOP_ALLOWANCE = 3;
|
||||
|
||||
private final Event tractracEvent;
|
||||
private final com.sap.sailing.domain.base.Regatta regatta;
|
||||
@@ -92,6 +100,7 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
|
||||
private final Set<RaceDefinition> races;
|
||||
private final DynamicTrackedRegatta trackedRegatta;
|
||||
private TrackedRaceStatus lastStatus;
|
||||
private HashMap<Triple<URL, URI, URI>, Pair<Integer, Float>> lastProgressPerID;
|
||||
|
||||
/**
|
||||
* paramURL, liveURI and storedURI for TracTrac connection
|
||||
@@ -192,6 +201,7 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
|
||||
this.races = new HashSet<RaceDefinition>();
|
||||
this.windStore = windStore;
|
||||
this.domainFactory = domainFactory;
|
||||
this.lastProgressPerID = new HashMap<Triple<URL, URI, URI>, Pair<Integer, Float>>();
|
||||
final Simulator simulator;
|
||||
if (simulateWithStartTimeNow) {
|
||||
simulator = new Simulator(windStore);
|
||||
@@ -673,11 +683,29 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
|
||||
@Override
|
||||
public void storedDataProgress(float progress) {
|
||||
logger.info("Stored data progress in tracker "+getID()+" for race(s) "+getRaces()+": "+progress);
|
||||
if (progress != 0.0 && progress < lastStatus.getLoadingProgress()) {
|
||||
// this should never happen but it happens - let's at least write some log about this problem
|
||||
logger.severe("I got a loading progress "+progress+" that is smaller than the one already received "+lastStatus.getLoadingProgress());
|
||||
Integer counter = 0;
|
||||
final Pair<Integer, Float> lastProgressPair = lastProgressPerID.get(getID());
|
||||
if (lastProgressPair != null) {
|
||||
Float lastProgress = lastProgressPair.getB();
|
||||
counter = lastProgressPair.getA();
|
||||
if (progress < lastProgress.floatValue()) {
|
||||
if (counter.intValue() > MAX_STORED_PACKET_HOP_ALLOWANCE) {
|
||||
try {
|
||||
logger.severe("Got " + MAX_STORED_PACKET_HOP_ALLOWANCE + " times a value for progress " + progress + " that is lower than one already received " + lastProgress + "! This is a severe error - stopping receivers for " + getID() + " now!");
|
||||
stop(/* stopReceiversPreemptively */ true);
|
||||
/* make sure to indicate that this race is erroneous */
|
||||
lastStatus = new TrackedRaceStatusImpl(TrackedRaceStatusEnum.ERROR, 0.0);
|
||||
updateStatusOfTrackedRaces();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
counter += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
lastStatus = new TrackedRaceStatusImpl(progress==1.0 ? TrackedRaceStatusEnum.TRACKING : TrackedRaceStatusEnum.LOADING, progress);
|
||||
lastProgressPerID.put(getID(), new Pair<Integer, Float>(counter, progress));
|
||||
updateStatusOfTrackedRaces();
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -63,8 +63,13 @@ public class UpdateHandler {
|
||||
}
|
||||
|
||||
protected URL buildUpdateURL(HashMap<String, String> additionalParameters) throws MalformedURLException, UnsupportedEncodingException {
|
||||
String serverUpdateURI = this.updateURI.toString();
|
||||
// make sure that the update URI always ends with a slash
|
||||
if (!serverUpdateURI.endsWith("/")) {
|
||||
serverUpdateURI = serverUpdateURI + "/";
|
||||
}
|
||||
String url = String.format(UpdateUrlTemplate,
|
||||
this.updateURI.toString(),
|
||||
serverUpdateURI.toString(),
|
||||
this.action,
|
||||
URLEncoder.encode(this.tracTracEventId.toString(), EncodingUtf8),
|
||||
URLEncoder.encode(this.raceId.toString(), EncodingUtf8),
|
||||
|
||||
+2
-1
@@ -134,7 +134,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
|
||||
private final Set<Competitor> suppressedCompetitors;
|
||||
private final NamedReentrantReadWriteLock suppressedCompetitorsLock;
|
||||
|
||||
private final Map<Pair<TrackedRace, Competitor>, RunnableFuture<RaceDetails>> raceDetailsAtEndOfTrackingCache;
|
||||
private transient Map<Pair<TrackedRace, Competitor>, RunnableFuture<RaceDetails>> raceDetailsAtEndOfTrackingCache;
|
||||
|
||||
/**
|
||||
* This executor needs to be a different one than {@link #executor} because the tasks run by {@link #executor}
|
||||
@@ -369,6 +369,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
|
||||
}
|
||||
|
||||
private void initTransientFields() {
|
||||
this.raceDetailsAtEndOfTrackingCache = new HashMap<Util.Pair<TrackedRace,Competitor>, RunnableFuture<RaceDetails>>();
|
||||
this.raceDetailsExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
||||
this.cacheInvalidationListeners = new HashSet<CacheInvalidationListener>();
|
||||
// When many updates are triggered in a short period of time by a single thread, ensure that the single thread
|
||||
|
||||
+30
-6
@@ -2,9 +2,13 @@ package com.sap.sailing.domain.leaderboard.meta;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
@@ -48,10 +52,22 @@ public abstract class AbstractMetaLeaderboard extends AbstractSimpleLeaderboardI
|
||||
private final Fleet metaFleet;
|
||||
private final ScoringScheme scoringScheme;
|
||||
private final String name;
|
||||
private transient WeakHashMap<Leaderboard, RaceColumn> columnsForLeaderboards;
|
||||
|
||||
/**
|
||||
* Weak hash maps cannot be serialized. Therefore, this field is serialized as a {@link HashMap} in {@link #writeObject(ObjectOutputStream)}
|
||||
* and de-serialized into a new {@link WeakHashMap} in {@link #readObject(ObjectInputStream)} again.
|
||||
*/
|
||||
private transient WeakHashMap<Leaderboard, MetaLeaderboardColumn> columnsForLeaderboards;
|
||||
|
||||
/**
|
||||
* Weak hash maps cannot be serialized. Therefore, this field is serialized as a {@link HashMap} in {@link #writeObject(ObjectOutputStream)}
|
||||
* and de-serialized into a new {@link WeakHashMap} in {@link #readObject(ObjectInputStream)} again.
|
||||
*/
|
||||
private transient WeakHashMap<Leaderboard, ScoreCorrectionListener> scoreCorrectionChangeForwardersByLeaderboard;
|
||||
|
||||
private class ScoreCorrectionChangeForwarder implements ScoreCorrectionListener {
|
||||
private class ScoreCorrectionChangeForwarder implements ScoreCorrectionListener, Serializable {
|
||||
private static final long serialVersionUID = 915433462154943441L;
|
||||
|
||||
@Override
|
||||
public void correctedScoreChanced(Competitor competitor, RaceColumn raceColumn, Double oldCorrectedScore, Double newCorrectedScore) {
|
||||
getScoreCorrection().notifyListeners(competitor, raceColumn, oldCorrectedScore, newCorrectedScore);
|
||||
@@ -88,12 +104,20 @@ public abstract class AbstractMetaLeaderboard extends AbstractSimpleLeaderboardI
|
||||
return new MetaLeaderboardScoreCorrection(this);
|
||||
}
|
||||
|
||||
|
||||
private void writeObject(ObjectOutputStream oos) throws IOException {
|
||||
oos.defaultWriteObject();
|
||||
oos.writeObject(new HashMap<Leaderboard, MetaLeaderboardColumn>(columnsForLeaderboards));
|
||||
oos.writeObject(new HashMap<Leaderboard, ScoreCorrectionListener>(scoreCorrectionChangeForwardersByLeaderboard));
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
|
||||
ois.defaultReadObject();
|
||||
columnsForLeaderboards = new WeakHashMap<>();
|
||||
scoreCorrectionChangeForwardersByLeaderboard = new WeakHashMap<Leaderboard, ScoreCorrectionListener>();
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<? extends Leaderboard, ? extends MetaLeaderboardColumn> columnsForLeaderboardAsStrongMap = (Map<? extends Leaderboard, ? extends MetaLeaderboardColumn>) ois.readObject();
|
||||
columnsForLeaderboards = new WeakHashMap<Leaderboard, MetaLeaderboardColumn>(columnsForLeaderboardAsStrongMap);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<? extends Leaderboard, ? extends ScoreCorrectionListener> scoreCorrectionChangeForwardersByLeaderboardAsStrongMap = (Map<? extends Leaderboard, ? extends ScoreCorrectionListener>) ois.readObject();
|
||||
scoreCorrectionChangeForwardersByLeaderboard = new WeakHashMap<Leaderboard, ScoreCorrectionListener>(scoreCorrectionChangeForwardersByLeaderboardAsStrongMap);
|
||||
}
|
||||
|
||||
public abstract Iterable<Leaderboard> getLeaderboards();
|
||||
@@ -134,7 +158,7 @@ public abstract class AbstractMetaLeaderboard extends AbstractSimpleLeaderboardI
|
||||
}
|
||||
|
||||
protected RaceColumn getColumnForLeaderboard(Leaderboard leaderboard) {
|
||||
RaceColumn result = columnsForLeaderboards.get(leaderboard);
|
||||
MetaLeaderboardColumn result = columnsForLeaderboards.get(leaderboard);
|
||||
if (result == null) {
|
||||
result = new MetaLeaderboardColumn(leaderboard, metaFleet);
|
||||
result.addRaceColumnListener(this);
|
||||
|
||||
+13
-6
@@ -435,6 +435,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
|
||||
directionFromStartToNextMarkCache = new HashMap<TimePoint, Future<Wind>>();
|
||||
crossTrackErrorCache = new CrossTrackErrorCache(this);
|
||||
maneuverCache = createManeuverCache();
|
||||
logger.info("Deserialized race " + getRace().getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1626,12 +1627,14 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
|
||||
clearDirectionFromStartToNextMarkCache();
|
||||
stopAndRemoveStartToNextMarkCacheInvalidationListener(waypointThatGotRemoved);
|
||||
Iterator<Waypoint> waypointsIter = getRace().getCourse().getWaypoints().iterator();
|
||||
waypointsIter.next(); // skip first
|
||||
if (waypointsIter.hasNext()) {
|
||||
waypointsIter.next(); // skip second
|
||||
if (waypointsIter.hasNext()) { // catches the case of a course being empty
|
||||
waypointsIter.next(); // skip first
|
||||
if (waypointsIter.hasNext()) {
|
||||
Waypoint newSecond = waypointsIter.next();
|
||||
addStartToNextMarkCacheInvalidationListener(newSecond);
|
||||
waypointsIter.next(); // skip second
|
||||
if (waypointsIter.hasNext()) {
|
||||
Waypoint newSecond = waypointsIter.next();
|
||||
addStartToNextMarkCacheInvalidationListener(newSecond);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2443,7 +2446,11 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
|
||||
|
||||
@Override
|
||||
public void attachRaceLog(RaceLog raceLog) {
|
||||
this.attachedRaceLogs.put(raceLog.getId(), raceLog);
|
||||
if (raceLog != null) {
|
||||
this.attachedRaceLogs.put(raceLog.getId(), raceLog);
|
||||
} else {
|
||||
logger.severe("Got a request to attach race log for an empty race log!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<stringAttribute key="com.google.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.GWTShell"/>
|
||||
<booleanAttribute key="com.google.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/>
|
||||
<listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES">
|
||||
<listEntry value="com.sap.sailing.gwt.ui.Simulator"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.PolarSheets"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="com.google.gwt.eclipse.core.URL" value="/gwt/AdminConsole.html"/>
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
||||
@@ -21,7 +21,6 @@
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6" javaProject="com.sap.sailing.gwt.ui" path="1" type="4"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.gwt.ui/src/main/resources" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.gwt.ui/src/main/java" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.simulator/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.googlecode.java-diff-utils/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain.common/src" path="3" type="2"/> "/>
|
||||
@@ -48,7 +47,7 @@
|
||||
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/>
|
||||
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-war "${project_loc:com.sap.sailing.gwt.ui}" -noserver -remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/UserManagement.html com.sap.sailing.gwt.ui.UserManagement -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/TvView.html com.sap.sailing.gwt.ui.TvView -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.ui.RegattaOverview -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-war "${project_loc:com.sap.sailing.gwt.ui}" -noserver -remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/UserManagement.html com.sap.sailing.gwt.ui.UserManagement -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/TvView.html com.sap.sailing.gwt.ui.TvView -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.ui.PolarSheets"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m -XX:MaxPermSize=512m"/>
|
||||
</launchConfiguration>
|
||||
+18
-14
@@ -1490,24 +1490,28 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
|
||||
// set the positions of start and finish
|
||||
Waypoint firstWaypoint = course.getFirstWaypoint();
|
||||
if (firstWaypoint != null) {
|
||||
if (firstWaypoint != null && Util.size(firstWaypoint.getMarks())==2) {
|
||||
final LineLengthAndAdvantage markPositionDTOsAndLineAdvantage = trackedRace.getStartLine(dateAsTimePoint);
|
||||
final List<PositionDTO> startMarkPositionDTOs = getMarkPositionDTOs(dateAsTimePoint, trackedRace, firstWaypoint);
|
||||
result.startMarkPositions = startMarkPositionDTOs;
|
||||
result.startLineLengthInMeters = markPositionDTOsAndLineAdvantage.getLength().getMeters();
|
||||
result.startLineAngleToCombinedWind = markPositionDTOsAndLineAdvantage.getAbsoluteAngleDifferenceToTrueWind().getDegrees();
|
||||
result.startLineAdvantageousSide = markPositionDTOsAndLineAdvantage.getAdvantageousSideWhileApproachingLine();
|
||||
result.startLineAdvantageInMeters = markPositionDTOsAndLineAdvantage.getAdvantage().getMeters();
|
||||
if (markPositionDTOsAndLineAdvantage != null) {
|
||||
final List<PositionDTO> startMarkPositionDTOs = getMarkPositionDTOs(dateAsTimePoint, trackedRace, firstWaypoint);
|
||||
result.startMarkPositions = startMarkPositionDTOs;
|
||||
result.startLineLengthInMeters = markPositionDTOsAndLineAdvantage.getLength().getMeters();
|
||||
result.startLineAngleToCombinedWind = markPositionDTOsAndLineAdvantage.getAbsoluteAngleDifferenceToTrueWind().getDegrees();
|
||||
result.startLineAdvantageousSide = markPositionDTOsAndLineAdvantage.getAdvantageousSideWhileApproachingLine();
|
||||
result.startLineAdvantageInMeters = markPositionDTOsAndLineAdvantage.getAdvantage().getMeters();
|
||||
}
|
||||
}
|
||||
Waypoint lastWaypoint = course.getLastWaypoint();
|
||||
if (lastWaypoint != null) {
|
||||
if (lastWaypoint != null && Util.size(lastWaypoint.getMarks())==2) {
|
||||
final LineLengthAndAdvantage markPositionDTOsAndLineAdvantage = trackedRace.getFinishLine(dateAsTimePoint);
|
||||
final List<PositionDTO> finishMarkPositionDTOs = getMarkPositionDTOs(dateAsTimePoint, trackedRace, lastWaypoint);
|
||||
result.finishMarkPositions = finishMarkPositionDTOs;
|
||||
result.finishLineLengthInMeters = markPositionDTOsAndLineAdvantage.getLength().getMeters();
|
||||
result.finishLineAngleToCombinedWind = markPositionDTOsAndLineAdvantage.getAbsoluteAngleDifferenceToTrueWind().getDegrees();
|
||||
result.finishLineAdvantageousSide = markPositionDTOsAndLineAdvantage.getAdvantageousSideWhileApproachingLine();
|
||||
result.finishLineAdvantageInMeters = markPositionDTOsAndLineAdvantage.getAdvantage().getMeters();
|
||||
if (markPositionDTOsAndLineAdvantage != null) {
|
||||
final List<PositionDTO> finishMarkPositionDTOs = getMarkPositionDTOs(dateAsTimePoint, trackedRace, lastWaypoint);
|
||||
result.finishMarkPositions = finishMarkPositionDTOs;
|
||||
result.finishLineLengthInMeters = markPositionDTOsAndLineAdvantage.getLength().getMeters();
|
||||
result.finishLineAngleToCombinedWind = markPositionDTOsAndLineAdvantage.getAbsoluteAngleDifferenceToTrueWind().getDegrees();
|
||||
result.finishLineAdvantageousSide = markPositionDTOsAndLineAdvantage.getAdvantageousSideWhileApproachingLine();
|
||||
result.finishLineAdvantageInMeters = markPositionDTOsAndLineAdvantage.getAdvantage().getMeters();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -71,6 +71,7 @@ public class LeaderboardGroupMasterDataJsonSerializer implements JsonSerializer<
|
||||
jsonLeaderboardGroup.put(FIELD_DESCRIPTION, leaderboardGroup.getDescription());
|
||||
jsonLeaderboardGroup.put(FIELD_HAS_OVERALL_LEADERBOARD, leaderboardGroup.getOverallLeaderboard() != null);
|
||||
if (leaderboardGroup.getOverallLeaderboard() != null) {
|
||||
// TODO see bug 1605; the overall leaderboard's column factors also need to be serialized
|
||||
jsonLeaderboardGroup.put(FIELD_OVERALL_LEADERBOARD_DISCARDING_THRESHOLDS,
|
||||
LeaderboardMasterDataJsonSerializer.createJsonForResultDiscardingRule(leaderboardGroup
|
||||
.getOverallLeaderboard().getResultDiscardingRule()));
|
||||
|
||||
+11
-2
@@ -1632,7 +1632,7 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
|
||||
logger.info("Serializing persisted competitors...");
|
||||
oos.writeObject(competitorStore);
|
||||
logoutput.append("Serialized " + competitorStore.size() + " persisted competitors\n");
|
||||
logger.fine(logoutput.toString());
|
||||
logger.info(logoutput.toString());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -1659,6 +1659,7 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("Clearing all data structures...");
|
||||
regattaTrackingCache.clear();
|
||||
leaderboardGroupsByName.clear();
|
||||
leaderboardsByName.clear();
|
||||
@@ -1668,12 +1669,14 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
|
||||
|
||||
StringBuffer logoutput = new StringBuffer();
|
||||
|
||||
logger.info("Reading all events...");
|
||||
eventsById.putAll((Map<Serializable, Event>) ois.readObject());
|
||||
logoutput.append("\nReceived " + eventsById.size() + " NEW events\n");
|
||||
for (Event event : eventsById.values()) {
|
||||
logoutput.append(String.format("%3s\n", event.toString()));
|
||||
}
|
||||
|
||||
logger.info("Reading all regattas...");
|
||||
regattasByName.putAll((Map<String, Regatta>) ois.readObject());
|
||||
logoutput.append("Received " + regattasByName.size() + " NEW regattas\n");
|
||||
for (Regatta regatta : regattasByName.values()) {
|
||||
@@ -1682,19 +1685,23 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
|
||||
|
||||
// it is important that the leaderboards and tracked regattas are cleared before auto-linking to
|
||||
// old leaderboards takes place which then don't match the new ones
|
||||
logger.info("Reading all dynamic tracked regattas...");
|
||||
for (DynamicTrackedRegatta trackedRegattaToObserve : (Set<DynamicTrackedRegatta>) ois.readObject()) {
|
||||
ensureRegattaIsObservedForDefaultLeaderboardAndAutoLeaderboardLinking(trackedRegattaToObserve);
|
||||
}
|
||||
|
||||
logger.info("Reading all of the regatta tracking cache...");
|
||||
regattaTrackingCache.putAll((Map<Regatta, DynamicTrackedRegatta>) ois.readObject());
|
||||
logoutput.append("Received " + regattaTrackingCache.size() + " NEW regatta tracking cache entries\n");
|
||||
|
||||
logger.info("Reading leaderboard groups...");
|
||||
leaderboardGroupsByName.putAll((Map<String, LeaderboardGroup>) ois.readObject());
|
||||
logoutput.append("Received " + leaderboardGroupsByName.size() + " NEW leaderboard groups\n");
|
||||
for (LeaderboardGroup lg : leaderboardGroupsByName.values()) {
|
||||
logoutput.append(String.format("%3s\n", lg.toString()));
|
||||
}
|
||||
|
||||
logger.info("Reading leaderboards by name...");
|
||||
leaderboardsByName.putAll((Map<String, Leaderboard>) ois.readObject());
|
||||
logoutput.append("Received " + leaderboardsByName.size() + " NEW leaderboards\n");
|
||||
for (Leaderboard leaderboard : leaderboardsByName.values()) {
|
||||
@@ -1709,6 +1716,7 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("Reading media library...");
|
||||
mediaLibrary.deserialize(ois);
|
||||
logoutput.append("Received " + mediaLibrary.allTracks().size() + " NEW media tracks\n");
|
||||
for (MediaTrack mediatrack : mediaLibrary.allTracks()) {
|
||||
@@ -1717,14 +1725,15 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
|
||||
|
||||
// only copy the competitors from the deserialized competitor store; don't use it because it will have set
|
||||
// a default Mongo object factory
|
||||
logger.info("Reading competitors...");
|
||||
for (Competitor competitor : ((CompetitorStore) ois.readObject()).getCompetitors()) {
|
||||
DynamicCompetitor dynamicCompetitor = (DynamicCompetitor) competitor;
|
||||
competitorStore.getOrCreateCompetitor(dynamicCompetitor.getId(), dynamicCompetitor.getName(), dynamicCompetitor.getTeam(), dynamicCompetitor.getBoat());
|
||||
}
|
||||
logoutput.append("\nReceived " + competitorStore.size() + " NEW competitors\n");
|
||||
|
||||
logger.info(logoutput.toString());
|
||||
logger.info("Done with initial replication on " + this);
|
||||
logger.info(logoutput.toString());
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(oldContextClassloader);
|
||||
}
|
||||
|
||||
+7
-5
@@ -169,8 +169,10 @@ public class RegattaDataPerRaceAction extends HttpAction {
|
||||
|
||||
final Element competitors_node = addNamedElement(race_node, "competitors"); // add node that contains all competitors
|
||||
|
||||
|
||||
for (Competitor competitor : trackedRace.getCompetitorsFromBestToWorst(trackedRace.getEndOfTracking())) {
|
||||
int rank = 0;
|
||||
List<Competitor> competitorsFromBestToWorst = leaderboard.getCompetitorsFromBestToWorst(trackedRace.getEndOfTracking());
|
||||
for (Competitor competitor : competitorsFromBestToWorst) {
|
||||
rank += 1;
|
||||
final Element competitor_node = addNamedElement(competitors_node, "competitor"); // add competitor node
|
||||
|
||||
try {
|
||||
@@ -200,9 +202,9 @@ public class RegattaDataPerRaceAction extends HttpAction {
|
||||
addNamedElementWithValue(competitor_node, "sail_id_formatted", sail_id);
|
||||
}
|
||||
|
||||
addNamedElementWithValue(competitor_node, "race_final_rank", trackedRace.getRank(competitor, now));
|
||||
addNamedElementWithValue(competitor_node, "race_final_rank", rank);
|
||||
addNamedElementWithValue(competitor_node, "race_participants", trackedRace.getCompetitorsFromBestToWorst(trackedRace.getStartOfTracking()).size());
|
||||
addNamedElementWithValue(competitor_node, "race_relative_final_rank", 1.0 - ((trackedRace.getRank(competitor, now) - 1.0)/(trackedRace.getCompetitorsFromBestToWorst(trackedRace.getStartOfTracking()).size() - 1.0)));
|
||||
addNamedElementWithValue(competitor_node, "race_relative_final_rank", 1.0 - ((rank - 1.0)/(leaderboard.getCompetitorsFromBestToWorst(trackedRace.getStartOfTracking()).size() - 1.0)));
|
||||
|
||||
addNamedElementWithValue(competitor_node, "distance_traveled_m", trackedRace.getDistanceTraveled(competitor, trackedRace.getEndOfTracking()).getMeters());
|
||||
addNamedElementWithValue(competitor_node, "avg_xte_m", trackedRace.getAverageCrossTrackError(competitor, trackedRace.getEndOfTracking(), true).getMeters());
|
||||
@@ -278,7 +280,7 @@ public class RegattaDataPerRaceAction extends HttpAction {
|
||||
addNamedElementWithValue(competitor_node, "rank_gains", posGLlist.toString()); // Ranks Gained/Lost
|
||||
|
||||
addNamedElementWithValue(competitor_node, "rank_after_first_leg", rankAfterFirstLeg); // Rank after first leg
|
||||
addNamedElementWithValue(competitor_node, "rank_gain_between_first_and_finish", rankAfterFirstLeg - trackedRace.getRank(competitor, now)); // Rank gain between first leg and finish
|
||||
addNamedElementWithValue(competitor_node, "rank_gain_between_first_and_finish", rankAfterFirstLeg - rank); // Rank gain between first leg and finish
|
||||
|
||||
addNamedElementWithValue(competitor_node, "race_time_s", race_time);
|
||||
|
||||
|
||||
+3
-1
@@ -56,4 +56,6 @@ The links above lead to short write-ups of the respective business case behind t
|
||||
|
||||
[[ISAF-Internal Projects|wiki/planning/ISAFInternalProjects]]
|
||||
|
||||
[[Microcopter Integration|wiki/planning/Microcopter]]
|
||||
[[Microcopter Integration|wiki/planning/Microcopter]]
|
||||
|
||||
[[Race Rendering Technology|wiki/planning/RaceRenderingTechnology]]
|
||||
@@ -0,0 +1,78 @@
|
||||
# Rendering Technologies for Races
|
||||
|
||||
Here we want to collect technology options to build a new innovative race viewer.
|
||||
|
||||
## Usage scenarios
|
||||
* TV + data overlays
|
||||
* Deep analytics
|
||||
* Casual user race viewer
|
||||
* Big screen / public viewing
|
||||
* Raw data viewer (jury support)
|
||||
* Moderator cockpit
|
||||
|
||||
## Unity Gaming Engine
|
||||
Unity is a cross-platform game engine with a built-in IDE developed by Unity Technologies. It is used to develop video games for web plugins, desktop platforms, consoles and mobile devices. It grew from an OS X supported game development tool in 2005 to a multi-platform game engine.
|
||||
|
||||
The latest update, Unity 4.3, was released November 2013. It currently supports development for iOS, Android, Windows, BlackBerry 10, OS X, Linux, web browsers, Flash, PlayStation 3, Xbox 360, Windows Phone 8, and Wii. Two versions of the game engine are available for download, Unity and Unity Pro.
|
||||
|
||||
* Product Owner: Unity
|
||||
* Web: http://unity3d.com/
|
||||
* Unity 4.3 and 2D: http://unity3d.com/unity/whats-new/unity-4.3
|
||||
* Web Player Support: http://unity3d.com/webplayer/
|
||||
* Mobile Support: http://unity3d.com/unity/multiplatform/mobile
|
||||
|
||||
## OpenLayers v3
|
||||
OpenLayers is a JavaScript library for displaying map data in web browsers. It provides an API for building rich web-based geographic applications similar to Google Maps and Bing Maps.
|
||||
* Product Owner: Opensource
|
||||
* Web: http://ol3js.org/
|
||||
* Demos: http://ol3js.org/en/master/examples/
|
||||
* Map rotation demo : http://ol3js.org/en/master/examples/drag-rotate-and-zoom.html
|
||||
* Licence: BSD
|
||||
|
||||
## Lienzo Framework
|
||||
Lienzo allows you to build scalable graphics applications (in Java) that will run in any browser or device that supports the HTML5 Canvas API, including smart phones and tablets.
|
||||
* Product Owner: Emitrom
|
||||
* Web: http://emitrom.com/lienzo
|
||||
* Demos: http://emitrom-lienzo.appspot.com/
|
||||
* Technology: GWT
|
||||
* Licence: Apache
|
||||
|
||||
## Google Maps
|
||||
* Product Owner: Google
|
||||
* Web: https://developers.google.com/maps/documentation/javascript/
|
||||
* Technology: Javascript
|
||||
* Licence: Google Licence
|
||||
|
||||
Google Maps based on WebGL
|
||||
|
||||
## CAAT: Canvas Advanced Animation Tookit
|
||||
CAAT is a director-based Scene graph manager.
|
||||
It is able to render using Canvas, WebGL and CSS without making changes to the applications that sit on top of it.
|
||||
* Product Owner
|
||||
* Web: https://github.com/hyperandroid/caat
|
||||
* Demos: http://hyperandroid.github.io/CAAT/documentation/demos/
|
||||
* Affine transformations demo: http://hyperandroid.github.io/CAAT/documentation/demos/demo7/anchors_org.html
|
||||
* Licence: MIT
|
||||
* Technology: Javascript
|
||||
|
||||
## D3
|
||||
D3 is a JavaScript library for manipulating documents based on data. D3 helps you bring data to life using HTML, SVG and CSS. D3’s emphasis on web standards gives you the full capabilities of modern browsers without tying yourself to a proprietary framework, combining powerful visualization components and a data-driven approach to DOM manipulation.
|
||||
* Product Owner: OpenSource
|
||||
* Web: http://d3js.org/
|
||||
* Demos: https://github.com/mbostock/d3/wiki/Gallery
|
||||
* Wind field demo: http://air.nullschool.net/
|
||||
* Technology: Javascript
|
||||
* Licence: BSD
|
||||
|
||||
## Standards to consider
|
||||
|
||||
### GeoJson
|
||||
* http://en.wikipedia.org/wiki/GeoJSON
|
||||
* MongoDB Geo support. http://docs.mongodb.org/manual/applications/geospatial-indexes/
|
||||
|
||||
### WebGL
|
||||
* http://en.wikipedia.org/wiki/WebGL
|
||||
* Demos: http://www.chromeexperiments.com/webgl/
|
||||
|
||||
## Other cool stuff
|
||||
* XNA Planet Renderer - Terrain & Ocean: http://www.youtube.com/watch?v=OiGADgezjC8
|
||||
@@ -0,0 +1,12 @@
|
||||
# Webdesign
|
||||
|
||||
This document contains some information for web designers and user interaction experts
|
||||
|
||||
### Layout Repository
|
||||
|
||||
#### Git
|
||||
|
||||
1. Get the content of the layout git repository
|
||||
Clone the repository to your local file system from `ssh://[SAP-User]@git.wdf.sap.corp:29418/SAPSail/sapsailing_layouts.git`
|
||||
|
||||
2. Check out the 'master' branch from the git repository. The 'master' branch is the main branch. Please check that you start your work on this branch.
|
||||
Reference in new issue
Block a user