DavidD003 commited on
Commit
f99e38a
1 Parent(s): 19cb7e6

Update SchedBuilderClasses2.py

Browse files
Files changed (1) hide show
  1. 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)