diff --git a/SAS/TMSS/backend/services/scheduling/lib/constraints/__init__.py b/SAS/TMSS/backend/services/scheduling/lib/constraints/__init__.py index 08871e5a5b13a966770f354038ed2f642666dd5d..0794eb96490838142478a90a23643e5cdeb595a7 100644 --- a/SAS/TMSS/backend/services/scheduling/lib/constraints/__init__.py +++ b/SAS/TMSS/backend/services/scheduling/lib/constraints/__init__.py @@ -71,7 +71,7 @@ def filter_scheduling_units_using_constraints(scheduling_units: [models.Scheduli logger.warning("cannot dynamically schedule scheduling_unit id=%s name='%s' because it has not constraints template", scheduling_unit.id, scheduling_unit.name) continue - if can_run_within_timewindow(scheduling_unit, lower_bound, upper_bound) and can_run_within_reserved_stations(scheduling_unit): + if can_run_within_timewindow(scheduling_unit, lower_bound, upper_bound) and can_run_within_station_reservations(scheduling_unit): runnable_scheduling_units.append(scheduling_unit) # if a schedulingunit cannot run after this window, then apparently its limited to run exclusively in this time window. @@ -238,7 +238,22 @@ def get_min_earliest_possible_start_time(scheduling_units: [models.SchedulingUni return lower_bound -def can_run_within_reserved_stations(scheduling_unit: models.SchedulingUnitBlueprint) -> bool: +def get_active_station_reservations_in_timewindow(lower_bound, upper_bound): + """ + Retrieve a list of all active stations reservations, which are reserved between a timewindow + """ + lst_active_station_reservations = [] + reservations = models.Reservation.objects.all() + for station_reservation in reservations: + if (station_reservation.duration is not None and \ + station_reservation.start_time < upper_bound and station_reservation.stop_time > lower_bound) \ + or (station_reservation.duration is None and station_reservation.start_time < upper_bound): + lst_active_station_reservations += station_reservation.specifications_doc["resources"]["stations"] + + return lst_active_station_reservations + + +def can_run_within_station_reservations(scheduling_unit: models.SchedulingUnitBlueprint) -> bool: """ Check if the given scheduling_unit can run if the reserved station are taken into account. The station requirement will be evaluated. If a reserved station will be used within the time window of @@ -250,23 +265,13 @@ def can_run_within_reserved_stations(scheduling_unit: models.SchedulingUnitBluep sub_start_time = scheduling_unit.start_time sub_stop_time = scheduling_unit.stop_time - reservations = models.Reservation.objects.all() - for station_reservation in reservations: - # Check for every reservation if reserved stations are going to be used - lst_reserved_stations = station_reservation.specifications_doc["resources"]["stations"] - common_set_stations = set(lst_stations_to_be_used).intersection(lst_reserved_stations) - if len(common_set_stations) > 0: - # there is a station reserved which is also used in the scheduling_unit, so lets check the time window - if station_reservation.duration is not None and \ - station_reservation.start_time < sub_stop_time and station_reservation.stop_time > sub_start_time: - can_run = False - logger.warning("There is/are station(s) reserved (%s) with a timewindow [%s - %s] which overlap with [%s - %s]", - common_set_stations, station_reservation.start_time, station_reservation.stop_time, sub_start_time, sub_stop_time) - break # we are done - if station_reservation.duration is None and station_reservation.start_time < sub_stop_time: - logger.warning("There is/are station(s) reserved (%s) with a timewindow [%s - forever] which overlap with [%s - %s]", - common_set_stations, station_reservation.start_time, sub_start_time, sub_stop_time) - can_run = False - break # we are done + + lst_reserved_stations = get_active_station_reservations_in_timewindow(sub_start_time, sub_stop_time) + # Check if the reserved stations are going to be used + common_set_stations = set(lst_stations_to_be_used).intersection(lst_reserved_stations) + if len(common_set_stations) > 0: + can_run = False + logger.warning("There is/are station(s) reserved (%s) which overlap with timewindow [%s - %s]", + common_set_stations, sub_start_time, sub_stop_time) return can_run diff --git a/SAS/TMSS/backend/services/scheduling/test/t_dynamic_scheduling.py b/SAS/TMSS/backend/services/scheduling/test/t_dynamic_scheduling.py index 635dc9d5944fab77c69c18f25f9bd9b5f8cbed64..2c02b11ad8549499922c8392d7400a345d437c47 100755 --- a/SAS/TMSS/backend/services/scheduling/test/t_dynamic_scheduling.py +++ b/SAS/TMSS/backend/services/scheduling/test/t_dynamic_scheduling.py @@ -883,28 +883,28 @@ class TestReservedStations(unittest.TestCase): """ # reservation start_time > SUB start_time and reservation stop_time > SUB stop_time self.set_1_reservation_start_time_gt_sub_start_time_and_stop_time_gt_sub_stop_time(self.reservation_one) - self.assertFalse(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint)) # reservation start_time < SUB start_time and stop_time < SUB stop_time self.set_2_reservation_start_time_lt_sub_start_time_and_stop_time_lt_sub_stop_time(self.reservation_one) - self.assertFalse(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint)) # reservation start_time > SUB start_time and stop_time < SUB stop_time self.set_3_reservation_start_time_gt_sub_start_time_and_stop_time_lt_sub_stop_time(self.reservation_one) - self.assertFalse(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint)) # reservation start_time < SUB start_time and stop_time > SUB stop_time self.set_4_reservation_start_time_lt_sub_start_time_and_stop_time_gt_sub_stop_time(self.reservation_one) - self.assertFalse(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint)) # Reservations outside boundary # start_time and stop_time < SUB start_time self.set_5_reservation_start_time_and_stop_time_lt_sub_start_time(self.reservation_one) - self.assertTrue(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint)) # start_time and stop_time > SUB stop_time self.set_6_reservation_start_time_and_stop_time_gt_sub_stop_time(self.reservation_one) - self.assertTrue(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint)) def test_two_stations_reserved(self): """ @@ -913,28 +913,28 @@ class TestReservedStations(unittest.TestCase): """ # reservation start_time > SUB start_time and reservation stop_time > SUB stop_time self.set_1_reservation_start_time_gt_sub_start_time_and_stop_time_gt_sub_stop_time(self.reservation_two) - self.assertFalse(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint)) # reservation start_time < SUB start_time and stop_time < SUB stop_time self.set_2_reservation_start_time_lt_sub_start_time_and_stop_time_lt_sub_stop_time(self.reservation_two) - self.assertFalse(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint)) # reservation start_time > SUB start_time and stop_time < SUB stop_time self.set_3_reservation_start_time_gt_sub_start_time_and_stop_time_lt_sub_stop_time(self.reservation_two) - self.assertFalse(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint)) # reservation start_time < SUB start_time and stop_time > SUB stop_time self.set_4_reservation_start_time_lt_sub_start_time_and_stop_time_gt_sub_stop_time(self.reservation_two) - self.assertFalse(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint)) # Reservations outside boundary # start_time and stop_time < SUB start_time self.set_5_reservation_start_time_and_stop_time_lt_sub_start_time(self.reservation_two) - self.assertTrue(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint)) # start_time and stop_time > SUB stop_time self.set_6_reservation_start_time_and_stop_time_gt_sub_stop_time(self.reservation_two) - self.assertTrue(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint)) def test_two_stations_reserved_but_not_used(self): """ @@ -944,28 +944,28 @@ class TestReservedStations(unittest.TestCase): """ # reservation start_time > SUB start_time and reservation stop_time > SUB stop_time self.set_1_reservation_start_time_gt_sub_start_time_and_stop_time_gt_sub_stop_time(self.reservation_two_no_overlap) - self.assertTrue(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint)) # reservation start_time < SUB start_time and stop_time < SUB stop_time self.set_2_reservation_start_time_lt_sub_start_time_and_stop_time_lt_sub_stop_time(self.reservation_two_no_overlap) - self.assertTrue(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint)) # reservation start_time > SUB start_time and stop_time < SUB stop_time self.set_3_reservation_start_time_gt_sub_start_time_and_stop_time_lt_sub_stop_time(self.reservation_two_no_overlap) - self.assertTrue(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint)) # reservation start_time < SUB start_time and stop_time > SUB stop_time self.set_4_reservation_start_time_lt_sub_start_time_and_stop_time_gt_sub_stop_time(self.reservation_two_no_overlap) - self.assertTrue(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint)) # Reservations outside boundary # start_time and stop_time < SUB start_time self.set_5_reservation_start_time_and_stop_time_lt_sub_start_time(self.reservation_two_no_overlap) - self.assertTrue(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint)) # start_time and stop_time > SUB stop_time self.set_6_reservation_start_time_and_stop_time_gt_sub_stop_time(self.reservation_two_no_overlap) - self.assertTrue(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint)) def test_two_stations_reserved_with_duration_null(self): """ @@ -977,17 +977,17 @@ class TestReservedStations(unittest.TestCase): # reservation start_time > SUB start_time and < SUB stop_time self.reservation_two_no_duration.start_time = self.scheduling_unit_blueprint.start_time + timedelta(minutes=5) self.reservation_two_no_duration.save() - self.assertFalse(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint)) # reservation start_time < SUB start_time (and < SUB stop_time of course) self.reservation_two_no_duration.start_time = self.scheduling_unit_blueprint.start_time - timedelta(minutes=5) self.reservation_two_no_duration.save() - self.assertFalse(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint)) # reservation start_time > SUB stop time self.reservation_two_no_duration.start_time = self.scheduling_unit_blueprint.stop_time + timedelta(minutes=5) self.reservation_two_no_duration.save() - self.assertTrue(can_run_within_reserved_stations(self.scheduling_unit_blueprint)) + self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint)) logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO)