def shiftPeriodBoundaries(self , period , start_boundary , time , neighbor , reason , desc): """ Shifts the boundary between a given period and it's neighbors: * period_id - the period obj. whose boundary we first adjust * start_boundary - boolean, true for start, false for end * time - new time for that boundary * neighbor - period affected (can't be None) * reason - other_session_weather, *_rfi, or *_other * desc - the description to put into time accounting After periods are adjusted, time accounting is adjusted appropriately """ # if there isn't a neighbor, then this change should be done by hand if neighbor is None: return (False, "Cannot shift period boundary if there is a neighboring gap in the schedule.") if period.state.abbreviation != 'S' or \ neighbor.state.abbreviation != 'S': return (False, "Affected Periods should be in the Scheduled State") # get the time range affected original_time = period.start if start_boundary else period.end() diff_hrs = TimeAgent.dtDiffHrs(original_time, time) #self.get_time_diff_hours(original_time, time) # check for the no-op if original_time == time: return (False, "Time given did not change Periods duration") # create the tag used for all descriptions in time accounting nowStr = datetime.now().strftime("%Y-%m-%d %H:%M") descHead = " [Shift Period Bnd. (%s) " % nowStr # dictionary of who gave and who got, where: # descDct[gave/got] = [(desc. of original period, time, period id)] descDct = {} # figure out the stuff that depends on which boundary we're moving if start_boundary: if time >= period.end(): return (False, "Cannot start this period after it ends.") period_growing = True if time < original_time else False else: if time <= period.start: return (False, "Cannot shrink period past its start time.") period_growing = True if time > original_time else False if period_growing: # what to do with the period? # give time! # take notes for later descDct["got_time"] = [(period.__str__(), diff_hrs, period.id)] descDct["gave_time"] = [] period.accounting.short_notice += diff_hrs period.accounting.scheduled += diff_hrs period.duration += diff_hrs if start_boundary: period.start = time # what to do w/ the other periods # what are the other periods affected (can be many when growing) # (ignore original period causing affect) range_time = time if start_boundary else original_time affected_periods = [p for p in \ Period.get_periods(range_time, diff_hrs * 60.0) \ if p.id != period.id] for p in affected_periods: if p.start >= period.start and p.end() <= period.end(): # remove this period; descDct["gave_time"].append((p.__str__(), p.duration, p.id)) value = p.accounting.get_time(reason) p.accounting.set_changed_time(reason, value + p.duration) p.delete() # The Deleted state! else: # give part of this periods time to the affecting period other_time_point = p.end() if start_boundary else p.start other_time = TimeAgent.dtDiffHrs(other_time_point, time) descDct["gave_time"].append((p.__str__(), other_time, p.id)) value = p.accounting.get_time(reason) p.accounting.set_changed_time(reason, value + other_time) p.duration -= other_time if not start_boundary: p.start = time self.reinitScore(p) p.accounting.save() p.save() else: # period is shrinking # what to do w/ the period? # take time! # take notes for later descDct["gave_time"] = [(period.__str__(), diff_hrs, period.id)] value = period.accounting.get_time(reason) period.accounting.set_changed_time(reason, value + diff_hrs) period.duration -= diff_hrs if start_boundary: period.start = time # what to do w/ the other affected period (just one!)? # give it time! # take notes for later descDct["got_time"] = [(neighbor.__str__(), diff_hrs, neighbor.id)] neighbor.accounting.short_notice += diff_hrs neighbor.accounting.scheduled += diff_hrs neighbor.accounting.save() neighbor.duration += diff_hrs if not start_boundary: neighbor.start = time self.reinitScore(neighbor) neighbor.save() # in all cases: self.reinitScore(period) period.accounting.save() period.save() # in all cases, give the description of entire event: self.assignDescriptions(descDct, descHead, desc) return (True, None)