gistools/readers/gtfs/schedule/
booking_rules.rs

1use crate::readers::csv::parse_csv_as_record;
2use alloc::{collections::BTreeMap, string::String};
3use s2json::MValueCompatible;
4
5/// Describes how far in advance rider can book:
6/// 0 - Real-time
7/// 1 - Same-day (with advance notice)
8/// 2 - Prior day(s)
9#[derive(Debug, Clone, Copy, PartialEq)]
10pub enum GTFSBookingType {
11    /// Real-time
12    RealTime = 0,
13    /// Same-day
14    SameDay = 1,
15    /// Prior day(s)
16    PriorDays = 2,
17}
18impl From<i8> for GTFSBookingType {
19    fn from(value: i8) -> Self {
20        match value {
21            1 => GTFSBookingType::SameDay,
22            2 => GTFSBookingType::PriorDays,
23            _ => GTFSBookingType::RealTime,
24        }
25    }
26}
27
28/// # Booking Rules
29///
30/// **Optional**
31/// Defines rules for booking rider-requested services. Useful when a trip or stop_time requires
32/// advanced scheduling (e.g., dial-a-ride, on-demand pickup).
33///
34/// **Primary Key**: (booking_rule_id)
35#[derive(Debug, Default, Clone, PartialEq, MValueCompatible)]
36pub struct GTFSBookingRule {
37    /// **Required**
38    /// Identifies a booking rule (`booking_rule_id`).
39    pub booking_rule_id: String,
40    /// **Required**
41    /// Indicates how far in advance booking can be made.
42    /// 0 = Real-time, 1 = Same-day, 2 = Prior-day(s)
43    pub booking_type: i8,
44    /// **Conditionally Required**
45    /// Minimum number of minutes before travel to make the request.
46    /// Required for booking_type=1; forbidden otherwise.
47    pub prior_notice_duration_min: Option<i32>,
48    /// **Conditionally Forbidden**
49    /// Maximum number of minutes before travel to make the same-day request.
50    /// - Forbidden for booking_type=0 or booking_type=2
51    /// - Optional for booking_type=1
52    pub prior_notice_duration_max: Option<i32>,
53    /// **Conditionally Required**
54    /// Last day before travel to make booking request. E.g., 1 = 1 day in advance.
55    /// Required for booking_type=2; forbidden otherwise.
56    pub prior_notice_last_day: Option<i32>,
57    /// **Conditionally Required**
58    /// Last time on the last day before travel to make booking request, e.g. "17:00:00".
59    /// Required if prior_notice_last_day is defined; forbidden otherwise.
60    pub prior_notice_last_time: Option<String>,
61    /// **Conditionally Forbidden**
62    /// Earliest day before travel to make booking request.
63    /// - Forbidden for booking_type=0.
64    /// - Forbidden for booking_type=1 if prior_notice_duration_max is defined.
65    /// - Optional otherwise (mainly for booking_type=2).
66    pub prior_notice_start_day: Option<i32>,
67    /// **Conditionally Required**
68    /// Earliest time on the earliest day before travel, e.g. "00:00:00".
69    /// Required if prior_notice_start_day is defined; forbidden otherwise.
70    pub prior_notice_start_time: Option<String>,
71    /// **Conditionally Forbidden**
72    /// Service days on which last_day / start_day are counted (`calendar.service_id`).
73    /// - Optional if booking_type=2.
74    /// - Forbidden otherwise.
75    pub prior_notice_service_id: Option<String>,
76    /// **Optional**
77    /// Generic message to riders for on-demand booking instructions.
78    pub message: Option<String>,
79    /// **Optional**
80    /// Message for on-demand pickup instructions.
81    pub pickup_message: Option<String>,
82    /// **Optional**
83    /// Message for on-demand drop-off instructions.
84    pub drop_off_message: Option<String>,
85    /// **Optional**
86    /// Phone number riders call to make the booking request.
87    pub phone_number: Option<String>,
88    /// **Optional**
89    /// URL providing additional booking info.
90    pub info_url: Option<String>,
91    /// **Optional**
92    /// URL to an online interface or app to make a booking request.
93    pub booking_url: Option<String>,
94}
95impl GTFSBookingRule {
96    /// Create a new GTFSBookingRule
97    pub fn new(source: &str) -> BTreeMap<String, GTFSBookingRule> {
98        let mut res = BTreeMap::new();
99        for record in parse_csv_as_record::<GTFSBookingRule>(source, None, None) {
100            res.insert(record.booking_rule_id.clone(), record);
101        }
102        res
103    }
104    /// Get the booking type
105    pub fn get_booking_type(&self) -> GTFSBookingType {
106        self.booking_type.into()
107    }
108}