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, vehicle_scoring: &[VehicleScoringInfoV01]) -> Result<()>; fn telemetry_update( &mut self, player_id: Option, telemetries: &[rF2VehicleTelemetry], ) -> Result<()>; } 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; } } } for receiver in self.receivers.iter() { receiver.borrow_mut().scoring_update(&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(()) } }