1use crate::dispatch::DispatchStrategy;
8use crate::events::EventBus;
9use crate::hooks::Phase;
10use crate::ids::GroupId;
11use crate::metrics::Metrics;
12use crate::systems::PhaseContext;
13use std::collections::BTreeMap;
14
15impl super::Simulation {
16 #[must_use]
20 pub fn dispatchers(&self) -> &BTreeMap<GroupId, Box<dyn DispatchStrategy>> {
21 &self.dispatchers
22 }
23
24 pub fn dispatchers_mut(&mut self) -> &mut BTreeMap<GroupId, Box<dyn DispatchStrategy>> {
26 &mut self.dispatchers
27 }
28
29 pub const fn events_mut(&mut self) -> &mut EventBus {
31 &mut self.events
32 }
33
34 pub const fn metrics_mut(&mut self) -> &mut Metrics {
36 &mut self.metrics
37 }
38
39 #[must_use]
41 pub const fn phase_context(&self) -> PhaseContext {
42 PhaseContext {
43 tick: self.tick,
44 dt: self.dt,
45 }
46 }
47
48 pub fn run_advance_transient(&mut self) {
68 self.tick_in_progress = true;
69 self.sync_world_tick();
70 self.hooks
71 .run_before(Phase::AdvanceTransient, &mut self.world);
72 for group in &self.groups {
73 self.hooks
74 .run_before_group(Phase::AdvanceTransient, group.id(), &mut self.world);
75 }
76 let ctx = self.phase_context();
77 crate::systems::advance_transient::run(
78 &mut self.world,
79 &mut self.events,
80 &ctx,
81 &mut self.rider_index,
82 );
83 for group in &self.groups {
84 self.hooks
85 .run_after_group(Phase::AdvanceTransient, group.id(), &mut self.world);
86 }
87 self.hooks
88 .run_after(Phase::AdvanceTransient, &mut self.world);
89 }
90
91 pub fn run_dispatch(&mut self) {
93 self.sync_world_tick();
94 self.hooks.run_before(Phase::Dispatch, &mut self.world);
95 for group in &self.groups {
96 self.hooks
97 .run_before_group(Phase::Dispatch, group.id(), &mut self.world);
98 }
99 let ctx = self.phase_context();
100 crate::systems::dispatch::run(
101 &mut self.world,
102 &mut self.events,
103 &ctx,
104 &self.groups,
105 &mut self.dispatchers,
106 &self.rider_index,
107 );
108 for group in &self.groups {
109 self.hooks
110 .run_after_group(Phase::Dispatch, group.id(), &mut self.world);
111 }
112 self.hooks.run_after(Phase::Dispatch, &mut self.world);
113 }
114
115 pub fn run_movement(&mut self) {
117 self.hooks.run_before(Phase::Movement, &mut self.world);
118 for group in &self.groups {
119 self.hooks
120 .run_before_group(Phase::Movement, group.id(), &mut self.world);
121 }
122 let ctx = self.phase_context();
123 self.world.elevator_ids_into(&mut self.elevator_ids_buf);
124 crate::systems::movement::run(
125 &mut self.world,
126 &mut self.events,
127 &ctx,
128 &self.elevator_ids_buf,
129 &mut self.metrics,
130 );
131 for group in &self.groups {
132 self.hooks
133 .run_after_group(Phase::Movement, group.id(), &mut self.world);
134 }
135 self.hooks.run_after(Phase::Movement, &mut self.world);
136 }
137
138 pub fn run_doors(&mut self) {
140 self.hooks.run_before(Phase::Doors, &mut self.world);
141 for group in &self.groups {
142 self.hooks
143 .run_before_group(Phase::Doors, group.id(), &mut self.world);
144 }
145 let ctx = self.phase_context();
146 self.world.elevator_ids_into(&mut self.elevator_ids_buf);
147 crate::systems::doors::run(
148 &mut self.world,
149 &mut self.events,
150 &ctx,
151 &self.elevator_ids_buf,
152 );
153 for group in &self.groups {
154 self.hooks
155 .run_after_group(Phase::Doors, group.id(), &mut self.world);
156 }
157 self.hooks.run_after(Phase::Doors, &mut self.world);
158 }
159
160 pub fn run_loading(&mut self) {
162 self.hooks.run_before(Phase::Loading, &mut self.world);
163 for group in &self.groups {
164 self.hooks
165 .run_before_group(Phase::Loading, group.id(), &mut self.world);
166 }
167 let ctx = self.phase_context();
168 self.world.elevator_ids_into(&mut self.elevator_ids_buf);
169 crate::systems::loading::run(
170 &mut self.world,
171 &mut self.events,
172 &ctx,
173 &self.elevator_ids_buf,
174 &mut self.rider_index,
175 );
176 for group in &self.groups {
177 self.hooks
178 .run_after_group(Phase::Loading, group.id(), &mut self.world);
179 }
180 self.hooks.run_after(Phase::Loading, &mut self.world);
181 }
182
183 pub fn run_advance_queue(&mut self) {
189 self.hooks.run_before(Phase::AdvanceQueue, &mut self.world);
190 for group in &self.groups {
191 self.hooks
192 .run_before_group(Phase::AdvanceQueue, group.id(), &mut self.world);
193 }
194 let ctx = self.phase_context();
195 self.world.elevator_ids_into(&mut self.elevator_ids_buf);
196 crate::systems::advance_queue::run(
197 &mut self.world,
198 &mut self.events,
199 &ctx,
200 &self.elevator_ids_buf,
201 );
202 for group in &self.groups {
203 self.hooks
204 .run_after_group(Phase::AdvanceQueue, group.id(), &mut self.world);
205 }
206 self.hooks.run_after(Phase::AdvanceQueue, &mut self.world);
207 }
208
209 pub fn run_reposition(&mut self) {
217 self.sync_world_tick();
218 self.hooks.run_before(Phase::Reposition, &mut self.world);
219 if !self.repositioners.is_empty() {
220 for group in &self.groups {
222 if self.repositioners.contains_key(&group.id()) {
223 self.hooks
224 .run_before_group(Phase::Reposition, group.id(), &mut self.world);
225 }
226 }
227 let ctx = self.phase_context();
228 crate::systems::reposition::run(
229 &mut self.world,
230 &mut self.events,
231 &ctx,
232 &self.groups,
233 &mut self.repositioners,
234 &mut self.reposition_buf,
235 );
236 for group in &self.groups {
237 if self.repositioners.contains_key(&group.id()) {
238 self.hooks
239 .run_after_group(Phase::Reposition, group.id(), &mut self.world);
240 }
241 }
242 }
243 self.hooks.run_after(Phase::Reposition, &mut self.world);
244 }
245
246 #[cfg(feature = "energy")]
248 fn run_energy(&mut self) {
249 let ctx = self.phase_context();
250 self.world.elevator_ids_into(&mut self.elevator_ids_buf);
251 crate::systems::energy::run(
252 &mut self.world,
253 &mut self.events,
254 &ctx,
255 &self.elevator_ids_buf,
256 );
257 }
258
259 pub fn run_metrics(&mut self) {
261 self.hooks.run_before(Phase::Metrics, &mut self.world);
262 for group in &self.groups {
263 self.hooks
264 .run_before_group(Phase::Metrics, group.id(), &mut self.world);
265 }
266 let ctx = self.phase_context();
267 crate::systems::metrics::run(
268 &mut self.world,
269 &self.events,
270 &mut self.metrics,
271 &ctx,
272 &self.groups,
273 );
274 for group in &self.groups {
275 self.hooks
276 .run_after_group(Phase::Metrics, group.id(), &mut self.world);
277 }
278 self.hooks.run_after(Phase::Metrics, &mut self.world);
279 }
280
281 pub fn advance_tick(&mut self) {
288 self.pending_output.extend(self.events.drain());
289 self.tick += 1;
290 self.tick_in_progress = false;
291 self.sync_world_tick();
295 let retention = self
299 .world
300 .resource::<crate::arrival_log::ArrivalLogRetention>()
301 .copied()
302 .unwrap_or_default()
303 .0;
304 let cutoff = self.tick.saturating_sub(retention);
305 if let Some(log) = self.world.resource_mut::<crate::arrival_log::ArrivalLog>() {
306 log.prune_before(cutoff);
307 }
308 if let Some(log) = self
309 .world
310 .resource_mut::<crate::arrival_log::DestinationLog>()
311 {
312 log.prune_before(cutoff);
313 }
314 }
315
316 fn sync_world_tick(&mut self) {
322 if let Some(ct) = self.world.resource_mut::<crate::arrival_log::CurrentTick>() {
323 ct.0 = self.tick;
324 }
325 }
326
327 pub fn step(&mut self) {
341 self.sync_world_tick();
342 self.world.snapshot_prev_positions();
343 self.run_advance_transient();
344 self.run_dispatch();
345 self.run_reposition();
346 self.run_advance_queue();
347 self.run_movement();
348 self.run_doors();
349 self.run_loading();
350 #[cfg(feature = "energy")]
351 self.run_energy();
352 self.run_metrics();
353 self.advance_tick();
354 }
355}