How do you implement 44 consecutive hours of rest in 7 days? In particular, there are multiple shifts with the same work hours and start time.
Shifts
Describe working hours and the start time as follows.
Set 0:00 for work hours and 0:00 for the work start time for Days Off shifts.
Python Source
import sc3
import datetime
def get_start_time_from_word(s):
start_time = datetime.datetime.strptime(s, '%H:%M')
return start_time
def get_start_time(tuple):
start_time = datetime.datetime.strptime(tuple[1], '%H:%M')
return start_time
def get_end_time(tuple):#(duration,work_start_time)
#print(tuple)
start_time = tuple[1]
end_time=start_time+datetime.timedelta(minutes=tuple[0])
return end_time
def get_intruded_offtime(Dic):
oneday_duration=datetime.timedelta(hours=24)
i=0
for tuple in Dic:
end_time=get_end_time(tuple)
if i==0:
most_intruded_time=end_time
else:
if end_time> most_intruded_time:
most_intruded_time=end_time
i+=1
work_end_duration=datetime.timedelta(days=most_intruded_time.day,hours=most_intruded_time.hour,minutes=most_intruded_time.minute)
#print(work_end_duration)
if work_end_duration>2*oneday_duration:
return (work_end_duration-2*oneday_duration)
else:
return 0
def get_rest_duration_after_work(tuple,intruded_offtime):
oneday_duration=datetime.timedelta(hours=24)
if tuple[0]==0:#Day Off
return oneday_duration-intruded_offtime#Assume previous day is most time consuming night shift
end_time=get_end_time(tuple)
work_end_duration=datetime.timedelta(days=end_time.day,hours=end_time.hour,minutes=end_time.minute)
if work_end_duration>2*oneday_duration:#Night Shift
return 2*oneday_duration-work_end_duration#works over night. return minus rest time
return 2*oneday_duration-work_end_duration#Regular Shift
def get_rest_duration_before_work(tuple):
oneday_duration=datetime.timedelta(hours=24)
if tuple[0]==0:#Day Off
return oneday_duration
ws=tuple[1]
work_duration=datetime.timedelta(days=ws.day,hours=ws.hour,minutes=ws.minute)
return work_duration-oneday_duration
def get_weekly_rest_pattern(Dic,rest_time):
rest_duration=datetime.timedelta(hours=rest_time)
oneday_duration=datetime.timedelta(hours=24)
intruded_offtime=get_intruded_offtime(Dic)
#print(intruded_offtime)
for i in Dic:#Get Days Off List
if i[0]==0:
days_off_list=Dic[i]
li=[]
for i in Dic:
#print("i",Dic[i])
res=get_rest_duration_after_work(i,intruded_offtime)#First Day
res+=oneday_duration#Second Day Off
full=True
l=[]
for m in Dic:
res1=get_rest_duration_before_work(m)
#print("m=",m,res1,"i=",i,res)
if (res1+res) >=rest_duration:
print(Dic[i],'→',days_off_list,'→',Dic[m],(res1+res).total_seconds()/3600,'hours')
l.append((Dic[i],days_off_list,Dic[m]))
else:
full=False
#print("False",Dic[i],Dic[m])
if full:
for a in l:
li.append((a[0],a[1],['*']))
#print((a[0],a[1],'*'))
break#enough
else:
for a in l:
li.append((a[0],a[1],a[2]))
return li
def check_pat3(list44,person,day,patterns):
#print(list44)
list=[]
S=set()
for tuple in list44:
and_list=[]
#rint("tuple",tuple)
if patterns<=2:
name_str=""
for i in range(patterns):
for name in tuple[i]:
name_str+=name
if name_str in S:
#print("name_str",name_str)
continue
S.add(name_str)
for i in range(patterns):
lx=[]
li=tuple[i]
break_true=False
for name in li:
if name=='*':
#print("*detected")
break_true=True
break
#print(i,day+i,name)
lx.append(sc3.GetShiftVar(person,day+i,name))
if break_true:
break
if len(lx)==1:
and_list.append(lx[0])
else:
and_list.append(sc3.Or(lx))
#print("andlist",len(and_list))
list.append(sc3.And(and_list))
return sc3.Or(list)
def check_44h_sub(list44,person):
for day in FromStartDateMinus6:#-6 -5 -3 -2 -1 0(StartDate)
if day >=FinishDate-3:# 6 5 4 3 2 1 0 | :patterns 3
break # 6 5 4 3 2 1 |0 :patterns 2
# 6 5 4 3 2 |1 0:patterns 1
list=[]
#print(daydef[day],end=' ')
for i in range(0,7,1):
#print(daydef[day+i],end=' ')
if i>=3 and i<=4 and day+i==FinishDate-1:
#print("FinishDate-1 ",person,daydef[day+i])
v=check_pat3(list44,person,day+i,2)
list.append(v)
elif i==4 and day+i==FinishDate:
#print("FinishDate ",person,daydef[day+i])
v=check_pat3(list44,person,day+i,1)
list.append(v)
elif day+i<=FinishDate-2:
v=check_pat3(list44,person,day+i,3)
list.append(v)
s='Consecutive Rest'+staffdef[person]+' '+daydef[day]
#sc3.AddSoft(sc3.Or(list),s,7)
if Use_weekly_rest44hours_as_hard_constraint:
sc3.AddHard(sc3.Or(list),s)
else:
sc3.AddSoft(sc3.Or(list),s,7)
def check_44h(list):
for person in A_Member_in_All:
check_44h_sub(list,person)
def get_shift_dic():
S={}
for s in shiftdef:
#print(s,shiftdef[s][2],shiftdef[s][3])
work_duration=int(shiftdef[s][2])
start_time=get_start_time_from_word(shiftdef[s][3])
if work_duration>=0 and shiftdef[s][3]!="":
st=(work_duration,start_time)
if st not in S:
l=[]
l.append(s)
S[st]=l
else:
S[st].append(s)
return S
S=get_shift_dic()
print("\n*** Weekly Consecutive Rest =",weekly_rest_hours," hours ***\n")
weekly_rest_pattern=get_weekly_rest_pattern(S,weekly_rest_hours)
print(weekly_rest_pattern)
#Use_weekly_rest=0
if Use_weekly_rest:
check_44h(weekly_rest_pattern)
print()
Macro
Describe macro as follows.
Reference
How do you implement 44 hours of rest consecutively within 7 days period?
Solution
Load the Example Project File
File → Open Project File from GitHub