Updates the competitor registration, note that requires to be passed the whole set every time it is called,
+and will perform a delta to the stored state. This will also allow to remove competitors
+
+Back to Web Service Overview
+
+
diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/eventCreateEvent.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/eventCreateEvent.html
index 0f9317d5776..7f7f3111e7e 100755
--- a/java/com.sap.sailing.server.gateway/webservices/api/v1/eventCreateEvent.html
+++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/eventCreateEvent.html
@@ -58,6 +58,7 @@ consumption of this service simple.
boatclassname must be provided if createretatta=true; can be the display name or an alias name of a boat class to
use for the new regatta
numberofraces tells how many races shall be created in the default series; by default the series remains empty
+
canBoatsOfCompetitorsChangePerRace If true, boats and competitors can change per race, also it is necessary to register them in this case for each race!
diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html
index 2b8218015f4..20ae273605d 100644
--- a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html
+++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html
@@ -133,6 +133,10 @@ name to make sure you get to the event you're interested in.
+
+Back to Web Service Overview
+
+
From a41d68571158efdcd4e21973ee90ca02eba2a4a8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kai=20B=C3=B6rnert?=
Date: Wed, 11 Jul 2018 13:12:59 +0200
Subject: [PATCH 011/197] bug4508 fixed typo in documentation link
---
.../webservices/api/v1/index.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html
index 20ae273605d..f38a50d8dbf 100644
--- a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html
+++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html
@@ -265,7 +265,7 @@ name to make sure you get to the event you're interested in.
Allows to create a Coursedefinition that is then inserted into the racelog
From 84af394f30f5a35ba52c4081f1a1c091cffe8bb2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kai=20B=C3=B6rnert?=
Date: Thu, 19 Jul 2018 18:39:14 +0200
Subject: [PATCH 012/197] bug4508 fixed parameter eventname actually being
eventName in documentation of api
---
.../webservices/api/v1/eventCreateEvent.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/eventCreateEvent.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/eventCreateEvent.html
index 7f7f3111e7e..f2ed5192668 100755
--- a/java/com.sap.sailing.server.gateway/webservices/api/v1/eventCreateEvent.html
+++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/eventCreateEvent.html
@@ -38,7 +38,7 @@ consumption of this service simple.
Optional parameters:
-
eventname name of the event; defaults to a name constructed from the user name
+
eventName name of the event; defaults to a name constructed from the user name
and a timestamp
eventdescription the event description text; defaults to the event name
startdate the event start date in ISO format (e.g., 2017-08-17T10:00:00+0200)
From f8de09726d5b4f85c71e5d5549d31db31ec6aaee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kai=20B=C3=B6rnert?=
Date: Fri, 20 Jul 2018 08:32:29 +0200
Subject: [PATCH 013/197] bug4508 replaced tabs with spaces
---
.../v1/regattasCompetitorsCreateAndAdd.html | 70 +++++++++----------
1 file changed, 35 insertions(+), 35 deletions(-)
diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/regattasCompetitorsCreateAndAdd.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/regattasCompetitorsCreateAndAdd.html
index d98ee361996..48495d4a607 100755
--- a/java/com.sap.sailing.server.gateway/webservices/api/v1/regattasCompetitorsCreateAndAdd.html
+++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/regattasCompetitorsCreateAndAdd.html
@@ -1,11 +1,11 @@
-
-
-
-
- SAP Sailing Analytics Webservices API Version 1.0
+
+
+
+
+ SAP Sailing Analytics Webservices API Version 1.0
SAP Sailing Analytics Webservices API Version 1.0
@@ -17,36 +17,36 @@ parameter; defaults will be obtained from the authenticated user invoking the se
All slashes contained within the {regattaname} parameter must be replaced by "__" (double underscore).
-
-
Webservice Type:
-
POST
-
-
-
Output format:
-
The competitor as a JSON document
-
-
-
Mandatory parameters:
-
boatclass the name of the competitor's boat class
-
-
-
Optional parameters:
-
-
sailid the sail number to use
-
nationalityIOC three-letter IOC country code
-
timeontimefactor a double value telling the ToT / TMF / time-on-time factor for handicap racing
-
timeondistanceallowancepernauticalmileasmillis distance-based allowance in milliseconds for handicap racing (ToD)
-
searchtag a search tag for the competitor
-
-
-
-
Request method:
-
POST
-
-
-
Example:
-
curl -X POST -H "Authorization: Bearer KMTuXevrA0CYyM6O1W2E0QB9gVeP8tIpgjafJOvj/6A=" "http://127.0.0.1:8888/sailingserver/api/v1/regattas/Smartphone%20Tracking%20Test%2022.06/competitors/createandadd?boatclass=49er&sailid=GER+123&nationalityIOC=GER"
-
+
+
Webservice Type:
+
POST
+
+
+
Output format:
+
The competitor as a JSON document
+
+
+
Mandatory parameters:
+
boatclass the name of the competitor's boat class
+
+
+
Optional parameters:
+
+
sailid the sail number to use
+
nationalityIOC three-letter IOC country code
+
timeontimefactor a double value telling the ToT / TMF / time-on-time factor for handicap racing
+
timeondistanceallowancepernauticalmileasmillis distance-based allowance in milliseconds for handicap racing (ToD)
+
searchtag a search tag for the competitor
+
+
+
+
Request method:
+
POST
+
+
+
Example:
+
curl -X POST -H "Authorization: Bearer KMTuXevrA0CYyM6O1W2E0QB9gVeP8tIpgjafJOvj/6A=" "http://127.0.0.1:8888/sailingserver/api/v1/regattas/Smartphone%20Tracking%20Test%2022.06/competitors/createandadd?boatclass=49er&sailid=GER+123&nationalityIOC=GER"
+
Back to Web Service Overview
From 73e51b7ed8cde08bec2e58517fa96a271e090075 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kai=20B=C3=B6rnert?=
Date: Fri, 20 Jul 2018 08:48:18 +0200
Subject: [PATCH 014/197] bug4508 added new parameters competitorName and
competitorEmail, fixed formating, fixed unnecessary hard cast
---
.../gateway/jaxrs/api/RegattasResource.java | 468 ++++++++++--------
.../v1/regattasCompetitorsCreateAndAdd.html | 2 +
2 files changed, 271 insertions(+), 199 deletions(-)
diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java
index d2210c0f412..a904600be20 100644
--- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java
+++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java
@@ -35,7 +35,6 @@ import org.json.simple.JSONValue;
import org.json.simple.parser.ParseException;
import com.sap.sailing.datamining.SailingPredefinedQueries;
-import com.sap.sailing.domain.base.Boat;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorWithBoat;
import com.sap.sailing.domain.base.Course;
@@ -131,7 +130,7 @@ public class RegattasResource extends AbstractSailingServerResource {
private static final Logger logger = Logger.getLogger(RegattasResource.class.getName());
private DataMiningResource dataMiningResource;
-
+
private DataMiningResource getDataMiningResource() {
if (dataMiningResource == null) {
dataMiningResource = getResourceContext().getResource(DataMiningResource.class);
@@ -140,41 +139,49 @@ public class RegattasResource extends AbstractSailingServerResource {
}
private Response getBadRegattaErrorResponse(String regattaName) {
- return Response.status(Status.NOT_FOUND).entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.")
+ return Response.status(Status.NOT_FOUND)
+ .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.")
.type(MediaType.TEXT_PLAIN).build();
}
private Response getBadBoatClassResponse(String boatClassName) {
- return Response.status(Status.NOT_FOUND).entity("Could not use a boat class with name '" + StringEscapeUtils.escapeHtml(boatClassName) + "'.")
+ return Response.status(Status.NOT_FOUND)
+ .entity("Could not use a boat class with name '" + StringEscapeUtils.escapeHtml(boatClassName) + "'.")
.type(MediaType.TEXT_PLAIN).build();
}
private Response getBadCompetitorIdResponse(Serializable competitorId) {
- return Response.status(Status.NOT_FOUND).entity("Could not find a competitor with ID '" + StringEscapeUtils.escapeHtml(competitorId.toString()) + "'.")
+ return Response
+ .status(Status.NOT_FOUND).entity("Could not find a competitor with ID '"
+ + StringEscapeUtils.escapeHtml(competitorId.toString()) + "'.")
.type(MediaType.TEXT_PLAIN).build();
}
private Response getBadRaceErrorResponse(String regattaName, String raceName) {
return Response.status(Status.NOT_FOUND)
- .entity("Could not find a race with name '" + StringEscapeUtils.escapeHtml(raceName) + "' in regatta '" + StringEscapeUtils.escapeHtml(regattaName) + "'.")
+ .entity("Could not find a race with name '" + StringEscapeUtils.escapeHtml(raceName) + "' in regatta '"
+ + StringEscapeUtils.escapeHtml(regattaName) + "'.")
.type(MediaType.TEXT_PLAIN).build();
}
-
+
private Response getBadSeriesErrorResponse(String regattaName, String seriesName) {
return Response.status(Status.NOT_FOUND)
- .entity("Could not find a series with name '" + StringEscapeUtils.escapeHtml(seriesName) + "' in regatta '" + StringEscapeUtils.escapeHtml(regattaName) + "'.")
+ .entity("Could not find a series with name '" + StringEscapeUtils.escapeHtml(seriesName)
+ + "' in regatta '" + StringEscapeUtils.escapeHtml(regattaName) + "'.")
.type(MediaType.TEXT_PLAIN).build();
}
-
+
private Response getNoTrackedRaceErrorResponse(String regattaName, String raceName) {
return Response.status(Status.NOT_FOUND)
- .entity("No tracked race for race with name '" + StringEscapeUtils.escapeHtml(raceName) + "' in regatta '" + StringEscapeUtils.escapeHtml(regattaName) + "'.")
+ .entity("No tracked race for race with name '" + StringEscapeUtils.escapeHtml(raceName)
+ + "' in regatta '" + StringEscapeUtils.escapeHtml(regattaName) + "'.")
.type(MediaType.TEXT_PLAIN).build();
}
private Response getNotEnoughDataAvailabeErrorResponse(String regattaName, String raceName) {
return Response.status(Status.NOT_FOUND)
- .entity("No wind or polar data for race with name '" + StringEscapeUtils.escapeHtml(raceName) + "' in regatta '" + StringEscapeUtils.escapeHtml(regattaName) + "'.")
+ .entity("No wind or polar data for race with name '" + StringEscapeUtils.escapeHtml(raceName)
+ + "' in regatta '" + StringEscapeUtils.escapeHtml(regattaName) + "'.")
.type(MediaType.TEXT_PLAIN).build();
}
@@ -200,8 +207,8 @@ public class RegattasResource extends AbstractSailingServerResource {
if (regatta == null) {
response = getBadRegattaErrorResponse(regattaName);
} else {
- SeriesJsonSerializer seriesJsonSerializer = new SeriesJsonSerializer(new FleetJsonSerializer(
- new ColorJsonSerializer()));
+ SeriesJsonSerializer seriesJsonSerializer = new SeriesJsonSerializer(
+ new FleetJsonSerializer(new ColorJsonSerializer()));
JsonSerializer regattaSerializer = new RegattaJsonSerializer(seriesJsonSerializer, null, null);
JSONObject serializedRegatta = regattaSerializer.serialize(regatta);
String json = serializedRegatta.toJSONString();
@@ -228,9 +235,10 @@ public class RegattasResource extends AbstractSailingServerResource {
} else {
NationalityJsonSerializer nationalityJsonSerializer = new NationalityJsonSerializer();
BoatJsonSerializer boatJsonSerializer = new BoatJsonSerializer(new BoatClassJsonSerializer());
- CompetitorJsonSerializer competitorJsonSerializer = new CompetitorJsonSerializer(new TeamJsonSerializer(
- new PersonJsonSerializer(nationalityJsonSerializer)), boatJsonSerializer);
- JsonSerializer regattaSerializer = new RegattaJsonSerializer(null, competitorJsonSerializer, boatJsonSerializer);
+ CompetitorJsonSerializer competitorJsonSerializer = new CompetitorJsonSerializer(
+ new TeamJsonSerializer(new PersonJsonSerializer(nationalityJsonSerializer)), boatJsonSerializer);
+ JsonSerializer regattaSerializer = new RegattaJsonSerializer(null, competitorJsonSerializer,
+ boatJsonSerializer);
JSONObject serializedRegatta = regattaSerializer.serialize(regatta);
String json = serializedRegatta.toJSONString();
response = Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
@@ -258,11 +266,14 @@ public class RegattasResource extends AbstractSailingServerResource {
if (race == null) {
response = getBadRaceErrorResponse(regattaName, raceName);
} else {
- CompetitorAndBoatJsonSerializer competitorAndBoatJsonSerializer = CompetitorAndBoatJsonSerializer.create();
- JsonSerializer raceEntriesSerializer = new RaceEntriesJsonSerializer(competitorAndBoatJsonSerializer);
+ CompetitorAndBoatJsonSerializer competitorAndBoatJsonSerializer = CompetitorAndBoatJsonSerializer
+ .create();
+ JsonSerializer raceEntriesSerializer = new RaceEntriesJsonSerializer(
+ competitorAndBoatJsonSerializer);
JSONObject serializedRaceEntries = raceEntriesSerializer.serialize(race);
String json = serializedRaceEntries.toJSONString();
- response = Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
+ response = Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8")
+ .build();
}
}
return response;
@@ -307,7 +318,8 @@ public class RegattasResource extends AbstractSailingServerResource {
competitorId = competitorIdAsString;
}
- final Competitor competitor = getService().getCompetitorAndBoatStore().getExistingCompetitorById(competitorId);
+ final Competitor competitor = getService().getCompetitorAndBoatStore()
+ .getExistingCompetitorById(competitorId);
if (competitor == null) {
response = getBadCompetitorIdResponse(competitorId);
} else {
@@ -326,7 +338,8 @@ public class RegattasResource extends AbstractSailingServerResource {
@QueryParam("nationalityIOC") String nationalityThreeLetterIOCCode,
@QueryParam("timeontimefactor") Double timeOnTimeFactor,
@QueryParam("timeondistanceallowancepernauticalmileasmillis") Long timeOnDistanceAllowancePerNauticalMileAsMillis,
- @QueryParam("searchtag") String searchTag) {
+ @QueryParam("searchtag") String searchTag, @QueryParam("competitorName") String competitorName,
+ @QueryParam("competitorEmail") String competitorEmail) {
final Subject subject = SecurityUtils.getSubject();
subject.checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regattaName));
Response response;
@@ -337,21 +350,40 @@ public class RegattasResource extends AbstractSailingServerResource {
response = getBadBoatClassResponse(boatClassName);
} else {
final User user = getService(SecurityService.class).getCurrentUser();
- final Boat boat = new BoatImpl(UUID.randomUUID(), user.getName(),
- getService().getBaseDomainFactory().getOrCreateBoatClass(boatClassName, /* typicallyStartsUpwind */ true),
- sailId);
- final CompetitorWithBoat competitor = getService().getCompetitorAndBoatStore().getOrCreateCompetitorWithBoat(UUID.randomUUID(),
- user.getFullName() == null ? user.getName() : user.getFullName(), /* shortName */ null,
- /* displayColor */ null, user.getEmail(), /* flagImageURI */ null,
- new TeamImpl(user.getName(), Collections.singleton(new PersonImpl(user.getFullName() == null ? user.getName() : user.getFullName(),
+ final String shortName;
+ final String name;
+ if (competitorName != null) {
+ name = competitorName;
+ shortName = competitorName;
+ } else {
+ shortName = user.getName();
+ name = user.getFullName() == null ? shortName : user.getFullName();
+ }
+ final String email;
+ if (competitorEmail != null) {
+ email = competitorEmail;
+ } else {
+ email = user.getEmail();
+ }
+
+ final DynamicBoat boat = new BoatImpl(UUID.randomUUID(), shortName, getService().getBaseDomainFactory()
+ .getOrCreateBoatClass(boatClassName, /* typicallyStartsUpwind */ true), sailId);
+
+ final TeamImpl team = new TeamImpl(shortName,
+ Collections.singleton(new PersonImpl(name,
getService().getBaseDomainFactory().getOrCreateNationality(nationalityThreeLetterIOCCode),
/* dateOfBirth */ null, /* description */ null)),
- /* coach */ null), timeOnTimeFactor,
- timeOnDistanceAllowancePerNauticalMileAsMillis == null ? null : new MillisecondsDurationImpl(timeOnDistanceAllowancePerNauticalMileAsMillis),
- searchTag, (DynamicBoat) boat);
+ /* coach */ null);
+ final Duration timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMileAsMillis == null
+ ? null
+ : new MillisecondsDurationImpl(timeOnDistanceAllowancePerNauticalMileAsMillis);
+ final CompetitorWithBoat competitor = getService().getCompetitorAndBoatStore()
+ .getOrCreateCompetitorWithBoat(UUID.randomUUID(), name, /* shortName */ null,
+ /* displayColor */ null, email, /* flagImageURI */ null, team, timeOnTimeFactor,
+ timeOnDistanceAllowancePerNauticalMile, searchTag, boat);
regatta.registerCompetitor(competitor);
- response = Response.ok(CompetitorJsonSerializer.create().serialize(competitor).toJSONString()).
- header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
+ response = Response.ok(CompetitorJsonSerializer.create().serialize(competitor).toJSONString())
+ .header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
}
return response;
}
@@ -375,7 +407,8 @@ public class RegattasResource extends AbstractSailingServerResource {
competitorId = competitorIdAsString;
}
- final Competitor competitor = getService().getCompetitorAndBoatStore().getExistingCompetitorById(competitorId);
+ final Competitor competitor = getService().getCompetitorAndBoatStore()
+ .getExistingCompetitorById(competitorId);
if (competitor == null) {
response = getBadCompetitorIdResponse(competitorId);
} else {
@@ -422,8 +455,8 @@ public class RegattasResource extends AbstractSailingServerResource {
try {
from = parseTimePoint(fromtime, fromtimeasmillis,
trackedRace.getStartOfRace() == null ? new MillisecondsTimePoint(0) :
- /* 24h before race start */new MillisecondsTimePoint(trackedRace.getStartOfRace()
- .asMillis() - 24 * 3600 * 1000));
+ /* 24h before race start */new MillisecondsTimePoint(
+ trackedRace.getStartOfRace().asMillis() - 24 * 3600 * 1000));
} catch (InvalidDateException e1) {
return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not parse the 'from' time.")
.type(MediaType.TEXT_PLAIN).build();
@@ -446,8 +479,9 @@ public class RegattasResource extends AbstractSailingServerResource {
jsonCompetitor.put("id", competitor.getId() != null ? competitor.getId().toString() : null);
jsonCompetitor.put("name", competitor.getName());
jsonCompetitor.put("sailNumber", trackedRace.getBoatOfCompetitor(competitor).getSailID());
- jsonCompetitor.put("color", competitor.getColor() != null ? competitor.getColor().getAsHtml() : null);
- if(competitor.getFlagImage() != null) {
+ jsonCompetitor.put("color",
+ competitor.getColor() != null ? competitor.getColor().getAsHtml() : null);
+ if (competitor.getFlagImage() != null) {
jsonCompetitor.put("flagImage", competitor.getFlagImage().toString());
}
GPSFixTrack track = trackedRace.getTrack(competitor);
@@ -460,7 +494,7 @@ public class RegattasResource extends AbstractSailingServerResource {
} else {
fixIter = track.getFixesIterator(from, /* inclusive */true);
}
- GPSFixMoving fix = null;
+ GPSFixMoving fix = null;
boolean lastAdded = false;
while (fixIter.hasNext()) {
fix = fixIter.next();
@@ -479,10 +513,11 @@ public class RegattasResource extends AbstractSailingServerResource {
addCompetitorFixToJsonFixes(jsonFixes, fix, tack);
lastAdded = true;
}
-
+
if (addLastKnown && !lastAdded) {
// find a fix earlier than the interval requested:
- Iterator earlierFixIter = track.getFixesDescendingIterator(from, /* inclusive */false);
+ Iterator earlierFixIter = track.getFixesDescendingIterator(from,
+ /* inclusive */false);
final GPSFixMoving earlierFix;
if (earlierFixIter.hasNext()) {
earlierFix = earlierFixIter.next();
@@ -497,8 +532,12 @@ public class RegattasResource extends AbstractSailingServerResource {
// don't output tack
}
}
- if (earlierFix != null && (fix == null || earlierFix.getTimePoint().until(from).compareTo(to.until(fix.getTimePoint())) <= 0)) {
- addCompetitorFixToJsonFixes(jsonFixes, earlierFix, tack); // the earlier fix is closer to the interval's beginning than fix is to its end
+ if (earlierFix != null && (fix == null || earlierFix.getTimePoint().until(from)
+ .compareTo(to.until(fix.getTimePoint())) <= 0)) {
+ addCompetitorFixToJsonFixes(jsonFixes, earlierFix, tack); // the earlier fix is
+ // closer to the
+ // interval's beginning
+ // than fix is to its end
} else if (fix != null) {
addCompetitorFixToJsonFixes(jsonFixes, fix, tack);
}
@@ -513,7 +552,8 @@ public class RegattasResource extends AbstractSailingServerResource {
jsonRace.put("competitors", jsonCompetitors);
String json = jsonRace.toJSONString();
- response = Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
+ response = Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8")
+ .build();
}
}
return response;
@@ -522,13 +562,10 @@ public class RegattasResource extends AbstractSailingServerResource {
private JSONObject addCompetitorFixToJsonFixes(JSONArray jsonFixes, GPSFixMoving fix, Tack tack) {
JSONObject jsonFix = new JSONObject();
jsonFix.put("timepoint-ms", fix.getTimePoint().asMillis());
- jsonFix.put("lat-deg", RoundingUtil.latLngDecimalFormatter.format(fix
- .getPosition().getLatDeg()));
- jsonFix.put("lng-deg", RoundingUtil.latLngDecimalFormatter.format(fix
- .getPosition().getLngDeg()));
+ jsonFix.put("lat-deg", RoundingUtil.latLngDecimalFormatter.format(fix.getPosition().getLatDeg()));
+ jsonFix.put("lng-deg", RoundingUtil.latLngDecimalFormatter.format(fix.getPosition().getLngDeg()));
jsonFix.put("truebearing-deg", fix.getSpeed().getBearing().getDegrees());
- jsonFix.put("speed-kts",
- RoundingUtil.knotsDecimalFormatter.format(fix.getSpeed().getKnots()));
+ jsonFix.put("speed-kts", RoundingUtil.knotsDecimalFormatter.format(fix.getSpeed().getKnots()));
if (tack != null) {
jsonFix.put("tack", tack.name());
}
@@ -607,7 +644,7 @@ public class RegattasResource extends AbstractSailingServerResource {
} else {
fixIter = track.getFixesIterator(from, /* inclusive */true);
}
- GPSFix fix = null;
+ GPSFix fix = null;
boolean lastAdded = false;
while (fixIter.hasNext()) {
fix = fixIter.next();
@@ -618,7 +655,7 @@ public class RegattasResource extends AbstractSailingServerResource {
addMarkFixToJsonFixes(jsonFixes, fix);
lastAdded = true;
}
-
+
if (addLastKnown && !lastAdded) {
// find a fix earlier than the interval requested:
Iterator earlierFixIter = track.getFixesDescendingIterator(from, /* inclusive */false);
@@ -628,13 +665,15 @@ public class RegattasResource extends AbstractSailingServerResource {
} else {
earlierFix = null;
}
- if (earlierFix != null && (fix == null || earlierFix.getTimePoint().until(from).compareTo(to.until(fix.getTimePoint())) <= 0)) {
- addMarkFixToJsonFixes(jsonFixes, earlierFix); // the earlier fix is closer to the interval's beginning than fix is to its end
+ if (earlierFix != null && (fix == null
+ || earlierFix.getTimePoint().until(from).compareTo(to.until(fix.getTimePoint())) <= 0)) {
+ addMarkFixToJsonFixes(jsonFixes, earlierFix); // the earlier fix is closer to the interval's
+ // beginning than fix is to its end
} else if (fix != null) {
addMarkFixToJsonFixes(jsonFixes, fix);
}
}
-
+
} finally {
track.unlockAfterRead();
}
@@ -651,10 +690,8 @@ public class RegattasResource extends AbstractSailingServerResource {
private JSONObject addMarkFixToJsonFixes(JSONArray jsonFixes, GPSFix fix) {
JSONObject jsonFix = new JSONObject();
jsonFix.put("timepoint-ms", fix.getTimePoint().asMillis());
- jsonFix.put("lat-deg",
- RoundingUtil.latLngDecimalFormatter.format(fix.getPosition().getLatDeg()));
- jsonFix.put("lng-deg",
- RoundingUtil.latLngDecimalFormatter.format(fix.getPosition().getLngDeg()));
+ jsonFix.put("lat-deg", RoundingUtil.latLngDecimalFormatter.format(fix.getPosition().getLatDeg()));
+ jsonFix.put("lng-deg", RoundingUtil.latLngDecimalFormatter.format(fix.getPosition().getLngDeg()));
jsonFixes.add(jsonFix);
return jsonFix;
}
@@ -680,18 +717,19 @@ public class RegattasResource extends AbstractSailingServerResource {
response = getBadRaceErrorResponse(regattaName, raceName);
} else {
Course course = race.getCourse();
- CourseBaseJsonSerializer serializer = new CourseBaseJsonSerializer(new WaypointJsonSerializer(
- new ControlPointJsonSerializer(new MarkJsonSerializer(), new GateJsonSerializer(
- new MarkJsonSerializer()))));
+ CourseBaseJsonSerializer serializer = new CourseBaseJsonSerializer(
+ new WaypointJsonSerializer(new ControlPointJsonSerializer(new MarkJsonSerializer(),
+ new GateJsonSerializer(new MarkJsonSerializer()))));
JSONObject jsonCourse = serializer.serialize(course);
String json = jsonCourse.toJSONString();
- response = Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
+ response = Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8")
+ .build();
}
}
return response;
}
-
+
/**
* Gets the target time of the race
*
@@ -723,17 +761,19 @@ public class RegattasResource extends AbstractSailingServerResource {
TargetTimeInfo targetTime;
try {
targetTime = trackedRace.getEstimatedTimeToComplete(timePoint);
- final TargetTimeInfoSerializer serializer = new TargetTimeInfoSerializer(new WindJsonSerializer(new PositionJsonSerializer()));
+ final TargetTimeInfoSerializer serializer = new TargetTimeInfoSerializer(
+ new WindJsonSerializer(new PositionJsonSerializer()));
JSONObject jsonCourse = serializer.serialize(targetTime);
String json = jsonCourse.toJSONString();
- response = Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
+ response = Response.ok(json)
+ .header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
} catch (NotEnoughDataHasBeenAddedException | NoWindException e) {
response = getNotEnoughDataAvailabeErrorResponse(regattaName, raceName);
}
} else {
response = getNoTrackedRaceErrorResponse(regattaName, raceName);
}
-
+
}
}
return response;
@@ -765,16 +805,16 @@ public class RegattasResource extends AbstractSailingServerResource {
jsonRaceTimes.put("name", trackedRace.getRace().getName());
jsonRaceTimes.put("regatta", regatta.getName());
- jsonRaceTimes.put("startOfRace-ms", trackedRace.getStartOfRace() == null ? null : trackedRace
- .getStartOfRace().asMillis());
- jsonRaceTimes.put("startOfTracking-ms", trackedRace.getStartOfTracking() == null ? null : trackedRace
- .getStartOfTracking().asMillis());
+ jsonRaceTimes.put("startOfRace-ms",
+ trackedRace.getStartOfRace() == null ? null : trackedRace.getStartOfRace().asMillis());
+ jsonRaceTimes.put("startOfTracking-ms",
+ trackedRace.getStartOfTracking() == null ? null : trackedRace.getStartOfTracking().asMillis());
jsonRaceTimes.put("newestTrackingEvent-ms", trackedRace.getTimePointOfNewestEvent() == null ? null
: trackedRace.getTimePointOfNewestEvent().asMillis());
- jsonRaceTimes.put("endOfTracking-ms", trackedRace.getEndOfTracking() == null ? null : trackedRace
- .getEndOfTracking().asMillis());
- jsonRaceTimes.put("endOfRace-ms", trackedRace.getEndOfRace() == null ? null : trackedRace
- .getEndOfRace().asMillis());
+ jsonRaceTimes.put("endOfTracking-ms",
+ trackedRace.getEndOfTracking() == null ? null : trackedRace.getEndOfTracking().asMillis());
+ jsonRaceTimes.put("endOfRace-ms",
+ trackedRace.getEndOfRace() == null ? null : trackedRace.getEndOfRace().asMillis());
jsonRaceTimes.put("delayToLive-ms", trackedRace.getDelayToLiveInMillis());
JSONArray jsonMarkPassingTimes = new JSONArray();
@@ -820,10 +860,8 @@ public class RegattasResource extends AbstractSailingServerResource {
TimePoint firstPassingTime = firstPassingTimepoints.get(legNumber - 1);
if (firstPassingTime != null) {
jsonLegInfo.put("type", trackedLeg.getLegType(firstPassingTime));
- jsonLegInfo.put(
- "bearing-deg",
- RoundingUtil.bearingDecimalFormatter.format(trackedLeg.getLegBearing(
- firstPassingTime).getDegrees()));
+ jsonLegInfo.put("bearing-deg", RoundingUtil.bearingDecimalFormatter
+ .format(trackedLeg.getLegBearing(firstPassingTime).getDegrees()));
}
} catch (NoWindException e) {
// do nothing
@@ -841,7 +879,8 @@ public class RegattasResource extends AbstractSailingServerResource {
jsonRaceTimes.put("currentServerTime-ms", now.getTime());
String json = jsonRaceTimes.toJSONString();
- response = Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
+ response = Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8")
+ .build();
}
}
return response;
@@ -850,19 +889,20 @@ public class RegattasResource extends AbstractSailingServerResource {
@GET
@Produces("application/json;charset=UTF-8")
@Path("{regattaname}/races/{racename}/windsources")
- public Response getWindSources(@PathParam("regattaname") String regattaName, @PathParam("racename") String raceName) {
+ public Response getWindSources(@PathParam("regattaname") String regattaName,
+ @PathParam("racename") String raceName) {
Response response;
Regatta regatta = findRegattaByName(regattaName);
if (regatta == null) {
response = Response.status(Status.NOT_FOUND)
- .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.").type(MediaType.TEXT_PLAIN)
- .build();
+ .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.")
+ .type(MediaType.TEXT_PLAIN).build();
} else {
RaceDefinition race = findRaceByName(regatta, raceName);
if (race == null) {
response = Response.status(Status.NOT_FOUND)
- .entity("Could not find a race with name '" + StringEscapeUtils.escapeHtml(raceName) + "'.").type(MediaType.TEXT_PLAIN)
- .build();
+ .entity("Could not find a race with name '" + StringEscapeUtils.escapeHtml(raceName) + "'.")
+ .type(MediaType.TEXT_PLAIN).build();
} else {
TrackedRace trackedRace = findTrackedRace(regattaName, raceName);
JSONArray windSourcesAvailable = new JSONArray();
@@ -874,7 +914,8 @@ public class RegattasResource extends AbstractSailingServerResource {
windSourcesAvailable.add(windSourceJson);
}
}
- return Response.ok(windSourcesAvailable.toString()).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
+ return Response.ok(windSourcesAvailable.toString())
+ .header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
}
}
return response;
@@ -892,18 +933,18 @@ public class RegattasResource extends AbstractSailingServerResource {
Regatta regatta = findRegattaByName(regattaName);
if (regatta == null) {
response = Response.status(Status.NOT_FOUND)
- .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.").type(MediaType.TEXT_PLAIN)
- .build();
+ .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.")
+ .type(MediaType.TEXT_PLAIN).build();
} else if (!((fromtime != null && totime != null) || (fromtimeasmillis != null && totimeasmillis != null))) {
- response = Response.status(Status.NOT_FOUND)
- .entity("Either the 'fromtime' and 'totime' or the 'fromtimeasmillis' and 'totimeasmillis' parameter must be set.").type(MediaType.TEXT_PLAIN)
- .build();
+ response = Response.status(Status.NOT_FOUND).entity(
+ "Either the 'fromtime' and 'totime' or the 'fromtimeasmillis' and 'totimeasmillis' parameter must be set.")
+ .type(MediaType.TEXT_PLAIN).build();
} else {
RaceDefinition race = findRaceByName(regatta, raceName);
if (race == null) {
response = Response.status(Status.NOT_FOUND)
- .entity("Could not find a race with name '" + StringEscapeUtils.escapeHtml(raceName) + "'.").type(MediaType.TEXT_PLAIN)
- .build();
+ .entity("Could not find a race with name '" + StringEscapeUtils.escapeHtml(raceName) + "'.")
+ .type(MediaType.TEXT_PLAIN).build();
} else {
TrackedRace trackedRace = findTrackedRace(regattaName, raceName);
@@ -912,8 +953,8 @@ public class RegattasResource extends AbstractSailingServerResource {
try {
from = parseTimePoint(fromtime, fromtimeasmillis,
trackedRace.getStartOfRace() == null ? new MillisecondsTimePoint(0) :
- /* 24h before race start */new MillisecondsTimePoint(trackedRace.getStartOfRace()
- .asMillis() - 24 * 3600 * 1000));
+ /* 24h before race start */new MillisecondsTimePoint(
+ trackedRace.getStartOfRace().asMillis() - 24 * 3600 * 1000));
} catch (InvalidDateException e1) {
return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not parse the 'from' time.")
.type(MediaType.TEXT_PLAIN).build();
@@ -926,9 +967,11 @@ public class RegattasResource extends AbstractSailingServerResource {
}
// Crop request interval to startOfTracking / [endOfTracking|timePointOfLastEvent]
final TimePoint finalFrom = Util.getLatestOfTimePoints(from, trackedRace.getStartOfTracking());
- final TimePoint finalTo = Util.getEarliestOfTimePoints(to, Util.getEarliestOfTimePoints(trackedRace.getEndOfTracking(), trackedRace.getTimePointOfNewestEvent()));
+ final TimePoint finalTo = Util.getEarliestOfTimePoints(to, Util.getEarliestOfTimePoints(
+ trackedRace.getEndOfTracking(), trackedRace.getTimePointOfNewestEvent()));
TrackedRaceJsonSerializer serializer = new TrackedRaceJsonSerializer(
- ws->new DefaultWindTrackJsonSerializer(/* maxNumberOfFixes */ 10000, finalFrom, finalTo, ws), windSource, windSourceId);
+ ws -> new DefaultWindTrackJsonSerializer(/* maxNumberOfFixes */ 10000, finalFrom, finalTo, ws),
+ windSource, windSourceId);
JSONObject jsonWindTracks = serializer.serialize(trackedRace);
String json = jsonWindTracks.toJSONString();
@@ -948,31 +991,29 @@ public class RegattasResource extends AbstractSailingServerResource {
Regatta regatta = findRegattaByName(regattaName);
if (regatta == null) {
response = Response.status(Status.NOT_FOUND)
- .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.").type(MediaType.TEXT_PLAIN)
- .build();
+ .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.")
+ .type(MediaType.TEXT_PLAIN).build();
} else {
RaceDefinition race = findRaceByName(regatta, raceName);
if (race == null) {
response = Response.status(Status.NOT_FOUND)
- .entity("Could not find a race with name '" + StringEscapeUtils.escapeHtml(raceName) + "'.").type(MediaType.TEXT_PLAIN)
- .build();
+ .entity("Could not find a race with name '" + StringEscapeUtils.escapeHtml(raceName) + "'.")
+ .type(MediaType.TEXT_PLAIN).build();
} else {
TrackedRace trackedRace = findTrackedRace(regattaName, raceName);
final TimePoint timePoint;
try {
- timePoint = parseTimePoint(
- time,
- timeasmillis,
- trackedRace.getStartOfRace() == null ? new MillisecondsTimePoint(0) : trackedRace
- .getStartOfRace());
+ timePoint = parseTimePoint(time, timeasmillis,
+ trackedRace.getStartOfRace() == null ? new MillisecondsTimePoint(0)
+ : trackedRace.getStartOfRace());
} catch (InvalidDateException e1) {
return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not parse the 'from' time.")
.type(MediaType.TEXT_PLAIN).build();
}
BearingJsonSerializer serializer = new BearingJsonSerializer();
- JSONObject jsonBearing = serializer.serialize(trackedRace.getDirectionFromStartToNextMark(timePoint)
- .getFrom());
+ JSONObject jsonBearing = serializer
+ .serialize(trackedRace.getDirectionFromStartToNextMark(timePoint).getFrom());
String json = jsonBearing.toJSONString();
return Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
}
@@ -983,19 +1024,20 @@ public class RegattasResource extends AbstractSailingServerResource {
@GET
@Produces("application/json;charset=UTF-8")
@Path("{regattaname}/races/{racename}/markpassings")
- public Response getMarkPassings(@PathParam("regattaname") String regattaName, @PathParam("racename") String raceName) {
+ public Response getMarkPassings(@PathParam("regattaname") String regattaName,
+ @PathParam("racename") String raceName) {
Response response;
Regatta regatta = findRegattaByName(regattaName);
if (regatta == null) {
response = Response.status(Status.NOT_FOUND)
- .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.").type(MediaType.TEXT_PLAIN)
- .build();
+ .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.")
+ .type(MediaType.TEXT_PLAIN).build();
} else {
RaceDefinition race = findRaceByName(regatta, raceName);
if (race == null) {
response = Response.status(Status.NOT_FOUND)
- .entity("Could not find a race with name '" + StringEscapeUtils.escapeHtml(raceName) + "'.").type(MediaType.TEXT_PLAIN)
- .build();
+ .entity("Could not find a race with name '" + StringEscapeUtils.escapeHtml(raceName) + "'.")
+ .type(MediaType.TEXT_PLAIN).build();
} else {
TrackedRace trackedRace = findTrackedRace(regattaName, raceName);
AbstractTrackedRaceDataJsonSerializer serializer = new MarkPassingsJsonSerializer();
@@ -1015,17 +1057,18 @@ public class RegattasResource extends AbstractSailingServerResource {
Regatta regatta = findRegattaByName(regattaName);
if (regatta == null) {
response = Response.status(Status.NOT_FOUND)
- .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.").type(MediaType.TEXT_PLAIN)
- .build();
+ .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.")
+ .type(MediaType.TEXT_PLAIN).build();
} else {
RaceDefinition race = findRaceByName(regatta, raceName);
if (race == null) {
response = Response.status(Status.NOT_FOUND)
- .entity("Could not find a race with name '" + StringEscapeUtils.escapeHtml(raceName) + "'.").type(MediaType.TEXT_PLAIN)
- .build();
+ .entity("Could not find a race with name '" + StringEscapeUtils.escapeHtml(raceName) + "'.")
+ .type(MediaType.TEXT_PLAIN).build();
} else {
TrackedRace trackedRace = findTrackedRace(regattaName, raceName);
- ManeuversJsonSerializer serializer = new ManeuversJsonSerializer(CompetitorAndBoatJsonSerializer.create(),
+ ManeuversJsonSerializer serializer = new ManeuversJsonSerializer(
+ CompetitorAndBoatJsonSerializer.create(),
new ManeuverJsonSerializer(new GPSFixJsonSerializer(), new DistanceJsonSerializer()));
JSONObject jsonMarkPassings = serializer.serialize(trackedRace);
String json = jsonMarkPassings.toJSONString();
@@ -1034,7 +1077,7 @@ public class RegattasResource extends AbstractSailingServerResource {
}
return response;
}
-
+
@GET
@Produces("application/json;charset=UTF-8")
@Path("{regattaname}/races/{racename}/completeManeuverCurvesWithEstimationData")
@@ -1138,8 +1181,8 @@ public class RegattasResource extends AbstractSailingServerResource {
Regatta regatta = findRegattaByName(regattaName);
if (regatta == null) {
response = Response.status(Status.NOT_FOUND)
- .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.").type(MediaType.TEXT_PLAIN)
- .build();
+ .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.")
+ .type(MediaType.TEXT_PLAIN).build();
} else {
JSONObject jsonRaceResults = new JSONObject();
jsonRaceResults.put("regatta", regatta.getName());
@@ -1156,7 +1199,7 @@ public class RegattasResource extends AbstractSailingServerResource {
}
return response;
}
-
+
@GET
@Produces("application/json;charset=UTF-8")
@Path("{regattaname}/races/{racename}/competitors/legs")
@@ -1166,14 +1209,14 @@ public class RegattasResource extends AbstractSailingServerResource {
Regatta regatta = findRegattaByName(regattaName);
if (regatta == null) {
response = Response.status(Status.NOT_FOUND)
- .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.").type(MediaType.TEXT_PLAIN)
- .build();
+ .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.")
+ .type(MediaType.TEXT_PLAIN).build();
} else {
RaceDefinition race = findRaceByName(regatta, raceName);
if (race == null) {
response = Response.status(Status.NOT_FOUND)
- .entity("Could not find a race with name '" + StringEscapeUtils.escapeHtml(raceName) + "'.").type(MediaType.TEXT_PLAIN)
- .build();
+ .entity("Could not find a race with name '" + StringEscapeUtils.escapeHtml(raceName) + "'.")
+ .type(MediaType.TEXT_PLAIN).build();
} else {
TrackedRace trackedRace = findTrackedRace(regattaName, raceName);
TimePoint timePoint = trackedRace.getTimePointOfNewestEvent() == null ? MillisecondsTimePoint.now()
@@ -1182,8 +1225,8 @@ public class RegattasResource extends AbstractSailingServerResource {
JSONObject jsonRaceResults = new JSONObject();
jsonRaceResults.put("name", trackedRace.getRace().getName());
jsonRaceResults.put("regatta", regatta.getName());
- jsonRaceResults.put("startOfRace-ms", trackedRace.getStartOfRace() == null ? null : trackedRace
- .getStartOfRace().asMillis());
+ jsonRaceResults.put("startOfRace-ms",
+ trackedRace.getStartOfRace() == null ? null : trackedRace.getStartOfRace().asMillis());
JSONArray jsonLegs = new JSONArray();
Course course = trackedRace.getRace().getCourse();
@@ -1192,9 +1235,12 @@ public class RegattasResource extends AbstractSailingServerResource {
for (TrackedLeg leg : trackedRace.getTrackedLegs()) {
JSONObject jsonLeg = new JSONObject();
jsonLeg.put("from", leg.getLeg().getFrom().getName());
- jsonLeg.put("fromWaypointId", leg.getLeg().getFrom().getId() != null ? leg.getLeg().getFrom().getId().toString() : null);
+ jsonLeg.put("fromWaypointId",
+ leg.getLeg().getFrom().getId() != null ? leg.getLeg().getFrom().getId().toString()
+ : null);
jsonLeg.put("to", leg.getLeg().getTo().getName());
- jsonLeg.put("toWaypointId", leg.getLeg().getTo().getId() != null ? leg.getLeg().getTo().getId().toString() : null);
+ jsonLeg.put("toWaypointId",
+ leg.getLeg().getTo().getId() != null ? leg.getLeg().getTo().getId().toString() : null);
try {
jsonLeg.put("upOrDownwindLeg", leg.isUpOrDownwindLeg(timePoint));
} catch (NoWindException e) {
@@ -1207,34 +1253,39 @@ public class RegattasResource extends AbstractSailingServerResource {
JSONObject jsonCompetitorInLeg = new JSONObject();
TrackedLegOfCompetitor trackedLegOfCompetitor = leg.getTrackedLeg(competitor);
if (trackedLegOfCompetitor != null) {
- jsonCompetitorInLeg.put("id", competitor.getId() != null ? competitor.getId()
- .toString() : null);
+ jsonCompetitorInLeg.put("id",
+ competitor.getId() != null ? competitor.getId().toString() : null);
jsonCompetitorInLeg.put("name", competitor.getName());
- jsonCompetitorInLeg.put("sailNumber", trackedRace.getBoatOfCompetitor(competitor).getSailID());
- jsonCompetitorInLeg.put("color", competitor.getColor() != null ? competitor.getColor()
- .getAsHtml() : null);
+ jsonCompetitorInLeg.put("sailNumber",
+ trackedRace.getBoatOfCompetitor(competitor).getSailID());
+ jsonCompetitorInLeg.put("color",
+ competitor.getColor() != null ? competitor.getColor().getAsHtml() : null);
Speed averageSpeedOverGround = trackedLegOfCompetitor
.getAverageSpeedOverGround(timePoint);
if (averageSpeedOverGround != null) {
- jsonCompetitorInLeg.put("averageSOG-kts",
- RoundingUtil.knotsDecimalFormatter.format(averageSpeedOverGround
- .getKnots()));
+ jsonCompetitorInLeg.put("averageSOG-kts", RoundingUtil.knotsDecimalFormatter
+ .format(averageSpeedOverGround.getKnots()));
}
try {
- Integer numberOfTacks = trackedLegOfCompetitor.getNumberOfTacks(timePoint, /* waitForLatest */
+ Integer numberOfTacks = trackedLegOfCompetitor.getNumberOfTacks(timePoint, /*
+ * waitForLatest
+ */
false);
- Integer numberOfJibes = trackedLegOfCompetitor.getNumberOfJibes(timePoint, /* waitForLatest */
+ Integer numberOfJibes = trackedLegOfCompetitor.getNumberOfJibes(timePoint, /*
+ * waitForLatest
+ */
false);
- Integer numberOfPenaltyCircles = trackedLegOfCompetitor.getNumberOfPenaltyCircles(
- timePoint, /* waitForLatest */false);
+ Integer numberOfPenaltyCircles = trackedLegOfCompetitor
+ .getNumberOfPenaltyCircles(timePoint, /* waitForLatest */false);
jsonCompetitorInLeg.put("tacks", numberOfTacks);
jsonCompetitorInLeg.put("jibes", numberOfJibes);
jsonCompetitorInLeg.put("penaltyCircles", numberOfPenaltyCircles);
} catch (NoWindException e) {
logger.log(Level.FINE,
"No wind information while trying to determing maneuvers for competitor "
- + competitor.getName(), e);
+ + competitor.getName(),
+ e);
}
TimePoint startTime = trackedLegOfCompetitor.getStartTime();
@@ -1257,16 +1308,15 @@ public class RegattasResource extends AbstractSailingServerResource {
startOfRace, finishTime != null ? finishTime : timePoint);
if (distanceSinceGun != null) {
jsonCompetitorInLeg.put("distanceSinceGun-m",
- RoundingUtil.distanceDecimalFormatter.format(distanceSinceGun
- .getMeters()));
+ RoundingUtil.distanceDecimalFormatter
+ .format(distanceSinceGun.getMeters()));
}
}
Distance distanceTraveled = trackedLegOfCompetitor.getDistanceTraveled(timePoint);
if (distanceTraveled != null) {
jsonCompetitorInLeg.put("distanceTraveled-m",
- RoundingUtil.distanceDecimalFormatter.format(distanceTraveled
- .getMeters()));
+ RoundingUtil.distanceDecimalFormatter.format(distanceTraveled.getMeters()));
}
Distance distanceTraveledIncludingGateStart = trackedLegOfCompetitor
.getDistanceTraveledConsideringGateStart(timePoint);
@@ -1285,10 +1335,15 @@ public class RegattasResource extends AbstractSailingServerResource {
throw re;
}
}
- Duration gapToLeaderDuration = trackedLegOfCompetitor.getGapToLeader(timePoint, rankingInfo, WindPositionMode.LEG_MIDDLE);
- jsonCompetitorInLeg.put("gapToLeader-s", gapToLeaderDuration != null ? gapToLeaderDuration.asSeconds() : 0.0);
- Distance gapToLeaderDistance = trackedLegOfCompetitor.getWindwardDistanceToCompetitorFarthestAhead(timePoint, WindPositionMode.LEG_MIDDLE, rankingInfo);
- jsonCompetitorInLeg.put("gapToLeader-m", gapToLeaderDistance != null ? gapToLeaderDistance.getMeters() : 0.0);
+ Duration gapToLeaderDuration = trackedLegOfCompetitor.getGapToLeader(timePoint,
+ rankingInfo, WindPositionMode.LEG_MIDDLE);
+ jsonCompetitorInLeg.put("gapToLeader-s",
+ gapToLeaderDuration != null ? gapToLeaderDuration.asSeconds() : 0.0);
+ Distance gapToLeaderDistance = trackedLegOfCompetitor
+ .getWindwardDistanceToCompetitorFarthestAhead(timePoint,
+ WindPositionMode.LEG_MIDDLE, rankingInfo);
+ jsonCompetitorInLeg.put("gapToLeader-m",
+ gapToLeaderDistance != null ? gapToLeaderDistance.getMeters() : 0.0);
jsonCompetitorInLeg.put("started", trackedLegOfCompetitor.hasStartedLeg(timePoint));
jsonCompetitorInLeg.put("finished", trackedLegOfCompetitor.hasFinishedLeg(timePoint));
jsonCompetitors.add(jsonCompetitorInLeg);
@@ -1318,14 +1373,14 @@ public class RegattasResource extends AbstractSailingServerResource {
Regatta regatta = findRegattaByName(regattaName);
if (regatta == null) {
response = Response.status(Status.NOT_FOUND)
- .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.").type(MediaType.TEXT_PLAIN)
- .build();
+ .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.")
+ .type(MediaType.TEXT_PLAIN).build();
} else {
RaceDefinition race = findRaceByName(regatta, raceName);
if (race == null) {
response = Response.status(Status.NOT_FOUND)
- .entity("Could not find a race with name '" + StringEscapeUtils.escapeHtml(raceName) + "'.").type(MediaType.TEXT_PLAIN)
- .build();
+ .entity("Could not find a race with name '" + StringEscapeUtils.escapeHtml(raceName) + "'.")
+ .type(MediaType.TEXT_PLAIN).build();
} else {
Leaderboard leaderboard = getService().getLeaderboardByName(regattaName);
TrackedRace trackedRace = findTrackedRace(regattaName, raceName);
@@ -1369,8 +1424,8 @@ public class RegattasResource extends AbstractSailingServerResource {
jsonCompetitorInLeg.put("id", competitor.getId() != null ? competitor.getId().toString() : null);
jsonCompetitorInLeg.put("name", competitor.getName());
jsonCompetitorInLeg.put("sailNumber", trackedRace.getBoatOfCompetitor(competitor).getSailID());
- jsonCompetitorInLeg.put("color", competitor.getColor() != null ? competitor.getColor().getAsHtml()
- : null);
+ jsonCompetitorInLeg.put("color",
+ competitor.getColor() != null ? competitor.getColor().getAsHtml() : null);
jsonCompetitorInLeg.put("rank", rank++);
final Integer overallRank = overallRankPerCompetitor.get(competitor);
if (overallRank != null) {
@@ -1381,7 +1436,8 @@ public class RegattasResource extends AbstractSailingServerResource {
if (competitorTrack != null) {
final SpeedWithBearing estimatedSpeed = competitorTrack.getEstimatedSpeed(timePoint);
if (estimatedSpeed != null) {
- jsonCompetitorInLeg.put("speedOverGround-kts", roundDouble(estimatedSpeed.getKnots(), 2));
+ jsonCompetitorInLeg.put("speedOverGround-kts",
+ roundDouble(estimatedSpeed.getKnots(), 2));
}
}
}
@@ -1400,14 +1456,15 @@ public class RegattasResource extends AbstractSailingServerResource {
roundDouble(distanceTraveledConsideringGateStart.getMeters(), 2));
}
- Duration gapToLeader = currentLegOfCompetitor.getGapToLeader(timePoint,
- rankingInfo, WindPositionMode.LEG_MIDDLE);
+ Duration gapToLeader = currentLegOfCompetitor.getGapToLeader(timePoint, rankingInfo,
+ WindPositionMode.LEG_MIDDLE);
if (gapToLeader != null) {
jsonCompetitorInLeg.put("gapToLeader-s", roundDouble(gapToLeader.asSeconds(), 2));
}
Distance windwardDistanceToCompetitorFarthestAhead = currentLegOfCompetitor
- .getWindwardDistanceToCompetitorFarthestAhead(timePoint, WindPositionMode.LEG_MIDDLE, rankingInfo);
+ .getWindwardDistanceToCompetitorFarthestAhead(timePoint, WindPositionMode.LEG_MIDDLE,
+ rankingInfo);
if (windwardDistanceToCompetitorFarthestAhead != null) {
jsonCompetitorInLeg.put("gapToLeader-m",
roundDouble(windwardDistanceToCompetitorFarthestAhead.getMeters(), 2));
@@ -1431,12 +1488,13 @@ public class RegattasResource extends AbstractSailingServerResource {
}
return response;
}
-
+
@GET
@Produces("application/json;charset=UTF-8")
@Path("datamining")
public Response getRegattaPredefinedQueries() {
- List predefinedRegattaQueries = getDataMiningResource().getPredefinedRegattaDataMiningQueries();
+ List predefinedRegattaQueries = getDataMiningResource()
+ .getPredefinedRegattaDataMiningQueries();
return getDataMiningResource().predefinedQueryIdentifiersToJSON(predefinedRegattaQueries);
}
@@ -1445,7 +1503,7 @@ public class RegattasResource extends AbstractSailingServerResource {
@Path("{regattaname}/datamining/" + SailingPredefinedQueries.QUERY_AVERAGE_SPEED_PER_COMPETITOR_LEGTYPE)
public Response avgSpeedPerCompetitorAndLegType(@PathParam("regattaname") String regattaName) {
Response response;
-
+
Regatta regatta = findRegattaByName(regattaName);
if (regatta == null) {
response = getBadRegattaErrorResponse(regattaName);
@@ -1457,10 +1515,12 @@ public class RegattasResource extends AbstractSailingServerResource {
@GET
@Produces("application/json;charset=UTF-8")
- @Path("{regattaname}/races/{racename}/datamining/" + SailingPredefinedQueries.QUERY_AVERAGE_SPEED_PER_COMPETITOR_LEGTYPE)
- public Response avgSpeedPerCompetitorAndLegType(@PathParam("regattaname") String regattaName, @PathParam("racename") String raceName) {
+ @Path("{regattaname}/races/{racename}/datamining/"
+ + SailingPredefinedQueries.QUERY_AVERAGE_SPEED_PER_COMPETITOR_LEGTYPE)
+ public Response avgSpeedPerCompetitorAndLegType(@PathParam("regattaname") String regattaName,
+ @PathParam("racename") String raceName) {
Response response;
-
+
Regatta regatta = findRegattaByName(regattaName);
if (regatta == null) {
response = getBadRegattaErrorResponse(regattaName);
@@ -1480,7 +1540,7 @@ public class RegattasResource extends AbstractSailingServerResource {
@Path("{regattaname}/datamining/" + SailingPredefinedQueries.QUERY_DISTANCE_TRAVELED_PER_COMPETITOR_LEGTYPE)
public Response sumDistancePerCompetitorAndLegType(@PathParam("regattaname") String regattaName) {
Response response;
-
+
Regatta regatta = findRegattaByName(regattaName);
if (regatta == null) {
response = getBadRegattaErrorResponse(regattaName);
@@ -1492,10 +1552,12 @@ public class RegattasResource extends AbstractSailingServerResource {
@GET
@Produces("application/json;charset=UTF-8")
- @Path("{regattaname}/races/{racename}/datamining/" + SailingPredefinedQueries.QUERY_DISTANCE_TRAVELED_PER_COMPETITOR_LEGTYPE)
- public Response sumDistancePerCompetitorAndLegType(@PathParam("regattaname") String regattaName, @PathParam("racename") String raceName) {
+ @Path("{regattaname}/races/{racename}/datamining/"
+ + SailingPredefinedQueries.QUERY_DISTANCE_TRAVELED_PER_COMPETITOR_LEGTYPE)
+ public Response sumDistancePerCompetitorAndLegType(@PathParam("regattaname") String regattaName,
+ @PathParam("racename") String raceName) {
Response response;
-
+
Regatta regatta = findRegattaByName(regattaName);
if (regatta == null) {
response = getBadRegattaErrorResponse(regattaName);
@@ -1515,7 +1577,7 @@ public class RegattasResource extends AbstractSailingServerResource {
@Path("{regattaname}/datamining/" + SailingPredefinedQueries.QUERY_MANEUVERS_PER_COMPETITOR)
public Response sumManeuversPerCompetitor(@PathParam("regattaname") String regattaName) {
Response response;
-
+
Regatta regatta = findRegattaByName(regattaName);
if (regatta == null) {
response = getBadRegattaErrorResponse(regattaName);
@@ -1528,9 +1590,10 @@ public class RegattasResource extends AbstractSailingServerResource {
@GET
@Produces("application/json;charset=UTF-8")
@Path("{regattaname}/races/{racename}/datamining/" + SailingPredefinedQueries.QUERY_MANEUVERS_PER_COMPETITOR)
- public Response sumManeuversPerCompetitor(@PathParam("regattaname") String regattaName, @PathParam("racename") String raceName) {
+ public Response sumManeuversPerCompetitor(@PathParam("regattaname") String regattaName,
+ @PathParam("racename") String raceName) {
Response response;
-
+
Regatta regatta = findRegattaByName(regattaName);
if (regatta == null) {
response = getBadRegattaErrorResponse(regattaName);
@@ -1550,7 +1613,7 @@ public class RegattasResource extends AbstractSailingServerResource {
@Path("{regattaname}/datamining/" + SailingPredefinedQueries.QUERY_AVERAGE_SPEED_PER_COMPETITOR)
public Response avgSpeedPerCompetitor(@PathParam("regattaname") String regattaName) {
Response response;
-
+
Regatta regatta = findRegattaByName(regattaName);
if (regatta == null) {
response = getBadRegattaErrorResponse(regattaName);
@@ -1563,7 +1626,8 @@ public class RegattasResource extends AbstractSailingServerResource {
@GET
@Produces("application/json;charset=UTF-8")
@Path("{regattaname}/races/{racename}/datamining/" + SailingPredefinedQueries.QUERY_AVERAGE_SPEED_PER_COMPETITOR)
- public Response avgSpeedPerCompetitor(@PathParam("regattaname") String regattaName, @PathParam("racename") String raceName) {
+ public Response avgSpeedPerCompetitor(@PathParam("regattaname") String regattaName,
+ @PathParam("racename") String raceName) {
Response response;
Regatta regatta = findRegattaByName(regattaName);
if (regatta == null) {
@@ -1581,7 +1645,7 @@ public class RegattasResource extends AbstractSailingServerResource {
@GET
@Produces("application/json;charset=UTF-8")
- @Path("{regattaname}/datamining/"+ SailingPredefinedQueries.QUERY_DISTANCE_TRAVELED_PER_COMPETITOR)
+ @Path("{regattaname}/datamining/" + SailingPredefinedQueries.QUERY_DISTANCE_TRAVELED_PER_COMPETITOR)
public Response sumDistancePerCompetitor(@PathParam("regattaname") String regattaName) {
Response response;
Regatta regatta = findRegattaByName(regattaName);
@@ -1595,8 +1659,10 @@ public class RegattasResource extends AbstractSailingServerResource {
@GET
@Produces("application/json;charset=UTF-8")
- @Path("{regattaname}/races/{racename}/datamining/" + SailingPredefinedQueries.QUERY_DISTANCE_TRAVELED_PER_COMPETITOR)
- public Response sumDistancePerCompetitor(@PathParam("regattaname") String regattaName, @PathParam("racename") String raceName) {
+ @Path("{regattaname}/races/{racename}/datamining/"
+ + SailingPredefinedQueries.QUERY_DISTANCE_TRAVELED_PER_COMPETITOR)
+ public Response sumDistancePerCompetitor(@PathParam("regattaname") String regattaName,
+ @PathParam("racename") String raceName) {
Response response;
Regatta regatta = findRegattaByName(regattaName);
if (regatta == null) {
@@ -1611,7 +1677,7 @@ public class RegattasResource extends AbstractSailingServerResource {
}
return response;
}
-
+
@POST
@Produces("application/json;charset=UTF-8")
@Path("{regattaname}/addracecolumns")
@@ -1630,9 +1696,10 @@ public class RegattasResource extends AbstractSailingServerResource {
} else {
final String raceNamePrefix = prefix == null ? "R" : prefix;
int oneBasedNumberOfLast = Util.size(series.getRaceColumns());
- for (int i = 1; i <= (numberOfRaces==null?1:numberOfRaces); i++) {
+ for (int i = 1; i <= (numberOfRaces == null ? 1 : numberOfRaces); i++) {
final int oneBasedNumberOfNext = findNextFreeRaceName(series, raceNamePrefix, oneBasedNumberOfLast);
- final RaceColumnInSeries raceColumn = addRaceColumn(regattaName, series.getName(), getRaceName(raceNamePrefix, oneBasedNumberOfNext));
+ final RaceColumnInSeries raceColumn = addRaceColumn(regattaName, series.getName(),
+ getRaceName(raceNamePrefix, oneBasedNumberOfNext));
final JSONObject raceColumnDataAsJson = new JSONObject();
raceColumnDataAsJson.put("seriesname", raceColumn.getSeries().getName());
raceColumnDataAsJson.put("racename", raceColumn.getName());
@@ -1640,7 +1707,8 @@ public class RegattasResource extends AbstractSailingServerResource {
oneBasedNumberOfLast = oneBasedNumberOfNext;
}
String json = jsonResponse.toJSONString();
- response = Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
+ response = Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8")
+ .build();
}
}
return response;
@@ -1650,7 +1718,8 @@ public class RegattasResource extends AbstractSailingServerResource {
@Path("{regattaname}/removeracecolumn")
public Response addRaceColumns(@PathParam("regattaname") String regattaName,
@QueryParam("racecolumn") String raceColumnName) {
- SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regattaName));
+ SecurityUtils.getSubject()
+ .checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regattaName));
final Response response;
Regatta regatta = findRegattaByName(regattaName);
if (regatta == null) {
@@ -1674,9 +1743,9 @@ public class RegattasResource extends AbstractSailingServerResource {
}
private String getRaceName(final String raceNamePrefix, final int number) {
- return raceNamePrefix+number;
+ return raceNamePrefix + number;
}
-
+
private int findNextFreeRaceName(Series series, String raceNamePrefix, int oneBasedNumberOfLast) {
int result = oneBasedNumberOfLast;
boolean clash = false;
@@ -1695,7 +1764,8 @@ public class RegattasResource extends AbstractSailingServerResource {
}
private RaceColumnInSeries addRaceColumn(String regattaName, String seriesName, String columnName) {
- SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regattaName));
+ SecurityUtils.getSubject()
+ .checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regattaName));
return getService().apply(new AddColumnToSeries(new RegattaName(regattaName), seriesName, columnName));
}
@@ -1713,7 +1783,7 @@ public class RegattasResource extends AbstractSailingServerResource {
}
return result;
}
-
+
@POST
@Path("/updateOrCreateSeries")
@Consumes(MediaType.APPLICATION_JSON)
@@ -1722,39 +1792,39 @@ public class RegattasResource extends AbstractSailingServerResource {
Object requestBody = JSONValue.parseWithException(json);
JSONObject requestObject = Helpers.toJSONObjectSafe(requestBody);
String regattaName = (String) requestObject.get("regattaName");
-
+
Regatta regatta = getService().getRegattaByName(regattaName);
if (regatta != null) {
-// SecurityUtils.getSubject()
-// .checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName()));
+ // SecurityUtils.getSubject()
+ // .checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName()));
}
-
-
+
String seriesName = (String) requestObject.get("seriesName");
String seriesNameNew = (String) requestObject.get("seriesNameNew");
boolean isMedal = (boolean) requestObject.get("isMedal");
boolean isFleetsCanRunInParallel = (boolean) requestObject.get("isFleetsCanRunInParallel");
boolean startsWithZeroScore = (boolean) requestObject.get("startsWithZeroScore");
- boolean firstColumnIsNonDiscardableCarryForward = (boolean) requestObject.get("firstColumnIsNonDiscardableCarryForward");
+ boolean firstColumnIsNonDiscardableCarryForward = (boolean) requestObject
+ .get("firstColumnIsNonDiscardableCarryForward");
boolean hasSplitFleetContiguousScoring = (boolean) requestObject.get("hasSplitFleetContiguousScoring");
-
+
Integer maximumNumberOfDiscards = null;
if (requestObject.containsKey("maximumNumberOfDiscards")) {
maximumNumberOfDiscards = (int) (long) requestObject.get("maximumNumberOfDiscards");
}
-
+
int[] resultDiscardingThresholds = null;
- if(requestObject.containsKey("resultDiscardingThresholds")) {
+ if (requestObject.containsKey("resultDiscardingThresholds")) {
JSONArray resultDiscardingThresholdsRaw = (JSONArray) requestObject.get("resultDiscardingThresholds");
resultDiscardingThresholds = new int[resultDiscardingThresholdsRaw.size()];
for (int i = 0; i < resultDiscardingThresholdsRaw.size(); i++) {
resultDiscardingThresholds[i] = (int) (long) resultDiscardingThresholdsRaw.get(i);
}
}
-
+
JSONArray fleetsRaw = (JSONArray) requestObject.get("fleets");
List fleets = new ArrayList<>();
- for(Object fleetRaw:fleetsRaw) {
+ for (Object fleetRaw : fleetsRaw) {
JSONObject fleet = Helpers.toJSONObjectSafe(fleetRaw);
String fleetName = (String) fleet.get("fleetName");
int orderNo = (int) (long) fleet.get("orderNo");
diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/regattasCompetitorsCreateAndAdd.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/regattasCompetitorsCreateAndAdd.html
index 48495d4a607..4915138a711 100755
--- a/java/com.sap.sailing.server.gateway/webservices/api/v1/regattasCompetitorsCreateAndAdd.html
+++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/regattasCompetitorsCreateAndAdd.html
@@ -37,6 +37,8 @@ All slashes contained within the {regattaname} parameter must be replaced by "__
timeontimefactor a double value telling the ToT / TMF / time-on-time factor for handicap racing
timeondistanceallowancepernauticalmileasmillis distance-based allowance in milliseconds for handicap racing (ToD)
searchtag a search tag for the competitor
+
competitorName the name to use for the newly created/added competitor
+
competitorEmail the email to use for the newly created/added competitor
From ec0a95268b55a2edaf66aa7eb20d2993c8eea7ce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kai=20B=C3=B6rnert?=
Date: Fri, 20 Jul 2018 08:58:55 +0200
Subject: [PATCH 015/197] bug4508 enabled permission checks for new api
---
.../gateway/jaxrs/api/MarkRessource.java | 11 ++-
.../gateway/jaxrs/api/RegattasResource.java | 73 ++++++++++---------
2 files changed, 44 insertions(+), 40 deletions(-)
diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkRessource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkRessource.java
index 33e5d13a973..4266b8fa1da 100644
--- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkRessource.java
+++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkRessource.java
@@ -16,6 +16,7 @@ import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
+import org.apache.shiro.SecurityUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
@@ -46,6 +47,8 @@ import com.sap.sailing.domain.common.NotFoundException;
import com.sap.sailing.domain.common.PassingInstruction;
import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException;
import com.sap.sailing.domain.common.racelog.tracking.DoesNotHaveRegattaLogException;
+import com.sap.sailing.domain.common.security.Permission;
+import com.sap.sailing.domain.common.security.Permission.Mode;
import com.sap.sailing.domain.common.tracking.GPSFix;
import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl;
import com.sap.sailing.domain.leaderboard.Leaderboard;
@@ -66,7 +69,7 @@ public class MarkRessource extends AbstractSailingServerResource {
@Consumes(MediaType.APPLICATION_JSON)
@Produces("application/json;charset=UTF-8")
public Response addMarkToRegatta(String json) throws Exception {
- // SecurityUtils.getSubject().checkPermission(Permission.MANAGE_COURSE_LAYOUT.getStringPermission(Mode.CREATE));
+ SecurityUtils.getSubject().checkPermission(Permission.MANAGE_COURSE_LAYOUT.getStringPermission(Mode.CREATE));
Object requestBody = JSONValue.parseWithException(json);
JSONObject requestObject = Helpers.toJSONObjectSafe(requestBody);
@@ -93,7 +96,7 @@ public class MarkRessource extends AbstractSailingServerResource {
@Produces("application/json;charset=UTF-8")
public Response addMarkFix(String json)
throws DoesNotHaveRegattaLogException, ParseException, JsonDeserializationException {
- // SecurityUtils.getSubject().checkPermission(Permission.MANAGE_MARK_POSITIONS.getStringPermission(Mode.CREATE));
+ SecurityUtils.getSubject().checkPermission(Permission.MANAGE_MARK_POSITIONS.getStringPermission(Mode.CREATE));
Object requestBody = JSONValue.parseWithException(json);
JSONObject requestObject = Helpers.toJSONObjectSafe(requestBody);
@@ -136,7 +139,7 @@ public class MarkRessource extends AbstractSailingServerResource {
@Produces("application/json;charset=UTF-8")
public Response addCourseDefinitionToRaceLog(String json)
throws DoesNotHaveRegattaLogException, NotFoundException, ParseException, JsonDeserializationException {
- // SecurityUtils.getSubject().checkPermission(Permission.MANAGE_COURSE_LAYOUT.getStringPermission(Mode.CREATE));
+ SecurityUtils.getSubject().checkPermission(Permission.MANAGE_COURSE_LAYOUT.getStringPermission(Mode.CREATE));
Object requestBody = JSONValue.parseWithException(json);
JSONObject requestObject = Helpers.toJSONObjectSafe(requestBody);
@@ -199,7 +202,7 @@ public class MarkRessource extends AbstractSailingServerResource {
@Produces("application/json;charset=UTF-8")
public Response addCompetitorToRace(String json) throws DoesNotHaveRegattaLogException, NotFoundException,
ParseException, JsonDeserializationException, CompetitorRegistrationOnRaceLogDisabledException {
- // SecurityUtils.getSubject().checkPermission(Permission.MANAGE_COURSE_LAYOUT.getStringPermission(Mode.CREATE));
+ SecurityUtils.getSubject().checkPermission(Permission.MANAGE_COURSE_LAYOUT.getStringPermission(Mode.CREATE));
Object requestBody = JSONValue.parseWithException(json);
JSONObject requestObject = Helpers.toJSONObjectSafe(requestBody);
diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java
index a904600be20..3e1c115a664 100644
--- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java
+++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java
@@ -1795,46 +1795,47 @@ public class RegattasResource extends AbstractSailingServerResource {
Regatta regatta = getService().getRegattaByName(regattaName);
if (regatta != null) {
- // SecurityUtils.getSubject()
- // .checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName()));
- }
+ SecurityUtils.getSubject()
+ .checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName()));
+ String seriesName = (String) requestObject.get("seriesName");
+ String seriesNameNew = (String) requestObject.get("seriesNameNew");
+ boolean isMedal = (boolean) requestObject.get("isMedal");
+ boolean isFleetsCanRunInParallel = (boolean) requestObject.get("isFleetsCanRunInParallel");
+ boolean startsWithZeroScore = (boolean) requestObject.get("startsWithZeroScore");
+ boolean firstColumnIsNonDiscardableCarryForward = (boolean) requestObject
+ .get("firstColumnIsNonDiscardableCarryForward");
+ boolean hasSplitFleetContiguousScoring = (boolean) requestObject.get("hasSplitFleetContiguousScoring");
- String seriesName = (String) requestObject.get("seriesName");
- String seriesNameNew = (String) requestObject.get("seriesNameNew");
- boolean isMedal = (boolean) requestObject.get("isMedal");
- boolean isFleetsCanRunInParallel = (boolean) requestObject.get("isFleetsCanRunInParallel");
- boolean startsWithZeroScore = (boolean) requestObject.get("startsWithZeroScore");
- boolean firstColumnIsNonDiscardableCarryForward = (boolean) requestObject
- .get("firstColumnIsNonDiscardableCarryForward");
- boolean hasSplitFleetContiguousScoring = (boolean) requestObject.get("hasSplitFleetContiguousScoring");
-
- Integer maximumNumberOfDiscards = null;
- if (requestObject.containsKey("maximumNumberOfDiscards")) {
- maximumNumberOfDiscards = (int) (long) requestObject.get("maximumNumberOfDiscards");
- }
-
- int[] resultDiscardingThresholds = null;
- if (requestObject.containsKey("resultDiscardingThresholds")) {
- JSONArray resultDiscardingThresholdsRaw = (JSONArray) requestObject.get("resultDiscardingThresholds");
- resultDiscardingThresholds = new int[resultDiscardingThresholdsRaw.size()];
- for (int i = 0; i < resultDiscardingThresholdsRaw.size(); i++) {
- resultDiscardingThresholds[i] = (int) (long) resultDiscardingThresholdsRaw.get(i);
+ Integer maximumNumberOfDiscards = null;
+ if (requestObject.containsKey("maximumNumberOfDiscards")) {
+ maximumNumberOfDiscards = (int) (long) requestObject.get("maximumNumberOfDiscards");
}
+
+ int[] resultDiscardingThresholds = null;
+ if (requestObject.containsKey("resultDiscardingThresholds")) {
+ JSONArray resultDiscardingThresholdsRaw = (JSONArray) requestObject.get("resultDiscardingThresholds");
+ resultDiscardingThresholds = new int[resultDiscardingThresholdsRaw.size()];
+ for (int i = 0; i < resultDiscardingThresholdsRaw.size(); i++) {
+ resultDiscardingThresholds[i] = (int) (long) resultDiscardingThresholdsRaw.get(i);
+ }
+ }
+
+ JSONArray fleetsRaw = (JSONArray) requestObject.get("fleets");
+ List fleets = new ArrayList<>();
+ for (Object fleetRaw : fleetsRaw) {
+ JSONObject fleet = Helpers.toJSONObjectSafe(fleetRaw);
+ String fleetName = (String) fleet.get("fleetName");
+ int orderNo = (int) (long) fleet.get("orderNo");
+ String htmlColor = (String) fleet.get("htmlColor");
+ fleets.add(new FleetDTO(fleetName, orderNo, new RGBColor(htmlColor)));
+ }
+ getService().apply(new UpdateSeries(regatta.getRegattaIdentifier(), seriesName, seriesNameNew, isMedal,
+ isFleetsCanRunInParallel, resultDiscardingThresholds, startsWithZeroScore,
+ firstColumnIsNonDiscardableCarryForward, hasSplitFleetContiguousScoring, maximumNumberOfDiscards,
+ fleets));
}
- JSONArray fleetsRaw = (JSONArray) requestObject.get("fleets");
- List fleets = new ArrayList<>();
- for (Object fleetRaw : fleetsRaw) {
- JSONObject fleet = Helpers.toJSONObjectSafe(fleetRaw);
- String fleetName = (String) fleet.get("fleetName");
- int orderNo = (int) (long) fleet.get("orderNo");
- String htmlColor = (String) fleet.get("htmlColor");
- fleets.add(new FleetDTO(fleetName, orderNo, new RGBColor(htmlColor)));
- }
- getService().apply(new UpdateSeries(regatta.getRegattaIdentifier(), seriesName, seriesNameNew, isMedal,
- isFleetsCanRunInParallel, resultDiscardingThresholds, startsWithZeroScore,
- firstColumnIsNonDiscardableCarryForward, hasSplitFleetContiguousScoring, maximumNumberOfDiscards,
- fleets));
+
return Response.ok().header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
}
From 97b1e4fb269be3b07e099fdfd1c6f0255a5ef61e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kai=20B=C3=B6rnert?=
Date: Fri, 20 Jul 2018 10:59:18 +0200
Subject: [PATCH 016/197] bug4508 improved error messages if an mark cannot be
resolved, returning the new course layout after update was applied in json
response
---
.../gateway/jaxrs/api/MarkRessource.java | 29 ++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkRessource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkRessource.java
index 4266b8fa1da..c7f371c8231 100644
--- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkRessource.java
+++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkRessource.java
@@ -58,6 +58,12 @@ import com.sap.sailing.domain.regattalike.HasRegattaLike;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
import com.sap.sailing.server.gateway.deserialization.impl.Helpers;
import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource;
+import com.sap.sailing.server.gateway.serialization.coursedata.impl.ControlPointJsonSerializer;
+import com.sap.sailing.server.gateway.serialization.coursedata.impl.CourseBaseJsonSerializer;
+import com.sap.sailing.server.gateway.serialization.coursedata.impl.CourseJsonSerializer;
+import com.sap.sailing.server.gateway.serialization.coursedata.impl.GateJsonSerializer;
+import com.sap.sailing.server.gateway.serialization.coursedata.impl.MarkJsonSerializer;
+import com.sap.sailing.server.gateway.serialization.coursedata.impl.WaypointJsonSerializer;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.impl.MillisecondsTimePoint;
@@ -171,12 +177,21 @@ public class MarkRessource extends AbstractSailingServerResource {
if (marksRaw.size() == 1) {
String markName = (String) marksRaw.get(0);
Mark mark = getService().getBaseDomainFactory().getExistingMarkByIdAsString(markName);
+ if (mark == null) {
+ throw new IllegalStateException("Could not resolve mark " + markName);
+ }
controlPoints.add(new Pair<>(mark, passing));
} else {
String markNameA = (String) marksRaw.get(0);
String markNameB = (String) marksRaw.get(1);
Mark markA = getService().getBaseDomainFactory().getExistingMarkByIdAsString(markNameA);
Mark markB = getService().getBaseDomainFactory().getExistingMarkByIdAsString(markNameB);
+ if (markA == null) {
+ throw new IllegalStateException("Could not resolve mark " + markA);
+ }
+ if (markB == null) {
+ throw new IllegalStateException("Could not resolve mark " + markB);
+ }
controlPoints.add(new Pair<>(
new ControlPointWithTwoMarksImpl(markA, markB, markA.getName() + "-" + markB.getName()),
passing));
@@ -185,6 +200,7 @@ public class MarkRessource extends AbstractSailingServerResource {
Course course = new CourseImpl(courseName, lastPublishedCourse.getWaypoints());
+
try {
course.update(controlPoints, getService().getBaseDomainFactory());
} catch (Exception e) {
@@ -193,7 +209,18 @@ public class MarkRessource extends AbstractSailingServerResource {
RaceLogEvent event = new RaceLogCourseDesignChangedEventImpl(MillisecondsTimePoint.now(),
getService().getServerAuthor(), raceLog.getCurrentPassId(), course, CourseDesignerMode.ADMIN_CONSOLE);
raceLog.add(event);
- return Response.ok().header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
+
+ CourseBase updatedPublishedCourse = new LastPublishedCourseDesignFinder(raceLog,
+ /* onlyCoursesWithValidWaypointList */ false).analyze();
+
+ JSONObject jsonResult = new JSONObject();
+ jsonResult.put("course",
+ new CourseJsonSerializer(new CourseBaseJsonSerializer(
+ new WaypointJsonSerializer(new ControlPointJsonSerializer(new MarkJsonSerializer(),
+ new GateJsonSerializer(new MarkJsonSerializer()))))).serialize(updatedPublishedCourse));
+
+ return Response.ok(jsonResult.toJSONString())
+ .header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
}
@POST
From 3289d0568d5cbfb999228be3ab8694ab73863685 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kai=20B=C3=B6rnert?=
Date: Fri, 20 Jul 2018 13:34:54 +0200
Subject: [PATCH 017/197] bug4508 fixed addMarkToRegatta call
---
.../sailing/server/gateway/jaxrs/api/MarkRessource.java | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkRessource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkRessource.java
index c7f371c8231..a4dda275d9c 100644
--- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkRessource.java
+++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkRessource.java
@@ -40,7 +40,6 @@ import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.impl.ControlPointWithTwoMarksImpl;
import com.sap.sailing.domain.base.impl.CourseDataImpl;
import com.sap.sailing.domain.base.impl.CourseImpl;
-import com.sap.sailing.domain.base.impl.MarkImpl;
import com.sap.sailing.domain.common.CourseDesignerMode;
import com.sap.sailing.domain.common.LeaderboardNameConstants;
import com.sap.sailing.domain.common.NotFoundException;
@@ -83,7 +82,7 @@ public class MarkRessource extends AbstractSailingServerResource {
String markName = (String) requestObject.get("markName");
UUID markId = UUID.randomUUID();
- MarkImpl mark = new MarkImpl(markId, markName);
+ Mark mark = getService().getBaseDomainFactory().getOrCreateMark(markId, markName);
String regattaName = (String) requestObject.get("regattaName");
RegattaLog regattaLog = getRegattaLogInternal(regattaName);
RegattaLogDefineMarkEventImpl event = new RegattaLogDefineMarkEventImpl(MillisecondsTimePoint.now(),
@@ -200,7 +199,6 @@ public class MarkRessource extends AbstractSailingServerResource {
Course course = new CourseImpl(courseName, lastPublishedCourse.getWaypoints());
-
try {
course.update(controlPoints, getService().getBaseDomainFactory());
} catch (Exception e) {
@@ -263,9 +261,8 @@ public class MarkRessource extends AbstractSailingServerResource {
}
return Response.ok().header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
}
-
- private Iterable filterCompetitorDuplicates(
- Map competitorToBoatMappingsToRegister,
+
+ private Iterable filterCompetitorDuplicates(Map competitorToBoatMappingsToRegister,
Map competitorToBoatMappingsRegistered) {
final Set competitorsToUnregister = new HashSet<>();
Util.addAll(competitorToBoatMappingsRegistered.keySet(), competitorsToUnregister);
From 46dd886200ca85bbee7b85847893d7a1bb53a83c Mon Sep 17 00:00:00 2001
From: Alessandro Stoltenberg
Date: Fri, 20 Jul 2018 16:33:11 +0200
Subject: [PATCH 018/197] bug4134_2: A working version of colored
windstreamlets according to minmax speed.
---
.../SwarmMinMaxSpeedChangedListener.java | 5 +
.../WindStreamletsRaceboardOverlay.java | 113 +++++++++++-------
.../simulator/streamlets/SchmittTrigger.java | 38 ++++++
.../gwt/ui/simulator/streamlets/Swarm.java | 90 +++++++++++++-
4 files changed, 200 insertions(+), 46 deletions(-)
create mode 100755 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/SwarmMinMaxSpeedChangedListener.java
create mode 100755 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/SchmittTrigger.java
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/SwarmMinMaxSpeedChangedListener.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/SwarmMinMaxSpeedChangedListener.java
new file mode 100755
index 00000000000..5bb53f1ffc6
--- /dev/null
+++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/SwarmMinMaxSpeedChangedListener.java
@@ -0,0 +1,5 @@
+package com.sap.sailing.gwt.ui.shared.racemap;
+
+public interface SwarmMinMaxSpeedChangedListener {
+ void onSwarmMinMaxSpeedChanged();
+}
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java
index 454418dda8f..059453c0a83 100755
--- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java
+++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java
@@ -11,6 +11,7 @@ import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.canvas.dom.client.TextMetrics;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
+import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.controls.ControlPosition;
import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -18,6 +19,7 @@ import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.WindSourceType;
import com.sap.sailing.gwt.ui.actions.GetWindInfoAction;
+import com.sap.sailing.gwt.ui.client.NumberFormatterFactory;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.shared.racemap.CoordinateSystem;
@@ -44,7 +46,7 @@ import com.sap.sse.gwt.client.player.Timer;
* @author Axel Uhl (D043530)
*
*/
-public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay {
+public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implements SwarmMinMaxSpeedChangedListener{
public static final String LOAD_WIND_STREAMLET_DATA_CATEGORY = "loadWindStreamletData";
private static final int animationIntervalMillis = 40;
private static final long RESOLUTION_IN_MILLIS = 5000;
@@ -66,6 +68,8 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay {
private long latitudeCount;
private double latitudeSum;
+
+ private final NumberFormat numberFormatOneDecimal = NumberFormatterFactory.getDecimalFormat(1);
public WindStreamletsRaceboardOverlay(MapWidget map, int zIndex, final Timer timer,
RegattaAndRaceIdentifier raceIdentifier, SailingServiceAsync sailingService,
@@ -130,45 +134,62 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay {
streamletLegend.setCoordinateSpaceWidth(canvasWidth);
streamletLegend.setCoordinateSpaceHeight(canvasHeight); }
- private void drawLegend() {
- double x, y;
- x=100;
- y=16;
- double w = 1;
- double h = 20;
- int maxIdx = 300;
- Context2d context2d = streamletLegend.getContext2d();
- context2d.setFillStyle("rgba(0,0,0,.3)");
- context2d.setLineWidth(1.0);
- context2d.beginPath();
- context2d.fillRect(x-7.0, y-16.0, w*maxIdx+15.0, 56.0);
- context2d.closePath();
- context2d.stroke();
- context2d.setFillStyle("white");
- String label = stringMessages.windSpeedInKnots();
- TextMetrics txtmet;
- txtmet = context2d.measureText(label);
- context2d.fillText(label, x + (w*maxIdx - txtmet.getWidth())/2.0, y - 5.0);
- for(int idx=0; idx <= maxIdx; idx++) {
- //double speed = idx * 24.0 / maxIdx;
- double speed = 4.0 + idx * 16.0 / maxIdx;
- context2d.setFillStyle(windField.getColor(speed));
- context2d.beginPath();
- context2d.fillRect(x + idx*w, y, w, h);
- context2d.closePath();
- context2d.stroke();
- if (Math.abs(speed % 2.0) < (12.0/maxIdx)) {
- context2d.setStrokeStyle("white");
+ public void drawLegend() {
+ if (streamletLegend.isVisible()) {
+ streamletLegend.getContext2d().clearRect(0, 0, streamletLegend.getCoordinateSpaceWidth(),
+ streamletLegend.getCoordinateSpaceHeight());
+ if (swarm != null && swarm.isColored()) {
+ final double x = 100;
+ final double y = 16;
+ final double w = 1;
+ final double h = 20;
+ final double speed_max = swarm.getMaxParticleSpeedInKnots();
+ final double speed_min = swarm.getMinParticleSpeedInKnots();
+ final double speed_spread = speed_max - speed_min;
+ final int scale_spread;
+ if (speed_spread < 0.5) {
+ scale_spread = 300;
+ }
+ else if (speed_spread < 1) {
+ scale_spread = 100;
+ }
+ else {
+ scale_spread = 50;
+ }
+ final int maxIdx = 300;
+ Context2d context2d = streamletLegend.getContext2d();
+ context2d.setFillStyle("rgba(0,0,0,.3)");
context2d.setLineWidth(1.0);
context2d.beginPath();
- context2d.moveTo(x + idx*w, y + h);
- context2d.lineTo(x + idx*w, y + h + 7.0);
+ context2d.fillRect(x - 10.0, y - 16.0, w * maxIdx + 20.0, 56.0);
context2d.closePath();
context2d.stroke();
context2d.setFillStyle("white");
- label = ""+Math.round(speed);
+ String label = stringMessages.windSpeedInKnots();
+ TextMetrics txtmet;
txtmet = context2d.measureText(label);
- context2d.fillText(label, x + idx*w - txtmet.getWidth()/2.0, y + h + 8.0 + 8.0);
+ context2d.fillText(label, x + (w * maxIdx - txtmet.getWidth()) / 2.0, y - 5.0);
+ for (int idx = 0; idx <= maxIdx; idx++) {
+ final double speedSteps = speed_min + idx * (speed_max - speed_min) / maxIdx;
+ context2d.setFillStyle(swarm.getColorWithSpectrumBoundaries(speedSteps));
+ context2d.beginPath();
+ context2d.fillRect(x + idx * w, y, w, h);
+ context2d.closePath();
+ context2d.stroke();
+ if (idx % scale_spread == 0) {
+ context2d.setStrokeStyle("white");
+ context2d.setLineWidth(1.0);
+ context2d.beginPath();
+ context2d.moveTo(x + idx * w, y + h);
+ context2d.lineTo(x + idx * w, y + h + 7.0);
+ context2d.closePath();
+ context2d.stroke();
+ context2d.setFillStyle("white");
+ label = numberFormatOneDecimal.format(speedSteps);
+ txtmet = context2d.measureText(label);
+ context2d.fillText(label, x + idx * w - txtmet.getWidth() / 2.0, y + h + 8.0 + 8.0);
+ }
+ }
}
}
}
@@ -180,7 +201,9 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay {
this.swarm = new Swarm(this, map, timer, windField, new StreamletParameters());
}
initCanvasOrigin();
+ this.swarm.setColors(colored);
this.swarm.start(animationIntervalMillis);
+ this.swarm.addSwarmMinMaxSpeedChangedListener(this);
}
private void scheduleWindDataRefresh() {
@@ -203,8 +226,9 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay {
}
private void stopStreamlets() {
- if (swarm != null) {
+ if (this.swarm != null) {
this.swarm.stop();
+ this.swarm.removeSwarmMinMaxSpeedChangedListener(this);
}
}
@@ -298,13 +322,13 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay {
public void setVisible(boolean isVisible) {
if (getCanvas() != null) {
if (isVisible) {
- if (this.windField.getColors()) {
- this.streamletLegend.setVisible(true);
- }
this.startStreamlets();
this.visible = isVisible;
+ if (this.swarm.isColored()) {
+ this.streamletLegend.setVisible(true);
+ }
} else {
- if (this.windField.getColors()) {
+ if (this.swarm.isColored()) {
this.streamletLegend.setVisible(false);
}
this.stopStreamlets();
@@ -312,14 +336,15 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay {
}
}
}
-
+private boolean colored;
public void setColors(boolean isColored) {
- this.windField.setColors(isColored);
+ this.colored = isColored;
if ((isColored) && (firstColoring)) {
firstColoring = false;
- this.drawLegend();
}
this.streamletLegend.setVisible(isColored);
+ if (swarm != null) {
+ swarm.setColors(isColored);}
}
@Override
@@ -337,4 +362,8 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay {
swarm.onBoundsChanged(zoomChanged, swarmPause);
}
}
+
+ public void onSwarmMinMaxSpeedChanged() {
+ drawLegend();
+ }
}
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/SchmittTrigger.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/SchmittTrigger.java
new file mode 100755
index 00000000000..d6e2d158167
--- /dev/null
+++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/SchmittTrigger.java
@@ -0,0 +1,38 @@
+package com.sap.sailing.gwt.ui.simulator.streamlets;
+
+public class SchmittTrigger {
+ private double percentage;
+
+ public SchmittTrigger() {}
+ public SchmittTrigger(double percentageTriggerThreeshold) {
+ this.percentage = percentageTriggerThreeshold;
+ }
+
+ public boolean isGreaterThanThreeshold(double input,double threesholdValue) {
+ if (input * (1 + percentage/100) > threesholdValue) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ public boolean isLesserThanThreeshold(double input,double threesholdValue) {
+ if (input * (1 - percentage/100) < threesholdValue) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ public boolean isValueChangeTriggered(double input, double threesholdValue) {
+ if (isGreaterThanThreeshold(input, threesholdValue) || isLesserThanThreeshold(input, threesholdValue)) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ public double getTriggerPercentage() {
+ return percentage;
+ }
+}
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java
index 5278452dd46..47bea5ab3fa 100755
--- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java
+++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java
@@ -1,6 +1,8 @@
package com.sap.sailing.gwt.ui.simulator.streamlets;
import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.Context2d;
@@ -13,6 +15,7 @@ import com.google.gwt.maps.client.events.bounds.BoundsChangeMapHandler;
import com.google.gwt.user.client.Timer;
import com.sap.sailing.gwt.ui.client.shared.racemap.BoundsUtil;
import com.sap.sailing.gwt.ui.client.shared.racemap.CoordinateSystem;
+import com.sap.sailing.gwt.ui.shared.racemap.SwarmMinMaxSpeedChangedListener;
import com.sap.sailing.gwt.ui.simulator.StreamletParameters;
import com.sap.sailing.gwt.ui.simulator.racemap.FullCanvasOverlay;
import com.sap.sse.gwt.client.player.TimeListener;
@@ -74,6 +77,8 @@ public class Swarm implements TimeListener {
timePoint = timer.getTime();
cosineOfAverageLatitude = 1.0; // default to equator
diffPx = new Vector(0, 0);
+ swarmMinMaxSpeedChangedListeners = new HashSet<>();
+ schmittTrigger = new SchmittTrigger(/*percent*/ 25);
}
public void start(final int animationIntervalMillis) {
@@ -113,7 +118,9 @@ public class Swarm implements TimeListener {
while (!done && attempts-- > 0) {
particle = new Particle();
particle.currentPosition = getRandomPosition();
- if (field.inBounds(particle.currentPosition)) {
+ // Is the if check really needed? getRandomPosition() returns always a position that is within the
+ // visibleBoundsOfField. visibleBoundsOfField is always within fieldBounds. See updateBounds().
+ if(field.inBounds(particle.currentPosition)) {
Vector v = field.getVector(particle.currentPosition, timePoint);
double weight = field.getParticleWeight(particle.currentPosition, v);
if (weight >= Math.random()) {
@@ -145,7 +152,6 @@ public class Swarm implements TimeListener {
result = LatLng.newInstance(latDeg, lngDeg);
return result;
}
-
private Particle[] createParticles() {
Particle[] newParticles = new Particle[nParticles];
for (int idx = 0; idx < newParticles.length; idx++) {
@@ -234,7 +240,7 @@ public class Swarm implements TimeListener {
}
double particleSpeed = particle.v == null ? 0 : particle.v.length();
ctxt.setLineWidth(field.getLineWidth(particleSpeed));
- ctxt.setStrokeStyle(field.getColor(particleSpeed));
+ ctxt.setStrokeStyle(getColorWithSpectrumBoundaries(particleSpeed));
ctxt.beginPath();
ctxt.moveTo(particle.previousPixelCoordinate.x, particle.previousPixelCoordinate.y);
ctxt.lineTo(particle.currentPixelCoordinate.x, particle.currentPixelCoordinate.y);
@@ -242,11 +248,61 @@ public class Swarm implements TimeListener {
}
}
+ private boolean colored = false;
+ public String getColorWithSpectrumBoundaries(double speed) {
+ if (colored) {
+ double h = (1 - (speed - minParticleSpeedInKnots)/(maxParticleSpeedInKnots - minParticleSpeedInKnots)) * 240;
+ return "hsl(" + Math.round(h) + ", 100%, 50%)";
+ } else {
+ return "rgba(255,255,255," + Math.min(1.0, speed / 40) + ")";
+ }
+ }
+ public void setColors(boolean isColored) {
+ this.colored = isColored;
+ }
+
+ public boolean isColored() {
+ return colored;
+ }
+
+ private double maxParticleSpeedInKnots = 0.0;
+ /**
+ * @return the maxParticleSpeedInKnots
+ */
+ public double getMaxParticleSpeedInKnots() {
+ return maxParticleSpeedInKnots;
+ }
+
+ /**
+ * @return the minParticleSpeedInKnots
+ */
+ public double getMinParticleSpeedInKnots() {
+ return minParticleSpeedInKnots;
+ }
+
+ private double minParticleSpeedInKnots = 120.0;
+
+ private boolean isNotifyListeners = true;
+
+ private void notifyListeners() {
+ if (isNotifyListeners) {
+ for (SwarmMinMaxSpeedChangedListener listener : swarmMinMaxSpeedChangedListeners) {
+ listener.onSwarmMinMaxSpeedChanged();
+ }
+ }
+ }
+
+ private final SchmittTrigger schmittTrigger;
+
/**
* Moves each particle by its vector {@link Particle#v} multiplied by the speed which is 0.01 times the
- * {@link VectorField#getMotionScale(int)} at the map's current zoom level.
+ * {@link VectorField#getMotionScale(int)} at the map's current zoom level. Also the max and min speed fields of the
+ * swarm get updated and the listeners get notified.
*/
private boolean execute(Vector diffPx) {
+ boolean isUpdateListeners = false;
+ double minSpeed = 120.0;
+ double maxSpeed = 0.0;
double speed = field.getMotionScale(map.getZoom());
for (int idx = 0; idx < particles.length; idx++) {
Particle particle = particles[idx];
@@ -268,6 +324,12 @@ public class Swarm implements TimeListener {
particle.stepsToLive--;
if ((particle.stepsToLive > 0) && (this.field.inBounds(particle.currentPosition))) {
particle.v = field.getVector(particle.currentPosition, timePoint);
+ if (particle.v.length() > maxSpeed) {
+ maxSpeed = particle.v.length();
+ }
+ if (particle.v.length() < minSpeed) {
+ minSpeed = particle.v.length();
+ }
} else {
particle.v = null;
}
@@ -276,7 +338,17 @@ public class Swarm implements TimeListener {
particles[idx] = this.createParticle();
}
}
+ if (schmittTrigger.isValueChangeTriggered(maxSpeed, maxParticleSpeedInKnots)) {
+ maxParticleSpeedInKnots = maxSpeed;
+ isUpdateListeners = true;
+ }
+ if (schmittTrigger.isValueChangeTriggered(minSpeed, minParticleSpeedInKnots)) {
+ minParticleSpeedInKnots = minSpeed;
+ isUpdateListeners = true;
+ }
+ this.isNotifyListeners = isUpdateListeners;
drawSwarm();
+ notifyListeners();
return true;
}
@@ -288,4 +360,14 @@ public class Swarm implements TimeListener {
public void timeChanged(Date newTime, Date oldTime) {
timePoint = newTime;
}
+
+ private final Set swarmMinMaxSpeedChangedListeners;
+ public void addSwarmMinMaxSpeedChangedListener(SwarmMinMaxSpeedChangedListener listener) {
+ swarmMinMaxSpeedChangedListeners.add(listener);
+ }
+ public void removeSwarmMinMaxSpeedChangedListener(SwarmMinMaxSpeedChangedListener listener) {
+ swarmMinMaxSpeedChangedListeners.remove(listener);
+ }
+
+
}
From aecf28f9729e81ddf9c53a7d30e9cbb8e22b72af Mon Sep 17 00:00:00 2001
From: Alessandro Stoltenberg
Date: Fri, 20 Jul 2018 16:51:25 +0200
Subject: [PATCH 019/197] bug4134_2: Added spectrum spread for non-colored
streamlets.
---
.../com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java
index 47bea5ab3fa..3233c6f51fa 100755
--- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java
+++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java
@@ -254,7 +254,7 @@ public class Swarm implements TimeListener {
double h = (1 - (speed - minParticleSpeedInKnots)/(maxParticleSpeedInKnots - minParticleSpeedInKnots)) * 240;
return "hsl(" + Math.round(h) + ", 100%, 50%)";
} else {
- return "rgba(255,255,255," + Math.min(1.0, speed / 40) + ")";
+ return "rgba(255,255,255," + Math.min(1.0, (speed - minParticleSpeedInKnots)/(maxParticleSpeedInKnots - minParticleSpeedInKnots)) + ")";
}
}
public void setColors(boolean isColored) {
@@ -346,7 +346,7 @@ public class Swarm implements TimeListener {
minParticleSpeedInKnots = minSpeed;
isUpdateListeners = true;
}
- this.isNotifyListeners = isUpdateListeners;
+ isNotifyListeners = isUpdateListeners;
drawSwarm();
notifyListeners();
return true;
From aa1d8cc793cf2eeaa425d365b8fae589b983dfb2 Mon Sep 17 00:00:00 2001
From: Alessandro Stoltenberg
Date: Fri, 20 Jul 2018 17:56:46 +0200
Subject: [PATCH 020/197] bug4134_2: commentbug4134_2: commentss
---
.../gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java | 1 +
.../java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java | 1 +
2 files changed, 2 insertions(+)
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java
index 059453c0a83..5b51f21b779 100755
--- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java
+++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java
@@ -157,6 +157,7 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen
scale_spread = 50;
}
final int maxIdx = 300;
+// final colors[] = swarm.getColorsForSteps(maxIdx);
Context2d context2d = streamletLegend.getContext2d();
context2d.setFillStyle("rgba(0,0,0,.3)");
context2d.setLineWidth(1.0);
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java
index 3233c6f51fa..e1e4729315c 100755
--- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java
+++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java
@@ -368,6 +368,7 @@ public class Swarm implements TimeListener {
public void removeSwarmMinMaxSpeedChangedListener(SwarmMinMaxSpeedChangedListener listener) {
swarmMinMaxSpeedChangedListeners.remove(listener);
}
+
}
From b4379c00c2ea2552b4109eb63eae7ea1182b4b9d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kai=20B=C3=B6rnert?=
Date: Tue, 24 Jul 2018 16:22:07 +0200
Subject: [PATCH 021/197] bug4508 added denoteForTracking call, added error
output for invalid regattaName in updateOrCreateSeries
---
.../jaxrs/api/LeaderboardsResource.java | 25 ++++++++++
.../gateway/jaxrs/api/RegattasResource.java | 5 +-
.../webservices/api/v1/index.html | 4 ++
.../v1/leaderboardRaceDenoteForTracking.html | 49 +++++++++++++++++++
4 files changed, 80 insertions(+), 3 deletions(-)
create mode 100644 java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardRaceDenoteForTracking.html
diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java
index e6fee705739..173dca94262 100644
--- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java
+++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java
@@ -69,6 +69,7 @@ import com.sap.sailing.domain.common.CourseDesignerMode;
import com.sap.sailing.domain.common.DeviceIdentifier;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.NoWindException;
+import com.sap.sailing.domain.common.NotFoundException;
import com.sap.sailing.domain.common.PassingInstruction;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.SpeedWithBearing;
@@ -82,6 +83,7 @@ import com.sap.sailing.domain.common.impl.MeterDistance;
import com.sap.sailing.domain.common.impl.RaceColumnConstants;
import com.sap.sailing.domain.common.racelog.RaceLogServletConstants;
import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants;
+import com.sap.sailing.domain.common.racelog.tracking.NotDenotableForRaceLogTrackingException;
import com.sap.sailing.domain.common.racelog.tracking.NotDenotedForRaceLogTrackingException;
import com.sap.sailing.domain.common.scalablevalue.impl.ScalableBearing;
import com.sap.sailing.domain.common.security.Permission;
@@ -1242,4 +1244,27 @@ public class LeaderboardsResource extends AbstractLeaderboardsResource {
}
return response;
}
+
+ @GET
+ @Path("{leaderboardName}/denoteForTracking")
+ public Response denoteForTracking(@PathParam("leaderboardName") String leaderboardName,
+ @QueryParam("raceColumnName") String raceColumnName, @QueryParam("fleetName") String fleetName,
+ @QueryParam("raceName") String raceName) throws NotFoundException, NotDenotableForRaceLogTrackingException {
+ Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName);
+ if (leaderboard == null) {
+ throw new NotFoundException("leaderboard with name " + leaderboardName + " not found");
+ }
+ RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName);
+ if (raceColumn == null) {
+ throw new NotFoundException("raceColumn with name " + raceColumnName + " not found");
+ }
+ Fleet fleet = raceColumn.getFleetByName(fleetName);
+ if (fleet == null) {
+ throw new NotFoundException("fleet with name " + fleetName + " not found");
+ }
+
+ boolean result = getRaceLogTrackingAdapter().denoteRaceForRaceLogTracking(getService(), leaderboard, raceColumn,
+ fleet, raceName);
+ return (result ? Response.ok() : Response.notModified()).build();
+ }
}
diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java
index 3e1c115a664..baadce1cb46 100644
--- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java
+++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java
@@ -1833,10 +1833,9 @@ public class RegattasResource extends AbstractSailingServerResource {
isFleetsCanRunInParallel, resultDiscardingThresholds, startsWithZeroScore,
firstColumnIsNonDiscardableCarryForward, hasSplitFleetContiguousScoring, maximumNumberOfDiscards,
fleets));
+ } else {
+ throw new IllegalStateException("RegattaName could not be resolved to regatta " + regattaName);
}
-
-
-
return Response.ok().header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
}
}
diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html
index f38a50d8dbf..aa6258bc3f4 100644
--- a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html
+++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html
@@ -205,6 +205,10 @@ name to make sure you get to the event you're interested in.