Spaces:
Sleeping
Sleeping
Update SchedBuilderClasses2.py
Browse files- SchedBuilderClasses2.py +35 -1
SchedBuilderClasses2.py
CHANGED
@@ -409,8 +409,21 @@ class Schedule():
|
|
409 |
self.assnLog.append('NO STAFF! No one to force to '+sl.key())
|
410 |
return None,'N' #No one to force
|
411 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
412 |
@debug
|
413 |
-
def fillOutSched_v3(self,noVol=None,iter=0,pre8={},last=None):
|
414 |
"""Improvement on v2 to prioritize voluntary 8 hour over voluntary 4hr, plus WWF crew assigning on long weekends"""
|
415 |
if iter>self.maxI: return last
|
416 |
#Setup
|
@@ -448,9 +461,15 @@ class Schedule():
|
|
448 |
if WIPschd.slots[k].assnType not in ['V','F']: #If k1 was already reached on prev iteration through k loop then don't perform assn function again
|
449 |
WIPschd.trackAssn(self.assns,loc='pre8 Success 1')
|
450 |
r=WIPschd.slots[k].assn(WIPschd,assnType="V",slAssignee=eId)
|
|
|
|
|
|
|
451 |
if WIPschd.slots[k2].assnType not in ['V','F']: #See above
|
452 |
WIPschd.trackAssn(self.assns,loc='pre8 Success 2')
|
453 |
r=WIPschd.slots[k2].assn(WIPschd,assnType="V",slAssignee=eId) #Assign both. When the second one gets iterated to, slOK will return False for being assigned on same slot arleady and itll be harmless
|
|
|
|
|
|
|
454 |
#If this ee was forced earlier and so they are no longer ok for the full8 assign, then the pre8 is effectively skipped and re evaluated in the '8hr assn' phase
|
455 |
else: #Case of assigning a slot not from pre8 list
|
456 |
s=WIPschd.slots[k]
|
@@ -458,6 +477,9 @@ class Schedule():
|
|
458 |
eId,tp=WIPschd.pickAssignee(s,tp='F')
|
459 |
WIPschd.trackAssn(self.assns,loc='force phase')
|
460 |
r=WIPschd.slots[k].assn(WIPschd,assnType=tp,slAssignee=eId) #return value to variable r is false if making that force assignments breaks rules around forcing past 48 hrs in week
|
|
|
|
|
|
|
461 |
if r==False and s.key() not in WIPschd.noVol: #also check if this slot is already in noVol list. Coming to this statement after the fact, I realize there isn't any sensical logic path happening here if the persons forcing broke a rule, but the slot is not in the list. I realize this is because I wrote this if statement at a point where I thought forcings might happen mid-iteration, but after making it so that forcings only happen start of iteration, I think this if statement will never be met. That's because at this point in the algorithm, no voluntary weekend OT has been assigned. but the point of the 'return value' was checking if already-assigned voluntary OT happends before or after the OT that is being forced. But since no voluntary OT has been assigned at all, the return constraint will always be ok. The pickAssignee() method will always return the guy who si to be assigned because if the perosn simply worked enough OT in the week that they can't be forced, then the pickAssignee wouldn't havepicked them anyways
|
462 |
WIPschd.noVol.append(s.key())
|
463 |
WIPschd.assnLog.append('The last assignment created a broken schedule where the person' +WIPschd.ee[eId].lastNm+' had a forcing (previously assigned) after 48h in the week (just assigned.) Adding this slot to priority sequence and reiterating')
|
@@ -513,6 +535,9 @@ class Schedule():
|
|
513 |
r1=WIPschd.slots[k1].assn(WIPschd,assnType="V",slAssignee=eId)
|
514 |
WIPschd.trackAssn(self.assns,loc='asn 8 on shift 2')
|
515 |
r2=WIPschd.slots[k2].assn(WIPschd,assnType="V",slAssignee=eId) #Don't need to check r1 or r2, they are redudnant with passing through frcOKdblAssn to get here
|
|
|
|
|
|
|
516 |
s=1
|
517 |
#------ Check if their assignments being made requires that another slot be forced due to losing eligVol
|
518 |
newK=set([k for k in WIPschd.slots if len(WIPschd.slots[k].eligVol)==0 and WIPschd.slots[k].assnType not in ['WWF','F','V','nV','DNS','N']]) #After assignment, see if anything now needing forcing that hasn't been seen before
|
@@ -551,8 +576,14 @@ class Schedule():
|
|
551 |
if WIPschd.ee[eId].frcOKdblAssn(WIPschd,WIPschd.slots[k1]): #If function returns true.. no forcing rules were broken
|
552 |
WIPschd.trackAssn(self.assns,loc='asn 8 straddle 1')
|
553 |
r1=WIPschd.slots[k1].assn(WIPschd,assnType="V",slAssignee=eId)
|
|
|
|
|
|
|
554 |
WIPschd.trackAssn(self.assns,loc='asn 8 straddle 2')
|
555 |
r2=WIPschd.slots[k2].assn(WIPschd,assnType="V",slAssignee=eId) #Don't need to check r1 or r2, they are redudnant with passing through frcOKdblAssn to get here
|
|
|
|
|
|
|
556 |
s=1
|
557 |
#------ Check if their assignments being made requires that another slot be forced due to losing eligVol
|
558 |
newK=set([k for k in WIPschd.slots if len(WIPschd.slots[k].eligVol)==0 and WIPschd.slots[k].assnType not in ['WWF','F','V','nV','DNS','N']]) #After assignment, see if anything now needing forcing that hasn't been seen before
|
@@ -618,6 +649,9 @@ class Schedule():
|
|
618 |
eId,tp=WIPschd.pickAssignee(curS)
|
619 |
WIPschd.trackAssn(self.assns,loc='4 hr assn')
|
620 |
r=WIPschd.slots[curS.key()].assn(WIPschd,assnType=tp,slAssignee=eId) #Note the assign method acts on original, not deepcopy, retrieved via key
|
|
|
|
|
|
|
621 |
newK=set([k for k in WIPschd.slots if len(WIPschd.slots[k].eligVol)==0 and WIPschd.slots[k].assnType not in ['WWF','F','V','nV','DNS','N']]) #After assignment, see if anything now needing forcing that hasn't been seen before
|
622 |
if len(newK-set(WIPschd.noVol))>0: #Case that a forced assignment made someone ineligible for a slot they were marked as the last volunteer in, creating a slot requiring forcing that hasn't been seen before, requiring re iteration
|
623 |
pullK=newK-set(WIPschd.noVol) #Get the keys for slots that are now without volunteers(could be more than one so use set subtraction)
|
|
|
409 |
self.assnLog.append('NO STAFF! No one to force to '+sl.key())
|
410 |
return None,'N' #No one to force
|
411 |
|
412 |
+
def checkForceStop(self,tup,iter,assn):
|
413 |
+
if tup!=None:
|
414 |
+
if iter==tup[0] and assn==tup[1]: return True
|
415 |
+
else: return False
|
416 |
+
else: return None
|
417 |
+
|
418 |
+
def handleAssnLog(self,WIPschd):
|
419 |
+
self.assnLog.extend(WIPschd.assnLog) #Add whats been logged this final iteration to master log
|
420 |
+
self.assnLog.extend(['final iteration: '+str(iter)])
|
421 |
+
WIPschd.assnLog=self.assnLog #Replace WIP with the master now that master had WIP tacked on to WWF assn since WIP sched object being passed as final outcome
|
422 |
+
return WIPschd
|
423 |
+
|
424 |
+
|
425 |
@debug
|
426 |
+
def fillOutSched_v3(self,noVol=None,iter=0,pre8={},last=None,stop=None):
|
427 |
"""Improvement on v2 to prioritize voluntary 8 hour over voluntary 4hr, plus WWF crew assigning on long weekends"""
|
428 |
if iter>self.maxI: return last
|
429 |
#Setup
|
|
|
461 |
if WIPschd.slots[k].assnType not in ['V','F']: #If k1 was already reached on prev iteration through k loop then don't perform assn function again
|
462 |
WIPschd.trackAssn(self.assns,loc='pre8 Success 1')
|
463 |
r=WIPschd.slots[k].assn(WIPschd,assnType="V",slAssignee=eId)
|
464 |
+
if self.checkForceStop(stop,iter,WIPschd.assignments)==True:
|
465 |
+
WIPschd=self.handleAssnLog(WIPschd)
|
466 |
+
return WIPschd
|
467 |
if WIPschd.slots[k2].assnType not in ['V','F']: #See above
|
468 |
WIPschd.trackAssn(self.assns,loc='pre8 Success 2')
|
469 |
r=WIPschd.slots[k2].assn(WIPschd,assnType="V",slAssignee=eId) #Assign both. When the second one gets iterated to, slOK will return False for being assigned on same slot arleady and itll be harmless
|
470 |
+
if self.checkForceStop(stop,iter,WIPschd.assignments)==True:
|
471 |
+
WIPschd=self.handleAssnLog(WIPschd)
|
472 |
+
return WIPschd
|
473 |
#If this ee was forced earlier and so they are no longer ok for the full8 assign, then the pre8 is effectively skipped and re evaluated in the '8hr assn' phase
|
474 |
else: #Case of assigning a slot not from pre8 list
|
475 |
s=WIPschd.slots[k]
|
|
|
477 |
eId,tp=WIPschd.pickAssignee(s,tp='F')
|
478 |
WIPschd.trackAssn(self.assns,loc='force phase')
|
479 |
r=WIPschd.slots[k].assn(WIPschd,assnType=tp,slAssignee=eId) #return value to variable r is false if making that force assignments breaks rules around forcing past 48 hrs in week
|
480 |
+
if self.checkForceStop(stop,iter,WIPschd.assignments)==True:
|
481 |
+
WIPschd=self.handleAssnLog(WIPschd)
|
482 |
+
return WIPschd
|
483 |
if r==False and s.key() not in WIPschd.noVol: #also check if this slot is already in noVol list. Coming to this statement after the fact, I realize there isn't any sensical logic path happening here if the persons forcing broke a rule, but the slot is not in the list. I realize this is because I wrote this if statement at a point where I thought forcings might happen mid-iteration, but after making it so that forcings only happen start of iteration, I think this if statement will never be met. That's because at this point in the algorithm, no voluntary weekend OT has been assigned. but the point of the 'return value' was checking if already-assigned voluntary OT happends before or after the OT that is being forced. But since no voluntary OT has been assigned at all, the return constraint will always be ok. The pickAssignee() method will always return the guy who si to be assigned because if the perosn simply worked enough OT in the week that they can't be forced, then the pickAssignee wouldn't havepicked them anyways
|
484 |
WIPschd.noVol.append(s.key())
|
485 |
WIPschd.assnLog.append('The last assignment created a broken schedule where the person' +WIPschd.ee[eId].lastNm+' had a forcing (previously assigned) after 48h in the week (just assigned.) Adding this slot to priority sequence and reiterating')
|
|
|
535 |
r1=WIPschd.slots[k1].assn(WIPschd,assnType="V",slAssignee=eId)
|
536 |
WIPschd.trackAssn(self.assns,loc='asn 8 on shift 2')
|
537 |
r2=WIPschd.slots[k2].assn(WIPschd,assnType="V",slAssignee=eId) #Don't need to check r1 or r2, they are redudnant with passing through frcOKdblAssn to get here
|
538 |
+
if self.checkForceStop(stop,iter,WIPschd.assignments)==True:
|
539 |
+
WIPschd=self.handleAssnLog(WIPschd)
|
540 |
+
return WIPschd
|
541 |
s=1
|
542 |
#------ Check if their assignments being made requires that another slot be forced due to losing eligVol
|
543 |
newK=set([k for k in WIPschd.slots if len(WIPschd.slots[k].eligVol)==0 and WIPschd.slots[k].assnType not in ['WWF','F','V','nV','DNS','N']]) #After assignment, see if anything now needing forcing that hasn't been seen before
|
|
|
576 |
if WIPschd.ee[eId].frcOKdblAssn(WIPschd,WIPschd.slots[k1]): #If function returns true.. no forcing rules were broken
|
577 |
WIPschd.trackAssn(self.assns,loc='asn 8 straddle 1')
|
578 |
r1=WIPschd.slots[k1].assn(WIPschd,assnType="V",slAssignee=eId)
|
579 |
+
if self.checkForceStop(stop,iter,WIPschd.assignments)==True:
|
580 |
+
WIPschd=self.handleAssnLog(WIPschd)
|
581 |
+
return WIPschd
|
582 |
WIPschd.trackAssn(self.assns,loc='asn 8 straddle 2')
|
583 |
r2=WIPschd.slots[k2].assn(WIPschd,assnType="V",slAssignee=eId) #Don't need to check r1 or r2, they are redudnant with passing through frcOKdblAssn to get here
|
584 |
+
if self.checkForceStop(stop,iter,WIPschd.assignments)==True:
|
585 |
+
WIPschd=self.handleAssnLog(WIPschd)
|
586 |
+
return WIPschd
|
587 |
s=1
|
588 |
#------ Check if their assignments being made requires that another slot be forced due to losing eligVol
|
589 |
newK=set([k for k in WIPschd.slots if len(WIPschd.slots[k].eligVol)==0 and WIPschd.slots[k].assnType not in ['WWF','F','V','nV','DNS','N']]) #After assignment, see if anything now needing forcing that hasn't been seen before
|
|
|
649 |
eId,tp=WIPschd.pickAssignee(curS)
|
650 |
WIPschd.trackAssn(self.assns,loc='4 hr assn')
|
651 |
r=WIPschd.slots[curS.key()].assn(WIPschd,assnType=tp,slAssignee=eId) #Note the assign method acts on original, not deepcopy, retrieved via key
|
652 |
+
if self.checkForceStop(stop,iter,WIPschd.assignments)==True:
|
653 |
+
WIPschd=self.handleAssnLog(WIPschd)
|
654 |
+
return WIPschd
|
655 |
newK=set([k for k in WIPschd.slots if len(WIPschd.slots[k].eligVol)==0 and WIPschd.slots[k].assnType not in ['WWF','F','V','nV','DNS','N']]) #After assignment, see if anything now needing forcing that hasn't been seen before
|
656 |
if len(newK-set(WIPschd.noVol))>0: #Case that a forced assignment made someone ineligible for a slot they were marked as the last volunteer in, creating a slot requiring forcing that hasn't been seen before, requiring re iteration
|
657 |
pullK=newK-set(WIPschd.noVol) #Get the keys for slots that are now without volunteers(could be more than one so use set subtraction)
|