diff --git a/home.md b/home.md index 50e58978086..3c5e22a1dae 100644 --- a/home.md +++ b/home.md @@ -26,6 +26,7 @@ SAP is at the center of today’s technology revolution, developing innovations * [[Polars|wiki/Polars]] * Production Environment * [[Amazon EC2|wiki/amazon-ec2]] + * [[SSL / HTTPS Support|wiki/ssl-support]] * [[EC2 Backup Strategy|wiki/amazon-ec2-backup-strategy]] * [[TracTrac|wiki/tractrac-lifecycle]] * [[Analytics on a stick|wiki/analytics-on-a-stick]] diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java index c89a195de69..1ce511c5810 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java @@ -70,7 +70,7 @@ public abstract class AbstractTracTracLiveTest extends StoredTrackBasedTest { public void setUp() throws MalformedURLException, IOException, InterruptedException, URISyntaxException, SubscriberInitializationException, ParseException, CreateModelException { final String eventID = "event_20110505_SailingTea"; final String raceID = "bd8c778e-7c65-11e0-8236-406186cbf87c"; - setUp(getParamURL(eventID, raceID), getLiveURI(), getStoredURI()); + setUp(getParamURL(eventID, raceID), /* liveURI */ null, /* storedURI */ null); } public static URI getStoredURI() throws URISyntaxException { @@ -82,8 +82,7 @@ public abstract class AbstractTracTracLiveTest extends StoredTrackBasedTest { } public static URL getParamURL(final String eventID, final String raceID) throws MalformedURLException { - return new URL("http://" + TracTracConnectionConstants.HOST_NAME + "/events/event_20110505_SailingTea/clientparams.php?event="+eventID+ - "&race="+raceID); + return new URL("http://" + TracTracConnectionConstants.HOST_NAME + "/events/"+eventID+"/"+raceID+".txt"); } protected IEventSubscriber getEventSubscriber() { @@ -99,11 +98,16 @@ public abstract class AbstractTracTracLiveTest extends StoredTrackBasedTest { final IRace race = ModelLocator.getEventFactory().createRace(new URI(paramUrl.toString())); this.race = race; ISubscriberFactory subscriberFactory = SubscriptionLocator.getSusbcriberFactory(); - eventSubscriber = subscriberFactory.createEventSubscriber(race.getEvent(), liveUri, storedUri); - raceSubscriber = subscriberFactory.createRaceSubscriber(race, liveUri, storedUri); + if (storedUri == null) { + eventSubscriber = subscriberFactory.createEventSubscriber(race.getEvent()); + raceSubscriber = subscriberFactory.createRaceSubscriber(race); + } else { + eventSubscriber = subscriberFactory.createEventSubscriber(race.getEvent(), liveUri, storedUri); + raceSubscriber = subscriberFactory.createRaceSubscriber(race, liveUri, storedUri); + } assertNotNull(race); // Initialize data controller using live and stored data sources - if (storedUri.toString().startsWith("file:")) { + if (storedUri != null && storedUri.toString().startsWith("file:")) { try { URI oldStoredUri = storedUri; storedUri = new URI(storedUri.toString().replaceFirst("file:/([^/])", "file:////$1")); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ConcurrencyTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ConcurrencyTest.java index a90757ec3df..0204088e717 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ConcurrencyTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ConcurrencyTest.java @@ -6,6 +6,7 @@ import static org.junit.Assert.assertTrue; import java.io.IOException; import java.net.MalformedURLException; +import java.net.URI; import java.net.URISyntaxException; import java.text.ParseException; import java.util.List; @@ -27,6 +28,7 @@ import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.tracking.DynamicGPSFixTrack; import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tractracadapter.ReceiverType; +import com.sap.sailing.domain.tractracadapter.TracTracConnectionConstants; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.tractrac.model.lib.api.event.CreateModelException; import com.tractrac.subscription.lib.api.SubscriberInitializationException; @@ -43,7 +45,10 @@ public class ConcurrencyTest extends OnlineTracTracBasedTest { super.setUp(); // load Race8 of RC44 Cup in Sweden super.setUp("event_20110815_RCSwedenCu", - /* raceId */ "1cdf8398-cafe-11e0-8c8e-406186cbf87c", new ReceiverType[] { ReceiverType.MARKPASSINGS, + /* raceId */ "event_20110815_RCSwedenCu-Race8", + /* liveUri */ null, + /* storedUri */ tractracTunnel ? new URI("tcp://"+tractracTunnelHost+":"+TracTracConnectionConstants.PORT_TUNNEL_STORED) : new URI("tcp://" + TracTracConnectionConstants.HOST_NAME + ":" + TracTracConnectionConstants.PORT_STORED), + new ReceiverType[] { ReceiverType.MARKPASSINGS, ReceiverType.RACECOURSE, ReceiverType.RAWPOSITIONS }); getTrackedRace().recordWind( new WindImpl(/* position */null, MillisecondsTimePoint.now(), new KnotSpeedWithBearingImpl(12, diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ManeuverDetectionOnMdM2011SemifinalTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ManeuverDetectionOnMdM2011SemifinalTest.java index ada2782a64c..e5603916460 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ManeuverDetectionOnMdM2011SemifinalTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ManeuverDetectionOnMdM2011SemifinalTest.java @@ -53,7 +53,9 @@ public class ManeuverDetectionOnMdM2011SemifinalTest extends OnlineTracTracBased public void setUp() throws MalformedURLException, IOException, InterruptedException, URISyntaxException, ParseException, SubscriberInitializationException, CreateModelException { super.setUp(); super.setUp("event_20110505_SailingTea", // Semifinale - /* raceId */ "01ea3604-02ef-11e1-9efc-406186cbf87c", new ReceiverType[] { ReceiverType.MARKPASSINGS, ReceiverType.RACECOURSE, ReceiverType.RAWPOSITIONS }); + /* raceId */ "01ea3604-02ef-11e1-9efc-406186cbf87c", + /* liveUri */ null, /* storedUri */ null, + new ReceiverType[] { ReceiverType.MARKPASSINGS, ReceiverType.RACECOURSE, ReceiverType.RAWPOSITIONS }); TimePoint epoch = new MillisecondsTimePoint(0l); TimePoint now = MillisecondsTimePoint.now(); Map markPositions = new HashMap(); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java index 815c328937b..730b08055cc 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java @@ -97,6 +97,12 @@ public abstract class OnlineTracTracBasedTest extends AbstractTracTracLiveTest { finishSetUp(receiverTypes); } + protected void setUp(String regattaName, String raceId, URI liveUri, URI storedUri, ReceiverType... receiverTypes) + throws MalformedURLException, IOException, InterruptedException, URISyntaxException, + SubscriberInitializationException, CreateModelException { + setUpWithoutLaunchingController(regattaName, raceId, liveUri, storedUri); + finishSetUp(receiverTypes); + } private void finishSetUp(ReceiverType... receiverTypes) throws InterruptedException { assertEquals(getExpectedEventName(), getTracTracEvent().getName()); @@ -208,9 +214,16 @@ public abstract class OnlineTracTracBasedTest extends AbstractTracTracLiveTest { protected void setUpWithoutLaunchingController(String regattaName, String raceId) throws FileNotFoundException, MalformedURLException, URISyntaxException, SubscriberInitializationException, CreateModelException { - final URL paramUrl = new URL("http://" + TracTracConnectionConstants.HOST_NAME + "/events/"+regattaName+"/clientparams.php?event="+regattaName+"&race="+raceId); final URI liveUri = tractracTunnel ? new URI("tcp://"+tractracTunnelHost+":"+TracTracConnectionConstants.PORT_TUNNEL_LIVE) : new URI("tcp://" + TracTracConnectionConstants.HOST_NAME + ":" + TracTracConnectionConstants.PORT_LIVE); final URI storedUri = tractracTunnel ? new URI("tcp://"+tractracTunnelHost+":"+TracTracConnectionConstants.PORT_TUNNEL_STORED) : new URI("tcp://" + TracTracConnectionConstants.HOST_NAME + ":" + TracTracConnectionConstants.PORT_STORED); + setUpWithoutLaunchingController(regattaName, raceId, liveUri, storedUri); + } + + + protected void setUpWithoutLaunchingController(String regattaName, String raceId, final URI liveUri, + final URI storedUri) throws MalformedURLException, FileNotFoundException, URISyntaxException, + SubscriberInitializationException, CreateModelException { + final URL paramUrl = new URL("http://" + TracTracConnectionConstants.HOST_NAME + "/events/"+regattaName+"/"+raceId+".txt"); setUpWithoutLaunchingController(paramUrl, liveUri, storedUri); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ParseTracTracJSONServiceOutputTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ParseTracTracJSONServiceOutputTest.java index aad99774831..7a5a922795d 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ParseTracTracJSONServiceOutputTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ParseTracTracJSONServiceOutputTest.java @@ -99,12 +99,15 @@ public class ParseTracTracJSONServiceOutputTest { // replay races may have an empty / null live URI assertTrue(race.getLiveURI() == null || new URI("tcp://" + TracTracConnectionConstants.HOST_NAME + ":4400").equals(race.getLiveURI())); // and they point to stored data in the form of a binary ".mtb" file - String expectedSuffix = ".mtb"; + final String expectedSuffix = ".mtb"; assertTrue(race.getStoredURI().toString().endsWith(expectedSuffix) || new URI("tcp://" + TracTracConnectionConstants.HOST_NAME + ":4401").equals(race.getStoredURI())); } else { - assertEquals(new URI("tcp://" + TracTracConnectionConstants.HOST_NAME + ":4400"), race.getLiveURI()); - assertEquals(new URI("tcp://" + TracTracConnectionConstants.HOST_NAME + ":4401"), race.getStoredURI()); + if (!"HIDDEN".equals(race.getRaceStatus())) { + // hidden races may have a null live URI and perhaps have already been converted to an .mtb, so only assert if not a HIDDEN race + assertEquals(new URI("tcp://" + TracTracConnectionConstants.HOST_NAME + ":4400"), race.getLiveURI()); + assertEquals(new URI("tcp://" + TracTracConnectionConstants.HOST_NAME + ":4401"), race.getStoredURI()); + } } } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/MartinAbstractMarkPassingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/MartinAbstractMarkPassingTest.java deleted file mode 100644 index 65457d3db7e..00000000000 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/MartinAbstractMarkPassingTest.java +++ /dev/null @@ -1,730 +0,0 @@ -package com.sap.sailing.domain.test.markpassing; - -import static org.junit.Assert.assertEquals; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.NavigableSet; - -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.Course; -import com.sap.sailing.domain.base.Mark; -import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.common.Bearing; -import com.sap.sailing.domain.common.Distance; -import com.sap.sailing.domain.common.PassingInstruction; -import com.sap.sailing.domain.common.Position; -import com.sap.sailing.domain.common.WindSourceType; -import com.sap.sailing.domain.common.impl.DegreeBearingImpl; -import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; -import com.sap.sailing.domain.common.impl.WindImpl; -import com.sap.sailing.domain.common.impl.WindSourceImpl; -import com.sap.sailing.domain.common.tracking.GPSFix; -import com.sap.sailing.domain.common.tracking.GPSFixMoving; -import com.sap.sailing.domain.test.OnlineTracTracBasedTest; -import com.sap.sailing.domain.tracking.DynamicGPSFixTrack; -import com.sap.sailing.domain.tracking.DynamicTrackedRace; -import com.sap.sailing.domain.tracking.MarkPassing; -import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl; -import com.sap.sailing.domain.tractracadapter.ReceiverType; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.tractrac.model.lib.api.event.CreateModelException; -import com.tractrac.subscription.lib.api.SubscriberInitializationException; - -/** - * Tests the mark passing algorithm by using the data provided by an {@link OnlineTracTracBasedTest}. Subclasses may - * implement different mark passing detection algorithms. - * - * @author Martin Hanysz - * - */ -public abstract class MartinAbstractMarkPassingTest extends OnlineTracTracBasedTest { - /** - * How many milliseconds may the given and computed mark passings drift apart before being counted as a miss. - */ - private static final int TIMEDELTA_TOLERANCE = 10000; - - /** - * Reload the test data from the web? - */ - private boolean forceReload = false; - - public MartinAbstractMarkPassingTest() throws MalformedURLException, URISyntaxException { - super(); - } - - public void setUp() throws IOException, InterruptedException, URISyntaxException, ParseException, SubscriberInitializationException, CreateModelException { - super.setUp(); - String raceID = "357c700a-9d9a-11e0-85be-406186cbf87c"; - if (!loadData(raceID) && !forceReload) { - System.out.println("Downloading new data from the web."); - this.setUp("event_20110609_KielerWoch", - /* raceId */raceID, new ReceiverType[] { ReceiverType.MARKPASSINGS, ReceiverType.MARKPOSITIONS, - ReceiverType.RACECOURSE, ReceiverType.RAWPOSITIONS }); - OnlineTracTracBasedTest.fixApproximateMarkPositionsForWindReadOut(getTrackedRace(), - new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23).getTime())); - getTrackedRace().recordWind( - new WindImpl(/* position */null, MillisecondsTimePoint.now(), new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(65))), new WindSourceImpl(WindSourceType.WEB)); - saveData(); - } - } - - /** - * Loads stored data for the given raceID or returns false if no data is present. - * - * @param raceID - * - ID of the race to load from disk - * @return true if data was loaded, false if not - */ - private boolean loadData(String raceID) { - String path = null; - File file = new File("resources/"); - if (file.exists() && file.isDirectory()) { - for (String fileName : file.list()) { - if (fileName.endsWith(".data") && fileName.contains(raceID)) { - path = "resources/" + fileName; - break; - } - } - } - if (path == null) - return false; - FileInputStream fs = null; - ObjectInputStream os = null; - Object obj = null; - - try { - System.out.print("Loading cached data for raceID " + raceID + "..."); - fs = new FileInputStream(path); - os = new ObjectInputStream(fs); - obj = os.readObject(); - System.out.println("done!"); - } catch (ClassNotFoundException | IOException e) { - e.printStackTrace(); - return false; - } finally { - if (os != null) { - try { - os.close(); - } catch (IOException e) { - e.printStackTrace(); - return false; - } - } - if (fs != null) { - try { - fs.close(); - } catch (IOException e) { - e.printStackTrace(); - return false; - } - } - } - - if (obj != null && obj instanceof DynamicTrackedRaceImpl) { - setTrackedRace((DynamicTrackedRaceImpl) obj); - setRace(getTrackedRace().getRace()); - return true; - } - return false; - } - - /** - * Saves current result of getTrackedRace to disk for future reuse. - */ - private void saveData() { - DynamicTrackedRace trackedRace = getTrackedRace(); - String racePath = "resources/" + trackedRace.getRace().getId() + ".data"; - FileOutputStream fs = null; - ObjectOutputStream os = null; - try { - System.out.println("Caching data for raceID " + trackedRace.getRace().getId()); - File f = new File(racePath); - f.createNewFile(); - fs = new FileOutputStream(f); - os = new ObjectOutputStream(fs); - os.writeObject(trackedRace); - } catch (IOException e) { - e.printStackTrace(); - return; - } finally { - if (os != null) { - try { - os.close(); - } catch (IOException e) { - e.printStackTrace(); - return; - } - } - if (fs != null) { - try { - fs.close(); - } catch (IOException e) { - e.printStackTrace(); - return; - } - } - } - } - - public void testMarkPassings() { - List markPassings = computeAllMarkPassings(); - // compare computed mark passings to given ones - int overallMisses = compareCalculatedAndGivenPassings(markPassings, true); - assertEquals("Calculation returned less mark passings than the test data contains", 0, overallMisses); - } - - /** - * This method starts the actual mark passing detection algorithm by handing a sequence of {@link GPSFix}es of each - * {@link Competitor} into the {@link MartinAbstractMarkPassingTest#computeMarkPassings(Competitor, GPSFixMoving)} - * method. For every competitor, sequences of mark passings for each waypoint of the course can be calculated. One - * sequence may contain multiple possible mark passings for the same waypoint that may represent the same passing of - * that specific waypoint. The list of sequences returned in the result should contain one sequence for each time - * the waypoint has to be passed to complete the course. - * - * @return a {@link Map} from each {@link Competitor} to a {@link Map} from each {@link Waypoint} to a {@link List} - * of mark passing sequences - */ - protected List computeAllMarkPassings() { - ArrayList markPassings = new ArrayList(); - - // To imitate GPSFixes that are received over time, we hand the GPSFixes to the detection algorithm in - // chronological order - HashMap> fixesIterators = new HashMap>(); - HashMap nextFixes = new HashMap(); - - // get all the GPSFix iterators - for (Competitor competitor : getRace().getCompetitors()) { - try { - getTrackedRace().getTrack(competitor).lockForRead(); - // from the start of tracking or "the dawn of time" - TimePoint start = getTrackedRace().getStartOfTracking() != null ? getTrackedRace().getStartOfTracking() - : new MillisecondsTimePoint(0); - fixesIterators.put(competitor, getTrackedRace().getTrack(competitor).getRawFixesIterator(start, true)); - } finally { - getTrackedRace().getTrack(competitor).unlockAfterRead(); - } - } - - // initially fill the next fix of each competitor to hand into the mark passing algorithm - for (Entry> entry : fixesIterators.entrySet()) { - if (entry.getValue().hasNext()) - nextFixes.put(entry.getKey(), entry.getValue().next()); - } - - while (!nextFixes.isEmpty()) { - // Find the chronologically first unhandled fix. - Entry firstUnhandledFix = null; - for (Entry entry : nextFixes.entrySet()) { - if (firstUnhandledFix == null - || entry.getValue().getTimePoint().compareTo(firstUnhandledFix.getValue().getTimePoint()) < 0) { - firstUnhandledFix = entry; - } - } - if (firstUnhandledFix != null) { - // compute a possible mark passing - MarkPassing computedPassing = computeMarkPassings(firstUnhandledFix.getKey(), - firstUnhandledFix.getValue()); - // replace the fix we just handled by the next fix of the competitor's track - if (fixesIterators.get(firstUnhandledFix.getKey()).hasNext()) { - nextFixes.put(firstUnhandledFix.getKey(), fixesIterators.get(firstUnhandledFix.getKey()).next()); - } else { - // If no further fixes can be obtained from the iterator, remove the competitor from the nextFixes - // map. - // This ensures the while loop eventually terminates after all fixes have been analyzed. - nextFixes.remove(firstUnhandledFix.getKey()); - } - firstUnhandledFix = null; - if (computedPassing != null) { - // A new mark passing has been detected. - // Find out if it overwrites a previous mark passing or is a new one. - MarkPassing latestPassingOfCompetitor = null; - int index = -1; - for (int i = 0; i < markPassings.size(); i++) { - MarkPassing p = markPassings.get(i); - if (p.getCompetitor().equals(computedPassing.getCompetitor())) { - latestPassingOfCompetitor = p; - index = i; - } - } - - if (latestPassingOfCompetitor != null - && latestPassingOfCompetitor.getWaypoint().equals(computedPassing.getWaypoint())) { - // Latest passing of the competitor was at the same waypoint -> replace it with the new one - markPassings.set(index, computedPassing); - } else { - markPassings.add(computedPassing); - } - } - } - } - - return markPassings; - } - - /** - * This method starts the actual mark passing detection algorithm. It is supposed to analyze if the given - * {@link Competitor} passed a {@link Mark} at or before the given {@link GPSFixMoving}. If a {@link MarkPassing} - * for a previously passed {@link Waypoint} is detected, it must only return a non-null result, if the returned - * {@link MarkPassing} should overwrite the previously returned one. - * - * @param competitor - * - the {@link Competitor} the given {@link GPSFixMoving} belongs to - * @param fix - * - the {@link GPSFixMoving} representing the latest known position of the given {@link Competitor} - * @return a {@link List} of mark passings - */ - abstract MarkPassing computeMarkPassings(Competitor competitor, GPSFixMoving fix); - - /** - * Compares the computed mark passings to the given ones. For each given sequence of mark passings, the one with the - * timestamp closest to the given data is selected. - * - * @param markPassings - * - a {@link Map} from each {@link Competitor} to a {@link Map} from each {@link Waypoint} to a - * {@link List} of mark passing sequences - * @return how many mark passings were missed or detected way too early or too late - */ - protected int compareCalculatedAndGivenPassings(List markPassings, boolean printDebug) { - int overallMisses = 0; - Iterable competitors = getRace().getCompetitors(); - for (Competitor c : competitors) { - int misses = 0; - NavigableSet givenPassingsForCompetitor = getTrackedRace().getMarkPassings(c); - List calculatedPassingsForCompetitor = new ArrayList(); - for (MarkPassing p : markPassings) { - if (p.getCompetitor().equals(c)) { - calculatedPassingsForCompetitor.add(p); - } - } - if (printDebug) - System.out.println("Competitor is " + c.getName()); - // Simultaneously iterate over given and computed mark passings and calculate the timedelta - ListIterator calculatedPassingsIt = calculatedPassingsForCompetitor.listIterator(); - for (MarkPassing givenPassing : givenPassingsForCompetitor) { - Waypoint passedWaypoint = givenPassing.getWaypoint(); - MarkPassing calculatedPassing; - if (calculatedPassingsIt.hasNext()) { - calculatedPassing = calculatedPassingsIt.next(); - } else { - calculatedPassing = null; - } - - if (calculatedPassing != null && calculatedPassing.getWaypoint().equals(passedWaypoint)) { - long timedelta = calculatedPassing.getTimePoint().asMillis() - - givenPassing.getTimePoint().asMillis(); - String waypointType = isGate(passedWaypoint) ? "Gate" : "Buoy"; - if (Math.abs(timedelta) < TIMEDELTA_TOLERANCE) { - // counts as detected - if (printDebug) - System.out.println("\tTimedelta of calculated mark passing for waypoint " - + passedWaypoint.getName() + " (" + waypointType + "): " + timedelta + "ms, " - + calculatedPassing.getTimePoint().asDate() + "(computed) vs. " - + givenPassing.getTimePoint().asDate() + "(given)"); - } else { - // timedelta too huge, counts as missed - misses++; - overallMisses++; - if (printDebug) - System.out.println("\tPassings of waypoint " + passedWaypoint.getName() + " (" - + waypointType + ") are detected way off (" + timedelta + "ms, " - + calculatedPassing.getTimePoint().asDate() + ")"); - } - } else { - // mark passing for given waypoint - misses++; - overallMisses++; - if (printDebug) - System.out.println("\tNo passings of waypoint " + passedWaypoint.getName()); - if (calculatedPassingsIt.hasPrevious()) { - // rewind the iterator to the previous entry - calculatedPassingsIt.previous(); - } - } - } - if (printDebug) - System.out.println("\t" + misses + " waypoints were missed."); - } - if (printDebug) - System.out.println("Overall, " + overallMisses + " mark passings were missed."); - return overallMisses; - } - - /** - * Get the previous {@link Waypoint} of a given {@link Waypoint}. - * - * @param waypoint - * - the {@link Waypoint} to obtain the predecessor of - * @return a {@link Waypoint} that has to be passed before the given {@link Waypoint} of the {@link Course}, or null - * if none - */ - protected Waypoint getPreviousWaypoint(Waypoint waypoint) { - Course course = getRace().getCourse(); - try { - course.lockForRead(); - int i = course.getIndexOfWaypoint(waypoint); - for (Waypoint w : course.getWaypoints()) { - if (course.getIndexOfWaypoint(w) == i - 1) { - return w; - } - } - } finally { - course.unlockAfterRead(); - } - return null; - } - - /** - * Get the next {@link Waypoint} after the given {@link Waypoint}. - * - * @param waypoint - * - the {@link Waypoint} to obtain the successor of - * @return a {@link Waypoint} that has to be passed after the given {@link Waypoint} of the {@link Course}, or null - * if none - */ - protected Waypoint getNextWaypoint(Waypoint waypoint) { - Course course = getRace().getCourse(); - try { - course.lockForRead(); - int i = course.getIndexOfWaypoint(waypoint); - for (Waypoint w : course.getWaypoints()) { - if (course.getIndexOfWaypoint(w) == i + 1) { - return w; - } - } - } finally { - course.unlockAfterRead(); - } - return null; - } - - /** - * Get the passing side of any given {@link Mark}. For single buoys this returns - * {@link Waypoint#getPassingInstructions()}, for gates, the passing side of the {@link Waypoint}'s first - * {@link Mark} is calculated and depending on the given {@link Mark} is returned unchanged (m = Mark 1) or inverted - * (m = Mark 2). Since the calculation of the passing side uses the {@link DynamicGPSFixTrack} of the - * {@link Waypoint}'s {@link Mark}s, a {@link TimePoint} has to be specified. - * - * @param waypoint - * - the {@link Waypoint} to get the passing side of - * @param m - * - the {@link Mark} of the {@link Waypoint} to get the passing side of - * @param timePoint - * - the {@link TimePoint} to get the passing side at - * @return the {@link NauticSide} the given {@link Mark} of the given {@link WayPoint} has to be passed on at the - * given {@link TimePoint} - */ - protected PassingInstruction getPassingInstructionOfMark(Waypoint waypoint, Mark m, TimePoint timePoint) { - if (isGate(waypoint)) { - PassingInstruction mark1PassingInstruction = getPassingInstructionForMark1OfGate(waypoint, timePoint); - if (m.equals(waypoint.getMarks().iterator().next())) { - // m is mark 1 of gate - return mark1PassingInstruction; - } else if (mark1PassingInstruction.equals(PassingInstruction.Starboard)) { - // m is mark 2 of gate -> opposite PassingInstruction of mark 1 - return PassingInstruction.Port; - } else { - return PassingInstruction.Starboard; - } - } else { - // waypoint is not a gate - return waypoint.getPassingInstructions(); - } - } - - /** - * Calculate the passing side of {@link Mark} 1 of the given {@link Waypoint} at the given {@link TimePoint}. - * - * @param waypoint - * - the {@link Waypoint} to calculate the passing side for - * @param timePoint - * - the {@link TimePoint} to calculate the passing side at - * @return the {@link NauticSide} the {@link Mark} 1 of the given {@link Waypoint} has to be passed on - */ - protected PassingInstruction getPassingInstructionForMark1OfGate(Waypoint waypoint, TimePoint timePoint) { - if (!isGate(waypoint)) { - return null; - } - // calculate the passing side of the first mark in the waypoints marks - Position mark1Pos = null; - Iterator markIt = waypoint.getMarks().iterator(); - DynamicGPSFixTrack mark1Track = getTrackedRace().getOrCreateTrack(markIt.next()); - try { - mark1Track.lockForRead(); - mark1Pos = mark1Track.getFirstRawFixAtOrAfter(timePoint).getPosition(); - } finally { - mark1Track.unlockAfterRead(); - } - - Position mark2Pos = null; - DynamicGPSFixTrack mark2Track = getTrackedRace().getOrCreateTrack(markIt.next()); - try { - mark2Track.lockForRead(); - mark2Pos = mark2Track.getFirstRawFixAtOrAfter(timePoint).getPosition(); - } finally { - mark2Track.unlockAfterRead(); - } - - if (getRace().getCourse().getFirstWaypoint().equals(waypoint)) { - // first waypoint of the course, racing direction is towards next waypoint - Position nextWpPos = getTrackedRace().getApproximatePosition(getNextWaypoint(waypoint), timePoint); - Bearing mark1ToNextWp = mark1Pos.getBearingGreatCircle(nextWpPos); - Bearing mark2ToNextWp = mark2Pos.getBearingGreatCircle(nextWpPos); - if (mark1ToNextWp.getDifferenceTo(mark2ToNextWp).getDegrees() > 0) { - return PassingInstruction.Starboard; - } else { - return PassingInstruction.Port; - } - } else { - // racing direction is from previous waypoint - Position prevWpPos = getTrackedRace().getApproximatePosition(getPreviousWaypoint(waypoint), timePoint); - Bearing prevWpToMark1 = prevWpPos.getBearingGreatCircle(mark1Pos); - Bearing prevWpToMark2 = prevWpPos.getBearingGreatCircle(mark2Pos); - if (prevWpToMark1.getDifferenceTo(prevWpToMark2).getDegrees() > 0) { - return PassingInstruction.Port; - } else { - return PassingInstruction.Starboard; - } - } - } - - /** - * Checks if a {@link Waypoint} has exactly 2 {@link Mark Marks}. - * - * @param wp - * the {@link Waypoint} to check - * @return true if {@link Waypoint#getMarks()} returns an {@link Iterable} with exactly 2 elements. - */ - protected boolean isGate(Waypoint wp) { - Iterator it = wp.getMarks().iterator(); - if (it != null && it.hasNext()) { - it.next(); - if (it.hasNext()) { - it.next(); - if (!it.hasNext()) { - return true; - } - } - } - return false; - } - - /** - * Calculates the passing {@link Bearing} of the given {@link Mark} which belongs to the given {@link Waypoint} at - * the given {@link TimePoint}. - * - * @param waypoint - * - the {@link Waypoint} the given {@link Mark} belongs to - * @param mark - * - the {@link Mark} to calculate the passing {@link Bearing} for - * @param time - * - the {@link TimePoint} at which to calculate the passing {@link Bearing} - * @return a {@link Bearing} that represents the line a boat has to pass in order to round the given {@link Mark} - */ - protected Bearing getPassingBearing(Waypoint waypoint, Mark mark, TimePoint time) { - Course course = getRace().getCourse(); - Bearing passingBearing = null; - - Position markPos = null; - DynamicGPSFixTrack markTrack = getTrackedRace().getOrCreateTrack(mark); - try { - markTrack.lockForRead(); - markPos = markTrack.getFirstRawFixAtOrAfter(time).getPosition(); - } finally { - markTrack.unlockAfterRead(); - } - - if (waypoint.equals(course.getFirstWaypoint()) || waypoint.equals(course.getLastWaypoint())) { - // passing a line - Mark otherMark = null; - for (Mark m : waypoint.getMarks()) { - if (!m.equals(mark)) { - otherMark = m; - } - } - Position otherMarkPos = null; - DynamicGPSFixTrack otherMarkTrack = getTrackedRace().getOrCreateTrack(otherMark); - try { - otherMarkTrack.lockForRead(); - otherMarkPos = otherMarkTrack.getFirstRawFixAtOrAfter(time).getPosition(); - } finally { - otherMarkTrack.unlockAfterRead(); - } - passingBearing = markPos.getBearingGreatCircle(otherMarkPos); - } else { - // passing a single buoy - - Bearing bearingToNextWp = null; - Bearing bearingfromPrevWp = null; - Bearing bearingDiff = null; - - // calculate bearings to next and from previous waypoint - if (!course.getLastWaypoint().equals(waypoint)) { - // not last waypoint of the race - Waypoint nextWp = getNextWaypoint(waypoint); - Position nextWaypointPos = getTrackedRace().getApproximatePosition(nextWp, time); - - bearingToNextWp = markPos.getBearingGreatCircle(nextWaypointPos); - } - if (!course.getFirstWaypoint().equals(waypoint)) { - // not first waypoint of the course - Waypoint prevWp = getPreviousWaypoint(waypoint); - Position prevWaypointPos = getTrackedRace().getApproximatePosition(prevWp, time); - - bearingfromPrevWp = prevWaypointPos.getBearingGreatCircle(markPos); - } - - // depending on passing side, set the bearing difference - PassingInstruction passingInstruction = getPassingInstructionOfMark(waypoint, mark, time); - if (passingInstruction != null && passingInstruction.equals(PassingInstruction.Starboard)) { - bearingDiff = new DegreeBearingImpl(-90); - } else { - bearingDiff = new DegreeBearingImpl(90); - } - - // calculate the passing bearing - if (course.getFirstWaypoint().equals(waypoint)) { - passingBearing = bearingToNextWp.add(bearingDiff); - } else if (course.getLastWaypoint().equals(waypoint)) { - passingBearing = bearingfromPrevWp.add(bearingDiff); - } else { - passingBearing = bearingToNextWp.add(bearingDiff).middle(bearingfromPrevWp.add(bearingDiff)); - } - } - return passingBearing; - } - - /** - * Finds the {@link Entry} with the best {@link MarkPassing} of the key set. A {@link MarkPassing} is better than - * another if: - *
    - *
  1. it is on the correct side of the mark and the other one is not
  2. - *
  3. it is closer to the mark than the other one
  4. - *
  5. its TimePoint is smaller (it happened earlier) than the other one
  6. - *
- * - * @param possiblePassings - * @return - */ - protected Entry findBestMarkPassing(Map passings) { - if (passings.size() == 1) { - return passings.entrySet().iterator().next(); - } else if (passings.isEmpty()) { - return null; - } - Map possibleResults = new HashMap(); - // check if mark was passed on correct side - for (Entry entry : passings.entrySet()) { - // find out on which side of the mark was passed - MarkPassing passing = entry.getKey(); - Position passPos = entry.getValue(); - Position markPos = null; - DynamicGPSFixTrack markTrack = getTrackedRace().getOrCreateTrack( - passing.getWaypoint().getMarks().iterator().next()); - try { - markTrack.lockForRead(); - markPos = markTrack.getLastFixAtOrBefore(passing.getTimePoint()).getPosition(); - } finally { - markTrack.unlockAfterRead(); - } - Bearing bearingDiff = markPos.getBearingGreatCircle(passPos).getDifferenceTo( - getPassingBearing(passing.getWaypoint(), passing.getWaypoint().getMarks().iterator().next(), - passing.getTimePoint())); - if (Math.abs(bearingDiff.getDegrees()) < 90) { - // passed on correct side of mark - possibleResults.put(entry.getKey(), entry.getValue()); - } - } - if (possibleResults.size() > 0) { - // All possible passings are on correct side, pass them to the distance test. - // If all passings were on the wrong side, passings is not overwritten and they are still passed to the - // distance test. - passings.putAll(possibleResults); - } - possibleResults.clear(); - - // find the mark passing with the smallest distance to the mark - for (Entry entry : passings.entrySet()) { - // find out how far away the mark was passed - MarkPassing passing = entry.getKey(); - Position passPos = entry.getValue(); - Position markPos = null; - DynamicGPSFixTrack markTrack = getTrackedRace().getOrCreateTrack( - passing.getWaypoint().getMarks().iterator().next()); - try { - markTrack.lockForRead(); - markPos = markTrack.getLastFixAtOrBefore(passing.getTimePoint()).getPosition(); - } finally { - markTrack.unlockAfterRead(); - } - if (possibleResults.isEmpty()) { - possibleResults.put(passing, passPos); - } else { - Distance shortestDistance = markPos - .getDistance(possibleResults.entrySet().iterator().next().getValue()); - Distance newDistance = markPos.getDistance(passPos); - if (shortestDistance.compareTo(newDistance) == 0) { - // same distance, add to possible results - possibleResults.put(passing, passPos); - } else if (shortestDistance.compareTo(newDistance) > 0) { - // shorter distance, remove all other possible results and add this one - possibleResults.clear(); - possibleResults.put(passing, passPos); - } - } - } - if (possibleResults.size() == 1) { - // only one possible result left, we're done - return possibleResults.entrySet().iterator().next(); - } else if (possibleResults.size() > 1) { - // all possible passings have the same distance to the mark, pass them to the timing test - passings.putAll(possibleResults); - } - possibleResults.clear(); - - // find the mark passing with the smallest timestamp - for (Entry entry : passings.entrySet()) { - // find out how far away the mark was passed - MarkPassing passing = entry.getKey(); - Position passPos = entry.getValue(); - if (possibleResults.isEmpty()) { - possibleResults.put(passing, passPos); - } else { - TimePoint smallestTime = possibleResults.entrySet().iterator().next().getKey().getTimePoint(); - TimePoint newTime = passing.getTimePoint(); - if (smallestTime.compareTo(newTime) == 0) { - // same timestamp, add to possible results - possibleResults.put(passing, passPos); - } else if (smallestTime.compareTo(newTime) > 0) { - // smaller timestamp, remove all other possible results and add this one - possibleResults.clear(); - possibleResults.put(passing, passPos); - } - } - } - if (possibleResults.size() > 0) { - // all possible passings have the same timestamp, just return the first one - return possibleResults.entrySet().iterator().next(); - } - - return null; - } - -} \ No newline at end of file diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/MartinMarkPassingBearingBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/MartinMarkPassingBearingBasedTest.java deleted file mode 100644 index 225dd649841..00000000000 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/MartinMarkPassingBearingBasedTest.java +++ /dev/null @@ -1,249 +0,0 @@ -package com.sap.sailing.domain.test.markpassing; - -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.Course; -import com.sap.sailing.domain.base.DomainFactory; -import com.sap.sailing.domain.base.Mark; -import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.common.Bearing; -import com.sap.sailing.domain.common.Distance; -import com.sap.sailing.domain.common.PassingInstruction; -import com.sap.sailing.domain.common.Position; -import com.sap.sailing.domain.common.tracking.GPSFix; -import com.sap.sailing.domain.common.tracking.GPSFixMoving; -import com.sap.sailing.domain.tracking.DynamicGPSFixTrack; -import com.sap.sailing.domain.tracking.MarkPassing; - -/** - * This class tests a mark passing detection algorithm that is based purely on bearing analyses - * from the {@link Course}'s {@link Mark}s to the GPS fixes of the {@link Competitor}'s boats. - * It uses a "hot zone" around the {@link Mark}s to avoid unnecessary testing of {@link Mark}s - * too far away from the boat. - * - * @author Martin Hanysz - * - */ -public class MartinMarkPassingBearingBasedTest extends MartinAbstractMarkPassingTest { - - /** - * Controls the size of the hot zone around buoys. It is multiplied with the boat length. - */ - private static final double HOT_ZONE_TO_BOAT_LENGHT_RATIO = 10.0; - - private Map> lastCompetitorPassings; - - public MartinMarkPassingBearingBasedTest() throws MalformedURLException, URISyntaxException { - super(); - lastCompetitorPassings = new HashMap>(); - } - - @Override - MarkPassing computeMarkPassings(Competitor competitor, GPSFixMoving fix) { - Map possibleMarkPassings = new HashMap(); - - // find out which waypoints to check (last waypoint passed and the next) - List waypointsToCheck = new ArrayList(); - Course course = getRace().getCourse(); - try { - course.lockForRead(); - if (!lastCompetitorPassings.containsKey(competitor)) { - // no previous passings, competitor needs to pass 1st waypoint - waypointsToCheck.add(course.getFirstWaypoint()); - } else { - // previous passing, competitor either passes same waypoint again or the next waypoint - waypointsToCheck.add(lastCompetitorPassings.get(competitor).getKey().getWaypoint()); - Waypoint next = getNextWaypoint(lastCompetitorPassings.get(competitor).getKey().getWaypoint()); - if (next != null) { - waypointsToCheck.add(next); - } - } - } finally { - course.unlockAfterRead(); - } - - for (Waypoint wp : waypointsToCheck) { - MarkPassing passing = null; - if (isGate(wp)) { - if (wp.equals(course.getFirstWaypoint()) || - wp.equals(course.getLastWaypoint())) { - // start or finish line - passing = getLinePassing(wp, fix, competitor); - } else { - // waypoint is a gate, either pass mark 1 or mark 2 of the gate - Iterator markIterator = wp.getMarks().iterator(); - while (passing == null && markIterator.hasNext()) { - passing = getBuoyPassing(wp, markIterator.next(), fix, competitor); - } - } - } else { - // waypoint is single buoy - passing = getBuoyPassing(wp, wp.getMarks().iterator().next(), fix, competitor); - } - - if (passing != null) { - // detected a passing - possibleMarkPassings.put(passing, fix.getPosition()); - } - } - Entry result = null; - if (possibleMarkPassings.size() > 0) { - Entry lastPassing = lastCompetitorPassings.get(competitor); - Entry possiblePassing = possibleMarkPassings.entrySet().iterator().next(); - if (lastPassing != null && - lastPassing.getKey().getWaypoint().equals(possiblePassing.getKey().getWaypoint())) { - // previous passing detected & passed same waypoint again - possibleMarkPassings.put(lastPassing.getKey(), lastPassing.getValue()); - } - result = findBestMarkPassing(possibleMarkPassings); - } - if (result != null) { - lastCompetitorPassings.put(competitor, result); - return result.getKey(); - } else { - return null; - } - } - - /** - * Check if the given {@link Waypoint} was passed with the given {@link GPSFixMoving} of the given {@link Competitor}. - * @param waypoint - the {@link Waypoint} to check - * @param mark - the mark of the given {@link Waypoint} to be checked - * @param fix - the {@link GPSFixMoving} to check - * @param competitor - the {@link Competitor} the given fix belongs to - * @return a {@link MarkPassing} if the fix represents a passing of the given {@link Waypoint}, null if not - */ - private MarkPassing getBuoyPassing(Waypoint waypoint, Mark mark, GPSFixMoving fix, Competitor competitor) { - if (waypoint == null || getTrackedRace().getStartOfRace().compareTo(fix.getTimePoint()) > 0) { - // no waypoint or race not started yet - return null; - } - - // get position of given mark - Position markPos = null; - DynamicGPSFixTrack markTrack = getTrackedRace().getOrCreateTrack(mark); - try { - markTrack.lockForRead(); - markPos = markTrack.getFirstRawFixAtOrAfter(fix.getTimePoint()).getPosition(); - } finally { - markTrack.unlockAfterRead(); - } - - // check if boat is in "hot zone" - // boat in "hot zone" <=> distance from boat to mark < boat length * x - if (fix.getPosition().getDistance(markPos).compareTo(competitor.getBoat().getBoatClass().getHullLength().scale(HOT_ZONE_TO_BOAT_LENGHT_RATIO)) > 0) { - // not in "hot zone" - return null; - } - - // calculate mark passing bearing for waypoint - Bearing markToBoatBearing = markPos.getBearingGreatCircle(fix.getPosition()); - Bearing passingBearing = getPassingBearing(waypoint, mark, fix.getTimePoint()); - PassingInstruction passingInstruction = getPassingInstructionOfMark(waypoint, mark, fix.getTimePoint()); - double passingBearingDelta = markToBoatBearing.getDifferenceTo(passingBearing).getDegrees(); - if (passingInstruction == null || - (passingInstruction.equals(PassingInstruction.Port) && - passingBearingDelta > 0)) { - // markToBoatBearing is smaller than passing bearing -> passed on port - return DomainFactory.INSTANCE.createMarkPassing(fix.getTimePoint(), waypoint, competitor); - } else if ( passingInstruction.equals(PassingInstruction.Starboard) && - passingBearingDelta < 0) { - // markToBoatBearing is greater than passing bearing -> passed on stb - return DomainFactory.INSTANCE.createMarkPassing(fix.getTimePoint(), waypoint, competitor); - } - return null; - } - - /** - * Check if the line represented by the given {@link Waypoint} was passed with the given {@link GPSFixMoving} of the given {@link Competitor}. - * @param waypoint - the {@link Waypoint} to check - * @param fix - the {@link GPSFixMoving} to check - * @param competitor - the {@link Competitor} the given fix belongs to - * @return a {@link MarkPassing} if the fix represents a passing of the line of the given {@link Waypoint}, null if not - */ - private MarkPassing getLinePassing(Waypoint waypoint, GPSFixMoving fix, Competitor competitor) { - if (waypoint == null || !isGate(waypoint)) { - // no waypoint, waypoint not a gate, or race not started yet - return null; - } - - /* A boat passes the line, if the bearing from the boat to mark 1 of the gate equals - * the bearing from mark 2 of the gate to mark 1 of the gate AND the bearing from the boat - * to mark 2 of the gate equals the bearing from mark 1 of the gate to mark 2 of the gate. - */ - // get tracks of both marks - Iterator markIt = waypoint.getMarks().iterator(); - DynamicGPSFixTrack mark1Track = null; - Mark mark1 = null; - DynamicGPSFixTrack mark2Track = null; - Mark mark2 = null; - if (markIt.hasNext()) { - mark1 = markIt.next(); - mark1Track = getTrackedRace().getOrCreateTrack(mark1); - if (markIt.hasNext()) - mark2 = markIt.next(); - mark2Track = getTrackedRace().getOrCreateTrack(mark2); - } - - // get positions for both marks of the gate - Position mark1Pos = null; - Position mark2Pos = null; - try { - mark1Track.lockForRead(); - try { - mark2Track.lockForRead(); - mark1Pos = mark1Track.getFirstRawFixAtOrAfter(fix.getTimePoint()).getPosition(); - mark2Pos = mark2Track.getFirstRawFixAtOrAfter(fix.getTimePoint()).getPosition(); - } finally { - mark2Track.unlockAfterRead(); - } - } finally { - mark1Track.unlockAfterRead(); - } - - // calculate if boat is in "hot zone" of gate - // in "hot zone" <=> distance from any mark of gate to boat < length of line between marks - Distance lineLength = mark1Pos.getDistance(mark2Pos); - if ( mark1Pos.getDistance(fix.getPosition()).compareTo(lineLength) > 0 && - mark2Pos.getDistance(fix.getPosition()).compareTo(lineLength) > 0) { - // not in "hot zone" - return null; - } - - // calculate bearings from boat to 1st and 2nd mark, from 1st mark to 2nd mark, and from 2nd mark to 1st mark - Bearing boatToMark1Bearing = fix.getPosition().getBearingGreatCircle(mark1Pos); - Bearing mark1ToMark2Bearing = mark1Pos.getBearingGreatCircle(mark2Pos); - Bearing boatToMark2Bearing = fix.getPosition().getBearingGreatCircle(mark2Pos); - Bearing mark2ToMark1Bearing = mark2Pos.getBearingGreatCircle(mark1Pos); - - PassingInstruction PassingInstructionOfMark1OfGate = getPassingInstructionForMark1OfGate(waypoint, fix.getTimePoint()); - double mark1PassingBearingDelta = boatToMark1Bearing.getDifferenceTo(mark2ToMark1Bearing).getDegrees(); - double mark2PassingBearingDelta = boatToMark2Bearing.getDifferenceTo(mark1ToMark2Bearing).getDegrees(); - //Mark closestMark = mark1; - if (mark2 != null && fix.getPosition().getDistance(mark1Pos).compareTo(fix.getPosition().getDistance(mark2Pos)) < 0) { - //closestMark = mark2; - - } - - if ( PassingInstructionOfMark1OfGate.equals(PassingInstruction.Starboard) && - mark1PassingBearingDelta < 0 && - mark2PassingBearingDelta > 0) { - // gate passed if mark1 had to be passed on stb - return DomainFactory.INSTANCE.createMarkPassing(fix.getTimePoint(), waypoint,competitor); - } else if ( PassingInstructionOfMark1OfGate.equals(PassingInstruction.Port) && - mark1PassingBearingDelta > 0 && - mark2PassingBearingDelta < 0) { - // gate passed if mark1 had to be passed on port - return DomainFactory.INSTANCE.createMarkPassing(fix.getTimePoint(), waypoint, competitor); - } - return null; - } -} diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/MartinMarkPassingSplineBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/MartinMarkPassingSplineBasedTest.java deleted file mode 100644 index 72acf4e8742..00000000000 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/MartinMarkPassingSplineBasedTest.java +++ /dev/null @@ -1,192 +0,0 @@ -package com.sap.sailing.domain.test.markpassing; - -import static org.junit.Assert.assertTrue; - -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.junit.Before; - -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.Course; -import com.sap.sailing.domain.base.DomainFactory; -import com.sap.sailing.domain.base.Mark; -import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.common.Bearing; -import com.sap.sailing.domain.common.Position; -import com.sap.sailing.domain.common.impl.DegreePosition; -import com.sap.sailing.domain.common.tracking.GPSFix; -import com.sap.sailing.domain.common.tracking.GPSFixMoving; -import com.sap.sailing.domain.markpassingcalculation.splining.HermiteCurve; -import com.sap.sailing.domain.markpassingcalculation.splining.StraightLine; -import com.sap.sailing.domain.markpassingcalculation.splining.Vector2D; -import com.sap.sailing.domain.tracking.DynamicGPSFixTrack; -import com.sap.sailing.domain.tracking.MarkPassing; -import com.sap.sse.common.TimePoint; - -/** - * This class tests a mark passing detection algorithm that interpolates the boats' positions between - * their GPS fixes using Hermite Splines. - * @author Martin Hanysz - * - */ -public class MartinMarkPassingSplineBasedTest extends MartinAbstractMarkPassingTest { - - // a factor to scale the tangents calculated from boat speed and bearing - private static double TANGENT_SCALING_FACTOR = 100; - private Map> lastCompetitorPassings; - - public MartinMarkPassingSplineBasedTest() throws MalformedURLException, URISyntaxException { - super(); - lastCompetitorPassings = new HashMap>(); - } - - @Before - public void setTangentScaling() { - TANGENT_SCALING_FACTOR = 100.0; - } - - - public void testTangentScaling() { - Map results = new HashMap(); - double s = 100.0; - double div = 10.0; - while (s > 0.000000001) { - MartinMarkPassingSplineBasedTest.TANGENT_SCALING_FACTOR = s; - List markPassings = computeAllMarkPassings(); - // compare computed mark passings to given ones - int overallMisses = compareCalculatedAndGivenPassings(markPassings, false); - results.put(s, overallMisses); - s /= div; - } - boolean success = false; - for (Entry e : results.entrySet()) { - System.out.println("Scaling: " + e.getKey() + ", Misses: " + e.getValue()); - if (e.getValue() == 0) { - success = true; - } - } - assertTrue("No setting for the scaling factor resulted in 0 missed waypoints.", success); - } - - - /* (non-Javadoc) - * @see com.sap.sailing.domain.test.AbstractMarkPassingTest#computeMarkPassings() - */ - @Override - MarkPassing computeMarkPassings(Competitor competitor, GPSFixMoving fix) { - // interpolate the course of the competitor from the previous fix to the given fix - DynamicGPSFixTrack competitorTrack = getTrackedRace().getTrack(competitor); - GPSFixMoving prevFix = null; - try { - competitorTrack.lockForRead(); - prevFix = competitorTrack.getLastRawFixBefore(fix.getTimePoint()); - } finally { - competitorTrack.unlockAfterRead(); - } - if (prevFix == null) { - return null; - } - Vector2D point1 = new Vector2D(prevFix.getPosition()); - Vector2D point2 = new Vector2D(fix.getPosition()); - Vector2D tangent1 = new Vector2D(prevFix.getSpeed().getBearing(), prevFix.getSpeed().getKnots() * TANGENT_SCALING_FACTOR /* abh�ngig von Bootsklasse, zeitl. Abstand zw. Fixes */); - Vector2D tangent2 = new Vector2D(fix.getSpeed().getBearing(), fix.getSpeed().getKnots() * TANGENT_SCALING_FACTOR); - HermiteCurve interpolatedCourse = new HermiteCurve(point1, point2, tangent1, tangent2); - - // find out which waypoints to check (last waypoint passed and the next) - List waypointsToCheck = new ArrayList(); - Course raceCourse = getRace().getCourse(); - try { - raceCourse.lockForRead(); - if (!lastCompetitorPassings.containsKey(competitor)) { - // no previous passings, competitor needs to pass 1st waypoint - waypointsToCheck.add(raceCourse.getFirstWaypoint()); - } else { - waypointsToCheck.add(lastCompetitorPassings.get(competitor).getKey().getWaypoint()); - Waypoint next = getNextWaypoint(lastCompetitorPassings.get(competitor).getKey().getWaypoint()); - if (next != null) { - waypointsToCheck.add(next); - } - } - } finally { - raceCourse.unlockAfterRead(); - } - - // check if the interpolated course passes one of the waypoints to check - Map possiblePassings = new HashMap(); - for (Waypoint wp : waypointsToCheck) { - StraightLine passingLine = null; - List markPositions = new ArrayList(); - for (Mark m : wp.getMarks()) { - DynamicGPSFixTrack markTrack = getTrackedRace().getOrCreateTrack(m); - try { - markTrack.lockForRead(); - markPositions.add(markTrack.getLastFixAtOrBefore(fix.getTimePoint()).getPosition()); - } finally { - markTrack.unlockAfterRead(); - } - } - Vector2D mark1Pos = new Vector2D(markPositions.get(0)); - Map intersections = null; - //Mark passedMark = wp.getMarks().iterator().next(); - if (isGate(wp)) { - if (wp.equals(raceCourse.getFirstWaypoint()) || wp.equals(raceCourse.getLastWaypoint())) { - // passing start or finish line - Vector2D mark2Pos = new Vector2D(markPositions.get(1)); - passingLine = new StraightLine(mark1Pos, mark2Pos.subtract(mark1Pos)); - intersections = interpolatedCourse.intersectWith(passingLine); - } else { - // passing either mark of the gate - for (Mark mark : wp.getMarks()) { - Bearing passingBearing = getPassingBearing(wp, mark, fix.getTimePoint()); - Vector2D passingVector = new Vector2D(passingBearing, 1.0); - passingLine = new StraightLine(mark1Pos, passingVector); - intersections = interpolatedCourse.intersectWith(passingLine); - if (intersections.size() > 0) { - // already found a passing of a mark - //passedMark = mark; - break; - } - } - } - } else { - // passing single buoy - Bearing passingBearing = getPassingBearing(wp, wp.getMarks().iterator().next(), fix.getTimePoint()); - Vector2D passingVector = new Vector2D(passingBearing, 1.0); - passingLine = new StraightLine(mark1Pos, passingVector); - intersections = interpolatedCourse.intersectWith(passingLine); - } - for (Entry entry : intersections.entrySet()) { - TimePoint time = fix.getTimePoint(); - TimePoint prevTime = prevFix.getTimePoint(); - // t_pass = t_fix - (t_prev - t_fix) * interpolationParameterOfIntersection - // If the intersection is at 75% of the interpolated course, t_pass is at 75% between t_prev and t_fix. - // This cast truncates the milliseconds, which is acceptable at the moment. - TimePoint timePoint = time.minus((long) ((prevTime.asMillis() - time.asMillis()) * entry.getValue())); - possiblePassings.put(DomainFactory.INSTANCE.createMarkPassing(timePoint, wp, competitor), new DegreePosition(entry.getKey().y(), entry.getKey().x())); - } - } - Entry result = null; - if (possiblePassings.size() > 0) { - Entry lastPassing = lastCompetitorPassings.get(competitor); - Entry possiblePassing = possiblePassings.entrySet().iterator().next(); - if (lastPassing != null && - lastPassing.getKey().getWaypoint().equals(possiblePassing.getKey().getWaypoint())) { - // previous passing detected & passed same waypoint again - possiblePassings.put(lastPassing.getKey(), lastPassing.getValue()); - } - result = findBestMarkPassing(possiblePassings); - } - if (result != null) { - lastCompetitorPassings.put(competitor, result); - return result.getKey(); - } else { - return null; - } - } -} diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/RaceRecord.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/RaceRecord.java index 54ae75fd10f..334e36e4e7f 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/RaceRecord.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/RaceRecord.java @@ -107,16 +107,16 @@ public class RaceRecord { throw e; } if (loadLiveAndStoredURI) { - Map paramURLContents = parseParams(paramURL); - String liveURIAsString = paramURLContents.get(LIVE_URI_PROPERTY); - liveURI = liveURIAsString == null ? null : new URI(liveURIAsString); - String storedURIAsString = paramURLContents.get(STORED_URI_PROPERTY); - if (storedURIAsString == null || storedURIAsString.startsWith("tcp:") || storedURIAsString.startsWith("http:") || - storedURIAsString.startsWith("https:")) { - storedURI = storedURIAsString == null ? null : new URI(storedURIAsString); - } else { - storedURI = new URI(baseURL+"/"+storedURIAsString); - } + Map paramURLContents = parseParams(paramURL); + String liveURIAsString = paramURLContents.get(LIVE_URI_PROPERTY); + liveURI = liveURIAsString == null ? null : new URI(liveURIAsString); + String storedURIAsString = paramURLContents.get(STORED_URI_PROPERTY); + if (storedURIAsString == null || storedURIAsString.startsWith("tcp:") || storedURIAsString.startsWith("http:") || + storedURIAsString.startsWith("https:")) { + storedURI = storedURIAsString == null ? null : new URI(storedURIAsString); + } else { + storedURI = new URI(baseURL+"/"+storedURIAsString); + } } else { paramURLAsString = null; liveURI = null; diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/TracTracConnectionConstants.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/TracTracConnectionConstants.java index 48615bee92c..cdfcc8187b0 100644 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/TracTracConnectionConstants.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/TracTracConnectionConstants.java @@ -11,13 +11,13 @@ public interface TracTracConnectionConstants { final int PORT_STORED = PORT_LIVE + 1; //For official usage use 4401; /* - * ‘Status’ is the one that we used originally and is an enumerate with the values: + * "Status" is the one that we used originally and is an enumerate with the values: * - HIDDEN: the race is hidden * - OFFLINE: the race is visible but it can not be loaded * - ONLINE: the race is visible and online * - REPLAY: the race is online and the mtb-file has been created (this value is no longer being used as we no longer display information about whether data are being retrieved from data base or file) - * ‘Visibility’ was introduced this year to improve some short comings of the ‘status’ attribute and is an enumerate with the values: + * "Visibility" was introduced this year to improve some short comings of the "status" attribute and is an enumerate with the values: * - HIDDEN: the race is hidden (same meaning as above) * - OFFLINE: the race is visible but it can not be loaded (same meaning as above) * - ONLINE: the race can be loaded and it is in a live status (live or future) diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch b/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch index 01f086d2cd1..2bd988c6083 100644 --- a/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch @@ -1,78 +1,78 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT.launch b/java/com.sap.sailing.gwt.ui/SailingGWT.launch index a533c08e61c..6adb642328e 100644 --- a/java/com.sap.sailing.gwt.ui/SailingGWT.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT.launch @@ -1,75 +1,75 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.gwt.ui/imprint.json b/java/com.sap.sailing.gwt.ui/imprint.json index 6a6fc4b5f77..adc22eb8176 100644 --- a/java/com.sap.sailing.gwt.ui/imprint.json +++ b/java/com.sap.sailing.gwt.ui/imprint.json @@ -1,381 +1,751 @@ { - "components" : - [ + "components": [ { - "name" : "Apache Commons BeanUtils", - "version" : "1.9.0", - "owner" : "The Apache Software Foundation", - "homepage" : "http://commons.apache.org/proper/commons-beanutils/", - "acknowledgements" : [ + "name": "Apache Commons BeanUtils", + "version": "1.9.0", + "owner": "The Apache Software Foundation", + "homepage": "http://commons.apache.org/proper/commons-beanutils/", + "acknowledgements": [ "Apache Commons BeanUtils Copyright 2000-2013 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/)." ], - "key" : "ASL2.0" - } - ,{ - "name" : "Apache Commons Codec", - "version" : "1.6", - "owner" : "The Apache Software Foundation", - "homepage" : "http://jakarta.apache.org/commons/codec/", - "acknowledgements" : [ - "Copyright 2002-2011 The Apache Software Foundation This product includes software developed by The Apache Software Foundation (http://www.apache.org/)." - ,"--------------------------------------------------------------------------------" - ,"src/test/org/apache/commons/codec/language/DoubleMetaphoneTest.java contains test data from http://aspell.sourceforge.net/test/batch0.tab. Copyright (C) 2002 Kevin Atkinson (kevina@gnu.org). Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved. " - ,"--------------------------------------------------------------------------------" + "key": "ASL2.0" + }, + { + "name": "Apache Commons Codec", + "version": "1.6", + "owner": "The Apache Software Foundation", + "homepage": "http://jakarta.apache.org/commons/codec/", + "acknowledgements": [ + "Copyright 2002-2011 The Apache Software Foundation This product includes software developed by The Apache Software Foundation (http://www.apache.org/).", + "--------------------------------------------------------------------------------", + "src/test/org/apache/commons/codec/language/DoubleMetaphoneTest.java contains test data from http://aspell.sourceforge.net/test/batch0.tab. Copyright (C) 2002 Kevin Atkinson (kevina@gnu.org). Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved. ", + "--------------------------------------------------------------------------------" ], - "key" : "ASL2.0" - } - ,{ - "name" : "Apache Commons Collections", - "version" : "3.2.1", - "owner" : "The Apache Software Foundation", - "homepage" : "http://commons.apache.org/collections/", - "acknowledgements" : [ + "key": "ASL2.0" + }, + { + "name": "Apache Commons Collections", + "version": "3.2.1", + "owner": "The Apache Software Foundation", + "homepage": "http://commons.apache.org/collections/", + "acknowledgements": [ "Apache Commons Collections Copyright 2001-2008 The Apache Software Foundation This product includes software developed by The Apache Software Foundation (http://www.apache.org/)." ], - "key" : "ASL2.0" - } - ,{ - "name" : "Apache Felix Remote Shell", - "version" : "1.1.2", - "owner" : "The Apache Software Foundation", - "homepage" : "http://felix.apache.org/site/apache-felix-remote-shell.html", - "acknowledgements" : [ + "key": "ASL2.0" + }, + { + "name": "Apache Felix Remote Shell", + "version": "1.1.2", + "owner": "The Apache Software Foundation", + "homepage": "http://felix.apache.org/documentation/subprojects/apache-felix-shell.html", + "acknowledgements": [ "Apache Felix Remote Shell Copyright 2010 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). Licensed under the Apache License 2.0." ], - "key" : "ASL2.0" - } - ,{ - "name" : "Apache POI - org.apache.poi:poi-ooxml", - "version" : "3.7", - "owner" : "The Apache Software Foundation", - "homepage" : "http://repo1.maven.org/maven2/org/apache/poi/poi-ooxml/", - "acknowledgements" : [ - "Copyright 2009 The Apache Software Foundation This product includes software developed by The Apache Software Foundation (http://www.apache.org/). " - ,"This product contains the DOM4J library (http://www.dom4j.org). Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. " - ,"This product contains parts that were originally based on software from BEA. Copyright (c) 2000-2003, BEA Systems, ." - ,"This product contains W3C XML Schema documents. Copyright 2001-2003 (c) World Wide Web Consortium (Massachusetts Institute of Technology, European Research Consortium for Informatics and Mathematics, Keio University) " - ,"This product contains the Piccolo XML Parser for Java (http://piccolo.sourceforge.net/). Copyright 2002 Yuval Oren." - ,"This product contains the chunks_parse_cmds.tbl file from the vsdump program. Copyright (C) 2006-2007 Valek Filippov (frob@df.ru) " - ,"APACHE POI SUBCOMPONENTS: Apache POI includes subcomponents with separate copyright notices and license terms. Your use of these subcomponents is subject to the terms and conditions of the following licenses: Office Open XML schemas (ooxml-schemas-1.0.jar) The Office Open XML schema definitions used by Apache POI are a part of the Office Open XML ECMA Specification (ECMA-376, [1]). As defined in section 9.4 of the ECMA bylaws [2], this specification is available to all interested parties without restriction: " - ,"9.4 All documents when approved shall be made available to all interested parties without restriction. Furthermore, both Microsoft and Adobe have granted patent licenses to this work [3,4,5]." - ," [1] http://www.ecma-international.org/publications/standards/Ecma-376.htm " - ," [2] http://www.ecma-international.org/memento/Ecmabylaws.htm " - ," [3] http://www.microsoft.com/interop/osp/" - ," [4] http://www.ecma-international.org/publications/files/ECMA-ST/Ecma%20PATENT/ECMA-376%20Edition%201%20Microsoft%20Patent%20Declaration.pdf " - ," [5] http://www.ecma-international.org/publications/files/ECMA-ST/Ecma%20PATENT/ga-2006-191.pdf " - ," DOM4J library (dom4j-1.6.1.jar) Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. Redistribution and use of this software and associated documentation (\"Software\"), with or without modification, are permitted provided that the following conditions are met: " - ,"1. Redistributions of source code must retain copyright statements and notices. Redistributions must also contain a copy of this document. " - ,"2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. " - ,"3. The name \"DOM4J\" must not be used to endorse or promote products derived from this Software without prior written permission of MetaStuff, Ltd. For written permission, please contact dom4j-info@metastuff.com. " - ,"4. Products derived from this Software may not be called \"DOM4J\" nor may \"DOM4J\" appear in their names without prior written permission of MetaStuff, Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. " - ,"5. Due credit should be given to the DOM4J Project - http://www.dom4j.org THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. " - ,"JUnit test library (junit-3.8.1.jar) Common Public License - v 1.0 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE (\"AGREEMENT\"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. " - ,"1. DEFINITIONS \"Contribution\" means: " - ,"a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and " - ,"b) in the case of each subsequent Contributor: " - ,"i) changes to the Program, and " - ,"ii) additions to the Program; " - ,"where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: " - ,"(i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and " - ,"(ii) are not derivative works of the Program. " - ,"\"Contributor\" means any person or entity that distributes the Program. " - ,"\"Licensed Patents\" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program." - ,"\"Program\" means the Contributions distributed in accordance with this Agreement." - ,"\"Recipient\" means anyone who receives the Program under this Agreement, including all Contributors. " - ,"2. GRANT OF RIGHTS" - ,"a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form." - ,"b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. " - ,"c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program." - ,"d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. " - ,"3. REQUIREMENTS " - ,"A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: " - ,"a) it complies with the terms and conditions of this Agreement; and " - ,"b) its license agreement: " - ,"i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; " - ,"ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; " - ,"iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and " - ,"iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. " - ,"When the Program is made available in source code form: " - ,"a) it must be made available under this Agreement; and " - ,"b) a copy of this Agreement must be included with each copy of the Program. " - ,"Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. " - ,"4. COMMERCIAL DISTRIBUTION " - ,"Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor (\"Commercial Contributor\") hereby agrees to defend and indemnify every other Contributor (\"Indemnified Contributor\") against any losses, damages and costs (collectively \"Losses\") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: " - ,"a) promptly notify the Commercial Contributor in writing of such claim, and " - ,"b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. " - ,"The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. " - ,"5. NO WARRANTY " - ,"EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. " - ,"6. DISCLAIMER OF LIABILITY " - ,"EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. " - ,"7. GENERAL " - ,"If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation." + "key": "ASL2.0" + }, + { + "name": "Apache Felix Remote Shell Service", + "version": "1.4.3", + "owner": "The Apache Software Foundation", + "homepage": "http://felix.apache.org/site/apache-felix-remote-shell.html", + "acknowledgements": [ + "Apache Felix Shell Service Copyright 2006-2012 The Apache Software Foundation", + "This product includes software developed at The Apache Software Foundation (http://www.apache.org/", + "This product uses software developed at The OSGi Alliance (http://www.osgi.org/). Copyright (c) OSGi Alliance (2000, 2007). Licensed under the Apache License 2.0." ], - "key" : "ASL2.0" - } - ,{ - "name" : "Apache ServiceMix :: Bundles :: aws-java-sdk", - "version" : "1.9.8_1", - "owner" : "The Apache Software Foundation", - "homepage" : "http://repo.maven.apache.org/maven2/org/apache/servicemix/bundles/org.apache.servicemix.bundles.aws-java-sdk/", - "acknowledgements" : [ + "key": "ASL2.0" + }, + { + "name": "Apache POI - org.apache.poi:poi-ooxml", + "version": "3.7", + "owner": "The Apache Software Foundation", + "homepage": "http://repo1.maven.org/maven2/org/apache/poi/poi-ooxml/", + "acknowledgements": [ + "Copyright 2009 The Apache Software Foundation This product includes software developed by The Apache Software Foundation (http://www.apache.org/). ", + "This product contains the DOM4J library (http://www.dom4j.org). Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. ", + "This product contains parts that were originally based on software from BEA. Copyright (c) 2000-2003, BEA Systems, .", + "This product contains W3C XML Schema documents. Copyright 2001-2003 (c) World Wide Web Consortium (Massachusetts Institute of Technology, European Research Consortium for Informatics and Mathematics, Keio University) ", + "This product contains the Piccolo XML Parser for Java (http://piccolo.sourceforge.net/). Copyright 2002 Yuval Oren.", + "This product contains the chunks_parse_cmds.tbl file from the vsdump program. Copyright (C) 2006-2007 Valek Filippov (frob@df.ru) ", + "APACHE POI SUBCOMPONENTS: Apache POI includes subcomponents with separate copyright notices and license terms. Your use of these subcomponents is subject to the terms and conditions of the following licenses: Office Open XML schemas (ooxml-schemas-1.0.jar) The Office Open XML schema definitions used by Apache POI are a part of the Office Open XML ECMA Specification (ECMA-376, [1]). As defined in section 9.4 of the ECMA bylaws [2], this specification is available to all interested parties without restriction: ", + "9.4 All documents when approved shall be made available to all interested parties without restriction. Furthermore, both Microsoft and Adobe have granted patent licenses to this work [3,4,5].", + " [1] http://www.ecma-international.org/publications/standards/Ecma-376.htm ", + " [2] http://www.ecma-international.org/memento/Ecmabylaws.htm ", + " [3] http://www.microsoft.com/interop/osp/", + " [4] http://www.ecma-international.org/publications/files/ECMA-ST/Ecma%20PATENT/ECMA-376%20Edition%201%20Microsoft%20Patent%20Declaration.pdf ", + " [5] http://www.ecma-international.org/publications/files/ECMA-ST/Ecma%20PATENT/ga-2006-191.pdf ", + " DOM4J library (dom4j-1.6.1.jar) Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. Redistribution and use of this software and associated documentation (\"Software\"), with or without modification, are permitted provided that the following conditions are met: ", + "1. Redistributions of source code must retain copyright statements and notices. Redistributions must also contain a copy of this document. ", + "2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. ", + "3. The name \"DOM4J\" must not be used to endorse or promote products derived from this Software without prior written permission of MetaStuff, Ltd. For written permission, please contact dom4j-info@metastuff.com. ", + "4. Products derived from this Software may not be called \"DOM4J\" nor may \"DOM4J\" appear in their names without prior written permission of MetaStuff, Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. ", + "5. Due credit should be given to the DOM4J Project - http://www.dom4j.org THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ", + "JUnit test library (junit-3.8.1.jar) Common Public License - v 1.0 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE (\"AGREEMENT\"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. ", + "1. DEFINITIONS \"Contribution\" means: ", + "a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and ", + "b) in the case of each subsequent Contributor: ", + "i) changes to the Program, and ", + "ii) additions to the Program; ", + "where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: ", + "(i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and ", + "(ii) are not derivative works of the Program. ", + "\"Contributor\" means any person or entity that distributes the Program. ", + "\"Licensed Patents\" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.", + "\"Program\" means the Contributions distributed in accordance with this Agreement.", + "\"Recipient\" means anyone who receives the Program under this Agreement, including all Contributors. ", + "2. GRANT OF RIGHTS", + "a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.", + "b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. ", + "c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.", + "d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. ", + "3. REQUIREMENTS ", + "A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: ", + "a) it complies with the terms and conditions of this Agreement; and ", + "b) its license agreement: ", + "i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ", + "ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; ", + "iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and ", + "iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. ", + "When the Program is made available in source code form: ", + "a) it must be made available under this Agreement; and ", + "b) a copy of this Agreement must be included with each copy of the Program. ", + "Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. ", + "4. COMMERCIAL DISTRIBUTION ", + "Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor (\"Commercial Contributor\") hereby agrees to defend and indemnify every other Contributor (\"Indemnified Contributor\") against any losses, damages and costs (collectively \"Losses\") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: ", + "a) promptly notify the Commercial Contributor in writing of such claim, and ", + "b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. ", + "The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. ", + "5. NO WARRANTY ", + "EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. ", + "6. DISCLAIMER OF LIABILITY ", + "EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. ", + "7. GENERAL ", + "If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation." + ], + "key": "ASL2.0" + }, + { + "name": "Apache ServiceMix :: Bundles :: aws-java-sdk", + "version": "1.9.8_1", + "owner": "The Apache Software Foundation", + "homepage": "http://repo.maven.apache.org/maven2/org/apache/servicemix/bundles/org.apache.servicemix.bundles.aws-java-sdk/", + "acknowledgements": [ "Apache ServiceMix :: Bundles :: aws-java-sdk Copyright 2005-2014 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/)." ], - "key" : "ASL2.0" - } - ,{ - "name" : "Apache ServiceMix :: Bundles :: ehcache", - "version" : "2.6.9_1", - "owner" : "The Apache Software Foundation", - "homepage" : "http://repo.maven.apache.org/maven2/org/apache/servicemix/bundles/org.apache.servicemix.bundles.ehcache/", - "acknowledgements" : [ + "key": "ASL2.0" + }, + { + "name": "Apache ServiceMix :: Bundles :: ehcache", + "version": "2.6.9_1", + "owner": "The Apache Software Foundation", + "homepage": "http://repo.maven.apache.org/maven2/org/apache/servicemix/bundles/org.apache.servicemix.bundles.ehcache/", + "acknowledgements": [ "Apache ServiceMix :: Bundles :: ehcache Copyright 2005-2014 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/)." ], - "key" : "ASL2.0" - } - ,{ - "name" : "Apache ServiceMix :: Bundles :: scribe", - "version" : "1.3.3_1", - "owner" : "The Apache Software Foundation", - "homepage" : "http://servicemix.apache.org/bundles-pom/org.apache.servicemix.bundles.scribe/", - "acknowledgements" : [ + "key": "ASL2.0" + }, + { + "name": "Apache ServiceMix :: Bundles :: scribe", + "version": "1.3.3_1", + "owner": "The Apache Software Foundation", + "homepage": "http://servicemix.apache.org/bundles-pom/org.apache.servicemix.bundles.scribe/", + "acknowledgements": [ "Apache ServiceMix :: Bundles :: scribe Copyright 2005-2013 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/)." ], - "key" : "ASL2.0" - } - ,{ - "name" : "Apache ServiceMix :: Bundles :: zxing", - "version" : "3.1.0_1", - "owner" : "The Apache Software Foundation", - "homepage" : "http://repo.maven.apache.org/maven2//org/apache/servicemix/bundles/org.apache.servicemix.bundles.zxing/", - "acknowledgements" : [ + "key": "ASL2.0" + }, + { + "name": "Apache ServiceMix :: Bundles :: zxing", + "version": "3.1.0_1", + "owner": "The Apache Software Foundation", + "homepage": "http://repo.maven.apache.org/maven2//org/apache/servicemix/bundles/org.apache.servicemix.bundles.zxing/", + "acknowledgements": [ "Apache ServiceMix :: Bundles :: zxing Copyright 2005-2014 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/)." ], - "key" : "ASL2.0" - } - ,{ - "name" : "Apache Shiro", - "version" : "1.2.2", - "owner" : "The Apache Software Foundation", - "homepage" : "http://shiro.apache.org/", - "acknowledgements" : [ + "key": "ASL2.0" + }, + { + "name": "Apache Shiro", + "version": "1.2.2", + "owner": "The Apache Software Foundation", + "homepage": "http://shiro.apache.org/", + "acknowledgements": [ "Copyright 2008-2012 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). The implementation for org.apache.shiro.util.SoftHashMap is based on initial ideas from Dr. Heinz Kabutz's publicly posted version available at http://www.javaspecialists.eu/archive/Issue015.html, with continued modifications. Certain parts (StringUtils etc.) of the source code for this product was copied for simplicity and to reduce dependencies from the source code developed by the Spring Framework Project (http://www.springframework.org)." ], - "key" : "ASL2.0" - } - ,{ - "name" : "Apache XMLBeans", - "version" : "2.4.0", - "owner" : "The Apache Software Foundation", - "homepage" : "http://xmlbeans.apache.org/", - "acknowledgements" : [ - "NOTICE file corresponding to section 4(d) of the Apache License, == == Version 2.0, in this case for the Apache XmlBeans distribution. == ========================================================================= This product includes software developed by The Apache Software Foundation (http://www.apache.org/). Portions of this software were originally based on the following: - software copyright (c) 2000-2003, BEA Systems, . Aside from contributions to the Apache XMLBeans project, this software also includes: - one or more source files from the Apache Xerces-J and Apache Axis products, Copyright (c) 1999-2003 Apache Software Foundation - W3C XML Schema documents Copyright 2001-2003 (c) World Wide Web Consortium (Massachusetts Institute of Technology, European Research Consortium for Informatics and Mathematics, Keio University) - resolver.jar from Apache Xml Commons project, Copyright (c) 2001-2003 Apache Software Foundation - Piccolo XML Parser for Java from http://piccolo.sourceforge.net/, Copyright 2002 Yuval Oren under the terms of the Apache Software License 2.0 - JSR-173 Streaming API for XML from http://sourceforge.net/projects/xmlpullparser/, Copyright 2005 BEA under the terms of the Apache Software License 2.0" + "key": "ASL2.0" + }, + { + "name": "Apache Shiro", + "version": "1.2.3", + "owner": "The Apache Software Foundation", + "homepage": "http://shiro.apache.org/", + "acknowledgements": [ + "Copyright 2008-2012 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/).", + "The implementation for org.apache.shiro.util.SoftHashMap is based on initial ideas from Dr. Heinz Kabutz's publicly posted version available at http://www.javaspecialists.eu/archive/Issue015.html, with continued modifications.", + "Certain parts (StringUtils etc.) of the source code for this product was copied for simplicity and to reduce dependencies from the source code developed by the Spring Framework Project (http://www.springframework.org)." ], - "key" : "ASL2.0" - } - ,{ - "name" : "DOM4J - Flexible XML Framework for Java", - "version" : "1.6.1", - "owner" : "MetaStuff, Ltd.", - "homepage" : "http://dom4j.sourceforge.net/", - "acknowledgements" : [ + "key": "ASL2.0" + }, + { + "name": "Apache XMLBeans", + "version": "2.4.0", + "owner": "The Apache Software Foundation", + "homepage": "http://xmlbeans.apache.org/", + "acknowledgements": [ + "NOTICE file corresponding to section 4(d) of the Apache License, == == Version 2.0, in this case for the Apache XmlBeans distribution. == ", + "=========================================================================", + "This product includes software developed by The Apache Software Foundation (http://www.apache.org/). ", + "Portions of this software were originally based on the following: ", + " - software copyright (c) 2000-2003, BEA Systems, . ", + "Aside from contributions to the Apache XMLBeans project, this software also includes: ", + " - one or more source files from the Apache Xerces-J and Apache Axis products, Copyright (c) 1999-2003 Apache Software Foundation ", + " - W3C XML Schema documents Copyright 2001-2003 (c) World Wide Web Consortium (Massachusetts Institute of Technology, European Research Consortium for Informatics and Mathematics, Keio University)", + " - resolver.jar from Apache Xml Commons project, Copyright (c) 2001-2003 Apache Software Foundation ", + " - Piccolo XML Parser for Java from http://piccolo.sourceforge.net/, Copyright 2002 Yuval Oren under the terms of the Apache Software License 2.0 ", + " - JSR-173 Streaming API for XML from http://sourceforge.net/projects/xmlpullparser/, Copyright 2005 BEA under the terms of the Apache Software License 2.0" + ], + "key": "ASL2.0" + }, + { + "name": "DOM4J - Flexible XML Framework for Java", + "version": "1.6.1", + "owner": "MetaStuff, Ltd.", + "homepage": "http://dom4j.sourceforge.net/", + "acknowledgements": [ "BSD 3-clause \"New\" or \"Revised\" License" ], - "key" : "ASL2.0" - } - ,{ - "name" : "GWT Highcharts", - "version" : "1.6.0", - "owner" : "Moxie Group", - "homepage" : "http://www.moxiegroup.com/moxieapps/gwt-highcharts/", - "acknowledgements" : [ + "key": "ASL2.0" + }, + { + "name": "google-web-toolkit ", + "version": "2.7.0", + "owner": "Google, Inc.", + "homepage": "http://www.moxiegroup.com/moxieapps/gwt-highcharts/", + "acknowledgements": [ + "Google Web Toolkit 2.7.0 (git revision a6da588) Copyright (c) Google, Inc. 2009. All rights reserved. Visit Google Code (http://code.google.com/webtoolkit/).", + "This product includes software developed by:", + "- The Apache Software Foundation (http://www.apache.org/).", + " - Tomcat (http://tomcat.apache.org/) with modifications", + " - Tapestry (http://tapestry.apache.org/)", + "- The Eclipse Foundation (http://www.eclipse.org/).", + " - Java Development Tools (http://www.eclipse.org/jdt/)", + " - Standard Widget Toolkit (http://www.eclipse.org/swt/) with modifications", + "- Mort Bay Consulting (http://www.mortbay.com/)", + " - Jetty 6.1.11 (http://mortbay.org/jetty/)", + "- The Mozilla Foundation (http://www.mozilla.org/).", + " - Mozilla 1.7.12 (http://www.mozilla.org/releases/mozilla1.7.12/)", + " - Rhino (http://www.mozilla.org/rhino/) with modifications", + "- ObjectWeb (http://www.objectweb.org/)", + "- ASM (http://asm.objectweb.org/) with modifications", + "- The OpenQA Project (http://openqa.org/)", + "- Selenium-RC (http://selenium-rc.openqa.org/)", + "- The Protobuf Project (http://code.google.com/p/protobuf/) with modifications", + "For source availability and license information see COPYING.", + "=====", + "", + "GOOGLE WEB TOOLKIT LICENSE INFORMATION", + "", + "March 3, 2008", + "", + "The Google Web Toolkit software and sample code developed by Google is", + "licensed under the Apache License, v. 2.0. Other software included in this", + "distribution is provided under other licenses, as listed in the Included", + "Software and Licenses section at the bottom of this page. Source code for", + "software included in this distribution is available from the Google Web", + "Toolkit project or as otherwise indicated at the bottom of this page.", + "", + "Please note that the executable version of the Google Web Toolkit", + "distributed by Google will communicate with Google's servers to check for", + "available updates. If updates are available, you will receive the option to", + "install them.", + "", + "===", + "", + "LICENSE INFORMATION REGARDING BUNDLED THIRD-PARTY SOFTWARE", + "", + "The following third party software is distributed with Google Web", + "Toolkit and is provided under other licenses and/or has source", + "available from other locations. Where \"gwt-dev.jar\" is listed,", + "substitute in the name of the jar corresponding to your platform,", + "e.g. \"gwt-dev-linux.jar\".", + "", + "* Apache Tomcat", + "License: Apache License v. 2.0 (above)", + "Source code availability: http://tomcat.apache.org", + "modifications are at org/apache/tomcat/ within gwt-dev.jar", + "", + "* Apache Tapestry", + "License: Apache License v. 2.0 (above)", + "Source code availability: http://tapestry.apache.org", + "", + "* ASM 3.1", + "License: (custom)", + "http://asm.objectweb.org/license.html", + "Source code availability: com/google/gwt/dev/asm/ within gwt-dev.jar", + "", + "* Eclipse Java Development Tools (JDT)", + "License: Eclipse Public License v. 1.0", + "http://www.eclipse.org/legal/epl-v10.html", + "Source code availability:", + "http://archive.eclipse.org/eclipse/downloads/drops/R-3.3.1-200709211145/download.php?dropFile=eclipse-JDT-SDK-3.3.1.zip", + "", + "* Eclipse Standard Widget Toolkit (SWT)", + "License: Eclipse Public License v. 1.0", + "http://www.eclipse.org/legal/epl-v10.html", + "Source code availability:", + "Linux: http://download.eclipse.org/eclipse/downloads/drops/R-3.2.1-200609210945/download.php?dropFile=swt-3.2.1-gtk-linux-x86.zip", + "Windows: http://download.eclipse.org/eclipse/downloads/drops/R-3.2.1-200609210945/download.php?dropFile=swt-3.2.1-win32-win32-x86.zip", + "Mac: http://download.eclipse.org/eclipse/downloads/drops/R-3.2.1-200609210945/download.php?dropFile=swt-3.2.1-carbon-macosx.zip", + "modifications are at org/eclipse/swt/ within gwt-dev.jar", + "", + "* Jetty", + "License: Apache License v. 2.0 (above)", + "Source code availability:", + "http://mortbay.org/jetty/", + "", + "* Mozilla Rhino", + "License: Mozilla Public License v. 1.1", + "http://www.mozilla.org/MPL/MPL-1.1.txt", + "Source code availability: com/google/gwt/dev/js/rhino/ within gwt-dev.jar", + "", + "* Mozilla 1.7.12 (Linux only)", + "License: Mozilla Public License v. 1.1", + "http://www.mozilla.org/MPL/MPL-1.1.txt", + "Source code availability:", + "http://developer.mozilla.org/en/docs/Download_Mozilla_Source_Code", + "", + "* Protobuf", + "License: New BSD License", + "http://www.opensource.org/licenses/bsd-license.php", + "Source code availablility:", + "http://code.google.com/p/protobuf/source/checkout", + "Binary modifications consist of package-rebasing. The rebased classes are rooted at com/google/gwt/dev/protobuf/ within gwt-dev.jar" + ], + "key": "ASL2.0" + }, + { + "name": "GWT Highcharts", + "version": "1.6.0", + "owner": "Moxie Group", + "homepage": "http://www.moxiegroup.com/moxieapps/gwt-highcharts/", + "acknowledgements": [ "Copyright 2011 Moxie Group" ], - "key" : "ASL2.0" - } - ,{ - "name" : "Hyperic SIGAR", - "version" : "1.6.4", - "owner" : "The Hyperic team", - "homepage" : "http://sourceforge.net/projects/sigar/", - "acknowledgements" : [ - "Hyperic SIGAR includes some third-party open source components in its distribution. The list below identifies the community or organization and links to their appropriate license terms. The Hyperic team would like to thank all the communities of the projects listed below for their contributions." - ,"---------------------------------------------------------------------" - ,"The following components are included without modification: " - ," - log4j - Information: http://logging.apache.org/ License: http://www.apache.org/licenses/LICENSE-2.0" - ,"The following components are included with modification:" - ," - cpptasks - Information: http://ant-contrib.sourceforge.net/ License: http://ant-contrib.sourceforge.net/LICENSE.txt" - ," - (portions of) APR - Information: http://apr.apache.org/ License: http://www.apache.org/licenses/LICENSE-2.0" - ," - solaris get_mib2 - Information: ftp://vic.cc.purdue.edu/pub/tools/unix/solaris/get_mib2/ License: within src/os/solaris/get_mib2.[ch] " - ," - getline by Chris Thewalt - Information: http://tinyurl.com/r438r License: within src/sigar_getline.c " - ," - PrintfFormat.java - Information: http://java.sun.com/developer/technicalArticles/Programming/sprintf/PrintfFormat.java License: within bindings/java/src/org/hyperic/sigar/util/PrintfFormat.java" + "key": "ASL2.0" + }, + { + "name": "GWT-Bootstrap", + "version": "2.3.2.0", + "owner": "GWT-Bootstrap", + "homepage": "http://gwtbootstrap.github.com/", + "acknowledgements": [ + "Copyright ${year} GWT-Bootstrap" ], - "key" : "ASL2.0" - } - ,{ - "name" : "Jackson JSON Mapper ASL", - "version" : "1.9.13", - "owner" : "The Apache Software Foundation", - "homepage" : "http://wiki.fasterxml.com/JacksonHome", - "acknowledgements" : [ + "key": "ASL2.0" + }, + { + "name": "gwt-google-apis", + "version": "ajaxloader-svn", + "owner": "Google, Inc.", + "homepage": "https://github.com/googlearchive/gwt-google-apis", + "acknowledgements": [ + "AjaxLoader API Library for GWT @GWT_VERSION@ (c) Copyright Google, Inc. 2008. All rights reserved. Visit Google Code (http://code.google.com/p/gwt-google-apis)." + ], + "key": "ASL2.0" + }, + { + "name": "GWT-Maps-V3-Api", + "version": "3.9.0-build-17", + "owner": "GWT Maps API V3", + "homepage": "http://github.com/branflake2267/GWT-Maps-V3-Api/", + "acknowledgements": [ + "Copyright (C) 2011 - 2012 GWT Maps API V3" + ], + "key": "ASL2.0" + }, + { + "name": "gwtoauthlogindemo ", + "version": "1.71-svn", + "owner": "Muhammad Muquit", + "homepage": "http://code.google.com/p/gwtoauthlogindemo/", + "acknowledgements": [ + "Copyright (C) 2013-2014 Muhammad Muquit (http://www.muquit.com/)" + ], + "key": "ASL2.0" + }, + { + "name": "Hyperic SIGAR", + "version": "1.6.4", + "owner": "The Hyperic team", + "homepage": "http://sourceforge.net/projects/sigar/", + "acknowledgements": [ + "Hyperic SIGAR includes some third-party open source components in its distribution. The list below identifies the community or organization and links to their appropriate license terms. The Hyperic team would like to thank all the communities of the projects listed below for their contributions.", + "---------------------------------------------------------------------", + "The following components are included without modification: ", + " - log4j - Information: http://logging.apache.org/ License: http://www.apache.org/licenses/LICENSE-2.0", + "The following components are included with modification:", + " - cpptasks - Information: http://ant-contrib.sourceforge.net/ License: http://ant-contrib.sourceforge.net/LICENSE.txt", + " - (portions of) APR - Information: http://apr.apache.org/ License: http://www.apache.org/licenses/LICENSE-2.0", + " - solaris get_mib2 - Information: ftp://vic.cc.purdue.edu/pub/tools/unix/solaris/get_mib2/ License: within src/os/solaris/get_mib2.[ch] ", + " - getline by Chris Thewalt - Information: http://tinyurl.com/r438r License: within src/sigar_getline.c ", + " - PrintfFormat.java - Information: http://java.sun.com/developer/technicalArticles/Programming/sprintf/PrintfFormat.java License: within bindings/java/src/org/hyperic/sigar/util/PrintfFormat.java" + ], + "key": "ASL2.0" + }, + { + "name": "Jackson JSON Mapper ASL", + "version": "1.9.13", + "owner": "The Apache Software Foundation", + "homepage": "http://wiki.fasterxml.com/JacksonHome", + "acknowledgements": [ "This product currently only contains code developed by authors of specific components, as identified by the source code files; if such notes are missing files have been created by Tatu Saloranta. For additional credits (generally to people who reported problems) see CREDITS file." ], - "key" : "ASL2.0" - } - ,{ - "name" : "Jackson-annotations", - "version" : "2.5.0", - "owner" : "FasterXML, LLC", - "homepage" : "https://github.com/FasterXML/jackson-annotations", - "acknowledgements" : [ + "key": "ASL2.0" + }, + { + "name": "Jackson", + "version": "1.9.13", + "owner": "Tatu Saloranta", + "homepage": "http://wiki.fasterxml.com/JacksonHome", + "acknowledgements": [ + "" ], - "key" : "ASL2.0" - } - ,{ - "name" : "jackson-databind", - "version" : "2.5.0", - "owner" : "Tatu Saloranta", - "homepage" : "http://github.com/FasterXML/jackson-databind/", - "acknowledgements" : [ + "key": "ASL2.0" + }, + { + "name": "Jackson - High-performance JSON processor (SAP)", + "version": "1.9.13", + "owner": "Tatu Saloranta", + "homepage": "https://github.com/FasterXML/jackson", + "acknowledgements": [ + "This product currently only contains code developed by authors of specific components, as identified by the source code files; if such notes are missing files have been created by Tatu Saloranta.", + "For additional credits (generally to people who reported problems) see CREDITS file." + ], + "key": "ASL2.0" + }, + { + "name": "Jackson JSON Mapper ASL", + "version": "1.9.13", + "owner": "The Apache Software Foundation", + "homepage": "http://wiki.fasterxml.com/JacksonHome", + "acknowledgements": [ + "This product currently only contains code developed by authors of specific components, as identified by the source code files; if such notes are missing files have been created by Tatu Saloranta. For additional credits (generally to people who reported problems) see CREDITS file." + ], + "key": "ASL2.0" + }, + { + "name": "Jackson-annotations", + "version": "2.5.0", + "owner": "FasterXML, LLC", + "homepage": "https://github.com/FasterXML/jackson-annotations", + "acknowledgements": [ + ], + "key": "ASL2.0" + }, + { + "name": "jackson-databind", + "version": "2.5.0", + "owner": "Tatu Saloranta", + "homepage": "http://github.com/FasterXML/jackson-databind/", + "acknowledgements": [ "Jackson JSON processor Jackson is a high-performance, Free/Open Source JSON processing library. It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has been in development since 2007. It is currently developed by a community of developers, as well as supported commercially by FasterXML.com. ## Licensing Jackson core and extension components may be licensed under different licenses. To find the details that apply to this artifact see the accompanying LICENSE file. For more information, including possible other licensing options, contact FasterXML.com (http://fasterxml.com). ## Credits A list of contributors may be found from CREDITS file, which is included in some artifacts (usually source distributions); but is always available from the source code management (SCM) system " ], - "key" : "ASL2.0" - } - ,{ - "name" : "Jackson-JAXRS-base", - "version" : "2.5.0", - "owner" : "FasterXML, LLC", - "homepage" : "http://repo.maven.apache.org/maven2/com/fasterxml/jackson/jaxrs/jackson-jaxrs-base/", - "acknowledgements" : [ - "" + "key": "ASL2.0" + }, + { + "name": "Jackson-JAXRS-base", + "version": "2.5.0", + "owner": "FasterXML, LLC", + "homepage": "http://repo.maven.apache.org/maven2/com/fasterxml/jackson/jaxrs/jackson-jaxrs-base/", + "acknowledgements": [ + ], - "key" : "ASL2.0" - } - ,{ - "name" : "jackson-jaxrs-providers", - "version" : "2.5.0", - "owner" : "FasterXML, LLC", - "homepage" : "http://github.com/FasterXML/jackson-jaxrs-providers/", - "acknowledgements" : [ - "# Jackson JSON processor Jackson is a high-performance, Free/Open Source JSON processing library. It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has been in development since 2007. It is currently developed by a community of developers, as well as supported commercially by FasterXML.com. " - ,"## Licensing Jackson core and extension components may be licensed under different licenses. To find the details that apply to this artifact see the accompanying LICENSE file. For more information, including possible other licensing options, contact FasterXML.com (http://fasterxml.com)." - ,"## Credits A list of contributors may be found from CREDITS file, which is included in some artifacts (usually source distributions); but is always available from the source code management (SCM) system project uses." + "key": "ASL2.0" + }, + { + "name": "jackson-jaxrs-providers", + "version": "2.5.0", + "owner": "FasterXML, LLC", + "homepage": "http://github.com/FasterXML/jackson-jaxrs-providers/", + "acknowledgements": [ + "# Jackson JSON processor Jackson is a high-performance, Free/Open Source JSON processing library. It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has been in development since 2007. It is currently developed by a community of developers, as well as supported commercially by FasterXML.com. ", + "## Licensing Jackson core and extension components may be licensed under different licenses. To find the details that apply to this artifact see the accompanying LICENSE file. For more information, including possible other licensing options, contact FasterXML.com (http://fasterxml.com).", + "## Credits A list of contributors may be found from CREDITS file, which is included in some artifacts (usually source distributions); but is always available from the source code management (SCM) system project uses." ], - "key" : "ASL2.0" - } - ,{ - "name" : "Java Servlet API", - "version" : "2.5.0", - "owner" : "Sun Microsystems, Inc.", - "homepage" : "http://ebr.springsource.com/repository/app/bundle/version/detail?name=com.springsource.javax.servlet&version=2.5.0", - "acknowledgements" : [ + "key": "ASL2.0" + }, + { + "name": "Java Servlet API", + "version": "2.5.0", + "owner": "Sun Microsystems, Inc.", + "homepage": "http://ebr.springsource.com/repository/app/bundle/version/detail?name=com.springsource.javax.servlet&version=2.5.0", + "acknowledgements": [ "Copyright 2005 Sun Microsystems, Inc. All rights reserved." ], - "key" : "CDDL1.0" - } - ,{ - "name" : "JavaMail", - "version" : "1.4.5", - "owner" : "Sun Microsystems, Inc.", - "homepage" : "http://www.oracle.com/technetwork/java/javamail/index-138643.html", - "acknowledgements" : [ + "key": "CDDL1.0" + }, + { + "name": "java-diff-utils", + "version": "1.2.1", + "owner": "Dmitry Naumenko", + "homepage": "http://code.google.com/p/java-diff-utils/", + "acknowledgements": [ + "Copyright 2010 Dmitry Naumenko (dm.naumenko@gmail.com)" + ], + "key": "ASL2.0" + }, + { + "name": "JavaMail", + "version": "1.4.5", + "owner": "Sun Microsystems, Inc.", + "homepage": "http://www.oracle.com/technetwork/java/javamail/index-138643.html", + "acknowledgements": [ "" ], - "key" : "CDDL1.1" - } - ,{ - "name" : "Jettison", - "version" : "1.3.7", - "owner" : "Envoi Solutions LLC", - "homepage" : "http://jettison.codehaus.org/", - "acknowledgements" : [ - "Copyright 2006 Envoi Solutions LLC" + "key": "CDDL1.1" + }, + { + "name": "JDOM ", + "version": "1.1", + "owner": "Jason Hunter & Brett McLaughlin", + "homepage": "http://www.jdom.org", + "acknowledgements": [ + "Copyright (C) 2000-2004 Jason Hunter & Brett McLaughlin. All rights reserved." ], - "key" : "ASL2.0" - } - ,{ - "name" : "JSR-311 - JAX-RS - The Java API for RESTful Web Services (Jersey)", - "version" : "1.17", - "owner" : "Oracle and/or its affiliates", - "homepage" : "Apache License 2.0", - "acknowledgements" : [ + "key": "JDOML" + }, + { + "name": "jersey-1.x", + "version": "1.17", + "owner": "Oracle and/or its affiliates", + "homepage": "http://github.com/jersey/jersey-1.x/", + "acknowledgements": [ "Copyright (c) 2010-2011 Oracle and/or its affiliates. All rights reserved." ], - "key" : "CDDL1.1" - } - ,{ - "name" : "MongoDB Java Driver - org.mongodb:mongo-java-driver", - "version" : "2.13.0", - "owner" : "10gen, Inc.", - "homepage" : "http://docs.mongodb.org/ecosystem/drivers/java/", - "acknowledgements" : [ + "key": "CDDL1.1" + }, + { + "name": "Jettison", + "version": "1.3.7", + "owner": "Envoi Solutions LLC", + "homepage": "http://jettison.codehaus.org/", + "acknowledgements": [ + "Copyright 2006 Envoi Solutions LLC" + ], + "key": "ASL2.0" + }, + { + "name": "JQuery", + "version": "1.10.1", + "owner": "jQuery Foundation and other contributors", + "homepage": "http://jquery.com/", + "acknowledgements": [ + "Copyright 2014 jQuery Foundation and other contributors" + ], + "key": "MITL" + }, + { + "name": "JQuery", + "version": "1.5.2", + "owner": "John Resig", + "homepage": "http://jquery.com/", + "acknowledgements": [ + "Copyright 2011, John Resig" + ], + "key": "MITL" + }, + { + "name": "JQuery", + "version": "1.7.1", + "owner": "John Resig", + "homepage": "http://code.jquery.com/", + "acknowledgements": [ + "Copyright 2011, John Resig" + ], + "key": "MITL" + }, + { + "name": "JQuery", + "version": "1.5.1", + "owner": "John Resig", + "homepage": "http://github.com/jquery/jquery/", + "acknowledgements": [ + "Copyright 2011, John Resig" + ], + "key": "MITL" + }, + { + "name": "json-simple", + "version": "1.1", + "owner": "Yidong Fang, Chris Nokleberg", + "homepage": "http://code.google.com/p/json-simple/", + "acknowledgements": [ + + ], + "key": "ASL2.0" + }, + { + "name": "JSR-311 - JAX-RS - The Java API for RESTful Web Services (Jersey)", + "version": "1.17", + "owner": "Oracle and/or its affiliates", + "homepage": "http://jersey.java.net/", + "acknowledgements": [ + "Copyright (c) 2010-2011 Oracle and/or its affiliates. All rights reserved." + ], + "key": "CDDL1.1" + }, + { + "name": "lz4-java", + "version": "1.3.0", + "owner": "Yann Collet", + "homepage": "http://github.com/jpountz/lz4-java/", + "acknowledgements": [ + "LZ4 Library Copyright (c) 2011-2014, Yann Collet All rights reserved." + ], + "key": "ASL2.0" + }, + { + "name": "mgwt", + "version": "2.0.0", + "owner": "Daniel Kurka", + "homepage": "http://www.m-gwt.com/", + "acknowledgements": [ + "Copyright 2010 Daniel Kurka" + ], + "key": "ASL2.0" + }, + { + "name": "MongoDB Java Driver - org.mongodb:mongo-java-driver", + "version": "2.13.0", + "owner": "10gen, Inc.", + "homepage": "http://docs.mongodb.org/ecosystem/drivers/java/", + "acknowledgements": [ "Copyright (C) 2008-2013 10gen, Inc." ], - "key" : "ASL2.0" - } - ,{ - "name" : "Pull API for parsing MIME messages - MIMEpull", - "version" : "1.9.4", - "owner" : "Oracle and/or its affiliates", - "homepage" : "http://mimepull.java.net/", - "acknowledgements" : [ + "key": "ASL2.0" + }, + { + "name": "MongoDB Java Driver - org.mongodb:mongo-java-driver", + "version": "2.13.2", + "owner": "MongoDB, Inc", + "homepage": "http://repo.maven.apache.org/maven2//org/mongodb/mongo-java-driver/", + "acknowledgements": [ + "Copyright (C) 2008-2013 10gen, Inc." + ], + "key": "ASL2.0" + }, + { + "name": "Pull API for parsing MIME messages - MIMEpull", + "version": "1.9.4", + "owner": "Oracle and/or its affiliates", + "homepage": "http://mimepull.java.net/", + "acknowledgements": [ "Copyright (c) 1997-2013 Oracle and/or its affiliates. All rights reserved." ], - "key" : "CDDL1.1" - } - ,{ - "name" : "rabbitmq-java-client", - "version" : "2_8_4", - "owner" : "VMware, Inc.", - "homepage" : "http://github.com/rabbitmq/rabbitmq-java-client/", - "acknowledgements" : [ + "key": "CDDL1.1" + }, + { + "name": "qrcodejs", + "version": "master-04f46c6a07", + "owner": "davidshimjs", + "homepage": "http://github.com/davidshimjs/qrcodejs/", + "acknowledgements": [ + "Copyright 2010 Daniel Kurka" + ], + "key": "MITL" + }, + { + "name": "rabbitmq-java-client", + "version": "2_8_4", + "owner": "VMware, Inc.", + "homepage": "http://github.com/rabbitmq/rabbitmq-java-client/", + "acknowledgements": [ "Copyright (c) 2007-2012 VMware, Inc. All rights reserved." ], - "key" : "ASL2.0" - } - ,{ - "name" : "routeConverter", - "version" : "2.12.2", - "owner" : "Christian Pesch", - "homepage" : "", - "acknowledgements" : [ - "RouteConverter is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version." - ,"RouteConverter is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details." + "key": "ASL2.0" + }, + { + "name": "routeConverter", + "version": "2.12.2", + "owner": "Christian Pesch", + "homepage": "", + "acknowledgements": [ + "RouteConverter is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.", + "RouteConverter is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details." ], - "key" : "GPL2.0" - } - ,{ - "name" : "Simple Logging Facade for Java (SLF4J)", - "version" : "1.6.4", - "owner" : "QOS.ch", - "homepage" : "http://www.slf4j.org/", - "acknowledgements" : [ + "key": "ASL2.0" + }, + { + "name": "Simple Logging Facade for Java (SLF4J)", + "version": "1.6.4", + "owner": "QOS.ch", + "homepage": "http://www.slf4j.org/", + "acknowledgements": [ "Copyright (c) 2004-2013 QOS.ch" ], - "key" : "MITL" + "key": "MITL" + }, + { + "name": "slick-carousel", + "version": "1.5.8", + "owner": "Ken Wheeler", + "homepage": "http://github.com/kenwheeler/slick/", + "acknowledgements": [ + "Copyright (c) 2004-2013 QOS.ch" + ], + "key": "MITL" + }, + { + "name": "video-js", + "version": "4.12.10", + "owner": "Brightcove, Inc.", + "homepage": "https://github.com/videojs/video.js", + "acknowledgements": [ + "Copyright 2013 Brightcove, Inc." + ], + "key": "ASL2.0" + }, + { + "name": "video-js-vimeo", + "version": "master-20140814", + "owner": "Benoit Tremblay", + "homepage": "http://github.com/eXon/videojs-vimeo/", + "acknowledgements": [ + "Copyright (c) 2015 Benoit Tremblay " + ], + "key": "MITL" + }, + { + "name": "video-js-youtube", + "version": "1.2.5", + "owner": "Benoit Tremblay", + "homepage": "http://github.com/eXon/videojs-youtube/", + "acknowledgements": [ + "Copyright (c) 2015 Benoit Tremblay " + ], + "key": "MITL" } ], - "licenses" : - [ - { - "key" : "ASL2.0", - "file" : "asl2.0.txt" - } - ,{ - "key" : "CDDL1.0", - "file" : "cddl1.0.txt" - } - ,{ - "key" : "CDDL1.1", - "file" : "cddl1.1.txt" - } - ,{ - "key" : "MITL", - "file" : "mitl.txt" - } - ,{ - "key" : "GPL2.0", - "file" : "gpl2.0.txt" - } - ] + "licenses": [ + { + "key": "ASL2.0", + "file": "asl2.0.txt" + }, + { + "key": "CDDL1.0", + "file": "cddl1.0.txt" + }, + { + "key": "CDDL1.1", + "file": "cddl1.1.txt" + }, + { + "key": "MITL", + "file": "mitl.txt" + }, + { + "key": "JDOML", + "file": "jdoml.txt" + } + ] } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/licenses/gpl2.0.txt b/java/com.sap.sailing.gwt.ui/licenses/gpl2.0.txt deleted file mode 100644 index 63dbca075ed..00000000000 --- a/java/com.sap.sailing.gwt.ui/licenses/gpl2.0.txt +++ /dev/null @@ -1,86 +0,0 @@ -GNU GENERAL PUBLIC LICENSE - -Version 2, June 1991 - -Copyright (C) 1989, 1991 Free Software Foundation, Inc. -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - -Everyone is permitted to copy and distribute verbatim copies -of this license document, but changing it is not allowed. -Preamble - -The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. - -When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. - -To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. - -For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. - -We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. - -Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. - -Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. - -The precise terms and conditions for copying, distribution and modification follow. - -TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - -0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. - -1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. - -You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. - -2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: - -a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. -b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. -c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) -These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. - -3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: - -a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, -b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, -c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) -The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. - -If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. - -4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. - -5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. - -6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. - -7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. - -This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. - -8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. - -9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. - -10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - -NO WARRANTY - -11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - -12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/licenses/jdoml.txt b/java/com.sap.sailing.gwt.ui/licenses/jdoml.txt new file mode 100644 index 00000000000..ab9d564c5c7 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/licenses/jdoml.txt @@ -0,0 +1,17 @@ +Jdom License +Copyright (C) 2000-2004 Jason Hunter & Brett McLaughlin. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the disclaimer that follows these conditions in the documentation and/or other materials provided with the distribution. +3. The name "JDOM" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact {request_AT_jdom_DOT_org}. +4. Products derived from this software may not be called "JDOM", nor may "JDOM" appear in their name, without prior written permission from the JDOM Project Management {request_AT_jdom_DOT_org}. + +In addition, we request (but do not require) that you include in the end-user documentation provided with the redistribution and/or in the software itself an acknowledgement equivalent to the following: +      "This product includes software developed by the JDOM Project (http://www.jdom.org/)." + +Alternatively, the acknowledgment may be graphical using the logos available at http://www.jdom.org/images/logos. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/imprint/ImprintViewImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/imprint/ImprintViewImpl.java index 8c1c5a545f0..3c695419349 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/imprint/ImprintViewImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/imprint/ImprintViewImpl.java @@ -50,7 +50,7 @@ public class ImprintViewImpl extends Composite implements ImprintView { if (c == null) { return "--"; } else { - return c.getName(); + return c.getName() + ", v." + c.getVersion(); } } @@ -59,7 +59,7 @@ public class ImprintViewImpl extends Composite implements ImprintView { if (c == null) { appendable.append("--"); } else { - appendable.append(c.getName()); + appendable.append(c.getName() + ", v." + c.getVersion()); } } }); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaWithSeriesAndFleetsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaWithSeriesAndFleetsDialog.java index 07a068228fc..d045599d0d6 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaWithSeriesAndFleetsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaWithSeriesAndFleetsDialog.java @@ -51,7 +51,7 @@ public abstract class AbstractRegattaWithSeriesAndFleetsDialog extends DataEn protected final ListBox courseAreaListBox; protected final ListBox sailingEventsListBox; protected final CheckBox useStartTimeInferenceCheckBox; - private final ListEditorComposite seriesEditor; + protected final ListEditorComposite seriesEditor; private final ListBox rankingMetricListBox; protected final List existingEvents; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CreateDefaultLeaderboardGroupDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CreateDefaultLeaderboardGroupDialog.java new file mode 100644 index 00000000000..8dbc484a9a0 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CreateDefaultLeaderboardGroupDialog.java @@ -0,0 +1,19 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.dialog.DataEntryDialog; + +public class CreateDefaultLeaderboardGroupDialog extends DataEntryDialog { + public CreateDefaultLeaderboardGroupDialog(SailingServiceAsync sailingService, StringMessages stringMessages, + ErrorReporter errorReporter, DialogCallback dialogCallBack) { + super(stringMessages.createDefaultLeaderboardGroup(), /* message */ stringMessages.createDefaultLeaderboardGroup(), + stringMessages.yes(), stringMessages.no(), /* validator */ null, dialogCallBack); + } + + @Override + protected Void getResult() { + return null; + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CreateDefaultRegattaLeaderboardDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CreateDefaultRegattaLeaderboardDialog.java index adc27848469..3a2db03de01 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CreateDefaultRegattaLeaderboardDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CreateDefaultRegattaLeaderboardDialog.java @@ -8,7 +8,7 @@ import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.dialog.DataEntryDialog; -public class CreateDefaultRegattaLeaderboardDialog extends DataEntryDialog{ +public class CreateDefaultRegattaLeaderboardDialog extends DataEntryDialog { private RegattaDTO regatta; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventCreateDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventCreateDialog.java index 780a27a9f81..66833ca584b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventCreateDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventCreateDialog.java @@ -39,5 +39,7 @@ public class EventCreateDialog extends EventDialog { isPublicCheckBox.setValue(false); imagesListComposite.fillImages(Collections.emptyList()); videosListComposite.fillVideos(Collections.emptyList()); + // add default course area + courseAreaNameList.setValue(Collections.singletonList("Default")); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java index 5c548c58620..fedf21d03f1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java @@ -9,6 +9,8 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; @@ -230,7 +232,6 @@ public abstract class EventDialog extends DataEntryDialogWithBootstrap @Override public void show() { super.show(); - nameEntryField.setFocus(true); + Scheduler.get().scheduleFinally(new ScheduledCommand() { @Override public void execute() { nameEntryField.setFocus(true); }}); } - } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventListComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventListComposite.java index 70012a52657..1122203b6fd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventListComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventListComposite.java @@ -32,6 +32,7 @@ import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.view.client.ListDataProvider; import com.google.gwt.view.client.SelectionChangeEvent; +import com.sap.sailing.gwt.ui.adminconsole.LeaderboardGroupDialog.LeaderboardGroupDescriptor; import com.sap.sailing.gwt.ui.client.EntryPointLinkFactory; import com.sap.sailing.gwt.ui.client.EventsRefresher; import com.sap.sailing.gwt.ui.client.LeaderboardGroupsDisplayer; @@ -41,6 +42,7 @@ import com.sap.sailing.gwt.ui.client.shared.controls.FlushableCellTable; import com.sap.sailing.gwt.ui.client.shared.controls.SelectionCheckboxColumn; import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil; import com.sap.sailing.gwt.ui.shared.CourseAreaDTO; +import com.sap.sailing.gwt.ui.shared.EventBaseDTO; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; @@ -48,6 +50,7 @@ import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; import com.sap.sse.common.util.NaturalComparator; import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.async.MarkedAsyncCallback; import com.sap.sse.gwt.client.celltable.EntityIdentityComparator; import com.sap.sse.gwt.client.celltable.RefreshableMultiSelectionModel; import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; @@ -433,7 +436,7 @@ public class EventListComposite extends Composite implements EventsRefresher, Le private void openCreateEventDialog() { List existingEvents = new ArrayList(eventListDataProvider.getList()); - List existingLeaderboardGroups = new ArrayList(); + final List existingLeaderboardGroups = new ArrayList(); Util.addAll(availableLeaderboardGroups, existingLeaderboardGroups); EventCreateDialog dialog = new EventCreateDialog(Collections.unmodifiableCollection(existingEvents), existingLeaderboardGroups, sailingService, stringMessages, new DialogCallback() { @@ -442,12 +445,57 @@ public class EventListComposite extends Composite implements EventsRefresher, Le } @Override - public void ok(EventDTO newEvent) { - createNewEvent(newEvent); + public void ok(final EventDTO newEvent) { + createNewEvent(newEvent, existingLeaderboardGroups); } }); dialog.show(); } + + /** + * @param newEvent the new event as created by the server, already including a valid {@link EventBaseDTO#id} value. + */ + private void openLeaderboardGroupCreationDialog(final List existingLeaderboardGroups, final EventDTO newEvent) { + LeaderboardGroupCreateDialog leaderboardGroupCreateDialog = new LeaderboardGroupCreateDialog(existingLeaderboardGroups, stringMessages, new DialogCallback() { + @Override + public void ok(final LeaderboardGroupDescriptor newGroup) { + sailingService.createLeaderboardGroup(newGroup.getName(), newGroup.getDescription(), + newGroup.getDisplayName(), newGroup.isDisplayLeaderboardsInReverseOrder(), + newGroup.getOverallLeaderboardDiscardThresholds(), newGroup.getOverallLeaderboardScoringSchemeType(), new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to create new leaderboard group" + newGroup.getName() + + ": " + t.getMessage()); + } + @Override + public void onSuccess(LeaderboardGroupDTO newGroup) { + newEvent.addLeaderboardGroup(newGroup); + // fillEvents() will have replaced newEvent in allEvents by a new copy coming from the server which + // doesn't know about the new leaderboard group yet. An updateEvent call will link the leaderboard group + // to the event on the server + EventDTO matchingEvent = null; + for (EventDTO event : allEvents) { + if (event.id.equals(newEvent.id)) { + matchingEvent = event; + } + } + if (matchingEvent != null) { + updateEvent(matchingEvent, newEvent); + } else { + errorReporter.reportError("Could not find the event with name "+newEvent.getName()+" to which the leaderboardgroup should be added"); + } + } + })); + } + + @Override + public void cancel() { + } + }); + leaderboardGroupCreateDialog.setFieldsBasedOnEventName(newEvent.getName()); + leaderboardGroupCreateDialog.show(); + } private void openEditEventDialog(final EventDTO selectedEvent) { List existingEvents = new ArrayList(eventListDataProvider.getList()); @@ -548,7 +596,7 @@ public class EventListComposite extends Composite implements EventsRefresher, Le return new Pair, List>(courseAreasToAdd, courseAreasToRemove); } - private void createNewEvent(final EventDTO newEvent) { + private void createNewEvent(final EventDTO newEvent, final List existingLeaderboardGroups) { List courseAreaNames = new ArrayList(); for (CourseAreaDTO courseAreaDTO : newEvent.venue.getCourseAreas()) { courseAreaNames.add(courseAreaDTO.getName()); @@ -562,8 +610,21 @@ public class EventListComposite extends Composite implements EventsRefresher, Le } @Override - public void onSuccess(EventDTO newEvent) { + public void onSuccess(final EventDTO newEvent) { fillEvents(); + if (newEvent.getLeaderboardGroups().isEmpty()) { + // show simple Dialog + new CreateDefaultLeaderboardGroupDialog(sailingService, stringMessages, errorReporter, new DialogCallback() { + @Override + public void ok(Void editedObject) { + openLeaderboardGroupCreationDialog(existingLeaderboardGroups, newEvent); + } + + @Override + public void cancel() { + } + }).show(); + } } }); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupCreateDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupCreateDialog.java index e013b6fd83c..01b1d69bffb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupCreateDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupCreateDialog.java @@ -23,4 +23,10 @@ public class LeaderboardGroupCreateDialog extends LeaderboardGroupDialog { displayLeaderboardsInReverseOrderCheckBox.setValue(false); useOverallLeaderboardCheckBox.setValue(false); } + + public void setFieldsBasedOnEventName(String name) { + nameEntryField.setText(name); + descriptionEntryField.setText(name); + validate(); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LinkRegattaLeaderboardToLeaderboardGroupOfEventDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LinkRegattaLeaderboardToLeaderboardGroupOfEventDialog.java new file mode 100644 index 00000000000..b0dc24b8532 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LinkRegattaLeaderboardToLeaderboardGroupOfEventDialog.java @@ -0,0 +1,61 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gwt.user.client.ui.ListBox; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; +import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; +import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.dialog.DataEntryDialog; + +public class LinkRegattaLeaderboardToLeaderboardGroupOfEventDialog extends DataEntryDialog { + private final List leaderboardGroups; + private ListBox leaderboardGroupsBox; + + public LinkRegattaLeaderboardToLeaderboardGroupOfEventDialog(SailingServiceAsync sailingService, final StringMessages stringMessages, + ErrorReporter errorReporter, StrippedLeaderboardDTO leaderboard, EventDTO event, DialogCallback callback) { + super(stringMessages.linkLeaderboardToLeaderboardGroupOfEvent(), + /*message*/ stringMessages.doYouWantToLinkLeaderboardToLeaderboardGroupOfEvent(leaderboard.name, event.getName()), + stringMessages.yes(), stringMessages.no(), + /*validator*/ new Validator() { + @Override + public String getErrorMessage(LeaderboardGroupDTO selectedLeaderboardGroup) { + final String errorMessage; + if (selectedLeaderboardGroup == null) { + errorMessage = stringMessages.pleaseSelectALeaderboardGroup(); + } else { + errorMessage = null; + } + return errorMessage; + } + }, callback); + this.leaderboardGroups = new ArrayList<>(); + leaderboardGroupsBox = createListBox(/* isMultipleSelect */ false); + for (final LeaderboardGroupDTO lgDTO : event.getLeaderboardGroups()) { + this.leaderboardGroups.add(lgDTO); + this.leaderboardGroupsBox.addItem(lgDTO.getName()); + } + } + + @Override + protected Widget getAdditionalWidget() { + return leaderboardGroupsBox; + } + + @Override + protected LeaderboardGroupDTO getResult() { + final LeaderboardGroupDTO result; + if (leaderboardGroupsBox.getSelectedItemText() == null) { + result = null; + } else { + result = leaderboardGroups.get(leaderboardGroupsBox.getSelectedIndex()); + } + return result; + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaManagementPanel.java index a8d35952281..c643f169822 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaManagementPanel.java @@ -6,6 +6,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; +import java.util.UUID; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; @@ -25,11 +26,14 @@ import com.sap.sailing.gwt.ui.client.RegattaRefresher; import com.sap.sailing.gwt.ui.client.RegattasDisplayer; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sailing.gwt.ui.shared.CourseAreaDTO; import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.SeriesDTO; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.async.MarkedAsyncCallback; import com.sap.sse.gwt.client.celltable.RefreshableMultiSelectionModel; import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; @@ -154,7 +158,6 @@ public class RegattaManagementPanel extends SimplePanel implements RegattasDispl private void openCreateRegattaDialog() { final Collection existingRegattas = Collections.unmodifiableCollection(regattaListComposite.getAllRegattas()); - sailingService.getEvents(new AsyncCallback>() { @Override public void onFailure(Throwable caught) { @@ -168,7 +171,7 @@ public class RegattaManagementPanel extends SimplePanel implements RegattasDispl }); } - private void openCreateRegattaDialog(Collection existingRegattas, List existingEvents) { + private void openCreateRegattaDialog(Collection existingRegattas, final List existingEvents) { RegattaWithSeriesAndFleetsCreateDialog dialog = new RegattaWithSeriesAndFleetsCreateDialog(existingRegattas, existingEvents, stringMessages, new DialogCallback() { @Override @@ -177,15 +180,14 @@ public class RegattaManagementPanel extends SimplePanel implements RegattasDispl @Override public void ok(RegattaDTO newRegatta) { - createNewRegatta(newRegatta); - openCreateDefaultRegattaLeaderboardDialog(newRegatta); + createNewRegatta(newRegatta, existingEvents); } }); dialog.ensureDebugId("RegattaCreateDialog"); dialog.show(); } - private void openCreateDefaultRegattaLeaderboardDialog(final RegattaDTO newRegatta){ + private void openCreateDefaultRegattaLeaderboardDialog(final RegattaDTO newRegatta, final List existingEvents) { CreateDefaultRegattaLeaderboardDialog dialog = new CreateDefaultRegattaLeaderboardDialog(sailingService, stringMessages, errorReporter, newRegatta, new DialogCallback() { @Override public void ok(RegattaIdentifier regattaIdentifier) { @@ -199,7 +201,15 @@ public class RegattaManagementPanel extends SimplePanel implements RegattasDispl @Override public void onSuccess(StrippedLeaderboardDTO result) { + if (newRegatta.defaultCourseAreaUuid != null) { + // Show the event's leaderboard groups and allow the user to pick one to assign the regatta leaderboard to + final EventDTO event = getEventForCourseArea(existingEvents, newRegatta.defaultCourseAreaUuid); + if (!event.getLeaderboardGroups().isEmpty()) { + openRegattaLeaderboardToLeaderboardGroupOfEventLinkingDialog(result, event); + } + } } + }); } @@ -207,12 +217,66 @@ public class RegattaManagementPanel extends SimplePanel implements RegattasDispl public void cancel() { } }); - dialog.ensureDebugId("CreateDefaultRegattaDialog"); dialog.show(); } - private void createNewRegatta(final RegattaDTO newRegatta) { + /** + * When a new regatta with a new regatta leaderboard has been created, the user will now be given the chance to link + * the regatta leaderboard into a leaderboard group of the event out of which the regatta chose its default course area. + * + * @param newRegattaLeaderboard the new regatta leaderboard that the user may link now to a leaderboard group of an event + * @param eventToLinkRegattaTo an event that has at least one {@link EventDTO#getLeaderboardGroups() leaderboard group} + */ + private void openRegattaLeaderboardToLeaderboardGroupOfEventLinkingDialog(final StrippedLeaderboardDTO newRegattaLeaderboard, EventDTO eventToLinkRegattaTo) { + LinkRegattaLeaderboardToLeaderboardGroupOfEventDialog dialog = new LinkRegattaLeaderboardToLeaderboardGroupOfEventDialog(sailingService, stringMessages, errorReporter, newRegattaLeaderboard, eventToLinkRegattaTo, + new DialogCallback() { + @Override + public void ok(final LeaderboardGroupDTO selectedLeaderboardGroup) { + final List leaderboardNames = new ArrayList<>(); + for (StrippedLeaderboardDTO leaderboard : selectedLeaderboardGroup.getLeaderboards()) { + leaderboardNames.add(leaderboard.name); + } + leaderboardNames.add(newRegattaLeaderboard.name); + sailingService.updateLeaderboardGroup(selectedLeaderboardGroup.getName(), selectedLeaderboardGroup.getName(), selectedLeaderboardGroup.description, + selectedLeaderboardGroup.getDisplayName(), leaderboardNames, selectedLeaderboardGroup.getOverallLeaderboardDiscardThresholds(), + selectedLeaderboardGroup.getOverallLeaderboardScoringSchemeType(), new MarkedAsyncCallback(new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError(stringMessages.failedToLinkLeaderboardToLeaderboardGroup(newRegattaLeaderboard.name, selectedLeaderboardGroup.getName())); + } + + @Override + public void onSuccess(Void result) { + } + })); + } + + @Override + public void cancel() { + } + }); + dialog.ensureDebugId("LinkRegattaLeaderboardToLeaderboardGroupOfEventDialog"); + dialog.show(); + } + + private EventDTO getEventForCourseArea(final List existingEvents, final UUID courseAreaId) { + EventDTO result = null; + eventLoop: + for (final EventDTO event : existingEvents) { + if (event.venue != null) { + for (CourseAreaDTO courseArea : event.venue.getCourseAreas()) { + if (courseArea.id.equals(courseAreaId)) { + result = event; + break eventLoop; + } + } + } + } + return result; + } + + private void createNewRegatta(final RegattaDTO newRegatta, final List existingEvents) { LinkedHashMap seriesStructure = new LinkedHashMap(); for (SeriesDTO seriesDTO : newRegatta.series) { SeriesCreationParametersDTO seriesPair = new SeriesCreationParametersDTO(seriesDTO.getFleets(), @@ -234,6 +298,7 @@ public class RegattaManagementPanel extends SimplePanel implements RegattasDispl @Override public void onSuccess(RegattaDTO regatta) { regattaRefresher.fillRegattas(); + openCreateDefaultRegattaLeaderboardDialog(regatta, existingEvents); } }); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsCreateDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsCreateDialog.java index 13f273b65ea..42def8f4926 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsCreateDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsCreateDialog.java @@ -11,6 +11,8 @@ import com.google.gwt.core.shared.GWT; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.TabPanel; import com.google.gwt.user.client.ui.VerticalPanel; +import com.sap.sailing.domain.common.LeaderboardNameConstants; +import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; @@ -103,6 +105,14 @@ public class RegattaWithSeriesAndFleetsCreateDialog extends RegattaWithSeriesAnd List existingEvents, StringMessages stringMessages, DialogCallback callback) { super(new RegattaDTO(), Collections.emptySet(), existingEvents, stringMessages.addRegatta(), stringMessages.ok(), stringMessages, new RegattaParameterValidator(stringMessages, existingRegattas), callback); + SeriesDTO series = new SeriesDTO(); + series.setName("Default"); + series.setMedal(false); + series.setStartsWithZeroScore(false); + series.setSplitFleetContiguousScoring(false); + series.setFirstColumnIsNonDiscardableCarryForward(false); + series.setFleets(Collections.singletonList(new FleetDTO(LeaderboardNameConstants.DEFAULT_FLEET_NAME, 0, null))); + seriesEditor.setValue(Collections.singleton(series)); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimePanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimePanel.java index 0271df48117..b6362eb93e2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimePanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimePanel.java @@ -210,7 +210,7 @@ public class RaceTimePanel extends TimePanel implements R * was null before, or extended to a later point in time. */ private void updateMinMax(RaceTimesInfoDTO newRaceTimesInfo) { - Util.Pair raceMinMax = RaceTimesCalculationUtil.caluclateRaceMinMax(timer, newRaceTimesInfo); + Util.Pair raceMinMax = RaceTimesCalculationUtil.calculateRaceMinMax(timer, newRaceTimesInfo); Date min = raceMinMax.getA(); Date max = raceMinMax.getB(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimesCalculationUtil.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimesCalculationUtil.java index 732d3cc677e..5dce068f4f7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimesCalculationUtil.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimesCalculationUtil.java @@ -7,12 +7,12 @@ import com.sap.sse.common.Util; import com.sap.sse.gwt.client.player.Timer; public class RaceTimesCalculationUtil { - public static final long MIN_TIME_BEFORE_RACE_START = 5 * 60 * 1000; // 5 minutes + public static final long MIN_TIME_BEFORE_RACE_START = 3 * 60 * 1000; // 3 minutes private static final long MIN_TIME_AFTER_RACE_START = 5 * 60 * 1000; // 5 minutes private static final long TIME_AFTER_LIVE = 5 * 60 * 1000; // 5 minutes - public static final long MAX_TIME_AFTER_RACE_END = 5 * 60 * 1000; // 5 minutes + public static final long MAX_TIME_AFTER_RACE_END = 1 * 60 * 1000; // 1 minutes - public static Util.Pair caluclateRaceMinMax(Timer timer, RaceTimesInfoDTO raceTimesInfo) { + public static Util.Pair calculateRaceMinMax(Timer timer, RaceTimesInfoDTO raceTimesInfo) { Date min = null; Date max = null; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index d13e7a7d396..1cf790cf217 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -1468,9 +1468,11 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, c String bufferLineStrokeWeight(); String profile(); String showOnlyCompetitorsOfLog(); + String maneuverType(); String confirmLosingCompetitorEditsWhenTogglingLogBasedView(); String removalOfMarkDisabledMayBeUsedInRaces(String raceNames); String pleaseCreateAtLeastOneMappingBy(); + String createDefaultLeaderboardGroup(); String matcherType(); String matchingDevices(); String addDevice(); @@ -1479,4 +1481,8 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, c String create(); String thereIsAlreadyAConfigurationForThisDevice(); String enterDeviceIdentifierName(); + String pleaseSelectALeaderboardGroup(); + String linkLeaderboardToLeaderboardGroupOfEvent(); + String doYouWantToLinkLeaderboardToLeaderboardGroupOfEvent(String leaderboardName, String eventName); + String failedToLinkLeaderboardToLeaderboardGroup(String leaderboardName, String leaderboardGroupName); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index 0a99c4252e6..4079fd6151b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -7,6 +7,7 @@ general=General listRaces=List Races listRegattas=List Regattas wind=Wind +maneuverType=Maneuver windPanelLabel=This is the Wind Panel which so far is completely empty. refresh=Refresh remove=Remove @@ -1437,6 +1438,8 @@ profile=Profile showOnlyCompetitorsOfLog=Show only competitors registered in Log confirmLosingCompetitorEditsWhenTogglingLogBasedView=This will reset your current, unsaved changes to the competitors.\nDo you really want to continue? removalOfMarkDisabledMayBeUsedInRaces=Removal deavticated, marks are used in races {0} +pleaseCreateAtLeastOneMappingBy=Plase create at list one mapping by first selecting a track on the left hand side and then selecting a mark or competitor on the right hand side +createDefaultLeaderboardGroup=Would you like to create a default LeaderboardGroup for your event? pleaseCreateAtLeastOneMappingBy=Please create at least one mapping by first selecting a track on the left hand side and then selecting a mark or competitor on the right hand side matcherType=Matcher type matchingDevices=Matching devices @@ -1446,3 +1449,7 @@ forWhichDeviceShouldConfigurationApply=Specify for which device the new configur create=Create thereIsAlreadyAConfigurationForThisDevice=There is already a configuration for this device. enterDeviceIdentifierName=Enter an identifier name +pleaseSelectALeaderboardGroup=Please select a leaderboard group +linkLeaderboardToLeaderboardGroupOfEvent=Link Leaderboard to Leaderboard Group of Event +doYouWantToLinkLeaderboardToLeaderboardGroupOfEvent=Link leaderboard {0} to a leaderboard group of event {1} +failedToLinkLeaderboardToLeaderboardGroup=Failed to link leaderboard {0} to leaderboard group {1} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index ce3d0f95d33..98d31df37b3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -81,6 +81,7 @@ leaderboard=Ergebnisse leaderboards=Ranglisten leaderboardSettings=Einstellungen Rangliste settings=Einstellungen +maneuverType=Manöver selectAtLeastOneLegDetail=Mindestens ein Detail auswählen currentSpeedOverGroundInKnots=FüG currentSpeedOverGroundInKnotsTooltip=Die aktuelle Fahrt über Grund @@ -1429,6 +1430,7 @@ scoringSchemeHighPointFirstGetsTwelveOrEightDescription=Scores als Punkte. Der G scoringSchemeHighPointEssOverall12=High Point System ESS Gesamtwertung (12) scoringSchemeHighPointEssOverall12Description=High Point System, der Gewinner eines Acts erhält 12 Punkte, der Zweite 11 und so weiter. pleaseCreateAtLeastOneMappingBy=Bitte erstellen Sie mindestens eine Zuordnung, indem Sie zunächst einen Track auf der linken Seite und anschließend einen Teilnehmer oder eine Tonne auf der rechten Seite auswählen +createDefaultLeaderboardGroup=Möchten Sie eine Default-Ranglisten-Gruppe für ihr Event anlegen? matcherType=Matcher-Typ matchingDevices=Passende Geräte addDevice=Gerät hinzufügen @@ -1437,3 +1439,7 @@ forWhichDeviceShouldConfigurationApply=Für welches Gerät soll die neue Konfigu create=Anlegen thereIsAlreadyAConfigurationForThisDevice=Es gibt bereits eine Konfiguration für dieses Gerät. enterDeviceIdentifierName=Geräteidentifikator eingeben +pleaseSelectALeaderboardGroup=Bitte eine Ranglisten-Gruppe auswählen +linkLeaderboardToLeaderboardGroupOfEvent=Ergebnisliste einer Ranglisten-Gruppe einer Veranstaltung hinzufügen +doYouWantToLinkLeaderboardToLeaderboardGroupOfEvent=Ergebnisliste {0} zu einer Ranglisten-Gruppe der Veranstaltung {1} hinzufügen +failedToLinkLeaderboardToLeaderboardGroup=Ergebnisliste {0} konnte nicht in Ranglisten-Gruppe {1} eingefügt werden diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties index c35ea8d4a31..6555cf07326 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties @@ -7,6 +7,7 @@ trackedBefore=Ранее Отслеженные general=Всенаро́дный listRaces=Перечень Гонок wind=ветра +maneuverType=Maneuver windPanelLabel=Это окно информации о ветре, которое до сих пор абсолютно пустое. refresh=Обновить remove=Удалить @@ -1359,6 +1360,8 @@ scoringSchemeHighPointFirstGetsTwelveOrEight=High Point, winner gets 12 points ( scoringSchemeHighPointFirstGetsTwelveOrEightDescription=Score in points. Winner scores 12 points, 2nd - 11 points, .... A tie is broken in favour of the competitor having won most races, if tie remains then tie is broken by the rank in the last race scored. scoringSchemeHighPointEssOverall12=High Point System ESS Overall (12) scoringSchemeHighPointEssOverall12Description=Score in points. Winner of an act scores 12 points, 2nd - 11 points, .... Any tie in the overall Extreme Sailing Series is broken in favour of the competitor with the most Act wins. If that does not break the tie, the result in the last Act will be used. +pleaseCreateAtLeastOneMappingBy=Plase create at list one mapping by first selecting a track on the left hand side and then selecting a mark or competitor on the right hand side +createDefaultLeaderboardGroup=Would you like to create a default LeaderboardGroup for your event? pleaseCreateAtLeastOneMappingBy=Please create at least one mapping by first selecting a track on the left hand side and then selecting a mark or competitor on the right hand side matcherType=Matcher type matchingDevices=Matching devices @@ -1368,3 +1371,7 @@ forWhichDeviceShouldConfigurationApply=Specify for which device the new configur create=Create thereIsAlreadyAConfigurationForThisDevice=There is already a configuration for this device. enterDeviceIdentifierName=Enter an identifier name +pleaseSelectALeaderboardGroup=Please select a leaderboard group +linkLeaderboardToLeaderboardGroupOfEvent=Link Leaderboard to Leaderboard Group of Event +doYouWantToLinkLeaderboardToLeaderboardGroupOfEvent=Link leaderboard {0} to a leaderboard group of event {1} +failedToLinkLeaderboardToLeaderboardGroup=Failed to link leaderboard {0} to leaderboard group {1} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties index 7b7e766d209..fd874185f8b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties @@ -7,6 +7,7 @@ pleaseSelectAnItemToMapTo=Please select an item to map the device to inEvent=in event pleaseSelectARace=Please select a race columnMoveUp=Up +maneuverType=Maneuver enterCarryValueFor=Enter carried points for competitor {0} eventOfficialWebsiteURL=Official Website URL eventSailorsInfoWebsiteURL=Sailors Info Website URL @@ -1374,6 +1375,8 @@ scoringSchemeHighPointFirstGetsTwelveOrEight=High Point, winner gets 12 points ( scoringSchemeHighPointFirstGetsTwelveOrEightDescription=Score in points. Winner scores 12 points, 2nd - 11 points, .... A tie is broken in favour of the competitor having won most races, if tie remains then tie is broken by the rank in the last race scored. scoringSchemeHighPointEssOverall12=High Point System ESS Overall (12) scoringSchemeHighPointEssOverall12Description=Score in points. Winner of an act scores 12 points, 2nd - 11 points, .... Any tie in the overall Extreme Sailing Series is broken in favour of the competitor with the most Act wins. If that does not break the tie, the result in the last Act will be used. +pleaseCreateAtLeastOneMappingBy=Plase create at list one mapping by first selecting a track on the left hand side and then selecting a mark or competitor on the right hand side +createDefaultLeaderboardGroup=Would you like to create a default LeaderboardGroup for your event? pleaseCreateAtLeastOneMappingBy=Please create at least one mapping by first selecting a track on the left hand side and then selecting a mark or competitor on the right hand side matcherType=Matcher type matchingDevices=Matching devices @@ -1383,3 +1386,7 @@ forWhichDeviceShouldConfigurationApply=Specify for which device the new configur create=Create thereIsAlreadyAConfigurationForThisDevice=There is already a configuration for this device. enterDeviceIdentifierName=Enter an identifier name +pleaseSelectALeaderboardGroup=Please select a leaderboard group +linkLeaderboardToLeaderboardGroupOfEvent=Link Leaderboard to Leaderboard Group of Event +doYouWantToLinkLeaderboardToLeaderboardGroupOfEvent=Link leaderboard {0} to a leaderboard group of event {1} +failedToLinkLeaderboardToLeaderboardGroup=Failed to link leaderboard {0} to leaderboard group {1} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TimePanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TimePanel.java index 222acc10ff6..e8d1cb4c194 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TimePanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TimePanel.java @@ -229,8 +229,6 @@ public class TimePanel extends SimplePanel implemen playSpeedBox = new IntegerBox(); playSpeedBox.setVisibleLength(3); - playSpeedBox.setWidth("25px"); - playSpeedBox.setHeight("14px"); playSpeedBox.setValue((int)timer.getPlaySpeedFactor()); // Christopher: initialize play speed box according to play speed factor playSpeedBox.setTitle(stringMessages.playSpeedHelp()); playSpeedBox.addValueChangeHandler(new ValueChangeHandler() { @@ -271,6 +269,7 @@ public class TimePanel extends SimplePanel implemen playSpeedImage.getElement().getStyle().setFloat(Style.Float.LEFT); playSpeedImage.getElement().getStyle().setPadding(3, Style.Unit.PX); + playSpeedImage.getElement().getStyle().setMarginRight(3, Style.Unit.PX); playSpeedBox.getElement().getStyle().setFloat(Style.Float.LEFT); playSpeedBox.getElement().getStyle().setPadding(2, Style.Unit.PX); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/BoatOverlay.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/BoatOverlay.java index 53eb5ff681c..031ac8554dc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/BoatOverlay.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/BoatOverlay.java @@ -143,11 +143,7 @@ public class BoatOverlay extends CanvasOverlayV3 { } public void setBoatFix(GPSFixDTO boatFix, long timeForPositionTransitionMillis) { - if (timeForPositionTransitionMillis == -1) { - removeCanvasPositionAndRotationTransition(); - } else { - setCanvasPositionAndRotationTransition(timeForPositionTransitionMillis); - } + updateTransition(timeForPositionTransitionMillis); this.boatFix = boatFix; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/CompetitorInfoOverlay.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/CompetitorInfoOverlay.java index 5f76ca9e062..38b993dc938 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/CompetitorInfoOverlay.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/CompetitorInfoOverlay.java @@ -111,11 +111,7 @@ public class CompetitorInfoOverlay extends CanvasOverlayV3 { */ public void setPosition(Position position, long timeForPositionTransitionMillis) { - if (timeForPositionTransitionMillis == -1) { - removeCanvasPositionAndRotationTransition(); - } else { - setCanvasPositionAndRotationTransition(timeForPositionTransitionMillis); - } + updateTransition(timeForPositionTransitionMillis); this.position = position; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/CourseMarkOverlay.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/CourseMarkOverlay.java index 1ee74519251..97f61851223 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/CourseMarkOverlay.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/CourseMarkOverlay.java @@ -20,7 +20,6 @@ import com.sap.sse.common.Util; * A google map overlay based on a HTML5 canvas for drawing course marks (canvases) and the buoy zone if the mark is a buoy. */ public class CourseMarkOverlay extends CanvasOverlayV3 { - /** * The course mark to draw */ @@ -167,7 +166,8 @@ public class CourseMarkOverlay extends CanvasOverlayV3 { return mark; } - public void setMarkPosition(Position position) { + public void setMarkPosition(Position position, long transitionTimeInMillis) { + updateTransition(transitionTimeInMillis); this.position = position; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/ManeuverColor.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/ManeuverColor.java new file mode 100644 index 00000000000..60cf474178c --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/ManeuverColor.java @@ -0,0 +1,12 @@ +package com.sap.sailing.gwt.ui.client.shared.racemap; + +import com.sap.sailing.gwt.ui.shared.ManeuverDTO; + +public enum ManeuverColor { + RED, GREEN; + + public static ManeuverColor getManeuverColor(ManeuverDTO maneuver) { + return maneuver.directionChangeInDegrees < 0 ? RED : GREEN; + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/ManeuverMarkerClickedListener.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/ManeuverMarkerClickedListener.java new file mode 100644 index 00000000000..229f221ad6b --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/ManeuverMarkerClickedListener.java @@ -0,0 +1,34 @@ +package com.sap.sailing.gwt.ui.client.shared.racemap; + +import com.google.gwt.maps.client.base.LatLng; +import com.google.gwt.maps.client.events.click.ClickMapEvent; +import com.google.gwt.maps.client.events.click.ClickMapHandler; +import com.google.gwt.maps.client.overlays.InfoWindow; +import com.google.gwt.maps.client.overlays.InfoWindowOptions; +import com.sap.sailing.gwt.ui.shared.ManeuverDTO; + +public class ManeuverMarkerClickedListener implements ClickMapHandler { + + private RaceMap racemap; + private ManeuverDTO maneuver; + + public ManeuverMarkerClickedListener(RaceMap racemap, ManeuverDTO maneuver) { + this.racemap = racemap; + this.maneuver = maneuver; + } + + @Override + public void onEvent(ClickMapEvent event) { + final InfoWindow lastInfoWindow = racemap.getLastInfoWindow(); + if (lastInfoWindow != null) { + lastInfoWindow.close(); + } + LatLng where = racemap.getCoordinateSystem().toLatLng(maneuver.position); + InfoWindowOptions options = InfoWindowOptions.newInstance(); + InfoWindow infoWindow = InfoWindow.newInstance(options); + infoWindow.setContent(racemap.getInfoWindowContent(maneuver)); + infoWindow.setPosition(where); + racemap.setLastInfoWindow(infoWindow); + infoWindow.open(racemap.getMap()); + } +} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMap.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMap.java index 0fa2d3fd81c..2a6100d06be 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMap.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMap.java @@ -21,7 +21,9 @@ import com.google.gwt.dom.client.Style; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.i18n.client.NumberFormat; +import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat; import com.google.gwt.maps.client.LoadApi; import com.google.gwt.maps.client.LoadApi.LoadLibrary; import com.google.gwt.maps.client.MapOptions; @@ -74,7 +76,6 @@ import com.sap.sailing.domain.common.ManeuverType; import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.Tack; import com.sap.sailing.domain.common.WindSource; import com.sap.sailing.domain.common.WindSourceType; import com.sap.sailing.domain.common.dto.CompetitorDTO; @@ -89,6 +90,7 @@ import com.sap.sailing.gwt.ui.actions.GetWindInfoAction; import com.sap.sailing.gwt.ui.client.ClientResources; import com.sap.sailing.gwt.ui.client.CompetitorSelectionChangeListener; import com.sap.sailing.gwt.ui.client.CompetitorSelectionProvider; +import com.sap.sailing.gwt.ui.client.ManeuverTypeFormatter; import com.sap.sailing.gwt.ui.client.NumberFormatterFactory; import com.sap.sailing.gwt.ui.client.RaceTimesInfoProviderListener; import com.sap.sailing.gwt.ui.client.RequiresDataInitialization; @@ -116,6 +118,7 @@ import com.sap.sailing.gwt.ui.shared.WaypointDTO; import com.sap.sailing.gwt.ui.shared.WindDTO; import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO; import com.sap.sailing.gwt.ui.shared.WindTrackInfoDTO; +import com.sap.sailing.gwt.ui.shared.racemap.CanvasOverlayV3; import com.sap.sailing.gwt.ui.shared.racemap.GoogleMapAPIKey; import com.sap.sailing.gwt.ui.shared.racemap.GoogleMapStyleHelper; import com.sap.sailing.gwt.ui.shared.racemap.RaceSimulationOverlay; @@ -707,13 +710,16 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe private void removeTransitions() { // remove the canvas animations for boats - for (BoatOverlay boatOverlay : RaceMap.this.getBoatOverlays().values()) { + for (CanvasOverlayV3 boatOverlay : RaceMap.this.getBoatOverlays().values()) { boatOverlay.removeCanvasPositionAndRotationTransition(); } // remove the canvas animations for the info overlays of the selected boats for (CompetitorInfoOverlay infoOverlay : competitorInfoOverlays.values()) { infoOverlay.removeCanvasPositionAndRotationTransition(); } + for (CourseMarkOverlay markOverlay : courseMarkOverlays.values()) { + markOverlay.removeCanvasPositionAndRotationTransition(); + } // remove the advantage line animation if (advantageTimer != null) { advantageTimer.removeAnimation(); @@ -950,7 +956,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe updateCoordinateSystemFromSettings(); } // Do mark specific actions - showCourseMarksOnMap(raceMapDataDTO.coursePositions); + showCourseMarksOnMap(raceMapDataDTO.coursePositions, transitionTimeInMillis); showCourseSidelinesOnMap(raceMapDataDTO.courseSidelines); showStartAndFinishAndCourseMiddleLines(raceMapDataDTO.coursePositions); showStartLineToFirstMarkTriangle(raceMapDataDTO.coursePositions); @@ -1076,7 +1082,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe } } - private void showCourseMarksOnMap(CoursePositionsDTO courseDTO) { + private void showCourseMarksOnMap(CoursePositionsDTO courseDTO, long transitionTimeInMillis) { if (map != null && courseDTO != null) { WaypointDTO endWaypointForCurrentLegNumber = null; if(courseDTO.currentLegNumber > 0 && courseDTO.currentLegNumber <= courseDTO.totalLegsCount) { @@ -1100,7 +1106,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe markDTOs.put(markDTO.getName(), markDTO); courseMarkOverlay.addToMap(); } else { - courseMarkOverlay.setMarkPosition(markDTO.position); + courseMarkOverlay.setMarkPosition(markDTO.position, transitionTimeInMillis); courseMarkOverlay.setShowBuoyZone(settings.getHelpLinesSettings().isVisible(HelpLineTypes.BUOYZONE)); courseMarkOverlay.setBuoyZoneRadiusInMeter(settings.getBuoyZoneRadiusInMeters()); courseMarkOverlay.setSelected(isSelected); @@ -1267,7 +1273,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe } if (!updateTailsOnly) { for (CompetitorDTO unusedBoatCanvasCompetitorDTO : competitorDTOsOfUnusedBoatCanvases) { - BoatOverlay boatCanvas = boatOverlays.get(unusedBoatCanvasCompetitorDTO); + CanvasOverlayV3 boatCanvas = boatOverlays.get(unusedBoatCanvasCompetitorDTO); boatCanvas.removeFromMap(); boatOverlays.remove(unusedBoatCanvasCompetitorDTO); } @@ -2003,6 +2009,27 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe return vPanel; } + public Widget getInfoWindowContent(ManeuverDTO maneuver) { + SpeedWithBearingDTO before = maneuver.speedWithBearingBefore; + SpeedWithBearingDTO after = maneuver.speedWithBearingAfter; + VerticalPanel vPanel = new VerticalPanel(); + vPanel.add(createInfoWindowLabelAndValue(stringMessages.maneuverType(), + ManeuverTypeFormatter.format(maneuver.type, stringMessages))); + vPanel.add(createInfoWindowLabelAndValue(stringMessages.time(), + DateTimeFormat.getFormat(PredefinedFormat.TIME_FULL).format(maneuver.timepoint))); + vPanel.add(createInfoWindowLabelAndValue(stringMessages.directionChange(), + ((int) maneuver.directionChangeInDegrees) + " " + stringMessages.degreesShort() + " (" + + ((int) before.bearingInDegrees) + " " + stringMessages.degreesShort() + " -> " + + ((int) after.bearingInDegrees) + " " + stringMessages.degreesShort() + ")")); + vPanel.add(createInfoWindowLabelAndValue(stringMessages.speedChange(), + NumberFormat.getDecimalFormat().format(after.speedInKnots - before.speedInKnots) + " " + + stringMessages.knotsUnit() + " (" + + NumberFormat.getDecimalFormat().format(before.speedInKnots) + " " + stringMessages.knotsUnit() + + " -> " + NumberFormat.getDecimalFormat().format(after.speedInKnots) + " " + + stringMessages.knotsUnit() + ")")); + return vPanel; + } + private Widget getInfoWindowContent(WindSource windSource, WindTrackInfoDTO windTrackInfoDTO) { WindDTO windDTO = windTrackInfoDTO.windFixes.get(0); NumberFormat numberFormat = NumberFormat.getFormat("0.0"); @@ -2169,21 +2196,27 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe List maneuversForCompetitor = maneuvers.get(competitorDTO); for (ManeuverDTO maneuver : maneuversForCompetitor) { if (settings.isShowManeuverType(maneuver.type)) { - LatLng latLng = coordinateSystem.toLatLng(maneuver.position); - Marker maneuverMarker = raceMapImageManager.maneuverIconsForTypeAndTargetTack.get(new com.sap.sse.common.Util.Pair(maneuver.type, maneuver.newTack)); - MarkerOptions options = MarkerOptions.newInstance(); - options.setTitle(maneuver.toString(stringMessages)); - options.setIcon(maneuverMarker.getIcon_MarkerImage()); - Marker marker = Marker.newInstance(options); - marker.setPosition(latLng); - maneuverMarkers.add(marker); - marker.setMap(map); + createAndAddMarkerOfManeuver(maneuver); } } } } } + private void createAndAddMarkerOfManeuver(ManeuverDTO maneuver) { + LatLng latLng = coordinateSystem.toLatLng(maneuver.position); + Marker maneuverMarker = raceMapImageManager.maneuverIconsForTypeAndDirectionIndicatingColor + .get(new Pair(maneuver.type, ManeuverColor.getManeuverColor(maneuver))); + MarkerOptions options = MarkerOptions.newInstance(); + options.setIcon(maneuverMarker.getIcon_MarkerImage()); + Marker marker = Marker.newInstance(options); + marker.setPosition(latLng); + marker.setTitle(ManeuverTypeFormatter.format(maneuver.type, stringMessages)); + marker.addClickHandler(new ManeuverMarkerClickedListener(this, maneuver)); + maneuverMarkers.add(marker); + marker.setMap(map); + } + /** * @param date * the point in time for which to determine the competitor's boat position; approximated by using the fix @@ -2270,7 +2303,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe while (i.hasNext()) { Entry next = i.next(); if (!next.getKey().equals(competitor)) { - BoatOverlay boatOverlay = next.getValue(); + CanvasOverlayV3 boatOverlay = next.getValue(); boatOverlay.removeFromMap(); fixesAndTails.removeTail(next.getKey()); i.remove(); // only this way a ConcurrentModificationException while looping can be avoided @@ -2749,4 +2782,16 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe protected String getLeftControlsIndentStyle() { return null; } + + DelegateCoordinateSystem getCoordinateSystem() { + return coordinateSystem; + } + + void setLastInfoWindow(InfoWindow infoWindow) { + lastInfoWindow = infoWindow; + } + + InfoWindow getLastInfoWindow() { + return lastInfoWindow; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapImageManager.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapImageManager.java index 84cb09b3ca6..4dffc1946d0 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapImageManager.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapImageManager.java @@ -1,21 +1,27 @@ package com.sap.sailing.gwt.ui.client.shared.racemap; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; -import java.util.Map.Entry; import com.google.gwt.core.client.GWT; import com.google.gwt.maps.client.MapWidget; import com.google.gwt.maps.client.base.Point; +import com.google.gwt.maps.client.base.Size; import com.google.gwt.maps.client.overlays.Marker; import com.google.gwt.maps.client.overlays.MarkerImage; import com.google.gwt.maps.client.overlays.MarkerOptions; +import com.google.gwt.resources.client.ImageResource; import com.sap.sailing.domain.common.ManeuverType; -import com.sap.sailing.domain.common.Tack; import com.sap.sse.common.Util; public class RaceMapImageManager { + private static final int MARKER_HEIGHT = 26; + + private static final int MARKER_WIDTH = 26; + /** * An arrow showing the combined wind depending on the wind direction */ @@ -31,49 +37,44 @@ public class RaceMapImageManager { */ protected ImageTransformer windSensorIconTransformer; - protected Map, Marker> maneuverIconsForTypeAndTargetTack; + protected Map, Marker> maneuverIconsForTypeAndDirectionIndicatingColor; private static RaceMapResources resources = GWT.create(RaceMapResources.class); public RaceMapImageManager() { - maneuverIconsForTypeAndTargetTack = new HashMap, Marker>(); + maneuverIconsForTypeAndDirectionIndicatingColor = new HashMap, Marker>(); trueNorthIndicatorIconTransformer = new ImageTransformer(resources.trueNorthIndicatorIcon()); combinedWindIconTransformer = new ImageTransformer(resources.combinedWindIcon()); windSensorIconTransformer = new ImageTransformer(resources.expeditionWindIcon()); } /** - * Loads the map overlay icons The method can only be called after the map is loaded. The {@link #maneuverIconsForTypeAndTargetTack} map - * is filled for all combinations of {@link ManeuverType maneuver types} and {@link Tack tacks} including the value null representing - * the unknown tack. + * Loads the map overlay icons The method can only be called after the map is loaded. The {@link #maneuverIconsForTypeAndDirectionIndicatingColor} map + * is filled for all combinations of {@link ManeuverType maneuver types} and {@link ManeuverColor colors}. */ public void loadMapIcons(MapWidget map) { if (map != null) { - final Map maneuverLetter = new HashMap<>(); - maneuverLetter.put(ManeuverType.TACK, 'T'); - maneuverLetter.put(ManeuverType.JIBE, 'J'); - maneuverLetter.put(ManeuverType.HEAD_UP, 'H'); - maneuverLetter.put(ManeuverType.BEAR_AWAY, 'B'); - maneuverLetter.put(ManeuverType.MARK_PASSING, 'M'); - maneuverLetter.put(ManeuverType.PENALTY_CIRCLE, 'P'); - maneuverLetter.put(ManeuverType.UNKNOWN, '?'); - final Map tackColor = new HashMap<>(); - tackColor.put(Tack.STARBOARD, "71bf44"); - tackColor.put(Tack.PORT, "d95252"); - tackColor.put(null, "FFFFFF"); - for (Entry m : maneuverLetter.entrySet()) { - for (Entry t : tackColor.entrySet()) { - final Marker icon = createMarker("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld="+m.getValue()+"|"+t.getValue()+"|000000", 10, 33); - maneuverIconsForTypeAndTargetTack.put(new Util.Pair(m.getKey(), t.getKey()), icon); - } + final List maneuvers = new ArrayList(); + for (ManeuverType type : ManeuverType.values()) { + maneuvers.add(type); + } + Marker icon; + for (ManeuverType maneuver : maneuvers) { + icon = createMarker(resources.maneuverMarkerRed()); + maneuverIconsForTypeAndDirectionIndicatingColor + .put(new Util.Pair(maneuver, ManeuverColor.RED), icon); + icon = createMarker(resources.maneuverMarkerGreen()); + maneuverIconsForTypeAndDirectionIndicatingColor + .put(new Util.Pair(maneuver, ManeuverColor.GREEN), icon); } } } - - private Marker createMarker(String iconUrl, int anchorX, int anchorY) { + + private Marker createMarker(ImageResource ressource) { MarkerOptions options = MarkerOptions.newInstance(); - MarkerImage markerImage = MarkerImage.newInstance(iconUrl); - markerImage.setAnchor(Point.newInstance(anchorX, anchorY)); + MarkerImage markerImage = MarkerImage.newInstance(ressource.getSafeUri().asString()); + markerImage.setAnchor(Point.newInstance(MARKER_WIDTH/2, MARKER_HEIGHT/2)); + markerImage.setScaledSize(Size.newInstance(MARKER_WIDTH, MARKER_HEIGHT)); options.setIcon(markerImage); Marker marker = Marker.newInstance(options); return marker; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapResources.java index 286b694b771..689799cb81c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapResources.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapResources.java @@ -21,7 +21,13 @@ public interface RaceMapResources extends ClientBundle { @Source("com/sap/sailing/gwt/ui/client/images/wind_expedition.png") ImageResource expeditionWindIcon(); - + + @Source("com/sap/sailing/gwt/ui/client/images/maneuver_red.png") + ImageResource maneuverMarkerRed(); + + @Source("com/sap/sailing/gwt/ui/client/images/maneuver_green.png") + ImageResource maneuverMarkerGreen(); + @Source("CombinedWindPanel.css") CombinedWindPanelStyle combinedWindPanelStyle(); } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapSettings.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapSettings.java index f303b9297e1..35ef398ca12 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapSettings.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapSettings.java @@ -51,8 +51,7 @@ public class RaceMapSettings extends AbstractSettings { private boolean windUp = false; public RaceMapSettings() { - // empty default settings; don't show maneuvers by default - maneuverTypesToShow = new HashSet(); + this.maneuverTypesToShow = getDefaultManeuvers(); this.zoomSettings = new RaceMapZoomSettings(); this.helpLinesSettings = new RaceMapHelpLinesSettings(); } @@ -217,7 +216,15 @@ public class RaceMapSettings extends AbstractSettings { public void setShowMapControls(boolean showMapControls) { this.showMapControls = showMapControls; } - + + private HashSet getDefaultManeuvers() { + HashSet types = new HashSet(); + types.add(ManeuverType.JIBE); + types.add(ManeuverType.TACK); + types.add(ManeuverType.PENALTY_CIRCLE); + return types; + } + public static RaceMapSettings readSettingsFromURL() { final boolean showMapControls = GwtHttpRequestUtils.getBooleanParameter(PARAM_SHOW_MAPCONTROLS, true /* default */); return new RaceMapSettings(showMapControls); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/SmallTransparentInfoOverlay.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/SmallTransparentInfoOverlay.java index 7846cd7f2b8..4b4b15d035b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/SmallTransparentInfoOverlay.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/SmallTransparentInfoOverlay.java @@ -134,11 +134,7 @@ public class SmallTransparentInfoOverlay extends CanvasOverlayV3 { */ public void setPosition(Position position, long timeForPositionTransitionMillis) { - if (timeForPositionTransitionMillis == -1) { - removeCanvasPositionAndRotationTransition(); - } else { - setCanvasPositionAndRotationTransition(timeForPositionTransitionMillis); - } + updateTransition(timeForPositionTransitionMillis); this.position = position; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/CanvasOverlayV3.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/CanvasOverlayV3.java index 4643473a660..06a0f656a97 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/CanvasOverlayV3.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/CanvasOverlayV3.java @@ -408,4 +408,12 @@ public abstract class CanvasOverlayV3 { public MapCanvasProjection getMapProjection() { return mapProjection; } + + protected void updateTransition(long timeForPositionTransitionMillis) { + if (timeForPositionTransitionMillis == -1) { + removeCanvasPositionAndRotationTransition(); + } else { + setCanvasPositionAndRotationTransition(timeForPositionTransitionMillis); + } + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/solutions/SailingAnalyticsNotes.html b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/solutions/SailingAnalyticsNotes.html index c9cc4d5a299..34d48bafbfc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/solutions/SailingAnalyticsNotes.html +++ b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/solutions/SailingAnalyticsNotes.html @@ -1,461 +1,470 @@ - - - -
-

What's New - SAP Sailing Analytics

-
-
February 2016
- -
    -
  • The website now features a user registration and authentication interface. - User accounts are currently used to grant special permissions to administrators and moderators. - New user specific features (e.g. preferences) will be available in the next couple of months. -
  • -
  • The RaceBoard URL Parameter "canReplayDuringLiveRaces" has been removed. - This parameter was used to allow users to trigger autoplay for live races on non-live points in time. - The permission "CAN_REPLAY_DURING_LIVE_RACES" and role "moderator" now grant this functionality to users. -
  • -
- -
December 2015
- -
    -
  • The advantage line is now animated and moves smoothly with the boats. -
  • -
  • New line hover behavior in race map. When the mouse is moved onto a line, for example the start line, a transparent, - wider line is activated behind it that acts as a buffer for the thin line, where the text displayed by the hover is still shown. - This makes it easier to hover over the lines. These wider lines can be made semi transparent instead of transparent - by unticking the corresponding checkbox in the settings of the race map. Furthermore the stroke weight of the wider lines can be - configured in the same settings dialog. -
  • -
  • The race viewer (RaceBoard.html) now intelligently chooses a layout that suits the screen size. - When only little horizontal space is available, only the sail number and nationality but not the - competitor's long name is displayed by default. When vertical space is scarce, competitor and wind - charts are disabled and more horizontal space can be given to the time slider at the bottom. The - leaderboard section can then be scaled to smaller widths and will reduce the column widths better - than in the past. -
  • -
  • With the changes described above, the RaceBoard is now also accessible from the races page on mobile devices. -
  • -
  • For overall / series leaderboards such as a national sailing league or the Extreme Sailing Series, the - live status of the overall leaderboard is now indicated. As long as a live race is ongoing, the respective - column in the overall leaderboard is highlighted, and a comment is displayed that indicates which regatta - is currently still live. -
  • -
- -
November 2015
- -
    -
  • The smartphone page provides some structural navigation items for several pages in the upper right burger menu. - You will see links to e.g. events, regattas and series when navigating on event and series pages. -
  • -
  • It is now possible to filter for competitors in the race list of events/regattas. - If competitor information is available, there is a filter box in the upper right corner of the races page. - The filter is searching for competitors by sail ID as well as the competitor's name. -
  • -
  • Regattas can now be filtered by boat category in the smartphone page. - The filter will be shown for events with multiple regattas if there is more than on boat category associated with the event. -
  • -
- -
October 2015
- -
    -
  • A variety of tablets will now show the desktop page by default. - The mobile version of the website is primarily designed to be used on smartphones, - but you can manually switch back to the mobile version by clicking the corresponding link in the page footer. -
  • -
  • There is some amount of caching on the web page to reduce the consumed traffic for mobile users. - Contents aren't loaded again on each page switch. This improves the traffic consumption and loading speed on fast page switches. -
  • -
  • The fullscreen image viewer (start page and event media page) can automatically slide through the images. - This can be turned on by clicking the corresponding icon in the upper right corner of the fullscreen viewer. -
  • -
  • There is an optimized search and results page for mobile devices now. -
  • -
- -
September 2015
- -
    -
  • Races in the event/regatta race list can now be shown in 'competition format'. - In this format the races and flights are shown in a structural view. - In contrast to the default list view there is no grouping by live and finished states and all - (including upcoming) races/flights are shown in one structural view. -
  • -
  • The mobile page now provides regatta overview pages for events having multiple regattas. - This page shows live races, an excerpt of the current results as well as statistics for the regatta. -
  • -
- -
August 2015
- -
    -
  • Series events appear as only one entry in the events list, with a marker that - this is only one of a certain number of events in a series. This way, the many series events - don't produce clutter in the events list. -
  • -
  • Bug fix: memory leaks for distance cache have been solved. The issue could - also lead to endless recursions, ultimately leading to server lock-ups. -
  • -
  • Bug fix: master data import detached race logs and regatta logs from database. - Log entries added after import on the importing server were not written to the - database and therefore were lost upon server restart. -
  • -
  • There is a smartphone-optimized version of the "solutions" page known from the desktop. -
  • -
  • The smartphone event history now has a slider that allows swiping through the events of a year. -
  • -
- -
July 2015
- -
    -
  • Major improvements to the web page, with specific enhancements for smartphone - users. Race lists are now sortable by various criteria by clicking on the column - headers. A new fancy progress indicator now also provides visual feedback for - multi-fleet regattas. A news ticker box has been implemented, and the event - overview page can hold a video player on its stage. The event media gallery section - has been greatly improved. -
  • -
  • Fixed a bug in the wind streamlet visualization. Now the wind streamlets - correctly show the wind at the location selected also in wind-up mode. -
  • -
  • Added the "Course Geometry" option to the map display. With this option selected, - the map will show an info text for each leg and the start and finish line (only - for one of start/finish line if they are identical), telling the length of the leg - or line, respectively, and its angle to the wind. For the start and finish line - the advantage of the favored side is shown in meters. -
  • -
  • The SAP Sailing Analytics start page is now available in the smartphone version. - This page features some events that are currently interesting as well as showing a - quickfinder for a variety of recent and upcoming events. - Previously, the start page redirected to the event history. -
  • -
- -
May 2015
- -
    -
  • Competitors can have a separate flag image, such as a club flag to be displayed instead of - the nationality flag usually displayed with the sail number. This enables national league events - to display the club flags consistently when all nation flags would be the same anyway. -
  • -
  • The wind estimation from the tracked courses over ground has been improved. It now takes into - account any polar data available for the boat class concerned. In particular, this helps to rule - out very unlikely gybing angles in downwind clusters that otherwise could have led to an incorrect - split of the downwind fleet into two clusters where actually all boats were on the same tack. -
  • -
  • Some significant improvements have been applied to the simulator feature which is embedded in the - race viewer since some time now. The simulator now copes with very shifty wind conditions and finds - solutions in scenarios where an upwind leg flips to a reach or even into a downwind leg over time. -
  • -
- -
April 2015
- -
    -
  • There is a new map setting "Wind-Up (show wind from top of map)". Selecting it will - align the map's top with the combined true wind average direction around the time currently - selected in the time slider. In this new view there are limitations as to how far you can zoom - out. Furthermore, you will not be able to use the Satellite view with this setting. Tip: - if you want to re-align to wind-up after a major wind shift, un-check the setting, confirm - the setting change, then set it again. A compass shows the true north orientation. Clicking - the compass will toggle between wind-up and north-up display. -
  • -
  • Bug fixes around addition of the "Regatta Rank" column in the leaderboard which could have - distorted the leaderboard's column layout under certain conditions. -
  • -
  • Bug fix for cumulative points in the leaderboard ("Show added scores for each entry in leaderboard"). - With this setting, scores of competitors not tracked in the current race were not correctly represented - and may have stayed blank. -
  • -
  • Bug fix for the leg counter in the regatta page: when the first boat has finished, the leg counter went - to zero (e.g., "0 of 8"). This has now been fixed, and it will show, e.g., "8 of 8" upon the first boat - crossing the finish line. -
  • -
- -
March 2015
- -
    -
  • Added competitor chart type for Course Over Ground (COG) -
  • -
  • Added leaderboard column and competitor chart entry for distances considering - gate starts. With gate starts, late starters sail a shorter distance in their first - leg. To still make distances comparable, a new metric has been introduced that for a gate - start adds the distance between the port side of the start line and the position where - the competitor started to the distance sailed in the first leg. -
  • -
  • The weights of the wind measurement units, the wind estimation and manual wind inputs by the - race committee are now used properly for the wind streamlet visualization. This fixes issues - with exaggerated weights for an estimated wind direction of very low confidence. -
  • -
  • The expand/collapse toggle button in the race viewer's time panel has correct arrows now. -
  • -
- -
February 2015
- -
    -
  • The leaderboard offers a new column: "Start delay." It shows the number of seconds that passed - since the race start and the time the competitor passes the start mark / start line. As usual, - you can sort for this column. For line starts, this is a fairly direct measure of start quality - except for port starts which may have to be considered differently. For gate starts, you can use - this measure to find out about early and late starters and dig into possible correlations between - results and start time point. -
  • -
- -
January 2015
- -
    -
  • The race viewer ("RaceBoard.html") now offers a new option in the map settings: - "Show simulation overlay". Checking this feature will simulate the current leader's leg - using different strategies and using the wind as it has been measured and estimated. - This feature becomes particularly interesting when combined with the "Show wind streamlets overlay" - feature that visualizes the spatial distribution of the wind field over the course. -
  • -
  • The race viewer is now more resilient against exceptional conditions such as the missing - of all wind information and the missing of a course with its waypoints. If no wind information - is available at all (no wind direction indicator is then shown in the upper left corner of - the map) then all ranking and distances will be based on a projection onto the course instead - of onto the wind direction, even for upwind and downwind legs. -
  • -
- -
September 2014
- -
    -
  • The search feature now also includes results from currently ongoing events that may not yet be - included in our archive. Search keywords are now properly used in constructing the query. -
  • -
- -
August 2014
- -
    -
  • The 2D race viewer, also known as the "Race Board," now comes with a fresh, new design. The orange - checkbox toggle buttons that open or close views such as the leaderboard or the charts for wind - and competitor comparison, have been replaced by tabs with ">>" symbols. Clicking on those - will expand or collapse the respective view. The views can now be resized using the handles attached - to the dividers separating the views. They work much better on mobile and touch devices than the splitters - used previously did. The settings buttons that used to be integrated with the orange toggle - checkbox buttons have now been moved into the views that they control. For example, the map settings - button is now displayed on the map, below the zoom control on the right map border. -
  • -
  • The leaderboard now has an improved search and filter control. Above the table displaying the - competitors and their figures is a new field with a text input that you can use to filter for - competitors, by their sail number or their name. While filtered, use the checkboxes in front of - the table row to add the competitor to or remove it from the selection. Use the "X" button to the - right of the search input field to clear the search. To the left of the search input field is a - filter symbol that you can use to select and create advanced filtering rules, such as filtering - by rank or nationality. Left of the filter button is the leaderboard settings button. -
  • -
  • The leaderboard has a new first column: a selection check box. We hope this makes it easier in - particular for users on mobile or other touch devices to select more than one competitor at a time. - The old-style multi-selection using the Control and Shift keys, as known well from typical desktop - file explorers, still work like they did before. Note that it is possible to sort for the checkbox - column, putting the selected competitors at the top of the leaderboard. -
  • -
  • When using the auto-zoom feature from the map settings, boats and wind streamlets will now - continue to move smoothly as long as the map only needs panning. Please also note that auto-zooming - to "tails" may slow down the display considerable, particularly when tracking at high frequency. -
  • -
  • When viewing a single race, the leaderboard now by default does no longer show the regatta rank as - the first column (and not as the second one either, given that the first column now usually shows - the checkboxes used for selecting items). If you'd like to get the regatta rank column back, also when - looking at a single race, please choose it from the leaderboard settings dialog where you can find it - in the "Overall Details" section. It may still be a nice column to have when following the last race - in a regatta. If you're just interested in the relative regatta rank ordering you may as well sort by - the right-most total points column which (surprising to some but welcome by most) sorts by the regatta - rank and not by the plain points sum (taking into account medal race and gold/silver/... fleet participations). -
  • -
- -
July 2014
- -
    -
  • The advantage line now uses the wind at the position in the middle of the leg that the - competitor to which the line is attached is currently sailing in. Before, the "global" wind - average was used which is still displayed in the top left corner of the map. You can understand - the details by turning on the "Streamlet" wind visualization in the Map Settings. -
  • -
  • Faster wind streamlet loading: when you activate the streamlets for wind visualization, they now - display much faster. -
  • -
  • Faster boat position display: We found that what you're probably the most interested in when - you first open a race map or move the time slider to some very different point in time is the - position of the boats at that point in time; and you want to know it fast. - The tails which show how the boats got there are also interesting, but you won't blame us as much - if it takes a little bit to update them. So we've separated the placement of the boats from the - drawing of their tails. Now you may blame us for the tails temporarily not being attached to the - boats anymore ;-). -
  • -
- -
June 2014
- -
    -
  • In the "Maps" settings in the RaceBoard page there is a new checkbox named - "Show wind streamlets overlay." If you select it and wait for about a minute, - a complete wind field will be calculated and visualized as an overlay on top - of the race course display. It reacts to you moving the time slider and shows - how the wind differs at different locations on the course. Stronger and faster-moving - streamlets mean stronger breeze. -
  • -
  • Wind is now calculated location-based. At locations closer to a sensor, that sensor - has a higher influence on the local wind field than sensors further away. The wind - estimations based on the courses sailed are assigned a location that corresponds with - the "center of gravity" of the field that was used for the estimation. For example, - if the fleet is approaching the windward mark and the wind sensor in on the committee - boat on the leeward side of the course, the course-based estimation influences the - assumed wind field more on the windward side whereas the sensor counts more for - the leeward side. -
  • -
  • Switched to the latest version of the Highcharts charting framework. This leads to improvements - especially on mobile devices. Charts can be zoomed using pinch gestures now. -
  • -
  • To support the use of the SAP Sailing Analytics also for live video streaming formats, we - introduced a new URL parameter viewShowMapControls for the Spectator.html - and the RaceBoard.html pages. Setting this parameter to "false" - will suppress the zoom, pan and map type selection - controls on the map display. Example: - http://danishleague2014.sapsailing.com/gwt/Spectator.html?leaderboardGroupName=Danish%20League%202014&showRaceDetails=true&viewShowMapControls=false. - When used for the Spectator.html URL, this will apply - to all RaceBoard.html pages (all races) reached from there. Of course, the map - can still be panned and zoomed using the usual mouse gestures. A left double click zooms - in, a right double click zooms out. Zoom can also be controlled using the mouse wheel. - And panning works by clicking on the map and dragging the mouse. Without the map type - control, switching to satellite view is not possible (keep this in mind when tracking - races in China, see below for Google's random coordinate transformations there). -
  • -
- -
May 2014
- -
    -
  • Fixed an issue with the wind speed charts. Charts that only had a single, unchanged - wind speed crashed the browser. The solution scales the right hand side Y-axis denoting - the wind speed such that it always starts at 0kts. -
  • -
  • Analysis of tacks and jibes around mark passings has now been improved. Before, - a jibe followed by a tack that turns in the same direction (e.g., to port) so far - was always called a penalty maneuver. Now, if a mark passing separates such a tack - from such a jibe, no penalty is called anymore, and the two maneuvers are identified - correctly. -
  • -
  • Another note on maneuver analysis: we received questions regarding the maneuvers - involved in clearing an OCS. The SAP Sailing Analytics treat a clearing of - an OCS, going back behind the start line and crossing it again, as if the competitor - started again. In particular this means that all maneuvers prior to this new start - do not count for the metrics; neither does the distance sailed between the first (OCS) - start and the clear start. -
  • -
  • A hint regarding the "distance to start line" metrics: please keep in mind that currently this - measurement is calculated as the distance of the GPS tracker from the line. Unless the tracker - is mounted near the bow (or at the bow sprit, if any), the distance calculated this way will - be greater than what counts for crossing the line. Ordering, comparing and aggregating over this - figure still makes sense as long as you remember this detail. -
  • -
  • Introduced a new leaderboard entry "XTE +/-" featuring a signed cross-track error which shows - for a leg and also aggregated for an entire race on which side of the leg a competitor stayed on - average. Currently, the "side" is defined as viewing in the leg's direction, so "left" for a downwind - leg is the same side as "right" for the corresponding upwind leg. -
  • -
- -
April 2014
- -
    -
  • China races, such as in Qingdao, may have the map background displayed at slightly wrong locations. - This is due to an intentional random transformation that Google applies to GPS locations for - China. You can circumvent this issue by switching to satellite view where the map background is displayed - correctly. -
  • -
  • Fixed a bug that in some cases has caused the wind chart, the advantage line, the wind indicator on the map - and the leaderboard to use slightly different wind values. The problem was related to different averaging and - damping methods used for these values which has now been aligned. -
  • -
  • Fixed a bug that caused the time spent in a leg, race or regatta to always show the time at the end of the leg - if the leg has been started by the competitor at the time point queried, e.g., by the time slider. While this - did not have any serious effects in live mode, for replay races this left the leg time and race time constant - at the total time spent so far up to the end of the last leg the competitor had started at that time. -
  • -
- -
March 2014
- -
    -
  • Added a new setting for a leaderboard called "Show added scores". Using this feature one - can display added scores for each leaderboard entry. An added score is the sum over all scores - from the first column to the current column. One can describe it as an intermediate overall score. - This feature can be used to know the score until a specific race while another race is live and - constantly changes the overall score.
  • - -
  • Added tooltips for leaderboard settings.
  • - -
  • Fixed HighPointOverall scheme to also break a tie by looking at the ranks of the last regatta.
  • - -
  • Progress indicator when expanding a race in the RaceBoard view
  • - -
  • Leaderboard column "GPS Lag" shows how far a competitor's GPS signal lags behind the average - tracking quality. A background color bar classifies into good/ok/bad (green/yellow/red).
  • -
- -
February 2014
- -
    -
  • Fixed an issue with boat rotation on Safari browsers
  • - -
  • Maneuver analysis now counts tacks and jibes based on wind - at boat position and not based on leg type; subsequently, - penalty circle analysis is now based on a tack and a jibe - in close succession instead of a full circle.
  • - -
  • Regatta rank and overall rank in competitor chart of leaderboard panel - has been fixed; it did erroneously display the rank of the particular - race, not the regatta/overall rank after that race.
  • - -
  • Regatta overview now also displays all regatta leaderboards
  • - -
  • Boat colors match tail colors
  • - -
  • When selecting boats in leaderboard, de-selected boats' tails turn grey
  • - -
- - -
January 2014
- -
    -
  • Boat movement animated smoothly
  • - -
  • Start and Finish line show line parameters (length, angle to wind, - advantage) when mouse hovers over them
  • - -
  • Start line has a count-down indicator displayed next to it - before the start. The count-down is also displayed underneath the time - slider
  • - -
  • Competitor and Wind charts show pre-start data where possible
  • - -
  • Competitors can be assigned a fixed color which they will keep - for all races in a regatta
  • - -
  • By default, videos are now shown in a moveable, resizable box embedded in - the web page. For a two screen setup, the embedded box can be popped out to a - dedicated browser window.
  • - -
  • Official score corrections for historic races are only applied after - the respective competitor finished the race. Therefore, in-between race - scores now correspond with tracking, regardless of final corrected score.
  • - -
  • By using negative playback speed (e.g., -1), replays can be run backwards.
  • - -
-
-
- - + + + +
+

What's New - SAP Sailing Analytics

+
+
February 2016
+ +
    +
  • The website now features a user registration and authentication interface. + User accounts are currently used to grant special permissions to administrators and moderators. + New user specific features (e.g. preferences) will be available in the next couple of months. +
  • +
  • The RaceBoard URL Parameter "canReplayDuringLiveRaces" has been removed. + This parameter was used to allow users to trigger autoplay for live races on non-live points in time. + The permission "CAN_REPLAY_DURING_LIVE_RACES" and role "moderator" now grant this functionality to users. +
  • +
+ +
January 2016
+
    +
  • Show maneuver markers on the race board by default + (tacks, jibes and penalty circles) with a smaller icon, which + shows an info bubble when the marker is clicked. + The icon turns green if the direction change is to starboard + and red if to port. +
  • +
+ +
December 2015
+
    +
  • The advantage line is now animated and moves smoothly with the boats. +
  • +
  • New line hover behavior in race map. When the mouse is moved onto a line, for example the start line, a transparent, + wider line is activated behind it that acts as a buffer for the thin line, where the text displayed by the hover is still shown. + This makes it easier to hover over the lines. These wider lines can be made semi transparent instead of transparent + by unticking the corresponding checkbox in the settings of the race map. Furthermore the stroke weight of the wider lines can be + configured in the same settings dialog. +
  • +
  • The race viewer (RaceBoard.html) now intelligently chooses a layout that suits the screen size. + When only little horizontal space is available, only the sail number and nationality but not the + competitor's long name is displayed by default. When vertical space is scarce, competitor and wind + charts are disabled and more horizontal space can be given to the time slider at the bottom. The + leaderboard section can then be scaled to smaller widths and will reduce the column widths better + than in the past. +
  • +
  • With the changes described above, the RaceBoard is now also accessible from the races page on mobile devices. +
  • +
  • For overall / series leaderboards such as a national sailing league or the Extreme Sailing Series, the + live status of the overall leaderboard is now indicated. As long as a live race is ongoing, the respective + column in the overall leaderboard is highlighted, and a comment is displayed that indicates which regatta + is currently still live. +
  • +
+ +
November 2015
+ +
    +
  • The smartphone page provides some structural navigation items for several pages in the upper right burger menu. + You will see links to e.g. events, regattas and series when navigating on event and series pages. +
  • +
  • It is now possible to filter for competitors in the race list of events/regattas. + If competitor information is available, there is a filter box in the upper right corner of the races page. + The filter is searching for competitors by sail ID as well as the competitor's name. +
  • +
  • Regattas can now be filtered by boat category in the smartphone page. + The filter will be shown for events with multiple regattas if there is more than on boat category associated with the event. +
  • +
+ +
October 2015
+ +
    +
  • A variety of tablets will now show the desktop page by default. + The mobile version of the website is primarily designed to be used on smartphones, + but you can manually switch back to the mobile version by clicking the corresponding link in the page footer. +
  • +
  • There is some amount of caching on the web page to reduce the consumed traffic for mobile users. + Contents aren't loaded again on each page switch. This improves the traffic consumption and loading speed on fast page switches. +
  • +
  • The fullscreen image viewer (start page and event media page) can automatically slide through the images. + This can be turned on by clicking the corresponding icon in the upper right corner of the fullscreen viewer. +
  • +
  • There is an optimized search and results page for mobile devices now. +
  • +
+ +
September 2015
+ +
    +
  • Races in the event/regatta race list can now be shown in 'competition format'. + In this format the races and flights are shown in a structural view. + In contrast to the default list view there is no grouping by live and finished states and all + (including upcoming) races/flights are shown in one structural view. +
  • +
  • The mobile page now provides regatta overview pages for events having multiple regattas. + This page shows live races, an excerpt of the current results as well as statistics for the regatta. +
  • +
+ +
August 2015
+ +
    +
  • Series events appear as only one entry in the events list, with a marker that + this is only one of a certain number of events in a series. This way, the many series events + don't produce clutter in the events list. +
  • +
  • Bug fix: memory leaks for distance cache have been solved. The issue could + also lead to endless recursions, ultimately leading to server lock-ups. +
  • +
  • Bug fix: master data import detached race logs and regatta logs from database. + Log entries added after import on the importing server were not written to the + database and therefore were lost upon server restart. +
  • +
  • There is a smartphone-optimized version of the "solutions" page known from the desktop. +
  • +
  • The smartphone event history now has a slider that allows swiping through the events of a year. +
  • +
+ +
July 2015
+ +
    +
  • Major improvements to the web page, with specific enhancements for smartphone + users. Race lists are now sortable by various criteria by clicking on the column + headers. A new fancy progress indicator now also provides visual feedback for + multi-fleet regattas. A news ticker box has been implemented, and the event + overview page can hold a video player on its stage. The event media gallery section + has been greatly improved. +
  • +
  • Fixed a bug in the wind streamlet visualization. Now the wind streamlets + correctly show the wind at the location selected also in wind-up mode. +
  • +
  • Added the "Course Geometry" option to the map display. With this option selected, + the map will show an info text for each leg and the start and finish line (only + for one of start/finish line if they are identical), telling the length of the leg + or line, respectively, and its angle to the wind. For the start and finish line + the advantage of the favored side is shown in meters. +
  • +
  • The SAP Sailing Analytics start page is now available in the smartphone version. + This page features some events that are currently interesting as well as showing a + quickfinder for a variety of recent and upcoming events. + Previously, the start page redirected to the event history. +
  • +
+ +
May 2015
+ +
    +
  • Competitors can have a separate flag image, such as a club flag to be displayed instead of + the nationality flag usually displayed with the sail number. This enables national league events + to display the club flags consistently when all nation flags would be the same anyway. +
  • +
  • The wind estimation from the tracked courses over ground has been improved. It now takes into + account any polar data available for the boat class concerned. In particular, this helps to rule + out very unlikely gybing angles in downwind clusters that otherwise could have led to an incorrect + split of the downwind fleet into two clusters where actually all boats were on the same tack. +
  • +
  • Some significant improvements have been applied to the simulator feature which is embedded in the + race viewer since some time now. The simulator now copes with very shifty wind conditions and finds + solutions in scenarios where an upwind leg flips to a reach or even into a downwind leg over time. +
  • +
+ +
April 2015
+ +
    +
  • There is a new map setting "Wind-Up (show wind from top of map)". Selecting it will + align the map's top with the combined true wind average direction around the time currently + selected in the time slider. In this new view there are limitations as to how far you can zoom + out. Furthermore, you will not be able to use the Satellite view with this setting. Tip: + if you want to re-align to wind-up after a major wind shift, un-check the setting, confirm + the setting change, then set it again. A compass shows the true north orientation. Clicking + the compass will toggle between wind-up and north-up display. +
  • +
  • Bug fixes around addition of the "Regatta Rank" column in the leaderboard which could have + distorted the leaderboard's column layout under certain conditions. +
  • +
  • Bug fix for cumulative points in the leaderboard ("Show added scores for each entry in leaderboard"). + With this setting, scores of competitors not tracked in the current race were not correctly represented + and may have stayed blank. +
  • +
  • Bug fix for the leg counter in the regatta page: when the first boat has finished, the leg counter went + to zero (e.g., "0 of 8"). This has now been fixed, and it will show, e.g., "8 of 8" upon the first boat + crossing the finish line. +
  • +
+ +
March 2015
+ +
    +
  • Added competitor chart type for Course Over Ground (COG) +
  • +
  • Added leaderboard column and competitor chart entry for distances considering + gate starts. With gate starts, late starters sail a shorter distance in their first + leg. To still make distances comparable, a new metric has been introduced that for a gate + start adds the distance between the port side of the start line and the position where + the competitor started to the distance sailed in the first leg. +
  • +
  • The weights of the wind measurement units, the wind estimation and manual wind inputs by the + race committee are now used properly for the wind streamlet visualization. This fixes issues + with exaggerated weights for an estimated wind direction of very low confidence. +
  • +
  • The expand/collapse toggle button in the race viewer's time panel has correct arrows now. +
  • +
+ +
February 2015
+ +
    +
  • The leaderboard offers a new column: "Start delay." It shows the number of seconds that passed + since the race start and the time the competitor passes the start mark / start line. As usual, + you can sort for this column. For line starts, this is a fairly direct measure of start quality + except for port starts which may have to be considered differently. For gate starts, you can use + this measure to find out about early and late starters and dig into possible correlations between + results and start time point. +
  • +
+ +
January 2015
+ +
    +
  • The race viewer ("RaceBoard.html") now offers a new option in the map settings: + "Show simulation overlay". Checking this feature will simulate the current leader's leg + using different strategies and using the wind as it has been measured and estimated. + This feature becomes particularly interesting when combined with the "Show wind streamlets overlay" + feature that visualizes the spatial distribution of the wind field over the course. +
  • +
  • The race viewer is now more resilient against exceptional conditions such as the missing + of all wind information and the missing of a course with its waypoints. If no wind information + is available at all (no wind direction indicator is then shown in the upper left corner of + the map) then all ranking and distances will be based on a projection onto the course instead + of onto the wind direction, even for upwind and downwind legs. +
  • +
+ +
September 2014
+ +
    +
  • The search feature now also includes results from currently ongoing events that may not yet be + included in our archive. Search keywords are now properly used in constructing the query. +
  • +
+ +
August 2014
+ +
    +
  • The 2D race viewer, also known as the "Race Board," now comes with a fresh, new design. The orange + checkbox toggle buttons that open or close views such as the leaderboard or the charts for wind + and competitor comparison, have been replaced by tabs with ">>" symbols. Clicking on those + will expand or collapse the respective view. The views can now be resized using the handles attached + to the dividers separating the views. They work much better on mobile and touch devices than the splitters + used previously did. The settings buttons that used to be integrated with the orange toggle + checkbox buttons have now been moved into the views that they control. For example, the map settings + button is now displayed on the map, below the zoom control on the right map border. +
  • +
  • The leaderboard now has an improved search and filter control. Above the table displaying the + competitors and their figures is a new field with a text input that you can use to filter for + competitors, by their sail number or their name. While filtered, use the checkboxes in front of + the table row to add the competitor to or remove it from the selection. Use the "X" button to the + right of the search input field to clear the search. To the left of the search input field is a + filter symbol that you can use to select and create advanced filtering rules, such as filtering + by rank or nationality. Left of the filter button is the leaderboard settings button. +
  • +
  • The leaderboard has a new first column: a selection check box. We hope this makes it easier in + particular for users on mobile or other touch devices to select more than one competitor at a time. + The old-style multi-selection using the Control and Shift keys, as known well from typical desktop + file explorers, still work like they did before. Note that it is possible to sort for the checkbox + column, putting the selected competitors at the top of the leaderboard. +
  • +
  • When using the auto-zoom feature from the map settings, boats and wind streamlets will now + continue to move smoothly as long as the map only needs panning. Please also note that auto-zooming + to "tails" may slow down the display considerable, particularly when tracking at high frequency. +
  • +
  • When viewing a single race, the leaderboard now by default does no longer show the regatta rank as + the first column (and not as the second one either, given that the first column now usually shows + the checkboxes used for selecting items). If you'd like to get the regatta rank column back, also when + looking at a single race, please choose it from the leaderboard settings dialog where you can find it + in the "Overall Details" section. It may still be a nice column to have when following the last race + in a regatta. If you're just interested in the relative regatta rank ordering you may as well sort by + the right-most total points column which (surprising to some but welcome by most) sorts by the regatta + rank and not by the plain points sum (taking into account medal race and gold/silver/... fleet participations). +
  • +
+ +
July 2014
+ +
    +
  • The advantage line now uses the wind at the position in the middle of the leg that the + competitor to which the line is attached is currently sailing in. Before, the "global" wind + average was used which is still displayed in the top left corner of the map. You can understand + the details by turning on the "Streamlet" wind visualization in the Map Settings. +
  • +
  • Faster wind streamlet loading: when you activate the streamlets for wind visualization, they now + display much faster. +
  • +
  • Faster boat position display: We found that what you're probably the most interested in when + you first open a race map or move the time slider to some very different point in time is the + position of the boats at that point in time; and you want to know it fast. + The tails which show how the boats got there are also interesting, but you won't blame us as much + if it takes a little bit to update them. So we've separated the placement of the boats from the + drawing of their tails. Now you may blame us for the tails temporarily not being attached to the + boats anymore ;-). +
  • +
+ +
June 2014
+ +
    +
  • In the "Maps" settings in the RaceBoard page there is a new checkbox named + "Show wind streamlets overlay." If you select it and wait for about a minute, + a complete wind field will be calculated and visualized as an overlay on top + of the race course display. It reacts to you moving the time slider and shows + how the wind differs at different locations on the course. Stronger and faster-moving + streamlets mean stronger breeze. +
  • +
  • Wind is now calculated location-based. At locations closer to a sensor, that sensor + has a higher influence on the local wind field than sensors further away. The wind + estimations based on the courses sailed are assigned a location that corresponds with + the "center of gravity" of the field that was used for the estimation. For example, + if the fleet is approaching the windward mark and the wind sensor in on the committee + boat on the leeward side of the course, the course-based estimation influences the + assumed wind field more on the windward side whereas the sensor counts more for + the leeward side. +
  • +
  • Switched to the latest version of the Highcharts charting framework. This leads to improvements + especially on mobile devices. Charts can be zoomed using pinch gestures now. +
  • +
  • To support the use of the SAP Sailing Analytics also for live video streaming formats, we + introduced a new URL parameter viewShowMapControls for the Spectator.html + and the RaceBoard.html pages. Setting this parameter to "false" + will suppress the zoom, pan and map type selection + controls on the map display. Example: + http://danishleague2014.sapsailing.com/gwt/Spectator.html?leaderboardGroupName=Danish%20League%202014&showRaceDetails=true&viewShowMapControls=false. + When used for the Spectator.html URL, this will apply + to all RaceBoard.html pages (all races) reached from there. Of course, the map + can still be panned and zoomed using the usual mouse gestures. A left double click zooms + in, a right double click zooms out. Zoom can also be controlled using the mouse wheel. + And panning works by clicking on the map and dragging the mouse. Without the map type + control, switching to satellite view is not possible (keep this in mind when tracking + races in China, see below for Google's random coordinate transformations there). +
  • +
+ +
May 2014
+ +
    +
  • Fixed an issue with the wind speed charts. Charts that only had a single, unchanged + wind speed crashed the browser. The solution scales the right hand side Y-axis denoting + the wind speed such that it always starts at 0kts. +
  • +
  • Analysis of tacks and jibes around mark passings has now been improved. Before, + a jibe followed by a tack that turns in the same direction (e.g., to port) so far + was always called a penalty maneuver. Now, if a mark passing separates such a tack + from such a jibe, no penalty is called anymore, and the two maneuvers are identified + correctly. +
  • +
  • Another note on maneuver analysis: we received questions regarding the maneuvers + involved in clearing an OCS. The SAP Sailing Analytics treat a clearing of + an OCS, going back behind the start line and crossing it again, as if the competitor + started again. In particular this means that all maneuvers prior to this new start + do not count for the metrics; neither does the distance sailed between the first (OCS) + start and the clear start. +
  • +
  • A hint regarding the "distance to start line" metrics: please keep in mind that currently this + measurement is calculated as the distance of the GPS tracker from the line. Unless the tracker + is mounted near the bow (or at the bow sprit, if any), the distance calculated this way will + be greater than what counts for crossing the line. Ordering, comparing and aggregating over this + figure still makes sense as long as you remember this detail. +
  • +
  • Introduced a new leaderboard entry "XTE +/-" featuring a signed cross-track error which shows + for a leg and also aggregated for an entire race on which side of the leg a competitor stayed on + average. Currently, the "side" is defined as viewing in the leg's direction, so "left" for a downwind + leg is the same side as "right" for the corresponding upwind leg. +
  • +
+ +
April 2014
+ +
    +
  • China races, such as in Qingdao, may have the map background displayed at slightly wrong locations. + This is due to an intentional random transformation that Google applies to GPS locations for + China. You can circumvent this issue by switching to satellite view where the map background is displayed + correctly. +
  • +
  • Fixed a bug that in some cases has caused the wind chart, the advantage line, the wind indicator on the map + and the leaderboard to use slightly different wind values. The problem was related to different averaging and + damping methods used for these values which has now been aligned. +
  • +
  • Fixed a bug that caused the time spent in a leg, race or regatta to always show the time at the end of the leg + if the leg has been started by the competitor at the time point queried, e.g., by the time slider. While this + did not have any serious effects in live mode, for replay races this left the leg time and race time constant + at the total time spent so far up to the end of the last leg the competitor had started at that time. +
  • +
+ +
March 2014
+ +
    +
  • Added a new setting for a leaderboard called "Show added scores". Using this feature one + can display added scores for each leaderboard entry. An added score is the sum over all scores + from the first column to the current column. One can describe it as an intermediate overall score. + This feature can be used to know the score until a specific race while another race is live and + constantly changes the overall score.
  • + +
  • Added tooltips for leaderboard settings.
  • + +
  • Fixed HighPointOverall scheme to also break a tie by looking at the ranks of the last regatta.
  • + +
  • Progress indicator when expanding a race in the RaceBoard view
  • + +
  • Leaderboard column "GPS Lag" shows how far a competitor's GPS signal lags behind the average + tracking quality. A background color bar classifies into good/ok/bad (green/yellow/red).
  • +
+ +
February 2014
+ +
    +
  • Fixed an issue with boat rotation on Safari browsers
  • + +
  • Maneuver analysis now counts tacks and jibes based on wind + at boat position and not based on leg type; subsequently, + penalty circle analysis is now based on a tack and a jibe + in close succession instead of a full circle.
  • + +
  • Regatta rank and overall rank in competitor chart of leaderboard panel + has been fixed; it did erroneously display the rank of the particular + race, not the regatta/overall rank after that race.
  • + +
  • Regatta overview now also displays all regatta leaderboards
  • + +
  • Boat colors match tail colors
  • + +
  • When selecting boats in leaderboard, de-selected boats' tails turn grey
  • + +
+ + +
January 2014
+ +
    +
  • Boat movement animated smoothly
  • + +
  • Start and Finish line show line parameters (length, angle to wind, + advantage) when mouse hovers over them
  • + +
  • Start line has a count-down indicator displayed next to it + before the start. The count-down is also displayed underneath the time + slider
  • + +
  • Competitor and Wind charts show pre-start data where possible
  • + +
  • Competitors can be assigned a fixed color which they will keep + for all races in a regatta
  • + +
  • By default, videos are now shown in a moveable, resizable box embedded in + the web page. For a two screen setup, the embedded box can be popped out to a + dedicated browser window.
  • + +
  • Official score corrections for historic races are only applied after + the respective competitor finished the race. Therefore, in-between race + scores now correspond with tracking, regardless of final corrected score.
  • + +
  • By using negative playback speed (e.g., -1), replays can be run backwards.
  • + +
+
+
+ + diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/maneuver_green.png b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/maneuver_green.png new file mode 100644 index 00000000000..ce6e5a48219 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/maneuver_green.png differ diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/maneuver_red.png b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/maneuver_red.png new file mode 100644 index 00000000000..cb2c7fb4c16 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/maneuver_red.png differ diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/timeslider-speed.png b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/timeslider-speed.png index 42c030f673a..defdfea3468 100644 Binary files a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/timeslider-speed.png and b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/timeslider-speed.png differ diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/RegattaStructureManagementPanelPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/RegattaStructureManagementPanelPO.java index 774ba59ebfa..8027a05948c 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/RegattaStructureManagementPanelPO.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/RegattaStructureManagementPanelPO.java @@ -9,7 +9,7 @@ import com.sap.sailing.selenium.pages.PageArea; import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaListCompositePO.RegattaDescriptor; public class RegattaStructureManagementPanelPO extends PageArea { - public static final String DEFAULT_SERIES_NAME = "Default"; //$NON-NLS-1$ + public static final String DEFAULT_SERIES_NAME = "DefaultSelenium"; //$NON-NLS-1$ @FindBy(how = BySeleniumId.class, using = "AddRegattaButton") WebElement addRegattaButton; diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestSmartphoneTrackingEventManagementPanel.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestSmartphoneTrackingEventManagementPanel.java index 316460cbcd5..7b8a8e38f18 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestSmartphoneTrackingEventManagementPanel.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestSmartphoneTrackingEventManagementPanel.java @@ -57,7 +57,7 @@ public class TestSmartphoneTrackingEventManagementPanel extends AbstractSelenium String raceName = String.format(RACE, i); TrackableRaceDescriptor trackableRace = new TrackableRaceDescriptor(EVENT, raceName, BOAT_CLASS); TrackedRaceDescriptor trackedRace = new TrackedRaceDescriptor(this.regatta.toString(), BOAT_CLASS, raceName); - RaceDescriptor leaderboardRace = new RaceDescriptor(String.format("R%s", i), "Default", false, false, 0); + RaceDescriptor leaderboardRace = new RaceDescriptor(String.format("D%s", i), "Default", false, false, 0); this.trackableRaces.add(trackableRace); this.trackedRaces.add(trackedRace); diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestColumnsInLeaderboard.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestColumnsInLeaderboard.java index fe6b53483e2..6258ba90338 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestColumnsInLeaderboard.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestColumnsInLeaderboard.java @@ -50,7 +50,7 @@ public class TestColumnsInLeaderboard extends AbstractSeleniumTest { this.regatta = new RegattaDescriptor(REGATTA, BOAT_CLASS); this.trackableRace = new TrackableRaceDescriptor(EVENT, RACE, BOAT_CLASS); this.trackedRace = new TrackedRaceDescriptor(this.regatta.toString(), BOAT_CLASS, RACE); - this.raceColumn = new RaceDescriptor("R1", "Default", false, false, 0.0); + this.raceColumn = new RaceDescriptor("D1", "Default", false, false, 0.0); clearState(getContextRoot()); super.setUp(); configureLeaderboard(); diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestLeaderboardConfiguration.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestLeaderboardConfiguration.java index e138920caad..32b7500e357 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestLeaderboardConfiguration.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestLeaderboardConfiguration.java @@ -60,7 +60,7 @@ public class TestLeaderboardConfiguration extends AbstractSeleniumTest { String raceName = String.format(RACE, i); TrackableRaceDescriptor trackableRace = new TrackableRaceDescriptor(EVENT, raceName, BOAT_CLASS); TrackedRaceDescriptor trackedRace = new TrackedRaceDescriptor(this.regatta.toString(), BOAT_CLASS, raceName); - RaceDescriptor leaderboardRace = new RaceDescriptor(String.format("R%s", i), "Default", false, false, 0); + RaceDescriptor leaderboardRace = new RaceDescriptor(String.format("D%s", i), "Default", false, false, 0); this.trackableRaces.add(trackableRace); this.trackedRaces.add(trackedRace); @@ -100,12 +100,12 @@ public class TestLeaderboardConfiguration extends AbstractSeleniumTest { leaderboard.refresh(); List allEntries = table.getEntries(); LeaderboardEntry findelJens = table.getEntry("8875"); - Integer points = findelJens.getPointsForRace(String.format("R%s", i + 1)); + Integer points = findelJens.getPointsForRace(String.format("D%s", i + 1)); Integer rank = findelJens.getTotalRank(); // Assertions assertThat("Number of competitors does not match", allEntries.size(), equalTo(28)); - assertThat("Points for race 'R" + (i + 1) + "' do not match for competitor '8875' (Findel, Jens)", + assertThat("Points for race 'D" + (i + 1) + "' do not match for competitor '8875' (Findel, Jens)", points, equalTo(expectedPointsForFindelJens[i])); assertThat("Total rank after " + (i + 1) + " race(s) does not match for competitor '8875' (Findel, Jens)", rank, equalTo(expectedRankForFindelJens[i])); @@ -136,13 +136,13 @@ public class TestLeaderboardConfiguration extends AbstractSeleniumTest { RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure(); RegattaDetailsCompositePO regattaDetails = regattaStructure.getRegattaDetails(this.regatta); SeriesEditDialogPO seriesDialog = regattaDetails.editSeries(RegattaStructureManagementPanelPO.DEFAULT_SERIES_NAME); - seriesDialog.deleteRace("R3"); + seriesDialog.deleteRace("D3"); seriesDialog.pressOk(true); // Now we can check the result with our expectation leaderboardWindow.switchToWindow(); leaderboard.refresh(); - assertThat("Race names do not match after deletion of race 'R3'", - table.getRaceNames(), equalTo(Arrays.asList("R1", "R2", "R4", "R5"))); + assertThat("Race names do not match after deletion of race 'D3'", + table.getRaceNames(), equalTo(Arrays.asList("D1", "D2", "D4", "D5"))); } @Ignore("This test belongs to bug 1892 and currently fails. It is currently enabled on branch bug1892.") @@ -175,15 +175,15 @@ public class TestLeaderboardConfiguration extends AbstractSeleniumTest { RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure(); RegattaDetailsCompositePO regattaDetails = regattaStructure.getRegattaDetails(this.regatta); SeriesEditDialogPO seriesDialog = regattaDetails.editSeries(RegattaStructureManagementPanelPO.DEFAULT_SERIES_NAME); - seriesDialog.renameRace("R1", "Q"); + seriesDialog.renameRace("D1", "Q"); seriesDialog.pressOk(true); // Now we can check the result with our expectation leaderboardWindow.switchToWindow(); leaderboard.refresh(); List races = table.getRaceNames(); - assertThat("Race names do not match after renaming race 'R1' to 'Q'", - races, equalTo(Arrays.asList("Q", "R2", "R3", "R4", "R5"))); + assertThat("Race names do not match after renaming race 'D1' to 'Q'", + races, equalTo(Arrays.asList("Q", "D2", "D3", "D4", "D5"))); } private void configureLeaderboard() { diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestSwitchingOffStartOfRaceInference.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestSwitchingOffStartOfRaceInference.java index 64af7f0bb6e..bd03dd17d59 100755 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestSwitchingOffStartOfRaceInference.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestSwitchingOffStartOfRaceInference.java @@ -54,7 +54,7 @@ public class TestSwitchingOffStartOfRaceInference extends AbstractSeleniumTest { this.regatta = new RegattaDescriptor(REGATTA, BOAT_CLASS); this.trackableRace = new TrackableRaceDescriptor(EVENT, RACE, BOAT_CLASS); this.trackedRace = new TrackedRaceDescriptor(this.regatta.toString(), BOAT_CLASS, RACE); - this.raceColumn = new RaceDescriptor("R3", "Default", false, false, 0.0); + this.raceColumn = new RaceDescriptor("D3", "Default", false, false, 0.0); clearState(getContextRoot()); super.setUp(); adminConsole = configureRegattaAndLeaderboard(); @@ -69,10 +69,10 @@ public class TestSwitchingOffStartOfRaceInference extends AbstractSeleniumTest { LeaderboardPage leaderboard = LeaderboardPage.goToPage(getWebDriver(), getContextRoot(), LEADERBOARD, /* race details */ false); LeaderboardTablePO leaderboardTable = leaderboard.getLeaderboardTable(); List races = leaderboardTable.getRaceNames(); - assertThat("Expected only R3", races, equalTo(Arrays.asList("R3"))); - int r3ColumnIndex = leaderboardTable.getColumnIndex("R3"); + assertThat("Expected only D3", races, equalTo(Arrays.asList("D3"))); + int d3ColumnIndex = leaderboardTable.getColumnIndex("D3"); for (LeaderboardEntry e : leaderboardTable.getEntries()) { - String raceColumnContent = e.getColumnContent(r3ColumnIndex); + String raceColumnContent = e.getColumnContent(d3ColumnIndex); assertTrue(Integer.parseInt(raceColumnContent) > 0); // all competitors have a positive score in R3 } adminConsoleWindow.switchToWindow(); @@ -85,7 +85,7 @@ public class TestSwitchingOffStartOfRaceInference extends AbstractSeleniumTest { leaderboardWindow.switchToWindow(); leaderboard.refresh(); for (LeaderboardEntry e : leaderboardTable.getEntries()) { - String raceColumnContent = e.getColumnContent(r3ColumnIndex); + String raceColumnContent = e.getColumnContent(d3ColumnIndex); assertEquals("", raceColumnContent); // all competitors have an empty score because there is no start time anymore } leaderboardWindow.close(); diff --git a/java/com.sap.sailing.www/release_notes_admin.html b/java/com.sap.sailing.www/release_notes_admin.html index 1264cc8b36e..1ed9c74f8d4 100644 --- a/java/com.sap.sailing.www/release_notes_admin.html +++ b/java/com.sap.sailing.www/release_notes_admin.html @@ -27,10 +27,19 @@

February 2016

    +
  • Several improvements regarding the creation of race metadata (events, regatta, etc.) including: + automatic creation of default series, dialog for creating a default leaderboard group +
  • The RaceBoard URL Parameter "canReplayDuringLiveRaces" has been removed. This parameter was used to allow users to trigger autoplay for live races on non-live points in time. The permission "CAN_REPLAY_DURING_LIVE_RACES" and role "moderator" now grant this functionality to users.
  • +
  • The "Manage Media" button in RegattaOverview is now bound to the Permission "MANAGE_MEDIA". + The Roles "eventmanager" and "mediaeditor" grant the "MANAGE_MEDIA" permission. +
  • +
  • The "Edit mark passings" button in RegattaOverview is now bound to the Permission "MANAGE_MARK_PASSINGS". + The Role "eventmanager" grants the "MANAGE_MARK_PASSINGS" permission. +
  • The user management page now provides a "Refresh" button to reload the user list.
  • The user management page now also lists sailing roles and permissions in the respective suggest boxes. diff --git a/java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/AmazonS3FileStorageServiceImpl.java b/java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/AmazonS3FileStorageServiceImpl.java index ff6fba44c4b..579370d34ef 100644 --- a/java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/AmazonS3FileStorageServiceImpl.java +++ b/java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/AmazonS3FileStorageServiceImpl.java @@ -37,7 +37,7 @@ public class AmazonS3FileStorageServiceImpl extends BaseFileStorageServiceImpl i private static final Logger logger = Logger.getLogger(AmazonS3FileStorageServiceImpl.class.getName()); - private static final String retrievalProtocol = "http"; + private static final String retrievalProtocol = "https"; private static final String regionRetrievalHost = "s3-eu-west-1.amazonaws.com"; private final FileStorageServicePropertyImpl accessId = new FileStorageServicePropertyImpl("accessId", false, diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/resources/css/CommonControls.css b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/resources/css/CommonControls.css index a30d6ccc9a7..ae26656e121 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/resources/css/CommonControls.css +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/resources/css/CommonControls.css @@ -330,7 +330,7 @@ body ::-webkit-scrollbar-track { } .gwt-MapSettingsButton { - margin-right: 30px; + margin-right: 10px; margin-top: 5px; border-top-left-radius: 25px; border-top-right-radius: 25px; diff --git a/java/com.tractrac.clientmodule/META-INF/MANIFEST.MF b/java/com.tractrac.clientmodule/META-INF/MANIFEST.MF index 5238374bdb5..d870aa3c9d3 100644 --- a/java/com.tractrac.clientmodule/META-INF/MANIFEST.MF +++ b/java/com.tractrac.clientmodule/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: TracTrac Client module Bundle-SymbolicName: com.tractrac.clientmodule -Bundle-Version: 3.1.3 +Bundle-Version: 3.1.5 Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ClassPath: ., lib/TracAPI.jar diff --git a/java/com.tractrac.clientmodule/README.txt b/java/com.tractrac.clientmodule/README.txt index 895702bd543..bb797ccce30 100644 --- a/java/com.tractrac.clientmodule/README.txt +++ b/java/com.tractrac.clientmodule/README.txt @@ -15,6 +15,31 @@ It contains also some files: - test.sh -> script that compiles the code in the src folder, creates the test.jar library and execute the code of the example. - Manifest.txt -> manifest used to create the test.jar file + +******************************************** +************* TracAPI 3.1.5 **************** +******************************************** +This is a final version. Only fixes bugs in the implementation + +Release date: 17/02/2016 +Build number: 11948 + + 1) Bugs + + - The bug of the previous release (3.1.2) was not fixed. + +******************************************** +************* TracAPI 3.1.4 **************** +******************************************** +This is a final version. Only fixes bugs in the implementation + +Release date: 15/02/2016 +Build number: 11938 + + 1) Bugs + + - An infinity loop has been detected in the thread that sends the application + messages (Repored by Axel Uhl, 12/02/2016) ******************************************** ************* TracAPI 3.1.3 **************** @@ -26,7 +51,7 @@ Build number: 11888 1) Bugs - - The bug of the previous release (3.1.3) was not fixed. + - The bug of the previous release (3.1.2) was not fixed. ******************************************** ************* TracAPI 3.1.2 **************** diff --git a/java/com.tractrac.clientmodule/lib/TracAPI-src.jar b/java/com.tractrac.clientmodule/lib/TracAPI-src.jar index 169fe555191..2599699c29f 100755 Binary files a/java/com.tractrac.clientmodule/lib/TracAPI-src.jar and b/java/com.tractrac.clientmodule/lib/TracAPI-src.jar differ diff --git a/java/com.tractrac.clientmodule/lib/TracAPI.jar b/java/com.tractrac.clientmodule/lib/TracAPI.jar index b2201015269..0b5d8926c2c 100644 Binary files a/java/com.tractrac.clientmodule/lib/TracAPI.jar and b/java/com.tractrac.clientmodule/lib/TracAPI.jar differ diff --git a/java/com.tractrac.clientmodule/pom.xml b/java/com.tractrac.clientmodule/pom.xml index 8628b049b63..93dc4d12afa 100755 --- a/java/com.tractrac.clientmodule/pom.xml +++ b/java/com.tractrac.clientmodule/pom.xml @@ -8,6 +8,6 @@ 1.0.0-SNAPSHOT com.tractrac.clientmodule - 3.1.3 + 3.1.5 eclipse-plugin diff --git a/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/ui/fragments/TrackingFragment.java b/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/ui/fragments/TrackingFragment.java index 8b590415975..234e535ff03 100644 --- a/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/ui/fragments/TrackingFragment.java +++ b/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/ui/fragments/TrackingFragment.java @@ -3,7 +3,6 @@ package com.sap.sailing.android.tracking.app.ui.fragments; import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; -import android.graphics.Color; import android.os.Build; import android.os.Bundle; import android.provider.Settings; @@ -16,9 +15,9 @@ import android.widget.TextView; import com.sap.sailing.android.shared.logging.ExLog; import com.sap.sailing.android.shared.services.sending.MessageSendingService.APIConnectivity; +import com.sap.sailing.android.shared.ui.customviews.SignalQualityIndicatorView; import com.sap.sailing.android.tracking.app.BuildConfig; import com.sap.sailing.android.tracking.app.R; -import com.sap.sailing.android.shared.ui.customviews.SignalQualityIndicatorView; import com.sap.sailing.android.tracking.app.services.TrackingService.GPSQuality; import com.sap.sailing.android.tracking.app.ui.activities.TrackingActivity; import com.sap.sailing.android.tracking.app.utils.AppPreferences; diff --git a/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/CirclePageIndicator.java b/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/CirclePageIndicator.java index f13bd459f75..2684cdc135e 100755 --- a/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/CirclePageIndicator.java +++ b/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/CirclePageIndicator.java @@ -384,13 +384,13 @@ public class CirclePageIndicator extends View implements PageIndicator { return; } if (mViewPager != null) { - mViewPager.setOnPageChangeListener(null); + mViewPager.clearOnPageChangeListeners(); } if (view.getAdapter() == null) { throw new IllegalStateException("ViewPager does not have adapter instance."); } mViewPager = view; - mViewPager.setOnPageChangeListener(this); + mViewPager.addOnPageChangeListener(this); invalidate(); } diff --git a/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/IconPageIndicator.java b/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/IconPageIndicator.java index 478bf4b4b08..16b601ca7b2 100755 --- a/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/IconPageIndicator.java +++ b/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/IconPageIndicator.java @@ -115,14 +115,14 @@ public class IconPageIndicator extends HorizontalScrollView implements PageIndic return; } if (mViewPager != null) { - mViewPager.setOnPageChangeListener(null); + mViewPager.clearOnPageChangeListeners(); } PagerAdapter adapter = view.getAdapter(); if (adapter == null) { throw new IllegalStateException("ViewPager does not have adapter instance."); } mViewPager = view; - view.setOnPageChangeListener(this); + view.addOnPageChangeListener(this); notifyDataSetChanged(); } diff --git a/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/LinePageIndicator.java b/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/LinePageIndicator.java index ec35a2aa54b..1f477f60981 100755 --- a/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/LinePageIndicator.java +++ b/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/LinePageIndicator.java @@ -296,13 +296,13 @@ public class LinePageIndicator extends View implements PageIndicator { } if (mViewPager != null) { // Clear us from the old pager. - mViewPager.setOnPageChangeListener(null); + mViewPager.clearOnPageChangeListeners(); } if (viewPager.getAdapter() == null) { throw new IllegalStateException("ViewPager does not have adapter instance."); } mViewPager = viewPager; - mViewPager.setOnPageChangeListener(this); + mViewPager.addOnPageChangeListener(this); invalidate(); } diff --git a/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/TabPageIndicator.java b/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/TabPageIndicator.java index d960f64f1d6..171bfe7b30d 100755 --- a/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/TabPageIndicator.java +++ b/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/TabPageIndicator.java @@ -196,14 +196,14 @@ public class TabPageIndicator extends HorizontalScrollView implements PageIndica return; } if (mViewPager != null) { - mViewPager.setOnPageChangeListener(null); + mViewPager.clearOnPageChangeListeners(); } final PagerAdapter adapter = view.getAdapter(); if (adapter == null) { throw new IllegalStateException("ViewPager does not have adapter instance."); } mViewPager = view; - view.setOnPageChangeListener(this); + view.addOnPageChangeListener(this); notifyDataSetChanged(); } diff --git a/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/TitlePageIndicator.java b/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/TitlePageIndicator.java index 4206f8bb15a..b527e132399 100755 --- a/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/TitlePageIndicator.java +++ b/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/TitlePageIndicator.java @@ -737,13 +737,13 @@ public class TitlePageIndicator extends View implements PageIndicator { return; } if (mViewPager != null) { - mViewPager.setOnPageChangeListener(null); + mViewPager.clearOnPageChangeListeners(); } if (view.getAdapter() == null) { throw new IllegalStateException("ViewPager does not have adapter instance."); } mViewPager = view; - mViewPager.setOnPageChangeListener(this); + mViewPager.addOnPageChangeListener(this); invalidate(); } diff --git a/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/UnderlinePageIndicator.java b/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/UnderlinePageIndicator.java index c5b609f03e4..d95f768a1cb 100755 --- a/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/UnderlinePageIndicator.java +++ b/mobile/com.sap.sailing.android.tracking.app/src/com/viewpagerindicator/UnderlinePageIndicator.java @@ -288,13 +288,13 @@ public class UnderlinePageIndicator extends View implements PageIndicator { } if (mViewPager != null) { // Clear us from the old pager. - mViewPager.setOnPageChangeListener(null); + mViewPager.clearOnPageChangeListeners(); } if (viewPager.getAdapter() == null) { throw new IllegalStateException("ViewPager does not have adapter instance."); } mViewPager = viewPager; - mViewPager.setOnPageChangeListener(this); + mViewPager.addOnPageChangeListener(this); invalidate(); post(new Runnable() { @Override diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/utils/BitmapHelper.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/utils/BitmapHelper.java index 650d4db268e..3eebba19c4b 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/utils/BitmapHelper.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/utils/BitmapHelper.java @@ -9,7 +9,6 @@ import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.Build; import android.support.annotation.AttrRes; -import android.support.annotation.ColorRes; import android.support.annotation.DrawableRes; import android.util.TypedValue; import android.view.View; diff --git a/mobile/google-android-support-v7-appcompat_lib/libs/android-support-v13.jar b/mobile/google-android-support-v7-appcompat_lib/libs/android-support-v13.jar new file mode 100644 index 00000000000..0d364e7452a Binary files /dev/null and b/mobile/google-android-support-v7-appcompat_lib/libs/android-support-v13.jar differ diff --git a/mobile/licensesdialog_lib/.gitignore b/mobile/licensesdialog_lib/.gitignore index 2f744e189d2..11119f91c64 100755 --- a/mobile/licensesdialog_lib/.gitignore +++ b/mobile/licensesdialog_lib/.gitignore @@ -28,4 +28,4 @@ gen-external-apklibs/ # Other # ######### .~lock* -tmp \ No newline at end of file +tmp diff --git a/mobile/licensesdialog_lib/de.psdev.licensesdialog/.classpath b/mobile/licensesdialog_lib/de.psdev.licensesdialog/.classpath new file mode 100755 index 00000000000..7330f706f01 --- /dev/null +++ b/mobile/licensesdialog_lib/de.psdev.licensesdialog/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/mobile/licensesdialog_lib/de.psdev.licensesdialog/.project b/mobile/licensesdialog_lib/de.psdev.licensesdialog/.project new file mode 100644 index 00000000000..27a0d6424e6 --- /dev/null +++ b/mobile/licensesdialog_lib/de.psdev.licensesdialog/.project @@ -0,0 +1,33 @@ + + + de.psdev.licensesdialog + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/mobile/licensesdialog_lib/de.psdev.licensesdialog/.settings/org.eclipse.jdt.core.prefs b/mobile/licensesdialog_lib/de.psdev.licensesdialog/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 00000000000..48ab4c6b113 --- /dev/null +++ b/mobile/licensesdialog_lib/de.psdev.licensesdialog/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/mobile/licensesdialog_lib/de.psdev.licensesdialog/project.properties b/mobile/licensesdialog_lib/de.psdev.licensesdialog/project.properties index 22e1c480410..58947f7e29a 100644 --- a/mobile/licensesdialog_lib/de.psdev.licensesdialog/project.properties +++ b/mobile/licensesdialog_lib/de.psdev.licensesdialog/project.properties @@ -11,5 +11,6 @@ #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt # Project target. -target=android-14 +target=android-22 android.library=true +android.library.reference.1=../../google-android-support-v7-appcompat_lib diff --git a/mobile/pom.xml b/mobile/pom.xml index b69d42e75ca..3c0da7945dc 100644 --- a/mobile/pom.xml +++ b/mobile/pom.xml @@ -26,7 +26,7 @@ - 22.1.1 + 22.2.1 7.5.0 ../android-keystore/STG-debug.jks diff --git a/wiki/ssl-support.md b/wiki/ssl-support.md new file mode 100644 index 00000000000..8c43fc1e1f1 --- /dev/null +++ b/wiki/ssl-support.md @@ -0,0 +1,49 @@ +# Supporting HTTPS / SSL + +On sapsailing.com, we have a security certificate installed. For root users its key is visible at `/etc/pki/tls/private/star_sapsailing_com.key`. The certicicate is at `/etc/pki/tls/certs/star_sapsailing_com.crt`. To enable SSL on a server, the module `mod_ssl` needs to be installed. Use ``yum install mod_ssl``. + +The `/etc/httpd/conf/httpd.conf` file must contain the following in order to ensure that the `ServerName` setting is respected for selecting the appropriate `VirtualHost` element: + +
    +    NameVirtualHost *:80
    +    NameVirtualHost *:443
    +
    + +When this is done, the server can use the following sequence of directives inside a <VirtualHost> element: + +
    +        SSLEngine  On
    +        SSLCertificateFile /etc/pki/tls/certs/star_sapsailing_com.crt
    +        SSLCertificateKeyFile /etc/pki/tls/private/star_sapsailing_com.key
    +
    + +A full-blown <VirtualHost> element in a rewrite macro in `000-macros.conf` then could look like this: + +``` + + + ServerName $HOSTNAME + + SSLEngine On + SSLCertificateFile /etc/pki/tls/certs/star_sapsailing_com.crt + SSLCertificateKeyFile /etc/pki/tls/private/star_sapsailing_com.key + + Use Headers + + RewriteEngine on + + RewriteCond %{REQUEST_URI} "^(/)?$" + RewriteRule ^(/)?$ "https://$HOSTNAME/gwt/Home.html?%{QUERY_STRING}#/event/:eventId=$EVENTUUID" [L,NE] + + Use Rewrite $IP $PORT + + +``` + +It can then be used inside the `001-events.conf` file like this + +``` +Use Event-SSL ssltest.sapsailing.com "f8087b3c-c641-4fda-bf8d-0bc2abe09e40" 172.31.22.239 8888 +``` + +Keep in mind that the certificate we have only is valid for `*.sapsailing.com` which does not include 2nd-level sub-domains such as a.b.sapsailing.com. \ No newline at end of file