record granular lap metrics

This commit is contained in:
Scott Pruett 2022-06-11 14:25:56 -04:00
parent 86a1df04ad
commit e524758a42
2 changed files with 49 additions and 5 deletions

View File

@ -16,7 +16,7 @@ use crate::{
image_processing::{self, extract_and_filter, hash_image, to_png_bytes, Region},
learned_tracks::get_track_hash,
ocr_db::OcrDatabase,
state::{AppState, DebugOcrFrame, LapState, RaceState, SharedAppState},
state::{AppState, DebugOcrFrame, LapState, RaceState, SharedAppState, LapMetrics},
};
fn check_penalty(image: &RgbImage, config: &Config) -> bool {
@ -98,6 +98,7 @@ fn handle_new_frame(state: &mut AppState, lap_state: LapState, image: &RgbImage)
if state.current_race.is_none() {
crate::tts::pre_race_summary(&state.tts, state.config.as_ref(), &lap_state);
state.penalties_this_lap = 0;
state.current_lap_metrics = LapMetrics::default();
let track_hash = get_track_hash(state.config.as_ref(), image);
let track_name = state
@ -124,6 +125,8 @@ fn handle_new_frame(state: &mut AppState, lap_state: LapState, image: &RgbImage)
state.current_race = Some(race);
}
state.current_lap_metrics.record(&lap_state);
if check_penalty(image, state.config.as_ref()) {
if !state.detecting_penalty {
state.penalties_this_lap += 1;
@ -147,6 +150,9 @@ fn handle_new_frame(state: &mut AppState, lap_state: LapState, image: &RgbImage)
if let Some(lap) = &merged.lap {
merged.lap = Some(lap - 1);
}
merged.metrics = state.current_lap_metrics.clone();
state.current_lap_metrics = LapMetrics::default();
merged.screenshot = Some(to_png_bytes(image));
merged.penalties = state.penalties_this_lap;
state.penalties_this_lap = 0;

View File

@ -6,11 +6,32 @@ use std::{
use egui_extras::RetainedImage;
use image::RgbImage;
use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};
use time::{format_description, OffsetDateTime};
use crate::{config::Config, learned_tracks::LearnedTracks, ocr_db::OcrDatabase, tts::Tts};
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct LapMetrics {
pub position: Vec<u16>,
pub health: Vec<u8>,
pub gas: Vec<u8>,
pub tyres: Vec<u8>,
}
fn record_metric<T: Copy>(vec: &mut Vec<T>, val: &Option<T>) {
if let Some(v) = val {
vec.push(*v);
}
}
impl LapMetrics {
pub fn record(&mut self, lap: &LapState) {
record_metric(&mut self.position, &lap.position);
record_metric(&mut self.gas, &lap.gas);
record_metric(&mut self.tyres, &lap.tyres);
record_metric(&mut self.health, &lap.health);
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct LapState {
pub lap: Option<u16>,
@ -32,6 +53,8 @@ pub struct LapState {
pub debug: bool,
pub penalties: usize,
pub metrics: LapMetrics,
}
fn parse_duration(time: &str) -> Option<Duration> {
@ -151,7 +174,11 @@ impl RaceState {
}
pub fn fastest_lap(&self) -> Option<Duration> {
self.laps.iter().filter(|lap| !lap.striked).filter_map(|lap| lap.lap_time).min()
self.laps
.iter()
.filter(|lap| !lap.striked)
.filter_map(|lap| lap.lap_time)
.min()
}
pub fn tyre_wear(&self) -> Option<u8> {
@ -163,7 +190,12 @@ impl RaceState {
}
pub fn latest_gas_diff(&self, to: u8) -> Option<u8> {
let last_gas = self.laps.iter().last().map(|l| l.gas).unwrap_or(Some(100))?;
let last_gas = self
.laps
.iter()
.last()
.map(|l| l.gas)
.unwrap_or(Some(100))?;
if to < last_gas {
Some(last_gas - to)
} else {
@ -171,7 +203,12 @@ impl RaceState {
}
}
pub fn latest_tyre_diff(&self, to: u8) -> Option<u8> {
let last_tyres = self.laps.iter().last().map(|l| l.tyres).unwrap_or(Some(100))?;
let last_tyres = self
.laps
.iter()
.last()
.map(|l| l.tyres)
.unwrap_or(Some(100))?;
if to < last_tyres {
Some(last_tyres - to)
} else {
@ -190,6 +227,7 @@ pub struct DebugOcrFrame {
#[derive(Default, Serialize, Deserialize)]
pub struct AppState {
pub last_frame: Option<LapState>,
pub current_lap_metrics: LapMetrics,
pub buffered_frames: VecDeque<LapState>,