View Javadoc
1   package org.opentrafficsim.road.gtu.lane.tactical.pt;
2   
3   import java.util.LinkedHashMap;
4   import java.util.List;
5   import java.util.Map;
6   import java.util.Set;
7   
8   import org.djunits.value.vdouble.scalar.Duration;
9   import org.djunits.value.vdouble.scalar.Time;
10  import org.djutils.exceptions.Throw;
11  import org.opentrafficsim.core.gtu.GtuType;
12  import org.opentrafficsim.core.network.NetworkException;
13  import org.opentrafficsim.core.network.Node;
14  import org.opentrafficsim.core.network.route.Route;
15  
16  /**
17   * <p>
18   * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
19   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
20   * </p>
21   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
22   * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
23   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
24   */
25  public class BusSchedule extends Route
26  {
27  
28      /** */
29      private static final long serialVersionUID = 20170124L;
30  
31      /** Line of the bus schedule. */
32      private final String line;
33  
34      /** List of bus stops. */
35      private final Map<String, BusStopInfo> schedule = new LinkedHashMap<>();
36  
37      /** Map of actual departures stored per bus stop. */
38      private final Map<String, Time> actualDeparturesBusStop = new LinkedHashMap<>();
39  
40      /** Map of actual departures stored per conflict. */
41      private final Map<String, Time> actualDeparturesConflict = new LinkedHashMap<>();
42  
43      /**
44       * @param id String; id
45       * @param gtuType GtuType; the GtuType for which this is a route
46       * @param nodes List&lt;Node&gt;; nodes
47       * @param line String; line of the bus schedule
48       * @throws NetworkException if intermediate nodes are missing in the route.
49       */
50      public BusSchedule(final String id, final GtuType gtuType, final List<Node> nodes, final String line)
51              throws NetworkException
52      {
53          super(id, gtuType, nodes);
54          this.line = line;
55      }
56  
57      /**
58       * @param id String; id
59       * @param gtuType GtuType; the GtuType for which this is a route
60       * @param line String; line of the bus schedule
61       */
62      public BusSchedule(final String id, final GtuType gtuType, final String line)
63      {
64          super(id, gtuType);
65          this.line = line;
66      }
67  
68      /**
69       * Adds a stop to the schedule.
70       * @param busStopId String; bus stop id
71       * @param departureTime Time; departure time
72       * @param dwellTime Duration; dwell time
73       * @param forceSchedule boolean; whether to wait until departure time
74       */
75      public final void addBusStop(final String busStopId, final Time departureTime, final Duration dwellTime,
76              final boolean forceSchedule)
77      {
78          Throw.whenNull(busStopId, "Bus stop id may not be null.");
79          Throw.whenNull(departureTime, "Departure time may not be null.");
80          Throw.whenNull(dwellTime, "Dwell time may not be null.");
81          this.schedule.put(busStopId, new BusStopInfo(departureTime, dwellTime, forceSchedule));
82      }
83  
84      /**
85       * Whether the bus of this line should stop for this bus stop. False if not the correct line, or already stopped.
86       * @param busStopId String; id of bus stop
87       * @param time Time; time to check
88       * @return whether the bus of this line should stop for this bus stop
89       */
90      public final boolean isLineStop(final String busStopId, final Time time)
91      {
92          return this.schedule.containsKey(busStopId) && (!this.actualDeparturesConflict.containsKey(busStopId)
93                  || time.lt(this.actualDeparturesConflict.get(busStopId)));
94      }
95  
96      /**
97       * Returns departure time for the given bus stop.
98       * @param busStopId String; id of bus stop
99       * @return departure time for the given bus stop
100      */
101     public final Time getDepartureTime(final String busStopId)
102     {
103         checkStop(busStopId);
104         return this.schedule.get(busStopId).getDepartureTime();
105     }
106 
107     /**
108      * Returns dwell time for the given bus stop.
109      * @param busStopId String; id of bus stop
110      * @return dwell time for the given bus stop
111      */
112     public final Duration getDwellTime(final String busStopId)
113     {
114         checkStop(busStopId);
115         return this.schedule.get(busStopId).getDwellTime();
116     }
117 
118     /**
119      * Returns whether the departure time is enforced.
120      * @param busStopId String; id of bus stop
121      * @return whether the departure time is enforced
122      */
123     public final boolean isForceSchedule(final String busStopId)
124     {
125         checkStop(busStopId);
126         return this.schedule.get(busStopId).isForceSchedule();
127     }
128 
129     /**
130      * Throws exception when the bus stop is not part of this schedule.
131      * @param busStopId String; id of bus stop
132      * @throws IllegalArgumentException if the bus stop is not part of this schedule
133      */
134     private void checkStop(final String busStopId)
135     {
136         Throw.when(!this.schedule.containsKey(busStopId), IllegalArgumentException.class, "Bus stop %s is not for schedule %s.",
137                 busStopId, this);
138     }
139 
140     /**
141      * Set actual departure time.
142      * @param busStopId String; bus stop id
143      * @param conflictIds Set&lt;String&gt;; conflicts downstream of the bus stop
144      * @param time Time; actual departure time
145      */
146     public final void setActualDeparture(final String busStopId, final Set<String> conflictIds, final Time time)
147     {
148         this.actualDeparturesBusStop.put(busStopId, time);
149         for (String conflictId : conflictIds)
150         {
151             this.actualDeparturesConflict.put(conflictId, time);
152         }
153     }
154 
155     /**
156      * Return the actual departure time.
157      * @param busStopId String; bus stop id
158      * @return actual departure time, {@code null} if not given
159      */
160     public final Time getActualDepartureBusStop(final String busStopId)
161     {
162         return this.actualDeparturesBusStop.get(busStopId);
163     }
164 
165     /**
166      * Return the actual departure time.
167      * @param conflictId String; conflict id
168      * @return actual departure time, {@code null} if not given
169      */
170     public final Time getActualDepartureConflict(final String conflictId)
171     {
172         return this.actualDeparturesConflict.get(conflictId);
173     }
174 
175     /**
176      * @return line.
177      */
178     public final String getLine()
179     {
180         return this.line;
181     }
182 
183     /** {@inheritDoc} */
184     @Override
185     public final String toString()
186     {
187         return "BusSchedule [id=" + getId() + ", line=" + this.line + "]";
188     }
189 
190     /**
191      * Class to contain info regarding a stop in the schedule.
192      * <p>
193      * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
194      * <br>
195      * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
196      * </p>
197      * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
198      * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
199      * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
200      */
201     private class BusStopInfo
202     {
203 
204         /** Departure time. */
205         private final Time departureTime;
206 
207         /** Dwell time. */
208         private final Duration dwellTime;
209 
210         /** Whether to wait until departure time. */
211         private final boolean forceSchedule;
212 
213         /**
214          * @param departureTime Time; departure time
215          * @param dwellTime Duration; dwell time
216          * @param forceSchedule boolean; whether to wait until departure time
217          */
218         BusStopInfo(final Time departureTime, final Duration dwellTime, final boolean forceSchedule)
219         {
220             this.departureTime = departureTime;
221             this.dwellTime = dwellTime;
222             this.forceSchedule = forceSchedule;
223         }
224 
225         /**
226          * @return departureTime.
227          */
228         public final Time getDepartureTime()
229         {
230             return this.departureTime;
231         }
232 
233         /**
234          * @return dwellTime.
235          */
236         public final Duration getDwellTime()
237         {
238             return this.dwellTime;
239         }
240 
241         /**
242          * @return forceSchedule.
243          */
244         public final boolean isForceSchedule()
245         {
246             return this.forceSchedule;
247         }
248 
249         /** {@inheritDoc} */
250         @Override
251         public String toString()
252         {
253             return "BusStopInfo [departureTime=" + this.departureTime + ", dwellTime=" + this.dwellTime + ", forceSchedule="
254                     + this.forceSchedule + "]";
255         }
256 
257     }
258 
259 }