All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentripplanner.model.transfer.TransferConstraint Maven / Gradle / Ivy

There is a newer version: 2.5.0
Show newest version
package org.opentripplanner.model.transfer;

import static org.opentripplanner.model.transfer.TransferPriority.ALLOWED;
import static org.opentripplanner.model.transfer.TransferPriority.NOT_ALLOWED;
import static org.opentripplanner.model.transfer.TransferPriority.PREFERRED;
import static org.opentripplanner.model.transfer.TransferPriority.RECOMMENDED;

import java.io.Serializable;
import java.util.Objects;
import javax.annotation.Nullable;
import org.opentripplanner.model.base.ToStringBuilder;
import org.opentripplanner.transit.raptor.api.transit.RaptorTransferConstraint;

/**
 * This class holds transfer constraint information.
 * 

* The class is immutable. */ public class TransferConstraint implements Serializable, RaptorTransferConstraint { private static final long serialVersionUID = 1L; /** * A regular transfer is a transfer with no constraints. */ public static final TransferConstraint REGULAR_TRANSFER = create().build(); /** * STAY_SEATED is not a priority, but we assign a cost to it to be able to compare it with other * transfers with a priority and the {@link #GUARANTIED_TRANSFER_COST}. */ private static final int STAY_SEATED_TRANSFER_COST = 10_00; /** * GUARANTIED is not a priority, but we assign a cost to it to be able to compare it with other * transfers with a priority. The cost is better than a pure prioritized transfer, but the * priority and GUARANTIED attribute is added together; Hence a (GUARANTIED, RECOMMENDED) * transfer is better than (GUARANTIED, ALLOWED). */ private static final int GUARANTIED_TRANSFER_COST = 20_00; /** * A cost penalty of 10 points is added to a Transfer which is NOT stay-seated or guaranteed. * This makes sure that stay-seated and guaranteed transfers take precedence over the priority * cost. */ private static final int NONE_FACILITATED_COST = 30_00; /** * A cost penalty of 4 points is added to transfers which are NOT stay-seated or guaranteed. */ private static final int DEFAULT_COST = NONE_FACILITATED_COST + ALLOWED.cost(); /** * Starting point for calculating the transfer constraint cost. */ public static final int ZERO_COST = 0; /** * Used with {@link #getMaxWaitTime()} and {@link #getMinTransferTime()} to indicate * the parameter is not available. */ public static final int NOT_SET = -1; private final TransferPriority priority; private final boolean staySeated; private final boolean guaranteed; private final int maxWaitTime; private final int minTransferTime; private final boolean includeInRaptorRouting; private TransferConstraint(Builder builder) { this.priority = builder.priority; this.staySeated = builder.staySeated; this.guaranteed = builder.guaranteed; this.maxWaitTime = builder.maxWaitTime; this.minTransferTime = builder.minTransferTime; // Decide if the transfer needs to be taken into account in the Raptor routing process // or can be dealt with outside raptor, e.g in path transfer optimization. this.includeInRaptorRouting = staySeated || guaranteed || priority == NOT_ALLOWED || minTransferTime != NOT_SET; if(isMaxWaitTimeSet() && !guaranteed) { throw new IllegalArgumentException( "'maxWaitTime' do only apply to guaranteed transfers." ); } } /** * @see #cost(TransferConstraint) */ public int cost() { return priority.cost() + facilitatedCost(); } public TransferPriority getPriority() { return priority; } /** * Also known as interlining of GTFS trips with the same block id. */ public boolean isStaySeated() { return staySeated; } public boolean isGuaranteed() { return guaranteed; } /** * A facilitated transfer is allowed even if there might not be enough time to walk or * if the alight-slack or board-slack is too tight. We ignore slack for facilitated transfers. *

* This is an aggregated field, which encapsulates an OTP specific rule. A facilitated transfer * is either stay-seated or guaranteed. High priority transfers are not facilitated. */ public boolean isFacilitated() { return staySeated || guaranteed; } /** * This switch enables transfers in Raptor, ignoring transfer constraints with for example * only priority set. */ public boolean includeInRaptorRouting() { return includeInRaptorRouting; } @Override public boolean isNotAllowed() { return priority == NOT_ALLOWED; } @Override public boolean isRegularTransfer() { // Note! The 'maxWaitTime' is only valid with the guaranteed flag set, so we // do not need to check it here return !(isFacilitated() || isMinTransferTimeSet() || priority.isConstrained()); } /** * Maximum time after scheduled departure time the connecting transport is guarantied to wait * for the delayed trip. *

* THIS IS NOT CONSIDERED IN RAPTOR. OTP relies on real-time data for this, so if the "from" * vehicle is delayed, then the real time system is also responsible for propagating the delay * onto the "to" trip. */ public int getMaxWaitTime() { return maxWaitTime; } /** * The min-transfer-time specify lower bound for the transfer time. * {@link org.opentripplanner.routing.algorithm.raptoradapter.transit.constrainedtransfer.ConstrainedBoardingSearch} * uses this to make sure at least the amount of seconds specified is available to do the * transfer. If the path transfer takes more time than specified by the * {@code min-transfer-time} then the path transfer is used. Normal slack parameters are added * to the path transfer, but not to the {@code min-transfer-time}. */ public int getMinTransferTime() { return minTransferTime; } public boolean isMinTransferTimeSet() { return minTransferTime != NOT_SET; } @Override public int hashCode() { return Objects.hash(priority, staySeated, guaranteed, maxWaitTime); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof TransferConstraint)) { return false; } final TransferConstraint that = (TransferConstraint) o; return staySeated == that.staySeated && guaranteed == that.guaranteed && priority == that.priority && maxWaitTime == that.maxWaitTime; } public String toString() { if(isRegularTransfer()) { return "{no constraints}"; } return ToStringBuilder.of() .addEnum("priority", priority, ALLOWED) .addBoolIfTrue("staySeated", staySeated) .addBoolIfTrue("guaranteed", guaranteed) .addDurationSec("minTransferTime", minTransferTime, NOT_SET) .addDurationSec("maxWaitTime", maxWaitTime, NOT_SET) .toString(); } /** * Calculate a cost for prioritizing transfers in a path, to select the best path with respect to * transfers. This cost is not related in any way to the path generalized-cost. It takes only the * transfer constraint attributes in consideration. *

* When comparing paths that ride the same trips, this can be used to find the optimal places to * do the transfers. The cost is created to prioritize the following: *

    *
  1. {@code stay-seated} - cost: 10 points
  2. *
  3. {@code guaranteed} - cost: 20 points
  4. *
  5. None facilitated - cost: 30 points
  6. *
* In addition, the {@code priority} cost is added. See {@link TransferPriority#cost()}. * * @param c The transfer to return a cost for, or {@code null} if the transfer is a regular OSM * street generated transfer. */ public static int cost(@Nullable TransferConstraint c) { return c == null ? DEFAULT_COST : c.cost(); } /** * Return a cost for stay-seated, guaranteed or none-facilitated transfers. This is * used to prioritize stay-seated over guaranteed, and guaranteed over non-facilitated * transfers. */ private int facilitatedCost() { if(staySeated) { return STAY_SEATED_TRANSFER_COST; } if(guaranteed) { return GUARANTIED_TRANSFER_COST; } return NONE_FACILITATED_COST; } private boolean isMaxWaitTimeSet() { return maxWaitTime != NOT_SET; } public static Builder create() { return new Builder(); } public static class Builder { private TransferPriority priority = ALLOWED; private boolean staySeated = false; private boolean guaranteed = false; private int maxWaitTime = NOT_SET; private int minTransferTime = NOT_SET; public Builder priority(TransferPriority priority) { this.priority = priority; return this; } public Builder notAllowed() { return priority(NOT_ALLOWED); } public Builder recommended() { return priority(RECOMMENDED); } public Builder preferred() { return priority(PREFERRED); } public Builder staySeated(boolean enable) { this.staySeated = enable; return this; } public Builder staySeated() { return staySeated(true); } public Builder guaranteed(boolean enable) { this.guaranteed = enable; return this; } public Builder guaranteed() { return guaranteed(true); } public Builder maxWaitTime(int maxWaitTime) { this.maxWaitTime = maxWaitTime; return this; } public Builder minTransferTime(int minTransferTime) { this.minTransferTime = minTransferTime; return this; } public TransferConstraint build() { return new TransferConstraint(this); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy