2023-01-20 15:08:14 +00:00
|
|
|
mod bg_generator;
|
2023-01-19 09:23:21 +00:00
|
|
|
mod leaderboard_entry;
|
|
|
|
|
|
|
|
use leaderboard_entry::*;
|
2023-01-20 21:31:43 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
2023-01-19 09:23:21 +00:00
|
|
|
|
2023-01-18 06:09:44 +00:00
|
|
|
use std::{
|
|
|
|
ffi::{c_char, CStr},
|
|
|
|
sync::Arc,
|
|
|
|
};
|
|
|
|
|
|
|
|
use anyhow::Result;
|
|
|
|
use rfactor_sm_reader::{rF2VehicleTelemetry, VehicleScoringInfoV01};
|
|
|
|
use ui::prelude::*;
|
2023-01-20 16:01:21 +00:00
|
|
|
use vulkan_rs::prelude::*;
|
2023-01-18 06:09:44 +00:00
|
|
|
|
2023-01-18 07:55:43 +00:00
|
|
|
use crate::overlay::{
|
|
|
|
rfactor_data::{DataReceiver, GamePhase},
|
|
|
|
UiOverlay,
|
|
|
|
};
|
2023-01-18 07:04:47 +00:00
|
|
|
use crate::write_log;
|
2023-01-18 06:09:44 +00:00
|
|
|
|
2023-01-20 21:31:43 +00:00
|
|
|
use bg_generator::BackgroundGenerator;
|
|
|
|
|
2023-01-23 06:21:52 +00:00
|
|
|
#[derive(Default, Deserialize, Serialize, Clone, Copy, Debug)]
|
2023-01-20 21:31:43 +00:00
|
|
|
pub struct LeaderBoardConfig {
|
|
|
|
first_board_color: [f32; 3],
|
|
|
|
second_board_color: [f32; 3],
|
|
|
|
player_board_color: [f32; 3],
|
|
|
|
}
|
|
|
|
|
|
|
|
impl LeaderBoardConfig {
|
|
|
|
pub const fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
first_board_color: [0.33; 3],
|
|
|
|
second_board_color: [0.51; 3],
|
|
|
|
player_board_color: [0.7, 0.75, 0.15],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-01-20 16:01:21 +00:00
|
|
|
|
2023-01-18 06:09:44 +00:00
|
|
|
pub struct LeaderBoard {
|
|
|
|
gui_handler: Arc<GuiHandler>,
|
2023-01-19 06:40:16 +00:00
|
|
|
leaderboard: Arc<GuiBuilder>,
|
2023-01-19 09:23:21 +00:00
|
|
|
deltaboard: Arc<GuiBuilder>,
|
|
|
|
|
|
|
|
leaderboard_grid: Arc<Grid>,
|
|
|
|
deltaboard_grid: Arc<Grid>,
|
2023-01-18 06:09:44 +00:00
|
|
|
|
2023-01-19 09:23:21 +00:00
|
|
|
leaderboard_entries: Vec<LeaderBoardEntry>,
|
|
|
|
deltaboard_entries: [LeaderBoardEntry; 5],
|
|
|
|
|
|
|
|
leaderboard_redraw: bool,
|
|
|
|
last_player_id: i32,
|
2023-01-18 06:09:44 +00:00
|
|
|
|
2023-01-20 16:01:21 +00:00
|
|
|
entry_backgrounds: [(Arc<Image>, Arc<Image>, Arc<Image>); 2],
|
|
|
|
player_background: (Arc<Image>, Arc<Image>, Arc<Image>),
|
2023-01-18 06:09:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl LeaderBoard {
|
2023-01-19 09:23:21 +00:00
|
|
|
const LEADERBOARD: &str = include_str!("leaderboard_grid.xml");
|
|
|
|
const DELTABOARD: &str = include_str!("deltaboard_grid.xml");
|
2023-01-18 06:09:44 +00:00
|
|
|
|
2023-01-20 21:31:43 +00:00
|
|
|
pub fn new(
|
|
|
|
gui_handler: &Arc<GuiHandler>,
|
|
|
|
leader_board_config: LeaderBoardConfig,
|
|
|
|
) -> Result<Self> {
|
2023-01-19 09:23:21 +00:00
|
|
|
let leaderboard = GuiBuilder::from_str(gui_handler, Self::LEADERBOARD)?;
|
|
|
|
let deltaboard = GuiBuilder::from_str(gui_handler, Self::DELTABOARD)?;
|
2023-01-18 06:09:44 +00:00
|
|
|
|
2023-01-20 16:01:21 +00:00
|
|
|
let leaderboard_grid: Arc<Grid> = leaderboard.element("main_grid")?;
|
2023-01-19 09:23:21 +00:00
|
|
|
let deltaboard_grid = deltaboard.element("main_grid")?;
|
2023-01-18 06:09:44 +00:00
|
|
|
|
2023-01-20 16:01:21 +00:00
|
|
|
let images = {
|
|
|
|
// attach snippet to leader board to let it resize its child element correctly
|
|
|
|
// then use these sizes to create actual UI element background
|
|
|
|
let dummy_snippet = LeaderBoardEntry::create_snippet(gui_handler)?;
|
|
|
|
|
|
|
|
let place: Arc<Icon> = dummy_snippet.element("place")?;
|
|
|
|
let name: Arc<Icon> = dummy_snippet.element("name")?;
|
|
|
|
let time: Arc<Icon> = dummy_snippet.element("time")?;
|
|
|
|
|
|
|
|
leaderboard_grid.attach(dummy_snippet, 0, 0, 1, 1)?;
|
|
|
|
|
|
|
|
let colors = [
|
|
|
|
{
|
2023-01-20 21:31:43 +00:00
|
|
|
let a = leader_board_config.first_board_color;
|
2023-01-20 16:01:21 +00:00
|
|
|
[a[0], a[1], a[2], 1.0]
|
|
|
|
},
|
|
|
|
{
|
2023-01-20 21:31:43 +00:00
|
|
|
let a = leader_board_config.second_board_color;
|
2023-01-20 16:01:21 +00:00
|
|
|
[a[0], a[1], a[2], 1.0]
|
|
|
|
},
|
|
|
|
{
|
2023-01-20 21:31:43 +00:00
|
|
|
let a = leader_board_config.player_board_color;
|
2023-01-20 16:01:21 +00:00
|
|
|
[a[0], a[1], a[2], 1.0]
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
let images = colors
|
|
|
|
.iter()
|
|
|
|
.map(|color| {
|
|
|
|
let images = BackgroundGenerator::generate(
|
|
|
|
gui_handler.device(),
|
|
|
|
gui_handler.queue(),
|
|
|
|
*color,
|
|
|
|
[
|
|
|
|
Self::extent_i_to_u(place.extent()),
|
|
|
|
Self::extent_i_to_u(name.extent()),
|
|
|
|
Self::extent_i_to_u(time.extent()),
|
|
|
|
],
|
|
|
|
)?;
|
|
|
|
|
|
|
|
Ok((images[0].clone(), images[1].clone(), images[2].clone()))
|
|
|
|
})
|
|
|
|
.collect::<Result<Vec<(Arc<Image>, Arc<Image>, Arc<Image>)>>>()?;
|
|
|
|
|
|
|
|
leaderboard_grid.detach(0, 0)?;
|
|
|
|
|
|
|
|
images
|
|
|
|
};
|
|
|
|
|
2023-01-18 06:09:44 +00:00
|
|
|
Ok(Self {
|
|
|
|
gui_handler: gui_handler.clone(),
|
2023-01-19 09:23:21 +00:00
|
|
|
leaderboard,
|
|
|
|
deltaboard,
|
2023-01-20 16:01:21 +00:00
|
|
|
|
2023-01-19 09:23:21 +00:00
|
|
|
leaderboard_grid,
|
|
|
|
deltaboard_grid,
|
|
|
|
|
|
|
|
leaderboard_entries: Vec::new(),
|
|
|
|
deltaboard_entries: [
|
|
|
|
LeaderBoardEntry::empty(gui_handler)?,
|
|
|
|
LeaderBoardEntry::empty(gui_handler)?,
|
|
|
|
LeaderBoardEntry::empty(gui_handler)?,
|
|
|
|
LeaderBoardEntry::empty(gui_handler)?,
|
|
|
|
LeaderBoardEntry::empty(gui_handler)?,
|
|
|
|
],
|
|
|
|
|
|
|
|
leaderboard_redraw: false,
|
|
|
|
last_player_id: -1,
|
2023-01-18 06:09:44 +00:00
|
|
|
|
2023-01-20 16:01:21 +00:00
|
|
|
entry_backgrounds: [images[0].clone(), images[1].clone()],
|
|
|
|
player_background: images[2].clone(),
|
2023-01-18 06:09:44 +00:00
|
|
|
})
|
|
|
|
}
|
2023-01-18 07:04:47 +00:00
|
|
|
|
2023-01-20 16:01:21 +00:00
|
|
|
fn extent_i_to_u((x, y): (i32, i32)) -> (u32, u32) {
|
|
|
|
(x as u32, y as u32)
|
|
|
|
}
|
|
|
|
|
2023-01-18 07:04:47 +00:00
|
|
|
fn c_char_to_string(c: [c_char; 32usize]) -> String {
|
|
|
|
unsafe { CStr::from_ptr(&c as *const c_char) }
|
|
|
|
.to_str()
|
|
|
|
.unwrap()
|
|
|
|
.to_string()
|
|
|
|
}
|
|
|
|
|
2023-01-20 05:56:26 +00:00
|
|
|
fn update_leaderboard<F, D>(
|
2023-01-18 16:02:20 +00:00
|
|
|
&mut self,
|
|
|
|
vehicle_scorings: &[VehicleScoringInfoV01],
|
|
|
|
f: F,
|
2023-01-20 05:56:26 +00:00
|
|
|
d: D,
|
2023-01-18 16:02:20 +00:00
|
|
|
) -> Result<()>
|
|
|
|
where
|
|
|
|
F: Fn(&mut LeaderBoardEntry, &VehicleScoringInfoV01) -> Result<()>,
|
2023-01-20 05:56:26 +00:00
|
|
|
D: Fn(&mut LeaderBoardEntry) -> Result<()>,
|
2023-01-18 16:02:20 +00:00
|
|
|
{
|
2023-01-18 06:09:44 +00:00
|
|
|
for vehicle_scoring in vehicle_scorings {
|
2023-01-18 07:04:47 +00:00
|
|
|
let driver_name = Self::c_char_to_string(vehicle_scoring.mDriverName);
|
|
|
|
|
2023-01-18 06:09:44 +00:00
|
|
|
// check driver list
|
|
|
|
match self
|
2023-01-19 09:23:21 +00:00
|
|
|
.leaderboard_entries
|
2023-01-18 06:09:44 +00:00
|
|
|
.iter_mut()
|
2023-01-18 07:04:47 +00:00
|
|
|
.find(|entry| vehicle_scoring.mID == entry.id())
|
2023-01-18 06:09:44 +00:00
|
|
|
{
|
2023-01-20 05:56:26 +00:00
|
|
|
// update existing entry
|
2023-01-18 06:09:44 +00:00
|
|
|
Some(entry) => {
|
2023-01-18 07:04:47 +00:00
|
|
|
if entry.name() != driver_name {
|
|
|
|
entry.change_name(driver_name)?;
|
|
|
|
}
|
|
|
|
|
2023-01-18 06:09:44 +00:00
|
|
|
entry.update_place(vehicle_scoring.mPlace)?;
|
2023-01-18 16:02:20 +00:00
|
|
|
|
|
|
|
f(entry, vehicle_scoring)?;
|
2023-01-18 06:09:44 +00:00
|
|
|
}
|
2023-01-20 05:56:26 +00:00
|
|
|
// add new entry if not found
|
2023-01-18 06:09:44 +00:00
|
|
|
None => {
|
2023-01-20 05:56:26 +00:00
|
|
|
let mut entry = LeaderBoardEntry::new(
|
2023-01-18 06:09:44 +00:00
|
|
|
&self.gui_handler,
|
|
|
|
vehicle_scoring.mID,
|
2023-01-18 07:04:47 +00:00
|
|
|
driver_name,
|
2023-01-18 06:09:44 +00:00
|
|
|
vehicle_scoring.mPlace,
|
2023-01-20 16:21:24 +00:00
|
|
|
Self::query_behind_leader(vehicle_scoring),
|
2023-01-18 06:09:44 +00:00
|
|
|
vehicle_scoring.mTimeBehindNext,
|
2023-01-18 16:02:20 +00:00
|
|
|
vehicle_scoring.mBestLapTime,
|
2023-01-18 06:09:44 +00:00
|
|
|
)?;
|
|
|
|
|
2023-01-20 05:56:26 +00:00
|
|
|
d(&mut entry)?;
|
|
|
|
|
2023-01-19 09:23:21 +00:00
|
|
|
self.leaderboard_entries.push(entry);
|
2023-01-18 06:09:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-18 07:04:47 +00:00
|
|
|
write_log!("create entries");
|
|
|
|
|
2023-01-18 06:09:44 +00:00
|
|
|
// check if entry count in grid is the same as the gathered entries
|
2023-01-19 17:08:13 +00:00
|
|
|
// that means some joined or left the game
|
2023-01-19 09:23:21 +00:00
|
|
|
let force_update = if !self.leaderboard_entries.is_empty()
|
2023-01-19 17:08:13 +00:00
|
|
|
&& self.leaderboard_entries.len() <= self.leaderboard_grid.dimensions().1
|
2023-01-18 07:04:47 +00:00
|
|
|
&& self
|
2023-01-19 09:23:21 +00:00
|
|
|
.leaderboard_grid
|
|
|
|
.child_at(0, self.leaderboard_entries.len() - 1)?
|
2023-01-18 07:04:47 +00:00
|
|
|
.is_none()
|
2023-01-18 06:09:44 +00:00
|
|
|
{
|
2023-01-19 09:23:21 +00:00
|
|
|
for (i, entry) in self.leaderboard_entries.iter().enumerate() {
|
|
|
|
self.leaderboard_grid.detach(0, i)?;
|
|
|
|
entry.snippet().set_visibility(false)?;
|
2023-01-18 06:09:44 +00:00
|
|
|
}
|
|
|
|
|
2023-01-19 14:36:56 +00:00
|
|
|
true
|
|
|
|
}
|
|
|
|
// there are more entries in leaderboard when someone leaves and ID doesn't get reused
|
|
|
|
else if self.leaderboard_entries.len() > vehicle_scorings.len() {
|
|
|
|
self.leaderboard_entries.retain(|entry| {
|
|
|
|
vehicle_scorings
|
|
|
|
.iter()
|
|
|
|
.any(|scoring| scoring.mID == entry.id())
|
|
|
|
});
|
|
|
|
|
2023-01-18 06:09:44 +00:00
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
};
|
|
|
|
|
|
|
|
// check if any entry needs resorting
|
2023-01-19 09:23:21 +00:00
|
|
|
if force_update
|
|
|
|
|| self
|
|
|
|
.leaderboard_entries
|
|
|
|
.iter()
|
|
|
|
.any(|entry| entry.needs_resorting())
|
|
|
|
{
|
2023-01-18 07:04:47 +00:00
|
|
|
write_log!("leader board update required");
|
|
|
|
|
2023-01-19 09:23:21 +00:00
|
|
|
self.leaderboard_entries
|
2023-01-18 06:09:44 +00:00
|
|
|
.sort_by(|lhs, rhs| lhs.place().cmp(&rhs.place()));
|
|
|
|
|
2023-01-19 09:23:21 +00:00
|
|
|
for (i, entry) in self.leaderboard_entries.iter_mut().enumerate() {
|
2023-01-18 06:09:44 +00:00
|
|
|
entry.resorting_finished();
|
|
|
|
|
2023-01-19 12:41:08 +00:00
|
|
|
// don't break here, just skip adding to grid
|
|
|
|
// because resorting_finished should be called for every entry
|
|
|
|
if i < self.leaderboard_grid.dimensions().1 {
|
2023-01-20 16:01:21 +00:00
|
|
|
entry.change_background_color(&self.entry_backgrounds[i % 2])?;
|
2023-01-19 12:41:08 +00:00
|
|
|
|
|
|
|
self.leaderboard_grid.attach(entry.snippet(), 0, i, 1, 1)?;
|
|
|
|
}
|
2023-01-19 09:23:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
self.leaderboard_redraw = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// update delta board
|
|
|
|
if self.last_player_id != -1 {
|
|
|
|
write_log!("update delta board");
|
|
|
|
|
|
|
|
if let Some((index, _player_entry)) = self
|
|
|
|
.leaderboard_entries
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.find(|(_index, entry)| entry.id() == self.last_player_id)
|
|
|
|
{
|
2023-01-20 07:14:51 +00:00
|
|
|
let mut start_index = if index >= 2 {
|
|
|
|
if index == self.leaderboard_entries.len() - 2 {
|
|
|
|
if index >= 3 {
|
|
|
|
index - 3
|
|
|
|
} else {
|
|
|
|
index - 2
|
|
|
|
}
|
|
|
|
} else if index == self.leaderboard_entries.len() - 1 {
|
|
|
|
if index >= 4 {
|
|
|
|
index - 4
|
|
|
|
} else if index >= 3 {
|
|
|
|
index - 3
|
|
|
|
} else {
|
|
|
|
index - 2
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
index - 2
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
};
|
2023-01-19 09:23:21 +00:00
|
|
|
|
|
|
|
let max = self.leaderboard_entries.len().min(5);
|
|
|
|
|
|
|
|
write_log!(format!(
|
|
|
|
"Delta Board: start {} - count {}",
|
|
|
|
start_index, max
|
|
|
|
));
|
|
|
|
|
|
|
|
// clear old entries
|
|
|
|
for i in 0..5 {
|
|
|
|
if let Some(child) = self.deltaboard_grid.detach(0, i)? {
|
|
|
|
if let Some(visiblity) = child.visibility() {
|
|
|
|
visiblity.set_visibility(false)?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// add new entries
|
|
|
|
for i in 0..max {
|
|
|
|
if let Some(leaderboard_entry) = self.leaderboard_entries.get(start_index) {
|
|
|
|
if let Some(entry) = self.deltaboard_entries.get_mut(i) {
|
|
|
|
entry.change_id(leaderboard_entry.id());
|
|
|
|
entry.update_place(leaderboard_entry.place())?;
|
2023-01-19 12:41:08 +00:00
|
|
|
|
|
|
|
if entry.id() == self.last_player_id {
|
2023-01-20 16:01:21 +00:00
|
|
|
entry.change_background_color(&self.player_background)?;
|
2023-01-19 12:41:08 +00:00
|
|
|
} else {
|
2023-01-20 16:01:21 +00:00
|
|
|
entry.change_background_color(&self.entry_backgrounds[i % 2])?;
|
2023-01-19 12:41:08 +00:00
|
|
|
}
|
2023-01-19 09:23:21 +00:00
|
|
|
|
|
|
|
if entry.name() != leaderboard_entry.name() {
|
|
|
|
entry.change_name(leaderboard_entry.name().to_string())?;
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(vehicle_scoring) = vehicle_scorings
|
|
|
|
.iter()
|
|
|
|
.find(|scoring| scoring.mID == entry.id())
|
|
|
|
{
|
|
|
|
entry.update_time_behind_next(vehicle_scoring.mTimeBehindNext)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.deltaboard_grid.attach(entry.snippet(), 0, i, 1, 1)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
start_index += 1;
|
|
|
|
}
|
|
|
|
}
|
2023-01-18 06:09:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-18 07:55:43 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2023-01-18 16:02:20 +00:00
|
|
|
|
2023-01-20 16:21:24 +00:00
|
|
|
fn query_behind_leader(scoring: &VehicleScoringInfoV01) -> BehindLeader {
|
2023-01-20 16:27:09 +00:00
|
|
|
match scoring.mFinishStatus {
|
|
|
|
0 | 1 => {
|
|
|
|
if scoring.mInPits != 0 {
|
|
|
|
BehindLeader::PITS
|
|
|
|
} else {
|
|
|
|
let laps_behind = scoring.mLapsBehindLeader;
|
2023-01-20 16:21:24 +00:00
|
|
|
|
2023-01-20 16:27:09 +00:00
|
|
|
if laps_behind != 0 {
|
|
|
|
BehindLeader::Laps(laps_behind)
|
|
|
|
} else {
|
|
|
|
BehindLeader::Time(scoring.mTimeBehindLeader)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
2 => BehindLeader::DNF,
|
|
|
|
3 => BehindLeader::DSQ,
|
|
|
|
|
|
|
|
_ => {
|
|
|
|
write_log!(format!(
|
|
|
|
"not allowed finish state: {}",
|
|
|
|
scoring.mFinishStatus
|
|
|
|
));
|
|
|
|
|
|
|
|
BehindLeader::Time(scoring.mTimeBehindLeader)
|
|
|
|
}
|
2023-01-20 16:21:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-18 16:02:20 +00:00
|
|
|
fn race_leaderboard(&mut self, vehicle_scorings: &[VehicleScoringInfoV01]) -> Result<()> {
|
2023-01-20 05:56:26 +00:00
|
|
|
self.update_leaderboard(
|
|
|
|
vehicle_scorings,
|
2023-01-20 16:21:24 +00:00
|
|
|
|entry, scoring| entry.update_time_behind_leader(Self::query_behind_leader(scoring)),
|
2023-01-20 05:56:26 +00:00
|
|
|
|entry| entry.force_display_behind_leader(),
|
|
|
|
)
|
2023-01-18 16:02:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn quali_leaderboard(&mut self, vehicle_scorings: &[VehicleScoringInfoV01]) -> Result<()> {
|
2023-01-20 05:56:26 +00:00
|
|
|
self.update_leaderboard(
|
|
|
|
vehicle_scorings,
|
|
|
|
|entry, scoring| entry.update_best_lap(scoring.mBestLapTime),
|
|
|
|
|entry| entry.force_display_best_lap(),
|
|
|
|
)
|
2023-01-18 16:02:20 +00:00
|
|
|
}
|
2023-01-18 07:55:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl UiOverlay for LeaderBoard {}
|
|
|
|
|
|
|
|
impl DataReceiver for LeaderBoard {
|
2023-01-18 16:02:20 +00:00
|
|
|
fn game_phase_change(&mut self, phase: GamePhase) -> Result<()> {
|
2023-01-21 15:50:29 +00:00
|
|
|
for i in 0..self.leaderboard_grid.dimensions().1 {
|
|
|
|
self.leaderboard_grid.detach(0, i)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
for i in 0..self.deltaboard_grid.dimensions().1 {
|
|
|
|
self.deltaboard_grid.detach(0, i)?;
|
|
|
|
}
|
|
|
|
|
2023-01-18 16:02:20 +00:00
|
|
|
match phase {
|
2023-01-19 14:36:56 +00:00
|
|
|
GamePhase::Practice | GamePhase::Qualifying | GamePhase::TestDay => {
|
2023-01-19 09:23:21 +00:00
|
|
|
for entry in self.leaderboard_entries.iter_mut() {
|
2023-01-20 04:49:57 +00:00
|
|
|
entry.reset_time()?;
|
2023-01-19 06:40:16 +00:00
|
|
|
}
|
|
|
|
|
2023-01-19 09:23:21 +00:00
|
|
|
self.leaderboard.enable()?;
|
2023-01-19 06:40:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GamePhase::Race => {
|
2023-01-19 09:23:21 +00:00
|
|
|
for entry in self.leaderboard_entries.iter_mut() {
|
2023-01-20 04:49:57 +00:00
|
|
|
entry.reset_time()?;
|
|
|
|
}
|
|
|
|
|
|
|
|
for entry in self.deltaboard_entries.iter_mut() {
|
|
|
|
entry.reset_time()?;
|
2023-01-19 06:40:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
self.leaderboard.enable()?;
|
2023-01-19 09:23:21 +00:00
|
|
|
self.deltaboard.enable()?;
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
self.last_player_id = -1;
|
|
|
|
self.leaderboard.disable()?;
|
|
|
|
self.deltaboard.disable()?;
|
2023-01-19 06:40:16 +00:00
|
|
|
}
|
2023-01-18 16:02:20 +00:00
|
|
|
}
|
2023-01-19 06:40:16 +00:00
|
|
|
|
|
|
|
Ok(())
|
2023-01-18 16:02:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn update_for_phase(&self, phase: GamePhase) -> bool {
|
|
|
|
match phase {
|
2023-01-19 14:36:56 +00:00
|
|
|
GamePhase::Practice | GamePhase::Qualifying | GamePhase::Race | GamePhase::TestDay => {
|
|
|
|
true
|
|
|
|
}
|
2023-01-18 16:02:20 +00:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-18 07:55:43 +00:00
|
|
|
fn scoring_update(
|
|
|
|
&mut self,
|
|
|
|
phase: GamePhase,
|
|
|
|
vehicle_scorings: &[VehicleScoringInfoV01],
|
|
|
|
) -> Result<()> {
|
|
|
|
write_log!("=================== leader board: scoring update ===================");
|
|
|
|
|
|
|
|
match phase {
|
2023-01-19 14:36:56 +00:00
|
|
|
GamePhase::Practice | GamePhase::Qualifying | GamePhase::TestDay => {
|
2023-01-19 09:23:21 +00:00
|
|
|
self.quali_leaderboard(vehicle_scorings)?;
|
2023-01-18 07:55:43 +00:00
|
|
|
}
|
2023-01-18 16:02:20 +00:00
|
|
|
|
2023-01-19 09:23:21 +00:00
|
|
|
GamePhase::Race => {
|
|
|
|
self.race_leaderboard(vehicle_scorings)?;
|
|
|
|
}
|
2023-01-18 16:02:20 +00:00
|
|
|
|
|
|
|
_ => (),
|
2023-01-18 07:55:43 +00:00
|
|
|
}
|
|
|
|
|
2023-01-18 07:04:47 +00:00
|
|
|
write_log!("leader board update finished");
|
|
|
|
|
2023-01-18 06:09:44 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn telemetry_update(
|
|
|
|
&mut self,
|
2023-01-18 07:04:47 +00:00
|
|
|
player_id: Option<i32>,
|
2023-01-18 06:09:44 +00:00
|
|
|
_telemetries: &[rF2VehicleTelemetry],
|
|
|
|
) -> Result<()> {
|
2023-01-19 09:23:21 +00:00
|
|
|
if self.leaderboard_redraw {
|
|
|
|
self.leaderboard_redraw = false;
|
|
|
|
|
2023-01-19 12:41:08 +00:00
|
|
|
if let Some(player_id) = player_id {
|
|
|
|
if let Some(entry) = self
|
|
|
|
.leaderboard_entries
|
|
|
|
.iter()
|
|
|
|
.find(|entry| entry.id() == player_id)
|
|
|
|
{
|
|
|
|
write_log!(format!(
|
|
|
|
"Update player entry background color: {:?}",
|
|
|
|
self.player_background
|
|
|
|
));
|
2023-01-20 16:01:21 +00:00
|
|
|
entry.change_background_color(&self.player_background)?;
|
2023-01-19 12:41:08 +00:00
|
|
|
}
|
|
|
|
}
|
2023-01-18 07:04:47 +00:00
|
|
|
}
|
|
|
|
|
2023-01-19 09:23:21 +00:00
|
|
|
if let Some(player_id) = player_id {
|
|
|
|
self.last_player_id = player_id;
|
2023-01-18 11:49:04 +00:00
|
|
|
}
|
2023-01-18 16:02:20 +00:00
|
|
|
|
|
|
|
Ok(())
|
2023-01-18 06:09:44 +00:00
|
|
|
}
|
|
|
|
}
|