-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Title: [Fares V2] Support for filtering fare leg rules by number of stops (hop count)
Introduction / Context
We are currently evaluating OTP for our use case and have identified a functional gap in the Fares V2 area. We are looking for feedback: Does this feature fit into the roadmap? How should the configuration (GTFS Extension vs. standard field) ideally be handled?
Is your feature request related to a problem? Please describe.
Yes. Many public transport agencies (particularly in the DACH region) offer "short-haul" tickets (e.g., "Kurzstrecke"). These tickets are often defined by the number of stops/stations traveled (e.g., "valid for up to 3 stops on the tram" or "up to 5 stops on the bus"), rather than by geographic distance.
Currently, OTP's implementation of GTFS Fares V2 allows filtering fare_leg_rules.txt by max_distance, but there is no native support for filtering by the number of stops (hop count). Using max_distance as a proxy for stop count is inaccurate because the distance between stations varies significantly. This leads to edge cases where short-haul tickets are either wrongly denied (long distance between few stops) or wrongly granted (short distance between many stops).
Goal / high level use-case
The goal is to allow OTP to accurately match fare products based on the specific number of stops traveled in a leg.
Use Case:
A user searches for a connection involving a short tram ride (e.g., 3 stations). The system should check the number of stops for this leg and, if it falls within the configured limit (e.g., max_stops=3), apply the cheaper "Short Haul" fare product defined in fare_leg_rules.txt.
Describe the solution you'd like
We would like to extend the Fares V2 matching logic in OTP to support filtering by stop count.
- Extend the internal
FareLegRulemodel to include a stop count limit (e.g., mapped from a GTFS extension field likex_max_stopsinfare_leg_rules.txtor a similar mechanism). - Update the
FareLegRuleMatcherto count the stops of the leg being evaluated and compare them against this limit.
Describe alternatives you've considered
We have considered the following alternatives, but they are not ideal:
- Filtering in Middleware: Calculating fares in OTP based on zones and then filtering out invalid short-haul tickets in a middleware layer by counting stops there. This splits the business logic and increases complexity.
- Filtering in Frontend: Sending all possible tickets to the client and letting the frontend filter based on stop count. This is insecure and exposes incorrect data in the API response.
- Using
max_distance: As described above, distance is an unreliable proxy for stop count in our network topology.
Additional context
We are currently evaluating OTP for our use case. We would appreciate guidance from the maintainers on the preferred implementation approach and how this aligns with the Fares V2 roadmap.