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  
18  
19  
20  
21  
22  
23  
24  
25  public class BusSchedule extends Route
26  {
27  
28      
29      private static final long serialVersionUID = 20170124L;
30  
31      
32      private final String line;
33  
34      
35      private final Map<String, BusStopInfo> schedule = new LinkedHashMap<>();
36  
37      
38      private final Map<String, Time> actualDeparturesBusStop = new LinkedHashMap<>();
39  
40      
41      private final Map<String, Time> actualDeparturesConflict = new LinkedHashMap<>();
42  
43      
44  
45  
46  
47  
48  
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  
59  
60  
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  
70  
71  
72  
73  
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  
86  
87  
88  
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  
98  
99  
100 
101     public final Time getDepartureTime(final String busStopId)
102     {
103         checkStop(busStopId);
104         return this.schedule.get(busStopId).getDepartureTime();
105     }
106 
107     
108 
109 
110 
111 
112     public final Duration getDwellTime(final String busStopId)
113     {
114         checkStop(busStopId);
115         return this.schedule.get(busStopId).getDwellTime();
116     }
117 
118     
119 
120 
121 
122 
123     public final boolean isForceSchedule(final String busStopId)
124     {
125         checkStop(busStopId);
126         return this.schedule.get(busStopId).isForceSchedule();
127     }
128 
129     
130 
131 
132 
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 
142 
143 
144 
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 
157 
158 
159 
160     public final Time getActualDepartureBusStop(final String busStopId)
161     {
162         return this.actualDeparturesBusStop.get(busStopId);
163     }
164 
165     
166 
167 
168 
169 
170     public final Time getActualDepartureConflict(final String conflictId)
171     {
172         return this.actualDeparturesConflict.get(conflictId);
173     }
174 
175     
176 
177 
178     public final String getLine()
179     {
180         return this.line;
181     }
182 
183     @Override
184     public final String toString()
185     {
186         return "BusSchedule [id=" + getId() + ", line=" + this.line + "]";
187     }
188 
189     
190 
191 
192 
193 
194 
195 
196 
197 
198 
199 
200     private class BusStopInfo
201     {
202 
203         
204         private final Time departureTime;
205 
206         
207         private final Duration dwellTime;
208 
209         
210         private final boolean forceSchedule;
211 
212         
213 
214 
215 
216 
217         BusStopInfo(final Time departureTime, final Duration dwellTime, final boolean forceSchedule)
218         {
219             this.departureTime = departureTime;
220             this.dwellTime = dwellTime;
221             this.forceSchedule = forceSchedule;
222         }
223 
224         
225 
226 
227         public final Time getDepartureTime()
228         {
229             return this.departureTime;
230         }
231 
232         
233 
234 
235         public final Duration getDwellTime()
236         {
237             return this.dwellTime;
238         }
239 
240         
241 
242 
243         public final boolean isForceSchedule()
244         {
245             return this.forceSchedule;
246         }
247 
248         @Override
249         public String toString()
250         {
251             return "BusStopInfo [departureTime=" + this.departureTime + ", dwellTime=" + this.dwellTime + ", forceSchedule="
252                     + this.forceSchedule + "]";
253         }
254 
255     }
256 
257 }