def test_passes_clean(self):
        """UNIT test: services.simulation.models = passes CLEAN UP
        """

        pass_models.PassSlots.objects.propagate()
        sc_passes_n_1 = pass_models.PassSlots.objects.filter(
            spacecraft=self.__sc_1).count()

        simulation_tasks.clean_passes()
        sc_passes_n_2 = pass_models.PassSlots.objects.filter(
            spacecraft=self.__sc_1).count()

        self.assertEquals(sc_passes_n_1, sc_passes_n_2)

        interval_2 = (sn_misc.get_next_midnight() + py_timedelta(days=5),
                      sn_misc.get_next_midnight() + py_timedelta(days=6))
        pass_models.PassSlots.objects.propagate(interval=interval_2)
        sc_passes_n_3 = pass_models.PassSlots.objects.filter(
            spacecraft=self.__sc_1).count()
        self.assertGreater(sc_passes_n_3, sc_passes_n_2)

        simulation_tasks.clean_passes(threshold=sn_misc.get_next_midnight() +
                                      py_timedelta(days=10))
        sc_passes_n_4 = pass_models.PassSlots.objects.filter(
            spacecraft=self.__sc_1).count()
        self.assertEquals(sc_passes_n_4, 0)
    def test_create_availability(self):
        """UNIT test: services.scheduling.models.availability
        This test validates the creation of an availability slot and the
        further automatic rejections for the creation of availability slots
        that match the start and end of this one.
        """

        slot_s = sn_misc.get_next_midnight()
        slot_e = slot_s + py_timedelta(days=1)

        self.assertIsNotNone(
            availability_models.AvailabilitySlot.objects.create(
                groundstation=self.__gs, start=slot_s, end=slot_e
            )
        )
        self.assertIsNone(
            availability_models.AvailabilitySlot.objects.create(
                groundstation=self.__gs, start=slot_s, end=slot_e
            )
        )

        slot_s = slot_s + py_timedelta(days=1)
        slot_e = slot_s + py_timedelta(days=1)

        self.assertIsNotNone(
            availability_models.AvailabilitySlot.objects.create(
                groundstation=self.__gs, start=slot_s, end=slot_e
            )
        )
        self.assertIsNone(
            availability_models.AvailabilitySlot.objects.create(
                groundstation=self.__gs, start=slot_s, end=slot_e
            )
        )
示例#3
0
    def generate_available_slots_daily(rule_values, interval=None):
        """
        This method generates the available slots for a daily rule that
        starts and ends in the given dates, during the specified interval.
        TODO :: improve the generation algorithm in order to avoid generating
                slots since the start of the rule until the validity of the
                current interval (can be long)
        :param interval: Interval of applicability
        :param rule_values: The values for the ONCE availability rule
        """
        if interval is None:
            interval = simulation.OrbitalSimulator.get_simulation_window()

        try:
            r = AvailabilityRuleDaily.objects.get(
                availabilityrule_ptr_id=rule_values['id'])
        except dj_exceptions.ObjectDoesNotExist as ex:
            logger.warning(
                '>>> Child rule does not exist, returning no slots, ex = ' +
                str(ex))
            return []

        result = []
        slot_i = slots.position(interval, (r.starting_time, r.ending_time))

        while slot_i[0] < interval[1]:

            slot = slots.cutoff(interval, slot_i)
            result.append((slot[0], slot[1]))

            slot_i = (slot_i[0] + py_timedelta(days=1),
                      slot_i[1] + py_timedelta(days=1))

        return result
示例#4
0
    def test_create_availability(self):
        """UNIT test: services.scheduling.models.availability
        This test validates the creation of an availability slot and the
        further automatic rejections for the creation of availability slots
        that match the start and end of this one.
        """

        slot_s = sn_misc.get_next_midnight()
        slot_e = slot_s + py_timedelta(days=1)

        self.assertIsNotNone(
            availability_models.AvailabilitySlot.objects.create(
                groundstation=self.__gs, start=slot_s, end=slot_e))
        self.assertIsNone(
            availability_models.AvailabilitySlot.objects.create(
                groundstation=self.__gs, start=slot_s, end=slot_e))

        slot_s = slot_s + py_timedelta(days=1)
        slot_e = slot_s + py_timedelta(days=1)

        self.assertIsNotNone(
            availability_models.AvailabilitySlot.objects.create(
                groundstation=self.__gs, start=slot_s, end=slot_e))
        self.assertIsNone(
            availability_models.AvailabilitySlot.objects.create(
                groundstation=self.__gs, start=slot_s, end=slot_e))
示例#5
0
    def test_create_passes(self):
        """UNIT test: services.simulation.models.passes
        This test validates the creation of an availability slot and the
        further automatic rejections for the creation of availability slots
        that match the start and end of this one.
        """

        slot_s = sn_misc.get_next_midnight()
        slot_e = slot_s + py_timedelta(days=1)

        self.assertIsNotNone(
            pass_models.PassSlots.objects.create(spacecraft=self.__sc_1,
                                                 groundstation=self.__gs_1,
                                                 start=slot_s,
                                                 end=slot_e))
        self.assertIsNone(
            pass_models.PassSlots.objects.create(spacecraft=self.__sc_1,
                                                 groundstation=self.__gs_1,
                                                 start=slot_s,
                                                 end=slot_e))

        slot_s = slot_s + py_timedelta(days=1)
        slot_e = slot_s + py_timedelta(days=1)

        self.assertIsNotNone(
            pass_models.PassSlots.objects.create(spacecraft=self.__sc_1,
                                                 groundstation=self.__gs_1,
                                                 start=slot_s,
                                                 end=slot_e))
        self.assertIsNone(
            pass_models.PassSlots.objects.create(spacecraft=self.__sc_1,
                                                 groundstation=self.__gs_1,
                                                 start=slot_s,
                                                 end=slot_e))
