Allow spliting forced blocks on nwdsAllow spliting forced blocks on nwds
This commit is contained in:
@@ -49,6 +49,7 @@ class SingleShift(object):
|
||||
rota_on_nwds=False,
|
||||
assign_as_block=False,
|
||||
force_as_block=False,
|
||||
force_as_block_unless_nwd=False,
|
||||
hard_constrain_shift=True,
|
||||
bank_holidays_only=False,
|
||||
constraints=[],
|
||||
@@ -71,6 +72,7 @@ class SingleShift(object):
|
||||
self.rota_on_nwds = rota_on_nwds
|
||||
self.assign_as_block = assign_as_block
|
||||
self.force_as_block = force_as_block
|
||||
self.force_as_block_unless_nwd = force_as_block_unless_nwd
|
||||
self.constraints = constraints
|
||||
|
||||
self.bank_holidays_only = bank_holidays_only
|
||||
@@ -205,13 +207,13 @@ class RotaBuilder(object):
|
||||
initialize=0,
|
||||
)
|
||||
|
||||
self.model.worker_block_shift_counts = Var(
|
||||
((worker.id, week, shift) for week in self.weeks
|
||||
for shift in self.shifts_to_assign_or_force_as_blocks()
|
||||
for worker in self.workers),
|
||||
within=NonNegativeIntegers,
|
||||
initialize=0,
|
||||
)
|
||||
#self.model.worker_block_shift_counts = Var(
|
||||
# ((worker.id, week, shift) for week in self.weeks
|
||||
# for shift in self.shifts_to_assign_or_force_as_blocks()
|
||||
# for worker in self.workers),
|
||||
# within=NonNegativeIntegers,
|
||||
# initialize=0,
|
||||
#)
|
||||
|
||||
self.model.blocks_worker_shift_assigned = Var(
|
||||
((worker.id, week, shift) for worker in self.workers
|
||||
@@ -592,7 +594,7 @@ class RotaBuilder(object):
|
||||
for week in self.weeks:
|
||||
for shift_name in self.shifts_to_assign_or_force_as_blocks():
|
||||
shift = self.get_shift_by_name(shift_name)
|
||||
for worker in self.workers:
|
||||
for worker in self.get_workers_for_shift(shift):
|
||||
self.model.constraints.add(
|
||||
8 * self.model.blocks_worker_shift_assigned[
|
||||
worker.id, week, shift_name] >= sum(
|
||||
@@ -607,17 +609,62 @@ class RotaBuilder(object):
|
||||
for worker in self.workers))
|
||||
|
||||
if shift.force_as_block:
|
||||
self.model.constraints.add(
|
||||
self.model.worker_block_shift_counts[worker.id, week,
|
||||
shift.name] ==
|
||||
sum(self.model.works[worker.id, week, day, shift.name]
|
||||
for day in self.days))
|
||||
#self.model.constraints.add(
|
||||
# self.model.worker_block_shift_counts[worker.id, week,
|
||||
# shift.name] ==
|
||||
# sum(self.model.works[worker.id, week, day, shift.name]
|
||||
# for day in self.days))
|
||||
|
||||
if shift.force_as_block_unless_nwd:
|
||||
workers = self.get_workers_for_shift(shift)
|
||||
# Get workers who have a nwd on the shift
|
||||
nwd_workers = []
|
||||
full_workers = []
|
||||
|
||||
for w in workers:
|
||||
if w.nwd is not None:
|
||||
l = []
|
||||
# This should take into account dates!
|
||||
for nwd, d1, d2 in w.nwd:
|
||||
if nwd in shift.shift_days:
|
||||
l.append(w)
|
||||
|
||||
self.model.constraints.add(
|
||||
sum(self.model.blocks_worker_shift_assigned[worker.id,
|
||||
week,
|
||||
shift.name]
|
||||
for worker in self.workers) <= 1)
|
||||
if l:
|
||||
nwd_workers.append(w)
|
||||
else:
|
||||
full_workers.append(w)
|
||||
|
||||
else:
|
||||
full_workers.append(w)
|
||||
print(shift.name, [n.name for n in nwd_workers])
|
||||
|
||||
if not nwd_workers: # Just do the usual
|
||||
self.model.constraints.add(
|
||||
sum(self.model.blocks_worker_shift_assigned[worker.id,
|
||||
week,
|
||||
shift.name]
|
||||
for worker in self.workers) <= 1)
|
||||
|
||||
else:
|
||||
print(shift.name)
|
||||
self.model.constraints.add(
|
||||
sum(self.model.blocks_worker_shift_assigned[worker.id,
|
||||
week,
|
||||
shift.name]
|
||||
for worker in full_workers) <= 1)
|
||||
|
||||
self.model.constraints.add(
|
||||
sum(self.model.blocks_worker_shift_assigned[worker.id,
|
||||
week,
|
||||
shift.name]
|
||||
for worker in workers) <= 2)
|
||||
|
||||
else:
|
||||
self.model.constraints.add(
|
||||
sum(self.model.blocks_worker_shift_assigned[worker.id,
|
||||
week,
|
||||
shift.name]
|
||||
for worker in self.workers) <= 1)
|
||||
|
||||
# Most of our constraints apply per worker
|
||||
for worker in self.workers:
|
||||
@@ -667,7 +714,7 @@ class RotaBuilder(object):
|
||||
worked, allocated = worker.previous_shifts[shift.name]
|
||||
target_shifts = target_shifts + float(allocated) - float(worked)
|
||||
|
||||
print(worker.name, shift.name, target_shifts)
|
||||
#print(worker.name, shift.name, target_shifts)
|
||||
worker.shift_target_number[shift.name] = target_shifts
|
||||
|
||||
if shift.hard_constrain_shift:
|
||||
@@ -848,7 +895,7 @@ class RotaBuilder(object):
|
||||
for week, day, shift in self.get_all_shiftclass_combinations():
|
||||
for n, start, end in worker.nwd:
|
||||
if not shift.rota_on_nwds and day == n:
|
||||
print(start, self.week_day_date_map[(week, day)], end)
|
||||
#print(start, self.week_day_date_map[(week, day)], end)
|
||||
if start <= self.week_day_date_map[(week, day)] <= end:
|
||||
self.model.constraints.add(
|
||||
0 == self.model.works[worker.id, week, day,
|
||||
@@ -1072,7 +1119,7 @@ class RotaBuilder(object):
|
||||
if worker_pairs[0] == worker:
|
||||
workers = worker_pairs
|
||||
|
||||
print("Workers", workers)
|
||||
#print("Workers", workers)
|
||||
|
||||
|
||||
self.model.constraints.add(
|
||||
@@ -1484,6 +1531,9 @@ class RotaBuilder(object):
|
||||
s = self.shifts_to_assign_as_blocks()
|
||||
s.extend(self.shifts_to_force_as_blocks())
|
||||
return s
|
||||
|
||||
def get_workers_for_shift(self, shift):
|
||||
return [worker for worker in self.workers if worker.site in shift.site]
|
||||
|
||||
def get_workers_total_fte(self):
|
||||
return self.full_time_equivalent
|
||||
|
||||
Reference in New Issue
Block a user