{ "horizon": { "start": "2026-06-08", "days": 7 }, "shift_templates": [ { "id": "jour", "name": "Jour 8h-16h", "start_h": 8, "end_h": 16, "hours": 8 }, { "id": "soir", "name": "Soir 14h-22h", "start_h": 14, "end_h": 22, "hours": 8 } ], "technicians": [ { "id": "T001", "name": "Marc Tremblay", "skills": ["fibre", "cuivre"], "max_hours_week": 40, "max_days": 5, "cost_per_h": 38, "zone_home": "Montréal", "preferred_off": ["sam", "dim"], "unavailable": [] }, { "id": "T002", "name": "Sophie Gagnon", "skills": ["fibre"], "max_hours_week": 40, "max_days": 5, "cost_per_h": 35, "zone_home": "Laval", "preferred_off": ["dim"], "unavailable": ["2026-06-10", "2026-06-11"] }, { "id": "T003", "name": "Hugo Thibert", "skills": ["fibre", "cuivre", "aerien"], "max_hours_week": 44, "max_days": 6, "cost_per_h": 42, "zone_home": "Montréal", "preferred_off": ["dim"], "unavailable": [] }, { "id": "T004", "name": "Émilie Roy", "skills": ["fibre"], "max_hours_week": 32, "max_days": 4, "cost_per_h": 33, "zone_home": "Laval", "preferred_off": ["sam", "dim"], "unavailable": [] } ], "coverage": [ { "date": "2026-06-08", "shift": "jour", "zone": "Montréal", "required": 2, "required_skills": ["fibre"] }, { "date": "2026-06-08", "shift": "jour", "zone": "Laval", "required": 1, "required_skills": ["fibre"] }, { "date": "2026-06-09", "shift": "jour", "zone": "Montréal", "required": 2, "required_skills": ["fibre"] }, { "date": "2026-06-09", "shift": "soir", "zone": "Montréal", "required": 1, "required_skills": ["aerien"] }, { "date": "2026-06-10", "shift": "jour", "zone": "Montréal", "required": 2, "required_skills": ["fibre"] }, { "date": "2026-06-10", "shift": "jour", "zone": "Laval", "required": 1, "required_skills": ["fibre"] }, { "date": "2026-06-11", "shift": "jour", "zone": "Montréal", "required": 2, "required_skills": ["cuivre"] }, { "date": "2026-06-12", "shift": "jour", "zone": "Montréal", "required": 3, "required_skills": ["fibre"] }, { "date": "2026-06-13", "shift": "jour", "zone": "Montréal", "required": 1, "required_skills": ["fibre"] } ], "weights": { "uncovered": 1000, "fairness": 5, "cost": 1, "preference": 8, "continuity": 4 }, "max_seconds": 10 }