示例#6
0
    def create(self, spacecraft, groundstation, start, end, **kwargs):
        """Overriden method
        Overriden method that creates the provided pass slot in case a similar
        one does not exist.
        :param spacecraft: The spacecraft involved in the operational slot
        :param groundstation: The groundstation for the pass
        :param start: The start datetime object of the pass
        :param end: The end datetime object of the pass
        :param kwargs: Additional parameters
        :return: A reference to the just created object
        """
        s_range = (start - py_timedelta(seconds=30),
                   start + py_timedelta(seconds=30))
        e_range = (end - py_timedelta(seconds=30),
                   end + py_timedelta(seconds=30))

        if self.filter(groundstation=groundstation,
                       spacecraft=spacecraft,
                       start__range=s_range,
                       end__range=e_range).exists():

            logger.warn('@PassManager.create(), CONFLICTING SLOT:\n' +
                        '\t * slot already exists GS = ' +
                        str(groundstation.identifier) + ', start = <' +
                        start.isoformat() + '>, end = <' + end.isoformat() +
                        '>')
            return None

        return super(PassManager, self).create(spacecraft=spacecraft,
                                               groundstation=groundstation,
                                               start=start,
                                               end=end,
                                               **kwargs)
示例#7
0
    def test_passes_reboot(self):
        """UNIT test: services.simulation.models - passes generation REBOOT
        This test validates that subsequent attempts to generate passes do not
        succeed in case that for the given update window, the passes had
        already been generated.
        """

        # 1) consecutive propagations should not be permitted
        logger.debug('#### FIRST PART OF THE TEST, CURRENT INTERVAL')

        pass_models.PassSlots.objects.propagate()
        sc_passes_n_1 = pass_models.PassSlots.objects.filter(
            spacecraft=self.__sc_1).count()
        pass_models.PassSlots.objects.propagate()
        sc_passes_n_2 = pass_models.PassSlots.objects.filter(
            spacecraft=self.__sc_1).count()
        self.assertEquals(sc_passes_n_1, sc_passes_n_2)

        # 2) now, we change the interval of application for avoiding reboots
        logger.debug('#### SECOND PART OF THE TEST, FUTURE INTERVAL')

        interval = (sn_misc.get_next_midnight() + py_timedelta(days=30),
                    sn_misc.get_next_midnight() + py_timedelta(days=33))
        pass_models.PassSlots.objects.propagate(interval=interval)
        sc_passes_n_3 = pass_models.PassSlots.objects.filter(
            spacecraft=self.__sc_1).count()
        self.assertGreater(sc_passes_n_3, sc_passes_n_2)
        pass_models.PassSlots.objects.propagate(interval=interval)
        sc_passes_n_4 = pass_models.PassSlots.objects.filter(
            spacecraft=self.__sc_1).count()
        self.assertEquals(sc_passes_n_4, sc_passes_n_3)
    def test_groundtracks_reboot(self):
        """UNIT test: services.simulation.models - gts generation REBOOT
        """

        # 1) consecutive propagations should not be permitted
        logger.debug('#### FIRST PART OF THE TEST, CURRENT INTERVAL')

        groundtrack_models.GroundTrack.objects.propagate()
        sc_gts_n_1 = len(
            groundtrack_models.GroundTrack.objects.get(
                spacecraft=self.__sc_1).timestamp)
        groundtrack_models.GroundTrack.objects.propagate()
        sc_gts_n_2 = len(
            groundtrack_models.GroundTrack.objects.get(
                spacecraft=self.__sc_1).timestamp)
        self.assertEquals(sc_gts_n_1, sc_gts_n_2)

        # 2) now, we change the interval of application for avoiding reboots
        logger.debug('#### SECOND PART OF THE TEST, FUTURE INTERVAL')

        interval = (sn_misc.get_next_midnight() + py_timedelta(days=3),
                    sn_misc.get_next_midnight() + py_timedelta(days=4))

        groundtrack_models.GroundTrack.objects.propagate(interval=interval)
        sc_gts_n_3 = len(
            groundtrack_models.GroundTrack.objects.get(
                spacecraft=self.__sc_1).timestamp)
        self.assertGreater(sc_gts_n_3, sc_gts_n_2)

        groundtrack_models.GroundTrack.objects.propagate(interval=interval)
        sc_gts_n_4 = len(
            groundtrack_models.GroundTrack.objects.get(
                spacecraft=self.__sc_1).timestamp)
        self.assertEquals(sc_gts_n_4, sc_gts_n_3)
    def test_groundtracks_clean(self):
        """UNIT test: services.simulation.models = groundtracks CLEAN UP
        """

        groundtrack_models.GroundTrack.objects.propagate()
        sc_gts_n_1 = len(
            groundtrack_models.GroundTrack.objects.get(
                spacecraft=self.__sc_1).timestamp)

        simulation_tasks.clean_passes()
        sc_gts_n_2 = len(
            groundtrack_models.GroundTrack.objects.get(
                spacecraft=self.__sc_1).timestamp)

        self.assertEquals(sc_gts_n_1, sc_gts_n_2)

        interval_2 = (sn_misc.get_next_midnight() + py_timedelta(days=5),
                      sn_misc.get_next_midnight() + py_timedelta(days=6))
        groundtrack_models.GroundTrack.objects.propagate(interval=interval_2)
        sc_gts_n_3 = len(
            groundtrack_models.GroundTrack.objects.get(
                spacecraft=self.__sc_1).timestamp)
        self.assertGreater(sc_gts_n_3, sc_gts_n_2)

        simulation_tasks.clean_groundtracks(
            threshold=sn_misc.get_next_midnight() + py_timedelta(days=10))
        sc_gts_n_4 = len(
            groundtrack_models.GroundTrack.objects.get(
                spacecraft=self.__sc_1).timestamp)
        self.assertEquals(sc_gts_n_4, 0)
示例#10
0
    def test_passes_clean(self):
        """UNIT test: services.simulation.models = passes CLEAN UP
        """

        pass_models.PassSlots.objects.propagate()
        sc_passes_n_1 = pass_models.PassSlots.objects.filter(
            spacecraft=self.__sc_1
        ).count()

        simulation_tasks.clean_passes()
        sc_passes_n_2 = pass_models.PassSlots.objects.filter(
            spacecraft=self.__sc_1
        ).count()

        self.assertEquals(sc_passes_n_1, sc_passes_n_2)

        interval_2 = (
            sn_misc.get_next_midnight() + py_timedelta(days=5),
            sn_misc.get_next_midnight() + py_timedelta(days=6)
        )
        pass_models.PassSlots.objects.propagate(interval=interval_2)
        sc_passes_n_3 = pass_models.PassSlots.objects.filter(
            spacecraft=self.__sc_1
        ).count()
        self.assertGreater(sc_passes_n_3, sc_passes_n_2)

        simulation_tasks.clean_passes(
            threshold=sn_misc.get_next_midnight() + py_timedelta(days=10)
        )
        sc_passes_n_4 = pass_models.PassSlots.objects.filter(
            spacecraft=self.__sc_1
        ).count()
        self.assertEquals(sc_passes_n_4, 0)
示例#11
0
def cutoff(interval, slot):
    """Slot manipulation library
    This function cuts off the given slot within the given interval. This way,
    in case the slot starting time happens before the starting of the interval,
    the slot starting time is cutoff to the starting time of the interval.
    The same is done with the ending time of the slot. In case the slot ends
    too early (ends before the interval starts) or starts too late (starts
    after the interval ends), an exception is raised.

    :param interval: 2-tuple with the datetime objects for the interval
    :param slot: 2-tuple with the datetime objects for the slot
    :return: Processed slot with the starting and ending times cutted off
    """
    if not slot or not interval:
        raise ValueError('@cutoff_slot: wrong parameters')
    if slot[0] > slot[1]:
        raise ValueError('@cutoff_slot: slot[0] > slot[1]')
    if interval[0] > interval[1]:
        raise ValueError('@cutoff_slot: interval[0] > interval[1]')

    # backup copy for cutting off and not ruining the original outter objects
    interval_w = (
        interval[0] + py_timedelta(days=0), interval[1] + py_timedelta(days=0)
    )
    slot_w = (
        slot[0] + py_timedelta(days=0), slot[1] + py_timedelta(days=0)
    )

    # CASE A: discard, too late
    if slot_w[1] <= interval_w[0]:
        raise ValueError('@cutoff_slot: slot[1] <= interval[0]')
    # CASE E: discard, too early
    if slot_w[0] >= interval_w[1]:
        raise ValueError('@cutoff_slot: slot[0] >= interval[1]')

    if slot_w[0] >= interval_w[0]:
        # CASE C: no cutoff is necessary
        if slot_w[1] <= interval_w[1]:
            return slot_w
        else:
            # CASE D: cutting off the ending time of the slot
            return slot_w[0], interval_w[1]

    # CASE B: cutting off slot's starting time
    return interval_w[0], slot_w[1]
示例#12
0
    def test_groundtracks_clean(self):
        """UNIT test: services.simulation.models = groundtracks CLEAN UP
        """

        groundtrack_models.GroundTrack.objects.propagate()
        sc_gts_n_1 = len(
            groundtrack_models.GroundTrack.objects.get(
                spacecraft=self.__sc_1
            ).timestamp
        )

        simulation_tasks.clean_passes()
        sc_gts_n_2 = len(
            groundtrack_models.GroundTrack.objects.get(
                spacecraft=self.__sc_1
            ).timestamp
        )

        self.assertEquals(sc_gts_n_1, sc_gts_n_2)

        interval_2 = (
            sn_misc.get_next_midnight() + py_timedelta(days=5),
            sn_misc.get_next_midnight() + py_timedelta(days=6)
        )
        groundtrack_models.GroundTrack.objects.propagate(interval=interval_2)
        sc_gts_n_3 = len(
            groundtrack_models.GroundTrack.objects.get(
                spacecraft=self.__sc_1
            ).timestamp
        )
        self.assertGreater(sc_gts_n_3, sc_gts_n_2)

        simulation_tasks.clean_groundtracks(
            threshold=sn_misc.get_next_midnight() + py_timedelta(days=10)
        )
        sc_gts_n_4 = len(
            groundtrack_models.GroundTrack.objects.get(
                spacecraft=self.__sc_1
            ).timestamp
        )
        self.assertEquals(sc_gts_n_4, 0)
示例#13
0
    def generate_available_slots_daily(rule_values, interval=None):
        """
        This method generates the available slots for a daily rule that
        starts and ends in the given dates, during the specified interval.
        TODO :: improve the generation algorithm in order to avoid generating
                slots since the start of the rule until the validity of the
                current interval (can be long)
        :param interval: Interval of applicability
        :param rule_values: The values for the ONCE availability rule
        """
        if interval is None:
            interval = simulation.OrbitalSimulator.get_simulation_window()

        try:
            r = AvailabilityRuleDaily.objects.get(
                availabilityrule_ptr_id=rule_values['id']
            )
        except dj_exceptions.ObjectDoesNotExist as ex:
            logger.warning(
                '>>> Child rule does not exist, returning no slots, ex = ' +
                str(ex)
            )
            return []

        result = []
        slot_i = slots.position(interval, (r.starting_time, r.ending_time))

        while slot_i[0] < interval[1]:

            slot = slots.cutoff(interval, slot_i)
            result.append((slot[0], slot[1]))

            slot_i = (
                slot_i[0] + py_timedelta(days=1),
                slot_i[1] + py_timedelta(days=1)
            )

        return result
