This commit is contained in:
Ross
2025-12-16 21:34:11 +00:00
parent 0b732a0b09
commit 8e580440e0
2 changed files with 22 additions and 29 deletions
+21 -29
View File
@@ -3,7 +3,7 @@ import datetime
import os
import sys
import time
from rota_generator.shifts import MaxShiftsPerWeekConstraint, NoWorkers, PostShiftConstraint, PreShiftConstraint, RotaBuilder, SingleShift, WorkerRequirement, days
from rota_generator.shifts import MaxShiftsPerWeekConstraint, NoWorkers, PostShiftConstraint, PreShiftConstraint, RotaBuilder, SingleShift, WorkerRequirement, days, RotaConstraintOptions
import typer
import subprocess
import pandas as pd
@@ -38,11 +38,11 @@ def extract_leave_and_rota_from_calender(calender_df):
# Get rota data from the second row (index 1), starting from column 5 (index 4)
# Extract the rota data for each worker from the first data row (index 0), columns 5 onwards
rota_row = calender_df.iloc[0]
#rota_row = calender_df.iloc[0]
#rota_data = {}
for i, worker in enumerate(worker_names):
assignment = str(rota_row.iloc[5 + i]).strip() if len(rota_row) > 5 + i else ""
#rota_data[worker] = f"rota {assignment.lower()}"
#for i, worker in enumerate(worker_names):
# assignment = str(rota_row.iloc[5 + i]).strip() if len(rota_row) > 5 + i else ""
# #rota_data[worker] = f"rota {assignment.lower()}"
leave_requests = []
work_requests = []
@@ -55,6 +55,9 @@ def extract_leave_and_rota_from_calender(calender_df):
date = datetime.datetime.strptime(date_str, "%Y-%m-%d").date()
except Exception:
continue # skip rows with invalid date
if date < datetime.date(2026, 2, 16):
continue # skip rows before rota start date
for i, worker in enumerate(worker_names):
if not worker or worker.lower() == "nan":
continue
@@ -91,6 +94,7 @@ def extract_shift_assignments_from_rota(rota_df):
shifts = ["twilight", "oncall"]
assignments = []
skipped_rows = 0
for idx, row in rota_df.iloc[2:].iterrows():
week_start_str = str(row.iloc[0]).strip().split(" ")[0] # Get the week start date from the first column (index 0)
try:
@@ -99,6 +103,10 @@ def extract_shift_assignments_from_rota(rota_df):
print(f"Invalid date format in row {idx}: {week_start_str}")
continue # skip rows with invalid date
if week_start < datetime.date(2026, 2, 16):
skipped_rows += 1
continue # skip rows before rota start date
for i, day in enumerate(days):
for j, shift in enumerate(shifts):
if i < 5:
@@ -122,7 +130,7 @@ def extract_shift_assignments_from_rota(rota_df):
shift = "weekend"
assignments.append({
"week_start": week_start,
"week": idx-1, # 1-indexed week number
"week": idx-1-skipped_rows, # 1-indexed week number
"day": day,
"date": week_start + datetime.timedelta(days=i),
"shift": shift,
@@ -147,7 +155,7 @@ def load_workers():
# Extract sheets
days_df = xls["Days"]
calender_df = xls["Calender"]
calender_df = xls["Calendar"]
rota_df = xls["Rota"]
@@ -193,7 +201,7 @@ def load_workers():
for i, day in enumerate(weekday_cols):
val = row.iloc[3 + i]
# You can adjust the logic below depending on your marking scheme (e.g. "Y", "Yes", "1", etc.)
available = not ("no" in str(val).strip().lower())
available = not ("no" in str(val).strip().lower() or str(val).strip().lower() == "yes*")
availability[day] = available
workers_days.append({"initial": initial, "name": name, "availability": availability, "requests": requests})
@@ -329,14 +337,12 @@ def main(
balance_offset_modifier=bom,
name="cons rota feb 2026",
allow_force_assignment_with_leave_conflict=True,
constraint_options=RotaConstraintOptions(
balance_weekends=True,
max_shifts_per_week=6,
max_days_per_week_block=[(4, 2), (6, 3)],
),
)
# Rota = RotaBuilder(start_date, weeks_to_rota=20, balance_offset_modifier=1)
Rota.constraint_options["balance_weekends"] = True
#Rota.constraint_options["max_weekend_frequency"] = 2
Rota.constraint_options["max_shifts_per_week"] = 6
Rota.constraint_options["max_days_worked_per_week"] = 3
# Rota.constraint_options["avoid_st2_first_month"] = True
Rota.constraint_options["max_days_per_week_block"] = [(4, 2), (6, 3)] # (max_days, week_block)
#Rota.enable_unavailabilities = False
@@ -351,10 +357,6 @@ def main(
constraints=[
PreShiftConstraint(days=2, start_date="2025-11-17", exclude_days=("Fri", "Sat", "Sun")),
PostShiftConstraint(days=1, start_date="2025-11-17", exclude_days=("Fri", "Sat", "Sun"), allow_self=True),
#{
# "name": "max_shifts_per_week",
# "options": 3,
#}
],
),
SingleShift(
@@ -365,9 +367,6 @@ def main(
days=days[5:],
balance_offset=1,
constraints=[
#{"name": "pre", "options": 2},
#{"name": "post", "options": 1},
PostShiftConstraint(days=1, start_date="2025-11-17", ignore_shifts=["oncall"]),
],
display_char="a",
@@ -380,10 +379,6 @@ def main(
length=12.5,
days=days[5:],
balance_offset=2,
#constraint=[
# {"name": "pre", "options": 1},
# {"name": "post", "options": 1},
#],
display_char="b",
),
SingleShift(
@@ -398,11 +393,8 @@ def main(
days=days[:5],
balance_offset=1,
constraints=[
#PreShiftConstraint(days=1, start_date="2025-11-17", ignore_shifts=["oncall"]),
PreShiftConstraint(days=1, start_date="2025-11-17", ignore_shifts=["oncall"], exclude_days=("Sat", "Sun")),
#PostShiftConstraint(days=1, start_date="2025-11-17", ignore_shifts=["oncall", "weekend a", "weekend b"], include_weekends=False),
MaxShiftsPerWeekConstraint(max_shifts=1),
#{"name": "post", "options": 1},
],
),
)
+1
View File
@@ -383,6 +383,7 @@ class RotaBuilder(object):
SHIFT_BOUNDS=SHIFT_BOUNDS,
name: str = "",
bank_holidays: dict[datetime.date, str] = bank_holiday_map,
constraint_options: RotaConstraintOptions | dict | None = None,
):
self.name = name