use anyhow::Result; use rfactor_sm_reader::*; use std::{cell::RefCell, rc::Rc, time::Instant}; use crate::write_log; use super::UiOverlay; pub trait DataReceiver { fn scoring_update( &mut self, phase: GamePhase, vehicle_scoring: &[VehicleScoringInfoV01], ) -> Result<()>; fn telemetry_update( &mut self, player_id: Option, telemetries: &[rF2VehicleTelemetry], ) -> Result<()>; } #[derive(Clone, Copy, Debug)] pub enum GamePhase { TestDay, Practice, Qualifying, Warmup, Race, } impl TryFrom for GamePhase { type Error = anyhow::Error; fn try_from(value: i32) -> Result { Ok(match value { 0 => Self::TestDay, 1..=4 => Self::Practice, 5..=8 => Self::Qualifying, 9 => Self::Warmup, 10..=13 => Self::Race, _ => return Err(anyhow::anyhow!("Failed to parse GamePhase from: {}", value)), }) } } pub struct RFactorData { // rf2 memory mapped data telemetry_reader: TelemetryReader, scoring_reader: ScoringReader, start_time: Instant, player_id: Option, receivers: Vec>>, } impl RFactorData { pub fn new() -> Result { write_log!(" =================== create RFactorData ==================="); let start_time = Instant::now(); Ok(Self { telemetry_reader: TelemetryReader::new(start_time.elapsed().as_secs_f32())?, scoring_reader: ScoringReader::new(start_time.elapsed().as_secs_f32())?, start_time, player_id: None, receivers: Vec::new(), }) } pub fn add_receiver(&mut self, receiver: Rc>) { self.receivers.push(receiver); } fn now(&self) -> f32 { self.start_time.elapsed().as_secs_f32() } pub fn update(&mut self) -> Result<()> { write_log!(" =================== update RFactorData ==================="); // get scoring info if let Some((scoring_info, vehicle_scorings)) = self.scoring_reader.vehicle_scoring(self.now()) { write_log!(format!( "new scoring info: vehicles: {}", scoring_info.mNumVehicles )); // check for player id if scoring_info.mNumVehicles == 0 { self.player_id = None; } else if self.player_id.is_none() { for vehicle_scoring in vehicle_scorings.iter() { if vehicle_scoring.mIsPlayer != 0 { write_log!(format!("player found: {}", vehicle_scoring.mID)); self.player_id = Some(vehicle_scoring.mID); break; } } } let phase = GamePhase::try_from(scoring_info.mSession)?; write_log!(format!("GamePhase: {:?}", phase)); for receiver in self.receivers.iter() { receiver .borrow_mut() .scoring_update(phase, &vehicle_scorings)?; } } // check telemetry data write_log!("before telemetry update"); if let Some(telemetries) = self.telemetry_reader.query_telemetry(self.now()) { write_log!("new telemetry update"); for receiver in self.receivers.iter() { receiver .borrow_mut() .telemetry_update(self.player_id, &telemetries)?; } } Ok(()) } }