use of org.opentripplanner.routing.core.State in project OpenTripPlanner by opentripplanner.
the class GraphPathFinder method compactLegsByReversedSearch.
/**
* Do a full reversed search to compact the legs of the path.
*
* By doing a reversed search we are looking for later departures that will still be in time for transfer
* to the next trip, shortening the transfer wait time. Also considering other routes than the ones found
* in the original search.
*
* For arrive-by searches, we are looking to shorten transfer wait time and rather arrive earlier.
*/
private List<GraphPath> compactLegsByReversedSearch(AStar aStar, RoutingRequest originalReq, RoutingRequest options, List<GraphPath> newPaths, double timeout, RemainingWeightHeuristic remainingWeightHeuristic) {
List<GraphPath> reversedPaths = new ArrayList<>();
for (GraphPath newPath : newPaths) {
State targetAcceptedState = options.arriveBy ? newPath.states.getLast().reverse() : newPath.states.getLast();
if (targetAcceptedState.stateData.getNumBooardings() < 2) {
reversedPaths.add(newPath);
continue;
}
final long arrDepTime = targetAcceptedState.getTimeSeconds();
LOG.debug("Dep time: " + new Date(newPath.getStartTime() * 1000));
LOG.debug("Arr time: " + new Date(newPath.getEndTime() * 1000));
// find first/last transit stop
Vertex transitStop = null;
long transitStopTime = arrDepTime;
while (transitStop == null) {
if (targetAcceptedState.backEdge instanceof TransitBoardAlight) {
if (options.arriveBy) {
transitStop = targetAcceptedState.backEdge.getFromVertex();
} else {
transitStop = targetAcceptedState.backEdge.getToVertex();
}
transitStopTime = targetAcceptedState.getTimeSeconds();
}
targetAcceptedState = targetAcceptedState.getBackState();
}
// find the path from transitStop to origin/destination
Vertex fromVertex = options.arriveBy ? options.rctx.fromVertex : transitStop;
Vertex toVertex = options.arriveBy ? transitStop : options.rctx.toVertex;
RoutingRequest reversedTransitRequest = createReversedTransitRequest(originalReq, options, fromVertex, toVertex, arrDepTime, new EuclideanRemainingWeightHeuristic());
aStar.getShortestPathTree(reversedTransitRequest, timeout);
List<GraphPath> pathsToTarget = aStar.getPathsToTarget();
if (pathsToTarget.isEmpty()) {
reversedPaths.add(newPath);
continue;
}
GraphPath walkPath = pathsToTarget.get(0);
// do the reversed search to/from transitStop
Vertex fromTransVertex = options.arriveBy ? transitStop : options.rctx.fromVertex;
Vertex toTransVertex = options.arriveBy ? options.rctx.toVertex : transitStop;
RoutingRequest reversedMainRequest = createReversedMainRequest(originalReq, options, fromTransVertex, toTransVertex, transitStopTime, remainingWeightHeuristic);
aStar.getShortestPathTree(reversedMainRequest, timeout);
List<GraphPath> newRevPaths = aStar.getPathsToTarget();
if (newRevPaths.isEmpty()) {
reversedPaths.add(newPath);
} else {
List<GraphPath> joinedPaths = new ArrayList<>();
for (GraphPath newRevPath : newRevPaths) {
LOG.debug("REV Dep time: " + new Date(newRevPath.getStartTime() * 1000));
LOG.debug("REV Arr time: " + new Date(newRevPath.getEndTime() * 1000));
List<GraphPath> concatenatedPaths = Arrays.asList(newRevPath, walkPath);
if (options.arriveBy) {
Collections.reverse(concatenatedPaths);
}
GraphPath joinedPath = joinPaths(concatenatedPaths);
if ((!options.arriveBy && joinedPath.states.getFirst().getTimeInMillis() > options.dateTime * 1000) || (options.arriveBy && joinedPath.states.getLast().getTimeInMillis() < options.dateTime * 1000)) {
joinedPaths.add(joinedPath);
if (newPaths.size() > 1) {
for (AgencyAndId tripId : joinedPath.getTrips()) {
options.banTrip(tripId);
}
}
}
}
reversedPaths.addAll(joinedPaths);
}
}
return reversedPaths.isEmpty() ? newPaths : reversedPaths;
}
use of org.opentripplanner.routing.core.State in project OpenTripPlanner by opentripplanner.
the class NycFareServiceImpl method getCost.
@Override
public Fare getCost(GraphPath path) {
final List<AgencyAndId> SIR_PAID_STOPS = makeMtaStopList("S31", "S30");
final List<AgencyAndId> SUBWAY_FREE_TRANSFER_STOPS = makeMtaStopList("R11", "B08", "629");
final List<AgencyAndId> SIR_BONUS_STOPS = makeMtaStopList("140", "420", "419", "418", "M22", "M23", "R27", "R26");
final List<AgencyAndId> SIR_BONUS_ROUTES = makeMtaStopList("M5", "M20", "M15-SBS");
final List<AgencyAndId> CANARSIE = makeMtaStopList("L29", "303345");
// List of NYC agencies to set fares for
final List<String> AGENCIES = new ArrayList<>();
AGENCIES.add("MTABC");
AGENCIES.add("MTA NYCT");
LinkedList<State> states = path.states;
// create rides
List<Ride> rides = new ArrayList<Ride>();
Ride newRide = null;
final int SUBWAY = 1;
final int SIR = 2;
final int LOCAL_BUS = 3;
final int EXPRESS_BUS = 30;
final int EXPENSIVE_EXPRESS_BUS = 34;
final int WALK = -1;
for (State state : states) {
Edge backEdge = state.getBackEdge();
if (backEdge instanceof StreetEdge) {
if (newRide == null || !newRide.classifier.equals(WALK)) {
if (rides.size() == 0 || !rides.get(rides.size() - 1).classifier.equals(WALK)) {
newRide = new Ride();
newRide.classifier = WALK;
rides.add(newRide);
}
}
continue;
}
// dwells do not affect fare.
if (backEdge instanceof DwellEdge)
continue;
if (!(backEdge instanceof HopEdge)) {
newRide = null;
continue;
}
AgencyAndId routeId = state.getRoute();
String agencyId = state.getBackTrip().getRoute().getAgency().getId();
if (!AGENCIES.contains(agencyId)) {
continue;
}
if (routeId == null) {
newRide = null;
} else {
if (newRide == null || !routeId.equals(newRide.route)) {
newRide = new Ride();
rides.add(newRide);
newRide.firstStop = ((HopEdge) backEdge).getBeginStop();
newRide.route = routeId;
Trip trip = state.getBackTrip();
Route route = trip.getRoute();
int type = route.getType();
newRide.classifier = type;
String shortName = route.getShortName();
if (shortName == null) {
newRide.classifier = SUBWAY;
} else if (shortName.equals("BxM4C")) {
newRide.classifier = EXPENSIVE_EXPRESS_BUS;
} else if (shortName.startsWith("X") || shortName.startsWith("BxM") || shortName.startsWith("QM") || shortName.startsWith("BM")) {
// Express bus
newRide.classifier = EXPRESS_BUS;
}
newRide.startTime = state.getTimeSeconds();
}
newRide.lastStop = ((HopEdge) backEdge).getBeginStop();
}
}
// There are no rides, so there's no fare.
if (rides.size() == 0) {
return null;
}
NycFareState state = NycFareState.INIT;
boolean lexFreeTransfer = false;
boolean canarsieFreeTransfer = false;
boolean siLocalBus = false;
boolean sirBonusTransfer = false;
float totalFare = 0;
for (Ride ride : rides) {
AgencyAndId firstStopId = null;
AgencyAndId lastStopId = null;
if (ride.firstStop != null) {
firstStopId = ride.firstStop.getId();
lastStopId = ride.lastStop.getId();
}
switch(state) {
case INIT:
lexFreeTransfer = siLocalBus = canarsieFreeTransfer = false;
if (ride.classifier.equals(WALK)) {
// walking keeps you in init
} else if (ride.classifier.equals(SUBWAY)) {
state = NycFareState.SUBWAY_PRE_TRANSFER;
totalFare += ORDINARY_FARE;
if (SUBWAY_FREE_TRANSFER_STOPS.contains(ride.lastStop.getId())) {
lexFreeTransfer = true;
}
if (CANARSIE.contains(ride.lastStop.getId())) {
canarsieFreeTransfer = true;
}
} else if (ride.classifier.equals(SIR)) {
state = NycFareState.SIR_PRE_TRANSFER;
if (SIR_PAID_STOPS.contains(firstStopId) || SIR_PAID_STOPS.contains(lastStopId)) {
totalFare += ORDINARY_FARE;
}
} else if (ride.classifier.equals(LOCAL_BUS)) {
state = NycFareState.BUS_PRE_TRANSFER;
totalFare += ORDINARY_FARE;
if (CANARSIE.contains(ride.lastStop.getId())) {
canarsieFreeTransfer = true;
}
siLocalBus = ride.route.getId().startsWith("S");
} else if (ride.classifier.equals(EXPRESS_BUS)) {
state = NycFareState.BUS_PRE_TRANSFER;
totalFare += EXPRESS_FARE;
} else if (ride.classifier.equals(EXPENSIVE_EXPRESS_BUS)) {
state = NycFareState.EXPENSIVE_EXPRESS_BUS;
totalFare += EXPENSIVE_EXPRESS_FARE;
}
break;
case SUBWAY_PRE_TRANSFER_WALKED:
if (ride.classifier.equals(SUBWAY)) {
// lex and 59/63
if (!(lexFreeTransfer && SUBWAY_FREE_TRANSFER_STOPS.contains(ride.firstStop.getId()))) {
totalFare += ORDINARY_FARE;
}
lexFreeTransfer = canarsieFreeTransfer = false;
if (SUBWAY_FREE_TRANSFER_STOPS.contains(ride.lastStop.getId())) {
lexFreeTransfer = true;
}
if (CANARSIE.contains(ride.lastStop.getId())) {
canarsieFreeTransfer = true;
}
}
/* FALL THROUGH */
case SUBWAY_PRE_TRANSFER:
// hours (if only just)
if (ride.classifier.equals(WALK)) {
state = NycFareState.SUBWAY_PRE_TRANSFER_WALKED;
} else if (ride.classifier.equals(SIR)) {
state = NycFareState.SIR_POST_TRANSFER_FROM_SUBWAY;
} else if (ride.classifier.equals(LOCAL_BUS)) {
if (CANARSIE.contains(ride.firstStop.getId()) && canarsieFreeTransfer) {
state = NycFareState.BUS_PRE_TRANSFER;
} else {
state = NycFareState.INIT;
}
} else if (ride.classifier.equals(EXPRESS_BUS)) {
// need to pay the upgrade cost
totalFare += EXPRESS_FARE - ORDINARY_FARE;
} else if (ride.classifier.equals(EXPENSIVE_EXPRESS_BUS)) {
// no transfers to the
totalFare += EXPENSIVE_EXPRESS_FARE;
// BxMM4C
}
break;
case BUS_PRE_TRANSFER:
if (ride.classifier.equals(SUBWAY)) {
if (CANARSIE.contains(ride.firstStop.getId()) && canarsieFreeTransfer) {
state = NycFareState.SUBWAY_PRE_TRANSFER;
} else {
state = NycFareState.INIT;
}
} else if (ride.classifier.equals(SIR)) {
if (siLocalBus) {
// SI local bus to SIR, so it is as if we started on the
// SIR (except that when we enter the bus or subway system we need to do
// so at certain places)
sirBonusTransfer = true;
state = NycFareState.SIR_PRE_TRANSFER;
} else {
// transfers exhausted
state = NycFareState.INIT;
}
} else if (ride.classifier.equals(LOCAL_BUS)) {
state = NycFareState.INIT;
} else if (ride.classifier.equals(EXPRESS_BUS)) {
// need to pay the upgrade cost
totalFare += EXPRESS_FARE - ORDINARY_FARE;
state = NycFareState.INIT;
} else if (ride.classifier.equals(EXPENSIVE_EXPRESS_BUS)) {
totalFare += EXPENSIVE_EXPRESS_FARE;
// no transfers to the BxMM4C
}
break;
case SIR_PRE_TRANSFER:
if (ride.classifier.equals(SUBWAY)) {
if (sirBonusTransfer && !SIR_BONUS_STOPS.contains(ride.firstStop.getId())) {
// we were relying on the bonus transfer to be in the "pre-transfer state",
// but the bonus transfer does not apply here
totalFare += ORDINARY_FARE;
}
if (CANARSIE.contains(ride.lastStop.getId())) {
canarsieFreeTransfer = true;
}
state = NycFareState.SUBWAY_POST_TRANSFER;
} else if (ride.classifier.equals(SIR)) {
/* should not happen, and unhandled */
LOG.warn("Should not transfer from SIR to SIR");
} else if (ride.classifier.equals(LOCAL_BUS)) {
if (!SIR_BONUS_ROUTES.contains(ride.route)) {
totalFare += ORDINARY_FARE;
}
state = NycFareState.BUS_PRE_TRANSFER;
} else if (ride.classifier.equals(EXPRESS_BUS)) {
totalFare += EXPRESS_BUS;
state = NycFareState.BUS_PRE_TRANSFER;
} else if (ride.classifier.equals(EXPENSIVE_EXPRESS_BUS)) {
totalFare += EXPENSIVE_EXPRESS_BUS;
state = NycFareState.BUS_PRE_TRANSFER;
}
break;
case SIR_POST_TRANSFER_FROM_SUBWAY:
if (ride.classifier.equals(SUBWAY)) {
/* should not happen */
totalFare += ORDINARY_FARE;
state = NycFareState.SUBWAY_PRE_TRANSFER;
} else if (ride.classifier.equals(SIR)) {
/* should not happen, and unhandled */
LOG.warn("Should not transfer from SIR to SIR");
} else if (ride.classifier.equals(LOCAL_BUS)) {
if (!ride.route.getId().startsWith("S")) {
totalFare += ORDINARY_FARE;
state = NycFareState.BUS_PRE_TRANSFER;
} else {
state = NycFareState.INIT;
}
} else if (ride.classifier.equals(EXPRESS_BUS)) {
// need to pay the full cost
totalFare += EXPRESS_FARE;
state = NycFareState.INIT;
} else if (ride.classifier.equals(EXPENSIVE_EXPRESS_BUS)) {
/* should not happen */
// no transfers to the BxMM4C
totalFare += EXPENSIVE_EXPRESS_FARE;
state = NycFareState.BUS_PRE_TRANSFER;
}
break;
case SUBWAY_POST_TRANSFER:
if (ride.classifier.equals(WALK)) {
if (!canarsieFreeTransfer) {
/* note: if we end up walking to another subway after alighting
* at Canarsie, we will mistakenly not be charged, but nobody
* would ever do this */
state = NycFareState.INIT;
}
} else if (ride.classifier.equals(SIR)) {
totalFare += ORDINARY_FARE;
state = NycFareState.SIR_PRE_TRANSFER;
} else if (ride.classifier.equals(LOCAL_BUS)) {
if (!(CANARSIE.contains(ride.firstStop.getId()) && canarsieFreeTransfer)) {
totalFare += ORDINARY_FARE;
}
state = NycFareState.INIT;
} else if (ride.classifier.equals(SUBWAY)) {
// walking transfer
totalFare += ORDINARY_FARE;
state = NycFareState.SUBWAY_PRE_TRANSFER;
} else if (ride.classifier.equals(EXPRESS_BUS)) {
totalFare += EXPRESS_FARE;
state = NycFareState.BUS_PRE_TRANSFER;
} else if (ride.classifier.equals(EXPENSIVE_EXPRESS_BUS)) {
totalFare += EXPENSIVE_EXPRESS_FARE;
state = NycFareState.BUS_PRE_TRANSFER;
}
}
}
Currency currency = Currency.getInstance("USD");
Fare fare = new Fare();
fare.addFare(FareType.regular, new WrappedCurrency(currency), (int) Math.round(totalFare * Math.pow(10, currency.getDefaultFractionDigits())));
return fare;
}
use of org.opentripplanner.routing.core.State in project OpenTripPlanner by opentripplanner.
the class BikeParkEdge method traversePark.
protected State traversePark(State s0) {
RoutingRequest options = s0.getOptions();
/*
* To park a bike, we need to be riding one, (not rented) and be allowed to walk and to park
* it.
*/
if (s0.getNonTransitMode() != TraverseMode.BICYCLE || !options.modes.getWalk() || s0.isBikeRenting() || s0.isBikeParked())
return null;
BikeParkVertex bikeParkVertex = (BikeParkVertex) tov;
if (bikeParkVertex.getSpacesAvailable() == 0) {
return null;
}
StateEditor s0e = s0.edit(this);
s0e.incrementWeight(options.bikeParkCost);
s0e.incrementTimeInSeconds(options.bikeParkTime);
s0e.setBackMode(TraverseMode.LEG_SWITCH);
s0e.setBikeParked(true);
State s1 = s0e.makeState();
return s1;
}
Aggregations