fix min summed shifts

This commit is contained in:
Ross
2025-06-30 09:23:33 +01:00
parent 48d6b748d1
commit adccf8211c
2 changed files with 40 additions and 67 deletions
+8 -58
View File
@@ -38,8 +38,8 @@ def main(
time_to_run: int = 60 * 60,
ratio: float = 0.001,
start_date: datetime.datetime = "2025-09-01",
weeks: int = 26,
bom: int = 1,
weeks: int = 16,
bom: int = 2,
):
rota_start_date = start_date.date()
suspend_on_finish = suspend
@@ -267,70 +267,20 @@ def main(
"name": "require_remote_site_presence_week",
"options": ("plymouth", 1),
},
{"name": "limit_grade_number", "options": {2: 1}},
{"name": "limit_grade_number", "options": {2: 2}},
{"name": "minimum_grade_number", "options": (4, 1)},
],
#end_date=datetime.datetime.strptime("2025-06-01", "%Y-%m-%d").date(),
),
# SingleShift(
# sites=sites,
# name="night_weekday4",
# length=12.25,
# days=days[:4],
# balance_offset=3.9,
# balance_weighting=1,
# # hard_constrain_shift=False,
# workers_required=NIGHT_REGISTRAR_NUMBER,
# force_as_block=True,
# rota_on_nwds=True,
# constraint=[
# {"name": "night"},
# {"name": "pre", "options": 2},
# {"name": "post", "options": 2},
# {
# "name": "require_remote_site_presence_week",
# "options": ("plymouth", 1),
# },
# {"name": "limit_grade_number", "options": {2: 1}},
# {"name": "minimum_grade_number", "options": (4, 1)},
# ],
# start_date=datetime.datetime.strptime("2025-06-02", "%Y-%m-%d").date(),
# ),
# SingleShift(
# sites=[
# *sites,
# "plymouth twilights, weekends and weekend nights",
# "truro twilights and weekend nights",
# "weekend nights",
# "truro twilights, weekends and weekend nights",
# ],
# name="night_weekend4",
# length=12.25,
# days=days[4:],
# balance_offset=2.9,
# balance_weighting=1,
# # hard_constrain_shift=False,
# workers_required=NIGHT_REGISTRAR_NUMBER,
# force_as_block=True,
# rota_on_nwds=True,
# constraint=[
# {"name": "night"},
# {"name": "pre", "options": 2},
# {"name": "post", "options": 3},
# {
# "name": "require_remote_site_presence_week",
# "options": ("plymouth", 1),
# },
# {"name": "limit_grade_number", "options": {2: 1}},
# {"name": "minimum_grade_number", "options": (4, 1)},
# ],
# start_date=datetime.datetime.strptime("2025-06-02", "%Y-%m-%d").date(),
# ),
)
# Rota.add_grade_constraint_by_week([2], [1, 2], ["night_weekday", "night_weekend"])
# Prevent shifts for ST2s for 2 weeks
Rota.add_grade_constraint_by_week([2], [1, 2], [shift.name for shift in Rota.shifts])
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.terminate_on_warning.remove("Worker/no valid shifts")
load_leave = True
Rota.build_shifts()
+32 -9
View File
@@ -1029,13 +1029,15 @@ class RotaBuilder(object):
for day in days_list:
# Only consider if all shifts are present that day
if all(shift in self.get_shift_names_by_week_day(week, day) for shift in constraint.shifts):
self.model.constraints.add(
sum(
worker.grade * self.model.works[worker.id, week, day, shift]
for shift in constraint.shifts
for worker in self.get_workers_for_shift(self.get_shift_by_name(shift))
) >= constraint.min_grade_sum
)
expr_terms = [
worker.grade * self.model.works[worker.id, week, day, shift]
for shift in constraint.shifts
for worker in self.get_workers_for_shift(self.get_shift_by_name(shift))
]
if expr_terms: # Only add constraint if there are eligible workers
self.model.constraints.add(
sum(expr_terms) >= constraint.min_grade_sum
)
@@ -1783,6 +1785,15 @@ class RotaBuilder(object):
- adjusted_balance_offset * self.balance_offset_modifier
)
# --- Store for export ---
if not hasattr(worker, "hard_constrain_shift_limits"):
worker.hard_constrain_shift_limits = {}
worker.hard_constrain_shift_limits[shift.name] = {
"min_shifts": min_shifts,
"max_shifts": max_shifts,
"target_shifts": target_shifts,
}
self.model.constraints.add(
inequality(
min_shifts,
@@ -1791,8 +1802,6 @@ class RotaBuilder(object):
for week, day in self.get_week_day_combinations_for_shift(
shift
)
# for week, day in self.get_week_day_combinations()
# if shift.name in self.get_shift_names_by_week_day(week, day)
),
max_shifts,
)
@@ -4190,6 +4199,15 @@ class RotaBuilder(object):
joined_timetable = "\n".join(timetable)
hard_constrain_shift_info = []
for worker in self.workers:
for shift_name, limits in getattr(worker, "hard_constrain_shift_limits", {}).items():
hard_constrain_shift_info.append({
"worker": worker.name,
"shift": shift_name,
**limits,
})
html = f"""
<body>
<div class="table-div" id="{table_name}">
@@ -4246,6 +4264,11 @@ class RotaBuilder(object):
<br/>
<div>
</details>
<details><summary><h2>Hard Constrain Shift Min/Max</h2></summary>
<pre>
{json.dumps(hard_constrain_shift_info, indent=4)}
"</pre></details>
</div
</body>
"""