diff --git a/POC_in_rust/Cargo.toml b/POC_in_rust/Cargo.toml index c5a5661..a048bdd 100644 --- a/POC_in_rust/Cargo.toml +++ b/POC_in_rust/Cargo.toml @@ -7,7 +7,8 @@ edition = "2024" env_logger = "0.11.8" futures-lite = "2.6.0" iced = {"git"= "https://github.com/iced-rs/iced.git", "features"=["tokio", "auto-detect-theme", "fira-sans", "tiny-skia", "wgpu", "sipper"]} +lazy_static = "1.5.0" nusb = "0.1.13" serde = {version = "1.0.219", features=["derive"]} serde_json = "1.0.140" -tokio = {version = "1.45.0", features=["time"]} +tokio = {version = "1.45.0", features=["time", "fs", "io-util", "macros"]} diff --git a/POC_in_rust/src/main.rs b/POC_in_rust/src/main.rs index 39d88ff..36bacc9 100644 --- a/POC_in_rust/src/main.rs +++ b/POC_in_rust/src/main.rs @@ -1,16 +1,18 @@ -use iced::time::{self, Duration, Instant, milliseconds}; +use iced::time::{self, Duration, Instant, milliseconds, seconds}; use std::collections::HashMap; -use std::fmt::{Formatter, Error}; +use std::fmt::{Formatter, Error as fmtError}; use serde::{Deserialize, Serialize}; use iced::widget::{center, column, row, text}; -use iced::{Element, Subscription, Theme, Center}; +use iced::{Element, Subscription, Theme, Center, Task}; +use tokio::fs::File; +use tokio::io::AsyncWriteExt; mod card_reader; mod approx_time; +mod config; +use config::CONFIG; -static DURATION: u64 = 60; - #[derive(Serialize, Deserialize)] struct RacerTime{ #[serde(with = "approx_time")] @@ -36,33 +38,49 @@ impl Default for State { } } +async fn dump_state(json: String) -> Result<(), tokio::io::Error> { + let mut file = File::create("state.json").await?; + file.write_all(json.as_bytes()).await?; + Ok(()) +} + impl State{ - fn update(&mut self, message: Message){ + fn update(&mut self, message: Message) -> Task{ match message { Message::RacerAdded(racer) => { self.db.insert(racer.card_id, racer); + Task::none() }, Message::Tick(time) => { if let Some(racer_time) = self.racers.iter().next() { - if time - racer_time.time > Duration::new(DURATION + 10, 0){ + if time - racer_time.time > Duration::new(CONFIG.DURATION + 10, 0){ self.racers.remove(0); } } self.time = time; + Task::none() }, + Message::DumpState(_) => { + let json = serde_json::to_string(self).unwrap(); + Task::perform(dump_state(json), |_| Message::Nothing) + }, + Message::Nothing => Task::none(), Message::CardReader(card_reader::Event::ReadedCardId(card_id)) => { if let Some(racer) = self.db.get(&card_id){ self.racers.push(RacerTime{time: Instant::now(), racer: racer.clone()}) }else{ println!("Racer {} not found in db!", card_id) - } + }; + Task::none() }, Message::CardReader(card_reader::Event::Connected) => { - println!("Card Reader Connected!") - } + println!("Card Reader Connected!"); + Task::none() + }, Message::CardReader(card_reader::Event::Disconnected) => { - println!("Card Reader Disconnected!") - } + println!("Card Reader Disconnected!"); + Task::none() + }, } } fn view(&self) -> Element { @@ -76,7 +94,7 @@ impl State{ let time = self.time - racer_time.time; - let duration = Duration::new(DURATION, 0); + let duration = Duration::new(CONFIG.DURATION, 0); let (duration, negative) = if duration < time { (time - duration, true) } else { @@ -104,7 +122,8 @@ impl State{ fn subscription(&self) -> Subscription { Subscription::batch(vec![ time::every(milliseconds(10)).map(Message::Tick), - Subscription::run(card_reader::connect).map(Message::CardReader) + time::every(seconds(CONFIG.SAVING_INTERVAL)).map(Message::DumpState), + Subscription::run(card_reader::connect).map(Message::CardReader), ]) } fn theme(&self) -> Theme { @@ -122,11 +141,13 @@ enum Message{ CardReader(card_reader::Event), RacerAdded(Racer), Tick(Instant), + DumpState(Instant), + Nothing, } impl std::fmt::Debug for Message { // Required method - fn fmt(&self, _f: &mut Formatter<'_>) -> Result<(), Error>{ + fn fmt(&self, _f: &mut Formatter<'_>) -> Result<(), fmtError>{ todo!() } }