#[cfg(test)]
mod tests;
pub mod average_segments;
pub mod balanced_pb;
pub mod best_segments;
pub mod best_split_times;
pub mod goal;
pub mod latest_run;
pub mod median_segments;
pub mod none;
pub mod worst_segments;
pub use self::{
average_segments::AverageSegments, balanced_pb::BalancedPB, best_segments::BestSegments,
best_split_times::BestSplitTimes, latest_run::LatestRun, median_segments::MedianSegments,
none::None, worst_segments::WorstSegments,
};
use crate::{platform::prelude::*, Attempt, Segment, Timer};
use core::fmt::Debug;
pub const RACE_COMPARISON_PREFIX: &str = "[Race]";
pub mod personal_best {
pub const SHORT_NAME: &str = "PB";
pub const NAME: &str = "Personal Best";
}
pub mod world_record {
pub const SHORT_NAME: &str = "WR";
pub const NAME: &str = "World Record";
}
pub trait ComparisonGenerator: Debug + Sync + Send + ComparisonGeneratorClone {
fn name(&self) -> &str;
fn generate(&mut self, segments: &mut [Segment], attempts: &[Attempt]);
}
pub trait ComparisonGeneratorClone {
fn clone_box(&self) -> Box<dyn ComparisonGenerator>;
}
impl<T> ComparisonGeneratorClone for T
where
T: 'static + ComparisonGenerator + Clone,
{
fn clone_box(&self) -> Box<dyn ComparisonGenerator> {
Box::new(self.clone())
}
}
impl Clone for Box<dyn ComparisonGenerator> {
fn clone(&self) -> Self {
self.clone_box()
}
}
pub fn default_generators() -> Vec<Box<dyn ComparisonGenerator>> {
vec![
Box::new(BestSegments),
Box::new(BestSplitTimes),
Box::new(AverageSegments),
Box::new(MedianSegments),
Box::new(WorstSegments),
Box::new(BalancedPB),
Box::new(LatestRun),
Box::new(None),
]
}
pub fn try_shorten(comparison: &str) -> Option<&'static str> {
Some(match comparison {
personal_best::NAME => personal_best::SHORT_NAME,
world_record::NAME => world_record::SHORT_NAME,
average_segments::NAME => average_segments::SHORT_NAME,
median_segments::NAME => median_segments::SHORT_NAME,
balanced_pb::NAME => balanced_pb::SHORT_NAME,
best_segments::NAME => best_segments::SHORT_NAME,
best_split_times::NAME => best_split_times::SHORT_NAME,
latest_run::NAME => latest_run::SHORT_NAME,
none::NAME => none::SHORT_NAME,
worst_segments::NAME => worst_segments::SHORT_NAME,
_ => return Option::None,
})
}
pub fn shorten(comparison: &str) -> &str {
try_shorten(comparison).unwrap_or(comparison)
}
pub fn or_current<'a>(comparison: Option<&'a str>, timer: &'a Timer) -> &'a str {
comparison.unwrap_or_else(|| timer.current_comparison())
}
pub fn resolve<'a>(comparison: &Option<String>, timer: &'a Timer) -> Option<&'a str> {
let comparison = comparison.as_ref()?;
timer.run().comparisons().find(|&rc| comparison == rc)
}