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", new Object[] {gtu, task});
105 }
106 else
107 {
108
109 if (!this.distractionQueues.containsKey(gtuId))
110 {
111 this.distractionQueues.put(gtuId, new LinkedList<>());
112 }
113 this.distractionQueues.get(gtuId).add(distraction);
114 }
115 if (scheduleNext)
116 {
117
118 this.simulator.scheduleEventRel(distraction.nextInterArrival(), this, "startDistraction",
119 new Object[] {gtu, distraction, true});
120 }
121 }
122
123
124
125
126
127
128
129 public void stopDistraction(final LaneBasedGtu gtu, final Task task) throws SimRuntimeException
130 {
131 if (gtu.isDestroyed())
132 {
133 return;
134 }
135 String gtuId = gtu.getId();
136 ((Fuller) gtu.getTacticalPlanner().getPerception().getMental()).removeTask(task);
137
138 if (!this.allowMultiTasking)
139 {
140 this.distractedGTUs.remove(gtuId);
141 if (this.distractionQueues.containsKey(gtuId))
142 {
143 Queue<Distraction> queue = this.distractionQueues.get(gtuId);
144 Distraction distraction = queue.poll();
145 startDistraction(gtu, distraction, false);
146 if (queue.isEmpty())
147 {
148 this.distractionQueues.remove(gtuId);
149 }
150 }
151 }
152 }
153
154 @Override
155 public void notify(final Event event) throws RemoteException
156 {
157 if (event.getType().equals(Network.GTU_ADD_EVENT))
158 {
159
160 String gtuId = (String) event.getContent();
161 Gtu gtu = this.network.getGTU(gtuId);
162 gtu.addListener(this, Gtu.MOVE_EVENT);
163 }
164 else if (event.getType().equals(Gtu.MOVE_EVENT))
165 {
166 String gtuId = (String) ((Object[]) event.getContent())[0];
167 LaneBasedGtu gtu = (LaneBasedGtu) this.network.getGTU(gtuId);
168 Mental mental = gtu.getTacticalPlanner().getPerception().getMental();
169 if (mental != null && mental instanceof Fuller)
170 {
171 for (Distraction distraction : this.distractions)
172 {
173 if (distraction.nextExposure())
174 {
175 Try.execute(
176 () -> this.simulator.scheduleEventRel(distraction.nextInterArrival(), this, "startDistraction",
177 new Object[] {gtu, distraction, true}),
178 "Exception while scheduling distraction start.");
179 }
180 }
181 }
182 gtu.removeListener(this, Gtu.MOVE_EVENT);
183 }
184 else if (event.getType().equals(Network.GTU_REMOVE_EVENT))
185 {
186 String gtuId = (String) event.getContent();
187 if (!this.allowMultiTasking)
188 {
189 this.distractedGTUs.remove(gtuId);
190 }
191 this.distractionQueues.remove(gtuId);
192 }
193 }
194
195 }