Add delta board
This commit is contained in:
parent
420b8fa914
commit
7cb07f1260
6 changed files with 365 additions and 213 deletions
6
src/overlay/elements/leaderboard/deltaboard_grid.xml
Normal file
6
src/overlay/elements/leaderboard/deltaboard_grid.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml-model href="../gui.xsd" type="application/xml" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<root reference_width="2560" reference_height="1440">
|
||||
<!-- max 5 entries, each entry gets 39 pixel (at 1440p) -->
|
||||
<grid id="main_grid" x_dim="1" y_dim="5" x_offset="-410" y_offset="10" width="400" height="195"
|
||||
vert_align="top" hori_align="right" margin="0" padding="0"> </grid>
|
||||
</root>
|
215
src/overlay/elements/leaderboard/leaderboard_entry.rs
Normal file
215
src/overlay/elements/leaderboard/leaderboard_entry.rs
Normal file
|
@ -0,0 +1,215 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use ui::prelude::*;
|
||||
use utilities::prelude::Color;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
|
||||
pub enum BehindLeader {
|
||||
Time(f64),
|
||||
Laps(i32),
|
||||
}
|
||||
|
||||
pub struct LeaderBoardEntry {
|
||||
id: i32,
|
||||
|
||||
name: String,
|
||||
place: u8,
|
||||
behind: BehindLeader,
|
||||
time_behind_next: f64,
|
||||
best_lap: f64,
|
||||
|
||||
snippet: Arc<GuiSnippet>,
|
||||
|
||||
name_label: Arc<Label>,
|
||||
place_label: Arc<Label>,
|
||||
time_label: Arc<Label>,
|
||||
|
||||
place_updated: bool,
|
||||
}
|
||||
|
||||
impl LeaderBoardEntry {
|
||||
const ENTRY: &str = include_str!("leaderboard_entry.xml");
|
||||
|
||||
pub fn empty(gui_handler: &Arc<GuiHandler>) -> Result<Self> {
|
||||
Self::new(
|
||||
gui_handler,
|
||||
-1,
|
||||
"".to_string(),
|
||||
0,
|
||||
BehindLeader::Laps(0),
|
||||
0.0,
|
||||
0.0,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
gui_handler: &Arc<GuiHandler>,
|
||||
id: i32,
|
||||
name: String,
|
||||
place: u8,
|
||||
behind: BehindLeader,
|
||||
time_behind_next: f64,
|
||||
best_lap: f64,
|
||||
) -> Result<Self> {
|
||||
let snippet = GuiSnippet::from_str(gui_handler, Self::ENTRY)?;
|
||||
|
||||
let name_label: Arc<Label> = snippet.element("name")?;
|
||||
let place_label: Arc<Label> = snippet.element("place")?;
|
||||
let time_label: Arc<Label> = snippet.element("time")?;
|
||||
|
||||
name_label.set_text(&name)?;
|
||||
place_label.set_text(place)?;
|
||||
time_label.set_text("---")?;
|
||||
|
||||
Ok(Self {
|
||||
id,
|
||||
|
||||
name,
|
||||
place,
|
||||
behind,
|
||||
time_behind_next,
|
||||
best_lap,
|
||||
|
||||
snippet,
|
||||
|
||||
name_label,
|
||||
place_label,
|
||||
time_label,
|
||||
|
||||
place_updated: true,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn change_id(&mut self, id: i32) {
|
||||
self.id = id;
|
||||
}
|
||||
|
||||
pub fn id(&self) -> i32 {
|
||||
self.id
|
||||
}
|
||||
|
||||
pub fn place(&self) -> u8 {
|
||||
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> {
|
||||
self.snippet.clone()
|
||||
}
|
||||
|
||||
pub fn change_background_color(&self, color: Color) -> Result<()> {
|
||||
self.time_label.set_background(color)?;
|
||||
self.name_label.set_background(color)?;
|
||||
self.place_label.set_background(color)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn _highlight(&self, color: Color) -> Result<()> {
|
||||
self.name_label.set_background(color)
|
||||
}
|
||||
|
||||
pub fn update_place(&mut self, place: u8) -> Result<()> {
|
||||
if self.place != place {
|
||||
self.place_updated = true;
|
||||
}
|
||||
|
||||
self.place = place;
|
||||
|
||||
self.place_label.set_text(self.place)
|
||||
}
|
||||
|
||||
pub fn update_time_behind_leader(&mut self, behind: BehindLeader) -> Result<()> {
|
||||
if self.behind != behind {
|
||||
self.behind = behind;
|
||||
|
||||
match self.behind {
|
||||
BehindLeader::Time(time_behind) => {
|
||||
// check if we are leader
|
||||
if time_behind == 0.0 {
|
||||
self.time_label.set_text("---")?;
|
||||
} else {
|
||||
let text = if time_behind > 60.0 {
|
||||
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)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn update_best_lap(&mut self, time: f64) -> Result<()> {
|
||||
if self.best_lap != time {
|
||||
self.best_lap = time;
|
||||
|
||||
if self.best_lap < 0.0 {
|
||||
self.time_label.set_text("---")?;
|
||||
} else {
|
||||
let text = if self.best_lap > 60.0 {
|
||||
let full_minutes = (self.best_lap / 60.0).floor();
|
||||
let remainder = self.best_lap - (full_minutes * 60.0);
|
||||
|
||||
format!("{:.0}:{:.3}", full_minutes, remainder)
|
||||
} else {
|
||||
format!("{:.3}", self.best_lap)
|
||||
};
|
||||
|
||||
self.time_label.set_text(text)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn update_time_behind_next(&mut self, time: f64) -> Result<()> {
|
||||
self.time_behind_next = time;
|
||||
|
||||
let text = if self.time_behind_next > 60.0 {
|
||||
let full_minutes = (self.time_behind_next / 60.0).floor();
|
||||
let remainder = self.time_behind_next - (full_minutes * 60.0);
|
||||
|
||||
format!("+{:.0}:{:.3}", full_minutes, remainder)
|
||||
} else {
|
||||
format!("+{:.3}", self.time_behind_next)
|
||||
};
|
||||
|
||||
self.time_label.set_text(text)
|
||||
}
|
||||
|
||||
pub fn needs_resorting(&self) -> bool {
|
||||
self.place_updated
|
||||
}
|
||||
|
||||
pub fn resorting_finished(&mut self) {
|
||||
self.place_updated = false;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
<?xml-model href="../gui.xsd" type="application/xml" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<root reference_width="2560" reference_height="1440">
|
||||
<grid id="main_grid" x_dim="1" y_dim="25" x_offset="10" y_offset="10" width="400" height="875"
|
||||
<!-- max 25 entries, each entry gets 39 pixel (at 1440p) -->
|
||||
<grid id="main_grid" x_dim="1" y_dim="25" x_offset="10" y_offset="10" width="400" height="975"
|
||||
vert_align="top" hori_align="left" margin="0" padding="0"> </grid>
|
||||
</root>
|
|
@ -1,3 +1,7 @@
|
|||
mod leaderboard_entry;
|
||||
|
||||
use leaderboard_entry::*;
|
||||
|
||||
use std::{
|
||||
ffi::{c_char, CStr},
|
||||
sync::Arc,
|
||||
|
@ -17,32 +21,53 @@ use crate::write_log;
|
|||
pub struct LeaderBoard {
|
||||
gui_handler: Arc<GuiHandler>,
|
||||
leaderboard: Arc<GuiBuilder>,
|
||||
main_grid: Arc<Grid>,
|
||||
deltaboard: Arc<GuiBuilder>,
|
||||
|
||||
entries: Vec<LeaderBoardEntry>,
|
||||
leaderboard_grid: Arc<Grid>,
|
||||
deltaboard_grid: Arc<Grid>,
|
||||
|
||||
leaderboard_entries: Vec<LeaderBoardEntry>,
|
||||
deltaboard_entries: [LeaderBoardEntry; 5],
|
||||
|
||||
leaderboard_redraw: bool,
|
||||
last_player_id: i32,
|
||||
|
||||
entry_backgrounds: [Color; 2],
|
||||
player_background: Color,
|
||||
_player_background: Color,
|
||||
}
|
||||
|
||||
impl LeaderBoard {
|
||||
const GRID: &str = include_str!("leaderboard_grid.xml");
|
||||
const ENTRY: &str = include_str!("leaderboard_entry.xml");
|
||||
const LEADERBOARD: &str = include_str!("leaderboard_grid.xml");
|
||||
const DELTABOARD: &str = include_str!("deltaboard_grid.xml");
|
||||
|
||||
pub fn new(gui_handler: &Arc<GuiHandler>) -> Result<Self> {
|
||||
let gui = GuiBuilder::from_str(gui_handler, Self::GRID)?;
|
||||
let leaderboard = GuiBuilder::from_str(gui_handler, Self::LEADERBOARD)?;
|
||||
let deltaboard = GuiBuilder::from_str(gui_handler, Self::DELTABOARD)?;
|
||||
|
||||
let main_grid = gui.element("main_grid")?;
|
||||
let leaderboard_grid = leaderboard.element("main_grid")?;
|
||||
let deltaboard_grid = deltaboard.element("main_grid")?;
|
||||
|
||||
Ok(Self {
|
||||
gui_handler: gui_handler.clone(),
|
||||
leaderboard: gui,
|
||||
main_grid,
|
||||
leaderboard,
|
||||
deltaboard,
|
||||
leaderboard_grid,
|
||||
deltaboard_grid,
|
||||
|
||||
entries: Vec::new(),
|
||||
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,
|
||||
|
||||
entry_backgrounds: [Color::try_from("#838383")?, Color::try_from("#545454")?],
|
||||
player_background: Color::try_from("#b4bf26")?,
|
||||
_player_background: Color::try_from("#b4bf26")?,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -66,7 +91,7 @@ impl LeaderBoard {
|
|||
|
||||
// check driver list
|
||||
match self
|
||||
.entries
|
||||
.leaderboard_entries
|
||||
.iter_mut()
|
||||
.find(|entry| vehicle_scoring.mID == entry.id())
|
||||
{
|
||||
|
@ -98,7 +123,7 @@ impl LeaderBoard {
|
|||
vehicle_scoring.mBestLapTime,
|
||||
)?;
|
||||
|
||||
self.entries.push(entry);
|
||||
self.leaderboard_entries.push(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,14 +131,15 @@ impl LeaderBoard {
|
|||
write_log!("create entries");
|
||||
|
||||
// check if entry count in grid is the same as the gathered entries
|
||||
let force_update = if !self.entries.is_empty()
|
||||
let force_update = if !self.leaderboard_entries.is_empty()
|
||||
&& self
|
||||
.main_grid
|
||||
.child_at(0, self.entries.len() - 1)?
|
||||
.leaderboard_grid
|
||||
.child_at(0, self.leaderboard_entries.len() - 1)?
|
||||
.is_none()
|
||||
{
|
||||
for i in 0..self.entries.len() {
|
||||
self.main_grid.detach(0, i)?;
|
||||
for (i, entry) in self.leaderboard_entries.iter().enumerate() {
|
||||
self.leaderboard_grid.detach(0, i)?;
|
||||
entry.snippet().set_visibility(false)?;
|
||||
}
|
||||
|
||||
true
|
||||
|
@ -122,17 +148,80 @@ impl LeaderBoard {
|
|||
};
|
||||
|
||||
// check if any entry needs resorting
|
||||
if force_update || self.entries.iter().any(|entry| entry.needs_resorting()) {
|
||||
if force_update
|
||||
|| self
|
||||
.leaderboard_entries
|
||||
.iter()
|
||||
.any(|entry| entry.needs_resorting())
|
||||
{
|
||||
write_log!("leader board update required");
|
||||
|
||||
self.entries
|
||||
self.leaderboard_entries
|
||||
.sort_by(|lhs, rhs| lhs.place().cmp(&rhs.place()));
|
||||
|
||||
for (i, entry) in self.entries.iter_mut().enumerate() {
|
||||
for (i, entry) in self.leaderboard_entries.iter_mut().enumerate() {
|
||||
entry.resorting_finished();
|
||||
entry.change_background_color(self.entry_backgrounds[i % 2])?;
|
||||
|
||||
self.main_grid.attach(entry.snippet(), 0, i, 1, 1)?;
|
||||
self.leaderboard_grid.attach(entry.snippet(), 0, i, 1, 1)?;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
let mut start_index = if index >= 2 { index - 2 } else { 0 };
|
||||
|
||||
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())?;
|
||||
entry.change_background_color(self.entry_backgrounds[i % 2])?;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,21 +253,27 @@ impl DataReceiver for LeaderBoard {
|
|||
fn game_phase_change(&mut self, phase: GamePhase) -> Result<()> {
|
||||
match phase {
|
||||
GamePhase::Practice | GamePhase::Qualifying => {
|
||||
for entry in self.entries.iter_mut() {
|
||||
for entry in self.leaderboard_entries.iter_mut() {
|
||||
entry.update_best_lap(-1.0)?;
|
||||
}
|
||||
|
||||
self.leaderboard.enable()?
|
||||
self.leaderboard.enable()?;
|
||||
self.deltaboard.enable()?;
|
||||
}
|
||||
|
||||
GamePhase::Race => {
|
||||
for entry in self.entries.iter_mut() {
|
||||
for entry in self.leaderboard_entries.iter_mut() {
|
||||
entry.update_time_behind_leader(BehindLeader::Time(0.0))?;
|
||||
}
|
||||
|
||||
self.leaderboard.enable()?;
|
||||
self.deltaboard.enable()?;
|
||||
}
|
||||
_ => {
|
||||
self.last_player_id = -1;
|
||||
self.leaderboard.disable()?;
|
||||
self.deltaboard.disable()?;
|
||||
}
|
||||
_ => self.leaderboard.disable()?,
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -200,10 +295,12 @@ impl DataReceiver for LeaderBoard {
|
|||
|
||||
match phase {
|
||||
GamePhase::Practice | GamePhase::Qualifying => {
|
||||
self.quali_leaderboard(vehicle_scorings)?
|
||||
self.quali_leaderboard(vehicle_scorings)?;
|
||||
}
|
||||
|
||||
GamePhase::Race => self.race_leaderboard(vehicle_scorings)?,
|
||||
GamePhase::Race => {
|
||||
self.race_leaderboard(vehicle_scorings)?;
|
||||
}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
|
@ -218,191 +315,24 @@ impl DataReceiver for LeaderBoard {
|
|||
player_id: Option<i32>,
|
||||
_telemetries: &[rF2VehicleTelemetry],
|
||||
) -> Result<()> {
|
||||
if self.leaderboard_redraw {
|
||||
self.leaderboard_redraw = false;
|
||||
|
||||
// if let Some(player_id) = player_id {
|
||||
// if let Some(entry) = self.entries.iter().find(|entry| entry.id() == player_id) {
|
||||
// write_log!(format!(
|
||||
// "Update player entry background color: {:?}",
|
||||
// self.player_background
|
||||
// ));
|
||||
// entry.highlight(self.player_background)?;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
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)?;
|
||||
}
|
||||
self.last_player_id = player_id;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
|
||||
enum BehindLeader {
|
||||
Time(f64),
|
||||
Laps(i32),
|
||||
}
|
||||
|
||||
struct LeaderBoardEntry {
|
||||
id: i32,
|
||||
|
||||
name: String,
|
||||
place: u8,
|
||||
behind: BehindLeader,
|
||||
time_behind_next: f64,
|
||||
best_lap: f64,
|
||||
|
||||
snippet: Arc<GuiSnippet>,
|
||||
|
||||
name_label: Arc<Label>,
|
||||
place_label: Arc<Label>,
|
||||
time_label: Arc<Label>,
|
||||
|
||||
place_updated: bool,
|
||||
}
|
||||
|
||||
impl LeaderBoardEntry {
|
||||
pub fn new(
|
||||
gui_handler: &Arc<GuiHandler>,
|
||||
id: i32,
|
||||
name: String,
|
||||
place: u8,
|
||||
behind: BehindLeader,
|
||||
time_behind_next: f64,
|
||||
best_lap: f64,
|
||||
) -> Result<Self> {
|
||||
let snippet = GuiSnippet::from_str(gui_handler, LeaderBoard::ENTRY)?;
|
||||
|
||||
let name_label: Arc<Label> = snippet.element("name")?;
|
||||
let place_label: Arc<Label> = snippet.element("place")?;
|
||||
let time_label: Arc<Label> = snippet.element("time")?;
|
||||
|
||||
name_label.set_text(&name)?;
|
||||
place_label.set_text(place)?;
|
||||
time_label.set_text("---")?;
|
||||
|
||||
Ok(Self {
|
||||
id,
|
||||
|
||||
name,
|
||||
place,
|
||||
behind,
|
||||
time_behind_next,
|
||||
best_lap,
|
||||
|
||||
snippet,
|
||||
|
||||
name_label,
|
||||
place_label,
|
||||
time_label,
|
||||
|
||||
place_updated: true,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn id(&self) -> i32 {
|
||||
self.id
|
||||
}
|
||||
|
||||
pub fn place(&self) -> u8 {
|
||||
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> {
|
||||
self.snippet.clone()
|
||||
}
|
||||
|
||||
pub fn change_background_color(&self, color: Color) -> Result<()> {
|
||||
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<()> {
|
||||
if self.place != place {
|
||||
self.place_updated = true;
|
||||
}
|
||||
|
||||
self.place = place;
|
||||
|
||||
self.place_label.set_text(self.place)
|
||||
}
|
||||
|
||||
pub fn update_time_behind_leader(&mut self, behind: BehindLeader) -> Result<()> {
|
||||
if self.behind != behind {
|
||||
self.behind = behind;
|
||||
|
||||
match self.behind {
|
||||
BehindLeader::Time(time_behind) => {
|
||||
// check if we are leader
|
||||
if time_behind == 0.0 {
|
||||
self.time_label.set_text("---")?;
|
||||
} else {
|
||||
let text = if time_behind > 60.0 {
|
||||
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)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn update_best_lap(&mut self, time: f64) -> Result<()> {
|
||||
if self.best_lap != time {
|
||||
self.best_lap = time;
|
||||
|
||||
if self.best_lap < 0.0 {
|
||||
self.time_label.set_text("---")?;
|
||||
} else {
|
||||
let text = if self.best_lap > 60.0 {
|
||||
let full_minutes = (self.best_lap / 60.0).floor();
|
||||
let remainder = self.best_lap - (full_minutes * 60.0);
|
||||
|
||||
format!("{:.0}:{:.3}", full_minutes, remainder)
|
||||
} else {
|
||||
format!("{:.3}", self.best_lap)
|
||||
};
|
||||
|
||||
self.time_label.set_text(text)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn update_time_behind_next(&mut self, time: f64) -> Result<()> {
|
||||
self.time_behind_next = time;
|
||||
|
||||
self.time_label
|
||||
.set_text(format!("+{:.3}", self.time_behind_next))
|
||||
}
|
||||
|
||||
pub fn needs_resorting(&self) -> bool {
|
||||
self.place_updated
|
||||
}
|
||||
|
||||
pub fn resorting_finished(&mut self) {
|
||||
self.place_updated = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -237,7 +237,7 @@ impl UiOverlay for Pedals {}
|
|||
impl DataReceiver for Pedals {
|
||||
fn game_phase_change(&mut self, phase: GamePhase) -> Result<()> {
|
||||
match phase {
|
||||
GamePhase::None => {
|
||||
GamePhase::None | GamePhase::TestDay => {
|
||||
self.enable = false;
|
||||
self.gui.disable()?;
|
||||
}
|
||||
|
|
|
@ -274,7 +274,7 @@ impl UiOverlay for Radar {}
|
|||
impl DataReceiver for Radar {
|
||||
fn game_phase_change(&mut self, phase: GamePhase) -> Result<()> {
|
||||
match phase {
|
||||
GamePhase::None => self.enable = false,
|
||||
GamePhase::None | GamePhase::TestDay => self.enable = false,
|
||||
_ => self.enable = true,
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue