Esempio n. 1
0
 def duty_day_classifier(duty_day):
     """Given a DutyDay, this classifier will insert the following tags:
        - regular : any continental flight under 10:00 duty time. It is the default value
        - transoceanic : MAD, CDG, MXP, FCO, LHR, AMS, SVO, BCN, MUC, FRA, NRT, ICN, PVG, PEK
        - special transoceanic :
                                 a) MUST be transoceanic
                                 b) scheduled block time > 13:00 hrs
                                 c) scheduled duty time  > 15:00 hrs
        - long haul : Any flight with
                                 a) #of legs <= 2
                                 b) AND at least one leg > 4:30 hrs
                                 c) AND
                                     - OR    BLK > 10:00
                                     - OR    DUTY > 12:00
                                     - OR    DUTY > 09:30 AND  DUTY.OVERLAPS(00:59, 04:59) inclusive
        """
     # TODO : I don't like the way this looks
     if set([airport.iata_code for airport in duty_day._credits['routing']
             ]).intersection(TRANSOCEANIC):
         duty_day._credits['duty_type'] = 'transoceanic'
         if (duty_day._credits['total']
             ) > MINIMUM_BLOCK or duty_day._credits['daily'] > MINIMUM_DUTY:
             duty_day._credits['duty_type'] = 'special trans'
     elif len(duty_day.events) <= 2:
         for event in duty_day.events:
             if event.duration > Duration(4 * 60 + 30):
                 if duty_day._credits['block'] > Duration(10 * 60) or \
                                 duty_day._credits['daily'] > Duration(12 * 60) or \
                         (duty_day._credits['daily'] > Duration(9 * 60 + 30) and
                              Creditator.has_early_morning_time(duty_day)):
                     duty_day._credits['duty_type'] = 'long haul'
                 break
Esempio n. 2
0
    def credits_from_line(self, line):
        """Returns a credits_list with all credits for given line"""

        # 1. Calculate pending credits for line DESC 7DAT HDAY
        line._credits.update({
            'day': '',
            'routing': 'TOTALS',
            'report': '',
            'release': '',
            'duty_type': '',
            'event_names': '',
            'daily': Duration(0),
            'block': Duration(0),
            'dh': Duration(0),
            'night': Duration(0),
            'xduty': Duration(0),
            'xblock': Duration(0),
            'maxirre': Duration(0),
            'delay': Duration(0),
            'pending_rest': Duration(0),
            'xturn': Duration(0),
            'sunday': 0,
            '7day': 0
        })

        # 2 Add all credits to find totals
        line_credits_list = []
        consecutive_days = ConsecutiveDays(line.duties[0].report.date(), 7)
        for duty in line.duties:
            credit_list = duty.compute_credits(self)
            if credit_list:
                line_credits_list.extend(credit_list)
                line._credits['block'] += duty._credits['block']
                line._credits['dh'] += duty._credits['dh']
                line._credits['daily'] += duty._credits['daily']
                line._credits['night'] += duty._credits['night']
                line._credits['xblock'] += duty._credits['xblock']
                line._credits['xduty'] += duty._credits['xduty']
                line._credits['maxirre'] += duty._credits['maxirre']
                line._credits['delay'] += duty._credits['delay']
                line._credits['pending_rest'] += duty._credits['pending_rest']
                line._credits['xturn'] += duty._credits['xturn']
                line._credits['sunday'] += duty._credits['sunday']
                consecutive_days.calculate(duty)

        # 3 How many 7day do we have?
        days7 = consecutive_days.dates
        line._credits['7day'] += len(days7)

        # 4 Assign the needed template to print credits
        line._credits['header'] = line_credits_header
        line._credits['template'] = line_credits_template

        return line_credits_list
Esempio n. 3
0
    def calculate_night_time(event):
        """
        Returns the nighttime flown in a given event, value is returned in seconds
        """

        BEGIN = event.begin.hour * 60 + event.begin.minute
        END = event.end.hour * 60 + event.end.minute
        NIGHTTIME_BEGIN = 22 * 60
        NIGHTTIME_END = 5 * 60
        MIDNIGHT = 24 * 60
        morninginter = [0, NIGHTTIME_END]
        nightinter = [NIGHTTIME_BEGIN, MIDNIGHT]

        if BEGIN > END:  # Event starts and ends in different days
            total = Creditator.overlapping(
                nightinter, [BEGIN, MIDNIGHT]) + Creditator.overlapping(
                    morninginter, [0, END])
        else:  # Event starts and ends in same day
            total = Creditator.overlapping(
                morninginter, [BEGIN, END]) + Creditator.overlapping(
                    nightinter, [BEGIN, END])

        return Duration(total)
