diff --git a/apps/ops/src/pages/PlanificationPage.vue b/apps/ops/src/pages/PlanificationPage.vue index 6435515..f9bbf41 100644 --- a/apps/ops/src/pages/PlanificationPage.vue +++ b/apps/ops/src/pages/PlanificationPage.vue @@ -4103,7 +4103,7 @@ async function optimizeSuggestion () { } if (!vehicles.length) { out.push(...entries); continue } // aucun tech éligible (ex. week-end sans quart) → garder l'assignation greedy let res - try { res = await roster.optimizeRoutes({ jobs, vehicles, max_seconds: 8, rank_weight: 6 }) } catch (e) { out.push(...entries); continue } + try { res = await roster.optimizeRoutes({ jobs, vehicles, max_seconds: 8, rank_weight: 2 }) } catch (e) { out.push(...entries); continue } // rank_weight faible = DISTANCE prioritaire, spécialité = simple départage if (!res || res.status !== 'OK') { out.push(...entries); continue } // solveur absent/erreur/infaisable → on GARDE l'assignation greedy (ne jamais perdre de jobs) const placed = new Set() for (const rt of (res.routes || [])) { diff --git a/services/roster-solver/route_solver.py b/services/roster-solver/route_solver.py index 1e86953..60b84a6 100644 --- a/services/roster-solver/route_solver.py +++ b/services/roster-solver/route_solver.py @@ -46,7 +46,10 @@ def solve_route(req: dict) -> dict: speed = float(req.get("speed_kmh") or 45.0) default_service = int(req.get("default_service_min") or 60) - rank_w = float(req.get("rank_weight") or 5.0) # « minutes virtuelles » par cran d'ordre de compétence (spécialiste=0) + # DISTANCE PRIORITAIRE : la spécialité (ordre de compétence) ne fait que DÉPARTAGER à trajet ~égal. + # rank_w = « minutes virtuelles » par cran d'ordre (spécialiste=0). Petit → un tech multi-compétences PROCHE + # passe avant un spécialiste LOIN (ex. un installateur qui a aussi la réparation prend une réparation voisine). + rank_w = float(req.get("rank_weight") if req.get("rank_weight") is not None else 2.0) base_pen = int(req.get("drop_penalty") or 100000) max_seconds = float(req.get("max_seconds") or 10)