MATSIM
DepartureDelayAverageCalculator.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * DepartureDelayAverageCalculator.java
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2007, 2008 by the members listed in the COPYING, *
8  * LICENSE and WARRANTY file. *
9  * email : info at matsim dot org *
10  * *
11  * *********************************************************************** *
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * See also COPYING, LICENSE and WARRANTY file *
18  * *
19  * *********************************************************************** */
20 
21 package org.matsim.core.trafficmonitoring;
22 
23 import org.apache.logging.log4j.LogManager;
24 import org.apache.logging.log4j.Logger;
25 import org.matsim.api.core.v01.Id;
26 import org.matsim.api.core.v01.IdMap;
38 
39 import java.util.HashMap;
40 
46 class DepartureDelayAverageCalculator implements PersonDepartureEventHandler, LinkLeaveEventHandler, VehicleEntersTrafficEventHandler, VehicleLeavesTrafficEventHandler {
47 
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;
52 
53  private Vehicle2DriverEventHandler delegate = new Vehicle2DriverEventHandler();
54 
55  private static final Logger log = LogManager.getLogger(DepartureDelayAverageCalculator.class);
56 
58  // Constructor
60 
61  public DepartureDelayAverageCalculator(Network network, int timeBinSize) {
62  super();
63  this.network = network;
64  this.timeBinSize = timeBinSize;
65  this.linkData = new IdMap<>(Link.class);
66  this.resetDepartureDelays();
67  }
68 
76  public double getLinkDepartureDelay(Id<Link> linkId, double departureTime) {
77  DepartureDelayData ddd = this.getDepartureDelayRole(linkId);
78  if (ddd == null) {
79  return 0.0;
80  }
81  return ddd.getDepartureDelay(departureTime);
82  }
83 
85  // Implementation of link role
87 
88  /*package*/ class DepartureDelayData {
89  private double[] timeSum = null;
90  private int[] timeCnt = null;
91 
92  private DepartureDelayData() {
93  this.resetDepartureDelays();
94  }
95 
96  private int getTimeSlotIndex(double time) {
97  int slice = (int)(time/DepartureDelayAverageCalculator.this.timeBinSize);
98  if (slice >= timeSum.length) {
99  slice = timeSum.length - 1;
100  }
101  return slice;
102  }
103 
104  public void addDepartureDelay(double departureTime, double departureDelay) {
105  int index = getTimeSlotIndex(departureTime);
106  this.timeSum[index] += departureDelay;
107  this.timeCnt[index]++;
108  }
109 
110  public double getDepartureDelay(double time) {
111  double departureDelay = 0.0;
112 
113  try {
114  int index = getTimeSlotIndex(time);
115  double sum = 0.0;
116  sum = this.timeSum[index];
117  if (sum > 0.0) {
118  int cnt = this.timeCnt[index];
119  if (cnt > 0) {
120  departureDelay = sum / cnt;
121  }
122  }
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));
125  }
126 
127  return departureDelay;
128 
129  }
130 
131  public void resetDepartureDelays() {
132  int nofSlots = ((27*3600)/DepartureDelayAverageCalculator.this.timeBinSize); // default number of slots
133  this.timeSum = new double[nofSlots];
134  this.timeCnt = new int[nofSlots];
135  }
136 
137  }
138 
139  private DepartureDelayData getDepartureDelayRole(Id<Link> linkId) {
140  return this.linkData.get(linkId);
141  }
142 
143  @Override
144  public void handleEvent(PersonDepartureEvent event) {
145  DepartureEvent depEvent = new DepartureEvent(event.getPersonId());
146  this.departureEventsTimes.put(depEvent, event.getTime());
147  }
148 
149  @Override
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) {
156  throw new RuntimeException("departureDelay cannot be < 0.");
157  }
158  Id<Link> linkId = event.getLinkId();
159  DepartureDelayData ddd = this.getDepartureDelayRole(linkId);
160  if (ddd == null) {
161  ddd = new DepartureDelayData();
162  this.linkData.put(linkId, ddd);
163  }
164  ddd.addDepartureDelay(departureTime, departureDelay);
165  }
166  }
167 
168  public void resetDepartureDelays() {
169  this.linkData.clear();
170  this.departureEventsTimes.clear();
171  }
172 
173  @Override
174  public void reset(int iteration) {
175  resetDepartureDelays();
176  delegate.reset(iteration);
177  }
178 
179  @Override
180  public String toString() {
181  return this.getClass().getSimpleName();
182  }
183 
184  @Override
185  public void handleEvent(VehicleLeavesTrafficEvent event) {
186  delegate.handleEvent(event);
187  }
188 
189  @Override
190  public void handleEvent(VehicleEntersTrafficEvent event) {
191  delegate.handleEvent(event);
192  }
193 
194 }