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

237
libseptastic/Cargo.lock generated
View file

@ -8,6 +8,15 @@ version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "atoi"
version = "2.0.0"
@ -53,6 +62,12 @@ dependencies = [
"generic-array",
]
[[package]]
name = "bumpalo"
version = "3.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
[[package]]
name = "byteorder"
version = "1.5.0"
@ -65,12 +80,46 @@ version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
[[package]]
name = "cc"
version = "1.2.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd4932aefd12402b36c60956a4fe0035421f544799057659ff86f923657aada3"
dependencies = [
"find-msvc-tools",
"shlex",
]
[[package]]
name = "cfg-if"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
[[package]]
name = "chrono"
version = "0.4.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
dependencies = [
"iana-time-zone",
"js-sys",
"num-traits",
"serde",
"wasm-bindgen",
"windows-link",
]
[[package]]
name = "chrono-tz"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3"
dependencies = [
"chrono",
"phf",
]
[[package]]
name = "concurrent-queue"
version = "2.5.0"
@ -86,6 +135,12 @@ version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "cpufeatures"
version = "0.2.17"
@ -212,6 +267,12 @@ dependencies = [
"pin-project-lite",
]
[[package]]
name = "find-msvc-tools"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f449e6c6c08c865631d4890cfacf252b3d396c9bcc83adb6623cdb02a8336c41"
[[package]]
name = "flume"
version = "0.11.1"
@ -390,6 +451,30 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "iana-time-zone"
version = "0.1.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"log",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "icu_collections"
version = "2.0.0"
@ -513,6 +598,16 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "js-sys"
version = "0.3.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8"
dependencies = [
"once_cell",
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
@ -538,6 +633,8 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
name = "libseptastic"
version = "0.1.0"
dependencies = [
"chrono",
"chrono-tz",
"serde",
"serde_json",
"sqlx",
@ -688,6 +785,24 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "phf"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7"
dependencies = [
"phf_shared",
]
[[package]]
name = "phf_shared"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981"
dependencies = [
"siphasher",
]
[[package]]
name = "pin-project-lite"
version = "0.2.16"
@ -822,6 +937,12 @@ dependencies = [
"zeroize",
]
[[package]]
name = "rustversion"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "ryu"
version = "1.0.20"
@ -900,6 +1021,12 @@ dependencies = [
"digest",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signature"
version = "2.2.0"
@ -910,6 +1037,12 @@ dependencies = [
"rand_core",
]
[[package]]
name = "siphasher"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
[[package]]
name = "slab"
version = "0.4.10"
@ -1325,6 +1458,51 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
[[package]]
name = "wasm-bindgen"
version = "0.2.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40"
dependencies = [
"bumpalo",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4"
dependencies = [
"unicode-ident",
]
[[package]]
name = "whoami"
version = "1.6.0"
@ -1335,6 +1513,65 @@ dependencies = [
"wasite",
]
[[package]]
name = "windows-core"
version = "0.62.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
dependencies = [
"windows-implement",
"windows-interface",
"windows-link",
"windows-result",
"windows-strings",
]
[[package]]
name = "windows-implement"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-interface"
version = "0.59.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-result"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-strings"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-sys"
version = "0.48.0"

View file

@ -4,6 +4,8 @@ version = "0.1.0"
edition = "2024"
[dependencies]
chrono = { version = "0.4.42", features = [ "serde" ] }
chrono-tz = "0.10.4"
serde = "1.0.219"
serde_json = "1.0.140"
sqlx = "0.8.6"

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,