147 lines
3.7 KiB
Python
147 lines
3.7 KiB
Python
|
|
"""
|
||
|
|
Evaluation Endpoints - Training Type Profiles
|
||
|
|
Endpoints for activity evaluation and re-evaluation.
|
||
|
|
|
||
|
|
Issue: #15
|
||
|
|
Date: 2026-03-23
|
||
|
|
"""
|
||
|
|
import logging
|
||
|
|
from typing import Optional
|
||
|
|
from fastapi import APIRouter, HTTPException, Depends
|
||
|
|
|
||
|
|
from db import get_db, get_cursor, r2d
|
||
|
|
from auth import require_auth, require_admin
|
||
|
|
from evaluation_helper import (
|
||
|
|
evaluate_and_save_activity,
|
||
|
|
batch_evaluate_activities,
|
||
|
|
load_parameters_registry
|
||
|
|
)
|
||
|
|
|
||
|
|
router = APIRouter(prefix="/api/evaluation", tags=["evaluation"])
|
||
|
|
logger = logging.getLogger(__name__)
|
||
|
|
|
||
|
|
|
||
|
|
@router.get("/parameters")
|
||
|
|
def list_parameters(session: dict = Depends(require_auth)):
|
||
|
|
"""
|
||
|
|
List all available training parameters.
|
||
|
|
"""
|
||
|
|
with get_db() as conn:
|
||
|
|
cur = get_cursor(conn)
|
||
|
|
parameters = load_parameters_registry(cur)
|
||
|
|
|
||
|
|
return {
|
||
|
|
"parameters": list(parameters.values()),
|
||
|
|
"count": len(parameters)
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
@router.post("/activity/{activity_id}")
|
||
|
|
def evaluate_activity(
|
||
|
|
activity_id: str,
|
||
|
|
session: dict = Depends(require_auth)
|
||
|
|
):
|
||
|
|
"""
|
||
|
|
Evaluates or re-evaluates a single activity.
|
||
|
|
|
||
|
|
Returns the evaluation result.
|
||
|
|
"""
|
||
|
|
profile_id = session['profile_id']
|
||
|
|
|
||
|
|
with get_db() as conn:
|
||
|
|
cur = get_cursor(conn)
|
||
|
|
|
||
|
|
# Load activity
|
||
|
|
cur.execute("""
|
||
|
|
SELECT id, profile_id, date, training_type_id, duration_min,
|
||
|
|
hr_avg, hr_max, distance_km, kcal_active, kcal_resting,
|
||
|
|
rpe, pace_min_per_km, cadence, elevation_gain
|
||
|
|
FROM activity_log
|
||
|
|
WHERE id = %s AND profile_id = %s
|
||
|
|
""", (activity_id, profile_id))
|
||
|
|
|
||
|
|
activity = cur.fetchone()
|
||
|
|
if not activity:
|
||
|
|
raise HTTPException(404, "Activity not found")
|
||
|
|
|
||
|
|
activity_dict = dict(activity)
|
||
|
|
|
||
|
|
# Evaluate
|
||
|
|
result = evaluate_and_save_activity(
|
||
|
|
cur,
|
||
|
|
activity_dict["id"],
|
||
|
|
activity_dict,
|
||
|
|
activity_dict["training_type_id"],
|
||
|
|
profile_id
|
||
|
|
)
|
||
|
|
|
||
|
|
if not result:
|
||
|
|
return {
|
||
|
|
"message": "No profile configured for this training type",
|
||
|
|
"evaluation": None
|
||
|
|
}
|
||
|
|
|
||
|
|
return {
|
||
|
|
"message": "Activity evaluated",
|
||
|
|
"evaluation": result
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
@router.post("/batch")
|
||
|
|
def batch_evaluate(
|
||
|
|
limit: Optional[int] = None,
|
||
|
|
session: dict = Depends(require_auth)
|
||
|
|
):
|
||
|
|
"""
|
||
|
|
Re-evaluates all activities for the current user.
|
||
|
|
|
||
|
|
Optional limit parameter for testing.
|
||
|
|
"""
|
||
|
|
profile_id = session['profile_id']
|
||
|
|
|
||
|
|
with get_db() as conn:
|
||
|
|
cur = get_cursor(conn)
|
||
|
|
stats = batch_evaluate_activities(cur, profile_id, limit)
|
||
|
|
|
||
|
|
return {
|
||
|
|
"message": "Batch evaluation completed",
|
||
|
|
"stats": stats
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
@router.post("/batch/all")
|
||
|
|
def batch_evaluate_all(session: dict = Depends(require_admin)):
|
||
|
|
"""
|
||
|
|
Admin-only: Re-evaluates all activities for all users.
|
||
|
|
|
||
|
|
Use with caution on large databases!
|
||
|
|
"""
|
||
|
|
with get_db() as conn:
|
||
|
|
cur = get_cursor(conn)
|
||
|
|
|
||
|
|
# Get all profiles
|
||
|
|
cur.execute("SELECT id FROM profiles")
|
||
|
|
profiles = cur.fetchall()
|
||
|
|
|
||
|
|
total_stats = {
|
||
|
|
"profiles": len(profiles),
|
||
|
|
"total": 0,
|
||
|
|
"evaluated": 0,
|
||
|
|
"skipped": 0,
|
||
|
|
"errors": 0
|
||
|
|
}
|
||
|
|
|
||
|
|
for profile in profiles:
|
||
|
|
profile_id = profile['id']
|
||
|
|
stats = batch_evaluate_activities(cur, profile_id)
|
||
|
|
|
||
|
|
total_stats["total"] += stats["total"]
|
||
|
|
total_stats["evaluated"] += stats["evaluated"]
|
||
|
|
total_stats["skipped"] += stats["skipped"]
|
||
|
|
total_stats["errors"] += stats["errors"]
|
||
|
|
|
||
|
|
return {
|
||
|
|
"message": "Batch evaluation for all users completed",
|
||
|
|
"stats": total_stats
|
||
|
|
}
|