Files
FitTrack2/FitnessSync/scratch/debug_specific_matches.py
2026-01-11 06:06:43 -08:00

169 lines
6.6 KiB
Python

import sys
import os
import statistics
import logging
sys.path.append('/app/backend')
from src.services.postgresql_manager import PostgreSQLManager
from src.utils.config import config
from src.models.activity import Activity
from src.models.bike_setup import BikeSetup
from src.services.parsers import extract_activity_data
from src.services.bike_matching import WHEEL_CIRCUMFERENCE_M
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Re-implement logic to capture samples
def analyze_streams_debug(speed_stream, cadence_stream, window_size=10):
if not speed_stream or not cadence_stream or len(speed_stream) != len(cadence_stream):
print(" - Streams missing or mismatched length")
return [], 0.0
ratios = []
samples = []
rejected_reasons = {'none': 0, 'threshold': 0, 'variance': 0}
n = len(speed_stream)
for i in range(0, n - window_size, 5):
window_speeds = speed_stream[i:i+window_size]
window_cadences = cadence_stream[i:i+window_size]
if any(v is None for v in window_speeds) or any(c is None for c in window_cadences):
rejected_reasons['none'] += 1
continue
if all(c > 55 for c in window_cadences) and all(v > 2.5 for v in window_speeds):
try:
cad_std = statistics.stdev(window_cadences)
spd_std = statistics.stdev(window_speeds)
if cad_std < 5 and spd_std < 0.5:
avg_speed = statistics.mean(window_speeds)
avg_cadence = statistics.mean(window_cadences)
ratio = (avg_speed * 60) / (avg_cadence * WHEEL_CIRCUMFERENCE_M)
ratios.append(ratio)
if len(samples) < 10:
samples.append({
'time_idx': i,
'avg_spd': avg_speed,
'avg_cad': avg_cadence,
'ratio': ratio,
'cad_std': cad_std
})
else:
rejected_reasons['variance'] += 1
except statistics.StatisticsError:
pass
else:
rejected_reasons['threshold'] += 1
if not ratios:
print(f" - No steady segments. Rejections: {rejected_reasons}")
return [], 0.0
return samples, statistics.median(ratios)
def main():
target_ids = ['21072264737', '18469350198', '18349164690']
db = PostgreSQLManager(config.DATABASE_URL).SessionLocal()
# Load all setups
setups = db.query(BikeSetup).all()
print(f"Loaded {len(setups)} bike setups.")
for s in setups:
if s.rear_cog == 0:
print(f" - {s.name or s.frame}: No gears configured (skipped)")
continue
mech_ratio = s.chainring / s.rear_cog
print(f" - {s.name or s.frame}: {s.chainring}/{s.rear_cog} = {mech_ratio:.3f} (Active: {s.purchase_date} to {s.retirement_date})")
print("\n" + "="*80)
# Add a control activity to verify script works
print("\n" + "="*80)
print("CONTROL CHECK: Finding a random activity WITH cadence to verify script logic...")
control_activity = db.query(Activity).filter(Activity.avg_cadence > 0, Activity.file_content != None).first()
if control_activity:
target_ids.append(control_activity.garmin_activity_id)
else:
print("No control activity found!")
for gid in target_ids:
print(f"\nAnalyzing Activity Garmin ID: {gid}")
activity = db.query(Activity).filter(Activity.garmin_activity_id == str(gid)).first()
if not activity:
print(" - Not found in DB")
continue
print(f" - Type: {activity.activity_type}")
print(f" - Date: {activity.start_time}")
print(f" - Global Avg Speed: {activity.avg_speed:.2f} m/s" if activity.avg_speed else " - Global Avg Speed: None")
print(f" - Global Avg Cadence: {activity.avg_cadence:.1f} rpm" if activity.avg_cadence else " - Global Avg Cadence: None")
if not activity.file_content:
print(" - No file content available")
continue
data = extract_activity_data(activity.file_content, activity.file_type)
speeds = data.get('speed') or []
cadences = data.get('cadence') or []
# Check if actual data exists
valid_speeds = [x for x in speeds if x is not None]
valid_cadences = [x for x in cadences if x is not None]
if len(valid_cadences) < 10:
print(" - CRITICAL: No cadence data stream found in file.")
print(" - Result: IMPOSSIBLE TO MATCH GEAR RATIO.")
continue
samples, observed_ratio = analyze_streams_debug(speeds, cadences)
print(f" - Steady Segments Found: {len(samples) if samples else 0}")
print(f" - Observed Ratio (Median): {observed_ratio:.3f}")
if samples:
print(" - First 10 Steady Samples:")
for s in samples:
print(f" - T={s['time_idx']}s | Spd={s['avg_spd']:.1f} | Cad={s['avg_cad']:.1f} | R={s['ratio']:.3f} (std_cad={s['cad_std']:.1f})")
# ... logic continues ...
print("\n - Matching Against Setups:")
if observed_ratio > 0:
for bike in setups:
if bike.rear_cog == 0:
continue
# Date Check
active = True
if bike.purchase_date and activity.start_time.date() < bike.purchase_date:
active = False
if bike.retirement_date and activity.start_time.date() > bike.retirement_date:
active = False
status_str = "ACTIVE" if active else "INACTIVE"
mech_ratio = bike.chainring / bike.rear_cog
diff = abs(observed_ratio - mech_ratio)
error_pct = diff / mech_ratio
confidence = max(0.0, 1.0 - error_pct)
marker = "<<< BEST MATCH" if confidence > 0.9 else ""
if not active: marker = "(Date Mismatch)"
print(f" - {bike.name or bike.frame} ({bike.chainring}/{bike.rear_cog}): Mech={mech_ratio:.3f} | Diff={diff:.3f} | Conf={confidence:.3f} [{status_str}] {marker}")
else:
print(" - Could not calculate valid observed ratio from streams.")
db.close()
if __name__ == "__main__":
main()