Esempio n. 4
0
    def credits_from_duty_day(duty_day):
        """
        Returns
        """
        # 1. Init our _credits
        duty_day._credits = CreditsDict()
        duty_day._credits.update({
            'day': duty_day.begin.day,
            'routing': FormattedList([duty_day.origin]),
            'report': duty_day.report,
            'release': duty_day.release,
            'duty_type': 'regular',
            'event_names': FormattedList(['']),
            'daily': duty_day.duration,
            'block': Duration(0),
            'dh': Duration(0),
            'night': Duration(0),
            'xduty': Duration(0),
            'xblock': Duration(0),
            'maxirre': Duration(0),
            'delay': duty_day.delay,
            'pending_rest': Duration(0),
            'xturn': Duration(0),
            'sunday': 0
        })

        # 2. Calculate night, event_names and routing
        for event in duty_day.events:
            event.compute_credits()
            #DH flights don't account for night time
            if isinstance(event, Flight) and not event.dh:
                duty_day._credits['night'] += Creditator.calculate_night_time(
                    event)
            duty_day._credits['block'] += event._credits['block']
            duty_day._credits['dh'] += event._credits['dh']
            duty_day._credits['event_names'].append(event.name)
            duty_day._credits['routing'].append(event.route.destination)
        duty_day._credits[
            'total'] = duty_day._credits['block'] + duty_day._credits['dh']

        # 3. Calculate xturn:
        for turn in duty_day.turns:
            duty_day._credits['xturn'] += (turn - MAX_TURN_TIME)

        # 4. Classify duty
        Creditator.duty_day_classifier(duty_day)

        if duty_day._credits['duty_type'] == 'regular':
            duty_day._credits['xblock'] = duty_day._credits[
                'block'] - JORNADA_ORDINARIA_VUELO_REGULAR
            duty_day._credits['xduty'] = duty_day._credits[
                'daily'] - JORNADA_ORDINARIA_SERVICIO_REGULAR
            duty_day._credits['maxirre'] = duty_day._credits[
                'daily'] - MAXIMA_IRREBASABLE_SERVICIO_REGULAR
        elif duty_day._credits['duty_type'] == 'transoceanic':
            duty_day._credits['xblock'] = duty_day._credits[
                'block'] - JORNADA_ORDINARIA_VUELO_TRAN
            duty_day._credits['xduty'] = duty_day._credits[
                'daily'] - JORNADA_ORDINARIA_SERVICIO_TRAN
            duty_day._credits['maxirre'] = duty_day._credits[
                'daily'] - MAXIMA_IRREBASABLE_SERVICIO_TRAN
        elif duty_day._credits['duty_type'] == 'special trans':
            duty_day._credits['xblock'] = duty_day._credits[
                'block'] - JORNADA_ORDINARIA_VUELO_TRANSP
            duty_day._credits['xduty'] = duty_day._credits[
                'daily'] - JORNADA_ORDINARIA_SERVICIO_TRANSP
            duty_day._credits['maxirre'] = duty_day._credits[
                'daily'] - MAXIMA_IRREBASABLE_SERVICIO_TRANSP
            # If there is a maxirre, normal xduty time ends where maxirre starts
        elif duty_day._credits['duty_type'] == 'long haul':
            duty_day._credits['xblock'] = duty_day._credits[
                'block'] - JORNADA_ORDINARIA_VUELO_LARGO_ALCANCE
            duty_day._credits['xduty'] = duty_day._credits[
                'daily'] - JORNADA_ORDINARIA_SERVICIO_LARGO_ALCANCE
            duty_day._credits['maxirre'] = duty_day._credits[
                'daily'] - MAXIMA_ASIGNABLE_SERVICIO_LARGO_ALCANCE
            # If there is a maxirre, normal xduty time ends where maxirre starts
            if duty_day._credits['maxirre'] > Duration(0):
                duty_day._credits['xduty'] = Duration(5 * 60)

        # 5. If there is a maxirre, normal xduty time ends where maxirre starts
        if duty_day._credits['maxirre'] > Duration(0):
            duty_day._credits['xduty'] = Duration(5 * 60)

        # 6. How many sundays?
        duty_day._credits['sunday'] = duty_day.how_many_sundays()
        duty_day_release_time = Duration(duty_day.release.hour * 60 +
                                         duty_day.release.minute)
        duty_day_ending_weekday = duty_day.release.isoweekday()
        is_a_worked_day = duty_day_release_time > WORKED_DAY
        if duty_day_ending_weekday == 7 and not is_a_worked_day:
            duty_day._credits['sunday'] -= 1

        # 7. Assign the needed template to print credits
        duty_day._credits['header'] = duty_day_credits_header
        duty_day._credits['template'] = duty_day_credits_template
