def scheduleTask(self, task: Task, start: arrow.Arrow, minutes=None, debug=False): # TODO: Consider minBlock if minutes is None: minutesToSchedule = task.maxRemainingTime else: minutesToSchedule = minutes if debug: print(f"Schedule is scheduling {minutesToSchedule}min for task {task}") scheduledMinutes = 0 startTime = util.arrowToTime(start) for day in self.__days: if debug: print("\n") print(day, end=" -> ") if task.maxRemainingTime == 0 or minutesToSchedule == scheduledMinutes: if debug: print("A", end="") return # Skip days prior to the startDate if day.date < start.date(): if debug: print("B", end="") continue # For the start day, consider only the times that lie after the start time if day.date == start.date(): if debug: print("C", end="") freeTimeSlots = day.freeTimeSlots(after=startTime) # Days in the future if day.date > start.date(): if debug: print("D", end="") freeTimeSlots = day.freeTimeSlots() if len(freeTimeSlots) == 0: if debug: print("E", end="") continue # For the valid TimeSlots of the future, fill them with the task until they are either all filled or "minutesToSchedule" minutes are scheduled for ts in freeTimeSlots: if debug: print("F", end="") if task.maxRemainingTime == 0 or minutesToSchedule == scheduledMinutes: if debug: print("G", end="") return # If TimeSlot is <= to what still needs to be scheduled, fill it completely if ts.durationInMinutes <= (minutesToSchedule - scheduledMinutes): if debug: print("H", end="") # Schedule the Task day.scheduleTask(ts, task, debug=debug) # Update the counters task.addCompletionTime(ts.durationInMinutes) # This mutates the ORIGINAL TASK scheduledMinutes += ts.durationInMinutes else: # If TimeSlot is bigger than what needs to be scheduled, fill the first section of it (until "minutesToSchedule" minutes are scheduled) if debug: print("I", end="") # Build the Partial TimeSlot remainingMinutesToSchedule = minutesToSchedule - scheduledMinutes length = Time.fromMinutes(remainingMinutesToSchedule) partialTimeSlot = TimeSlot(ts.startTime, ts.startTime + length) # Schedule the Task day.scheduleTask(partialTimeSlot, task, debug=debug) # Update the counters task.addCompletionTime(partialTimeSlot.durationInMinutes) # This mutates the ORIGINAL TASK scheduledMinutes += partialTimeSlot.durationInMinutes # Unnecessary. ScheduledMinutes will == MinutesToSchedule after this every time. return # Since the TimeSlot was bigger than the remaining minutesToSchedule, we are done here now. raise ImpossibleScheduleException("Unable to schedule task!")