示例#14
0
    def test_create_passes(self):
        """UNIT test: services.simulation.models.passes
        This test validates the creation of an availability slot and the
        further automatic rejections for the creation of availability slots
        that match the start and end of this one.
        """

        slot_s = sn_misc.get_next_midnight()
        slot_e = slot_s + py_timedelta(days=1)

        self.assertIsNotNone(
            pass_models.PassSlots.objects.create(
                spacecraft=self.__sc_1, groundstation=self.__gs_1,
                start=slot_s, end=slot_e
            )
        )
        self.assertIsNone(
            pass_models.PassSlots.objects.create(
                spacecraft=self.__sc_1, groundstation=self.__gs_1,
                start=slot_s, end=slot_e
            )
        )

        slot_s = slot_s + py_timedelta(days=1)
        slot_e = slot_s + py_timedelta(days=1)

        self.assertIsNotNone(
            pass_models.PassSlots.objects.create(
                spacecraft=self.__sc_1, groundstation=self.__gs_1,
                start=slot_s, end=slot_e
            )
        )
        self.assertIsNone(
            pass_models.PassSlots.objects.create(
                spacecraft=self.__sc_1, groundstation=self.__gs_1,
                start=slot_s, end=slot_e
            )
        )
示例#15
0
 def __convert__(self, value):
     if isinstance(value, py_timedelta):
         return value
     elif DateTimeDeltaType is not None and \
              type(value) == DateTimeDeltaType:
         ret = py_timedelta(0,
                            hours=value.hour,
                            minutes=value.minute,
                            seconds=value.second)
         return ret
     else:
         raise ValueError("This dbattribute may only be set to "+\
                          "datetime.datetime instances, not %s!" % \
                          repr(type(value)))
示例#16
0
 def __convert__(self, value):
     if isinstance(value, py_timedelta):
         return value
     elif DateTimeDeltaType is not None and \
              type(value) == DateTimeDeltaType:
         ret = py_timedelta(0,
                            hours=value.hour,
                            minutes=value.minute,
                            seconds=value.second)
         return ret
     else:
         raise ValueError("This dbattribute may only be set to "+\
                          "datetime.datetime instances, not %s!" % \
                          repr(type(value)))
示例#17
0
    def test_passes_reboot(self):
        """UNIT test: services.simulation.models - passes generation REBOOT
        This test validates that subsequent attempts to generate passes do not
        succeed in case that for the given update window, the passes had
        already been generated.
        """

        # 1) consecutive propagations should not be permitted
        logger.debug('#### FIRST PART OF THE TEST, CURRENT INTERVAL')

        pass_models.PassSlots.objects.propagate()
        sc_passes_n_1 = pass_models.PassSlots.objects.filter(
            spacecraft=self.__sc_1
        ).count()
        pass_models.PassSlots.objects.propagate()
        sc_passes_n_2 = pass_models.PassSlots.objects.filter(
            spacecraft=self.__sc_1
        ).count()
        self.assertEquals(sc_passes_n_1, sc_passes_n_2)

        # 2) now, we change the interval of application for avoiding reboots
        logger.debug('#### SECOND PART OF THE TEST, FUTURE INTERVAL')

        interval = (
            sn_misc.get_next_midnight() + py_timedelta(days=30),
            sn_misc.get_next_midnight() + py_timedelta(days=33)
        )
        pass_models.PassSlots.objects.propagate(interval=interval)
        sc_passes_n_3 = pass_models.PassSlots.objects.filter(
            spacecraft=self.__sc_1
        ).count()
        self.assertGreater(sc_passes_n_3, sc_passes_n_2)
        pass_models.PassSlots.objects.propagate(interval=interval)
        sc_passes_n_4 = pass_models.PassSlots.objects.filter(
            spacecraft=self.__sc_1
        ).count()
        self.assertEquals(sc_passes_n_4, sc_passes_n_3)
示例#18
0
def position(interval, slot):
    """Slot manipulation library
    This function repositions the given slot within the given interval, so that
    the calculation of the generated slots can start right away.

    :param interval: The interval to reposition the slot within
    :param slot: The slot to be repositioned
    :return: The slot repositioned (start, end) might've changed
    """
    if not slot or not interval:
        raise ValueError('@cutoff_slot: wrong parameters')
    if slot[0] > slot[1]:
        raise ValueError('@cutoff_slot: slot[0] > slot[1]')
    if interval[0] > interval[1]:
        raise ValueError('@cutoff_slot: interval[0] > interval[1]')

    r0_p = py_datetime.combine(interval[0].date(), slot[0].timetz())
    r1_p = r0_p + (slot[1] - slot[0])

    if r1_p < interval[0]:
        r0_p += py_timedelta(days=1)
        r1_p += py_timedelta(days=1)

    return r0_p, r1_p
示例#19
0
    def test_groundtracks_reboot(self):
        """UNIT test: services.simulation.models - gts generation REBOOT
        """

        # 1) consecutive propagations should not be permitted
        logger.debug('#### FIRST PART OF THE TEST, CURRENT INTERVAL')

        groundtrack_models.GroundTrack.objects.propagate()
        sc_gts_n_1 = len(groundtrack_models.GroundTrack.objects.get(
            spacecraft=self.__sc_1
        ).timestamp)
        groundtrack_models.GroundTrack.objects.propagate()
        sc_gts_n_2 = len(groundtrack_models.GroundTrack.objects.get(
            spacecraft=self.__sc_1
        ).timestamp)
        self.assertEquals(sc_gts_n_1, sc_gts_n_2)

        # 2) now, we change the interval of application for avoiding reboots
        logger.debug('#### SECOND PART OF THE TEST, FUTURE INTERVAL')

        interval = (
            sn_misc.get_next_midnight() + py_timedelta(days=3),
            sn_misc.get_next_midnight() + py_timedelta(days=4)
        )

        groundtrack_models.GroundTrack.objects.propagate(interval=interval)
        sc_gts_n_3 = len(groundtrack_models.GroundTrack.objects.get(
            spacecraft=self.__sc_1
        ).timestamp)
        self.assertGreater(sc_gts_n_3, sc_gts_n_2)

        groundtrack_models.GroundTrack.objects.propagate(interval=interval)
        sc_gts_n_4 = len(groundtrack_models.GroundTrack.objects.get(
            spacecraft=self.__sc_1
        ).timestamp)
        self.assertEquals(sc_gts_n_4, sc_gts_n_3)
