add preliminary nta support

This commit is contained in:
Nicholas Orlowsky 2026-01-12 22:46:53 -05:00
parent a7d323056a
commit 1d66553398
No known key found for this signature in database
GPG key ID: A9F3BA4C0AA7A70B
21 changed files with 3318 additions and 257 deletions

View file

@ -1,18 +1,41 @@
use std::{hash::{Hash, Hasher}, sync::Arc};
use serde::{Deserialize, Serialize};
#[derive(sqlx::Type, PartialEq, Debug, Clone, Serialize, Deserialize)]
#[derive(sqlx::Type, Eq, PartialEq, Debug, Clone, Serialize, Deserialize)]
#[sqlx(type_name = "septa_stop_type", rename_all = "snake_case")]
pub enum StopType {
pub enum PlatformLocationType {
FarSide,
MiddleBlockNearSide,
Normal
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Stop {
pub id: String,
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum StopType {
SinglePlatform(Arc<Platform>),
MultiPlatform(Vec<Arc<Platform>>)
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Platform {
pub id: String,
pub name: String,
pub lat: f64,
pub lng: f64,
pub stop_type: StopType
pub platform_location: PlatformLocationType
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Stop {
pub id: String,
pub name: String,
pub platforms: StopType,
}
impl Hash for Stop {
fn hash<H: Hasher>(&self, state: &mut H) {
self.id.hash(state)
}
}
impl Eq for Stop {}

View file

@ -1,21 +1,51 @@
use std::sync::Arc;
use chrono::{Datelike, Days, TimeZone, Weekday};
use serde::{Deserialize, Serialize};
use crate::direction::Direction;
use crate::{direction::Direction, route::Route, stop::Platform};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StopSchedule {
pub arrival_time: i64,
pub stop_sequence: i64,
pub stop: crate::stop::Stop
pub stop: Arc<crate::stop::Stop>,
pub platform: Arc<Platform>
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Trip {
pub service_id: String,
pub route: Arc<Route>,
pub trip_id: String,
pub direction: Direction,
pub tracking_data: TripTracking,
pub schedule: Vec<StopSchedule>
pub schedule: Vec<StopSchedule>,
pub calendar_day: Arc<CalendarDay>
}
impl Trip {
pub fn is_active_on(&self, datetime: &chrono::NaiveDateTime) -> bool {
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 mut dt_trip_start = chrono::NaiveDateTime::new(datetime.date(), time_trip_start);
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 mut dt_trip_end = chrono::NaiveDateTime::new(datetime.date(), time_trip_end);
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;
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@ -25,6 +55,38 @@ pub enum TripTracking {
Cancelled
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CalendarDay {
pub id: String,
pub monday: bool,
pub tuesday: bool,
pub wednesday: bool,
pub thursday: bool,
pub friday: bool,
pub saturday: bool,
pub sunday: bool,
pub start_date: chrono::NaiveDate,
pub end_date: chrono::NaiveDate
}
impl CalendarDay {
pub fn is_calendar_active_for_date(&self, date: &chrono::NaiveDate) -> bool {
if *date < self.start_date || *date > self.end_date {
return false;
}
match date.weekday() {
Weekday::Mon => self.monday,
Weekday::Tue => self.tuesday,
Weekday::Wed => self.wednesday,
Weekday::Thu => self.thursday,
Weekday::Fri => self.friday,
Weekday::Sat => self.saturday,
Weekday::Sun => self.sunday,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LiveTrip {
pub delay: f64,