def changeSchedule(self, start, duration, sesshun, reason, desc): """ Change the schedule, and take care of all the time accounting. This is meant for use in such cases as examplified in Memo 11.2. Right now, this only handles substituting one session for one or more sessions, where the time taken is accounted to one of these Reasons: time to other session due to weather time to other session due to rfi time to other session due to other reason and the time given to the new session is marked as short notice. Note that the times are not *assigned*, but instead times and descs. are incremented, so as not to overwrite previous changes. """ # get rid of this once develompent has stablized. debug = False if debug: print "changeSchedule: " print start, duration, sesshun # tag the description nowStr = datetime.now().strftime("%Y-%m-%d %H:%M") descHead = " [Insert Period (%s) " % nowStr # dictionary of who gave and who got, where: # descDct[gave/got] = [(desc. of original period, time, period id)] descDct = dict(gave_time = [], got_time = []) # what periods are we affecting? duration_mins = duration * 60.0 ps = Period.get_periods(start, duration_mins) if debug: print "len(ps): ", len(ps) for p in ps: print p scheduledPeriods = [p for p in ps if p.state.abbreviation == 'S'] if len(scheduledPeriods) != len(ps): msg = "All affected Periods must be in the Scheduled State" return (False, msg) # first, adjust each of the affected periods - including time accnting end = start + timedelta(hours = duration) for p in ps: need_scoring = False if debug: print "changing period: ", p print "comparing period: ", p.start, p.end() print "w/: ", start, end if p.start >= start and p.end() <= end: if debug: print "delete period!" # this entire period is being replaced descDct["gave_time"].append((p.__str__(), p.duration, p.id)) other_sess_time = p.duration p.delete() # the Deleted State! elif p.start >= start and p.end() > end: if debug: print "start period later" # we're chopping off the beginning of this period new_duration = TimeAgent.timedelta2frachours(p.end() - end) other_sess_time = p.duration - new_duration descDct["gave_time"].append((p.__str__(),other_sess_time, p.id)) p.duration = new_duration p.start = end need_scoring = True elif p.start < start and p.end() > end: if debug: print "bi-secting period" # we're chopping out the middle of a period: we fix this # by adjusting the period, then creating a new one descDct["gave_time"].append((p.__str__(), duration, p.id)) original_duration = p.duration original_end = p.end() p.duration = TimeAgent.timedelta2frachours(start - p.start) # the new one new_dur = TimeAgent.timedelta2frachours(original_end - end) accounting = Period_Accounting(scheduled = new_dur , short_notice = new_dur , description = "" #description ) accounting.save() pending = Period_State.objects.get(abbreviation = 'P') period_2cd_half = Period.create(session = p.session , start = end , duration = new_dur , state = pending , score = 0.0 , forecast = end , accounting = accounting ) init_rcvrs_from_session(period_2cd_half.session, period_2cd_half) self.reinitScore(period_2cd_half) period_2cd_half.save() # the original period is really giving up time to the # bi-secting new period, and the new second half! other_sess_time = duration + new_dur need_scoring = True elif p.start < start and p.end() > start: if debug: print "shorten period" # we're chopping off the end of this period new_duration = TimeAgent.timedelta2frachours(start - p.start) other_sess_time = p.duration - new_duration descDct["gave_time"].append((p.__str__(),other_sess_time, p.id)) p.duration = new_duration need_scoring = True else: raise "not covered" # now change this periods time accounting if p is not None: if debug: print "changes: ", p # increment values: don't overwrite them! value = p.accounting.get_time(reason) p.accounting.set_changed_time(reason, value + other_sess_time) p.accounting.save() if need_scoring: self.reinitScore(p) p.save() # finally, anything to replace it with? if sesshun is not None: # create a period for this pa = Period_Accounting(scheduled = duration , short_notice = duration , description = "") #description) pa.save() scheduled = Period_State.objects.get(abbreviation = 'S') p = Period.create(session = sesshun , start = start , duration = duration , score = 0.0 , state = scheduled , forecast = start , accounting = pa) init_rcvrs_from_session(p.session, p) self.reinitScore(p) p.save() descDct["got_time"].append((p.__str__(),p.duration, p.id)) # in all cases, give the description of entire event: self.assignDescriptions(descDct, descHead, desc) return (True, None)