示例#20
0
    def create(self, groundstation, operation, periodicity, dates):
        """
        This method creates a new object in the database.
        :param groundstation: reference to the ground station for the rule
        :param operation: type of operation (create or remove slots)
        :param periodicity: periodicity for the rule (once, daily, weekly)
        :param dates: applicability dates for the rule
        """
        localtime = pytz_ref.LocalTimezone()
        starting_date_tz = localtime.tzname(dates[0])
        ending_date_tz = localtime.tzname(dates[1])

        if starting_date_tz != ending_date_tz:
            raise ValueError(
                'Invalid DAILY rule, dates TZ differ: ' +
                '( starting_date_tz = ' + starting_date_tz +
                'ending_date_tz = ' + ending_date_tz + ' )'
            )

        starting_dt = dates[2].astimezone(pytz.utc)
        ending_dt = dates[3].astimezone(pytz.utc)
        diff_dt = ending_dt - starting_dt

        if diff_dt > py_timedelta(hours=24):
            raise ValueError(
                'Invalid DAILY rule, diff_dt = ' + str(diff_dt) + ' > 24 hours'
            )

        if ending_dt <= starting_dt:
            raise ValueError(
                'Invalid DAILY rule, ending (' + ending_dt.isoformat() + ') ' +
                '<= starting (' + starting_dt.isoformat() + ')'
            )

        return super(AvailabilityRuleDailyManager, self).create(
            groundstation=groundstation,
            operation=operation,
            periodicity=periodicity,
            starting_date=dates[0],
            ending_date=dates[1],
            starting_time=starting_dt,
            ending_time=ending_dt
        )
示例#21
0
    def create(self, groundstation, operation, periodicity, dates):
        """
        This method creates a new object in the database.
        :param groundstation: reference to the ground station for the rule
        :param operation: type of operation (create or remove slots)
        :param periodicity: periodicity for the rule (once, daily, weekly)
        :param dates: applicability dates for the rule
        """
        localtime = pytz_ref.LocalTimezone()
        starting_date_tz = localtime.tzname(dates[0])
        ending_date_tz = localtime.tzname(dates[1])

        if starting_date_tz != ending_date_tz:
            raise ValueError('Invalid DAILY rule, dates TZ differ: ' +
                             '( starting_date_tz = ' + starting_date_tz +
                             'ending_date_tz = ' + ending_date_tz + ' )')

        starting_dt = dates[2].astimezone(pytz.utc)
        ending_dt = dates[3].astimezone(pytz.utc)
        diff_dt = ending_dt - starting_dt

        if diff_dt > py_timedelta(hours=24):
            raise ValueError('Invalid DAILY rule, diff_dt = ' + str(diff_dt) +
                             ' > 24 hours')

        if ending_dt <= starting_dt:
            raise ValueError('Invalid DAILY rule, ending (' +
                             ending_dt.isoformat() + ') ' + '<= starting (' +
                             starting_dt.isoformat() + ')')

        return super(AvailabilityRuleDailyManager,
                     self).create(groundstation=groundstation,
                                  operation=operation,
                                  periodicity=periodicity,
                                  starting_date=dates[0],
                                  ending_date=dates[1],
                                  starting_time=starting_dt,
                                  ending_time=ending_dt)
示例#22
0
    def test_generate_slots_daily_rule(self):
        """UNIT test: services.configuration.models.rules - DAILY slots
        This test validates that a DAILY rule generates the right amount of
        slots depending on the interval relation with the start/end moments of
        the rule itself.
        """
        if self.__verbose_testing:
            print('>>> test_generate_slots_once_rule:')

        #######################################################################
        # ### XXXX SIGNAL DISCONNECTED
        django_signals.post_save.disconnect(
            availability_signals.daily_rule_saved,
            sender=rule_models.AvailabilityRuleDaily
        )

        #######################################################################
        # ### 1) rule starts ends interval, no slot the first day
        rule_id = rule_jrpc.add_rule(
            self.__gs_1_id,
            sn_helpers.create_jrpc_daily_rule(
                starting_time=sn_misc.get_next_midnight() + py_timedelta(
                    hours=2
                ),
                ending_time=sn_misc.get_next_midnight() + py_timedelta(
                    hours=3
                )
            )
        )

        rule_db_values = rule_models.AvailabilityRule.objects.filter(
            pk=rule_id
        ).values()

        interval = (
            sn_misc.get_next_midnight() + py_timedelta(days=300, hours=4),
            sn_misc.get_next_midnight() + py_timedelta(days=303)
        )

        slots = rule_models.AvailabilityRuleManager\
            .generate_available_slots_daily(
                rule_db_values[0], interval=interval
            )

        expected = [
            (
                sn_misc.get_next_midnight() + py_timedelta(days=301, hours=2),
                sn_misc.get_next_midnight() + py_timedelta(days=301, hours=3)
            ),
            (
                sn_misc.get_next_midnight() + py_timedelta(days=302, hours=2),
                sn_misc.get_next_midnight() + py_timedelta(days=302, hours=3)
            ),
        ]

        self.assertListEqual(slots, expected)

        #######################################################################
        # ### 2) rule starts before interval, ends within,
        #           first day slot truncated
        rule_id = rule_jrpc.add_rule(
            self.__gs_1_id,
            sn_helpers.create_jrpc_daily_rule(
                starting_time=sn_misc.get_next_midnight() + py_timedelta(
                    hours=2
                ),
                ending_time=sn_misc.get_next_midnight() + py_timedelta(
                    hours=6
                )
            )
        )

        rule_db_values = rule_models.AvailabilityRule.objects.filter(
            pk=rule_id
        ).values()

        interval = (
            sn_misc.get_next_midnight() + py_timedelta(days=300, hours=4),
            sn_misc.get_next_midnight() + py_timedelta(days=303)
        )

        slots = rule_models.AvailabilityRuleManager\
            .generate_available_slots_daily(
                rule_db_values[0], interval=interval
            )

        expected = [
            (
                sn_misc.get_next_midnight() + py_timedelta(days=300, hours=4),
                sn_misc.get_next_midnight() + py_timedelta(days=300, hours=6)
            ),
            (
                sn_misc.get_next_midnight() + py_timedelta(days=301, hours=2),
                sn_misc.get_next_midnight() + py_timedelta(days=301, hours=6)
            ),
            (
                sn_misc.get_next_midnight() + py_timedelta(days=302, hours=2),
                sn_misc.get_next_midnight() + py_timedelta(days=302, hours=6)
            ),
        ]

        self.assertListEqual(slots, expected)

        #######################################################################
        # ### XXXX SIGNAL RECONNECTED
        django_signals.post_save.connect(
            availability_signals.daily_rule_saved,
            sender=rule_models.AvailabilityRuleDaily
        )
