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}