
org.opentripplanner.ext.fares.impl.SFBayFareServiceImpl 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.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Currency;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.opentripplanner.ext.fares.model.FareRuleSet;
import org.opentripplanner.model.plan.Leg;
import org.opentripplanner.model.plan.TransitLeg;
import org.opentripplanner.routing.core.FareType;
import org.opentripplanner.routing.core.ItineraryFares;
import org.opentripplanner.transit.model.basic.TransitMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SFBayFareServiceImpl extends DefaultFareService {
@SuppressWarnings("unused")
private static final Logger LOG = LoggerFactory.getLogger(SFBayFareServiceImpl.class);
public static final int SFMTA_TRANSFER_DURATION = 60 * 90;
public static final int BART_TRANSFER_DURATION = 60 * 60;
public static final float SFMTA_BASE_FARE = 2.00f;
public static final float CABLE_CAR_FARE = 5.00f;
public static final float AIRBART_FARE = 3.00f;
public static final float SFMTA_BART_TRANSFER_FARE = 1.75f;
public static final Set SFMTA_BART_TRANSFER_STOPS = new HashSet<>(
Arrays.asList("EMBR", "MONT", "POWL", "CIVC", "16TH", "24TH", "GLEN", "BALB", "DALY")
);
public static final String SFMTA_BART_FREE_TRANSFER_STOP = "DALY";
public SFBayFareServiceImpl(Collection regularFareRules) {
addFareRules(FareType.regular, regularFareRules);
}
@Override
protected float getLowestCost(
FareType fareType,
List rides,
Collection fareRules
) {
List bartBlock = null;
Long sfmtaTransferIssued = null;
Long alightedBart = null;
String alightedBartStop = null;
float cost = 0f;
String agencyId = null;
for (var ride : rides) {
agencyId = ride.getRoute().getId().getFeedId();
if (agencyId.equals("BART")) {
if (bartBlock == null) {
bartBlock = new ArrayList<>();
}
bartBlock.add(ride);
alightedBart = ride.getEndTime().toEpochSecond();
alightedBartStop = ride.getTo().stop.getId().getId();
} else { // non-BART agency
if (bartBlock != null) {
// finalize outstanding bart block, if any
cost += calculateCost(fareType, bartBlock, fareRules);
bartBlock = null;
}
if (agencyId.equals("SFMTA")) {
TransitMode mode = (ride instanceof TransitLeg transitLeg) ? transitLeg.getMode() : null;
if (mode == TransitMode.CABLE_CAR) {
// no transfers issued or accepted
cost += CABLE_CAR_FARE;
} else if (
sfmtaTransferIssued == null ||
sfmtaTransferIssued + SFMTA_TRANSFER_DURATION < ride.getEndTime().toEpochSecond()
) {
sfmtaTransferIssued = ride.getStartTime().toEpochSecond();
if (
alightedBart != null &&
alightedBart + BART_TRANSFER_DURATION > ride.getEndTime().toEpochSecond() &&
SFMTA_BART_TRANSFER_STOPS.contains(alightedBartStop)
) {
// discount for BART to Muni transfer
if (alightedBartStop.equals(SFMTA_BART_FREE_TRANSFER_STOP)) {
// no cost to ride Muni
} else {
cost += SFMTA_BART_TRANSFER_FARE;
}
} else {
// no transfer, basic fare
cost += SFMTA_BASE_FARE;
}
} else {
// SFMTA-SFMTA non-cable-car transfer within time limit, no cost
}
} else if (agencyId.equals("AirBART")) {
cost += AIRBART_FARE;
}
}
}
if (bartBlock != null) {
// finalize outstanding bart block, if any
cost += calculateCost(fareType, bartBlock, fareRules);
}
return cost;
}
@Override
protected boolean populateFare(
ItineraryFares fare,
Currency currency,
FareType fareType,
List rides,
Collection fareRules
) {
float lowestCost = getLowestCost(fareType, rides, fareRules);
if (lowestCost != Float.POSITIVE_INFINITY) {
fare.addFare(fareType, getMoney(currency, lowestCost));
return true;
}
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy