Implement scoring reader

This commit is contained in:
hodasemi 2023-01-13 06:41:28 +01:00
parent 8e7600b3d8
commit 4754eca8b6
3 changed files with 121 additions and 73 deletions

View file

@ -37,8 +37,8 @@ struct TelemVect3
void Set( const double a, const double b, const double c ) { x = a; y = b; z = c; }
// Allowed to reference as [0], [1], or [2], instead of .x, .y, or .z, respectively
double &operator[]( long i ) { return( ( &x )[ i ] ); }
const double &operator[]( long i ) const { return( ( &x )[ i ] ); }
double &operator[]( int i ) { return( ( &x )[ i ] ); }
const double &operator[]( int i ) const { return( ( &x )[ i ] ); }
};
@ -140,8 +140,8 @@ struct TelemWheelV01
double mWear; // wear (0.0-1.0, fraction of maximum) ... this is not necessarily proportional with grip loss
char mTerrainName[16]; // the material prefixes from the TDF file
unsigned char mSurfaceType; // 0=dry, 1=wet, 2=grass, 3=dirt, 4=gravel, 5=rumblestrip, 6=special
bool mFlat; // whether tire is flat
bool mDetached; // whether wheel is detached
char mFlat; // whether tire is flat
char mDetached; // whether wheel is detached
double mVerticalTireDeflection;// how much is tire deflected from its (speed-sensitive) radius
double mWheelYLocation; // wheel's y location relative to vehicle y location
@ -274,15 +274,15 @@ struct TelemInfoV01
struct CameraControlInfoV01
{
// Cameras
long mID; // slot ID to view
long mCameraType; // see GraphicsInfoV02 comments for values
int mID; // slot ID to view
int mCameraType; // see GraphicsInfoV02 comments for values
// Replays (note that these are asynchronous)
bool mReplayActive; // This variable is an *input* filled with whether the replay is currently active (as opposed to realtime).
bool mReplayUnused; //
char mReplayActive; // This variable is an *input* filled with whether the replay is currently active (as opposed to realtime).
char mReplayUnused; //
unsigned char mReplayCommand; // 0=do nothing, 1=begin, 2=end, 3=rewind, 4=fast backwards, 5=backwards, 6=slow backwards, 7=stop, 8=slow play, 9=play, 10=fast play, 11=fast forward
bool mReplaySetTime; // Whether to skip to the following replay time:
char mReplaySetTime; // Whether to skip to the following replay time:
float mReplaySeconds; // The replay time in seconds to skip to (note: the current replay maximum ET is passed into this variable in case you need it)
//
@ -303,7 +303,7 @@ struct MessageInfoV01
struct VehicleScoringInfoV01
{
long mID; // slot ID (note that it can be re-used in multiplayer after someone leaves)
int mID; // slot ID (note that it can be re-used in multiplayer after someone leaves)
char mDriverName[32]; // driver name
char mVehicleName[64]; // vehicle name
short mTotalLaps; // laps completed
@ -325,18 +325,18 @@ struct VehicleScoringInfoV01
short mNumPitstops; // number of pitstops made
short mNumPenalties; // number of outstanding penalties
bool mIsPlayer; // is this the player's vehicle
char mIsPlayer; // is this the player's vehicle
signed char mControl; // who's in control: -1=nobody (shouldn't get this), 0=local player, 1=local AI, 2=remote, 3=replay (shouldn't get this)
bool mInPits; // between pit entrance and pit exit (not always accurate for remote vehicles)
char mInPits; // between pit entrance and pit exit (not always accurate for remote vehicles)
unsigned char mPlace; // 1-based position
char mVehicleClass[32]; // vehicle class
// Dash Indicators
double mTimeBehindNext; // time behind vehicle in next higher place
long mLapsBehindNext; // laps behind vehicle in next higher place
int mLapsBehindNext; // laps behind vehicle in next higher place
double mTimeBehindLeader; // time behind leader
long mLapsBehindLeader; // laps behind leader
int mLapsBehindLeader; // laps behind leader
double mLapStartET; // time this lap was started
// Position and derivatives
@ -356,16 +356,16 @@ struct VehicleScoringInfoV01
unsigned char mServerScored; // whether this vehicle is being scored by server (could be off in qualifying or racing heats)
unsigned char mIndividualPhase;// game phases (described below) plus 9=after formation, 10=under yellow, 11=under blue (not used)
long mQualification; // 1-based, can be -1 when invalid
int mQualification; // 1-based, can be -1 when invalid
double mTimeIntoLap; // estimated time into lap
double mEstimatedLapTime; // estimated laptime used for 'time behind' and 'time into lap' (note: this may changed based on vehicle and setup!?)
char mPitGroup[24]; // pit group (same as team name unless pit is shared)
unsigned char mFlag; // primary flag being shown to vehicle (currently only 0=green or 6=blue)
bool mUnderYellow; // whether this car has taken a full-course caution flag at the start/finish line
char mUnderYellow; // whether this car has taken a full-course caution flag at the start/finish line
unsigned char mCountLapFlag; // 0 = do not count lap or time, 1 = count lap but not time, 2 = count lap and time
bool mInGarageStall; // appears to be within the correct garage stall
char mInGarageStall; // appears to be within the correct garage stall
unsigned char mUpgradePack[16]; // Coded upgrades
@ -378,14 +378,14 @@ struct VehicleScoringInfoV01
struct ScoringInfoV01
{
char mTrackName[64]; // current track name
long mSession; // current session (0=testday 1-4=practice 5-8=qual 9=warmup 10-13=race)
int mSession; // current session (0=testday 1-4=practice 5-8=qual 9=warmup 10-13=race)
double mCurrentET; // current time
double mEndET; // ending time
long mMaxLaps; // maximum laps
int mMaxLaps; // maximum laps
double mLapDist; // distance around track
char *mResultsStream; // results stream additions since last update (newline-delimited and NULL-terminated)
long mNumVehicles; // current number of vehicles
int mNumVehicles; // current number of vehicles
// Game phases:
// 0 Before session has begun
@ -414,7 +414,7 @@ struct ScoringInfoV01
signed char mSectorFlag[3]; // whether there are any local yellows at the moment in each sector (not sure if sector 0 is first or last, so test)
unsigned char mStartLight; // start light frame (number depends on track)
unsigned char mNumRedLights; // number of red lights in start sequence
bool mInRealtime; // in realtime as opposed to at the monitor
char mInRealtime; // in realtime as opposed to at the monitor
char mPlayerName[32]; // player name (including possible multiplayer override)
char mPlrFileName[64]; // may be encoded to be a legal filename
@ -441,7 +441,7 @@ struct CommentaryRequestInfoV01
double mInput1; // first value to pass in (if any)
double mInput2; // first value to pass in (if any)
double mInput3; // first value to pass in (if any)
bool mSkipChecks; // ignores commentary detail and random probability of event
char mSkipChecks; // ignores commentary detail and random probability of event
// constructor (for noobs, this just helps make sure everything is initialized to something reasonable)
CommentaryRequestInfoV01() { mName[0] = 0; mInput1 = 0.0; mInput2 = 0.0; mInput3 = 0.0; mSkipChecks = false; }
@ -508,7 +508,7 @@ struct CustomControlInfoV01
{
// The name passed through CheckHWControl() will be the mUntranslatedName prepended with an underscore (e.g. "Track Map Toggle" -> "_Track Map Toggle")
char mUntranslatedName[ 64 ]; // name of the control that will show up in UI (but translated if available)
long mRepeat; // 0=registers once per hit, 1=registers once, waits briefly, then starts repeating quickly, 2=registers as long as key is down
int mRepeat; // 0=registers once per hit, 1=registers once, waits briefly, then starts repeating quickly, 2=registers as int as key is down
unsigned char mExpansion[ 64 ]; // future use
};
@ -530,10 +530,10 @@ struct WeatherControlInfoV01
double mAmbientTempK; // ambient temperature (Kelvin)
double mWindMaxSpeed; // maximum speed of wind (ground speed, but it affects how fast the clouds move, too)
bool mApplyCloudinessInstantly; // preferably we roll the new clouds in, but you can instantly change them now
bool mUnused1; //
bool mUnused2; //
bool mUnused3; //
char mApplyCloudinessInstantly; // preferably we roll the new clouds in, but you can instantly change them now
char mUnused1; //
char mUnused2; //
char mUnused3; //
unsigned char mExpansion[ 508 ]; // future use (humidity, pressure, air density, etc.)
};
@ -546,8 +546,8 @@ struct WeatherControlInfoV01
struct CustomVariableV01
{
char mCaption[ 128 ]; // Name of variable. This will be used for storage. In the future, this may also be used in the UI (after attempting to translate).
long mNumSettings; // Number of available settings. The special value 0 should be used for types that have limitless possibilities, which will be treated as a string type.
long mCurrentSetting; // Current setting (also the default setting when returned in GetCustomVariable()). This is zero-based, so: ( 0 <= mCurrentSetting < mNumSettings )
int mNumSettings; // Number of available settings. The special value 0 should be used for types that have limitless possibilities, which will be treated as a string type.
int mCurrentSetting; // Current setting (also the default setting when returned in GetCustomVariable()). This is zero-based, so: ( 0 <= mCurrentSetting < mNumSettings )
// future expansion
unsigned char mExpansion[ 256 ];
@ -561,22 +561,22 @@ struct CustomSettingV01
struct MultiSessionParticipantV01
{
// input only
long mID; // slot ID (if loaded) or -1 (if currently disconnected)
int mID; // slot ID (if loaded) or -1 (if currently disconnected)
char mDriverName[ 32 ]; // driver name
char mVehicleName[ 64 ]; // vehicle name
unsigned char mUpgradePack[ 16 ]; // coded upgrades
float mBestPracticeTime; // best practice time
long mQualParticipantIndex; // once qualifying begins, this becomes valid and ranks participants according to practice time if possible
int mQualParticipantIndex; // once qualifying begins, this becomes valid and ranks participants according to practice time if possible
float mQualificationTime[ 4 ]; // best qualification time in up to 4 qual sessions
float mFinalRacePlace[ 4 ]; // final race place in up to 4 race sessions
float mFinalRaceTime[ 4 ]; // final race time in up to 4 race sessions
// input/output
bool mServerScored; // whether vehicle is allowed to participate in current session
long mGridPosition; // 1-based grid position for current race session (or upcoming race session if it is currently warmup), or -1 if currently disconnected
// long mPitIndex;
// long mGarageIndex;
char mServerScored; // whether vehicle is allowed to participate in current session
int mGridPosition; // 1-based grid position for current race session (or upcoming race session if it is currently warmup), or -1 if currently disconnected
// int mPitIndex;
// int mGarageIndex;
// future expansion
unsigned char mExpansion[ 128 ];
@ -585,17 +585,17 @@ struct MultiSessionParticipantV01
struct MultiSessionRulesV01
{
// input only
long mSession; // current session (0=testday 1-4=practice 5-8=qual 9=warmup 10-13=race)
long mSpecialSlotID; // slot ID of someone who just joined, or -2 requesting to update qual order, or -1 (default/general)
int mSession; // current session (0=testday 1-4=practice 5-8=qual 9=warmup 10-13=race)
int mSpecialSlotID; // slot ID of someone who just joined, or -2 requesting to update qual order, or -1 (default/general)
char mTrackType[ 32 ]; // track type from GDB
long mNumParticipants; // number of participants (vehicles)
int mNumParticipants; // number of participants (vehicles)
// input/output
MultiSessionParticipantV01 *mParticipant; // array of partipants (vehicles)
long mNumQualSessions; // number of qualifying sessions configured
long mNumRaceSessions; // number of race sessions configured
long mMaxLaps; // maximum laps allowed in current session (LONG_MAX = unlimited) (note: cannot currently edit in *race* sessions)
long mMaxSeconds; // maximum time allowed in current session (LONG_MAX = unlimited) (note: cannot currently edit in *race* sessions)
int mNumQualSessions; // number of qualifying sessions configured
int mNumRaceSessions; // number of race sessions configured
int mMaxLaps; // maximum laps allowed in current session (LONG_MAX = unlimited) (note: cannot currently edit in *race* sessions)
int mMaxSeconds; // maximum time allowed in current session (LONG_MAX = unlimited) (note: cannot currently edit in *race* sessions)
char mName[ 32 ]; // untranslated name override for session (please use mixed case here, it should get uppercased if necessary)
// future expansion
@ -622,7 +622,7 @@ struct TrackRulesActionV01
{
// input only
TrackRulesCommandV01 mCommand; // recommended action
long mID; // slot ID if applicable
int mID; // slot ID if applicable
double mET; // elapsed time that event occurred, if applicable
};
@ -646,18 +646,18 @@ enum TrackRulesColumnV01
struct TrackRulesParticipantV01
{
// input only
long mID; // slot ID
int mID; // slot ID
short mFrozenOrder; // 0-based place when caution came out (not valid for formation laps)
short mPlace; // 1-based place (typically used for the initialization of the formation lap track order)
float mYellowSeverity; // a rating of how much this vehicle is contributing to a yellow flag (the sum of all vehicles is compared to TrackRulesV01::mSafetyCarThreshold)
double mCurrentRelativeDistance; // equal to ( ( ScoringInfoV01::mLapDist * this->mRelativeLaps ) + VehicleScoringInfoV01::mLapDist )
// input/output
long mRelativeLaps; // current formation/caution laps relative to safety car (should generally be zero except when safety car crosses s/f line); this can be decremented to implement 'wave around' or 'beneficiary rule' (a.k.a. 'lucky dog' or 'free pass')
int mRelativeLaps; // current formation/caution laps relative to safety car (should generally be zero except when safety car crosses s/f line); this can be decremented to implement 'wave around' or 'beneficiary rule' (a.k.a. 'lucky dog' or 'free pass')
TrackRulesColumnV01 mColumnAssignment;// which column (line/lane) that participant is supposed to be in
long mPositionAssignment; // 0-based position within column (line/lane) that participant is supposed to be located at (-1 is invalid)
bool mAllowedToPit; // whether the rules allow this particular vehicle to enter pits right now
bool mUnused[ 3 ]; //
int mPositionAssignment; // 0-based position within column (line/lane) that participant is supposed to be located at (-1 is invalid)
char mAllowedToPit; // whether the rules allow this particular vehicle to enter pits right now
char mUnused[ 3 ]; //
double mGoalRelativeDistance; // calculated based on where the leader is, and adjusted by the desired column spacing and the column/position assignments
char mMessage[ 96 ]; // a message for this participant to explain what is going on (untranslated; it will get run through translator on client machines)
@ -682,16 +682,16 @@ struct TrackRulesV01
double mCurrentET; // current time
TrackRulesStageV01 mStage; // current stage
TrackRulesColumnV01 mPoleColumn; // column assignment where pole position seems to be located
long mNumActions; // number of recent actions
int mNumActions; // number of recent actions
TrackRulesActionV01 *mAction; // array of recent actions
long mNumParticipants; // number of participants (vehicles)
int mNumParticipants; // number of participants (vehicles)
bool mYellowFlagDetected; // whether yellow flag was requested or sum of participant mYellowSeverity's exceeds mSafetyCarThreshold
bool mYellowFlagLapsWasOverridden; // whether mYellowFlagLaps (below) is an admin request
char mYellowFlagDetected; // whether yellow flag was requested or sum of participant mYellowSeverity's exceeds mSafetyCarThreshold
char mYellowFlagLapsWasOverridden; // whether mYellowFlagLaps (below) is an admin request
bool mSafetyCarExists; // whether safety car even exists
bool mSafetyCarActive; // whether safety car is active
long mSafetyCarLaps; // number of laps
char mSafetyCarExists; // whether safety car even exists
char mSafetyCarActive; // whether safety car is active
int mSafetyCarLaps; // number of laps
float mSafetyCarThreshold; // the threshold at which a safety car is called out (compared to the sum of TrackRulesParticipantV01::mYellowSeverity for each vehicle)
double mSafetyCarLapDist; // safety car lap distance
float mSafetyCarLapDistAtStart; // where the safety car starts from
@ -706,7 +706,7 @@ struct TrackRulesV01
signed char mYellowFlagState; // see ScoringInfoV01 for values
short mYellowFlagLaps; // suggested number of laps to run under yellow (may be passed in with admin command)
long mSafetyCarInstruction; // 0=no change, 1=go active, 2=head for pits
int mSafetyCarInstruction; // 0=no change, 1=go active, 2=head for pits
float mSafetyCarSpeed; // maximum speed at which to drive
float mSafetyCarMinimumSpacing; // minimum spacing behind safety car (-1 to indicate no limit)
float mSafetyCarMaximumSpacing; // maximum spacing behind safety car (-1 to indicate no limit)
@ -727,12 +727,12 @@ struct TrackRulesV01
struct PitMenuV01
{
long mCategoryIndex; // index of the current category
int mCategoryIndex; // index of the current category
char mCategoryName[ 32 ]; // name of the current category (untranslated)
long mChoiceIndex; // index of the current choice (within the current category)
int mChoiceIndex; // index of the current choice (within the current category)
char mChoiceString[ 32 ]; // name of the current choice (may have some translated words)
long mNumChoices; // total number of choices (0 <= mChoiceIndex < mNumChoices)
int mNumChoices; // total number of choices (0 <= mChoiceIndex < mNumChoices)
unsigned char mExpansion[ 256 ]; // for future use
};

View file

@ -53,6 +53,10 @@ pub struct rF2Scoring {
impl rF2Scoring {
pub const SIZE: usize = mem::size_of::<Self>();
pub fn vehicles(&self) -> &[VehicleScoringInfoV01] {
&self.vehicles[0..self.scoring_info.mNumVehicles as usize]
}
}
impl From<&[u8]> for rF2Scoring {
@ -194,7 +198,7 @@ pub struct rF2Wheel {
pub pressure: f64,
pub temperature: [f64; 3],
pub wear: f64,
pub terrain_name: [u8; 16usize],
pub terrain_name: [u8; 16],
pub surface_type: u8,
pub flat: u8,
pub detached: u8,
@ -207,5 +211,5 @@ pub struct rF2Wheel {
pub tire_carcass_temperature: f64,
pub tire_inner_layer_temperature: [f64; 3],
expansion: [::std::os::raw::c_uchar; 24usize],
expansion: [::std::os::raw::c_uchar; 24],
}

View file

@ -2,34 +2,78 @@ pub mod additional_rfactor;
#[allow(warnings)]
mod rfactor_structs;
use std::{fs::File, path::Path};
use std::{fs::File, marker::PhantomData, path::Path};
use additional_rfactor::*;
pub use additional_rfactor::{rF2Vec3, rF2VehicleTelemetry, rF2Wheel};
use anyhow::Result;
use memmap2::Mmap;
pub use rfactor_structs::{ScoringInfoV01, VehicleScoringInfoV01};
const RFACTOR_SHM_FILE: &str = "/dev/shm";
pub struct TelemetryReader {
_telemetry_file: File,
struct ShMReader<T> {
_file: File,
shm: Mmap,
data: PhantomData<T>,
}
impl<T> ShMReader<T> {
const SIZE: usize = std::mem::size_of::<T>();
fn new(mm_file_name: &str) -> Result<Self> {
let file = File::open(Path::new(RFACTOR_SHM_FILE).join(mm_file_name))?;
let mmap = unsafe { Mmap::map(&file)? };
Ok(Self {
_file: file,
shm: mmap,
data: PhantomData,
})
}
}
impl<'a, T> ShMReader<T>
where
T: From<&'a [u8]>,
{
fn read(&'a self) -> T {
T::from(&self.shm[0..Self::SIZE])
}
}
pub struct TelemetryReader {
mm_reader: ShMReader<rF2Telemetry>,
}
impl TelemetryReader {
pub fn new() -> Result<Self> {
let file = File::open(Path::new(RFACTOR_SHM_FILE).join(MM_TELEMETRY_FILE_NAME))?;
let mmap = unsafe { Mmap::map(&file)? };
Ok(Self {
_telemetry_file: file,
shm: mmap,
mm_reader: ShMReader::new(MM_TELEMETRY_FILE_NAME)?,
})
}
pub fn query_telemetry(&self) -> Vec<rF2VehicleTelemetry> {
let telemetry = rF2Telemetry::from(&self.shm[0..rF2Telemetry::SIZE]);
let vehicles = telemetry.vehicles();
vehicles.to_vec()
self.mm_reader.read().vehicles().to_vec()
}
}
pub struct ScoringReader {
mm_reader: ShMReader<rF2Scoring>,
}
impl ScoringReader {
pub fn new() -> Result<Self> {
Ok(Self {
mm_reader: ShMReader::new(MM_SCORING_FILE_NAME)?,
})
}
pub fn vehicle_scoring(&self) -> (ScoringInfoV01, Vec<VehicleScoringInfoV01>) {
let scoring = self.mm_reader.read();
(scoring.scoring_info, scoring.vehicles().to_vec())
}
}