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}