package cz.agents.agentpolis.darptestbed.simmodel.agent.data; /** * One item that belongs to the FlexiblePlan (it represents either a start or a * target request node) * * @author Lukas Canda */ public class PlanItem implements Cloneable { /** * This plan item represents one of two nodes of this request */ protected Request request; /** * True, if it represents the start node, false, if it's the target node */ public final boolean isBoarding; /** * The time when the taxi driver arrives to this node (according to the * plan) */ protected long arrivalTime = -1; /** * How much time the driver needs to wait on this node (for the time window * to open) */ protected long waitingTime = -1; public PlanItem(Request request, boolean isBoarding) { this.request = request; this.isBoarding = isBoarding; // these fields need to be set up later this.arrivalTime = -1; this.waitingTime = -1; } /** * Creates new instance of PlanItem * * @param request this plan item represents one of two nodes of this request * @param getIn true, if it represents the start node, false, if it's the * target node * @param arrivalTime the time when the taxi arrives into this node * @return new instance of PlanItem, or null, if the timeToArrive is too * late */ public static PlanItem createPlanItem(Request request, boolean getIn, long arrivalTime) { if (PlanItem.hasDelay(request, getIn, arrivalTime)) { return null; } return new PlanItem(request, getIn, arrivalTime); } private PlanItem(Request request, boolean isBoarding, long arrivalTime) { this.request = request; this.isBoarding = isBoarding; this.arrivalTime = arrivalTime; computeWaitingTime(); } /** * Sets the arrival time to this node, counts waiting time * * @param arrivalTime * @return -1 if the time causes delay, else it returns the departure time * (including waiting) */ public long setArrivalTime(long arrivalTime) { if (hasDelay(arrivalTime)) { return -1; } this.arrivalTime = arrivalTime; computeWaitingTime(); return getDepartureTime(); } /** * Adds a time to the current arrival time * * @param timeToAdd time to add to the current arrival time * @return -1 if the time causes delay, else it returns the difference that * it causes in departure time (including waiting) */ public long addTime(long timeToAdd) { long returnDiff = computeDepartureDifference(timeToAdd); if (returnDiff >= 0) { // count savings in waiting if (waitingTime >= timeToAdd) { waitingTime -= timeToAdd; } else { waitingTime = 0; } arrivalTime += timeToAdd; return returnDiff; } return -1; } /** * Tries to add a time (but doesn't really add it) * * @param timeToAdd time to add to the current arrival time * @return -1 if the time causes delay, else it returns the difference that * it causes in departure time (including waiting) */ public long computeDepartureDifference(long timeToAdd) { if (canAddTime(timeToAdd)) { // no difference, only saves some waiting if (waitingTime >= timeToAdd) { return 0; } return timeToAdd - waitingTime; } return -1; } /** * The vehicle will arrive sooner, so lets adjust the arrival time * * @param timeToTake the amount of time we should subtract * @return the decrease that it caused in departure time */ public long takeTime(long timeToTake) { long departTime = getDepartureTime(); arrivalTime -= timeToTake; computeWaitingTime(); return departTime - getDepartureTime(); } /** * The time we try to add won't cause the delay in this node (that is, if * the driver doesn't come too late) * * @param timeToAdd time we're trying to add * @return true, if it won't cause the delay */ public boolean canAddTime(long timeToAdd) { if (hasDelay(arrivalTime + timeToAdd)) { return false; } return true; } /** * Counts the waiting time according to the request and arrival time */ private void computeWaitingTime() { this.waitingTime = 0; TimeWindow timeWin = request.getTimeWindow(); if (timeWin == null) { return; } if (isBoarding) { long earliestDep = timeWin.getEarliestDeparture(); if (arrivalTime < earliestDep) { this.waitingTime = earliestDep - arrivalTime; } } else if (!timeWin.isOneInterval()) { long earliestArr = timeWin.getEarliestArrival(); if (arrivalTime < earliestArr) { this.waitingTime = earliestArr - arrivalTime; } } } /** * @param arrivalTime * @return true, if the arrival time is too late */ public boolean hasDelay(long arrivalTime) { return PlanItem.hasDelay(request, isBoarding, arrivalTime); } private static boolean hasDelay(Request request, boolean getIn, long arrivalTime) { TimeWindow timeWin = request.getTimeWindow(); if (timeWin == null) { return false; } if (getIn) { if ((timeWin.isOneInterval() && arrivalTime > timeWin.getLatestArrival()) || (!timeWin.isOneInterval() && arrivalTime > timeWin.getLatestDeparture())) { return true; } } else { if (arrivalTime > timeWin.getLatestArrival()) { return true; } } return false; } /** * @return the time when the driver departs from this node (according to the * plan) */ public long getDepartureTime() { return arrivalTime + waitingTime; } public long getArrivalTime() { return arrivalTime; } /** * Get the number of node this plan item represents * * @return the number of node */ public long getNode() { if (isBoarding) { return request.getFromNode(); } return request.getToNode(); } public String getPassengerId() { return request.getPassengerId(); } /** * Sets arrival time and waiting time back do default */ public void resetArrivalTime() { this.arrivalTime = -1; this.waitingTime = -1; } @Override public Object clone() throws CloneNotSupportedException { return new PlanItem(request, isBoarding, arrivalTime); } }