1 package org.opentrafficsim.road.gtu.generator.od;
2
3 import java.util.HashMap;
4 import java.util.Map;
5
6 import org.djunits.value.vdouble.scalar.Frequency;
7 import org.djunits.value.vdouble.scalar.Length;
8 import org.djutils.exceptions.Throw;
9 import org.opentrafficsim.core.gtu.GTUType;
10 import org.opentrafficsim.core.idgenerator.IdGenerator;
11 import org.opentrafficsim.core.network.LinkType;
12 import org.opentrafficsim.core.network.Node;
13 import org.opentrafficsim.road.gtu.generator.CFBARoomChecker;
14 import org.opentrafficsim.road.gtu.generator.GeneratorPositions.LaneBias;
15 import org.opentrafficsim.road.gtu.generator.GeneratorPositions.LaneBiases;
16 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
17 import org.opentrafficsim.road.gtu.generator.MarkovCorrelation;
18 import org.opentrafficsim.road.gtu.generator.headway.ArrivalsHeadwayGenerator.HeadwayDistribution;
19 import org.opentrafficsim.road.network.lane.Lane;
20
21 /**
22 * Options for vehicle generation based on an OD matrix.
23 * <p>
24 * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
25 * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
26 * <p>
27 * @version $Revision$, $LastChangedDate$, by $Author$, initial version 6 dec. 2017 <br>
28 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
29 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
30 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
31 */
32 public class ODOptions
33 {
34
35 /** Headway randomization option. */
36 public static final Option<HeadwayDistribution> HEADWAY_DIST =
37 new Option<>("headway distribution", HeadwayDistribution.EXPONENTIAL);
38
39 /** ID generator option. */
40 public static final Option<IdGenerator> GTU_ID = new Option<>("gtu id", new IdGenerator(""));
41
42 /** GTU characteristics generator option. */
43 public static final Option<GTUCharacteristicsGeneratorOD> GTU_TYPE =
44 new Option<>("gtu type", new DefaultGTUCharacteristicsGeneratorOD());
45
46 /** Room checker option. */
47 public static final Option<RoomChecker> ROOM_CHECKER = new Option<>("room checker", new CFBARoomChecker());
48
49 /** Markov chain for GTU type option. */
50 public static final Option<MarkovCorrelation<GTUType, Frequency>> MARKOV = new Option<>("markov", null);
51
52 /** Lane bias. Default is Truck: truck right (strong right, max 2 lanes), Vehicle (other): weak left. */
53 public static final Option<LaneBiases> LANE_BIAS = new Option<>("lane bias",
54 new LaneBiases().addBias(GTUType.TRUCK, LaneBias.TRUCK_RIGHT).addBias(GTUType.VEHICLE, LaneBias.WEAK_LEFT));
55
56 /** Initial distance over which lane changes shouldn't be performed option. */
57 public static final Option<Length> NO_LC_DIST = new Option<>("no lc distance", null);
58
59 /** Options overall. */
60 private OptionSet<Void> options = new OptionSet<>();
61
62 /** Options per lane. */
63 private OptionSet<Lane> laneOptions = new OptionSet<>();
64
65 /** Options per node. */
66 private OptionSet<Node> nodeOptions = new OptionSet<>();
67
68 /** Options per road type. */
69 private OptionSet<LinkType> linkTypeOptions = new OptionSet<>();
70
71 /**
72 * Set option value.
73 * @param option Option<K>; option
74 * @param value K; option value
75 * @param <K> value type
76 * @return this option set
77 */
78 public final <K> ODOptions set(final Option<K> option, final K value)
79 {
80 this.options.set(null, option, value);
81 return this;
82 }
83
84 /**
85 * Set option value for lane.
86 * @param lane Lane; lane
87 * @param option Option<K>; option
88 * @param value K; option value
89 * @param <K> value type
90 * @return this option set
91 */
92 public final <K> ODOptions set(final Lane lane, final Option<K> option, final K value)
93 {
94 this.laneOptions.set(lane, option, value);
95 return this;
96 }
97
98 /**
99 * Set option value for node.
100 * @param node Node; node
101 * @param option Option<K>; option
102 * @param value K; option value
103 * @param <K> value type
104 * @return this option set
105 */
106 public final <K> ODOptions set(final Node node, final Option<K> option, final K value)
107 {
108 this.nodeOptions.set(node, option, value);
109 return this;
110 }
111
112 /**
113 * Set option value for link type.
114 * @param linkType LinkType; link type
115 * @param option Option<K>; option
116 * @param value K; option value
117 * @param <K> value type
118 * @return this option set
119 */
120 public final <K> ODOptions set(final LinkType linkType, final Option<K> option, final K value)
121 {
122 this.linkTypeOptions.set(linkType, option, value);
123 return this;
124 }
125
126 /**
127 * Get option value. If a value is specified for a specific category, it is returned. The following order is used:
128 * <ul>
129 * <li>{@code Lane}</li>
130 * <li>{@code Node} (origin)</li>
131 * <li>{@code LinkType}</li>
132 * <li>None (global option value)</li>
133 * <li>Default option value</li>
134 * </ul>
135 * @param option Option<K>; option
136 * @param lane Lane; lane to obtain specific option value, may be null
137 * @param node Node; node to obtain specific option value, may be null
138 * @param linkType LinkType; link type to obtain specific option value, may be null
139 * @param <K> value type
140 * @return K; option value
141 */
142 public final <K> K get(final Option<K> option, final Lane lane, final Node node, final LinkType linkType)
143 {
144 Throw.whenNull(option, "Option may not be null.");
145 K value = this.laneOptions.get(lane, option);
146 if (value != null)
147 {
148 return value;
149 }
150 value = this.nodeOptions.get(node, option);
151 if (value != null)
152 {
153 return value;
154 }
155 value = this.linkTypeOptions.get(linkType, option);
156 if (value != null)
157 {
158 return value;
159 }
160 value = this.options.get(null, option);
161 if (value != null)
162 {
163 return value;
164 }
165 return option.getDefaultValue();
166 }
167
168 /**
169 * Utility class to store options.
170 * <p>
171 * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
172 * <br>
173 * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
174 * <p>
175 * @version $Revision$, $LastChangedDate$, by $Author$, initial version 6 dec. 2017 <br>
176 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
177 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
178 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
179 * @param <K> option value type
180 */
181 private static final class Option<K>
182 {
183
184 /** Id. */
185 private final String id;
186
187 /** Default value. */
188 private final K defaultValue;
189
190 /**
191 * Constructor.
192 * @param id String; id
193 * @param defaultValue K; default value
194 */
195 Option(final String id, final K defaultValue)
196 {
197 this.id = id;
198 this.defaultValue = defaultValue;
199 }
200
201 /**
202 * Returns the default value.
203 * @return default value
204 */
205 public K getDefaultValue()
206 {
207 return this.defaultValue;
208 }
209
210 /** {@inheritDoc} */
211 @Override
212 public int hashCode()
213 {
214 final int prime = 31;
215 int result = 1;
216 result = prime * result + ((this.id == null) ? 0 : this.id.hashCode());
217 return result;
218 }
219
220 /** {@inheritDoc} */
221 @Override
222 public boolean equals(final Object obj)
223 {
224 if (this == obj)
225 {
226 return true;
227 }
228 if (obj == null)
229 {
230 return false;
231 }
232 if (getClass() != obj.getClass())
233 {
234 return false;
235 }
236 Option<?> other = (Option<?>) obj;
237 if (this.id == null)
238 {
239 if (other.id != null)
240 {
241 return false;
242 }
243 }
244 else if (!this.id.equals(other.id))
245 {
246 return false;
247 }
248 return true;
249 }
250
251 /** {@inheritDoc} */
252 @Override
253 public String toString()
254 {
255 return "Option [id=" + this.id + "]";
256 }
257
258 }
259
260 /**
261 * Single set of options for a certain category, i.e. lane, node, link type or null (i.e. global).
262 * <p>
263 * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
264 * <br>
265 * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
266 * <p>
267 * @version $Revision$, $LastChangedDate$, by $Author$, initial version 11 jan. 2018 <br>
268 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
269 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
270 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
271 * @param <C> category type, i.e. {@code Lane}, {@code Node}, {@code LinkType} or {@code Void} (i.e. global).
272 */
273 private class OptionSet<C>
274 {
275
276 /** Options. */
277 private Map<C, Map<Option<?>, Object>> optionsSet = new HashMap<>();
278
279 /**
280 * Constructor.
281 */
282 OptionSet()
283 {
284 //
285 }
286
287 /**
288 * Set value in option set.
289 * @param category C; category
290 * @param option Option<K>; option
291 * @param value K; value
292 * @param <K> option value type
293 */
294 public <K> void set(final C category, final Option<K> option, final K value)
295 {
296 Map<Option<?>, Object> map = this.optionsSet.get(category);
297 if (map == null)
298 {
299 map = new HashMap<>();
300 this.optionsSet.put(category, map);
301 }
302 map.put(option, value);
303 }
304
305 /**
306 * Returns the option value for the category.
307 * @param category C; category
308 * @param option Option<K>; option
309 * @return option value for the category
310 * @param <K> value type
311 */
312 @SuppressWarnings("unchecked")
313 public <K> K get(final C category, final Option<K> option)
314 {
315 if (!this.optionsSet.containsKey(category))
316 {
317 return null;
318 }
319 return (K) this.optionsSet.get(category).get(option);
320 }
321
322 }
323
324 }