#!/usr/bin/env python3 """ Test script to verify the opening kickoff detection fix. Tests: 1. Tennessee: Opening kickoff should be detected around 117s 2. Oregon: Opening kickoff should be detected around 332s 3. Texas: Should REJECT the fake kickoff at 20.5s and detect real game start around 444s The fix requires: - k=3 consecutive clock readings to confirm kickoff start - Maximum kickoff duration of 90s (rejects if too long) """ import sys import logging from pathlib import Path # Add src to path sys.path.insert(0, str(Path(__file__).parent.parent / "src")) from config import SessionConfig, load_session_config, get_video_basename, OUTPUT_DIR from pipeline import run_extraction # Configure logging logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s") logger = logging.getLogger(__name__) def test_video(video_name: str, video_path: str, start_time: float, end_time: float, expected_kickoff_start: float, expected_kickoff_tolerance: float = 30.0): """ Test opening kickoff detection on a video segment. Args: video_name: Name for display video_path: Path to video file start_time: Start time in seconds end_time: End time in seconds expected_kickoff_start: Expected kickoff start time (within video segment) expected_kickoff_tolerance: Tolerance for kickoff timing match """ print(f"\n{'=' * 60}") print(f"Testing: {video_name}") print(f"Video: {video_path}") print(f"Time range: {start_time}s - {end_time}s") print(f"Expected kickoff around: {expected_kickoff_start}s (±{expected_kickoff_tolerance}s)") print("=" * 60) try: # Load existing session config for this video video_basename = get_video_basename(video_path, testing_mode=False) config_path = OUTPUT_DIR / f"{video_basename}_config.json" if not config_path.exists(): logger.error(f"Config not found: {config_path}") logger.error("Run main.py with --use-saved-regions first") return False # Load config and update time bounds session_config = load_session_config(str(config_path)) session_config.video_path = video_path session_config.start_time = start_time session_config.end_time = end_time session_config.video_basename = video_basename # Run extraction results = run_extraction(session_config, OUTPUT_DIR, num_workers=1) # Analyze results - plays are dicts, not objects plays = results.get("plays", []) kickoff_plays = [p for p in plays if p.get("play_type") == "kickoff"] print(f"\nResults:") print(f" Total plays detected: {len(plays)}") print(f" Kickoff plays: {len(kickoff_plays)}") success = True if kickoff_plays: for kp in kickoff_plays: start = kp.get("start_time", 0) end = kp.get("end_time", 0) print(f"\n Kickoff found:") print(f" Start: {start:.1f}s") print(f" End: {end:.1f}s") print(f" Duration: {end - start:.1f}s") # Check if within expected range diff = abs(start - expected_kickoff_start) if diff <= expected_kickoff_tolerance: print(f" ✅ PASS: Within expected range ({diff:.1f}s from expected)") else: print(f" ❌ FAIL: Outside expected range ({diff:.1f}s from expected)") success = False else: print(f"\n ❌ No kickoff detected!") success = False # Show first few plays for context print(f"\nFirst 5 plays:") for p in plays[:5]: pnum = p.get("play_number", "?") pstart = p.get("start_time", 0) pend = p.get("end_time", 0) ptype = p.get("play_type", "?") pmethod = p.get("start_method", "?") print(f" Play #{pnum}: {pstart:.1f}s - {pend:.1f}s ({ptype}, {pmethod})") return success except Exception as e: logger.error(f"Error testing {video_name}: {e}") import traceback traceback.print_exc() return False def main(): """Run all tests.""" base_path = Path("/Users/andytaylor/Documents/Personal/cfb40/full_videos") # Test configurations tests = [ { "video_name": "Tennessee (baseline - should pass)", "video_path": str(base_path / "OSU vs Tenn 12.21.24.mkv"), "start_time": 0, "end_time": 300, # First 5 minutes "expected_kickoff_start": 117, # ~1:57 video time "expected_kickoff_tolerance": 30, }, { "video_name": "Oregon (baseline - should pass)", "video_path": str(base_path / "OSU vs Oregon 01.01.25.mkv"), "start_time": 200, "end_time": 500, # Around kickoff time "expected_kickoff_start": 332, # ~5:32 video time "expected_kickoff_tolerance": 30, }, { "video_name": "Texas (fix test - should reject fake kickoff at 20s)", "video_path": str(base_path / "OSU vs Texas 01.10.25.mkv"), "start_time": 0, "end_time": 600, # First 10 minutes "expected_kickoff_start": 444, # Real game starts ~7:24 "expected_kickoff_tolerance": 30, }, ] print("\n" + "=" * 60) print("OPENING KICKOFF DETECTION FIX TEST") print("=" * 60) results = [] for test_config in tests: success = test_video(**test_config) results.append((test_config["video_name"], success)) # Summary print("\n" + "=" * 60) print("TEST SUMMARY") print("=" * 60) for name, success in results: status = "✅ PASS" if success else "❌ FAIL" print(f" {status}: {name}") if __name__ == "__main__": main()