1 package org.opentrafficsim.demo.conflict;
2
3 import java.net.URL;
4 import java.rmi.RemoteException;
5 import java.util.ArrayList;
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Set;
11
12 import javax.naming.NamingException;
13 import javax.swing.SwingUtilities;
14
15 import org.djunits.unit.AccelerationUnit;
16 import org.djunits.unit.FrequencyUnit;
17 import org.djunits.unit.LengthUnit;
18 import org.djunits.unit.SpeedUnit;
19 import org.djunits.unit.TimeUnit;
20 import org.djunits.value.vdouble.scalar.Acceleration;
21 import org.djunits.value.vdouble.scalar.Duration;
22 import org.djunits.value.vdouble.scalar.Frequency;
23 import org.djunits.value.vdouble.scalar.Length;
24 import org.djunits.value.vdouble.scalar.Speed;
25 import org.djunits.value.vdouble.scalar.Time;
26 import org.opentrafficsim.base.modelproperties.Property;
27 import org.opentrafficsim.base.modelproperties.PropertyException;
28 import org.opentrafficsim.core.distributions.Generator;
29 import org.opentrafficsim.core.distributions.ProbabilityException;
30 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
31 import org.opentrafficsim.core.dsol.OTSModelInterface;
32 import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
33 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
34 import org.opentrafficsim.core.gtu.GTUCharacteristics;
35 import org.opentrafficsim.core.gtu.GTUDirectionality;
36 import org.opentrafficsim.core.gtu.GTUException;
37 import org.opentrafficsim.core.gtu.GTUType;
38 import org.opentrafficsim.core.gtu.animation.GTUColorer;
39 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
40 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristicsFactory;
41 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException;
42 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterTypes;
43 import org.opentrafficsim.core.idgenerator.IdGenerator;
44 import org.opentrafficsim.core.network.Node;
45 import org.opentrafficsim.core.network.OTSLink;
46 import org.opentrafficsim.core.network.OTSNetwork;
47 import org.opentrafficsim.core.network.route.Route;
48 import org.opentrafficsim.road.animation.AnimationToggles;
49 import org.opentrafficsim.road.gtu.animation.DefaultSwitchableGTUColorer;
50 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
51 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
52 import org.opentrafficsim.road.gtu.generator.TTCRoomChecker;
53 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
54 import org.opentrafficsim.road.gtu.lane.LaneBasedGTUCharacteristics;
55 import org.opentrafficsim.road.gtu.lane.LaneBasedGTUCharacteristicsGenerator;
56 import org.opentrafficsim.road.gtu.lane.RoadGTUTypes;
57 import org.opentrafficsim.road.gtu.lane.perception.categories.DirectBusStopPerception;
58 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedTacticalPlannerFactory;
59 import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
60 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlus;
61 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationBusStop;
62 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
63 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveBusStop;
64 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRS;
65 import org.opentrafficsim.road.gtu.lane.tactical.pt.BusSchedule;
66 import org.opentrafficsim.road.gtu.lane.tactical.util.ConflictUtil;
67 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
68 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
69 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
70 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
71 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
72 import org.opentrafficsim.road.network.factory.xml.XmlNetworkLaneParser;
73 import org.opentrafficsim.road.network.lane.CrossSectionLink;
74 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
75 import org.opentrafficsim.road.network.lane.Lane;
76 import org.opentrafficsim.road.network.lane.conflict.ConflictBuilder;
77 import org.opentrafficsim.road.network.lane.object.BusStop;
78 import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
79 import org.opentrafficsim.simulationengine.OTSSimulationException;
80
81 import nl.tudelft.simulation.dsol.SimRuntimeException;
82 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
83 import nl.tudelft.simulation.jstats.streams.MersenneTwister;
84 import nl.tudelft.simulation.jstats.streams.StreamInterface;
85 import nl.tudelft.simulation.language.io.URLResource;
86
87
88
89
90
91
92
93
94
95
96
97 public class BusStreetDemo extends AbstractWrappableAnimation
98 {
99
100
101 private static final long serialVersionUID = 20161211L;
102
103
104 @Override
105 protected final OTSModelInterface makeModel(final GTUColorer colorer) throws OTSSimulationException
106 {
107 return new BusStreetModel();
108 }
109
110
111 @Override
112 protected final void addAnimationToggles()
113 {
114 AnimationToggles.setTextAnimationTogglesFull(this);
115 this.hideAnimationClass(OTSLink.class);
116 }
117
118
119 @Override
120 public final String shortName()
121 {
122 return "Bus street demonstration";
123 }
124
125
126 @Override
127 public final String description()
128 {
129 return "Bus street demonstration";
130 }
131
132
133
134
135 class BusStreetModel implements OTSModelInterface
136 {
137
138
139 private static final long serialVersionUID = 20161211L;
140
141
142 private OTSNetwork network;
143
144
145 private OTSDEVSSimulatorInterface simulator;
146
147
148 private GTUColorer gtuColorer;
149
150
151 @Override
152 public void constructModel(final SimulatorInterface<Time, Duration, OTSSimTimeDouble> arg0)
153 throws SimRuntimeException, RemoteException
154 {
155 this.gtuColorer = new DefaultSwitchableGTUColorer();
156 this.simulator = (OTSDEVSSimulatorInterface) arg0;
157 Map<String, StreamInterface> streams = new HashMap<>();
158 streams.put("generation", new MersenneTwister(100L));
159 this.simulator.getReplication().setStreams(streams);
160 try
161 {
162 URL url = URLResource.getResource("/conflict/BusStreet.xml");
163 XmlNetworkLaneParser nlp = new XmlNetworkLaneParser(this.simulator);
164 this.network = nlp.build(url);
165 ConflictBuilder.buildConflicts(this.network, GTUType.ALL, this.simulator,
166 new ConflictBuilder.FixedWidthGenerator(new Length(2.0, LengthUnit.SI)));
167
168
169 Lane lane = ((CrossSectionLink) this.network.getLink("B1B2")).getLanes().get(0);
170 BusStop stop = new BusStop("Cafe Boszicht.1", lane, lane.getLength(), "Cafe Boszicht", this.simulator);
171 Set<String> lines1 = new HashSet<>();
172 lines1.add("1");
173 stop.setLines(lines1);
174
175 lane = ((CrossSectionLink) this.network.getLink("C1C2")).getLanes().get(0);
176 stop = new BusStop("Cafe Boszicht.2", lane, lane.getLength(), "Cafe Boszicht", this.simulator);
177 Set<String> lines2 = new HashSet<>();
178 lines2.add("2");
179 stop.setLines(lines2);
180
181 lane = ((CrossSectionLink) this.network.getLink("EF")).getLanes().get(0);
182 stop = new BusStop("Herberg De Deugd", lane, new Length(75.0, LengthUnit.SI), "Herberg De Deugd",
183 this.simulator);
184 stop.setLines(lines1);
185
186 lane = ((CrossSectionLink) this.network.getLink("FG")).getLanes().get(1);
187 stop = new BusStop("De Vleeshoeve", lane, new Length(75.0, LengthUnit.SI), "De Vleeshoeve", this.simulator);
188 Set<String> lines12 = new HashSet<>();
189 lines12.add("1");
190 lines12.add("2");
191 stop.setLines(lines12);
192
193 lane = ((CrossSectionLink) this.network.getLink("GH")).getLanes().get(2);
194 stop = new BusStop("Kippenboerderij De Scharrelaar", lane, new Length(50.0, LengthUnit.SI),
195 "Kippenboerderij De Scharrelaar", this.simulator);
196 stop.setLines(lines2);
197
198 lane = ((CrossSectionLink) this.network.getLink("I1I2")).getLanes().get(0);
199 stop = new BusStop("Dorpshuys", lane, lane.getLength(), "Dorpshuys", this.simulator);
200 stop.setLines(lines1);
201
202 lane = ((CrossSectionLink) this.network.getLink("K1K2")).getLanes().get(0);
203 stop = new BusStop("De verkeerde afslag", lane, lane.getLength(), "De verkeerde afslag", this.simulator);
204 stop.setLines(lines12);
205
206 makeGenerator();
207
208 }
209 catch (Exception exception)
210 {
211 exception.printStackTrace();
212 }
213 }
214
215
216 @Override
217 public SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
218 {
219 return this.simulator;
220 }
221
222
223 @Override
224 public OTSNetwork getNetwork()
225 {
226 return this.network;
227 }
228
229
230
231
232
233
234
235
236 private void makeGenerator() throws GTUException, SimRuntimeException, ProbabilityException, ParameterException
237 {
238 Lane lane = ((CrossSectionLink) this.network.getLink("AB")).getLanes().get(0);
239 String id = lane.getId();
240 Set<DirectedLanePosition> initialLongitudinalPositions = new HashSet<>();
241 initialLongitudinalPositions
242 .add(new DirectedLanePosition(lane, new Length(10.0, LengthUnit.SI), GTUDirectionality.DIR_PLUS));
243 Generator<Duration> headwayGenerator =
244 new HeadwayGenerator(new Frequency(800, FrequencyUnit.PER_HOUR), this.simulator);
245 LaneBasedGTUCharacteristicsGenerator characteristicsGenerator = new CharacteristicsGenerator(this.simulator,
246 new double[] { 0.9, 0.06, 0.04 }, initialLongitudinalPositions, this.network);
247 RoomChecker roomChecker = new TTCRoomChecker(new Duration(10.0, TimeUnit.SI));
248 new LaneBasedGTUGenerator(id, headwayGenerator, Long.MAX_VALUE, Time.ZERO, new Time(Double.MAX_VALUE, TimeUnit.SI),
249 this.gtuColorer, characteristicsGenerator, initialLongitudinalPositions, this.network, roomChecker);
250 }
251
252 }
253
254
255
256
257
258
259 public static void main(final String[] args) throws SimRuntimeException
260 {
261 SwingUtilities.invokeLater(new Runnable()
262 {
263 @Override
264 public void run()
265 {
266 try
267 {
268 BusStreetDemo animation = new BusStreetDemo();
269
270 animation.buildAnimator(Time.ZERO, Duration.ZERO, new Duration(60.0, TimeUnit.MINUTE),
271 new ArrayList<Property<?>>(), null, true);
272
273 }
274 catch (SimRuntimeException | NamingException | OTSSimulationException | PropertyException exception)
275 {
276 exception.printStackTrace();
277 }
278 }
279 });
280 }
281
282
283
284
285
286
287
288
289
290
291
292
293 private class HeadwayGenerator implements Generator<Duration>
294 {
295
296
297 private final Frequency demand;
298
299
300 private final OTSSimulatorInterface simulator;
301
302
303
304
305
306 HeadwayGenerator(final Frequency demand, final OTSSimulatorInterface simulator)
307 {
308 this.demand = demand;
309 this.simulator = simulator;
310 }
311
312
313 @Override
314 public Duration draw() throws ProbabilityException, ParameterException
315 {
316 try
317 {
318 return new Duration(
319 -Math.log(this.simulator.getReplication().getStream("generation").nextDouble()) / this.demand.si,
320 TimeUnit.SI);
321 }
322 catch (RemoteException exception)
323 {
324 throw new ProbabilityException("Could not draw for Probability.", exception);
325 }
326 }
327
328 }
329
330
331
332
333
334
335
336
337
338
339
340
341 public class CharacteristicsGenerator implements LaneBasedGTUCharacteristicsGenerator
342 {
343
344
345 private final OTSDEVSSimulatorInterface simulator;
346
347
348 private final double[] probabilities;
349
350
351 private final Set<DirectedLanePosition> initialLongitudinalPositions;
352
353
354 private final OTSNetwork network;
355
356
357 private final IdGenerator idGenerator = new IdGenerator("");
358
359
360 private final LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> plannerFactory;
361
362
363 private final Route carRouteN;
364
365
366 private final Route carRouteO;
367
368
369 private final List<Node> busNodes1;
370
371
372 private final List<Node> busNodes2;
373
374
375 private final Duration shortDwellTime = new Duration(15.0, TimeUnit.SI);
376
377
378 private final Duration longDwellTime = new Duration(60.0, TimeUnit.SI);
379
380
381
382
383
384
385
386 public CharacteristicsGenerator(final OTSDEVSSimulatorInterface simulator, final double[] probabilities,
387 final Set<DirectedLanePosition> initialLongitudinalPositions, final OTSNetwork network)
388 {
389 this.simulator = simulator;
390 this.probabilities = probabilities;
391 this.initialLongitudinalPositions = initialLongitudinalPositions;
392 this.network = network;
393 List<Node> carNodesN = new ArrayList<>();
394 carNodesN.add(network.getNode("A"));
395 carNodesN.add(network.getNode("B"));
396 carNodesN.add(network.getNode("C"));
397 carNodesN.add(network.getNode("D"));
398 carNodesN.add(network.getNode("E"));
399 carNodesN.add(network.getNode("F"));
400 carNodesN.add(network.getNode("G"));
401 carNodesN.add(network.getNode("H"));
402 carNodesN.add(network.getNode("I"));
403 carNodesN.add(network.getNode("J"));
404 carNodesN.add(network.getNode("K"));
405 carNodesN.add(network.getNode("L"));
406 carNodesN.add(network.getNode("M"));
407 List<Node> carNodesO = new ArrayList<>(carNodesN);
408 carNodesN.add(network.getNode("N"));
409 carNodesO.add(network.getNode("O"));
410 this.carRouteN = new Route("carN", carNodesN);
411 this.carRouteO = new Route("carO", carNodesO);
412 this.busNodes1 = new ArrayList<>();
413 this.busNodes1.add(network.getNode("A"));
414 this.busNodes1.add(network.getNode("B"));
415 this.busNodes1.add(network.getNode("B1"));
416 this.busNodes1.add(network.getNode("B2"));
417 this.busNodes1.add(network.getNode("D"));
418 this.busNodes1.add(network.getNode("E"));
419 this.busNodes1.add(network.getNode("F"));
420 this.busNodes1.add(network.getNode("G"));
421 this.busNodes1.add(network.getNode("H"));
422 this.busNodes1.add(network.getNode("I"));
423 this.busNodes1.add(network.getNode("I1"));
424 this.busNodes1.add(network.getNode("I2"));
425 this.busNodes1.add(network.getNode("J"));
426 this.busNodes1.add(network.getNode("K"));
427 this.busNodes1.add(network.getNode("K1"));
428 this.busNodes1.add(network.getNode("K2"));
429 this.busNodes1.add(network.getNode("L"));
430 this.busNodes1.add(network.getNode("M"));
431 this.busNodes1.add(network.getNode("N"));
432
433 this.busNodes2 = new ArrayList<>();
434 this.busNodes2.add(network.getNode("A"));
435 this.busNodes2.add(network.getNode("B"));
436 this.busNodes2.add(network.getNode("C"));
437 this.busNodes2.add(network.getNode("C1"));
438 this.busNodes2.add(network.getNode("C2"));
439 this.busNodes2.add(network.getNode("E"));
440 this.busNodes2.add(network.getNode("F"));
441 this.busNodes2.add(network.getNode("G"));
442 this.busNodes2.add(network.getNode("H"));
443 this.busNodes2.add(network.getNode("I"));
444 this.busNodes2.add(network.getNode("J"));
445 this.busNodes2.add(network.getNode("K"));
446 this.busNodes2.add(network.getNode("K1"));
447 this.busNodes2.add(network.getNode("K2"));
448 this.busNodes2.add(network.getNode("K3"));
449 this.busNodes2.add(network.getNode("L"));
450 this.busNodes2.add(network.getNode("M"));
451 this.busNodes2.add(network.getNode("O"));
452
453 this.plannerFactory = new LaneBasedStrategicalRoutePlannerFactory(new LMRSFactoryCarBus(),
454 new BehavioralCharacteristicsFactoryCarBus());
455 }
456
457
458 @Override
459 public LaneBasedGTUCharacteristics draw() throws ProbabilityException, ParameterException, GTUException
460 {
461
462 double r = this.simulator.getReplication().getStream("generation").nextDouble();
463 int classNum = r < this.probabilities[0] ? 0 : r < this.probabilities[0] + this.probabilities[1] ? 1 : 2;
464 r = this.simulator.getReplication().getStream("generation").nextDouble();
465 GTUType gtuType;
466 Length length;
467 Length width;
468 Speed maximumSpeed;
469 Route route;
470 switch (classNum)
471 {
472 case 0:
473 {
474 gtuType = new GTUType("CAR", RoadGTUTypes.CAR);
475 length = new Length(4.0, LengthUnit.SI);
476 width = new Length(1.8, LengthUnit.SI);
477 maximumSpeed = new Speed(200.0, SpeedUnit.KM_PER_HOUR);
478 route = r < 0.5 ? this.carRouteN : this.carRouteO;
479 break;
480 }
481 case 1:
482 {
483 gtuType = new GTUType("BUS1", RoadGTUTypes.SCHEDULED_BUS);
484 length = new Length(8.0, LengthUnit.SI);
485 width = new Length(2.0, LengthUnit.SI);
486 maximumSpeed = new Speed(100.0, SpeedUnit.KM_PER_HOUR);
487 BusSchedule schedule =
488 new BusSchedule("bus1." + this.simulator.getSimulatorTime().getTime(), this.busNodes1, "1");
489 Time now = this.simulator.getSimulatorTime().getTime();
490 schedule.addBusStop("Cafe Boszicht.1", now.plus(new Duration(70.0, TimeUnit.SI)), this.longDwellTime, true);
491 schedule.addBusStop("Herberg De Deugd", now.plus(new Duration(100.0, TimeUnit.SI)), this.shortDwellTime,
492 false);
493 schedule.addBusStop("De Vleeshoeve", now.plus(new Duration(120.0, TimeUnit.SI)), this.shortDwellTime,
494 false);
495 schedule.addBusStop("Dorpshuys", now.plus(new Duration(200.0, TimeUnit.SI)), this.longDwellTime, true);
496 schedule.addBusStop("De verkeerde afslag", now.plus(new Duration(270.0, TimeUnit.SI)), this.longDwellTime,
497 true);
498 route = schedule;
499 break;
500 }
501 case 2:
502 {
503 gtuType = new GTUType("BUS2", RoadGTUTypes.SCHEDULED_BUS);
504 length = new Length(12.0, LengthUnit.SI);
505 width = new Length(2.0, LengthUnit.SI);
506 maximumSpeed = new Speed(100.0, SpeedUnit.KM_PER_HOUR);
507 BusSchedule schedule =
508 new BusSchedule("bus2." + this.simulator.getSimulatorTime().getTime(), this.busNodes2, "2");
509 Time now = this.simulator.getSimulatorTime().getTime();
510 schedule.addBusStop("Cafe Boszicht.2", now.plus(new Duration(80.0, TimeUnit.SI)), this.longDwellTime, true);
511 schedule.addBusStop("De Vleeshoeve", now.plus(new Duration(110.0, TimeUnit.SI)), this.shortDwellTime,
512 false);
513 schedule.addBusStop("Kippenboerderij De Scharrelaar", now.plus(new Duration(180.0, TimeUnit.SI)),
514 this.longDwellTime, false);
515 schedule.addBusStop("De verkeerde afslag", now.plus(new Duration(260.0, TimeUnit.SI)), this.longDwellTime,
516 true);
517 route = schedule;
518 break;
519 }
520 default:
521 throw new RuntimeException("Reaching default of switch case.");
522 }
523
524 GTUCharacteristics gtuCharacteristics = new GTUCharacteristics(gtuType, this.idGenerator, length, width,
525 maximumSpeed, this.simulator, this.network);
526
527 return new LaneBasedGTUCharacteristics(gtuCharacteristics, this.plannerFactory, route,
528 new Speed(50.0, SpeedUnit.KM_PER_HOUR), this.initialLongitudinalPositions);
529 }
530
531
532 @Override
533 public OTSDEVSSimulatorInterface getSimulator() throws ProbabilityException
534 {
535 return this.simulator;
536 }
537
538 }
539
540
541
542
543
544
545
546
547
548
549
550
551 private class LMRSFactoryCarBus implements LaneBasedTacticalPlannerFactory<LMRS>
552 {
553
554
555 LMRSFactoryCarBus()
556 {
557 }
558
559
560 @Override
561 public final BehavioralCharacteristics getDefaultBehavioralCharacteristics()
562 {
563 BehavioralCharacteristics behavioralCharacteristics = new BehavioralCharacteristics();
564 behavioralCharacteristics.setDefaultParameters(ParameterTypes.class);
565 behavioralCharacteristics.setDefaultParameters(LmrsParameters.class);
566 behavioralCharacteristics.setDefaultParameters(ConflictUtil.class);
567 behavioralCharacteristics.setDefaultParameters(AbstractIDM.class);
568 return behavioralCharacteristics;
569 }
570
571
572 @Override
573 public final LMRS create(final LaneBasedGTU gtu) throws GTUException
574 {
575 DefaultLMRSPerceptionFactory pFac = new DefaultLMRSPerceptionFactory();
576 LMRS lmrs = new LMRS(new IDMPlus(), gtu, pFac.generatePerception(gtu), Synchronization.PASSIVE);
577 lmrs.setDefaultIncentives();
578 if (gtu.getGTUType().isOfType(RoadGTUTypes.SCHEDULED_BUS))
579 {
580 lmrs.addMandatoryIncentive(new IncentiveBusStop());
581 lmrs.addAccelerationIncentive(new AccelerationBusStop());
582 lmrs.getPerception().addPerceptionCategory(new DirectBusStopPerception(lmrs.getPerception()));
583 }
584 return lmrs;
585 }
586
587 }
588
589
590
591
592
593
594
595
596
597
598
599
600 private class BehavioralCharacteristicsFactoryCarBus implements BehavioralCharacteristicsFactory
601 {
602
603
604 BehavioralCharacteristicsFactoryCarBus()
605 {
606 }
607
608
609 @Override
610 public void setValues(final BehavioralCharacteristics defaultCharacteristics, final GTUType gtuType)
611 throws ParameterException
612 {
613
614 defaultCharacteristics.setParameter(ParameterTypes.LOOKAHEAD, new Length(100.0, LengthUnit.METER));
615 if (gtuType.isOfType(RoadGTUTypes.CAR))
616 {
617 defaultCharacteristics.setParameter(LmrsParameters.VGAIN, new Speed(3.0, SpeedUnit.METER_PER_SECOND));
618 }
619 else if (gtuType.isOfType(RoadGTUTypes.SCHEDULED_BUS))
620 {
621 defaultCharacteristics.setParameter(ParameterTypes.A,
622 new Acceleration(0.8, AccelerationUnit.METER_PER_SECOND_2));
623 }
624 else
625 {
626 throw new RuntimeException("Unable to determine characteristics for GTU of type " + gtuType);
627 }
628
629 }
630
631 }
632
633 }