import sys import os import json import logging from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker # Add backend to path sys.path.append(os.path.join(os.getcwd(), 'backend')) 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 from src.utils.geo import haversine_distance, calculate_bounds, ramer_douglas_peucker from src.utils.config import config # Setup DB engine = create_engine(config.DATABASE_URL) Session = sessionmaker(bind=engine) db = Session() def auto_create_segments(garmin_activity_id, split_dist_meters=1000): print(f"\n--- Auto Creating Segments for {garmin_activity_id} (Split: {split_dist_meters}m) ---") activity = db.query(Activity).filter(Activity.garmin_activity_id == garmin_activity_id).first() if not activity: print(f"Activity {garmin_activity_id} not found in DB.") return # Extract points points = extract_points_from_file(activity.file_content, activity.file_type) if not points or len(points) < 2: print("No points found in activity.") return print(f"Total Points: {len(points)}") accum_dist = 0.0 split_start_idx = 0 split_count = 1 segments_created = [] for i in range(1, len(points)): p1 = points[i-1] p2 = points[i] # dist between p1 and p2 d = haversine_distance(p1[1], p1[0], p2[1], p2[0]) accum_dist += d if accum_dist >= split_dist_meters: # Create segment split_end_idx = i seg_points = points[split_start_idx : split_end_idx + 1] # Simplify simple_points = ramer_douglas_peucker(seg_points, epsilon=5.0) bounds = calculate_bounds(seg_points) # Calc actual distance & elevation seg_dist = 0.0 seg_elev_gain = 0.0 for k in range(len(seg_points)-1): sp1 = seg_points[k] sp2 = seg_points[k+1] seg_dist += haversine_distance(sp1[1], sp1[0], sp2[1], sp2[0]) if len(sp1) > 2 and len(sp2) > 2 and sp1[2] is not None and sp2[2] is not None: diff = sp2[2] - sp1[2] if diff > 0: seg_elev_gain += diff name = f"AutoSplit #{split_count} ({garmin_activity_id})" print(f"Creating Segment: {name} | Dist: {seg_dist:.1f}m | Elev: {seg_elev_gain:.1f}m | Indices: {split_start_idx}-{split_end_idx}") segment = Segment( name=name, description=f"Auto-generated {split_dist_meters}m split", distance=seg_dist, elevation_gain=seg_elev_gain, activity_type=activity.activity_type or 'cycling', points=json.dumps(simple_points), bounds=json.dumps(bounds) ) db.add(segment) segments_created.append(segment) # Reset for next split accum_dist = 0.0 split_start_idx = i split_count += 1 db.commit() print(f"\nCreated {len(segments_created)} segments.") # Trigger Matching if segments_created: print("\nTriggering Segment Matcher...") matcher = SegmentMatcher(db) matcher.match_activity(activity, points) print("Matching complete.") if __name__ == "__main__": auto_create_segments("21249259141", 1000)