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.event.Event;
13 import org.djutils.event.EventListener;
14 import org.djutils.exceptions.Throw;
15 import org.djutils.exceptions.Try;
16 import org.opentrafficsim.core.dsol.OtsSimulatorInterface;
17 import org.opentrafficsim.core.gtu.Gtu;
18 import org.opentrafficsim.core.network.Network;
19 import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
20 import org.opentrafficsim.road.gtu.lane.perception.mental.Fuller;
21 import org.opentrafficsim.road.gtu.lane.perception.mental.Mental;
22 import org.opentrafficsim.road.gtu.lane.perception.mental.Task;
23 import org.opentrafficsim.road.network.RoadNetwork;
24
25 import nl.tudelft.simulation.dsol.SimRuntimeException;
26
27
28
29
30
31
32
33
34
35
36
37 public class StochasticDistractionModel implements EventListener
38 {
39
40
41 private final boolean allowMultiTasking;
42
43
44 private final List<Distraction> distractions;
45
46
47 private final OtsSimulatorInterface simulator;
48
49
50 private final RoadNetwork 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 OtsSimulatorInterface simulator, final RoadNetwork 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, "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, "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 Event event) throws RemoteException
158 {
159 if (event.getType().equals(Network.GTU_ADD_EVENT))
160 {
161
162 String gtuId = (String) event.getContent();
163 Gtu gtu = this.network.getGTU(gtuId);
164 gtu.addListener(this, Gtu.MOVE_EVENT);
165 }
166 else if (event.getType().equals(Gtu.MOVE_EVENT))
167 {
168 String gtuId = (String) ((Object[]) event.getContent())[0];
169 LaneBasedGtu gtu = (LaneBasedGtu) this.network.getGTU(gtuId);
170 Mental mental = gtu.getTacticalPlanner().getPerception().getMental();
171 if (mental != null && mental instanceof Fuller)
172 {
173 for (Distraction distraction : this.distractions)
174 {
175 if (distraction.nextExposure())
176 {
177 Try.execute(
178 () -> this.simulator.scheduleEventRel(distraction.nextInterArrival(), this, "startDistraction",
179 new Object[] {gtu, distraction, true}),
180 "Exception while scheduling distraction start.");
181 }
182 }
183 }
184 gtu.removeListener(this, Gtu.MOVE_EVENT);
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 }