Skip to content

Commit e8ad32a

Browse files
committed
feat: leverage new alert components in telemetry analysis to show all detail
1 parent 2b8c0f5 commit e8ad32a

File tree

2 files changed

+125
-22
lines changed

2 files changed

+125
-22
lines changed

src/ui/analysis/mod.rs

Lines changed: 91 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
use std::{path::PathBuf, sync::Arc};
22

33
use egui::{
4-
style::Widgets, Color32, Direction, Frame, Layout, Margin, RichText, TextEdit, Ui, Vec2b,
4+
style::Widgets, Align, Color32, Direction, Frame, Label, Layout, Margin, RichText, Ui, Vec2b,
55
Visuals,
66
};
77
use egui_dropdown::DropDownBox;
88
use egui_plot::{Legend, Line, PlotPoints, Points};
99
use itertools::Itertools;
1010

1111
use crate::{
12-
telemetry::{SessionInfo, TelemetryOutput, TelemetryPoint},
12+
telemetry::{SessionInfo, TelemetryAnnotation, TelemetryOutput, TelemetryPoint},
1313
ui::live::{PALETTE_BLACK, PALETTE_BROWN, PALETTE_MAROON, PALETTE_ORANGE},
1414
OcypodeError,
1515
};
1616

17-
use super::stroke_shade;
17+
use super::{stroke_shade, Alert, DefaultAlert, ScrubSlipAlert};
1818

1919
#[derive(Default, Clone, Debug)]
2020
struct TelemetryFile {
@@ -45,6 +45,7 @@ pub(crate) struct TelemetryAnalysisApp<'file> {
4545
data: Option<TelemetryFile>,
4646
selected_session: String,
4747
selected_lap: String,
48+
selected_annotation_content: String,
4849
selected_x: Option<usize>,
4950
}
5051

