1 package org.opentrafficsim.road.gtu.lane.perception.mental.sdm;
2
3 import java.rmi.RemoteException;
4 import java.util.LinkedHashMap;
5 import java.util.LinkedHashSet;
6 import java.util.LinkedList;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Queue;
10 import java.util.Set;
11
12 import org.opentrafficsim.core.gtu.Try;
13 import org.opentrafficsim.core.network.Network;
14 import org.opentrafficsim.core.network.OTSNetwork;
15 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
16 import org.opentrafficsim.road.gtu.lane.perception.mental.Fuller;
17 import org.opentrafficsim.road.gtu.lane.perception.mental.Fuller.Task;
18 import org.opentrafficsim.road.gtu.lane.perception.mental.Mental;
19
20 import nl.tudelft.simulation.dsol.SimRuntimeException;
21 import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
22 import nl.tudelft.simulation.event.EventInterface;
23 import nl.tudelft.simulation.event.EventListenerInterface;
24 import nl.tudelft.simulation.language.Throw;
25
26
27
28
29
30
31
32
33
34
35
36
37 public class StochasticDistractionModel implements EventListenerInterface
38 {
39
40
41 private final boolean allowMultiTasking;
42
43
44 private final List<Distraction> distractions;
45
46
47 private final DEVSSimulatorInterface.TimeDoubleUnit simulator;
48
49
50 private final OTSNetwork network;
51
52
53 private final Set<String> distractedGTUs = new LinkedHashSet<>();
54
55
56 private final Map<String, Queue<Distraction>> distractionQueues = new LinkedHashMap<>();
57
58
59
60
61
62
63
64
65 public StochasticDistractionModel(final boolean allowMultiTasking, final List<Distraction> distractions,
66 final DEVSSimulatorInterface.TimeDoubleUnit simulator, final OTSNetwork network)
67 {
68 Throw.whenNull(distractions, "List of tasks may not be null.");
69 Throw.whenNull(simulator, "Simulator may not be null.");
70 Throw.whenNull(network, "Network may not be null.");
71 this.allowMultiTasking = allowMultiTasking;
72 this.distractions = distractions;
73 this.simulator = simulator;
74 this.network = network;
75 network.addListener(this, Network.GTU_ADD_EVENT);
76 network.addListener(this, Network.GTU_REMOVE_EVENT);
77 }
78
79
80
81
82
83
84
85
86 public void startDistraction(final LaneBasedGTU gtu, final Distraction distraction, final boolean scheduleNext)
87 throws SimRuntimeException
88 {
89 if (gtu.isDestroyed())
90 {
91 return;
92 }
93 String gtuId = gtu.getId();
94 if (this.allowMultiTasking || !this.distractedGTUs.contains(gtuId))
95 {
96
97 if (!this.allowMultiTasking)
98 {
99 this.distractedGTUs.add(gtuId);
100 }
101 Task task = distraction.getTask(gtu);
102 ((Fuller) gtu.getTacticalPlanner().getPerception().getMental()).addTask(task);
103
104 this.simulator.scheduleEventRel(distraction.nextDuration(), this, this, "stopDistraction",
105 new Object[] { gtu, task });
106 }
107 else
108 {
109
110 if (!this.distractionQueues.containsKey(gtuId))
111 {
112 this.distractionQueues.put(gtuId, new LinkedList<>());
113 }
114 this.distractionQueues.get(gtuId).add(distraction);
115 }
116 if (scheduleNext)
117 {
118
119 this.simulator.scheduleEventRel(distraction.nextInterArrival(), this, this, "startDistraction",
120 new Object[] { gtu, distraction, true });
121 }
122 }
123
124
125
126
127
128
129
130 public void stopDistraction(final LaneBasedGTU gtu, final Task task) throws SimRuntimeException
131 {
132 if (gtu.isDestroyed())
133 {
134 return;
135 }
136 String gtuId = gtu.getId();
137 ((Fuller) gtu.getTacticalPlanner().getPerception().getMental()).removeTask(task);
138
139 if (!this.allowMultiTasking)
140 {
141 this.distractedGTUs.remove(gtuId);
142 if (this.distractionQueues.containsKey(gtuId))
143 {
144 Queue<Distraction> queue = this.distractionQueues.get(gtuId);
145 Distraction distraction = queue.poll();
146 startDistraction(gtu, distraction, false);
147 if (queue.isEmpty())
148 {
149 this.distractionQueues.remove(gtuId);
150 }
151 }
152 }
153 }
154
155
156 @Override
157 public void notify(final EventInterface event) throws RemoteException
158 {
159 if (event.getType().equals(Network.GTU_ADD_EVENT))
160 {
161 String gtuId = (String) event.getContent();
162 LaneBasedGTU gtu = (LaneBasedGTU) this.network.getGTU(gtuId);
163 Mental mental = gtu.getTacticalPlanner().getPerception().getMental();
164 if (mental != null && mental instanceof Fuller)
165 {
166 for (Distraction distraction : this.distractions)
167 {
168 if (distraction.nextExposure())
169 {
170 Try.execute(
171 () -> this.simulator.scheduleEventRel(distraction.nextInterArrival(), this, this,
172 "startDistraction", new Object[] { gtu, distraction, true }),
173 "Exception while scheduling distraction start.");
174 }
175 }
176 }
177 }
178 else if (event.getType().equals(Network.GTU_REMOVE_EVENT))
179 {
180 String gtuId = (String) event.getContent();
181 if (!this.allowMultiTasking)
182 {
183 this.distractedGTUs.remove(gtuId);
184 }
185 this.distractionQueues.remove(gtuId);
186 }
187 }
188
189 }