Esempio n. 5
0
    def credits_from_trip(self, trip):
        """Returns a list of all duty_day_credits_dict within the trip_match"""

        credits_list = []
        trip._credits = CreditsDict()
        # 1 Add all credits to find totals
        trip._credits['block'] = Duration(0)
        trip._credits['dh'] = Duration(0)
        trip._credits['daily'] = Duration(0)
        trip._credits['night'] = Duration(0)
        trip._credits['xblock'] = Duration(0)
        trip._credits['xduty'] = Duration(0)
        trip._credits['maxirre'] = Duration(0)
        trip._credits['delay'] = Duration(0)
        trip._credits['pending_rest'] = Duration(0)
        trip._credits['xturn'] = Duration(0)
        trip._credits['sunday'] = 0
        for duty_day in trip.duty_days:
            if duty_day.begin.month == self.month_scope:
                duty_day.compute_credits(self)
                trip._credits['block'] += duty_day._credits['block']
                trip._credits['dh'] += duty_day._credits['dh']
                trip._credits['daily'] += duty_day._credits['daily']
                trip._credits['night'] += duty_day._credits['night']
                trip._credits['xblock'] += duty_day._credits['xblock']
                trip._credits['xduty'] += duty_day._credits['xduty']
                trip._credits['maxirre'] += duty_day._credits['maxirre']
                trip._credits['delay'] += duty_day._credits['delay']
                trip._credits['xturn'] += duty_day._credits['xturn']
                trip._credits['sunday'] += duty_day._credits['sunday']
                credits_list.append(duty_day._credits)

        # 2. Calculate pending_rest between each duty day
        for rest, duty_day in zip(trip.rests, trip.duty_days):
            if (duty_day.begin.month
                    == self.month_scope) and rest < Duration(12 * 60):
                tempo = Creditator.calculate_pending_rest(rest)
                duty_day._credits['pending_rest'] = tempo
                trip._credits['pending_rest'] += duty_day._credits[
                    'pending_rest']

        # 3. How many sundays?
        trip._credits['sunday'] = trip.how_many_sundays()
        trip_release_time = Duration(duty_day.release.hour * 60 +
                                     duty_day.release.minute)
        trip_ending_weekday = duty_day.release.isoweekday()
        is_a_worked_day = trip_release_time > WORKED_DAY
        if trip_ending_weekday == 7 and not is_a_worked_day:
            trip._credits['sunday'] -= 1

        # 4 Assign the needed template to print credits
        trip._credits['header'] = trip_credits_header
        trip._credits['template'] = trip_credits_template

        return credits_list
Esempio n. 6
0
def test_as_timedelta():
    td = timedelta(minutes=30)
    d = Duration.from_timedelta(td)
    assert isinstance(d, Duration)
    assert td.total_seconds() == 30 * 60
Esempio n. 7
0
"""
Created on 23/06/2016

@author: Xico
"""
from datetime import timedelta

# TODO : Move all this constants into a configuration file, associated to method set_rules
from models.scheduleclasses import Flight
from models.timeclasses import Duration

TRANSOCEANIC = [
    'MAD', 'CDG', 'MXP', 'FCO', 'LHR', 'AMS', 'SVO', 'BCN', 'MUC', 'FRA',
    'NRT', 'ICN', 'PVG', 'PEK'
]
MINIMUM_BLOCK = Duration(13 * 60)
MINIMUM_DUTY = Duration(15 * 60)
WORKED_DAY = Duration(1 * 60 + 30)

# TABLA 1  Jornada continental
JORNADA_ORDINARIA_VUELO_REGULAR = Duration(7 * 60 + 30)
MAXIMA_IRREBASABLE_VUELO_REGULAR = Duration(10 * 60)
JORNADA_ORDINARIA_SERVICIO_REGULAR = Duration(9 * 60)
MAXIMA_IRREBASABLE_SERVICIO_REGULAR = Duration(12 * 60)

# TABLA 1 Jornada transoceanica
JORNADA_ORDINARIA_VUELO_TRAN = Duration(8 * 60)
MAXIMA_IRREBASABLE_VUELO_TRAN = Duration(13 * 60)
JORNADA_ORDINARIA_SERVICIO_TRAN = Duration(10 * 60)
MAXIMA_IRREBASABLE_SERVICIO_TRAN = Duration(15 * 60)
Esempio n. 8
0
 def test_duration_formatting_zero_hide(self):
     d = Duration(0)
     expected = 4 * ' '
     obtained = "{0:<4H}".format(d)
     assert obtained == expected
Esempio n. 9
0
 def test_duration_rep_method(self):
     d = Duration(23 * 60 + 30)
     expected = "Duration({})".format(23 * 60 + 30)
     obtained = d.__repr__()
     assert obtained == expected
Esempio n. 10
0
 def test_duration_formatting_no_colon(self):
     d = Duration(23 * 60 + 30)
     expected = "2330"
     obtained = "{0:<4}".format(d)
     assert expected == obtained
Esempio n. 11
0
 def test_duration_formatting_zero_show(self):
     d = Duration(0)
     expected = '0000'
     obtained = "{0:0<4}".format(d)
     assert obtained == expected
Esempio n. 12
0
 def test_duration_formatting_default(self):
     d = Duration(23 * 60 + 30)
     expected = "23:30"
     obtained = "{0:<5:}".format(d)
     assert expected == obtained
Esempio n. 13
0
 def test_init(self, minutes):
     duration = Duration(minutes)
     assert isinstance(duration, Duration)
     assert duration.minutes == minutes
Esempio n. 14
0
 def setUp(self):
     self.duration = Duration(minutes=40)
     self.td = timedelta(minutes=40)
Esempio n. 15
0
 def test_from_string(self):
     duration = Duration.from_string('0040')
     self.assertEqual(duration, self.duration)
Esempio n. 16
0
 def test_from_timedelta(self):
     duration = Duration.from_timedelta(self.td)
     self.assertEqual(self.duration, duration)