@@ -69,6 +70,7 @@ impl<'file> TelemetryAnalysisApp<'file> {
6970
data: None,
7071
selected_session: "".to_string(),
7172
selected_lap: "".to_string(),
73+
selected_annotation_content: "".to_string(),
7274
selected_x: None,
7375
}
7476
}
@@ -188,6 +190,7 @@ impl<'file> TelemetryAnalysisApp<'file> {
188190
});
189191
if plot_response.response.clicked() {
190192
if let Some(mouse_pos) = plot_response.response.interact_pointer_pos() {
193+
self.selected_annotation_content = "".to_string();
191194
self.selected_x = Some(
192195
plot_response
193196
.transform
@@ -204,8 +207,9 @@ impl<'file> TelemetryAnalysisApp<'file> {
204207

205208
impl eframe::App for TelemetryAnalysisApp<'_> {
206209
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
207-
let cur_ui_stae = self.ui_state.clone();
208-
match cur_ui_stae {
210+
egui_extras::install_image_loaders(ctx);
211+
let cur_ui_state = self.ui_state.clone();
212+
match cur_ui_state {
209213
UiState::Loading => {
210214
if self.data.is_none() {
211215
let telemetry_load_result = load_telemetry_jsonl(self.source_file);
@@ -247,21 +251,94 @@ impl eframe::App for TelemetryAnalysisApp<'_> {
247251
.fill(Color32::TRANSPARENT)
248252
.inner_margin(Margin::same(5)),
249253
)
250-
.resizable(true)
251-
.max_width(ctx.available_rect().width() * 0.3)
254+
.resizable(false)
255+
.min_width(ctx.available_rect().width() * 0.3)
256+
.max_width(ctx.available_rect().height() / 7.)
252257
.show(ctx, |local_ui| {
253258
if let Ok(selected_lap) = self.selected_lap.parse::<usize>() {
254259
if let Some(x_point) = self.selected_x {
255260
if let Some(lap) = session.laps.get(selected_lap) {
256261
if let Some(telemetry) = lap.telemetry.get(x_point) {
257-
let mut str_buffer =
258-
serde_json::to_string_pretty(&telemetry.annotations)
259-
.unwrap();
262+
let mut abs_alert = DefaultAlert::abs().button();
263+
let mut shift_alert = DefaultAlert::shift().button();
264+
let mut traction_alert = DefaultAlert::traction().button();
265+
let mut trailbrake_steering_alert = DefaultAlert::trailbrake_steering().button();
266+
let mut slip_alert = ScrubSlipAlert::default().button();
267+
268+
let _ = abs_alert.update_state(telemetry);
269+
let _ = shift_alert.update_state(telemetry);
270+
let _ = traction_alert.update_state(telemetry);
271+
let _ = trailbrake_steering_alert.update_state(telemetry);
272+
let _ = slip_alert.update_state(telemetry);
273+
274+
local_ui.with_layout(Layout::top_down(Align::Center), |ui| {
275+
if abs_alert.show(ui, Align::Center).clicked() {
276+
self.selected_annotation_content = format!("brake force: {:.2}", telemetry.brake);
277+
};
278+
ui.separator();
279+
if shift_alert.show(ui, Align::Center).clicked() {
280+
if let Some(TelemetryAnnotation::ShortShifting { gear_change_rpm, optimal_rpm, is_short_shifting: _ }) =
281+
telemetry.annotations.iter().find(|p| matches!(p, TelemetryAnnotation::ShortShifting { gear_change_rpm: _, optimal_rpm: _, is_short_shifting: _ })) {
282+
self.selected_annotation_content = format!(
283+
"From gear: {}\nTo gear: {}\nIdeal RPM: {}\nActual RPM: {}",
284+
telemetry.cur_gear - 1,
285+
telemetry.cur_gear,
286+
optimal_rpm,
287+
gear_change_rpm
288+
)
289+
}
290+
}
291+
ui.separator();
292+
if traction_alert.show(ui, Align::Center).clicked() {
293+
if let Some(TelemetryAnnotation::Wheelspin { avg_rpm_increase_per_gear, cur_gear, cur_rpm_increase, is_wheelspin: _ }) =
294+
telemetry.annotations.iter().find(|p| matches!(p, TelemetryAnnotation::Wheelspin { avg_rpm_increase_per_gear: _, cur_gear: _, cur_rpm_increase: _, is_wheelspin: _ })) {
295+
self.selected_annotation_content = format!(
296+
"Gear: {}\nRPM increase: {:.1}\np90 RPM increase: {:.1}\nRPM increase per gear:\n{}",
297+
cur_gear,
298+
cur_rpm_increase,
299+
avg_rpm_increase_per_gear.get(cur_gear).unwrap(),
300+
serde_json::to_string_pretty(avg_rpm_increase_per_gear).unwrap()
301+
);
302+
}
303+
}
304+
ui.separator();
305+
if trailbrake_steering_alert.show(ui, Align::Center).clicked() {
306+
if let Some(TelemetryAnnotation::TrailbrakeSteering { cur_trailbrake_steering, is_excessive_trailbrake_steering: _ }) =
307+
telemetry.annotations.iter().find(|p| matches!(p, TelemetryAnnotation::TrailbrakeSteering { cur_trailbrake_steering: _, is_excessive_trailbrake_steering: _ })) {
308+
self.selected_annotation_content = format!(
309+
"Steering: {:.2}%\nSteering angle (rad): {}",
310+
cur_trailbrake_steering,
311+
telemetry.steering
312+
);
313+
}
314+
}
315+
ui.separator();
316+
if slip_alert.show(ui, Align::Center).clicked() {
317+
if let Some(TelemetryAnnotation::Scrub { avg_yaw_rate_change, cur_yaw_rate_change, is_scrubbing: _ }) =
318+
telemetry.annotations.iter().find(|p| matches!(p, TelemetryAnnotation::Scrub { avg_yaw_rate_change: _, cur_yaw_rate_change: _, is_scrubbing: _ })) {
319+
self.selected_annotation_content = format!(
320+
"Yaw change: {:.2}\nAvg yaw change: {:.2}\nSteering (rad): {:.2}\nSpeed: {:.2}",
321+
cur_yaw_rate_change,
322+
avg_yaw_rate_change,
323+
telemetry.steering,
324+
telemetry.cur_speed
325+
);
326+
}
327+
if let Some(TelemetryAnnotation::Slip { prev_speed, cur_speed, is_slip: _ }) =
328+
telemetry.annotations.iter().find(|p| matches!(p, TelemetryAnnotation::Slip { prev_speed: _, cur_speed: _, is_slip: _ })) {
329+
self.selected_annotation_content = format!(
330+
"Speed: {:.2}\nPrev speed: {:.2}\nThrottle %: {:.2}%\nSteering (rad): {:.2}%",
331+
cur_speed,
332+
prev_speed,
333+
telemetry.throttle,
334+
telemetry.steering
335+
);
336+
}
337+
}
338+
});
339+
260340
local_ui.add(
261-
TextEdit::multiline(&mut str_buffer)
262-
.interactive(false)
263-
.desired_width(ctx.available_rect().width() * 0.3)
264-
.code_editor(),
341+
Label::new(RichText::new(self.selected_annotation_content.clone()).color(Color32::WHITE))
265342
);
266343
}
267344
}

src/ui/mod.rs

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::time::SystemTime;
22

3-
use egui::{Align, Color32, Image, Layout, RichText, Ui};
3+
use egui::{Align, Color32, Image, ImageButton, Layout, Response, RichText, Ui};
44
use log::debug;
55

66
use crate::{
@@ -16,13 +16,14 @@ pub(crate) type AlertImageSelector<'a> = fn(&TelemetryPoint) -> Image<'a>;
1616

1717
pub(crate) trait Alert {
1818
fn update_state(&mut self, telemetry_point: &TelemetryPoint) -> Result<(), OcypodeError>;
19-
fn show(&mut self, ui: &mut Ui, align: Align);
19+
fn show(&mut self, ui: &mut Ui, align: Align) -> Response;
2020
}
2121

2222
pub(crate) struct DefaultAlert<'i> {
2323
image_selector: AlertImageSelector<'i>,
2424
current_image: Image<'i>,
2525
text: String,
26+
is_button: bool,
2627
}
2728

2829
impl<'i> DefaultAlert<'i> {
@@ -31,6 +32,7 @@ impl<'i> DefaultAlert<'i> {
3132
image_selector,
3233
text,
3334
current_image: image_selector(&TelemetryPoint::default()),
35+
is_button: false,
3436
}
3537
}
3638

@@ -123,6 +125,11 @@ impl<'i> DefaultAlert<'i> {
123125
trailbrake_image.into()
124126
})
125127
}
128+
129+
pub(crate) fn button(mut self) -> Self {
130+
self.is_button = true;
131+
self
132+
}
126133
}
127134

128135
impl Alert for DefaultAlert<'_> {
@@ -131,18 +138,24 @@ impl Alert for DefaultAlert<'_> {
131138
Ok(())
132139
}
133140

134-
fn show(&mut self, ui: &mut Ui, align: Align) {
141+
fn show(&mut self, ui: &mut Ui, align: Align) -> Response {
135142
ui.with_layout(Layout::top_down(align), |ui| {
136143
ui.label(RichText::new(self.text.clone()).color(Color32::WHITE));
137-
ui.add(self.current_image.clone());
138-
});
144+
if self.is_button {
145+
ui.add(ImageButton::new(self.current_image.clone()).frame(false))
146+
} else {
147+
ui.add(self.current_image.clone())
148+
}
149+
})
150+
.inner
139151
}
140152
}
141153

142154
pub(crate) struct ScrubSlipAlert {
143155
alert_start_time: SystemTime,
144156
is_slip: bool,
145157
is_scrub: bool,
158+
is_button: bool,
146159
}
147160

148161
impl Default for ScrubSlipAlert {
@@ -151,10 +164,18 @@ impl Default for ScrubSlipAlert {
151164
alert_start_time: SystemTime::now(),
152165
is_slip: false,
153166
is_scrub: false,
167+
is_button: false,
154168
}
155169
}
156170
}
157171

172+
impl ScrubSlipAlert {
173+
pub(crate) fn button(mut self) -> Self {
174+
self.is_button = true;
175+
self
176+
}
177+
}
178+
158179
impl Alert for ScrubSlipAlert {
159180
fn update_state(&mut self, telemetry_point: &TelemetryPoint) -> Result<(), OcypodeError> {
160181
for annotation in &telemetry_point.annotations {
@@ -183,7 +204,7 @@ impl Alert for ScrubSlipAlert {
183204
Ok(())
184205
}
185206

186-
fn show(&mut self, ui: &mut Ui, button_align: Align) {
207+
fn show(&mut self, ui: &mut Ui, button_align: Align) -> Response {
187208
let mut turn_image = egui::include_image!("../../assets/turn-grey.png");
188209
let mut text = "slip";
189210
if SystemTime::now()
@@ -204,8 +225,13 @@ impl Alert for ScrubSlipAlert {
204225

205226
ui.with_layout(Layout::top_down(button_align), |ui| {
206227
ui.label(RichText::new(text).color(Color32::WHITE));
207-
ui.add(Image::new(turn_image));
208-
});
228+
if self.is_button {
229+
ui.add(ImageButton::new(turn_image).frame(false))
230+
} else {
231+
ui.add(Image::new(turn_image))
232+
}
233+
})
234+
.inner
209235
}
210236
}
211237

0 commit comments

Comments
 (0)