Merge remote-tracking branch 'origin/master'

This commit is contained in:
Fredrik Teschke committed 2014-05-16 00:28:04 +02:00
commit 2ed0ead422
80 files changed
+2908 -1460

No files matched your search

@@ -2,5 +2,5 @@ package com.sap.sailing.domain.common;
public enum ScoringSchemeType {
LOW_POINT, HIGH_POINT, HIGH_POINT_ESS_OVERALL, HIGH_POINT_LAST_BREAKS_TIE, HIGH_POINT_FIRST_GETS_TEN,
HIGH_POINT_FIRST_GETS_ONE, LOW_POINT_WINNER_GETS_ZERO, HIGH_POINT_WINNER_GETS_SIX
HIGH_POINT_FIRST_GETS_ONE, LOW_POINT_WINNER_GETS_ZERO, HIGH_POINT_WINNER_GETS_SIX, HIGH_POINT_WINNER_GETS_FIVE
}
@@ -13,7 +13,7 @@ import java.util.Comparator;
public class NaturalComparator implements Comparator<String> {
boolean caseSensitive;
public NaturalComparator(boolean caseSensitive){
public NaturalComparator(boolean caseSensitive) {
this.caseSensitive = caseSensitive;
}
@@ -26,7 +26,7 @@ public class NaturalComparator implements Comparator<String> {
*/
@Override
public int compare(String a, String b) {
if(!caseSensitive){
if (!caseSensitive){
a = a.toLowerCase();
b = a.toLowerCase();
}
@@ -89,7 +89,7 @@ public class TeamImpl extends NamedImpl implements DynamicTeam {
@Override
public Nationality getNationality() {
return getNationalityDonor().getNationality();
return getNationalityDonor() == null ? null : getNationalityDonor().getNationality();
}
private WithNationality getNationalityDonor() {
@@ -111,6 +111,9 @@ public class TeamImpl extends NamedImpl implements DynamicTeam {
for (Person sailor : getSailors()) {
((DynamicPerson) sailor).setNationality(newNationality);
}
if (getCoach() != null) {
getCoach().setNationality(newNationality);
}
for (NationalityChangeListener listener : getNationalityChangeListeners()) {
listener.nationalityChanged(this, oldNationality, newNationality);
}
@@ -1,11 +1,15 @@
package com.sap.sailing.domain.base.impl;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.Venue;
import com.sap.sailing.util.impl.LockUtil;
import com.sap.sailing.util.impl.NamedReentrantReadWriteLock;
public class VenueImpl implements Venue {
private static final long serialVersionUID = 6854152040737643290L;
@@ -16,25 +20,54 @@ public class VenueImpl implements Venue {
* "NATO alphabet" (Alpha, Bravo, Charlie, ...).
*/
private final List<CourseArea> courseAreas;
private NamedReentrantReadWriteLock courseAreasLock;
public VenueImpl(String name) {
this.name = name;
courseAreas = new ArrayList<CourseArea>();
courseAreasLock = createCourseAreasLock(name);
}
private NamedReentrantReadWriteLock createCourseAreasLock(String name) {
return new NamedReentrantReadWriteLock("Course Areas for venue "+name, /* fair */ false);
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
if (courseAreasLock == null) {
courseAreasLock = createCourseAreasLock(getName());
}
}
@Override
public Iterable<CourseArea> getCourseAreas() {
return Collections.unmodifiableList(courseAreas);
LockUtil.lockForRead(courseAreasLock);
try {
return Collections.unmodifiableList(courseAreas);
} finally {
LockUtil.unlockAfterRead(courseAreasLock);
}
}
@Override
public void addCourseArea(CourseArea courseArea) {
courseAreas.add(courseArea);
LockUtil.lockForWrite(courseAreasLock);
try {
courseAreas.add(courseArea);
} finally {
LockUtil.unlockAfterWrite(courseAreasLock);
}
}
@Override
public void removeCourseArea(CourseArea courseArea) {
courseAreas.remove(courseArea);
LockUtil.lockForWrite(courseAreasLock);
try {
courseAreas.remove(courseArea);
} finally {
LockUtil.unlockAfterWrite(courseAreasLock);
}
}
@Override
@@ -122,7 +122,7 @@ public class RaceLogImpl extends TrackImpl<RaceLogEvent> implements RaceLog {
eventsById.put(event.getId(), event);
notifyListenersAboutReceive(event);
} else {
logger.warning(String.format("%s (%s) was not added to race log %s. Ignoring", event, event.getClass().getName(), getId()));
logger.fine(String.format("%s (%s) was not added to race log %s because it already existed there.", event, event.getClass().getName(), getId()));
}
return isAdded;
}
@@ -142,8 +142,8 @@ public class RaceLogImpl extends TrackImpl<RaceLogEvent> implements RaceLog {
revokeIfNecessary(event);
eventsById.put(event.getId(), event);
} else {
logger.warning(String
.format("%s (%s) was not loaded into log. Ignoring", event, event.getClass().getName()));
logger.fine(String
.format("%s (%s) was not loaded into log because it already existed there.", event, event.getClass().getName()));
}
return isAdded;
}
@@ -202,7 +202,7 @@ public class RaceLogImpl extends TrackImpl<RaceLogEvent> implements RaceLog {
revokeIfNecessary(event);
notifyListenersAboutReceive(event);
} else {
logger.warning(String.format("%s (%s) was not added to log. Ignoring", event, event.getClass().getName()));
logger.fine(String.format("%s (%s) was not added to log because it already eists there.", event, event.getClass().getName()));
}
return getEventsToDeliver(clientId, event);
}
@@ -191,7 +191,7 @@ public class DomainFactoryImpl implements DomainFactory {
Iterable<Competitor> competitors = createCompetitorList(startList, race.getRaceID(), race.getBoatClass());
logger.info("Creating RaceDefinitionImpl for race "+race.getRaceID());
BoatClass boatClass = race.getBoatClass() != null ? race.getBoatClass() : getRaceTypeFromRaceID(race.getRaceID()).getBoatClass();
RaceDefinition result = new RaceDefinitionImpl(race.getRaceName(), domainCourse, boatClass, competitors);
RaceDefinition result = new RaceDefinitionImpl(race.getRaceName(), domainCourse, boatClass, competitors, race.getRaceID());
regatta.addRace(result);
return result;
}
@@ -518,8 +518,9 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
SailMasterMessage opnResponse = new SailMasterMessageImpl(receiveMessage(is));
if (opnResponse.getType() != MessageType.OPN || !"OK".equals(opnResponse.getSections()[1])) {
logger.info("Recevied non-OK response " + opnResponse + " in "+this+" for our request " + opnRequest
+ ". Closing socket and trying again in 1s...");
closeAndNullSocketAndWaitABit();
+ ". Closing socket and stopping because we have no hope for recovery");
stopped = true;
closeSocket();
} else {
logger.info("Received " + opnResponse + " in "+this+" which seems OK. Continuing with "
+ MessageType.LSN.name() + " request...");
@@ -553,6 +554,11 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
}
private void closeAndNullSocketAndWaitABit() throws InterruptedException {
closeSocket();
Thread.sleep(1000);
}
private void closeSocket() {
if (socket != null) {
try {
socket.close();
@@ -561,7 +567,6 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
}
socket = null;
}
Thread.sleep(1000);
}
@Override
@@ -68,7 +68,11 @@ public class SailMasterMessageImpl implements SailMasterMessage {
} else {
typeAsString = typeAsStringWithOptionalSuffix.substring(0, typeAsStringWithOptionalSuffix.length()-1);
}
return MessageType.valueOf(typeAsString);
try {
return MessageType.valueOf(typeAsString);
} catch (IllegalArgumentException e) {
return null;
}
}
@Override
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.swisstimingreplayadapter.test;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
@@ -195,6 +196,7 @@ public class SwissTimingReplayAdapterServiceTest {
Iterable<? extends TrackedRace> trackedRaces = replayListener.getTrackedRaces();
TrackedRace trackedRace = trackedRaces.iterator().next();
for (Competitor competitor : trackedRace.getRace().getCompetitors()) {
assertSame(DomainFactory.INSTANCE.getBaseDomainFactory().getOrCreateBoatClass("470"), competitor.getBoat().getBoatClass());
Distance distanceToLineAtStart = trackedRace.getDistanceToStartLine(competitor, trackedRace.getStartOfRace());
assertTrue(distanceToLineAtStart.getMeters() > 0);
assertTrue(distanceToLineAtStart.getMeters() < 8.5);
@@ -233,7 +233,7 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter {
short ctPoints_x10_Winner) {
if (boatType == BoatType.Competitor) {
Competitor competitor = domainFactory.createCompetitorWithoutID(sailNumberOrTrackerID, threeLetterIOCCode.trim(), name.trim(),
currentRaceID, null /* boat class */);
currentRaceID, domainFactory.getRaceTypeFromRaceID(currentRaceID).getBoatClass());
Set<Competitor> competitorsOfCurrentRace = competitorsPerRaceID.get(currentRaceID);
if (competitorsOfCurrentRace == null) {
competitorsOfCurrentRace = new HashSet<>();
@@ -306,7 +306,7 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter {
private void createRace() {
final Regatta myRegatta = regatta != null ? regatta : domainFactory.getOrCreateDefaultRegatta(EmptyRaceLogStore.INSTANCE,
currentRaceID, null /* boat class */, trackedRegattaRegistry);
currentRaceID, domainFactory.getRaceTypeFromRaceID(currentRaceID).getBoatClass(), trackedRegattaRegistry);
RaceDefinition race = domainFactory.createRaceDefinition(myRegatta,
currentRaceID, competitorsPerRaceID.get(currentRaceID), currentCourseDefinition);
racePerRaceID.put(currentRaceID, race);
@@ -3,6 +3,10 @@ package com.sap.sailing.domain.common.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
@@ -103,5 +107,12 @@ public class NaturalComparatorTest {
assertTrue(comparator.compare("0.01", "0.2") < 0);
assertTrue(comparator.compare("0.1.5b", "0.2a") < 0);
}
@Test
public void testSortSailIDs() {
List<String> list = Arrays.asList("Groupama", "GER8829", "A", "FRA 56893", "Cam", "GAC Pindar", "Grün", "a/m", "d/n");
Collections.sort(list, new NaturalComparator(/* case sensitive */ false));
assertTrue(list.indexOf("A") < list.indexOf("Cam"));
}
}
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
@@ -97,6 +98,18 @@ public class CompetitorListenerTest extends AbstractSerializationTest {
competitor.addCompetitorChangeListener(listener);
}
@Test
public void testNullNationality() {
competitor.getTeam().setNationality(null);
assertNull(competitor.getTeam().getNationality());
competitor.getTeam().setNationality(null);
assertNull(competitor.getTeam().getNationality());
competitor.getTeam().setNationality(baseDomainFactory.getOrCreateNationality("GER"));
assertEquals(baseDomainFactory.getOrCreateNationality("GER"), competitor.getTeam().getNationality());
competitor.getTeam().setNationality(null);
assertNull(competitor.getTeam().getNationality());
}
@Test
public void testSimpleCompetitorListenerPatternForName() {
competitor.setName("Dr. Hasso Plattner");
@@ -48,7 +48,7 @@ public class DummyTrackedRegattaRegistry implements TrackedRegattaRegistry {
}
@Override
public boolean isRaceBeingTracked(RaceDefinition r) {
public boolean isRaceBeingTracked(Regatta regattaContext, RaceDefinition r) {
return false;
}
@@ -140,7 +140,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest {
return null;
}
@Override
public boolean isRaceBeingTracked(RaceDefinition r) {
public boolean isRaceBeingTracked(Regatta regattaContext, RaceDefinition r) {
return true;
}
@Override
@@ -4,12 +4,16 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import org.junit.Ignore;
import org.junit.Test;
import com.sap.sailing.domain.test.measurements.Measurement;
import com.sap.sailing.domain.test.measurements.MeasurementCase;
import com.sap.sailing.domain.test.measurements.MeasurementXMLFile;
import com.sap.sailing.util.impl.LockUtil;
import com.sap.sailing.util.impl.NamedReentrantReadWriteLock;
@@ -52,17 +56,46 @@ public class LockTraceTest {
assertFalse(lock.getReaders().contains(Thread.currentThread()));
assertEquals(0, lock.getReadHoldCount());
}
@Test
public void testReentrantWriteLockingWithInBetweenReadLocking() {
NamedReentrantReadWriteLock lock = new NamedReentrantReadWriteLock("testReentrantWriteLockingWithInBetweenReadLocking-Lock", /* fair */ false);
LockUtil.lockForWrite(lock);
assertTrue(lock.getWriter() == Thread.currentThread());
LockUtil.lockForRead(lock); // reentrant read while holding write
assertTrue(lock.getReaders().contains(Thread.currentThread()));
LockUtil.lockForWrite(lock); // reentrant write
assertTrue(lock.getWriter() == Thread.currentThread());
assertTrue(lock.getReaders().contains(Thread.currentThread()));
LockUtil.unlockAfterRead(lock);
assertFalse(lock.getReaders().contains(Thread.currentThread()));
assertEquals(0, lock.getReadHoldCount());
assertTrue(lock.getWriter() == Thread.currentThread());
assertFalse(lock.getReaders().contains(Thread.currentThread()));
assertEquals(0, lock.getReadHoldCount());
LockUtil.unlockAfterWrite(lock);
assertTrue(lock.getWriter() == Thread.currentThread());
LockUtil.unlockAfterWrite(lock);
assertFalse(lock.getWriter() == Thread.currentThread());
}
@Test
public void testLockingPerformance() {
public void testLockingPerformance() throws IOException {
NamedReentrantReadWriteLock lock = new NamedReentrantReadWriteLock("Lock", /* fair */ true);
long start = System.currentTimeMillis();
for (int i=0; i<100000; i++) {
final int count = 100000;
for (int i=0; i<count; i++) {
LockUtil.lockForRead(lock);
LockUtil.unlockAfterRead(lock);
LockUtil.lockForWrite(lock);
LockUtil.unlockAfterWrite(lock);
}
MeasurementXMLFile performanceReport = new MeasurementXMLFile(this.getClass());
MeasurementCase performanceReportCase = performanceReport.addCase(getClass().getSimpleName());
performanceReportCase.addMeasurement(new Measurement("Obtaining and releasing "+count+" read and write locks in ms",
System.currentTimeMillis()-start));
performanceReport.write();
System.out.println("Took "+(System.currentTimeMillis()-start)+"ms");
}
@@ -13,16 +13,6 @@ public class FlorianopolisMarkPassingTest extends AbstractMarkPassingTest {
super();
}
@Test
public void testRace1() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("1");
}
@Test
public void testRace2() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("2");
}
@Test
public void testRace3() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("3");
@@ -33,75 +23,57 @@ public class FlorianopolisMarkPassingTest extends AbstractMarkPassingTest {
testRace("4");
}
@Test
public void testRace5() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("5");
}
@Test
public void testRace6() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("6");
}
@Test
public void testRace7() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("7");
}
@Test
public void testRace8() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("8");
}
@Test
public void testRace10() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("10");
}
@Test
public void testRace11() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("11");
}
@Test
public void testRace12() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("12");
}
@Test
public void testRace13() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("13");
}
@Test
public void testRace14() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("14");
}
@Test
public void testRace16() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("16");
}
@Test
public void testRace17() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("17");
}
@Test
public void testRace19() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("19");
}
@Test
public void testRace22() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("22");
}
@Test
public void testRace24() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("24");
}
/*
* Test ignored on master branch to quicken the hudson build.
*
* @Test public void testRace1() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("1"); }
*
* @Test public void testRace2() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("2"); }
*
* @Test public void testRace5() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("5"); }
*
* @Test public void testRace6() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("6"); }
*
* @Test public void testRace7() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("7"); }
*
* @Test public void testRace8() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("8"); }
*
* @Test public void testRace10() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("10"); }
*
* @Test public void testRace11() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("11"); }
*
* @Test public void testRace12() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("12"); }
*
* @Test public void testRace13() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("13"); }
*
* @Test public void testRace14() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("14"); }
*
* @Test public void testRace16() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("16"); }
*
* @Test public void testRace17() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("17"); }
*
* @Test public void testRace19() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("19"); }
*
* @Test public void testRace22() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("22"); }
*
* @Test public void testRace24() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("24"); }
*/
/*
* Alinghi acting wierd
@@ -17,16 +17,16 @@ public class KW470MarkPassingTest extends AbstractMarkPassingTest {
public void testRace4() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("4");
}
@Test
public void testRace5() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("5");
}
@Test
public void testRace6() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("6");
}
/*
* Ignored on master branch
*
* @Test public void testRace5() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("5"); }
*
* @Test public void testRace6() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("6"); }
*/
@Override
protected String getFileName() {
@@ -27,16 +27,14 @@ import com.sap.sailing.domain.tracking.GPSFixMoving;
public class MarkPassingCalculatorPerformanceTest extends AbstractMockedRaceMarkPassingTest {
private static LinkedHashMap<String, Long> result = new LinkedHashMap<>();
private static String className;
public MarkPassingCalculatorPerformanceTest() {
super();
className = getClass().getName();
}
@AfterClass
public static void createXMLFile() throws IOException {
MeasurementXMLFile performanceReport = new MeasurementXMLFile("TEST-MarkPassingCaculatorPerformanceTest.xml", "MarkPassingCaculatorPerformanceTest", className);
MeasurementXMLFile performanceReport = new MeasurementXMLFile(MarkPassingCalculatorPerformanceTest.class);
for (String key : result.keySet()) {
MeasurementCase performanceReportCase = performanceReport.addCase(key);
performanceReportCase.addMeasurement(new Measurement(key, result.get(key)));
@@ -9,7 +9,7 @@ import org.junit.Test;
public class OBMR2012VRMarkPassingTest extends AbstractMarkPassingTest {
public OBMR2012VRMarkPassingTest() throws MalformedURLException, URISyntaxException {
public OBMR2012VRMarkPassingTest() throws MalformedURLException, URISyntaxException {
super();
}
@@ -17,57 +17,43 @@ public class OBMR2012VRMarkPassingTest extends AbstractMarkPassingTest {
public void testRaceFr11() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("Fr_Fleet_1_1");
}
@Test
public void testRaceFr12() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("Fr_Fleet_1_2");
}
@Test
public void testRaceFr13() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("Fr_Fleet_1_3");
}
@Test
public void testRaceFr21() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("Fr_Fleet_2_1");
}
@Test
public void testRaceFr22() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("Fr_Fleet_2_2");
}
@Test
public void testRaceFr23() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("Fr_Fleet_2_3");
}
@Test
public void testRaceSaVm11() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("Sa-Vm_Fleet_1_1");
}
@Test
public void testRaceSaVm12() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("Sa-Vm_Fleet_1_2");
}
@Test
public void testRaceSaVm13() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("Sa-Vm_Fleet_1_3");
}
@Test
public void testRaceSaVm21() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("Sa-Vm_Fleet_2_1");
}
@Test
public void testRaceSaVm22() throws IOException, InterruptedException, URISyntaxException, ParseException {
testRace("Sa-Vm_Fleet_2_2");
}
/*
* Ignored on master branch.
*
* @Test public void testRaceFr13() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("Fr_Fleet_1_3"); }
*
* @Test public void testRaceFr21() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("Fr_Fleet_2_1"); }
*
* @Test public void testRaceFr22() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("Fr_Fleet_2_2"); }
*
* @Test public void testRaceFr23() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("Fr_Fleet_2_3"); }
*
* @Test public void testRaceSaVm11() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("Sa-Vm_Fleet_1_1"); }
*
* @Test public void testRaceSaVm12() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("Sa-Vm_Fleet_1_2"); }
*
* @Test public void testRaceSaVm13() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("Sa-Vm_Fleet_1_3"); }
*
* @Test public void testRaceSaVm21() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("Sa-Vm_Fleet_2_1"); }
*
* @Test public void testRaceSaVm22() throws IOException, InterruptedException, URISyntaxException, ParseException {
* testRace("Sa-Vm_Fleet_2_2"); }
*/
@Override
protected String getExpectedEventName() {
return "OBMR 2012";
@@ -27,6 +27,10 @@ public class MeasurementXMLFile {
private final Set<MeasurementCase> cases;
private final String testClassName;
public MeasurementXMLFile(Class<?> testClass) {
this("TEST-"+testClass.getSimpleName()+".xml", testClass.getSimpleName(), testClass.getName());
}
public MeasurementXMLFile(String reportFileName, String testSuiteName, String testClassName) {
this.reportFileName = reportFileName;
this.testSuiteName = testSuiteName;
@@ -21,5 +21,4 @@ public interface RaceDefinition extends Named, WithID {
Course getCourse();
Iterable<Competitor> getCompetitors();
}
@@ -39,7 +39,6 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
this.trackedRaces = new TrackedRaces();
this.raceIdentifiers = new HashMap<Fleet, RaceIdentifier>();
this.raceLogs = new HashMap<Fleet, RaceLog>();
}
@Override
@@ -35,6 +35,7 @@ import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOver
import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets10LastBreaksTie;
import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets1LastBreaksTie;
import com.sap.sailing.domain.leaderboard.impl.HighPointLastBreaksTie;
import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsFive;
import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsSix;
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
import com.sap.sailing.domain.leaderboard.impl.LowPointWinnerGetsZero;
@@ -87,6 +88,8 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain
return new HighPointFirstGets10LastBreaksTie();
case LOW_POINT_WINNER_GETS_ZERO:
return new LowPointWinnerGetsZero();
case HIGH_POINT_WINNER_GETS_FIVE:
return new HighPointWinnerGetsFive();
case HIGH_POINT_WINNER_GETS_SIX:
return new HighPointWinnerGetsSix();
}
@@ -109,7 +112,8 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain
// Optional: Getting the places of the race
PlacemarkOrderDTO racePlaces = withGeoLocationData ? getRacePlaces(trackedRace) : null;
TrackedRaceDTO trackedRaceDTO = createTrackedRaceDTO(trackedRace);
RaceDTO raceDTO = new RaceDTO(raceIdentifier, trackedRaceDTO, trackedRegattaRegistry.isRaceBeingTracked(trackedRace.getRace()));
RaceDTO raceDTO = new RaceDTO(raceIdentifier, trackedRaceDTO, trackedRegattaRegistry.isRaceBeingTracked(
trackedRace.getTrackedRegatta().getRegatta(), trackedRace.getRace()));
raceDTO.places = racePlaces;
updateRaceDTOWithTrackedRaceData(trackedRace, raceDTO);
return raceDTO;
@@ -34,6 +34,7 @@ import com.sap.sailing.domain.leaderboard.ResultDiscardingRule;
import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
import com.sap.sailing.domain.racelog.RaceLogInformation;
import com.sap.sailing.domain.racelog.RaceLogStore;
import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore;
import com.sap.sailing.domain.racelog.impl.RaceLogInformationImpl;
@@ -159,11 +160,20 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
/**
* When de-serializing, a possibly remote {@link #raceLogStore} is ignored because it is transient. Instead, an
* {@link EmptyRaceLogStore} is used for the de-serialized instance.
* {@link EmptyRaceLogStore} is used for the de-serialized instance. A new {@link RaceLogInformation} is assembled
* for this empty race log and applied to all columns.
*/
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
raceLogStore = EmptyRaceLogStore.INSTANCE;
for (Series series : getSeries()) {
if (series.getRaceColumns() != null) {
for (RaceColumnInSeries column : series.getRaceColumns()) {
column.setRaceLogInformation(new RaceLogInformationImpl(raceLogStore,
new RaceLogOnRegattaIdentifier(this, column.getName())));
}
}
}
regattaListeners = new HashSet<RegattaListener>();
}
@@ -19,6 +19,7 @@ import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
import com.sap.sailing.domain.leaderboard.FlexibleRaceColumn;
import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
import com.sap.sailing.domain.racelog.RaceLogInformation;
import com.sap.sailing.domain.racelog.RaceLogStore;
import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore;
import com.sap.sailing.domain.racelog.impl.RaceLogInformationImpl;
@@ -67,11 +68,16 @@ public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements
/**
* Deserialization has to be maintained in lock-step with {@link #writeObject(ObjectOutputStream) serialization}.
* When de-serializing, a possibly remote {@link #raceLogStore} is ignored because it is transient. Instead, an
* {@link EmptyRaceLogStore} is used for the de-serialized instance.
* {@link EmptyRaceLogStore} is used for the de-serialized instance. A new {@link RaceLogInformation} is
* assembled for this empty race log and applied to all columns.
*/
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
raceLogStore = EmptyRaceLogStore.INSTANCE;
for (RaceColumn column : getRaceColumns()) {
column.setRaceLogInformation(new RaceLogInformationImpl(raceLogStore, new RaceLogOnLeaderboardIdentifier(
this, column.getName())));
}
}
@Override
@@ -0,0 +1,16 @@
package com.sap.sailing.domain.leaderboard.impl;
import com.sap.sailing.domain.common.ScoringSchemeType;
public class HighPointWinnerGetsFive extends HighPointFirstGetsFixedScore {
private static final long serialVersionUID = 1367473387431601943L;
public HighPointWinnerGetsFive() {
super(/* scoreForRaceWinner */ 5);
}
@Override
public ScoringSchemeType getType() {
return ScoringSchemeType.HIGH_POINT_WINNER_GETS_FIVE;
}
}
@@ -44,7 +44,7 @@ public interface TrackedRegattaRegistry {
*/
Regatta getRememberedRegattaForRace(Serializable raceID);
boolean isRaceBeingTracked(RaceDefinition r);
boolean isRaceBeingTracked(Regatta regattaContext, RaceDefinition r);
/**
* Stops all {@link RaceTracker}s currently tracking <code>race</code>. Note that if the same tracker also may have
+1
View File
@@ -35,5 +35,6 @@
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>com.google.gwt.eclipse.core.gwtNature</nature>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
</natures>
</projectDescription>
@@ -1,3 +1,3 @@
#Fri Jan 13 22:25:34 CET 2012
eclipse.preferences.version=1
encoding//src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties=UTF-8
eclipse.preferences.version=1
encoding//src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties=UTF-8
encoding//src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties=UTF-8
+59 -59
View File
@@ -1,59 +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"/>
<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>
<?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>
@@ -1,848 +0,0 @@
/**
* 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);
}
@@ -58,9 +58,10 @@ public class CompetitorTableWrapper extends TableWrapper<CompetitorDTO, MultiSel
};
boatClassColumn.setSortable(true);
competitorColumnListHandler.setComparator(boatClassColumn, new Comparator<CompetitorDTO>() {
private final NaturalComparator comparator = new NaturalComparator(/* caseSensitive */ false);
@Override
public int compare(CompetitorDTO o1, CompetitorDTO o2) {
return new NaturalComparator(false).compare(o1.getBoatClass().getName(), o2.getBoatClass().getName());
return comparator.compare(o1.getBoatClass().getName(), o2.getBoatClass().getName());
}
});
@@ -86,9 +87,10 @@ public class CompetitorTableWrapper extends TableWrapper<CompetitorDTO, MultiSel
};
sailIdColumn.setSortable(true);
competitorColumnListHandler.setComparator(sailIdColumn, new Comparator<CompetitorDTO>() {
private final NaturalComparator comparator = new NaturalComparator(/* case sensitive */ false);
@Override
public int compare(CompetitorDTO o1, CompetitorDTO o2) {
return new NaturalComparator(false).compare(o1.getSailID(), o2.getSailID());
return comparator.compare(o1.getSailID(), o2.getSailID());
}
});
@@ -39,12 +39,9 @@ public abstract class TableWrapper<T, S extends SelectionModel<T>> implements Is
this.selectionModel = selectionModel;
this.dataProvider = new ListDataProvider<T>();
mainPanel = new VerticalPanel();
table = new CellTable<T>(10000, tableRes);
dataProvider.addDataDisplay(table);
table.setSelectionModel(selectionModel);
mainPanel.add(table);
}
@@ -374,6 +374,7 @@ public interface StringMessages extends Messages {
String scoringSchemeLowPointSystem();
String scoringSchemeHighPointSystem();
String scoringSchemeLowPointWinnerGetsZero();
String scoringSchemeWinnerGetsFive();
String scoringSchemeWinnerGetsSix();
String scoringSystem();
String createFlexibleLeaderboard();
@@ -403,6 +403,7 @@ scoringSchemeHighPointSystem=High Point System
scoringSchemeHighPointEssOverall=High Point System ESS Overall
scoringSchemeHighPointLastBreaksTie=High Point System, Last Race Breaks Tie
scoringSchemeLowPointWinnerGetsZero=Low Point System, Winner Gets Zero
scoringSchemeWinnerGetsFive=High Point System, Winner Gets 5 Points
scoringSchemeWinnerGetsSix=High Point System, Winner Gets 6 Points
scoringSystem=Scoring system
createFlexibleLeaderboard=Create flexible leaderboard
@@ -404,6 +404,7 @@ scoringSchemeHighPointSystem=High Point System
scoringSchemeHighPointEssOverall=High Point System ESS Gesamtwertung
scoringSchemeHighPointLastBreaksTie=High Point System, letztes Rennen entscheidet bei Gleichstand
scoringSchemeLowPointWinnerGetsZero=Low Point System, Gewinner erhält 0 Punkte
scoringSchemeWinnerGetsFive=High Point System, Gewinner erhält 5 Punkte
scoringSchemeWinnerGetsSix=High Point System, Gewinner erhält 6 Punkte
scoringSystem=Bepunktungssystem
createFlexibleLeaderboard=Flexible Rangliste anlegen
@@ -0,0 +1,970 @@
# If you want new properties translated then sent this over GMR (Mark Angell <mangell@gmr.com>)
helloWorld=Привет Мир
kielWeel2011=Кильская Неделя 2011
stgAccount=Счет STG
tracTracEvents=События Трак Трак
swissTimingEvents=События Swiss Timing
trackedBefore=Ранее Отслеженные
listRaces=Перечень Гонок
wind=Ветер
windPanelLabel=Это окно информации о ветре, которое до сих пор абсолютно пустое.
refresh=Обновить
remove=Удалить
windSource=Источники информации о ветре
dampeningInterval=Интервал ослабления
map=Карта
race=Гонка
races=Гонки
tracked=Отслежена
time=Время
timeTooltip=Учет времени соперника, выступавшего на этом этапе. На первом этапе учет времени ведется с начала гонки, а не при пересечении соперником линии старта.
playSpeed=Скорость воспроизведения
playSpeedHelp=Используйте "1" для обычной скорости воспроизведения, "2" для удвоенной скорости воспроизведения и т. д.
playModeLive=В прямом эфире
playModeReplay=Режим повтора
timeDelay=Задержка
timeDelayHelp=Не указывайте, для воспроизведения повтора в любой момент времени; введите секунды (например, "60" для одной минуты или "0" без указания) задержки перед загрузкой данных в режиме реального времени
speedInKnots=Скорость (узлы)
fromDeg=Начиная с (градус)
noRacesYet=Гонок пока нет.
total=\u03A3
carry=Суммарная
competitor=Соперник
competitors=Соперники
defaultLeaderboard=Таблица лидеров по умолчанию
noSuchLeaderboard=Такая таблица лидеров отсутствует
leaderboardConfiguration=Форма таблицы лидеров
newDotDotDot=Новый...
editScores=Изменить баллы...
columnNamesInSelectedLeaderboard=Названия гонок в выбранной таблице лидеров
addDotDotDot=Добавить...
renameDotDotDot=Переименовать...
trackedRaceConnectedToSelectedRaceName=Отслеженная гонка, соединенная с выбранным названием гонки
linkToColumn=Соединить со столбцом
unlink=Отсоединить
leaderboardName=Имя таблицы лидеров
cancel=Отмена
pleaseEnterAName=Пожалуйста, введите имя
pleaseEnterABoatClass=Пожалуйста, введите класс судна
discardRacesFromHowManyStartedRacesOn=Не учитывать еще одну начинающуюся гонку в количестве начавшихся гонок
leaderboardWithThisNameAlreadyExists=Таблица лидеров с таким именем уже существует
discardThresholdsMustBeNumeric=Предельные значения не учитываемых должны быть выражены числом
discardThresholdsMustBeAscending=Предельные значения не учитываемых должны быть возрастающими
discarding=Неучет
startingFromNumberOfRaces=Начиная с количества гонок
renameLeaderboard=Переименовать таблицу лидеров
addColumnToLeaderboard=Добавить столбец в таблицу лидеров
pleaseEnterNameForNewRaceColumn=Введите, пожалуйста, имя для столбца новой гонки
ok=OK
medalRace=Медальная гонка
renameRace=Переименовать гонку
openSelectedLeaderboard=Открыть выбранную таблицу лидеров
rank=Занимаемое место
rankTooltip=Место, занимаемое участником в гонке
regattaRank=Место, занимаемое в регате
regattaRankTooltip=Место, занимаемое участником в регате
overallRank=Итоговое место
overallRankTooltip=Место, занимаемое участником на этапах
totalRegattaRank=Итоговое место в регате
collapse=-
expand=+
leg=L
distanceInMeters=Расстояние
averageSpeedInKnots=\u2205 Скорость
averageSpeedInKnotsTooltip=Средняя скорость относительно земли в ходе этого этапа,\nрассчитывается путем деления пройденного расстояния на затраченное на это время.
raceAverageSpeedInKnotsTooltip=Средняя скорость относительно земли в ходе этой гонки,\nрассчитывается путем деления пройденного расстояния на затраченное на это время.
rankGain=Улучшение места
rankGainTooltip=Разность между местом, занятым на текущем и предыдущем этапах.
sapSailingAnalytics=Аналитическая информация парусного спорта
leaderboard=Таблица лидеров
leaderboards=Таблицы лидеров
leaderboardSettings=Параметры таблицы лидеров
settings=Параметры
selectAtLeastOneLegDetail=Выберите хотя бы одну подробность об этапе
currentSpeedOverGroundInKnots=Скорость относительно земли (SOG)
currentSpeedOverGroundInKnotsTooltip=Текущая скорость относительно земли.
estimatedTimeToNextWaypointInSeconds=Расчетное время прибытия (ETA).
estimatedTimeToNextWaypointInSecondsTooltip= Расчетное время, необходимое участнику для прибытия в следующую промежуточную точку маршрута, исходя из скорости лавирования участника и с учетом истинного направление ветра.
gapToLeaderInSeconds=Отставание от лидера
gapToLeaderInSecondsTooltip=Время, необходимое участнику для достижения текущего положения лидера, исходя из скорости лавирования.
velocityMadeGoodInKnots=Скорость лавирования (VMG)
velocityMadeGoodInKnotsTooltip=Скорость лавирования, представляет собой скорость продвижения на ветер/ по ветру для этапов движения против ветра/ по ветру соответственно, или скорость в направлении движения при лавировании по ветру
windwardDistanceToGoInMeters=Расстояние, которое необходимо пройти на ветер
windwardDistanceToGoInMetersTooltip=Расстояние движения на ветер/ по ветру от текущего положения участника до конца этапа для этапов движения против ветра/ по ветру соответственно, или скорость в направлении движения при лавировании по ветру.
windwardDistanceToLeaderInMeters=Расстояние на ветер до лидера
windwardDistanceToLeaderInMetersTooltip=Расстояние на ветер/ под ветер от участника до лидера для этапов движения против ветра/ по ветру соответственно или скорость в направлении движения при лавировании по ветру.
name=Имя
leaveEmptyForDefault=Оставьте пустым по умолчанию.
trackNewEvent=Отследить новое событие
trackableRaces=Отслеживаемые гонки
trackWind=Отслеживать ветер
regattaName=Название регаты
eventName=Название события
event=Событие
startTime=Время старта
regatta=Регата
regattas=Регаты
startTracking=Начать отслеживание
stopTracking=Остановить отслеживание
connections=Подключения
historyOfConnections=История подключений
defineNewConnection=Определить новое подключение
trackedRaces=Отслеженные гонки
canSendRequests=Можно отправить запрос
connectAndReadRaces=Подключиться и прочитать данные о гонке
ports=Порты
liveData=Данные в реальном времени
storedData=Сохраненные данные
uris=URI-адреса
jsonUrl=JSON URL
livePort=Порт данных в реальном времени
storedPort=Порт сохраненных данных
liveUri=Данные пользователя в реальном времени
storedUri=Сохраненные данные пользователя
eventsConnectedTo=Текущие отслеживаемые события
hostname=Имя узла
declinationCheckbox=Корректировка направления ветра с помощью отклонения
raceStartTrackingColumn=Отслеживание начато
pauseAutomaticRefresh=Приостановка автоматического обновления
autoRefresh=Обновлять автоматически
delayInSeconds=Задержка (и)
delayBetweenAutoAdvances=Задержка между автоматическими обновлениями в секундах:
delayMustBeNonNegative=Значение задержки должно быть больше нуля
chooseUpdateIntervalOfAtLeastOneSecond=Выберите интервал обновления, он должен быть не менее одной секунды
errorSettingWindForRace=Ошибка при настройке параметра ветер для гонки
errorFetchingWindInformationForRace=Ошибка при получении данных о ветре для гонки
errorWhileTryingToSetWindSourceForRace=Ошибка при попытке установить флажок «начинается встречный ветер»
inEvent=В случае
to=к
showEstimatedWind=Показать оценочный ветер
timing=Хронометраж
raceDetailsToShow=Подробные сведения о гонке
overallDetailsToShow=Общие сведения
legDetailsToShow=Сведения об этапе
columnMoveUp=Вверх
columnMoveDown=Вниз
port=Порт
raceStartTimeColumn=Гонка началась
showOnlySelectedCompetitors=Показать только выбранных участников
showSelectedCompetitorsInfo=Показать окно краткого описания только для выбранных участников
tailLength=Длина (с) хвоста
selectedRaces=Какие гонки вы хотели бы отобразить?
lengthInSeconds=Длина (с)
stressTest=Стресс тест
numberOfManeuvers=Маневры
numberOfManeuversTooltip=Количество маневров, выполненных во время этого этапа.
numberOfManeuversInRaceTooltip=Количество маневров, выполненных во время этой гонки.
tacks=Галсы
jibes=Перекладывания паруса
penaltyCircles=Штрафные круги
medalRaceIsNull=Значение медальной гонки недопустимо
configuration=Конфигурация
maneuverTypes=Маневры
chooseChart=Выбрать график
distanceTraveled=Пройденное расстояние
distanceTraveledTooltip=Расстояние, пройденное от старта до финиша этапа\а не до текущего момента времени, если этап не завершен.
raceDistanceTraveledTooltip=Расстояние, пройденное от старта до финиша гонки\а не до текущего момента времени, если гонка не завершена.
velocityMadeGoodLong=Скорость лавирования
speedOverGroundLong=Скорость относительно земли
gapToLeaderLong=Отставание от лидера
pointsToLoad=Баллов для нагрузки
speed=Скорость
distance=Расстояние
in=в
secondsUnit=с
metersUnit=м
close=Закрыть
compareCompetitors=Сравнить участников
description=Описание
sailNumber=Номер на парусе
country=Страна
no3LetterCodes=Не удалось найти 3-х буквенные коды стран МОК.
add=Добавить
delete=Удалить
showCharts=Показать графики
raceWithThisNameAlreadyExists=Гонка с таким именем уже существует.
raceWithThisNameAlreadyExistsInRegatta=Гонка с таким именем уже существует в этой регате.
headUp=Заголовок
bearAway=Поворачивать под ветер
tack=Галс
tackTooltip=Количество галсов совершенных во время этой гонки.
jibe=Перебрасывать парус
jibeTooltip=Количество перебрасываний паруса во время этой гонки.
penaltyCircle=Штрафной круг
penaltyCircleTooltip=Количество штрафных кругов, пройденных в ходе этой гонки.
markPassing=Проход знака
mark=Знак
otherManeuver=Неизвестный маневр
douglasPeuckerPoints=Точки алгоритма Дугласа-Пойкера
filterRacesByName=Сортировать гонки по названию
trackSettings=Отслеживать параметры
actionEdit=Изменить
actionEditCompetitors=Изменить участников
actionEditScores=Изменить баллы
actionOpenBrowser=Открыть в браузере
actionRemove=Удалить
actionEditSeries=Изменить серии
actionRaceEdit=Изменить или переименовать гонку
actionRaceUnlink=Отсоединить гонку
actionRaceRemove=Удалить гонку
actionExportXML=Экспорт в формате XML
filterLeaderboardsByName=Сортировать таблицы лидеров по названию
actions=Действия
islinked=Соединен
yes=Да
no=Нет
hoverOverAPoint=Наведите курсор на точку для просмотра подробных сведений
noSelection=Ничего не выбрано
raceIsKnownToStartUpwind=Гонка начинается с этапа с наветренной стороны
events=События
settingsForComponent=Параметры для {0}
noEventsFound=События не обнаружены
noEventSelected=События не выбраны
noLeaderboardsFound=Талицы лидеров не обнаружены
searchEvents=Поиск событий
location=Местонахождение
from=С
until=По
onlyLiveEvents=Только события в прямом эфире
locationNotAvailable=Местонахождение недоступно
startDateNotAvailable=Дата начала недоступна
startDate=Дата начала
endDate=Дата окончания
unknownManeuver=Неизвестный маневр
tailLengthMustBePositive=Число длины хвоста должно быть больше нуля.
failedToLoadRaceInformation=Сбой при загрузке сведений о гонке: {0}
competitorPassedMarkAtDate={0} прошли {1} в {2}
valueForCompetitorAt={0} в {1}: {2}
reallyRemoveRace=Вы действительно хотите удалить гонку ''{0}''? Примечание: все записи о гонке будут также удалены без возможности восстановления!
showDetails=Показать подробности
hideLeaderboard=Скрыть таблицу лидеров
hideLeaderboards=Скрыть таблицы лидеров
showLeaderboard=Показать таблицу лидеров
hideRaces=Скрыть гонки
showMap=Показать карту
hideMap=Скрыть карту
noLeaderboardSelected=Таблица лидеров не выбрана
leaderboardGroups=Группы таблицы лидеров
filterLeaderboardGroupsByName=Сортировать группы таблицы лидеров по имени
createNewLeaderboardGroup=Создать группу таблицы лидеров
leaderboardGroupConfiguration=Конфигурация группы таблицы лидеров
legs=Этапы
currentLeg=На этапе
currentLegTooltip=Номер этапа, на котором находится участник в данный момент, начиная с 1
leaderboardGroup=Группа таблицы лидеров
pleaseEnterNonEmptyDescription=Пожалуйста, введите непустое описание
groupWithThisNameAlreadyExists=Группа таблицы лидеров с этим именем уже существует.
detailsOfLeaderboardGroup=Сведения о группе таблицы лидеров
edit=Изменить
save=Сохранить
abort=Отмена
noLeaderboardGroupWithNameFound=Группа таблицы лидеров с именем {0} не обнаружена
overview=Обзор
welcomeToSailingAnalytics=Добро пожаловать в Аналитическую информацию парусного спорта SAP
welcomeToSailingAnalyticsBody=SAP приближает любителей парусного спорта к происходящим на воде событиям как никогда раньше.\
\ Таблица лидеров в прямом эфире расширяет возможности для любителей, отображая в режиме реального времени место, занимаемое участником, скорости судов, а также победителей с указанием отрыва. Следите за каждой гонкой и благодаря SAP не пропускайте ни одного совершенного маневра.\
\ Это самый простой способ наблюдать за парусной гонкой в прямом эфире, где бы вы ни находились.
home=Главная
clickAndDragToZoomIn=Щелкните и перетащите область графика для увеличения
windSpeed=Скорость ветра (узлы)
allTimesInUTC=Время указано в универсальном глобальном времени по Гринвичу (UTC)
autoZoomTo=Автоматическое масштабирование до
autoZoomToBoats=Суда
autoZoomToBuoys=Буи
autoZoomToWindSensors=Датчики ветра
autoZoomOff=Выкл
autoZoomToTails=Хвосты
autoZoomSelectedCompetitors=Масштабировать только выбранных участников
bearing=Направление (ветра)
zoom=Масштабирование
stepSizeMustBeGreaterThanNull=Размер шага должен быть больше 0
stepSizeInSeconds=Размер шага в секундах
refreshInterval=Обновить интервал (ы)
refreshIntervalMustBeGreaterThanXSeconds=Обновление интервала должно быть больше, чем {0} секунд
competitorCharts=Графики участника
selectAtLeastOneCompetitor=Для отображения графиков участников, выберите хотя бы одного участника
directionChange=Изменение направления
speedChange=Изменение скорости
degreesShort=градус
untracked=Неотслеженная
delayForLiveMode=Задержка для режима прямого эфира:
notAvailable=Недоступно
details=Подробности
noGroupSelected=Группа не выбрана
combinedWindSourceTypeName=Комбинированная
courseBasedWindSourceTypeName=Проложенный курс
trackBasedEstimationWindSourceTypeName=Расчетный
expeditionWindSourceTypeName=Измеренный
webWindSourceTypeName=Вручную
raceCommitteeWindSourceTypeName=Гоночный комитет
clickChartToSetTime=Щелкните по графику для установки времени
position=Положение
windSourcesUsed=Использованные источники информации о ветре
errorTryingToUpdateWindSourcesToExclude=Ошибка при попытке обновления источников информации о ветре для исключения для гонки {0}: {1}
feedback=Комментарии
startStopPlaying=Начать/Остановить воспроизведение
backToLive=Вернуться к моменту времени в прямом эфире
slowPlaySpeedDown=Замедлить скорость воспроизведения или даже воспроизводить назад.
speedPlaySpeedUp=Увеличить скорость воспроизведения или снова воспроизводить вперед.
showHideComponent=Показать/ Скрыть {0}
degreesBoatToTheWind=Угол к ветру
racesInLeaderboard=Гонки в таблице лидеров
leaderboardsInGroup=Таблицы лидеров в группе
replication=Дублирование
errorFetchingReplicaData=Ошибка получения данных дублирования: {0}
averageCrossTrackErrorInMeters=\u2205 XTE
averageCrossTrackErrorInMetersTooltip=Среднее боковое уклонение от заданного курса по большой дуге окружности, соединяющей начало и конец этапа
raceAverageCrossTrackErrorInMetersTooltip=Среднее боковое уклонение от заданного курса по большой дуге окружности, соединяющей начало и конец этапа в течение этой гонки.
enterMaster=Имя узла ведущего экземпляра
errorStartingReplication=Ошибка начала повтора с узла {0} / обмена {1}: {2}
helpLines=Вспомогательные линии
startLine=Линия старта
finishLine=Линия финиша
advantageLine=Линия преимущества
courseMiddleLine=Средняя линия курса
messagingPortNumber=Номер порта обмена сообщениями ( по умолчанию 0)
servletPortNumber=Номер порта сервлета
registeredAt=Зарегистрирован в {0}
replicatingFromMaster=Дублирование с основного {0}, порт передачи обмена сообщениями {1}, порт сервлета {2}
showWindSpeedSeries=Показать данные о силе ветра
showWindDirectionSeries=Показать данные о направлении ветра
fleet=Флот
boatClass=Класс судна
setDelayToLive=Установить задержку от прямого эфира
pleaseEnterNonEmptyVenue=Введите, пожалуйста, место проведения соревнования.
pleaseEnterStartAndEndDate=Пожалуйста, введите дату начала и дату окончания.
startDateMustBeforeEndDate=Дата начала должна предшествовать дате окончания.
eventWithThisNameAlreadyExists=Событие с этим именем уже существует.
venue=Место проведения
pleaseSelectABoatClass=Выберите, пожалуйста, класс судна.
regattaWithThisNameAlreadyExists=Регата с этим именем уже существует.
seriesWithThisNameAlreadyExists=Серия с этим именем уже существует.
fleetWithThisNameAlreadyExists=Флот с этим именем уже существует.
fleets=Флоты
series=Серии
splitFleet=Разделить флот
color=Цвет
medalSeries=Медальные серии
noColor=Цвет не указан
pleaseSelectARegatta=Пожалуйста, выберите регату.
addFleet=Добавить флот
doYouReallyWantToRemoveRegatta=Вы действительно хотите удалить регату "{0}"? Это приведет к удалению без возможности восстановления всех таблиц лидеров для этой регаты!
errorLoadingScoreCorrectionProviders=Ошибка при загрузке провайдеров для корректировки очков: {0}
selectResultListToImportFrom=Выберите список результатов для импорта из
of=из
errorObtainingScoreCorrections=Ошибка получения корректировки очков от провайдера {0} и события {1} для класса судна {2} опубликованного {3}: {4}
assignRaceNumbersToRaceColumns=Назначение номеров гонок из официальных результатов столбам гонок таблицы лидеров
importOfficialResults=Импорт официальных результатов...
selectAll=Выбрать все
apply=Применить
successfullyUpdatedScores=Очки обновлены успешно
errorUpdatingScoresForLeaderboard=Ошибка обновления очков для таблицы лидеров {0}: {1}
maneuverTypesToShowWhenCompetitorIsClicked=Типы маневров для отображения при нажатии на участника
simulateWithStartTimeNow=Моделирования с "сейчас" в качестве времени начала
boatClassDoesNotMatchSelectedRegatta=Выбранные гонки содержат классы судов не соответствующие классу судов ''{0}'' выбранной регаты.\\ Вы действительно хотите использовать регату ''{1}''?
regattaExistForSelectedBoatClass=Есть только одна регата для выбранных классов судов.\\ Вы действительно хотите использовать выбор ''ни одной регаты''?
reload=Перезагрузить
addRegatta=Добавить регату...
exchangeName=Заменить имя
course=Курс
courseLayout=Проложенный курс
buoy=Буй
gate=Ворота
buoys=Буи
waypoint=Точка маршрута
showAllCompetitors=Показать всех участников
boatTails=Лодочные хвосты
resultImportUrls=URL-адреса импорта результатов
errorRefreshingResultImportUrlList=Ошибка обновления списка URL-адресов импорта результатов: {0}
successfullyUpdatedResultImportUrls=Список URL-адресов импорта результатов успешно обновлен
errorRemovingResultImportUrls=Ошибка удаления URL-адресов импорта результатов: {0}
pleaseEnterNonEmptyUrl=Пожалуйста, введите URL-адрес
addResultImportUrl=Добавить URL-адрес импорта результатов
errorAddingResultImportUrl=Ошибка добавления URL-адреса импорта результатов: {0}
errorTryingToObtainLeaderboardContents=Ошибка попытки получения содержимого таблицы лидеров: {0}
lastScoreUpdate=Обновление последних очков
warningBrowserUnsupported=Этот веб-сайт не оптимизирован для вашего браузера. Пожалуйста, выберите браузер новой версии, такой как Firefox или Chrome.
newMark=Новый знак
controlPoint=Знак/Ворота
errorUpdatingRaceCourse=Ошибка обновления курса гонки: {0}
successfullyUpdatedCourse=Курс гонки успешно обновлен
selectOneMarkOrTwoMarksForGate=Выберите одну отметку или две отметки для создания ворот
errorTryingToObtainTheMarksOfTheRace=Ошибка попытки получения отметок дистанции гонки: {0}
errorTryingToObtainRaceCourse=Ошибка попытки получения курса гонки: {0}
insertWaypointBeforeSelected=Вставьте ранее выбранную точку маршрута
insertWaypointAfterSelected=Вставьте точку маршрута, выбранную позднее
scoringSchemeLowPointSystem=Низкобальная (линейная) система подсчета очков
scoringSchemeHighPointSystem=Высокобальная система подсчета очков
scoringSchemeHighPointEssOverall=Высокобальная система подсчета, итоговые баллы экстремальной серии ESS
scoringSchemeHighPointLastBreaksTie=Высокобальная система подсчета, тай-брейк на последней гонке
scoringSchemeLowPointWinnerGetsZero=Низкобальная система подсчета очков, победитель получает ноль очков
scoringSchemeWinnerGetsFive=Высокобальная система подсчета, победитель получает 5 очков
scoringSchemeWinnerGetsSix=Высокобальная система подсчета, победитель получает 6 очков
scoringSystem=Система подсчета очков
createFlexibleLeaderboard=Создание адаптивной таблицы лидеров
createRegattaLeaderboard=Создание таблицы лидеров регаты
editFlexibleLeaderboard=Изменение адаптивной таблицы лидеров
editRegattaLeaderboard=Изменение таблицы лидеров регаты
defaultRegatta=Регата по умолчанию
useOverallLeaderboard=Использование общей таблицы лидеров
overallStandings=Общий зачет
type=Тип
actionAddRaces=Добавить гонки
racesWithNamePrefix=Гонки с именем-префиксом
maximumSpeedOverGroundInKnots=Максимальная скорость относительно земли
maximumSpeedOverGroundInKnotsTooltip=Самая большая скорость относительно земли участника, измеренная в ходе регаты.
totalTimeSailedDownwindInSeconds=Общее время под ветером
totalTimeSailedDownwindInSecondsTooltip=Общее время, которое в течение регаты участник шел под ветер.
totalTimeSailedUpwindInSeconds=Общее время против ветер
totalTimeSailedUpwindInSecondsTooltip=Общее время, которое в течение регаты участник шел против ветер.
totalTimeSailedReachingInSeconds=Общее время лавирования по ветру
totalTimeSailedReachingInSecondsTooltip=Общее время этапов лавирования по ветру участником в ходе регаты.
totalTimeSailedInSeconds=Общее время
totalTimeSailedInSecondsTooltip=Общее время, которое участник проплыл в регате.
totalDistanceTraveled=Общее расстояние
totalDistanceTraveledTooltip=Общее расстояние, пройденное во время регаты.
totalAverageSpeedOverGround=\u2205 Скорость относительно земли
totalAverageSpeedOverGroundTooltip=Средняя скорость относительно земли на протяжении регаты.
hhmmssUnit=чч:мм:сс
actionAddWindData=Добавить данные о ветре
valueMustBeBetweenMinMax=Значение ''{0}''должно быть в пределах от {1} до {2}.
optional=Дополнительно
pleaseEnterAValue=Введите, пожалуйста, значение.
latitude=Широта
longitude=Долгота
actionAddEvent=Добавить событие
publicationUrl=URL-адрес для публикации
suppress=скрыть
isPublic=является открытым
suppress=скрыть
unsuppress=Отобразить
suppressedCompetitors=Скрытые участники
mediaPanel=Аудио и Видео
url=URL
mimeType=MIME-тип
title=Заголовок
duration=Продолжительность (ч:мм:сс.мс)
addMediaTrack=Добавить аудио/видео
addYoutubeTrack=Добавить Youtube
youtubeId=Идентификатор Youtube
reallyRemoveMediaTrack=Вы действительно хотите удалить медиа трек''{0}''?
pleaseSelectASeries=Пожалуйста, выберите серию
pleaseSelectARace=Пожалуйста, выберите гонку
displayGroupsInReverseOrder=Отобразить группы в обратном порядке
actionConfigureUrl=Настроить URL-адрес
configureLeaderboardUrlDescription=Настроить таблицу лидеров и получить результирующий URL-адрес по ссылке
embedded=Внедренный
additionalUrlSettings=Дополнительные параметры URL-адреса
restrictToSingleSelectedRace=Ограничить одной выбранной гонкой
expandSelectedRace=Расширить выбранную гонку
showRaceDetails=Разрешить подробности для гонки
numberOfRaces=Количество гонок
numberOfRacesMustBeNonNegativeNumber=Пожалуйста, введите количество последних гонок, которые должны отображаться
chooseTheWayYouSelectRaces=Выберите способ выбора гонок
selectFromAllRaces=Выбрать из всех гонок
selectANumberOfRaces=Выбрать несколько гонок
numberOfLastNRaces=Количество самых последних гонок для отображения
expandLastRace=Всегда раскрывать последнюю отображенную гонку
factor=Фактор
errorUpdatingIsMedalRace=Ошибка обновления параметров медальной гонки: {0}
maneuverLoss=Потеря при выполнении маневра
averageManeuverLossInMeters=\u2205 Потеря при выполнение маневра
averageManeuverLossInMetersTooltip=Усредненная потеря расстояния при выполнении маневра.
averageTackLossInMeters=\u2205 Потеря при смене галса
averageTackLossInMetersTooltip=Усредненная потеря расстояния при смене галса.
averageJibeLossInMeters=\u2205 Потеря при перекладывании паруса
averageJibeLossInMetersTooltip=Усредненная потеря расстояния при перекладывании паруса.
shape=Форма
pattern=Модель
legend=Легенда
live=прямой эфир
swissTimingArchiveConnector=события SwissTiming, помещенные в архив
errorFetchingChartData=Ошибка получения данных графика: {0}
loadingCompetitorData=Загрузка данных участника...
competitorRegattaDataAfterRaceN={0} после гонки {1}
rankChart=Рейтинг
totalPoints=Итоговое количество очков
raceTotalPointsTooltip=Итоговое количество очков участника в гонке
regattaTotalPointsTooltip=Итоговое количество очков участника в регате
showRankChart=Показать таблицу рейтинга
overallLeaderboardSelection=Итоговая таблица лидеров
errorTryingToObtainOverallLeaderboards=Ошибка получения итоговых таблиц лидеров: {0}
finished=Завершившиеся
passedTo=Переданные в {0}
gapChangeSinceLegStartInSeconds=Изменение отставания
gapChangeSinceLegStartInSecondsTooltip=Изменение отставания от лидера с начала последнего этапа.\nОтрицательное число означает, что отставание уменьшилось;\nположительное число означает, что отставание увеличилось.
sideToWhichMarkAtLegStartWasRounded=Отметка округленная до
sideToWhichMarkAtLegStartWasRoundedTooltip=Сторона в которую округляется отметка на старте этапа.
raceIsLive=Гонка {0} в прямом эфире
racesAreLive=Гонки {0} в прямом эфире
knotsUnit=Узлы
scoringSchemeHighPointFirstGetsOne=Самый лучший результат, победитель получает 1 очко
scoringSchemeHighPointFirstGetsTen=Самый лучший результат, победитель получает 10 очков
knotsUnit=Узлы
generatePolarSheet=Создать полярную электронную таблицу
polars=Полярная диаграмма
polarSheetChart=Полярная электронная таблица
polarSheetMinimumDataSizePerGraph=Минимальное количество данных на графике
polarSheetMinimumDataSizePerGraphTooltip=Все графики с меньшим количеством точек данных визуально не отображаются.\nТаким образом, не отображаются отвлекающие внимание диаграммы для \nскоростей ветра, в которых отсутствует достаточный объем данных.
polarSheetMinimumDataSizePerAngle=Минимальное количество точек данных в расчете на угол
polarSheetMinimumDataSizePerAngleTooltip=На каждом графике будут отображаться только данные об углах с указанным числом\nбазовых точек данных. Не имеющие важного значения\nчасти графика могут быть скрыты с помощью задания этой пороговой величины.
polarSheetMinimumWindConfidence=Минимальное значение достоверных данных о ветре
polarSheetMinimumWindConfidenceTooltip=Только фиксированные значения ветра с достоверностью, превышающей указанное пороговое значение\nприменяются. Эта достоверность от 0 до 1.
polarSheetMinimumConfidenceMeasure=Минимально допустимое измерение достоверности
polarSheetMinimumConfidenceMeasureTooltip=Минимальная степень достоверности для точки, указанной на графике.\nЕсли она ниже установленного порогового значения, то точка не отображается.\nЗначение лежит от 0 до 1 и детерминируется \nс использованием статистических мер.
polarSheetUseOnlyWindGaugeData=Для определения скорости ветра используйте только данные, полученные с помощью анемометра
polarSheetUseOnlyWindGaugeDataTooltip=Благодаря учету данных о скорости ветра, полученных с помощью анемометра\nмы исключаем примерные значения скорости ветра, введенные вручную, которые могли бы исказить данные, отображенные на полярной диаграмме.
polarSheetUseOnlyEstimationData=Используйте, определенные на глаз значения только для направления ветра
polarSheetUseOnlyEstimationDataTooltip=Использование точных расчетных значений о направлении ветра,\nпозволяет нам устранить ошибки полярных диаграмм, которые вращаются из-за неправильных данных, полученных с анемометра\n.
polarSheetRemoveOutliers=Удалите сильно отличающиеся значения (Подход основан на расстоянии)
polarSheetRemoveOutliersTooltip=Сильно отличающиеся значения удаляются с помощью применения подхода, основанного на расстоянии.\nПараметры могут быть отрегулированы ниже.
polarSheetOutlierDetectionRadius=Соседний радиус, определяющий сильно отличающееся значение
polarSheetOutlierDetectionRadiusTooltip=Радиус, используемый в алгоритме определения сильно отличающегося значения\nна основании расстояния.
polarSheetOutlierDetectionMinimumPerc=Минимальный процент соседних точек, определяющий сильно отличающееся значение
polarSheetOutlierDetectionMinimumPercTooltip=Процент соседних точек данных /всего точек данных\nдолжен быть ниже указанного значения для того, чтобы считаться сильно отличающимся значением.
polarSheetNumberOfHistogramColumns=Количество столбцов гистограммы
polarSheetWindSteppingInKnots=Шаг значения ветра в узлах
polarSheetWindSteppingMaxDistance=Максимальное расстояние до уровня ветра
polarSheetWindSteppingMaxDistanceTooltip=Устанавливает максимальный радиус, для которого уровни ветра будут фиксированными.
polarSheetSplitByWindGauges=Разделить источники данных о ветре
polarSheetSplitByWindGaugesTooltip=Разделение источников данных о ветре позволяет найти неисправные анемометры.\nСтатистическая правильность не гарантируется. Такое исправление может \nбыть учтено в полярной диаграмме результатов несколько раз (для разных анемомтеров).
pleaseSeeToolTips=Пожалуйста, наведите курсор на свойства, чтобы ознакомиться с всплывающими подсказками, при их наличии.
competitorColumnTooltip=Имена членов команды этого участника.
sailIdColumnTooltip=Отображает флаг страны и номер на парусе участника.
rankColumnTooltip=Итоговое место этого участника в регате.
carryColumnTooltip=Очки, перенесенные из предыдущих гонок.
totalsColumnTooltip=Итоговое количество очков участника в регате.
windData=Данные о ветре
gpsData=GPS-данные
status=Статус
noDataFound=Данные не обнаружены
displayName=Отобразить имя
histogram=Гистограмма
numberOfDataPoints=Количество точек данных
angleAndTotalNumberOfDataPointsAndCovAndCm=Угол: {0}; Общее количество точек данных: {1}; Коэффициент отклонения: {2}; Степень достоверности: {3}
buoyZone=Зона буя
radiusInMeters=Радиус (м)
filterRegattasByName=Сортировка регат по имени
noRegattasYet=Пока регат нет.
addCourseArea=Добавить зону курса
courseAreas=Зоны курса
courseArea=Зона курса
pleaseEnterNonEmptyCourseArea=Пожалуйста, выведите зону курса.
pleaseSelectACourseArea=Пожалуйста, выберите зону курса.
radiusInMeters=Радиус (м)
lastUpperFlag=Верхний флажок
lastLowerFlag=Нижний флажок
cannotAddRacesToRegattaLeaderboardButOnlyToRegatta=Это таблица лидеров регаты. Вы можете добавлять гонки в эту таблицу лидеров только непосредственно в определении регаты.
correctScore=Исправить очки
correctScoreFor=Исправить очки для участника {0} в гонке {1}
penaltyOrRedress=Штраф/Корректировка
netScore=Чистые очки
timePointMustBeAfterStartOfTracking=Момент времени должен быть после начала отслеживания.
timePointMustBeBeforeEndOfTracking=Момент времени должен быть до окончания отслеживания.
regattaUsedForTheTrackedRace=Регата, используемая для отслеживаемой гонки
tracTracUpdateUrl=Обновление URl-адреса сервера ТракТрак
passingInstructions=Инструкции по передаче
refreshNow=Обновить сейчас
stopUpdating=Остановить обновление
startUpdating=Начать обновление
currentTime=Текущее время:
tractracUsername=Имя пользователя ТракТрак
tractracPassword=Пароль ТракТрак
operatorEquals=Равно
operatorNotEqualTo=Не равно
operatorLessThan=Меньше
operatorLessThanEquals=Меньше или равно
operatorGreaterThan=Больше чем
operatorGreaterThanEquals=Больше или равно
operatorContains=Содержит
operatorNotContains=Не содержит
operatorStartsWith=Начинается с
operatorEndsWith=Заканчивается на
nationality=Гражданство
numberMustBePositive=Цифра должна быть больше нуля.
distanceToLineAtRaceStart=Расстояние до линии «Старт»
distanceToLineFiveSecondsBeforeStart=Расстояние до линии 5с до старта
speedOverGroundAtRaceStart=Скорость относительно земли на линии «Старт»
speedOverGroundFiveSecondsBeforeStart=Скорость относительно земли на линии 5с до старта
speedOverGroundWhenPassingStart=Скорость относительно земли во время старта
distanceToLineAtRaceStartTooltip=Расстояние до стартовой линии во время начала гонки
distanceToLineFiveSecondsBeforeStartTooltip=Расстояние до стартовой линии за пять секунд до начала гонки
speedOverGroundAtRaceStartTooltip=Скорость относительно земли во время начала гонки
speedOverGroundFiveSecondsBeforeStartTooltip=Скорость относительно земли за пять секунд до начала гонки
speedOverGroundWhenPassingStartTooltip=Скорость относительно земли при пересечении участником линии старта
startTack=Сменить галс
startTackTooltip=галс, на котором участник начал
portTack=Левый галс
starboardTack=Правый галс
portSide=Левый борт
starboardSide=Правый борт
pleaseEnterANumber=Пожалуйста, введите номер.
competitorsFilter=Сортировать участников
flagStatus=Флажок состояния
additionalInformation=Информация
windFixListingDescription=Исправления для ветра (первые 3, последние 3, фактические значения)
noWindFixesAvailable=Исправления для ветра недоступны.
distanceToStarboardEndOfStartlineWhenPassingStart=Расстояние от линии до правого борта во время прохождения старта
distanceToStarboardEndOfStartlineWhenPassingStartTooltip=Расстояние до правого борта от стартовой линии или одной отметки начала, когда участник пересек линию старта
actionAddFilter=Добавить фильтр
actionEditFilter=Изменить фильтр
availableFilters=Доступные фильтры
createFilterHint=Создать набор фильтров для сортировки списка участников.
filterThisNameAlreadyExists=Фильтр с таким именем уже существует.
addAtLeastOneFilterCriteria=Добавьте хотя бы один критерий сортировки.
filterCriteria=Критерий сортировки
selectAFilterCriteria=Выбрать критерий сортировки
filterName=Имя фильтра
operator=Оператор
value=Значение
nationalityMustBeISOorIOCcode=Гражданство должно содержать двухбуквенный код МОК или трехбуквенный код МОК.
raceRank=Рейтинг гонки
waypoints=Точки маршрута
disableRaceFilter=Отключить фильтр
enableRaceFilter=Включить фильтр
raceStatusColumn=Статус гонки
loading=Загрузка (при медленном соединении с Интернетом процесс может занять несколько минут)...
racesWithHiddenState=Гонки со статусом «СКРЫТЫ»
mediaDateFormatError=Недействительный формат даты. Использовать: {0}
selectedCompetitors=Выбранные участники
filterNothing=Нечего сортировать
topNCompetitorsByRaceRank=Лидеры гонки {0}
topNCompetitorsByTotalRank=Лидеры в общем зачете {0}
simulator=Модель
optionsBar=Панель опций
simulateButton=Прогнозировать
setup=Установка
strength=Сила (в узлах)
oscillation=Колебание
oscillating=Колеблющийся
amplitude=Амплитуда(в градусах)
frequency=Частота (в 1/ч)
noise=Шум
sailing=Плавание под парусом
optimality=Оптимальность
maximumTurns=Максимальное количество галсов
raceDirection=Направление гонки
upWind=Против ветра
downWind=По ветру
strategies=Стратегии
omniscient=Всезнающий
opportunistic=Оппортунист
mixed=Смешанный
maps=Карты
startEnd=Старт-Финиш
racecourse=Курс
summary=Сводная информация
replay=Повтор
display=Отобразить
simulatorPolarHeader = Полярная диаграмма
show=Показать
hide=скрыть
leftWind=Ветер слева
rightWind=Ветер справа
strategyOption1=стратегияВариант1
strategyOption2=стратегияВариант2
strategyOption3=стратегияВариант3
legLabel=Этап
raceLabel=Гонка
competitorLabel=Участник
freemode=Сохранять направления
whatIfCourse=Что если курс
editRegatta=Изменить регату...
selectSailingEvent=Пожалуйста, выберите событие парусного спорта...
selectCourseArea=Пожалуйста, выберите зону курса..
courseAreaOverview=Обзор зоны
courseDesignOverview=Обзор создания курса
regattaOverview=Обзор регаты
additionalSettings=Дополнительные параметры
showFollowingCourseAreas=Показать следующие зоны курса
showFollowingRegattas=Показать следующие регаты
showOnlyRacesOfSameDay=Показать только гонки, проходившие в один и тот же день
showOnlyCurrentlyRunningRaces=Показать только проходящие гонки
seriesDefinesResultDiscardingRule=Серии определяют правила исключения результатов
addSeries=Все серии
regattaDefinesResultDiscardingRules=Регата определяет правила исключения результатов
startsWithZeroScore=Серия начинается с нуля очков
masterDataImportPanel=Импорт основных данных
importSuccess=Успех\nСозданная {0} группа таблиц (ы) лидеров и {1} таблиц (ы) и {2} события (й) и {3} регат (ы).
importSuccessOverwriteInfo=Пришлось перезаписать следующие регаты, необходимо повторно проложить их гонки:
regattaOverviewConfiguration=Обзор конфигурации регаты
firstRaceIsNonDiscardableCarryForward=Начиная с не исключаемых переносов в другую графу
addReplicationMaster=Подключение к главному серверу дублирования
connect=Подключиться
connectToMaster=Подключиться к Главному
exchangeHost=Имя узла обмена сообщениями
explainExchangeHostName=Имя узла, где сообщения ставятся в очередь ожидания.
explainReplicationHostname=Имя узла, где работает главный сервер дублирования.
explainReplicationExchangeName=Имя очереди ожидания обмена сообщениями. Она должна быть настроена как главный сервер.
explainReplicationExchangePort=Порт очереди ожидания обмена сообщениями. Он используется после первоначальной загрузки для всех данных.
explainReplicationServletPort=Номер порта сервлета, используемого для подключения для регистрации этой копии и получения первоначальной загрузки.
explainReplicasRegistered=Копии зарегистрированы (этот сервер главный ):
explainConnectionsToMaster=Подключения к главному серверу (это сервер копий):
explainNoConnectionsToMaster=Не настроенных подключений к главному серверу.Для настройки одного соединения щелкните «Подключиться к главному серверу» .
explainNoConnectionsFromReplicas=Подключений к серверу копий не обнаружено. Копии можно подключить используя их Консоль администрирования.
stopConnectionToMaster=Остановить копирование
asLink=Как ссылка
noStarttimeAnnouncedYet=Ожидание
raceIsRunning=Проходящая
raceIsFinishing=Завершающаяся
raceIsFinished=Завершенная
raceIsScheduled=Запланированная
raceIsInStartphase=Этап старта
generalRecall=Общая отмена
startPostponed=Отложенная
raceAbandoned=Прекращенная
stopAllReplicas=Разъединить соединение со всеми копиями (Опасно!)
warningServerIsReplica=ВНИМАНИЕ: Этот сервер настроек может быть сервером копий. НЕ ВНОСИТЕ никаких изменений или это приведет к нежелательным последствиям!
dropReplicaConnection=Разъединить соединение
timePanelName=Контроль времени
competitorFilterExplanation=Фильтр отображает всех участников, соответствующих критериям:
dropReplicaConnection=Разъединить соединения
protestTimeFinishesAt=Срок подачи протеста истекает в
protestTimeFinishedAt=Срок подачи протеста истек в
flags=Флаги
lastUpdate=Последние обновления
noMoreRacingToday=Сегодня больше нет гонок
furtherSignalsAshore=Дальнейшие сигналы на берегу
earlyStarters=Совершивших фальшстар
showingDetailsOfRace=Отобразить подробности для гонки {0}
startAt=Старт в
finishAt=Финиш в
protestEndsAt=Срок подачи протеста завершается в
unknown=Неизвестно
earlyStarters=Совершивших фальшстарт
raceLog=Запись о гонке
refreshRaceLog=Обновить запись о гонке
raceLogReloaded=Запись о гонке успешно повторно загружена из базы данных
reloadAllRaceLogs=Повторно загрузить все записи о гонке
export=Эскпорт
sideline=Боковая линия
classAndGolfUp=Флаг поднят – восемь минут до старта – процедура старта – через стартовые ворота
classDisplayed=Флаг поднят – пять минут до старта
papaDisplayed=Флаг режима старта четыре минуты до старта
blackDisplayed=Флаг режима старта – дисквалификация совершивших фальшстарт – четыре минуты до старта
zuluIndiaDisplayed=Флаг режима старта – штрафы для совершивших фальшстарт – четыре минуты до старта
papaRemoved=Флаг режима старта - одна минута до старта
blackRemoved=Флаг режима старта – дисквалификация для совершивших фальшстарт - одна минута до старта
zuluIndiaRemoved=Флаг режима старта – старт со штрафами совершившим фальшстарт – одна минута до старта
classFlagRemoved=Флаг убран – сигнал начала гонки
xray=Индивидуальная отмена – есть совершившие фальшстарт
firstSubstitute=Общая отмена – слишком много совершивших фальшстарт – процедура старта будет повторена
blueFlagDisplayed=Флаг отображается – первый участник пересек линию финиша
blueFlagRemoved=Флаг убран – последний участник пересек линию финиша или предельное время финиша прошло
golfRemoved=Флаг убран –ворота закрыты
answeringPennantOverAlphaDisplayed=Флаг отображается - старт отложен - сегодня больше нет гонок
answeringPennantOverHotelDisplayed=Флаг отображается – старт отложен - дальнейшие сигналы на берегу
answeringPennantDisplayed=Флаг отображается – старт отложен
answeringPennantRemoved=Флаг убран – процедура старта начинается через одну минуту
novemberOverAlphaDisplayed=Флаг поднят - гонка отменена – сегодня гонок больше нет
novemberOverHotelDisplayed=Флаг поднят – гонка отменена - дальнейшие сигналы на берегу
novemberDisplayed=Флаг поднят – гонка отменена
bravoDisplayed=Срок подачи протеста начался
bravoRemoved=Срок подачи протеста закончился
essThreeDisplayed=Три минуты до старта
essTwoDisplayed=Две минуты до старта
essOneDisplayed=Одна минуты до старта
essOneRemoved=Сигнал начала гонки
dataBeforeAfter=Данные до/после гонки
rawFixes=Все значения (включая сильно отличающиеся значения)
importRemoteHost=Удаленный узел:
importFetchRemoteLgs=Получить список группы таблицы лидеров
importUrlInvalid=Недействительный URL-адрес для получения групп таблицы лидеров: {0}
importGetLeaderboardsFailed=Запрос ПОЛУЧИТЬ группы таблиц лидеров выполнить не удалось для узла {0} с ошибкой {1}
importNoDataReturned=Данные сервером не возвращены
importServerError=Запрос ПОЛУЧИТЬ группы таблиц лидеров выполнить не удалось с ошибкой Сервера. Дополнительные сведения, см. в журнале сервера.
importLeaderboardGroups=Группы таблиц лидеров:
importOverrideSwitchLabel=Перезаписать существующие данные, если имена и идентификационные данные совпадают
importSelectedLeaderboardGroups=Импорт выбранных групп таблиц лидеров
importSelectAtLeastOne=Нужно выбрать хотя бы одну группу таблиц лидеров для импорта
deselectAll=Отменить выбор всех
polarDiagramButton=Полярная диаграмма
ratioBetweenTimeSinceLastPositionFixAndAverageSamplingInterval=Запаздывание GPS
ratioBetweenTimeSinceLastPositionFixAndAverageSamplingIntervalTooltip=Соотношение между последними полученными с помощью GPS данными о положении и усредненным интервалом выборки
trackingQuality=Качество отслеживания
legType=Тип этапа
sailID=Номер на парусе
seriesLeaderboard=Серия таблиц лидеров
regattaLeaderboards=Таблица лидеров регаты
clearSelection=Отменить выбор
running=Проходящая в настоящее время
runAsSubstantive=Начать
done=Готово
lastFinished=Последняя завершенная
run=Начать
times=раз
numberOfGPSFixes=Количество точек фиксации GPS
averageCleanedServerTime=\u2205 Чистое время на сервере
averageCleanedOverallTime=\u2205 Чистое итоговое время
dataMiningBenchmarkResults=Результаты сравнительного теста сбора данных
serverTime=Время на сервере
confidenceShouldBeBetween=Достоверность данных должна быть от 0 до 1.
minDataValuesNeedToBeAtLeastZero=Минимальные значения объема данных не могут быть отрицательными.
numberOfColumnsAtLeast2=Количество столбцов гистограммы должно быть больше одного.
outlierRadiusNeedsToBePositiveString=Сильно отличающееся значение радиуса должно быть положительным числом.
outlierMinimumNeighborhoodPctString=Сильно отличающееся значение в процентах соседней точки должно быть положительным и максимально равно 1.
oneOrMoreParametersAreEmpty=Поле параметра не может быть пустым.
errorWhileAddingSeriesToChart=При добавлении \nновой серии в график возникла ошибка
generatingPolarSheet=Создание полярной таблицы...
dataCount=Объем данных
generationFinished=Создание завершено!
generating=Создание
removeAllSheets=Удалить все листы
removeAll=Удалить все
selectSheet=Выбрать лист
cleanedServerTime=Чистое время на сервере
overallTime=Общее время
cleanedOverallTime=Чистое итоговое время
dataMiningResult=Результат сбора данных
groupBy=Группировать по
statisticToCalculate=Рассчитать статистику
queryResultsChartSubtitle=Обработанные {1}/{0} элементы данных через {2} секунд
noQuerySelected=Запросы не выбраны
runAutomatically=Запустить автоматически
windImport_Upload=Загрузить
windImport_Title=Импортировать данные о ветре от экспедиции
windImport_BoatId=Идентификационный номер судна:
windImport_SelectedRacesWarning=Вы действительно хотите импортировать данные о ветре в выбранные {0} гонки?\nЭто в любом случае повлияет только на гонки с применимым временным окном.
windImport_AllRacesWarning=Вы действительно хотите импортировать данные о ветре во все гонки?\nЭто в любом случае повлияет только на гонки с применимым временным окном.
windImport_ResultHeader=Импортированные данные с: {0} по: {1}. {2} повлияли на гонки.
windImport_ResultEntry=Гонка: {0} ({1}) - {2} корректировка с: {3} по: {4}
windImport_ResultError=Ошибка: {0}
showWindSpeedSeriesTooltip=Переключает видимость скорости ветра для всех источников данных
showWindDirectionSeriesTooltip=Переключает видимость направления ветра для всех источников данных
combinedWindSourceTypeTooltip=Объединяет данные из всех других источников данных о ветре в один набор данных
courseBasedWindSourceTypeTooltip=Значение основано на прокладке курса гонки (с учетом предположения, что гонка начнется с этапа против ветра)
trackBasedEstimationWindSourceTypeTooltip=Расчетные данные из маршрута участника
expeditionWindSourceTypeTooltip=Данные, полученные из мобильных систем измерения
webWindSourceTypeTooltip=Значения данных, установленные вручную
raceCommitteeWindSourceTypeTooltip=Значения данных, установленные вручную, полученные от официальных лиц гонки
sheetName=Имя листа
sheetNameTooltip=Вы можете присвоить имя своему полярному листу используя текстовое поле.\nИмя будет создано с использованием класса судна\nесли имя не предоставлено.
timeDownwind=Время по ветру
timeReaching=Время лавирования по ветру
timeUpwind=Время против ветра
raceTimeTooltip=Общее время затраченное в этой гонке
raceTimeDownwindTooltip=Общее время движения по ветру в этой гонке
raceTimeReachingTooltip=Общее время лавирования по ветру в этой гонке
raceTimeUpwindTooltip=Общее время движения против ветра в этой гонке
noStatisticSelectedError=Статистических данных для расчета не выбрано
noCustomGrouperScriptTextError=Скрипт блока группирования пустой
noDimensionToGroupBySelectedError=Размер для группировки по не выбран
noGrouperSelectedError=Тип блока группирования не выбран
queryNotValidBecause=Запрос не возможен, т.к.
dataMining=Сбор данных
errorRunningDataMiningQuery=Ошибка при выполнении запроса
hideToolbar=Скрыть панель инструментов
showSeriesLeaderboards=Показать таблицу лидеров серии
showOverallLeaderboard=Показать общую таблицу лидеров
lineAngleToWindAndAdvantage=длина: {0}м; угол к ветру: {1}градус; {2} борт {3}м имеет преимущество
doYouReallyWantToRemoveEvents=Вы действительно хотите удалить все события?
doYouReallyWantToRemoveEvent=Вы действительно хотите удалить событие {0}?
line=Строка
offset=Смещение
doYouReallyWantToRemoveCompetitors=Вы действительно хотите удалить всех выбранных участников?
doYouReallyWantToRemoveCompetitor=Вы действительно хотите удалить выбранного участника {0}?
filterCompetitors=Сортировать по имени, классу судна или номеру на парусе
editCompetitor=Изменить участника
pleaseEnterASailNumber=Пожалуйста, введите номер на парусе
successfullyAllowedCompetitorReset=Перезагрузка участника (ов) {0} разрешена.
id=Идентификатор
allowReload=Разрешить перезагрузку
compress=Сжать
compressTooltip=Используйте только, если на экземпляре сервера, с которого выполняется экспорт, хотя бы\nзапущена операция подтверждения 0fbf6071dea125bec4a56dee55d61c99def4a62e.
queryRunner=Отправка запросов
rerunQueryAfterRefresh=Повторно выполнить запрос после обновления
refreshIntervalMustntBeEmpty=Интервал обновления не может быть пустым
selectionTables=Выбор таблиц
addConfiguration=Добавить конфигурацию
noConfigurations=Конфигурации отсутствуют.
errorRetrievingConfiguration=Ошибка получения данных о конфигурации с сервера.
allowedCourseAreas=Разрешить зоны курса
minimumRoundsForCourse=Минимальное количество кругов для курса гонки
maximumRoundsForCourse=Максимальное количество кругов для курса гонки
resultsMailRecipient=Результаты получателя почты
deviceConfiguration=Конфигурация устройства
none=Ни одного
courseDesignerMode=Создатель курсов
racingProcedure=Процедура гонки
courseNames=Имена курсов гонок
generate=Создать
dontoverwrite=Не перезаписывать
setRacingProcedureConfiguration=Настроить конфигурацию регаты
racingProcedureConfiguration=Конфигурация регаты
activateIndividualRecall=Активировать индивидуальную отмену
rrs26Start=RRS26 старт
setConfiguration=Активировать конфигурацию
classFlag=Флаг класса
classFlagHelpText=Устанавливает флаг класса, используемый для {0}. Выберите ''Не перезаписывать''для активации флага по умолчанию для процедуры.
individualRecallHelpText=После активации можно обратиться к официальному лицу гонки для индивидуальной отмены.
startmodeFlags=Флаги режима старта
startmodeFlagsHelpText=Устанавливает доступные флаги для режима старта. Выберите «ни один» из предложенных, для включения флагов по умолчанию для этой процедуры.
gateStart=Ворота старта
activatePathfinder=Активировать «Следопыт»
pathfinderHelpText=После активации официальное лицо гонки может настроить судно «Следопыт».
essStart=Старт ESS
basicStart=Основной старт
configured=Настроенный
overwriteRacingProceduresConfiguration=Активировать конфигурацию регаты
overwriteRacingProceduresConfigurationHelpText=Включение этой опции предоставляет базовую конфигурацию регаты для всех опций, не настроенных в специальной конфигурации регаты.
setStartTime=Установить время старта
currentPass=Текущий пропуск
setStartTimeDescription=Выбрать новое время старта для гонки
hasAdditionalGolfDownTime=Активировать дополнительное время отсчета
additionalGolfDownTimeHelpText=Активировать дополнительное время отсчета
invalidColor=Недействительный цвет: {0}
igtimiAccounts=Учетные записи Igtimi
errorFetchingIgtimiAccounts=Ошибка получения всех Igtimi учетных записей: {0}
addIgtimiAccount=Добавить учетную запись Igtimi
errorAuthorizingAccessToIgtimiUser=Ошибка авторизации доступа к Igtimi пользователю {0}: {1}
successfullyAuthorizedAccessToIgtimiUser=Успешная авторизация доступа к Igtimi пользователю {0}
couldNotAuthorizedAccessToIgtimiUser=Невозможно авторизовать пользователя {0}; недействительное имя пользователя или пароль
errorGettingIgtimiAuthorizationUrl=Ошибка получения URL-адреса для авторизации Igtimi: {0}
addIgtimiUser=Добавить пользователя Igtimi
doYouReallyWantToRemoveLeaderboards=Вы действительно хотите удалить таблицы лидеров?
errorTryingToRemoveIgtimiAccount=Ошибка попытки удаления учетной записи Igtimi для пользователя {0}
successfullyRemoveIgtimiAccount=Учетная запись Igtimi для пользователя {0} удалена успешно
eMailMustNotBeEmpty=Адрес электронной почты не должен быть пустым
emailAddress=адрес электронной почты
password=Пароль
doYouReallyWantToRemoveLeaderboard=Вы действительно хотите удалить таблицу лидеров: ''{0}''?
metaLeaderboardCannotBeChanged=Это мета таблица лидеров. Ее нельзя изменить здесь.
failedToSetNewStartTime=Ошибка при установке нового времени старта.
doYouReallyWantToRemoveIgtimiAccount=Вы действительно хотите удалить учетную запись Igtimi, предоставляющую доступ к данным пользователя {0}?
igtimiWindImport=Импорт данных о ветре из Igtimi
seeIgtimiTabForAccountSettings=См. вкладку ''Igtimi'' для параметров учетной записи, определяющих какие данные из Igtimi будут учитываться.
importWindFromIgtimi=Импорт данных о ветре из Igtimi
errorImportingIgtimiWind=Ошибка импорта данных о ветре из Igtimi: {0}
resultFromIgtimiWindImport=Следующее количество фиксированных точек было импортировано для перечисленных гонок: {0}
timeToStart={0} до старта
timeSinceStart={0} со старта
distanceToLine=Растояние до линии старта
beatAngleTooltip=Угол между направлением движения участника и ветром
beatAngle=Угол лавирования
runAutomaticallyTooltip=Запустить запрос автоматически, например, после изменения статистических данных или группировки.
rerunQueryAfterRefreshTooltip=Повторно запускает запрос после обновления таблиц.
queryDefinitionProvider=Поставщик определения запроса
statisticProvider=Поставщик статистических данных
toCalculateThe=для расчета
use=Использовать
groupingProvider=Поставщик группировки
releaseNotes=Новости и история выпусков
hasSplitFleetContiguousScoring=Разделить флоты, имеющие близкие количества очков
overallProgress=Итоговое улучшение
eventOverview=Обзор события
start=Старт
showAddedScores=Показать добавленные очки для каждой записи таблицы лидеров
ratio=коэффициент
importWind=Имопрт данных о ветре
importWindTooltip=Снятие флажка с этой опции значительно снизит объем передаваемых данных.
authorName=Имя автора
authorPriority=Приоритет автора
removeDenotation=Remove Denotation
competitorRegistrationsMissingProceed=At least one of the selected races ({0}) is missing competitor registrations. Proceed anyway?
pleaseSelectAControlPoint=Please select a control point
twoMarkControlPoint=2-mark-controlpoint
registeredCompetitors=Registered Competitors
competitorPool=Competitor Pool
selectAtLeastOne=Select at least one
selectRaces=Select the Races
importFixes=Import Fixes
@@ -20,6 +20,8 @@ public class ScoringSchemeTypeFormatter {
return stringMessages.scoringSchemeHighPointFirstGetsTen();
case LOW_POINT_WINNER_GETS_ZERO:
return stringMessages.scoringSchemeLowPointWinnerGetsZero();
case HIGH_POINT_WINNER_GETS_FIVE:
return stringMessages.scoringSchemeWinnerGetsFive();
case HIGH_POINT_WINNER_GETS_SIX:
return stringMessages.scoringSchemeWinnerGetsSix();
}
@@ -202,7 +202,7 @@ public class RegattaOverviewPanel extends SimplePanel {
}
private CheckBox addLeaderboardEnablerButton() {
final CheckBox checkBox = new CheckBox("Leaderboard");
final CheckBox checkBox = new CheckBox(stringMessages.leaderboard());
checkBox.getElement().getStyle().setFloat(Style.Float.LEFT);
@@ -900,7 +900,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
trackedRaceDTO = getBaseDomainFactory().createTrackedRaceDTO(trackedRace);
}
RaceWithCompetitorsDTO raceDTO = new RaceWithCompetitorsDTO(raceIdentifier, convertToCompetitorDTOs(r.getCompetitors()),
trackedRaceDTO, getService().isRaceBeingTracked(r));
trackedRaceDTO, getService().isRaceBeingTracked(regatta, r));
if (trackedRace != null) {
getBaseDomainFactory().updateRaceDTOWithTrackedRaceData(trackedRace, raceDTO);
}
@@ -2099,9 +2099,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
raceColumn.getFactor(), fleetDTO, raceColumn.isMedalRace(), raceIdentifier, raceDTO);
RaceLog raceLog = raceColumn.getRaceLog(fleet);
RaceLogTrackingState raceLogTrackingState = new RaceLogTrackingStateAnalyzer(raceLog).analyze();
boolean raceLogTrackerExists = getService().getRaceTrackerById(raceLog.getId()) != null;
boolean competitorRegistrationsExist = ! new RegisteredCompetitorsAnalyzer(raceLog).analyze().isEmpty();
RaceLogTrackingState raceLogTrackingState = raceLog == null ? RaceLogTrackingState.NOT_A_RACELOG_TRACKED_RACE :
new RaceLogTrackingStateAnalyzer(raceLog).analyze();
boolean raceLogTrackerExists = raceLog == null ? false : getService().getRaceTrackerById(raceLog.getId()) != null;
boolean competitorRegistrationsExist = raceLog == null ? false : !new RegisteredCompetitorsAnalyzer(raceLog).analyze().isEmpty();
RaceLogTrackingInfoDTO raceLogTrackingInfo = new RaceLogTrackingInfoDTO(raceLogTrackerExists,
competitorRegistrationsExist, raceLogTrackingState);
raceColumnDTO.setRaceLogTrackingInfo(fleetDTO, raceLogTrackingInfo);
@@ -140,7 +140,7 @@ public class PathLegendCanvasOverlay extends FullCanvasOverlay {
}
@Override
protected void setCanvasSettings() {
public void setCanvasSettings() {
super.setCanvasSettings();
canvas.getElement().getStyle().setZIndex(100000); // make legend float on-top of all overlays
}
@@ -15,6 +15,7 @@ import com.sap.sailing.gwt.ui.client.LogoAndTitlePanel;
import com.sap.sailing.gwt.ui.client.RemoteServiceMappingConstants;
import com.sap.sailing.gwt.ui.client.SimulatorService;
import com.sap.sailing.gwt.ui.client.SimulatorServiceAsync;
import com.sap.sailing.gwt.ui.simulator.streamlets.SimulatorJSBundle;
import com.sap.sailing.simulator.util.SailingSimulatorConstants;
public class SimulatorEntryPoint extends AbstractEntryPoint {
@@ -25,6 +26,7 @@ public class SimulatorEntryPoint extends AbstractEntryPoint {
private int xRes = 40;
private int yRes = 20;
private int border = 0;
private int particles = 0;
private boolean autoUpdate = false;
private char mode = SailingSimulatorConstants.ModeEvent; // default mode: 'e'vent
private char event = SailingSimulatorConstants.EventKielerWoche; // default event: 'k'ieler woche
@@ -75,6 +77,12 @@ public class SimulatorEntryPoint extends AbstractEntryPoint {
} else {
this.border = Integer.parseInt(border);
}
String particlesStr = Window.Location.getParameter("particles");
if (particlesStr == null || particlesStr.isEmpty()) {
logger.config("Using default particles " + this.particles);
} else {
this.particles = Integer.parseInt(particlesStr);
}
String autoUpdateStr = Window.Location.getParameter("autoUpdate");
if (autoUpdateStr == null || autoUpdateStr.isEmpty()) {
logger.config("Using default auto update " + autoUpdate);
@@ -132,7 +140,7 @@ public class SimulatorEntryPoint extends AbstractEntryPoint {
showStreamlets2 = true;
injectWindDataJS = true;
}
if ((showStreamlets2)&&(this.border==0)) {
if ((showStreamlets2)&&(border==null)) {
this.border = 10;
}
if (windDisplayStr.contains("b")) {
@@ -163,7 +171,7 @@ public class SimulatorEntryPoint extends AbstractEntryPoint {
}
private void createSimulatorPanel() {
SimulatorMainPanel simulatorPanel = new SimulatorMainPanel(simulatorService, stringMessages, this, xRes, yRes, border,
SimulatorMainPanel simulatorPanel = new SimulatorMainPanel(simulatorService, stringMessages, this, xRes, yRes, border, particles,
autoUpdate, mode, event, showGrid, showLines, seedLines, showArrows, showStreamlets, showStreamlets2, injectWindDataJS);
DockLayoutPanel p = new DockLayoutPanel(Unit.PX);
@@ -71,7 +71,9 @@ public class SimulatorMainPanel extends SimplePanel {
simulatorMap.getMap().triggerResize();
}
}
public int particles;
private DockLayoutPanel mainPanel;
private FlowPanel leftPanel;
private ResizableFlowPanel rightPanel;
@@ -225,10 +227,12 @@ public class SimulatorMainPanel extends SimplePanel {
return NumberFormat.getFormat("0.0").format(value);
}
public SimulatorMainPanel(SimulatorServiceAsync svc, StringMessages stringMessages, ErrorReporter errorReporter, int xRes, int yRes, int border, boolean autoUpdate,
public SimulatorMainPanel(SimulatorServiceAsync svc, StringMessages stringMessages, ErrorReporter errorReporter, int xRes, int yRes, int border, int particles, boolean autoUpdate,
char mode, char event, boolean showGrid, boolean showLines, char seedLines, boolean showArrows, boolean showStreamlets, boolean showStreamlets2, boolean injectWindDataJS) {
super();
this.particles = particles;
this.simulatorSvc = svc;
this.stringMessages = stringMessages;
this.errorReporter = errorReporter;
@@ -7,6 +7,7 @@ import java.util.List;
import java.util.logging.Logger;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.maps.client.LoadApi;
@@ -19,6 +20,8 @@ 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.bounds.BoundsChangeMapEvent;
import com.google.gwt.maps.client.events.bounds.BoundsChangeMapHandler;
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;
@@ -208,9 +211,13 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
legendCanvasOverlay.setCurrent(result.getWindField().curSpeed,result.getWindField().curBearing);
if (timePanel != null) {
timePanel.setMinMax(new Date(startTime), new Date(startTime + maxDurationTime), true);
Date endDate = new Date(startTime + maxDurationTime);
timePanel.setMinMax(new Date(startTime), endDate, true);
timePanel.resetTimeSlider();
timePanel.timeChanged(windParams.getStartTime(), null);
if (windParams.isShowStreamlets2()) {
windStreamletsCanvasOverlay.setEndDate(endDate);
}
}
/**
@@ -369,7 +376,7 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
if (windParams.isShowStreamlets2()) {
mapTypeStyles = new MapTypeStyle[7];
mapTypeStyles = new MapTypeStyle[11];
// hide all transit lines including ferry lines
mapTypeStyles[0] = GoogleMapStyleHelper.createHiddenStyle(MapTypeStyleFeatureType.TRANSIT);
@@ -379,18 +386,45 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
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);
mapTypeStyles[4] = GoogleMapStyleHelper.createColorStyle(MapTypeStyleFeatureType.LANDSCAPE, new RGBColor(255, 255, 255), -100, -70);
mapTypeStyles[5] = GoogleMapStyleHelper.createColorStyle(MapTypeStyleFeatureType.POI, new RGBColor(255, 255, 255), -100, -70);
mapTypeStyles[6] = GoogleMapStyleHelper.createElementStyleOnlyLightness(MapTypeStyleFeatureType.ROAD, MapTypeStyleElementType.ALL, -40);
MapTypeStyle mapStyle = MapTypeStyle.newInstance();
mapStyle.setFeatureType(MapTypeStyleFeatureType.ADMINISTRATIVE);
mapStyle.setElementType(MapTypeStyleElementType.LABELS);
mapStyle.setElementType(MapTypeStyleElementType.LABELS__TEXT__FILL);
MapTypeStyler[] typeStylers = new MapTypeStyler[1];
typeStylers[0] = MapTypeStyler.newInvertLightnessStyler(true);
mapStyle.setStylers(typeStylers);
mapTypeStyles[6] = mapStyle;
mapTypeStyles[7] = mapStyle;
mapStyle = MapTypeStyle.newInstance();
mapStyle.setFeatureType(MapTypeStyleFeatureType.ADMINISTRATIVE);
mapStyle.setElementType(MapTypeStyleElementType.LABELS__TEXT__STROKE);
typeStylers = new MapTypeStyler[1];
typeStylers[0] = MapTypeStyler.newInvertLightnessStyler(true);
mapStyle.setStylers(typeStylers);
mapTypeStyles[8] = mapStyle;
mapStyle = MapTypeStyle.newInstance();
mapStyle.setFeatureType(MapTypeStyleFeatureType.ADMINISTRATIVE);
mapStyle.setElementType(MapTypeStyleElementType.GEOMETRY__FILL);
typeStylers = new MapTypeStyler[3];
typeStylers[0] = MapTypeStyler.newHueStyler("#ffffff");
typeStylers[1] = MapTypeStyler.newLightnessStyler(-70);
typeStylers[2] = MapTypeStyler.newSaturationStyler(-100);
mapStyle.setStylers(typeStylers);
mapTypeStyles[9] = mapStyle;
} else {
mapStyle = MapTypeStyle.newInstance();
mapStyle.setFeatureType(MapTypeStyleFeatureType.ADMINISTRATIVE);
mapStyle.setElementType(MapTypeStyleElementType.GEOMETRY__STROKE);
typeStylers = new MapTypeStyler[1];
typeStylers[0] = MapTypeStyler.newLightnessStyler(-70);
mapStyle.setStylers(typeStylers);
mapTypeStyles[10] = mapStyle;
} else {
mapTypeStyles = new MapTypeStyle[4];
@@ -433,6 +467,22 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
add(map, 0, 0);
map.setSize("100%", "100%");
if (windParams.isShowStreamlets2()) {
map.addBoundsChangeHandler(new BoundsChangeMapHandler() {
@Override
public void onEvent(BoundsChangeMapEvent event) {
// improve browser performance by deferred scheduling of redraws
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
public void execute() {
if (windStreamletsCanvasOverlay.getSwarm() != null) {
windStreamletsCanvasOverlay.getSwarm().onBoundsChanged();
}
}
});
}
});
}
/*map.addZoomChangeHandler(new ZoomChangeMapHandler() {
@Override
@@ -263,7 +263,7 @@ public class WindLineCanvasOverlay extends FullCanvasOverlay implements TimeList
}
@Override
protected void setCanvasSettings() {
public void setCanvasSettings() {
if (corners != null && corners.length == 4) {
final Point corner0 = getPointInDivPixel(corners[0]);
final Point corner1 = getPointInDivPixel(corners[1]);
@@ -14,6 +14,7 @@ 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.streamlets.Swarm;
import com.sap.sse.gwt.client.player.Timer;
/**
@@ -32,6 +33,10 @@ public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements Ti
private boolean visible = false;
private Timer timer;
private Date endDate;
private int nParticles;
private Swarm swarm;
private static Logger logger = Logger.getLogger(WindStreamletsCanvasOverlay.class.getName());
@@ -42,17 +47,23 @@ public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements Ti
this.timer = timer;
this.windParams = windParams;
this.nParticles = this.simulatorMap.getMainPanel().particles;
windFieldDTO = null;
getCanvas().getElement().setId("swarm-display");
/*if (!this.isSwarmDataExt()) {
// random test windfield
JavaScriptObject swarmData = this.getJSONRandomWindData();
this.setSwarmData(swarmData);
}*/
}
public WindFieldDTO getWindFieldDTO() {
return this.windFieldDTO;
}
public WindFieldGenParamsDTO getWindParams() {
return this.windParams;
}
public JavaScriptObject getJSONRandomWindData() {
JSONObject jsonWindData = new JSONObject();
@@ -137,24 +148,22 @@ public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements Ti
$wnd.swarmCanvasProjection = instance;
}-*/;
public native void startStreamlets() /*-{
if ($wnd.swarmAnimator) {
$wnd.swarmUpdData = true;
$wnd.updateStreamlets($wnd.swarmUpdData);
} else {
$wnd.initStreamlets($wnd.swarmMap);
public void startStreamlets() {
if (swarm == null) {
this.swarm = new Swarm(this,map);
}
}-*/;
this.swarm.start(40, windFieldDTO);
}
public void setStreamletsStep(int step) {
this.swarm.getField().setStep(step);
}
public native void setStreamletsStep(int step) /*-{
$wnd.swarmField.setStep(step);
}-*/;
public native void stopStreamlets() /*-{
if ($wnd.stopStreamlets) {
$wnd.stopStreamlets();
};
}-*/;
public void stopStreamlets() {
if (swarm != null) {
this.swarm.stop();
}
}
public void extendWindDataJSON() {
@@ -198,17 +207,12 @@ public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements Ti
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
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
@@ -254,13 +258,23 @@ public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements Ti
@Override
protected void draw() {
super.draw();
if (mapProjection != null && windFieldDTO != null) {
// drawing is done by external JavaScript for Streamlets
if (mapProjection != null) {
if ((nParticles > 0)&&(swarm == null)) {
this.swarm = new Swarm(this,map);
this.swarm.start(40, null);
}
if (windFieldDTO != null) {
// drawing is done by external JavaScript for Streamlets
}
}
}
public Swarm getSwarm() {
return this.swarm;
}
private void clear() {
this.stopStreamlets();
this.stopStreamlets();
}
@Override
@@ -271,7 +285,7 @@ public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements Ti
@Override
public boolean shallStop() {
if (timer.getTime().getTime() >= this.windParams.getEndTime().getTime()) {
if (timer.getTime().getTime() >= this.endDate.getTime()) {
return true;
} else {
return false;
@@ -59,7 +59,7 @@ public abstract class FullCanvasOverlay extends CanvasOverlayV3 implements Requi
/**
* Set the canvas to be the size of the map and set it to the top left corner of the map
*/
protected void setCanvasSettings() {
public void setCanvasSettings() {
int canvasWidth = getMap().getDiv().getClientWidth();
int canvasHeight = getMap().getDiv().getClientHeight();
@@ -0,0 +1,12 @@
package com.sap.sailing.gwt.ui.simulator.streamlets;
public class Index {
public long x;
public long y;
public Index(long x, long y) {
this.x = x;
this.y = y;
}
}
@@ -0,0 +1,89 @@
package com.sap.sailing.gwt.ui.simulator.streamlets;
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.Position;
import com.sap.sailing.domain.common.impl.DegreePosition;
import com.sap.sailing.gwt.ui.simulator.racemap.FullCanvasOverlay;
public class Mercator {
private FullCanvasOverlay canvas;
private MapWidget map;
private double alpha;
private double beta;
private double gamma;
private double delta;
public Mercator(FullCanvasOverlay canvas, MapWidget map) {
this.canvas = canvas;
this.alpha = 0.0;
this.beta = 0.0;
this.gamma = 0.0;
this.delta = 0.0;
this.map = map;
this.calibrate();
}
public void calibrate() {
Vector pointSW;
Vector pointNE;
int canvasHeight = canvas.getCanvas().getOffsetHeight();
Position mapSW = new DegreePosition(this.map.getBounds().getSouthWest().getLatitude(), this.map.getBounds().getSouthWest().getLongitude());
Position mapNE = new DegreePosition(this.map.getBounds().getNorthEast().getLatitude(), this.map.getBounds().getNorthEast().getLongitude());
pointSW = this.sphere2plane(mapSW);
pointNE = this.sphere2plane(mapNE);
if (pointNE.x < pointSW.x) {
pointSW.x -= 2*Math.PI;
}
this.alpha = canvasHeight / (pointNE.y - pointSW.y);
this.beta = pointSW.x;
this.gamma = - this.alpha;
this.delta = pointNE.y;
}
public Vector sphere2plane(Position p) {
Vector result = new Vector();
result.x = p.getLngDeg()*Math.PI/180.0;
double latsin = Math.sin(p.getLatDeg()*Math.PI/180.0);
result.y = 0.5*Math.log((1.0+latsin)/(1.0-latsin));
return result;
}
public LatLng plane2sphere(Point px) {
double lng = px.getX()*180.0/Math.PI;
double lat = Math.atan(Math.sinh(px.getY()))*180.0/Math.PI;
return LatLng.newInstance(lat, lng);
}
public Vector latlng2pixel(Position p) {
Vector proj = this.sphere2plane(p);
proj.x = this.alpha * (proj.x - this.beta);
proj.y = this.gamma * (proj.y - this.delta);
return proj;
}
public LatLng pixel2latlng(Point px) {
double p = px.getX() / this.alpha + this.beta;
double q = px.getY() / this.gamma + this.delta;
return this.plane2sphere(Point.newInstance(p, q));
}
public void clearCanvas() {
double w = this.canvas.getCanvas().getOffsetWidth();
double h = this.canvas.getCanvas().getOffsetHeight();
Context2d g = this.canvas.getCanvas().getContext2d();
g.clearRect(0, 0, w, h);
};
}
@@ -0,0 +1,20 @@
package com.sap.sailing.gwt.ui.simulator.streamlets;
public class Neighbors {
public int xBot;
public int xTop;
public double xMod;
public int yBot;
public int yTop;
public double yMod;
public Neighbors(int xTop, int yTop, int xBot, int yBot, double xMod, double yMod) {
this.xTop = xTop;
this.yTop = yTop;
this.xBot = xBot;
this.yBot = yBot;
this.xMod = xMod;
this.yMod = yMod;
}
}
@@ -0,0 +1,14 @@
package com.sap.sailing.gwt.ui.simulator.streamlets;
import com.sap.sailing.domain.common.Position;
public class Particle {
public Position pos;
public Vector pxOld;
public int alpha;
public int age;
public Vector v;
}
@@ -0,0 +1,187 @@
package com.sap.sailing.gwt.ui.simulator.streamlets;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.maps.client.base.LatLng;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.impl.DegreePosition;
public class RectField implements VectorField {
private Vector[][] field;
public double x0;
public double x1;
public double y0;
public double y1;
//public double visX0;
public double visX1;
public double visY0;
public double visY1;
public Position visSW;
public Position visNE;
private int w;
private int h;
private double maxLength;
public double particleFactor;
public RectField(Vector[][] field, double x0, double y0, double x1, double y1) {
this.x0 = x0;
this.x1 = x1;
this.y0 = y0;
this.y1 = y1;
this.visSW = new DegreePosition(0.0, 0.0);
this.visNE = new DegreePosition(0.0, 0.0);
this.field = field;
this.w = field.length;
this.h = field[0].length;
this.maxLength = 0;
this.particleFactor = 4.5;
double mx = 0;
double my = 0;
for (int i = 0; i < this.w; i++) {
for (int 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;
}
public static RectField read(String jsonData, boolean correctForSphere) {
JSONObject data = JSONParser.parseLenient(jsonData).isObject();
int w = (int)data.get("gridWidth").isNumber().doubleValue();
int h = (int)data.get("gridHeight").isNumber().doubleValue();
Vector[][] field = new Vector[w][h];
int i = 0;
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
Vector v = new Vector();
v.x = data.get("field").isArray().get(i++).isNumber().doubleValue();
v.y = data.get("field").isArray().get(i++).isNumber().doubleValue();
if (correctForSphere) {
double uy = y / (h - 1);
double lat = data.get("y0").isNumber().doubleValue() * (1 - uy) + data.get("y1").isNumber().doubleValue() * uy;
double m = Math.PI * lat / 180;
double length = v.length();
v.x = v.x / Math.cos(m);
v.setLength(length);
}
field[x][y] = v;
}
}
RectField result = new RectField(field, data.get("x0").isNumber().doubleValue(), data.get("y0").isNumber().doubleValue(), data.get("x1").isNumber().doubleValue(), data.get("y1").isNumber().doubleValue());
return result;
}
public void setStep(int step) {
}
public void nextStep() {
}
public void prevStep() {
}
public Position getRandomPosition() {
double rndY = Math.random();
double rndX = Math.random();
double latDeg = rndY * this.visSW.getLatDeg() + (1 - rndY) * this.visNE.getLatDeg();
double lngDeg = rndX * this.visSW.getLngDeg() + (1 - rndX) * this.visNE.getLngDeg();
return new DegreePosition(latDeg, lngDeg);
}
public boolean inBounds(Position p) {
return p.getLngDeg() >= this.x0 && p.getLngDeg() < this.x1 && p.getLatDeg() >= this.y0 && p.getLatDeg() < this.y1;
}
public Vector interpolate(Position p) {
int na = (int)Math.floor(p.getLngDeg());
int nb = (int)Math.floor(p.getLatDeg());
int ma = (int)Math.ceil(p.getLngDeg());
int mb = (int)Math.ceil(p.getLatDeg());
double fa = p.getLngDeg() - na;
double fb = p.getLatDeg() - nb;
Vector result = new Vector();
result.x = 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;
result.y = 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 result;
}
public Vector getVector(Position p) {
double lngDeg = (this.w - 1 - 1e-6) * (p.getLngDeg() - this.x0) / (this.x1 - this.x0);
double latDeg = (this.h - 1 - 1e-6) * (p.getLatDeg() - this.y0) / (this.y1 - this.y0);
if ((lngDeg < 0)||(lngDeg > (this.w-1))||(latDeg < 0)||(latDeg > (this.h-1))) {
return null;
} else {
Position q = new DegreePosition(latDeg, lngDeg);
return this.interpolate(q);
}
}
public LatLng getCenter() {
return LatLng.newInstance((y0+y1)/2.0, (x0+x1)/2.0);
}
public double getMaxLength() {
return maxLength;
}
public double motionScale(int zoomLevel) {
return 0.9 * Math.pow(1.7, Math.min(1.0, 6.0 - zoomLevel));
}
public double particleWeight(Position p, Vector v) {
return 1.0 - v.length() / this.maxLength;
}
public String[] getColors() {
String[] colors = new String[256];
double alpha = 1.0;
int greyValue = 255;
for (int 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;
}
public double lineWidth(int alpha) {
return 1.0;
}
public Position getFieldNE() {
return new DegreePosition(Math.max(this.y0, this.y1), Math.max(this.x0, this.x1));
}
public Position getFieldSW() {
return new DegreePosition(Math.min(this.y0, this.y1), Math.min(this.x0, this.x1));
}
public void setVisNE(Position visNE) {
this.visNE = visNE;
}
public void setVisSW(Position visSW) {
this.visSW = visSW;
}
public double getParticleFactor() {
return this.particleFactor;
}
}
@@ -0,0 +1,295 @@
package com.sap.sailing.gwt.ui.simulator.streamlets;
import java.util.List;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.impl.DegreePosition;
import com.sap.sailing.gwt.ui.shared.SimulatorWindDTO;
import com.sap.sailing.gwt.ui.shared.WindFieldDTO;
import com.sap.sailing.gwt.ui.shared.WindFieldGenParamsDTO;
public class SimulatorField implements VectorField {
private boolean swarmDebug = false;
private Position rcStart;
private Position rcEnd;
private int resY;
private int resX;
private int borderY;
private int borderX;
private double bdXi;
private double bdPhi;
private Position bdA;
private Position bdB;
private Position bdC;
private double xScale;
private double x0;
private double x1;
private double y0;
private double y1;
public Position visSW;
public Position visNE;
private double maxLength;
private double particleFactor;
private double lngScale;
private Position nvY;
private Position nvX;
private Position gvX;
private double[][][] data;
private int step;
public SimulatorField(WindFieldDTO windData, WindFieldGenParamsDTO windParams) {
this.step = 0;
String parseString = windData.windDataJSON.substring(18, windData.windDataJSON.length()-1) + "}";
JSONObject baseData = JSONParser.parseLenient(parseString).isObject();
this.rcStart = new DegreePosition(baseData.get("rcStart").isObject().get("lat").isNumber().doubleValue(), baseData.get("rcStart").isObject().get("lng").isNumber().doubleValue());
this.rcEnd = new DegreePosition(baseData.get("rcEnd").isObject().get("lat").isNumber().doubleValue(), baseData.get("rcEnd").isObject().get("lng").isNumber().doubleValue());
this.resY = (int)baseData.get("resY").isNumber().doubleValue();
this.resX = (int)baseData.get("resX").isNumber().doubleValue();
this.borderY = (int)baseData.get("borderY").isNumber().doubleValue();
this.borderX = (int)baseData.get("borderX").isNumber().doubleValue();
this.bdXi = (this.borderY + 0.5) / (this.resY - 1);
this.bdPhi = 1.0 + 2*this.bdXi;
this.bdA = new DegreePosition(this.rcEnd.getLatDeg()+(this.rcEnd.getLatDeg()-this.rcStart.getLatDeg())*this.bdXi, this.rcEnd.getLngDeg()+(this.rcEnd.getLngDeg()-this.rcStart.getLngDeg())*this.bdXi);
this.bdB = new DegreePosition((this.rcStart.getLatDeg()-this.rcEnd.getLatDeg())*this.bdPhi, (this.rcStart.getLngDeg()-this.rcEnd.getLngDeg())*this.bdPhi);
this.xScale = baseData.get("xScale").isNumber().doubleValue();
this.x0 = baseData.get("boundsSW").isObject().get("lng").isNumber().doubleValue();
this.x1 = baseData.get("boundsNE").isObject().get("lng").isNumber().doubleValue();
this.y0 = baseData.get("boundsSW").isObject().get("lat").isNumber().doubleValue();
this.y1 = baseData.get("boundsNE").isObject().get("lat").isNumber().doubleValue();
this.visSW = new DegreePosition(0.0, 0.0);
this.visNE = new DegreePosition(0.0, 0.0);
List<SimulatorWindDTO> gridData = windData.getMatrix();
int p = 0;
int imax = windParams.getyRes() + 2*windParams.getBorderY();
int jmax = windParams.getxRes() + 2*windParams.getBorderX();
int steps = gridData.size() / (imax * jmax);
this.data = new double[steps][imax][2*jmax];
double maxWindSpeed = 0;
for(int s=0; s<steps; s++) {
for(int i=0; i<imax; i++) {
for(int j=0; j<jmax; j++) {
SimulatorWindDTO wind = gridData.get(p);
p++;
if (wind.trueWindSpeedInKnots > maxWindSpeed) {
maxWindSpeed = wind.trueWindSpeedInKnots;
}
this.data[s][i][2*j+1] = wind.trueWindSpeedInKnots*Math.cos(wind.trueWindBearingDeg*Math.PI/180.0);
this.data[s][i][2*j] = wind.trueWindSpeedInKnots*Math.sin(wind.trueWindBearingDeg*Math.PI/180.0);
}
}
}
this.maxLength = maxWindSpeed;
this.particleFactor = 2.0;
double latAvg = (this.rcEnd.getLatDeg() + this.rcStart.getLatDeg()) / 2.;
this.lngScale = Math.cos(latAvg * Math.PI / 180.0);
double difLat = this.rcEnd.getLatDeg() - this.rcStart.getLatDeg();
double difLng = (this.rcEnd.getLngDeg() - this.rcStart.getLngDeg()) * this.lngScale;
double difLen = Math.sqrt(difLat*difLat + difLng*difLng);
this.nvY = new DegreePosition(difLat/difLen/difLen*(this.resY-1), difLng/difLen/difLen*(this.resY-1));
double nrmLat = -difLng/difLen;
double nrmLng = difLat/difLen;
this.nvX = new DegreePosition( nrmLat/this.xScale/difLen*(this.resX-1), nrmLng/this.xScale/difLen*(this.resX-1) );
this.gvX = new DegreePosition( nrmLat*this.xScale*difLen, nrmLng/this.lngScale*this.xScale*difLen );
this.bdC = new DegreePosition( this.gvX.getLatDeg()*(this.resX+2*this.borderX-1)/(this.resX-1), this.gvX.getLngDeg()*(this.resX+2*this.borderX-1)/(this.resX-1) );
}
public static native void console(String msg) /*-{
console.log(msg);
}-*/;
public Position getRandomPosition() {
double rndY = Math.random();
double rndX = Math.random() - 0.5;
double latDeg = this.bdA.getLatDeg() + rndY * this.bdB.getLatDeg() + rndX * this.bdC.getLatDeg();
double lngDeg = this.bdA.getLngDeg() + rndY * this.bdB.getLngDeg() + rndX * this.bdC.getLngDeg();
Position result = new DegreePosition(latDeg, lngDeg);
if (swarmDebug&&(!this.inBounds(result))) {
console("random-position: out of bounds");
}
return result;
}
public boolean inBounds(Position p) {
Index idx = this.getIndex(p);
boolean inBool = (idx.x >= 0) && (idx.x < (this.resX+2*this.borderX)) && (idx.y >= 0) && (idx.y < (this.resY+2*this.borderY));
return inBool;
}
public Vector interpolate(Position p) {
Neighbors idx = this.getNeighbors(p);
if (swarmDebug&&((idx.xTop >= (this.resX+2*this.borderX))||(idx.yTop >= (this.resY+2*this.borderY)))) {
console("interpolate: out of range: " + idx.xTop + " " + idx.yTop);
}
//System.out.println("neighbors:"+idx.xBot+","+idx.xTop+","+idx.yBot+","+idx.yTop);
double avgX = this.data[this.step][idx.yBot][2*idx.xBot] * (1 - idx.yMod) * (1 - idx.xMod) + this.data[this.step][idx.yTop][2*idx.xBot] * idx.yMod * (1 - idx.xMod)
+ this.data[this.step][idx.yBot][2*idx.xTop] * (1 - idx.yMod) * idx.xMod + this.data[this.step][idx.yTop][2*idx.xTop] * idx.yMod * idx.xMod;
double avgY = this.data[this.step][idx.yBot][2*idx.xBot+1] * (1 - idx.yMod) * (1 - idx.xMod) + this.data[this.step][idx.yTop][2*idx.xBot+1] * idx.yMod * (1 - idx.xMod)
+ this.data[this.step][idx.yBot][2*idx.xTop+1] * (1 - idx.yMod) * idx.xMod + this.data[this.step][idx.yTop][2*idx.xTop+1] * idx.yMod * idx.xMod;
return new Vector(avgX / this.lngScale, avgY);
}
public void setStep(int step) {
if (step < 0) {
this.step = 0;
} else if (step >= this.data.length) {
this.step = this.data.length-1;
} else {
this.step = step;
}
}
public void nextStep() {
if (this.step < (this.data.length-1)) {
this.step++;
}
}
public void prevStep() {
if (this.step > 0) {
this.step--;
}
}
public Vector getVector(Position p) {
return this.interpolate(p);
}
public Index getIndex(Position p) {
// calculate grid indexes
Position posR = new DegreePosition( p.getLatDeg() - this.rcStart.getLatDeg(), (p.getLngDeg() - this.rcStart.getLngDeg()) * this.lngScale );
// closest grid point
long yIdx = Math.round( posR.getLatDeg() * this.nvY.getLatDeg() + posR.getLngDeg() * this.nvY.getLngDeg() ) + this.borderY;
long xIdx = Math.round( posR.getLatDeg() * this.nvX.getLatDeg() + posR.getLngDeg() * this.nvX.getLngDeg() + (this.resX - 1) / 2. ) + this.borderX;
return new Index( xIdx, yIdx );
}
public Neighbors getNeighbors(Position p) {
// calculate grid indexes
Position posR = new DegreePosition( p.getLatDeg() - this.rcStart.getLatDeg(), (p.getLngDeg() - this.rcStart.getLngDeg()) * this.lngScale );
// surrounding grid points
double yFlt = posR.getLatDeg() * this.nvY.getLatDeg() + posR.getLngDeg() * this.nvY.getLngDeg() + this.borderY;
double xFlt = posR.getLatDeg() * this.nvX.getLatDeg() + posR.getLngDeg() * this.nvX.getLngDeg() + (this.resX - 1) / 2. + this.borderX;
double yBot = Math.floor( yFlt );
double xBot = Math.floor( xFlt );
double yTop = Math.ceil( yFlt );
double xTop = Math.ceil( xFlt );
double yMod = yFlt - yBot;
double 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;
}
//System.out.println("neighbors:"+xFlt+","+xBot+","+xTop+","+yFlt+","+yBot+","+yTop);
return new Neighbors((int)xTop, (int)yTop, (int)xBot, (int)yBot, xMod, yMod );
}
public double getMaxLength() {
return maxLength;
}
public double motionScale(int zoomLevel) {
return 0.08 * Math.pow(1.6, Math.min(1.0, 6.0 - zoomLevel));
}
public double particleWeight(Position p, Vector v) {
return v.length() / this.maxLength + 0.1;
}
public String[] getColors() {
String[] colors = new String[256];
double alpha = 0.7;
int greyValue = 255;
for (int 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;
}
public double lineWidth(int alpha) {
return 1.0;
}
public Position getFieldNE() {
return new DegreePosition(Math.max(this.y0, this.y1), Math.max(this.x0, this.x1));
}
public Position getFieldSW() {
return new DegreePosition(Math.min(this.y0, this.y1), Math.min(this.x0, this.x1));
}
public void setVisNE(Position visNE) {
this.visNE = visNE;
}
public void setVisSW(Position visSW) {
this.visSW = visSW;
}
public double getParticleFactor() {
return this.particleFactor;
}
}
@@ -1,4 +1,4 @@
package com.sap.sailing.gwt.ui.simulator;
package com.sap.sailing.gwt.ui.simulator.streamlets;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.TextResource;
@@ -8,7 +8,7 @@ public interface SimulatorJSBundle extends ClientBundle {
//@Source("wind-streamlets.js")
//TextResource windStreamletsJS();
@Source("com/sap/sailing/gwt/ui/simulator/wind-data.js")
@Source("com/sap/sailing/gwt/ui/simulator/streamlets/wind-data.js")
TextResource windStreamletsDataJS();
}
@@ -0,0 +1,292 @@
package com.sap.sailing.gwt.ui.simulator.streamlets;
import java.util.Date;
import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.core.client.GWT;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.user.client.Timer;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.impl.DegreePosition;
import com.sap.sailing.gwt.ui.shared.WindFieldDTO;
import com.sap.sailing.gwt.ui.simulator.WindStreamletsCanvasOverlay;
import com.sap.sailing.gwt.ui.simulator.racemap.FullCanvasOverlay;
public class Swarm {
protected FullCanvasOverlay fullcanvas;
protected Canvas canvas;
protected MapWidget map;
private Timer loopTimer;
private String[] color;
private Mercator projection;
private VectorField field;
private int nParticles;
private Particle[] particles;
private boolean swarmOffScreen = false;
private int swarmPause = 0;
private boolean swarmContinue = true;
private Position boundsNE;
private Position boundsSW;
public Swarm(FullCanvasOverlay fullcanvas, MapWidget map) {
this.fullcanvas = fullcanvas;
this.canvas = fullcanvas.getCanvas();
this.map = map;
}
public void start(int animationDuration, WindFieldDTO windField) {
projection = new Mercator(fullcanvas, map);
if (windField == null) {
SimulatorJSBundle bundle = GWT.create(SimulatorJSBundle.class);
String jsonStr = bundle.windStreamletsDataJS().getText();
field = RectField.read(jsonStr.substring(19, jsonStr.length()-1), false);
map.setZoom(5);
map.panTo(((RectField)field).getCenter());
projection.calibrate();
} else {
field = new SimulatorField(((WindStreamletsCanvasOverlay)fullcanvas).getWindFieldDTO(), ((WindStreamletsCanvasOverlay)fullcanvas).getWindParams());
fullcanvas.setCanvasSettings();
projection.calibrate();
}
this.updateBounds();
color = field.getColors();
Context2d ctxt = canvas.getContext2d();
ctxt.setFillStyle("red");
/*Vector p = this.projection.latlng2pixel(this.field.getFieldNE());
ctxt.fillRect(p.x,p.y,5.0,5.0);
p = this.projection.latlng2pixel(this.field.getFieldSW());
ctxt.fillRect(p.x,p.y,5.0,5.0);*/
particles = this.createParticles();
this.swarmContinue = true;
startLoop(animationDuration);
}
public void stop() {
this.swarmContinue = false;
}
public Particle createParticle() {
Particle particle = new Particle();
boolean done = false;
while (!done) {
particle.pos = field.getRandomPosition();
Vector v = field.getVector(particle.pos);
double weight = field.particleWeight(particle.pos, v);
if (weight >= Math.random()) {
if (v.length() == 0) {
particle.age = 0;
} else {
particle.age = 1 + (int)Math.round(Math.random()*40);
}
particle.pxOld = projection.latlng2pixel(particle.pos);
particle.alpha = 0;
particle.v = v;
done = true;
}
}
return particle;
}
public Particle[] createParticles() {
Particle[] newParticles = new Particle[nParticles];
for(int idx=0; idx<newParticles.length; idx++) {
newParticles[idx] = this.createParticle();
}
return newParticles;
}
public void onBoundsChanged() {
projection.clearCanvas();
swarmPause = 5;
}
public void onMoveEnd() {
}
public static native void console(String msg) /*-{
console.log(msg);
}-*/;
public void updateBounds() {
Position mapNE = new DegreePosition(map.getBounds().getNorthEast().getLatitude(), map.getBounds().getNorthEast().getLongitude());
Position mapSW = new DegreePosition(map.getBounds().getSouthWest().getLatitude(), map.getBounds().getSouthWest().getLongitude());
Position fieldNE = this.field.getFieldNE();
Position fieldSW = this.field.getFieldSW();
Vector visibleNE = this.isVisible(fieldNE);
Vector visibleSW = this.isVisible(fieldSW);
boolean useBoundsNorth = (visibleNE.y == 0);
boolean useBoundsEast = (visibleNE.x == 0);
boolean useBoundsSouth = (visibleSW.y == 0);
boolean 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 DegreePosition(mapNE.getLatDeg(), fieldNE.getLngDeg());
} else if (!useBoundsEast) {
this.boundsNE = new DegreePosition(fieldNE.getLatDeg(), mapNE.getLngDeg());
} else {
this.boundsNE = fieldNE;
}
if ((!useBoundsSouth)&&(!useBoundsWest)) {
this.boundsSW = mapSW;
} else if (!useBoundsSouth) {
this.boundsSW = new DegreePosition(mapSW.getLatDeg(), fieldSW.getLngDeg());
} else if (!useBoundsWest) {
this.boundsSW = new DegreePosition(fieldSW.getLatDeg(), mapSW.getLngDeg());
} else {
this.boundsSW = fieldSW;
}
}
this.field.setVisSW(this.boundsSW);
this.field.setVisNE(this.boundsNE);
Vector boundsSWpx = this.projection.latlng2pixel(this.boundsSW);
Vector boundsNEpx = this.projection.latlng2pixel(this.boundsNE);
double boundsWidthpx = Math.abs(boundsNEpx.x - boundsSWpx.x);
double boundsHeightpx = Math.abs(boundsSWpx.y - boundsNEpx.y);
this.nParticles = (int)Math.round(Math.sqrt(boundsWidthpx * boundsHeightpx) * this.field.getParticleFactor());
//console("#particles: "+this.nParticles + " at " + (boundsWidthpx) +"x" + (boundsHeightpx) + "px (" + (boundsWidthpx * boundsHeightpx) + " pixels)");
};
public Vector isVisible(Position pos) {
// test for visibility of swarm
Vector proj = this.projection.latlng2pixel(pos);
Vector result = new Vector();
result.x = (proj.x < 0 ? -1 : 0) + (proj.x > canvas.getOffsetWidth() ? 1 : 0);
result.y = (proj.y < 0 ? -1 : 0) + (proj.y > canvas.getOffsetHeight() ? 1 : 0);
return result;
}
public void startLoop(final int millis) {
// Create animation-loop based on timer timeout
loopTimer = new com.google.gwt.user.client.Timer() {
public void run() {
Date time0 = new Date();
if (swarmPause > 1) {
swarmPause--;
} else if (swarmPause == 1) {
fullcanvas.setCanvasSettings();
projection.calibrate();
updateBounds();
particles = createParticles();
swarmPause = 0;
}
//console("swarmOffScreen:"+swarmOffScreen);
if ((!swarmOffScreen)&&(swarmPause == 0)) {
execute();
}
Date time1 = new Date();
//console("delta:"+(time1.getTime()-time0.getTime())+"/"+millis);
if (swarmContinue) {
loopTimer.schedule((int)Math.max(10, millis - (time1.getTime()-time0.getTime())));
} else {
projection.clearCanvas();
}
}
};
loopTimer.schedule(millis);
}
public void drawSwarm() {
Context2d ctxt = canvas.getContext2d();
ctxt.setGlobalAlpha(0.08);
ctxt.setGlobalCompositeOperation("destination-out");
ctxt.setFillStyle("black");
ctxt.fillRect(0, 0, canvas.getOffsetWidth(), canvas.getOffsetHeight());
ctxt.setGlobalAlpha(1.0);
ctxt.setGlobalCompositeOperation("source-over");
ctxt.setFillStyle("white");
for(int idx=0; idx<particles.length; idx++) {
Particle particle = particles[idx];
if (particle.age == 0) {
continue;
}
ctxt.setLineWidth(field.lineWidth(particle.alpha));
ctxt.setStrokeStyle(color[particle.alpha]);
ctxt.beginPath();
ctxt.moveTo(particle.pxOld.x, particle.pxOld.y);
particle.pxOld = projection.latlng2pixel(particle.pos);
ctxt.lineTo(particle.pxOld.x, particle.pxOld.y);
ctxt.stroke();
}
}
public boolean execute() {
double speed = 0.01*field.motionScale(map.getZoom());
for(int idx=0; idx<particles.length; idx++) {
Particle particle = particles[idx];
if ((particle.age > 0) && (particle.v != null)) {
double latDeg = particle.pos.getLatDeg() + speed*particle.v.y;
double lngDeg = particle.pos.getLngDeg() + speed*particle.v.x;
particle.pos = new DegreePosition(latDeg, lngDeg);
double s = particle.v.length() / field.getMaxLength();
particle.alpha = (int)Math.min(255, 90 + Math.round(350 * s));
particle.age--;
if ((particle.age > 0) && (this.field.inBounds(particle.pos))) {
particle.v = field.getVector(particle.pos);
} else {
particle.v = null;
}
} else {
particles[idx] = this.createParticle();
}
}
drawSwarm();
return true;
}
public VectorField getField() {
return field;
}
}
@@ -0,0 +1,29 @@
package com.sap.sailing.gwt.ui.simulator.streamlets;
public class Vector {
public double x;
public double y;
public Vector() {
}
public Vector(double x, double y) {
this.x = x;
this.y = y;
}
public double length() {
return Math.sqrt(x*x + y*y);
}
public Vector setLength(double length) {
double current = this.length();
if (current > 0) {
double scale = length / current;
this.x *= scale;
this.y *= scale;
}
return this;
}
}
@@ -0,0 +1,42 @@
package com.sap.sailing.gwt.ui.simulator.streamlets;
import com.sap.sailing.domain.common.Position;
public interface VectorField {
public Position getRandomPosition();
public boolean inBounds(Position p);
public Vector interpolate(Position p);
public Vector getVector(Position p);
public double getMaxLength();
public double motionScale(int zoomLevel);
public double particleWeight(Position p, Vector v);
public String[] getColors();
public double lineWidth(int alpha);
public Position getFieldNE();
public Position getFieldSW();
public void setVisNE(Position visNE);
public void setVisSW(Position visSW);
public double getParticleFactor();
public void setStep(int step);
public void nextStep();
public void prevStep();
}
@@ -55,8 +55,9 @@
<set-property name="gwt.logging.popupHandler" value="DISABLED" />
<set-property name="gwt.logging.systemHandler" value="ENABLED" />
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<extend-property name="locale" values="de"/>
<extend-property name="locale" values="ru"/>
<source path='client'/>
<source path='controls'/>
<source path='components'/>
@@ -21,6 +21,7 @@
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de" />
<extend-property name="locale" values="ru"/>
<source path="client" />
<source path="datamining" />
@@ -29,8 +29,11 @@
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.leaderboard.LeaderboardEntryPoint'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<extend-property name="locale" values="de"/>
<extend-property name="locale" values="ru"/>
<source path='client'/>
<source path='leaderboard'/>
<source path='adminconsole'/>
@@ -33,6 +33,8 @@
<entry-point class='com.sap.sailing.gwt.ui.raceboard.RaceBoardEntryPoint'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<extend-property name="locale" values="ru"/>
<source path='client'/>
<source path='controls'/>
<source path='raceboard'/>
@@ -42,6 +42,8 @@
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<extend-property name="locale" values="ru"/>
<source path='client'/>
<source path='controls'/>
<source path='components'/>
@@ -31,6 +31,8 @@
<entry-point class='com.sap.sailing.gwt.ui.simulator.SimulatorEntryPoint'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<extend-property name="locale" values="ru"/>
<source path='shared'/>
<source path='client'/>
<source path='actions'/>
@@ -29,6 +29,8 @@
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<extend-property name="locale" values="ru"/>
<source path='client'/>
<source path='shared'/>
<source path='spectator'/>
@@ -31,6 +31,8 @@
<entry-point class='com.sap.sailing.gwt.ui.tv.TVEntryPoint'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<extend-property name="locale" values="ru"/>
<source path='client'/>
<source path='tv'/>
<source path='leaderboard'/>
@@ -599,8 +599,10 @@ public class RegattasResource extends AbstractSailingServerResource {
try {
Integer numberOfTacks = trackedLegOfCompetitor.getNumberOfTacks(timePoint);
Integer numberOfJibes = trackedLegOfCompetitor.getNumberOfJibes(timePoint);
Integer numberOfPenaltyCircles = trackedLegOfCompetitor.getNumberOfPenaltyCircles(timePoint);
jsonCompetitorInLeg.put("tacks", numberOfTacks);
jsonCompetitorInLeg.put("jibes", numberOfJibes);
jsonCompetitorInLeg.put("penaltyCircles", numberOfPenaltyCircles);
} catch (NoWindException e) {
}
@@ -15,6 +15,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.junit.Before;
import org.junit.Test;
@@ -50,7 +51,7 @@ public class RaceTrackerStartStopTest {
private RacingEventServiceImplMock racingEventService;
private Regatta regatta;
private BoatClass boatClass;
private Set<RaceTracker> raceTrackerSet = new HashSet<RaceTracker>();
private Set<RaceTracker> raceTrackerSet = Collections.newSetFromMap(new ConcurrentHashMap<RaceTracker, Boolean>());
private RaceDefinition raceDef1;
private RaceDefinition raceDef2;
@@ -66,10 +67,10 @@ public class RaceTrackerStartStopTest {
boatClass = new BoatClassImpl(BOATCLASSNAME, /* typicallyStartsUpwind */ true);
regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, EVENTNAME, boatClass, /* trackedRegattaRegistry */ null,
DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), UUID.randomUUID(), null);
racingEventService.getEventsByName().put(EVENTNAME, regatta);
racingEventService.getRegattasByName().put(EVENTNAME, regatta);
TrackedRegatta trackedRegatta1 = racingEventService.getOrCreateTrackedRegatta(regatta);
racingEventService.getEventsByNameMap().put(EVENTNAME, regatta);
raceTrackerSet = new HashSet<RaceTracker>();
racingEventService.getRegattasByName().put(EVENTNAME, regatta);
raceTrackerSet = Collections.newSetFromMap(new ConcurrentHashMap<RaceTracker, Boolean>());
raceDef1 = new RaceDefinitionImpl(RACENAME1, new CourseImpl("Course1", new ArrayList<Waypoint>()), boatClass, new ArrayList<Competitor>());
raceDef2 = new RaceDefinitionImpl(RACENAME2, new CourseImpl("Course2", new ArrayList<Waypoint>()), boatClass, new ArrayList<Competitor>());
raceDef3 = new RaceDefinitionImpl(RACENAME3, new CourseImpl("Course3", new ArrayList<Waypoint>()), boatClass, new ArrayList<Competitor>());
@@ -100,7 +101,7 @@ public class RaceTrackerStartStopTest {
raceTrackerSet.add(raceTracker1);
raceTrackerSet.add(raceTracker2);
raceTrackerSet.add(raceTracker3);
racingEventService.getRaceTrackersByEventMap().put(regatta, raceTrackerSet);
racingEventService.getRaceTrackersByRegattaMap().put(regatta, raceTrackerSet);
racingEventService.getRaceTrackersByIDMap().put(trackerID1, raceTracker1);
racingEventService.getRaceTrackersByIDMap().put(trackerID2, raceTracker2);
racingEventService.getRaceTrackersByIDMap().put(trackerID3, raceTracker3);
@@ -136,8 +137,8 @@ public class RaceTrackerStartStopTest {
assertFalse(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker3));
// The RaceTrakcersByEvent map should contain a tracker with a set of RaceDefinitions, containing the
// raceDefinition1
assertEquals(1, racingEventService.getRaceTrackersByEventMap().size());
Iterator<RaceTracker> raceTrackerIter = racingEventService.getRaceTrackersByEventMap().get(regatta).iterator();
assertEquals(1, racingEventService.getRaceTrackersByRegattaMap().size());
Iterator<RaceTracker> raceTrackerIter = racingEventService.getRaceTrackersByRegattaMap().get(regatta).iterator();
while (raceTrackerIter.hasNext()) {
RaceTracker currentTracker = raceTrackerIter.next();
assertSame(raceTracker1, currentTracker);
@@ -165,9 +166,9 @@ public class RaceTrackerStartStopTest {
}
assertFalse(foundTrackedRaceForRaceDef2);
// The trackers map should still contain the raceTrackers
assertTrue(racingEventService.getRaceTrackersByEventMap().get(regatta).contains(raceTracker1));
assertTrue(racingEventService.getRaceTrackersByEventMap().get(regatta).contains(raceTracker2));
assertTrue(racingEventService.getRaceTrackersByEventMap().get(regatta).contains(raceTracker3));
assertTrue(racingEventService.getRaceTrackersByRegattaMap().get(regatta).contains(raceTracker1));
assertTrue(racingEventService.getRaceTrackersByRegattaMap().get(regatta).contains(raceTracker2));
assertTrue(racingEventService.getRaceTrackersByRegattaMap().get(regatta).contains(raceTracker3));
// The raceTrackerMap should still contain the raceTrackers. These raceTracker should not contain the raceDefinition raceDef2 anymore
assertTrue(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker1));
assertTrue(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker2));
@@ -193,9 +194,9 @@ public class RaceTrackerStartStopTest {
racingEventService.removeRace(regatta, raceDef1);
racingEventService.removeRace(regatta, raceDef2);
// The event map should still contain the raceTrackers except of raceTracker1 and raceTracker2
assertFalse(racingEventService.getRaceTrackersByEventMap().get(regatta).contains(raceTracker1));
assertFalse(racingEventService.getRaceTrackersByEventMap().get(regatta).contains(raceTracker2));
assertTrue(racingEventService.getRaceTrackersByEventMap().get(regatta).contains(raceTracker3));
assertFalse(racingEventService.getRaceTrackersByRegattaMap().get(regatta).contains(raceTracker1));
assertFalse(racingEventService.getRaceTrackersByRegattaMap().get(regatta).contains(raceTracker2));
assertTrue(racingEventService.getRaceTrackersByRegattaMap().get(regatta).contains(raceTracker3));
// The RaceTrackerByID map should still contain raceTracker3, but not raceTracker1 and raceTracker2 anymore
assertFalse(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker1));
assertFalse(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker2));
@@ -22,11 +22,7 @@ public class RacingEventServiceImplMock extends RacingEventServiceImpl {
lock.addProgress(dataImportProgressImpl.getOperationId(), dataImportProgressImpl);
}
public Map<String, Regatta> getEventsByNameMap() {
return regattasByName;
}
public Map<Regatta, Set<RaceTracker>> getRaceTrackersByEventMap() {
public Map<Regatta, Set<RaceTracker>> getRaceTrackersByRegattaMap() {
return raceTrackersByRegatta;
}
@@ -34,7 +30,7 @@ public class RacingEventServiceImplMock extends RacingEventServiceImpl {
return raceTrackersByID;
}
public Map<String, Regatta> getEventsByName() {
public Map<String, Regatta> getRegattasByName() {
return regattasByName;
}
@@ -26,6 +26,6 @@
<booleanAttribute key="tracing" value="false"/>
<booleanAttribute key="useCustomFeatures" value="false"/>
<booleanAttribute key="useDefaultConfigArea" value="false"/>
<stringAttribute key="workspace_bundles" value="com.google.gwt.osgi@default:default,com.googlecode.java-diff-utils@default:default,com.mongodb.driver@default:default,com.sap.sailing.barbados.resultimport@default:default,com.sap.sailing.datamining.shared@default:default,com.sap.sailing.datamining@default:default,com.sap.sailing.declination@default:default,com.sap.sailing.domain.common@default:default,com.sap.sailing.domain.igtimiadapter.persistence@default:default,com.sap.sailing.domain.igtimiadapter@default:default,com.sap.sailing.domain.persistence@default:default,com.sap.sailing.domain.racelogtrackingadapter@3:true,com.sap.sailing.domain.shared.android@default:default,com.sap.sailing.domain.swisstimingadapter.persistence@default:default,com.sap.sailing.domain.swisstimingadapter@5:true,com.sap.sailing.domain.swisstimingreplayadapter@5:true,com.sap.sailing.domain.tractracadapter.persistence@default:default,com.sap.sailing.domain.tractracadapter@5:true,com.sap.sailing.domain@default:default,com.sap.sailing.ess40.resultimport@default:default,com.sap.sailing.expeditionconnector@default:default,com.sap.sailing.freg.resultimport@default:default,com.sap.sailing.geocoding@default:default,com.sap.sailing.gwt.ui@default:default,com.sap.sailing.kiworesultimport@default:default,com.sap.sailing.manage2sail.resultimport@default:default,com.sap.sailing.manage2sail@default:default,com.sap.sailing.mongodb@default:default,com.sap.sailing.operationaltransformation@default:default,com.sap.sailing.resultimport@default:default,com.sap.sailing.sailwave.resultimport@default:default,com.sap.sailing.server.gateway.ess40@default:default,com.sap.sailing.server.gateway.serialization@default:default,com.sap.sailing.server.gateway@default:default,com.sap.sailing.server.replication@default:default,com.sap.sailing.server.trackfiles@default:default,com.sap.sailing.server@default:default,com.sap.sailing.simulator@default:default,com.sap.sailing.udpconnector@default:default,com.sap.sailing.velum.resultimport@default:default,com.sap.sailing.www.events@default:default,com.sap.sailing.www@default:default,com.sap.sailing.xmlexport@default:default,com.sap.sailing.xrr.resultimport@default:default,com.sap.sse.common@default:default,com.sap.sse.datamining.shared@default:default,com.sap.sse.datamining@default:default,com.sap.sse.gwt@default:default,com.tractrac.clientmodule@default:default,org.json.simple@default:default,org.moxieapps.gwt.highcharts@default:default"/>
<stringAttribute key="workspace_bundles" value="com.google.gwt.osgi@default:default,com.googlecode.java-diff-utils@default:default,com.mongodb.driver@default:default,com.sap.sailing.barbados.resultimport@default:default,com.sap.sailing.datamining.shared@default:default,com.sap.sailing.datamining@default:default,com.sap.sailing.declination@default:default,com.sap.sailing.domain.common@default:default,com.sap.sailing.domain.igtimiadapter.persistence@default:default,com.sap.sailing.domain.igtimiadapter@default:default,com.sap.sailing.domain.persistence@default:default,com.sap.sailing.domain.racelogtrackingadapter@3:true,com.sap.sailing.domain.shared.android@default:default,com.sap.sailing.domain.swisstimingadapter.persistence@default:default,com.sap.sailing.domain.swisstimingadapter@5:true,com.sap.sailing.domain.swisstimingreplayadapter@5:true,com.sap.sailing.domain.tractracadapter.persistence@default:default,com.sap.sailing.domain.tractracadapter@5:true,com.sap.sailing.domain@default:default,com.sap.sailing.ess40.resultimport@default:default,com.sap.sailing.expeditionconnector@default:default,com.sap.sailing.freg.resultimport@default:default,com.sap.sailing.geocoding@default:default,com.sap.sailing.gwt.ui@default:default,com.sap.sailing.kiworesultimport@default:default,com.sap.sailing.manage2sail.resultimport@default:default,com.sap.sailing.manage2sail@default:default,com.sap.sailing.mongodb@default:default,com.sap.sailing.operationaltransformation@default:default,com.sap.sailing.resultimport@default:default,com.sap.sailing.sailwave.resultimport@default:default,com.sap.sailing.server.gateway.ess40@default:default,com.sap.sailing.server.gateway.serialization@default:default,com.sap.sailing.server.gateway@default:default,com.sap.sailing.server.replication@default:default,com.sap.sailing.server.trackfiles@default:default,com.sap.sailing.server@default:default,com.sap.sailing.simulator@default:default,com.sap.sailing.udpconnector@default:default,com.sap.sailing.velum.resultimport@default:default,com.sap.sailing.www.events@default:default,com.sap.sailing.www@default:default,com.sap.sailing.xmlexport@default:default,com.sap.sailing.xrr.resultimport@default:default,com.sap.sse.common@default:default,com.sap.sse.datamining.shared@default:default,com.sap.sse.datamining@default:default,com.sap.sse.gwt@default:default,com.tractrac.clientmodule@default:default,net.sf.marineapi@default:default,org.json.simple@default:default,org.moxieapps.gwt.highcharts@default:default"/>
<stringAttribute key="yk-options" value="&#13;&#10;additional-options2=onexit\=snapshot&#13;&#10;"/>
</launchConfiguration>
@@ -26,6 +26,6 @@
<booleanAttribute key="tracing" value="false"/>
<booleanAttribute key="useCustomFeatures" value="false"/>
<booleanAttribute key="useDefaultConfigArea" value="false"/>
<stringAttribute key="workspace_bundles" value="com.google.gwt.osgi@default:default,com.googlecode.java-diff-utils@default:default,com.mongodb.driver@default:default,com.sap.sailing.barbados.resultimport@default:default,com.sap.sailing.datamining.shared@default:default,com.sap.sailing.datamining@default:default,com.sap.sailing.declination@default:default,com.sap.sailing.domain.common@default:default,com.sap.sailing.domain.igtimiadapter.persistence@default:default,com.sap.sailing.domain.igtimiadapter@default:default,com.sap.sailing.domain.persistence@default:default,com.sap.sailing.domain.racelogtrackingadapter@3:true,com.sap.sailing.domain.shared.android@default:default,com.sap.sailing.domain.swisstimingadapter.persistence@default:default,com.sap.sailing.domain.swisstimingadapter@5:true,com.sap.sailing.domain.swisstimingreplayadapter@5:true,com.sap.sailing.domain.tractracadapter.persistence@default:default,com.sap.sailing.domain.tractracadapter@5:true,com.sap.sailing.domain@default:default,com.sap.sailing.ess40.resultimport@default:default,com.sap.sailing.expeditionconnector@default:default,com.sap.sailing.freg.resultimport@default:default,com.sap.sailing.geocoding@default:default,com.sap.sailing.gwt.ui@default:default,com.sap.sailing.kiworesultimport@default:default,com.sap.sailing.manage2sail.resultimport@default:default,com.sap.sailing.manage2sail@default:default,com.sap.sailing.mongodb@default:default,com.sap.sailing.operationaltransformation@default:default,com.sap.sailing.resultimport@default:default,com.sap.sailing.sailwave.resultimport@default:default,com.sap.sailing.server.gateway.ess40@default:default,com.sap.sailing.server.gateway.serialization@default:default,com.sap.sailing.server.gateway@default:default,com.sap.sailing.server.replication@default:default,com.sap.sailing.server.trackfiles@default:default,com.sap.sailing.server@default:default,com.sap.sailing.simulator@default:default,com.sap.sailing.udpconnector@default:default,com.sap.sailing.velum.resultimport@default:default,com.sap.sailing.www.events@default:default,com.sap.sailing.www@default:default,com.sap.sailing.xrr.resultimport@default:default,com.sap.sse.common@default:default,com.sap.sse.datamining.shared@default:default,com.sap.sse.datamining@default:default,com.sap.sse.gwt@default:default,com.tractrac.clientmodule@default:default,org.json.simple@default:default,org.moxieapps.gwt.highcharts@default:default"/>
<stringAttribute key="workspace_bundles" value="com.google.gwt.osgi@default:default,com.googlecode.java-diff-utils@default:default,com.mongodb.driver@default:default,com.sap.sailing.barbados.resultimport@default:default,com.sap.sailing.datamining.shared@default:default,com.sap.sailing.datamining@default:default,com.sap.sailing.declination@default:default,com.sap.sailing.domain.common@default:default,com.sap.sailing.domain.igtimiadapter.persistence@default:default,com.sap.sailing.domain.igtimiadapter@default:default,com.sap.sailing.domain.persistence@default:default,com.sap.sailing.domain.racelogtrackingadapter@3:true,com.sap.sailing.domain.shared.android@default:default,com.sap.sailing.domain.swisstimingadapter.persistence@default:default,com.sap.sailing.domain.swisstimingadapter@5:true,com.sap.sailing.domain.swisstimingreplayadapter@5:true,com.sap.sailing.domain.tractracadapter.persistence@default:default,com.sap.sailing.domain.tractracadapter@5:true,com.sap.sailing.domain@default:default,com.sap.sailing.ess40.resultimport@default:default,com.sap.sailing.expeditionconnector@default:default,com.sap.sailing.freg.resultimport@default:default,com.sap.sailing.geocoding@default:default,com.sap.sailing.gwt.ui@default:default,com.sap.sailing.kiworesultimport@default:default,com.sap.sailing.manage2sail.resultimport@default:default,com.sap.sailing.manage2sail@default:default,com.sap.sailing.mongodb@default:default,com.sap.sailing.operationaltransformation@default:default,com.sap.sailing.resultimport@default:default,com.sap.sailing.sailwave.resultimport@default:default,com.sap.sailing.server.gateway.ess40@default:default,com.sap.sailing.server.gateway.serialization@default:default,com.sap.sailing.server.gateway@default:default,com.sap.sailing.server.replication@default:default,com.sap.sailing.server.trackfiles@default:default,com.sap.sailing.server@default:default,com.sap.sailing.simulator@default:default,com.sap.sailing.udpconnector@default:default,com.sap.sailing.velum.resultimport@default:default,com.sap.sailing.www.events@default:default,com.sap.sailing.www@default:default,com.sap.sailing.xrr.resultimport@default:default,com.sap.sse.common@default:default,com.sap.sse.datamining.shared@default:default,com.sap.sse.datamining@default:default,com.sap.sse.gwt@default:default,com.tractrac.clientmodule@default:default,net.sf.marineapi@default:default,org.json.simple@default:default,org.moxieapps.gwt.highcharts@default:default"/>
<stringAttribute key="yk-options" value="&#13;&#10;additional-options2=onexit\=snapshot&#13;&#10;"/>
</launchConfiguration>
@@ -269,6 +269,9 @@ class MediaLibrary {
}
}
/**
* Returns a non-live copy of the media tracks
*/
Collection<MediaTrack> allTracks() {
readLock.lock();
try {
File diff suppressed because it is too large. Load diff
-1
View File
@@ -1,5 +1,4 @@
#!/bin/sh
#!/bin/sh
target="`dirname \"$0\"`"
pwd=`pwd`
echo "$target" | grep "^/"
+15 -16
View File
@@ -1,16 +1,15 @@
#!/bin/sh
#!/bin/sh
target="`dirname \"$0\"`"
pwd=`pwd`
echo "$target" | grep "^/"
if [ "$0" != "0" ]; then
# no leading slash, therefore no absolute path; prepend pwd
target="$pwd/$target"
fi
target=c:/data/SAP/sailing/workspace/java/target
echo target is $target
cd "$target/../com.sap.sailing.feature.p2build/bin/products/raceanalysis.product.id/win32/win32/x86_64"
echo pwd is now `pwd`
classpath="`find plugins -name 'com.sap.sailing.expeditionconnector_*.jar' | sort | tail -1`;`find plugins -name 'com.sap.sailing.domain.common_*.jar' | sort | tail -1`"
echo Using classpath $classpath
"$JAVA_HOME/bin/java" -cp "$classpath" -Djava.util.logging.config.file=$target/configuration/logging.properties com.sap.sailing.expeditionconnector.FromHttpToUdpMirror $*
#!/bin/sh
target="`dirname \"$0\"`"
pwd=`pwd`
echo "$target" | grep "^/"
if [ "$0" != "0" ]; then
# no leading slash, therefore no absolute path; prepend pwd
target="$pwd/$target"
fi
target=c:/data/SAP/sailing/workspace/java/target
echo target is $target
cd "$target/../com.sap.sailing.feature.p2build/bin/products/raceanalysis.product.id/win32/win32/x86_64"
echo pwd is now `pwd`
classpath="`find plugins -name 'com.sap.sailing.expeditionconnector_*.jar' | sort | tail -1`;`find plugins -name 'com.sap.sailing.domain.common_*.jar' | sort | tail -1`"
echo Using classpath $classpath
"$JAVA_HOME/bin/java" -cp "$classpath" -Djava.util.logging.config.file=$target/configuration/logging.properties com.sap.sailing.expeditionconnector.FromHttpToUdpMirror $*