Improve leaderboard

This commit is contained in:
hodasemi 2023-01-18 08:04:47 +01:00
parent 1c37ce6029
commit 966414a17c
3 changed files with 56 additions and 14 deletions

View file

@ -9,6 +9,7 @@ use ui::prelude::*;
use utilities::prelude::Color; use utilities::prelude::Color;
use crate::overlay::{rfactor_data::DataReceiver, UiOverlay}; use crate::overlay::{rfactor_data::DataReceiver, UiOverlay};
use crate::write_log;
pub struct LeaderBoard { pub struct LeaderBoard {
gui_handler: Arc<GuiHandler>, gui_handler: Arc<GuiHandler>,
@ -18,6 +19,7 @@ pub struct LeaderBoard {
entries: Vec<LeaderBoardEntry>, entries: Vec<LeaderBoardEntry>,
entry_backgrounds: [Color; 2], entry_backgrounds: [Color; 2],
player_background: Color,
} }
impl LeaderBoard { impl LeaderBoard {
@ -37,22 +39,38 @@ impl LeaderBoard {
entries: Vec::new(), entries: Vec::new(),
entry_backgrounds: [Color::try_from("#838383")?, Color::try_from("#545454")?], entry_backgrounds: [Color::try_from("#838383")?, Color::try_from("#545454")?],
player_background: Color::try_from("#b4bf26")?,
}) })
} }
fn c_char_to_string(c: [c_char; 32usize]) -> String {
unsafe { CStr::from_ptr(&c as *const c_char) }
.to_str()
.unwrap()
.to_string()
}
} }
impl UiOverlay for LeaderBoard {} impl UiOverlay for LeaderBoard {}
impl DataReceiver for LeaderBoard { impl DataReceiver for LeaderBoard {
fn scoring_update(&mut self, vehicle_scorings: &[VehicleScoringInfoV01]) -> Result<()> { fn scoring_update(&mut self, vehicle_scorings: &[VehicleScoringInfoV01]) -> Result<()> {
write_log!("=================== leader board: scoring update ===================");
for vehicle_scoring in vehicle_scorings { for vehicle_scoring in vehicle_scorings {
let driver_name = Self::c_char_to_string(vehicle_scoring.mDriverName);
// check driver list // check driver list
match self match self
.entries .entries
.iter_mut() .iter_mut()
.find(|entry| vehicle_scoring.mID == entry.id) .find(|entry| vehicle_scoring.mID == entry.id())
{ {
Some(entry) => { Some(entry) => {
if entry.name() != driver_name {
entry.change_name(driver_name)?;
}
entry.update_place(vehicle_scoring.mPlace)?; entry.update_place(vehicle_scoring.mPlace)?;
entry.update_time_behind_leader(vehicle_scoring.mTimeBehindLeader)?; entry.update_time_behind_leader(vehicle_scoring.mTimeBehindLeader)?;
entry.update_time_behind_next(vehicle_scoring.mTimeBehindNext)?; entry.update_time_behind_next(vehicle_scoring.mTimeBehindNext)?;
@ -61,10 +79,7 @@ impl DataReceiver for LeaderBoard {
let entry = LeaderBoardEntry::new( let entry = LeaderBoardEntry::new(
&self.gui_handler, &self.gui_handler,
vehicle_scoring.mID, vehicle_scoring.mID,
unsafe { CStr::from_ptr(&vehicle_scoring.mDriverName as *const c_char) } driver_name,
.to_str()
.unwrap()
.to_string(),
vehicle_scoring.mPlace, vehicle_scoring.mPlace,
vehicle_scoring.mTimeBehindLeader, vehicle_scoring.mTimeBehindLeader,
vehicle_scoring.mTimeBehindNext, vehicle_scoring.mTimeBehindNext,
@ -75,11 +90,14 @@ impl DataReceiver for LeaderBoard {
} }
} }
write_log!("create entries");
// check if entry count in grid is the same as the gathered entries // check if entry count in grid is the same as the gathered entries
let force_update = if self let force_update = if !self.entries.is_empty()
.main_grid && self
.child_at(0, self.entries.len() - 1)? .main_grid
.is_none() .child_at(0, self.entries.len() - 1)?
.is_none()
{ {
for i in 0..self.entries.len() { for i in 0..self.entries.len() {
self.main_grid.detach(0, i)?; self.main_grid.detach(0, i)?;
@ -92,6 +110,8 @@ impl DataReceiver for LeaderBoard {
// check if any entry needs resorting // check if any entry needs resorting
if force_update || self.entries.iter().any(|entry| entry.needs_resorting()) { if force_update || self.entries.iter().any(|entry| entry.needs_resorting()) {
write_log!("leader board update required");
self.entries self.entries
.sort_by(|lhs, rhs| lhs.place().cmp(&rhs.place())); .sort_by(|lhs, rhs| lhs.place().cmp(&rhs.place()));
@ -109,14 +129,22 @@ impl DataReceiver for LeaderBoard {
self.gui.enable()?; self.gui.enable()?;
} }
write_log!("leader board update finished");
Ok(()) Ok(())
} }
fn telemetry_update( fn telemetry_update(
&mut self, &mut self,
_player_id: Option<i32>, player_id: Option<i32>,
_telemetries: &[rF2VehicleTelemetry], _telemetries: &[rF2VehicleTelemetry],
) -> Result<()> { ) -> Result<()> {
if let Some(player_id) = player_id {
if let Some(entry) = self.entries.iter().find(|entry| entry.id() == player_id) {
entry.change_background_color(self.player_background)?;
}
}
Ok(()) Ok(())
} }
} }
@ -178,10 +206,24 @@ impl LeaderBoardEntry {
}) })
} }
pub fn id(&self) -> i32 {
self.id
}
pub fn place(&self) -> u8 { pub fn place(&self) -> u8 {
self.place self.place
} }
pub fn name(&self) -> &str {
&self.name
}
pub fn change_name(&mut self, name: String) -> Result<()> {
self.name = name;
self.name_label.set_text(&self.name)
}
pub fn snippet(&self) -> Arc<GuiSnippet> { pub fn snippet(&self) -> Arc<GuiSnippet> {
self.snippet.clone() self.snippet.clone()
} }

View file

@ -1,7 +1,7 @@
<root> <root>
<grid id="grid" x_dim="6" y_dim="1"> <grid id="grid" x_dim="9" y_dim="1">
<label id="place" x_slot="0" y_slot="0" text_color="black"></label> <label id="place" x_slot="0" y_slot="0" text_color="black"></label>
<label id="name" x_slot="1" y_slot="0" x_size="3" text_color="black"></label> <label id="name" x_slot="1" y_slot="0" x_size="6" text_color="black"></label>
<label id="time_behind" x_slot="4" y_slot="0" x_size="2" text_color="black"></label> <label id="time_behind" x_slot="7" y_slot="0" x_size="2" text_color="black"></label>
</grid> </grid>
</root> </root>

View file

@ -1,5 +1,5 @@
<?xml-model href="gui.xsd" type="application/xml" schematypens="http://www.w3.org/2001/XMLSchema"?> <?xml-model href="gui.xsd" type="application/xml" schematypens="http://www.w3.org/2001/XMLSchema"?>
<root reference_width="2560" reference_height="1440"> <root reference_width="2560" reference_height="1440">
<grid id="main_grid" x_dim="1" y_dim="25" x_offset="10" y_offset="70" width="250" height="1000" <grid id="main_grid" x_dim="1" y_dim="25" x_offset="10" y_offset="70" width="350" height="875"
vert_align="top" hori_align="left" margin="0" padding="0"> </grid> vert_align="top" hori_align="left" margin="0" padding="0"> </grid>
</root> </root>