org.opentripplanner.ext.fares.impl.HighestFareInFreeTransferWindowFareService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of otp Show documentation
Show all versions of otp Show documentation
The OpenTripPlanner multimodal journey planning system
package org.opentripplanner.ext.fares.impl;
import java.time.Duration;
import java.util.Collection;
import java.util.Currency;
import java.util.List;
import org.opentripplanner.ext.fares.model.FareRuleSet;
import org.opentripplanner.model.plan.Leg;
import org.opentripplanner.model.plan.ScheduledTransitLeg;
import org.opentripplanner.routing.core.FareType;
import org.opentripplanner.routing.core.ItineraryFares;
/**
* This calculator is maintained by IBI Group.
*/
public class HighestFareInFreeTransferWindowFareService extends DefaultFareService {
private final boolean analyzeInterlinedTransfers;
private final Duration freeTransferWindow;
public HighestFareInFreeTransferWindowFareService(
Collection regularFareRules,
Duration freeTransferWindow,
boolean analyzeInterlinedTransfers
) {
addFareRules(FareType.regular, regularFareRules);
this.freeTransferWindow = freeTransferWindow;
this.analyzeInterlinedTransfers = analyzeInterlinedTransfers;
}
public boolean analyzeInterlinedTransfers() {
return analyzeInterlinedTransfers;
}
public Duration freeTransferWindow() {
return freeTransferWindow;
}
/**
* The fare calculation is designed to charge the rider incrementally as they use each service.
* The total cost of the itinerary will be equal to the leg of the journey that had the maximum
* fare. Additionally, a free transfer window is taken into account that will apply the current
* highest cost within the free transfer window and then reset to a new window and calculate
* additional free transfers from there.
*/
@Override
protected boolean populateFare(
ItineraryFares fare,
Currency currency,
FareType fareType,
List legs,
Collection fareRules
) {
float cost = 0;
float currentTransferWindowCost = 0;
// The initial value of -1 indicates that the free transfer window end time has not yet been set
long freeTransferWindowEndTimeEpochSeconds = -1;
for (var leg : legs) {
float rideCost = calculateCost(fareType, List.of(leg), fareRules);
if (leg.getStartTime().toEpochSecond() > freeTransferWindowEndTimeEpochSeconds) {
// free transfer window has expired or has not yet been initialized. Reset some items and add to the
// overall cost. This is fine to do if the free transfer window hasn't been initialized since the
// overall cost will be 0.
cost += currentTransferWindowCost;
// reset current window cost
currentTransferWindowCost = 0;
// reset transfer window end time to trigger recalculation in next block
freeTransferWindowEndTimeEpochSeconds = -1;
}
// recalculate free transfer window if needed
if (freeTransferWindowEndTimeEpochSeconds == -1) {
// the new transfer window end time should be calculated by adding the ride's start time (which is in
// seconds past the epoch) and the number of equivalent seconds in the free transfer window minutes.
freeTransferWindowEndTimeEpochSeconds =
leg.getStartTime().plus(freeTransferWindow).toEpochSecond();
}
currentTransferWindowCost = Float.max(currentTransferWindowCost, rideCost);
}
cost += currentTransferWindowCost;
if (cost < Float.POSITIVE_INFINITY) fare.addFare(fareType, getMoney(currency, cost));
return cost > 0 && cost < Float.POSITIVE_INFINITY;
}
@Override
protected boolean shouldCombineInterlinedLegs(
ScheduledTransitLeg current,
ScheduledTransitLeg previous
) {
return !analyzeInterlinedTransfers;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy