package cz.agents.agentpolis.darptestbed.simmodel.agent.data; import com.google.common.collect.Sets; import cz.agents.agentpolis.darptestbed.global.Utils; import cz.agents.agentpolis.darptestbed.simmodel.agent.data.generator.PassengersInAndOutPair; import cz.agents.agentpolis.darptestbed.simmodel.agent.driver.logic.DriverLogic; import cz.agents.agentpolis.siminfrastructure.planner.trip.Trip; import cz.agents.agentpolis.siminfrastructure.planner.trip.Trips; import org.apache.log4j.Logger; import java.util.*; import java.util.Map.Entry; import static com.google.common.base.Preconditions.checkNotNull; /** * A trip plan to be driven by a taxi driver. It consists of the list of nodes * to visit, along with the lists of passengers that get in on those nodes. * * @author Lukas Canda */ public class TripPlan { private static final Logger LOGGER = Logger.getLogger(TripPlan.class); /** * A list of trips to serve a few passengers. Each trip ends at a * pickup/drop location. */ protected Trips trips; /** * The map that lists passengers that get in on some nodes of the trips * (couples <node number, ids of passengers>) */ protected final Map<Long, PassengersInAndOutPair> mapOfBoardingAndDisembarkingPassengers; /** * The plan, that can be re-planned by a planner (optional) */ protected FlexiblePlan flexiblePlan = null; public TripPlan(Trips trips, Map<Long, PassengersInAndOutPair> mapOfBoardingAndDisembarkingPassengers) { this(trips, mapOfBoardingAndDisembarkingPassengers, null); } public TripPlan(Trips trips, Map<Long, PassengersInAndOutPair> mapOfBoardingAndDisembarkingPassengers, FlexiblePlan planForPlanner) { this.trips = trips; this.mapOfBoardingAndDisembarkingPassengers = mapOfBoardingAndDisembarkingPassengers; this.flexiblePlan = planForPlanner; } public TripPlan() { this.trips = new Trips(); this.mapOfBoardingAndDisembarkingPassengers = new HashMap<>(); } public TripPlan(TripPlan toCopy) { if (toCopy.mapOfBoardingAndDisembarkingPassengers != null) { mapOfBoardingAndDisembarkingPassengers = new HashMap(toCopy.mapOfBoardingAndDisembarkingPassengers); for (Entry<Long, PassengersInAndOutPair> passengersEntry : mapOfBoardingAndDisembarkingPassengers.entrySet()) { PassengersInAndOutPair pair = new PassengersInAndOutPair(passengersEntry.getValue()); passengersEntry.setValue(pair); } } else { mapOfBoardingAndDisembarkingPassengers = null; } if (toCopy.trips != null) { trips = new Trips(); for (Trip<?> tTrip : toCopy.trips) { if (tTrip != null) { trips.addTrip(tTrip.clone()); } else { // trips.addTrip(null); } } } if (toCopy.flexiblePlan != null) { try { flexiblePlan = (FlexiblePlan) toCopy.flexiblePlan.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } } } public Trips getTrips() { return trips; } public void extend(TripPlan tripPlan) { tripPlan = checkNotNull(tripPlan); Trips clone = tripPlan.getTrips().clone(); while (clone.hasTrip()) { trips.addEndCurrentTrips(clone.getAndRemoveFirstTrip()); } for (Entry<Long, PassengersInAndOutPair> tripPlanEntry : tripPlan.getMapOfBoardingAndDisembarkingPassengers().entrySet()) { PassengersInAndOutPair set = mapOfBoardingAndDisembarkingPassengers.get(tripPlanEntry.getKey()); if (set == null) { set = new PassengersInAndOutPair(); } PassengersInAndOutPair setNew = tripPlan.getMapOfBoardingAndDisembarkingPassengers().get(tripPlanEntry.getKey()); if (setNew == null) { setNew = new PassengersInAndOutPair(); } set.addAll(setNew); mapOfBoardingAndDisembarkingPassengers.put(tripPlanEntry.getKey(), set); } if (this.flexiblePlan != null && tripPlan.flexiblePlan != null) { this.flexiblePlan.currentTime = tripPlan.flexiblePlan.currentTime; this.flexiblePlan.lastNode = tripPlan.flexiblePlan.lastNode; this.flexiblePlan.planItems.addAll(tripPlan.flexiblePlan.planItems); if (this.flexiblePlan.vehicle.getId() != tripPlan.flexiblePlan.vehicle.getId()) { throw new RuntimeException("Vehicle ids of flexible plans have to the same"); } } if (this.flexiblePlan == null) { this.flexiblePlan = tripPlan.flexiblePlan; } } public void setTrips(Trips trips) { this.trips = trips; } protected Map<Long, PassengersInAndOutPair> getMapOfBoardingAndDisembarkingPassengers() { return mapOfBoardingAndDisembarkingPassengers; } public FlexiblePlan getFlexiblePlan(Utils utils) { return flexiblePlan; } @Override public String toString() { return TripPlan.class.getSimpleName() + " Passengers: " + mapOfBoardingAndDisembarkingPassengers + " " + this.getTrips().numTrips() + " Trips: " + trips; } public boolean removeRequestFromBoardingAndDisembarkingPassengers(Request request) { boolean success = true; try { PassengersInAndOutPair passengersAtNode = getMapOfBoardingAndDisembarkingPassengers().get(request.getFromNode()); if (passengersAtNode != null) { passengersAtNode.getIn().remove(request.getPassengerId()); if (passengersAtNode.isEmpty()) { getMapOfBoardingAndDisembarkingPassengers().remove(request.getFromNode()); } } else { success = false; } passengersAtNode = getMapOfBoardingAndDisembarkingPassengers().get(request.getToNode()); if (passengersAtNode == null) { // LOGGER.debug("NULL REMOVE: " + request + " " + this); } passengersAtNode.getOff().remove(request.getPassengerId()); if (passengersAtNode.isEmpty()) { getMapOfBoardingAndDisembarkingPassengers().remove(request.getToNode()); } } catch (NullPointerException e) { // LOGGER.debug("NULL POINTER"); } return success; } public boolean removePassengerFromBoardingPassengersAtNode(String passengerId, long node) { PassengersInAndOutPair passengersAtNode = getMapOfBoardingAndDisembarkingPassengers().get(node); if (passengersAtNode != null) { passengersAtNode.getIn().remove(passengerId); if (passengersAtNode.isEmpty()) getMapOfBoardingAndDisembarkingPassengers().remove(node); return true; } else { return false; } } public boolean removePassengerFromDisembarkingPassengersAtNode(String passengerId, long node) { PassengersInAndOutPair passengersAtNode = getMapOfBoardingAndDisembarkingPassengers().get(node); if (passengersAtNode != null) { passengersAtNode.getOff().remove(passengerId); if (passengersAtNode.isEmpty()) getMapOfBoardingAndDisembarkingPassengers().remove(node); return true; } else { return false; } } public boolean removePassengerFromBoardingAndDisembarkingPassengersAtNode(String passengerId, long node) { return removePassengerFromBoardingPassengersAtNode(passengerId, node) && removePassengerFromDisembarkingPassengersAtNode(passengerId, node); } public void addRequestToBoardingAndDisembarkingPassengers(Request request) { PassengersInAndOutPair passengersAtNode = getMapOfBoardingAndDisembarkingPassengers().get(request.getFromNode()); if (passengersAtNode == null) { passengersAtNode = new PassengersInAndOutPair(); getMapOfBoardingAndDisembarkingPassengers().put(request.getFromNode(), passengersAtNode); } passengersAtNode.getIn().add(request.getPassengerId()); passengersAtNode = getMapOfBoardingAndDisembarkingPassengers().get(request.getToNode()); if (passengersAtNode == null) { passengersAtNode = new PassengersInAndOutPair(); getMapOfBoardingAndDisembarkingPassengers().put(request.getToNode(), passengersAtNode); } passengersAtNode.getOff().add(request.getPassengerId()); } public PassengersInAndOutPair getNodeWithBoardingAndDisembarkingPassengers(long node) { return getMapOfBoardingAndDisembarkingPassengers().get(node); } public void clear() { trips = new Trips(); flexiblePlan = null; getMapOfBoardingAndDisembarkingPassengers().clear(); } public Set<String> getPassengersOnBoard() { Set<String> inPassengersRegistry = new HashSet<>(); Set<String> allPassengersRegistry = new HashSet<>(); for (PassengersInAndOutPair onOffPair : getMapOfBoardingAndDisembarkingPassengers().values()) { allPassengersRegistry = Sets.union(allPassengersRegistry, onOffPair.getIn()); allPassengersRegistry = Sets.union(allPassengersRegistry, onOffPair.getOff()); inPassengersRegistry = Sets.union(inPassengersRegistry, onOffPair.getIn()); } return Sets.difference(allPassengersRegistry, inPassengersRegistry).immutableCopy(); } public void removeLatePickupPassengerFromTripPlan(String passengerId, String vehicleId, Utils utils) { Trips trips = getTrips().clone(); Trips constructed = new Trips(); while (trips.hasTrip()) { Trip current = null; while (trips.hasTrip() && (current = trips.getAndRemoveFirstTrip()) == null) ; long lastNode = current.showLastTripItem().tripPositionByNodeId; PassengersInAndOutPair off = getNodeWithBoardingAndDisembarkingPassengers(lastNode); if (off != null && off.getOff().contains(passengerId)) { removePassengerFromDisembarkingPassengersAtNode(passengerId, lastNode); long start = current.showCurrentTripItem().tripPositionByNodeId; if (trips.hasTrip()) { while (trips.hasTrip() && (current = trips.getAndRemoveFirstTrip()) == null); } else { continue; } if (current != null) { long end = current.showLastTripItem().tripPositionByNodeId; current = utils.planTrip(vehicleId, start, end); } else { continue; } } constructed.addTrip(current); } setTrips(constructed); } }