diff --git a/Cargo.toml b/Cargo.toml index 8629e60..47d00c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,13 +8,13 @@ host = "x86_64-unknown-linux-gnu" sdl3 = {version = "0.17", features = ["ttf"]} serde = "1.0" gtfs-structures = "0.47" -chrono = "*" -log = "*" +chrono = "0.4" +log = "0.4" zip = "8.3" csv = "1.4" [profile.dev] -opt-level = 0 +opt-level = 1 [profile.release] opt-level = 3 diff --git a/src/gtfs/arrival.rs b/src/gtfs/arrival.rs new file mode 100644 index 0000000..8b0f95a --- /dev/null +++ b/src/gtfs/arrival.rs @@ -0,0 +1,33 @@ +use std::cmp::Ordering; +use crate::gtfs::structs::Arrival; + + +impl Ord for Arrival<'_> { + fn cmp(&self, other: &Self) -> Ordering { + return self.departure_time.cmp(&other.departure_time); + } +} + +impl PartialOrd for Arrival<'_> { + fn partial_cmp(&self, other: &Self) -> Option { + match self.departure_time.partial_cmp(&other.departure_time) { + Some(core::cmp::Ordering::Equal) => {} + ord => return ord, + } + match self.route.id.partial_cmp(&other.route.id) { + Some(core::cmp::Ordering::Equal) => {} + ord => return ord, + } + self.stop.id.partial_cmp(&other.stop.id) + } +} + +impl PartialEq for Arrival<'_> { + fn eq(&self, other: &Self) -> bool { + self.departure_time == other.departure_time && self.route.id == other.route.id && self.stop.id == other.stop.id + } +} + +impl Eq for Arrival<'_> { + +} \ No newline at end of file diff --git a/src/gtfs/mod.rs b/src/gtfs/mod.rs index 5dda86c..587b393 100644 --- a/src/gtfs/mod.rs +++ b/src/gtfs/mod.rs @@ -1,3 +1,4 @@ +mod arrival; mod loader; mod utils; pub mod structs; diff --git a/src/gtfs/structs.rs b/src/gtfs/structs.rs index 51f7cd4..0bcd116 100644 --- a/src/gtfs/structs.rs +++ b/src/gtfs/structs.rs @@ -14,26 +14,25 @@ pub struct Preferences { #[derive(Debug)] pub struct Gtfs { /// All agencies. They can not be read by `agency_id`, as it is not a required field - pub agencies: Vec, + pub(crate) agencies: Vec, /// All Calendar by `service_id` - pub calendar: HashMap, + pub(crate) calendar: HashMap, /// All calendar dates grouped by service_id - pub calendar_dates: HashMap>, + pub(crate) calendar_dates: HashMap>, /// All routes by `route_id` - pub routes: HashMap, + pub(crate) routes: HashMap, /// All stop by `stop_id`. - pub stops: HashMap, + pub(crate) stops: HashMap, /// All trips by trip_id - pub trips: HashMap, + pub(crate) trips: HashMap, /// Stop times for the chosen stops and the chosen routes - pub stop_times: HashMap<(String, u32), RawStopTime>, + pub(crate) stop_times: HashMap<(String, u32), RawStopTime>, } #[derive(Debug)] - pub struct Arrival<'a> { + pub departure_time: NaiveTime, pub route: &'a Route, pub stop: &'a Stop, - pub departure_time: NaiveTime, } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index e687df0..185cb80 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,19 +1,28 @@ mod gtfs; mod renderer; -use std::{collections::HashSet, process, time::SystemTime}; -use chrono::{DateTime, Local}; -use sdl3::{event::Event, libc::statx_timestamp}; -use log::{Level, Metadata, Record, debug, error, info, warn}; - -use crate::{gtfs::structs::Gtfs, renderer::Screen}; +use std::{collections::HashSet, ops::Add, thread::{Builder}, time::SystemTime}; +use chrono::{DateTime, Duration, Local, NaiveTime}; +use log::{Metadata, Record, debug, info}; +use crate::gtfs::structs::{Arrival, Gtfs}; const SRC_FILE: &str = "/home/nahuel/Downloads/GTFS_Realtime.zip"; +const NUM_ARRIVALS: usize = 4; -fn refresh_schedule(gtfs: &Gtfs) { +fn refresh_schedule(gtfs: &Gtfs) -> Box>> { let current_timestamp = SystemTime::now(); let datetime: DateTime = current_timestamp.clone().into(); - let next_arrivals = gtfs.get_next_arrivals_for(&datetime); - debug!("Next arrivals: {:#?}", next_arrivals); + let mut next_arrivals: Box>> = gtfs.get_next_arrivals_for(&datetime); + + if next_arrivals.len() < NUM_ARRIVALS { + // If we don't have enough entries today, look for arrivals tomorrow. + let mut tomorrow: DateTime = datetime.clone(); + tomorrow = tomorrow.with_time(NaiveTime::from_hms_opt(0, 0, 0).unwrap()).unwrap(); + tomorrow = tomorrow.add(Duration::days(1)); + next_arrivals.append(&mut gtfs.get_next_arrivals_for(&tomorrow)); + } + + next_arrivals.sort(); + return next_arrivals; } @@ -45,7 +54,7 @@ fn main() { stop_codes: HashSet::from([String::from("1117")]) }; - let screen_prefs = renderer::structs::Prefs { + let _screen_prefs = renderer::structs::Prefs { font_path: String::from("resources/jd_lcd_rounded/jd-lcd-rounded.ttf"), screen_width: 1920, screen_height: 720, @@ -61,10 +70,18 @@ fn main() { //println!("Startup done."); // Start an asynchronous refresh thread - //let _update_thread = thread::Builder::new().name("updater".to_string()).spawn(move || { refresh_schedule(>fs) }); + let update_thread = Builder::new() + .name("updater".to_string()) + .spawn(move || { + loop { + let _data = refresh_schedule(>fs); + debug!("-------------------------------- Refresh done."); + std::thread::sleep(std::time::Duration::new(60,0)); + }; + }).unwrap(); + + let _ = update_thread.join(); - refresh_schedule(>fs); - debug!("Refresh done."); // Main event loop /* diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 1e761fe..5bd4845 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -1,22 +1,18 @@ pub mod structs; -use sdl3::{Sdl, pixels::Color, rect::Rect, render::Canvas, ttf::Font, video::Window}; +use sdl3::{Sdl, pixels::Color, rect::Rect}; use structs::{Prefs}; -pub struct Screen<'a> { - canvas: Box>, - font: Box>, - context: Box -} +use crate::renderer::structs::Screen; impl Screen<'_> { - pub fn get_context(&self) -> &Sdl { + pub fn _get_context(&self) -> &Sdl { return &self.context; } - pub fn print(&mut self, line: u32, text: &str) { + pub fn _print(&mut self, line: u32, text: &str) { let rendered_text = self.font.render(text).solid(Color::RED).unwrap(); let texture_creator = self.canvas.texture_creator(); let texture = rendered_text.as_texture(&texture_creator).unwrap(); @@ -35,7 +31,7 @@ impl Screen<'_> { /// Initialize video, allocate buffers and load fonts /// Based on https://github.com/vhspace/sdl3-rs/blob/master/examples/ttf-demo.rs - pub fn init(prefs: &Prefs) -> Screen<'_> { + pub fn _init(prefs: &Prefs) -> Screen<'_> { // Initialize the screen let sdl_context = sdl3::init().unwrap(); let video_subsys = sdl_context.video().unwrap(); diff --git a/src/renderer/structs.rs b/src/renderer/structs.rs index 75ca0ea..50cbd62 100644 --- a/src/renderer/structs.rs +++ b/src/renderer/structs.rs @@ -1,3 +1,11 @@ +use sdl3::{Sdl, render::Canvas, ttf::Font, video::Window}; + + +pub struct Screen<'a> { + pub(crate) canvas: Box>, + pub(crate) font: Box>, + pub(crate) context: Box +} pub struct Prefs { pub font_path: String,