diff --git a/README b/README deleted file mode 100644 index de37fc78386..00000000000 --- a/README +++ /dev/null @@ -1 +0,0 @@ -This branch will contain a sailing simulator diff --git a/home.md b/home.md index 009119af613..c84bd2926fa 100644 --- a/home.md +++ b/home.md @@ -18,6 +18,7 @@ Like businesses, sailors need the latest information to make strategic decisions * [[Cook Book|wiki/cook-book]] * [[OnBoarding Information|wiki/onboarding]] * [[Building and Deploying|wiki/building-and-deploying]] + * [[Continuous Integration with Hudson/Jenkins|wiki/ci]] * [[UI Tests with Selenium|wiki/selenium-ui-tests]] * [[Typical Development Scenarios|wiki/typical-development-scenarios]] * [[Server Replication|wiki/server-replication]] diff --git a/java/com.google.gwt.osgi/META-INF/MANIFEST.MF b/java/com.google.gwt.osgi/META-INF/MANIFEST.MF index ad79717c61c..3ebccfdf386 100755 --- a/java/com.google.gwt.osgi/META-INF/MANIFEST.MF +++ b/java/com.google.gwt.osgi/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Osgi Bundle-SymbolicName: com.google.gwt.osgi -Bundle-Version: 2.5.1.qualifier +Bundle-Version: 2.6.0.qualifier Bundle-Vendor: GOOGLE Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Bundle-ClassPath: lib/gwt-dev.jar, @@ -29,16 +29,10 @@ Export-Package: com.gargoylesoftware.htmlunit, com.gargoylesoftware.htmlunit.protocol.javascript, com.gargoylesoftware.htmlunit.util, com.gargoylesoftware.htmlunit.xml, - com.google.common.base, - com.google.common.cache, com.google.gwt.activity.shared, com.google.gwt.animation.client, com.google.gwt.animation.client.testing, com.google.gwt.aria.client, - com.google.gwt.benchmarks, - com.google.gwt.benchmarks.client, - com.google.gwt.benchmarks.client.impl, - com.google.gwt.benchmarks.rebind, com.google.gwt.canvas.client, com.google.gwt.canvas.dom.client, com.google.gwt.cell.client, @@ -204,28 +198,10 @@ Export-Package: com.gargoylesoftware.htmlunit, com.google.gwt.thirdparty.javascript.jscomp.ant, com.google.gwt.thirdparty.javascript.jscomp.deps, com.google.gwt.thirdparty.javascript.jscomp.graph, - com.google.gwt.thirdparty.javascript.jscomp.mozilla.rhino, - com.google.gwt.thirdparty.javascript.jscomp.mozilla.rhino.annotations, - com.google.gwt.thirdparty.javascript.jscomp.mozilla.rhino.ast, - com.google.gwt.thirdparty.javascript.jscomp.mozilla.rhino.debug, - com.google.gwt.thirdparty.javascript.jscomp.mozilla.rhino.jdk13, - com.google.gwt.thirdparty.javascript.jscomp.mozilla.rhino.jdk15, - com.google.gwt.thirdparty.javascript.jscomp.mozilla.rhino.json, - com.google.gwt.thirdparty.javascript.jscomp.mozilla.rhino.optimizer, - com.google.gwt.thirdparty.javascript.jscomp.mozilla.rhino.regexp, - com.google.gwt.thirdparty.javascript.jscomp.mozilla.rhino.serialize, - com.google.gwt.thirdparty.javascript.jscomp.mozilla.rhino.tools, - com.google.gwt.thirdparty.javascript.jscomp.mozilla.rhino.tools.debugger, - com.google.gwt.thirdparty.javascript.jscomp.mozilla.rhino.tools.debugger.treetable, - com.google.gwt.thirdparty.javascript.jscomp.mozilla.rhino.tools.idswitch, - com.google.gwt.thirdparty.javascript.jscomp.mozilla.rhino.tools.jsc, - com.google.gwt.thirdparty.javascript.jscomp.mozilla.rhino.tools.shell, - com.google.gwt.thirdparty.javascript.jscomp.mozilla.rhino.xml, com.google.gwt.thirdparty.javascript.jscomp.parsing, com.google.gwt.thirdparty.javascript.jscomp.regex, com.google.gwt.thirdparty.javascript.rhino, com.google.gwt.thirdparty.javascript.rhino.jstype, - com.google.gwt.thirdparty.mozilla.classfile, com.google.gwt.thirdparty.streamhtmlparser, com.google.gwt.thirdparty.streamhtmlparser.impl, com.google.gwt.thirdparty.streamhtmlparser.util, @@ -261,7 +237,6 @@ Export-Package: com.gargoylesoftware.htmlunit, com.google.gwt.user.server.rpc, com.google.gwt.user.server.rpc.core.java.lang, com.google.gwt.user.server.rpc.core.java.util, - com.google.gwt.user.server.rpc.core.java.util.logging, com.google.gwt.user.server.rpc.impl, com.google.gwt.user.tools, com.google.gwt.user.tools.util, @@ -339,7 +314,6 @@ Export-Package: com.gargoylesoftware.htmlunit, net.sourceforge.htmlunit.corejs.javascript.serialize, net.sourceforge.htmlunit.corejs.javascript.tools, net.sourceforge.htmlunit.corejs.javascript.tools.debugger, - net.sourceforge.htmlunit.corejs.javascript.tools.debugger.downloaded, net.sourceforge.htmlunit.corejs.javascript.tools.debugger.treetable, net.sourceforge.htmlunit.corejs.javascript.tools.shell, net.sourceforge.htmlunit.corejs.javascript.xml, @@ -375,14 +349,6 @@ Export-Package: com.gargoylesoftware.htmlunit, org.apache.commons.io.filefilter, org.apache.commons.io.input, org.apache.commons.io.output, - org.apache.commons.lang, - org.apache.commons.lang.builder, - org.apache.commons.lang.enums, - org.apache.commons.lang.exception, - org.apache.commons.lang.math, - org.apache.commons.lang.mutable, - org.apache.commons.lang.text, - org.apache.commons.lang.time, org.apache.commons.logging, org.apache.commons.logging.impl, org.apache.html.dom, @@ -577,27 +543,7 @@ Export-Package: com.gargoylesoftware.htmlunit, org.eclipse.jdt.internal.core.util, org.hibernate.validator, org.hibernate.validator.engine, - org.jdesktop.swingworker, - org.mortbay.component, - org.mortbay.io, - org.mortbay.io.bio, - org.mortbay.io.nio, - org.mortbay.jetty, - org.mortbay.jetty.bio, - org.mortbay.jetty.deployer, - org.mortbay.jetty.handler, - org.mortbay.jetty.nio, - org.mortbay.jetty.security, - org.mortbay.jetty.servlet, - org.mortbay.jetty.webapp, - org.mortbay.log, - org.mortbay.resource, - org.mortbay.servlet, - org.mortbay.servlet.jetty, - org.mortbay.thread, - org.mortbay.util, - org.mortbay.util.ajax, - org.mortbay.xml + org.jdesktop.swingworker Require-Bundle: javax.validation;bundle-version="1.0.0" -Import-Package: javax.servlet;version="2.5.0", - javax.servlet.http;version="2.5.0" +Import-Package: javax.servlet;version="2.6.0", + javax.servlet.http;version="2.6.0" diff --git a/java/com.google.gwt.osgi/lib/gwt-dev.jar b/java/com.google.gwt.osgi/lib/gwt-dev.jar index 9eac2483b3d..a160825141c 100755 Binary files a/java/com.google.gwt.osgi/lib/gwt-dev.jar and b/java/com.google.gwt.osgi/lib/gwt-dev.jar differ diff --git a/java/com.google.gwt.osgi/lib/gwt-user.jar b/java/com.google.gwt.osgi/lib/gwt-user.jar index 23e450f6a8a..a74abb888b4 100755 Binary files a/java/com.google.gwt.osgi/lib/gwt-user.jar and b/java/com.google.gwt.osgi/lib/gwt-user.jar differ diff --git a/java/com.google.gwt.osgi/pom.xml b/java/com.google.gwt.osgi/pom.xml index c4f2099a8d5..7085429e5ca 100644 --- a/java/com.google.gwt.osgi/pom.xml +++ b/java/com.google.gwt.osgi/pom.xml @@ -8,6 +8,6 @@ 1.0.0-SNAPSHOT com.google.gwt.osgi - 2.5.1-SNAPSHOT + 2.6.0-SNAPSHOT eclipse-plugin diff --git a/java/com.sap.sailing.datamining.shared/META-INF/MANIFEST.MF b/java/com.sap.sailing.datamining.shared/META-INF/MANIFEST.MF index 0bb7ee2b471..d99a71e68eb 100644 --- a/java/com.sap.sailing.datamining.shared/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.datamining.shared/META-INF/MANIFEST.MF @@ -9,5 +9,4 @@ Bundle-ActivationPolicy: lazy Bundle-ClassPath: . Export-Package: com.sap.sailing.datamining.shared, com.sap.sailing.datamining.shared.impl -Import-Package: com.google.gwt.i18n.client Require-Bundle: com.sap.sse.datamining.shared;bundle-version="1.0.0" diff --git a/java/com.sap.sailing.datamining/.classpath b/java/com.sap.sailing.datamining/.classpath index e15e4b3e412..f9609b26c9e 100644 --- a/java/com.sap.sailing.datamining/.classpath +++ b/java/com.sap.sailing.datamining/.classpath @@ -1,6 +1,5 @@ - diff --git a/java/com.sap.sailing.datamining/META-INF/MANIFEST.MF b/java/com.sap.sailing.datamining/META-INF/MANIFEST.MF index 18c5247894a..55ba7a730cb 100644 --- a/java/com.sap.sailing.datamining/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.datamining/META-INF/MANIFEST.MF @@ -5,8 +5,7 @@ Bundle-SymbolicName: com.sap.sailing.datamining Bundle-Version: 1.0.0.qualifier Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.7 -Import-Package: com.google.gwt.i18n.client, - com.sap.sailing.server, +Import-Package: com.sap.sailing.server, org.osgi.framework;version="1.7.0" Export-Package: com.sap.sailing.datamining, com.sap.sailing.datamining.data, diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/DetailType.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/DetailType.java index 53e9f558845..e9c6215c65a 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/DetailType.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/DetailType.java @@ -33,8 +33,7 @@ public enum DetailType implements Serializable { TOTAL_DISTANCE_TRAVELED(0, ASCENDING), TOTAL_AVERAGE_SPEED_OVER_GROUND(2, DESCENDING), TOTAL_TIME_SAILED_IN_SECONDS(1, ASCENDING), RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS(2, DESCENDING), RACE_TOTAL_POINTS(2, ASCENDING), REGATTA_TOTAL_POINTS(2, ASCENDING), - RACE_TIME_SINCE_LAST_POSITION_FIX_IN_SECONDS(0 , ASCENDING), - RACE_TRACKING_QUALITY(0 , ASCENDING), RACE_DISTANCE_TO_START_FIVE_SECONDS_BEFORE_RACE_START(1, ASCENDING), + RACE_RATIO_BETWEEN_TIME_SINCE_LAST_POSITION_FIX_AND_AVERAGE_SAMPLING_INTERVAL(1, ASCENDING), RACE_DISTANCE_TO_START_FIVE_SECONDS_BEFORE_RACE_START(1, ASCENDING), RACE_SPEED_OVER_GROUND_FIVE_SECONDS_BEFORE_START(2, DESCENDING), RACE_TIME_TRAVELED(0, ASCENDING), RACE_TIME_TRAVELED_UPWIND(0, ASCENDING), RACE_TIME_TRAVELED_DOWNWIND(0, ASCENDING), RACE_TIME_TRAVELED_REACHING(0, ASCENDING), DISTANCE_TO_START_LINE(0, ASCENDING), BEAT_ANGLE(0, ASCENDING); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoRaceLogStoreFactory.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoRaceLogStoreFactory.java index 18e70f18e5a..7f791550902 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoRaceLogStoreFactory.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoRaceLogStoreFactory.java @@ -2,6 +2,8 @@ package com.sap.sailing.domain.persistence; import com.sap.sailing.domain.persistence.impl.MongoRaceLogStoreFactoryImpl; +import com.sap.sailing.domain.racelog.RaceLogEventVisitor; +import com.sap.sailing.domain.racelog.RaceLogIdentifier; import com.sap.sailing.domain.racelog.RaceLogStore; public interface MongoRaceLogStoreFactory { @@ -12,4 +14,6 @@ public interface MongoRaceLogStoreFactory { * and mongo.dbName[=<contents of constant {@link #DEFAULT_DB_NAME}>] specified in the bundle context */ RaceLogStore getMongoRaceLogStore(MongoObjectFactory mongoObjectFactory, DomainObjectFactory domainObjectFactory); + + RaceLogEventVisitor getMongoRaceLogStoreVisitor(RaceLogIdentifier identifier, MongoObjectFactory mongoObjectFactory); } diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreFactoryImpl.java index 2692e1ef9a3..f15d80bbf17 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreFactoryImpl.java @@ -1,9 +1,10 @@ package com.sap.sailing.domain.persistence.impl; - import com.sap.sailing.domain.persistence.DomainObjectFactory; import com.sap.sailing.domain.persistence.MongoObjectFactory; import com.sap.sailing.domain.persistence.MongoRaceLogStoreFactory; +import com.sap.sailing.domain.racelog.RaceLogEventVisitor; +import com.sap.sailing.domain.racelog.RaceLogIdentifier; import com.sap.sailing.domain.racelog.RaceLogStore; public class MongoRaceLogStoreFactoryImpl implements MongoRaceLogStoreFactory { @@ -11,4 +12,9 @@ public class MongoRaceLogStoreFactoryImpl implements MongoRaceLogStoreFactory { public RaceLogStore getMongoRaceLogStore(MongoObjectFactory mongoObjectFactory, DomainObjectFactory domainObjectFactory) { return new MongoRaceLogStoreImpl(mongoObjectFactory, domainObjectFactory); } + + @Override + public RaceLogEventVisitor getMongoRaceLogStoreVisitor(RaceLogIdentifier identifier, MongoObjectFactory mongoObjectFactory) { + return new MongoRaceLogStoreVisitor(identifier, mongoObjectFactory); + } } diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogTest.java index ff074f84b98..cbdc055cc66 100644 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogTest.java @@ -5,6 +5,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -29,12 +30,28 @@ import com.sap.sailing.domain.racelog.RaceLogEventVisitor; import com.sap.sailing.domain.racelog.RaceLogFlagEvent; import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent; import com.sap.sailing.domain.racelog.impl.RaceLogEventAuthorImpl; +import com.sap.sailing.domain.racelog.impl.RaceLogEventImpl; import com.sap.sailing.domain.racelog.impl.RaceLogImpl; public class RaceLogTest { private RaceLog raceLog; + private static class MockRaceLogEventForSorting extends RaceLogEventImpl { + public MockRaceLogEventForSorting(long createdAtMillis) { + super(new MillisecondsTimePoint(createdAtMillis), + /* author */ new RaceLogEventAuthorImpl("Dummy Author", /* priority */ 0), + MillisecondsTimePoint.now(), /* ID */ UUID.randomUUID(), /* pInvolvedBoats */ null, /* pass ID */ 1); + } + + private static final long serialVersionUID = 4928452859543831451L; + + @Override + public void accept(RaceLogEventVisitor visitor) { + } + + } + @Before public void setUp() { raceLog = new RaceLogImpl("testlock", "test-identifier"); @@ -66,6 +83,158 @@ public class RaceLogTest { assertEquals(event, Util.get(raceLog.getRawFixes(), 0)); raceLog.unlockAfterRead(); } + + private RaceLog merge(long[] intoTimePoints, long[] mergeTimePoints) { + RaceLog into = new RaceLogImpl(UUID.randomUUID()); + RaceLog merge = new RaceLogImpl(UUID.randomUUID()); + for (long l : intoTimePoints) { + into.add(new MockRaceLogEventForSorting(l)); + } + for (long l : mergeTimePoints) { + merge.add(new MockRaceLogEventForSorting(l)); + } + into.merge(merge); + return into; + } + + @Test + public void testSimpleMergeOfEmptyLog() { + RaceLog into = merge(new long[] { 123, 234 }, new long[] {}); + into.lockForRead(); + try { + assertEquals(2, Util.size(into.getRawFixes())); + assertBefore(into, 123, 234); + } finally { + into.unlockAfterRead(); + } + } + + /** + * Asserts that both, events with creation time stamp millis eventOne and eventTwo occur + * in log and the one with eventOne occurs before the one with eventTwo in + * the log's raw fixes iteration order. + */ + private void assertBefore(RaceLog log, long eventOne, long eventTwo) { + log.lockForRead(); + boolean foundEventOne = false; + try { + for (RaceLogEvent e : log.getRawFixes()) { + if (e.getCreatedAt().asMillis() == eventOne) { + foundEventOne = true; + } else if (e.getCreatedAt().asMillis() == eventTwo) { + if (foundEventOne) { + break; // all is good + } else { + fail("Found "+eventTwo+" before "+eventOne+" but expected to find them in the opposite order"); + } + } + } + } finally { + log.unlockAfterRead(); + } + } + + @Test + public void testSimpleMergeIntoEmptyLog() { + RaceLog into = merge(new long[0], new long[] { 123, 234 }); + into.lockForRead(); + try { + assertEquals(2, Util.size(into.getRawFixes())); + assertBefore(into, 123, 234); + } finally { + into.unlockAfterRead(); + } + } + + @Test + public void testSimpleMergeOfLogWithOneElementToTheMiddle() { + RaceLog into = merge(new long[] { 123, 234 }, new long[] { 200 }); + into.lockForRead(); + try { + assertEquals(3, Util.size(into.getRawFixes())); + assertBefore(into, 123, 200); + assertBefore(into, 200, 234); + } finally { + into.unlockAfterRead(); + } + } + + @Test + public void testSimpleMergeOfLogWithOneElementToTheBeginning() { + RaceLog into = merge(new long[] { 123, 234 }, new long[] { 100 }); + into.lockForRead(); + try { + assertEquals(3, Util.size(into.getRawFixes())); + assertBefore(into, 100, 123); + assertBefore(into, 123, 234); + } finally { + into.unlockAfterRead(); + } + } + + @Test + public void testSimpleMergeOfLogWithOneElementToTheEnd() { + RaceLog into = merge(new long[] { 123, 234 }, new long[] { 345 }); + into.lockForRead(); + try { + assertEquals(3, Util.size(into.getRawFixes())); + assertBefore(into, 123, 234); + assertBefore(into, 234, 345); + } finally { + into.unlockAfterRead(); + } + } + + @Test + public void testSimpleMergeOfLogWithThreeElementsAroundTwoOthers() { + RaceLog into = merge(new long[] { 123, 234 }, new long[] { 100, 200, 345 }); + into.lockForRead(); + try { + assertEquals(5, Util.size(into.getRawFixes())); + assertBefore(into, 100, 123); + assertBefore(into, 123, 200); + assertBefore(into, 200, 234); + assertBefore(into, 234, 345); + } finally { + into.unlockAfterRead(); + } + } + + @Test + public void testSimpleMergeOfLogWithSequencesOfElementsAroundTwoOthers() { + RaceLog into = merge(new long[] { 123, 234 }, new long[] { 100, 101, 200, 201, 345, 346 }); + into.lockForRead(); + try { + assertEquals(8, Util.size(into.getRawFixes())); + assertBefore(into, 100, 101); + assertBefore(into, 101, 123); + assertBefore(into, 123, 200); + assertBefore(into, 200, 201); + assertBefore(into, 201, 234); + assertBefore(into, 234, 345); + assertBefore(into, 234, 346); + } finally { + into.unlockAfterRead(); + } + } + + @Test + public void testSimpleMergeOfLogWithTwoElementsAroundSequenceOfOthers() { + RaceLog into = merge(new long[] { 100, 101, 200, 201, 345, 346 }, new long[] { 123, 234 }); + into.lockForRead(); + try { + assertEquals(8, Util.size(into.getRawFixes())); + assertBefore(into, 100, 101); + assertBefore(into, 101, 123); + assertBefore(into, 123, 200); + assertBefore(into, 200, 201); + assertBefore(into, 201, 234); + assertBefore(into, 234, 345); + assertBefore(into, 234, 346); + } finally { + into.unlockAfterRead(); + } + } @Test public void testAddEventDifferentPassButSameTimePoint() { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLog.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLog.java index 5a6a248b3b0..f364f7cc475 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLog.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLog.java @@ -98,4 +98,9 @@ public interface RaceLog extends Track, WithID { * in this race log yet */ boolean load(RaceLogEvent event); + + /** + * Merges all events from the other race log into this. + */ + void merge(RaceLog other); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/NoAddingRaceLogWrapper.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/NoAddingRaceLogWrapper.java index 49f99c4c7c8..4a29b026ce7 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/NoAddingRaceLogWrapper.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/NoAddingRaceLogWrapper.java @@ -210,4 +210,9 @@ public class NoAddingRaceLogWrapper implements RaceLog { public Duration getAverageIntervalBetweenRawFixes() { return innerRaceLog.getAverageIntervalBetweenRawFixes(); } + + @Override + public void merge(RaceLog other) { + innerRaceLog.merge(other); + } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogImpl.java index 0219c4f792e..6e8d605cc8b 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogImpl.java @@ -5,6 +5,7 @@ import java.io.ObjectInputStream; import java.io.Serializable; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Map; import java.util.NavigableSet; @@ -278,4 +279,48 @@ public class RaceLogImpl extends TrackImpl implements RaceLog { edtc.addAll(result); return result; } + + @Override + public void merge(RaceLog other) { + lockForWrite(); + other.lockForRead(); + try { + RaceLogEventComparator comparator = RaceLogEventComparator.INSTANCE; + Iterator thisIter = getRawFixes().iterator(); + Iterator otherIter = other.getRawFixes().iterator(); + RaceLogEvent thisEvent = null; + RaceLogEvent otherEvent = null; + while (otherIter.hasNext() || otherEvent != null) { + if (thisEvent == null && thisIter.hasNext()) { + thisEvent = thisIter.next(); + } + if (otherEvent == null) { + otherEvent = otherIter.next(); + } + if (thisEvent == null) { + // All events of this race log have been consumed; simply keep adding the events + // from the other race log to this race log. + // otherEvent has to be non-null because if thisIter didn't have a next, otherIter must have had a next + add(otherEvent); + otherEvent = null; // "consumed" otherEvent; try to grab next if a next element exists in otherIter + } else { + final int comparison = comparator.compare(thisEvent, otherEvent); + if (comparison < 0) { + thisEvent = null; // skip the "lesser" race log event on this race log + } else if (comparison == 0) { + // the race log event from the other log is already contained in this log; skip both + thisEvent = null; + otherEvent = null; + } else { + // comparison > 0; we skipped on this race log until we found a "greater" event on this race log; insert otherEvent + add(otherEvent); + otherEvent = null; // "consumed" + } + } + } + } finally { + other.unlockAfterRead(); + unlockAfterWrite(); + } + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java index fb43e881705..6f525493686 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java @@ -186,11 +186,8 @@ public interface RaceColumn extends Named { /** * Sets (or reloads) {@link RaceLog} for this column with the given fleet - * - * @param raceLogInformation - * @param fleetImpl */ - void setOrReloadRaceLogInformation(RaceLogInformation raceLogInformation, Fleet fleetImpl); + void setOrReloadRaceLogInformation(RaceLogInformation raceLogInformation, Fleet fleet); /** * Remove the association between a race and a column. This is different from diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java index faee1a650c5..901546fae10 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java @@ -2,9 +2,7 @@ package com.sap.sailing.domain.base.impl; import java.io.IOException; import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; @@ -14,7 +12,6 @@ import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.impl.Util; import com.sap.sailing.domain.racelog.RaceLog; -import com.sap.sailing.domain.racelog.RaceLogEventVisitor; import com.sap.sailing.domain.racelog.RaceLogIdentifier; import com.sap.sailing.domain.racelog.RaceLogIdentifierTemplate; import com.sap.sailing.domain.racelog.RaceLogInformation; @@ -25,7 +22,7 @@ import com.sap.sailing.domain.tracking.TrackedRace; public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implements RaceColumn { private static final long serialVersionUID = -7801617988982540470L; - private Map trackedRaces; + private TrackedRaces trackedRaces; private Map raceIdentifiers; private Map raceLogs; @@ -38,25 +35,11 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem private transient RaceLogInformation raceLogInformation; private RaceLogIdentifierTemplate raceLogIdentifierTemplate; - /** - * we don't want the TrackedRaces to be serialized during a master data export. Thus, we need this thread flag which - * is true only during master data export - */ - private transient ThreadLocal ongoingMasterDataExport; - public AbstractRaceColumn() { - this.trackedRaces = new HashMap(); + this.trackedRaces = new TrackedRaces(); this.raceIdentifiers = new HashMap(); this.raceLogs = new HashMap(); - this.ongoingMasterDataExport = createOngoingMasterDataExportThreadLocal(); - } - - private ThreadLocal createOngoingMasterDataExportThreadLocal() { - return new ThreadLocal() { - protected Boolean initialValue() { - return false; - }; - }; + } @Override @@ -176,48 +159,30 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem } @Override - public void setOrReloadRaceLogInformation(RaceLogInformation information, Fleet fleetImpl) { + public void setOrReloadRaceLogInformation(RaceLogInformation information, Fleet fleet) { synchronized(raceLogs) { raceLogInformation = information; RaceLogStore store = information.getStore(); - HashSet listeners = new HashSet(); - RaceLog raceLogAvailable = raceLogs.get(fleetImpl); - if (raceLogAvailable != null) { - store.removeListenersAddedByStoreFrom(raceLogAvailable); - listeners = raceLogAvailable.removeAllListeners(); - raceLogs.remove(fleetImpl); - } - raceLogIdentifierTemplate = raceLogInformation.getIdentifierTemplate(); - RaceLogIdentifier identifier = raceLogIdentifierTemplate.compileRaceLogIdentifier(fleetImpl); - RaceLog raceLog = store.getRaceLog(identifier, /*ignoreCache*/ true); - - if (listeners.isEmpty()) { + RaceLogIdentifier identifier = raceLogIdentifierTemplate.compileRaceLogIdentifier(fleet); + RaceLog newOrLoadedRaceLog = store.getRaceLog(identifier, /*ignoreCache*/ true); + RaceLog raceLogAvailable = raceLogs.get(fleet); + if (raceLogAvailable == null) { RaceColumnRaceLogReplicator listener = new RaceColumnRaceLogReplicator(this, identifier); - raceLog.addListener(listener); + newOrLoadedRaceLog.addListener(listener); + raceLogs.put(fleet, newOrLoadedRaceLog); } else { - raceLog.addAllListeners(listeners); + // now add all race log events from newOrLoadedRaceLog that are not already in raceLogAvailable + raceLogAvailable.merge(newOrLoadedRaceLog); } - raceLogs.put(fleetImpl, raceLog); } } /** * When deserializing, replication listeners are registered on all race logs. */ - @SuppressWarnings("unchecked") - private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { - this.ongoingMasterDataExport = createOngoingMasterDataExportThreadLocal(); - // Check if master data export is ongoing - boolean masterDataImportOngoing = ois.readBoolean(); - if (masterDataImportOngoing) { - this.trackedRaces = new HashMap(); - this.raceIdentifiers = (Map) ois.readObject(); - this.raceLogs = (Map) ois.readObject(); - this.raceLogIdentifierTemplate = (RaceLogIdentifierTemplate) ois.readObject(); - } else { - ois.defaultReadObject(); - } + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + ois.defaultReadObject(); for (Entry entry : raceLogs.entrySet()) { Fleet fleet = entry.getKey(); RaceLog raceLog = entry.getValue(); @@ -227,18 +192,7 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem @Override public void setMasterDataExportOngoingThreadFlag(boolean flagValue) { - ongoingMasterDataExport.set(flagValue); + trackedRaces.setMasterDataExportOngoingThreadFlag(flagValue); } - private void writeObject(ObjectOutputStream stream) throws IOException { - if (ongoingMasterDataExport.get()) { - stream.writeBoolean(true); - stream.writeObject(raceIdentifiers); - stream.writeObject(raceLogs); - stream.writeObject(raceLogIdentifierTemplate); - } else { - stream.writeBoolean(false); - stream.defaultWriteObject(); - } - } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/TrackedRaces.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/TrackedRaces.java new file mode 100644 index 00000000000..6dfbc055d7a --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/TrackedRaces.java @@ -0,0 +1,100 @@ +package com.sap.sailing.domain.base.impl; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.tracking.TrackedRace; + +/** + * Wraps the trackedRaces map in the {@link AbstractRaceColumn} allowing to serialize an empty map when a master data + * import is running by using the {@link ThreadLocal} flag {@link #ongoingMasterDataExport}. If the flag is + * false the map is serialized as is. + * + * + * @author Frederik Petersen (D054528) + * + */ +public class TrackedRaces implements Serializable { + + private static final long serialVersionUID = -5521115213267651333L; + + /** + * we don't want the TrackedRaces to be serialized during a master data export. Thus, we need this thread flag which + * is true only during master data export + */ + private transient ThreadLocal ongoingMasterDataExport; + + private Map trackedRaces; + + public TrackedRaces(Map trackedRaces) { + this.trackedRaces = trackedRaces; + this.ongoingMasterDataExport = createOngoingMasterDataExportThreadLocal(); + } + + public TrackedRaces() { + this(new HashMap()); + } + + public TrackedRace get(Fleet fleet) { + return trackedRaces.get(fleet); + } + + public void put(Fleet fleet, TrackedRace trackedRace) { + trackedRaces.put(fleet, trackedRace); + } + + public void remove(Fleet fleet) { + trackedRaces.remove(fleet); + } + + public Set> entrySet() { + return trackedRaces.entrySet(); + } + + public boolean isEmpty() { + return trackedRaces.isEmpty(); + } + + public Collection values() { + return trackedRaces.values(); + } + + private ThreadLocal createOngoingMasterDataExportThreadLocal() { + return new ThreadLocal() { + protected Boolean initialValue() { + return false; + }; + }; + } + + public void setMasterDataExportOngoingThreadFlag(boolean flagValue) { + ongoingMasterDataExport.set(flagValue); + } + + private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { + final boolean masterDataImportOngoing = ois.readBoolean(); + if (masterDataImportOngoing) { + trackedRaces = new HashMap<>(); + } else { + ois.defaultReadObject(); + } + this.ongoingMasterDataExport = createOngoingMasterDataExportThreadLocal(); + } + + private void writeObject(ObjectOutputStream oos) throws IOException { + final Boolean masterDataExportOngoing = ongoingMasterDataExport.get(); + oos.writeBoolean(masterDataExportOngoing); + if (!masterDataExportOngoing) { + oos.defaultWriteObject(); + } + } + +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/racelog/RaceLogIdentifierTemplate.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/racelog/RaceLogIdentifierTemplate.java index f97405a6793..35d705f030e 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/racelog/RaceLogIdentifierTemplate.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/racelog/RaceLogIdentifierTemplate.java @@ -9,29 +9,34 @@ import com.sap.sailing.domain.base.Fleet; *

* {LeaderboardName / RegattaName} + RaceColumnName + FleetName *

- * As the components of the RaceLogIdentifier are not available on RaceColumn level, we have to propagate the + * As the components of the RaceLogIdentifier are not available on RaceColumn level, we have to propagate the * information in this template data object. - * */ public interface RaceLogIdentifierTemplate extends Serializable { /** - * This method returns the name of parent object of the {@link RaceColumn}. This can be a {@link FlexibleLeaderboard} or a {@link Regatta}. + * This method returns the name of parent object of the {@link RaceColumn}. This can be a + * {@link FlexibleLeaderboard} or a {@link Regatta}. + * * @return the name of the parent object */ String getParentObjectName(); /** - * Compiles the template with giving the last component, the {@link Fleet}, to a RaceLogIdentifier that is used to retrieve the - * {@link RaceLogEvent}s from a RaceLogStore - * @param fleet the fleet of the race + * Compiles the template with giving the last component, the {@link Fleet}, to a RaceLogIdentifier that is used to + * retrieve the {@link RaceLogEvent}s from a RaceLogStore + * + * @param fleet + * the fleet of the race * @return the RaceLogIdentifier */ RaceLogIdentifier compileRaceLogIdentifier(Fleet fleet); /** * Resolves this RaceLogIdentifier template for replication with the help of the given resolver. - * @param resolver the resolver that resolves this template, either for {@link Leaderboard} or for {@link Regatta}. + * + * @param resolver + * the resolver that resolves this template, either for {@link Leaderboard} or for {@link Regatta}. */ void resolve(RaceLogIdentifierTemplateResolver resolver); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/util/impl/RaceColumnListeners.java b/java/com.sap.sailing.domain/src/com/sap/sailing/util/impl/RaceColumnListeners.java index 3fd17e9b759..32d21ec2be0 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/util/impl/RaceColumnListeners.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/util/impl/RaceColumnListeners.java @@ -151,11 +151,9 @@ public class RaceColumnListeners implements Serializable { } } - public void notifyListenersAboutRaceLogEventAdded(RaceColumn raceColumn, RaceLogIdentifier raceLogIdentifier, - RaceLogEvent event) { + public void notifyListenersAboutRaceLogEventAdded(RaceColumn raceColumn, RaceLogIdentifier raceLogIdentifier, RaceLogEvent event) { for (RaceColumnListener listener : getRaceColumnListeners()) { listener.raceLogEventAdded(raceColumn, raceLogIdentifier, event); } } - } diff --git a/java/com.sap.sailing.gwt.ui/CommonControls.css b/java/com.sap.sailing.gwt.ui/CommonControls.css index f610d184b15..86ac829d7e7 100644 --- a/java/com.sap.sailing.gwt.ui/CommonControls.css +++ b/java/com.sap.sailing.gwt.ui/CommonControls.css @@ -697,6 +697,20 @@ body ::-webkit-scrollbar-track { background-repeat: no-repeat; } +.minMaxBackgroundBarBad { + left: 0px; + background-image: url(images/redBar.png); + background-position: left; + background-repeat: no-repeat; +} + +.minMaxBackgroundBarGood { + left: 0px; + background-image: url(images/greenBar.png); + background-position: left; + background-repeat: no-repeat; +} + .inlineButton { height: 20px; padding: 0px 10px 3px; diff --git a/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF b/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF index 8b2b7c2f023..f0a5a043a25 100755 --- a/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF @@ -25,7 +25,7 @@ Require-Bundle: com.sap.sailing.domain, com.sap.sailing.domain.swisstimingreplayadapter, com.sap.sailing.simulator;bundle-version="1.0.0", de.csenk.gwt.ws, - com.google.gwt.osgi;bundle-version="2.5.1", + com.google.gwt.osgi;bundle-version="2.6.0", com.sap.sailing.domain.igtimiadapter, com.sap.sailing.datamining.shared;bundle-version="1.0.0", com.sap.sailing.datamining;bundle-version="1.0.0", diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling.launch b/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling.launch index 3b48a46e865..0f7980a58d2 100755 --- a/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling.launch @@ -1,53 +1,53 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT.launch b/java/com.sap.sailing.gwt.ui/SailingGWT.launch index 276fc714052..b23d6c67870 100755 --- a/java/com.sap.sailing.gwt.ui/SailingGWT.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT.launch @@ -49,7 +49,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/WEB-INF/lib/gwt-servlet.jar b/java/com.sap.sailing.gwt.ui/WEB-INF/lib/gwt-servlet.jar index c8ea21f4d48..2e85a1a4b52 100755 Binary files a/java/com.sap.sailing.gwt.ui/WEB-INF/lib/gwt-servlet.jar and b/java/com.sap.sailing.gwt.ui/WEB-INF/lib/gwt-servlet.jar differ diff --git a/java/com.sap.sailing.gwt.ui/images/greenBar.png b/java/com.sap.sailing.gwt.ui/images/greenBar.png new file mode 100755 index 00000000000..2b3b6fd5afb Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/greenBar.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/redBar.png b/java/com.sap.sailing.gwt.ui/images/redBar.png new file mode 100755 index 00000000000..060f3d81cbc Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/redBar.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/greyBar.png b/java/com.sap.sailing.gwt.ui/images/yellowBar.png similarity index 100% rename from java/com.sap.sailing.gwt.ui/images/greyBar.png rename to java/com.sap.sailing.gwt.ui/images/yellowBar.png diff --git a/java/com.sap.sailing.gwt.ui/pom.xml b/java/com.sap.sailing.gwt.ui/pom.xml index e3fbce9b646..c84263601d1 100644 --- a/java/com.sap.sailing.gwt.ui/pom.xml +++ b/java/com.sap.sailing.gwt.ui/pom.xml @@ -10,7 +10,7 @@ com.sap.sailing.gwt.ui eclipse-plugin - 2.5.1 + 2.6.0 @@ -79,7 +79,7 @@ org.codehaus.mojo gwt-maven-plugin - 2.5.1 + 2.6.0 diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/AsyncAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/AsyncAction.java index 5343f1a9188..88a52adf45b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/AsyncAction.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/AsyncAction.java @@ -10,13 +10,5 @@ import com.google.gwt.user.client.rpc.AsyncCallback; * @author c5163874 */ public interface AsyncAction { - void execute(AsyncActionsExecutor asyncActionsExecutor); - - Result getResult(); - - AsyncCallback getCallback(); - - AsyncCallback getWrapperCallback(AsyncActionsExecutor asyncActionsExecutor); - - String getType(); + public void execute(AsyncCallback callback); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/AsyncActionsExecutor.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/AsyncActionsExecutor.java index 20589284811..89c7ebf42e1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/AsyncActionsExecutor.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/AsyncActionsExecutor.java @@ -5,6 +5,10 @@ import java.util.Map; import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.rpc.AsyncCallback; + +import com.sap.sailing.gwt.ui.client.MarkedAsyncCallback; + /** * A executor class making the actual remote call for an {@link AsyncAction}. The class is managing the number of * executed actions in order to prevent a server overload. If the amount of actions to be executed exceeds a defined @@ -13,42 +17,99 @@ import com.google.gwt.core.client.GWT; * @author c5163874 */ public class AsyncActionsExecutor { - private Map> lastRequestedActions; - private int numPendingCalls; + private class ExecutionJob implements AsyncCallback { + private AsyncAction action; + private String category; + private AsyncCallback callback; + + public ExecutionJob(AsyncAction action, String category, AsyncCallback callback) { + this.action = action; + this.category = category; + this.callback = callback; + } + + public String getCategory() { + return (this.category == null ? MarkedAsyncCallback.CATEGORY_GLOBAL : this.category); + } + + public String getType() { + return this.action.getClass().getName(); + } + + public void execute() { + this.action.execute(new MarkedAsyncCallback(this, getCategory())); + } + + @Override + public void onSuccess(T result) { + try { + GWT.log("Execution success for action of type: " + getType()); + this.callback.onSuccess(result); + } finally { + AsyncActionsExecutor.this.callCompleted(this); + } + } + + @Override + public void onFailure(Throwable caught) { + try { + GWT.log("Execution failure for action of type: " + getType()); + this.callback.onFailure(caught); + } finally { + AsyncActionsExecutor.this.callCompleted(this); + } + } + } + private final int maxPendingCalls; private final int maxPendingCallsPerType; - private Map actionsPerType; - + private int numPendingCalls = 0; + private final Map actionsPerType = new HashMap(); + private final Map> lastRequestedActions = new HashMap>(); + + public AsyncActionsExecutor() { - numPendingCalls = 0; - maxPendingCalls = 6; - maxPendingCallsPerType = 4; - lastRequestedActions = new HashMap>(); - actionsPerType = new HashMap(); + this(6, 4); } + + public AsyncActionsExecutor(int maxPendingCalls, int maxPendingCallsPerType) { + this.maxPendingCalls = maxPendingCalls; + this.maxPendingCallsPerType = maxPendingCallsPerType; + } + + public void execute(AsyncAction action, AsyncCallback callback) { + execute(action, MarkedAsyncCallback.CATEGORY_GLOBAL, callback); + } + + public void execute(AsyncAction action, String category, AsyncCallback callback) { + execute(new ExecutionJob(action, category, callback)); + } + + private void execute(ExecutionJob job) { + Integer numActionsOfType = actionsPerType.get(job.getType()); + + if (numActionsOfType == null) { + numActionsOfType = Integer.valueOf(0); + } - public void execute(final AsyncAction action) { - Integer numActionsOfType = actionsPerType.get(action.getType()); - if (numPendingCalls >= maxPendingCalls || (numActionsOfType != null && numActionsOfType >= maxPendingCallsPerType)) { - GWT.log("Drop action : " + action.getType()); + if (numPendingCalls >= maxPendingCalls || (numActionsOfType >= maxPendingCallsPerType)) { + GWT.log("Drop action : " + job.getType()); // don't put the call into the execution queue, but save it as the last one of each type - lastRequestedActions.put(action.getType(), action); + lastRequestedActions.put(job.getType(), job); return; } - action.execute(this); - if (numActionsOfType == null) { - numActionsOfType = 0; - } - actionsPerType.put(action.getType(), numActionsOfType+1); + + actionsPerType.put(job.getType(), numActionsOfType + 1); numPendingCalls++; - GWT.log("Execute action: " + action.getType()); - GWT.log("Pending actions counter: " + numPendingCalls); + + job.execute(); } - protected void callCompleted(String type) { + private void callCompleted(ExecutionJob job) { + String type = job.getType(); Integer numActionsPerType = actionsPerType.get(type); if (numActionsPerType != null && numActionsPerType > 0) { - actionsPerType.put(type, numActionsPerType-1); + actionsPerType.put(type, numActionsPerType - 1); } numPendingCalls--; checkForEmptyCallQueue(type); @@ -57,7 +118,7 @@ public class AsyncActionsExecutor { private void checkForEmptyCallQueue(String type) { Integer numActionsPerType = actionsPerType.get(type); if (numActionsPerType != null && numActionsPerType < maxPendingCallsPerType && lastRequestedActions.containsKey(type)) { - AsyncAction lastRequestedAction = lastRequestedActions.remove(type); + ExecutionJob lastRequestedAction = lastRequestedActions.remove(type); GWT.log("Set back last action : " + lastRequestedAction.getType()); execute(lastRequestedAction); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/DefaultAsyncAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/DefaultAsyncAction.java deleted file mode 100644 index acd6bc53cdf..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/DefaultAsyncAction.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.sap.sailing.gwt.ui.actions; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.user.client.rpc.AsyncCallback; - -public abstract class DefaultAsyncAction implements AsyncAction { - private final AsyncCallback callback; - private Result result; - - protected DefaultAsyncAction(AsyncCallback callback) { - this.callback = callback; - } - - public AsyncCallback getWrapperCallback(final AsyncActionsExecutor asyncActionsExecutor) { - // Wrap with action callback to hook into the call chain - AsyncCallback wrapper = new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - String type = DefaultAsyncAction.this.getType(); - GWT.log("Execution failure for action of type: " + type); - AsyncCallback callback = DefaultAsyncAction.this.getCallback(); - callback.onFailure(caught); - asyncActionsExecutor.callCompleted(type); - } - - @Override - public void onSuccess(Result result) { - String type = DefaultAsyncAction.this.getType(); - GWT.log("Execution success for action of type: " + type); - AsyncCallback callback = DefaultAsyncAction.this.getCallback(); - callback.onSuccess(result); - asyncActionsExecutor.callCompleted(type); - } - }; - return wrapper; - } - - @Override - public AsyncCallback getCallback() { - return callback; - } - - @Override - public String getType() { - return getClass().getName(); - } - - @Override - public Result getResult() { - return result; - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetCompetitorsRaceDataAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetCompetitorsRaceDataAction.java index 51d23d8b5c5..59aab739b3e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetCompetitorsRaceDataAction.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetCompetitorsRaceDataAction.java @@ -10,7 +10,7 @@ import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.shared.CompetitorsRaceDataDTO; -public class GetCompetitorsRaceDataAction extends DefaultAsyncAction { +public class GetCompetitorsRaceDataAction implements AsyncAction { private final SailingServiceAsync sailingService; private final RegattaAndRaceIdentifier raceIdentifier; private final List competitors; @@ -23,8 +23,7 @@ public class GetCompetitorsRaceDataAction extends DefaultAsyncAction competitors, Date fromDate, Date toDate, long stepSizeInMs, DetailType detailType, - String leaderboardGroupName, String leaderboardName, AsyncCallback callback) { - super(callback); + String leaderboardGroupName, String leaderboardName) { this.sailingService = sailingService; this.raceIdentifier = raceIdentifier; this.competitors = competitors; @@ -37,8 +36,8 @@ public class GetCompetitorsRaceDataAction extends DefaultAsyncAction) getWrapperCallback(asyncActionsExecutor)); + public void execute(AsyncCallback callback) { + sailingService.getCompetitorsRaceData(raceIdentifier, competitors, fromDate, toDate, stepSizeInMs, detailType, + leaderboarGroupName, leaderboardName, callback); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetCoursePositionsAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetCoursePositionsAction.java index abe0a7af58b..3d035c957b5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetCoursePositionsAction.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetCoursePositionsAction.java @@ -7,21 +7,19 @@ import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.shared.CoursePositionsDTO; -public class GetCoursePositionsAction extends DefaultAsyncAction { +public class GetCoursePositionsAction implements AsyncAction { private final SailingServiceAsync sailingService; private final RegattaAndRaceIdentifier raceIdentifier; private final Date date; - public GetCoursePositionsAction(SailingServiceAsync sailingService, RegattaAndRaceIdentifier raceIdentifier, Date date, - AsyncCallback callback) { - super(callback); + public GetCoursePositionsAction(SailingServiceAsync sailingService, RegattaAndRaceIdentifier raceIdentifier, Date date) { this.sailingService = sailingService; this.raceIdentifier = raceIdentifier; this.date = date; } @Override - public void execute(AsyncActionsExecutor asyncActionsExecutor) { - sailingService.getCoursePositions(raceIdentifier, date, (AsyncCallback) getWrapperCallback(asyncActionsExecutor)); + public void execute(AsyncCallback callback) { + sailingService.getCoursePositions(raceIdentifier, date, callback); } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetLeaderboardByNameAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetLeaderboardByNameAction.java index 5b07bc2bc68..c762c6be0a9 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetLeaderboardByNameAction.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetLeaderboardByNameAction.java @@ -26,7 +26,7 @@ import com.sap.sailing.gwt.ui.client.Timer; * @author Frank Mittag, Axel Uhl (d043530) * */ -public class GetLeaderboardByNameAction extends DefaultAsyncAction { +public class GetLeaderboardByNameAction implements AsyncAction { private final SailingServiceAsync sailingService; private final String leaderboardName; private final Date date; @@ -38,8 +38,7 @@ public class GetLeaderboardByNameAction extends DefaultAsyncAction namesOfRacesForWhichToLoadLegDetails, LeaderboardDTO previousLeaderboard, - Timer timerToAdjustOffsetIn, ErrorReporter errorReporter, StringMessages stringMessages, AsyncCallback callback) { - super(callback); + Timer timerToAdjustOffsetIn, ErrorReporter errorReporter, StringMessages stringMessages) { this.sailingService = sailingService; this.errorReporter = errorReporter; this.stringMessages = stringMessages; @@ -51,16 +50,14 @@ public class GetLeaderboardByNameAction extends DefaultAsyncAction wrapperCallback = getWrapperCallback(asyncActionsExecutor); + public void execute(final AsyncCallback callback) { final long clientTimeWhenRequestWasSent = System.currentTimeMillis(); - sailingService - .getLeaderboardByName(leaderboardName, date, namesOfRacesForWhichToLoadLegDetails, + sailingService.getLeaderboardByName(leaderboardName, date, namesOfRacesForWhichToLoadLegDetails, previousLeaderboard==null?null:previousLeaderboard.getId(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { - wrapperCallback.onFailure(caught); + callback.onFailure(caught); } @Override @@ -74,7 +71,7 @@ public class GetLeaderboardByNameAction extends DefaultAsyncAction, List>>> { +public class GetLeaderboardDataEntriesAction implements AsyncAction, List>>> { private final SailingServiceAsync sailingService; private final DetailType detailType; private final String leaderboardName; private final Date date; - public GetLeaderboardDataEntriesAction(SailingServiceAsync sailingService, String leaderboardName, Date date, DetailType detailType, - AsyncCallback, List>>> callback) { - super(callback); + public GetLeaderboardDataEntriesAction(SailingServiceAsync sailingService, String leaderboardName, Date date, DetailType detailType) { this.sailingService = sailingService; this.leaderboardName = leaderboardName; this.date = date; @@ -25,8 +23,7 @@ public class GetLeaderboardDataEntriesAction extends DefaultAsyncAction, List>>>) getWrapperCallback(asyncActionsExecutor)); + public void execute(AsyncCallback, List>>> callback) { + sailingService.getLeaderboardDataEntriesForAllRaceColumns(leaderboardName, date, detailType, callback); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetRaceMapDataAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetRaceMapDataAction.java index 5816ab58b4e..e5492407ecb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetRaceMapDataAction.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetRaceMapDataAction.java @@ -11,7 +11,7 @@ import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.shared.CompactRaceMapDataDTO; import com.sap.sailing.gwt.ui.shared.RaceMapDataDTO; -public class GetRaceMapDataAction extends DefaultAsyncAction { +public class GetRaceMapDataAction implements AsyncAction { private final SailingServiceAsync sailingService; private final Iterable allCompetitors; private final RegattaAndRaceIdentifier raceIdentifier; @@ -20,10 +20,9 @@ public class GetRaceMapDataAction extends DefaultAsyncAction { private final boolean extrapolate; private final Date date; - public GetRaceMapDataAction(SailingServiceAsync sailingService, Iterable allCompetitors, RegattaAndRaceIdentifier raceIdentifier, - Date date, Map from, Map to, - boolean extrapolate, AsyncCallback callback) { - super(callback); + public GetRaceMapDataAction(SailingServiceAsync sailingService, Iterable allCompetitors, + RegattaAndRaceIdentifier raceIdentifier, Date date, Map from, + Map to, boolean extrapolate) { this.allCompetitors = allCompetitors; this.sailingService = sailingService; this.raceIdentifier = raceIdentifier; @@ -34,28 +33,28 @@ public class GetRaceMapDataAction extends DefaultAsyncAction { } @Override - public void execute(final AsyncActionsExecutor asyncActionsExecutor) { - final AsyncCallback wrapperCallback = (AsyncCallback) getWrapperCallback(asyncActionsExecutor); - AsyncCallback uncompactingCallback = new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - wrapperCallback.onFailure(caught); - } - - @Override - public void onSuccess(CompactRaceMapDataDTO result) { - wrapperCallback.onSuccess(result.getRaceMapDataDTO(allCompetitors)); - } - }; + public void execute(final AsyncCallback callback) { Map fromByCompetitorIdAsString = new HashMap(); for (Map.Entry fromEntry : from.entrySet()) { fromByCompetitorIdAsString.put(fromEntry.getKey().getIdAsString(), fromEntry.getValue()); } + Map toByCompetitorIdAsString = new HashMap(); for (Map.Entry toEntry : to.entrySet()) { toByCompetitorIdAsString.put(toEntry.getKey().getIdAsString(), toEntry.getValue()); } + sailingService.getRaceMapData(raceIdentifier, date, fromByCompetitorIdAsString, toByCompetitorIdAsString, - extrapolate, uncompactingCallback); + extrapolate, new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + callback.onFailure(caught); + } + + @Override + public void onSuccess(CompactRaceMapDataDTO result) { + callback.onSuccess(result.getRaceMapDataDTO(allCompetitors)); + } + }); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetWindInfoAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetWindInfoAction.java index 82ca40c8a68..7254cbf8a37 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetWindInfoAction.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetWindInfoAction.java @@ -8,7 +8,7 @@ import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO; -public class GetWindInfoAction extends DefaultAsyncAction { +public class GetWindInfoAction implements AsyncAction { private final SailingServiceAsync sailingService; private final RegattaAndRaceIdentifier raceIdentifier; private Date from; @@ -23,9 +23,8 @@ public class GetWindInfoAction extends DefaultAsyncAction { private enum CallVariants { Variant1, Variant2 }; private final CallVariants callVariant; - public GetWindInfoAction(SailingServiceAsync sailingService, RegattaAndRaceIdentifier raceIdentifier, Date from, long millisecondsStepWidth, - int numberOfFixes, Collection windSourceTypeNames, AsyncCallback callback) { - super(callback); + public GetWindInfoAction(SailingServiceAsync sailingService, RegattaAndRaceIdentifier raceIdentifier, Date from, + long millisecondsStepWidth, int numberOfFixes, Collection windSourceTypeNames) { this.sailingService = sailingService; this.raceIdentifier = raceIdentifier; this.from = from; @@ -36,9 +35,7 @@ public class GetWindInfoAction extends DefaultAsyncAction { } public GetWindInfoAction(SailingServiceAsync sailingService, RegattaAndRaceIdentifier raceIdentifier, Date fromDate, - Date toDate, long resolutionInMilliseconds, Collection windSourceTypeNames, - AsyncCallback callback) { - super(callback); + Date toDate, long resolutionInMilliseconds, Collection windSourceTypeNames) { this.sailingService = sailingService; this.raceIdentifier = raceIdentifier; this.fromDate = fromDate; @@ -49,13 +46,13 @@ public class GetWindInfoAction extends DefaultAsyncAction { } @Override - public void execute(AsyncActionsExecutor asyncActionsExecutor) { + public void execute(AsyncCallback callback) { switch (callVariant) { case Variant1: - sailingService.getAveragedWindInfo(raceIdentifier, from, millisecondsStepWidth, numberOfFixes, windSourceTypeNames, (AsyncCallback) getWrapperCallback(asyncActionsExecutor)); + sailingService.getAveragedWindInfo(raceIdentifier, from, millisecondsStepWidth, numberOfFixes, windSourceTypeNames, callback); break; case Variant2: - sailingService.getAveragedWindInfo(raceIdentifier, fromDate, toDate, resolutionInMilliseconds, windSourceTypeNames, (AsyncCallback) getWrapperCallback(asyncActionsExecutor)); + sailingService.getAveragedWindInfo(raceIdentifier, fromDate, toDate, resolutionInMilliseconds, windSourceTypeNames, callback); break; } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractTrackedRacesListComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractTrackedRacesListComposite.java index dfcaa47b45b..1bbc626bbc2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractTrackedRacesListComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractTrackedRacesListComposite.java @@ -16,6 +16,7 @@ import com.google.gwt.user.cellview.client.CellTable; import com.google.gwt.user.cellview.client.Column; import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; import com.google.gwt.user.cellview.client.TextColumn; +import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; @@ -382,19 +383,21 @@ public abstract class AbstractTrackedRacesListComposite extends SimplePanel impl if (raceIdentifiersToUpdate != null && !raceIdentifiersToUpdate.isEmpty()) { sailingService.updateRacesDelayToLive(raceIdentifiersToUpdate, settings.getDelayToLiveInSeconds() * 1000l, - new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable caught) { - errorReporter - .reportError("Exception trying to set the delay to live for the selected tracked races: " - + caught.getMessage()); - } + new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError( + "Exception trying to set the delay to live for the selected tracked races: " + + caught.getMessage()); + } - @Override - public void handleSuccess(Void result) { - regattaRefresher.fillRegattas(); - } - }); + @Override + public void onSuccess(Void result) { + regattaRefresher.fillRegattas(); + } + } + )); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java index d545fc105e6..7412e6366c6 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java @@ -610,19 +610,20 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb protected void openUpdateFlexibleLeaderboardDialog(final StrippedLeaderboardDTO leaderboardDTO, final List otherExistingLeaderboard, final String oldLeaderboardName, final LeaderboardDescriptor descriptor) { - sailingService.getEvents(new AsyncCallback>() { - @Override - public void onSuccess(List result) { - openUpdateFlexibleLeaderboardDialog(leaderboardDTO, otherExistingLeaderboard, oldLeaderboardName, - descriptor, result); - } - - @Override - public void onFailure(Throwable caught) { - openUpdateFlexibleLeaderboardDialog(leaderboardDTO, otherExistingLeaderboard, oldLeaderboardName, - descriptor, new ArrayList()); - } - }); + sailingService.getEvents(new MarkedAsyncCallback>( + new AsyncCallback>() { + @Override + public void onSuccess(List result) { + openUpdateFlexibleLeaderboardDialog(leaderboardDTO, otherExistingLeaderboard, oldLeaderboardName, + descriptor, result); + } + + @Override + public void onFailure(Throwable caught) { + openUpdateFlexibleLeaderboardDialog(leaderboardDTO, otherExistingLeaderboard, oldLeaderboardName, + descriptor, new ArrayList()); + } + })); } protected void openUpdateFlexibleLeaderboardDialog(StrippedLeaderboardDTO leaderboardDTO, List otherExistingLeaderboard, @@ -654,24 +655,25 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb } public void loadLeaderboards() { - sailingService.getLeaderboards(new MarkedAsyncCallback>() { - @Override - public void handleSuccess(List leaderboards) { - leaderboardList.getList().clear(); - availableLeaderboardList.clear(); - leaderboardList.getList().addAll(leaderboards); - availableLeaderboardList.addAll(leaderboards); - filterLeaderboardPanel.updateAll(availableLeaderboardList); - leaderboardSelectionChanged(); - leaderboardRaceColumnSelectionChanged(); - } - - @Override - public void handleFailure(Throwable t) { - LeaderboardConfigPanel.this.errorReporter.reportError("Error trying to obtain list of leaderboards: " - + t.getMessage()); - } - }); + sailingService.getLeaderboards(new MarkedAsyncCallback>( + new AsyncCallback>() { + @Override + public void onSuccess(List leaderboards) { + leaderboardList.getList().clear(); + availableLeaderboardList.clear(); + leaderboardList.getList().addAll(leaderboards); + availableLeaderboardList.addAll(leaderboards); + filterLeaderboardPanel.updateAll(availableLeaderboardList); + leaderboardSelectionChanged(); + leaderboardRaceColumnSelectionChanged(); + } + + @Override + public void onFailure(Throwable t) { + LeaderboardConfigPanel.this.errorReporter.reportError("Error trying to obtain list of leaderboards: " + + t.getMessage()); + } + })); } /** @@ -680,31 +682,32 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb * after the refresh has successfully completed. See {@link #selectRaceColumn(String)}. */ public void loadAndRefreshLeaderboard(final String leaderboardName, final String nameOfRaceColumnToSelect) { - sailingService.getLeaderboard(leaderboardName, new MarkedAsyncCallback() { - @Override - public void handleSuccess(StrippedLeaderboardDTO leaderboard) { - for (StrippedLeaderboardDTO leaderboardDTO : leaderboardSelectionModel.getSelectedSet()) { - if (leaderboardDTO.name.equals(leaderboardName)) { - leaderboardSelectionModel.setSelected(leaderboardDTO, false); - break; - } - } - - replaceLeaderboardInList(leaderboardList.getList(), leaderboardName, leaderboard); - replaceLeaderboardInList(availableLeaderboardList, leaderboardName, leaderboard); - leaderboardSelectionModel.setSelected(leaderboard, true); - if (nameOfRaceColumnToSelect != null) { - selectRaceColumn(nameOfRaceColumnToSelect); - } - leaderboardSelectionChanged(); - } - - @Override - public void handleFailure(Throwable t) { - LeaderboardConfigPanel.this.errorReporter.reportError("Error trying to update leaderboard with name " + leaderboardName + " : " - + t.getMessage()); - } - }); + sailingService.getLeaderboard(leaderboardName, new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onSuccess(StrippedLeaderboardDTO leaderboard) { + for (StrippedLeaderboardDTO leaderboardDTO : leaderboardSelectionModel.getSelectedSet()) { + if (leaderboardDTO.name.equals(leaderboardName)) { + leaderboardSelectionModel.setSelected(leaderboardDTO, false); + break; + } + } + + replaceLeaderboardInList(leaderboardList.getList(), leaderboardName, leaderboard); + replaceLeaderboardInList(availableLeaderboardList, leaderboardName, leaderboard); + leaderboardSelectionModel.setSelected(leaderboard, true); + if (nameOfRaceColumnToSelect != null) { + selectRaceColumn(nameOfRaceColumnToSelect); + } + leaderboardSelectionChanged(); + } + + @Override + public void onFailure(Throwable t) { + LeaderboardConfigPanel.this.errorReporter.reportError("Error trying to update leaderboard with name " + leaderboardName + " : " + + t.getMessage()); + } + })); } private void replaceLeaderboardInList(List leaderboardList, String leaderboardToReplace, StrippedLeaderboardDTO newLeaderboard) { @@ -723,20 +726,21 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb private void unlinkRaceColumnFromTrackedRace(final String raceColumnName, final FleetDTO fleet) { final String selectedLeaderboardName = getSelectedLeaderboardName(); sailingService.disconnectLeaderboardColumnFromTrackedRace(selectedLeaderboardName, raceColumnName, fleet.getName(), - new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable t) { - errorReporter.reportError("Error trying to unlink tracked race from column " + raceColumnName - + " from leaderboard " + selectedLeaderboardName + ": " + t.getMessage()); - } - - @Override - public void handleSuccess(Void arg0) { - trackedRacesListComposite.clearSelection(); - getSelectedRaceColumnWithFleet().getA().setRaceIdentifier(fleet, null); - raceColumnAndFleetList.refresh(); - } - }); + new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to unlink tracked race from column " + raceColumnName + + " from leaderboard " + selectedLeaderboardName + ": " + t.getMessage()); + } + + @Override + public void onSuccess(Void arg0) { + trackedRacesListComposite.clearSelection(); + getSelectedRaceColumnWithFleet().getA().setRaceIdentifier(fleet, null); + raceColumnAndFleetList.refresh(); + } + })); } private void setStartTime(RaceColumnDTO raceColumnDTO, FleetDTO fleetDTO) { @@ -766,16 +770,18 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb private void showRaceLog(final RaceColumnDTO raceColumnDTO, final FleetDTO fleetDTO) { final String selectedLeaderboardName = getSelectedLeaderboardName(); - sailingService.getRaceLog(selectedLeaderboardName, raceColumnDTO, fleetDTO, new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError(caught.getMessage(), true); - } - @Override - public void onSuccess(RaceLogDTO result) { - openRaceLogDialog(result); - } - }); + sailingService.getRaceLog(selectedLeaderboardName, raceColumnDTO, fleetDTO, + new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError(caught.getMessage(), true); + } + @Override + public void onSuccess(RaceLogDTO result) { + openRaceLogDialog(result); + } + })); } private void openRaceLogDialog(RaceLogDTO raceLogDTO) { @@ -793,38 +799,40 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb private void refreshRaceLog(final RaceColumnDTO raceColumnDTO, final FleetDTO fleet, final boolean showAlerts) { final String selectedLeaderboardName = getSelectedLeaderboardName(); - sailingService.reloadRaceLog(selectedLeaderboardName, raceColumnDTO, fleet, new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable caught) { - if (showAlerts) { - errorReporter.reportError(caught.getMessage()); - } - } - @Override - public void handleSuccess(Void result) { - if (showAlerts) { - Window.alert(stringMessages.raceLogReloaded()); - } - } - }); + sailingService.reloadRaceLog(selectedLeaderboardName, raceColumnDTO, fleet, new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + if (showAlerts) { + errorReporter.reportError(caught.getMessage()); + } + } + @Override + public void onSuccess(Void result) { + if (showAlerts) { + Window.alert(stringMessages.raceLogReloaded()); + } + } + })); } private void removeRaceColumn(final RaceColumnDTO raceColumnDTO) { final String selectedLeaderboardName = getSelectedLeaderboardName(); final String raceColumnString = raceColumnDTO.getRaceColumnName(); sailingService.removeLeaderboardColumn(getSelectedLeaderboardName(), raceColumnString, - new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable t) { - errorReporter.reportError("Error trying to remove leaderboard race column " + raceColumnDTO - + " in leaderboard " + getSelectedLeaderboardName() + ": " + t.getMessage()); - } - - @Override - public void handleSuccess(Void arg0) { - loadAndRefreshLeaderboard(selectedLeaderboardName, /* raceColumnNameToSelect */ null); - } - }); + new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to remove leaderboard race column " + raceColumnDTO + + " in leaderboard " + getSelectedLeaderboardName() + ": " + t.getMessage()); + } + + @Override + public void onSuccess(Void arg0) { + loadAndRefreshLeaderboard(selectedLeaderboardName, /* raceColumnNameToSelect */ null); + } + })); } /** @@ -835,19 +843,20 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb final String selectedLeaderboardName = getSelectedLeaderboardName(); final String selectedRaceColumnName = raceColumnTableSelectionModel.getSelectedObject().getA().getRaceColumnName(); sailingService.moveLeaderboardColumnDown(getSelectedLeaderboardName(), selectedRaceColumnName, - new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable caught) { - errorReporter.reportError("Error trying to move leaderboard race column " - + selectedRaceColumnName + " in leaderboard " + getSelectedLeaderboardName() - + " down: " + caught.getMessage()); - } - - @Override - public void handleSuccess(Void result) { - loadAndRefreshLeaderboard(selectedLeaderboardName, selectedRaceColumnName); - } - }); + new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to move leaderboard race column " + + selectedRaceColumnName + " in leaderboard " + getSelectedLeaderboardName() + + " down: " + caught.getMessage()); + } + + @Override + public void onSuccess(Void result) { + loadAndRefreshLeaderboard(selectedLeaderboardName, selectedRaceColumnName); + } + })); } /** @@ -858,19 +867,20 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb final String selectedLeaderboardName = getSelectedLeaderboardName(); final String selectedRaceColumnName = raceColumnTableSelectionModel.getSelectedObject().getA().getRaceColumnName(); sailingService.moveLeaderboardColumnUp(getSelectedLeaderboardName(), selectedRaceColumnName, - new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable caught) { - errorReporter.reportError("Error trying to move leaderboard race column " - + selectedRaceColumnName + " in leaderboard " + getSelectedLeaderboardName() + " up: " - + caught.getMessage()); - } - - @Override - public void handleSuccess(Void result) { - loadAndRefreshLeaderboard(selectedLeaderboardName, selectedRaceColumnName); - } - }); + new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to move leaderboard race column " + + selectedRaceColumnName + " in leaderboard " + getSelectedLeaderboardName() + " up: " + + caught.getMessage()); + } + + @Override + public void onSuccess(Void result) { + loadAndRefreshLeaderboard(selectedLeaderboardName, selectedRaceColumnName); + } + })); } private void leaderboardRaceColumnSelectionChanged() { @@ -903,29 +913,30 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb final String selectedRaceColumnName = selectedRaceColumnAndFleetNameInLeaderboard.getA().getRaceColumnName(); final String selectedFleetName = selectedRaceColumnAndFleetNameInLeaderboard.getB().getName(); sailingService.getRegattaAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(selectedLeaderboardName, - selectedRaceColumnName, new MarkedAsyncCallback>() { - @Override - public void handleFailure(Throwable t) { - errorReporter.reportError("Error trying to determine tracked race linked to race column " - + selectedRaceColumnName + " in leaderboard " + selectedLeaderboardName + ": " - + t.getMessage()); - } - - @Override - public void handleSuccess(Map regattaAndRaceNamesPerFleet) { - if (regattaAndRaceNamesPerFleet != null && !regattaAndRaceNamesPerFleet.isEmpty()) { - RegattaAndRaceIdentifier raceIdentifier = regattaAndRaceNamesPerFleet - .get(selectedFleetName); - if (raceIdentifier != null) { - selectRaceInList(raceIdentifier.getRegattaName(), raceIdentifier.getRaceName()); - } else { - trackedRacesListComposite.clearSelection(); - } - } else { - trackedRacesListComposite.clearSelection(); - } - } - }); + selectedRaceColumnName, new MarkedAsyncCallback>( + new AsyncCallback>() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to determine tracked race linked to race column " + + selectedRaceColumnName + " in leaderboard " + selectedLeaderboardName + ": " + + t.getMessage()); + } + + @Override + public void onSuccess(Map regattaAndRaceNamesPerFleet) { + if (regattaAndRaceNamesPerFleet != null && !regattaAndRaceNamesPerFleet.isEmpty()) { + RegattaAndRaceIdentifier raceIdentifier = regattaAndRaceNamesPerFleet.get(selectedFleetName); + + if (raceIdentifier != null) { + selectRaceInList(raceIdentifier.getRegattaName(), raceIdentifier.getRaceName()); + } else { + trackedRacesListComposite.clearSelection(); + } + } else { + trackedRacesListComposite.clearSelection(); + } + } + })); } } @@ -1006,17 +1017,18 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb private void setIsMedalRace(String leaderboardName, final RaceColumnDTO raceInLeaderboard, final boolean isMedalRace) { sailingService.updateIsMedalRace(leaderboardName, raceInLeaderboard.getRaceColumnName(), isMedalRace, - new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable caught) { - errorReporter.reportError(stringMessages.errorUpdatingIsMedalRace(caught.getMessage())); - } - - @Override - public void handleSuccess(Void result) { - getSelectedLeaderboard().setIsMedalRace(raceInLeaderboard.getRaceColumnName(), isMedalRace); - } - }); + new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError(stringMessages.errorUpdatingIsMedalRace(caught.getMessage())); + } + + @Override + public void onSuccess(Void result) { + getSelectedLeaderboard().setIsMedalRace(raceInLeaderboard.getRaceColumnName(), isMedalRace); + } + })); } private void addRaceColumnsToLeaderboard() { @@ -1049,18 +1061,19 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb } } - sailingService.addColumnsToLeaderboard(leaderboardName, raceColumnsToAdd, new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable caught) { - errorReporter.reportError("Error trying to add race columns to leaderboard " + leaderboardName - + ": " + caught.getMessage()); - } - - @Override - public void handleSuccess(Void v) { - loadAndRefreshLeaderboard(leaderboardName, /* nameOfRaceColumnToSelect */ null); - } - }); + sailingService.addColumnsToLeaderboard(leaderboardName, raceColumnsToAdd, new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to add race columns to leaderboard " + leaderboardName + + ": " + caught.getMessage()); + } + + @Override + public void onSuccess(Void v) { + loadAndRefreshLeaderboard(leaderboardName, /* nameOfRaceColumnToSelect */ null); + } + })); } private String getSelectedLeaderboardName() { @@ -1125,18 +1138,18 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb } private void createFlexibleLeaderboard() { - sailingService.getEvents(new MarkedAsyncCallback>() { - - @Override - public void handleSuccess(List result) { - createFlexibleLeaderboard(result); - } - - @Override - public void handleFailure(Throwable caught) { - createFlexibleLeaderboard(new ArrayList()); - } - }); + sailingService.getEvents(new MarkedAsyncCallback>( + new AsyncCallback>() { + @Override + public void onSuccess(List result) { + createFlexibleLeaderboard(result); + } + + @Override + public void onFailure(Throwable caught) { + createFlexibleLeaderboard(new ArrayList()); + } + })); } private void createFlexibleLeaderboard(List existingEvents) { @@ -1149,20 +1162,21 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb @Override public void ok(final LeaderboardDescriptor newLeaderboard) { - sailingService.createFlexibleLeaderboard(newLeaderboard.getName(), newLeaderboard.getDisplayName(), newLeaderboard.getDiscardThresholds(), - newLeaderboard.getScoringScheme(), newLeaderboard.getCourseAreaId(), - new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable t) { - errorReporter.reportError("Error trying to create the new flexible leaderboard " + newLeaderboard.getName() - + ": " + t.getMessage()); - } - - @Override - public void handleSuccess(StrippedLeaderboardDTO result) { - addLeaderboard(result); - } - }); + sailingService.createFlexibleLeaderboard(newLeaderboard.getName(), newLeaderboard.getDisplayName(), + newLeaderboard.getDiscardThresholds(), newLeaderboard.getScoringScheme(), newLeaderboard.getCourseAreaId(), + new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to create the new flexible leaderboard " + newLeaderboard.getName() + + ": " + t.getMessage()); + } + + @Override + public void onSuccess(StrippedLeaderboardDTO result) { + addLeaderboard(result); + } + })); } }); dialog.ensureDebugId("FlexibleLeaderboardCreateDialog"); @@ -1207,27 +1221,29 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb private void updateLeaderboard(final String oldLeaderboardName, final LeaderboardDescriptor leaderboardToUpdate) { sailingService.updateLeaderboard(oldLeaderboardName, leaderboardToUpdate.getName(), leaderboardToUpdate.getDisplayName(), - leaderboardToUpdate.getDiscardThresholds(), leaderboardToUpdate.getCourseAreaId(), new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable t) { - errorReporter.reportError("Error trying to update leaderboard " + oldLeaderboardName + ": " - + t.getMessage()); - } - - @Override - public void handleSuccess(StrippedLeaderboardDTO updatedLeaderboard) { - int indexOfLeaderboard = 0; - for (int i = 0; i < leaderboardList.getList().size(); i++) { - StrippedLeaderboardDTO dao = leaderboardList.getList().get(i); - if (dao.name.equals(oldLeaderboardName)) { - indexOfLeaderboard = i; - break; - } - } - leaderboardList.getList().set(indexOfLeaderboard, updatedLeaderboard); - leaderboardList.refresh(); - } - }); + leaderboardToUpdate.getDiscardThresholds(), leaderboardToUpdate.getCourseAreaId(), + new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to update leaderboard " + oldLeaderboardName + ": " + + t.getMessage()); + } + + @Override + public void onSuccess(StrippedLeaderboardDTO updatedLeaderboard) { + int indexOfLeaderboard = 0; + for (int i = 0; i < leaderboardList.getList().size(); i++) { + StrippedLeaderboardDTO dao = leaderboardList.getList().get(i); + if (dao.name.equals(oldLeaderboardName)) { + indexOfLeaderboard = i; + break; + } + } + leaderboardList.getList().set(indexOfLeaderboard, updatedLeaderboard); + leaderboardList.refresh(); + } + })); } private void removeLeaderboards(final Collection leaderboards) { @@ -1236,38 +1252,39 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb for (StrippedLeaderboardDTO leaderboard : leaderboards) { leaderboardNames.add(leaderboard.name); } - sailingService.removeLeaderboards(leaderboardNames, new MarkedAsyncCallback() { - - @Override - public void handleFailure(Throwable caught) { - errorReporter.reportError("Error trying to remove the leaderboards:" + caught.getMessage()); - - - } - - @Override - public void handleSuccess(Void result) { - for (StrippedLeaderboardDTO leaderboard : leaderboards) { - removeLeaderboardFromTable(leaderboard); - } - } - }); + sailingService.removeLeaderboards(leaderboardNames, new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to remove the leaderboards:" + caught.getMessage()); + + + } + + @Override + public void onSuccess(Void result) { + for (StrippedLeaderboardDTO leaderboard : leaderboards) { + removeLeaderboardFromTable(leaderboard); + } + } + })); } } private void removeLeaderboard(final StrippedLeaderboardDTO leaderBoard) { - sailingService.removeLeaderboard(leaderBoard.name, new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable caught) { - errorReporter.reportError("Error trying to remove leaderboard " + leaderBoard.name + ": " - + caught.getMessage()); - } - - @Override - public void handleSuccess(Void result) { - removeLeaderboardFromTable(leaderBoard); - } - }); + sailingService.removeLeaderboard(leaderBoard.name, new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to remove leaderboard " + leaderBoard.name + ": " + + caught.getMessage()); + } + + @Override + public void onSuccess(Void result) { + removeLeaderboardFromTable(leaderBoard); + } + })); } private void removeLeaderboardFromTable(final StrippedLeaderboardDTO leaderBoard) { @@ -1296,24 +1313,25 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb final FleetDTO fleet, final RegattaAndRaceIdentifier selectedRace) { sailingService.connectTrackedRaceToLeaderboardColumn(getSelectedLeaderboardName(), selectedRaceInLeaderboard .getRaceColumnName(), fleet.getName(), selectedRace, - new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable t) { - errorReporter.reportError("Error trying to link tracked race " + selectedRace + " to race column named " - + selectedRaceInLeaderboard.getRaceColumnName() + " of leaderboard " - + getSelectedLeaderboardName() + ": " + t.getMessage()); - trackedRacesListComposite.clearSelection(); - } - - @Override - public void handleSuccess(Boolean success) { - if (success) { - // TODO consider enabling the Unlink button - selectedRaceInLeaderboard.setRaceIdentifier(fleet, selectedRace); - raceColumnAndFleetList.refresh(); - } - } - }); + new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to link tracked race " + selectedRace + " to race column named " + + selectedRaceInLeaderboard.getRaceColumnName() + " of leaderboard " + + getSelectedLeaderboardName() + ": " + t.getMessage()); + trackedRacesListComposite.clearSelection(); + } + + @Override + public void onSuccess(Boolean success) { + if (success) { + // TODO consider enabling the Unlink button + selectedRaceInLeaderboard.setRaceIdentifier(fleet, selectedRace); + raceColumnAndFleetList.refresh(); + } + } + })); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupConfigPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupConfigPanel.java index 602bbdfc7eb..4b7cc578384 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupConfigPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupConfigPanel.java @@ -20,6 +20,7 @@ import com.google.gwt.user.cellview.client.Column; import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; import com.google.gwt.user.cellview.client.TextColumn; import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CaptionPanel; import com.google.gwt.user.client.ui.HorizontalPanel; @@ -540,39 +541,42 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel implements } public void fillLeaderboardGroups() { - sailingService.getLeaderboardGroups(false /*withGeoLocationData*/, new MarkedAsyncCallback>() { - @Override - public void handleSuccess(List groups) { - availableLeaderboardGroups.clear(); - if (groups != null) { - availableLeaderboardGroups.addAll(groups); - } - groupsProvider.getList().clear(); - groupsProvider.getList().addAll(availableLeaderboardGroups); - } - @Override - public void handleFailure(Throwable t) { - errorReporter.reportError("Error trying to obtain list of leaderboard groups: " + t.getMessage()); - } - }); + sailingService.getLeaderboardGroups(false /*withGeoLocationData*/, + new MarkedAsyncCallback>( + new AsyncCallback>() { + @Override + public void onSuccess(List groups) { + availableLeaderboardGroups.clear(); + if (groups != null) { + availableLeaderboardGroups.addAll(groups); + } + groupsProvider.getList().clear(); + groupsProvider.getList().addAll(availableLeaderboardGroups); + } + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to obtain list of leaderboard groups: " + t.getMessage()); + } + })); } private void loadLeaderboards() { - sailingService.getLeaderboards(new MarkedAsyncCallback>() { - @Override - public void handleFailure(Throwable t) { - errorReporter.reportError("Error trying to obtain list of leaderboards: " + t.getMessage()); - } - @Override - public void handleSuccess(List leaderboards) { - availableLeaderboards.clear(); - if (leaderboards != null) { - availableLeaderboards.addAll(leaderboards); - } - leaderboardsProvider.getList().clear(); - leaderboardsProvider.getList().addAll(availableLeaderboards); - } - }); + sailingService.getLeaderboards(new MarkedAsyncCallback>( + new AsyncCallback>() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to obtain list of leaderboards: " + t.getMessage()); + } + @Override + public void onSuccess(List leaderboards) { + availableLeaderboards.clear(); + if (leaderboards != null) { + availableLeaderboards.addAll(leaderboards); + } + leaderboardsProvider.getList().clear(); + leaderboardsProvider.getList().addAll(availableLeaderboards); + } + })); } /** @@ -585,28 +589,29 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel implements final LeaderboardGroupDTO selectedGroup = getSelectedGroup(); final Set selectedLeaderboards = leaderboardsSelectionModel.getSelectedSet(); if (isSingleGroupSelected && selectedGroup != null) { - sailingService.getLeaderboards(new MarkedAsyncCallback>() { - @Override - public void handleFailure(Throwable t) { - errorReporter.reportError("Error trying to obtain list of leaderboards: " + t.getMessage()); - } - - @Override - public void handleSuccess(List leaderboards) { - availableLeaderboards.clear(); - if (leaderboards != null) { - availableLeaderboards.addAll(leaderboards); - } - leaderboardsProvider.getList().clear(); - leaderboardsProvider.getList().addAll(availableLeaderboards); - leaderboardsProvider.getList().removeAll(selectedGroup.leaderboards); - leaderboardsFilterablePanel.getTextBox().setText(""); - leaderboardsSelectionModel.clear(); - for (StrippedLeaderboardDTO leaderboard : selectedLeaderboards) { - leaderboardsSelectionModel.setSelected(leaderboard, true); - } - } - }); + sailingService.getLeaderboards(new MarkedAsyncCallback>( + new AsyncCallback>() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to obtain list of leaderboards: " + t.getMessage()); + } + + @Override + public void onSuccess(List leaderboards) { + availableLeaderboards.clear(); + if (leaderboards != null) { + availableLeaderboards.addAll(leaderboards); + } + leaderboardsProvider.getList().clear(); + leaderboardsProvider.getList().addAll(availableLeaderboards); + leaderboardsProvider.getList().removeAll(selectedGroup.leaderboards); + leaderboardsFilterablePanel.getTextBox().setText(""); + leaderboardsSelectionModel.clear(); + for (StrippedLeaderboardDTO leaderboard : selectedLeaderboards) { + leaderboardsSelectionModel.setSelected(leaderboard, true); + } + } + })); } } @@ -626,22 +631,23 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel implements } private void createNewGroup(final LeaderboardGroupDescriptor newGroup) { - sailingService.createLeaderboardGroup(newGroup.getName(), newGroup.getDescription(), newGroup.isDisplayLeaderboardsInReverseOrder(), - newGroup.getOverallLeaderboardDiscardThresholds(), - newGroup.getOverallLeaderboardScoringSchemeType(), new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable t) { - errorReporter.reportError("Error trying to create new leaderboard group" + newGroup.getName() - + ": " + t.getMessage()); - } - @Override - public void handleSuccess(LeaderboardGroupDTO newGroup) { - availableLeaderboardGroups.add(newGroup); - groupsProvider.getList().add(newGroup); - groupsSelectionModel.clear(); - groupsSelectionModel.setSelected(newGroup, true); - } - }); + sailingService.createLeaderboardGroup(newGroup.getName(), newGroup.getDescription(), + newGroup.isDisplayLeaderboardsInReverseOrder(), newGroup.getOverallLeaderboardDiscardThresholds(), + newGroup.getOverallLeaderboardScoringSchemeType(), new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to create new leaderboard group" + newGroup.getName() + + ": " + t.getMessage()); + } + @Override + public void onSuccess(LeaderboardGroupDTO newGroup) { + availableLeaderboardGroups.add(newGroup); + groupsProvider.getList().add(newGroup); + groupsSelectionModel.clear(); + groupsSelectionModel.setSelected(newGroup, true); + } + })); } private void updateGroup(final String oldGroupName, final LeaderboardGroupDTO groupToUpdate, final LeaderboardGroupDescriptor updateDescriptor) { @@ -651,33 +657,34 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel implements } sailingService.updateLeaderboardGroup(oldGroupName, updateDescriptor.getName(), updateDescriptor.getDescription(), leaderboardNames, updateDescriptor.getOverallLeaderboardDiscardThresholds(), - updateDescriptor.getOverallLeaderboardScoringSchemeType(), new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable t) { - errorReporter.reportError("Error trying to update leaderboard group " + oldGroupName + ": " - + t.getMessage()); - } - @Override - public void handleSuccess(Void v) { - // Update the availableLeaderboardGroups and the list of displayed groups - for (int i = 0; i < availableLeaderboardGroups.size(); i++) { - LeaderboardGroupDTO group = availableLeaderboardGroups.get(i); - if (oldGroupName.equals(group.getName())) { - groupToUpdate.setName(updateDescriptor.getName()); - groupToUpdate.description = updateDescriptor.getDescription(); - groupToUpdate.displayLeaderboardsInReverseOrder = updateDescriptor.isDisplayLeaderboardsInReverseOrder(); - groupToUpdate.setOverallLeaderboardDiscardThresholds(updateDescriptor.getOverallLeaderboardDiscardThresholds()); - groupToUpdate.setOverallLeaderboardScoringSchemeType(updateDescriptor.getOverallLeaderboardScoringSchemeType()); - availableLeaderboardGroups.set(i, groupToUpdate); - int displayedIndex = groupsProvider.getList().indexOf(group); - if (displayedIndex != -1) { - groupsProvider.getList().set(displayedIndex, groupToUpdate); - } - } - } - groupsProvider.refresh(); - } - }); + updateDescriptor.getOverallLeaderboardScoringSchemeType(), new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to update leaderboard group " + oldGroupName + ": " + + t.getMessage()); + } + @Override + public void onSuccess(Void v) { + // Update the availableLeaderboardGroups and the list of displayed groups + for (int i = 0; i < availableLeaderboardGroups.size(); i++) { + LeaderboardGroupDTO group = availableLeaderboardGroups.get(i); + if (oldGroupName.equals(group.getName())) { + groupToUpdate.setName(updateDescriptor.getName()); + groupToUpdate.description = updateDescriptor.getDescription(); + groupToUpdate.displayLeaderboardsInReverseOrder = updateDescriptor.isDisplayLeaderboardsInReverseOrder(); + groupToUpdate.setOverallLeaderboardDiscardThresholds(updateDescriptor.getOverallLeaderboardDiscardThresholds()); + groupToUpdate.setOverallLeaderboardScoringSchemeType(updateDescriptor.getOverallLeaderboardScoringSchemeType()); + availableLeaderboardGroups.set(i, groupToUpdate); + int displayedIndex = groupsProvider.getList().indexOf(group); + if (displayedIndex != -1) { + groupsProvider.getList().set(displayedIndex, groupToUpdate); + } + } + } + groupsProvider.refresh(); + } + })); } /** @@ -690,16 +697,17 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel implements } sailingService.updateLeaderboardGroup(group.getName(), group.getName(), group.description, leaderboardNames, group.getOverallLeaderboardDiscardThresholds(), - group.getOverallLeaderboardScoringSchemeType(), new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable t) { - errorReporter.reportError("Error trying to update leaderboard group " + group.getName() + ": " - + t.getMessage()); - } - @Override - public void handleSuccess(Void v) { - } - }); + group.getOverallLeaderboardScoringSchemeType(), new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to update leaderboard group " + group.getName() + ": " + + t.getMessage()); + } + @Override + public void onSuccess(Void v) { + } + })); } private void removeLeaderboardGroups(final Collection groups) { @@ -708,36 +716,38 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel implements for (LeaderboardGroupDTO group : groups) { groupNames.add(group.getName()); } - sailingService.removeLeaderboardGroups(groupNames, new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable t) { - errorReporter.reportError("Error trying to remove the leaderboard groups: " - + t.getMessage()); - } - @Override - public void handleSuccess(Void result) { - for (LeaderboardGroupDTO group : groups) { - removeGroupFromTable(group); - } - } - }); + sailingService.removeLeaderboardGroups(groupNames, new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to remove the leaderboard groups: " + + t.getMessage()); + } + @Override + public void onSuccess(Void result) { + for (LeaderboardGroupDTO group : groups) { + removeGroupFromTable(group); + } + } + })); } } private void removeLeaderboardGroup(final LeaderboardGroupDTO group) { Set groups = new HashSet(); groups.add(group.getName()); - sailingService.removeLeaderboardGroups(groups, new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable t) { - errorReporter.reportError("Error trying to remove leaderboard group " + group.getName() + ": " - + t.getMessage()); - } - @Override - public void handleSuccess(Void v) { - removeGroupFromTable(group); - } - }); + sailingService.removeLeaderboardGroups(groups, new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to remove leaderboard group " + group.getName() + ": " + + t.getMessage()); + } + @Override + public void onSuccess(Void v) { + removeGroupFromTable(group); + } + })); } private void removeGroupFromTable(final LeaderboardGroupDTO group) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaDetailsComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaDetailsComposite.java index 44e6a389cc1..349b2adf43e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaDetailsComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaDetailsComposite.java @@ -221,19 +221,19 @@ public class RegattaDetailsComposite extends Composite { editRacesOfRegattaSeries(regatta, series); } else if (SeriesConfigImagesBarCell.ACTION_REMOVE.equals(value)) { RegattaIdentifier identifier = new RegattaName(regatta.getName()); - sailingService.removeSeries(identifier, series.getName(), new MarkedAsyncCallback() { - - @Override - protected void handleFailure(Throwable cause) { - errorReporter.reportError("Error trying to remove series " + series.getName() - + ": " + cause.getMessage()); - } - - @Override - protected void handleSuccess(Void result) { - regattaRefresher.fillRegattas(); - } - }); + sailingService.removeSeries(identifier, series.getName(), new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable cause) { + errorReporter.reportError("Error trying to remove series " + series.getName() + + ": " + cause.getMessage()); + } + + @Override + public void onSuccess(Void result) { + regattaRefresher.fillRegattas(); + } + })); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaListComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaListComposite.java index 3190c64efe4..6d8b8221ece 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaListComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaListComposite.java @@ -182,32 +182,34 @@ public class RegattaListComposite extends Composite implements RegattaDisplayer private void removeRegatta(final RegattaDTO regatta) { final RegattaIdentifier regattaIdentifier = new RegattaName(regatta.getName()); - sailingService.removeRegatta(regattaIdentifier, new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Error trying to remove regatta " + regatta.getName() + ": " + caught.getMessage()); - } - - @Override - public void onSuccess(Void result) { - regattaRefresher.fillRegattas(); - } - }); + sailingService.removeRegatta(regattaIdentifier,new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to remove regatta " + regatta.getName() + ": " + caught.getMessage()); + } + + @Override + public void onSuccess(Void result) { + regattaRefresher.fillRegattas(); + } + })); } private void editRegatta(final RegattaDTO toBeEdited) { final Collection existingRegattas = getAllRegattas(); - sailingService.getEvents(new MarkedAsyncCallback>() { - @Override - public void handleFailure(Throwable caught) { - openEditRegattaDialog(toBeEdited, existingRegattas, Collections. emptyList()); - } - - @Override - public void handleSuccess(List events) { - openEditRegattaDialog(toBeEdited, existingRegattas, Collections.unmodifiableList(events)); - } - }); + sailingService.getEvents(new MarkedAsyncCallback>( + new AsyncCallback>() { + @Override + public void onFailure(Throwable caught) { + openEditRegattaDialog(toBeEdited, existingRegattas, Collections. emptyList()); + } + + @Override + public void onSuccess(List events) { + openEditRegattaDialog(toBeEdited, existingRegattas, Collections.unmodifiableList(events)); + } + })); } private void openEditRegattaDialog(RegattaDTO regatta, Collection existingRegattas, @@ -229,35 +231,36 @@ public class RegattaListComposite extends Composite implements RegattaDisplayer final RegattaIdentifier regattaName = new RegattaName(editedRegatta.getName()); sailingService.updateRegatta(regattaName, editedRegatta.defaultCourseAreaUuid, - editedRegatta.configuration, new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable caught) { - errorReporter.reportError("Error trying to update regatta " + editedRegatta.getName() + ": " + caught.getMessage()); - } - - @Override - public void handleSuccess(Void result) { - regattaRefresher.fillRegattas(); - } - }); + editedRegatta.configuration, new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to update regatta " + editedRegatta.getName() + + ": " + caught.getMessage()); + } + + @Override + public void onSuccess(Void result) { + regattaRefresher.fillRegattas(); + } + })); for (SeriesDTO series : editedRegatta.series) { sailingService.updateSeries(regattaName, series.getName(), series.getName(), series.isMedal(), series.getDiscardThresholds(), series.isStartsWithZeroScore(), series.isFirstColumnIsNonDiscardableCarryForward(), series.hasSplitFleetContiguousScoring(), - series.getFleets(), - new AsyncCallback() { - - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Error trying to update regatta " + editedRegatta.getName() + ": " + caught.getMessage()); - } - - @Override - public void onSuccess(Void result) { - regattaRefresher.fillRegattas(); - } - }); + series.getFleets(), new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to update regatta " + editedRegatta.getName() + ": " + caught.getMessage()); + } + + @Override + public void onSuccess(Void result) { + regattaRefresher.fillRegattas(); + } + })); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TracTracEventManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TracTracEventManagementPanel.java index 3bc0f723a0c..a9008533233 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TracTracEventManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TracTracEventManagementPanel.java @@ -16,6 +16,7 @@ import com.google.gwt.user.cellview.client.Column; import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; import com.google.gwt.user.cellview.client.TextColumn; import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CaptionPanel; import com.google.gwt.user.client.ui.CheckBox; @@ -432,28 +433,29 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel { } private void fillConfigurations() { - this.sailingService.getPreviousTracTracConfigurations(new MarkedAsyncCallback>() { - @Override - public void handleFailure(Throwable caught) { - reportError("Remote Procedure Call getPreviousConfigurations() - Failure: " + caught.getMessage()); - } - - @Override - public void handleSuccess(List result) { - TracTracEventManagementPanel.this.previousConfigurations.clear(); - TracTracEventManagementPanel.this.connectionsHistoryListBox.clear(); - - for (TracTracConfigurationDTO config : result) { - TracTracEventManagementPanel.this.previousConfigurations.put(config.name, config); - TracTracEventManagementPanel.this.connectionsHistoryListBox.addItem(config.name); - } - - - if (!result.isEmpty()) { - updatePanelFromSelectedStoredConfiguration(); - } - } - }); + this.sailingService.getPreviousTracTracConfigurations(new MarkedAsyncCallback>( + new AsyncCallback>() { + @Override + public void onFailure(Throwable caught) { + reportError("Remote Procedure Call getPreviousConfigurations() - Failure: " + caught.getMessage()); + } + + @Override + public void onSuccess(List result) { + TracTracEventManagementPanel.this.previousConfigurations.clear(); + TracTracEventManagementPanel.this.connectionsHistoryListBox.clear(); + + for (TracTracConfigurationDTO config : result) { + TracTracEventManagementPanel.this.previousConfigurations.put(config.name, config); + TracTracEventManagementPanel.this.connectionsHistoryListBox.addItem(config.name); + } + + + if (!result.isEmpty()) { + updatePanelFromSelectedStoredConfiguration(); + } + } + })); } private void fillRaces(final SailingServiceAsync sailingService, boolean listHiddenRaces) { @@ -464,55 +466,57 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel { final String tractracUsername = tractracUsernameTextBox.getValue(); final String tractracPassword = tractracPasswordTextBox.getValue(); - sailingService.listTracTracRacesInEvent(jsonURL, listHiddenRaces, new MarkedAsyncCallback>>() { - @Override - public void handleFailure(Throwable caught) { - loadingMessageLabel.setText(""); - reportError("Error trying to list races: " + caught.getMessage()); - } - - @Override - public void handleSuccess(final Pair> result) { - loadingMessageLabel.setText("Building resultset and saving configuration..."); - TracTracEventManagementPanel.this.availableTracTracRaces.clear(); + sailingService.listTracTracRacesInEvent(jsonURL, listHiddenRaces, new MarkedAsyncCallback>>( + new AsyncCallback>>() { + @Override + public void onFailure(Throwable caught) { + loadingMessageLabel.setText(""); + reportError("Error trying to list races: " + caught.getMessage()); + } + + @Override + public void onSuccess(final Pair> result) { + loadingMessageLabel.setText("Building resultset and saving configuration..."); + TracTracEventManagementPanel.this.availableTracTracRaces.clear(); + + final String eventName = result.getA(); + final List eventRaces = result.getB(); + + if (eventRaces != null) { + TracTracEventManagementPanel.this.availableTracTracRaces.addAll(eventRaces); + } + + List races = TracTracEventManagementPanel.this.raceList.getList(); + + races.clear(); + races.addAll(TracTracEventManagementPanel.this.availableTracTracRaces); + + TracTracEventManagementPanel.this.racesFilterablePanel.getTextBox().setText(""); + TracTracEventManagementPanel.this.racesTable.setPageSize(races.size()); + loadingMessageLabel.setText(""); + + // store a successful configuration in the database for later retrieval + sailingService.storeTracTracConfiguration(eventName, jsonURL, liveDataURI, storedDataURI, + courseDesignUpdateURI, tractracUsername, tractracPassword, new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + reportError("Exception trying to store configuration in DB: " + caught.getMessage()); + } - final String eventName = result.getA(); - final List eventRaces = result.getB(); - - if (eventRaces != null) { - TracTracEventManagementPanel.this.availableTracTracRaces.addAll(eventRaces); - } - - List races = TracTracEventManagementPanel.this.raceList.getList(); - - races.clear(); - races.addAll(TracTracEventManagementPanel.this.availableTracTracRaces); - - TracTracEventManagementPanel.this.racesFilterablePanel.getTextBox().setText(""); - TracTracEventManagementPanel.this.racesTable.setPageSize(races.size()); - loadingMessageLabel.setText(""); - - // store a successful configuration in the database for later retrieval - sailingService.storeTracTracConfiguration(eventName, jsonURL, liveDataURI, storedDataURI, courseDesignUpdateURI, tractracUsername, tractracPassword, - new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable caught) { - reportError("Exception trying to store configuration in DB: " + caught.getMessage()); - } - - @Override - public void handleSuccess(Void voidResult) { - // refresh list of previous configurations - TracTracConfigurationDTO config = new TracTracConfigurationDTO(eventName, jsonURL, - liveDataURI, storedDataURI, courseDesignUpdateURI, tractracUsername, tractracPassword); - - if (TracTracEventManagementPanel.this.previousConfigurations.put(config.name, config) == null) { - TracTracEventManagementPanel.this.connectionsHistoryListBox.addItem(config.name); - } - } - }); - } - }); + @Override + public void onSuccess(Void voidResult) { + // refresh list of previous configurations + TracTracConfigurationDTO config = new TracTracConfigurationDTO(eventName, jsonURL, + liveDataURI, storedDataURI, courseDesignUpdateURI, tractracUsername, tractracPassword); + + if (TracTracEventManagementPanel.this.previousConfigurations.put(config.name, config) == null) { + TracTracEventManagementPanel.this.connectionsHistoryListBox.addItem(config.name); + } + } + })); + } + })); } private boolean checkBoatClassMatch(TracTracRaceRecordDTO tracTracRecord, RegattaDTO selectedRegatta) { @@ -587,18 +591,19 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel { } } sailingService.trackWithTracTrac(regattaIdentifier, selectedRaces, liveURI, storedURI, courseDesignUpdateURI, trackWind, correctWind, - simulateWithStartTimeNow, tractracUsername, tractracPassword, new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable caught) { - reportError("Error trying to register races " + selectedRaces + " for tracking: " - + caught.getMessage() + ". Check live/stored URI syntax."); - } - - @Override - public void handleSuccess(Void result) { - TracTracEventManagementPanel.this.regattaRefresher.fillRegattas(); - } - }); + simulateWithStartTimeNow, tractracUsername, tractracPassword, new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + reportError("Error trying to register races " + selectedRaces + " for tracking: " + + caught.getMessage() + ". Check live/stored URI syntax."); + } + + @Override + public void onSuccess(Void result) { + TracTracEventManagementPanel.this.regattaRefresher.fillRegattas(); + } + })); } private void updatePanelFromSelectedStoredConfiguration() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesListComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesListComposite.java index 4cd2436ba3a..fdfeeec2b95 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesListComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesListComposite.java @@ -4,7 +4,7 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; - +import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.ui.Button; @@ -60,20 +60,21 @@ public class TrackedRacesListComposite extends AbstractTrackedRacesListComposite racesToStopTracking.add(race.getRaceIdentifier()); } } - sailingService.stopTrackingRaces(racesToStopTracking, new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable caught) { - errorReporter.reportError("Exception trying to stop tracking races " + races + ": " + caught.getMessage()); - } - - @Override - public void handleSuccess(Void result) { - regattaRefresher.fillRegattas(); - for (TrackedRaceChangedListener listener : raceIsTrackedRaceChangeListener) { - listener.changeTrackingRace(racesToStopTracking, false); - } - } - }); + sailingService.stopTrackingRaces(racesToStopTracking, new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Exception trying to stop tracking races " + races + ": " + caught.getMessage()); + } + + @Override + public void onSuccess(Void result) { + regattaRefresher.fillRegattas(); + for (TrackedRaceChangedListener listener : raceIsTrackedRaceChangeListener) { + listener.changeTrackingRace(racesToStopTracking, false); + } + } + })); } private void removeAndUntrackRaces(final Iterable races) { @@ -81,22 +82,22 @@ public class TrackedRacesListComposite extends AbstractTrackedRacesListComposite for (RaceDTO race : races) { regattaNamesAndRaceNames.add((RegattaNameAndRaceName) race.getRaceIdentifier()); } - sailingService.removeAndUntrackRaces(regattaNamesAndRaceNames, - new MarkedAsyncCallback() { + sailingService.removeAndUntrackRaces(regattaNamesAndRaceNames, new MarkedAsyncCallback( + new AsyncCallback() { @Override - public void handleFailure(Throwable caught) { + public void onFailure(Throwable caught) { errorReporter.reportError("Exception trying to remove races " + regattaNamesAndRaceNames + ": " + caught.getMessage()); } @Override - public void handleSuccess(Void result) { + public void onSuccess(Void result) { regattaRefresher.fillRegattas(); for (TrackedRaceChangedListener listener : raceIsTrackedRaceChangeListener) { listener.changeTrackingRace(regattaNamesAndRaceNames, false); } } - }); + })); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DetailTypeFormatter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DetailTypeFormatter.java index 391f0d3198f..481828356ac 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DetailTypeFormatter.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DetailTypeFormatter.java @@ -101,10 +101,8 @@ public class DetailTypeFormatter { return stringMessages.averageTackLossInMeters(); case AVERAGE_JIBE_LOSS_IN_METERS: return stringMessages.averageJibeLossInMeters(); - case RACE_TIME_SINCE_LAST_POSITION_FIX_IN_SECONDS: - return stringMessages.timeSinceLastPositionFix(); - case RACE_TRACKING_QUALITY: - return "TQ"; + case RACE_RATIO_BETWEEN_TIME_SINCE_LAST_POSITION_FIX_AND_AVERAGE_SAMPLING_INTERVAL: + return stringMessages.ratioBetweenTimeSinceLastPositionFixAndAverageSamplingInterval(); case RACE_DISTANCE_TO_START_FIVE_SECONDS_BEFORE_RACE_START: return stringMessages.distanceToLineFiveSecondsBeforeStart(); case RACE_SPEED_OVER_GROUND_FIVE_SECONDS_BEFORE_START: @@ -168,7 +166,6 @@ public class DetailTypeFormatter { case GAP_CHANGE_SINCE_LEG_START_IN_SECONDS: case RACE_GAP_TO_LEADER_IN_SECONDS: case ESTIMATED_TIME_TO_NEXT_WAYPOINT_IN_SECONDS: - case RACE_TIME_SINCE_LAST_POSITION_FIX_IN_SECONDS: case TIME_TRAVELED: case RACE_TIME_TRAVELED: case RACE_TIME_TRAVELED_DOWNWIND: @@ -176,6 +173,9 @@ public class DetailTypeFormatter { case RACE_TIME_TRAVELED_UPWIND: return stringMessages.secondsUnit(); + case RACE_RATIO_BETWEEN_TIME_SINCE_LAST_POSITION_FIX_AND_AVERAGE_SAMPLING_INTERVAL: + return stringMessages.ratio(); + case TOTAL_TIME_SAILED_IN_SECONDS: case TOTAL_TIME_SAILED_DOWNWIND_IN_SECONDS: case TOTAL_TIME_SAILED_UPWIND_IN_SECONDS: @@ -197,7 +197,6 @@ public class DetailTypeFormatter { case NUMBER_OF_MANEUVERS: case DISPLAY_LEGS: case SIDE_TO_WHICH_MARK_AT_LEG_START_WAS_ROUNDED: - case RACE_TRACKING_QUALITY: case BEAT_ANGLE: return ""; } @@ -304,10 +303,8 @@ public class DetailTypeFormatter { return stringMessages.totalAverageSpeedOverGroundTooltip(); case WINDWARD_DISTANCE_TO_GO_IN_METERS: return stringMessages.windwardDistanceToGoInMetersTooltip(); - case RACE_TIME_SINCE_LAST_POSITION_FIX_IN_SECONDS: - return stringMessages.timeSinceLastPositionFixTooltip(); - case RACE_TRACKING_QUALITY: - return stringMessages.trackingQuality(); + case RACE_RATIO_BETWEEN_TIME_SINCE_LAST_POSITION_FIX_AND_AVERAGE_SAMPLING_INTERVAL: + return stringMessages.ratioBetweenTimeSinceLastPositionFixAndAverageSamplingIntervalTooltip(); case RACE_DISTANCE_TO_START_FIVE_SECONDS_BEFORE_RACE_START: return stringMessages.distanceToLineFiveSecondsBeforeStartTooltip(); case RACE_SPEED_OVER_GROUND_FIVE_SECONDS_BEFORE_START: diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/MarkedAsyncCallback.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/MarkedAsyncCallback.java index 5f29978ccff..7ff655fe4ce 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/MarkedAsyncCallback.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/MarkedAsyncCallback.java @@ -4,21 +4,21 @@ import com.google.gwt.debug.client.DebugInfo; import com.google.gwt.user.client.rpc.AsyncCallback; /** - *

Abstract base class for asynchronous remote procedure calls which should be marked as pending until they complete. + *

Decorator for asynchronous remote procedure calls which should be marked as pending until they complete. * Such calls will be marked using a counter, which is necessary in UI tests to be able able to tell exactly when an * asynchronous request has finished. With this counter a test which triggers a request (which can cause additional * request) can wait until the requests have finished. It's guaranteed that the counter is decremented no matter if * the call was successful or not.

* *

Note: Since the counter for pending Ajax requests is incremented as soon as an instance of this class is created - * you must not create instances which are not used or assigned to an field!

+ * you must not create instances of this class which are not used or assigned to an field for multiple uses!

* * @param * The type of the return value for the asynchronous remote procedure call. * @author * D049941 */ -public abstract class MarkedAsyncCallback implements AsyncCallback { +public final class MarkedAsyncCallback implements AsyncCallback { /** *

The key for the category of global requests. The key for the global category is just an empty string.

*/ @@ -26,21 +26,30 @@ public abstract class MarkedAsyncCallback implements AsyncCallback { private String category; + private AsyncCallback callback; + /** *

Creates a marked asynchronous remote procedure call for the global category.

+ * + *

ATTENION: Since the counter for pending Ajax requests is incremented as soon as an instance of this class is + * created you must not create instances which are not used or assigned to an field!

*/ - public MarkedAsyncCallback() { - this(CATEGORY_GLOBAL); + public MarkedAsyncCallback(AsyncCallback callback) { + this(callback, CATEGORY_GLOBAL); } /** *

Creates a marked asynchronous remote procedure call for the given category. As soon as the asynchronous remote * procedure call is created, the counter for pending Ajax calls for the given category is incremented.

* + *

ATTENION: Since the counter for pending Ajax requests is incremented as soon as an instance of this class is + * created you must not create instances which are not used or assigned to an field!

+ * * @param category * The category of the asynchronous remote procedure call. */ - public MarkedAsyncCallback(String category) { + public MarkedAsyncCallback(AsyncCallback callback, String category) { + this.callback = callback; this.category = category; if(DebugInfo.isDebugIdEnabled()) { @@ -49,8 +58,8 @@ public abstract class MarkedAsyncCallback implements AsyncCallback { } /** - *

Called when the asynchronous call fails to complete normally. The concrete handling of the failure has to be - * implemented in {@link #handleFailure(Throwable)}. It's guaranteed that the counter for the pending requests is + *

Called when the asynchronous call fails to complete normally. The concrete handling of the failure is + * delegated to the decorated callback. It's guaranteed that the counter for the pending requests is * decremented.

* * @param cause @@ -59,7 +68,7 @@ public abstract class MarkedAsyncCallback implements AsyncCallback { @Override public final void onFailure(Throwable cause) { try { - handleFailure(cause); + this.callback.onFailure(cause); } finally { if(DebugInfo.isDebugIdEnabled()) { PendingAjaxCallMarker.decrementPendingAjaxCalls(this.category); @@ -68,8 +77,8 @@ public abstract class MarkedAsyncCallback implements AsyncCallback { } /** - *

Called when the asynchronous call completes successfully. The concrete handling of the result has to be - * implemented in {@link #handleSuccess(Object)}. It's guaranteed that the counter for the pending requests is + *

Called when the asynchronous call completes successfully. The concrete handling of the result is delegated to + * the decorated callback. It's guaranteed that the counter for the pending requests is * decremented.

* * @param result @@ -78,27 +87,11 @@ public abstract class MarkedAsyncCallback implements AsyncCallback { @Override public final void onSuccess(T result) { try { - handleSuccess(result); + this.callback.onSuccess(result); } finally { if(DebugInfo.isDebugIdEnabled()) { PendingAjaxCallMarker.decrementPendingAjaxCalls(this.category); } } } - - /** - *

Called when the asynchronous call fails to complete normally.

- * - * @param cause - * The failure encountered while executing the remote procedure call. - */ - protected abstract void handleFailure(Throwable cause); - - /** - *

Called when the asynchronous call completes successfully.

- * - * @param result - * The return value of the remote produced call. - */ - protected abstract void handleSuccess(T result); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index 2b63098bd16..15c6f96068d 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -778,8 +778,8 @@ public interface StringMessages extends Messages { String importSelectAtLeastOne(); String deselectAll(); String polarDiagramButton(); - String timeSinceLastPositionFix(); - String timeSinceLastPositionFixTooltip(); + String ratioBetweenTimeSinceLastPositionFixAndAverageSamplingInterval(); + String ratioBetweenTimeSinceLastPositionFixAndAverageSamplingIntervalTooltip(); String trackingQuality(); String legType(); String seriesLeaderboard(); @@ -964,4 +964,6 @@ public interface StringMessages extends Messages { String eventOverview(); String start(); String overallProgress(); + String showAddedScores(); + String ratio(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index 8033e4a1e76..9c4d2b3ff9e 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -778,8 +778,8 @@ importSelectedLeaderboardGroups=Import selected leaderboard groups importSelectAtLeastOne=You have to select at least one leaderboard group to import deselectAll=Deselect all polarDiagramButton=Polar Diagram -timeSinceLastPositionFix=Last GPS -timeSinceLastPositionFixTooltip=Time since last received GPS position +ratioBetweenTimeSinceLastPositionFixAndAverageSamplingInterval=GPS Lag +ratioBetweenTimeSinceLastPositionFixAndAverageSamplingIntervalTooltip=Ratio between time since last received GPS position and average sampling interval trackingQuality=Tracking quality legType=Leg Type sailID=Sail Number @@ -952,4 +952,6 @@ releaseNotes=News and Release History hasSplitFleetContiguousScoring=Split fleets scored contiguously overallProgress=Overall Progress eventOverview=Event Overview -start=Start \ No newline at end of file +start=Start +showAddedScores=Show added scores for each entry in leaderboard +ratio=ratio \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index a9a29519830..fef03c01e43 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -774,8 +774,8 @@ importSelectedLeaderboardGroups=Ausgewählte Leaderboard Groups selektieren importSelectAtLeastOne=Es muss mindestens eine Leaderboard Group ausgewählt werden deselectAll=Alle deselektieren polarDiagramButton=Polardiagramm -timeSinceLastPositionFix=Letztes GPS -timeSinceLastPositionFixTooltip=Zeit seit der letzten empfangenen GPS-Position +ratioBetweenTimeSinceLastPositionFixAndAverageSamplingInterval=GPS Verzug +ratioBetweenTimeSinceLastPositionFixAndAverageSamplingIntervalTooltip=Verhältnis zwischen dem Alter der zuletzt empfangenen GPS-Position und dem durchschnittlichen Abtastintervall trackingQuality=Tracking-Qualität legType=Art des Schenkels sailID=Segelnummer @@ -948,4 +948,6 @@ releaseNotes=Neuigkeiten und Änderungshistorie hasSplitFleetContiguousScoring=Gruppen durchgängig bepunkten overallProgress=Gesamtfortschritt eventOverview=Veranstaltungsübersicht -start=Start \ No newline at end of file +start=Start +showAddedScores=Addierte Punkte für jeden Eintrag im Leaderboard anzeigen +ratio=Verhältnis \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorLeaderboardChart.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorLeaderboardChart.java index e8030b29cfa..16331eaf40e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorLeaderboardChart.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorLeaderboardChart.java @@ -53,6 +53,8 @@ import com.sap.sailing.gwt.ui.client.shared.components.Component; */ public abstract class AbstractCompetitorLeaderboardChart extends AbstractLazyComponent implements Component, CompetitorSelectionChangeListener, RequiresResize, TimeListener { + public static final String LODA_LEADERBOARD_CHART_DATA_CATEGORY = "loadLeaderboradChartData"; + private static final int LINE_WIDTH = 1; protected final CompetitorSelectionProvider competitorSelectionProvider; protected final Map competitorSeries; @@ -217,8 +219,11 @@ public abstract class AbstractCompetitorLeaderboardChart extends A chart.showLoading(stringMessages.loadingCompetitorData()); } - GetLeaderboardDataEntriesAction getLeaderboardDataEntriesAction = new GetLeaderboardDataEntriesAction(sailingService, - leaderboardName, /* date */ null, selectedDetailType, new AsyncCallback, List>>>() { + GetLeaderboardDataEntriesAction getLeaderboardDataEntriesAction = new GetLeaderboardDataEntriesAction( + sailingService, leaderboardName, /* date */ null, selectedDetailType); + + asyncActionsExecutor.execute(getLeaderboardDataEntriesAction, LODA_LEADERBOARD_CHART_DATA_CATEGORY, + new AsyncCallback, List>>>() { @Override public void onSuccess(List, List>> result) { List chartSeries = new ArrayList(Arrays.asList(chart.getSeries())); @@ -237,14 +242,14 @@ public abstract class AbstractCompetitorLeaderboardChart extends A default: break; } - + chart.setSizeToMatchContainer(); // it's important here to recall the redraw method, otherwise the bug fix for wrong checkbox // positions (nativeAdjustCheckboxPosition) // in the BaseChart class would not be called chart.redraw(); } - + @Override public void onFailure(Throwable caught) { chart.hideLoading(); @@ -252,8 +257,6 @@ public abstract class AbstractCompetitorLeaderboardChart extends A timer.getPlayMode() == PlayModes.Live); } }); - - asyncActionsExecutor.execute(getLeaderboardDataEntriesAction); } private void fillTotalRanksSeries(List, List>> result, List chartSeries) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorRaceChart.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorRaceChart.java index 86da0f117f4..2b31873584b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorRaceChart.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorRaceChart.java @@ -72,6 +72,8 @@ import com.sap.sailing.gwt.ui.shared.CompetitorsRaceDataDTO; */ public abstract class AbstractCompetitorRaceChart extends AbstractRaceChart implements CompetitorSelectionChangeListener, RequiresResize { + public static final String LODA_COMPETITOR_CHART_DATA_CATEGORY = "loadCompetitorChartData"; + private static final int LINE_WIDTH = 1; private final Label noCompetitorsSelectedLabel; @@ -218,7 +220,9 @@ public abstract class AbstractCompetitorRaceChart() { + leaderboardGroupName, leaderboardName); + asyncActionsExecutor.execute(getCompetitorsRaceDataAction, LODA_COMPETITOR_CHART_DATA_CATEGORY, + new AsyncCallback() { @Override public void onSuccess(final CompetitorsRaceDataDTO result) { hideLoading(); @@ -234,7 +238,7 @@ public abstract class AbstractCompetitorRaceChart, RequiresResize { + public static final String LODA_WIND_CHART_DATA_CATEGORY = "loadWindChartData"; + private static final int LINE_WIDTH = 1; private final WindChartSettings settings; @@ -449,8 +451,9 @@ public class WindChart extends AbstractRaceChart implements Component() { + from, to, settings.getResolutionInMilliseconds(), null); + asyncActionsExecutor.execute(getWindInfoAction, LODA_WIND_CHART_DATA_CATEGORY, + new AsyncCallback() { @Override public void onSuccess(WindInfoForRaceDTO result) { if (result != null) { @@ -463,7 +466,7 @@ public class WindChart extends AbstractRaceChart implements Component 0) { shiftRight(1); } else { @@ -524,35 +528,35 @@ public class SliderBar extends FocusPanel implements RequiresResize, HasValue 0) { int lineWidth = lineElement.getOffsetWidth(); int lineLeft = lineElement.getAbsoluteLeft(); @@ -1115,8 +1116,8 @@ public class SliderBar extends FocusPanel implements RequiresResize, HasValue, RequiresDataInitialization, RequiresResize { + public static final String GET_RACE_MAP_DATA_CATEGORY = "getRaceMapData"; + public static final String GET_WIND_DATA_CATEGORY = "getWindData"; + private MapWidget map; private final SailingServiceAsync sailingService; @@ -426,108 +429,107 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe final int requestID = ++boatPositionRequestIDCounter; GetRaceMapDataAction getRaceMapDataAction = new GetRaceMapDataAction(sailingService, competitorSelection.getAllCompetitors(), race, - newTime, fromAndToAndOverlap.getA(), fromAndToAndOverlap.getB(), /* extrapolate */ true, new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Error obtaining racemap data: " + caught.getMessage(), true /*silentMode */); - } - - @Override - public void onSuccess(RaceMapDataDTO raceMapDataDTO) { - if (map != null && raceMapDataDTO != null) { - quickRanks = raceMapDataDTO.quickRanks; - // process response only if not received out of order - if (startedProcessingRequestID < requestID) { - startedProcessingRequestID = requestID; - // Do boat specific actions - Map> boatData = raceMapDataDTO.boatPositions; - long timeForPositionTransitionMillis = calculateTimeForPositionTransition(newTime, oldTime); - fixesAndTails.updateFixes(boatData, fromAndToAndOverlap.getC(), RaceMap.this, timeForPositionTransitionMillis); - showBoatsOnMap(newTime, timeForPositionTransitionMillis, getCompetitorsToShow()); - showCompetitorInfoOnMap(newTime, timeForPositionTransitionMillis, competitorSelection.getSelectedCompetitors()); - if (douglasMarkers != null) { - removeAllMarkDouglasPeuckerpoints(); - } - if (maneuverMarkers != null) { - removeAllManeuverMarkers(); - } - - // Do mark specific actions - showCourseMarksOnMap(raceMapDataDTO.coursePositions); - showCourseSidelinesOnMap(raceMapDataDTO.courseSidelines); - showStartAndFinishLines(raceMapDataDTO.coursePositions); - showAdvantageLine(competitorsToShow, newTime); - - // Rezoom the map - // TODO make this a loop across the LatLngBoundsCalculators, pulling them from a collection updated in updateSettings - if (!settings.getZoomSettings().containsZoomType(ZoomTypes.NONE)) { // Auto zoom if setting is not manual - LatLngBounds bounds = settings.getZoomSettings().getNewBounds(RaceMap.this); - zoomMapToNewBounds(bounds); - mapFirstZoomDone = true; - } else if (!mapFirstZoomDone) { // Zoom once to the marks - zoomMapToNewBounds(new CourseMarksBoundsCalculator().calculateNewBounds(RaceMap.this)); - mapFirstZoomDone = true; - /* - * Reset the mapZoomedOrPannedSinceLastRaceSelection: In spite of the fact that - * the map was just zoomed to the bounds of the marks, it was not a zoom or pan - * triggered by the user. As a consequence the - * mapZoomedOrPannedSinceLastRaceSelection option has to reset again. - */ - // TODO bug 494: consider initial user-specific zoom settings + newTime, fromAndToAndOverlap.getA(), fromAndToAndOverlap.getB(), /* extrapolate */ true); + asyncActionsExecutor.execute(getRaceMapDataAction, GET_RACE_MAP_DATA_CATEGORY, new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error obtaining racemap data: " + caught.getMessage(), true /*silentMode */); + } + + @Override + public void onSuccess(RaceMapDataDTO raceMapDataDTO) { + if (map != null && raceMapDataDTO != null) { + quickRanks = raceMapDataDTO.quickRanks; + // process response only if not received out of order + if (startedProcessingRequestID < requestID) { + startedProcessingRequestID = requestID; + // Do boat specific actions + Map> boatData = raceMapDataDTO.boatPositions; + long timeForPositionTransitionMillis = calculateTimeForPositionTransition(newTime, oldTime); + fixesAndTails.updateFixes(boatData, fromAndToAndOverlap.getC(), RaceMap.this, timeForPositionTransitionMillis); + showBoatsOnMap(newTime, timeForPositionTransitionMillis, getCompetitorsToShow()); + showCompetitorInfoOnMap(newTime, timeForPositionTransitionMillis, competitorSelection.getSelectedCompetitors()); + if (douglasMarkers != null) { + removeAllMarkDouglasPeuckerpoints(); + } + if (maneuverMarkers != null) { + removeAllManeuverMarkers(); + } + + // Do mark specific actions + showCourseMarksOnMap(raceMapDataDTO.coursePositions); + showCourseSidelinesOnMap(raceMapDataDTO.courseSidelines); + showStartAndFinishLines(raceMapDataDTO.coursePositions); + showAdvantageLine(competitorsToShow, newTime); + + // Rezoom the map + // TODO make this a loop across the LatLngBoundsCalculators, pulling them from a collection updated in updateSettings + if (!settings.getZoomSettings().containsZoomType(ZoomTypes.NONE)) { // Auto zoom if setting is not manual + LatLngBounds bounds = settings.getZoomSettings().getNewBounds(RaceMap.this); + zoomMapToNewBounds(bounds); + mapFirstZoomDone = true; + } else if (!mapFirstZoomDone) { // Zoom once to the marks + zoomMapToNewBounds(new CourseMarksBoundsCalculator().calculateNewBounds(RaceMap.this)); + mapFirstZoomDone = true; + /* + * Reset the mapZoomedOrPannedSinceLastRaceSelection: In spite of the fact that + * the map was just zoomed to the bounds of the marks, it was not a zoom or pan + * triggered by the user. As a consequence the + * mapZoomedOrPannedSinceLastRaceSelection option has to reset again. + */ + // TODO bug 494: consider initial user-specific zoom settings + } + } + } else { + lastTimeChangeBeforeInitialization = newTime; } } - } else { - lastTimeChangeBeforeInitialization = newTime; - } - } - }); - asyncActionsExecutor.execute(getRaceMapDataAction); + }); + // draw the wind into the map, get the combined wind List windSourceTypeNames = new ArrayList(); windSourceTypeNames.add(WindSourceType.EXPEDITION.name()); windSourceTypeNames.add(WindSourceType.COMBINED.name()); - GetWindInfoAction getWindInfoAction = new GetWindInfoAction(sailingService, race, newTime, 1000L, 1, windSourceTypeNames, - new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Error obtaining wind information: " + caught.getMessage(), true /*silentMode */); - } + GetWindInfoAction getWindInfoAction = new GetWindInfoAction(sailingService, race, newTime, 1000L, 1, windSourceTypeNames); + asyncActionsExecutor.execute(getWindInfoAction, GET_WIND_DATA_CATEGORY, new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error obtaining wind information: " + caught.getMessage(), true /*silentMode */); + } - @Override - public void onSuccess(WindInfoForRaceDTO windInfo) { - List> windSourcesToShow = new ArrayList>(); - if (windInfo != null) { - for (WindSource windSource: windInfo.windTrackInfoByWindSource.keySet()) { - WindTrackInfoDTO windTrackInfoDTO = windInfo.windTrackInfoByWindSource.get(windSource); - switch (windSource.getType()) { - case EXPEDITION: - // we filter out measured wind sources with a very little confidence - if (windTrackInfoDTO.minWindConfidence > 0.01) { - windSourcesToShow.add(new Pair(windSource, windTrackInfoDTO)); - } - break; - case COMBINED: - showCombinedWindOnMap(windSource, windTrackInfoDTO); - if (windTrackInfoDTO != null) { - lastCombinedWindTrackInfoDTO = windTrackInfoDTO; - showAdvantageLine(competitorsToShow, newTime); - } - break; - default: - // Which wind sources are requested is defined in a list above this - // action. So we throw here an exception to notice a missing source. - throw new UnsupportedOperationException( - "There is currently no support for the enum value '" - + windSource.getType() + "' in this method."); + @Override + public void onSuccess(WindInfoForRaceDTO windInfo) { + List> windSourcesToShow = new ArrayList>(); + if (windInfo != null) { + for (WindSource windSource: windInfo.windTrackInfoByWindSource.keySet()) { + WindTrackInfoDTO windTrackInfoDTO = windInfo.windTrackInfoByWindSource.get(windSource); + switch (windSource.getType()) { + case EXPEDITION: + // we filter out measured wind sources with a very little confidence + if (windTrackInfoDTO.minWindConfidence > 0.01) { + windSourcesToShow.add(new Pair(windSource, windTrackInfoDTO)); } - } + break; + case COMBINED: + showCombinedWindOnMap(windSource, windTrackInfoDTO); + if (windTrackInfoDTO != null) { + lastCombinedWindTrackInfoDTO = windTrackInfoDTO; + showAdvantageLine(competitorsToShow, newTime); + } + break; + default: + // Which wind sources are requested is defined in a list above this + // action. So we throw here an exception to notice a missing source. + throw new UnsupportedOperationException( + "There is currently no support for the enum value '" + + windSource.getType() + "' in this method."); } - showWindSensorsOnMap(windSourcesToShow); } - }); - - asyncActionsExecutor.execute(getWindInfoAction); + } + showWindSensorsOnMap(windSourcesToShow); + } + }); } } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapImageManager.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapImageManager.java index f089f106132..e68d25917f4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapImageManager.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapImageManager.java @@ -42,44 +42,44 @@ public class RaceMapImageManager { */ public void loadMapIcons(MapWidget map) { if(map != null) { - Marker tackToStarboardIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=T|00FF00|000000", 10, 33); + Marker tackToStarboardIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=T|71bf44|000000", 10, 33); maneuverIconsForTypeAndTargetTack.put(new Pair(ManeuverType.TACK, Tack.STARBOARD), tackToStarboardIcon); - Marker tackToPortIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=T|FF0000|000000", 10, 33); + Marker tackToPortIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=T|d95252|000000", 10, 33); maneuverIconsForTypeAndTargetTack.put(new Pair(ManeuverType.TACK, Tack.PORT), tackToPortIcon); - Marker jibeToStarboardIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=J|00FF00|000000", 10, 33); + Marker jibeToStarboardIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=J|71bf44|000000", 10, 33); maneuverIconsForTypeAndTargetTack.put(new Pair(ManeuverType.JIBE, Tack.STARBOARD), jibeToStarboardIcon); - Marker jibeToPortIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=J|FF0000|000000", 10, 33); + Marker jibeToPortIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=J|d95252|000000", 10, 33); maneuverIconsForTypeAndTargetTack.put(new Pair(ManeuverType.JIBE, Tack.PORT), jibeToPortIcon); - Marker headUpOnStarboardIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=H|00FF00|000000", 10, 33); + Marker headUpOnStarboardIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=H|71bf44|000000", 10, 33); maneuverIconsForTypeAndTargetTack.put(new Pair(ManeuverType.HEAD_UP, Tack.STARBOARD), headUpOnStarboardIcon); - Marker headUpOnPortIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=H|FF0000|000000", 10, 33); + Marker headUpOnPortIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=H|d95252|000000", 10, 33); maneuverIconsForTypeAndTargetTack.put(new Pair(ManeuverType.HEAD_UP, Tack.PORT), headUpOnPortIcon); - Marker bearAwayOnStarboardIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=B|00FF00|000000", 10, 33); + Marker bearAwayOnStarboardIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=B|71bf44|000000", 10, 33); maneuverIconsForTypeAndTargetTack.put(new Pair(ManeuverType.BEAR_AWAY, Tack.STARBOARD), bearAwayOnStarboardIcon); - Marker bearAwayOnPortIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=B|FF0000|000000", 10, 33); + Marker bearAwayOnPortIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=B|d95252|000000", 10, 33); maneuverIconsForTypeAndTargetTack.put(new Pair(ManeuverType.BEAR_AWAY, Tack.PORT), bearAwayOnPortIcon); - Marker markPassingToStarboardIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=M|00FF00|000000", 10, 33); + Marker markPassingToStarboardIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=M|71bf44|000000", 10, 33); maneuverIconsForTypeAndTargetTack.put(new Pair(ManeuverType.MARK_PASSING, Tack.STARBOARD), markPassingToStarboardIcon); - Marker markPassingToPortIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=M|FF0000|000000", 10, 33); + Marker markPassingToPortIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=M|d95252|000000", 10, 33); maneuverIconsForTypeAndTargetTack.put(new Pair(ManeuverType.MARK_PASSING, Tack.PORT), markPassingToPortIcon); Marker unknownManeuverIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=?|FFFFFF|000000", 10, 33); maneuverIconsForTypeAndTargetTack.put(new Pair(ManeuverType.UNKNOWN, Tack.STARBOARD), unknownManeuverIcon); maneuverIconsForTypeAndTargetTack.put(new Pair(ManeuverType.UNKNOWN, Tack.PORT), unknownManeuverIcon); - Marker penaltyCircleToStarboardIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=P|00FF00|000000", 10, 33); + Marker penaltyCircleToStarboardIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=P|71bf44|000000", 10, 33); maneuverIconsForTypeAndTargetTack.put(new Pair(ManeuverType.PENALTY_CIRCLE, Tack.STARBOARD), penaltyCircleToStarboardIcon); - Marker penaltyCircleToPortIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=P|FF0000|000000", 10, 33); + Marker penaltyCircleToPortIcon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=P|d95252|000000", 10, 33); maneuverIconsForTypeAndTargetTack.put(new Pair(ManeuverType.PENALTY_CIRCLE, Tack.PORT), penaltyCircleToPortIcon); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/CompareCompetitorsChartDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/CompareCompetitorsChartDialog.java deleted file mode 100644 index 0f92d3d4c16..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/CompareCompetitorsChartDialog.java +++ /dev/null @@ -1,163 +0,0 @@ -package com.sap.sailing.gwt.ui.leaderboard; - -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Map; - -import com.google.gwt.dom.client.Style.Float; -import com.google.gwt.event.dom.client.ChangeEvent; -import com.google.gwt.event.dom.client.ChangeHandler; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.HorizontalPanel; -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.ListBox; -import com.google.gwt.user.client.ui.VerticalPanel; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.impl.Util.Pair; -import com.sap.sailing.gwt.ui.actions.AsyncActionsExecutor; -import com.sap.sailing.gwt.ui.client.CompetitorSelectionProvider; -import com.sap.sailing.gwt.ui.client.ErrorReporter; -import com.sap.sailing.gwt.ui.client.RaceSelectionModel; -import com.sap.sailing.gwt.ui.client.RaceSelectionProvider; -import com.sap.sailing.gwt.ui.client.RaceTimesCalculationUtil; -import com.sap.sailing.gwt.ui.client.RaceTimesInfoProvider; -import com.sap.sailing.gwt.ui.client.RaceTimesInfoProviderListener; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; -import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.client.TimeRangeChangeListener; -import com.sap.sailing.gwt.ui.client.TimeRangeWithZoomModel; -import com.sap.sailing.gwt.ui.client.TimeRangeWithZoomProvider; -import com.sap.sailing.gwt.ui.client.Timer; -import com.sap.sailing.gwt.ui.client.shared.charts.MultiCompetitorRaceChart; -import com.sap.sailing.gwt.ui.client.shared.charts.MultiCompetitorRaceChartSettings; -import com.sap.sailing.gwt.ui.client.shared.components.ComponentToolbar; -import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; - -/** - * A dialog box that holds a {@link MultiCompetitorRaceChart} for comparing a list of preselected competitors. - * - * @author Benjamin Ebling, Axel Uhl (d043530) - * - */ -public class CompareCompetitorsChartDialog extends DialogBoxExt implements RaceTimesInfoProviderListener { - private final RaceSelectionProvider raceSelectionProvider; - private final SailingServiceAsync sailingService; - private final TimeRangeWithZoomProvider timeRangeWithZoomProvider; - private final Timer timer; - private final ErrorReporter errorReporter; - - private final MultiCompetitorRaceChart multiChartPanel; - - private final ListBox racesListBox; - - public CompareCompetitorsChartDialog(SailingServiceAsync sailingService, - List races, final RaceTimesInfoProvider raceTimesInfoProvider, final CompetitorSelectionProvider competitorSelectionProvider, - Timer timer, StringMessages stringMessages, ErrorReporter errorReporter, String leaderboardGroupName, String leaderboardName) { - super(new Label(stringMessages.close())); - this.sailingService = sailingService; - this.timer = timer; - this.errorReporter = errorReporter; - this.timeRangeWithZoomProvider = new TimeRangeWithZoomModel(); - this.setPopupPosition(15, 15); - this.setHTML(stringMessages.competitorCharts()); - this.setWidth(Window.getClientWidth() - 250 + "px"); - this.setAnimationEnabled(true); - - raceTimesInfoProvider.addRaceTimesInfoProviderListener(this); - raceSelectionProvider = new RaceSelectionModel(); - raceSelectionProvider.setAllRaces(races); - - multiChartPanel = new MultiCompetitorRaceChart(sailingService, new AsyncActionsExecutor(), competitorSelectionProvider, raceSelectionProvider, - timer, timeRangeWithZoomProvider, stringMessages, errorReporter, false, false, leaderboardGroupName, leaderboardName); - multiChartPanel.setSize("100%", "100%"); - - VerticalPanel contentPanel = new VerticalPanel(); - contentPanel.setSize("100%", "100%"); - - ComponentToolbar toolbar = new ComponentToolbar(multiChartPanel, stringMessages); - toolbar.addSettingsButton(); - - FlowPanel flowPanel = new FlowPanel(); - - HorizontalPanel raceSelectionPanel = new HorizontalPanel(); - raceSelectionPanel.setSpacing(3); - racesListBox = new ListBox(); - raceSelectionPanel.add(new Label(stringMessages.pleaseSelectARace() + ":")); - raceSelectionPanel.add(racesListBox); - for (RegattaAndRaceIdentifier race : raceSelectionProvider.getAllRaces()) { - racesListBox.addItem(race.toString()); - } - racesListBox.addChangeHandler(new ChangeHandler() { - @Override - public void onChange(ChangeEvent event) { - int selIndex = racesListBox.getSelectedIndex(); - String selItem = racesListBox.getItemText(selIndex); - for (RegattaAndRaceIdentifier race : raceSelectionProvider.getAllRaces()) { - if(selItem.equals(race.toString())) { - selectRace(race); - break; - } - } - } - }); - - RegattaAndRaceIdentifier firstRace = raceSelectionProvider.getAllRaces().iterator().next(); - racesListBox.setSelectedIndex(0); - selectRace(firstRace); - - flowPanel.add(raceSelectionPanel); - raceSelectionPanel.getElement().getStyle().setFloat(Float.LEFT); - flowPanel.add(toolbar); - toolbar.getElement().getStyle().setFloat(Float.RIGHT); - toolbar.setSpacing(0); - contentPanel.add(flowPanel); - contentPanel.add(multiChartPanel.getEntryWidget()); - - this.setWidget(contentPanel); - } - - private void selectRace(final RegattaAndRaceIdentifier selectedRace) { - sailingService.getRaceTimesInfo(selectedRace, new AsyncCallback() { - @Override - public void onSuccess(RaceTimesInfoDTO raceTimesInfo) { - updateMinMax(raceTimesInfo); - raceSelectionProvider.setSelection(Collections.singletonList(selectedRace)); - } - - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Error obtaining race times: " + caught.getMessage(), true /*silentMode */); - } - }); - - } - - private void updateMinMax(RaceTimesInfoDTO newRaceTimesInfo) { - Pair raceMinMax = RaceTimesCalculationUtil.caluclateRaceMinMax(timer, newRaceTimesInfo); - - Date min = raceMinMax.getA(); - Date max = raceMinMax.getB(); - - // never reduce max if it was already set - if (min != null && max != null && (timeRangeWithZoomProvider.getToTime() == null || timeRangeWithZoomProvider.getToTime().before(max))) { - timeRangeWithZoomProvider.setTimeRange(min, max, new TimeRangeChangeListener[0]); - } - } - - private RegattaAndRaceIdentifier getSelectedRace() { - return raceSelectionProvider.getSelectedRaces().size() > 0 ? raceSelectionProvider.getSelectedRaces().get(0) : null; - } - - @Override - public void raceTimesInfosReceived(Map raceTimesInfos, long clientTimeWhenRequestWasSent, Date serverTimeDuringRequest, long clientTimeWhenResponseWasReceived) { - timer.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived); - RegattaAndRaceIdentifier selectedRace = getSelectedRace(); - if (selectedRace != null) { - updateMinMax(raceTimesInfos.get(selectedRace)); - } - } - -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/DialogBoxExt.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/DialogBoxExt.java index a3535b49b73..4abd972eb15 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/DialogBoxExt.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/DialogBoxExt.java @@ -3,7 +3,7 @@ package com.sap.sailing.gwt.ui.leaderboard; import com.google.gwt.dom.client.EventTarget; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.safehtml.shared.SafeHtml; -import com.google.gwt.user.client.Element; +import com.google.gwt.dom.client.Element; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.DialogBox; import com.google.gwt.user.client.ui.HTML; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/FormattedDoubleDetailTypeColumn.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/FormattedDoubleDetailTypeColumn.java index 7a858f1363d..d4fbc480414 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/FormattedDoubleDetailTypeColumn.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/FormattedDoubleDetailTypeColumn.java @@ -17,18 +17,21 @@ public class FormattedDoubleDetailTypeColumn extends DetailTypeColumn field, String headerStyle, String columnStyle) { super(detailType, field, new TextCell(), headerStyle, columnStyle); - formatter = NumberFormatterFactory.getDecimalFormat(detailType.getPrecision()); - this.minMaxRenderer = new MinMaxRenderer(this, getComparator()); + formatter = createNumberFormatter(detailType); + this.minMaxRenderer = createMinMaxRenderer(); } + protected MinMaxRenderer createMinMaxRenderer() { + return new MinMaxRenderer(this, getComparator()); + } + + private NumberFormat createNumberFormatter(DetailType detailType) { + return NumberFormatterFactory.getDecimalFormat(detailType.getPrecision()); + } + protected MinMaxRenderer getMinMaxRenderer() { return minMaxRenderer; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardEntryPoint.java index deddbc30401..d840e4f1b7c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardEntryPoint.java @@ -53,6 +53,7 @@ public class LeaderboardEntryPoint extends AbstractEntryPoint { private static final String PARAM_CHART_DETAIL = "chartDetail"; private static final String PARAM_SHOW_OVERALL_LEADERBOARD = "showOverallLeaderboard"; private static final String PARAM_SHOW_SERIES_LEADERBOARDS = "showSeriesLeaderboards"; + private static final String PARAM_SHOW_ADDED_SCORES = "showAddedScores"; /** * Parameter to support scaling the complete page by a given factor. This works by either using the @@ -205,12 +206,14 @@ public class LeaderboardEntryPoint extends AbstractEntryPoint { } if (parameterMap.containsKey(PARAM_RACE_NAME) || parameterMap.containsKey(PARAM_RACE_DETAIL) || parameterMap.containsKey(PARAM_LEG_DETAIL) || parameterMap.containsKey(PARAM_MANEUVER_DETAIL) || - parameterMap.containsKey(PARAM_OVERALL_DETAIL)) { + parameterMap.containsKey(PARAM_OVERALL_DETAIL) || parameterMap.containsKey(PARAM_SHOW_ADDED_SCORES)) { List maneuverDetails = getDetailTypeListFromParamValue(parameterMap.get(PARAM_MANEUVER_DETAIL)); List raceDetails = getDetailTypeListFromParamValue(parameterMap.get(PARAM_RACE_DETAIL)); List overallDetails = getDetailTypeListFromParamValue(parameterMap.get(PARAM_OVERALL_DETAIL)); List legDetails = getDetailTypeListFromParamValue(parameterMap.get(PARAM_LEG_DETAIL)); List namesOfRacesToShow = getStringListFromParamValue(parameterMap.get(PARAM_RACE_NAME)); + boolean showAddedScores = parameterMap.containsKey(PARAM_SHOW_ADDED_SCORES) ? + Boolean.valueOf(parameterMap.get(PARAM_SHOW_ADDED_SCORES).get(0)) : false; boolean autoExpandPreSelectedRace = parameterMap.containsKey(PARAM_AUTO_EXPAND_PRESELECTED_RACE) ? Boolean.valueOf(parameterMap.get(PARAM_AUTO_EXPAND_PRESELECTED_RACE).get(0)) : (namesOfRacesToShow != null && namesOfRacesToShow.size() == 1); @@ -220,7 +223,7 @@ public class LeaderboardEntryPoint extends AbstractEntryPoint { autoExpandPreSelectedRace, refreshIntervalMillis, /* sort by column */ (namesOfRacesToShow != null && !namesOfRacesToShow.isEmpty()) ? namesOfRacesToShow.get(0) : null, /* ascending */ true, /* updateUponPlayStateChange */ raceDetails.isEmpty() && legDetails.isEmpty(), - raceColumnSelectionStrategy); + raceColumnSelectionStrategy, showAddedScores); } else { final List overallDetails = Collections.emptyList(); @@ -371,6 +374,12 @@ public class LeaderboardEntryPoint extends AbstractEntryPoint { maneuverDetails.append('='); maneuverDetails.append(maneuverDetail.name()); } + StringBuilder showAddedScores = new StringBuilder(); + showAddedScores.append('&'); + showAddedScores.append(PARAM_SHOW_ADDED_SCORES); + showAddedScores.append('='); + showAddedScores.append(settings.getLeaderboardSettings().isShowAddedScores()); + String debugParam = Window.Location.getParameter("gwt.codesvr"); String link = URLEncoder.encode("/gwt/Leaderboard.html?name=" + leaderboardName + (settings.isShowRaceDetails() ? "&"+PARAM_SHOW_RACE_DETAILS+"=true" : "") @@ -391,6 +400,7 @@ public class LeaderboardEntryPoint extends AbstractEntryPoint { + (settings.isAutoExpandLastRaceColumn() ? "&"+PARAM_AUTO_EXPAND_LAST_RACE_COLUMN+"=true" : "") + (settings.getLeaderboardSettings().getNumberOfLastRacesToShow() == null ? "" : "&"+PARAM_NAME_LAST_N+"="+settings.getLeaderboardSettings().getNumberOfLastRacesToShow()) + + showAddedScores.toString() + (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : "")); return link; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java index 3a581db97d3..0cadb54abe4 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java @@ -103,6 +103,7 @@ import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; */ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayStateListener, Component, IsEmbeddableComponent, CompetitorSelectionChangeListener, LeaderboardFetcher { + public static final String LOAD_LEADERBOARD_DATA_CATEGORY = "loadLeaderboardData"; private static final int RANK_COLUMN_INDEX = 0; private static final int SAIL_ID_COLUMN_INDEX = 1; @@ -202,6 +203,12 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS private boolean autoExpandPreSelectedRace; private boolean autoExpandLastRaceColumn; + + /** + * When true, the race columns don't display the competitors' scores in the race represented by the column + * but the cumulative score up to that race. + */ + private boolean showAddedScores; /** * Remembers whether the auto-expand of the pre-selected race (see {@link #autoExpandPreSelectedRace}) or last @@ -331,6 +338,7 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS if (!newSettings.isUpdateUponPlayStateChange() || !currentlyHandlingPlayStateChange) { settingsUpdatedExplicitly = true; } + setShowAddedScores(newSettings.isShowAddedScores()); List> columnsToExpandAgain = new ArrayList>(); for (int i = 0; i < getLeaderboardTable().getColumnCount(); i++) { Column c = getLeaderboardTable().getColumn(i); @@ -614,11 +622,28 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS public boolean isLive(FleetDTO fleetDTO) { return race.isLive(fleetDTO, timer.getLiveTimePointInMillis()); } - + @Override public String getColumnStyle() { return columnStyle; } + + /** + * Computes added scores for this RaceColumn + */ + private double computeAddedScores(LeaderboardRowDTO object) { + double addedScores = 0; + for (RaceColumnDTO raceColumn : getLeaderboard().getRaceList()) { + LeaderboardEntryDTO entryBefore = object.fieldsByRaceColumnName.get(raceColumn.getName()); + if (entryBefore.totalPoints != null) { + addedScores += entryBefore.totalPoints; + } + if (raceColumn.getName().equals(getRaceColumnName())) { + break; // we've reached the current column - stop here + } + } + return addedScores; + } /** * Displays a combination of total points and maxPointsReason in bold, transparent, strike-through, depending on @@ -640,28 +665,30 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS boolean isLive = isLive(entry.fleet); String textColor = isLive ? IS_LIVE_TEXT_COLOR : DEFAULT_TEXT_COLOR; - String totalPointsAsText = entry.totalPoints == null ? "" : scoreFormat.format(entry.totalPoints); - String netPointsAsText = entry.netPoints == null ? "" : scoreFormat.format(entry.netPoints); - + String totalOrAddedPointsAsText = isShowAddedScores() ? scoreFormat.format(computeAddedScores(object)) + : entry.totalPoints == null ? "" : scoreFormat.format(entry.totalPoints); + String netOrAddedPointsAsText = isShowAddedScores() ? scoreFormat.format(computeAddedScores(object)) + : entry.netPoints == null ? "" : scoreFormat.format(entry.netPoints); + if (entry.fleet != null && entry.fleet.getColor() != null) { - html.append(raceColumnTemplate.cellFrameWithTextColorAndFleetBorder(textColor, entry.fleet.getColor().getAsHtml())); + html.append(raceColumnTemplate.cellFrameWithTextColorAndFleetBorder(textColor, entry.fleet.getColor().getAsHtml())); } else { - html.append(raceColumnTemplate.cellFrameWithTextColor(textColor)); + html.append(raceColumnTemplate.cellFrameWithTextColor(textColor)); } - + // don't show points if max points / penalty if (entry.reasonForMaxPoints == null || entry.reasonForMaxPoints == MaxPointsReason.NONE) { if (!entry.discarded) { html.appendHtmlConstant(""); - html.appendHtmlConstant(totalPointsAsText); + html.appendHtmlConstant(totalOrAddedPointsAsText); html.appendHtmlConstant(""); } else { html.appendHtmlConstant(" "); - html.appendHtmlConstant(netPointsAsText); + html.appendHtmlConstant(netOrAddedPointsAsText); html.appendHtmlConstant(""); } } else { - html.appendHtmlConstant(" "); if (entry.discarded) { html.appendHtmlConstant(""); @@ -681,12 +708,19 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS return new InvertibleComparatorAdapter() { @Override public int compare(LeaderboardRowDTO o1, LeaderboardRowDTO o2) { - List competitorsFromBestToWorst = getLeaderboard().getCompetitorsFromBestToWorst( - race); - int o1Rank = competitorsFromBestToWorst.indexOf(o1.competitor) + 1; - int o2Rank = competitorsFromBestToWorst.indexOf(o2.competitor) + 1; - return o1Rank == 0 ? o2Rank == 0 ? 0 : isAscending() ? 1 : -1 : o2Rank == 0 ? isAscending() ? -1 - : 1 : o1Rank - o2Rank; + if (isShowAddedScores()) { + double o1AddedScore = computeAddedScores(o1); + double o2AddedScore = computeAddedScores(o2); + double result = o1AddedScore == 0. ? o2AddedScore == 0. ? 0. : isAscending() ? 1. : -1. : o2AddedScore == 0. ? isAscending() ? -1. : 1. : o1AddedScore - o2AddedScore; + return result > 0 ? 1 : result < 0 ? -1 : 0; + } else { + List competitorsFromBestToWorst = getLeaderboard().getCompetitorsFromBestToWorst( + race); + int o1Rank = competitorsFromBestToWorst.indexOf(o1.competitor) + 1; + int o2Rank = competitorsFromBestToWorst.indexOf(o2.competitor) + 1; + return o1Rank == 0 ? o2Rank == 0 ? 0 : isAscending() ? 1 : -1 : o2Rank == 0 ? isAscending() ? -1 + : 1 : o1Rank - o2Rank; + } } }; } @@ -717,8 +751,7 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS DetailType.SPEED_OVER_GROUND_WHEN_PASSING_START, DetailType.DISTANCE_TO_STARBOARD_END_OF_STARTLINE_WHEN_PASSING_START_IN_METERS, DetailType.START_TACK, - DetailType.RACE_TIME_SINCE_LAST_POSITION_FIX_IN_SECONDS, - DetailType.RACE_TRACKING_QUALITY }; + DetailType.RACE_RATIO_BETWEEN_TIME_SINCE_LAST_POSITION_FIX_AND_AVERAGE_SAMPLING_INTERVAL }; } public static DetailType[] getAvailableOverallDetailColumnTypes() { @@ -779,11 +812,9 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS LeaderboardPanel leaderboardPanel, StringMessages stringMessages, String detailHeaderStyle, String detailColumnStyle) { Map> result = new HashMap>(); - result.put(DetailType.RACE_TIME_SINCE_LAST_POSITION_FIX_IN_SECONDS, - new FormattedDoubleDetailTypeColumn(DetailType.RACE_TIME_SINCE_LAST_POSITION_FIX_IN_SECONDS, - new RaceTimeSinceLastPositionFixInSeconds(), LEG_COLUMN_HEADER_STYLE, LEG_COLUMN_STYLE)); - result.put(DetailType.RACE_TRACKING_QUALITY, new TrackingQualityColumn(stringMessages.trackingQuality(), new RaceTrackingQuality(), LEG_COLUMN_HEADER_STYLE, LEG_COLUMN_STYLE)); - + result.put(DetailType.RACE_RATIO_BETWEEN_TIME_SINCE_LAST_POSITION_FIX_AND_AVERAGE_SAMPLING_INTERVAL, + new TimeSinceLastGpsFixColumn(DetailType.RACE_RATIO_BETWEEN_TIME_SINCE_LAST_POSITION_FIX_AND_AVERAGE_SAMPLING_INTERVAL, + new RaceRatioBetweenTimeSinceLastPositionFixAndAverageSamplingInterval(), LEG_COLUMN_HEADER_STYLE, LEG_COLUMN_STYLE)); result.put(DetailType.RACE_DISTANCE_TRAVELED, new FormattedDoubleDetailTypeColumn(DetailType.RACE_DISTANCE_TRAVELED, new RaceDistanceTraveledInMeters(), LEG_COLUMN_HEADER_STYLE, LEG_COLUMN_STYLE)); @@ -893,7 +924,7 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS * @author Axel Uhl (D043530) * */ - private class RaceTrackingQuality implements LegDetailField { + private class RaceRatioBetweenTimeSinceLastPositionFixAndAverageSamplingInterval implements LegDetailField { @Override public Double get(LeaderboardRowDTO row) { Double result = null; @@ -905,18 +936,6 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS } } - private class RaceTimeSinceLastPositionFixInSeconds implements LegDetailField { - @Override - public Double get(LeaderboardRowDTO row) { - Double result = null; - LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceColumnName.get(getRaceColumnName()); - if (fieldsForRace != null) { - result = fieldsForRace.timeSinceLastPositionFixInSeconds; - } - return result; - } - } - /** * Accumulates the average speed over all legs of a race * @@ -1438,6 +1457,7 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS } else { leaderboardTable.setSelectionModel(leaderboardSelectionModel); } + setShowAddedScores(settings.isShowAddedScores()); loadCompleteLeaderboard(getLeaderboardDisplayDate()); if (this.preSelectedRace == null) { @@ -1636,6 +1656,14 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS } } + private boolean isShowAddedScores() { + return showAddedScores; + } + + private void setShowAddedScores(boolean showAddedScores) { + this.showAddedScores = showAddedScores; + } + /** * The time point for which the leaderboard currently shows results. In {@link PlayModes#Replay replay mode} this is * the {@link #timer}'s time point. In {@link PlayModes#Live live mode} the {@link #timer}'s time is quantizes to @@ -1721,13 +1749,15 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS GetLeaderboardByNameAction getLeaderboardByNameAction = new GetLeaderboardByNameAction(sailingService, getLeaderboardName(), timer.getPlayMode() == PlayModes.Live ? null : date, /* namesOfRacesForWhichToLoadLegDetails */getNamesOfExpandedRaces(), - /* previousLeaderboard */ getLeaderboard(), timer, errorReporter, stringMessages, new AsyncCallback() { + /* previousLeaderboard */ getLeaderboard(), timer, errorReporter, stringMessages); + asyncActionsExecutor.execute(getLeaderboardByNameAction, LOAD_LEADERBOARD_DATA_CATEGORY, + new AsyncCallback() { @Override public void onSuccess(LeaderboardDTO result) { updateLeaderboard(result); getBusyIndicator().setBusy(false); } - + @Override public void onFailure(Throwable caught) { getBusyIndicator().setBusy(false); @@ -1736,7 +1766,6 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS true /* silentMode */); } }); - asyncActionsExecutor.execute(getLeaderboardByNameAction); } else { getBusyIndicator().setBusy(false); } @@ -2420,7 +2449,7 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS Collections.unmodifiableList(selectedLegDetails), Collections.unmodifiableList(selectedRaceDetails), Collections.unmodifiableList(selectedOverallDetailColumns), /* All races to select */ leaderboard.getRaceList(), raceColumnSelection.getSelectedRaceColumnsOrderedAsInLeaderboard(leaderboard), raceColumnSelection, autoExpandPreSelectedRace, - timer.getRefreshInterval(), stringMessages); + isShowAddedScores(), timer.getRefreshInterval(), stringMessages); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardSettings.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardSettings.java index 78d26495d5e..9dd7bbfd082 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardSettings.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardSettings.java @@ -44,6 +44,11 @@ public class LeaderboardSettings { private final String nameOfRaceToSort; private final boolean sortAscending; + /** + * Shows scores sum'd up for each race column + */ + private final boolean showAddedScores; + /** * @param raceColumnsToShow null means don't modify the list of races shown */ @@ -51,7 +56,8 @@ public class LeaderboardSettings { List raceDetailsToShow, List overallDetailsToShow, List namesOfRaceColumnsToShow, List namesOfRacesToShow, Integer numberOfLastRacesToShow, boolean autoExpandPreSelectedRace, Long delayBetweenAutoAdvancesInMilliseconds, String nameOfRaceToSort, - boolean sortAscending, boolean updateUponPlayStateChange, RaceColumnSelectionStrategies activeRaceColumnSelectionStrategy) { + boolean sortAscending, boolean updateUponPlayStateChange, RaceColumnSelectionStrategies activeRaceColumnSelectionStrategy, + boolean showAddedScores) { if (namesOfRacesToShow != null && namesOfRaceColumnsToShow != null) { throw new IllegalArgumentException("You can identify races either only by their race or by their column names, not both"); } @@ -68,6 +74,7 @@ public class LeaderboardSettings { this.nameOfRaceToSort = nameOfRaceToSort; this.sortAscending = sortAscending; this.updateUponPlayStateChange = updateUponPlayStateChange; + this.showAddedScores = showAddedScores; } public List getManeuverDetailsToShow() { @@ -141,4 +148,8 @@ public class LeaderboardSettings { public RaceColumnSelectionStrategies getActiveRaceColumnSelectionStrategy() { return activeRaceColumnSelectionStrategy; } + + public boolean isShowAddedScores() { + return showAddedScores; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardSettingsDialogComponent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardSettingsDialogComponent.java index 3d942072f19..b7d11893697 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardSettingsDialogComponent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardSettingsDialogComponent.java @@ -27,8 +27,8 @@ import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.SettingsDialogComponent; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings.RaceColumnSelectionStrategies; import com.sap.sse.gwt.ui.DataEntryDialog; -import com.sap.sse.gwt.ui.IntegerBox; import com.sap.sse.gwt.ui.DataEntryDialog.Validator; +import com.sap.sse.gwt.ui.IntegerBox; public class LeaderboardSettingsDialogComponent implements SettingsDialogComponent { private final Iterable raceColumnSelection; @@ -45,18 +45,20 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone private final StringMessages stringMessages; private LongBox refreshIntervalInSecondsBox; private final boolean autoExpandPreSelectedRace; + private final boolean showAddedScores; private final long delayBetweenAutoAdvancesInMilliseconds; private final Integer numberOfLastRacesToShow; private RaceColumnSelectionStrategies activeRaceColumnSelectionStrategy; private RadioButton explicitRaceColumnSelectionRadioBtn; private RadioButton lastNRacesColumnSelectionRadioBtn; private IntegerBox numberOfLastRacesToShowBox; + private CheckBox showAddedScoresCheckBox; protected LeaderboardSettingsDialogComponent(List maneuverDetailSelection, List legDetailSelection, List raceDetailSelection, List overallDetailSelection, List raceAllRaceColumns, Iterable raceColumnSelection, RaceColumnSelection raceColumnSelectionStrategy, - boolean autoExpandPreSelectedRace, + boolean autoExpandPreSelectedRace, boolean showAddedScores, long delayBetweenAutoAdvancesInMilliseconds, StringMessages stringMessages) { this.raceAllRaceColumns = raceAllRaceColumns; this.numberOfLastRacesToShow = raceColumnSelectionStrategy.getNumberOfLastRaceColumnsToShow(); @@ -74,6 +76,7 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone this.stringMessages = stringMessages; this.autoExpandPreSelectedRace = autoExpandPreSelectedRace; this.delayBetweenAutoAdvancesInMilliseconds = delayBetweenAutoAdvancesInMilliseconds; + this.showAddedScores = showAddedScores; } @Override @@ -97,6 +100,7 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone List currentMeneuverDetailSelection = maneuverDetailSelection; for (DetailType detailType : ManeuverCountRaceColumn.getAvailableManeuverDetailColumnTypes()) { CheckBox checkbox = dialog.createCheckbox(DetailTypeFormatter.format(detailType)); + dialog.addTooltip(checkbox, DetailTypeFormatter.getTooltip(detailType)); checkbox.setValue(currentMeneuverDetailSelection.contains(detailType)); maneuverDetailCheckboxes.put(detailType, checkbox); meneuverContent.add(checkbox); @@ -141,10 +145,19 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone } CheckBox checkbox = dialog.createCheckbox(DetailTypeFormatter.format(type)); checkbox.setValue(currentRaceDetailSelection.contains(type)); + dialog.addTooltip(checkbox, DetailTypeFormatter.getTooltip(type)); raceDetailCheckboxes.put(type, checkbox); raceDetailDialogContent.add(checkbox); detailCountInCurrentFlowPanel++; } + // Make it possible to configure added points + FlowPanel addedScoresFlowPanel = new FlowPanel(); + addedScoresFlowPanel.addStyleName("dialogInnerContent"); + showAddedScoresCheckBox = dialog.createCheckbox(stringMessages.showAddedScores()); + dialog.addTooltip(showAddedScoresCheckBox, stringMessages.showAddedScores()); + showAddedScoresCheckBox.setValue(showAddedScores); + addedScoresFlowPanel.add(showAddedScoresCheckBox); + raceDetailDialog.add(addedScoresFlowPanel); return raceDetailDialog; } @@ -157,6 +170,7 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone List currentOverallDetailSelection = overallDetailSelection; for (DetailType type : LeaderboardPanel.getAvailableOverallDetailColumnTypes()) { CheckBox checkbox = dialog.createCheckbox(DetailTypeFormatter.format(type)); + dialog.addTooltip(checkbox, DetailTypeFormatter.getTooltip(type)); checkbox.setValue(currentOverallDetailSelection.contains(type)); overallDetailCheckboxes.put(type, checkbox); overallDetailDialogContent.add(checkbox); @@ -179,6 +193,7 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone legDetailsToShow.add(legDetailsContent); } CheckBox checkbox = dialog.createCheckbox(DetailTypeFormatter.format(type)); + dialog.addTooltip(checkbox, DetailTypeFormatter.getTooltip(type)); checkbox.setValue(currentLegDetailSelection.contains(type)); legDetailCheckboxes.put(type, checkbox); legDetailsContent.add(checkbox); @@ -317,7 +332,8 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone lastNRacesToShowValue, autoExpandPreSelectedRace, 1000l * (delayBetweenAutoAdvancesValue == null ? 0l : delayBetweenAutoAdvancesValue.longValue()), null, - true, /* updateUponPlayStateChange */ true, activeRaceColumnSelectionStrategy); + true, /* updateUponPlayStateChange */ true, activeRaceColumnSelectionStrategy, + /*showAddedScores*/ showAddedScoresCheckBox.getValue().booleanValue()); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardSettingsFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardSettingsFactory.java index 50eceb1c570..79622cb6b7b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardSettingsFactory.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardSettingsFactory.java @@ -69,7 +69,8 @@ public class LeaderboardSettingsFactory { namesOfRacesToShow, raceColumnSelection.getNumberOfLastRaceColumnsToShow(), /* set autoExpandPreSelectedRace to true if we look at a single race */ nameOfRaceColumnToShow != null || nameOfRaceToShow != null, /* refresh interval */ null, /* name of race to sort */ nameOfRaceToSort, - /* ascending */ true, /* updateUponPlayStateChange */ true, raceColumnSelection.getType()); + /* ascending */ true, /* updateUponPlayStateChange */ true, raceColumnSelection.getType(), + /*showAddedScores*/ false); break; case Replay: settings = createNewDefaultSettings(namesOfRaceColumnsToShow, namesOfRacesToShow, nameOfRaceToSort, /* autoExpandFirstRace */ @@ -131,7 +132,8 @@ public class LeaderboardSettingsFactory { namesOfRaceColumnsToShow, namesOfRacesToShow, numberOfLastRacesToShow, autoExpandPreSelectedRace, refreshIntervalMillis, /* sort by column */ nameOfRaceToSort, - /* ascending */ true, /* updateUponPlayStateChange */ true, raceColumnSelectionStrategy); + /* ascending */ true, /* updateUponPlayStateChange */ true, raceColumnSelectionStrategy, + /*showAddedScores*/ false); } public LeaderboardSettings mergeLeaderboardSettings(LeaderboardSettings settingsWithRaceSelection, LeaderboardSettings settingsWithDetails) { @@ -152,7 +154,7 @@ public class LeaderboardSettingsFactory { return new LeaderboardSettings(maneuverDetails, legDetails, raceDetails, overallDetailsToShow, namesOfRaceColumnsToShow, namesOfRacesToShow, numberOfLastRacesToShow, autoExpandPreSelectedRace, refreshIntervalInMs, - nameOfRaceToSort, sortAscending, updateUponPlayStateChange, strategy); + nameOfRaceToSort, sortAscending, updateUponPlayStateChange, strategy, /*showAddedScores*/ false); } private List copyDetailTypes(List detailTypes) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardUrlConfigurationDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardUrlConfigurationDialog.java index dde2fcca34d..ecc8d1ad85d 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardUrlConfigurationDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardUrlConfigurationDialog.java @@ -108,7 +108,7 @@ public class LeaderboardUrlConfigurationDialog extends SettingsDialog comparator; + private final HasStringAndDoubleValue valueProvider; + private final Comparator comparator; private Double minimumValue; private Double maximumValue; @@ -56,7 +56,7 @@ public class MinMaxRenderer { * @param row * The row to get the percentage for. */ - private int getPercentage(LeaderboardRowDTO row) { + protected int getPercentage(LeaderboardRowDTO row) { int percentage = 0; Double value = valueProvider.getDoubleValue(row); if (value != null) { @@ -105,4 +105,9 @@ public class MinMaxRenderer { maximumValue = valueProvider.getDoubleValue(maximumRow); } } + + protected HasStringAndDoubleValue getValueProvider() { + return valueProvider; + } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/TimeSinceLastGpsFixColumn.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/TimeSinceLastGpsFixColumn.java new file mode 100755 index 00000000000..36b94682620 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/TimeSinceLastGpsFixColumn.java @@ -0,0 +1,18 @@ +package com.sap.sailing.gwt.ui.leaderboard; + +import com.sap.sailing.domain.common.DetailType; + +public class TimeSinceLastGpsFixColumn extends FormattedDoubleDetailTypeColumn { + + public TimeSinceLastGpsFixColumn(DetailType detailType, + com.sap.sailing.gwt.ui.leaderboard.DetailTypeColumn.LegDetailField field, String headerStyle, + String columnStyle) { + super(detailType, field, headerStyle, columnStyle); + } + + @Override + protected MinMaxRenderer createMinMaxRenderer() { + return new TrackingQualityMinMaxRenderer(this, getComparator()); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/TrackingQualityColumn.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/TrackingQualityColumn.java deleted file mode 100644 index e78421c094d..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/TrackingQualityColumn.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.sap.sailing.gwt.ui.leaderboard; - -import com.google.gwt.cell.client.AbstractSafeHtmlCell; -import com.google.gwt.safehtml.shared.SafeHtml; -import com.google.gwt.safehtml.shared.SafeHtmlBuilder; -import com.google.gwt.safehtml.shared.SafeHtmlUtils; -import com.google.gwt.text.shared.SafeHtmlRenderer; -import com.sap.sailing.domain.common.DetailType; -import com.sap.sailing.domain.common.dto.LeaderboardRowDTO; - -public class TrackingQualityColumn extends DetailTypeColumn { - public TrackingQualityColumn(String title, LegDetailField field, String headerStyle, String columnStyle) { - super(DetailType.RACE_TRACKING_QUALITY, field, new TrackingQualityCell(), headerStyle, columnStyle); - } - - @Override - public Double getValue(LeaderboardRowDTO row) { - return getField().get(row); - } - - private static class TrackingQualityCell extends AbstractSafeHtmlCell { - private static final String STYLE_TRACKING_QUALITY_CIRCLE = "trackingQuality-circle"; - private static final String STYLE_TRACKING_QUALITY_CIRCLE_RED = "circleRed"; - private static final String STYLE_TRACKING_QUALITY_CIRCLE_YELLOW = "circleYellow"; - private static final String STYLE_TRACKING_QUALITY_CIRCLE_GREEN = "circleGreen"; - - public TrackingQualityCell() { - super(new SafeHtmlRenderer() { - @Override - public SafeHtml render(Double rank) { - SafeHtmlBuilder builder = new SafeHtmlBuilder(); - render(rank, builder); - return builder.toSafeHtml(); - } - - @Override - public void render(Double ratioOfLagAndAverageSamplingInterval, SafeHtmlBuilder builder) { - if (ratioOfLagAndAverageSamplingInterval != null) { - builder.append(SafeHtmlUtils.fromTrustedString("
")); - } else { - builder.append(SafeHtmlUtils.fromTrustedString(STYLE_TRACKING_QUALITY_CIRCLE_GREEN)); - } - } - }); - } - - @Override - protected void render(com.google.gwt.cell.client.Cell.Context context, SafeHtml data, SafeHtmlBuilder sb) { - if (data != null) { - sb.append(data); - } - } - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/TrackingQualityMinMaxRenderer.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/TrackingQualityMinMaxRenderer.java new file mode 100755 index 00000000000..efb28111680 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/TrackingQualityMinMaxRenderer.java @@ -0,0 +1,40 @@ +package com.sap.sailing.gwt.ui.leaderboard; + +import java.util.Comparator; + +import com.google.gwt.cell.client.Cell.Context; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; +import com.sap.sailing.domain.common.dto.LeaderboardRowDTO; + +public class TrackingQualityMinMaxRenderer extends MinMaxRenderer { + + public TrackingQualityMinMaxRenderer(HasStringAndDoubleValue valueProvider, Comparator comparator) { + super(valueProvider, comparator); + } + + /** + * Renders the value of a {@link LeaderboardRowDTO}. Values up to 1.5 are considered good, meaning that there is no more than + * 50% overshoot compared to the average sampling interval; values worse than 300% of the average sampling interval are considered + * bad; anything in between is "OK." + * + * @param title + * tool tip title to display; if null, no tool tip will be rendered + */ + public void render(Context context, LeaderboardRowDTO row, String title, SafeHtmlBuilder sb) { + Double ratio = getValueProvider().getDoubleValue(row); + String stringValue = getValueProvider().getStringValueToRender(row); + stringValue = stringValue == null ? "" : stringValue; + final String barStyle; + if (ratio <= 1.5) { + barStyle = "minMaxBackgroundBarGood"; + } else if (ratio <= 3) { + barStyle = "minMaxBackgroundBar"; + } else { + barStyle = "minMaxBackgroundBarBad"; + } + sb.appendHtmlConstant("
").appendEscaped(stringValue).appendHtmlConstant("
"); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/LeaderboardEditPage.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/LeaderboardEditPage.java index eb4aa83cd17..244c4bfcc3a 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/LeaderboardEditPage.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/LeaderboardEditPage.java @@ -3,6 +3,7 @@ package com.sap.sailing.gwt.ui.leaderboardedit; import java.util.List; import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import com.sap.sailing.gwt.ui.actions.AsyncActionsExecutor; @@ -14,28 +15,28 @@ public class LeaderboardEditPage extends AbstractEntryPoint { @Override protected void doOnModuleLoad() { super.doOnModuleLoad(); - sailingService.getLeaderboardNames(new MarkedAsyncCallback>() { - @Override - public void handleSuccess(List leaderboardNames) { - String leaderboardName = Window.Location.getParameter("name"); - if (leaderboardNames.contains(leaderboardName)) { - LogoAndTitlePanel logoAndTitlePanel = new LogoAndTitlePanel(stringMessages.editScores(), stringMessages, LeaderboardEditPage.this); - logoAndTitlePanel.addStyleName("LogoAndTitlePanel"); - // TODO: Here happens something async. We have to use the semaphore for ui tests. - EditableLeaderboardPanel leaderboardPanel = new EditableLeaderboardPanel(sailingService, new AsyncActionsExecutor(), leaderboardName, null, - LeaderboardEditPage.this, stringMessages, userAgent); - leaderboardPanel.ensureDebugId("EditableLeaderboardPanel"); - RootPanel.get().add(logoAndTitlePanel); - RootPanel.get().add(leaderboardPanel); - } else { - RootPanel.get().add(new Label(stringMessages.noSuchLeaderboard())); - } - } - @Override - public void handleFailure(Throwable t) { - reportError("Error trying to obtain list of leaderboard names: "+t.getMessage()); - } - }); + sailingService.getLeaderboardNames(new MarkedAsyncCallback>( + new AsyncCallback>() { + @Override + public void onSuccess(List leaderboardNames) { + String leaderboardName = Window.Location.getParameter("name"); + if (leaderboardNames.contains(leaderboardName)) { + LogoAndTitlePanel logoAndTitlePanel = new LogoAndTitlePanel(stringMessages.editScores(), stringMessages, LeaderboardEditPage.this); + logoAndTitlePanel.addStyleName("LogoAndTitlePanel"); + EditableLeaderboardPanel leaderboardPanel = new EditableLeaderboardPanel(sailingService, new AsyncActionsExecutor(), leaderboardName, null, + LeaderboardEditPage.this, stringMessages, userAgent); + leaderboardPanel.ensureDebugId("EditableLeaderboardPanel"); + RootPanel.get().add(logoAndTitlePanel); + RootPanel.get().add(leaderboardPanel); + } else { + RootPanel.get().add(new Label(stringMessages.noSuchLeaderboard())); + } + } + @Override + public void onFailure(Throwable t) { + reportError("Error trying to obtain list of leaderboard names: "+t.getMessage()); + } + })); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewPanel.java index abf840e50a9..0d1df12ee10 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewPanel.java @@ -230,26 +230,27 @@ public class RegattaOverviewPanel extends SimplePanel { if (showLeaderboard) { final CompetitorSelectionModel competitorSelectionProvider = new CompetitorSelectionModel(/* hasMultiSelection */ true); final LeaderboardSettings leaderboardSettings = LeaderboardSettingsFactory.getInstance().createNewDefaultSettings(null, null, null, /* autoExpandFirstRace */ false); - sailingService.getLeaderboardsByEvent(eventDTO, new AsyncCallback>() { - @Override - public void onSuccess(List result) { - leaderboardsTabPanel.clear(); - for (StrippedLeaderboardDTO leaderboard : result) { - LeaderboardPanel leaderboardPanel = new LeaderboardPanel(sailingService, - new AsyncActionsExecutor(), leaderboardSettings, - /*preSelectedRace*/null, - competitorSelectionProvider, - null, leaderboard.name, - errorReporter, stringMessages, userAgent, /*showRaceDetails*/false); - leaderboardsTabPanel.add(leaderboardPanel, leaderboard.getDisplayName() + " " + stringMessages.leaderboard()); - } - leaderboardsTabPanel.setVisible(true); - leaderboardsTabPanel.selectTab(0); - } - @Override - public void onFailure(Throwable caught) { - } - }); + sailingService.getLeaderboardsByEvent(eventDTO, new MarkedAsyncCallback>( + new AsyncCallback>() { + @Override + public void onSuccess(List result) { + leaderboardsTabPanel.clear(); + for (StrippedLeaderboardDTO leaderboard : result) { + LeaderboardPanel leaderboardPanel = new LeaderboardPanel(sailingService, + new AsyncActionsExecutor(), leaderboardSettings, + /*preSelectedRace*/null, + competitorSelectionProvider, + null, leaderboard.name, + errorReporter, stringMessages, userAgent, /*showRaceDetails*/false); + leaderboardsTabPanel.add(leaderboardPanel, leaderboard.getDisplayName() + " " + stringMessages.leaderboard()); + } + leaderboardsTabPanel.setVisible(true); + leaderboardsTabPanel.selectTab(0); + } + @Override + public void onFailure(Throwable caught) { + } + })); } else { leaderboardsTabPanel.clear(); leaderboardsTabPanel.setVisible(false); @@ -275,23 +276,23 @@ public class RegattaOverviewPanel extends SimplePanel { } private void retrieveEvent() { - sailingService.getEventById(eventId, new MarkedAsyncCallback() { - - @Override - protected void handleFailure(Throwable cause) { - settingsButton.setEnabled(false); - errorReporter.reportError("Error trying to load event with id " + eventId + " : " - + cause.getMessage()); - } - - @Override - protected void handleSuccess(EventDTO result) { - if (result != null) { - setEvent(result); - loadLeaderboard(); - } - } - }); + sailingService.getEventById(eventId, new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable cause) { + settingsButton.setEnabled(false); + errorReporter.reportError("Error trying to load event with id " + eventId + " : " + + cause.getMessage()); + } + + @Override + public void onSuccess(EventDTO result) { + if (result != null) { + setEvent(result); + loadLeaderboard(); + } + } + })); } private void fillEventAndVenueName() { @@ -313,22 +314,22 @@ public class RegattaOverviewPanel extends SimplePanel { } private void retrieveRegattaStructure() { - sailingService.getRegattaStructureForEvent(eventId, new MarkedAsyncCallback>() { - - @Override - protected void handleFailure(Throwable cause) { - errorReporter.reportError("Error trying to load regattas for event with id " + eventId + " : " - + cause.getMessage()); - } - - @Override - protected void handleSuccess(List result) { - if (result != null) { - setRaceGroups(result); - } - } - - }); + sailingService.getRegattaStructureForEvent(eventId, new MarkedAsyncCallback>( + new AsyncCallback>() { + @Override + public void onFailure(Throwable cause) { + errorReporter.reportError("Error trying to load regattas for event with id " + eventId + " : " + + cause.getMessage()); + } + + @Override + public void onSuccess(List result) { + if (result != null) { + setRaceGroups(result); + } + } + + })); } protected void setRaceGroups(List result) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesComponent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesComponent.java index 619c3901149..7a9fe984589 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesComponent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesComponent.java @@ -28,6 +28,7 @@ import com.google.gwt.user.cellview.client.Column; import com.google.gwt.user.cellview.client.ColumnSortEvent; import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; import com.google.gwt.user.cellview.client.TextColumn; +import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.DialogBox; @@ -184,27 +185,27 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component } final long clientTimeWhenRequestWasSent = System.currentTimeMillis(); sailingService.getRaceStateEntriesForRaceGroup(eventId, settings.getVisibleCourseAreas(), settings.getVisibleRegattas(), - settings.isShowOnlyCurrentlyRunningRaces(), settings.isShowOnlyRacesOfSameDay(), new MarkedAsyncCallback>() { - - @Override - protected void handleFailure(Throwable cause) { - - } - - @Override - protected void handleSuccess(List result) { - final long clientTimeWhenResponseWasReceived = System.currentTimeMillis(); - Date serverTimeDuringRequest = null; - for (RegattaOverviewEntryDTO entryDTO : result) { - if (entryDTO.currentServerTime != null) { - serverTimeDuringRequest = entryDTO.currentServerTime; - } - } - updateTable(result); - timerToSynchronize.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived); - } - - }); + settings.isShowOnlyCurrentlyRunningRaces(), settings.isShowOnlyRacesOfSameDay(), + new MarkedAsyncCallback>( + new AsyncCallback>() { + @Override + public void onFailure(Throwable cause) { + + } + + @Override + public void onSuccess(List result) { + final long clientTimeWhenResponseWasReceived = System.currentTimeMillis(); + Date serverTimeDuringRequest = null; + for (RegattaOverviewEntryDTO entryDTO : result) { + if (entryDTO.currentServerTime != null) { + serverTimeDuringRequest = entryDTO.currentServerTime; + } + } + updateTable(result); + timerToSynchronize.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived); + } + })); } private CellTable createRegattaTable() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/ajax-semaphore.js b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/ajax-semaphore.js index 5acf0f46811..824d7373d6f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/ajax-semaphore.js +++ b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/ajax-semaphore.js @@ -8,18 +8,32 @@ * completes. With this counter a test which triggers a request (which can cause additional request) can wait until * the counter reaches 0 again.

* - * TODO: Write some additional documentation for categories! - * * @author * D049941 */ -// TODO: Support categories of requests! var PENDING_AJAX_CALLS = PENDING_AJAX_CALLS || function() { - /* Private variable bound through closure which is initialized the counter to be 1. This is important because the - * GWT bootstrap process in itself can take a bit of time. So, at a minimum we have to wait until the module is - * fully loaded. Otherwise, we will get the occasional timing/synchronization failure during test runs. - */ - var pendingCalls = 1; + /* Private variable bound through closure which holds the categories of AJAX requests. The counter for the global + * category (empty string) is initialized to be 1. This is important because the GWT bootstrap process in itself can + * take a bit of time. So, at a minimum we have to wait until the module is fully loaded. Otherwise, we will get the + * occasional timing/synchronization failure during test runs. + */ + var categories = { + "" : { + pendingCalls : 1, + finishedCalls : 0 + } + }; + + function getCategory(category) { + if(!(category in categories)) { + categories[category] = { + pendingCalls : 0, + finishedCalls : 0 + } + } + + return categories[category]; + }; return { /** @@ -31,7 +45,19 @@ var PENDING_AJAX_CALLS = PENDING_AJAX_CALLS || function() { * The number of pending Ajax requests. */ numberOfPendingCalls : function(category) { - return pendingCalls; + return getCategory(category).pendingCalls; + }, + + /** + *

+ * + * @param {string} category + * The category of finished Ajax requests. + * @returns {int} + * The number of finished Ajax requests. + */ + numberOfFinishedCalls : function(category) { + return getCategory(category).finishedCalls; }, /** @@ -41,7 +67,8 @@ var PENDING_AJAX_CALLS = PENDING_AJAX_CALLS || function() { * The category of the Ajax request. */ decrementPendingCalls : function(category) { - pendingCalls--; + getCategory(category).pendingCalls--; + getCategory(category).finishedCalls++; }, /** @@ -52,7 +79,7 @@ var PENDING_AJAX_CALLS = PENDING_AJAX_CALLS || function() { * The category of the Ajax request. */ incrementPendingCalls : function(category) { - pendingCalls++; + getCategory(category).pendingCalls++; } } -}(); \ No newline at end of file +}(); diff --git a/java/com.sap.sailing.selenium.test/local-test-environment.xml b/java/com.sap.sailing.selenium.test/local-test-environment.xml index 25f275bb799..8261c0668e9 100755 --- a/java/com.sap.sailing.selenium.test/local-test-environment.xml +++ b/java/com.sap.sailing.selenium.test/local-test-environment.xml @@ -40,7 +40,7 @@ webdriver.firefox.bin - c:/Program Files (x86)/Mozilla Firefox/firefox.exe + /usr/bin/firefox @@ -54,12 +54,6 @@ pages mentioned above. --> - - - nativeEvents - false - - "Execute Shell" and paste as command something like this: `ANDROID_HOME=/usr/local/android-sdk-linux configuration/buildAndUpdateProduct.sh build`. Adjust the location of the Android SDK accordingly and install it if not already present. +* as Post-build Action, select "Publish JUnit test result report" and as Test report XMLs provide `**/TEST-*.xml` as the file pattern for the test reports. +* check the "Additional test reports features / Measurement Plots" box +* provide e-mail notification settings as you see fit \ No newline at end of file diff --git a/wiki/planning/finding-a-design-agency.md b/wiki/planning/finding-a-design-agency.md index 31025547ff8..b12c2f91144 100644 --- a/wiki/planning/finding-a-design-agency.md +++ b/wiki/planning/finding-a-design-agency.md @@ -29,82 +29,6 @@ Fragen, die eher allgemeine Rahmenbedingungen betreffen: 5. Sailing team starts integration with the server. 6. Agency provides long-term support for changes. Lifecycle is communicated with agency. -## Decision Matrix - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ObjectiveCreative WorklineUbilabsGMRDigitalsunrayMedienfabrik
Mobile HTML Knowledge, References and Developers?
Android Knowledge, References and Developers?
iOS skills, References and Developers?
Professional Meeting in terms of preparation and participants?
GWT Knowledge?
Technical Knowledge (GIT, SVN, ...)?
Knowledge of Sailing Domain?
Team size of developers and designers (10+)?
# Meeting Notes (20.01.2014) @@ -243,31 +167,207 @@ Telefon: 040 / 22 81 72 62 0 -# Priority list +# Final Decision + +## Decision Matrix - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - -
SimonAxelFrankJens
Ubilabs
ObjectiveSovanta (Heidelberg)Ubilabs (Hamburg)Digital Sunray (Wien)Creative Workline (Berlin)GMR (London)Pier2Port (Hamburg)
Office Location+++ (STG)000+
Mobile HTML Knowledge, References and Developers?+++++++ ?+
Android Knowledge, References and Developers?+ (more iOS)+++++? (no news)0
iOS skills, References and Developers?++++++ ??
Creative Workline???
Sysvision???
\ No newline at end of file + 0 + + + Professional Meeting at the office in terms of preparation and participants? + ++ + ++ + + + - + 0 + 0 + + + GWT Knowledge? + 0 + 0 + 0 + 0 + 0 + 0 + + + Technical Knowledge (GIT, Web-Technologies, Programming Languages)? + + + + + + + + + + + + + + + Knowledge of Sailing Domain? + 0 + 0 + 0 + 0 + ++ + + + + + Transformation of domain knowledge to design ideas (general)* + + + ++ + - + + + 0 + + + + + Team size of developers and designers (10+)? + ++ (30) + + (20) + 0 (10) + 0 (10) + ++ (30) + 0 (10) + + + SAP Preferred Supplier? + + + 0 + 0 + 0 + 0 + 0 + + + Cost per day (developer) + - (~1000) + 0 (~800) + 0 (~800) + + (~700) + - (~900) + - (~900) + + + Task (Redesign of Homepage) + + + ++ + - + 0 + 0 + 0 + + + Argumentation of task solution* + 0 + ++ + + + 0 + 0 + 0 + + + Transformation of domain knowledge to design ideas (Homepage task)* + + + ++ + - + 0 + 0 + 0 + + + Sympathy factor (gut feeling) + 0 + ++ + 0 + + + 0 + ++ + + +   + 15 + 20 + 5 + 9 + 3 + 5 + + + +Items marked with * have a heigher weight in theory. This weight is not reflected in the bare numbers. + +## Pros/Cons + + + + + + + + + + + + + + + + + +
ObjectiveSovanta (Heidelberg)Ubilabs (Hamburg)
Pros
  • Project is supported by Claus Heinrich (CEO)
  • Professional processes and environment
  • Near to SAP headquarters
  • Big, scalable team
  • Excellect design and user interaction understanding -> best prototype
  • CEO's are coming from the 'visual communication' world
  • Experience with map based solutions -> Google-Maps partner
  • Project references fit better to our project.
Cons
  • Expensive
  • We did not meet the people who made the prototype
  • People from the enterprise world -> not clear how flexible in dynamic event situations
  • We did not get a handout of the prototype
  • Small team, probably not scalable
  • Hamburg based -> communication overhead
+ +## Resumee + +The two only serious contenders in the process eventually turned out to be Sovanta and Ubilabs. After both agencies had presented themselves professionally and well-prepared at their respective offices, had listened carefully and created serious enthusiasm around the project, we tasked them with a tiny test project to better allow us to differentiate their skills and processes. In short, we asked them to spend a day or two into the re-design of our landing page sapsailing.com. + +Both completed the task in time, and we had both present their results and findings to our team. The Sovanta presentation demonstrated that they spent serious effort in understanding the domain. The scribbles they showed were OK but not overwhelming. The explanations of how they got there and why things were proposed the way they were was not entirely satisfactory to us. There was a very strong focus on a live video feed which is not always present. Some ideas such as the world map of events were nice and showed that Sovanta worked their way into the domain. + +Ubilabs presented a flawless and incredibly great design. With a lot less effort they had reached a clearer structure and were able to explain exactly why they did what and how. They conveyed the "Apple" feeling we had so long been looking for. Simple but not simplistic; beautiful, yet functional, combined with a solid understanding of the domain, given the comparably little effort they were able to put in. Their greatest skills are undoubtedly in the areas that we require the most. + +The working relation and the communication style worked better for all of our team in the Ubilabs case. We consider this an important aspect when it comes to a long-term working relation, and we are convinced that it outweighs the additional cost and effort incurred by the remoteness of their office location. Their significantly lower price, though certainly not the main criteria, helps in making their offer even more attractive. Ubilabs has a strong focus on anything geo-spatial as shown in theire rerefences and is Google Maps Premier Partner, adding lots of specific know-how to the project when it comes to the visualization of spatial data as we have it for the SAP Sailing Analytics. + +Last but not least, we felt that for Ubilabs, being a small, excellent and very ambitious company, the project will mean more to them than it would mean to Sovanta, giving the project more priority and the best of skills the company has to offer. + +All things considered, we think that partnering with Ubilabs will lead to better results at lower cost which is what we want. Although it was a close call, our thoughts are backed by the evaluation matrix above, which gives Ubilabs a five-point edge over Sovanta. \ No newline at end of file