This commit is contained in:
Nicholas Orlowsky 2026-02-16 21:36:36 -05:00
parent b7ec6a292f
commit 9297006ab3
No known key found for this signature in database
GPG key ID: A9F3BA4C0AA7A70B
58 changed files with 2032 additions and 2074 deletions

View file

@ -1,8 +1,7 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Agency {
pub id: String,
pub name: String
pub name: String,
}

View file

@ -1,7 +1,8 @@
use serde::{Deserialize, Serialize};
#[derive(sqlx::Type, Serialize, Deserialize, PartialEq, Debug, Clone, Copy, Eq, PartialOrd, Ord)]
#[derive(
sqlx::Type, Serialize, Deserialize, PartialEq, Debug, Clone, Copy, Eq, PartialOrd, Ord,
)]
#[sqlx(type_name = "septa_direction_type", rename_all = "snake_case")]
pub enum CardinalDirection {
Northbound,
@ -10,17 +11,17 @@ pub enum CardinalDirection {
Westbound,
Inbound,
Outbound,
Loop
Loop,
}
#[derive(::sqlx::Decode, Serialize, Deserialize, Debug, Clone)]
pub struct Direction {
pub direction: CardinalDirection,
pub direction_destination: String
pub direction_destination: String,
}
impl std::fmt::Display for CardinalDirection {
fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let output = match self {
CardinalDirection::Northbound => "Northbound",
CardinalDirection::Southbound => "Southbound",
@ -28,7 +29,7 @@ impl std::fmt::Display for CardinalDirection {
CardinalDirection::Westbound => "Westbound",
CardinalDirection::Inbound => "Inbound",
CardinalDirection::Outbound => "Outbound",
CardinalDirection::Loop => "Loop"
CardinalDirection::Loop => "Loop",
};
std::write!(f, "{}", output)
}

View file

@ -1,8 +1,8 @@
pub mod route;
pub mod agency;
pub mod stop;
pub mod route_stop;
pub mod stop_schedule;
pub mod schedule_day;
pub mod direction;
pub mod ridership;
pub mod route;
pub mod route_stop;
pub mod schedule_day;
pub mod stop;
pub mod stop_schedule;

View file

@ -17,5 +17,5 @@ pub struct Ridership {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LineRidership {
pub route_id: String,
pub unlinked_trips: i64
pub unlinked_trips: i64,
}

View file

@ -9,7 +9,7 @@ pub enum RouteType {
SubwayElevated,
RegionalRail,
Bus,
TracklessTrolley
TracklessTrolley,
}
#[derive(::sqlx::FromRow, Serialize, Deserialize, Debug, Clone)]
@ -19,12 +19,12 @@ pub struct Route {
pub color_hex: String,
pub route_type: RouteType,
pub id: String,
pub directions: Vec<crate::direction::Direction>
pub directions: Vec<crate::direction::Direction>,
}
impl PartialEq for Route {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
self.id == other.id
}
}
@ -42,10 +42,9 @@ impl PartialOrd for Route {
}
}
#[derive(::sqlx::FromRow, Serialize, Deserialize, Debug, Clone)]
pub struct InterlinedRoute {
pub interline_id: String,
pub interline_name: String,
pub interlined_routes: Vec<String>
pub interlined_routes: Vec<String>,
}

View file

@ -3,5 +3,5 @@ pub struct RouteStop {
pub route_id: String,
pub stop_id: i64,
pub direction_id: i64,
pub stop_sequence: i64
pub stop_sequence: i64,
}

View file

@ -1,5 +1,5 @@
#[derive(Debug, Clone)]
pub struct ScheduleDay {
pub date: String,
pub service_id: String
pub service_id: String,
}

View file

@ -1,4 +1,7 @@
use std::{hash::{Hash, Hasher}, sync::Arc};
use std::{
hash::{Hash, Hasher},
sync::Arc,
};
use serde::{Deserialize, Serialize};
@ -7,13 +10,13 @@ use serde::{Deserialize, Serialize};
pub enum PlatformLocationType {
FarSide,
MiddleBlockNearSide,
Normal
Normal,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum StopType {
SinglePlatform(Arc<Platform>),
MultiPlatform(Vec<Arc<Platform>>)
MultiPlatform(Vec<Arc<Platform>>),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
@ -22,12 +25,12 @@ pub struct Platform {
pub name: String,
pub lat: f64,
pub lng: f64,
pub platform_location: PlatformLocationType
pub platform_location: PlatformLocationType,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Stop {
pub id: String,
pub id: String,
pub name: String,
pub platforms: StopType,
}

View file

@ -1,7 +1,7 @@
use std::sync::Arc;
use chrono::{Datelike, Days, TimeZone, Weekday};
use serde::{Deserialize, Serialize, Serializer, de::Error};
use chrono::{Datelike, Days, Weekday};
use serde::{Deserialize, Serialize, Serializer};
use crate::{direction::Direction, route::Route, stop::Platform};
@ -10,11 +10,11 @@ pub struct StopSchedule {
pub arrival_time: i64,
pub stop_sequence: i64,
pub stop: Arc<crate::stop::Stop>,
pub platform: Arc<Platform>
pub platform: Arc<Platform>,
}
impl StopSchedule {
pub fn get_arrival_time(&self, live_info: &LiveTrip) -> i64 {
impl StopSchedule {
pub fn get_arrival_time(&self, live_info: &LiveTrip) -> i64 {
return self.arrival_time + (live_info.delay * 60.0 as f64) as i64;
}
}
@ -22,34 +22,45 @@ impl StopSchedule {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Trip {
pub service_id: String,
pub route: Arc<Route>,
pub route: Arc<Route>,
pub trip_id: String,
pub direction: Direction,
pub tracking_data: TripTracking,
pub schedule: Vec<StopSchedule>,
pub calendar_day: Arc<CalendarDay>
pub calendar_day: Arc<CalendarDay>,
}
impl Trip {
impl Trip {
pub fn is_active_on(&self, datetime: &chrono::NaiveDateTime) -> bool {
if !self.calendar_day.is_calendar_active_for_date(&datetime.date()) {
if !self
.calendar_day
.is_calendar_active_for_date(&datetime.date())
{
return false;
}
let time_trip_start = chrono::NaiveTime::from_num_seconds_from_midnight_opt(self.schedule.first().unwrap().arrival_time as u32 % (60*60*24), 0).unwrap();
let time_trip_start = chrono::NaiveTime::from_num_seconds_from_midnight_opt(
self.schedule.first().unwrap().arrival_time as u32 % (60 * 60 * 24),
0,
)
.unwrap();
let mut dt_trip_start = chrono::NaiveDateTime::new(datetime.date(), time_trip_start);
if self.schedule.first().unwrap().arrival_time > (60*60*24) {
if self.schedule.first().unwrap().arrival_time > (60 * 60 * 24) {
dt_trip_start = dt_trip_start.checked_add_days(Days::new(1)).unwrap();
}
let time_trip_end = chrono::NaiveTime::from_num_seconds_from_midnight_opt(self.schedule.last().unwrap().arrival_time as u32 % (60*60*24), 0).unwrap();
let time_trip_end = chrono::NaiveTime::from_num_seconds_from_midnight_opt(
self.schedule.last().unwrap().arrival_time as u32 % (60 * 60 * 24),
0,
)
.unwrap();
let mut dt_trip_end = chrono::NaiveDateTime::new(datetime.date(), time_trip_end);
if self.schedule.last().unwrap().arrival_time > (60*60*24) {
if self.schedule.last().unwrap().arrival_time > (60 * 60 * 24) {
dt_trip_end = dt_trip_end.checked_add_days(Days::new(1)).unwrap();
}
return *datetime >= dt_trip_start && *datetime <= dt_trip_end;
}
}
@ -58,7 +69,7 @@ impl Trip {
pub enum TripTracking {
Tracked(LiveTrip),
Untracked,
Cancelled
Cancelled,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@ -72,7 +83,7 @@ pub struct CalendarDay {
pub saturday: bool,
pub sunday: bool,
pub start_date: chrono::NaiveDate,
pub end_date: chrono::NaiveDate
pub end_date: chrono::NaiveDate,
}
impl CalendarDay {
@ -99,17 +110,18 @@ pub enum SeatAvailability {
CrushedStandingRoomOnly = 3,
FewSeats = 2,
ManySeats = 1,
Empty = 0
Empty = 0,
}
impl<'de> Deserialize<'de> for SeatAvailability {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de> {
where
D: serde::Deserializer<'de>,
{
let string = String::deserialize(deserializer)?;
return match SeatAvailability::from_string(&string) {
Some(x) => Ok(x),
None => Err(serde::de::Error::custom(""))
None => Err(serde::de::Error::custom("")),
};
}
}
@ -123,10 +135,15 @@ impl Serialize for SeatAvailability {
}
}
impl SeatAvailability {
pub fn iter() -> Vec<SeatAvailability> {
vec![Self::Empty, Self::ManySeats, Self::FewSeats, Self::CrushedStandingRoomOnly, Self::Full]
vec![
Self::Empty,
Self::ManySeats,
Self::FewSeats,
Self::CrushedStandingRoomOnly,
Self::Full,
]
}
pub fn to_string(&self) -> String {
@ -138,14 +155,14 @@ impl SeatAvailability {
Self::Empty => "EMPTY",
})
}
pub fn to_human_string(&self) -> String {
String::from(match &self {
Self::Full => "Full",
Self::CrushedStandingRoomOnly => "Sardines",
Self::FewSeats => "Few seats",
Self::ManySeats => "Many seats",
Self::Empty => "Empty"
Self::Empty => "Empty",
})
}
@ -156,10 +173,10 @@ impl SeatAvailability {
"FEW_SEATS_AVAILABLE" => Some(Self::FewSeats),
"MANY_SEATS_AVAILABLE" => Some(Self::ManySeats),
"EMPTY" => Some(Self::Empty),
_ => None
_ => None,
}
}
pub fn from_opt_string(opt_str: &Option<String>) -> Option<SeatAvailability> {
if let Some(str) = &opt_str {
Self::from_string(str)