11use std:: { path:: PathBuf , sync:: Arc } ;
22
33use 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} ;
77use egui_dropdown:: DropDownBox ;
88use egui_plot:: { Legend , Line , PlotPoints , Points } ;
99use itertools:: Itertools ;
1010
1111use 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 ) ]
2020struct 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
205208impl 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: {}\n To gear: {}\n Ideal RPM: {}\n Actual 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: {}\n RPM increase: {:.1}\n p90 RPM increase: {:.1}\n RPM 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}%\n Steering 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}\n Avg yaw change: {:.2}\n Steering (rad): {:.2}\n Speed: {:.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}\n Prev speed: {:.2}\n Throttle %: {:.2}%\n Steering (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 }
0 commit comments