112 lines
3.2 KiB
Rust
112 lines
3.2 KiB
Rust
use std::collections::{HashMap, HashSet};
|
|
use gtfs_structures::{Agency, Calendar, CalendarDate, RawStopTime, RawTrip, Route, Stop};
|
|
use log::error;
|
|
use serde::{Serialize, Deserialize};
|
|
use serde_json::value;
|
|
use zip::result::ZipError;
|
|
|
|
|
|
#[derive(Debug)]
|
|
pub struct Error {
|
|
pub(crate) _message: String,
|
|
}
|
|
|
|
impl From<std::io::Error> for Error {
|
|
fn from(value: std::io::Error) -> Self {
|
|
return Error { _message: value.to_string() }
|
|
}
|
|
}
|
|
|
|
impl From<reqwest::Error> for Error {
|
|
fn from(value: reqwest::Error) -> Self {
|
|
return Error { _message: value.to_string() }
|
|
}
|
|
}
|
|
|
|
impl From<ZipError> for Error {
|
|
fn from(value: ZipError) -> Self {
|
|
return Error { _message: value.to_string() }
|
|
}
|
|
}
|
|
|
|
impl From<serde_json::Error> for Error {
|
|
fn from(value: serde_json::Error) -> Self {
|
|
return Error { _message: value.to_string() }
|
|
}
|
|
}
|
|
|
|
|
|
// This is to store the preferences for the GTFS(-R) side of the code.
|
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
|
pub struct Preferences {
|
|
#[serde(rename = "routes")]
|
|
pub route_numbers: HashSet<String>,
|
|
|
|
#[serde(rename = "stops")]
|
|
pub stop_codes: HashSet<String>,
|
|
|
|
#[serde(rename = "data-folder")]
|
|
pub data_folder: String,
|
|
|
|
#[serde(rename = "gtfs-url")]
|
|
pub gtfs_url: String,
|
|
|
|
#[serde(rename = "realtime-url")]
|
|
pub realtime_url: String,
|
|
|
|
#[serde(rename = "realtime-api-key")]
|
|
pub realtime_api_key: String,
|
|
|
|
#[serde(rename = "refresh-seconds")]
|
|
pub refresh_seconds: u64,
|
|
}
|
|
|
|
// Utility functions
|
|
impl Preferences {
|
|
pub fn gtfs_file_name(&self) -> Result<String, Error> {
|
|
let file_name_part = self.gtfs_url.split("/").last();
|
|
if file_name_part.is_none() {
|
|
error!("The config for gtfs-url is not a valid URL: {}", self.gtfs_url);
|
|
return Err(Error {_message: String::from("Failed to refresh GTFS data")});
|
|
}
|
|
return Ok(String::from(file_name_part.unwrap()));
|
|
}
|
|
|
|
pub fn gtfs_file_path(&self) -> Result<String, Error> {
|
|
return Ok(format!("{}/{}", self.data_folder, self.gtfs_file_name()?));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// The main GTFS struct. This is similar to (but not exactly) gtfs-structures::Gtfs because we don't need everything
|
|
#[derive(Debug)]
|
|
pub struct Gtfs<'a> {
|
|
/// A copy of the preferences struct
|
|
pub(crate) preferences: &'a Preferences,
|
|
|
|
/// All agencies. They can not be read by `agency_id`, as it is not a required field
|
|
pub(crate) agencies: Vec<Agency>,
|
|
/// All Calendar by `service_id`
|
|
pub(crate) calendar: HashMap<String, Calendar>,
|
|
/// All calendar dates grouped by service_id
|
|
pub(crate) calendar_dates: HashMap<String, Vec<CalendarDate>>,
|
|
/// All routes by `route_id`
|
|
pub(crate) routes: HashMap<String, Route>,
|
|
/// All stop by `stop_id`.
|
|
pub(crate) stops: HashMap<String, Stop>,
|
|
/// All trips by trip_id
|
|
pub(crate) trips: HashMap<String, RawTrip>,
|
|
/// Stop times for the chosen stops and the chosen routes
|
|
pub(crate) stop_times: HashMap<(String, u32), RawStopTime>,
|
|
}
|
|
|
|
|
|
#[derive(Debug)]
|
|
pub struct Arrival<'a> {
|
|
pub departure_time: u32,
|
|
pub route: &'a Route,
|
|
pub stop: &'a Stop,
|
|
pub stop_time: &'a RawStopTime,
|
|
pub trip: &'a RawTrip,
|
|
} |