Leaderboard improvements

This commit is contained in:
hodasemi 2023-01-19 07:40:16 +01:00
parent eec17e1039
commit 3f914ffdeb
2 changed files with 81 additions and 23 deletions

View file

@ -1,6 +1,6 @@
<?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> <root>
<grid id="grid" x_dim="11" y_dim="1"> <grid x_dim="11" y_dim="1" padding="2" margin="2">
<label id="place" x_slot="0" y_slot="0" text_color="black" text_alignment="right"></label> <label id="place" x_slot="0" y_slot="0" text_color="black" text_alignment="right"></label>
<label <label
id="name" id="name"

View file

@ -16,7 +16,7 @@ use crate::write_log;
pub struct LeaderBoard { pub struct LeaderBoard {
gui_handler: Arc<GuiHandler>, gui_handler: Arc<GuiHandler>,
gui: Arc<GuiBuilder>, leaderboard: Arc<GuiBuilder>,
main_grid: Arc<Grid>, main_grid: Arc<Grid>,
entries: Vec<LeaderBoardEntry>, entries: Vec<LeaderBoardEntry>,
@ -36,7 +36,7 @@ impl LeaderBoard {
Ok(Self { Ok(Self {
gui_handler: gui_handler.clone(), gui_handler: gui_handler.clone(),
gui, leaderboard: gui,
main_grid, main_grid,
entries: Vec::new(), entries: Vec::new(),
@ -85,7 +85,15 @@ impl LeaderBoard {
vehicle_scoring.mID, vehicle_scoring.mID,
driver_name, driver_name,
vehicle_scoring.mPlace, vehicle_scoring.mPlace,
vehicle_scoring.mTimeBehindLeader, {
let laps_behind = vehicle_scoring.mLapsBehindLeader;
if laps_behind != 0 {
BehindLeader::Laps(laps_behind)
} else {
BehindLeader::Time(vehicle_scoring.mTimeBehindLeader)
}
},
vehicle_scoring.mTimeBehindNext, vehicle_scoring.mTimeBehindNext,
vehicle_scoring.mBestLapTime, vehicle_scoring.mBestLapTime,
)?; )?;
@ -133,7 +141,13 @@ impl LeaderBoard {
fn race_leaderboard(&mut self, vehicle_scorings: &[VehicleScoringInfoV01]) -> Result<()> { fn race_leaderboard(&mut self, vehicle_scorings: &[VehicleScoringInfoV01]) -> Result<()> {
self.update_leaderboard(vehicle_scorings, |entry, scoring| { self.update_leaderboard(vehicle_scorings, |entry, scoring| {
entry.update_time_behind_leader(scoring.mTimeBehindLeader) let laps_behind = scoring.mLapsBehindLeader;
if laps_behind != 0 {
entry.update_time_behind_leader(BehindLeader::Laps(laps_behind))
} else {
entry.update_time_behind_leader(BehindLeader::Time(scoring.mTimeBehindLeader))
}
}) })
} }
@ -149,9 +163,25 @@ impl UiOverlay for LeaderBoard {}
impl DataReceiver for LeaderBoard { impl DataReceiver for LeaderBoard {
fn game_phase_change(&mut self, phase: GamePhase) -> Result<()> { fn game_phase_change(&mut self, phase: GamePhase) -> Result<()> {
match phase { match phase {
GamePhase::Practice | GamePhase::Qualifying | GamePhase::Race => self.gui.enable(), GamePhase::Practice | GamePhase::Qualifying => {
_ => self.gui.disable(), for entry in self.entries.iter_mut() {
entry.update_best_lap(-1.0)?;
} }
self.leaderboard.enable()?
}
GamePhase::Race => {
for entry in self.entries.iter_mut() {
entry.update_time_behind_leader(BehindLeader::Time(0.0))?;
}
self.leaderboard.enable()?;
}
_ => self.leaderboard.disable()?,
}
Ok(())
} }
fn update_for_phase(&self, phase: GamePhase) -> bool { fn update_for_phase(&self, phase: GamePhase) -> bool {
@ -198,18 +228,23 @@ impl DataReceiver for LeaderBoard {
} }
} }
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
enum BehindLeader {
Time(f64),
Laps(i32),
}
struct LeaderBoardEntry { struct LeaderBoardEntry {
id: i32, id: i32,
name: String, name: String,
place: u8, place: u8,
time_behind_leader: f64, behind: BehindLeader,
time_behind_next: f64, time_behind_next: f64,
best_lap: f64, best_lap: f64,
snippet: Arc<GuiSnippet>, snippet: Arc<GuiSnippet>,
grid: Arc<Grid>,
name_label: Arc<Label>, name_label: Arc<Label>,
place_label: Arc<Label>, place_label: Arc<Label>,
time_label: Arc<Label>, time_label: Arc<Label>,
@ -223,13 +258,12 @@ impl LeaderBoardEntry {
id: i32, id: i32,
name: String, name: String,
place: u8, place: u8,
time_behind_leader: f64, behind: BehindLeader,
time_behind_next: f64, time_behind_next: f64,
best_lap: f64, best_lap: f64,
) -> Result<Self> { ) -> Result<Self> {
let snippet = GuiSnippet::from_str(gui_handler, LeaderBoard::ENTRY)?; let snippet = GuiSnippet::from_str(gui_handler, LeaderBoard::ENTRY)?;
let background = snippet.element("grid")?;
let name_label: Arc<Label> = snippet.element("name")?; let name_label: Arc<Label> = snippet.element("name")?;
let place_label: Arc<Label> = snippet.element("place")?; let place_label: Arc<Label> = snippet.element("place")?;
let time_label: Arc<Label> = snippet.element("time")?; let time_label: Arc<Label> = snippet.element("time")?;
@ -243,13 +277,12 @@ impl LeaderBoardEntry {
name, name,
place, place,
time_behind_leader, behind,
time_behind_next, time_behind_next,
best_lap, best_lap,
snippet, snippet,
grid: background,
name_label, name_label,
place_label, place_label,
time_label, time_label,
@ -281,7 +314,11 @@ impl LeaderBoardEntry {
} }
pub fn change_background_color(&self, color: Color) -> Result<()> { pub fn change_background_color(&self, color: Color) -> Result<()> {
self.grid.set_background(color) self.name_label.set_background(color)?;
self.place_label.set_background(color)?;
self.time_label.set_background(color)?;
Ok(())
} }
pub fn update_place(&mut self, place: u8) -> Result<()> { pub fn update_place(&mut self, place: u8) -> Result<()> {
@ -294,16 +331,37 @@ impl LeaderBoardEntry {
self.place_label.set_text(self.place) self.place_label.set_text(self.place)
} }
pub fn update_time_behind_leader(&mut self, time: f64) -> Result<()> { pub fn update_time_behind_leader(&mut self, behind: BehindLeader) -> Result<()> {
if self.time_behind_leader != time { if self.behind != behind {
self.time_behind_leader = time; self.behind = behind;
match self.behind {
BehindLeader::Time(time_behind) => {
// check if we are leader // check if we are leader
if self.time_behind_leader == 0.0 { if time_behind == 0.0 {
self.time_label.set_text("---")?; self.time_label.set_text("---")?;
} else { } else {
self.time_label let text = if time_behind > 60.0 {
.set_text(format!("+{:.3}", self.time_behind_leader))?; let full_minutes = (self.best_lap / 60.0).floor();
let remainder = self.best_lap - (full_minutes * 60.0);
format!("+{:.0}:{:.0}", full_minutes, remainder)
} else {
format!("+{:.3}", time_behind)
};
self.time_label.set_text(text)?;
}
}
BehindLeader::Laps(laps_behind) => {
let text = if laps_behind == 1 {
format!("+{} Lap", laps_behind)
} else {
format!("+{} Laps", laps_behind)
};
self.time_label.set_text(text)?;
}
} }
} }