many updates
This commit is contained in:
138
FitnessSync/scratch/debug_match.py
Normal file
138
FitnessSync/scratch/debug_match.py
Normal file
@@ -0,0 +1,138 @@
|
||||
|
||||
import logging
|
||||
from sqlalchemy.orm import Session
|
||||
from src.services.postgresql_manager import PostgreSQLManager
|
||||
from src.utils.config import config
|
||||
from src.models.activity import Activity
|
||||
from src.models.segment import Segment
|
||||
from src.services.segment_matcher import SegmentMatcher
|
||||
from src.services.parsers import extract_points_from_file
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def debug_matching():
|
||||
db_manager = PostgreSQLManager(config.DATABASE_URL)
|
||||
|
||||
with db_manager.get_db_session() as db:
|
||||
# 1. Fetch Segment
|
||||
segment = db.query(Segment).filter(Segment.name.like("%Etiwanda%")).first()
|
||||
if not segment:
|
||||
print("ERROR: Segment 'Etiwanda Climb' not found.")
|
||||
return
|
||||
|
||||
print(f"DEBUG: Found Segment ID {segment.id}: {segment.name}")
|
||||
print(f"DEBUG: Segment Distance: {segment.distance}")
|
||||
|
||||
# 2. Fetch Activity
|
||||
# Try finding by ID or Garmin ID
|
||||
act_id = 21072264737
|
||||
activity = db.query(Activity).filter(Activity.id == act_id).first()
|
||||
if not activity:
|
||||
activity = db.query(Activity).filter(Activity.garmin_activity_id == str(act_id)).first()
|
||||
|
||||
if not activity:
|
||||
print(f"ERROR: Activity {act_id} not found.")
|
||||
return
|
||||
|
||||
print(f"DEBUG: Found Activity ID {activity.id} (Garmin: {activity.garmin_activity_id})")
|
||||
|
||||
# 3. Extract Points
|
||||
if not activity.file_content:
|
||||
print("ERROR: Activity has no file content")
|
||||
return
|
||||
|
||||
points = extract_points_from_file(activity.file_content, activity.file_type)
|
||||
print(f"DEBUG: Extracted {len(points)} points from activity.")
|
||||
|
||||
# 4. Trigger Match
|
||||
matcher = SegmentMatcher(db)
|
||||
|
||||
# Manually invoke match parts to trace
|
||||
# (Copying logic from match_activity wrapper)
|
||||
|
||||
import json
|
||||
seg_points = json.loads(segment.points) if isinstance(segment.points, str) else segment.points
|
||||
|
||||
print(f"DEBUG: Segment has {len(seg_points)} points.")
|
||||
|
||||
print(f"DEBUG: Segment has {len(seg_points)} points.")
|
||||
|
||||
efforts = matcher.match_activity(activity, points)
|
||||
|
||||
if efforts:
|
||||
print(f"SUCCESS: match_activity returned {len(efforts)} efforts.")
|
||||
for e in efforts:
|
||||
print(f" - Segment {e.segment_id} (Duration: {e.elapsed_time}s)")
|
||||
else:
|
||||
print("FAILURE: match_activity returned NO efforts.")
|
||||
|
||||
# --- Deep Trace ---
|
||||
print("\n--- DEEP TRACE ---")
|
||||
ENTRY_RADIUS = 25.0
|
||||
CORRIDOR_RADIUS = 35.0
|
||||
from src.utils.geo import haversine_distance, perpendicular_distance
|
||||
|
||||
start_node = seg_points[0]
|
||||
end_node = seg_points[-1]
|
||||
|
||||
# Check Start Proximity
|
||||
start_candidates = []
|
||||
min_start_dist = float('inf')
|
||||
|
||||
for i, p in enumerate(points):
|
||||
dist = haversine_distance(p[1], p[0], start_node[1], start_node[0])
|
||||
if dist < min_start_dist: min_start_dist = dist
|
||||
if dist <= ENTRY_RADIUS:
|
||||
start_candidates.append(i)
|
||||
|
||||
print(f"Min distance to Start Node: {min_start_dist:.2f}m")
|
||||
print(f"Start Candidates: {start_candidates}")
|
||||
|
||||
if not start_candidates:
|
||||
print("FAIL: Start node never reached within 25m.")
|
||||
return
|
||||
|
||||
# Trace Candidate 0 (or all)
|
||||
for start_idx in start_candidates:
|
||||
print(f"\nChecking candidate starting at index {start_idx}...")
|
||||
|
||||
effort_accum_dist = 0.0
|
||||
deviated = False
|
||||
completed = False
|
||||
|
||||
max_deviation = 0.0
|
||||
|
||||
for j in range(start_idx + 1, len(points)):
|
||||
p = points[j]
|
||||
prev_p = points[j-1]
|
||||
|
||||
# Accumulate distance
|
||||
step_dist = haversine_distance(p[1], p[0], prev_p[1], prev_p[0])
|
||||
effort_accum_dist += step_dist
|
||||
|
||||
# Check deviation
|
||||
dev = matcher._min_dist_to_segment_path(p, seg_points)
|
||||
if dev > max_deviation: max_deviation = dev
|
||||
|
||||
if dev > CORRIDOR_RADIUS:
|
||||
print(f" DEVIATION at index {j}! Dist {dev:.2f}m > {CORRIDOR_RADIUS}m. AccumDist: {effort_accum_dist:.2f}m")
|
||||
deviated = True
|
||||
break
|
||||
|
||||
# Check completion
|
||||
d_end = haversine_distance(p[1], p[0], end_node[1], end_node[0])
|
||||
if d_end <= ENTRY_RADIUS:
|
||||
if effort_accum_dist >= 0.8 * segment.distance:
|
||||
print(f" COMPLETION possible at index {j}. d_end={d_end:.2f}m, dist={effort_accum_dist:.2f}m")
|
||||
completed = True
|
||||
# Don't break immediately, could get closer?
|
||||
# But logic breaks on completion check?
|
||||
# Logic: returns first valid end.
|
||||
|
||||
if not completed:
|
||||
print(f" Candidate ended without completion. Max Deviation: {max_deviation:.2f}m. Total Dist: {effort_accum_dist:.2f}m vs Target {segment.distance:.2f}m")
|
||||
|
||||
if __name__ == "__main__":
|
||||
debug_matching()
|
||||
Reference in New Issue
Block a user