use iced::time::{self, Duration, Instant, milliseconds}; use std::collections::HashMap; use std::fmt::{Formatter, Error}; use serde::{Deserialize, Serialize}; use iced::widget::{center, column, row, text}; use iced::{Element, Subscription, Theme, Center}; mod card_reader; mod approx_time; static DURATION: u64 = 60; #[derive(Serialize, Deserialize)] struct RacerTime{ #[serde(with = "approx_time")] time: Instant, racer: Racer, } #[derive(Serialize, Deserialize)] struct State{ racers: Vec, db: HashMap, #[serde(with = "approx_time")] time: Instant, } impl Default for State { fn default() -> Self { Self { racers: vec![RacerTime{time: Instant::now(), racer: Racer{starting_number:11,racer_id: 0, card_id: 0}}], db: Default::default(), time: Instant::now(), } } } impl State{ fn update(&mut self, message: Message){ match message { Message::RacerAdded(racer) => { self.db.insert(racer.card_id, racer); }, Message::Tick(time) => { if let Some(racer_time) = self.racers.iter().next() { if time - racer_time.time > Duration::new(DURATION + 10, 0){ self.racers.remove(0); } } self.time = time; }, 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) } }, Message::CardReader(card_reader::Event::Connected) => { println!("Card Reader Connected!") } Message::CardReader(card_reader::Event::Disconnected) => { println!("Card Reader Disconnected!") } } } fn view(&self) -> Element { let mut content = column![ row![ text("Číslo závodníka").width(120).align_x(Center).align_y(Center), text("čas").size(20).width(120).align_x(Center).align_y(Center) ], ]; for racer_time in &self.racers { const MINUTE: u64 = 60; let time = self.time - racer_time.time; let duration = Duration::new(DURATION, 0); let (duration, negative) = if duration < time { (time - duration, true) } else { (duration - time, false) }; let seconds = duration.as_secs(); let duration = text!( "{}{:0>2}:{:0>2}.{:0>2}", if negative {"-"} else {""}, seconds / MINUTE, seconds % MINUTE, duration.subsec_millis() / 10, ).size(20).width(120).align_x(Center).align_y(Center); content = content.push( row![ text(racer_time.racer.starting_number.to_string()).size(20).width(120).align_x(Center).align_y(Center), duration ] ); } center(content).into() } fn subscription(&self) -> Subscription { Subscription::batch(vec![ time::every(milliseconds(10)).map(Message::Tick), Subscription::run(card_reader::connect).map(Message::CardReader) ]) } fn theme(&self) -> Theme { Theme::Dark } } #[derive(Serialize, Deserialize, Clone)] struct Racer{ starting_number: usize, card_id: usize, } enum Message{ CardReader(card_reader::Event), RacerAdded(Racer), Tick(Instant), } impl std::fmt::Debug for Message { // Required method fn fmt(&self, _f: &mut Formatter<'_>) -> Result<(), Error>{ todo!() } } pub fn main() -> iced::Result { env_logger::init(); iced::application(State::default, State::update, State::view) .subscription(State::subscription) .theme(State::theme) .run() }