21 package org.matsim.core.trafficmonitoring;
23 import org.apache.logging.log4j.LogManager;
24 import org.apache.logging.log4j.Logger;
39 import java.util.HashMap;
46 class DepartureDelayAverageCalculator
implements PersonDepartureEventHandler, LinkLeaveEventHandler, VehicleEntersTrafficEventHandler, VehicleLeavesTrafficEventHandler {
48 private Network network;
49 private int timeBinSize;
50 private HashMap<DepartureEvent, Double> departureEventsTimes =
new HashMap<DepartureEvent, Double>();
51 private final IdMap<Link, DepartureDelayData> linkData;
53 private Vehicle2DriverEventHandler delegate =
new Vehicle2DriverEventHandler();
55 private static final Logger log = LogManager.getLogger(DepartureDelayAverageCalculator.class);
61 public DepartureDelayAverageCalculator(Network network,
int timeBinSize) {
63 this.network = network;
64 this.timeBinSize = timeBinSize;
65 this.linkData =
new IdMap<>(Link.class);
66 this.resetDepartureDelays();
76 public double getLinkDepartureDelay(Id<Link> linkId,
double departureTime) {
77 DepartureDelayData ddd = this.getDepartureDelayRole(linkId);
81 return ddd.getDepartureDelay(departureTime);
88 class DepartureDelayData {
89 private double[] timeSum = null;
90 private int[] timeCnt = null;
92 private DepartureDelayData() {
93 this.resetDepartureDelays();
96 private int getTimeSlotIndex(
double time) {
97 int slice = (int)(time/DepartureDelayAverageCalculator.this.timeBinSize);
98 if (slice >= timeSum.length) {
99 slice = timeSum.length - 1;
104 public void addDepartureDelay(
double departureTime,
double departureDelay) {
105 int index = getTimeSlotIndex(departureTime);
106 this.timeSum[index] += departureDelay;
107 this.timeCnt[index]++;
110 public double getDepartureDelay(
double time) {
111 double departureDelay = 0.0;
114 int index = getTimeSlotIndex(time);
116 sum = this.timeSum[index];
118 int cnt = this.timeCnt[index];
120 departureDelay = sum / cnt;
123 }
catch (ArrayIndexOutOfBoundsException e) {
124 log.warn(
"A departure delay for an invalid value of time was requested. Returning departureDelay = 0.0. time = " + Double.toString(time));
127 return departureDelay;
131 public void resetDepartureDelays() {
132 int nofSlots = ((27*3600)/DepartureDelayAverageCalculator.this.timeBinSize);
133 this.timeSum =
new double[nofSlots];
134 this.timeCnt =
new int[nofSlots];
139 private DepartureDelayData getDepartureDelayRole(Id<Link> linkId) {
140 return this.linkData.get(linkId);
144 public void handleEvent(PersonDepartureEvent event) {
145 DepartureEvent depEvent =
new DepartureEvent(event.getPersonId());
146 this.departureEventsTimes.put(depEvent, event.getTime());
150 public void handleEvent(LinkLeaveEvent event) {
151 DepartureEvent removeMe =
new DepartureEvent(delegate.getDriverOfVehicle(event.getVehicleId()));
152 Double departureTime = departureEventsTimes.remove(removeMe);
153 if (departureTime != null) {
154 double departureDelay =
event.getTime() - departureTime.intValue();
155 if (departureDelay < 0) {
158 Id<Link> linkId =
event.getLinkId();
159 DepartureDelayData ddd = this.getDepartureDelayRole(linkId);
161 ddd =
new DepartureDelayData();
162 this.linkData.put(linkId, ddd);
164 ddd.addDepartureDelay(departureTime, departureDelay);
168 public void resetDepartureDelays() {
169 this.linkData.clear();
170 this.departureEventsTimes.clear();
174 public void reset(
int iteration) {
175 resetDepartureDelays();
176 delegate.reset(iteration);
180 public String toString() {
181 return this.getClass().getSimpleName();
185 public void handleEvent(VehicleLeavesTrafficEvent event) {
186 delegate.handleEvent(event);
190 public void handleEvent(VehicleEntersTrafficEvent event) {
191 delegate.handleEvent(event);