Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/dev-2.x' into swap-debug-clients
Browse files Browse the repository at this point in the history
  • Loading branch information
leonardehrenfried committed Jun 25, 2024
2 parents a5b829f + 827684a commit cc46619
Show file tree
Hide file tree
Showing 18 changed files with 428 additions and 248 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/cibuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,13 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20

- name: Build GTFS GraphQL API documentation
run: |
npm install -g @magidoc/[email protected]
magidoc generate
npm install -g @magidoc/[email protected]
cat src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls
magidoc generate --stacktrace
- name: Deploy compiled HTML to Github pages
if: github.event_name == 'push' && (github.ref == 'refs/heads/dev-2.x' || github.ref == 'refs/heads/master')
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/performance-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ jobs:

- name: Archive Flight Recorder instrumentation file
if: matrix.profile == 'core' || github.ref == 'refs/heads/dev-2.x'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.location }}-flight-recorder
path: ${{ matrix.location}}-speed-test.jfr
1 change: 1 addition & 0 deletions docs/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ based on merged pull requests. Search GitHub issues and pull requests for smalle
- Fix debug client after breaking change in dependency graphql-request [#5899](https://github.com/opentripplanner/OpenTripPlanner/pull/5899)
- Remove TravelTime API [#5890](https://github.com/opentripplanner/OpenTripPlanner/pull/5890)
- Improve cancellation of large response in TransModel API [#5908](https://github.com/opentripplanner/OpenTripPlanner/pull/5908)
- Refactor SIRI-ET updaters [#5904](https://github.com/opentripplanner/OpenTripPlanner/pull/5904)
[](AUTOMATIC_CHANGELOG_PLACEHOLDER_DO_NOT_REMOVE)

## 2.5.0 (2024-03-13)
Expand Down
10 changes: 9 additions & 1 deletion magidoc.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,15 @@ To learn how to deactivate it, read the
queryGenerationFactories: {
'Polyline': '<>',
'GeoJson': '<>',
'OffsetDateTime': '2024-02-05T18:04:23+01:00'
'OffsetDateTime': '2024-02-05T18:04:23+01:00',
'Duration': 'PT10M',
'CoordinateValue': 19.24,
'Reluctance': 3.1,
'Speed': 3.4,
'Cost': 100,
'Ratio': 0.25,
'Locale': 'en'

},
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ private static void assertLegFareEquals(
void calculateFareForSingleAgency() {
List<Leg> rides = List.of(getLeg(COMM_TRANS_AGENCY_ID, "400", 0));
calculateFare(rides, regular, DEFAULT_TEST_RIDE_PRICE);
calculateFare(rides, FareType.senior, DEFAULT_TEST_RIDE_PRICE);
calculateFare(rides, FareType.senior, TWO_DOLLARS);
calculateFare(rides, FareType.youth, ZERO_USD);
calculateFare(rides, FareType.electronicSpecial, TWO_DOLLARS);
calculateFare(rides, FareType.electronicRegular, DEFAULT_TEST_RIDE_PRICE);
Expand All @@ -154,18 +154,14 @@ void calculateFareWithNoFreeTransfer() {
getLeg(COMM_TRANS_AGENCY_ID, 2)
);
calculateFare(rides, regular, DEFAULT_TEST_RIDE_PRICE.times(3));
calculateFare(rides, FareType.senior, DEFAULT_TEST_RIDE_PRICE.times(3));
calculateFare(rides, FareType.senior, DEFAULT_TEST_RIDE_PRICE.plus(usDollars(2.25f)));
calculateFare(rides, FareType.youth, Money.ZERO_USD);
calculateFare(
rides,
FareType.electronicSpecial,
DEFAULT_TEST_RIDE_PRICE.plus(usDollars(1.25f))
);
calculateFare(
rides,
FareType.electronicRegular,
DEFAULT_TEST_RIDE_PRICE.plus(DEFAULT_TEST_RIDE_PRICE)
);
calculateFare(rides, FareType.electronicRegular, DEFAULT_TEST_RIDE_PRICE.times(2));
calculateFare(rides, FareType.electronicSenior, DEFAULT_TEST_RIDE_PRICE.plus(usDollars(1.25f)));
calculateFare(rides, FareType.electronicYouth, Money.ZERO_USD);
}
Expand Down Expand Up @@ -200,7 +196,7 @@ void calculateFareThatExceedsTwoHourFreeTransferWindow() {
);

calculateFare(rides, regular, DEFAULT_TEST_RIDE_PRICE.times(2));
calculateFare(rides, FareType.senior, DEFAULT_TEST_RIDE_PRICE.times(2));
calculateFare(rides, FareType.senior, TWO_DOLLARS);
calculateFare(rides, FareType.youth, ZERO_USD);
calculateFare(rides, FareType.electronicSpecial, TWO_DOLLARS);
calculateFare(rides, FareType.electronicRegular, DEFAULT_TEST_RIDE_PRICE.times(2));
Expand All @@ -227,7 +223,7 @@ void calculateFareThatIncludesNoFreeTransfers() {
calculateFare(
rides,
FareType.senior,
DEFAULT_TEST_RIDE_PRICE.times(2).plus(usDollars(.50f)).plus(HALF_FERRY_FARE)
ONE_DOLLAR.plus(ONE_DOLLAR).plus(HALF_FERRY_FARE).plus(usDollars(0.5f))
);
calculateFare(rides, FareType.youth, Money.ZERO_USD);
// We don't get any fares for the skagit transit leg below here because they don't accept ORCA (electronic)
Expand Down Expand Up @@ -263,7 +259,7 @@ void calculateFareThatExceedsTwoHourFreeTransferWindowTwice() {
getLeg(KITSAP_TRANSIT_AGENCY_ID, 270)
);
calculateFare(rides, regular, DEFAULT_TEST_RIDE_PRICE.times(3));
calculateFare(rides, FareType.senior, DEFAULT_TEST_RIDE_PRICE.times(3));
calculateFare(rides, FareType.senior, usDollars(3));
calculateFare(rides, FareType.youth, Money.ZERO_USD);
calculateFare(rides, FareType.electronicSpecial, usDollars(3));
calculateFare(rides, FareType.electronicRegular, DEFAULT_TEST_RIDE_PRICE.times(3));
Expand All @@ -286,7 +282,7 @@ void calculateFareThatStartsWithACashFare() {
getLeg(KITSAP_TRANSIT_AGENCY_ID, 149)
);
calculateFare(rides, regular, DEFAULT_TEST_RIDE_PRICE.times(2));
calculateFare(rides, FareType.senior, DEFAULT_TEST_RIDE_PRICE.times(2));
calculateFare(rides, FareType.senior, DEFAULT_TEST_RIDE_PRICE.plus(ONE_DOLLAR));
calculateFare(rides, FareType.youth, Money.ZERO_USD);
calculateFare(rides, FareType.electronicSpecial, DEFAULT_TEST_RIDE_PRICE.plus(ONE_DOLLAR));
calculateFare(
Expand All @@ -305,7 +301,7 @@ void calculateFareThatStartsWithACashFare() {
void calculateFareForKitsapFastFerry() {
List<Leg> rides = List.of(getLeg(KITSAP_TRANSIT_AGENCY_ID, 0, 4, "404", "east"));
calculateFare(rides, regular, TWO_DOLLARS);
calculateFare(rides, FareType.senior, TWO_DOLLARS);
calculateFare(rides, FareType.senior, ONE_DOLLAR);
calculateFare(rides, FareType.youth, Money.ZERO_USD);
calculateFare(rides, FareType.electronicSpecial, ONE_DOLLAR);
calculateFare(rides, FareType.electronicRegular, TWO_DOLLARS);
Expand All @@ -314,7 +310,7 @@ void calculateFareForKitsapFastFerry() {

rides = List.of(getLeg(KITSAP_TRANSIT_AGENCY_ID, 0, 4, "404", "west"));
calculateFare(rides, regular, usDollars(10f));
calculateFare(rides, FareType.senior, usDollars(10f));
calculateFare(rides, FareType.senior, usDollars(5f));
calculateFare(rides, FareType.youth, Money.ZERO_USD);
calculateFare(rides, FareType.electronicSpecial, usDollars(5f));
calculateFare(rides, FareType.electronicRegular, usDollars(10f));
Expand Down Expand Up @@ -349,7 +345,7 @@ void calculateFareForSTRail() {
getLeg(SOUND_TRANSIT_AGENCY_ID, "S Line", 100, "King Street Station", "Auburn Station")
);
calculateFare(rides, regular, DEFAULT_TEST_RIDE_PRICE.times(2));
calculateFare(rides, FareType.senior, DEFAULT_TEST_RIDE_PRICE.times(2));
calculateFare(rides, FareType.senior, TWO_DOLLARS);
calculateFare(rides, FareType.youth, Money.ZERO_USD);
calculateFare(rides, FareType.electronicSpecial, ORCA_SPECIAL_FARE);
calculateFare(rides, FareType.electronicRegular, DEFAULT_TEST_RIDE_PRICE);
Expand All @@ -364,7 +360,7 @@ void calculateFareForSTRail() {
void calculateWaterTaxiFares() {
List<Leg> rides = List.of(getLeg(KC_METRO_AGENCY_ID, "973", 1));
calculateFare(rides, regular, WEST_SEATTLE_WATER_TAXI_CASH_FARE);
calculateFare(rides, FareType.senior, WEST_SEATTLE_WATER_TAXI_CASH_FARE);
calculateFare(rides, FareType.senior, usDollars(2.50f));
calculateFare(rides, FareType.youth, Money.ZERO_USD);
calculateFare(rides, FareType.electronicSpecial, usDollars(3.75f));
calculateFare(rides, FareType.electronicRegular, usDollars(5f));
Expand All @@ -374,7 +370,7 @@ void calculateWaterTaxiFares() {
rides = List.of(getLeg(KC_METRO_AGENCY_ID, "975", 1));

calculateFare(rides, regular, VASHON_WATER_TAXI_CASH_FARE);
calculateFare(rides, FareType.senior, VASHON_WATER_TAXI_CASH_FARE);
calculateFare(rides, FareType.senior, usDollars(3f));
calculateFare(rides, FareType.youth, Money.ZERO_USD);
calculateFare(rides, FareType.electronicSpecial, usDollars(4.50f));
calculateFare(rides, FareType.electronicRegular, usDollars(5.75f));
Expand All @@ -395,8 +391,7 @@ void calculateSoundTransitBusFares() {
getLeg(KC_METRO_AGENCY_ID, "550", 240)
);
calculateFare(rides, regular, usDollars(9.75f));
// Sound Transit does not accept senior fares in cash
calculateFare(rides, FareType.senior, usDollars(9.75f));
calculateFare(rides, FareType.senior, usDollars(3.00f));
calculateFare(rides, FareType.youth, Money.ZERO_USD);
calculateFare(rides, FareType.electronicSpecial, usDollars(3f));
calculateFare(rides, FareType.electronicRegular, usDollars(9.75f));
Expand All @@ -410,7 +405,7 @@ void calculateSoundTransitBusFares() {
getLeg(PIERCE_COUNTY_TRANSIT_AGENCY_ID, "501", 60)
);
calculateFare(rides, regular, DEFAULT_TEST_RIDE_PRICE.times(2));
calculateFare(rides, FareType.senior, DEFAULT_TEST_RIDE_PRICE.times(2));
calculateFare(rides, FareType.senior, TWO_DOLLARS);
calculateFare(rides, FareType.youth, Money.ZERO_USD);
calculateFare(rides, FareType.electronicSpecial, usDollars(1f));
calculateFare(rides, FareType.electronicRegular, DEFAULT_TEST_RIDE_PRICE);
Expand All @@ -430,7 +425,7 @@ void calculateCashFreeTransferKCMetroAndKitsap() {
getLeg(KITSAP_TRANSIT_AGENCY_ID, 132)
);
calculateFare(rides, regular, DEFAULT_TEST_RIDE_PRICE.times(4));
calculateFare(rides, FareType.senior, DEFAULT_TEST_RIDE_PRICE.times(4));
calculateFare(rides, FareType.senior, usDollars(4.25f));
calculateFare(rides, FareType.youth, Money.ZERO_USD);
calculateFare(rides, FareType.electronicSpecial, usDollars(1.25f));
calculateFare(rides, FareType.electronicRegular, DEFAULT_TEST_RIDE_PRICE.times(2));
Expand All @@ -442,12 +437,12 @@ void calculateCashFreeTransferKCMetroAndKitsap() {
void calculateTransferExtension() {
List<Leg> rides = List.of(
getLeg(KITSAP_TRANSIT_AGENCY_ID, 0, 4, "Kitsap Fast Ferry", "east"), // 2.00
getLeg(KC_METRO_AGENCY_ID, 100), // Default ride price, extends transfer
getLeg(KC_METRO_AGENCY_ID, 100), // Default ride price, extends transfer for regular fare
getLeg(KITSAP_TRANSIT_AGENCY_ID, 150, 4, "Kitsap Fast Ferry", "west") // 10.00
);
var regularFare = usDollars(2.00f).plus(DEFAULT_TEST_RIDE_PRICE).plus(usDollars(10f));
calculateFare(rides, regular, regularFare);
calculateFare(rides, FareType.senior, regularFare);
calculateFare(rides, FareType.senior, usDollars(7f));
calculateFare(rides, FareType.youth, Money.ZERO_USD);
calculateFare(rides, FareType.electronicSpecial, usDollars(6f));
calculateFare(rides, FareType.electronicRegular, usDollars(10f)); // transfer extended on second leg
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,10 +352,10 @@ private Optional<Money> getSeniorFare(
var regularFare = getRegularFare(fareType, rideType, defaultFare, leg);
// Many agencies only provide senior discount if using ORCA
return switch (rideType) {
case COMM_TRANS_LOCAL_SWIFT -> usesOrca(fareType) ? optionalUSD(1.25f) : regularFare;
case COMM_TRANS_COMMUTER_EXPRESS -> usesOrca(fareType) ? optionalUSD(2f) : regularFare;
case COMM_TRANS_LOCAL_SWIFT -> optionalUSD(1.25f);
case COMM_TRANS_COMMUTER_EXPRESS -> optionalUSD(2f);
case SKAGIT_TRANSIT, WHATCOM_LOCAL, SKAGIT_LOCAL -> optionalUSD(0.5f);
case EVERETT_TRANSIT -> usesOrca(fareType) ? optionalUSD(0.5f) : regularFare;
case EVERETT_TRANSIT -> optionalUSD(0.5f);
case KITSAP_TRANSIT_FAST_FERRY_EASTBOUND,
SOUND_TRANSIT,
SOUND_TRANSIT_BUS,
Expand All @@ -365,14 +365,10 @@ private Optional<Money> getSeniorFare(
KC_METRO,
PIERCE_COUNTY_TRANSIT,
SEATTLE_STREET_CAR,
KITSAP_TRANSIT -> fareType.equals(FareType.electronicSenior)
? optionalUSD(1f)
: regularFare;
case KC_WATER_TAXI_VASHON_ISLAND -> usesOrca(fareType) ? optionalUSD(3f) : regularFare;
case KC_WATER_TAXI_WEST_SEATTLE -> usesOrca(fareType) ? optionalUSD(2.5f) : regularFare;
case KITSAP_TRANSIT_FAST_FERRY_WESTBOUND -> fareType.equals(FareType.electronicSenior)
? optionalUSD(5f)
: regularFare;
KITSAP_TRANSIT -> optionalUSD(1f);
case KC_WATER_TAXI_VASHON_ISLAND -> optionalUSD(3f);
case KC_WATER_TAXI_WEST_SEATTLE -> optionalUSD(2.5f);
case KITSAP_TRANSIT_FAST_FERRY_WESTBOUND -> optionalUSD(5f);
// Discount specific to Skagit transit and not Orca.
case WASHINGTON_STATE_FERRIES -> Optional.of(
getWashingtonStateFerriesFare(route.getLongName(), fareType, defaultFare)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.opentripplanner.ext.siri.updater;

import java.util.concurrent.Future;
import java.util.function.Consumer;
import org.opentripplanner.updater.spi.UpdateResult;
import org.opentripplanner.updater.spi.WriteToGraphCallback;
import org.opentripplanner.updater.trip.UpdateIncrementality;
import uk.org.siri.siri20.ServiceDelivery;

/**
* Apply asynchronously estimated timetable updates in the graph-writer thread and forward the
* result to an update result consumer.
*/
public class AsyncEstimatedTimetableProcessor {

private final EstimatedTimetableHandler estimatedTimetableHandler;
private final WriteToGraphCallback saveResultOnGraph;
private final Consumer<UpdateResult> updateResultConsumer;

public AsyncEstimatedTimetableProcessor(
EstimatedTimetableHandler estimatedTimetableHandler,
WriteToGraphCallback saveResultOnGraph,
Consumer<UpdateResult> updateResultConsumer
) {
this.estimatedTimetableHandler = estimatedTimetableHandler;
this.saveResultOnGraph = saveResultOnGraph;
this.updateResultConsumer = updateResultConsumer;
}

/**
* Apply the estimated timetables to the transit model.
* This method is non-blocking and applies the changes asynchronously.
* @return a future indicating when the changes are applied.
*/
public Future<?> processSiriData(ServiceDelivery serviceDelivery) {
return saveResultOnGraph.execute((graph, transitModel) ->
updateResultConsumer.accept(
estimatedTimetableHandler.applyUpdate(
serviceDelivery.getEstimatedTimetableDeliveries(),
UpdateIncrementality.DIFFERENTIAL
)
)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.opentripplanner.ext.siri.updater;

import java.util.concurrent.Future;
import java.util.function.Function;
import uk.org.siri.siri20.ServiceDelivery;

/**
* A source of estimated timetables produced by an asynchronous (push) SIRI-ET feed.
*/
public interface AsyncEstimatedTimetableSource {
/**
* Start reading from the SIRI-ET feed and forward the estimated timetables to a consumer for
* further processing.
* <br>Starting the source includes all the necessary steps to set up the network
* communication with the SIRI-ET feed as well as the (optional) processing of the message
* backlog, that is the recent history of SIRI-ET messages produced by this feed and made
* available by a message cache.
*
* @param serviceDeliveryConsumer apply asynchronously the updates to the transit model. Return a
* future indicating when the updates are applied.
*/
void start(Function<ServiceDelivery, Future<?>> serviceDeliveryConsumer);

/**
* Return true if the message backlog is processed and the source is ready to listen to the feed.
*/
boolean isPrimed();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package org.opentripplanner.ext.siri.updater;

import java.util.List;
import org.opentripplanner.ext.siri.EntityResolver;
import org.opentripplanner.ext.siri.SiriFuzzyTripMatcher;
import org.opentripplanner.ext.siri.SiriTimetableSnapshotSource;
import org.opentripplanner.transit.service.TransitService;
import org.opentripplanner.updater.spi.UpdateResult;
import org.opentripplanner.updater.trip.UpdateIncrementality;
import uk.org.siri.siri20.EstimatedTimetableDeliveryStructure;

/**
* A consumer of estimated timetables that applies the real-time updates to the transit model.
*/
public class EstimatedTimetableHandler {

private final SiriTimetableSnapshotSource snapshotSource;
private final SiriFuzzyTripMatcher fuzzyTripMatcher;
private final EntityResolver entityResolver;
/**
* The ID for the static feed to which these real time updates are applied
*/
private final String feedId;

public EstimatedTimetableHandler(
SiriTimetableSnapshotSource snapshotSource,
boolean fuzzyMatching,
TransitService transitService,
String feedId
) {
this(
snapshotSource,
fuzzyMatching ? SiriFuzzyTripMatcher.of(transitService) : null,
transitService,
feedId
);
}

/**
* Constructor for tests only.
*/
public EstimatedTimetableHandler(
SiriTimetableSnapshotSource snapshotSource,
SiriFuzzyTripMatcher siriFuzzyTripMatcher,
TransitService transitService,
String feedId
) {
this.snapshotSource = snapshotSource;
this.fuzzyTripMatcher = siriFuzzyTripMatcher;
this.entityResolver = new EntityResolver(transitService, feedId);
this.feedId = feedId;
}

/**
* Apply the update to the transit model.
*/
public UpdateResult applyUpdate(
List<EstimatedTimetableDeliveryStructure> estimatedTimetableDeliveries,
UpdateIncrementality updateMode
) {
return snapshotSource.applyEstimatedTimetable(
fuzzyTripMatcher,
entityResolver,
feedId,
updateMode,
estimatedTimetableDeliveries
);
}
}
Loading

0 comments on commit cc46619

Please sign in to comment.