gistools/readers/gtfs/schedule/routes.rs
1use crate::{parsers::RGBA, readers::csv::parse_csv_as_record};
2use alloc::{collections::BTreeMap, string::String};
3use s2json::MValueCompatible;
4
5/// Indicates the type of transportation used on a route.
6/// Valid options include:
7/// 0 - Tram
8/// 1 - Subway
9/// 2 - Rail
10/// 3 - Bus
11/// 4 - Ferry,
12/// 5 - Cable tram
13/// 6 - Aerial lift
14/// 7 - Funicular,
15/// 11 - Trolleybus
16/// 12 - Monorail.
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
18pub enum GTFSRouteType {
19 /// 0 - Tram
20 Tram = 0,
21 /// 1 - Subway
22 Subway = 1,
23 /// 2 - Rail
24 Rail = 2,
25 /// 3 - Bus
26 Bus = 3,
27 /// 4 - Ferry
28 Ferry = 4,
29 /// 5 - Cable tram
30 CableTram = 5,
31 /// 6 - Aerial lift
32 AerialLift = 6,
33 /// 7 - Funicular
34 Funicular = 7,
35 /// 11 - Trolleybus
36 Trolleybus = 11,
37 /// 12 - Monorail
38 Monorail = 12,
39}
40impl From<i8> for GTFSRouteType {
41 fn from(s: i8) -> Self {
42 match s {
43 1 => GTFSRouteType::Subway,
44 2 => GTFSRouteType::Rail,
45 3 => GTFSRouteType::Bus,
46 4 => GTFSRouteType::Ferry,
47 5 => GTFSRouteType::CableTram,
48 6 => GTFSRouteType::AerialLift,
49 7 => GTFSRouteType::Funicular,
50 11 => GTFSRouteType::Trolleybus,
51 12 => GTFSRouteType::Monorail,
52 _ => GTFSRouteType::Tram,
53 }
54 }
55}
56
57/// Continuous pickup setting for the entire route.
58/// 0 - Continuous stopping pickup,
59/// 1/empty - No continuous stopping pickup,
60/// 2 - Must phone agency,
61/// 3 - Must coordinate with driver.
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
63pub enum GTFSRoutePickupType {
64 /// 0 - Continuous stopping pickup
65 ContinuousStoppingPickup = 0,
66 /// 1/empty - No continuous stopping pickup
67 NoContinuousStoppingPickup = 1,
68 /// 2 - Must phone agency
69 MustPhoneAgency = 2,
70 /// 3 - Must coordinate with driver
71 MustCoordinateWithDriver = 3,
72}
73impl From<i8> for GTFSRoutePickupType {
74 fn from(s: i8) -> Self {
75 match s {
76 0 => GTFSRoutePickupType::ContinuousStoppingPickup,
77 2 => GTFSRoutePickupType::MustPhoneAgency,
78 3 => GTFSRoutePickupType::MustCoordinateWithDriver,
79 _ => GTFSRoutePickupType::NoContinuousStoppingPickup,
80 }
81 }
82}
83
84/// # Route Information
85///
86/// ## Details
87/// **Required** - Transit routes. A route is a group of trips that are displayed to riders as a
88/// single service.
89#[derive(Debug, Default, Clone, PartialEq, MValueCompatible)]
90pub struct GTFSRoute {
91 /// **Required**
92 /// Identifies a route.
93 pub route_id: String,
94 /// **Conditionally Required**
95 /// Agency for the specified route.
96 /// Required if multiple agencies are defined in agency.txt.
97 pub agency_id: Option<String>,
98 /// **Conditionally Required**
99 /// Short name of a route, e.g. "32", "100X", "Green".
100 /// Required if `route_long_name` is empty. Recommended otherwise.
101 pub route_short_name: Option<String>,
102 /// **Conditionally Required**
103 /// Full name of a route, generally more descriptive than `shortName`.
104 /// Required if `route_short_name` is empty. Optional otherwise.
105 pub route_long_name: Option<String>,
106 /// **Optional**
107 /// Description of a route providing useful info, not a duplicate of short/long name.
108 pub route_desc: Option<String>,
109 /// **Required**
110 /// Indicates the type of transportation used on a route.
111 /// Valid options include:
112 /// 0 - Tram, 1 - Subway, 2 - Rail, 3 - Bus, 4 - Ferry,
113 /// 5 - Cable tram, 6 - Aerial lift, 7 - Funicular,
114 /// 11 - Trolleybus, 12 - Monorail.
115 pub route_type: i8,
116 /// **Optional**
117 /// URL of a web page about the route. Should differ from `agency.agency_url`.
118 pub route_url: Option<String>,
119 /// **Optional**
120 /// Route color (hex) matching public-facing material. Defaults to `FFFFFF` if empty.
121 pub route_color: Option<String>,
122 /// **Optional**
123 /// Text color (hex) used against the `route_color`. Defaults to `000000` if empty.
124 pub route_text_color: Option<String>,
125 /// **Optional**
126 /// Orders routes for ideal presentation (smaller values displayed first).
127 pub route_sort_order: Option<i8>,
128 /// **Conditionally Forbidden**
129 /// Continuous pickup setting for the entire route.
130 /// 0 - Continuous stopping pickup,
131 /// 1/empty - No continuous stopping pickup,
132 /// 2 - Must phone agency,
133 /// 3 - Must coordinate with driver.
134 ///
135 /// Forbidden if `stop_times.start_pickup_drop_off_window`
136 /// or `stop_times.end_pickup_drop_off_window` are used.
137 pub continuous_pickup: Option<i8>,
138 /// **Conditionally Forbidden**
139 /// Continuous drop-off setting for the entire route.
140 /// 0 - Continuous stopping drop off,
141 /// 1/empty - No continuous stopping drop off,
142 /// 2 - Must phone agency,
143 /// 3 - Must coordinate with driver.
144 ///
145 /// Forbidden if `stop_times.start_pickup_drop_off_window`
146 /// or `stop_times.end_pickup_drop_off_window` are used.
147 pub continuous_drop_off: Option<i8>,
148 /// **Conditionally Forbidden**
149 /// Identifies a group of routes. Multiple rows may share the same `network_id`.
150 /// Forbidden if `route_networks.txt` is used.
151 pub network_id: Option<String>,
152}
153impl GTFSRoute {
154 /// Create a new GTFSRoute
155 pub fn new(source: &str) -> BTreeMap<String, GTFSRoute> {
156 let mut res = BTreeMap::new();
157 for record in parse_csv_as_record::<GTFSRoute>(source, None, None) {
158 res.insert(record.route_id.clone(), record);
159 }
160 res
161 }
162 /// Get route type
163 pub fn route_type(&self) -> GTFSRouteType {
164 GTFSRouteType::from(self.route_type)
165 }
166 /// Get the continuous_pickup
167 pub fn continuous_pickup(&self) -> Option<GTFSRoutePickupType> {
168 self.continuous_pickup.map(GTFSRoutePickupType::from)
169 }
170 /// Get the continuous_drop_off
171 pub fn continuous_drop_off(&self) -> Option<GTFSRoutePickupType> {
172 self.continuous_drop_off.map(GTFSRoutePickupType::from)
173 }
174 /// Get the route color
175 pub fn route_color(&self) -> Option<RGBA> {
176 self.route_color.as_ref().map(|c| RGBA::from_hex(c))
177 }
178 /// Get the route text color
179 pub fn route_text_color(&self) -> Option<RGBA> {
180 self.route_text_color.as_ref().map(|c| RGBA::from_hex(c))
181 }
182}