1use std::any::{Any, TypeId};
4use std::collections::HashMap;
5
6use slotmap::{SecondaryMap, SlotMap};
7
8use crate::components::{
9 AccessControl, Elevator, Line, Patience, Position, Preferences, Rider, Route, ServiceMode,
10 Stop, Velocity,
11};
12#[cfg(feature = "energy")]
13use crate::energy::{EnergyMetrics, EnergyProfile};
14use crate::entity::EntityId;
15use crate::query::storage::AnyExtMap;
16
17pub struct World {
27 pub(crate) alive: SlotMap<EntityId, ()>,
29
30 pub(crate) positions: SecondaryMap<EntityId, Position>,
33 pub(crate) velocities: SecondaryMap<EntityId, Velocity>,
35 pub(crate) elevators: SecondaryMap<EntityId, Elevator>,
37 pub(crate) stops: SecondaryMap<EntityId, Stop>,
39 pub(crate) riders: SecondaryMap<EntityId, Rider>,
41 pub(crate) routes: SecondaryMap<EntityId, Route>,
43 pub(crate) lines: SecondaryMap<EntityId, Line>,
45 pub(crate) patience: SecondaryMap<EntityId, Patience>,
47 pub(crate) preferences: SecondaryMap<EntityId, Preferences>,
49 pub(crate) access_controls: SecondaryMap<EntityId, AccessControl>,
51
52 #[cfg(feature = "energy")]
54 pub(crate) energy_profiles: SecondaryMap<EntityId, EnergyProfile>,
55 #[cfg(feature = "energy")]
57 pub(crate) energy_metrics: SecondaryMap<EntityId, EnergyMetrics>,
58 pub(crate) service_modes: SecondaryMap<EntityId, ServiceMode>,
60
61 pub(crate) disabled: SecondaryMap<EntityId, ()>,
63
64 extensions: HashMap<TypeId, Box<dyn AnyExtMap>>,
67 ext_names: HashMap<TypeId, String>,
69
70 resources: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
73}
74
75impl World {
76 #[must_use]
78 pub fn new() -> Self {
79 Self {
80 alive: SlotMap::with_key(),
81 positions: SecondaryMap::new(),
82 velocities: SecondaryMap::new(),
83 elevators: SecondaryMap::new(),
84 stops: SecondaryMap::new(),
85 riders: SecondaryMap::new(),
86 routes: SecondaryMap::new(),
87 lines: SecondaryMap::new(),
88 patience: SecondaryMap::new(),
89 preferences: SecondaryMap::new(),
90 access_controls: SecondaryMap::new(),
91 #[cfg(feature = "energy")]
92 energy_profiles: SecondaryMap::new(),
93 #[cfg(feature = "energy")]
94 energy_metrics: SecondaryMap::new(),
95 service_modes: SecondaryMap::new(),
96 disabled: SecondaryMap::new(),
97 extensions: HashMap::new(),
98 ext_names: HashMap::new(),
99 resources: HashMap::new(),
100 }
101 }
102
103 pub fn spawn(&mut self) -> EntityId {
105 self.alive.insert(())
106 }
107
108 pub fn despawn(&mut self, id: EntityId) {
115 if let Some(rider) = self.riders.get(id) {
117 let weight = rider.weight;
118 match rider.phase {
120 crate::components::RiderPhase::Boarding(elev)
121 | crate::components::RiderPhase::Riding(elev)
122 | crate::components::RiderPhase::Exiting(elev) => {
123 if let Some(car) = self.elevators.get_mut(elev) {
124 car.riders.retain(|r| *r != id);
125 car.current_load = (car.current_load - weight).max(0.0);
126 }
127 }
128 _ => {}
129 }
130 }
131
132 if let Some(car) = self.elevators.get(id) {
134 let rider_ids: Vec<EntityId> = car.riders.clone();
135 let elev_pos = self.positions.get(id).map(|p| p.value);
136 let nearest_stop = elev_pos.and_then(|p| self.find_nearest_stop(p));
137 for rid in rider_ids {
138 if let Some(rider) = self.riders.get_mut(rid) {
139 rider.phase = crate::components::RiderPhase::Waiting;
140 rider.current_stop = nearest_stop;
141 }
142 }
143 }
144
145 self.alive.remove(id);
146 self.positions.remove(id);
147 self.velocities.remove(id);
148 self.elevators.remove(id);
149 self.stops.remove(id);
150 self.riders.remove(id);
151 self.routes.remove(id);
152 self.lines.remove(id);
153 self.patience.remove(id);
154 self.preferences.remove(id);
155 self.access_controls.remove(id);
156 #[cfg(feature = "energy")]
157 self.energy_profiles.remove(id);
158 #[cfg(feature = "energy")]
159 self.energy_metrics.remove(id);
160 self.service_modes.remove(id);
161 self.disabled.remove(id);
162
163 for ext in self.extensions.values_mut() {
164 ext.remove(id);
165 }
166 }
167
168 #[must_use]
170 pub fn is_alive(&self, id: EntityId) -> bool {
171 self.alive.contains_key(id)
172 }
173
174 #[must_use]
176 pub fn entity_count(&self) -> usize {
177 self.alive.len()
178 }
179
180 pub(crate) fn alive_keys(&self) -> slotmap::basic::Keys<'_, EntityId, ()> {
182 self.alive.keys()
183 }
184
185 #[must_use]
189 pub fn position(&self, id: EntityId) -> Option<&Position> {
190 self.positions.get(id)
191 }
192
193 pub fn position_mut(&mut self, id: EntityId) -> Option<&mut Position> {
195 self.positions.get_mut(id)
196 }
197
198 pub fn set_position(&mut self, id: EntityId, pos: Position) {
200 self.positions.insert(id, pos);
201 }
202
203 #[must_use]
207 pub fn velocity(&self, id: EntityId) -> Option<&Velocity> {
208 self.velocities.get(id)
209 }
210
211 pub fn velocity_mut(&mut self, id: EntityId) -> Option<&mut Velocity> {
213 self.velocities.get_mut(id)
214 }
215
216 pub fn set_velocity(&mut self, id: EntityId, vel: Velocity) {
218 self.velocities.insert(id, vel);
219 }
220
221 #[must_use]
225 pub fn elevator(&self, id: EntityId) -> Option<&Elevator> {
226 self.elevators.get(id)
227 }
228
229 pub fn elevator_mut(&mut self, id: EntityId) -> Option<&mut Elevator> {
231 self.elevators.get_mut(id)
232 }
233
234 pub fn set_elevator(&mut self, id: EntityId, elev: Elevator) {
236 self.elevators.insert(id, elev);
237 }
238
239 #[must_use]
243 pub fn rider(&self, id: EntityId) -> Option<&Rider> {
244 self.riders.get(id)
245 }
246
247 pub fn rider_mut(&mut self, id: EntityId) -> Option<&mut Rider> {
249 self.riders.get_mut(id)
250 }
251
252 pub fn set_rider(&mut self, id: EntityId, rider: Rider) {
254 self.riders.insert(id, rider);
255 }
256
257 #[must_use]
261 pub fn stop(&self, id: EntityId) -> Option<&Stop> {
262 self.stops.get(id)
263 }
264
265 pub fn stop_mut(&mut self, id: EntityId) -> Option<&mut Stop> {
267 self.stops.get_mut(id)
268 }
269
270 pub fn set_stop(&mut self, id: EntityId, stop: Stop) {
272 self.stops.insert(id, stop);
273 }
274
275 #[must_use]
279 pub fn route(&self, id: EntityId) -> Option<&Route> {
280 self.routes.get(id)
281 }
282
283 pub fn route_mut(&mut self, id: EntityId) -> Option<&mut Route> {
285 self.routes.get_mut(id)
286 }
287
288 pub fn set_route(&mut self, id: EntityId, route: Route) {
290 self.routes.insert(id, route);
291 }
292
293 #[must_use]
297 pub fn line(&self, id: EntityId) -> Option<&Line> {
298 self.lines.get(id)
299 }
300
301 pub fn line_mut(&mut self, id: EntityId) -> Option<&mut Line> {
303 self.lines.get_mut(id)
304 }
305
306 pub fn set_line(&mut self, id: EntityId, line: Line) {
308 self.lines.insert(id, line);
309 }
310
311 pub fn remove_line(&mut self, id: EntityId) -> Option<Line> {
313 self.lines.remove(id)
314 }
315
316 pub fn iter_lines(&self) -> impl Iterator<Item = (EntityId, &Line)> {
318 self.lines.iter()
319 }
320
321 #[must_use]
325 pub fn patience(&self, id: EntityId) -> Option<&Patience> {
326 self.patience.get(id)
327 }
328
329 pub fn patience_mut(&mut self, id: EntityId) -> Option<&mut Patience> {
331 self.patience.get_mut(id)
332 }
333
334 pub fn set_patience(&mut self, id: EntityId, patience: Patience) {
336 self.patience.insert(id, patience);
337 }
338
339 #[must_use]
343 pub fn preferences(&self, id: EntityId) -> Option<&Preferences> {
344 self.preferences.get(id)
345 }
346
347 pub fn set_preferences(&mut self, id: EntityId, prefs: Preferences) {
349 self.preferences.insert(id, prefs);
350 }
351
352 #[must_use]
356 pub fn access_control(&self, id: EntityId) -> Option<&AccessControl> {
357 self.access_controls.get(id)
358 }
359
360 pub fn access_control_mut(&mut self, id: EntityId) -> Option<&mut AccessControl> {
362 self.access_controls.get_mut(id)
363 }
364
365 pub fn set_access_control(&mut self, id: EntityId, ac: AccessControl) {
367 self.access_controls.insert(id, ac);
368 }
369
370 #[cfg(feature = "energy")]
373 #[must_use]
375 pub fn energy_profile(&self, id: EntityId) -> Option<&EnergyProfile> {
376 self.energy_profiles.get(id)
377 }
378
379 #[cfg(feature = "energy")]
380 #[must_use]
382 pub fn energy_metrics(&self, id: EntityId) -> Option<&EnergyMetrics> {
383 self.energy_metrics.get(id)
384 }
385
386 #[cfg(feature = "energy")]
387 pub fn energy_metrics_mut(&mut self, id: EntityId) -> Option<&mut EnergyMetrics> {
389 self.energy_metrics.get_mut(id)
390 }
391
392 #[cfg(feature = "energy")]
393 pub fn set_energy_profile(&mut self, id: EntityId, profile: EnergyProfile) {
395 self.energy_profiles.insert(id, profile);
396 }
397
398 #[cfg(feature = "energy")]
399 pub fn set_energy_metrics(&mut self, id: EntityId, metrics: EnergyMetrics) {
401 self.energy_metrics.insert(id, metrics);
402 }
403
404 #[must_use]
408 pub fn service_mode(&self, id: EntityId) -> Option<&ServiceMode> {
409 self.service_modes.get(id)
410 }
411
412 pub fn set_service_mode(&mut self, id: EntityId, mode: ServiceMode) {
414 self.service_modes.insert(id, mode);
415 }
416
417 pub fn iter_elevators(&self) -> impl Iterator<Item = (EntityId, &Position, &Elevator)> {
421 self.elevators
422 .iter()
423 .filter_map(|(id, car)| self.positions.get(id).map(|pos| (id, pos, car)))
424 }
425
426 #[must_use]
428 pub fn elevator_ids(&self) -> Vec<EntityId> {
429 self.elevators.keys().collect()
430 }
431
432 pub fn elevator_ids_into(&self, buf: &mut Vec<EntityId>) {
434 buf.clear();
435 buf.extend(self.elevators.keys());
436 }
437
438 pub fn iter_riders(&self) -> impl Iterator<Item = (EntityId, &Rider)> {
440 self.riders.iter()
441 }
442
443 pub fn iter_riders_mut(&mut self) -> impl Iterator<Item = (EntityId, &mut Rider)> {
445 self.riders.iter_mut()
446 }
447
448 #[must_use]
450 pub fn rider_ids(&self) -> Vec<EntityId> {
451 self.riders.keys().collect()
452 }
453
454 pub fn iter_stops(&self) -> impl Iterator<Item = (EntityId, &Stop)> {
456 self.stops.iter()
457 }
458
459 #[must_use]
461 pub fn stop_ids(&self) -> Vec<EntityId> {
462 self.stops.keys().collect()
463 }
464
465 pub fn iter_idle_elevators(&self) -> impl Iterator<Item = (EntityId, &Position, &Elevator)> {
467 use crate::components::ElevatorPhase;
468 self.iter_elevators()
469 .filter(|(id, _, car)| car.phase == ElevatorPhase::Idle && !self.is_disabled(*id))
470 }
471
472 pub fn iter_moving_elevators(&self) -> impl Iterator<Item = (EntityId, &Position, &Elevator)> {
474 self.iter_elevators().filter(|(id, _, car)| {
475 matches!(car.phase, crate::components::ElevatorPhase::MovingToStop(_))
476 && !self.is_disabled(*id)
477 })
478 }
479
480 pub fn iter_waiting_riders(&self) -> impl Iterator<Item = (EntityId, &Rider)> {
482 use crate::components::RiderPhase;
483 self.iter_riders()
484 .filter(|(id, r)| r.phase == RiderPhase::Waiting && !self.is_disabled(*id))
485 }
486
487 #[must_use]
489 pub fn find_stop_at_position(&self, position: f64) -> Option<EntityId> {
490 const EPSILON: f64 = 1e-6;
491 self.stops.iter().find_map(|(id, stop)| {
492 if (stop.position - position).abs() < EPSILON {
493 Some(id)
494 } else {
495 None
496 }
497 })
498 }
499
500 #[must_use]
506 pub fn find_nearest_stop(&self, position: f64) -> Option<EntityId> {
507 self.stops
508 .iter()
509 .min_by(|(_, a), (_, b)| {
510 (a.position - position)
511 .abs()
512 .total_cmp(&(b.position - position).abs())
513 })
514 .map(|(id, _)| id)
515 }
516
517 #[must_use]
519 pub fn stop_position(&self, id: EntityId) -> Option<f64> {
520 self.stops.get(id).map(|s| s.position)
521 }
522
523 pub fn insert_ext<T: 'static + Send + Sync + serde::Serialize + serde::de::DeserializeOwned>(
544 &mut self,
545 id: EntityId,
546 value: T,
547 name: &str,
548 ) {
549 let type_id = TypeId::of::<T>();
550 let map = self
551 .extensions
552 .entry(type_id)
553 .or_insert_with(|| Box::new(SecondaryMap::<EntityId, T>::new()));
554 if let Some(m) = map.as_any_mut().downcast_mut::<SecondaryMap<EntityId, T>>() {
555 m.insert(id, value);
556 }
557 self.ext_names.insert(type_id, name.to_owned());
558 }
559
560 #[must_use]
562 pub fn get_ext<T: 'static + Send + Sync + Clone>(&self, id: EntityId) -> Option<T> {
563 self.ext_map::<T>()?.get(id).cloned()
564 }
565
566 pub fn get_ext_mut<T: 'static + Send + Sync>(&mut self, id: EntityId) -> Option<&mut T> {
568 self.ext_map_mut::<T>()?.get_mut(id)
569 }
570
571 pub fn remove_ext<T: 'static + Send + Sync>(&mut self, id: EntityId) -> Option<T> {
573 self.ext_map_mut::<T>()?.remove(id)
574 }
575
576 pub(crate) fn ext_map<T: 'static + Send + Sync>(&self) -> Option<&SecondaryMap<EntityId, T>> {
578 self.extensions
579 .get(&TypeId::of::<T>())?
580 .as_any()
581 .downcast_ref::<SecondaryMap<EntityId, T>>()
582 }
583
584 fn ext_map_mut<T: 'static + Send + Sync>(&mut self) -> Option<&mut SecondaryMap<EntityId, T>> {
586 self.extensions
587 .get_mut(&TypeId::of::<T>())?
588 .as_any_mut()
589 .downcast_mut::<SecondaryMap<EntityId, T>>()
590 }
591
592 pub(crate) fn serialize_extensions(&self) -> HashMap<String, HashMap<EntityId, String>> {
595 let mut result = HashMap::new();
596 for (type_id, map) in &self.extensions {
597 if let Some(name) = self.ext_names.get(type_id) {
598 result.insert(name.clone(), map.serialize_entries());
599 }
600 }
601 result
602 }
603
604 pub(crate) fn deserialize_extensions(
607 &mut self,
608 data: &HashMap<String, HashMap<EntityId, String>>,
609 ) {
610 for (name, entries) in data {
611 if let Some((&type_id, _)) = self.ext_names.iter().find(|(_, n)| *n == name) {
613 if let Some(map) = self.extensions.get_mut(&type_id) {
614 map.deserialize_entries(entries);
615 }
616 }
617 }
618 }
619
620 pub fn register_ext<
625 T: 'static + Send + Sync + serde::Serialize + serde::de::DeserializeOwned,
626 >(
627 &mut self,
628 name: &str,
629 ) {
630 let type_id = TypeId::of::<T>();
631 self.extensions
632 .entry(type_id)
633 .or_insert_with(|| Box::new(SecondaryMap::<EntityId, T>::new()));
634 self.ext_names.insert(type_id, name.to_owned());
635 }
636
637 pub fn disable(&mut self, id: EntityId) {
641 self.disabled.insert(id, ());
642 }
643
644 pub fn enable(&mut self, id: EntityId) {
646 self.disabled.remove(id);
647 }
648
649 #[must_use]
651 pub fn is_disabled(&self, id: EntityId) -> bool {
652 self.disabled.contains_key(id)
653 }
654
655 pub fn insert_resource<T: 'static + Send + Sync>(&mut self, value: T) {
673 self.resources.insert(TypeId::of::<T>(), Box::new(value));
674 }
675
676 #[must_use]
678 pub fn resource<T: 'static + Send + Sync>(&self) -> Option<&T> {
679 self.resources.get(&TypeId::of::<T>())?.downcast_ref()
680 }
681
682 pub fn resource_mut<T: 'static + Send + Sync>(&mut self) -> Option<&mut T> {
684 self.resources.get_mut(&TypeId::of::<T>())?.downcast_mut()
685 }
686
687 pub fn remove_resource<T: 'static + Send + Sync>(&mut self) -> Option<T> {
689 self.resources
690 .remove(&TypeId::of::<T>())
691 .and_then(|b| b.downcast().ok())
692 .map(|b| *b)
693 }
694
695 #[must_use]
711 pub const fn query<Q: crate::query::WorldQuery>(&self) -> crate::query::QueryBuilder<'_, Q> {
712 crate::query::QueryBuilder::new(self)
713 }
714
715 pub fn query_ext_mut<T: 'static + Send + Sync>(&mut self) -> crate::query::ExtQueryMut<'_, T> {
729 crate::query::ExtQueryMut::new(self)
730 }
731}
732
733impl Default for World {
734 fn default() -> Self {
735 Self::new()
736 }
737}
738
739pub(crate) struct SortedStops(pub(crate) Vec<(f64, EntityId)>);