示例#23
0
    def test_generate_slots_once_rule(self):
        """UNIT test: services.configuration.models.rules - ONCE slots
        This test validates that a ONCE rule generates the right amount of
        slots depending on the interval relation with the start/end moments of
        the rule itself.
        """
        if self.__verbose_testing:
            print('>>> test_generate_slots_once_rule:')

        #######################################################################
        # ### XXXX SIGNAL DISCONNECTED
        django_signals.post_save.disconnect(
            availability_signals.once_rule_saved,
            sender=rule_models.AvailabilityRuleOnce
        )

        #######################################################################
        # ### 1) rule after interval
        rule_1_id = rule_jrpc.add_rule(
            self.__gs_1_id,
            sn_helpers.create_jrpc_once_rule(
                starting_time=sn_misc.get_next_midnight(),
                ending_time=sn_misc.get_next_midnight() + py_timedelta(hours=4)
            )
        )
        rule_1_db_values = rule_models.AvailabilityRule.objects.filter(
            pk=rule_1_id
        ).values()

        self.assertListEqual(
            rule_models.AvailabilityRuleManager.generate_available_slots_once(
                rule_1_db_values[0], (
                    sn_misc.get_next_midnight() - py_timedelta(hours=12),
                    sn_misc.get_next_midnight() - py_timedelta(hours=3)
                )
            ),
            []
        )

        self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_1_id))

        #######################################################################
        # ### 2) rule before interval

        rule_2_id = rule_jrpc.add_rule(
            self.__gs_1_id,
            sn_helpers.create_jrpc_once_rule(
                starting_time=sn_misc.get_next_midnight() - py_timedelta(
                    hours=6
                ),
                ending_time=sn_misc.get_next_midnight() - py_timedelta(
                    hours=4
                )
            )
        )
        rule_2_db_values = rule_models.AvailabilityRule.objects.filter(
            pk=rule_2_id
        ).values()

        self.assertListEqual(
            rule_models.AvailabilityRuleManager.generate_available_slots_once(
                rule_2_db_values[0], (
                    sn_misc.get_next_midnight(),
                    sn_misc.get_next_midnight() + py_timedelta(hours=9)
                )
            ),
            []
        )

        self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_2_id))

        #######################################################################
        # ### 3) rule FULLY inside interval

        rule_3_id = rule_jrpc.add_rule(
            self.__gs_1_id,
            sn_helpers.create_jrpc_once_rule(
                starting_time=sn_misc.get_next_midnight() + py_timedelta(
                    hours=2
                ),
                ending_time=sn_misc.get_next_midnight() + py_timedelta(
                    hours=4
                )
            )
        )
        rule_3_db_values = rule_models.AvailabilityRule.objects.filter(
            pk=rule_3_id
        ).values()

        self.assertListEqual(
            rule_models.AvailabilityRuleManager.generate_available_slots_once(
                rule_3_db_values[0], (
                    sn_misc.get_next_midnight(),
                    sn_misc.get_next_midnight() + py_timedelta(hours=9)
                )
            ), [(
                sn_misc.get_next_midnight() + py_timedelta(hours=2),
                sn_misc.get_next_midnight() + py_timedelta(hours=4)
            )]
        )

        self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_3_id))

        #######################################################################
        # ### 4) rule start before the interval

        rule_4_id = rule_jrpc.add_rule(
            self.__gs_1_id,
            sn_helpers.create_jrpc_once_rule(
                starting_time=sn_misc.get_next_midnight() - py_timedelta(
                    hours=1
                ),
                ending_time=sn_misc.get_next_midnight() + py_timedelta(
                    hours=4
                )
            )
        )
        rule_4_db_values = rule_models.AvailabilityRule.objects.filter(
            pk=rule_4_id
        ).values()

        self.assertListEqual(
            rule_models.AvailabilityRuleManager.generate_available_slots_once(
                rule_4_db_values[0], (
                    sn_misc.get_next_midnight(),
                    sn_misc.get_next_midnight() + py_timedelta(hours=9)
                )
            ), [(
                sn_misc.get_next_midnight(),
                sn_misc.get_next_midnight() + py_timedelta(hours=4)
            )]
        )

        self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_4_id))

        #######################################################################
        # ### 5) rule ends after the interval

        rule_5_id = rule_jrpc.add_rule(
            self.__gs_1_id,
            sn_helpers.create_jrpc_once_rule(
                starting_time=sn_misc.get_next_midnight() + py_timedelta(
                    hours=2
                ),
                ending_time=sn_misc.get_next_midnight() + py_timedelta(
                    hours=12
                )
            )
        )
        rule_5_db_values = rule_models.AvailabilityRule.objects.filter(
            pk=rule_5_id
        ).values()

        self.assertListEqual(
            rule_models.AvailabilityRuleManager.generate_available_slots_once(
                rule_5_db_values[0], (
                    sn_misc.get_next_midnight(),
                    sn_misc.get_next_midnight() + py_timedelta(hours=9)
                )
            ), [(
                sn_misc.get_next_midnight() + py_timedelta(hours=2),
                sn_misc.get_next_midnight() + py_timedelta(hours=9)
            )]
        )

        self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_5_id))

        #######################################################################
        # ### XXXX SIGNAL RECONNECTED
        django_signals.post_save.connect(
            availability_signals.once_rule_saved,
            sender=rule_models.AvailabilityRuleOnce
        )
