diff --git a/src/main.rs b/src/main.rs index 19a7706..afee225 100644 --- a/src/main.rs +++ b/src/main.rs @@ -375,6 +375,23 @@ impl eframe::App for AppUi { .unwrap_or(Duration::from_secs(0)) .as_secs_f32() )); + + if let Some(race) = &state.current_race { + ui.separator(); + ui.heading("Strategy"); + if let Some(tyre_wear) = race.tyre_wear() { + ui.heading(&format!("p50 Tyre Wear: {}", tyre_wear)); + if let Some(tyres) = frame.tyres { + ui.label(&format!("Out of tires in {:.1} lap(s)", (tyres as f64) / (tyre_wear as f64))); + } + } + if let Some(gas_wear) = race.gas_per_lap() { + ui.heading(&format!("p50 Gas Wear: {}", gas_wear)); + if let Some(gas) = frame.gas { + ui.label(&format!("Out of gas in {:.1} lap(s)", (gas as f64) / (gas_wear as f64))); + } + } + } } ui.separator(); diff --git a/src/state.rs b/src/state.rs index 86b83ba..2bb2df5 100644 --- a/src/state.rs +++ b/src/state.rs @@ -63,6 +63,21 @@ impl LapState { } } +fn median_wear(values: Vec>) -> Option { + let mut wear_values = Vec::new(); + let mut last_value = 100; + for val in values { + if let Some(val) = val { + if val < last_value { + wear_values.push(last_value - val); + } + last_value = val; + } + } + wear_values.sort(); + wear_values.get(wear_values.len() / 2).cloned() +} + #[derive(Default)] pub struct RaceState { pub race_time: Option, @@ -94,6 +109,14 @@ impl RaceState { pub fn fastest_lap(&self) -> Option { self.laps.iter().filter_map(|lap| lap.lap_time).min() } + + pub fn tyre_wear(&self) -> Option { + median_wear(self.laps.iter().map(|lap| lap.tyres).collect()) + } + + pub fn gas_per_lap(&self) -> Option { + median_wear(self.laps.iter().map(|lap| lap.gas).collect()) + } } pub struct DebugOcrFrame {