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