diff --git a/docs/sandbox/ReportApi.md b/docs/sandbox/ReportApi.md
index fdb6c2d3146..1a0668d1740 100644
--- a/docs/sandbox/ReportApi.md
+++ b/docs/sandbox/ReportApi.md
@@ -32,6 +32,8 @@ This module mounts an endpoint for generating reports under `otp/report`. Availa
- [German version](http://localhost:8080/otp/report/bicycle-safety.csv?osmWayPropertySet=germany)
- [UK version](http://localhost:8080/otp/report/bicycle-safety.csv?osmWayPropertySet=uk)
- [Finnish version](http://localhost:8080/otp/report/bicycle-safety.csv?osmWayPropertySet=finland)
+- [/otp/report/transit/group/priorities](http://localhost:8080/otp/report/transit/group/priorities):
+ List all transit groups used for transit-group-priority (Competition neutral planning).
### Configuration
diff --git a/src/ext/java/org/opentripplanner/ext/reportapi/model/TransitGroupPriorityReport.java b/src/ext/java/org/opentripplanner/ext/reportapi/model/TransitGroupPriorityReport.java
new file mode 100644
index 00000000000..635469cb3a2
--- /dev/null
+++ b/src/ext/java/org/opentripplanner/ext/reportapi/model/TransitGroupPriorityReport.java
@@ -0,0 +1,86 @@
+package org.opentripplanner.ext.reportapi.model;
+
+import java.util.Collection;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
+import org.opentripplanner.routing.algorithm.raptoradapter.transit.request.PriorityGroupConfigurator;
+import org.opentripplanner.routing.api.request.request.TransitRequest;
+import org.opentripplanner.transit.model.network.TripPattern;
+
+/**
+ * This class is used to report all transit-groups used for transit-group-priority. The report is
+ * useful when configuring/debugging this functionality.
+ *
+ * The format is pure text.
+ */
+public class TransitGroupPriorityReport {
+
+ public static String build(Collection patterns, TransitRequest request) {
+ var c = PriorityGroupConfigurator.of(
+ request.priorityGroupsByAgency(),
+ request.priorityGroupsGlobal()
+ );
+
+ var map = new TreeMap();
+ for (var it : patterns) {
+ int groupId = c.lookupTransitGroupPriorityId(it);
+ var de = map.computeIfAbsent(groupId, DebugEntity::new);
+ de.add(
+ it.getRoute().getAgency().getId().toString(),
+ it.getMode().name(),
+ it.getNetexSubmode().name()
+ );
+ }
+ return (
+ "TRANSIT GROUPS PRIORITY" +
+ map.values().stream().map(DebugEntity::toString).sorted().collect(Collectors.joining(""))
+ );
+ }
+
+ private static class DebugEntity {
+
+ private final int groupId;
+ private final TreeMap agencies = new TreeMap<>();
+
+ public DebugEntity(int groupId) {
+ this.groupId = groupId;
+ }
+
+ void add(String agency, String mode, String submode) {
+ agencies.computeIfAbsent(agency, AgencyEntry::new).add(mode, submode);
+ }
+
+ @Override
+ public String toString() {
+ var buf = new StringBuilder("\n %#010x".formatted(groupId));
+ for (var it : agencies.values()) {
+ buf.append("\n ").append(it.toString());
+ }
+ return buf.toString();
+ }
+ }
+
+ private record AgencyEntry(String agency, TreeMap> modes) {
+ private AgencyEntry(String agency) {
+ this(agency, new TreeMap<>());
+ }
+
+ void add(String mode, String submode) {
+ modes.computeIfAbsent(mode, m -> new TreeSet<>()).add(submode);
+ }
+
+ @Override
+ public String toString() {
+ var buf = new StringBuilder();
+ for (var it : modes.entrySet()) {
+ buf.append(", ");
+ buf.append(it.getKey());
+ if (!it.getValue().isEmpty()) {
+ buf.append(" (").append(String.join(", ", it.getValue())).append(")");
+ }
+ }
+ return agency + " ~ " + buf.substring(2);
+ }
+ }
+}
diff --git a/src/ext/java/org/opentripplanner/ext/reportapi/resource/ReportResource.java b/src/ext/java/org/opentripplanner/ext/reportapi/resource/ReportResource.java
index 6ccb728800e..a859b4ff78a 100644
--- a/src/ext/java/org/opentripplanner/ext/reportapi/resource/ReportResource.java
+++ b/src/ext/java/org/opentripplanner/ext/reportapi/resource/ReportResource.java
@@ -17,8 +17,10 @@
import org.opentripplanner.ext.reportapi.model.GraphReportBuilder;
import org.opentripplanner.ext.reportapi.model.GraphReportBuilder.GraphStats;
import org.opentripplanner.ext.reportapi.model.TransfersReport;
+import org.opentripplanner.ext.reportapi.model.TransitGroupPriorityReport;
import org.opentripplanner.model.transfer.TransferService;
import org.opentripplanner.openstreetmap.tagmapping.OsmTagMapperSource;
+import org.opentripplanner.routing.api.request.RouteRequest;
import org.opentripplanner.standalone.api.OtpServerRequestContext;
import org.opentripplanner.transit.service.TransitService;
@@ -33,11 +35,13 @@ public class ReportResource {
private final TransferService transferService;
private final TransitService transitService;
+ private final RouteRequest defaultRequest;
@SuppressWarnings("unused")
public ReportResource(@Context OtpServerRequestContext requestContext) {
this.transferService = requestContext.transitService().getTransferService();
this.transitService = requestContext.transitService();
+ this.defaultRequest = requestContext.defaultRouteRequest();
}
@GET
@@ -80,6 +84,16 @@ public Response getBicycleSafetyAsCsv(
.build();
}
+ @GET
+ @Path("/transit/group/priorities")
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getTransitGroupPriorities() {
+ return TransitGroupPriorityReport.build(
+ transitService.getAllTripPatterns(),
+ defaultRequest.journey().transit()
+ );
+ }
+
@GET
@Path("/graph.json")
public Response stats(@Context OtpServerRequestContext serverRequestContext) {
diff --git a/src/main/java/org/opentripplanner/framework/logging/Throttle.java b/src/main/java/org/opentripplanner/framework/logging/Throttle.java
index 631d59a2697..ed8a2c1bef4 100644
--- a/src/main/java/org/opentripplanner/framework/logging/Throttle.java
+++ b/src/main/java/org/opentripplanner/framework/logging/Throttle.java
@@ -1,5 +1,6 @@
package org.opentripplanner.framework.logging;
+import java.time.Duration;
import org.opentripplanner.framework.time.TimeUtils;
/**
@@ -26,17 +27,20 @@ public class Throttle {
private long timeout = Long.MIN_VALUE;
private final String setupInfo;
- Throttle(int quietPeriodMilliseconds) {
- this.quietPeriodMilliseconds = quietPeriodMilliseconds;
+ /**
+ * Package local to be able to unit test.
+ */
+ Throttle(Duration quietPeriod) {
+ this.quietPeriodMilliseconds = (int) quietPeriod.toMillis();
this.setupInfo = "(throttle " + TimeUtils.msToString(quietPeriodMilliseconds) + " interval)";
}
public static Throttle ofOneSecond() {
- return new Throttle(1000);
+ return new Throttle(Duration.ofSeconds(1));
}
public static Throttle ofOneMinute() {
- return new Throttle(1000 * 60);
+ return new Throttle(Duration.ofMinutes(1));
}
public String setupInfo() {
diff --git a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupConfigurator.java b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupConfigurator.java
index 826b9c09a13..6ef82786b99 100644
--- a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupConfigurator.java
+++ b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupConfigurator.java
@@ -11,7 +11,7 @@
import org.opentripplanner.routing.algorithm.raptoradapter.transit.cost.grouppriority.TransitGroupPriority32n;
import org.opentripplanner.routing.api.request.request.filter.TransitGroupSelect;
import org.opentripplanner.transit.model.framework.FeedScopedId;
-import org.opentripplanner.transit.model.network.RoutingTripPattern;
+import org.opentripplanner.transit.model.network.TripPattern;
/**
* This class dynamically builds an index of transit-group-ids from the
@@ -94,16 +94,14 @@ public static PriorityGroupConfigurator of(
*
* @throws IllegalArgumentException if more than 32 group-ids are requested.
*/
- public int lookupTransitGroupPriorityId(RoutingTripPattern tripPattern) {
+ public int lookupTransitGroupPriorityId(TripPattern tripPattern) {
if (!enabled || tripPattern == null) {
return baseGroupId;
}
- var p = tripPattern.getPattern();
-
for (var it : agencyMatchersIds) {
- if (it.matcher().match(p)) {
- var agencyId = p.getRoute().getAgency().getId();
+ if (it.matcher().match(tripPattern)) {
+ var agencyId = tripPattern.getRoute().getAgency().getId();
int groupId = it.ids().get(agencyId);
if (groupId < 0) {
@@ -115,7 +113,7 @@ public int lookupTransitGroupPriorityId(RoutingTripPattern tripPattern) {
}
for (var it : globalMatchersIds) {
- if (it.matcher.match(p)) {
+ if (it.matcher.match(tripPattern)) {
return it.groupId();
}
}
diff --git a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/RaptorRoutingRequestTransitDataCreator.java b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/RaptorRoutingRequestTransitDataCreator.java
index b8f915d6eb4..863a4ca9ae8 100644
--- a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/RaptorRoutingRequestTransitDataCreator.java
+++ b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/RaptorRoutingRequestTransitDataCreator.java
@@ -147,7 +147,7 @@ static List merge(
tripPattern.getAlightingPossible(),
BoardAlight.ALIGHT
),
- priorityGroupConfigurator.lookupTransitGroupPriorityId(tripPattern)
+ priorityGroupConfigurator.lookupTransitGroupPriorityId(tripPattern.getPattern())
)
);
}
diff --git a/src/test/java/org/opentripplanner/framework/logging/ThrottleTest.java b/src/test/java/org/opentripplanner/framework/logging/ThrottleTest.java
index 91f1667486d..c9155992daa 100644
--- a/src/test/java/org/opentripplanner/framework/logging/ThrottleTest.java
+++ b/src/test/java/org/opentripplanner/framework/logging/ThrottleTest.java
@@ -1,5 +1,6 @@
package org.opentripplanner.framework.logging;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -36,8 +37,8 @@ void smokeTest() {
@Test
@Disabled("Run this test manually")
void manualTest() {
- double quietPeriodMs = 50.0;
- var subject = new Throttle((int) quietPeriodMs);
+ var quietPeriod = Duration.ofMillis(50);
+ var subject = new Throttle(quietPeriod);
List events = createIntegerSequence(20_000_000);
long start = System.currentTimeMillis();
diff --git a/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupConfiguratorTest.java b/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupConfiguratorTest.java
index cc4bb09f01e..7f974927c1b 100644
--- a/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupConfiguratorTest.java
+++ b/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupConfiguratorTest.java
@@ -9,7 +9,7 @@
import org.junit.jupiter.api.Test;
import org.opentripplanner.routing.api.request.request.filter.TransitGroupSelect;
import org.opentripplanner.transit.model.basic.TransitMode;
-import org.opentripplanner.transit.model.network.RoutingTripPattern;
+import org.opentripplanner.transit.model.network.TripPattern;
import org.opentripplanner.transit.model.site.RegularStop;
class PriorityGroupConfiguratorTest {
@@ -60,11 +60,11 @@ class PriorityGroupConfiguratorTest {
"10:00 10:10"
);
- private final RoutingTripPattern railR1 = routeR1.getTripPattern().getRoutingTripPattern();
- private final RoutingTripPattern busB2 = routeB2.getTripPattern().getRoutingTripPattern();
- private final RoutingTripPattern railR3 = routeR3.getTripPattern().getRoutingTripPattern();
- private final RoutingTripPattern ferryF3 = routeF3.getTripPattern().getRoutingTripPattern();
- private final RoutingTripPattern busB3 = routeB3.getTripPattern().getRoutingTripPattern();
+ private final TripPattern railR1 = routeR1.getTripPattern();
+ private final TripPattern busB2 = routeB2.getTripPattern();
+ private final TripPattern railR3 = routeR3.getTripPattern();
+ private final TripPattern ferryF3 = routeF3.getTripPattern();
+ private final TripPattern busB3 = routeB3.getTripPattern();
@Test
void emptyConfigurationShouldReturnGroupZero() {