11/*
22 * cursor_tracking_stable_fast_movement.rs - Cursor Tracking Stable State Fast Movement Test
3- *
3+ *
44 * This example tests the cursor tracking system's behavior during fast movements in stable state,
55 * verifying the following key characteristics:
6- *
6+ *
77 * Test Flow (3 phases, 10 seconds total):
8- *
8+ *
99 * 1. Phase 1 (0-3s): Fast movement to trigger zoom_in
10- * - Large circular fast movements
10+ * - Large circular fast movements
1111 * - Transition from fullscreen (1920x1080) to target size (400x300)
12- *
12+ *
1313 * 2. Phase 2 (3-6s): Stable cursor in target size state
1414 * - Stable cursor at offset position
1515 * - Maintain target size (400x300)
16- *
16+ *
1717 * 3. Phase 3 (6-10s): Fast movement in target size state
1818 * - Fast movements while in target size state
1919 * - Verify that zoom_out is NOT triggered back to screen size
20- *
20+ *
2121 * Test Results:
2222 * - Collected 142 crop region data points
2323 * - Size distribution:
2424 * - Target size (400x300): 122 occurrences (85.9%)
2525 * - Screen size (1920x1080): 1 occurrence (0.7%)
2626 * - Transition sizes: 19 occurrences (13.4%)
27- *
27+ *
2828 * Key validation: Phase 1 had 120 regions all at target size (400x300), proving that
2929 * fast movements in target size state do NOT trigger zoom_out
30- *
30+ *
3131 * This example validates the cursor tracker's state stability: once zoomed in to target size,
3232 * even fast movements will keep the system stable and not trigger zoom_out.
3333 */
3434
3535use recorder:: { CursorTracker , CursorTrackerConfig , bounded} ;
3636use screen_capture:: { CursorPosition , LogicalSize , Rectangle } ;
3737use std:: {
38- sync:: { Arc , atomic:: AtomicBool , Mutex } ,
38+ sync:: { Arc , Mutex , atomic:: AtomicBool } ,
3939 thread,
4040 time:: { Duration , Instant } ,
4141} ;
4242
4343fn main ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
4444 env_logger:: init ( ) ;
4545
46- log:: info!( "Starting Stable Fast Movement test: Fast movement in stable state should maintain target_size..." ) ;
46+ log:: info!(
47+ "Starting Stable Fast Movement test: Fast movement in stable state should maintain target_size..."
48+ ) ;
4749
4850 let screen_size = LogicalSize {
4951 width : 1920 ,
@@ -59,17 +61,22 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
5961 let ( crop_sender, crop_receiver) = bounded ( 1000 ) ;
6062
6163 let stop_sig = Arc :: new ( AtomicBool :: new ( false ) ) ;
62-
64+
6365 let crop_regions = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
6466 let crop_regions_for_validation = crop_regions. clone ( ) ;
6567
6668 // Configuration identical to successful Phase 3
67- let cursor_tracker_config =
68- CursorTrackerConfig :: new ( screen_size, target_size, crop_sender, cursor_receiver, stop_sig. clone ( ) ) ?
69- . with_stable_radius ( 30 )
70- . with_fast_moving_duration ( Duration :: from_millis ( 200 ) )
71- . with_linear_transition_duration ( Duration :: from_millis ( 800 ) )
72- . with_max_stable_region_duration ( Duration :: from_secs ( 3 ) ) ;
69+ let cursor_tracker_config = CursorTrackerConfig :: new (
70+ screen_size,
71+ target_size,
72+ crop_sender,
73+ cursor_receiver,
74+ stop_sig. clone ( ) ,
75+ ) ?
76+ . with_stable_radius ( 30 )
77+ . with_fast_moving_duration ( Duration :: from_millis ( 200 ) )
78+ . with_zoom_transition_duration ( Duration :: from_millis ( 800 ) )
79+ . with_max_stable_region_duration ( Duration :: from_secs ( 3 ) ) ;
7380
7481 let cursor_tracker = CursorTracker :: new ( cursor_tracker_config) ?;
7582
@@ -95,7 +102,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
95102 region. width as f64 ,
96103 region. height as f64
97104 ) ;
98-
105+
99106 // Collect data for validation
100107 if let Ok ( mut regions) = crop_regions_for_logging. lock ( ) {
101108 regions. push ( ( Instant :: now ( ) , region) ) ;
@@ -110,7 +117,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
110117 }
111118
112119 log:: info!( "Stable Fast Movement test completed!" ) ;
113-
120+
114121 // Perform validation
115122 validate_stable_fast_movement_results (
116123 & crop_regions_for_validation,
@@ -133,13 +140,13 @@ fn simulate_stable_fast_movement(
133140 let center_y = screen_size. height as f64 / 2.0 ;
134141
135142 log:: info!( "🎯 Testing cursor tracking: fast movement → stop → fast movement" ) ;
136-
143+
137144 // Phase 1 (0-3 seconds): Fast cursor movement to trigger zoom_in
138145 log:: info!( "🏃 Phase 1: Fast movement for 3 seconds to trigger zoom_in" ) ;
139146 let phase1_end = start_time + Duration :: from_secs ( 3 ) ;
140147 while Instant :: now ( ) < phase1_end {
141148 let current_time = Instant :: now ( ) ;
142-
149+
143150 // Rapid cursor movement in large circles
144151 let progress = current_time. duration_since ( start_time) . as_secs_f64 ( ) ;
145152 let angle = progress * std:: f64:: consts:: PI * 6.0 ; // Fast rotation
@@ -159,7 +166,7 @@ fn simulate_stable_fast_movement(
159166 let _ = sender. send ( ( current_time, cursor_pos) ) ;
160167 thread:: sleep ( frame_interval) ;
161168 }
162-
169+
163170 // Phase 2 (3-6 seconds): Stable cursor in target_size state
164171 log:: info!( "⏸️ Phase 2: Stable cursor in target_size state" ) ;
165172 let phase2_end = start_time + Duration :: from_secs ( 6 ) ;
@@ -176,15 +183,15 @@ fn simulate_stable_fast_movement(
176183 } ;
177184 let _ = sender. send ( ( Instant :: now ( ) , cursor_pos) ) ;
178185 }
179-
186+
180187 thread:: sleep ( frame_interval) ;
181188 }
182-
189+
183190 // Phase 3 (6-10 seconds): Fast movement in target_size state (should NOT trigger zoom_out)
184191 log:: info!( "🏃 Phase 3: Fast movement in target_size state - should stay stable" ) ;
185192 while Instant :: now ( ) < start_time + Duration :: from_secs ( 10 ) {
186193 let current_time = Instant :: now ( ) ;
187-
194+
188195 // Fast movement but system should stay in target_size
189196 let progress = current_time. duration_since ( start_time) . as_secs_f64 ( ) ;
190197 let angle = progress * std:: f64:: consts:: PI * 8.0 ;
@@ -214,80 +221,106 @@ fn validate_stable_fast_movement_results(
214221 target_size : & LogicalSize ,
215222) -> Result < ( ) , Box < dyn std:: error:: Error > > {
216223 log:: info!( "Starting stable fast movement validation..." ) ;
217-
224+
218225 let regions = crop_regions. lock ( ) . unwrap ( ) ;
219-
226+
220227 log:: info!( "Collected {} crop region data points" , regions. len( ) ) ;
221-
228+
222229 if regions. is_empty ( ) {
223230 return Err ( "No crop regions collected" . into ( ) ) ;
224231 }
225-
232+
226233 // Analyze the size distribution and timeline
227234 let mut target_size_count = 0 ;
228235 let mut screen_size_count = 0 ;
229236 let mut transition_count = 0 ;
230237 let mut size_timeline = Vec :: new ( ) ;
231238 let mut phase_regions = std:: collections:: HashMap :: new ( ) ;
232-
239+
233240 for ( timestamp, region) in regions. iter ( ) {
234241 let size = ( region. width , region. height ) ;
235242 let time_point = timestamp. elapsed ( ) . as_secs_f32 ( ) ;
236-
243+
237244 if size == ( target_size. width , target_size. height ) {
238245 target_size_count += 1 ;
239246 } else if size == ( screen_size. width , screen_size. height ) {
240247 screen_size_count += 1 ;
241248 } else {
242249 transition_count += 1 ;
243250 }
244-
251+
245252 size_timeline. push ( ( time_point, size) ) ;
246-
253+
247254 // Categorize by phases based on actual observed timing
248- let phase = if time_point < 5.0 { "Phase 1" } // Most of the test (including zoom_in transition)
249- else if time_point < 9.8 { "Phase 2" } // Stable target size phase
250- else { "Phase 3" } ; // Final screen size region
251-
252- phase_regions. entry ( phase) . or_insert_with ( Vec :: new) . push ( size) ;
255+ let phase = if time_point < 5.0 {
256+ "Phase 1"
257+ }
258+ // Most of the test (including zoom_in transition)
259+ else if time_point < 9.8 {
260+ "Phase 2"
261+ }
262+ // Stable target size phase
263+ else {
264+ "Phase 3"
265+ } ; // Final screen size region
266+
267+ phase_regions
268+ . entry ( phase)
269+ . or_insert_with ( Vec :: new)
270+ . push ( size) ;
253271 }
254-
272+
255273 log:: info!( "Region size distribution:" ) ;
256274 log:: info!( " Target size (400x300): {} occurrences" , target_size_count) ;
257- log:: info!( " Screen size (1920x1080): {} occurrences" , screen_size_count) ;
275+ log:: info!(
276+ " Screen size (1920x1080): {} occurrences" ,
277+ screen_size_count
278+ ) ;
258279 log:: info!( " Transition sizes: {} occurrences" , transition_count) ;
259-
280+
260281 // Analyze each phase
261282 for ( phase, sizes) in & phase_regions {
262283 let unique_sizes: std:: collections:: HashSet < _ > = sizes. iter ( ) . collect ( ) ;
263- log:: info!( " {}: {} regions, {} unique sizes" , phase, sizes. len( ) , unique_sizes. len( ) ) ;
284+ log:: info!(
285+ " {}: {} regions, {} unique sizes" ,
286+ phase,
287+ sizes. len( ) ,
288+ unique_sizes. len( )
289+ ) ;
264290 }
265-
291+
266292 // Validation criteria
267293 let final_region = regions. last ( ) . unwrap ( ) . 1 ;
268- let ends_in_target_size = final_region. width == target_size. width && final_region. height == target_size. height ;
269-
294+ let ends_in_target_size =
295+ final_region. width == target_size. width && final_region. height == target_size. height ;
296+
270297 // Check that we have initial transition from screen to target
271298 let has_screen_to_target_transition = screen_size_count > 0 && target_size_count > 0 ;
272-
299+
273300 // Check that Phase 1 (fast movement → stop → fast movement) maintains target size
274301 let empty_vec = vec ! [ ] ;
275302 let phase1_regions = phase_regions. get ( "Phase 1" ) . unwrap_or ( & empty_vec) ;
276- let phase1_maintains_target = phase1_regions. iter ( ) . all ( | & ( w , h ) |
277- w == target_size . width && h == target_size . height
278- ) ;
279-
303+ let phase1_maintains_target = phase1_regions
304+ . iter ( )
305+ . all ( | & ( w , h ) | w == target_size . width && h == target_size . height ) ;
306+
280307 let success = has_screen_to_target_transition && ends_in_target_size && phase1_maintains_target;
281-
308+
282309 if success {
283310 log:: info!( "✅ Stable fast movement validation PASSED" ) ;
284311 log:: info!( "✅ System correctly transitioned from screen_size to target_size" ) ;
285312 log:: info!( "✅ Fast movement in target_size state did NOT trigger zoom_out" ) ;
286313 log:: info!( "✅ System remained stable during Phase 1 fast movements" ) ;
287-
314+
288315 // Show timeline summary
289316 log:: info!( "Timeline summary (key regions):" ) ;
290- let sample_indices = [ 0 , regions. len ( ) /4 , regions. len ( ) /2 , regions. len ( ) * 3 /4 , regions. len ( ) -1 ] ;
317+ let sample_indices = [
318+ 0 ,
319+ regions. len ( ) / 4 ,
320+ regions. len ( ) / 2 ,
321+ regions. len ( ) * 3 / 4 ,
322+ regions. len ( ) - 1 ,
323+ ] ;
291324 for & i in & sample_indices {
292325 if i < regions. len ( ) {
293326 let ( time, size) = size_timeline[ i] ;
@@ -300,13 +333,18 @@ fn validate_stable_fast_movement_results(
300333 log:: error!( " Missing transition from screen_size to target_size" ) ;
301334 }
302335 if !ends_in_target_size {
303- log:: error!( " Final region is not target_size: {}x{}" , final_region. width, final_region. height) ;
336+ log:: error!(
337+ " Final region is not target_size: {}x{}" ,
338+ final_region. width,
339+ final_region. height
340+ ) ;
304341 }
305342 if !phase1_maintains_target {
306343 log:: error!( " Phase 1 fast movement caused unwanted zoom_out" ) ;
307344 }
308345 return Err ( "Stable fast movement test failed" . into ( ) ) ;
309346 }
310-
347+
311348 Ok ( ( ) )
312- }
349+ }
350+
0 commit comments