示例#24
0
def merge_slots(p_slots, m_slots):
    """Slot manipulation library
    This function  merges the slots that define the availability of the
    ground station with the slots that define the non-availability of a
    ground station. The result are the actual availability slots.
    IMPORTANT: input lists of slots must be order by starting datetime.
    :param p_slots: The list of (+) slots.
    :param m_slots: The list of (-) slots.
    :return: Resulting list with the actual available slots.
    """
    if p_slots is None or m_slots is None:
        return []
    if len(p_slots) < 1:
        return []

    # Algorithm initialization
    slots = []
    p_next = True  # ### indicates whether the 'p' vector has to be updated
    p_n = len(p_slots)
    p_i = 0
    m_i = 0
    m_n = len(m_slots)
    if m_n > 0:
        m = m_slots[0]
        m_i = 1
    else:
        # All slots will be generated from today on, so this will be the
        # "oldest" slot independently of the rest...
        m = (
            misc.get_today_utc() - py_timedelta(days=1),
            misc.get_today_utc() - py_timedelta(days=1)
        )

    # The algorithm is executed for all the add slots, since negative slots
    # do not generate actual slots at all, they only limit the range of the
    # add slots.
    while True:

        if p_next:
            # ### stop condition
            if p_i == p_n:
                break
            p = p_slots[p_i]
            p_i += 1
        else:
            p_next = True

        if p[1] <= m[0]:
            # ### CASE A:
            slots.append(p)
            continue

        if p[0] >= m[1]:
            # ### CASE F:
            if m_i < m_n:
                m = m_slots[m_i]
                m_i += 1
            else:
                slots.append(p)
            continue

        if p[0] < m[0]:

            if (p[1] > m[0]) and (p[1] <= m[1]):
                # ### CASE B:
                slots.append((p[0], m[0]))
            if p[1] > m[1]:
                # ### CASE C:
                slots.append((p[0], m[0]))
                p = (m[1], p[1])
                p_next = False

        else:

            # ### CASE D:
            if p[1] > m[1]:
                p = (m[1], p[1])
                p_next = False
                if m_i < m_n:
                    m = m_slots[m_i]
                    m_i += 1

    return slots
示例#25
0
    def test_generate_slots_daily_rule(self):
        """UNIT test: services.configuration.models.rules - DAILY slots
        This test validates that a DAILY rule generates the right amount of
        slots depending on the interval relation with the start/end moments of
        the rule itself.
        """
        if self.__verbose_testing:
            print('>>> test_generate_slots_once_rule:')

        #######################################################################
        # ### XXXX SIGNAL DISCONNECTED
        django_signals.post_save.disconnect(
            availability_signals.daily_rule_saved,
            sender=rule_models.AvailabilityRuleDaily)

        #######################################################################
        # ### 1) rule starts ends interval, no slot the first day
        rule_id = rule_jrpc.add_rule(
            self.__gs_1_id,
            sn_helpers.create_jrpc_daily_rule(
                starting_time=sn_misc.get_next_midnight() +
                py_timedelta(hours=2),
                ending_time=sn_misc.get_next_midnight() +
                py_timedelta(hours=3)))

        rule_db_values = rule_models.AvailabilityRule.objects.filter(
            pk=rule_id).values()

        interval = (sn_misc.get_next_midnight() +
                    py_timedelta(days=300, hours=4),
                    sn_misc.get_next_midnight() + py_timedelta(days=303))

        slots = rule_models.AvailabilityRuleManager\
            .generate_available_slots_daily(
                rule_db_values[0], interval=interval
            )

        expected = [
            (sn_misc.get_next_midnight() + py_timedelta(days=301, hours=2),
             sn_misc.get_next_midnight() + py_timedelta(days=301, hours=3)),
            (sn_misc.get_next_midnight() + py_timedelta(days=302, hours=2),
             sn_misc.get_next_midnight() + py_timedelta(days=302, hours=3)),
        ]

        self.assertListEqual(slots, expected)

        #######################################################################
        # ### 2) rule starts before interval, ends within,
        #           first day slot truncated
        rule_id = rule_jrpc.add_rule(
            self.__gs_1_id,
            sn_helpers.create_jrpc_daily_rule(
                starting_time=sn_misc.get_next_midnight() +
                py_timedelta(hours=2),
                ending_time=sn_misc.get_next_midnight() +
                py_timedelta(hours=6)))

        rule_db_values = rule_models.AvailabilityRule.objects.filter(
            pk=rule_id).values()

        interval = (sn_misc.get_next_midnight() +
                    py_timedelta(days=300, hours=4),
                    sn_misc.get_next_midnight() + py_timedelta(days=303))

        slots = rule_models.AvailabilityRuleManager\
            .generate_available_slots_daily(
                rule_db_values[0], interval=interval
            )

        expected = [
            (sn_misc.get_next_midnight() + py_timedelta(days=300, hours=4),
             sn_misc.get_next_midnight() + py_timedelta(days=300, hours=6)),
            (sn_misc.get_next_midnight() + py_timedelta(days=301, hours=2),
             sn_misc.get_next_midnight() + py_timedelta(days=301, hours=6)),
            (sn_misc.get_next_midnight() + py_timedelta(days=302, hours=2),
             sn_misc.get_next_midnight() + py_timedelta(days=302, hours=6)),
        ]

        self.assertListEqual(slots, expected)

        #######################################################################
        # ### XXXX SIGNAL RECONNECTED
        django_signals.post_save.connect(
            availability_signals.daily_rule_saved,
            sender=rule_models.AvailabilityRuleDaily)
