Increase max_number in LimitGradeNumberConstraint from 1 to 2 for better shift allocation and add internal leave removal functionality

This commit is contained in:
Ross
2026-01-07 21:58:50 +00:00
parent e637c5ac60
commit 277f14747a
+38 -1
View File
@@ -243,7 +243,7 @@ def main(
PreShiftConstraint(days=2), PreShiftConstraint(days=2),
PostShiftConstraint(days=2), PostShiftConstraint(days=2),
RequireRemoteSitePresenceConstraint(site="plymouth", required_number=1), RequireRemoteSitePresenceConstraint(site="plymouth", required_number=1),
LimitGradeNumberConstraint(grade=2, max_number=1), LimitGradeNumberConstraint(grade=2, max_number=2),
MinimumGradeNumberConstraint(grade=4, min_number=1), MinimumGradeNumberConstraint(grade=4, min_number=1),
], ],
#end_date=datetime.datetime.strptime("2025-06-01", "%Y-%m-%d").date(), #end_date=datetime.datetime.strptime("2025-06-01", "%Y-%m-%d").date(),
@@ -283,6 +283,8 @@ def main(
Rota.add_min_summed_grade_by_shifts_per_day_constraint(["weekend_plymouth1", "weekend_plymouth2"], 6) Rota.add_min_summed_grade_by_shifts_per_day_constraint(["weekend_plymouth1", "weekend_plymouth2"], 6)
Rota.add_min_summed_grade_by_shifts_per_day_constraint(["plymouth_twilight", "plymouth_bank_holidays"], 6) Rota.add_min_summed_grade_by_shifts_per_day_constraint(["plymouth_twilight", "plymouth_bank_holidays"], 6)
Rota.add_min_summed_grade_by_shifts_per_day_constraint(["night_weekday"], 12)
Rota.terminate_on_warning.remove("Worker/no valid shifts") Rota.terminate_on_warning.remove("Worker/no valid shifts")
load_leave = True load_leave = True
@@ -292,8 +294,43 @@ def main(
if load_leave: if load_leave:
import leave import leave
# Internal-only option: remove leave requests between two dates.
# Configure by editing the two variables below (not exposed via CLI).
# Use strings in 'YYYY-MM-DD' or datetime.date objects. Set either to None to disable.
REMOVE_LEAVE_FROM = ""
REMOVE_LEAVE_TO = ""
workers = leave.load_leave(Rota) workers = leave.load_leave(Rota)
# If the internal remove range is set, filter out NotAvailableToWork entries
if REMOVE_LEAVE_FROM and REMOVE_LEAVE_TO:
# Coerce to date objects if strings provided
def _to_date(v):
if isinstance(v, str):
for fmt in ("%Y-%m-%d", "%d/%m/%Y", "%d/%m/%y"):
try:
return datetime.datetime.strptime(v, fmt).date()
except Exception:
continue
raise ValueError(f"Cannot parse date: {v}")
if isinstance(v, datetime.datetime):
return v.date()
return v
_from = _to_date(REMOVE_LEAVE_FROM)
_to = _to_date(REMOVE_LEAVE_TO)
for name, w in list(workers.items()):
original = w.get("leave", [])
before_count = len(original)
filtered = [lr for lr in original if not (_from <= lr.date <= _to)]
after_count = len(filtered)
if after_count != before_count:
print(
f"Removed {before_count-after_count} leave entries for '{name}' between {_from} and {_to}"
)
w["leave"] = filtered
n = 0 n = 0
for worker in workers: for worker in workers:
worker_name = worker worker_name = worker