From ba16135dee31b74d722419cb483b0a449235b030 Mon Sep 17 00:00:00 2001 From: Thomas Gran Date: Sun, 14 Jan 2024 12:41:02 +0100 Subject: [PATCH 1/4] refactor: Code cleanup Throttle --- .../opentripplanner/framework/logging/Throttle.java | 12 ++++++++---- .../framework/logging/ThrottleTest.java | 5 +++-- 2 files changed, 11 insertions(+), 6 deletions(-) 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/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(); From 1a0e3739b7c61d060348de3186bb329087ee1e6f Mon Sep 17 00:00:00 2001 From: Thomas Gran Date: Wed, 17 Jan 2024 16:58:02 +0100 Subject: [PATCH 2/4] refactor: Reduce dependency scope for PriorityGroupConfigurator This will make it simpler to build a report later --- .../transit/request/PriorityGroupConfigurator.java | 12 +++++------- .../RaptorRoutingRequestTransitDataCreator.java | 2 +- .../request/PriorityGroupConfiguratorTest.java | 12 ++++++------ 3 files changed, 12 insertions(+), 14 deletions(-) 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/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() { From 390fe32ec826a99bc41e0cd7f96eabd84857e14a Mon Sep 17 00:00:00 2001 From: Thomas Gran Date: Wed, 17 Jan 2024 16:59:25 +0100 Subject: [PATCH 3/4] feature: Add a report for transit groups to the report API --- .../model/TransitGroupPriorityReport.java | 86 +++++++++++++++++++ .../reportapi/resource/ReportResource.java | 14 +++ 2 files changed, 100 insertions(+) create mode 100644 src/ext/java/org/opentripplanner/ext/reportapi/model/TransitGroupPriorityReport.java 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) { From 90eb73cea489823295bcce368a7a3a2778217ba1 Mon Sep 17 00:00:00 2001 From: Thomas Gran Date: Wed, 17 Jan 2024 17:08:48 +0100 Subject: [PATCH 4/4] doc: Add sandbox report doc. --- docs/sandbox/ReportApi.md | 2 ++ 1 file changed, 2 insertions(+) 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