INITIAL COMMIT
This commit is contained in:
110
scripts/analyze_dump.py
Executable file
110
scripts/analyze_dump.py
Executable file
@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
|
||||
|
||||
from garmin_coach_clone.coach import (
|
||||
best_workout_for_date,
|
||||
find_date_matches,
|
||||
find_workout_like_objects,
|
||||
)
|
||||
from garmin_coach_clone.dates import parse_date
|
||||
from garmin_coach_clone.io import dump_redacted_json, print_json
|
||||
from garmin_coach_clone.workouts import (
|
||||
clone_workout_payload,
|
||||
summarize_workout,
|
||||
validate_workout_payload,
|
||||
)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="Analyze saved Garmin JSON without logging in.")
|
||||
parser.add_argument("json_file", type=Path, help="Path to a saved JSON dump.")
|
||||
parser.add_argument("--date", default="today", help="today, tomorrow, or YYYY-MM-DD")
|
||||
parser.add_argument(
|
||||
"--clone-dry-run",
|
||||
action="store_true",
|
||||
help="Build a local clone payload from the matched workout.",
|
||||
)
|
||||
parser.add_argument("--prefix", default="GCClone", help="Clone workout name prefix.")
|
||||
parser.add_argument(
|
||||
"--dump-json", action="store_true", help="Write analysis JSON under debug/."
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
target_date = parse_date(args.date)
|
||||
data = _load_json(args.json_file)
|
||||
date_matches = find_date_matches(data, target_date)
|
||||
workout_like = find_workout_like_objects(data)
|
||||
matched = best_workout_for_date(data, target_date)
|
||||
|
||||
analysis: dict[str, Any] = {
|
||||
"source": str(args.json_file),
|
||||
"target_date": target_date.isoformat(),
|
||||
"date_match_count": len(date_matches),
|
||||
"workout_like_count": len(workout_like),
|
||||
"matched_workout": matched is not None,
|
||||
}
|
||||
|
||||
print(f"Source: {args.json_file}")
|
||||
print(f"Target date: {target_date.isoformat()}")
|
||||
print(f"Date-containing objects: {len(date_matches)}")
|
||||
print(f"Workout-like objects with workoutSegments/workoutSteps: {len(workout_like)}")
|
||||
|
||||
if matched is None:
|
||||
print("No dated workout-like object was found.")
|
||||
if args.dump_json:
|
||||
out = _analysis_path(args.json_file)
|
||||
dump_redacted_json(out, analysis)
|
||||
print(f"Analysis JSON written to {out}")
|
||||
return 1
|
||||
|
||||
print("\nMatched workout summary:")
|
||||
print(summarize_workout(matched))
|
||||
|
||||
if args.clone_dry_run:
|
||||
payload = clone_workout_payload(matched, target_date, args.prefix)
|
||||
errors = validate_workout_payload(payload)
|
||||
analysis["clone_validation_errors"] = errors
|
||||
analysis["clone_payload"] = payload
|
||||
if errors:
|
||||
print("\nLocal clone payload failed validation:")
|
||||
for error in errors:
|
||||
print(f" - {error}")
|
||||
return_code = 1
|
||||
else:
|
||||
print("\nLocal clone payload passed validation.")
|
||||
print_json(payload)
|
||||
return_code = 0
|
||||
else:
|
||||
return_code = 0
|
||||
|
||||
if args.dump_json:
|
||||
out = _analysis_path(args.json_file)
|
||||
dump_redacted_json(out, analysis)
|
||||
print(f"Analysis JSON written to {out}")
|
||||
return return_code
|
||||
|
||||
|
||||
def _load_json(path: Path) -> Any:
|
||||
try:
|
||||
return json.loads(path.read_text(encoding="utf-8"))
|
||||
except FileNotFoundError:
|
||||
raise SystemExit(f"File not found: {path}") from None
|
||||
except json.JSONDecodeError as exc:
|
||||
raise SystemExit(f"Invalid JSON in {path}: {exc}") from None
|
||||
|
||||
|
||||
def _analysis_path(source: Path) -> Path:
|
||||
stem = source.stem.replace(".", "_")
|
||||
return Path("debug") / f"analysis_{stem}.json"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user