Merge remote-tracking branch 'origin/master' into swisstiming-2.0

This commit is contained in:
fmittag committed 2014-04-22 13:51:25 +02:00
commit 7f692fb852
201 files changed
+122949 -12033

No files matched your search

+3
View File
@@ -37,6 +37,9 @@ http://germanmaster.traclive.dk/events/event_20120615_KielerWoch1/jsonservice.ph
Extreme Sailing Series 2012:
http://germanmaster.traclive.dk/events/event_20120101_ExtremeSai/jsonservice.php
Extreme Sailing Series 2014:
http://secondary.traclive.dk/events/event_20140218_ESSSingapo/jsonservice.php
OBMR 2012:
http://germanmaster.traclive.dk/events/event_20121031_OBMR/jsonservice.php
-1
View File
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry exported="true" kind="lib" path="lib/gwt-dev.jar"/>
<classpathentry exported="true" kind="lib" path="lib/gwt-user.jar"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+3 -365
View File
@@ -5,31 +5,9 @@ Bundle-SymbolicName: com.google.gwt.osgi
Bundle-Version: 2.6.0.qualifier
Bundle-Vendor: GOOGLE
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-ClassPath: lib/gwt-dev.jar,
lib/gwt-user.jar,
Bundle-ClassPath: lib/gwt-user.jar,
.
Export-Package: com.gargoylesoftware.htmlunit,
com.gargoylesoftware.htmlunit.attachment,
com.gargoylesoftware.htmlunit.gae,
com.gargoylesoftware.htmlunit.html,
com.gargoylesoftware.htmlunit.html.applets,
com.gargoylesoftware.htmlunit.html.impl,
com.gargoylesoftware.htmlunit.html.xpath,
com.gargoylesoftware.htmlunit.javascript,
com.gargoylesoftware.htmlunit.javascript.background,
com.gargoylesoftware.htmlunit.javascript.configuration,
com.gargoylesoftware.htmlunit.javascript.host,
com.gargoylesoftware.htmlunit.javascript.host.canvas,
com.gargoylesoftware.htmlunit.javascript.host.css,
com.gargoylesoftware.htmlunit.javascript.host.html,
com.gargoylesoftware.htmlunit.javascript.host.xml,
com.gargoylesoftware.htmlunit.javascript.regexp,
com.gargoylesoftware.htmlunit.protocol.about,
com.gargoylesoftware.htmlunit.protocol.data,
com.gargoylesoftware.htmlunit.protocol.javascript,
com.gargoylesoftware.htmlunit.util,
com.gargoylesoftware.htmlunit.xml,
com.google.gwt.activity.shared,
Export-Package: com.google.gwt.activity.shared,
com.google.gwt.animation.client,
com.google.gwt.animation.client.testing,
com.google.gwt.aria.client,
@@ -43,65 +21,9 @@ Export-Package: com.gargoylesoftware.htmlunit,
com.google.gwt.core.client.impl,
com.google.gwt.core.client.prefetch,
com.google.gwt.core.client.testing,
com.google.gwt.core.ext,
com.google.gwt.core.ext.debug,
com.google.gwt.core.ext.linker,
com.google.gwt.core.ext.linker.impl,
com.google.gwt.core.ext.soyc,
com.google.gwt.core.ext.soyc.impl,
com.google.gwt.core.ext.typeinfo,
com.google.gwt.core.linker,
com.google.gwt.core.server,
com.google.gwt.core.shared,
com.google.gwt.debug.client,
com.google.gwt.dev,
com.google.gwt.dev.asm,
com.google.gwt.dev.asm.commons,
com.google.gwt.dev.asm.signature,
com.google.gwt.dev.asm.tree,
com.google.gwt.dev.asm.util,
com.google.gwt.dev.cfg,
com.google.gwt.dev.generator,
com.google.gwt.dev.generator.ast,
com.google.gwt.dev.javac,
com.google.gwt.dev.javac.asm,
com.google.gwt.dev.javac.testing,
com.google.gwt.dev.javac.testing.impl,
com.google.gwt.dev.javac.typemodel,
com.google.gwt.dev.jdt,
com.google.gwt.dev.jjs,
com.google.gwt.dev.jjs.ast,
com.google.gwt.dev.jjs.ast.js,
com.google.gwt.dev.jjs.impl,
com.google.gwt.dev.jjs.impl.gflow,
com.google.gwt.dev.jjs.impl.gflow.cfg,
com.google.gwt.dev.jjs.impl.gflow.constants,
com.google.gwt.dev.jjs.impl.gflow.copy,
com.google.gwt.dev.jjs.impl.gflow.liveness,
com.google.gwt.dev.jjs.impl.gflow.unreachable,
com.google.gwt.dev.js,
com.google.gwt.dev.js.ast,
com.google.gwt.dev.js.rhino,
com.google.gwt.dev.json,
com.google.gwt.dev.protobuf,
com.google.gwt.dev.resource,
com.google.gwt.dev.resource.impl,
com.google.gwt.dev.shell,
com.google.gwt.dev.shell.ie,
com.google.gwt.dev.shell.jetty,
com.google.gwt.dev.shell.log,
com.google.gwt.dev.shell.remoteui,
com.google.gwt.dev.shell.rewrite,
com.google.gwt.dev.ui,
com.google.gwt.dev.util,
com.google.gwt.dev.util.arg,
com.google.gwt.dev.util.collect,
com.google.gwt.dev.util.editdistance,
com.google.gwt.dev.util.log,
com.google.gwt.dev.util.log.dashboard,
com.google.gwt.dev.util.log.speedtracer,
com.google.gwt.dev.util.msg,
com.google.gwt.dev.util.xml,
com.google.gwt.dom.builder.client,
com.google.gwt.dom.builder.shared,
com.google.gwt.dom.client,
@@ -146,7 +68,6 @@ Export-Package: com.gargoylesoftware.htmlunit,
com.google.gwt.junit.remote,
com.google.gwt.junit.server,
com.google.gwt.junit.tools,
com.google.gwt.lang,
com.google.gwt.layout.client,
com.google.gwt.logging.client,
com.google.gwt.logging.impl,
@@ -176,32 +97,10 @@ Export-Package: com.gargoylesoftware.htmlunit,
com.google.gwt.safehtml.client,
com.google.gwt.safehtml.rebind,
com.google.gwt.safehtml.shared,
com.google.gwt.soyc,
com.google.gwt.soyc.io,
com.google.gwt.storage.client,
com.google.gwt.text.client,
com.google.gwt.text.shared,
com.google.gwt.text.shared.testing,
com.google.gwt.thirdparty.debugging.sourcemap,
com.google.gwt.thirdparty.debugging.sourcemap.proto,
com.google.gwt.thirdparty.guava.common.annotations,
com.google.gwt.thirdparty.guava.common.base,
com.google.gwt.thirdparty.guava.common.base.internal,
com.google.gwt.thirdparty.guava.common.cache,
com.google.gwt.thirdparty.guava.common.collect,
com.google.gwt.thirdparty.guava.common.eventbus,
com.google.gwt.thirdparty.guava.common.io,
com.google.gwt.thirdparty.guava.common.net,
com.google.gwt.thirdparty.guava.common.primitives,
com.google.gwt.thirdparty.guava.common.util.concurrent,
com.google.gwt.thirdparty.javascript.jscomp,
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.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.streamhtmlparser,
com.google.gwt.thirdparty.streamhtmlparser.impl,
com.google.gwt.thirdparty.streamhtmlparser.util,
@@ -242,10 +141,7 @@ Export-Package: com.gargoylesoftware.htmlunit,
com.google.gwt.user.tools.util,
com.google.gwt.useragent.client,
com.google.gwt.useragent.rebind,
com.google.gwt.util,
com.google.gwt.util.regexfilter,
com.google.gwt.util.tools,
com.google.gwt.util.tools.shared,
com.google.gwt.validation.client,
com.google.gwt.validation.client.constraints,
com.google.gwt.validation.client.impl,
@@ -284,266 +180,8 @@ Export-Package: com.gargoylesoftware.htmlunit,
com.google.web.bindery.requestfactory.vm,
com.google.web.bindery.requestfactory.vm.impl,
com.google.web.bindery.requestfactory.vm.testing,
com.ibm.icu.impl,
com.ibm.icu.impl.data,
com.ibm.icu.impl.duration,
com.ibm.icu.impl.duration.impl,
com.ibm.icu.impl.locale,
com.ibm.icu.lang,
com.ibm.icu.math,
com.ibm.icu.text,
com.ibm.icu.util,
com.steadystate.css.dom,
com.steadystate.css.parser,
com.steadystate.css.parser.selectors,
com.steadystate.css.sac,
com.steadystate.css.userdata,
java_cup,
java_cup.anttask,
java_cup.runtime,
net.sourceforge.htmlunit.corejs.classfile,
net.sourceforge.htmlunit.corejs.javascript,
net.sourceforge.htmlunit.corejs.javascript.annotations,
net.sourceforge.htmlunit.corejs.javascript.ast,
net.sourceforge.htmlunit.corejs.javascript.debug,
net.sourceforge.htmlunit.corejs.javascript.jdk13,
net.sourceforge.htmlunit.corejs.javascript.jdk15,
net.sourceforge.htmlunit.corejs.javascript.json,
net.sourceforge.htmlunit.corejs.javascript.optimizer,
net.sourceforge.htmlunit.corejs.javascript.regexp,
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.treetable,
net.sourceforge.htmlunit.corejs.javascript.tools.shell,
net.sourceforge.htmlunit.corejs.javascript.xml,
org.apache.bcel,
org.apache.bcel.classfile,
org.apache.bcel.generic,
org.apache.bcel.util,
org.apache.bcel.verifier,
org.apache.bcel.verifier.exc,
org.apache.bcel.verifier.statics,
org.apache.bcel.verifier.structurals,
org.apache.commons.codec,
org.apache.commons.codec.binary,
org.apache.commons.codec.digest,
org.apache.commons.codec.language,
org.apache.commons.codec.net,
org.apache.commons.collections,
org.apache.commons.collections.bag,
org.apache.commons.collections.bidimap,
org.apache.commons.collections.buffer,
org.apache.commons.collections.collection,
org.apache.commons.collections.comparators,
org.apache.commons.collections.functors,
org.apache.commons.collections.iterators,
org.apache.commons.collections.keyvalue,
org.apache.commons.collections.list,
org.apache.commons.collections.map,
org.apache.commons.collections.set,
org.apache.commons.el,
org.apache.commons.el.parser,
org.apache.commons.io,
org.apache.commons.io.comparator,
org.apache.commons.io.filefilter,
org.apache.commons.io.input,
org.apache.commons.io.output,
org.apache.commons.logging,
org.apache.commons.logging.impl,
org.apache.html.dom,
org.apache.http,
org.apache.http.annotation,
org.apache.http.auth,
org.apache.http.auth.params,
org.apache.http.client,
org.apache.http.client.entity,
org.apache.http.client.methods,
org.apache.http.client.params,
org.apache.http.client.protocol,
org.apache.http.client.utils,
org.apache.http.conn,
org.apache.http.conn.params,
org.apache.http.conn.routing,
org.apache.http.conn.scheme,
org.apache.http.conn.ssl,
org.apache.http.conn.util,
org.apache.http.cookie,
org.apache.http.cookie.params,
org.apache.http.entity,
org.apache.http.entity.mime,
org.apache.http.entity.mime.content,
org.apache.http.impl,
org.apache.http.impl.auth,
org.apache.http.impl.client,
org.apache.http.impl.conn,
org.apache.http.impl.conn.tsccm,
org.apache.http.impl.cookie,
org.apache.http.impl.entity,
org.apache.http.impl.io,
org.apache.http.io,
org.apache.http.message,
org.apache.http.params,
org.apache.http.protocol,
org.apache.http.util,
org.apache.james.mime4j,
org.apache.james.mime4j.codec,
org.apache.james.mime4j.descriptor,
org.apache.james.mime4j.field,
org.apache.james.mime4j.field.address,
org.apache.james.mime4j.field.address.parser,
org.apache.james.mime4j.field.contentdisposition.parser,
org.apache.james.mime4j.field.contenttype.parser,
org.apache.james.mime4j.field.datetime,
org.apache.james.mime4j.field.datetime.parser,
org.apache.james.mime4j.field.language.parser,
org.apache.james.mime4j.field.mimeversion.parser,
org.apache.james.mime4j.field.structured.parser,
org.apache.james.mime4j.io,
org.apache.james.mime4j.message,
org.apache.james.mime4j.parser,
org.apache.james.mime4j.storage,
org.apache.james.mime4j.util,
org.apache.jasper,
org.apache.jasper.compiler,
org.apache.jasper.compiler.tagplugin,
org.apache.jasper.runtime,
org.apache.jasper.security,
org.apache.jasper.servlet,
org.apache.jasper.tagplugins.jstl,
org.apache.jasper.util,
org.apache.jasper.xmlparser,
org.apache.regexp,
org.apache.tapestry.util.text,
org.apache.tools.ant,
org.apache.tools.ant.filters,
org.apache.tools.ant.filters.util,
org.apache.tools.ant.helper,
org.apache.tools.ant.input,
org.apache.tools.ant.listener,
org.apache.tools.ant.loader,
org.apache.tools.ant.taskdefs,
org.apache.tools.ant.taskdefs.compilers,
org.apache.tools.ant.taskdefs.condition,
org.apache.tools.ant.taskdefs.cvslib,
org.apache.tools.ant.taskdefs.email,
org.apache.tools.ant.taskdefs.rmic,
org.apache.tools.ant.types,
org.apache.tools.ant.types.mappers,
org.apache.tools.ant.types.resolver,
org.apache.tools.ant.types.selectors,
org.apache.tools.ant.types.selectors.modifiedselector,
org.apache.tools.ant.util,
org.apache.tools.ant.util.facade,
org.apache.tools.ant.util.regexp,
org.apache.tools.bzip2,
org.apache.tools.mail,
org.apache.tools.tar,
org.apache.tools.zip,
org.apache.wml,
org.apache.wml.dom,
org.apache.xalan,
org.apache.xalan.client,
org.apache.xalan.extensions,
org.apache.xalan.lib,
org.apache.xalan.lib.sql,
org.apache.xalan.processor,
org.apache.xalan.res,
org.apache.xalan.serialize,
org.apache.xalan.templates,
org.apache.xalan.trace,
org.apache.xalan.transformer,
org.apache.xalan.xslt,
org.apache.xalan.xsltc,
org.apache.xalan.xsltc.cmdline,
org.apache.xalan.xsltc.cmdline.getopt,
org.apache.xalan.xsltc.compiler,
org.apache.xalan.xsltc.compiler.util,
org.apache.xalan.xsltc.dom,
org.apache.xalan.xsltc.runtime,
org.apache.xalan.xsltc.runtime.output,
org.apache.xalan.xsltc.trax,
org.apache.xalan.xsltc.util,
org.apache.xerces.dom,
org.apache.xerces.dom.events,
org.apache.xerces.dom3.as,
org.apache.xerces.impl,
org.apache.xerces.impl.dtd,
org.apache.xerces.impl.dtd.models,
org.apache.xerces.impl.dv,
org.apache.xerces.impl.dv.dtd,
org.apache.xerces.impl.dv.util,
org.apache.xerces.impl.dv.xs,
org.apache.xerces.impl.io,
org.apache.xerces.impl.msg,
org.apache.xerces.impl.validation,
org.apache.xerces.impl.xpath,
org.apache.xerces.impl.xpath.regex,
org.apache.xerces.impl.xs,
org.apache.xerces.impl.xs.identity,
org.apache.xerces.impl.xs.models,
org.apache.xerces.impl.xs.opti,
org.apache.xerces.impl.xs.traversers,
org.apache.xerces.impl.xs.util,
org.apache.xerces.jaxp,
org.apache.xerces.jaxp.datatype,
org.apache.xerces.jaxp.validation,
org.apache.xerces.parsers,
org.apache.xerces.util,
org.apache.xerces.xinclude,
org.apache.xerces.xni,
org.apache.xerces.xni.grammars,
org.apache.xerces.xni.parser,
org.apache.xerces.xpointer,
org.apache.xerces.xs,
org.apache.xerces.xs.datatypes,
org.apache.xml.dtm,
org.apache.xml.dtm.ref,
org.apache.xml.dtm.ref.dom2dtm,
org.apache.xml.dtm.ref.sax2dtm,
org.apache.xml.res,
org.apache.xml.serialize,
org.apache.xml.serializer,
org.apache.xml.serializer.dom3,
org.apache.xml.serializer.utils,
org.apache.xml.utils,
org.apache.xml.utils.res,
org.apache.xmlcommons,
org.apache.xpath,
org.apache.xpath.axes,
org.apache.xpath.compiler,
org.apache.xpath.domapi,
org.apache.xpath.functions,
org.apache.xpath.jaxp,
org.apache.xpath.objects,
org.apache.xpath.operations,
org.apache.xpath.patterns,
org.apache.xpath.res,
org.cyberneko.html,
org.cyberneko.html.filters,
org.cyberneko.html.parsers,
org.cyberneko.html.xercesbridge,
org.eclipse.jdt.core,
org.eclipse.jdt.core.compiler,
org.eclipse.jdt.core.compiler.batch,
org.eclipse.jdt.internal.antadapter,
org.eclipse.jdt.internal.compiler,
org.eclipse.jdt.internal.compiler.ast,
org.eclipse.jdt.internal.compiler.batch,
org.eclipse.jdt.internal.compiler.classfmt,
org.eclipse.jdt.internal.compiler.codegen,
org.eclipse.jdt.internal.compiler.env,
org.eclipse.jdt.internal.compiler.flow,
org.eclipse.jdt.internal.compiler.impl,
org.eclipse.jdt.internal.compiler.lookup,
org.eclipse.jdt.internal.compiler.parser,
org.eclipse.jdt.internal.compiler.parser.diagnose,
org.eclipse.jdt.internal.compiler.problem,
org.eclipse.jdt.internal.compiler.util,
org.eclipse.jdt.internal.core.util,
org.hibernate.validator,
org.hibernate.validator.engine,
org.jdesktop.swingworker
org.hibernate.validator.engine
Require-Bundle: javax.validation;bundle-version="1.0.0"
Import-Package: javax.servlet;version="2.6.0",
javax.servlet.http;version="2.6.0"
@@ -1,4 +1,3 @@
bin.includes = META-INF/,\
.,\
lib/gwt-dev.jar,\
lib/gwt-user.jar
Binary file not shown.
@@ -190,7 +190,7 @@ public abstract class AbstractMarkPassingTest extends OnlineTracTracBasedTest {
incorrect += incorrectPasses;
skipped += wronglyNotComputed;
extra += wronglyComputed;
assertTrue(accuracy >= 0.8);
assertTrue("Expected accuracy to be at least 0.8 but was "+accuracy, accuracy >= 0.8);
}
private void testMiddleOfRace(int waypoint) {
@@ -202,46 +202,44 @@ public abstract class AbstractMarkPassingTest extends OnlineTracTracBasedTest {
for (Competitor c : getRace().getCompetitors()) {
TimePoint startTime;
TimePoint secondPass;
try {
if (givenPasses.get(c).get(start) != null && givenPasses.get(c).get(second) != null) {
startTime = givenPasses.get(c).get(start).getTimePoint();
secondPass = givenPasses.get(c).get(second).getTimePoint();
} catch (NullPointerException e) {
continue;
}
TimePoint delta = new MillisecondsTimePoint(startTime.plus(secondPass.asMillis()).asMillis() / 2);
List<GPSFix> fixes = new ArrayList<GPSFix>();
try {
getTrackedRace().getTrack(c).lockForRead();
for (GPSFixMoving fix : getTrackedRace().getTrack(c).getFixes()) {
if (fix.getTimePoint().before(delta)) {
fixes.add(fix);
TimePoint delta = new MillisecondsTimePoint(startTime.plus(secondPass.asMillis()).asMillis() / 2);
List<GPSFix> fixes = new ArrayList<GPSFix>();
try {
getTrackedRace().getTrack(c).lockForRead();
for (GPSFixMoving fix : getTrackedRace().getTrack(c).getFixes()) {
if (fix.getTimePoint().before(delta)) {
fixes.add(fix);
}
}
} finally {
getTrackedRace().getTrack(c).unlockAfterRead();
}
Pair<Iterable<Candidate>, Iterable<Candidate>> f = finder.getCandidateDeltas(c, fixes);
chooser.calculateMarkPassDeltas(c, f);
boolean gotPassed = true;
boolean gotOther = false;
// System.out.println(c);
for (Waypoint w : getRace().getCourse().getWaypoints()) {
MarkPassing old = givenPasses.get(c).get(w);
MarkPassing newm = getTrackedRace().getMarkPassing(c, w);
// System.out.println(newm);
if (waypoints.indexOf(w) <= waypoint) {
if ((old == null) != (newm == null)) {
gotPassed = false;
}
} else {
if (newm != null) {
gotOther = true;
}
}
}
} finally {
getTrackedRace().getTrack(c).unlockAfterRead();
}
Pair<Iterable<Candidate>, Iterable<Candidate>> f = finder.getCandidateDeltas(c, fixes);
chooser.calculateMarkPassDeltas(c, f);
boolean gotPassed = true;
boolean gotOther = false;
// System.out.println(c);
for (Waypoint w : getRace().getCourse().getWaypoints()) {
MarkPassing old = givenPasses.get(c).get(w);
MarkPassing newm = getTrackedRace().getMarkPassing(c, w);
// System.out.println(newm);
if (waypoints.indexOf(w) <= waypoint) {
if ((old == null) != (newm == null)) {
gotPassed = false;
}
} else {
if (newm != null) {
gotOther = true;
}
if (!gotPassed || gotOther) {
mistakes++;
}
}
if (!gotPassed || gotOther) {
mistakes++;
}
}
Assert.assertTrue(mistakes == 0);
}
@@ -30,4 +30,3 @@ Require-Bundle: com.googlecode.java-diff-utils;bundle-version="1.3.0",
com.sap.sailing.domain.common,
org.json.simple;bundle-version="1.1.0",
com.sap.sailing.geocoding
Import-Package: org.apache.commons.collections.map
@@ -6,27 +6,26 @@ import com.sap.sailing.domain.common.TimePoint;
/**
* A possible passing of a {@link Waypoint}. It contains the {@link Waypoint} that it might be passing, a
* {@link TimePoint}, the probability that this candidate is a passing (e.g. based on the distance to the
* {@link Waypoint}) and the one-based(!) ID of this Waypoint. The ID is one based because the standard implemantation
* {@link Waypoint}) and the one-based(!) ID of this Waypoint. The ID is one based because the standard implementation
* of {@link AbstractCandidateChooser} (see {@link CandidateChooser}) uses a proxy Candidates at the end and the
* beginning of the race, the one at the beginning recieves the ID 0. Candidates are created in an
* beginning of the race, the one at the beginning receives the ID 0. Candidates are created in an
* {@link AbstractCandidateFinder}, which determines where a passing could be and assigns them
*
* @author Nicolas Klose
*
*/
public class Candidate implements Comparable<Candidate> {
private Waypoint w;
private TimePoint p;
private Waypoint waypoint;
private TimePoint timePoint;
private double distanceProbability;
private Integer id;
private boolean rightSide;
private boolean rightDirection;
private String type;
public Candidate(int id, TimePoint p, double distanceProbability, Waypoint w, boolean rightSide, boolean rightDirection, String type) {
this.w = w;
this.p = p;
public Candidate(int id, TimePoint timePoint, double distanceProbability, Waypoint w, boolean rightSide, boolean rightDirection, String type) {
this.waypoint = w;
this.timePoint = timePoint;
this.distanceProbability = distanceProbability;
this.id = id;
this.rightSide = rightSide;
@@ -39,7 +38,7 @@ public class Candidate implements Comparable<Candidate> {
}
public TimePoint getTimePoint() {
return p;
return timePoint;
}
public Double getProbability() {
@@ -49,15 +48,15 @@ public class Candidate implements Comparable<Candidate> {
}
public Waypoint getWaypoint() {
return w;
return waypoint;
}
public String toString() {
return type + "-Candidate for " + id + " with cost " + getProbability() + "and Timepoint " + p;
return type + "-Candidate for " + id + " with cost " + getProbability() + "and Timepoint " + timePoint;
}
@Override
public int compareTo(Candidate arg0) {
return id != arg0.getID() ? id.compareTo(arg0.getID()) : p != arg0.getTimePoint() ? p.compareTo(arg0.getTimePoint()) : getProbability().compareTo(arg0.getProbability());
return id != arg0.getID() ? id.compareTo(arg0.getID()) : timePoint != arg0.getTimePoint() ? timePoint.compareTo(arg0.getTimePoint()) : getProbability().compareTo(arg0.getProbability());
}
}
@@ -68,7 +68,7 @@ public class CandidateChooser implements AbstractCandidateChooser {
@Override
public void calculateMarkPassDeltas(Competitor c, Pair<Iterable<Candidate>, Iterable<Candidate>> candidateDeltas) {
if (race.getStartOfRace()!=null&&!race.getStartOfRace().minus(2000).equals(raceStartTime)) {
if (race.getStartOfRace() != null && (raceStartTime == null || !race.getStartOfRace().minus(2000).equals(raceStartTime))) {
raceStartTime = race.getStartOfRace().minus(2000);
for (Competitor com : allEdges.keySet()) {
removeCandidates(Arrays.asList(start), com);
@@ -28,33 +28,33 @@ import com.sap.sailing.util.impl.ThreadFactoryWithPriority;
/**
* Calculates the {@link MarkPassing}s for a {@link DynamicTrackedRace} using a {@link AbstractCandidateFinder} and a
* {@link AbstractCandidateChooser}. The finder evaluates the fixes and finds possible MarkPassings as {@link Candidate}
* s. The chooser than finds the most likely sequence of {@link Candidate}s and creates the {@link MarkPassing}s for
* {@link AbstractCandidateChooser}. The finder evaluates the fixes and finds possible MarkPassings as {@link Candidate}s.
* The chooser then finds the most likely sequence of {@link Candidate}s and creates the {@link MarkPassing}s for
* this sequence. If <code>listen</code> is true, a {@link MarkPassingUpdateListener} is initialized which puts new
* fixes into a queue. Additionally a new Thread is started, which takes the fixes out of the queue and sorts them so
* fixes into a queue. Additionally a new thread is started, which takes the fixes out of the queue and sorts them so
* that each object (Competitor or Mark) has a list of Fixes in <code>combinedFixes</code>. If <code>suspended</code> is
* false, the new Fixes are handed to the <code>executor</code> as FutureTasks, first to calculate the affected Fixes
* and then the actual MarkPassings (See {@link CandidateFinder} and {@link CandidateChooser}). Then the listening
* process begins again with the queue being emptied. This continues until the <code>end</code> Object is put in the
* queue by the {@link MarkPassingUpdateListener}, signalising that the race is over.
* queue by the {@link MarkPassingUpdateListener}, signaling that the race is over.
*
* @author Nicolas Klose
*
*/
public class MarkPassingCalculator {
private AbstractCandidateFinder finder;
private AbstractCandidateChooser chooser;
private static final Logger logger = Logger.getLogger(MarkPassingCalculator.class.getName());
private MarkPassingUpdateListener listener;
private final static Pair<Object, GPSFix> end = new Pair<Object, GPSFix>(null, null);
private boolean suspended = false;
private final static ExecutorService executor = new ThreadPoolExecutor(/* corePoolSize */Math.max(Runtime.getRuntime()
.availableProcessors() - 1, 3),
/* maximumPoolSize */Math.max(Runtime.getRuntime().availableProcessors() - 1, 3),
/* keepAliveTime */60, TimeUnit.SECONDS,
/* workQueue */new LinkedBlockingQueue<Runnable>(), new ThreadFactoryWithPriority(Thread.NORM_PRIORITY - 1));
private MarkPassingUpdateListener listener;
private AbstractCandidateFinder finder;
private AbstractCandidateChooser chooser;
private boolean suspended = false;
public MarkPassingCalculator(DynamicTrackedRace race, boolean listen) {
if (listen) {
listener = new MarkPassingUpdateListener(race, end);
@@ -70,7 +70,6 @@ public class MarkPassingCalculator {
}
private class Listen implements Runnable {
@Override
public void run() {
logger.fine("MarkPassingCalculator is listening for new Fixes.");
@@ -21,9 +21,8 @@ import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener;
*
*/
public class MarkPassingUpdateListener extends AbstractRaceChangeListener {
private LinkedBlockingQueue<Pair<Object, GPSFix>> queue;
private final LinkedBlockingQueue<Pair<Object, GPSFix>> queue;
private final Pair<Object, GPSFix> end;
int i = 0;
public MarkPassingUpdateListener(TrackedRace race, Pair<Object, GPSFix> end) {
race.addListener(this);
@@ -47,7 +46,6 @@ public class MarkPassingUpdateListener extends AbstractRaceChangeListener {
@Override
public void statusChanged(TrackedRaceStatus newStatus) {
if (newStatus.getStatus() == TrackedRaceStatusEnum.FINISHED) {
queue.add(end);
}
+1 -1
View File
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="resources"/>
<classpathentry exported="true" kind="con" path="com.google.gwt.eclipse.core.GWT_CONTAINER"/>
<classpathentry exported="true" kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry exported="true" kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>
@@ -1,8 +0,0 @@
#Wed Nov 02 13:57:42 CET 2011
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6
@@ -4,13 +4,13 @@ Bundle-Name: Test
Bundle-SymbolicName: com.sap.sailing.gwt.ui.test
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: SAP
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Fragment-Host: com.sap.sailing.gwt.ui
Require-Bundle: com.sap.sailing.server,
org.hamcrest.core;bundle-version="1.1.0",
com.sap.sailing.expeditionconnector,
org.mockito.mockito-core;bundle-version="1.9.5",
org.objenesis;bundle-version="1.3.0"
org.objenesis;bundle-version="1.3.0",
org.hamcrest;bundle-version="1.1.0"
Bundle-ClassPath: .
Import-Package: javax.jms;version="1.1.0",
javax.servlet;version="2.6.0",
@@ -1,66 +1,119 @@
package com.sap.sailing.gwt.ui.test;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.closeTo;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.hamcrest.core.IsEqual.*;
import org.junit.Test;
import org.moxieapps.gwt.highcharts.client.Point;
import com.sap.sailing.gwt.ui.client.shared.charts.WindChartPointRecalculator;
import com.sap.sailing.gwt.ui.client.shared.charts.ChartPointRecalculator;
public class TestWindChartPointRecalculation {
private static final double POINT_Y_EQUALITY_EPSILON = 0.005;
private static final List<Double> MULTIPLE_WRAP_AROUNDS = Arrays.asList(356.74, 10.54, 30.192, 20.625, 5.647, 350.526);
private static final List<Double> EXPECTED_RECALCULATED_VALUES_FOR_MULTIPLE_WRAP_AROUNDS = Arrays.asList(356.74, 10.54 + 360, 30.192 + 360, 20.625 + 360, 5.647 + 360, 350.526);
private static final List<Double> CONTINOUS_WRAP_AROUNDS = Arrays.asList(5.34, 358.97, 10.42, 50.0, 110.65, 140.54,
210.85, 280.38, 330.5, 358.97, 7.24, 48.0, 112.65, 135.54, 215.85, 278.38, 333.5, 356.97, 8.24, 48.245,
112.57, 133.54, 215.637, 278.38, 333.5, 356.97);
private static final List<Double> EXPECTED_RECALCULATED_VALUES_FOR_CONTINOUS_WRAP_AROUNDS_OVERALL_DELTA_MINIMUM = Arrays.asList(
5.34, 358.97 - 360, 10.42, 50.0, 110.65, 140.54, 210.85 - 360, 280.38 - 360, 330.5 - 360,
358.97 - 360, 7.24, 48.0, 112.65, 135.54, 215.85 - 360, 278.38 - 360, 333.5 - 360, 356.97 - 360,
8.24, 48.245, 112.57, 133.54, 215.637 - 360, 278.38 - 360, 333.5 - 360, 356.97 - 360);
private static final List<Double> EXPECTED_RECALCULATED_VALUES_FOR_CONTINOUS_WRAP_AROUNDS_CLOSEST_TO_PREVIOUS_POINT = Arrays.asList(
5.34, 358.97 - 360, 10.42, 50.0, 110.65, 140.54, 210.85, 280.38, 330.5, 358.97, 367.24, 408.0, 472.65,
135.54 + 360, 575.85, 638.38, 693.5, 716.97, 728.24, 768.245, 112.57 + 720, 853.54, 935.637, 998.38, 1053.5,
1076.97);
private static void pointYEquals(Point actual, double expectedY) {
assertThat(actual.getY().doubleValue(), closeTo(expectedY, POINT_Y_EQUALITY_EPSILON));
}
@Test
public void testRecalculaion() {
public void testClosestToPreviousPointRecalculation() {
Point previousPoint = new Point(9, 20);
Point notToBeRecalculated = new Point(10, 100);
assertThat(WindChartPointRecalculator.recalculateDirectionPoint(90.0, 110.0, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY()));
assertThat(WindChartPointRecalculator.recalculateDirectionPoint(null, 110.0, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY()));
assertThat(WindChartPointRecalculator.recalculateDirectionPoint(90.0, null, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY()));
assertThat(WindChartPointRecalculator.recalculateDirectionPoint(100.27458, 110.0, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY()));
assertThat(WindChartPointRecalculator.recalculateDirectionPoint(90.0, 100.75639, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY()));
pointYEquals(ChartPointRecalculator.stayClosestToPreviousPoint(previousPoint, notToBeRecalculated), notToBeRecalculated.getY().doubleValue());
notToBeRecalculated = new Point(10, 5);
pointYEquals(ChartPointRecalculator.stayClosestToPreviousPoint(previousPoint, notToBeRecalculated), notToBeRecalculated.getY().doubleValue());
Point toBeMovedDown = new Point(10, 358);
pointYEquals(ChartPointRecalculator.stayClosestToPreviousPoint(previousPoint, toBeMovedDown), -2);
previousPoint = new Point(9, 350);
Point toBeMovedUp = new Point(10, 2);
pointYEquals(ChartPointRecalculator.stayClosestToPreviousPoint(previousPoint, toBeMovedUp), 362);
}
@Test
public void testOverallDeltaMinimalRecalculaion() {
Point notToBeRecalculated = new Point(10, 100);
assertThat(ChartPointRecalculator.keepOverallDeltaMinimal(90.0, 110.0, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY()));
assertThat(ChartPointRecalculator.keepOverallDeltaMinimal(null, 110.0, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY()));
assertThat(ChartPointRecalculator.keepOverallDeltaMinimal(90.0, null, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY()));
assertThat(ChartPointRecalculator.keepOverallDeltaMinimal(100.27458, 110.0, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY()));
assertThat(ChartPointRecalculator.keepOverallDeltaMinimal(90.0, 100.75639, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY()));
//Test for special case, which caused a wrong recalculation, because of the wrong use of Math.abs()
notToBeRecalculated = new Point(10, 179.8537);
assertThat(WindChartPointRecalculator.recalculateDirectionPoint(180.12356, 190.0, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY()));
assertThat(WindChartPointRecalculator.recalculateDirectionPoint(170.0, 179.5372, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY()));
assertThat(ChartPointRecalculator.keepOverallDeltaMinimal(180.12356, 190.0, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY()));
assertThat(ChartPointRecalculator.keepOverallDeltaMinimal(170.0, 179.5372, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY()));
Point toBeMovedDown = new Point(10, 356);
assertThat(WindChartPointRecalculator.recalculateDirectionPoint(4.0, 23.0, toBeMovedDown).getY(), equalTo(new Point(10, 356.0 - 360.0).getY()));
assertThat(ChartPointRecalculator.keepOverallDeltaMinimal(4.0, 23.0, toBeMovedDown).getY(), equalTo(new Point(10, 356.0 - 360.0).getY()));
Point toBeMovedUp = new Point(10, 5);
assertThat(WindChartPointRecalculator.recalculateDirectionPoint(356.0, 359.83364, toBeMovedUp).getY(), equalTo(new Point(10, 5.0 + 360.0).getY()));
assertThat(ChartPointRecalculator.keepOverallDeltaMinimal(356.0, 359.83364, toBeMovedUp).getY(), equalTo(new Point(10, 5.0 + 360.0).getY()));
}
@Test
public void testContinuousWrapAround() {
//Test multiple wrap around between 350� and 30�
List<Double> pointYValues = Arrays.asList(356.74, 10.54, 30.192, 20.625, 5.647, 350.526);
List<Double> expectedPointYValues = Arrays.asList(356.74, 10.54 + 360, 30.192 + 360, 20.625 + 360, 5.647 + 360, 350.526);
assertThat(recalculatePoints(pointYValues), equalTo(expectedPointYValues));
public void testClosestToPreviousPointWithMultipleAndContiniusWrapArounds() {
//Test multiple wrap around between 350 and 30
assertThat(recalculatePointsClosestToPreviousPoint(MULTIPLE_WRAP_AROUNDS), equalTo(EXPECTED_RECALCULATED_VALUES_FOR_MULTIPLE_WRAP_AROUNDS));
//Test multiple round trips from 0� to 360�
pointYValues = Arrays.asList(5.34, 358.97, 10.42, 50.0, 110.65, 140.54, 210.85, 280.38, 330.5, 358.97,
7.24, 48.0, 112.65, 135.54, 215.85, 278.38, 333.5, 356.97,
8.24, 48.245, 112.57, 133.54, 215.637, 278.38, 333.5, 356.97);
expectedPointYValues = Arrays.asList(5.34, 358.97 - 360, 10.42, 50.0, 110.65, 140.54, 210.85 - 360, 280.38 - 360, 330.5 - 360, 358.97 - 360,
7.24, 48.0, 112.65, 135.54, 215.85 - 360, 278.38 - 360, 333.5 - 360, 356.97 - 360,
8.24, 48.245, 112.57, 133.54, 215.637 - 360, 278.38 - 360, 333.5 - 360, 356.97 - 360);
assertThat(recalculatePoints(pointYValues), equalTo(expectedPointYValues));
//Test multiple round trips from 0 to 360
assertThat(recalculatePointsClosestToPreviousPoint(CONTINOUS_WRAP_AROUNDS), equalTo(EXPECTED_RECALCULATED_VALUES_FOR_CONTINOUS_WRAP_AROUNDS_CLOSEST_TO_PREVIOUS_POINT));
}
private List<Double> recalculatePointsClosestToPreviousPoint(List<Double> points) {
List<Double> racalculatedPoints = new ArrayList<Double>();
Point previousPoint = null;
for (Double yValue : points) {
Point newPoint = new Point(10, yValue);
if (previousPoint != null) {
newPoint = ChartPointRecalculator.stayClosestToPreviousPoint(previousPoint, newPoint);
}
racalculatedPoints.add(newPoint.getY().doubleValue());
previousPoint = newPoint;
}
return racalculatedPoints;
}
private List<Double> recalculatePoints(List<Double> pointYValues) {
@Test
public void testOverallDeltaMinimalWithMultipleAndContinuousWrapArounds() {
//Test multiple wrap around between 350 and 30
assertThat(recalculatePointsWithOverallDeltaMinimal(MULTIPLE_WRAP_AROUNDS), equalTo(EXPECTED_RECALCULATED_VALUES_FOR_MULTIPLE_WRAP_AROUNDS));
//Test multiple round trips from 0 to 360
assertThat(recalculatePointsWithOverallDeltaMinimal(CONTINOUS_WRAP_AROUNDS), equalTo(EXPECTED_RECALCULATED_VALUES_FOR_CONTINOUS_WRAP_AROUNDS_OVERALL_DELTA_MINIMUM));
}
private List<Double> recalculatePointsWithOverallDeltaMinimal(List<Double> pointYValues) {
List<Double> recalculatedPointYValues = new ArrayList<Double>();
Double min = null;
Double max = null;
for (Double yValue : pointYValues) {
Point p = new Point(10, yValue);
p = WindChartPointRecalculator.recalculateDirectionPoint(min, max, p);
p = ChartPointRecalculator.keepOverallDeltaMinimal(min, max, p);
Double newYValue = p.getY().doubleValue();
recalculatedPointYValues.add(newYValue);
+3 -4
View File
@@ -1,14 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="com.google.gwt.eclipse.core.GWT_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src/main/resources"/>
<classpathentry excluding="com/sap/sailing/gwt/ui/jre/" kind="src" path="src/main/java"/>
<classpathentry kind="lib" path="WEB-INF/lib/gwt-servlet.jar" sourcepath="/com.google.gwt.osgi/lib/gwt-user.jar"/>
<classpathentry exported="true" kind="lib" path="WEB-INF/lib/gwt-maps-api-3.9.0-build-17.jar"/>
<classpathentry exported="true" kind="lib" path="WEB-INF/lib/gwt-ajaxloader.jar"/>
<classpathentry exported="true" kind="lib" path="WEB-INF/lib/gwt-bootstrap-2.3.2.0.jar"/>
<classpathentry exported="true" kind="lib" path="WEB-INF/classes/"/>
<classpathentry kind="output" path="bin"/>
<classpathentry exported="true" kind="lib" path="WEB-INF/classes/"/>
<classpathentry kind="con" path="com.google.gwt.eclipse.core.GWT_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>
@@ -158,3 +158,10 @@ body, table td, select, button {
.circleRed {
background: #f01010;
}
.busyIndicator-Simple {
margin-top: 7px;
}
.busyIndicator-Circle {
}
@@ -24,7 +24,6 @@ Require-Bundle: com.sap.sailing.domain,
com.sap.sailing.freg.resultimport,
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.6.0",
com.sap.sailing.domain.igtimiadapter,
com.sap.sailing.datamining.shared;bundle-version="1.0.0",
@@ -40,13 +39,13 @@ Import-Package: javax.jms;version="1.1.0",
javax.servlet;version="2.6.0",
javax.servlet.descriptor;version="2.6.0",
javax.servlet.http;version="2.6.0",
org.apache.http.client;version="4.2.5",
org.json.simple,
org.json.simple.parser,
org.osgi.framework,
org.osgi.util.tracker
Web-ContextPath: /gwt
Bundle-ClassPath: WEB-INF/classes/,
WEB-INF/lib/gwt-servlet.jar,
WEB-INF/lib/gwt-maps-api-3.9.0-build-17.jar,
WEB-INF/lib/gwt-ajaxloader.jar,
WEB-INF/lib/gwt-bootstrap-2.3.2.0.jar
@@ -371,3 +371,9 @@ img.openColumn {
background: #f01010;
}
.busyIndicator-Simple {
margin-top: 7px;
}
.busyIndicator-Circle {
}
@@ -1,54 +1,52 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="com.google.gdt.eclipse.suite.webapp">
<booleanAttribute key="com.google.gdt.eclipse.core.RUN_SERVER" value="false"/>
<stringAttribute key="com.google.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.GWTShell"/>
<booleanAttribute key="com.google.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/>
<listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES">
<listEntry value="com.sap.sailing.gwt.ui.RegattaOverview"/>
</listAttribute>
<stringAttribute key="com.google.gwt.eclipse.core.URL" value="/gwt/AdminConsole.html"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/com.sap.sailing.gwt.ui"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
</listAttribute>
<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/sapjvm_7&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.googlecode.java-diff-utils/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.json.simple/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.tractrac.clientmodule/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.expeditionconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.udpconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.mongodb/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.operationaltransformation/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.moxieapps.gwt.highcharts/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.geocoding/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server.replication/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.google.gwt.osgi/lib/gwt-user.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;com.sap.sailing.gwt.ui&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/>
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/sapjvm_7"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/UserManagement.html com.sap.sailing.gwt.ui.UserManagement -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.ui.RegattaOverview"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx1024m -Xdebug -Xrunjdwp:transport=dt_socket,address=7999,server=y"/>
</launchConfiguration>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="com.google.gdt.eclipse.suite.webapp">
<booleanAttribute key="com.google.gdt.eclipse.core.RUN_SERVER" value="false"/>
<stringAttribute key="com.google.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.GWTShell"/>
<booleanAttribute key="com.google.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/>
<listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES">
<listEntry value="com.sap.sailing.gwt.ui.RegattaOverview"/>
</listAttribute>
<stringAttribute key="com.google.gwt.eclipse.core.URL" value="/gwt/AdminConsole.html"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/com.sap.sailing.gwt.ui"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
</listAttribute>
<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/sapjvm_7&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.googlecode.java-diff-utils/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.json.simple/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.expeditionconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.udpconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.mongodb/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.operationaltransformation/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.moxieapps.gwt.highcharts/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.geocoding/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server.replication/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.google.gwt.osgi/lib/gwt-user.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;com.sap.sailing.gwt.ui&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/>
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/UserManagement.html com.sap.sailing.gwt.ui.UserManagement -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.ui.RegattaOverview"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx1024m -Xdebug -Xrunjdwp:transport=dt_socket,address=7999,server=y"/>
</launchConfiguration>
+59 -55
View File
@@ -1,55 +1,59 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="com.google.gdt.eclipse.suite.webapp">
<booleanAttribute key="com.google.gdt.eclipse.core.RUN_SERVER" value="false"/>
<stringAttribute key="com.google.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.GWTShell"/>
<booleanAttribute key="com.google.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/>
<listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES">
<listEntry value="com.sap.sailing.gwt.ui.VideoPopup"/>
</listAttribute>
<stringAttribute key="com.google.gwt.eclipse.core.URL" value="/gwt/AdminConsole.html"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/com.sap.sailing.gwt.ui"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
</listAttribute>
<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6&quot; javaProject=&quot;com.sap.sailing.gwt.ui&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.googlecode.java-diff-utils/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.json.simple/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.expeditionconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.udpconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.mongodb/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.operationaltransformation/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.moxieapps.gwt.highcharts/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.geocoding/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server.replication/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.google.gwt.osgi/lib/gwt-user.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;com.sap.sailing.gwt.ui&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/>
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/UserManagement.html com.sap.sailing.gwt.ui.UserManagement -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/TvView.html com.sap.sailing.gwt.ui.TvView -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.ui.RegattaOverview -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/YoutubePopup.html com.sap.sailing.gwt.ui.YoutubePopup -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m -XX:MaxPermSize=512m"/>
</launchConfiguration>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="com.google.gdt.eclipse.suite.webapp">
<booleanAttribute key="com.google.gdt.eclipse.core.RUN_SERVER" value="false"/>
<stringAttribute key="com.google.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.GWTShell"/>
<booleanAttribute key="com.google.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/>
<listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES">
<listEntry value="com.sap.sailing.gwt.ui.VideoPopup"/>
<listEntry value="com.sap.sailing.gwt.ui.Simulator"/>
</listAttribute>
<stringAttribute key="com.google.gwt.eclipse.core.URL" value="/gwt/AdminConsole.html"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/com.sap.sailing.gwt.ui"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
</listAttribute>
<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6&quot; javaProject=&quot;com.sap.sailing.gwt.ui&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.googlecode.java-diff-utils/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.json.simple/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.expeditionconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.udpconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.mongodb/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.operationaltransformation/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.moxieapps.gwt.highcharts/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.geocoding/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server.replication/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.google.gwt.osgi/lib/gwt-user.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;com.sap.sailing.gwt.ui&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/>
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/UserManagement.html com.sap.sailing.gwt.ui.UserManagement -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/TvView.html com.sap.sailing.gwt.ui.TvView -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.ui.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.VideoPopup"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m -XX:MaxPermSize=512m"/>
</launchConfiguration>
@@ -2,7 +2,6 @@ source.WEB-INF/classes/ = src/main/java,\
src/main/resources
output.WEB-INF/classes/ = bin
bin.includes = META-INF/,\
WEB-INF/lib/gwt-servlet.jar,\
WEB-INF/classes/,\
WEB-INF/web.xml,\
AdminConsole.css,\
@@ -0,0 +1,848 @@
/**
* Streamlets
*
* Visualizes a vector field using an animated swarm of particles
* where each particle moves along the flow of the vector field
*
* - integrated with Google Maps v3
* - support vector fields unaligned with lat/lng-grid
* - support time-dependent vector fields
* - integrated with GWT for Strategy Simulator
*
* @author Christopher Ronnewinkel (D036654)
*
*/
var Vector = function(x, y) {
this.x = x;
this.y = y;
};
Vector.prototype.length = function() {
return Math.sqrt(this.x * this.x + this.y * this.y);
};
Vector.prototype.setLength = function(length) {
var current = this.length();
if (current) {
var scale = length / current;
this.x *= scale;
this.y *= scale;
}
return this;
};
var Mercator = function(map, canvas, field_opt) {
this.canvas = canvas;
this.alpha = 0.0;
this.beta = 0.0;
this.gamma = 0.0;
this.delta = 0.0;
this.map = map;
if (field_opt) {
this.fieldNW = new google.maps.LatLng(field_opt.y1, field_opt.x0);
this.fieldSE = new google.maps.LatLng(field_opt.y0, field_opt.x1);
}
this.calibrate();
};
Mercator.prototype.calibrate = function() {
var pointSW;
var pointNE;
if (this.fieldNW === undefined) {
var canvasWidth = this.map.getDiv().clientWidth;
var canvasHeight = this.map.getDiv().clientHeight;
this.canvas.style.width = canvasWidth + "px";
this.canvas.style.height = canvasHeight + "px";
this.canvas.width = canvasWidth;
this.canvas.height = canvasHeight;
var sw = swarmCanvasProjection.fromLatLngToDivPixel(this.map.getBounds()
.getSouthWest());
var ne = swarmCanvasProjection.fromLatLngToDivPixel(this.map.getBounds()
.getNorthEast());
this.canvas.style.position = "absolute";
this.canvas.style.left = sw.x + "px";
this.canvas.style.top = ne.y + "px";
var mapSW = this.map.getBounds().getSouthWest();
var mapNE = this.map.getBounds().getNorthEast();
pointSW = this.sphere2plane(mapSW.lat(), mapSW.lng());
pointNE = this.sphere2plane(mapNE.lat(), mapNE.lng());
} else {
var fieldNWpx = swarmCanvasProjection.fromLatLngToDivPixel(this.fieldNW);
var fieldSEpx = swarmCanvasProjection.fromLatLngToDivPixel(this.fieldSE);
this.canvas.style.left = fieldNWpx.x+"px";
this.canvas.style.top = fieldNWpx.y+"px";
var canvasWidth = fieldSEpx.x - fieldNWpx.x;
var canvasHeight = fieldSEpx.y - fieldNWpx.y;
this.canvas.style.width = canvasWidth + "px";
this.canvas.style.height = canvasHeight + "px";
this.canvas.width = canvasWidth;
this.canvas.height = canvasHeight;
pointSW = this.sphere2plane(this.fieldSE.lat(), this.fieldNW.lng());
pointNE = this.sphere2plane(this.fieldNW.lat(), this.fieldSE.lng());
}
if (pointNE.x < pointSW.x) {
pointSW.x -= 2*Math.PI;
}
this.alpha = this.canvas.height / (pointNE.y - pointSW.y);
this.beta = pointSW.x;
this.gamma = - this.alpha;
this.delta = pointNE.y;
};
Mercator.prototype.sphere2plane = function(lat, lng) {
var p = lng*Math.PI/180.0;
var latrad = lat*Math.PI/180.0;
var q = Math.log((1.0+Math.sin(latrad))/Math.cos(latrad));
return {x:p, y:q};
};
Mercator.prototype.plane2sphere = function(x,y) {
var lng = x*180.0/Math.PI;
var lat = Math.atan(Math.sinh(y))*180.0/Math.PI;
return {lat:lat, lng:lng};
};
Mercator.prototype.latlng2pixel = function(lat, lng) {
var proj = this.sphere2plane(lat,lng);
var x = this.alpha * (proj.x - this.beta);
var y = this.gamma * (proj.y - this.delta);
return {x:x, y:y};
};
Mercator.prototype.pixel2latlng = function(x, y) {
var p = x / this.alpha + this.beta;
var q = y / this.gamma + this.delta;
return this.plane2sphere({x:p, y:q});
};
Mercator.prototype.clearCanvas = function() {
var w = this.canvas.width;
var h = this.canvas.height;
var g = this.canvas.getContext('2d');
g.clearRect(0, 0, w, h);
};
var VectorField = function(data) {
this.data = data;
this.step = 0;
this.rcStart = data.rcStart;
this.rcEnd = data.rcEnd;
this.resY = data.resY;
this.resX = data.resX;
this.borderY = data.borderY;
this.borderX = data.borderX;
this.bdXi = (data.borderY + 0.5) / (this.resY - 1);
this.bdPhi = 1.0 + 2*this.bdXi;
this.bdA = { lat:this.rcEnd.lat+(this.rcEnd.lat-this.rcStart.lat)*this.bdXi, lng:this.rcEnd.lng+(this.rcEnd.lng-this.rcStart.lng)*this.bdXi };
this.bdB = { lat:(this.rcStart.lat-this.rcEnd.lat)*this.bdPhi, lng:(this.rcStart.lng-this.rcEnd.lng)*this.bdPhi };
this.xScale = data.xScale;
this.x0 = data.boundsSW.lng;
this.x1 = data.boundsNE.lng;
this.y0 = data.boundsSW.lat;
this.y1 = data.boundsNE.lat;
this.visX0 = 0;
this.visY0 = 0;
this.visX1 = 0;
this.visY1 = 0;
this.maxLength = data.maxLength;
this.numParticleFactor = 2.0;
var latAvg = (this.rcEnd.lat + this.rcStart.lat) / 2.;
this.lngScale = Math.cos(latAvg * Math.PI / 180.0);
var difLat = this.rcEnd.lat - this.rcStart.lat;
var difLng = (this.rcEnd.lng - this.rcStart.lng) * this.lngScale;
var difLen = Math.sqrt(difLat*difLat + difLng*difLng);
this.nvY = { lat: difLat/difLen/difLen*(this.resY-1), lng: difLng/difLen/difLen*(this.resY-1) };
var nrmLat = -difLng/difLen;
var nrmLng = difLat/difLen;
this.nvX = { lat: nrmLat/this.xScale/difLen*(this.resX-1), lng: nrmLng/this.xScale/difLen*(this.resX-1) };
this.gvX = { lat: nrmLat*this.xScale*difLen, lng: nrmLng/this.lngScale*this.xScale*difLen };
this.bdC = { lat:this.gvX.lat*(this.resX+2*this.borderX-1)/(this.resX-1), lng:this.gvX.lng*(this.resX+2*this.borderX-1)/(this.resX-1)};
};
VectorField.prototype.getRandomPosition = function() {
var rndY = Math.random();
var rndX = Math.random() - 0.5;
var latP = this.bdA.lat + rndY * this.bdB.lat + rndX * this.bdC.lat;
var lngP = this.bdA.lng + rndY * this.bdB.lng + rndX * this.bdC.lng;
if (!this.inBounds(lngP, latP)) {
console.log("random-position: out of bounds");
}
return {lat:latP, lng:lngP};
};
VectorField.prototype.inBounds = function(lng, lat) {
var idx = this.getIndex(lat, lng);
var inBool = (idx.x >= 0) && (idx.x < (this.resX+2*this.borderX)) && (idx.y >= 0) && (idx.y < (this.resY+2*this.borderY));
return inBool;
};
VectorField.prototype.interpolate = function(lat, lng) {
var idx = this.getNeighbors(lat, lng);
var idxOff = 0;
if ((idx.xTop >= (this.resX+2*this.borderX))||(idx.yTop >= (this.resY+2*this.borderY))) {
console.log("interpolate: out of range: " + idx.xTop + " " + idx.yTop);
}
var avgX = this.data.data[this.step][idx.yBot][2*idx.xBot] * (1 - idx.yMod) * (1 - idx.xMod) + this.data.data[this.step][idx.yTop][2*idx.xBot] * idx.yMod * (1 - idx.xMod)
+ this.data.data[this.step][idx.yBot][2*idx.xTop] * (1 - idx.yMod) * idx.xMod + this.data.data[this.step][idx.yTop][2*idx.xTop] * idx.yMod * idx.xMod;
var avgY = this.data.data[this.step][idx.yBot][2*idx.xBot+1] * (1 - idx.yMod) * (1 - idx.xMod) + this.data.data[this.step][idx.yTop][2*idx.xBot+1] * idx.yMod * (1 - idx.xMod)
+ this.data.data[this.step][idx.yBot][2*idx.xTop+1] * (1 - idx.yMod) * idx.xMod + this.data.data[this.step][idx.yTop][2*idx.xTop+1] * idx.yMod * idx.xMod;
return {x:avgX / this.lngScale, y:avgY};
};
VectorField.prototype.interpolate2 = function(lat, lng) {
var idx = this.getNeighbors(lat, lng);
var idxOff = 0;
if ((idx.xTop >= (this.resX+2*this.borderX))||(idx.yTop >= (this.resY+2*this.borderY))) {
console.log("interpolate: out of range: " + idx.xTop + " " + idx.yTop);
}
var idxBase = this.step*this.resX*this.resY;
var yBotxBot = getWindfromSimulator(idxBase + idx.yBot*this.resY + idx.xBot);
var yTopxBot = getWindfromSimulator(idxBase + idx.yTop*this.resY + idx.xBot);
var yBotxTop = getWindfromSimulator(idxBase + idx.yBot*this.resY + idx.xTop);
var yTopxTop = getWindfromSimulator(idxBase + idx.yTop*this.resY + idx.xTop);
var avgX = yBotxBot.x * (1 - idx.yMod) * (1 - idx.xMod) + yTopxBot.x * idx.yMod * (1 - idx.xMod) + yBotxTop.x * (1 - idx.yMod) * idx.xMod + yTopxTop.x * idx.yMod * idx.xMod;
var avgY = yBotxBot.y * (1 - idx.yMod) * (1 - idx.xMod) + yTopxBot.y * idx.yMod * (1 - idx.xMod) + yBotxTop.y * (1 - idx.yMod) * idx.xMod + yTopxTop.y * idx.yMod * idx.xMod;
return {x:avgX / this.lngScale, y:avgY};
};
VectorField.prototype.setStep = function(step) {
if (step < 0) {
this.step = 0;
} else if (step >= this.data.data.length) {
this.step = this.data.data.length-1;
} else {
this.step = step;
}
}
VectorField.prototype.nextStep = function() {
if (this.step < (this.data.data.length-1)) {
this.step++;
}
}
VectorField.prototype.prevStep = function() {
if (this.step > 0) {
this.step--;
}
}
VectorField.prototype.getValue = function(lat, lng, opt_result) {
var v = this.interpolate(lat, lng);
if (opt_result) {
opt_result.x = v.x;
opt_result.y = v.y;
return opt_result;
}
return new Vector(v.x, v.y);
};
VectorField.prototype.getValue2 = function(lat, lng, opt_result) {
var v = this.interpolate(lat, lng);
if (opt_result) {
opt_result.x = v.x;
opt_result.y = v.y;
return opt_result;
}
return new Vector(v.x, v.y);
};
VectorField.prototype.getIndex = function(lat, lng) {
// calculate grid indexes
var posR = { lat: lat - this.rcStart.lat, lng: (lng - this.rcStart.lng) * this.lngScale };
// closest grid point
var yIdx = Math.round( posR.lat * this.nvY.lat + posR.lng * this.nvY.lng ) + this.borderY;
var xIdx = Math.round( posR.lat * this.nvX.lat + posR.lng * this.nvX.lng + (this.resX - 1) / 2. ) + this.borderX;
return { x: xIdx, y: yIdx };
};
VectorField.prototype.getNeighbors = function(lat, lng) {
// calculate grid indexes
var posR = { lat: lat - this.rcStart.lat, lng: (lng - this.rcStart.lng) * this.lngScale };
// surrounding grid points
var yFlt = posR.lat * this.nvY.lat + posR.lng * this.nvY.lng + this.borderY;
var xFlt = posR.lat * this.nvX.lat + posR.lng * this.nvX.lng + (this.resX - 1) / 2. + this.borderX;
var yBot = Math.floor( yFlt );
var xBot = Math.floor( xFlt );
var yTop = Math.ceil( yFlt );
var xTop = Math.ceil( xFlt );
var yMod = yFlt - yBot;
var xMod = xFlt - xBot;
if (xBot < 0) {
xBot = 0;
}
if (yBot < 0) {
yBot = 0;
}
if (xTop >= (this.resX+2*this.borderX)) {
xTop = this.resX+2*this.borderX-1;
}
if (yTop >= (this.resY+2*this.borderY)) {
yTop = this.resY+2*this.borderY-1;
}
return { xTop: xTop, yTop:yTop, xBot:xBot, yBot:yBot, xMod:xMod, yMod:yMod };
};
VectorField.prototype.motionScale = function(zoomLevel) {
return 0.08 * Math.pow(1.6, Math.min(1.0, 6.0 - zoomLevel));
};
VectorField.prototype.particleWeight = function(p,v) {
return v.length() / this.maxLength + 0.1;
}
VectorField.prototype.getColors = function() {
var colors = [];
var alpha = 0.7;
var greyValue = 255;
for (var i = 0; i < 256; i++) {
colors[i] = 'rgba(' + (greyValue) + ',' + (greyValue) + ',' + (greyValue) + ',' + (alpha*i/255.0) + ')';
//this.colors[i] = 'hsla(' + 360*(0.55+0.9*(0.5-i/255)) + ',' + (100) + '% ,' + (50) + '%,' + (i/255) + ')';
}
return colors;
}
VectorField.prototype.lineWidth = function(s) {
return 1.0;
}
/**
* for compatibility with vector fields aligned with lat/lng-grid
**/
var RectField = function(field, x0, y0, x1, y1) {
this.x0 = x0;
this.x1 = x1;
this.y0 = y0;
this.y1 = y1;
this.visX0 = 0;
this.visY0 = 0;
this.visX1 = 0;
this.visY1 = 0;
this.field = field;
this.w = field.length;
this.h = field[0].length;
this.maxLength = 0;
this.numParticleFactor = 4.5;
var mx = 0;
var my = 0;
for (var i = 0; i < this.w; i++) {
for (var j = 0; j < this.h; j++) {
if (field[i][j].length() > this.maxLength) {
mx = i;
my = j;
}
this.maxLength = Math.max(this.maxLength, field[i][j].length());
}
}
mx = (mx / this.w) * (x1 - x0) + x0;
my = (my / this.h) * (y1 - y0) + y0;
};
RectField.read = function(data, correctForSphere) {
var field = [];
var w = data.gridWidth;
var h = data.gridHeight;
var i = 0;
for (var x = 0; x < w; x++) {
field[x] = [];
for (var y = 0; y < h; y++) {
var vx = data.field[i++];
var vy = data.field[i++];
var v = new Vector(vx, vy);
if (correctForSphere) {
var uy = y / (h - 1);
var lat = data.y0 * (1 - uy) + data.y1 * uy;
var m = Math.PI * lat / 180;
var length = v.length();
v.x /= Math.cos(m);
v.setLength(length);
}
field[x][y] = v;
}
}
var result = new RectField(field, data.x0, data.y0, data.x1, data.y1);
return result;
};
RectField.prototype.getRandomPosition = function() {
var rndY = Math.random();
var rndX = Math.random();
var y = rndY * this.visY0 + (1 - rndY) * this.visY1;
var x = rndX * this.visX0 + (1 - rndX) * this.visX1;
return {lat:y, lng:x};
};
RectField.prototype.inBounds = function(x, y) {
return x >= this.x0 && x < this.x1 && y >= this.y0 && y < this.y1;
};
RectField.prototype.interpolate = function(a, b) {
var na = Math.floor(a);
var nb = Math.floor(b);
var ma = Math.ceil(a);
var mb = Math.ceil(b);
var fa = a - na;
var fb = b - nb;
var avgX = this.field[na][nb]['x'] * (1 - fa) * (1 - fb) + this.field[ma][nb]['x'] * fa * (1 - fb) + this.field[na][mb]['x'] * (1 - fa) * fb + this.field[ma][mb]['x'] * fa * fb;
var avgY = this.field[na][nb]['y'] * (1 - fa) * (1 - fb) + this.field[ma][nb]['y'] * fa * (1 - fb) + this.field[na][mb]['y'] * (1 - fa) * fb + this.field[ma][mb]['y'] * fa * fb;
return {x:avgX, y:avgY};
};
RectField.prototype.getValue = function(y, x, opt_result) {
var a = (this.w - 1 - 1e-6) * (x - this.x0) / (this.x1 - this.x0);
var b = (this.h - 1 - 1e-6) * (y - this.y0) / (this.y1 - this.y0);
var v = this.interpolate(a, b);
if (opt_result) {
opt_result.x = v.x;
opt_result.y = v.y;
return opt_result;
}
return new Vector(v.x, v.y);
};
RectField.prototype.motionScale = function(zoomLevel) {
return 0.9 * Math.pow(1.7, Math.min(1.0, 6.0 - zoomLevel));
};
RectField.prototype.particleWeight = function(p,v) {
return 1.0 - v.length() / this.maxLength;
}
RectField.prototype.getColors = function() {
var colors = [];
var alpha = 1.0;
var greyValue = 255;
for (var i = 0; i < 256; i++) {
colors[i] = 'rgba(' + (greyValue) + ',' + (greyValue) + ',' + (greyValue) + ',' + (alpha*i/255.0) + ')';
//this.colors[i] = 'hsla(' + 360*(0.55+0.9*(0.5-i/255)) + ',' + (100) + '% ,' + (50) + '%,' + (i/255) + ')';
}
return colors;
}
RectField.prototype.lineWidth = function(s) {
return 1.0;
}
var Animator = function() {
this.animating = true;
this.state = 'animate';
this.pause = 0;
this.listeners = [];
this.dx = 0;
this.dy = 0;
this.scale = 1;
this.zoomProgress = 0;
this.scaleTarget = 1;
this.scaleStart = 1;
};
Animator.prototype.add = function(listener) {
this.listeners.push(listener);
};
Animator.prototype.notify = function(message) {
if (this.animFunc && !this.animFunc()) {
return;
}
for (var i = 0; i < this.listeners.length; i++) {
var listener = this.listeners[i];
if (listener[message]) {
listener[message].call(listener, this);
}
}
};
Animator.prototype.start = function(opt_millis) {
var millis = opt_millis || 20;
var self = this;
function go() {
var start = new Date();
if (self.loop()) {
return;
}
var time = new Date() - start;
setTimeout(go, Math.max(10, millis - time));
}
go();
};
Animator.prototype.loop = function() {
if (this.state == 'stop') {
return true;
}
if (this.pause > 1) {
this.pause--;
} else if (this.pause == 1){
this.state = 'animate';
this.pause = 0;
}
if (this.state == 'animate') {
this.notify('animate');
return false;
}
if ((this.state == 'pause')&&(this.pause == 0)) {
this.pause = 5;
}
return false;
};
var Particle = function(x, y, age) {
this.x = x;
this.y = y;
this.oldX = -1;
this.oldY = -1;
this.age = age;
this.rnd = Math.random();
};
var swarmOffScreen = false;
var Swarm = function(canvas, field, opt_projection) {
this.canvas = canvas;
this.projection = opt_projection || IDProjection;
this.field = field;
this.numParticles = 0;
this.first = true;
this.maxLength = field.maxLength;
this.speedScale = 1;
this.renderState = 'normal';
this.boundsSW = new google.maps.LatLng(this.field.y0, this.field.x0);
this.boundsNE = new google.maps.LatLng(this.field.y1, this.field.x1);
this.updateBounds(null);
this.makeNewParticles(null, true);
this.rgb = '40, 40, 40';
this.background = 'rgb(' + this.rgb + ')';
this.colors = this.field.getColors();
if (this.projection) {
this.startOffsetX = this.projection.offsetX;
this.startOffsetY = this.projection.offsetY;
this.startScale = this.projection.scale;
}
};
Swarm.prototype.updateBounds = function() {
var mapNE = this.projection.map.getBounds().getNorthEast();
var mapSW = this.projection.map.getBounds().getSouthWest();
var fieldNE = new google.maps.LatLng(Math.max(this.field.y0, this.field.y1), Math.max(this.field.x0, this.field.x1));
var fieldSW = new google.maps.LatLng(Math.min(this.field.y0, this.field.y1), Math.min(this.field.x0, this.field.x1));
var visibleNE = this.isVisible(fieldNE);
var visibleSW = this.isVisible(fieldSW);
var useBoundsNorth = (visibleNE.y == 0);
var useBoundsEast = (visibleNE.x == 0);
var useBoundsSouth = (visibleSW.y == 0);
var useBoundsWest = (visibleSW.x == 0);
swarmOffScreen = (visibleNE.y > 0)||(visibleSW.y < 0)||(visibleNE.x < 0)||(visibleSW.x > 0);
if (swarmOffScreen) {
this.boundsNE = fieldNE;
this.boundsSW = fieldSW;
} else {
if ((!useBoundsNorth)&&(!useBoundsEast)) {
this.boundsNE = mapNE;
} else if (!useBoundsNorth) {
this.boundsNE = new google.maps.LatLng(mapNE.lat(), fieldNE.lng());
} else if (!useBoundsEast) {
this.boundsNE = new google.maps.LatLng(fieldNE.lat(), mapNE.lng());
} else {
this.boundsNE = fieldNE;
}
if ((!useBoundsSouth)&&(!useBoundsWest)) {
this.boundsSW = mapSW;
} else if (!useBoundsSouth) {
this.boundsSW = new google.maps.LatLng(mapSW.lat(), fieldSW.lng());
} else if (!useBoundsWest) {
this.boundsSW = new google.maps.LatLng(fieldSW.lat(), mapSW.lng());
} else {
this.boundsSW = fieldSW;
}
}
this.field.visX0 = this.boundsSW.lng();
this.field.visY0 = this.boundsSW.lat();
this.field.visX1 = this.boundsNE.lng();
this.field.visY1 = this.boundsNE.lat();
var boundsSWpx = this.projection.latlng2pixel(this.boundsSW.lat(), this.boundsSW.lng());
var boundsNEpx = this.projection.latlng2pixel(this.boundsNE.lat(), this.boundsNE.lng());
var boundsWidthpx = Math.abs(boundsNEpx.x - boundsSWpx.x);
var boundsHeightpx = Math.abs(boundsSWpx.y - boundsNEpx.y);
this.numParticles = Math.sqrt(boundsWidthpx * boundsHeightpx) * this.field.numParticleFactor;
//this.numParticles = Math.sqrt(boundsWidthpx*boundsWidthpx + boundsHeightpx*boundsHeightpx) * this.field.numParticleFactor;
console.log("numParticles: "+this.numParticles + " at " + (boundsWidthpx) +"x" + (boundsHeightpx) + "px (" + (boundsWidthpx * boundsHeightpx) + " pixels)");
};
Swarm.prototype.isVisible = function(pos) {
// test for visibility of swarm
var proj = this.projection.latlng2pixel(pos.lat(), pos.lng());
var xVisible = -(proj.x < 0) + (proj.x > this.canvas.width);
var yVisible = -(proj.y < 0) + (proj.y > this.canvas.height);
return {x:xVisible, y:yVisible};
};
Swarm.prototype.makeNewParticles = function() {
this.particles = [];
for (var i = 0; i < this.numParticles; i++) {
particle = this.makeParticle();
if (particle) {
this.particles.push(particle);
} else {
break;
}
}
};
Swarm.prototype.makeParticle = function() {
var trials = 0;
while (true) {
var pos = this.field.getRandomPosition();
var x = pos.lng;
var y = pos.lat;
var v = this.field.getValue(y, x);
if (this.field.maxLength == 0) {
return new Particle(x, y, 1 + 40 * Math.random());
}
var weight = this.field.particleWeight(pos, v);
if (weight >= Math.random()) {
var proj = this.projection.latlng2pixel(y, x);
if (++trials > 10 || !(proj.x < 0 || proj.y < 0 || proj.x > this.canvas.width || proj.y > this.canvas.height)) {
if (v.x || v.y) {
return new Particle(x, y, 1 + 40 * Math.random());
} else {
return new Particle(x, y, 0); // "zombie" particles to avoid dead-lock when Google Maps is moved so that only zero-wind-area is visible
}
}
}
}
};
Swarm.prototype.endMove = function() {
this.updateBounds();
this.makeNewParticles();
};
Swarm.prototype.animate = function() {
if (!swarmOffScreen) {
this.moveThings();
this.draw();
}
};
Swarm.prototype.moveThings = function() {
var speed = .01 * this.speedScale * this.field.motionScale(this.projection.map.getZoom());
for (var i = 0; i < this.particles.length; i++) {
var p = this.particles[i];
if (p.age > 0 && this.field.inBounds(p.x, p.y)) {
var a = this.field.getValue(p.y, p.x);
p.x += speed * a.x;
p.y += speed * a.y;
p.age--;
} else {
this.particles[i] = this.makeParticle();
}
}
};
Swarm.prototype.draw = function() {
var g = this.canvas.getContext('2d');
var w = this.canvas.width;
var h = this.canvas.height;
g.globalCompositeOperation = "destination-out";
g.globalAlpha = 0.08;
g.fillStyle = this.background;
g.fillRect(0, 0, w, h);
g.globalCompositeOperation = "source-over";
g.globalAlpha = 1.0;
var proj; // = new Vector(0, 0);
var val = new Vector(0, 0);
for (var i = 0; i < this.particles.length; i++) {
var p = this.particles[i];
if (!this.field.inBounds(p.x, p.y)) {
p.age = -2;
continue;
}
proj = this.projection.latlng2pixel(p.y, p.x);
if (proj.x < 0 || proj.y < 0 || proj.x > w || proj.y > h) {
p.age = -2;
}
if (p.oldX != -1) {
var wind = this.field.getValue(p.y, p.x, val);
var s = wind.length() / this.maxLength;
var c = 90 + Math.round(350 * s); // was 400
if (c > 255) {
c = 255;
}
g.globalAlpha = 1.0;
g.lineWidth = this.field.lineWidth(s);
g.strokeStyle = this.colors[c];
g.beginPath();
g.moveTo(proj.x, proj.y);
g.lineTo(p.oldX, p.oldY);
g.stroke();
g.globalAlpha = 1.0;
}
p.oldX = proj.x;
p.oldY = proj.y;
}
};
var swarmData;
var swarmField;
var swarmAnimator;
var swarmProjection;
function initStreamlets(map, canvas) {
if (!map) {
alert("Google Maps Instance required.");
return;
}
if (!canvas) {
canvas = document.getElementById('swarm-display');
if (!canvas) {
alert("canvas 'swarm-display' not available");
}
}
if ("windFieldSim" in window) {
swarmField = new VectorField(windFieldSim);
} else {
if ("swarmDataExt" in window) {
swarmData = swarmDataExt;
map.setZoom(5.0);
var center = new google.maps.LatLng((swarmData.y0+swarmData.y1)/2., (swarmData.x0+swarmData.x1)/2.);
map.panTo(center);
};
swarmField = RectField.read(swarmData, false);
};
swarmProjection = new Mercator(map, canvas); //, field);
//var isMacFF = navigator.platform.indexOf('Mac') != -1 && navigator.userAgent.indexOf('Firefox') != -1;
var isWinFF = navigator.platform.indexOf('Win') != -1 && navigator.userAgent.indexOf('Firefox') != -1;
var isWinIE = navigator.platform.indexOf('Win') != -1 && navigator.userAgent.indexOf('MSIE') != -1;
var swarm = new Swarm(canvas, swarmField, swarmProjection);
swarmAnimator = new Animator();
swarmAnimator.add(swarm);
updateStreamlets = function(upd_data) {
if (!(upd_data === undefined)) {
swarmAnimator.state = 'stop'
swarmAnimator = new Animator();
swarmField = new VectorField(windFieldSim);
swarm = new Swarm(canvas, swarmField, swarmProjection);
swarmAnimator.add(swarm);
swarmAnimator.start(40);
} else if (swarmAnimator.state == 'stop') {
return;
}
swarmAnimator.state = 'pause';
swarmProjection.clearCanvas();
swarmProjection.calibrate();
swarmAnimator.notify('endMove');
};
stopStreamlets = function() {
swarmAnimator.state = 'stop';
swarmProjection.clearCanvas();
}
if (swarmProjection.fieldNW === undefined) {
google.maps.event.addListener(map, 'bounds_changed', updateStreamlets);
} else {
google.maps.event.addListener(map, 'zoom_changed', updateStreamlets);
}
swarmAnimator.start(40);
}
-6
View File
@@ -66,12 +66,6 @@
<version>1.0.0-SNAPSHOT</version>
<classifier>sources</classifier>
</dependency>
<dependency>
<groupId>com.sap.sailing</groupId>
<artifactId>de.csenk.gwt.ws</artifactId>
<version>1.0.0-SNAPSHOT</version>
<classifier>sources</classifier>
</dependency>
<dependency>
<groupId>com.github.gwtbootstrap</groupId>
<artifactId>gwt-bootstrap</artifactId>
@@ -36,6 +36,7 @@ import com.sap.sailing.gwt.ui.masterdataimport.MasterDataImportPanel;
import com.sap.sailing.gwt.ui.shared.BetterDateTimeBox;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
public class AdminConsoleEntryPoint extends AbstractEntryPoint implements RegattaRefresher {
private Set<RegattaDisplayer> regattaDisplayers;
@@ -207,18 +208,19 @@ public class AdminConsoleEntryPoint extends AbstractEntryPoint implements Regatt
@Override
public void fillRegattas() {
sailingService.getRegattas(new AsyncCallback<List<RegattaDTO>>() {
@Override
public void onSuccess(List<RegattaDTO> result) {
for (RegattaDisplayer regattaDisplayer : regattaDisplayers) {
regattaDisplayer.fillRegattas(result);
}
}
@Override
public void onFailure(Throwable caught) {
reportError("Remote Procedure Call getRegattas() - Failure");
}
});
sailingService.getRegattas(new MarkedAsyncCallback<List<RegattaDTO>>(
new AsyncCallback<List<RegattaDTO>>() {
@Override
public void onSuccess(List<RegattaDTO> result) {
for (RegattaDisplayer regattaDisplayer : regattaDisplayers) {
regattaDisplayer.fillRegattas(result);
}
}
@Override
public void onFailure(Throwable caught) {
reportError("Remote Procedure Call getRegattas() - Failure");
}
}));
}
}
@@ -0,0 +1,45 @@
package com.sap.sailing.gwt.ui.client;
/**
* <p>Helper class for generating debug identifiers.</p>
*
* @author
* Riccardo Nimser
*/
public class DebugIdHelper {
/**
* <p>Creates a debug identifier for the given enum value. The identifier is the camel cased name of the enum value
* as declared in its enum declaration. The name is split into single words using the underscore.</p>
*
* @param value
* The enum value for which the identfier should be created.
* @return
* A debug identifier for the given enum value.
*/
public static <T extends Enum<?>> String createDebugId(T value) {
return createDebugId(value.name(), "_");
}
/**
* <p>Creates a debug identifier for the given name. The name is splited into single words using all whitespace
* characters.</p>
*
* @param value
* The name for which the identifier should be created.
* @return
* A debug identifier for the given enum value.
*/
public static String createDebugId(String name) {
return createDebugId(name, "\\s");
}
private static String createDebugId(String name, String splitRegex) {
StringBuilder builder = new StringBuilder();
for (String token : name.split(splitRegex)) {
builder.append(token.substring(0, 1).toUpperCase());
builder.append(token.substring(1, token.length()).toLowerCase());
}
return builder.toString();
}
}
@@ -158,15 +158,12 @@ public class TimePanel<T extends TimePanelSettings> extends SimplePanel implemen
@Override
public void onClick(ClickEvent event) {
switch(TimePanel.this.timer.getPlayState()) {
case Stopped:
case Paused:
TimePanel.this.timer.play();
break;
case Playing:
TimePanel.this.timer.pause();
break;
case Paused:
TimePanel.this.timer.play();
break;
}
}
});
@@ -313,7 +310,7 @@ public class TimePanel<T extends TimePanelSettings> extends SimplePanel implemen
setMinMax(getFromTime(), newMaxTime, /* fireEvent */ false); // no event because we guarantee that time is between min/max
break;
case Replay:
timer.stop();
timer.pause();
break;
}
}
@@ -420,7 +417,6 @@ public class TimePanel<T extends TimePanelSettings> extends SimplePanel implemen
}
break;
case Paused:
case Stopped:
updatePlayPauseButtonsVisibility(playMode);
playPauseButton.getElement().removeClassName("playPauseButtonPause");
playModeImage.setResource(playModeInactiveImg);
@@ -215,8 +215,6 @@ public class MediaSelector implements PlayStateListener, TimeListener,
startPlaying();
break;
case Paused:
// fall through to Stopped
case Stopped:
pausePlaying();
default:
break;
@@ -463,8 +461,6 @@ public class MediaSelector implements PlayStateListener, TimeListener,
}
break;
case Paused:
// fall through to Stopped
case Stopped:
if (!mediaPlayer.isMediaPaused()) {
mediaPlayer.pauseMedia();
}
@@ -159,6 +159,7 @@ public abstract class AbstractCompetitorLeaderboardChart<SettingsType> extends A
break;
}
chart.setTitle(new ChartTitle().setText(DetailTypeFormatter.format(selectedDetailType)), null);
chart.ensureDebugId("CompetitorChart");
final String unit = DetailTypeFormatter.getUnit(getSelectedDetailType());
final String label = unit.isEmpty() ? "" : "[" + unit + "]";
chart.getYAxis().setAxisTitleText(label);
@@ -0,0 +1,58 @@
package com.sap.sailing.gwt.ui.client.shared.charts;
import org.moxieapps.gwt.highcharts.client.Point;
public final class ChartPointRecalculator {
private ChartPointRecalculator() { }
public static Point stayClosestToPreviousPoint(Point previousPoint, Point newPoint) {
double previousY = previousPoint.getY().doubleValue();
double newY = newPoint.getY().doubleValue();
double bestNewY = newY;
boolean hasBeenMoved;
do {
hasBeenMoved = false;
double deltaPreviousYToNewY = Math.abs(previousY - bestNewY);
double deltaPreviousYToNewYUp = Math.abs(previousY - (bestNewY + 360));
double deltaPreviousYToNewYDown = Math.abs(previousY - (bestNewY - 360));
if (deltaPreviousYToNewYUp < deltaPreviousYToNewY ||
deltaPreviousYToNewYDown < deltaPreviousYToNewY) {
bestNewY = deltaPreviousYToNewYUp <= deltaPreviousYToNewYDown ?
bestNewY + 360 : bestNewY - 360;
hasBeenMoved = true;
}
} while (hasBeenMoved);
return new Point(newPoint.getX(), bestNewY);
}
public static Point keepOverallDeltaMinimal(Double yMin, Double yMax, Point newPoint) {
double y = newPoint.getY().doubleValue();
if (yMax != null && yMin != null && (y < yMin || y > yMax)) {
double deltaMin = Math.abs(yMin - y);
double deltaMax = Math.abs(yMax - y);
double yDown = y - 360;
double deltaMinDown = Math.abs(yMin - yDown);
double yUp = y + 360;
double deltaMaxUp = Math.abs(yMax - yUp);
if (isRecalculationNeeded(deltaMin, deltaMax, deltaMinDown, deltaMaxUp)) {
y = deltaMaxUp <= deltaMinDown ? yUp : yDown;
return new Point(newPoint.getX(), y);
}
}
return newPoint;
}
private static boolean isRecalculationNeeded(double deltaMin, double deltaMax, double deltaMinDown, double deltaMaxUp) {
return (deltaMinDown < deltaMin || deltaMinDown < deltaMax) || (deltaMaxUp < deltaMin || deltaMaxUp < deltaMax);
}
}
@@ -49,6 +49,7 @@ public class MultiCompetitorLeaderboardChartSettingsDialogComponent implements S
Label chartSelectionLabel = new Label(stringMessages.chooseChart());
mainPanel.add(chartSelectionLabel);
chartTypeSelectionListBox = dialog.createListBox(/* isMultiSelect */false);
chartTypeSelectionListBox.ensureDebugId("ChartTypeListBox");
int i = 0;
for (DetailType detailType : availableDetailsTypes) {
chartTypeSelectionListBox.addItem(DetailTypeFormatter.format(detailType), detailType.name());
@@ -15,12 +15,12 @@ import org.moxieapps.gwt.highcharts.client.ChartTitle;
import org.moxieapps.gwt.highcharts.client.Color;
import org.moxieapps.gwt.highcharts.client.Credits;
import org.moxieapps.gwt.highcharts.client.PlotLine;
import org.moxieapps.gwt.highcharts.client.PlotLine.DashStyle;
import org.moxieapps.gwt.highcharts.client.Point;
import org.moxieapps.gwt.highcharts.client.Series;
import org.moxieapps.gwt.highcharts.client.ToolTip;
import org.moxieapps.gwt.highcharts.client.ToolTipData;
import org.moxieapps.gwt.highcharts.client.ToolTipFormatter;
import org.moxieapps.gwt.highcharts.client.PlotLine.DashStyle;
import org.moxieapps.gwt.highcharts.client.events.ChartClickEvent;
import org.moxieapps.gwt.highcharts.client.events.ChartClickEventHandler;
import org.moxieapps.gwt.highcharts.client.events.ChartSelectionEvent;
@@ -42,15 +42,14 @@ import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.impl.ColorMapImpl;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.gwt.ui.actions.GetWindInfoAction;
import com.sap.sailing.gwt.ui.client.ErrorReporter;
import com.sap.sailing.gwt.ui.client.RaceSelectionProvider;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.WindSourceTypeFormatter;
import com.sap.sailing.gwt.ui.client.shared.components.Component;
import com.sap.sailing.gwt.ui.client.shared.components.SettingsDialogComponent;
import com.sap.sailing.gwt.ui.client.WindSourceTypeFormatter;
import com.sap.sailing.gwt.ui.shared.WindDTO;
import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO;
import com.sap.sailing.gwt.ui.shared.WindTrackInfoDTO;
@@ -73,7 +72,6 @@ public class WindChart extends AbstractRaceChart implements Component<WindChartS
private final Map<WindSource, Series> windSourceSpeedSeries;
private final Map<WindSource, Point[]> windSourceDirectionPoints;
private final Map<WindSource, Point[]> windSourceSpeedPoints;
private Pair<Double, Double> overallDirectionMinMax;
private Long timeOfEarliestRequestInMillis;
private Long timeOfLatestRequestInMillis;
@@ -96,7 +94,6 @@ public class WindChart extends AbstractRaceChart implements Component<WindChartS
windSourceSpeedSeries = new HashMap<WindSource, Series>();
windSourceDirectionPoints = new HashMap<WindSource, Point[]>();
windSourceSpeedPoints = new HashMap<WindSource, Point[]>();
overallDirectionMinMax = new Pair<Double, Double>(null, null);
colorMap = new ColorMapImpl<WindSource>();
chart = new Chart()
.setPersistent(true)
@@ -327,8 +324,8 @@ public class WindChart extends AbstractRaceChart implements Component<WindChartS
if (windSource.getType().useSpeed()) {
speedSeries = getOrCreateSpeedSeries(windSource);
}
Double directionMin = overallDirectionMinMax.getA();
Double directionMax = overallDirectionMinMax.getB();
Point previousDirectionPoint = null;
Point[] directionPoints = new Point[windTrackInfo.windFixes.size()];
Point[] speedPoints = new Point[windTrackInfo.windFixes.size()];
int currentPointIndex = 0;
@@ -350,22 +347,17 @@ public class WindChart extends AbstractRaceChart implements Component<WindChartS
newDirectionPoint.setName(name);
}
newDirectionPoint = WindChartPointRecalculator.recalculateDirectionPoint(directionMin, directionMax, newDirectionPoint);
if (previousDirectionPoint != null) {
newDirectionPoint = ChartPointRecalculator.stayClosestToPreviousPoint(previousDirectionPoint,
newDirectionPoint);
}
directionPoints[currentPointIndex] = newDirectionPoint;
previousDirectionPoint = newDirectionPoint;
double direction = newDirectionPoint.getY().doubleValue();
if (directionMax == null || direction > directionMax) {
directionMax = direction;
}
if (directionMin == null || direction < directionMin) {
directionMin = direction;
}
Point newSpeedPoint = new Point(wind.requestTimepoint, wind.dampenedTrueWindSpeedInKnots);
speedPoints[currentPointIndex++] = newSpeedPoint;
}
}
overallDirectionMinMax = new Pair<Double, Double>(directionMin, directionMax);
Point[] newDirectionPoints;
Point[] newSpeedPoints = null;
@@ -430,7 +422,6 @@ public class WindChart extends AbstractRaceChart implements Component<WindChartS
private void clearCacheAndReload() {
timeOfEarliestRequestInMillis = null;
timeOfLatestRequestInMillis = null;
overallDirectionMinMax = new Pair<Double, Double>(null, null);
windSourceDirectionPoints.clear();
windSourceSpeedPoints.clear();
@@ -1,35 +0,0 @@
package com.sap.sailing.gwt.ui.client.shared.charts;
import org.moxieapps.gwt.highcharts.client.Point;
public final class WindChartPointRecalculator {
private WindChartPointRecalculator() { }
public static Point recalculateDirectionPoint(Double yMin, Double yMax, Point directionPoint) {
double y = directionPoint.getY().doubleValue();
if (yMax != null && yMin != null && (y < yMin || y > yMax)) {
double deltaMin = Math.abs(yMin - y);
double deltaMax = Math.abs(yMax - y);
double yDown = y - 360;
double deltaMinDown = Math.abs(yMin - yDown);
double yUp = y + 360;
double deltaMaxUp = Math.abs(yMax - yUp);
if (isRecalculationNeeded(deltaMin, deltaMax, deltaMinDown, deltaMaxUp)) {
y = deltaMaxUp <= deltaMinDown ? yUp : yDown;
return new Point(directionPoint.getX(), y);
}
}
return directionPoint;
}
private static boolean isRecalculationNeeded(double deltaMin, double deltaMax, double deltaMinDown, double deltaMaxUp) {
return (deltaMinDown < deltaMin || deltaMinDown < deltaMax) || (deltaMaxUp < deltaMin || deltaMaxUp < deltaMax);
}
}
@@ -30,7 +30,8 @@ public abstract class ExpandedListEditorUi<ValueType> extends ListEditorUi<Value
@Override
public Widget initWidget() {
expandedValuesGrid = new Grid(0, 2);
expandedValuesGrid.ensureDebugId("ExpandedValuesGrid");
VerticalPanel panel = new VerticalPanel();
panel.add(createAddWidget());
panel.add(expandedValuesGrid);
@@ -55,6 +56,7 @@ public abstract class ExpandedListEditorUi<ValueType> extends ListEditorUi<Value
if (canRemoveItems) {
PushButton removeButton = new PushButton(new Image(removeImage));
removeButton.ensureDebugId("RemoveButton");
removeButton.setTitle(stringMessages.remove());
removeButton.addClickHandler(new ClickHandler() {
@@ -66,7 +68,6 @@ public abstract class ExpandedListEditorUi<ValueType> extends ListEditorUi<Value
});
expandedValuesGrid.setWidget(rowIndex, 1, removeButton);
}
expandedValuesGrid.setWidget(rowIndex, 0, createValueWidget(rowIndex, newValue));
}
@@ -105,6 +105,7 @@ public class StringListInlineEditorComposite extends StringListEditorComposite {
@Override
protected Widget createValueWidget(final int rowIndex, String newValue) {
final TextBox textBox = new TextBox();
textBox.ensureDebugId("ValueTextBox");
textBox.setValue(newValue);
textBox.addKeyUpHandler(new KeyUpHandler() {
@@ -11,6 +11,7 @@ import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel;
import com.sap.sailing.gwt.ui.client.DebugIdHelper;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.shared.components.Component;
import com.sap.sailing.gwt.ui.client.shared.components.SettingsDialog;
@@ -20,8 +21,8 @@ import com.sap.sse.gwt.client.player.Timer;
/**
* A base class for a leaderboard viewer.
*
* @author Frank Mittag (c163874)
*
*/
public abstract class AbstractLeaderboardViewer extends SimplePanel {
protected final StringMessages stringMessages;
@@ -49,69 +50,62 @@ public abstract class AbstractLeaderboardViewer extends SimplePanel {
protected FlowPanel createViewerPanel() {
FlowPanel mainPanel = new FlowPanel();
mainPanel.setSize("100%", "100%");
getElement().getStyle().setMarginLeft(12, Unit.PX);
getElement().getStyle().setMarginRight(12, Unit.PX);
if(!hideToolbar) {
if (!hideToolbar) {
componentsNavigationPanel = new FlowPanel();
componentsNavigationPanel.addStyleName(STYLE_VIEWER_TOOLBAR);
mainPanel.add(componentsNavigationPanel);
}
return mainPanel;
}
protected <SettingsType> void addComponentToNavigationMenu(final Component<SettingsType> component, boolean isCheckboxEnabled,
String componentDisplayName, final boolean hasSettingsWhenComponentIsInvisible) {
if(hideToolbar) {
return;
}
final String componentName = componentDisplayName != null ? componentDisplayName : component.getLocalizedShortName();
final CheckBox checkBox= new CheckBox(componentName);
final Button settingsButton = new Button("");
checkBox.getElement().getStyle().setFloat(Style.Float.LEFT);
checkBox.setEnabled(isCheckboxEnabled);
checkBox.setValue(component.isVisible());
checkBox.setTitle(stringMessages.showHideComponent(componentName));
checkBox.addStyleName(STYLE_VIEWER_TOOLBAR_INNERELEMENT);
checkBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
@Override
public void onValueChange(ValueChangeEvent<Boolean> newValue) {
boolean visible = checkBox.getValue();
component.setVisible(visible);
if (visible && component instanceof TimeListener) {
// trigger the component to update its data
((TimeListener) component).timeChanged(timer.getTime(), null);
}
if(component.hasSettings() && !hasSettingsWhenComponentIsInvisible) {
settingsButton.setEnabled(visible);
}
}
});
componentsNavigationPanel.add(checkBox);
if(component.hasSettings()) {
settingsButton.addClickHandler(new ClickHandler() {
if (!hideToolbar) {
final String componentName = componentDisplayName != null ? componentDisplayName : component.getLocalizedShortName();
final String debugIdPrefix = DebugIdHelper.createDebugId(componentName);
final CheckBox checkBox = new CheckBox(componentName);
checkBox.ensureDebugId(debugIdPrefix + "DisplayCheckBox");
final Button settingsButton = new Button("");
settingsButton.ensureDebugId(debugIdPrefix + "SettingsButton");
checkBox.getElement().getStyle().setFloat(Style.Float.LEFT);
checkBox.setEnabled(isCheckboxEnabled);
checkBox.setValue(component.isVisible());
checkBox.setTitle(stringMessages.showHideComponent(componentName));
checkBox.addStyleName(STYLE_VIEWER_TOOLBAR_INNERELEMENT);
checkBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
@Override
public void onClick(ClickEvent event) {
new SettingsDialog<SettingsType>(component, stringMessages).show();
}
public void onValueChange(ValueChangeEvent<Boolean> newValue) {
boolean visible = checkBox.getValue();
component.setVisible(visible);
if (visible && component instanceof TimeListener) {
// trigger the component to update its data
((TimeListener) component).timeChanged(timer.getTime(), null);
}
if (component.hasSettings() && !hasSettingsWhenComponentIsInvisible) {
settingsButton.setEnabled(visible);
}
}
});
}
settingsButton.setEnabled(component.hasSettings() && hasSettingsWhenComponentIsInvisible);
settingsButton.addStyleName(STYLE_VIEWER_TOOLBAR_SETTINGS_BUTTON);
settingsButton.getElement().getStyle().setFloat(Style.Float.LEFT);
settingsButton.setTitle(stringMessages.settingsForComponent(componentName));
componentsNavigationPanel.add(settingsButton);
componentsNavigationPanel.add(checkBox);
if (component.hasSettings()) {
settingsButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
SettingsDialog<SettingsType> dialog = new SettingsDialog<SettingsType>(component,
stringMessages);
dialog.ensureDebugId(debugIdPrefix + "SettingsDialog");
dialog.show();
}
});
}
settingsButton.setEnabled(component.hasSettings() && hasSettingsWhenComponentIsInvisible);
settingsButton.addStyleName(STYLE_VIEWER_TOOLBAR_SETTINGS_BUTTON);
settingsButton.getElement().getStyle().setFloat(Style.Float.LEFT);
settingsButton.setTitle(stringMessages.settingsForComponent(componentName));
componentsNavigationPanel.add(settingsButton);
}
}
}
@@ -33,6 +33,7 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.URLEncoder;
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings.RaceColumnSelectionStrategies;
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.player.Timer.PlayModes;
@@ -95,23 +96,24 @@ public class LeaderboardEntryPoint extends AbstractEntryPoint {
leaderboardGroupName = Window.Location.getParameter(PARAM_LEADERBOARD_GROUP_NAME);
if (leaderboardName != null) {
sailingService.checkLeaderboardName(leaderboardName, new AsyncCallback<Pair<String, LeaderboardType>>() {
@Override
public void onSuccess(Pair<String, LeaderboardType> leaderboardNameAndType) {
if (leaderboardNameAndType != null && leaderboardName.equals(leaderboardNameAndType.getA())) {
Window.setTitle(leaderboardName);
leaderboardType = leaderboardNameAndType.getB();
createUI(showRaceDetails, embedded, hideToolbar);
} 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());
}
});
sailingService.checkLeaderboardName(leaderboardName, new MarkedAsyncCallback<Pair<String, LeaderboardType>>(
new AsyncCallback<Pair<String, LeaderboardType>>() {
@Override
public void onSuccess(Pair<String, LeaderboardType> leaderboardNameAndType) {
if (leaderboardNameAndType != null && leaderboardName.equals(leaderboardNameAndType.getA())) {
Window.setTitle(leaderboardName);
leaderboardType = leaderboardNameAndType.getB();
createUI(showRaceDetails, embedded, hideToolbar);
} 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());
}
}));
} else {
RootPanel.get().add(new Label(stringMessages.noSuchLeaderboard()));
}
@@ -86,6 +86,7 @@ import com.sap.sailing.gwt.ui.leaderboard.DetailTypeColumn.LegDetailField;
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings.RaceColumnSelectionStrategies;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
import com.sap.sse.gwt.client.controls.busyindicator.BusyIndicator;
import com.sap.sse.gwt.client.controls.busyindicator.SimpleBusyIndicator;
import com.sap.sse.gwt.client.player.PlayStateListener;
@@ -790,20 +791,21 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS
getSailingService().getLeaderboardByName(getLeaderboardName(),
timer.getPlayMode() == PlayModes.Live ? null : getLeaderboardDisplayDate(),
/* namesOfRacesForWhichToLoadLegDetails */getNamesOfExpandedRaces(),
previousLeaderboard.getId(), new AsyncCallback<IncrementalOrFullLeaderboardDTO>() {
@Override
public void onSuccess(IncrementalOrFullLeaderboardDTO result) {
updateLeaderboard(result.getLeaderboardDTO(previousLeaderboard));
callWhenExpansionDataIsLoaded.run();
}
@Override
public void onFailure(Throwable caught) {
getErrorReporter().reportError(
stringMessages.errorTryingToObtainLeaderboardContents(caught.getMessage()),
true /* silentMode */);
}
});
previousLeaderboard.getId(), new MarkedAsyncCallback<IncrementalOrFullLeaderboardDTO>(
new AsyncCallback<IncrementalOrFullLeaderboardDTO>() {
@Override
public void onSuccess(IncrementalOrFullLeaderboardDTO result) {
updateLeaderboard(result.getLeaderboardDTO(previousLeaderboard));
callWhenExpansionDataIsLoaded.run();
}
@Override
public void onFailure(Throwable caught) {
getErrorReporter().reportError(
stringMessages.errorTryingToObtainLeaderboardContents(caught.getMessage()),
true /* silentMode */);
}
}));
}
}
@@ -1365,7 +1367,8 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS
String leaderboardName, ErrorReporter errorReporter, final StringMessages stringMessages,
final UserAgentDetails userAgent, boolean showRaceDetails) {
this(sailingService, asyncActionsExecutor, settings, preSelectedRace, competitorSelectionProvider, new Timer(
PlayModes.Replay, /* delayBetweenAutoAdvancesInMilliseconds */3000l), leaderboardGroupName,
// perform the first request as "live" but don't by default auto-play
PlayModes.Live, PlayStates.Paused, /* delayBetweenAutoAdvancesInMilliseconds */3000l), leaderboardGroupName,
leaderboardName, errorReporter, stringMessages, userAgent, showRaceDetails,
/* optionalRaceTimesInfoProvider */ null, /* autoExpandLastRaceColumn */ false, /* adjustTimerDelay */ true);
}
@@ -1435,7 +1438,7 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS
TOTAL_COLUMN_STYLE = tableResources.cellTableStyle().cellTableTotalColumn();
leaderboardTable = new SortedCellTableWithStylableHeaders<LeaderboardRowDTO>(
/* pageSize */10000, tableResources);
leaderboardTable.ensureDebugId("LeaderboardTable");
leaderboardTable.ensureDebugId("LeaderboardCellTable");
getLeaderboardTable().setWidth("100%");
leaderboardSelectionModel = new MultiSelectionModel<LeaderboardRowDTO>();
leaderboardSelectionModel.addSelectionChangeHandler(new Handler() {
@@ -1470,7 +1473,7 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS
// the information panel
informationPanel = new FlowPanel();
informationPanel.setStyleName(STYLE_LEADERBOARD_INFO);
informationPanel.setStyleName(STYLE_LEADERBOARD_INFO);
scoreCorrectionLastUpdateTimeLabel = new Label("");
scoreCorrectionCommentLabel = new Label("");
informationPanel.add(scoreCorrectionCommentLabel);
@@ -1485,8 +1488,10 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS
// the toolbar panel
DockPanel toolbarPanel = new DockPanel();
toolbarPanel.setStyleName(STYLE_LEADERBOARD_TOOLBAR);
toolbarPanel.ensureDebugId("ToolbarPanel");
toolbarPanel.setStyleName(STYLE_LEADERBOARD_TOOLBAR);
busyIndicator = new SimpleBusyIndicator(false, 0.8f);
busyIndicator.ensureDebugId("BusyIndicator");
if (!isEmbedded) {
toolbarPanel.add(informationPanel, DockPanel.WEST);
toolbarPanel.add(busyIndicator, DockPanel.WEST);
@@ -1507,12 +1512,14 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS
pauseIcon = resources.autoRefreshEnabledIcon();
playIcon = resources.autoRefreshDisabledIcon();
refreshAndSettingsPanel = new HorizontalPanel();
refreshAndSettingsPanel.ensureDebugId("RefreshAndSettingsPanel");
refreshAndSettingsPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
FlowPanel refreshPanel = new FlowPanel();
refreshPanel.addStyleName("refreshPanel");
toolbarPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
toolbarPanel.addStyleName("refreshAndSettings");
playPause = new Anchor(getPlayPauseImgHtml(timer.getPlayState()));
playPause.ensureDebugId("PlayAndPauseAnchor");
playPause.addClickHandler(playPauseHandler);
playStateChanged(timer.getPlayState(), timer.getPlayMode());
refreshPanel.add(playPause);
@@ -1750,7 +1757,7 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS
getLeaderboardName(), timer.getPlayMode() == PlayModes.Live ? null : date,
/* namesOfRacesForWhichToLoadLegDetails */getNamesOfExpandedRaces(),
/* previousLeaderboard */ getLeaderboard(), timer, errorReporter, stringMessages);
asyncActionsExecutor.execute(getLeaderboardByNameAction, LOAD_LEADERBOARD_DATA_CATEGORY,
this.asyncActionsExecutor.execute(getLeaderboardByNameAction, LOAD_LEADERBOARD_DATA_CATEGORY,
new AsyncCallback<LeaderboardDTO>() {
@Override
public void onSuccess(LeaderboardDTO result) {
@@ -22,6 +22,7 @@ import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.domain.common.DetailType;
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.gwt.ui.client.DebugIdHelper;
import com.sap.sailing.gwt.ui.client.DetailTypeFormatter;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.shared.components.SettingsDialogComponent;
@@ -90,19 +91,19 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
dialogPanel.add(createTimingDetailsPanel(dialog));
return dialogPanel;
}
private FlowPanel createManeuverDetailsPanel(DataEntryDialog<?> dialog) {
FlowPanel meneuverPanel = new FlowPanel();
meneuverPanel.ensureDebugId("ManeuverSettingsPanel");
meneuverPanel.add(dialog.createHeadline(stringMessages.maneuverTypes(), true));
meneuverPanel.addStyleName("SettingsDialogComponent");
FlowPanel meneuverContent = new FlowPanel();
meneuverContent.addStyleName("dialogInnerContent");
List<DetailType> 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);
CheckBox checkbox = createAndRegisterCheckbox(dialog, detailType,
currentMeneuverDetailSelection.contains(detailType), maneuverDetailCheckboxes);
meneuverContent.add(checkbox);
}
meneuverPanel.add(meneuverContent);
@@ -111,7 +112,9 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
private FlowPanel createTimingDetailsPanel(DataEntryDialog<?> dialog) {
FlowPanel timingPanel = new FlowPanel();
timingPanel.ensureDebugId("TimingSettingsPanel");
refreshIntervalInSecondsBox = dialog.createLongBox(delayBetweenAutoAdvancesInMilliseconds / 1000l, 4);
refreshIntervalInSecondsBox.ensureDebugId("RefreshIntervalLongBox");
timingPanel.add(dialog.createHeadline(stringMessages.timing(), true));
timingPanel.addStyleName("SettingsDialogComponent");
@@ -132,6 +135,7 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
private FlowPanel createRaceDetailPanel(DataEntryDialog<?> dialog) {
FlowPanel raceDetailDialog = new FlowPanel();
raceDetailDialog.ensureDebugId("RaceDetailsSettingsPanel");
raceDetailDialog.add(dialog.createHeadline(stringMessages.raceDetailsToShow(), true));
raceDetailDialog.addStyleName("SettingsDialogComponent");
int detailCountInCurrentFlowPanel = 0;
@@ -143,10 +147,8 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
raceDetailDialogContent.addStyleName("dialogInnerContent");
raceDetailDialog.add(raceDetailDialogContent);
}
CheckBox checkbox = dialog.createCheckbox(DetailTypeFormatter.format(type));
checkbox.setValue(currentRaceDetailSelection.contains(type));
dialog.addTooltip(checkbox, DetailTypeFormatter.getTooltip(type));
raceDetailCheckboxes.put(type, checkbox);
CheckBox checkbox = createAndRegisterCheckbox(dialog, type, currentRaceDetailSelection.contains(type),
raceDetailCheckboxes);
raceDetailDialogContent.add(checkbox);
detailCountInCurrentFlowPanel++;
}
@@ -163,16 +165,15 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
private FlowPanel createOverallDetailPanel(DataEntryDialog<?> dialog) {
FlowPanel overallDetailDialog = new FlowPanel();
overallDetailDialog.ensureDebugId("OverallDetailsSettingsPanel");
overallDetailDialog.add(dialog.createHeadline(stringMessages.overallDetailsToShow(), true));
overallDetailDialog.addStyleName("SettingsDialogComponent overallDetailSettings");
FlowPanel overallDetailDialogContent = new FlowPanel();
overallDetailDialogContent.addStyleName("dialogInnerContent");
List<DetailType> 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);
CheckBox checkbox = createAndRegisterCheckbox(dialog, type, currentOverallDetailSelection.contains(type),
overallDetailCheckboxes);
overallDetailDialogContent.add(checkbox);
}
overallDetailDialog.add(overallDetailDialogContent);
@@ -181,6 +182,7 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
private FlowPanel createLegDetailsPanel(DataEntryDialog<?> dialog) {
FlowPanel legDetailsToShow = new FlowPanel();
legDetailsToShow.ensureDebugId("LegDetailsSettingsPanel");
legDetailsToShow.add(dialog.createHeadline(stringMessages.legDetailsToShow(), true));
legDetailsToShow.addStyleName("SettingsDialogComponent");
FlowPanel legDetailsContent = null;
@@ -192,10 +194,8 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
legDetailsContent.addStyleName("dialogInnerContent");
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);
CheckBox checkbox = createAndRegisterCheckbox(dialog, type, currentLegDetailSelection.contains(type),
legDetailCheckboxes);
legDetailsContent.add(checkbox);
detailCountInCurrentFlowPanel++;
}
@@ -204,6 +204,7 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
private FlowPanel createSelectedRacesPanel(DataEntryDialog<?> dialog) {
FlowPanel selectedRacesPanel = new FlowPanel();
selectedRacesPanel.ensureDebugId("RaceSelectionSettingsPanel");
selectedRacesPanel.addStyleName("SettingsDialogComponent");
selectedRacesPanel.add(dialog.createHeadline(stringMessages.selectedRaces(), true));
// race selection strategy elements
@@ -218,12 +219,16 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
int racesCount = raceAllRaceColumns.size();
if (racesCount > 0) {
final FlowPanel explicitRaceSelectionContent = new FlowPanel();
explicitRaceSelectionContent.ensureDebugId("ExplicitRaceSelectionPanel");
final FlowPanel lastNRacesSelectionContent = new FlowPanel();
lastNRacesSelectionContent.ensureDebugId("MostCurrentRacesSelectionPanel");
String radioButtonGroupName = "raceSelectionStrategyGroup";
Label raceSelectionWayLabel = new Label(stringMessages.chooseTheWayYouSelectRaces() + ":");
raceSelectionWayLabel.getElement().getStyle().setPaddingRight(5, Unit.PX);
racesSelectionStrategyPanel.add(raceSelectionWayLabel);
explicitRaceColumnSelectionRadioBtn = dialog.createRadioButton(radioButtonGroupName, stringMessages.selectFromAllRaces());
explicitRaceColumnSelectionRadioBtn.ensureDebugId("ExplicitRaceSelectionRadioButton");
racesSelectionStrategyPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
explicitRaceColumnSelectionRadioBtn.setValue(activeRaceColumnSelectionStrategy == RaceColumnSelectionStrategies.EXPLICIT);
explicitRaceColumnSelectionRadioBtn.addClickHandler(new ClickHandler() {
@@ -246,8 +251,8 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
}
Grid grid = new Grid(rowCount, maxRacesPerRow);
for (RaceColumnDTO expandableSortableColumn : raceAllRaceColumns) {
CheckBox checkbox = dialog.createCheckbox(expandableSortableColumn.getRaceColumnName());
checkbox.setValue(Util.contains(raceColumnSelection, expandableSortableColumn));
CheckBox checkbox = createCheckbox(dialog, expandableSortableColumn.getRaceColumnName(),
Util.contains(raceColumnSelection, expandableSortableColumn), null);
raceColumnCheckboxes.put(expandableSortableColumn, checkbox);
grid.setWidget(rowIndex, columnIndex++, checkbox);
if(columnIndex == maxRacesPerRow) {
@@ -260,6 +265,7 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
selectedRacesContent.add(explicitRaceSelectionContent);
lastNRacesColumnSelectionRadioBtn = dialog.createRadioButton(radioButtonGroupName, stringMessages.selectANumberOfRaces());
lastNRacesColumnSelectionRadioBtn.ensureDebugId("MostCurrentRacesSelectionRadioButton");
lastNRacesColumnSelectionRadioBtn.setValue(activeRaceColumnSelectionStrategy == RaceColumnSelectionStrategies.LAST_N);
lastNRacesColumnSelectionRadioBtn.addClickHandler(new ClickHandler() {
@Override
@@ -279,6 +285,7 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
numberOfLastRacesLabel.getElement().getStyle().setPaddingRight(10, Unit.PX);
hPanel.add(numberOfLastRacesLabel);
numberOfLastRacesToShowBox = dialog.createIntegerBox(numberOfLastRacesToShow != null ? numberOfLastRacesToShow : racesCount, 3);
numberOfLastRacesToShowBox.ensureDebugId("NumberOfMostCurrentRacesIntegerBox");
hPanel.add(numberOfLastRacesToShowBox);
dialog.alignAllPanelWidgetsVertically(hPanel, HasVerticalAlignment.ALIGN_MIDDLE);
lastNRacesSelectionContent.setVisible(activeRaceColumnSelectionStrategy == RaceColumnSelectionStrategies.LAST_N);
@@ -288,6 +295,28 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
}
return selectedRacesPanel;
}
private CheckBox createAndRegisterCheckbox(DataEntryDialog<?> dialog, DetailType detailType, boolean selected,
Map<DetailType, CheckBox> registry) {
CheckBox checkbox = createCheckbox(dialog, detailType, selected);
registry.put(detailType, checkbox);
return checkbox;
}
private CheckBox createCheckbox(DataEntryDialog<?> dialog, DetailType detailType, boolean selected) {
CheckBox checkbox = createCheckbox(dialog, DetailTypeFormatter.format(detailType), selected,
DetailTypeFormatter.getTooltip(detailType));
checkbox.ensureDebugId(DebugIdHelper.createDebugId(detailType) + "CheckBox");
return checkbox;
}
private CheckBox createCheckbox(DataEntryDialog<?> dialog, String label, boolean selected, String tooltip) {
CheckBox checkbox = dialog.createCheckbox(label);
checkbox.ensureDebugId(DebugIdHelper.createDebugId(label) + "CheckBox");
checkbox.setValue(selected);
dialog.addTooltip(checkbox, tooltip);
return checkbox;
}
@Override
public LeaderboardSettings getResult() {
@@ -341,16 +370,18 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
return new Validator<LeaderboardSettings>() {
@Override
public String getErrorMessage(LeaderboardSettings valueToValidate) {
final String result;
if (valueToValidate.getLegDetailsToShow().isEmpty()) {
return stringMessages.selectAtLeastOneLegDetail();
result = stringMessages.selectAtLeastOneLegDetail();
} else if (valueToValidate.getDelayBetweenAutoAdvancesInMilliseconds() < 1000) {
return stringMessages.chooseUpdateIntervalOfAtLeastOneSecond();
result = stringMessages.chooseUpdateIntervalOfAtLeastOneSecond();
} else if (valueToValidate.getActiveRaceColumnSelectionStrategy() == RaceColumnSelectionStrategies.LAST_N
&& (numberOfLastRacesToShowBox.getValue() == null || numberOfLastRacesToShowBox.getValue() < 0)) {
return stringMessages.numberOfRacesMustBeNonNegativeNumber();
result = stringMessages.numberOfRacesMustBeNonNegativeNumber();
} else {
return null;
result = null;
}
return result;
}
};
}
@@ -13,8 +13,10 @@ import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.shared.charts.MultiCompetitorLeaderboardChart;
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.player.Timer.PlayModes;
import com.sap.sse.gwt.client.player.Timer.PlayStates;
import com.sap.sse.gwt.client.useragent.UserAgentDetails;
/**
@@ -34,7 +36,8 @@ public class LeaderboardViewer extends AbstractLeaderboardViewer {
final UserAgentDetails userAgent, boolean showRaceDetails, boolean hideToolbar, boolean autoExpandLastRaceColumn,
boolean showCharts, DetailType chartDetailType, boolean showOverallLeaderboard) {
super(new CompetitorSelectionModel(/* hasMultiSelection */true), asyncActionsExecutor,
new Timer(PlayModes.Replay, /*delayBetweenAutoAdvancesInMilliseconds*/ 3000l), stringMessages, hideToolbar);
// perform the first request as live request but don't auto-play
new Timer(PlayModes.Live, PlayStates.Paused, /* delayBetweenAutoAdvancesInMilliseconds */ 3000l), stringMessages, hideToolbar);
final FlowPanel mainPanel = createViewerPanel();
setWidget(mainPanel);
@@ -60,29 +63,29 @@ public class LeaderboardViewer extends AbstractLeaderboardViewer {
if(showCharts) {
multiCompetitorChart.timeChanged(timer.getTime(), null);
}
overallLeaderboardPanel = null;
if(showOverallLeaderboard) {
sailingService.getOverallLeaderboardNamesContaining(leaderboardName, new AsyncCallback<List<String>>() {
@Override
public void onSuccess(List<String> result) {
if(result.size() == 1) {
String overallLeaderboardName = result.get(0);
overallLeaderboardPanel = new LeaderboardPanel(sailingService, asyncActionsExecutor,
leaderboardSettings, preselectedRace, competitorSelectionProvider, timer,
leaderboardGroupName, overallLeaderboardName, errorReporter, stringMessages, userAgent,
false, /* raceTimesInfoProvider */null, false, /* adjustTimerDelay */ true);
mainPanel.add(overallLeaderboardPanel);
addComponentToNavigationMenu(overallLeaderboardPanel, true, stringMessages.seriesLeaderboard(),
/* hasSettingsWhenComponentIsInvisible*/ true);
}
}
@Override
public void onFailure(Throwable caught) {
// DO NOTHING
}
});
sailingService.getOverallLeaderboardNamesContaining(leaderboardName, new MarkedAsyncCallback<List<String>>(
new AsyncCallback<List<String>>() {
@Override
public void onSuccess(List<String> result) {
if(result.size() == 1) {
String overallLeaderboardName = result.get(0);
overallLeaderboardPanel = new LeaderboardPanel(sailingService, asyncActionsExecutor,
leaderboardSettings, preselectedRace, competitorSelectionProvider, timer,
leaderboardGroupName, overallLeaderboardName, errorReporter, stringMessages, userAgent,
false, /* raceTimesInfoProvider */null, false, /* adjustTimerDelay */ true);
mainPanel.add(overallLeaderboardPanel);
addComponentToNavigationMenu(overallLeaderboardPanel, true, stringMessages.seriesLeaderboard(),
/* hasSettingsWhenComponentIsInvisible*/ true);
}
}
@Override
public void onFailure(Throwable caught) {
// DO NOTHING
}
}));
}
}
@@ -13,6 +13,7 @@ import com.sap.sailing.gwt.ui.client.shared.charts.MultiCompetitorLeaderboardCha
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.player.Timer.PlayModes;
import com.sap.sse.gwt.client.player.Timer.PlayStates;
import com.sap.sse.gwt.client.useragent.UserAgentDetails;
/**
@@ -32,34 +33,28 @@ public class MetaLeaderboardViewer extends AbstractLeaderboardViewer {
UserAgentDetails userAgent, boolean showRaceDetails, boolean hideToolbar, boolean autoExpandLastRaceColumn,
boolean showCharts, DetailType chartDetailType, boolean showSeriesLeaderboards) {
super(new CompetitorSelectionModel(/* hasMultiSelection */true), asyncActionsExecutor,
new Timer(PlayModes.Replay, /*delayBetweenAutoAdvancesInMilliseconds*/ 3000l), stringMessages, hideToolbar);
// perform the first request as live request but don't auto-play
new Timer(PlayModes.Live, PlayStates.Paused, /*delayBetweenAutoAdvancesInMilliseconds*/ 3000l), stringMessages, hideToolbar);
FlowPanel mainPanel = createViewerPanel();
setWidget(mainPanel);
final Label overallStandingsLabel = new Label(stringMessages.overallStandings());
overallStandingsLabel.setStyleName("leaderboardHeading");
metaLeaderboardPanel = new LeaderboardPanel(sailingService, asyncActionsExecutor,
leaderboardSettings, preselectedRace, competitorSelectionProvider, timer,
leaderboardGroupName, metaLeaderboardName, errorReporter, stringMessages, userAgent,
showRaceDetails, /* raceTimesInfoProvider */null, autoExpandLastRaceColumn, /* adjustTimerDelay */ true);
multiCompetitorChart = new MultiCompetitorLeaderboardChart(sailingService, asyncActionsExecutor, metaLeaderboardName,
chartDetailType, competitorSelectionProvider, timer, stringMessages, errorReporter);
multiCompetitorChart.setVisible(showCharts);
multiCompetitorChart.getElement().getStyle().setMarginTop(10, Unit.PX);
multiCompetitorChart.getElement().getStyle().setMarginBottom(10, Unit.PX);
multiLeaderboardPanel = new MultiLeaderboardPanel(sailingService, metaLeaderboardName, asyncActionsExecutor, timer,
preselectedLeaderboardName, preselectedRace, errorReporter, stringMessages,
userAgent, showRaceDetails, autoExpandLastRaceColumn);
multiLeaderboardPanel.setVisible(showSeriesLeaderboards);
mainPanel.add(metaLeaderboardPanel);
mainPanel.add(multiCompetitorChart);
mainPanel.add(multiLeaderboardPanel);
addComponentToNavigationMenu(metaLeaderboardPanel, false, stringMessages.seriesLeaderboard(), /* hasSettingsWhenComponentIsInvisible*/ true);
addComponentToNavigationMenu(multiCompetitorChart, true, null, /* hasSettingsWhenComponentIsInvisible*/ true);
addComponentToNavigationMenu(multiLeaderboardPanel, true , stringMessages.regattaLeaderboards(), /* hasSettingsWhenComponentIsInvisible*/ false);
@@ -8,7 +8,6 @@ import java.util.Map;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.Style.VerticalAlign;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
@@ -39,12 +38,12 @@ import com.sap.sailing.gwt.ui.client.RaceTimesInfoProvider;
import com.sap.sailing.gwt.ui.client.RegattaDisplayer;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.media.MediaSelector;
import com.sap.sailing.gwt.ui.client.shared.charts.MultiCompetitorRaceChart;
import com.sap.sailing.gwt.ui.client.shared.charts.WindChart;
import com.sap.sailing.gwt.ui.client.shared.charts.WindChartSettings;
import com.sap.sailing.gwt.ui.client.shared.components.Component;
import com.sap.sailing.gwt.ui.client.shared.components.ComponentViewer;
import com.sap.sailing.gwt.ui.client.media.MediaSelector;
import com.sap.sailing.gwt.ui.client.shared.components.SettingsDialog;
import com.sap.sailing.gwt.ui.client.shared.filter.CompetitorRaceRankFilter;
import com.sap.sailing.gwt.ui.client.shared.filter.CompetitorSelectionProviderFilterContext;
@@ -175,7 +174,6 @@ public class RaceBoardPanel extends SimplePanel implements RegattaDisplayer, Rac
// add busy indicator to toolbar panel because the embedded leaderboard has no space for it
toolbarPanel.add(leaderboardPanel.getBusyIndicator());
leaderboardPanel.getBusyIndicator().getElement().getStyle().setVerticalAlign(VerticalAlign.MIDDLE);
CompetitorsFilterSets loadedCompetitorsFilterSets = loadCompetitorsFilterSets();
if (loadedCompetitorsFilterSets != null) {
@@ -199,7 +199,7 @@ public class SimulatorServiceImpl extends RemoteServiceServlet implements Simula
throw new WindPatternNotFoundException("Please select a valid wind pattern.");
}
Position[][] grid = bd.extractGrid(params.getxRes(), params.getyRes());
Position[][] grid = bd.extractGrid(params.getxRes(), params.getyRes(), params.getBorderY(), params.getBorderX());
wf.setPositionGrid(grid);
TimePoint startTime = new MillisecondsTimePoint(params.getStartTime().getTime());// new
@@ -217,7 +217,8 @@ public class SimulatorServiceImpl extends RemoteServiceServlet implements Simula
wf.setGridAreaGps(gridAreaGps);
}
WindFieldDTO wfDTO = createWindFieldDTO(wf, startTime, endTime, timeStep, params.isShowLines(), params.getSeedLines());
WindFieldDTO wfDTO = createWindFieldDTO(wf, startTime, endTime, timeStep, params); //params.isShowStreamlets2(), params.isShowLines(), params.getSeedLines());
LOGGER.info("Exiting getWindField");
return wfDTO;
@@ -273,9 +274,11 @@ public class SimulatorServiceImpl extends RemoteServiceServlet implements Simula
wf.setGridAreaGps(gridAreaGps);
}
int[] gridRes = new int[2];
int[] gridRes = new int[4];
gridRes[0] = params.getxRes();
gridRes[1] = params.getyRes();
gridRes[2] = params.getBorderY();
gridRes[3] = params.getBorderX();
wf.setGridResolution(gridRes);
wf.generate(startTime, null, timeStep);
@@ -299,7 +302,7 @@ public class SimulatorServiceImpl extends RemoteServiceServlet implements Simula
WindFieldDTO windFieldDTO = null;
if (pattern != null) {
windFieldDTO = this.createWindFieldDTO(wf, startTime, endTime, timeStep, params.isShowLines(), params.getSeedLines());
windFieldDTO = this.createWindFieldDTO(wf, startTime, endTime, timeStep, params); // params.isShowStreamlets2(), params.isShowLines(), params.getSeedLines());
}
return new SimulatorResultsDTO(rcDTO, pathDTOs, windFieldDTO, simulatedPaths.notificationMessage);
@@ -721,40 +724,115 @@ public class SimulatorServiceImpl extends RemoteServiceServlet implements Simula
return result;
}
private WindFieldDTO createWindFieldDTO(WindFieldGenerator wf, TimePoint startTime, TimePoint endTime, TimePoint timeStep, boolean isShowLines,
char seedLines) {
private WindFieldDTO createWindFieldDTO(WindFieldGenerator wf, TimePoint startTime, TimePoint endTime, TimePoint timeStep, WindFieldGenParamsDTO params) {
//boolean isStreamlets, boolean isShowLines, char seedLines) {
WindFieldDTO windFieldDTO = new WindFieldDTO();
List<SimulatorWindDTO> wList = new ArrayList<SimulatorWindDTO>();
Position[][] positionGrid = wf.getPositionGrid();
//if (!params.isShowStreamlets2()) {
List<SimulatorWindDTO> wList = new ArrayList<SimulatorWindDTO>();
if (positionGrid != null && positionGrid.length > 0) {
TimePoint t = startTime;
while (t.compareTo(endTime) <= 0) {
for (int i = 0; i < positionGrid.length; ++i) {
for (int j = 0; j < positionGrid[i].length; ++j) {
Wind localWind = wf.getWind(new TimedPositionWithSpeedImpl(t, positionGrid[i][j], null));
LOGGER.finer(localWind.toString());
wList.add(createSimulatorWindDTO(localWind));
}
}
t = new MillisecondsTimePoint(t.asMillis() + timeStep.asMillis());
}
TimePoint t = startTime;
while (t.compareTo(endTime) <= 0) {
for (int i = 0; i < positionGrid.length; ++i) {
for (int j = 0; j < positionGrid[i].length; ++j) {
Wind localWind = wf.getWind(new TimedPositionWithSpeedImpl(t, positionGrid[i][j], null));
LOGGER.finer(localWind.toString());
wList.add(createSimulatorWindDTO(localWind));
}
}
t = new MillisecondsTimePoint(t.asMillis() + timeStep.asMillis());
}
}
windFieldDTO.setMatrix(wList);
if (isShowLines && seedLines == 'f') {
this.getWindLinesFromStartLine(wf, windFieldDTO, startTime, endTime, timeStep);
if (params.isShowLines() && params.getSeedLines() == 'f') {
this.getWindLinesFromStartLine(wf, windFieldDTO, startTime, endTime, timeStep);
}
if (isShowLines && seedLines == 'b') {
this.getWindLinesFromEndLine(wf, windFieldDTO, startTime, endTime, timeStep);
if (params.isShowLines() && params.getSeedLines() == 'b') {
this.getWindLinesFromEndLine(wf, windFieldDTO, startTime, endTime, timeStep);
}
windFieldDTO.curBearing = wf.getWindParameters().curBearing;
windFieldDTO.curSpeed = wf.getWindParameters().curSpeed;
//} else {
if (params.isShowStreamlets2()) {
// generate JSON-vectorfield
String jsonField = "$wnd.windFieldSim={";
//this.rcStart = field.rcStart;
jsonField += "rcStart:{lat:" + params.getNorthWest().latDeg + ",lng:" + params.getNorthWest().lngDeg + "},";
//this.rcEnd = field.rcEnd;
jsonField += "rcEnd:{lat:" + params.getSouthEast().latDeg + ",lng:" + params.getSouthEast().lngDeg + "},";
// SouthWest
jsonField += "boundsSW:{lat:" + positionGrid[0][0].getLatDeg() + ",lng:" + positionGrid[0][0].getLngDeg() + "},";
// NorthEast
jsonField += "boundsNE:{lat:" + positionGrid[params.getyRes()+2*params.getBorderY()-1][params.getxRes()+2*params.getBorderX()-1].getLatDeg() + ",lng:" + positionGrid[params.getyRes()+2*params.getBorderY()-1][params.getxRes()+2*params.getBorderX()-1].getLngDeg() + "},";
//this.resY = field.resY;
jsonField += "resY:" + params.getyRes() + ",";
//this.resX = field.resX;
jsonField += "resX:" + params.getxRes() + ",";
// border
jsonField += "borderY:" + params.getBorderY() + ",";
jsonField += "borderX:" + params.getBorderX() + ",";
//this.xScale = field.xScale;
jsonField += "xScale:1.5,";
/*String jsonField2 = "data:[";
DecimalFormat df = new DecimalFormat("#.00");
double maxWindSpeed = 0;
//List<SimulatorWindDTO> windMat = wfDTO.getMatrix();
if (positionGrid != null && positionGrid.length > 0) {
TimePoint t = startTime;
while (t.compareTo(endTime) <= 0) {
jsonField2 += "[";
for (int i = 0; i < positionGrid.length; ++i) {
jsonField2 += "[";
for (int j = 0; j < positionGrid[i].length; ++j) {
Wind localWind = wf.getWind(new TimedPositionWithSpeedImpl(t, positionGrid[i][j], null));
if (localWind.getKnots() > maxWindSpeed) {
maxWindSpeed = localWind.getKnots();
}
double windY = localWind.getKnots() * Math.cos(localWind.getBearing().getRadians());
double windX = localWind.getKnots() * Math.sin(localWind.getBearing().getRadians());
jsonField2 += df.format(windX) + "," + df.format(windY);
if (j<(params.getxRes()-1)) {
jsonField2 += ",";
}
}
if (i<(params.getyRes()-1)) {
jsonField2 += "],";
} else {
jsonField2 += "]";
}
}
t = new MillisecondsTimePoint(t.asMillis() + timeStep.asMillis());
if (t.compareTo(endTime) <= 0) {
jsonField2 += "],";
} else {
jsonField2 += "]";
}
}
}
jsonField += "maxLength:" + maxWindSpeed + "," + jsonField2;
jsonField += "]";
// finalize JSON Field
jsonField += "};";*/
//LOGGER.info("JSON Field:\n" + jsonField);
windFieldDTO.windDataJSON = jsonField;
// windFieldDTO.setMatrix(null);
}
return windFieldDTO;
}
@@ -9,6 +9,8 @@ public class WindFieldDTO implements IsSerializable {
public double curSpeed;
public double curBearing;
public String windDataJSON;
private List<SimulatorWindDTO> matrix;
private WindLinesDTO windLinesDTO;
@@ -12,6 +12,8 @@ public class WindFieldGenParamsDTO implements IsSerializable {
private int xRes;
private int yRes;
private int borderY;
private int borderX;
private Date startTime;
private Date endTime;
@@ -35,6 +37,7 @@ public class WindFieldGenParamsDTO implements IsSerializable {
private boolean showGrid;
private boolean showStreamlets;
private boolean showStreamlets2;
private boolean showLines;
@@ -79,6 +82,19 @@ public class WindFieldGenParamsDTO implements IsSerializable {
this.yRes = yRes;
}
public int getBorderY() {
return borderY;
}
public int getBorderX() {
return borderX;
}
public void setBorder(int border) {
this.borderY = border;
this.borderX = (int)Math.round(border * ((double)xRes) / ((double)yRes));
}
public Date getStartTime() {
return startTime;
}
@@ -149,6 +165,14 @@ public class WindFieldGenParamsDTO implements IsSerializable {
this.showStreamlets = showStreamlets;
}
public boolean isShowStreamlets2() {
return showStreamlets2;
}
public void setShowStreamlets2(boolean showStreamlets2) {
this.showStreamlets2 = showStreamlets2;
}
public boolean isShowLines() {
return showLines;
}
@@ -34,6 +34,18 @@ public class GoogleMapStyleHelper {
return result;
}
public static MapTypeStyle createElementStyleOnlyLightness(MapTypeStyleFeatureType featureType, MapTypeStyleElementType elementType, int ligthness) {
MapTypeStyle result = MapTypeStyle.newInstance();
result.setFeatureType(featureType);
result.setElementType(elementType);
MapTypeStyler[] typeStylers = new MapTypeStyler[1];
typeStylers[0] = MapTypeStyler.newLightnessStyler(ligthness);
result.setStylers(typeStylers);
return result;
}
public static MapTypeStyle createElementStyleWithVisibility(MapTypeStyleFeatureType featureType, MapTypeStyleElementType elementType, String visibility) {
MapTypeStyle result = MapTypeStyle.newInstance();
@@ -9,10 +9,14 @@ import com.google.gwt.maps.client.base.Point;
import com.google.gwt.maps.client.events.click.ClickMapEvent;
import com.google.gwt.maps.client.events.click.ClickMapHandler;
import com.google.gwt.maps.client.mvc.MVCArray;
import com.google.gwt.maps.client.overlays.MapCanvasProjection;
import com.google.gwt.maps.client.overlays.Marker;
import com.google.gwt.maps.client.overlays.MarkerOptions;
import com.google.gwt.maps.client.overlays.OverlayView;
import com.google.gwt.maps.client.overlays.Polyline;
import com.google.gwt.maps.client.overlays.PolylineOptions;
import com.google.gwt.maps.client.overlays.overlayhandlers.OverlayViewMethods;
import com.google.gwt.maps.client.overlays.overlayhandlers.OverlayViewOnDrawHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sailing.domain.common.Bearing;
import com.sap.sailing.domain.common.Position;
@@ -66,6 +70,8 @@ public class PathPolyline {
private List<SimulatorWindDTO> allPoints = null;
private SimulatorServiceAsync simulatorService = null;
private MapWidget map = null;
protected OverlayView mapView;
protected MapCanvasProjection mapProjection;
private ErrorReporter errorReporter = null;
private boolean warningAlreadyShown = false;
private SimulatorMap simulatorMap = null;
@@ -114,6 +120,12 @@ public class PathPolyline {
this.allPoints = pathPoints;
this.simulatorService = simulatorService;
this.map = map;
this.mapView = OverlayView.newInstance(map, new OverlayViewOnDrawHandler() {
@Override
public void onDraw(OverlayViewMethods methods) {
mapProjection = methods.getProjection();
}
}, null, null);
this.selectedBoatClassIndex = selection.boatClassIndex;
this.selectedRaceIndex = selection.raceIndex;
this.selectedCompetitorIndex = selection.competitorIndex;
@@ -234,7 +246,7 @@ public class PathPolyline {
simulatorMap.setPolyline(polyline);
polyline.setEditable(true);
// old call: polyline.setEditingEnabled(PolyEditingOptions.newInstance(turnPoints.length - 1));
getTotalTime();
}
@@ -1037,7 +1049,7 @@ public class PathPolyline {
/**
* Converts a LatLng object to a TwoD object. Considering that a LatLng represent a point on a sphere, and that the
* TwoDPoint represent one on a plane, it will use the MapWidget aproximation to a container pixel in order to do
* TwoDPoint represent one on a plane, it will use the MapWidget approximation to a container pixel in order to do
* so.
*
* @param latLng
@@ -1045,8 +1057,7 @@ public class PathPolyline {
* @returns a TwoDPoint object.
*/
private TwoDPoint toTwoDPoint(LatLng latLng) {
// TODO MigrationV3: Point point = map.convertLatLngToContainerPixel(latLng);
Point point = Point.newInstance(latLng.getLatitude(), latLng.getLongitude());
Point point = this.mapProjection.fromLatLngToContainerPixel(latLng);
return new TwoDPoint(point.getX(), point.getY());
}
@@ -1065,8 +1076,7 @@ public class PathPolyline {
* @returns a LatLng object.
*/
private LatLng toLatLng(TwoDPoint point) {
return LatLng.newInstance((int) point.getX(), (int) point.getY());
// TODO MigrationV3: return this.map.convertContainerPixelToLatLng(Point.newInstance((int) point.getX(), (int) point.getY()));
return this.mapProjection.fromContainerPixelToLatLng(Point.newInstance((int) point.getX(), (int) point.getY()));
}
/**
@@ -148,8 +148,10 @@ public class RaceCourseCanvasOverlay extends FullCanvasOverlay {
if (startPoint != null) {
Point point = mapProjection.fromLatLngToDivPixel(startPoint);
drawCircleWithText(point.getX() - getWidgetPosLeft(), point.getY() - getWidgetPosTop(), racecourseBuoySize,
racecourseColor, "Start");
if (racecourseBuoySize > 0.0) {
drawCircleWithText(point.getX() - getWidgetPosLeft(), point.getY() - getWidgetPosTop(), racecourseBuoySize,
racecourseColor, "Start");
}
if (startMarker != null) {
startMarker.setPosition(startPoint);
} else {
@@ -174,10 +176,11 @@ public class RaceCourseCanvasOverlay extends FullCanvasOverlay {
}
if (endPoint != null) {
Point point = mapProjection.fromLatLngToDivPixel(endPoint);
drawCircleWithText(point.getX() - getWidgetPosLeft(), point.getY() - getWidgetPosTop(), racecourseBuoySize,
racecourseColor, "End");
Point point = mapProjection.fromLatLngToDivPixel(endPoint);
if (racecourseBuoySize > 0.0) {
drawCircleWithText(point.getX() - getWidgetPosLeft(), point.getY() - getWidgetPosTop(), racecourseBuoySize,
racecourseColor, "End");
}
if (endMarker != null) {
endMarker.setPosition(endPoint);
} else {
@@ -5,12 +5,6 @@ import com.google.gwt.canvas.dom.client.Context2d.TextAlign;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.base.LatLng;
import com.google.gwt.maps.client.base.Point;
import com.google.gwt.maps.client.events.click.ClickMapEvent;
import com.google.gwt.maps.client.events.click.ClickMapHandler;
import com.google.gwt.maps.client.events.idle.IdleMapEvent;
import com.google.gwt.maps.client.events.idle.IdleMapHandler;
import com.google.gwt.maps.client.overlays.Circle;
import com.google.gwt.maps.client.overlays.CircleOptions;
import com.sap.sailing.gwt.ui.simulator.racemap.FullCanvasOverlay;
import com.sap.sailing.simulator.util.SailingSimulatorConstants;
@@ -22,7 +16,6 @@ public class RegattaAreaCanvasOverlay extends FullCanvasOverlay {
private CourseAreaDescriptor currentCourseArea = null;
private boolean initial;
private boolean mapPan = false;
private double raceBearing = 0.0;
private double diffBearing = 0.0;
@@ -32,58 +25,7 @@ public class RegattaAreaCanvasOverlay extends FullCanvasOverlay {
this.simulatorMap = simulatorMap;
this.venue = VenueDescriptorFactory.createVenue(event);
this.currentCourseArea = this.venue.getDefaultCourseArea();
/*getMap().addZoomChangeHandler(new ZoomChangeMapHandler() {
@Override
public void onEvent(ZoomChangeMapEvent event) {
// TODO Auto-generated method stub
simulatorMap.windRoseCanvasOverlay.removeFromMap();
simulatorMap.windNeedleCanvasOverlay.removeFromMap();
mapPan = true;
}
});
getMap().addDragStartHandler(new DragStartMapHandler() {
@Override
public void onEvent(DragStartMapEvent event) {
// TODO Auto-generated method stub
simulatorMap.windRoseCanvasOverlay.removeFromMap();
simulatorMap.windNeedleCanvasOverlay.removeFromMap();
}
});
getMap().addDragEndHandler(new DragEndMapHandler() {
@Override
public void onEvent(DragEndMapEvent event) {
// TODO Auto-generated method stub
simulatorMap.windRoseCanvasOverlay.addToMap();
simulatorMap.windNeedleCanvasOverlay.addToMap();
}
});*/
getMap().addIdleHandler(new IdleMapHandler() {
@Override
public void onEvent(IdleMapEvent event) {
// TODO Auto-generated method stub
if (mapPan) {
//System.out.println("Map Idle Event Handler.");
simulatorMap.getWindRoseCanvasOverlay().addToMap();
simulatorMap.getWindNeedleCanvasOverlay().addToMap();
mapPan = false;
}
}
});
this.currentCourseArea = this.venue.getDefaultCourseArea();
}
@@ -93,7 +35,7 @@ public class RegattaAreaCanvasOverlay extends FullCanvasOverlay {
int counter = 0;
for (CourseAreaDescriptor courseArea : venue.getCourseAreas()) {
drawCircleFromRadius(counter++, courseArea);
simulatorMap.drawCircleFromRadius(counter++, courseArea);
}
map.panTo(venue.getCenterPos());
@@ -142,48 +84,6 @@ public class RegattaAreaCanvasOverlay extends FullCanvasOverlay {
}
}
// TODO MigrationV3: This is not the right place to create Circles being not drawn to the canvas -> move to SimulatorMap
public void drawCircleFromRadius(int regIdx, CourseAreaDescriptor courseArea) {
CircleOptions circleOptions = CircleOptions.newInstance();
circleOptions.setStrokeColor("white");
circleOptions.setStrokeWeight(1);
circleOptions.setStrokeOpacity(0.0);
circleOptions.setFillColor("green");
circleOptions.setFillOpacity(0.0);
circleOptions.setCenter(courseArea.getCenterPos());
Circle circle = Circle.newInstance(circleOptions);
circle.setRadius(courseArea.getRadiusInMeters());
final int regIdxFinal = regIdx;
circle.addClickHandler(new ClickMapHandler() {
public void onEvent(ClickMapEvent e) {
//System.out.println("Click: "+currentCourseArea.getName());
CourseAreaDescriptor newRegArea = venue.getCourseAreas().get(regIdxFinal);
if (newRegArea != currentCourseArea) {
currentCourseArea = newRegArea;
simulatorMap.clearOverlays();
simulatorMap.getWindRoseCanvasOverlay().removeFromMap();
simulatorMap.getWindNeedleCanvasOverlay().removeFromMap();
updateRaceCourse(0, 0);
raceCourseCanvasOverlay.draw();
}
map.panTo(currentCourseArea.getCenterPos());
mapPan = true;
if (map.getZoom() < 14) {
map.setZoom(14);
}
}
});
circle.setMap(getMap());
}
protected void updateRaceCourse(int type, double bearing) {
if (type == 1) {
@@ -209,6 +109,14 @@ public class RegattaAreaCanvasOverlay extends FullCanvasOverlay {
}
}
public CourseAreaDescriptor getCurrentCourseArea() {
return this.currentCourseArea;
}
public void setCurrentCourseArea(CourseAreaDescriptor courseArea) {
this.currentCourseArea = courseArea;
}
protected void drawCourseArea(String name, Context2d context2d, Point centerPoint, Point borderPoint,
String color, String colorText, double pxStroke) {
@@ -216,18 +124,23 @@ public class RegattaAreaCanvasOverlay extends FullCanvasOverlay {
centerPoint.getY() - borderPoint.getY());
double pxRadius = Math.sqrt(diffPoint.getX() * diffPoint.getX() + diffPoint.getY() * diffPoint.getY());
String bgColor;
if (simulatorMap.getWindParams().isShowStreamlets2()) {
bgColor = "#505050";
} else {
bgColor = "#DEDEDE";
}
context2d.setGlobalAlpha(1.0f);
context2d.setFillStyle("#DEDEDE");
context2d.setLineWidth(pxStroke);
context2d.setStrokeStyle(color);
context2d.setFillStyle(bgColor);
context2d.beginPath();
context2d.arc(centerPoint.getX() - this.getWidgetPosLeft(), centerPoint.getY() - this.getWidgetPosTop(),
pxRadius, 0.0, 2 * Math.PI);
context2d.closePath();
context2d.fill();
context2d.stroke();
context2d.setGlobalAlpha(0.4f);
context2d.setGlobalAlpha(0.5f);
context2d.setFillStyle(color);
context2d.beginPath();
context2d.arc(centerPoint.getX() - this.getWidgetPosLeft(), centerPoint.getY() - this.getWidgetPosTop(),
@@ -235,6 +148,24 @@ public class RegattaAreaCanvasOverlay extends FullCanvasOverlay {
context2d.closePath();
context2d.fill();
context2d.setGlobalAlpha(1.0f);
context2d.setLineWidth(pxStroke);
context2d.setStrokeStyle(bgColor);
context2d.beginPath();
context2d.arc(centerPoint.getX() - this.getWidgetPosLeft(), centerPoint.getY() - this.getWidgetPosTop(),
pxRadius, 0.0, 2 * Math.PI);
context2d.closePath();
context2d.stroke();
context2d.setGlobalAlpha(0.8f);
context2d.setLineWidth(pxStroke);
context2d.setStrokeStyle(color);
context2d.beginPath();
context2d.arc(centerPoint.getX() - this.getWidgetPosLeft(), centerPoint.getY() - this.getWidgetPosTop(),
pxRadius, 0.0, 2 * Math.PI);
context2d.closePath();
context2d.stroke();
if (getMap().getZoom() >= 11) {
context2d.setGlobalAlpha(0.8f);
context2d.setFillStyle(colorText);
@@ -246,9 +177,9 @@ public class RegattaAreaCanvasOverlay extends FullCanvasOverlay {
context2d.fillText(name, centerPoint.getX() - this.getWidgetPosLeft(), centerPoint.getY() + 0.32 * fontsize
- this.getWidgetPosTop());
context2d.setGlobalAlpha(1.0f);
}
context2d.setGlobalAlpha(1.0f);
}
protected LatLng getEdgePoint(LatLng pos, double dist) {
@@ -282,4 +213,8 @@ public class RegattaAreaCanvasOverlay extends FullCanvasOverlay {
this.raceCourseCanvasOverlay = rcCanvas;
}
public VenueDescriptor getVenue() {
return this.venue;
}
}
@@ -10,6 +10,7 @@ import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.sap.sailing.gwt.ui.client.AbstractEntryPoint;
import com.sap.sailing.gwt.ui.client.JavaScriptInjector;
import com.sap.sailing.gwt.ui.client.LogoAndTitlePanel;
import com.sap.sailing.gwt.ui.client.RemoteServiceMappingConstants;
import com.sap.sailing.gwt.ui.client.SimulatorService;
@@ -23,6 +24,7 @@ public class SimulatorEntryPoint extends AbstractEntryPoint {
private final SimulatorServiceAsync simulatorService = GWT.create(SimulatorService.class);
private int xRes = 40;
private int yRes = 20;
private int border = 0;
private boolean autoUpdate = false;
private char mode = SailingSimulatorConstants.ModeEvent; // default mode: 'e'vent
private char event = SailingSimulatorConstants.EventKielerWoche; // default event: 'k'ieler woche
@@ -32,16 +34,25 @@ public class SimulatorEntryPoint extends AbstractEntryPoint {
private boolean showLines = false; // show the wind lines in the wind display and replay modes.
private char seedLines = 'b'; // seed lines at: 'b'ack, 'f'ront
private boolean showStreamlets = true; // show the wind streamlets in the wind display and replay modes.
private boolean showStreamlets2 = false; // show animated wind streamlets in the wind display and replay modes.
private boolean injectWindDataJS = false;
private static Logger logger = Logger.getLogger(SimulatorEntryPoint.class.getName());
@Override
protected void doOnModuleLoad() {
super.doOnModuleLoad();
super.doOnModuleLoad();
registerASyncService((ServiceDefTarget) simulatorService, RemoteServiceMappingConstants.simulatorServiceRemotePath);
checkUrlParameters();
checkUrlParameters();
if (this.injectWindDataJS) {
SimulatorJSBundle bundle = GWT.create(SimulatorJSBundle.class);
JavaScriptInjector.inject(bundle.windStreamletsDataJS().getText());
}
createSimulatorPanel();
}
@@ -58,6 +69,12 @@ public class SimulatorEntryPoint extends AbstractEntryPoint {
} else {
yRes = Integer.parseInt(verticalRes);
}
String border = Window.Location.getParameter("border");
if (border == null || border.isEmpty()) {
logger.config("Using default border " + this.border);
} else {
this.border = Integer.parseInt(border);
}
String autoUpdateStr = Window.Location.getParameter("autoUpdate");
if (autoUpdateStr == null || autoUpdateStr.isEmpty()) {
logger.config("Using default auto update " + autoUpdate);
@@ -106,6 +123,18 @@ public class SimulatorEntryPoint extends AbstractEntryPoint {
} else {
showStreamlets = false;
}
if (windDisplayStr.contains("z")) {
showStreamlets2 = true;
} else {
showStreamlets2 = false;
}
if (windDisplayStr.contains("y")) {
showStreamlets2 = true;
injectWindDataJS = true;
}
if ((showStreamlets2)&&(this.border==0)) {
this.border = 10;
}
if (windDisplayStr.contains("b")) {
seedLines = 'b';
}
@@ -134,8 +163,8 @@ public class SimulatorEntryPoint extends AbstractEntryPoint {
}
private void createSimulatorPanel() {
SimulatorMainPanel simulatorPanel = new SimulatorMainPanel(simulatorService, stringMessages, this, xRes, yRes,
autoUpdate, mode, event, showGrid, showLines, seedLines, showArrows, showStreamlets);
SimulatorMainPanel simulatorPanel = new SimulatorMainPanel(simulatorService, stringMessages, this, xRes, yRes, border,
autoUpdate, mode, event, showGrid, showLines, seedLines, showArrows, showStreamlets, showStreamlets2, injectWindDataJS);
DockLayoutPanel p = new DockLayoutPanel(Unit.PX);
RootLayoutPanel.get().add(p);
@@ -0,0 +1,14 @@
package com.sap.sailing.gwt.ui.simulator;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.TextResource;
public interface SimulatorJSBundle extends ClientBundle {
//@Source("wind-streamlets.js")
//TextResource windStreamletsJS();
@Source("com/sap/sailing/gwt/ui/simulator/wind-data.js")
TextResource windStreamletsDataJS();
}
@@ -71,7 +71,7 @@ public class SimulatorMainPanel extends SimplePanel {
simulatorMap.getMap().triggerResize();
}
}
private DockLayoutPanel mainPanel;
private FlowPanel leftPanel;
private ResizableFlowPanel rightPanel;
@@ -122,6 +122,7 @@ public class SimulatorMainPanel extends SimplePanel {
private CheckBox isPathPolylineFreeMode;
private Chart chart;
private boolean injectWindDataJS = false;
private boolean warningAlreadyShown = false;
private DialogBox polarDiagramDialogBox;
private Button polarDiagramDialogCloseButton;
@@ -224,8 +225,8 @@ public class SimulatorMainPanel extends SimplePanel {
return NumberFormat.getFormat("0.0").format(value);
}
public SimulatorMainPanel(SimulatorServiceAsync svc, StringMessages stringMessages, ErrorReporter errorReporter, int xRes, int yRes, boolean autoUpdate,
char mode, char event, boolean showGrid, boolean showLines, char seedLines, boolean showArrows, boolean showStreamlets) {
public SimulatorMainPanel(SimulatorServiceAsync svc, StringMessages stringMessages, ErrorReporter errorReporter, int xRes, int yRes, int border, boolean autoUpdate,
char mode, char event, boolean showGrid, boolean showLines, char seedLines, boolean showArrows, boolean showStreamlets, boolean showStreamlets2, boolean injectWindDataJS) {
super();
this.simulatorSvc = svc;
@@ -293,26 +294,26 @@ public class SimulatorMainPanel extends SimplePanel {
windParams.setShowLines(showLines);
windParams.setSeedLines(seedLines);
windParams.setShowStreamlets(showStreamlets);
windParams.setShowStreamlets2(showStreamlets2);
this.setDefaultTimeSettings();
this.injectWindDataJS = injectWindDataJS;
timer = new Timer(PlayModes.Replay, 1000l);
TimeRangeWithZoomProvider timeRangeProvider = new TimeRangeWithZoomModel();
initTimer();
timer.setTime(windParams.getStartTime().getTime());
int secondsTimeStep = (int) windParams.getTimeStep().getTime() / 1000;
timer.setPlaySpeedFactor(secondsTimeStep);
timer.setAutoAdvance(true);
timePanel = new TimePanel<TimePanelSettings>(timer, timeRangeProvider, stringMessages, false);
busyIndicator = new SimpleBusyIndicator(false, 0.8f);
simulatorMap = new SimulatorMap(simulatorSvc, stringMessages, errorReporter, xRes, yRes, timer, timePanel,
simulatorMap = new SimulatorMap(simulatorSvc, stringMessages, errorReporter, xRes, yRes, border, timer, timePanel,
windParams, busyIndicator, mode, this);
simulatorMap.setSize("100%", "100%");
this.rightPanel.add(this.simulatorMap);
createOptionsPanelTop();
createOptionsPanel();
@@ -333,6 +334,23 @@ public class SimulatorMainPanel extends SimplePanel {
this.polarDiagramDialogBox = this.createPolarDiagramDialogBox();
}
public native void setMapInstance(Object mapInstance) /*-{
$wnd.swarmMap = mapInstance;
}-*/;
public native void setCanvasProjectionInstance(Object instance) /*-{
$wnd.swarmCanvasProjection = instance;
}-*/;
public native void startStreamlets() /*-{
if ($wnd.swarmAnimator) {
$wnd.swarmUpdData = true;
$wnd.updateStreamlets($wnd.swarmUpdData);
} else {
$wnd.initStreamlets($wnd.swarmMap);
}
}-*/;
public void setDefaultTimeSettings() {
Date defaultNow = new Date();
DateTimeFormat fmt = DateTimeFormat.getFormat("Z");
@@ -464,6 +482,10 @@ public class SimulatorMainPanel extends SimplePanel {
return windControlPanel;
}
public WindPatternDisplay getWindPatternDisplay() {
return currentWPDisplay;
}
private Panel getSliderPanel(Panel parentPanel, WindPatternSetting<?> s) {
String labelName = s.getDisplayName();
@@ -823,36 +845,53 @@ public class SimulatorMainPanel extends SimplePanel {
private void update() {
// int selectedBoatClassIndex = boatClassSelector.getSelectedIndex();
// int selectedRaceIndex = raceSelector.getSelectedIndex();
// int selectedCompetitorIndex = competitorSelector.getSelectedIndex();
int selectedLegIndex = legSelector.getSelectedIndex();
if (this.windParams.isShowStreamlets2()) {
SimulatorUISelectionDTO selection = new SimulatorUISelectionDTO(boatClassSelector.getSelectedIndex(), raceSelector.getSelectedIndex(),
competitorSelector.getSelectedIndex(), legSelector.getSelectedIndex());
this.setMapInstance(this.simulatorMap.getMap().getJso());
this.setCanvasProjectionInstance(this.simulatorMap.getRegattaAreaCanvasOverlay().getMapProjection());
if (windDisplayButton.getValue()) {
showTimePanel(true);
simulatorMap.refreshView(SimulatorMap.ViewName.WINDDISPLAY, currentWPDisplay, selection, true);
} else if (summaryButton.getValue()) {
showTimePanel(false);
simulatorMap.getRegattaAreaCanvasOverlay().draw();
simulatorMap.refreshView(SimulatorMap.ViewName.SUMMARY, currentWPDisplay, selection, true);
} else if (replayButton.getValue()) {
showTimePanel(true);
simulatorMap.refreshView(SimulatorMap.ViewName.REPLAY, currentWPDisplay, selection, true);
} else {
if (mode == SailingSimulatorConstants.ModeMeasured) {
//this.setDefaultTimeSettings();
//this.simulatorMap.generateWindField(this.getWindPatternDisplay(), true);
if (selectedLegIndex % 2 != 0) {
errorReporter.reportError("Downwind legs are NOT supported yet. Sorry about that :)");
} else {
simulatorMap.removePolyline();
showTimePanel(false);
simulatorMap.refreshView(SimulatorMap.ViewName.SUMMARY, currentWPDisplay, selection, true);
}
}
}
}
if (this.injectWindDataJS) {
this.startStreamlets();
} else {
// int selectedBoatClassIndex = boatClassSelector.getSelectedIndex();
// int selectedRaceIndex = raceSelector.getSelectedIndex();
// int selectedCompetitorIndex = competitorSelector.getSelectedIndex();
int selectedLegIndex = legSelector.getSelectedIndex();
SimulatorUISelectionDTO selection = new SimulatorUISelectionDTO(boatClassSelector.getSelectedIndex(), raceSelector.getSelectedIndex(),
competitorSelector.getSelectedIndex(), legSelector.getSelectedIndex());
if (windDisplayButton.getValue()) {
showTimePanel(true);
simulatorMap.refreshView(SimulatorMap.ViewName.WINDDISPLAY, currentWPDisplay, selection, true);
} else if (summaryButton.getValue()) {
showTimePanel(false);
simulatorMap.getRegattaAreaCanvasOverlay().draw();
simulatorMap.refreshView(SimulatorMap.ViewName.SUMMARY, currentWPDisplay, selection, true);
} else if (replayButton.getValue()) {
showTimePanel(true);
simulatorMap.refreshView(SimulatorMap.ViewName.REPLAY, currentWPDisplay, selection, true);
} else {
if (mode == SailingSimulatorConstants.ModeMeasured) {
if (selectedLegIndex % 2 != 0) {
errorReporter.reportError("Downwind legs are NOT supported yet. Sorry about that :)");
} else {
simulatorMap.removePolyline();
showTimePanel(false);
simulatorMap.refreshView(SimulatorMap.ViewName.SUMMARY, currentWPDisplay, selection, true);
}
}
}
}
}
private void initPolarDiagramButton() {
@@ -19,7 +19,15 @@ import com.google.gwt.maps.client.controls.MapTypeStyle;
import com.google.gwt.maps.client.controls.PanControlOptions;
import com.google.gwt.maps.client.controls.ScaleControlOptions;
import com.google.gwt.maps.client.controls.ZoomControlOptions;
import com.google.gwt.maps.client.events.click.ClickMapEvent;
import com.google.gwt.maps.client.events.click.ClickMapHandler;
import com.google.gwt.maps.client.events.idle.IdleMapEvent;
import com.google.gwt.maps.client.events.idle.IdleMapHandler;
import com.google.gwt.maps.client.maptypes.MapTypeStyleElementType;
import com.google.gwt.maps.client.maptypes.MapTypeStyleFeatureType;
import com.google.gwt.maps.client.maptypes.MapTypeStyler;
import com.google.gwt.maps.client.overlays.Circle;
import com.google.gwt.maps.client.overlays.CircleOptions;
import com.google.gwt.maps.client.overlays.Polyline;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -58,17 +66,19 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
private static SimulatorResources resources = GWT.create(SimulatorResources.class);
private MapWidget map;
private boolean mapPan = false;
private boolean dataInitialized;
private boolean overlaysInitialized;
private WindFieldGenParamsDTO windParams;
// the canvas overlays
private WindStreamletsCanvasOverlay windStreamletsCanvasOverlay;
private WindLineGuidesCanvasOverlay windLineGuidesCanvasOverlay;
private WindFieldCanvasOverlay windFieldCanvasOverlay;
private WindGridCanvasOverlay windGridCanvasOverlay;
private WindLineCanvasOverlay windLineCanvasOverlay;
private RegattaAreaCanvasOverlay regattaAreaCanvasOverlay;
private WindStreamletsCanvasOverlay windStreamletsCanvasOverlay;
private ImageCanvasOverlay windRoseCanvasOverlay;
private ImageCanvasOverlay windNeedleCanvasOverlay;
private List<PathCanvasOverlay> replayPathCanvasOverlays;
@@ -87,6 +97,7 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
private ColorPalette colorPalette;
private int xRes;
private int yRes;
private int border;
private boolean warningAlreadyShown = false;
private SimulatorMainPanel parent = null;
private PathPolyline pathPolyline = null;
@@ -199,13 +210,14 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
if (timePanel != null) {
timePanel.setMinMax(new Date(startTime), new Date(startTime + maxDurationTime), true);
timePanel.resetTimeSlider();
timePanel.timeChanged(windParams.getStartTime(), null);
}
/**
* Now we always get the wind field
*/
WindFieldDTO windFieldDTO = result.getWindField();
LOGGER.info("Number of windDTO : " + windFieldDTO.getMatrix().size());
//LOGGER.info("Number of windDTO : " + windFieldDTO.getMatrix().size());
if (windParams.isShowGrid()) {
windGridCanvasOverlay.addToMap();
@@ -217,6 +229,9 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
windFieldCanvasOverlay.addToMap();
}
if (windParams.isShowStreamlets()) {
windLineGuidesCanvasOverlay.addToMap();
}
if (windParams.isShowStreamlets2()) {
windStreamletsCanvasOverlay.addToMap();
}
@@ -228,6 +243,9 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
timeListeners.add(windFieldCanvasOverlay);
}
if (windParams.isShowStreamlets()) {
timeListeners.add(windLineGuidesCanvasOverlay);
}
if (windParams.isShowStreamlets2()) {
timeListeners.add(windStreamletsCanvasOverlay);
}
if (windParams.isShowGrid()) {
@@ -244,8 +262,8 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
if (windFieldCanvasOverlay != null) {
windFieldCanvasOverlay.setVisible(false);
}
if (windStreamletsCanvasOverlay != null) {
windStreamletsCanvasOverlay.setVisible(false);
if (windLineGuidesCanvasOverlay != null) {
windLineGuidesCanvasOverlay.setVisible(false);
}
if (windGridCanvasOverlay != null) {
windGridCanvasOverlay.setVisible(false);
@@ -253,6 +271,13 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
if (windLineCanvasOverlay != null) {
windLineCanvasOverlay.setVisible(false);
}
if (windStreamletsCanvasOverlay != null) {
windStreamletsCanvasOverlay.setVisible(false);
}
} else {
if (windStreamletsCanvasOverlay != null) {
windStreamletsCanvasOverlay.setVisible(true);
}
}
legendCanvasOverlay.addToMap();
@@ -264,7 +289,7 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
}
public SimulatorMap(SimulatorServiceAsync simulatorSvc, StringMessages stringMessages, ErrorReporter errorReporter, int xRes, int yRes, Timer timer,
public SimulatorMap(SimulatorServiceAsync simulatorSvc, StringMessages stringMessages, ErrorReporter errorReporter, int xRes, int yRes, int border, Timer timer,
WindFieldGenParamsDTO windParams, SimpleBusyIndicator busyIndicator, char mode,
SimulatorMainPanel parent) {
this.simulatorService = simulatorSvc;
@@ -272,6 +297,7 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
this.errorReporter = errorReporter;
this.xRes = xRes;
this.yRes = yRes;
this.border = border;
this.timer = timer;
this.timePanel = null;
timer.addTimeListener(this);
@@ -282,7 +308,7 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
this.dataInitialized = false;
this.overlaysInitialized = false;
this.windFieldCanvasOverlay = null;
this.windStreamletsCanvasOverlay = null;
this.windLineGuidesCanvasOverlay = null;
this.windGridCanvasOverlay = null;
this.windLineCanvasOverlay = null;
this.replayPathCanvasOverlays = null;
@@ -292,13 +318,14 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
this.parent = parent;
}
public SimulatorMap(SimulatorServiceAsync simulatorSvc, StringMessages stringMessages, ErrorReporter errorReporter, int xRes, int yRes, Timer timer,
public SimulatorMap(SimulatorServiceAsync simulatorSvc, StringMessages stringMessages, ErrorReporter errorReporter, int xRes, int yRes, int border, Timer timer,
TimePanel<TimePanelSettings> timePanel, WindFieldGenParamsDTO windParams, SimpleBusyIndicator busyIndicator, char mode, SimulatorMainPanel parent) {
this.simulatorService = simulatorSvc;
this.stringMessages = stringMessages;
this.errorReporter = errorReporter;
this.xRes = xRes;
this.yRes = yRes;
this.border = border;
this.timer = timer;
this.timePanel = timePanel;
timer.addTimeListener(this);
@@ -309,7 +336,7 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
this.dataInitialized = false;
this.overlaysInitialized = false;
this.windFieldCanvasOverlay = null;
this.windStreamletsCanvasOverlay = null;
this.windLineGuidesCanvasOverlay = null;
this.windGridCanvasOverlay = null;
this.windLineCanvasOverlay = null;
this.replayPathCanvasOverlays = null;
@@ -338,16 +365,45 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
mapOptions.setRotateControl(true);
mapOptions.setStreetViewControl(false);
MapTypeStyle[] mapTypeStyles = new MapTypeStyle[4];
MapTypeStyle[] mapTypeStyles;
// hide all transit lines including ferry lines
mapTypeStyles[0] = GoogleMapStyleHelper.createHiddenStyle(MapTypeStyleFeatureType.TRANSIT);
// hide points of interest
mapTypeStyles[1] = GoogleMapStyleHelper.createHiddenStyle(MapTypeStyleFeatureType.POI);
// simplify road display
mapTypeStyles[2] = GoogleMapStyleHelper.createSimplifiedStyle(MapTypeStyleFeatureType.ROAD);
// set water color
mapTypeStyles[3] = GoogleMapStyleHelper.createColorStyle(MapTypeStyleFeatureType.WATER, new RGBColor(0, 136, 255), -35, -34);
if (windParams.isShowStreamlets2()) {
mapTypeStyles = new MapTypeStyle[7];
// hide all transit lines including ferry lines
mapTypeStyles[0] = GoogleMapStyleHelper.createHiddenStyle(MapTypeStyleFeatureType.TRANSIT);
// hide points of interest
mapTypeStyles[1] = GoogleMapStyleHelper.createHiddenStyle(MapTypeStyleFeatureType.POI);
// simplify road display
mapTypeStyles[2] = GoogleMapStyleHelper.createSimplifiedStyle(MapTypeStyleFeatureType.ROAD);
// set water color
mapTypeStyles[3] = GoogleMapStyleHelper.createColorStyle(MapTypeStyleFeatureType.WATER, new RGBColor(0, 136, 255), -50, -50);
mapTypeStyles[4] = GoogleMapStyleHelper.createColorStyle(MapTypeStyleFeatureType.LANDSCAPE, new RGBColor(255, 255, 255), 0, -70);
mapTypeStyles[5] = GoogleMapStyleHelper.createElementStyleOnlyLightness(MapTypeStyleFeatureType.ROAD, MapTypeStyleElementType.ALL, -40);
MapTypeStyle mapStyle = MapTypeStyle.newInstance();
mapStyle.setFeatureType(MapTypeStyleFeatureType.ADMINISTRATIVE);
mapStyle.setElementType(MapTypeStyleElementType.LABELS);
MapTypeStyler[] typeStylers = new MapTypeStyler[1];
typeStylers[0] = MapTypeStyler.newInvertLightnessStyler(true);
mapStyle.setStylers(typeStylers);
mapTypeStyles[6] = mapStyle;
} else {
mapTypeStyles = new MapTypeStyle[4];
// hide all transit lines including ferry lines
mapTypeStyles[0] = GoogleMapStyleHelper.createHiddenStyle(MapTypeStyleFeatureType.TRANSIT);
// hide points of interest
mapTypeStyles[1] = GoogleMapStyleHelper.createHiddenStyle(MapTypeStyleFeatureType.POI);
// simplify road display
mapTypeStyles[2] = GoogleMapStyleHelper.createSimplifiedStyle(MapTypeStyleFeatureType.ROAD);
// set water color
mapTypeStyles[3] = GoogleMapStyleHelper.createColorStyle(MapTypeStyleFeatureType.WATER, new RGBColor(0, 136, 255), -35, -34);
}
mapOptions.setMapTypeStyles(mapTypeStyles);
@@ -376,7 +432,56 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
add(map, 0, 0);
map.setSize("100%", "100%");
/*map.addZoomChangeHandler(new ZoomChangeMapHandler() {
@Override
public void onEvent(ZoomChangeMapEvent event) {
// TODO Auto-generated method stub
windRoseCanvasOverlay.removeFromMap();
windNeedleCanvasOverlay.removeFromMap();
mapPan = true;
}
});
map.addDragStartHandler(new DragStartMapHandler() {
@Override
public void onEvent(DragStartMapEvent event) {
// TODO Auto-generated method stub
windRoseCanvasOverlay.removeFromMap();
windNeedleCanvasOverlay.removeFromMap();
}
});
map.addDragEndHandler(new DragEndMapHandler() {
@Override
public void onEvent(DragEndMapEvent event) {
// TODO Auto-generated method stub
windRoseCanvasOverlay.addToMap();
windNeedleCanvasOverlay.addToMap();
}
});*/
map.addIdleHandler(new IdleMapHandler() {
@Override
public void onEvent(IdleMapEvent event) {
// TODO Auto-generated method stub
if (mapPan) {
//System.out.println("Map Idle Event Handler.");
getWindRoseCanvasOverlay().addToMap();
getWindNeedleCanvasOverlay().addToMap();
mapPan = false;
}
}
});
initializeOverlays();
dataInitialized = true;
@@ -420,7 +525,10 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
windFieldCanvasOverlay = new WindFieldCanvasOverlay(map, SimulatorMapOverlaysZIndexes.WINDFIELD_ZINDEX, timer, windParams);
}
if (windParams.isShowStreamlets()) {
windStreamletsCanvasOverlay = new WindStreamletsCanvasOverlay(map, SimulatorMapOverlaysZIndexes.WINDSTREAMLETS_ZINDEX, timer, xRes);
windLineGuidesCanvasOverlay = new WindLineGuidesCanvasOverlay(map, SimulatorMapOverlaysZIndexes.WINDSTREAMLETS_ZINDEX, timer, xRes);
}
if (windParams.isShowStreamlets2()) {
windStreamletsCanvasOverlay = new WindStreamletsCanvasOverlay(this, SimulatorMapOverlaysZIndexes.WINDFIELD_ZINDEX, timer, windParams);
}
if (windParams.isShowGrid()) {
windGridCanvasOverlay = new WindGridCanvasOverlay(map, SimulatorMapOverlaysZIndexes.WINDGRID_ZINDEX, timer, xRes, yRes);
@@ -443,8 +551,8 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
if (windFieldCanvasOverlay != null) {
windFieldCanvasOverlay.onResize();
}
if (windStreamletsCanvasOverlay != null) {
windStreamletsCanvasOverlay.onResize();
if (windLineGuidesCanvasOverlay != null) {
windLineGuidesCanvasOverlay.onResize();
}
if (windGridCanvasOverlay != null) {
windGridCanvasOverlay.onResize();
@@ -461,12 +569,17 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
overlaysInitialized = true;
}
private void generateWindField(final WindPatternDisplay windPatternDisplay, final boolean removeOverlays) {
public void generateWindField(final WindPatternDisplay windPatternDisplay, final boolean removeOverlays) {
LOGGER.info("In generateWindField");
if (windPatternDisplay == null) {
errorReporter.reportError("Please select a valid wind pattern.");
return;
}
if ((windStreamletsCanvasOverlay != null)&&(windStreamletsCanvasOverlay.isVisible())) {
windStreamletsCanvasOverlay.setVisible(false);
}
PositionDTO startPointDTO = new PositionDTO(raceCourseCanvasOverlay.getStartPoint().getLatitude(),
raceCourseCanvasOverlay.getStartPoint().getLongitude());
PositionDTO endPointDTO = new PositionDTO(raceCourseCanvasOverlay.getEndPoint().getLatitude(),
@@ -476,6 +589,7 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
windParams.setSouthEast(endPointDTO);
windParams.setxRes(xRes);
windParams.setyRes(yRes);
windParams.setBorder(border);
busyIndicator.setBusy(true);
timer.setTime(windParams.getStartTime().getTime());
@@ -490,7 +604,7 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
if (removeOverlays) {
removeOverlays();
}
LOGGER.info("Number of windDTO : " + wl.getMatrix().size());
//LOGGER.info("Number of windDTO : " + wl.getMatrix().size());
// Window.alert("Number of windDTO : " + wl.getMatrix().size());
if (windParams.isShowGrid()) {
windGridCanvasOverlay.addToMap();
@@ -502,6 +616,9 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
windFieldCanvasOverlay.addToMap();
}
if (windParams.isShowStreamlets()) {
windLineGuidesCanvasOverlay.addToMap();
}
if (windParams.isShowStreamlets2()) {
windStreamletsCanvasOverlay.addToMap();
}
refreshWindFieldOverlay(wl);
@@ -510,7 +627,11 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
timeListeners.add(windFieldCanvasOverlay);
}
if (windParams.isShowStreamlets()) {
timeListeners.add(windLineGuidesCanvasOverlay);
}
if (windParams.isShowStreamlets2()) {
timeListeners.add(windStreamletsCanvasOverlay);
windStreamletsCanvasOverlay.setVisible(true);
}
if (windParams.isShowGrid()) {
timeListeners.add(windGridCanvasOverlay);
@@ -520,7 +641,7 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
}
timePanel.setMinMax(windParams.getStartTime(), windParams.getEndTime(), true);
timePanel.resetTimeSlider();
//timer.setTime(windParams.getStartTime().getTime());
timePanel.timeChanged(windParams.getStartTime(), null);
busyIndicator.setBusy(false);
}
@@ -528,11 +649,14 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
}
private void refreshWindFieldOverlay(WindFieldDTO windFieldDTO) {
if (this.windStreamletsCanvasOverlay != null) {
this.windStreamletsCanvasOverlay.setWindField(windFieldDTO);
}
if (this.windFieldCanvasOverlay != null) {
this.windFieldCanvasOverlay.setWindField(windFieldDTO);
}
if (this.windStreamletsCanvasOverlay != null) {
this.windStreamletsCanvasOverlay.setWindField(windFieldDTO);
if (this.windLineGuidesCanvasOverlay != null) {
this.windLineGuidesCanvasOverlay.setWindField(windFieldDTO);
}
if (this.windGridCanvasOverlay != null) {
this.windGridCanvasOverlay.setWindField(windFieldDTO);
@@ -549,7 +673,7 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
this.windFieldCanvasOverlay.draw();
}
if (this.windParams.isShowStreamlets()) {
this.windStreamletsCanvasOverlay.draw();
this.windLineGuidesCanvasOverlay.draw();
}
if (this.windParams.isShowGrid()) {
this.windGridCanvasOverlay.draw();
@@ -567,6 +691,10 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
return;
}
if ((windStreamletsCanvasOverlay != null)&&(windStreamletsCanvasOverlay.isVisible())) {
windStreamletsCanvasOverlay.setVisible(false);
}
if (mode != SailingSimulatorConstants.ModeMeasured) {
PositionDTO startPointDTO = new PositionDTO(raceCourseCanvasOverlay.getStartPoint().getLatitude(),
raceCourseCanvasOverlay.getStartPoint().getLongitude());
@@ -579,6 +707,7 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
windParams.setxRes(xRes);
windParams.setyRes(yRes);
windParams.setBorder(border);
busyIndicator.setBusy(true);
timer.setTime(windParams.getStartTime().getTime());
@@ -611,6 +740,10 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
windFieldCanvasOverlay.removeFromMap();
num++;
}
if (windLineGuidesCanvasOverlay != null) {
windLineGuidesCanvasOverlay.removeFromMap();
num++;
}
if (windStreamletsCanvasOverlay != null) {
windStreamletsCanvasOverlay.removeFromMap();
num++;
@@ -656,6 +789,9 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
if (windStreamletsCanvasOverlay != null) {
windStreamletsCanvasOverlay.setVisible(false);
}
if (windLineGuidesCanvasOverlay != null) {
windLineGuidesCanvasOverlay.setVisible(false);
}
if (windGridCanvasOverlay != null) {
windGridCanvasOverlay.setVisible(false);
}
@@ -692,7 +828,10 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
if (windFieldCanvasOverlay != null) {
windFieldCanvasOverlay.setVisible(true);
}
if (windStreamletsCanvasOverlay != null) {
if (windLineGuidesCanvasOverlay != null) {
windLineGuidesCanvasOverlay.setVisible(true);
}
if ((windStreamletsCanvasOverlay != null)&&(!windStreamletsCanvasOverlay.isVisible())) {
windStreamletsCanvasOverlay.setVisible(true);
}
if (windGridCanvasOverlay != null) {
@@ -731,9 +870,13 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
windFieldCanvasOverlay.setVisible(true);
windFieldCanvasOverlay.draw();
}
if (windStreamletsCanvasOverlay != null) {
if (windLineGuidesCanvasOverlay != null) {
windLineGuidesCanvasOverlay.setVisible(true);
windLineGuidesCanvasOverlay.draw();
}
if ((windStreamletsCanvasOverlay != null)&&(!windStreamletsCanvasOverlay.isVisible())) {
windStreamletsCanvasOverlay.setVisible(true);
windStreamletsCanvasOverlay.draw();
//windStreamletsCanvasOverlay.draw();
}
if (windGridCanvasOverlay != null) {
windGridCanvasOverlay.setVisible(true);
@@ -773,6 +916,9 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
}
switch (name) {
case SUMMARY:
if ((windStreamletsCanvasOverlay != null)&&(windStreamletsCanvasOverlay.isVisible())) {
windStreamletsCanvasOverlay.setVisible(false);
}
refreshSummaryView(windPatternDisplay, selection, force);
break;
case REPLAY:
@@ -808,7 +954,7 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
public void timeChanged(Date newTime, Date oldTime) {
if (shallStop()) {
LOGGER.info("Stopping the timer");
timer.stop();
timer.pause();
}
}
@@ -889,5 +1035,44 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
public RaceCourseCanvasOverlay getRaceCourseCanvasOverlay() {
return raceCourseCanvasOverlay;
}
public void drawCircleFromRadius(int regIdx, CourseAreaDescriptor courseArea) {
CircleOptions circleOptions = CircleOptions.newInstance();
circleOptions.setStrokeColor("white");
circleOptions.setStrokeWeight(1);
circleOptions.setStrokeOpacity(0.0);
circleOptions.setFillColor("green");
circleOptions.setFillOpacity(0.0);
circleOptions.setCenter(courseArea.getCenterPos());
Circle circle = Circle.newInstance(circleOptions);
circle.setRadius(courseArea.getRadiusInMeters());
final int regIdxFinal = regIdx;
circle.addClickHandler(new ClickMapHandler() {
public void onEvent(ClickMapEvent e) {
//System.out.println("Click: "+currentCourseArea.getName());
CourseAreaDescriptor newRegArea = regattaAreaCanvasOverlay.getVenue().getCourseAreas().get(regIdxFinal);
if (newRegArea != regattaAreaCanvasOverlay.getCurrentCourseArea()) {
regattaAreaCanvasOverlay.setCurrentCourseArea(newRegArea);
clearOverlays();
getWindRoseCanvasOverlay().removeFromMap();
getWindNeedleCanvasOverlay().removeFromMap();
regattaAreaCanvasOverlay.updateRaceCourse(0, 0);
raceCourseCanvasOverlay.draw();
}
map.panTo(regattaAreaCanvasOverlay.getCurrentCourseArea().getCenterPos());
mapPan = true;
if (map.getZoom() < 14) {
map.setZoom(14);
}
}
});
circle.setMap(getMap());
}
}
@@ -38,15 +38,15 @@ public class VenueDescriptorFactory {
// Foxtrot
cPos = LatLng.newInstance(54.445775, 10.29223889);
courseAreas.add(new CourseAreaDescriptor("Foxtrot", cPos, 0.65, "#B4287C"));
courseAreas.add(new CourseAreaDescriptor("Foxtrot", cPos, 0.65, "#DA58A6"));
// India
cPos = LatLng.newInstance(54.44803611, 10.20863611);
courseAreas.add(new CourseAreaDescriptor("India", cPos, 0.40, "#774741"));
courseAreas.add(new CourseAreaDescriptor("India", cPos, 0.40, "#B7827B"));
// Juliett
cPos = LatLng.newInstance(54.46183611, 10.2239);
courseAreas.add(new CourseAreaDescriptor("Juliett", cPos, 0.55, "#818585"));
courseAreas.add(new CourseAreaDescriptor("Juliett", cPos, 0.55, "#979b9b"));
// Echo
cPos = LatLng.newInstance(54.47640278, 10.20090556);
@@ -58,7 +58,7 @@ public class VenueDescriptorFactory {
// Charlie
cPos = LatLng.newInstance(54.49327222, 10.17525833);
courseAreas.add(new CourseAreaDescriptor("Charlie", cPos, 0.70, "#0A5998"));
courseAreas.add(new CourseAreaDescriptor("Charlie", cPos, 0.70, "#2796f1"));
// Delta
cPos = LatLng.newInstance(54.49706111, 10.21921944);
@@ -66,11 +66,11 @@ public class VenueDescriptorFactory {
// Bravo
cPos = LatLng.newInstance(54.50911667, 10.13973333);
courseAreas.add(new CourseAreaDescriptor("Bravo", cPos, 0.80, "#CE3032"));
courseAreas.add(new CourseAreaDescriptor("Bravo", cPos, 0.80, "#d34547"));
// Alfa
cPos = LatLng.newInstance(54.52905, 10.18515278);
courseAreas.add(new CourseAreaDescriptor("Alfa", cPos, 1.00, "#D9699B"));
courseAreas.add(new CourseAreaDescriptor("Alfa", cPos, 1.00, "#d65c93"));
venue.setDefaultCourseArea(defaultCourseArea);
return venue;
@@ -229,7 +229,7 @@ public class WindLineCanvasOverlay extends FullCanvasOverlay implements TimeList
final double weight = 1.0;
LatLng positionLatLng = LatLng.newInstance(p1.latDeg, p1.lngDeg);
Point canvasPositionInPx = mapProjection.fromLatLngToContainerPixel(positionLatLng);
Point canvasPositionInPx = mapProjection.fromLatLngToDivPixel(positionLatLng);
final double x1 = canvasPositionInPx.getX() - this.getWidgetPosLeft();
final double y1 = canvasPositionInPx.getY() - this.getWidgetPosTop();
@@ -0,0 +1,273 @@
package com.sap.sailing.gwt.ui.simulator;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.logging.Logger;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.base.LatLng;
import com.google.gwt.maps.client.base.Point;
import com.sap.sailing.domain.common.dto.PositionDTO;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.gwt.ui.shared.SimulatorWindDTO;
import com.sap.sailing.gwt.ui.shared.WindFieldDTO;
import com.sap.sailing.gwt.ui.simulator.racemap.FullCanvasOverlay;
import com.sap.sailing.gwt.ui.simulator.util.ToolTip;
import com.sap.sse.gwt.client.player.Timer;
/**
* A google map overlay based on a HTML5 canvas for drawing a wind field. The overlay covers the whole map and displays
* the wind objects inside it.
*
* @author Nidhi Sawhney(D054070)
*
*/
public class WindLineGuidesCanvasOverlay extends FullCanvasOverlay implements TimeListenerWithStoppingCriteria {
/** The wind field that is to be displayed in the overlay */
private WindFieldDTO windFieldDTO;
/**
* Map containing the windfield for easy retrieval with key as time point.
*/
private SortedMap<Long, List<SimulatorWindDTO>> timePointWindDTOMap;
/** The points where ToolTip is to be displayed */
private Map<ToolTip, SimulatorWindDTO> windFieldPoints;
private String arrowColor = "Black";
private String arrowHeadColor = "Blue";
private int xRes;
private Timer timer;
private static Logger logger = Logger.getLogger(WindLineGuidesCanvasOverlay.class.getName());
public WindLineGuidesCanvasOverlay(MapWidget map, int zIndex, final Timer timer, int xRes) {
super(map, zIndex);
this.timer = timer;
this.xRes = xRes;
windFieldDTO = null;
windFieldPoints = new HashMap<ToolTip, SimulatorWindDTO>();
timePointWindDTOMap = new TreeMap<Long, List<SimulatorWindDTO>>();
}
public WindLineGuidesCanvasOverlay(MapWidget map, int zIndex) {
this(map, zIndex, null, 0);
}
@Override
public void addToMap() {
super.addToMap();
if (timer != null) {
timer.addTimeListener(this);
}
}
@Override
public void removeFromMap() {
super.removeFromMap();
if (timer != null) {
timer.removeTimeListener(this);
}
}
public void setWindField(final WindFieldDTO windField) {
this.windFieldDTO = windField;
timePointWindDTOMap.clear();
if (windField != null) {
for(final SimulatorWindDTO w : windField.getMatrix()) {
if (!timePointWindDTOMap.containsKey(w.timepoint)) {
timePointWindDTOMap.put(w.timepoint, new LinkedList<SimulatorWindDTO>());
}
timePointWindDTOMap.get(w.timepoint).add(w);
}
}
}
public void setArrowColor(final String arrowColor, final String arrowHeadColor) {
this.arrowColor = arrowColor;
this.arrowHeadColor = arrowHeadColor;
}
@Override
protected void draw() {
super.draw();
if (mapProjection != null && windFieldDTO != null) {
clear();
drawWindField();
}
}
private void clear() {
canvas.getContext2d().clearRect(0.0 /*canvas.getAbsoluteLeft()*/, 0.0/*canvas.getAbsoluteTop()*/,
canvas.getCoordinateSpaceWidth(), canvas.getCoordinateSpaceHeight());
windFieldPoints.clear();
}
protected void drawWindField() {
if (timer != null) {
timeChanged(timer.getTime(), null);
} else {
drawWindField(windFieldDTO.getMatrix());
}
}
protected void drawScaledArrow(final SimulatorWindDTO windDTO, final double angle, final int index, final double pxLength, final boolean drawHead) {
final double aWidth = 1.0;
drawArrow(windDTO, angle, pxLength, aWidth, index, drawHead);
}
protected void drawWindField(final List<SimulatorWindDTO> windDTOList) {
final boolean drawHead = false;
clear();
final Context2d context2d = canvas.getContext2d();
context2d.setGlobalAlpha(0.4);
if (windDTOList != null && windDTOList.size() > 0) {
Iterator<SimulatorWindDTO> windDTOIter = windDTOList.iterator();
final SimulatorWindDTO w0 = windDTOIter.next();
final SimulatorWindDTO w1 = windDTOIter.next();
final LatLng pg0 = LatLng.newInstance(w0.position.latDeg, w0.position.lngDeg);
final LatLng pg1 = LatLng.newInstance(w1.position.latDeg, w1.position.lngDeg);
final Point px0 = mapProjection.fromLatLngToDivPixel(pg0);
final Point px1 = mapProjection.fromLatLngToDivPixel(pg1);
final double dx = px0.getX()-px1.getX();
final double dy = px0.getY()-px1.getY();
final double pxLength = Math.sqrt( dx*dx + dy*dy );
logger.fine("pxLength = "+pxLength);
windDTOIter = windDTOList.iterator();
int index = 0;
while (windDTOIter.hasNext()) {
SimulatorWindDTO windDTO = windDTOIter.next();
//System.out.println("wind angle: "+index+", "+windDTO.trueWindBearingDeg);
if (((index % xRes) > 0)&&((index % xRes) < (xRes-1))) {
DegreeBearingImpl dbi = new DegreeBearingImpl(windDTO.trueWindBearingDeg);
drawScaledArrow(windDTO, dbi.getRadians(), index, pxLength, drawHead);
}
index++;
}
final String title = "Wind Field at " + windDTOList.size() + " points.";
getCanvas().setTitle(title);
}
}
protected void drawArrow(final SimulatorWindDTO windDTO, final double angle, final double length, final double weight, final int index, final boolean drawHead) {
final String msg = "Wind @ P" + index + ": time : " + windDTO.timepoint + " speed: " + windDTO.trueWindSpeedInKnots + "knots "
+ windDTO.trueWindBearingDeg;
logger.fine(msg);
final Context2d context2d = canvas.getContext2d();
context2d.setGlobalAlpha(0.2);
final PositionDTO position = windDTO.position;
final LatLng positionLatLng = LatLng.newInstance(position.latDeg, position.lngDeg);
final Point canvasPositionInPx = mapProjection.fromLatLngToDivPixel(positionLatLng);
final double x = canvasPositionInPx.getX() - getWidgetPosLeft();
final double y = canvasPositionInPx.getY() - getWidgetPosTop();
windFieldPoints.put(new ToolTip(x, y), windDTO);
final double dx = length * Math.sin(angle);
final double dy = -length * Math.cos(angle);
final double x1 = x + dx / 2;
final double y1 = y + dy / 2;
drawLine(x - dx / 2, y - dy / 2, x1, y1, weight, arrowColor);
final double theta = Math.atan2(-dy, dx);
final double hLength = Math.max(6.,6.+(10./(60.-10.))*Math.max(length-6.,0));
logger.finer("headlength: "+hLength+", arrowlength: "+length);
if (drawHead) {
drawHead(x1, y1, theta, hLength, weight);
}
//String text = "P" + index;// + NumberFormat.getFormat("0.00").format(windDTO.trueWindBearingDeg) + "�";
//drawPointWithText(x, y, text);
//drawPoint(x, y);
context2d.setGlobalAlpha(0.4);
}
protected void drawHead(final double x, final double y, final double theta, final double headLength, final double weight) {
double t = theta + (Math.PI / 4);
if (t > Math.PI) {
t -= 2 * Math.PI;
}
double t2 = theta - (Math.PI / 4);
if (t2 <= (-Math.PI)) {
t2 += 2 * Math.PI;
}
final double x1 = (x - Math.cos(t) * headLength);
final double y1 = (y + Math.sin(t) * headLength);
final double x1o = (x + Math.cos(t) * weight/2);
final double y1o = (y - Math.sin(t) * weight/2);
final double x2 = (x - Math.cos(t2) * headLength);
final double y2 = (y + Math.sin(t2) * headLength);
final double x2o = (x + Math.cos(t2) * weight/2);
final double y2o = (y - Math.sin(t2) * weight/2);
drawLine(x1o, y1o, x1, y1, weight, arrowHeadColor);
drawLine(x2o, y2o, x2, y2, weight, arrowHeadColor);
}
@Override
public void timeChanged(final Date newDate, Date oldDate) {
List<SimulatorWindDTO> windDTOToDraw = new ArrayList<SimulatorWindDTO>();
final SortedMap<Long, List<SimulatorWindDTO>> headMap = (timePointWindDTOMap.headMap(newDate.getTime()+1));
if (!headMap.isEmpty()) {
windDTOToDraw = headMap.get(headMap.lastKey());
}
logger.info("In WindFieldCanvasOverlay.drawWindField drawing " + windDTOToDraw.size() + " points" + " @ "
+ newDate);
drawWindField(windDTOToDraw);
}
@Override
public boolean shallStop() {
if (!this.isVisible() || timePointWindDTOMap == null || timer == null || timePointWindDTOMap.isEmpty()) {
return true;
}
if (timePointWindDTOMap.lastKey() < timer.getTime().getTime()) {
return true;
} else {
return false;
}
}
public void setTimer(final Timer timer) {
this.timer = timer;
}
public Timer getTimer() {
return timer;
}
}
@@ -1,26 +1,19 @@
package com.sap.sailing.gwt.ui.simulator;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.logging.Logger;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONNumber;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.maps.client.base.LatLng;
import com.google.gwt.maps.client.base.Point;
import com.sap.sailing.domain.common.dto.PositionDTO;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.gwt.ui.shared.SimulatorWindDTO;
import com.sap.sailing.gwt.ui.shared.WindFieldDTO;
import com.sap.sailing.gwt.ui.shared.WindFieldGenParamsDTO;
import com.sap.sailing.gwt.ui.simulator.racemap.FullCanvasOverlay;
import com.sap.sailing.gwt.ui.simulator.util.ToolTip;
import com.sap.sse.gwt.client.player.Timer;
/**
@@ -31,45 +24,216 @@ import com.sap.sse.gwt.client.player.Timer;
*
*/
public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements TimeListenerWithStoppingCriteria {
/** The wind field that is to be displayed in the overlay */
private WindFieldDTO windFieldDTO;
/**
* Map containing the windfield for easy retrieval with key as time point.
*/
private SortedMap<Long, List<SimulatorWindDTO>> timePointWindDTOMap;
protected WindFieldDTO windFieldDTO;
protected WindFieldGenParamsDTO windParams = null;
protected SimulatorMap simulatorMap;
/** The points where ToolTip is to be displayed */
private Map<ToolTip, SimulatorWindDTO> windFieldPoints;
private String arrowColor = "Black";
private String arrowHeadColor = "Blue";
private int xRes;
private boolean visible = false;
private Timer timer;
private static Logger logger = Logger.getLogger(WindStreamletsCanvasOverlay.class.getName());
public WindStreamletsCanvasOverlay(MapWidget map, int zIndex, final Timer timer, int xRes) {
super(map, zIndex);
public WindStreamletsCanvasOverlay(SimulatorMap simulatorMap, int zIndex, final Timer timer, final WindFieldGenParamsDTO windParams) {
super(simulatorMap.getMap(), zIndex);
this.simulatorMap = simulatorMap;
this.timer = timer;
this.xRes = xRes;
this.windParams = windParams;
windFieldDTO = null;
windFieldPoints = new HashMap<ToolTip, SimulatorWindDTO>();
getCanvas().getElement().setId("swarm-display");
timePointWindDTOMap = new TreeMap<Long, List<SimulatorWindDTO>>();
/*if (!this.isSwarmDataExt()) {
// random test windfield
JavaScriptObject swarmData = this.getJSONRandomWindData();
this.setSwarmData(swarmData);
}*/
}
public WindStreamletsCanvasOverlay(MapWidget map, int zIndex) {
this(map, zIndex, null, 0);
public JavaScriptObject getJSONRandomWindData() {
JSONObject jsonWindData = new JSONObject();
jsonWindData.put("timestamp", new JSONString("11:55 am on March 18, 2014"));
LatLng boundsSW = LatLng.newInstance(53.854617, 8.159124);
LatLng boundsNE = LatLng.newInstance(55.263922, 11.413824);
jsonWindData.put("x0", new JSONNumber(boundsSW.getLongitude()));
jsonWindData.put("y0", new JSONNumber(boundsSW.getLatitude()));
jsonWindData.put("x1", new JSONNumber(boundsNE.getLongitude()));
jsonWindData.put("y1", new JSONNumber(boundsNE.getLatitude()));
int maxSteps = 1;
int gridWidth = 100;
int gridHeight = 100;
jsonWindData.put("gridWidth", new JSONNumber(gridWidth));
jsonWindData.put("gridHeight", new JSONNumber(gridHeight));
JSONArray windField = new JSONArray();
for(int stp=0; stp < maxSteps; stp++) {
JSONArray vectorField = new JSONArray();
for(int idx=0; idx < (gridWidth*gridHeight*2); idx++) {
vectorField.set(idx, new JSONNumber((Math.random()-0.5)*10.0+3.0));
//windField.set(idx, new JSONNumber(10.0));
}
windField.set(stp, vectorField);
}
jsonWindData.put("field", windField);
return jsonWindData.getJavaScriptObject();
}
public native boolean isSwarmDataExt() /*-{
if ($wnd.swarmDataExt) {
return true;
} else {
return false;
}
}-*/;
public native String getSwarmData() /*-{
return JSON.stringify($wnd.swarmData);
}-*/;
public native void setSwarmData(JavaScriptObject swarmData) /*-{
$wnd.swarmData = swarmData;
}-*/;
private native void getJSNIWind(WindStreamletsCanvasOverlay wsc) /*-{
$wnd.getWindfromSimulator = function(idx) {
return wsc.@com.sap.sailing.gwt.ui.simulator.WindStreamletsCanvasOverlay::getWind(I)(idx);
};
}-*/;
private native JavaScriptObject getWindInst(double x, double y) /*-{
return {x:x, y:y};
}-*/;
public JavaScriptObject getWind(int idx){
SimulatorWindDTO wind = this.windFieldDTO.getMatrix().get(idx);
double y = wind.trueWindSpeedInKnots*Math.cos(wind.trueWindBearingDeg*Math.PI/180.0);
double x = wind.trueWindSpeedInKnots*Math.sin(wind.trueWindBearingDeg*Math.PI/180.0);
return getWindInst(x,y);
}
public native void setWindDataJSON(String jsonField) /*-{
eval(jsonField);
}-*/;
public WindStreamletsCanvasOverlay(SimulatorMap simulatorMap, int zIndex) {
this(simulatorMap, zIndex, null, null);
}
public native void setMapInstance(Object mapInstance) /*-{
$wnd.swarmMap = mapInstance;
}-*/;
public native void setCanvasProjectionInstance(Object instance) /*-{
$wnd.swarmCanvasProjection = instance;
}-*/;
public native void startStreamlets() /*-{
if ($wnd.swarmAnimator) {
$wnd.swarmUpdData = true;
$wnd.updateStreamlets($wnd.swarmUpdData);
} else {
$wnd.initStreamlets($wnd.swarmMap);
}
}-*/;
public native void setStreamletsStep(int step) /*-{
$wnd.swarmField.setStep(step);
}-*/;
public native void stopStreamlets() /*-{
if ($wnd.stopStreamlets) {
$wnd.stopStreamlets();
};
}-*/;
public void extendWindDataJSON() {
List<SimulatorWindDTO> data = this.windFieldDTO.getMatrix();
String jsonData = "data:[";
int p = 0;
int imax = this.windParams.getyRes() + 2*this.windParams.getBorderY();
int jmax = this.windParams.getxRes() + 2*this.windParams.getBorderX();
int steps = data.size() / (imax * jmax);
double maxWindSpeed = 0;
for(int s=0; s<steps; s++) {
jsonData +="[";
for(int i=0; i<imax; i++) {
jsonData +="[";
for(int j=0; j<jmax; j++) {
SimulatorWindDTO wind = data.get(p);
p++;
if (wind.trueWindSpeedInKnots > maxWindSpeed) {
maxWindSpeed = wind.trueWindSpeedInKnots;
}
double y = wind.trueWindSpeedInKnots*Math.cos(wind.trueWindBearingDeg*Math.PI/180.0);
double x = wind.trueWindSpeedInKnots*Math.sin(wind.trueWindBearingDeg*Math.PI/180.0);
jsonData += x + "," + y;
if (j<(jmax-1)) {
jsonData += ",";
}
}
if (i<(imax-1)) {
jsonData += "],";
} else {
jsonData += "]";
}
}
if (s<(steps-1)) {
jsonData += "],";
} else {
jsonData += "]";
}
}
this.windFieldDTO.windDataJSON += jsonData + "],maxLength:" + maxWindSpeed + "};";
}
public void setWindField(final WindFieldDTO windFieldDTO) {
this.windFieldDTO = windFieldDTO;
this.extendWindDataJSON();
this.setWindDataJSON(this.windFieldDTO.windDataJSON);
//this.getJSNIWind(this);
this.setMapInstance(this.simulatorMap.getMap().getJso());
this.setCanvasProjectionInstance(this.simulatorMap.getRegattaAreaCanvasOverlay().getMapProjection());
}
@Override
public boolean isVisible() {
return this.visible;
}
@Override
public void setVisible(boolean isVisible) {
if (getCanvas() != null) {
if (isVisible) {
this.startStreamlets();
if (timer.getTime().compareTo(this.windParams.getStartTime()) != 0) {
this.timeChanged(timer.getTime(), null);
}
this.visible = isVisible;
} else {
this.stopStreamlets();
this.visible = isVisible;
}
}
}
@Override
public void addToMap() {
super.addToMap();
if (timer != null) {
timer.addTimeListener(this);
}
@@ -77,190 +241,41 @@ public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements Ti
@Override
public void removeFromMap() {
super.removeFromMap();
if (timer != null) {
timer.removeTimeListener(this);
}
this.setVisible(false);
}
@Override
protected void drawCenterChanged() {
}
public void setWindField(final WindFieldDTO windField) {
this.windFieldDTO = windField;
timePointWindDTOMap.clear();
if (windField != null) {
for(final SimulatorWindDTO w : windField.getMatrix()) {
if (!timePointWindDTOMap.containsKey(w.timepoint)) {
timePointWindDTOMap.put(w.timepoint, new LinkedList<SimulatorWindDTO>());
}
timePointWindDTOMap.get(w.timepoint).add(w);
}
}
}
public void setArrowColor(final String arrowColor, final String arrowHeadColor) {
this.arrowColor = arrowColor;
this.arrowHeadColor = arrowHeadColor;
}
@Override
protected void draw() {
super.draw();
if (mapProjection != null && windFieldDTO != null) {
clear();
drawWindField();
// drawing is done by external JavaScript for Streamlets
}
}
private void clear() {
canvas.getContext2d().clearRect(0.0 /*canvas.getAbsoluteLeft()*/, 0.0/*canvas.getAbsoluteTop()*/,
canvas.getCoordinateSpaceWidth(), canvas.getCoordinateSpaceHeight());
windFieldPoints.clear();
}
protected void drawWindField() {
if (timer != null) {
timeChanged(timer.getTime(), null);
} else {
drawWindField(windFieldDTO.getMatrix());
}
}
protected void drawScaledArrow(final SimulatorWindDTO windDTO, final double angle, final int index, final double pxLength, final boolean drawHead) {
final double aWidth = 1.0;
drawArrow(windDTO, angle, pxLength, aWidth, index, drawHead);
}
protected void drawWindField(final List<SimulatorWindDTO> windDTOList) {
final boolean drawHead = false;
clear();
final Context2d context2d = canvas.getContext2d();
context2d.setGlobalAlpha(0.4);
if (windDTOList != null && windDTOList.size() > 0) {
Iterator<SimulatorWindDTO> windDTOIter = windDTOList.iterator();
final SimulatorWindDTO w0 = windDTOIter.next();
final SimulatorWindDTO w1 = windDTOIter.next();
final LatLng pg0 = LatLng.newInstance(w0.position.latDeg, w0.position.lngDeg);
final LatLng pg1 = LatLng.newInstance(w1.position.latDeg, w1.position.lngDeg);
final Point px0 = mapProjection.fromLatLngToDivPixel(pg0);
final Point px1 = mapProjection.fromLatLngToDivPixel(pg1);
final double dx = px0.getX()-px1.getX();
final double dy = px0.getY()-px1.getY();
final double pxLength = Math.sqrt( dx*dx + dy*dy );
logger.fine("pxLength = "+pxLength);
windDTOIter = windDTOList.iterator();
int index = 0;
while (windDTOIter.hasNext()) {
SimulatorWindDTO windDTO = windDTOIter.next();
//System.out.println("wind angle: "+index+", "+windDTO.trueWindBearingDeg);
if (((index % xRes) > 0)&&((index % xRes) < (xRes-1))) {
DegreeBearingImpl dbi = new DegreeBearingImpl(windDTO.trueWindBearingDeg);
drawScaledArrow(windDTO, dbi.getRadians(), index, pxLength, drawHead);
}
index++;
}
final String title = "Wind Field at " + windDTOList.size() + " points.";
getCanvas().setTitle(title);
}
}
protected void drawArrow(final SimulatorWindDTO windDTO, final double angle, final double length, final double weight, final int index, final boolean drawHead) {
final String msg = "Wind @ P" + index + ": time : " + windDTO.timepoint + " speed: " + windDTO.trueWindSpeedInKnots + "knots "
+ windDTO.trueWindBearingDeg;
logger.fine(msg);
final Context2d context2d = canvas.getContext2d();
context2d.setGlobalAlpha(0.2);
final PositionDTO position = windDTO.position;
final LatLng positionLatLng = LatLng.newInstance(position.latDeg, position.lngDeg);
final Point canvasPositionInPx = mapProjection.fromLatLngToDivPixel(positionLatLng);
final double x = canvasPositionInPx.getX() - getWidgetPosLeft();
final double y = canvasPositionInPx.getY() - getWidgetPosTop();
windFieldPoints.put(new ToolTip(x, y), windDTO);
final double dx = length * Math.sin(angle);
final double dy = -length * Math.cos(angle);
final double x1 = x + dx / 2;
final double y1 = y + dy / 2;
drawLine(x - dx / 2, y - dy / 2, x1, y1, weight, arrowColor);
final double theta = Math.atan2(-dy, dx);
final double hLength = Math.max(6.,6.+(10./(60.-10.))*Math.max(length-6.,0));
logger.finer("headlength: "+hLength+", arrowlength: "+length);
if (drawHead) {
drawHead(x1, y1, theta, hLength, weight);
}
//String text = "P" + index;// + NumberFormat.getFormat("0.00").format(windDTO.trueWindBearingDeg) + "�";
//drawPointWithText(x, y, text);
//drawPoint(x, y);
context2d.setGlobalAlpha(0.4);
}
protected void drawHead(final double x, final double y, final double theta, final double headLength, final double weight) {
double t = theta + (Math.PI / 4);
if (t > Math.PI) {
t -= 2 * Math.PI;
}
double t2 = theta - (Math.PI / 4);
if (t2 <= (-Math.PI)) {
t2 += 2 * Math.PI;
}
final double x1 = (x - Math.cos(t) * headLength);
final double y1 = (y + Math.sin(t) * headLength);
final double x1o = (x + Math.cos(t) * weight/2);
final double y1o = (y - Math.sin(t) * weight/2);
final double x2 = (x - Math.cos(t2) * headLength);
final double y2 = (y + Math.sin(t2) * headLength);
final double x2o = (x + Math.cos(t2) * weight/2);
final double y2o = (y - Math.sin(t2) * weight/2);
drawLine(x1o, y1o, x1, y1, weight, arrowHeadColor);
drawLine(x2o, y2o, x2, y2, weight, arrowHeadColor);
this.stopStreamlets();
}
@Override
public void timeChanged(final Date newTime, Date oldTime) {
List<SimulatorWindDTO> windDTOToDraw = new ArrayList<SimulatorWindDTO>();
final SortedMap<Long, List<SimulatorWindDTO>> headMap = (timePointWindDTOMap.headMap(newTime.getTime()+1));
if (!headMap.isEmpty()) {
windDTOToDraw = headMap.get(headMap.lastKey());
}
logger.info("In WindFieldCanvasOverlay.drawWindField drawing " + windDTOToDraw.size() + " points" + " @ "
+ newTime);
drawWindField(windDTOToDraw);
public void timeChanged(final Date newDate, Date oldDate) {
int step = (int)((newDate.getTime() - this.windParams.getStartTime().getTime()) / this.windParams.getTimeStep().getTime());
this.setStreamletsStep(step);
}
@Override
public boolean shallStop() {
if (!this.isVisible() || timePointWindDTOMap == null || timer == null || timePointWindDTOMap.isEmpty()) {
return true;
}
if (timePointWindDTOMap.lastKey() < timer.getTime().getTime()) {
return true;
} else {
return false;
}
if (timer.getTime().getTime() >= this.windParams.getEndTime().getTime()) {
return true;
} else {
return false;
}
}
public void setTimer(final Timer timer) {
@@ -50,7 +50,7 @@ public abstract class FullCanvasOverlay extends CanvasOverlayV3 implements Requi
@Override
public void onEvent(CenterChangeMapEvent event) {
// TODO Auto-generated method stub
draw();
drawCenterChanged();
};
});
@@ -86,6 +86,10 @@ public abstract class FullCanvasOverlay extends CanvasOverlayV3 implements Requi
});
}
protected void drawCenterChanged() {
draw();
}
@Override
protected void draw() {
if (mapProjection != null) {
@@ -3,7 +3,7 @@ package com.sap.sailing.gwt.ui.simulator.util;
public class ColorPaletteGenerator implements ColorPalette {
//private String[] colors = {"Green","Red","Blue","Yellow","Black"};
private String[] colors = {"#00ED00","#FFBB00","#FFEA00","#0092C7","#0092C7","#666666","Blue","Blue","Yellow","Black"};
private String[] colors = {"#00ED00","#FFBB00","#FFEA00","#0bf","#0bf","#808080","Blue","Blue","Yellow","Black"};
private int currentIndex = -1;
public ColorPaletteGenerator() {
@@ -29,7 +29,6 @@
<inherits name="com.sap.sse.SSECommon" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="de.csenk.gwt.ws.WebSocket" />
<!-- Fancy DateTimePicker (without the rest of Bootstrap!) -->
<!-- GWT-Bootstrap License: Apache License, Version 2.0 -->
@@ -6,7 +6,9 @@
<stylesheet src="../reset.css" />
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<inherits name='com.google.gwt.debug.Debug'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
@@ -1,51 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt-module.dtd">
<module>
<stylesheet src="../reset.css" />
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<!-- inherits name='com.google.gwt.user.theme.clean.Clean'/> -->
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../Simulator.css" />
<!-- Google Maps API -->
<inherits name='com.google.gwt.maps.Maps' />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<!-- Other module inherits -->
<inherits name="com.sap.sailing.gwt.ui.EmulatedJRE" />
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sse.SSECommon" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.simulator.Simulator" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.simulator.SimulatorEntryPoint'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='shared'/>
<source path='client'/>
<source path='actions'/>
<source path='simulator'/>
<inherits name='com.google.gwt.logging.Logging'/>
<set-property name="gwt.logging.enabled" value="FALSE"/>
<!-- Set logging level to INFO -->
<set-property name="gwt.logging.logLevel" value="INFO"/>
<set-property name="gwt.logging.simpleRemoteHandler" value="ENABLED" />
<set-property name="gwt.logging.consoleHandler" value="DISABLED" />
<set-property name="gwt.logging.popupHandler" value="DISABLED" />
<!-- Add compiler.stackMode to get a readable stacktrace from JavaScript
It generates a set of files in WEB-INF/deploy; those files need to
be placed on the server
-->
<set-property name="compiler.stackMode" value="emulated" />
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt-module.dtd">
<module>
<stylesheet src="../reset.css" />
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<!-- inherits name='com.google.gwt.user.theme.clean.Clean'/> -->
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../Simulator.css" />
<!-- Google Maps API -->
<inherits name='com.google.gwt.maps.Maps' />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<!-- Other module inherits -->
<inherits name="com.sap.sailing.gwt.ui.EmulatedJRE" />
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sse.SSECommon" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.simulator.Simulator" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.simulator.SimulatorEntryPoint'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='shared'/>
<source path='client'/>
<source path='actions'/>
<source path='simulator'/>
<script src="../js/wind-streamlets.js" />
<inherits name='com.google.gwt.logging.Logging'/>
<set-property name="gwt.logging.enabled" value="FALSE"/>
<!-- Set logging level to INFO -->
<set-property name="gwt.logging.logLevel" value="INFO"/>
<set-property name="gwt.logging.simpleRemoteHandler" value="ENABLED" />
<set-property name="gwt.logging.consoleHandler" value="DISABLED" />
<set-property name="gwt.logging.popupHandler" value="DISABLED" />
<!-- Add compiler.stackMode to get a readable stacktrace from JavaScript
It generates a set of files in WEB-INF/deploy; those files need to
be placed on the server
-->
<set-property name="compiler.stackMode" value="emulated" />
</module>
@@ -5,8 +5,9 @@ Bundle-SymbolicName: com.sap.sailing.selenium.test
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: SAP
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Require-Bundle: org.junit4;bundle-version="4.8.2",
org.openqa.selenium.osgi;bundle-version="2.39.0",
Require-Bundle: org.hamcrest;bundle-version="1.1.0",
org.junit4;bundle-version="4.8.2",
org.openqa.selenium.osgi;bundle-version="2.40.0",
com.sap.sailing.mongodb;bundle-version="1.0.0",
com.mongodb.driver;bundle-version="2.6.2",
com.sap.sailing.domain.common
@@ -19,7 +19,7 @@
The folder where screenshots (attachments) are stored.
-->
<screenshots-folder>
file:///home/hudson/repo/jobs/SAPSailingAnalytics-selenium/workspace/java/com.sap.sailing.selenium.test/bin/surefire-reports/
./bin/surefire-reports/
</screenshots-folder>
<!--
<screenshots-folder>file://{user.dir}/bin/surefire-reports/</screenshots-folder>
@@ -15,9 +15,7 @@
-->
<context-root>http://riccardo:riccardo@localhost:8888/</context-root>
<!--
<screenshots-folder>file:///C:/Users/D049941/screenshots/</screenshots-folder>
-->
<screenshots-folder>./bin/surefire-reports/</screenshots-folder>
<!--
In this section necessary system properties for the different web drivers can be provided if needed. For more
@@ -40,7 +38,7 @@
</system-property>
<system-property>
<name>webdriver.firefox.bin</name>
<value>/usr/bin/firefox</value>
<value>c:\Program Files (x86)\Mozilla Firefox\firefox.exe</value>
</system-property>
</system-properties>
@@ -21,7 +21,7 @@ public class AjaxCallsExecuted implements ExpectedCondition<Boolean> {
*/
public static final String CATEGORY_GLOBAL = ""; //$NON-NLS-1$
private static final String JAVASCRIPT = "return (window.PENDING_AJAX_CALLS.numberOfFinishedCalls(arguments[0]) === arguments[1])"; //$NON-NLS-1$
private static final String JAVASCRIPT = "return (window.PENDING_AJAX_CALLS.numberOfFinishedCalls(arguments[0]) >= arguments[1])"; //$NON-NLS-1$
private String category;
@@ -1,8 +1,8 @@
package com.sap.sailing.selenium.core;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -44,7 +44,7 @@ public class SeleniumRunner extends ParentRunner<SeleniumJUnit4ClassRunner> {
*/
protected class SeleniumJUnit4ClassRunner extends BlockJUnit4ClassRunner {
private String root;
private URL screenshots;
private File screenshotsFolder;
private DriverDefinition definition;
private TestEnvironmentImpl environment;
@@ -57,19 +57,18 @@ public class SeleniumRunner extends ParentRunner<SeleniumJUnit4ClassRunner> {
* The class containing the tests.
* @param root
* The context root (base URL) against the tests should be executed.
* @param screenshots
* @param screenshotsFolder
* The folder where screenshots should be stored.
* @param definition
* Definition of the web driver to use.
* @throws InitializationError
*
*/
public SeleniumJUnit4ClassRunner(Class<?> klass, String root, URL screenshots, DriverDefinition definition)
public SeleniumJUnit4ClassRunner(Class<?> klass, String root, File screenshotsFolder, DriverDefinition definition)
throws InitializationError {
super(klass);
this.root = root;
this.screenshots = screenshots;
this.screenshotsFolder = screenshotsFolder;
this.definition = definition;
}
@@ -178,7 +177,7 @@ public class SeleniumRunner extends ParentRunner<SeleniumJUnit4ClassRunner> {
Constructor<WebDriver> constructor = clazz.getConstructor(Capabilities.class);
WebDriver driver = constructor.newInstance(capabilities);
URL screenshots = resolveScreenshotFolder();
File screenshots = resolveScreenshotFolder();
return new TestEnvironmentImpl(driver, this.root, screenshots);
} catch (Exception exception) {
@@ -187,8 +186,8 @@ public class SeleniumRunner extends ParentRunner<SeleniumJUnit4ClassRunner> {
}
// TODO: Implement in a way that we construct a unique folder which is a subfolder of the defined one!
private URL resolveScreenshotFolder() {
return this.screenshots;
private File resolveScreenshotFolder() {
return this.screenshotsFolder;
}
private void setValueForField(Object instance, Field field, Object value) throws IllegalArgumentException,
@@ -254,11 +253,11 @@ public class SeleniumRunner extends ParentRunner<SeleniumJUnit4ClassRunner> {
}
TestClass test = getTestClass();
URL screenshotsStorage = (configuration.screenshotsEnabled() ? new URL(resolveScreenshotFolder(screenshotsFolder)) : null);
File screenshotsStorage = (configuration.screenshotsEnabled() ? new File(resolveScreenshotFolder(screenshotsFolder)) : null);
for (DriverDefinition defenition : configuration.getDriverDefinitions()) {
for (DriverDefinition definition : configuration.getDriverDefinitions()) {
SeleniumJUnit4ClassRunner child = new SeleniumJUnit4ClassRunner(test.getJavaClass(), contextRoot,
screenshotsStorage, defenition);
screenshotsStorage, definition);
this.children.add(child);
}
@@ -1,6 +1,6 @@
package com.sap.sailing.selenium.core;
import java.net.URL;
import java.io.File;
import org.openqa.selenium.WebDriver;
@@ -45,5 +45,5 @@ public interface TestEnvironment {
* @return
* The folder where screenshots should be stored.
*/
public URL getScreenshotFolder();
public File getScreenshotFolder();
}
@@ -140,9 +140,9 @@ public class TestEnvironmentConfiguration {
String contextRoot = XMLHelper.getContentTextNS(testEnvironmentNode, CONTEXT_ROOT, NAMESPACE_URI);
String screenshotsFolder = XMLHelper.getContentTextNS(testEnvironmentNode, SCREENSHOTS_FOLDER, NAMESPACE_URI);
Map<String, String> systemProperties = createSystemProperties(testEnvironmentNode);
List<DriverDefinition> driverDefenitions = createDriverDefinitions(testEnvironmentNode);
List<DriverDefinition> driverDefinitions = createDriverDefinitions(testEnvironmentNode);
return new TestEnvironmentConfiguration(contextRoot, screenshotsFolder, systemProperties, driverDefenitions);
return new TestEnvironmentConfiguration(contextRoot, screenshotsFolder, systemProperties, driverDefinitions);
}
private static synchronized Document readTestConfiguration() throws ParserConfigurationException,
@@ -229,11 +229,11 @@ public class TestEnvironmentConfiguration {
private List<DriverDefinition> definitions;
private TestEnvironmentConfiguration(String root, String screenshots, Map<String, String> properties,
List<DriverDefinition> defenitions) {
List<DriverDefinition> definitions) {
this.root = root;
this.screenshotsFolder = screenshots;
this.properties = properties;
this.definitions = defenitions;
this.definitions = definitions;
}
/**
@@ -83,7 +83,11 @@ public class WindowManager {
* @return
*/
public WebDriverWindow openNewWindow() {
return openNewWindow("");
return openNewWindow(false);
}
public WebDriverWindow openNewWindow(boolean focus) {
return openNewWindow("", focus);
}
/**
@@ -93,7 +97,17 @@ public class WindowManager {
* @return
*/
public WebDriverWindow openNewWindow(String url) {
return new WebDriverWindow(this.driver, createWindow(url));
return openNewWindow(url, false);
}
public WebDriverWindow openNewWindow(String url, boolean focus) {
WebDriverWindow window = new WebDriverWindow(this.driver, createWindow(url));
if(focus) {
window.switchToWindow();
}
return window;
}
private String createWindow(String url) {
@@ -1,6 +1,6 @@
package com.sap.sailing.selenium.core.impl;
import java.net.URL;
import java.io.File;
import org.openqa.selenium.WebDriver;
@@ -17,7 +17,7 @@ public class TestEnvironmentImpl implements TestEnvironment {
private WebDriver driver;
private WindowManager manager;
private String root;
private URL screenshots;
private File screenshotsFolder;
/**
* <p>Creates a new description of the test environment in which a test is executed.</p>
@@ -26,13 +26,13 @@ public class TestEnvironmentImpl implements TestEnvironment {
* The web driver used for the execution of the test.
* @param root
* The context root (base URL) against the tests should be executed.
* @param screenshots
* @param screenshotsFolder
* The folder where screenshots should be stored.
*/
public TestEnvironmentImpl(WebDriver driver, String root, URL screenshots) {
public TestEnvironmentImpl(WebDriver driver, String root, File screenshotsFolder) {
this.driver = driver;
this.root = root;
this.screenshots = screenshots;
this.screenshotsFolder = screenshotsFolder;
this.manager = new WindowManager(driver);
}
@@ -53,8 +53,8 @@ public class TestEnvironmentImpl implements TestEnvironment {
}
@Override
public URL getScreenshotFolder() {
return this.screenshots;
public File getScreenshotFolder() {
return this.screenshotsFolder;
}
/**
@@ -64,6 +64,6 @@ public class TestEnvironmentImpl implements TestEnvironment {
this.driver.quit();
this.driver = null;
this.root = null;
this.screenshots = null;
this.screenshotsFolder = null;
}
}
@@ -9,18 +9,39 @@ import org.openqa.selenium.WebElement;
import com.sap.sailing.selenium.core.BySeleniumId;
import com.sap.sailing.selenium.core.FindBy;
import com.sap.sailing.selenium.pages.PageArea;
import com.sap.sailing.selenium.pages.adminconsole.ActionsHelper;
import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaListCompositePO.RegattaDescriptor;
import com.sap.sailing.selenium.pages.gwt.CellTablePO;
import com.sap.sailing.selenium.pages.gwt.DataEntryPO;
import com.sap.sailing.selenium.pages.gwt.GenericCellTablePO;
public class LeaderboardConfigurationPanelPO extends PageArea {
public static class LeaderboardEntryPO extends DataEntryPO {
public LeaderboardEntryPO(CellTablePO<?> table, WebElement element) {
super(table, element);
}
protected LeaderboardEntryPO() {
super();
}
@Override
public String getIdentifier() {
return getName();
}
public String getName() {
return getColumnContent(0);
}
public String getLeaderboardURL() {
WebElement link = this.context.findElement(By.xpath(".//td/div/a"));
return link.getAttribute("href");
}
}
@FindBy(how = BySeleniumId.class, using = "CreateFlexibleLeaderboardButton")
private WebElement createFlexibleLeaderboardButton;
@@ -75,7 +96,7 @@ public class LeaderboardConfigurationPanelPO extends PageArea {
}
public void deleteLeaderboard(String leaderboard) {
DataEntryPO entry = findLeaderboard(leaderboard);
LeaderboardEntryPO entry = findLeaderboard(leaderboard);
if(entry != null) {
WebElement removeAction = ActionsHelper.findRemoveAction(entry.getWebElement());
@@ -88,12 +109,10 @@ public class LeaderboardConfigurationPanelPO extends PageArea {
}
public String getLeaderboardURL(String leaderboard) {
DataEntryPO entry = findLeaderboard(leaderboard);
LeaderboardEntryPO entry = findLeaderboard(leaderboard);
if(entry != null) {
WebElement link = entry.getWebElement().findElement(By.xpath(".//td/div/a"));
return link.getAttribute("href");
return entry.getLeaderboardURL();
}
return null;
@@ -102,48 +121,35 @@ public class LeaderboardConfigurationPanelPO extends PageArea {
public List<String> getAvailableLeaderboards() {
List<String> leaderboards = new ArrayList<>();
CellTablePO<DataEntryPO> table = getLeaderboardTable();
List<DataEntryPO> entries = table.getEntries();
CellTablePO<LeaderboardEntryPO> table = getLeaderboardTable();
List<LeaderboardEntryPO> entries = table.getEntries();
for(DataEntryPO entry : entries) {
leaderboards.add(entry.getColumnContent(0));
for(LeaderboardEntryPO entry : entries) {
leaderboards.add(entry.getIdentifier());
}
return leaderboards;
}
public LeaderboardDetailsPanelPO getLeaderboardDetails(String leaderboard) {
CellTablePO<DataEntryPO> table = getLeaderboardTable();
List<DataEntryPO> entries = table.getEntries();
LeaderboardEntryPO entry = findLeaderboard(leaderboard);
for(DataEntryPO entry : entries) {
String name = entry.getColumnContent(0);
if(leaderboard.equals(name)) {
entry.select();
return new LeaderboardDetailsPanelPO(this.driver, this.leaderboardDetailsPanel);
}
if(entry == null) {
return null;
}
return null;
entry.select();
return new LeaderboardDetailsPanelPO(this.driver, this.leaderboardDetailsPanel);
}
private CellTablePO<DataEntryPO> getLeaderboardTable() {
return new GenericCellTablePO<>(this.driver, this.leaderboardsCellTable, DataEntryPO.class);
private CellTablePO<LeaderboardEntryPO> getLeaderboardTable() {
return new GenericCellTablePO<>(this.driver, this.leaderboardsCellTable, LeaderboardEntryPO.class);
}
private DataEntryPO findLeaderboard(String leaderboard) {
CellTablePO<DataEntryPO> table = getLeaderboardTable();
private LeaderboardEntryPO findLeaderboard(String name) {
CellTablePO<LeaderboardEntryPO> table = getLeaderboardTable();
for(DataEntryPO entry : table.getEntries()) {
String name = entry.getColumnContent(0);
if(leaderboard.equals(name)) {
return entry;
}
}
return null;
return table.getEntry(name);
}
}
@@ -9,11 +9,11 @@ import com.sap.sailing.selenium.core.FindBy;
import com.sap.sailing.selenium.pages.common.DataEntryDialogPO;
public class RegattaCreateDialogPO extends DataEntryDialogPO {
@FindBy(how = BySeleniumId.class, using = "RegattaNameTextField")
private WebElement regattaNameTextField;
@FindBy(how = BySeleniumId.class, using = "NameTextBox")
private WebElement nameTextBox;
@FindBy(how = BySeleniumId.class, using = "BoatClassTextField")
private WebElement boatClassTextField;
@FindBy(how = BySeleniumId.class, using = "BoatClassTextBox")
private WebElement boatClassTextBox;
// @FindBy(how = BySeleniumId.class, using = "ScoringSchemeListBox")
// private WebElement scoringSystemDropDown;
@@ -30,13 +30,13 @@ public class RegattaCreateDialogPO extends DataEntryDialogPO {
}
public void setRegattaName(String name) {
this.regattaNameTextField.clear();
this.regattaNameTextField.sendKeys(name);
this.nameTextBox.clear();
this.nameTextBox.sendKeys(name);
}
public void setBoatClass(String boatClass) {
this.boatClassTextField.clear();
this.boatClassTextField.sendKeys(boatClass);
this.boatClassTextBox.clear();
this.boatClassTextBox.sendKeys(boatClass);
}
// TODO: Scoring System, Event and Course Area
@@ -9,8 +9,8 @@ import com.sap.sailing.selenium.core.FindBy;
import com.sap.sailing.selenium.pages.common.DataEntryDialogPO;
public class SeriesCreateDialogPO extends DataEntryDialogPO {
@FindBy(how = BySeleniumId.class, using = "NameTextField")
private WebElement seriesNameTextField;
@FindBy(how = BySeleniumId.class, using = "NameTextBox")
private WebElement nameTextBox;
// @FindBy(how = BySeleniumId.class, using = "MedalSeriesCheckbox")
// private WebElement medalSeriesCheckbox;
@@ -32,8 +32,8 @@ public class SeriesCreateDialogPO extends DataEntryDialogPO {
}
public void setSeriesName(String name) {
this.seriesNameTextField.clear();
this.seriesNameTextField.sendKeys(name);
this.nameTextBox.clear();
this.nameTextBox.sendKeys(name);
}
// TODO: Checkboxes and Fleets
@@ -1,12 +1,15 @@
package com.sap.sailing.selenium.pages.adminconsole.regatta;
import java.util.Arrays;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Select;
import com.sap.sailing.selenium.core.BySeleniumId;
import com.sap.sailing.selenium.core.FindBy;
import com.sap.sailing.selenium.pages.common.DataEntryDialogPO;
public class SeriesEditDialogPO extends DataEntryDialogPO {
@@ -23,8 +26,11 @@ public class SeriesEditDialogPO extends DataEntryDialogPO {
@FindBy(how = BySeleniumId.class, using = "DefinesResultDiscardingRulesCheckbox")
private WebElement definesResultDiscardingRulesCheckbox;
@FindBy(how = BySeleniumId.class, using = "NumberOfRacesListBox")
private WebElement numberOfRacesDropDown;
@FindBy(how = BySeleniumId.class, using = "AddRacesFromListBox")
private WebElement addRacesFromListBox;
@FindBy(how = BySeleniumId.class, using = "AddRacesToListBox")
private WebElement addRacesToListBox;
@FindBy(how = BySeleniumId.class, using = "RaceNamePrefixTextBox")
private WebElement raceNamePrefixTextField;
@@ -36,15 +42,27 @@ public class SeriesEditDialogPO extends DataEntryDialogPO {
super(driver, element);
}
public int getSetNumberOfRacesToAdd() {
Select select = new Select(this.numberOfRacesDropDown);
public int getFromNumberOfRacesToAdd() {
Select select = new Select(this.addRacesFromListBox);
WebElement option = select.getFirstSelectedOption();
return Integer.parseInt(option.getAttribute("value"));
}
public void setSetNumberOfRacesToAdd(int races) {
Select select = new Select(this.numberOfRacesDropDown);
public void setFromNumberOfRacesToAdd(int races) {
Select select = new Select(this.addRacesFromListBox);
select.selectByValue(Integer.toString(races));
}
public int getToNumberOfRacesToAdd() {
Select select = new Select(this.addRacesToListBox);
WebElement option = select.getFirstSelectedOption();
return Integer.parseInt(option.getAttribute("value"));
}
public void setToNumberOfRacesToAdd(int races) {
Select select = new Select(this.addRacesToListBox);
select.selectByValue(Integer.toString(races));
}
@@ -61,14 +79,50 @@ public class SeriesEditDialogPO extends DataEntryDialogPO {
this.addRacesButton.click();
}
public void addRaces(int races) {
setSetNumberOfRacesToAdd(races);
public void addRaces(int from, int to) {
setFromNumberOfRacesToAdd(from);
setToNumberOfRacesToAdd(to);
pressAddRaces();
}
public void addRaces(int races, String prefix) {
setSetNumberOfRacesToAdd(races);
public void addRaces(int from, int to, String prefix) {
setFromNumberOfRacesToAdd(from);
setToNumberOfRacesToAdd(to);
setRaceNamePrefix(prefix);
pressAddRaces();
}
public void renameRace(String race, String newName) {
for(WebElement editorRow : getRaceNameEditors()) {
WebElement valueTextBox = findElementBySeleniumId(editorRow, "ValueTextBox");
String raceName = valueTextBox.getAttribute("value");
if(raceName.equals(race)) {
valueTextBox.clear();
valueTextBox.sendKeys(newName);
}
}
}
public void deleteRace(String race) {
deleteRaces(Arrays.asList(race));
}
public void deleteRaces(List<String> races) {
for(WebElement editorRow : getRaceNameEditors()) {
WebElement valueTextBox = findElementBySeleniumId(editorRow, "ValueTextBox");
if(races.contains(valueTextBox.getAttribute("value"))) {
WebElement removeButton = findElementBySeleniumId(editorRow, "RemoveButton");
removeButton.click();
}
}
}
private List<WebElement> getRaceNameEditors() {
WebElement raceNamesEditor = findElementBySeleniumId("RaceNamesStringListEditorComposite");
WebElement raceNamesGrid = findElementBySeleniumId(raceNamesEditor, "ExpandedValuesGrid");
return raceNamesGrid.findElements(By.tagName("tr"));
}
}
@@ -141,7 +141,7 @@ public class TrackedRacesListPO extends PageArea {
// return null;
// }
public Object getStatus(TrackedRaceDescriptor race) {
public Status getStatus(TrackedRaceDescriptor race) {
List<Status> status = getStatus(Arrays.asList(race));
return status.get(0);
@@ -169,15 +169,19 @@ public class TrackedRacesListPO extends PageArea {
}
public void stopTracking(TrackedRaceDescriptor race) {
stopTracking(Arrays.asList(race));
stopTracking(Arrays.asList(race), false);
}
public void stopTrackingAndWaitForFinshed(TrackedRaceDescriptor race) {
stopTracking(Arrays.asList(race), true);
}
public void stopTracking(List<TrackedRaceDescriptor> races) {
selectRaces(races);
this.stopTrackingButton.click();
waitForAjaxRequests();
stopTracking(races, false);
}
public void stopTrackingAndWaitForFinshed(List<TrackedRaceDescriptor> races) {
stopTracking(races, true);
}
public void remove(TrackedRaceDescriptor race) {
@@ -198,19 +202,20 @@ public class TrackedRacesListPO extends PageArea {
waitForAjaxRequests();
}
public void waitForTrackedRace(TrackedRaceDescriptor race) {
waitForTrackedRaces(Arrays.asList(race));
public void waitForTrackedRace(TrackedRaceDescriptor race, Status status) {
waitForTrackedRaces(Arrays.asList(race), status);
}
public void waitForTrackedRace(TrackedRaceDescriptor race, int timeout) {
waitForTrackedRaces(Arrays.asList(race), timeout);
public void waitForTrackedRace(TrackedRaceDescriptor race, Status status, int timeout) {
waitForTrackedRaces(Arrays.asList(race), status, timeout);
}
public void waitForTrackedRaces(List<TrackedRaceDescriptor> races) {
waitForTrackedRaces(races, DEFAULT_WAIT_TIMEOUT);
public void waitForTrackedRaces(List<TrackedRaceDescriptor> races, Status status) {
waitForTrackedRaces(races, status, DEFAULT_WAIT_TIMEOUT);
}
public void waitForTrackedRaces(List<TrackedRaceDescriptor> races, int timeout) {
public void waitForTrackedRaces(List<TrackedRaceDescriptor> races, Status status, int timeout) {
final Status statusToWaitFor = status;
FluentWait<List<TrackedRaceDescriptor>> wait = createFluentWait(races, timeout, DEFAULT_POLLING_INTERVAL);
wait.until(new Function<List<TrackedRaceDescriptor>, Object>() {
@Override
@@ -219,7 +224,7 @@ public class TrackedRacesListPO extends PageArea {
refresh();
for(Status status : getStatus(races)) {
if(status != Status.TRACKING)
if(status != statusToWaitFor)
return Boolean.FALSE;
}
} catch(TimeoutException exception) {
@@ -244,6 +249,18 @@ public class TrackedRacesListPO extends PageArea {
// }
// }
public void stopTracking(List<TrackedRaceDescriptor> races, boolean waitForFinished) {
selectRaces(races);
this.stopTrackingButton.click();
waitForAjaxRequests();
if(waitForFinished) {
waitForTrackedRaces(races, Status.FINISHED);
}
}
private CellTablePO<DataEntryPO> getTrackedRacesTable() {
// if(!this.trackedRacesTable.isDisplayed()) {
// return null;
@@ -7,9 +7,12 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import com.sap.sailing.selenium.core.FindBy;
@@ -199,10 +202,14 @@ public class TracTracEventManagementPanelPO extends PageArea {
return regatta;
}
public void setReggataForTracking(RegattaDescriptor regatta) {
public void setReggataForTracking(String regatta) {
Select select = new Select(this.availableRegattasListBox);
select.selectByValue(regatta.toString());
select.selectByValue(regatta);
}
public void setReggataForTracking(RegattaDescriptor regatta) {
setReggataForTracking(regatta.toString());
}
/**
@@ -249,9 +256,10 @@ public class TracTracEventManagementPanelPO extends PageArea {
this.startTrackingButton.click();
// TODO: Dialog ignore
ExpectedCondition<Alert> condition = ExpectedConditions.alertIsPresent();
waitForAjaxRequests();
if(condition.apply(this.driver) == null)
waitForAjaxRequests();
}
public TrackedRacesListPO getTrackedRacesList() {
@@ -7,4 +7,6 @@ public interface CSSConstants {
public static final String CSS_STYLE_ATTRIBUTE_NAME = "style"; //$NON-NLS-1$
public static final String CSS_BACKGROUND_IMAGE = "background-image"; //$NON-NLS-1$
public static final String CSS_BACKGROUND_COLOR = "background-color"; //$NON-NLS-1$
}
@@ -6,31 +6,52 @@ import java.util.List;
import org.openqa.selenium.WebElement;
public class CSSHelper {
public class CSSHelper {
/**
* <p>Creates an XPath 1.0 predicate that matches if an element has the given style sheet class in its "class"
* attribute.</p>
*
* @param className
* The name of the style sheet class to check for.
* @return
* An XPath predicate that matches if an element has the given style sheet class in its "class" attribute.
*/
public static String containsCSSClassPredicate(String className) {
return "contains(concat(' ',normalize-space(@class),' '),' " + className + " ')";
}
public static String containsCSSClassesPredicate(String... classNames) {
StringBuilder builder = new StringBuilder(70 * classNames.length);
for(String className : classNames) {
builder.append(containsCSSClassPredicate(className));
builder.append(" and ");
}
return builder.substring(0, builder.length() - 5);
}
public static List<String> getCSSClassNames(WebElement element) {
String cssClasses = element.getAttribute(CSSConstants.CSS_CLASS_ATTRIBUTE_NAME);
if(cssClasses == null)
return Collections.emptyList();
ArrayList<String> cssClassNames = new ArrayList<>();
for(String part : cssClasses.split(" ")) {
String cssClass = part.trim();
if(!cssClass.isEmpty())
cssClassNames.add(cssClass);
final List<String> result;
if (cssClasses == null) {
result = Collections.emptyList();
} else {
ArrayList<String> cssClassNames = new ArrayList<>();
for (String part : cssClasses.split(" ")) {
String cssClass = part.trim();
if (!cssClass.isEmpty()) {
cssClassNames.add(cssClass);
}
}
result = cssClassNames;
}
return cssClassNames;
return result;
}
public static boolean hasCSSClass(WebElement element, String cssClass) {
if(cssClass == null || cssClass.isEmpty())
if (cssClass == null || cssClass.isEmpty()) {
return true;
}
List<String> cssClasses = getCSSClassNames(element);
return cssClasses.contains(cssClass);
}
@@ -1,7 +1,10 @@
package com.sap.sailing.selenium.pages.common;
import org.openqa.selenium.Alert;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
import com.sap.sailing.selenium.core.BySeleniumId;
import com.sap.sailing.selenium.core.FindBy;
@@ -46,12 +49,24 @@ public abstract class DataEntryDialogPO extends PageArea {
return this.cancelButton.isEnabled();
}
// QUESTION: What should we do, if the button is not enabled?
public void pressOk() {
pressOk(false);
}
public void pressOk(boolean accept) {
this.okButton.click();
// Wait, since we do a callback usually
waitForAjaxRequests();
ExpectedCondition<Alert> condition = ExpectedConditions.alertIsPresent();
Alert alert = condition.apply(this.driver);
if(alert != null && accept) {
alert.accept();
}
if(alert == null || accept) {
// Wait, since we do a callback usually
waitForAjaxRequests();
}
}
public void pressCancel() {
@@ -1,9 +1,9 @@
package com.sap.sailing.selenium.pages.gwt;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
@@ -43,11 +43,13 @@ public abstract class CellTablePO<T extends DataEntryPO> extends PageArea {
protected static final String FOOT_TAG_NAME = "tfoot"; //$NON-NLS-1$
private static final String TABLE_HEADER_XPATH = "./thead/tr/th";
protected static final String TABLE_HEADER_XPATH = "./thead/tr/th";
protected static final String GWT_HEADER_XPATH = "./thead/tr//*[@__gwt_header]";
private static final String SORTING_INDICATOR_XPATH = ".//div/div/img";
private static final String LOADING_ANIMATION_XPATH = ".//td/div/div/div/img";
private static final String LOADING_ANIMATION_XPATH = "./td/div/div/div/img";
// It seems that the css class is not allways the same
//private static final String CELL_TABLE_CSS_CLASS = "GJTB2DRDFQ"; //$NON-NLS-1$
@@ -187,6 +189,28 @@ public abstract class CellTablePO<T extends DataEntryPO> extends PageArea {
return entries;
}
public T getEntry(Object identifier) {
for(T entry : getEntries()) {
if(Objects.equals(identifier, entry.getIdentifier())) {
return entry;
}
}
return null;
}
public List<T> getEntries(List<?> identifiers) {
List<T> entries = new ArrayList<>();
for(T entry : getEntries()) {
if(identifiers.contains(entry.getIdentifier())) {
entries.add(entry);
}
}
return entries;
}
/**
* <p>Selects the specified entry.</p>
*
@@ -261,27 +285,17 @@ public abstract class CellTablePO<T extends DataEntryPO> extends PageArea {
}
protected List<WebElement> getRows() {
List<WebElement> bodies = this.context.findElements(By.tagName(BODY_TAG_NAME));
for(WebElement body : bodies) {
if(!body.isDisplayed())
continue;
List<WebElement> rows = this.context.findElements(By.xpath("./tbody/tr"));
Iterator<WebElement> iterator = rows.iterator();
List<WebElement> rows = body.findElements(By.tagName("tr"));
while(iterator.hasNext()) {
WebElement row = iterator.next();
Iterator<WebElement> iterator = rows.iterator();
while(iterator.hasNext()) {
WebElement row = iterator.next();
if(isRowForLoadingIndicatorOrEmptyTableWidget(row))
iterator.remove();
}
return rows;
if(!row.isDisplayed() || isRowForLoadingIndicatorOrEmptyTableWidget(row))
iterator.remove();
}
return Collections.emptyList();
return rows;
}
protected abstract T createDataEntry(WebElement element);
@@ -294,7 +308,7 @@ public abstract class CellTablePO<T extends DataEntryPO> extends PageArea {
private boolean isRowForLoadingIndicatorOrEmptyTableWidget(WebElement row) {
List<WebElement> images = row.findElements(By.xpath(LOADING_ANIMATION_XPATH));
if(images.isEmpty() || images.size() > 1)
if(images.size() != 1)
return false;
String image = images.get(0).getAttribute("src");
@@ -10,12 +10,12 @@ import com.sap.sailing.selenium.pages.PageArea;
import com.sap.sailing.selenium.pages.common.CSSHelper;
public class CheckBoxPO extends PageArea {
protected static final String CHECKBOX_TAG_NAME = "span"; //$NON-NLS-1$
protected static final String TAG_NAME = "span"; //$NON-NLS-1$
private static final String CHECKBOX_CSS_CLASS = "gwt-CheckBox";
@FindBy(how = ByTagName.class, using = "input")
private WebElement checkbox;
private WebElement input;
@FindBy(how = ByTagName.class, using = "label")
private WebElement label;
@@ -29,12 +29,12 @@ public class CheckBoxPO extends PageArea {
WebElement element = (WebElement) this.context;
String tagName = element.getTagName();
if(!CHECKBOX_TAG_NAME.equalsIgnoreCase(tagName) || !CSSHelper.hasCSSClass(element, CHECKBOX_CSS_CLASS))
if(!TAG_NAME.equalsIgnoreCase(tagName) || !CSSHelper.hasCSSClass(element, getCssClassName()))
throw new IllegalArgumentException("WebElement does not represent a CheckBox");
}
public boolean isEnabled() {
return this.checkbox.isEnabled();
return this.input.isEnabled();
}
public String getLabel() {
@@ -42,11 +42,15 @@ public class CheckBoxPO extends PageArea {
}
public boolean isSelected() {
return this.checkbox.isSelected();
return this.input.isSelected();
}
public void setSelected(boolean selected) {
if(selected != isSelected())
this.checkbox.click();
this.input.click();
}
protected String getCssClassName() {
return CHECKBOX_CSS_CLASS;
}
}
@@ -2,48 +2,61 @@ package com.sap.sailing.selenium.pages.gwt;
import java.util.List;
import org.openqa.selenium.By.ByTagName;
import org.openqa.selenium.By.ByXPath;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Action;
import org.openqa.selenium.interactions.ClickAction;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.interactions.CompositeAction;
import org.openqa.selenium.interactions.HasInputDevices;
import org.openqa.selenium.interactions.KeyDownAction;
import org.openqa.selenium.interactions.KeyUpAction;
import org.openqa.selenium.interactions.Keyboard;
import org.openqa.selenium.interactions.Mouse;
import org.openqa.selenium.interactions.MoveToOffsetAction;
import org.openqa.selenium.internal.Locatable;
import com.sap.sailing.selenium.core.FindBy;
import com.sap.sailing.selenium.pages.common.CSSHelper;
public class DataEntryPO extends CellTableRowPO {
protected static final String CELL_TAG_NAME = "td"; //$NON-NLS-1$
@FindBy(how = ByTagName.class, using = CELL_TAG_NAME)
@FindBy(how = ByXPath.class, using = "./td")
private List<WebElement> columns;
public DataEntryPO(CellTablePO<?> table, WebElement element) {
super(table, element);
}
public DataEntryPO() {
protected DataEntryPO() {
super();
}
public int getNumberOfColumns() {
return this.columns.size();
}
public String getColumnContent(int column) {
return this.columns.get(column).getText();
return this.columns.get(column).getText().trim();
}
public String getColumnContent(String name) {
return getColumnContent(this.table.getColumnIndex(name));
}
/**
* <p>Returns an identifier for data entry that uniquely identifies the entry in the containing table. The default
* implementation simply returns the underlying web element, but subclasses should overwrite this method and
* return a more meaningful value. An example would be the String value of one ore more columns.</p>
*
* @return
* An identifier that uniquely identifies the entry in the containing table.
*/
public Object getIdentifier() {
// TODO: Test if its valid to return the context (the web element)
// To verify this take the key of an entry and ask the table for the entry with this key!
return this.context;
}
public boolean isSelected() {
return CSSHelper.hasCSSClass((WebElement) this.context, CellTablePO.SELECTED_ROW_CSS_CLASS);
}
@@ -68,26 +81,33 @@ public class DataEntryPO extends CellTableRowPO {
}
protected Action getSelectAction() {
HasInputDevices devices = (HasInputDevices) this.driver;
Mouse mouse = devices.getMouse();
Locatable locatable = getLocatableForSelect();
Actions actions = new Actions(this.driver);
actions.moveToElement(getElementForSelect(), 1, 1);
actions.click();
CompositeAction action = new CompositeAction();
action.addAction(new MoveToOffsetAction(mouse, locatable, 1, 1));
action.addAction(new ClickAction(mouse, null));
return action;
return actions.build();
}
protected Locatable getLocatableForSelect() {
return (Locatable) (this.columns.isEmpty() ? this.context : this.columns.get(0));
/**
* <p>Returns the element on which to click to select or deselect the data entry in the table. The default
* implementation returns the first column or the row if there are no columns. It may be necessary to overwrite
* this method for the case the first column contains a widget that should not be clicked accidentally.</p>
*
* @return
* The element on which to click to select or deselect the data entry in the table.
*/
protected WebElement getElementForSelect() {
return (this.columns.isEmpty() ? getWebElement() : this.columns.get(0));
}
protected Action getModifiedSelectAction() {
CompositeAction action = getModifiedCompositeActionAction();
action.addAction(getSelectAction());
Actions actions = new Actions(this.driver);
actions.keyDown(Keys.CONTROL);
actions.moveToElement(getElementForSelect(), 1, 1);
actions.click();
actions.keyUp(Keys.CONTROL);
return action;
return actions.build();
}
protected CompositeAction getModifiedCompositeActionAction() {
@@ -65,19 +65,19 @@ public class GenericCellTablePO<T extends DataEntryPO> extends CellTablePO<T> {
*/
@Override
public <S extends CellTablePO<T>> T createEntry(S table, WebElement element) {
Class<?> clazz = table.getClass();
while(clazz != null) {
try {
Constructor<T> constructor = this.type.getConstructor(clazz, WebElement.class);
Class<?> clazz = table.getClass();
while(clazz != null) {
try {
Constructor<T> constructor = this.type.getConstructor(clazz, WebElement.class);
return constructor.newInstance(table, element);
} catch (Exception exception) {
clazz = clazz.getSuperclass();
}
}
throw new RuntimeException("Can't create DataEntry of type " + this.type);
} catch (Exception exception) {
clazz = clazz.getSuperclass();
}
}
throw new RuntimeException("Can't create DataEntry of type " + this.type);
}
}
@@ -0,0 +1,16 @@
package com.sap.sailing.selenium.pages.gwt;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
public class RadioButtonPO extends CheckBoxPO {
private static final String RADIO_BUTTON_CSS_CLASS = "gwt-RadioButton";
public RadioButtonPO(WebDriver driver, WebElement element) {
super(driver, element);
}
protected String getCssClassName() {
return RADIO_BUTTON_CSS_CLASS;
}
}
@@ -0,0 +1,25 @@
package com.sap.sailing.selenium.pages.highcharts;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import com.sap.sailing.selenium.pages.PageArea;
import com.sap.sailing.selenium.pages.common.CSSHelper;
public class Chart extends PageArea {
private static final String TAG_NAME = "div";
private static final String CSS_CLASS = "highcharts-container";
public Chart(WebDriver driver, WebElement element) {
super(driver, element);
}
@Override
protected void verify() {
WebElement element = getWebElement();
if(!TAG_NAME.equals(element.getTagName()) || !CSSHelper.hasCSSClass(element, CSS_CLASS)) {
throw new IllegalArgumentException("The element " + element + " does not represent a Highchart");
}
}
}
@@ -0,0 +1,10 @@
package com.sap.sailing.selenium.pages.highcharts;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
public class LineChart extends Chart {
public LineChart(WebDriver driver, WebElement element) {
super(driver, element);
}
}
@@ -0,0 +1,39 @@
package com.sap.sailing.selenium.pages.leaderboard;
import java.util.ArrayList;
import java.util.List;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Select;
import com.sap.sailing.selenium.core.BySeleniumId;
import com.sap.sailing.selenium.core.FindBy;
import com.sap.sailing.selenium.pages.PageArea;
public class CompetitorChartsSettingsDialogPO extends PageArea {
@FindBy(how = BySeleniumId.class, using = "ChartTypeListBox")
private WebElement chartTypeListBox;
public CompetitorChartsSettingsDialogPO(WebDriver driver, WebElement element) {
super(driver, element);
}
public void selectChartType(String type) {
Select select = new Select(this.chartTypeListBox);
//select.selectByVisibleText(type);
select.selectByValue(type);
}
public List<String> getChartTypes() {
List<String> types = new ArrayList<>();
Select select = new Select(this.chartTypeListBox);
for(WebElement option : select.getOptions()) {
types.add(option.getAttribute("value"));
}
return types;
}
}
@@ -1,16 +1,16 @@
package com.sap.sailing.selenium.pages.leaderboard;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import com.sap.sailing.selenium.core.BySeleniumId;
import com.sap.sailing.selenium.core.FindBy;
import com.sap.sailing.selenium.pages.HostPage;
import com.sap.sailing.selenium.pages.common.CSSConstants;
import com.sap.sailing.selenium.pages.common.HTMLConstants;
import com.sap.sailing.selenium.pages.gwt.CheckBoxPO;
/**
* <p>The page object representing the leaderboard.</p>
@@ -19,9 +19,9 @@ import com.sap.sailing.selenium.pages.common.HTMLConstants;
* D049941
*/
public class LeaderboardPage extends HostPage {
private static final String PAGE_TITLE = "SAP Sailing Analytics Leaderboard"; //$NON-NLS-1$
private static final String LEADERBOAR_PARAMTER_NAME = "name"; //$NON-NLS-1$
private static final String SHOW_RACE_DETAILS_PARAMTER_NAME = "showRaceDetails"; //$NON-NLS-1$
private static final String AUTO_REFRESH_ENABLED_IMAGE = "url(\"data:image/png;base64," + //$NON-NLS-1$
"iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAAR0lEQVR42mOoqan5T2vMMGoJxZZUV1fPB9IOWDC" + //$NON-NLS-1$
@@ -32,6 +32,10 @@ public class LeaderboardPage extends HostPage {
"nDQxAAKQDgBbep6klIFBfXy9QW1vbT1NLYKCqqsoAKH6eppbAADD4CoDy72lqCTQIFYhNGGRbAgPEJAyKLSEmYV" + //$NON-NLS-1$
"DFEhgAWpQwdH1C0ziheeqiaT6haY6nedlF01KYXvXJaB0/MJYAANIIBwANoTb3AAAAAElFTkSuQmCC\")"; //$NON-NLS-1$
public static LeaderboardPage goToPage(WebDriver driver, String root, String leaderboard) {
return goToPage(driver, root, leaderboard, false);
}
/**
* <p>Goes to the specified leaderboard and returns the representing page object.</p>
*
@@ -44,29 +48,49 @@ public class LeaderboardPage extends HostPage {
* @return
* The page object for the administration console.
*/
public static LeaderboardPage goToPage(WebDriver driver, String root, String leaderboard) {
public static LeaderboardPage goToPage(WebDriver driver, String root, String leaderboard, boolean raceDetails) {
driver.get(root + "gwt/Leaderboard.html?" + getLeaderboard(leaderboard) + //$NON-NLS-1$
"&" + getGWTCodeServer()); //$NON-NLS-1$
"&" + getGWTCodeServer() + "&" + getShowRaceDeatails(raceDetails)); //$NON-NLS-1$
return new LeaderboardPage(driver);
return new LeaderboardPage(driver, leaderboard);
}
private static String getLeaderboard(String leaderboard) {
return LEADERBOAR_PARAMTER_NAME + "=" + leaderboard; //$NON-NLS-1$
}
@FindBy(how = BySeleniumId.class, using = "AutoRefreshToggleButton")
private WebElement autoRefreshToggleButton;
private static String getShowRaceDeatails(boolean raceDetails) {
return SHOW_RACE_DETAILS_PARAMTER_NAME + "=" + raceDetails; //$NON-NLS-1$
}
@FindBy(how = BySeleniumId.class, using = "LeaderboardTable")
private WebElement leaderboardTable;
@FindBy(how = BySeleniumId.class, using = "LeaderboardDisplayCheckBox")
private WebElement leaderboardDisplayCheckBox;
private LeaderboardPage(WebDriver driver) {
@FindBy(how = BySeleniumId.class, using = "LeaderboardSettingsButton")
private WebElement leaderboardSettingsButton;
@FindBy(how = BySeleniumId.class, using = "CompetitorChartsDisplayCheckBox")
private WebElement competitorChartsDisplayCheckBox;
@FindBy(how = BySeleniumId.class, using = "CompetitorChartsSettingsButton")
private WebElement competitorChartsSettingsButton;
@FindBy(how = BySeleniumId.class, using = "PlayAndPauseAnchor")
private WebElement playAndPauseAnchor;
@FindBy(how = BySeleniumId.class, using = "LeaderboardCellTable")
private WebElement leaderboardCellTable;
private LeaderboardPage(WebDriver driver, String leaderboard) {
super(driver);
if(!this.driver.getTitle().equals(leaderboard)) {
throw new IllegalStateException("This is not the leaderboard"); //$NON-NLS-1$
}
}
public boolean isAutoRefreshEnabled() {
WebElement image = this.autoRefreshToggleButton.findElement(By.tagName(HTMLConstants.IMAGE_TAG_NAME));
WebElement image = this.playAndPauseAnchor.findElement(By.tagName(HTMLConstants.IMAGE_TAG_NAME));
String background = image.getCssValue(CSSConstants.CSS_BACKGROUND_IMAGE);
if(AUTO_REFRESH_ENABLED_IMAGE.equals(background))
@@ -78,18 +102,60 @@ public class LeaderboardPage extends HostPage {
throw new RuntimeException("Can not determine auto refresh state"); //$NON-NLS-1$
}
public void setAutoRefreshEnabled(boolean enabled) {
if(isAutoRefreshEnabled() != enabled)
this.autoRefreshToggleButton.click();
public void refresh() {
JavascriptExecutor executor = (JavascriptExecutor) driver;
Long finishedCalls = (Long) executor.executeScript(
"return window.PENDING_AJAX_CALLS.numberOfFinishedCalls(arguments[0])", "loadLeaderboardData");
this.playAndPauseAnchor.click();
waitForAjaxRequestsExecuted("loadLeaderboardData", finishedCalls.intValue() + 1);
this.playAndPauseAnchor.click();
}
/**
* <p>Verifies that the current page is the leaderboard by checking the title of the page.</p>
*/
public CompetitorChartsSettingsDialogPO getCompetitorChartsSettings() {
this.competitorChartsSettingsButton.click();
return new CompetitorChartsSettingsDialogPO(this.driver,
findElementBySeleniumId(this.driver, "CompetitorChartsSettingsDialog"));
}
public LeaderboardSettingsDialogPO getLeaderboardSettings() {
this.leaderboardSettingsButton.click();
return new LeaderboardSettingsDialogPO(this.driver,
findElementBySeleniumId(this.driver, "LeaderboardSettingsDialog"));
}
public LeaderboardTablePO getLeaderboardTable() {
return new LeaderboardTablePO(this.driver, this.leaderboardCellTable);
}
public void showCompetitorChart(String chart) {
this.competitorChartsSettingsButton.click();
CompetitorChartsSettingsDialogPO dialog = new CompetitorChartsSettingsDialogPO(this.driver,
findElementBySeleniumId(this.driver, "CompetitorChartsSettingsDialog"));
dialog.selectChartType(chart);
CheckBoxPO checkbox = new CheckBoxPO(this.driver, this.competitorChartsDisplayCheckBox);
checkbox.setSelected(true);
}
public void hideCompetitorChart() {
CheckBoxPO checkbox = new CheckBoxPO(this.driver, this.competitorChartsDisplayCheckBox);
checkbox.setSelected(false);
}
// public LineChart getCompetitorChart() {
// return new LineChart(this.driver, findElementBySeleniumId("CompetitorChart"));
// }
@Override
protected void verify() {
if(!PAGE_TITLE.equals(this.driver.getTitle())) {
throw new IllegalStateException("This is not the leaderboard"); //$NON-NLS-1$
}
protected void initElements() {
super.initElements();
// Wait for the initial loading of the data
waitForAjaxRequestsExecuted("loadLeaderboardData", 1);
}
}
@@ -0,0 +1,110 @@
package com.sap.sailing.selenium.pages.leaderboard;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import com.sap.sailing.selenium.core.BySeleniumId;
import com.sap.sailing.selenium.core.FindBy;
import com.sap.sailing.selenium.pages.common.CSSHelper;
import com.sap.sailing.selenium.pages.common.DataEntryDialogPO;
import com.sap.sailing.selenium.pages.gwt.CheckBoxPO;
import com.sap.sailing.selenium.pages.gwt.RadioButtonPO;
public class LeaderboardSettingsDialogPO extends DataEntryDialogPO {
@FindBy(how = BySeleniumId.class, using = "RaceSelectionSettingsPanel")
private WebElement raceSelectionSettingsPanel;
@FindBy(how = BySeleniumId.class, using = "ExplicitRaceSelectionRadioButton")
private WebElement explicitRaceSelectionRadioButton;
@FindBy(how = BySeleniumId.class, using = "MostCurrentRacesSelectionRadioButton")
private WebElement mostCurrentRacesSelectionRadioButton;
@FindBy(how = BySeleniumId.class, using = "OverallDetailsSettingsPanel")
private WebElement overallDetailsSettingsPanel;
@FindBy(how = BySeleniumId.class, using = "RaceDetailsSettingsPanel")
private WebElement raceDetailsSettingsPanel;
@FindBy(how = BySeleniumId.class, using = "LegDetailsSettingsPanel")
private WebElement legDetailsSettingsPanel;
@FindBy(how = BySeleniumId.class, using = "ManeuverSettingsPanel")
private WebElement maneuverSettingsPanel;
public LeaderboardSettingsDialogPO(WebDriver driver, WebElement element) {
super(driver, element);
}
public void setRacesToDisplay(List<String> races) {
RadioButtonPO button = new RadioButtonPO(this.driver, this.explicitRaceSelectionRadioButton);
if(!button.isSelected()) {
button.setSelected(true);
}
for(WebElement element : findAllCheckboxesForSettings(this.raceSelectionSettingsPanel)) {
CheckBoxPO checkbox = new CheckBoxPO(this.driver, element);
checkbox.setSelected(races.contains(checkbox.getLabel()));
}
}
public void setNumberOfRacesToDisplay(int numberOfRaces) {
RadioButtonPO button = new RadioButtonPO(this.driver, this.mostCurrentRacesSelectionRadioButton);
if(!button.isSelected()) {
button.setSelected(true);
}
WebElement textField = findElementBySeleniumId(this.raceSelectionSettingsPanel, "NumberOfMostCurrentRacesIntegerBox");
textField.clear();
textField.sendKeys(Integer.toString(numberOfRaces));
}
public void setOverallDetails() {
}
public void showAllOverallDetails() {
setSelectionForAllSettings(this.overallDetailsSettingsPanel, true);
}
public void setRaceDetails() {
}
public void showAllRaceDetails() {
setSelectionForAllSettings(this.raceDetailsSettingsPanel, true);
}
public void setLegDetails() {
}
public void showAllLegDetails() {
setSelectionForAllSettings(this.legDetailsSettingsPanel, true);
}
public void setManeuverDetails() {
}
public void showAllManeuverDetails() {
setSelectionForAllSettings(this.maneuverSettingsPanel, true);
}
private void setSelectionForAllSettings(WebElement settingsPanel, boolean selected) {
for(WebElement element : findAllCheckboxesForSettings(settingsPanel)) {
CheckBoxPO checkbox = new CheckBoxPO(this.driver, element);
checkbox.setSelected(selected);
}
}
private List<WebElement> findAllCheckboxesForSettings(WebElement settingsPanel) {
List<WebElement> e = settingsPanel.findElements(By.xpath(".//span[" + CSSHelper.containsCSSClassPredicate("gwt-CheckBox") + "]"));
return e;
}
}
@@ -1,65 +1,196 @@
package com.sap.sailing.selenium.pages.leaderboard;
import java.util.ArrayList;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import com.sap.sailing.selenium.pages.common.CSSHelper;
import com.sap.sailing.selenium.pages.gwt.CellTablePO;
import com.sap.sailing.selenium.pages.gwt.DataEntryPO;
import com.sap.sailing.selenium.pages.leaderboard.LeaderboardTablePO.LeaderboardEntry;
public class LeaderboardTablePO extends CellTablePO<LeaderboardEntry> {
public class LeaderboardEntry extends DataEntryPO {
private static final String TOTAL_RANK = "Total rank";
private static final String COMPETITOR = "Competitor";
private static final String NAME = "Name";
public static class LeaderboardEntry extends DataEntryPO {
private static final int TOTAL_RANK_COLUMN = 0;
private static final int COMPETITOR_COLUMN = 1;
private static final int NAME_COLUMN = 2;
protected LeaderboardEntry(WebElement element) {
super(LeaderboardTablePO.this, element);
private static final String TOTAL_POINTS_COLUMN = "Σ";
protected LeaderboardEntry(LeaderboardTablePO table, WebElement element) {
super(table, element);
}
public String getDescriptor() {
@Override
public String getIdentifier() {
return getCompetitor();
}
public int getTotalRank() {
return Integer.parseInt(getColumnContent(TOTAL_RANK));
public Integer getTotalRank() {
return Integer.valueOf(getColumnContent(TOTAL_RANK_COLUMN));
}
public String getCompetitor() {
return getColumnContent(COMPETITOR);
return getColumnContent(COMPETITOR_COLUMN);
}
public String getName() {
return getColumnContent(NAME);
return getColumnContent(NAME_COLUMN);
}
// public int getTotalSailedDistance() {
// }
// public void getAverageSpeedOverGround() {
// }
// public void getMaximumSpeedOverGround() {
// }
// public int getTotalDownwindTime() {
// }
// public int getTotalUpwindTime() {
// }
// public int getTotalReachingLegsTime() {
// }
// public int getTotalSailingTime() {
// }
// public int getTotalPoints() {
// }
// Overall details
// ...
// Race details
// ...
public Integer getPointsForRace(String race) {
String points = getColumnContent(race);
if(points == null || points.isEmpty()) {
return null;
}
try {
return Integer.valueOf(points);
} catch(NumberFormatException exception) {
return Integer.valueOf(-1);
}
}
// Leg details
// ...
public Integer getTotalPoints() {
return Integer.valueOf(getColumnContent(TOTAL_POINTS_COLUMN));
}
}
// Style classes to find columns in different levels (children of expanded columns)
// We don't use the style classes for the second and third level at the moment, but they may be needed if more
// functionality is added to the page object soon.
//private static final String FIRST_LEVEL_COLUMN_STYLE_CLASS = ".GCKY0V4BLK"; //$NON-NLS-1$
//private static final String SECOND_LEVEL_COLUMN_STYLE_CLASS = ".GCKY0V4BFL"; //$NON-NLS-1$
//private static final String THIRD_LEVEL_COLUMN_STYLE_CLASS = ".GCKY0V4BHL"; //$NON-NLS-1$
//private static final String RACE_COLUMN_STYLE_CLASS = ".GCKY0V4BML"; //$NON-NLS-1$
private static final String EXPANDABLE_COLUMN_STYLE_CLASS = "openColumn"; //$NON-NLS-1$
private static final String RACE_NAME_STYLE_CLASS = "race-name"; //$NON-NLS-1$
private static final String EXPANDED_IMAGE = "data:image/png;base64," + //$NON-NLS-1$
"iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAAj0lEQVR42u2SPQrEIBgFc2JjJQF/Cm0SzxDRE6a" + //$NON-NLS-1$
"xEQvf8lksW2QlC9slwlS+mUYnpRT+yfQE7xaUUoJzDsbYJeZ57s5pkC6MMdj3HSklxBiH0CaE0J3P6Du4LAuccy" + //$NON-NLS-1$
"il4OqhLTnkngattTiOA6011FqH0Cbn/D1IaK2xriu895fYtq07w1cWQvzE87HvGHwB11fK7fckleMAAAAASUVOR" + //$NON-NLS-1$
"K5CYII=";
private static final String COLLAPSED_IMAGE = "data:image/png;base64," + //$NON-NLS-1$
"iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAABMUlEQVR42tWUzYqDQAzH+6x6U7Dag60f9bPQ6kk" + //$NON-NLS-1$
"PraVV1IMP0IOv5cWLeGiWBBzs1rLFXRYa+MMwSX4zk4RZmKYJf6nFZwO32y1omgaSJJFwjXuzgbquw263gyzLSJ" + //$NON-NLS-1$
"7nEXQ2UFEUAg2WJAnIsjwfuFqt4Hq9MuDpdKJD3gYahkE3GGrG8zxEUcSAYRgCx3HMv1wuKWcSiA7LsiBNUyiKA" + //$NON-NLS-1$
"vI8h/P5DHVdM+DtdqNnow9jsByYM4Yy4GazAd/3oes6GNv9foe+70m4HhvGYg7mTgKxi03TPEBeCWPatn0NHObu" + //$NON-NLS-1$
"cDhQrVCu60JVVexGZVmC4zjMHwTB01w+dVlVVSZRFKmzg8VxDIIgPMT879hMAS+XCwMej8ffAXEcbNuG/X5P+j4" + //$NON-NLS-1$
"is34bBKzXa9JPsM/4D78ABqXmiURzXL4AAAAASUVORK5CYII=";
// QUESTION: Do we need this predicate in the RACE_COLUMN_XPATH and in the RACE_NAMES_XPATH?
//private static final String RACE_COLUMN_PREDICATE = CSSHelper.containsCSSClassesPredicate(FIRST_LEVEL_COLUMN_STYLE_CLASS,
// RACE_COLUMN_STYLE_CLASS);
private static final String RACE_COLUMN_XPATH = "./thead/tr/th[//*[@__gwt_header] and .//span[" +
CSSHelper.containsCSSClassPredicate(RACE_NAME_STYLE_CLASS) + " and text() = '%s']]";
private static final String RACE_NAMES_XPATH = "./thead/tr//*[@__gwt_header]//span[" +
CSSHelper.containsCSSClassPredicate(RACE_NAME_STYLE_CLASS) + "]";
private static final String EXPANSION_BUTTON_XPATH = "./span/div[" +
CSSHelper.containsCSSClassPredicate(EXPANDABLE_COLUMN_STYLE_CLASS) + "]/img";
public LeaderboardTablePO(WebDriver driver, WebElement element) {
super(driver, element);
}
public boolean isColumnExpandable(int column) {
List<WebElement> headers = this.context.findElements(By.xpath(TABLE_HEADER_XPATH));
WebElement header = headers.get(column);
return !header.findElements(By.xpath(EXPANSION_BUTTON_XPATH)).isEmpty();
}
public boolean isColumnExpanded(int column) {
List<WebElement> headers = this.context.findElements(By.xpath(TABLE_HEADER_XPATH));
WebElement header = headers.get(column);
List<WebElement> elements = header.findElements(By.xpath(EXPANSION_BUTTON_XPATH));
if(elements.isEmpty() || COLLAPSED_IMAGE.equals(elements.get(0).getAttribute("src")))
return false;
return true;
}
public void expandColumn(int column) {
List<WebElement> headers = this.context.findElements(By.xpath(TABLE_HEADER_XPATH));
setExpansionState(headers.get(column), true);
}
public void collapseColumn(int column) {
List<WebElement> headers = this.context.findElements(By.xpath(TABLE_HEADER_XPATH));
setExpansionState(headers.get(column), false);
}
public List<String> getRaceNames() {
List<String> raceNames = new ArrayList<>();
List<WebElement> elements = this.context.findElements(By.xpath(RACE_NAMES_XPATH));
for(WebElement element : elements) {
raceNames.add(element.getText());
}
return raceNames;
}
public void expandRace(String name) {
setExpansionState(getRaceColumn(name), true);
}
public void collapseRace(String name) {
setExpansionState(getRaceColumn(name), false);
}
@Override
protected LeaderboardEntry createDataEntry(WebElement element) {
return new LeaderboardEntry(element);
return new LeaderboardEntry(this, element);
}
private WebElement getRaceColumn(String race) {
return this.context.findElement(By.xpath(String.format(RACE_COLUMN_XPATH, race)));
}
private void setExpansionState(WebElement column, boolean expanded) {
try {
WebElement button = getExpansionButton(column);
String image = button.getAttribute("src");
boolean toggleSate = (expanded ? COLLAPSED_IMAGE.equals(image) : EXPANDED_IMAGE.equals(image));
if(toggleSate) {
button.click();
waitForAjaxRequests();
}
} catch(NoSuchElementException excpetion) {
// The column is not expandable. For a race this happens if its not linked to a tracked race yet.
}
}
private WebElement getExpansionButton(WebElement header) {
return header.findElement(By.xpath(EXPANSION_BUTTON_XPATH));
}
}
@@ -44,7 +44,7 @@ public class LeaderboardEditingPage extends HostPage {
}
public LeaderboardTable getLeaderboardTable() {
return new LeaderboardTable(this.driver, findElementBySeleniumId(context, "LeaderboardTable"));
return new LeaderboardTable(this.driver, findElementBySeleniumId(context, "LeaderboardCellTable"));
}
@Override
@@ -1,14 +1,13 @@
package com.sap.sailing.selenium.test;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.UUID;
@@ -155,42 +154,27 @@ public abstract class AbstractSeleniumTest {
* if an I/O error occurs.
*/
protected void captureScreenshot(String filename) {
URL screenshotFolder = this.environment.getScreenshotFolder();
if(screenshotFolder == null)
return;
WebDriver driver = getWebDriver();
if(RemoteWebDriver.class.equals(driver.getClass())) {
driver = new Augmenter().augment(driver);
}
InputStream source = getScreenshotNotSupportedImage();
if(driver instanceof TakesScreenshot) {
source = new ByteArrayInputStream(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES));
}
try {
URL destination = new URL(screenshotFolder, getClass().getName() + "/" + filename + SCREENSHOT_FILE_EXTENSION); //$NON-NLS-1$
Path path = Paths.get(destination.toURI());
Path parent = path.getParent();
if(parent != null) {
Files.createDirectories(parent);
File screenshotFolder = this.environment.getScreenshotFolder();
if (screenshotFolder != null) {
WebDriver driver = getWebDriver();
if (RemoteWebDriver.class.equals(driver.getClass())) {
driver = new Augmenter().augment(driver);
}
InputStream source = getScreenshotNotSupportedImage();
if (driver instanceof TakesScreenshot) {
source = new ByteArrayInputStream(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES));
}
try {
File destinationDir = new File(screenshotFolder, getClass().getName());
destinationDir.mkdirs();
File destination = new File(destinationDir, filename + SCREENSHOT_FILE_EXTENSION); //$NON-NLS-1$
Path path = destination.toPath();
Files.copy(source, path, StandardCopyOption.REPLACE_EXISTING);
// ATTENTION: Do not remove this line because it is needed for the JUnit Attachment Plugin!
System.out.println(String.format(ATTACHMENT_FORMAT, destination.getCanonicalFile().toURI()));
} catch (IOException exception) {
throw new RuntimeException(exception);
}
Files.copy(source, path, StandardCopyOption.REPLACE_EXISTING);
// ATTENTION: Do not remove this line because it is needed for the JUnit Attachment Plugin!
System.out.println(String.format(ATTACHMENT_FORMAT, destination));
} catch(URISyntaxException exception) {
// This should never happen, but it's a checked exception.
} catch(IOException exception) {
throw new RuntimeException(exception);
}
}
@@ -34,7 +34,7 @@ public class TestLeaderboardFilterInLeaderboardGroupConfig extends AbstractSelen
leaderboardConfiguration.createFlexibleLeaderboard("Test");
leaderboardGroupConfiguration = adminConsole.goToLeaderboardGroupConfiguration();
LeaderboardGroupDetailsPanelPO leaderboardGroupDetails = leaderboardGroupConfiguration.getLeaderboardGroupDetails();
LeaderboardGroupDetailsPanelPO leaderboardGroupDetails = leaderboardGroupConfiguration.getLeaderboardGroupDetails("Test");
leaderboardGroupDetails.refreshLeaderboards();
DataEntryPO leaderboardEntry = leaderboardGroupDetails.findLeaderboardEntry("Test");
assertNotNull(leaderboardEntry);
@@ -1,9 +1,27 @@
package com.sap.sailing.selenium.test.adminconsole;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.Alert;
import org.openqa.selenium.WebDriver.TargetLocator;
import com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage;
import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaListCompositePO.RegattaDescriptor;
import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaStructureManagementPanelPO;
import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO;
import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO.Status;
import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO.TrackedRaceDescriptor;
import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO;
import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO.TrackableRaceDescriptor;
import com.sap.sailing.selenium.test.AbstractSeleniumTest;
/**
@@ -14,30 +32,121 @@ import com.sap.sailing.selenium.test.AbstractSeleniumTest;
*/
public class TestStartAndStopTrackingForTracTracEvents extends AbstractSeleniumTest {
private static final String BMW_CUP_JSON_URL = "http://kml.skitrac.traclive.dk/events/event_20120803_BMWCup/jsonservice.php"; //$NON-NLS-1$
private static final String BMW_CUP_EVENT = "BMW Cup";
private static final String IDM_2013_EVENT = "IDM 5O5 2013";
private static final String BMW_CUP_BOAT_CLASS = "J80";
private static final String IDM_2013_BOAT_CLASS = "505";
private static final String DEFAULT_REGATTA = "Default regatta";
private static final String BMW_CUP_REGATTA = "BMW Cup (J80)"; //$NON-NLS-1$
private static final String IDM_2013_REGATTA = "IDM 5O5 2013 (505)"; //$NON-NLS-1$
private static final String RACE = "BMW Cup Race %d";
private TrackableRaceDescriptor trackableRace;
private TrackedRaceDescriptor trackedRace;
// TODO see below: Complete the test case
// private static final String NO_REGATTA = "No regatta";
// private static final String BMW_CUP_REGATTA = "BMW Cup (J80)";
// private static final String BMW_CUP_RACE_8 = "BMW Cup Race 8";
@Before
public void setUp() {
this.trackableRace = new TrackableRaceDescriptor(BMW_CUP_EVENT, String.format(RACE, 1), BMW_CUP_BOAT_CLASS);
this.trackedRace = new TrackedRaceDescriptor(BMW_CUP_REGATTA, BMW_CUP_BOAT_CLASS, String.format(RACE, 1));
clearState(getContextRoot());
}
/**
* <p>Test for the correct start and stop of a tracking.</p>
*/
@Test
public void testStartAndStopTrackingWithCorrectRegatta() {
RegattaDescriptor bmwCupDescriptor = new RegattaDescriptor(BMW_CUP_EVENT, BMW_CUP_BOAT_CLASS);
AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure();
regattaStructure.createRegatta(bmwCupDescriptor);
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
tracTracEvents.listTrackableRaces(BMW_CUP_JSON_URL);
// TODO: Complete the test case!
//tracTracEvents.startTracking(BMW_CUP_RACE_8, BMW_CUP_REGATTA, false, false, false);
tracTracEvents.setReggataForTracking(bmwCupDescriptor);
tracTracEvents.setTrackSettings(false, false, false);
tracTracEvents.startTrackingForRace(this.trackableRace);
//assertThat(tracTracEvents.getTrackedRaces(), hasItem(12));
TrackedRacesListPO trackedRacesList = tracTracEvents.getTrackedRacesList();
trackedRacesList.waitForTrackedRace(this.trackedRace, Status.TRACKING);
//tracTracEvents.stopTracking("BMW_CUP_RACE_8");
assertThat(trackedRacesList.getStatus(this.trackedRace), equalTo(Status.TRACKING));
//assertThat(tracTracEvents.getTrackedRaces(), not(hasItem(12)));
trackedRacesList.stopTracking(this.trackedRace);
trackedRacesList.waitForTrackedRace(this.trackedRace, Status.FINISHED);
assertThat(trackedRacesList.getStatus(this.trackedRace), equalTo(Status.FINISHED));
}
@Test
public void testStartTrackingWithDefaultReggataWhileReggataForBoatClassExists() {
AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure();
regattaStructure.createRegatta(new RegattaDescriptor(BMW_CUP_EVENT, BMW_CUP_BOAT_CLASS));
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
tracTracEvents.listTrackableRaces(BMW_CUP_JSON_URL);
tracTracEvents.setReggataForTracking(DEFAULT_REGATTA);
tracTracEvents.setTrackSettings(false, false, false);
tracTracEvents.startTrackingForRace(this.trackableRace);
TargetLocator locator = getWebDriver().switchTo();
Alert alert = locator.alert();
String text = alert.getText();
alert.dismiss();
String message = "There is at least one regatta for the selected boat classes. Do you really want " +
"to use the 'no regatta' selection?";
assertThat(text, containsString("WARNING"));
assertThat(text, containsString(message));
}
@Test
public void testStartTrackingWithReggataAndNoneMatchingBoatClass() {
RegattaDescriptor bmwCupDescriptor = new RegattaDescriptor(BMW_CUP_EVENT, BMW_CUP_BOAT_CLASS);
RegattaDescriptor idm2013Descriptor = new RegattaDescriptor(IDM_2013_EVENT, IDM_2013_BOAT_CLASS);
AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure();
regattaStructure.createRegatta(bmwCupDescriptor);
regattaStructure.createRegatta(idm2013Descriptor);
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
tracTracEvents.listTrackableRaces(BMW_CUP_JSON_URL);
tracTracEvents.setReggataForTracking(idm2013Descriptor);
tracTracEvents.setTrackSettings(false, false, false);
tracTracEvents.startTrackingForRace(this.trackableRace);
TargetLocator locator = getWebDriver().switchTo();
Alert alert = locator.alert();
String text = alert.getText();
alert.dismiss();
String message = String.format("The selected races contain boat classes which are not the same as " +
"the boat class '%s' of the selected regatta. Do you really want to use the regatta '%s'?",
IDM_2013_BOAT_CLASS, IDM_2013_REGATTA);
assertThat(text, containsString("WARNING"));
assertThat(text, containsString(message));
}
}
@@ -0,0 +1,126 @@
package com.sap.sailing.selenium.test.leaderboard;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage;
import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardConfigurationPanelPO;
import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardDetailsPanelPO;
import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardDetailsPanelPO.RaceDescriptor;
import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaDetailsCompositePO;
import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaListCompositePO.RegattaDescriptor;
import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaStructureManagementPanelPO;
import com.sap.sailing.selenium.pages.adminconsole.regatta.SeriesEditDialogPO;
import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO;
import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO.Status;
import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO.TrackedRaceDescriptor;
import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO;
import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO.TrackableRaceDescriptor;
import com.sap.sailing.selenium.pages.leaderboard.LeaderboardPage;
import com.sap.sailing.selenium.pages.leaderboard.LeaderboardSettingsDialogPO;
import com.sap.sailing.selenium.pages.leaderboard.LeaderboardTablePO;
import com.sap.sailing.selenium.pages.leaderboard.LeaderboardTablePO.LeaderboardEntry;
import com.sap.sailing.selenium.test.AbstractSeleniumTest;
public class TestColumnsInLeaderboard extends AbstractSeleniumTest {
private static final String KIELER_WOCHE_2013_JSON_URL =
"http://secondary.traclive.dk/events/event_20130621_KielerWoch/jsonservice.php"; //$NON-NLS-1$
private static final String REGATTA = "KW 2013 Offshore Kaiser-Pokal"; //$NON-NLS-1$
private static final String LEADERBOARD = "KW 2013 Offshore Kaiser-Pokal (ORC)"; //$NON-NLS-1$
private static final String EVENT = "Kieler Woche 2013"; //$NON-NLS-1$
private static final String BOAT_CLASS = "ORC"; //$NON-NLS-1$
private static final String RACE = "Kaiserpokal"; //$NON-NLS-1$
private RegattaDescriptor regatta;
private TrackableRaceDescriptor trackableRace;
private TrackedRaceDescriptor trackedRace;
private RaceDescriptor raceColumn;
@Before
public void setUp() {
this.regatta = new RegattaDescriptor(REGATTA, BOAT_CLASS);
this.trackableRace = new TrackableRaceDescriptor(EVENT, RACE, BOAT_CLASS);
this.trackedRace = new TrackedRaceDescriptor(this.regatta.toString(), BOAT_CLASS, RACE);
this.raceColumn = new RaceDescriptor("R1", "Default", false, false, 0.0);
clearState(getContextRoot());
configureLeaderboard();
}
@Test
public void testCorrectDisplayOfAllColumns() {
LeaderboardPage leaderboard = LeaderboardPage.goToPage(getWebDriver(), getContextRoot(), LEADERBOARD, true);
LeaderboardTablePO leaderboardTabel = leaderboard.getLeaderboardTable();
LeaderboardSettingsDialogPO settings = leaderboard.getLeaderboardSettings();
settings.setRacesToDisplay(leaderboardTabel.getRaceNames());
settings.showAllOverallDetails();
settings.showAllRaceDetails();
settings.showAllLegDetails();
settings.showAllManeuverDetails();
settings.pressOk();
boolean stateHasChanged;
do {
List<String> headers = leaderboardTabel.getColumnHeaders();
stateHasChanged = false;
// Since this test is very expensive we iterate from the end to the beginning because the lower
// indexes are still valid after the expansion of a column.
for(int i = headers.size() - 1; i >= 0; i--) {
if(leaderboardTabel.isColumnExpandable(i) && !leaderboardTabel.isColumnExpanded(i)) {
leaderboardTabel.expandColumn(i);
stateHasChanged = true;
List<LeaderboardEntry> entries = leaderboardTabel.getEntries();
// NOTE: We have to resolve the headers again for the assertion since there should be more now
// because of the expansion
assertThat(entries.get(0).getNumberOfColumns(), equalTo(leaderboardTabel.getColumnHeaders().size()));
}
}
} while(stateHasChanged);
}
private void configureLeaderboard() {
// Open the admin console for some configuration steps
AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
// Create a regatta with 1 series and 5 races as well as a leaderborad
RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure();
regattaStructure.createRegatta(this.regatta);
RegattaDetailsCompositePO regattaDetails = regattaStructure.getRegattaDetails(this.regatta);
SeriesEditDialogPO seriesDialog = regattaDetails.editSeries(RegattaStructureManagementPanelPO.DEFAULT_SERIES_NAME);
seriesDialog.addRaces(1, 1);
seriesDialog.pressOk();
// Start the tracking for the races and wait until they are ready to use
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
tracTracEvents.listTrackableRaces(KIELER_WOCHE_2013_JSON_URL);
tracTracEvents.setReggataForTracking(this.regatta);
tracTracEvents.setTrackSettings(false, false, false);
tracTracEvents.startTrackingForRace(this.trackableRace);
TrackedRacesListPO trackedRacesList = tracTracEvents.getTrackedRacesList();
trackedRacesList.waitForTrackedRace(this.trackedRace, Status.TRACKING);
trackedRacesList.stopTracking(this.trackedRace);
LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
leaderboardConfiguration.createRegattaLeaderboard(this.regatta);
LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(LEADERBOARD);
leaderboardDetails.linkRace(this.raceColumn, this.trackedRace);
}
}
@@ -0,0 +1,245 @@
package com.sap.sailing.selenium.test.leaderboard;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import com.sap.sailing.selenium.core.WebDriverWindow;
import com.sap.sailing.selenium.core.WindowManager;
import com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage;
import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardConfigurationPanelPO;
import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardDetailsPanelPO;
import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardDetailsPanelPO.RaceDescriptor;
import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaDetailsCompositePO;
import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaListCompositePO.RegattaDescriptor;
import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaStructureManagementPanelPO;
import com.sap.sailing.selenium.pages.adminconsole.regatta.SeriesEditDialogPO;
import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO;
import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO.Status;
import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO.TrackedRaceDescriptor;
import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO;
import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO.TrackableRaceDescriptor;
import com.sap.sailing.selenium.pages.leaderboard.LeaderboardPage;
import com.sap.sailing.selenium.pages.leaderboard.LeaderboardTablePO;
import com.sap.sailing.selenium.pages.leaderboard.LeaderboardTablePO.LeaderboardEntry;
import com.sap.sailing.selenium.test.AbstractSeleniumTest;
public class TestLeaderboardConfiguration extends AbstractSeleniumTest {
private static final String IDM_5O5_2013_JSON_URL =
"http://traclive.dk/events/event_20130917_IDMO/jsonservice.php"; //$NON-NLS-1$
private static final String REGATTA = "IDM 2013"; //$NON-NLS-1$
private static final String LEADERBOARD = "IDM 2013 (505)"; //$NON-NLS-1$
private static final String EVENT = "IDM 5O5 2013"; //$NON-NLS-1$
private static final String BOAT_CLASS = "505"; //$NON-NLS-1$
private static final String RACE = "Race %d"; //$NON-NLS-1$
private RegattaDescriptor regatta;
private List<TrackableRaceDescriptor> trackableRaces;
private List<TrackedRaceDescriptor> trackedRaces;
private List<RaceDescriptor> leaderboardRaces;
@Before
public void setUp() {
this.regatta = new RegattaDescriptor(REGATTA, BOAT_CLASS);
this.trackableRaces = new ArrayList<>();
this.trackedRaces = new ArrayList<>();
this.leaderboardRaces = new ArrayList<>();
for(int i = 1; i <= 5; i++) {
TrackableRaceDescriptor trackableRace = new TrackableRaceDescriptor(EVENT, String.format(RACE, i), BOAT_CLASS);
TrackedRaceDescriptor trackedRace = new TrackedRaceDescriptor(this.regatta.toString(), BOAT_CLASS, String.format(RACE, i));
RaceDescriptor leaderboardRace = new RaceDescriptor(String.format("R%s", i), "Default", false, false, 0);
this.trackableRaces.add(trackableRace);
this.trackedRaces.add(trackedRace);
this.leaderboardRaces.add(leaderboardRace);
}
clearState(getContextRoot());
configureLeaderboard();
}
@Test
public void testDynamicRaceLinking() {
// Open a second window which we use for the leaderboard later
WindowManager manager = this.environment.getWindowManager();
WebDriverWindow leaderboardWindow = manager.getCurrentWindow();
WebDriverWindow adminConsoleWindow = manager.openNewWindow();
// Open the leaderboard and check for "empty" leaderboard
LeaderboardPage leaderboard = LeaderboardPage.goToPage(getWebDriver(), getContextRoot(), LEADERBOARD, false);
LeaderboardTablePO table = leaderboard.getLeaderboardTable();
List<String> races = table.getRaceNames();
assertThat(races.size(), equalTo(5));
assertThat(table.getEntries().size(), equalTo(0));
adminConsoleWindow.switchToWindow();
AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(this.regatta.toString());
Integer[] expectedPointsForFindelJens = new Integer[] {2, 18, 12, 4, 7};
Integer[] expectedRankForFindelJens = new Integer[] {2, 8, 10, 6, 5};
// Link the races and check the leaderboard again
for(int i = 0; i < 5; i++) {
leaderboardDetails.linkRace(this.leaderboardRaces.get(i), this.trackedRaces.get(i));
leaderboardWindow.switchToWindow();
leaderboard.refresh();
List<LeaderboardEntry> allEntries = table.getEntries();
LeaderboardEntry findelJens = table.getEntry("8875");
Integer points = findelJens.getPointsForRace(String.format("R%s", i + 1));
Integer rank = findelJens.getTotalRank();
// Assertions
assertThat("Number of competitors does not match",
allEntries.size(), equalTo(28));
assertThat("Points for race 'R" + (i + 1) + "' do not match for competitor '8875' (Findel, Jens)",
points, equalTo(expectedPointsForFindelJens[i]));
assertThat("Total rank after " + (i + 1) + " race(s) does not match for competitor '8875' (Findel, Jens)",
rank, equalTo(expectedRankForFindelJens[i]));
adminConsoleWindow.switchToWindow();
}
}
@Test
public void testDynamicRaceDeletion() {
WindowManager manager = this.environment.getWindowManager();
WebDriverWindow adminConsoleWindow = manager.getCurrentWindow();
WebDriverWindow leaderboardWindow = manager.openNewWindow();
// Go to the administration console and link al 5 races
AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(this.regatta.toString());
leaderboardDetails.linkRace(this.leaderboardRaces.get(0), this.trackedRaces.get(0));
leaderboardDetails.linkRace(this.leaderboardRaces.get(1), this.trackedRaces.get(1));
leaderboardDetails.linkRace(this.leaderboardRaces.get(2), this.trackedRaces.get(2));
leaderboardDetails.linkRace(this.leaderboardRaces.get(3), this.trackedRaces.get(3));
leaderboardDetails.linkRace(this.leaderboardRaces.get(4), this.trackedRaces.get(4));
// Open the leaderboard in our second window
leaderboardWindow.switchToWindow();
LeaderboardPage leaderboard = LeaderboardPage.goToPage(getWebDriver(), getContextRoot(), LEADERBOARD, false);
LeaderboardTablePO table = leaderboard.getLeaderboardTable();
// Go back to the administration console and delete third race
adminConsoleWindow.switchToWindow();
RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure();
RegattaDetailsCompositePO regattaDetails = regattaStructure.getRegattaDetails(this.regatta);
SeriesEditDialogPO seriesDialog = regattaDetails.editSeries(RegattaStructureManagementPanelPO.DEFAULT_SERIES_NAME);
seriesDialog.deleteRace("R3");
seriesDialog.pressOk(true);
// Now we can check the result with our expectation
leaderboardWindow.switchToWindow();
leaderboard.refresh();
assertThat("Race names do not match after deletion of race 'R3'",
table.getRaceNames(), equalTo(Arrays.asList("R1", "R2", "R4", "R5")));
}
@Ignore("This test belongs to bug 1892 and currently fails. It is currently enabled on branch bug1892.")
@Test
public void testDynamicRenamingOfRace() {
WindowManager manager = this.environment.getWindowManager();
WebDriverWindow adminConsoleWindow = manager.getCurrentWindow();
WebDriverWindow leaderboardWindow = manager.openNewWindow();
// Go to the administration console and link al 5 races
AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(this.regatta.toString());
leaderboardDetails.linkRace(this.leaderboardRaces.get(0), this.trackedRaces.get(0));
leaderboardDetails.linkRace(this.leaderboardRaces.get(1), this.trackedRaces.get(1));
leaderboardDetails.linkRace(this.leaderboardRaces.get(2), this.trackedRaces.get(2));
leaderboardDetails.linkRace(this.leaderboardRaces.get(3), this.trackedRaces.get(3));
leaderboardDetails.linkRace(this.leaderboardRaces.get(4), this.trackedRaces.get(4));
// Open the leaderboard in our second window
leaderboardWindow.switchToWindow();
LeaderboardPage leaderboard = LeaderboardPage.goToPage(getWebDriver(), getContextRoot(), LEADERBOARD, false);
LeaderboardTablePO table = leaderboard.getLeaderboardTable();
// Go back to the administration console and rename the first race
adminConsoleWindow.switchToWindow();
RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure();
RegattaDetailsCompositePO regattaDetails = regattaStructure.getRegattaDetails(this.regatta);
SeriesEditDialogPO seriesDialog = regattaDetails.editSeries(RegattaStructureManagementPanelPO.DEFAULT_SERIES_NAME);
seriesDialog.renameRace("R1", "Q");
seriesDialog.pressOk(true);
// Now we can check the result with our expectation
leaderboardWindow.switchToWindow();
leaderboard.refresh();
List<String> races = table.getRaceNames();
assertThat("Race names do not match after renaming race 'R1' to 'Q'",
races, equalTo(Arrays.asList("Q", "R2", "R3", "R4", "R5")));
}
private void configureLeaderboard() {
// Open the admin console for some configuration steps
AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
// Create a regatta with 1 series and 5 races as well as a leaderborad
RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure();
regattaStructure.createRegatta(this.regatta);
RegattaDetailsCompositePO regattaDetails = regattaStructure.getRegattaDetails(this.regatta);
SeriesEditDialogPO seriesDialog = regattaDetails.editSeries(RegattaStructureManagementPanelPO.DEFAULT_SERIES_NAME);
seriesDialog.addRaces(1, 5);
seriesDialog.pressOk();
LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
leaderboardConfiguration.createRegattaLeaderboard(this.regatta);
// Start the tracking for the races and wait until they are ready to use
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
tracTracEvents.listTrackableRaces(IDM_5O5_2013_JSON_URL);
tracTracEvents.setReggataForTracking(this.regatta);
tracTracEvents.setTrackSettings(false, false, false);
// TODO: There exists a bug in Selenium with key modifiers (Issue 3734 and 6817), so we can't use multi
// selection (Firefox on Windows)
//tracTracEvents.startTrackingForRaces(this.trackableRaces);
for(TrackableRaceDescriptor race : this.trackableRaces) {
tracTracEvents.startTrackingForRace(race);
}
TrackedRacesListPO trackedRacesList = tracTracEvents.getTrackedRacesList();
trackedRacesList.waitForTrackedRaces(this.trackedRaces, Status.TRACKING);
// TODO: There exists a bug in Selenium with key modifiers (Issue 3734 and 6817), so we can't use multi
// selection (Firefox on Windows)
//trackedRacesList.stopTracking(this.trackedRaces);
for(TrackedRaceDescriptor race : this.trackedRaces) {
trackedRacesList.stopTracking(race);
}
}
}
@@ -12,6 +12,7 @@ import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardConfig
import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardDetailsPanelPO;
import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardDetailsPanelPO.RaceDescriptor;
import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO;
import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO.Status;
import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO.TrackedRaceDescriptor;
import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO;
import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO.TrackableRaceDescriptor;
@@ -70,7 +71,7 @@ public class TestLeaderboardEditing extends AbstractSeleniumTest {
tracTracEvents.startTrackingForRace(trackableRace);
TrackedRacesListPO trackedRacesList = tracTracEvents.getTrackedRacesList();
trackedRacesList.waitForTrackedRace(trackedRace);
trackedRacesList.waitForTrackedRace(trackedRace, Status.TRACKING);
trackedRacesList.stopTracking(trackedRace);
}
Loaded 100 of 201 files, more files were not shown because too many files have changed in this diff. Show more