示例#26
0
    def test_generate_slots_once_rule(self):
        """UNIT test: services.configuration.models.rules - ONCE slots
        This test validates that a ONCE rule generates the right amount of
        slots depending on the interval relation with the start/end moments of
        the rule itself.
        """
        if self.__verbose_testing:
            print('>>> test_generate_slots_once_rule:')

        #######################################################################
        # ### XXXX SIGNAL DISCONNECTED
        django_signals.post_save.disconnect(
            availability_signals.once_rule_saved,
            sender=rule_models.AvailabilityRuleOnce)

        #######################################################################
        # ### 1) rule after interval
        rule_1_id = rule_jrpc.add_rule(
            self.__gs_1_id,
            sn_helpers.create_jrpc_once_rule(
                starting_time=sn_misc.get_next_midnight(),
                ending_time=sn_misc.get_next_midnight() +
                py_timedelta(hours=4)))
        rule_1_db_values = rule_models.AvailabilityRule.objects.filter(
            pk=rule_1_id).values()

        self.assertListEqual(
            rule_models.AvailabilityRuleManager.generate_available_slots_once(
                rule_1_db_values[0],
                (sn_misc.get_next_midnight() - py_timedelta(hours=12),
                 sn_misc.get_next_midnight() - py_timedelta(hours=3))), [])

        self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_1_id))

        #######################################################################
        # ### 2) rule before interval

        rule_2_id = rule_jrpc.add_rule(
            self.__gs_1_id,
            sn_helpers.create_jrpc_once_rule(
                starting_time=sn_misc.get_next_midnight() -
                py_timedelta(hours=6),
                ending_time=sn_misc.get_next_midnight() -
                py_timedelta(hours=4)))
        rule_2_db_values = rule_models.AvailabilityRule.objects.filter(
            pk=rule_2_id).values()

        self.assertListEqual(
            rule_models.AvailabilityRuleManager.generate_available_slots_once(
                rule_2_db_values[0],
                (sn_misc.get_next_midnight(),
                 sn_misc.get_next_midnight() + py_timedelta(hours=9))), [])

        self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_2_id))

        #######################################################################
        # ### 3) rule FULLY inside interval

        rule_3_id = rule_jrpc.add_rule(
            self.__gs_1_id,
            sn_helpers.create_jrpc_once_rule(
                starting_time=sn_misc.get_next_midnight() +
                py_timedelta(hours=2),
                ending_time=sn_misc.get_next_midnight() +
                py_timedelta(hours=4)))
        rule_3_db_values = rule_models.AvailabilityRule.objects.filter(
            pk=rule_3_id).values()

        self.assertListEqual(
            rule_models.AvailabilityRuleManager.generate_available_slots_once(
                rule_3_db_values[0],
                (sn_misc.get_next_midnight(),
                 sn_misc.get_next_midnight() + py_timedelta(hours=9))),
            [(sn_misc.get_next_midnight() + py_timedelta(hours=2),
              sn_misc.get_next_midnight() + py_timedelta(hours=4))])

        self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_3_id))

        #######################################################################
        # ### 4) rule start before the interval

        rule_4_id = rule_jrpc.add_rule(
            self.__gs_1_id,
            sn_helpers.create_jrpc_once_rule(
                starting_time=sn_misc.get_next_midnight() -
                py_timedelta(hours=1),
                ending_time=sn_misc.get_next_midnight() +
                py_timedelta(hours=4)))
        rule_4_db_values = rule_models.AvailabilityRule.objects.filter(
            pk=rule_4_id).values()

        self.assertListEqual(
            rule_models.AvailabilityRuleManager.generate_available_slots_once(
                rule_4_db_values[0],
                (sn_misc.get_next_midnight(),
                 sn_misc.get_next_midnight() + py_timedelta(hours=9))),
            [(sn_misc.get_next_midnight(),
              sn_misc.get_next_midnight() + py_timedelta(hours=4))])

        self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_4_id))

        #######################################################################
        # ### 5) rule ends after the interval

        rule_5_id = rule_jrpc.add_rule(
            self.__gs_1_id,
            sn_helpers.create_jrpc_once_rule(
                starting_time=sn_misc.get_next_midnight() +
                py_timedelta(hours=2),
                ending_time=sn_misc.get_next_midnight() +
                py_timedelta(hours=12)))
        rule_5_db_values = rule_models.AvailabilityRule.objects.filter(
            pk=rule_5_id).values()

        self.assertListEqual(
            rule_models.AvailabilityRuleManager.generate_available_slots_once(
                rule_5_db_values[0],
                (sn_misc.get_next_midnight(),
                 sn_misc.get_next_midnight() + py_timedelta(hours=9))),
            [(sn_misc.get_next_midnight() + py_timedelta(hours=2),
              sn_misc.get_next_midnight() + py_timedelta(hours=9))])

        self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_5_id))

        #######################################################################
        # ### XXXX SIGNAL RECONNECTED
        django_signals.post_save.connect(
            availability_signals.once_rule_saved,
            sender=rule_models.AvailabilityRuleOnce)