86 lines
2.5 KiB
Rust

use crate::constants::{MarshalZoneFlag, TemperatureChange, Weather};
use binrw::BinRead;
use serde::{Deserialize, Serialize};
pub(super) const MAX_NUM_MARSHAL_ZONES: usize = 21;
pub(super) const MARSHAL_ZONE_RAW_SIZE: usize = 5;
pub(super) const FORECAST_SAMPLE_RAW_SIZE: usize = 8;
pub(super) const MAX_AI_DIFFICULTY: u8 = 110;
pub(super) const MAX_NUM_SESSIONS: usize = 12;
/// Section of the track supervised by marshals.
#[non_exhaustive]
#[derive(BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize)]
#[br(
little,
import(_packet_format: u16),
assert(
(0.0..1.0).contains(&zone_start),
"Marshal zone has an invalid zone start value: {}",
zone_start
)
)]
pub struct MarshalZone {
/// Fraction (in range `(0.0..1.0)`) of way through the lap the marshal zone starts.
pub zone_start: f32,
/// Flag that's currently being waved in the marshal zone.
pub zone_flag: MarshalZoneFlag,
}
#[non_exhaustive]
/// Weather forecast sample for a given session.
#[derive(
BinRead, Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize,
)]
#[br(
little,
import(_packet_format: u16),
assert(
rain_percentage <= 100,
"Weather forecast sample has an invalid rain percentage value: {}",
rain_percentage
)
)]
pub struct WeatherForecastSample {
/// Session's type.
/// See [`session_type`](mod@crate::constants::session_type)
/// for possible values.
pub session_type: u8,
/// Time in minutes the forecast is for.
pub time_offset: u8,
/// Forecasted weather.
pub weather: Weather,
/// Track temperature in degrees Celsius.
pub track_temperature: i8,
/// Track temperature change.
pub track_temperature_change: TemperatureChange,
/// Air temperature in degrees Celsius.
pub air_temperature: i8,
/// Air temperature change.
pub air_temperature_change: TemperatureChange,
/// Chance of rain.
pub rain_percentage: u8,
}
#[inline(always)]
pub(super) fn check_num_forecast_samples(packet_format: u16, num_samples: usize) -> bool {
num_samples <= get_max_num_samples(packet_format)
}
#[inline(always)]
pub(super) fn get_forecast_samples_padding(
packet_format: u16,
num_samples: usize,
) -> usize {
(get_max_num_samples(packet_format) - num_samples) * FORECAST_SAMPLE_RAW_SIZE
}
#[inline(always)]
fn get_max_num_samples(packet_format: u16) -> usize {
if packet_format == 2024 {
64
} else {
56
}
}