paiagram/
vehicles.rs

1use crate::graph::Station;
2use crate::vehicles::services::VehicleService;
3use bevy::prelude::*;
4use moonshine_core::kind::Instance;
5use moonshine_core::save::prelude::*;
6mod calculate_estimates;
7pub mod entries;
8pub mod services;
9pub mod vehicle_set;
10
11#[derive(Reflect, Debug, Component)]
12#[reflect(Component)]
13#[require(Name, entries::VehicleSchedule, Save)]
14pub struct Vehicle;
15
16pub struct VehiclesPlugin;
17
18impl Plugin for VehiclesPlugin {
19    fn build(&self, app: &mut App) {
20        app.add_message::<AdjustTimetableEntry>()
21            .add_message::<AdjustVehicle>()
22            .add_systems(
23                FixedUpdate,
24                (
25                    adjust_timetable_entry,
26                    entries::calculate_actual_route,
27                    calculate_estimates::calculate_estimates,
28                    entries::populate_services,
29                )
30                    .chain()
31                    .run_if(on_message::<AdjustTimetableEntry>),
32            );
33    }
34}
35
36#[derive(Debug)]
37pub enum TimetableAdjustment {
38    SetArrivalType(entries::TravelMode),
39    AdjustArrivalTime(crate::units::time::Duration),
40    SetDepartureType(Option<entries::TravelMode>),
41    AdjustDepartureTime(crate::units::time::Duration),
42    SetStation(Instance<Station>),
43    SetService(Option<Instance<VehicleService>>),
44    SetTrack(Option<Entity>),
45    SetNote(Option<String>),
46    PassThrough,
47}
48
49#[derive(Message, Debug)]
50pub struct AdjustTimetableEntry {
51    pub entity: Entity,
52    pub adjustment: TimetableAdjustment,
53}
54
55pub enum VehicleAdjustment {
56    AddEntry(usize, Entity),
57    RemoveEntry(Entity),
58    Rename(String),
59    Remove,
60}
61
62#[derive(Message)]
63pub struct AdjustVehicle {
64    pub entity: Entity,
65    pub adjustment: VehicleAdjustment,
66}
67
68pub fn adjust_timetable_entry(
69    mut commands: Commands,
70    mut reader: MessageReader<AdjustTimetableEntry>,
71    entries: Populated<&entries::TimetableEntry>,
72) {
73    for msg in reader.read() {
74        let AdjustTimetableEntry { entity, adjustment } = msg;
75        let entry = match entries.get(*entity) {
76            Ok(a) => a,
77            Err(e) => {
78                warn!("Failed to adjust timetable entry {entity:?}: {e:?}");
79                continue;
80            }
81        };
82        let mut new_entry = entry.clone();
83
84        use TimetableAdjustment::*;
85        match adjustment {
86            AdjustArrivalTime(dt) => new_entry.arrival.adjust_time(*dt),
87            SetArrivalType(nt) => new_entry.arrival = *nt,
88            AdjustDepartureTime(dt) => {
89                new_entry.departure.as_mut().map(|d| d.adjust_time(*dt));
90            }
91            SetDepartureType(nt) => new_entry.departure = *nt,
92            SetStation(ns) => new_entry.station = ns.entity(),
93            SetService(ns) => new_entry.service = *ns,
94            SetTrack(nt) => new_entry.track = *nt,
95            SetNote(note) => {}
96            PassThrough => return,
97        }
98        commands.entity(*entity).insert(new_entry);
99    }
100}