"""Suggestions du solveur (OR-Tools CP-SAT). Ne persiste rien : la coordination affecte elle-même, dans l'écran habituel, en tenant compte des bénévoles remontés en tête de liste.""" import logging import time import uuid from fastapi import APIRouter, Depends from sqlmodel import Session from app.api.deps import get_edition from app.api.schemas import SolverRunResult, SolverSuggestion from app.auth.deps import require_staff from app.db import get_session from app.models import Account, Edition from app.solver import build_solver_input, solve logger = logging.getLogger("app.solver") router = APIRouter(prefix="/editions/{edition_id}/solver", tags=["solver"]) @router.post("/suggestions", response_model=SolverRunResult) def run_solver( edition: Edition = Depends(get_edition), _guard: Account = Depends(require_staff), session: Session = Depends(get_session), ) -> SolverRunResult: started = time.monotonic() data = build_solver_input(session=session, edition=edition) loaded = time.monotonic() solution = solve(data) logger.info( "Solveur (édition %s) : %d créneaux, %d bénévoles, %d suggestions — " "chargement %d ms, résolution %d ms", edition.id, len(data.shifts), len(data.volunteers), len(solution.suggestions), (loaded - started) * 1000, (time.monotonic() - loaded) * 1000, ) return SolverRunResult( suggestions=[ SolverSuggestion( shift_id=uuid.UUID(s.shift_id), volunteer_ids=[uuid.UUID(v) for v in s.volunteer_ids], ) for s in solution.suggestions ], shifts_considered=len(data.shifts), volunteers_considered=len(data.volunteers), )