Skip to main content

paiagram_core/import/
llt.rs

1use bevy::platform::collections::HashMap;
2use bevy::prelude::*;
3use moonshine_core::kind::Instance;
4use serde::{Deserialize, Serialize};
5use serde_json;
6
7use crate::class::{Class, ClassBundle, DisplayedStroke};
8use crate::entry::{EntryBundle, TravelMode};
9use crate::graph::Graph;
10use crate::route::Route;
11use crate::station::Station;
12use crate::trip::{TripBundle, TripClass};
13use crate::units::distance::Distance;
14use crate::units::time::TimetableTime;
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct TimetableData {
18    pub stations: Vec<String>,
19    pub lines: Vec<Line>,
20    pub trains: Vec<Train>,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct Line {
25    pub code: i64,
26    pub name: String,
27    pub stations: Vec<LineStation>,
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct LineStation {
32    pub station: String,
33    pub telecode: String,
34    #[serde(rename = "routeFlag")]
35    pub route_flag: i64,
36    pub distance: i64,
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct Train {
41    pub number: String,
42    #[serde(rename = "type")]
43    pub r#type: String,
44    pub stops: Vec<TrainStop>,
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct TrainStop {
49    pub station: String,
50    #[serde(rename = "type")]
51    pub r#type: StopType,
52    pub line_code: i64,
53    pub arrival_time: String,
54    pub departure_time: String,
55    pub mileage: i64,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize)]
59#[serde(rename_all = "lowercase")]
60pub enum StopType {
61    Stop,
62    Crossline,
63}
64
65pub fn load_llt(msg: On<super::LoadLlt>, mut graph: ResMut<Graph>, mut commands: Commands) {
66    let root: TimetableData = serde_json::from_str(&msg.content).unwrap();
67    let mut station_map: HashMap<String, Instance<Station>> = HashMap::new();
68    let mut class_map: HashMap<String, Instance<Class>> = HashMap::new();
69    for station_name in root.stations {
70        super::make_station(&station_name, &mut station_map, &mut graph, &mut commands);
71    }
72    for Line {
73        code: _,
74        name: line_name,
75        stations,
76    } in root.lines
77    {
78        let mut station_entities = Vec::with_capacity(stations.len());
79        let mut distances: Vec<f32> = Vec::with_capacity(stations.len());
80        let mut station_iter = stations.into_iter();
81        let Some(station) = station_iter.next() else {
82            continue;
83        };
84        let mut previous_station = super::make_station(
85            &station.station,
86            &mut station_map,
87            &mut graph,
88            &mut commands,
89        );
90        let mut previous_distance = station.distance;
91        station_entities.push(previous_station.entity());
92        distances.push(0.0f32);
93        for station in station_iter {
94            let current_station = super::make_station(
95                &station.station,
96                &mut station_map,
97                &mut graph,
98                &mut commands,
99            );
100            let interval_length = station.distance - previous_distance;
101            super::add_interval_pair(
102                &mut graph,
103                &mut commands,
104                previous_station.entity(),
105                current_station.entity(),
106                Distance::from_m(interval_length as i32 * 1000),
107            );
108            previous_distance = station.distance;
109            previous_station = current_station;
110            station_entities.push(previous_station.entity());
111            distances.push(interval_length as f32);
112        }
113        commands.spawn((
114            Route {
115                stops: station_entities,
116                lengths: distances,
117            },
118            Name::new(line_name),
119        ));
120    }
121    for Train {
122        number: trip_name,
123        r#type,
124        stops,
125    } in root.trains
126    {
127        let mut entries: Vec<_> = stops
128            .into_iter()
129            .map(|e| {
130                (
131                    TimetableTime::from_str(&e.arrival_time),
132                    TimetableTime::from_str(&e.departure_time),
133                    super::make_station(&e.station, &mut station_map, &mut graph, &mut commands),
134                )
135            })
136            .collect();
137        super::normalize_times(
138            entries
139                .iter_mut()
140                .flat_map(|(a, d, _)| a.iter_mut().chain(d.iter_mut())),
141        );
142        let trip_class =
143            super::make_class(&r#type, &mut class_map, &mut commands, || ClassBundle {
144                class: Class::default(),
145                name: Name::new(r#type.clone()),
146                stroke: DisplayedStroke::from_seed(r#type.as_bytes()),
147            });
148
149        let nominal_schedule: Vec<_> = entries
150            .into_iter()
151            .map(|(arr, dep, stop)| {
152                let (arr, dep) = match (arr, dep) {
153                    (None, None) => (None, TravelMode::Flexible),
154                    (Some(t), None) | (None, Some(t)) => (None, TravelMode::At(t)),
155                    (Some(at), Some(dt)) => {
156                        if at == dt {
157                            (None, TravelMode::At(dt))
158                        } else {
159                            (Some(TravelMode::At(at)), TravelMode::At(dt))
160                        }
161                    }
162                };
163                commands
164                    .spawn(EntryBundle::new(arr, dep, stop.entity()))
165                    .id()
166            })
167            .collect();
168
169        commands
170            .spawn_empty()
171            .add_children(&nominal_schedule)
172            .insert(TripBundle::new(
173                &trip_name,
174                TripClass(trip_class.entity()),
175                nominal_schedule,
176            ));
177    }
178}