1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
//! Data about all the cars in the session and their lap times
//!
//! The F1 games publish data about each car in a session and their lap times. The frequency with
//! which the packets are sent can be configured in the game. F1 2018 and F1 2019 share the same
//! packet format.

use crate::packet::header::Header;
use derive_new::new;
use getset::{CopyGetters, Getters};
use std::time::Duration;

/// Statuses a driver can have during a lap
#[derive(Debug, PartialEq, Copy, Clone, Eq, Ord, PartialOrd, Hash)]
pub enum DriverStatus {
    /// The driver is still in the garage, and has not left it yet.
    InGarage,

    /// The driver is on a flying lap, and cars that are on an in- or out-lap have to give room.
    FlyingLap,

    /// The driver is on an in-lap, i.e. on the way to the pits. The in-lap is often used to cool
    /// the car down, so the driver might be going slower than normal.
    InLap,

    /// The driver is on an out-lap. The out-lap is used to get heat into the tires and breaks to
    /// optimize them for the following flying lap.
    OutLap,

    /// The driver is on track, but not on a special lap. This is the case during a race or practice
    /// session, where drivers do many laps in a row.
    OnTrack,
}

impl Default for DriverStatus {
    fn default() -> Self {
        DriverStatus::InGarage
    }
}

/// Statuses used to signal the progression of a pit stop
#[derive(Debug, PartialEq, Copy, Clone, Eq, Ord, PartialOrd, Hash)]
pub enum PitStatus {
    /// No pit stop is being performed, and the car is most likely on track or in the garage.
    None,

    /// The car is pitting, which means it is on the pit lane but not stationary in the pit box.
    Pitting,

    /// The car is stationary in the pit box, and the pit stop is being performed.
    InPits,
}

impl Default for PitStatus {
    fn default() -> Self {
        PitStatus::None
    }
}

/// Statuses that classify the result
#[derive(Debug, PartialEq, Copy, Clone, Eq, Ord, PartialOrd, Hash)]
pub enum ResultStatus {
    /// The results are invalid.
    Invalid,

    /// The results are not being collected yet.
    Inactive,

    /// The results are being actively collected.
    Active,

    /// The session has finished and the results are final.
    Finished,

    /// The car has been disqualified from the session.
    Disqualified,

    /// The car failed to classify in the session, for example because it did not achieve the
    /// required number of laps.
    NotClassified,

    /// The car has been retired.
    Retired,
}

impl Default for ResultStatus {
    fn default() -> Self {
        ResultStatus::Invalid
    }
}

/// The three sectors of a race track in F1
#[derive(Debug, PartialEq, Copy, Clone, Eq, Ord, PartialOrd, Hash)]
pub enum Sector {
    /// The first sector
    First,

    /// The second sector
    Second,

    /// The third sector
    Third,
}

impl Default for Sector {
    fn default() -> Self {
        Sector::First
    }
}

/// Data about a car and its lap times
///
/// For each car in the session, a set of lap data is published. It contains data on the current
/// lap, e.g. the current lap time and the sector the car is currently in, but also the time of the
/// last and best lap.
#[derive(new, Debug, Getters, CopyGetters, PartialEq, Copy, Clone, PartialOrd, Default)]
#[allow(clippy::too_many_arguments)]
pub struct Lap {
    /// Returns the time of the last lap.
    #[getset(get = "pub")]
    last_lap_time: Duration,

    /// Returns the time of the current lap.
    #[getset(get = "pub")]
    current_lap_time: Duration,

    /// Returns the time of the best lap.
    #[getset(get = "pub")]
    best_lap_time: Duration,

    /// Returns the time spent in sector 1 during the current lap.
    #[getset(get = "pub")]
    sector1_time: Duration,

    /// Returns the time spent in sector 2 during the current lap.
    #[getset(get = "pub")]
    sector2_time: Duration,

    /// Returns the distance the car has travelled in the current lap in meters.
    #[getset(get_copy = "pub")]
    lap_distance: f32,

    /// Returns the total distance the car has travelled in the session in meters.
    #[getset(get_copy = "pub")]
    total_distance: f32,

    /// Returns the delta during a safety car in seconds.
    #[getset(get = "pub")]
    safety_car_delta: Duration,

    /// Returns a car's position in the race.
    #[getset(get_copy = "pub")]
    position: u8,

    /// Returns the number of the current lap.
    #[getset(get_copy = "pub")]
    current_lap_number: u8,

    /// Returns a car's pit stop status.
    #[getset(get_copy = "pub")]
    pit_status: PitStatus,

    /// Returns the sector the car is currently in.
    #[getset(get_copy = "pub")]
    sector: Sector,

    /// Returns whether the current lap is valid.
    ///
    /// The F1 games apply different rules to determine if a lap is valid. Cutting the track, losing
    /// control, or hitting objects or opponents can all invalidate a lap. This is crucial for
    /// qualifying, where invalid laps might not count for the results.
    #[getset(get_copy = "pub")]
    is_valid_lap: bool,

    /// Returns the accumulated penalties for a car in seconds.
    #[getset(get_copy = "pub")]
    penalties: u8,

    /// Returns the grid position the car started the race in.
    #[getset(get_copy = "pub")]
    grid_position: u8,

    /// Returns the status of the driver.
    #[getset(get_copy = "pub")]
    driver_status: DriverStatus,

    /// Returns the status of the race results.
    #[getset(get_copy = "pub")]
    result_status: ResultStatus,
}

/// Packet containing lap data for all 20 cars in a session
///
/// The F1 games publish a lap packet that contains data on all 20 cars in a session. The packet is
/// sent at a fixed interval that can be configured in the game.
#[derive(new, Debug, Getters, PartialEq, Clone, PartialOrd)]
pub struct LapPacket {
    /// Returns the packet header prefixing the lap data packet.
    #[getset(get = "pub")]
    header: Header,

    /// Returns the laps for all 20 cars in a session.
    #[getset(get = "pub")]
    laps: Vec<Lap>,
}