Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/components/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const LOADING: Asset = asset!("/assets/loading.webp");
#[derive(Debug)]
pub enum Action {
Start(Track, DateTime<Utc>),
FinishByStartNumber(StartNumber),
FinishByStartNumber(StartNumber, DateTime<Utc>),
}

fn handle_rfid_event(selected_race: &mut Signal<SelectedRace>, event: rfid_reader::Event) {
Expand All @@ -37,7 +37,7 @@ fn handle_rfid_event(selected_race: &mut Signal<SelectedRace>, event: rfid_reade
info!("Tag {tag}");
selected_race.with_mut(|maybe_race| {
if let Some(Ok(race)) = maybe_race {
race.tag_finished(&tag);
race.tag_finished(&tag, Utc::now());
}
});
}
Expand All @@ -53,10 +53,10 @@ fn handle_action(selected_race: &mut Signal<SelectedRace>, action: Action) {
}
});
}
Action::FinishByStartNumber(starting_number) => {
Action::FinishByStartNumber(starting_number, time) => {
selected_race.with_mut(|maybe_race| {
if let Some(Ok(race)) = maybe_race {
race.finish_start_number(starting_number);
race.finish_start_number(starting_number, time);
}
});
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/manual_start_number_input.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use chrono::Utc;
use dioxus::prelude::*;

use crate::components::app::Action;
Expand All @@ -13,7 +14,7 @@ pub fn ManualStartNumberInput() -> Element {
event.prevent_default();
if let Ok(start_number) = start_number().parse() {
use_coroutine_handle::<Action>()
.send(Action::FinishByStartNumber(start_number));
.send(Action::FinishByStartNumber(start_number, Utc::now()));
}
start_number.set(String::from(""));
},
Expand Down
1 change: 1 addition & 0 deletions src/components/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod app;
pub mod categories_list;
pub mod manual_start_number_input;
pub mod racer_row;
pub mod racers;
pub mod races_list;
pub mod th;
Expand Down
44 changes: 44 additions & 0 deletions src/components/racer_row.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use dioxus::prelude::*;

use crate::components::app::Action;
use crate::components::time_input::TimeInput;
use crate::race::Racer;
use crate::time_utils::{format_time, format_time_delta};

#[component]
pub fn RacerRow(racer: Racer) -> Element {
let editing = use_signal(|| false);
let start_number = racer.start_number.clone();

rsx! {
tr {
td { "{racer.start_number}" }
td { "{racer.first_name}" }
td { "{racer.last_name}" }
td { "{racer.track}" }
td { "{format_time(racer.start)}" }
td { width: "124px",
TimeInput {
time: racer.finish,
editing,
onsave: move |time| {
use_coroutine_handle::<Action>()
.send(Action::FinishByStartNumber(start_number.clone(), time));
},
}
}
td { "{format_time_delta(racer.time)}" }
td { "{racer.track_rank.map(|rank| rank.to_string()).unwrap_or_default() }" }
td {
for category in racer.categories.clone() {
"{category} "
}
}
td {
for category_rank in &racer.categories_rank {
span { class: "me-2", "{category_rank.0}: {category_rank.1}" }
}
}
}
}
}
49 changes: 3 additions & 46 deletions src/components/racers.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,15 @@
use chrono::{DateTime, Local, TimeDelta, Utc};
use dioxus::prelude::*;

use crate::{
components::{
categories_list::CategoriesList,
racer_row::RacerRow,
th::{Sorter, Th},
},
race::{Category, Race, Racer, RacerField},
time_utils::{format_time, format_time_delta},
};

fn format_time(datetime: Option<DateTime<Utc>>) -> String {
match datetime {
Some(datetime) => datetime
.with_timezone(&Local)
.format("%H:%M:%S%.3f")
.to_string(),
None => "".to_string(),
}
}

pub fn format_time_delta(delta: Option<TimeDelta>) -> String {
let delta = match delta {
Some(delta) => delta,
_ => return "".to_string(),
};

let total_millis = delta.num_milliseconds();
let hours = total_millis / 1000 / 3600;
let mins = (total_millis / 1000 / 60) % 60;
let secs = (total_millis / 1000) % 60;
let millis = total_millis % 1000;

format!("{hours:02}:{mins:02}:{secs:02}.{millis:03}")
}

// Checks whether a racer matches all active filters in the map.
// The `filters` map contains RacerField -> Option<String>. Only non-empty Some()
// values are applied. Matching is case-insensitive for string like types.
Expand Down Expand Up @@ -180,26 +156,7 @@ pub fn Racers(race: Race) -> Element {
.iter()
.filter(|racer| matches_filters(racer, &filters(), selected_category_id()))
{
tr {
td { "{racer.start_number}" }
td { "{racer.first_name}" }
td { "{racer.last_name}" }
td { "{racer.track}" }
td { "{format_time(racer.start)}" }
td { "{format_time(racer.finish)}" }
td { "{format_time_delta(racer.time)}" }
td { "{racer.track_rank.map(|rank| rank.to_string()).unwrap_or_default() }" }
td {
for category in racer.categories.clone() {
"{category} "
}
}
td {
for category_rank in &racer.categories_rank {
span { class: "me-2", "{category_rank.0}: {category_rank.1}" }
}
}
}
RacerRow { racer: racer.clone() }
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/time_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub fn TimeInput(
time: Option<DateTime<Utc>>,
editing: Signal<bool>,
onsave: EventHandler<DateTime<Utc>>,
span_class: Option<String>,
) -> Element {
let mut text = use_signal(|| "".to_string());

Expand Down Expand Up @@ -54,7 +55,7 @@ pub fn TimeInput(
}
} else {
span {
class: "input-group-text flex-grow-1",
class: span_class,
ondoubleclick: move |_evt| {
editing.set(true);
},
Expand Down
1 change: 1 addition & 0 deletions src/components/track_start.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub fn TrackStart(track: Track, start: Option<DateTime<Utc>>) -> Element {
TimeInput {
time: start,
editing,
span_class: "input-group-text flex-grow-1",
onsave: move |time| {
use_coroutine_handle::<Action>().send(Action::Start(track.clone(), time));
},
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ mod race;
mod race_events;
mod restclient;
mod rfid_reader;
mod time_utils;

const MAIN_CSS: Asset = asset!("/assets/main.css");
const BOOTSTRAP_CSS: Asset = asset!("/assets/bootstrap.css");
Expand Down
2 changes: 1 addition & 1 deletion src/printer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::components::racers::format_time_delta;
use crate::race::{Race, Racer};
use crate::time_utils::format_time_delta;
use std::path::PathBuf;
use tracing::{error, info};

Expand Down
21 changes: 13 additions & 8 deletions src/race.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,34 +249,39 @@ impl Race {
self.track_starts.insert(track, time);
}

fn finish<F>(&mut self, mut predicate: F) -> Result<(), ()>
fn finish<F>(&mut self, mut predicate: F, time: DateTime<Utc>) -> Result<(), ()>
where
F: for<'a> FnMut(&&'a mut Racer) -> bool,
{
let racer = self.racers.iter_mut().find(|r| predicate(r)).ok_or(())?;
let finish_time = Utc::now();
racer.finish = Some(finish_time);
racer.finish = Some(time);
racer.time = calculate_time(racer.start, racer.finish);
self.log
.borrow_mut()
.log_finish(racer.start_number.clone(), finish_time);
.log_finish(racer.start_number.clone(), time);
self.map_start_number_to_track_rank();
self.map_start_number_to_categories_rank();
Ok(())
}

pub fn finish_start_number(&mut self, start_number: StartNumber) {
pub fn finish_start_number(&mut self, start_number: StartNumber, time: DateTime<Utc>) {
if self
.finish(|r| r.start_number == start_number && r.start.is_some() && r.finish.is_none())
.finish(
|r| r.start_number == start_number && r.start.is_some(),
time,
)
.is_err()
{
error!("Racer with starting number {start_number:?} not found.");
}
}

pub fn tag_finished(&mut self, tag: &str) {
pub fn tag_finished(&mut self, tag: &str, time: DateTime<Utc>) {
if self
.finish(|r| r.tag == tag && r.start.is_some() && r.finish.is_none())
.finish(
|r| r.tag == tag && r.start.is_some() && r.finish.is_none(),
time,
)
.is_err()
{
error!("Racer with tag {tag} not found.");
Expand Down
26 changes: 26 additions & 0 deletions src/time_utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use chrono::{DateTime, Local, TimeDelta, Utc};

pub fn format_time(datetime: Option<DateTime<Utc>>) -> String {
match datetime {
Some(datetime) => datetime
.with_timezone(&Local)
.format("%H:%M:%S%.3f")
.to_string(),
None => "".to_string(),
}
}

pub fn format_time_delta(delta: Option<TimeDelta>) -> String {
let delta = match delta {
Some(delta) => delta,
_ => return "".to_string(),
};

let total_millis = delta.num_milliseconds();
let hours = total_millis / 1000 / 3600;
let mins = (total_millis / 1000 / 60) % 60;
let secs = (total_millis / 1000) % 60;
let millis = total_millis % 1000;

format!("{hours:02}:{mins:02}:{secs:02}.{millis:03}")
}
Loading