bug5058: added showOnlyActiveRacesForCompetitorId parameter to leaderboard v2 end point

Change-Id: If6fd5c1f98792e6a9e8acc13d2e301dd9979e490
This commit is contained in:
Axel Uhl committed 2019-05-29 16:28:55 +02:00
1 parent 6facaa1745
commit fbdd85b83b
6 files changed
+99 -17

No files matched your search

@@ -4,6 +4,5 @@ import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
import com.sap.sse.security.shared.WithQualifiedObjectIdentifier;
public interface RegattaAndRaceIdentifier extends RegattaIdentifier, RaceIdentifier, WithQualifiedObjectIdentifier {
TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier();
}
@@ -1833,7 +1833,6 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
.hasCurrentUserAnyPermission(SecuredDomainType.SIMULATOR.getPermission(DefaultActions.READ))) {
throw new UnauthorizedException("Not permitted to see simulator results.");
}
// get simulation-results from smart-future-cached simulation-service
SimulatorResultsDTO result = null;
SimulationService simulationService = getService().getSimulationService();
@@ -196,15 +196,19 @@ public abstract class AbstractLeaderboardsResource extends AbstractSailingServer
protected abstract JSONObject getLeaderboardJson(Leaderboard leaderboard, TimePoint resultTimePoint,
ResultStates resultState, Integer maxCompetitorsCount, List<String> raceColumnNames,
List<String> raceDetailNames, boolean competitorAndBoatIdsOnly) throws NoWindException, InterruptedException, ExecutionException;
List<String> raceDetailNames, boolean competitorAndBoatIdsOnly,
List<String> showOnlyActiveRacesForCompetitorIds)
throws NoWindException, InterruptedException, ExecutionException;
protected JSONObject getLeaderboardJson(ResultStates resultState, Integer maxCompetitorsCount,
TimePoint requestTimePoint, Leaderboard leaderboard, TimePoint timePoint, List<String> raceColumnNames,
List<String> raceDetailNames, boolean competitorAndBoatIdsOnly) throws NoWindException, InterruptedException, ExecutionException {
List<String> raceDetailNames, boolean competitorAndBoatIdsOnly,
List<String> showOnlyActiveRacesForCompetitorIds)
throws NoWindException, InterruptedException, ExecutionException {
final JSONObject jsonLeaderboard;
if (timePoint != null || resultState == ResultStates.Live) {
jsonLeaderboard = getLeaderboardJson(leaderboard, timePoint, resultState, maxCompetitorsCount,
raceColumnNames, raceDetailNames, competitorAndBoatIdsOnly);
raceColumnNames, raceDetailNames, competitorAndBoatIdsOnly, showOnlyActiveRacesForCompetitorIds);
} else {
jsonLeaderboard = createEmptyLeaderboardJson(leaderboard, resultState, maxCompetitorsCount);
}
@@ -200,7 +200,8 @@ public class LeaderboardsResource extends AbstractLeaderboardsResource {
TimePoint timePoint = calculateTimePointForResultState(leaderboard, resultState);
JSONObject jsonLeaderboard;
jsonLeaderboard = getLeaderboardJson(resultState, maxCompetitorsCount, requestTimePoint,
leaderboard, timePoint, /* race column names */ null, /* race detail names */ null, competitorAndBoatIdsOnly);
leaderboard, timePoint, /* race column names */ null, /* race detail names */ null, competitorAndBoatIdsOnly,
/* showOnlyActiveRacesForCompetitorIds */ null);
StringWriter sw = new StringWriter();
jsonLeaderboard.writeJSONString(sw);
String json = sw.getBuffer().toString();
@@ -220,7 +221,7 @@ public class LeaderboardsResource extends AbstractLeaderboardsResource {
@Override
protected JSONObject getLeaderboardJson(Leaderboard leaderboard,
TimePoint resultTimePoint, ResultStates resultState, Integer maxCompetitorsCount, List<String> raceColumnNames,
List<String> raceDetailNames, boolean competitorIdsOnly)
List<String> raceDetailNames, boolean competitorIdsOnly, List<String> showOnlyActiveRacesForCompetitorIds)
throws NoWindException, InterruptedException, ExecutionException {
LeaderboardDTO leaderboardDTO = leaderboard.getLeaderboardDTO(
resultTimePoint, Collections.<String> emptyList(), /* addOverallDetails */
@@ -27,6 +27,7 @@ import org.apache.shiro.SecurityUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.common.DetailType;
import com.sap.sailing.domain.common.ManeuverType;
@@ -46,6 +47,7 @@ import com.sap.sse.InvalidDateException;
import com.sap.sse.common.Distance;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
import com.sap.sse.security.shared.impl.SecuredSecurityTypes;
@@ -63,7 +65,8 @@ public class LeaderboardsResourceV2 extends AbstractLeaderboardsResource {
@QueryParam("time") String time, @QueryParam("timeasmillis") Long timeasmillis,
@QueryParam("maxCompetitorsCount") Integer maxCompetitorsCount,
@QueryParam("secret") String regattaSecret,
@DefaultValue("false") @QueryParam("competitorAndBoatIdsOnly") boolean competitorAndBoatIdsOnly) {
@DefaultValue("false") @QueryParam("competitorAndBoatIdsOnly") boolean competitorAndBoatIdsOnly,
@QueryParam("showOnlyActiveRacesForCompetitorIds") List<String> showOnlyActiveRacesForCompetitorIds) {
ShardingContext.setShardingConstraint(ShardingType.LEADERBOARDNAME, leaderboardName);
try {
Response response;
@@ -87,7 +90,9 @@ public class LeaderboardsResourceV2 extends AbstractLeaderboardsResource {
}
JSONObject jsonLeaderboard;
if (timePoint != null || resultState == ResultStates.Live) {
jsonLeaderboard = getLeaderboardJson(leaderboard, timePoint, resultState, maxCompetitorsCount, raceColumnNames, raceDetails, competitorAndBoatIdsOnly);
jsonLeaderboard = getLeaderboardJson(leaderboard, timePoint, resultState, maxCompetitorsCount,
raceColumnNames, raceDetails, competitorAndBoatIdsOnly,
showOnlyActiveRacesForCompetitorIds);
} else {
jsonLeaderboard = createEmptyLeaderboardJson(leaderboard, resultState, maxCompetitorsCount);
}
@@ -109,9 +114,9 @@ public class LeaderboardsResourceV2 extends AbstractLeaderboardsResource {
@Override
protected JSONObject getLeaderboardJson(Leaderboard leaderboard,
TimePoint resultTimePoint, ResultStates resultState, Integer maxCompetitorsCount,
List<String> raceColumnNames, List<String> raceDetailNames, boolean competitorAndBoatIdsOnly)
List<String> raceColumnNames, List<String> raceDetailNames, boolean competitorAndBoatIdsOnly, List<String> showOnlyActiveRacesForCompetitorIds)
throws NoWindException, InterruptedException, ExecutionException {
List<String> raceColumnsToShow = calculateRaceColumnsToShow(raceColumnNames, leaderboard.getRaceColumns());
List<String> raceColumnsToShow = calculateRaceColumnsToShow(leaderboard, raceColumnNames, showOnlyActiveRacesForCompetitorIds, resultTimePoint);
List<DetailType> raceDetailsToShow = calculateRaceDetailTypesToShow(raceDetailNames);
LeaderboardDTO leaderboardDTO = leaderboard.getLeaderboardDTO(
resultTimePoint, raceColumnsToShow, /* addOverallDetails */
@@ -424,22 +429,80 @@ public class LeaderboardsResourceV2 extends AbstractLeaderboardsResource {
}
/**
* If {@code raceColumnNames} is empty or {@code null}, return the names of all {@link raceColumnsOfLeaderboard}; otherwise
* return those race column names from {@code raceColumnsOfLeaderboard} that are also in {@code raceColumnNames}.
* If {@code raceColumnNames} is empty or {@code null}, return the names of all {@link raceColumnsOfLeaderboard};
* otherwise return those race column names from {@code raceColumnsOfLeaderboard} that are also in
* {@code raceColumnNames}.
* @param leaderboard TODO
* @param showOnlyActiveRacesForCompetitorIds
* {@code null}, or specifies zero or more competitor IDs, requesting that the result contained the race
* column holding that competitor's "active" race at the time requested; see also the
* {@code resultTimePoint} parameter. A race is active if it is currently live or is the last race for
* which the competitor has a result. In case multiple competitor IDs are given, all race columns that
* contain an active race of any of the competitors specified will be added to the result. It is possible
* that no such race is found, e.g., because racing has not started yet and the leaderboard is empty. No
* race column will be delivered then. In case the {@code raceColumnNames} parameter is used, too, the
* combined set of race columns from the columnNames parameter and this parameter will be delivered.
* @param resultTimePoint
* used together with {@code showOnlyActiveRacesForCompetitorIds} to determine which races are "active"
* for the competitors whose IDs are specified in {@link showOnlyActiveRacesForCompetitorIds} at that
* time
*/
private List<String> calculateRaceColumnsToShow(List<String> raceColumnNames, Iterable<RaceColumn> raceColumnsOfLeaderboard) {
private List<String> calculateRaceColumnsToShow(Leaderboard leaderboard,
List<String> raceColumnNames, Iterable<String> showOnlyActiveRacesForCompetitorIds,
TimePoint resultTimePoint) {
final Set<String> raceColumnNamesAsSet = new HashSet<>();
if (raceColumnNames != null) {
raceColumnNamesAsSet.addAll(raceColumnNames);
}
if (showOnlyActiveRacesForCompetitorIds != null) {
Util.addAll(getRaceColumnNamesOfActiveRaceColumnsForCompetitorIds(showOnlyActiveRacesForCompetitorIds,
leaderboard, resultTimePoint), raceColumnNamesAsSet);
}
// Calculates the race columns to retrieve data for
final List<String> raceColumnsToShow = new ArrayList<>();
for (final RaceColumn raceColumn : raceColumnsOfLeaderboard) {
if (raceColumnNamesAsSet.isEmpty() || raceColumnNamesAsSet.contains(raceColumn.getName())) {
for (final RaceColumn raceColumn : leaderboard.getRaceColumns()) {
// if showOnlyActiveRacesForCompetitorIds specifies at least one ID, don't default to delivering
// all columns, even if raceColumnNames is empty, but only show what resulted from finding the
// active races combined with columns explicitly specified in raceColumnNames.
if ((raceColumnNamesAsSet.isEmpty() && (showOnlyActiveRacesForCompetitorIds==null || Util.isEmpty(showOnlyActiveRacesForCompetitorIds)))
|| raceColumnNamesAsSet.contains(raceColumn.getName())) {
raceColumnsToShow.add(raceColumn.getName());
}
}
return raceColumnsToShow;
}
private Iterable<String> getRaceColumnNamesOfActiveRaceColumnsForCompetitorIds(
Iterable<String> showOnlyActiveRacesForCompetitorIds, Leaderboard leaderboard, TimePoint timePoint) {
final Set<String> result = new HashSet<>();
for (final String showOnlyActiveRacesForCompetitorId : showOnlyActiveRacesForCompetitorIds) {
final String nameOfActiveRaceColumnForCompetitor = getNameOfActiveRaceColumnForCompetitor(showOnlyActiveRacesForCompetitorId, leaderboard, timePoint);
if (nameOfActiveRaceColumnForCompetitor != null) {
result.add(nameOfActiveRaceColumnForCompetitor);
}
}
return result;
}
private String getNameOfActiveRaceColumnForCompetitor(String showOnlyActiveRacesForCompetitorId, Leaderboard leaderboard, TimePoint timePoint) {
final String result;
final TimePoint timePointOrLiveTimeIfNull = timePoint != null ? timePoint : leaderboard.getNowMinusDelay();
final Competitor competitor = leaderboard.getCompetitorByIdAsString(showOnlyActiveRacesForCompetitorId);
if (competitor != null) {
RaceColumn lastRaceColumnWithResultForCompetitorAtTimePoint = null;
for (final RaceColumn raceColumn : leaderboard.getRaceColumns()) {
if (leaderboard.getTotalPoints(competitor, raceColumn, timePointOrLiveTimeIfNull) != null) {
lastRaceColumnWithResultForCompetitorAtTimePoint = raceColumn;
}
}
if (lastRaceColumnWithResultForCompetitorAtTimePoint != null) {
result = lastRaceColumnWithResultForCompetitorAtTimePoint.getName();
} else {
result = null;
}
} else {
result = null;
}
return result;
}
}
@@ -46,7 +46,23 @@ There is also the 'ALL' shortcut constant which can be used to get all available
</tr>
<tr>
<td>&nbsp;</td>
<td>columnNames [Default = all columns]</td>
<td>columnNames [Default = all columns or what showOnlyActiveRacesForCompetitorIds specifies]</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<div>showOnlyActiveRacesForCompetitorIds: specify a competitor ID, and the result will contain
the race column holding that competitor's "active" race at the time requested; see also the time and
timeasmillis parameters. A race is active if it is currently live or is the last race for which the
competitor has a result. The parameter can be specified multiple times, thus providing more than
one competitor ID. In case multiple competitor IDs are given, all race columns that contain an
active race of any of the competitors specified will be added to the result. It is possible that no such
race is found, e.g., because racing has not started yet and the leaderboard is empty. No race column
will be delivered then. In case the columnNames parameter is used, too, the combined set of
race columns from the columnNames parameter and this parameter will be delivered. If
this parameter is used but columnNames is not, only the columns specified by this parameter
will be delivered.</div>
</td>
</tr>
<tr>
<td>&nbsp;</td>