messageboard-2025-01-04-1440.py
01234567890123456789012345678901234567890123456789012345678901234567890123456789









364365366367368369370371372373374375376377378379380381382383384385386387  388389390391392393394395396397398399400401402403404405406407408409410 411412413414415416417418419420421422423424425426427428429430431432433434435436437 438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493 494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567








21702171217221732174217521762177217821792180218121822183218421852186218721882189 219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213








282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855  28562857285828592860286128622863286428652866286728682869287028712872287328742875








305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105











                            <----SKIPPED LINES---->




# www.adsbexchange.com/forum/threads/
# units-in-the-dump1090-json-file.630617/#post-639541
CLIMB_RATE_UNITS = 'fpm'
#speed units from tracker are knots, based on dump-1090/track.c
#https://github.com/SDRplay/dump1090/blob/master/track.c
SPEED_UNITS = 'kn'
DISTANCE_UNITS = 'ft'  # altitude

# For displaying histograms
# If a key is not present, how should it be displayed in histograms?
KEY_NOT_PRESENT_STRING = 'Unknown'
OTHER_STRING = 'Other' # What key strings should be listed last in sequence?
# What key strings should be listed last in sequence?
SORT_AT_END_STRINGS = [OTHER_STRING, KEY_NOT_PRESENT_STRING]
# What is the sorted sequence of keys for days of week?
DAYS_OF_WEEK = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']

# AIRCRAFT_LENGTH[''] =
AIRCRAFT_LENGTH = {} # in meters

AIRCRAFT_LENGTH['Airbus A220-100 (twin-jet)'] = 35
AIRCRAFT_LENGTH['Airbus A220-300 (twin-jet)'] = 38.71
AIRCRAFT_LENGTH['Airbus A300F4-600 (twin-jet)'] = 54.08
AIRCRAFT_LENGTH['Airbus A319 (twin-jet)'] = 33.84


AIRCRAFT_LENGTH['Airbus A320 (twin-jet)'] = 37.57
AIRCRAFT_LENGTH['Airbus A320 (jet bimotor)'] = 37.57
AIRCRAFT_LENGTH['Airbus A320neo (twin-jet)'] = 37.57
AIRCRAFT_LENGTH['Airbus A321 (twin-jet)'] = 44.51
AIRCRAFT_LENGTH['Airbus A321neo (twin-jet)'] = 44.51
AIRCRAFT_LENGTH['Airbus A330 (twin-jet)'] = 58.82  # assumed -200 or -300
AIRCRAFT_LENGTH['Airbus A330-200 (twin-jet)'] = 58.82
AIRCRAFT_LENGTH['Airbus A330-300 (twin-jet)'] = 63.67
AIRCRAFT_LENGTH['AIRBUS A-330-900 (twin-jet)'] = 63.66
AIRCRAFT_LENGTH['Airbus A330-900 (twin-jet)'] = 63.66
AIRCRAFT_LENGTH['Airbus A340-300 (quad-jet)'] = 63.69
AIRCRAFT_LENGTH['Airbus A350-1000 (twin-jet)'] = 73.79
AIRCRAFT_LENGTH['Airbus A350-900 (twin-jet)'] = 66.8
AIRCRAFT_LENGTH['Airbus A380-800 (quad-jet)'] = 72.72
AIRCRAFT_LENGTH['Antonov An-124 Ruslan (quad-jet)'] = 69.1
AIRCRAFT_LENGTH['Beechcraft Beechjet (twin-jet)'] = 14.76
AIRCRAFT_LENGTH['Beechcraft Bonanza (33) (piston-single)'] = 7.65
AIRCRAFT_LENGTH['Beechcraft Bonanza (36) (piston-single)'] = 8.38
AIRCRAFT_LENGTH['Beechcraft King Air 90 (twin-turboprop)'] = 10.82
AIRCRAFT_LENGTH['Beechcraft King Air F90 (twin-turboprop)'] = 12.14
AIRCRAFT_LENGTH['Beechcraft Premier 1 (twin-jet)'] = 14.02
AIRCRAFT_LENGTH['Beechcraft Super King Air 200 (twin-turboprop)'] = 13.31
AIRCRAFT_LENGTH['Beechcraft Super King Air 350 (twin-turboprop)'] = 14.22

AIRCRAFT_LENGTH['Bell 429 GlobalRanger (twin-turboshaft)'] = 12.70
AIRCRAFT_LENGTH['Boeing 737-400 (twin-jet)'] = 36.4
AIRCRAFT_LENGTH['Boeing 737-500 (twin-jet)'] = 31.0
AIRCRAFT_LENGTH['Boeing 737-700 (twin-jet)'] = 33.63
AIRCRAFT_LENGTH['Boeing 737-800 (twin-jet)'] = 39.47
AIRCRAFT_LENGTH['Boeing 737-900 (twin-jet)'] = 42.11
AIRCRAFT_LENGTH['Boeing 737-900 (jet bimotor)'] = 42.11
AIRCRAFT_LENGTH['Boeing 737 MAX 8 (twin-jet)'] = 39.47
AIRCRAFT_LENGTH['Boeing 737 MAX 9 (twin-jet)'] = 42.1
AIRCRAFT_LENGTH['Boeing 737 MAX 9 (twin-jet)'] = 42.1
AIRCRAFT_LENGTH['Boeing 747-100 (quad-jet)'] = 70.66
AIRCRAFT_LENGTH['Boeing 747-400 (quad-jet)'] = 70.66
AIRCRAFT_LENGTH['Boeing 747-8 (quad-jet)'] = 76.25
AIRCRAFT_LENGTH['Boeing 757-200 (twin-jet)'] = 47.3
AIRCRAFT_LENGTH['Boeing 757-300 (twin-jet)'] = 54.4
AIRCRAFT_LENGTH['Boeing 767-200 (twin-jet)'] = 48.51
AIRCRAFT_LENGTH['BOEING 767-300 (twin-jet)'] = 54.94
AIRCRAFT_LENGTH['Boeing 767-300 (twin-jet)'] = 54.94
AIRCRAFT_LENGTH['BOEING 767-400 (twin-jet)'] = 61.37
AIRCRAFT_LENGTH['Boeing 777 (twin-jet)'] = (63.73 + 73.86) / 2
AIRCRAFT_LENGTH['Boeing 777-200 (twin-jet)'] = 63.73
AIRCRAFT_LENGTH['BOEING 777-200ER (twin-jet)'] = 63.73
AIRCRAFT_LENGTH['BOEING 777-200LR (twin-jet)'] = 63.73
AIRCRAFT_LENGTH['Boeing 777-200LR/F (twin-jet)'] = 63.73
AIRCRAFT_LENGTH['Boeing 777-300 (twin-jet)'] = 33.4
AIRCRAFT_LENGTH['BOEING 777-300ER (jet bimotor)'] = 73.86
AIRCRAFT_LENGTH['BOEING 777-300ER (twin-jet)'] = 73.86

AIRCRAFT_LENGTH['Boeing 777-300ER (twin-jet)'] = 73.86
AIRCRAFT_LENGTH['Boeing 787-10 (twin-jet)'] = 68.28
AIRCRAFT_LENGTH['Boeing 787-8 (twin-jet)'] = 56.72
AIRCRAFT_LENGTH['Boeing 787-9 (twin-jet)'] = 62.81
AIRCRAFT_LENGTH['Boeing 787-9 Dreamliner (twin-jet)'] = 62.81
AIRCRAFT_LENGTH['BOEING 787-10 Dreamliner (twin-jet)'] = 68.28
AIRCRAFT_LENGTH['BOEING BBJ (747-8) (quad-jet)'] = 76.25
AIRCRAFT_LENGTH['BOEING BBJ (777-200LR) (twin-jet)'] = 63.73
AIRCRAFT_LENGTH['BOEING BBJ (777-300ER) (twin-jet)'] = 73.86
AIRCRAFT_LENGTH['BOEING BBJ3 (twin-jet)'] = 42.11
AIRCRAFT_LENGTH['Boeing Dreamliner (Srs.8) (twin-jet)'] = 56.72
AIRCRAFT_LENGTH['BOEING Dreamliner (Srs.9) (twin-jet)'] = 62.81
AIRCRAFT_LENGTH['Boeing MD-11 (tri-jet)'] = (61.2 + 61.6) / 2
AIRCRAFT_LENGTH['BOMBARDIER BD-700 Global 7500 (twin-jet)'] = 33.88
AIRCRAFT_LENGTH['Bombardier Challenger 300 (twin-jet)'] = 20.92
AIRCRAFT_LENGTH['Bombardier Global 5000 (twin-jet)'] = 29.5
AIRCRAFT_LENGTH['Bombardier Global Express (twin-jet)'] = (29.5 + 30.3) / 2
AIRCRAFT_LENGTH['Bombardier Learjet 75 (twin-jet)'] = 17.7
AIRCRAFT_LENGTH['Canadair Challenger (twin-jet)'] = 20.9
AIRCRAFT_LENGTH['Canadair Challenger 350 (twin-jet)'] = 20.9
AIRCRAFT_LENGTH['Canadair Regional Jet CRJ-200 (twin-jet)'] = 26.77
AIRCRAFT_LENGTH['Canadair Regional Jet CRJ-700 (twin-jet)'] = 32.3
AIRCRAFT_LENGTH['Canadair Regional Jet CRJ-900 (twin-jet)'] = 36.2
AIRCRAFT_LENGTH['Cessna 152 (piston-single)'] = 7.34
AIRCRAFT_LENGTH['Cessna Caravan (single-turboprop)'] = 11.46
AIRCRAFT_LENGTH['Cessna Citation 1SP (twin-jet)'] = 13.26
AIRCRAFT_LENGTH['Cessna Citation Bravo (twin-jet)'] = 14.54
AIRCRAFT_LENGTH['Cessna Citation CJ1 (twin-jet)'] = 12.98
AIRCRAFT_LENGTH['Cessna Citation CJ2+ (twin-jet)'] = 14.53
AIRCRAFT_LENGTH['Cessna Citation CJ3 (twin-jet)'] = 15.59
AIRCRAFT_LENGTH['Cessna Citation CJ4 (twin-jet)'] = 16.26
AIRCRAFT_LENGTH['Cessna Citation M2 (twin-jet)'] = 12.98
AIRCRAFT_LENGTH['Cessna Citation Excel/XLS (twin-jet)'] = 16.0
AIRCRAFT_LENGTH['Cessna Citation II (twin-jet)'] = 14.54
AIRCRAFT_LENGTH['Cessna Citation Latitude (twin-jet)'] = 18.97
AIRCRAFT_LENGTH['Cessna Citation Longitude (twin-jet)'] = 22.3
AIRCRAFT_LENGTH['Cessna Citation Mustang (twin-jet)'] = 12.37
AIRCRAFT_LENGTH['Cessna Citation Sovereign (twin-jet)'] = 19.35
AIRCRAFT_LENGTH['Cessna Citation V (twin-jet)'] = 14.91
AIRCRAFT_LENGTH['Cessna Citation X (twin-jet)'] = 22.04
AIRCRAFT_LENGTH['Cessna Conquest 2 (twin-turboprop)'] = 11.89
AIRCRAFT_LENGTH['Cessna Skyhawk (piston-single)'] = 8.28
AIRCRAFT_LENGTH['Cessna Skylane (piston-single)'] = 8.84
AIRCRAFT_LENGTH['CESSNA T182 Turbo Skylane (piston-single)'] = 8.84
AIRCRAFT_LENGTH['Cessna T206 Turbo Stationair (piston-single)'] = 8.61
AIRCRAFT_LENGTH['Cessna 310 (twin-piston)'] = 8.23
AIRCRAFT_LENGTH['Cessna 421 (twin-piston)'] = 11.09
AIRCRAFT_LENGTH['Cirrus SR-20 (piston-single)'] = 7.92
AIRCRAFT_LENGTH['Cirrus SR-22 (piston-single)'] = 7.92
AIRCRAFT_LENGTH['Cirrus SR22 Turbo (piston-single)'] = 7.92
AIRCRAFT_LENGTH['Cirrus Vision SF50 (single-jet)'] = 9.42
AIRCRAFT_LENGTH['Daher-Socata TBM-900 (single-turboprop)'] = 10.72
AIRCRAFT_LENGTH['Dassault Falcon 50 (tri-jet)'] = 18.52
AIRCRAFT_LENGTH['Dassault Falcon 7X (tri-jet)'] = 23.38
AIRCRAFT_LENGTH['Dassault Falcon 2000 (twin-jet)'] = 20.23
AIRCRAFT_LENGTH['Dassault Falcon 900 (tri-jet)'] = 20.21

AIRCRAFT_LENGTH['Diamond Star (piston-single)'] = 8.1
AIRCRAFT_LENGTH['Embraer 170/175 (twin-jet)'] = (29.90 + 31.68) / 2
AIRCRAFT_LENGTH['EMBRAER 175 (long wing) (twin-jet)'] = 31.68
AIRCRAFT_LENGTH['EMBRAER 195 (twin-jet)'] = 38.66
AIRCRAFT_LENGTH['Embraer ERJ-135 (twin-jet)'] = 26.33
AIRCRAFT_LENGTH['Embraer ERJ-145 (twin-jet)'] = 29.87
AIRCRAFT_LENGTH['Embraer ERJ 175 (twin-jet)'] = 31.68
AIRCRAFT_LENGTH['Embraer ERJ 190 (twin-jet)'] = 36.25
AIRCRAFT_LENGTH['Embraer ERJ-190 (twin-jet)'] = 36.25
AIRCRAFT_LENGTH['Embraer Legacy 450 (twin-jet)'] = 19.69
AIRCRAFT_LENGTH['Embraer Legacy 550 (twin-jet)'] = 20.74
AIRCRAFT_LENGTH['Embraer Legacy 600/650 (twin-jet)'] = 26.33
AIRCRAFT_LENGTH['Embraer Phenom 100 (twin-jet)'] = 12.82
AIRCRAFT_LENGTH['Embraer Phenom 300 (twin-jet)'] = 15.9
AIRCRAFT_LENGTH['Epic Aircraft LT (single-turboprop)'] = 10.92
AIRCRAFT_LENGTH['Eurocopter EC-635 (twin-turboshaft)'] = 10.21
AIRCRAFT_LENGTH['Fairchild Dornier 328JET (twin-jet)'] = 21.11
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream 3 (twin-jet)'] = 25.32
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream G450 (twin-jet)'] = 27.23
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream G550 (twin-jet)'] = 29.39
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream G650 (twin-jet)'] = 30.41
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream G-7 (twin-jet)'] = 33.48
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream IV (twin-jet)'] = 26.92
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream V (twin-jet)'] = 29.4
AIRCRAFT_LENGTH['GULFSTREAM AEROSPACE G-7 Gulfstream G600 (twin-jet)'] = 29.29
AIRCRAFT_LENGTH['Hawker Beechcraft 4000 (twin-jet)'] = 21.08
AIRCRAFT_LENGTH['Honda HondaJet (twin-jet)'] = 12.99
AIRCRAFT_LENGTH['IAI Gulfstream G100 (twin-jet)'] = 16.94
AIRCRAFT_LENGTH['IAI Gulfstream G150 (twin-jet)'] = 16.94
AIRCRAFT_LENGTH['IAI Gulfstream G200 (twin-jet)'] = 18.97
AIRCRAFT_LENGTH['IAI Gulfstream G280 (twin-jet)'] = 20.3
AIRCRAFT_LENGTH['Learjet 31 (twin-jet)'] = 14.83
AIRCRAFT_LENGTH['Learjet 35 (twin-jet)'] = 14.83
AIRCRAFT_LENGTH['Learjet 40 (twin-jet)'] = 16.92
AIRCRAFT_LENGTH['Learjet 45 (twin-jet)'] = 17.68
AIRCRAFT_LENGTH['Learjet 55 (twin-jet)'] = 16.79
AIRCRAFT_LENGTH['Learjet 60 (twin-jet)'] = 17.88
AIRCRAFT_LENGTH['McDonnell Douglas MD-11 (tri-jet)'] = 61.6
AIRCRAFT_LENGTH['McDonnell Douglas MD-83 (twin-jet)'] = 45.06
AIRCRAFT_LENGTH['Mooney M-20 (piston-single)'] = 8.13
AIRCRAFT_LENGTH['North American Navion (piston-single)'] = 8.38
AIRCRAFT_LENGTH['North American Sabreliner (twin-jet)'] = 13.41
AIRCRAFT_LENGTH['Piaggio P.180 Avanti (twin-turboprop)'] = 47.3
AIRCRAFT_LENGTH['Pilatus PC-12 (single-turboprop)'] = 14.4
AIRCRAFT_LENGTH['Pilatus PC-24 (twin-jet)'] = 16.85
AIRCRAFT_LENGTH['Piper Cherokee (piston-single)'] = 7.10
AIRCRAFT_LENGTH['Piper Malibu Meridian (single-turboprop)'] = 9.02
AIRCRAFT_LENGTH['Piper Navajo (twin-piston)'] = 9.94
AIRCRAFT_LENGTH['Raytheon Hawker 800 (twin-jet)'] = 15.60
AIRCRAFT_LENGTH['Raytheon Hawker 800XP (twin-jet)'] = 15.60
AIRCRAFT_LENGTH['Raytheon Hawker 850XP (twin-jet)'] = 15.60
AIRCRAFT_LENGTH['Raytheon Hawker 900XP (twin-jet)'] = 15.60
AIRCRAFT_LENGTH['Raytheon Hawker 1000 (twin-jet)'] = 16.08
AIRCRAFT_LENGTH['Rockwell Turbo Commander 690 (twin-turboprop)'] = 11.22
for mixed_case_plane in list(AIRCRAFT_LENGTH.keys()):  # pylint: disable=C0201
  AIRCRAFT_LENGTH[mixed_case_plane.upper()] = AIRCRAFT_LENGTH[mixed_case_plane]
  AIRCRAFT_LENGTH.pop(mixed_case_plane)

# pylint: disable=line-too-long
SHORTER_AIRCRAFT_NAME = {}
SHORTER_AIRCRAFT_NAME['Boeing 787-9 Dreamliner (twin-jet)'] = 'Boeing 787-9 (twin-jet)'
SHORTER_AIRCRAFT_NAME['BOEING 787-10 Dreamliner (twin-jet)'] = 'Boeing 787-10 (twin-jet)'
SHORTER_AIRCRAFT_NAME['Canadair Regional Jet CRJ-200 (twin-jet)'] = 'Canadair CRJ-200 (twin-jet)'
SHORTER_AIRCRAFT_NAME['Canadair Regional Jet CRJ-700 (twin-jet)'] = 'Canadair CRJ-700 (twin-jet)'
SHORTER_AIRCRAFT_NAME['Canadair Regional Jet CRJ-900 (twin-jet)'] = 'Canadair CRJ-900 (twin-jet)'
SHORTER_AIRCRAFT_NAME['Gulfstream Aerospace Gulfstream 3 (twin-jet)'] = 'Gulfstream 3 (twin-jet)'
SHORTER_AIRCRAFT_NAME['Gulfstream Aerospace Gulfstream G450 (twin-jet)'] = 'Gulfstream G450 (twin-jet)'
SHORTER_AIRCRAFT_NAME['Gulfstream Aerospace Gulfstream G550 (twin-jet)'] = 'Gulfstream G550 (twin-jet)'
SHORTER_AIRCRAFT_NAME['Gulfstream Aerospace Gulfstream IV (twin-jet)'] = 'Gulfstream IV (twin-jet)'
SHORTER_AIRCRAFT_NAME['Gulfstream Aerospace Gulfstream V (twin-jet)'] = 'Gulfstream V (twin-jet)'
SHORTER_AIRCRAFT_NAME['GULFSTREAM AEROSPACE G-7 Gulfstream G600 (twin-jet)'] = 'Gulfstream G600 (twin-jet)'
SHORTER_AIRCRAFT_NAME['Gulfstream Aerospace Gulfstream G-7 (twin-jet)'] = 'Gulfstream G-7 (twin-jet)'
# pylint: enable=line-too-long





                            <----SKIPPED LINES---->





  fa_flight_number = list(parsed_json['flights'].keys())[0]
  parsed_flight_details = parsed_json['flights'][fa_flight_number]
  flight['fa_flight_number'] = fa_flight_number

  origin = parsed_flight_details.get('origin')
  if origin:
    flight['origin_friendly'] = origin.get('friendlyLocation')
    flight['origin_iata'] = origin.get('iata')

  destination = parsed_flight_details.get('destination')
  if destination:
    flight['destination_friendly'] = destination.get('friendlyLocation')
    flight['destination_iata'] = destination.get('iata')

  aircraft_type = parsed_flight_details.get('aircraft')
  if aircraft_type:
    flight['aircraft_type_code'] = aircraft_type.get('type')
    flight['aircraft_type_friendly'] = aircraft_type.get('friendlyType')
    if flight['aircraft_type_friendly']:

      flight['aircraft_type_friendly'] = flight[
          'aircraft_type_friendly'].replace('biréacteur', 'twin-jet')
      flight['aircraft_type_friendly'] = flight[
          'aircraft_type_friendly'].replace('zweimotoriger Jet', 'twin-jet')
    flight['owner_location'] = Unidecode(aircraft_type.get('ownerLocation'))
    flight['owner'] = Unidecode(aircraft_type.get('owner'))
    flight['tail'] = Unidecode(aircraft_type.get('tail'))

  takeoff_time = parsed_flight_details.get('takeoffTimes')
  if takeoff_time:
    flight['scheduled_takeofftime'] = takeoff_time.get('scheduled')
    flight['actual_takeoff_time'] = takeoff_time.get('actual')

  gate_departure_time = parsed_flight_details.get('gateDepartureTimes')
  if gate_departure_time:
    flight['scheduled_departure_time'] = gate_departure_time.get('scheduled')
    flight['actual_departure_time'] = gate_departure_time.get('actual')

  gate_arrival_time = parsed_flight_details.get('gateArrivalTimes')
  if gate_arrival_time:
    flight['scheduled_arrival_time'] = gate_arrival_time.get('scheduled')
    flight['estimated_arrival_time'] = gate_arrival_time.get('estimated')

  landing_time = parsed_flight_details.get('landingTimes')




                            <----SKIPPED LINES---->




    line_elements.append('Alt:%d%s' % (altitude, DISTANCE_UNITS))
  if vert_rate:
    line_elements.append('%+d%s' % (vert_rate, CLIMB_RATE_UNITS))
  if line_elements:
    lines.append(EvenlySpace(line_elements))

  return lines


def EvenlySpace(l):
  """Converts list to string with equal space between each element in list."""
  if not l:
    return ''
  if len(l) == 1:
    return l[0]
  extra_space = SPLITFLAP_CHARS_PER_LINE - sum([len(str(s)) for s in l])
  last_gap = round(extra_space / (len(l) - 1))
  return EvenlySpace([*l[:-2], str(l[-2]) + ' '*last_gap + str(l[-1])])


def RemoveParentheticals(s):
  """Removes all instances of () and the text contained within - from string."""
  if not s:
    return s
  if '(' in s and ')' in s:
    open_paren = s.find('(')
    close_paren = s.find(')')
  else:
    return s
  if close_paren < open_paren:
    return s
  s = s.replace(s[open_paren:close_paren+1], '').strip().replace('  ', ' ')
  return RemoveParentheticals(s)




def ShorterPlaneName(s):
  """Replaces full plane name with a shorter name, if it exists."""
  return SHORTER_AIRCRAFT_NAME.get(s, s)


def Ordinal(n):
  """Converts integer n to an ordinal string - i.e.: 2 -> 2nd; 5 -> 5th."""
  return '%d%s' % (n, 'tsnrhtdd'[(math.floor(n/10)%10 != 1)*(n%10 < 4)*n%10::4])


def Screenify(lines, splitflap):
  """Transforms a list of lines to a single text string for display / print.

  Given a list of lines that is a fully-formed message to send to the splitflap
  display, this function transforms the list of strings to a single string that
  is an easier-to-read and more faithful representation of how the message will
  be displayed. The transformations are to add blank lines to the message to
  make it consistent number of lines, and to add border to the sides & top /




                            <----SKIPPED LINES---->




    this_aircraft_bigger = False
    last_aircraft_bigger = False
    if (likely_same_commercial_flight and
        this_aircraft_length > last_aircraft_length * (
            1 + percent_size_difference)):
      this_aircraft_bigger = True
      comparative_text = 'larger'
    elif (likely_same_commercial_flight and
          last_aircraft_length > this_aircraft_length * (
              1 + percent_size_difference)):
      last_aircraft_bigger = True
      comparative_text = 'smaller'

    last_flight_time_string = DisplayTime(last_flight, '%b %-d')
    if this_aircraft and last_aircraft:
      if this_aircraft_bigger or last_aircraft_bigger:
        message = ('%s used a %s plane today compared with last, on %s '
                   '(%s @ %dft vs. %s @ %dft)' % (
                       this_flight_number, comparative_text,
                       last_flight_time_string,
                       RemoveParentheticals(this_aircraft),
                       this_aircraft_length*FEET_IN_METER,
                       RemoveParentheticals(last_aircraft),
                       last_aircraft_length*FEET_IN_METER))
      elif last_aircraft and this_aircraft and last_aircraft != this_aircraft:
        message = (
            '%s used a different aircraft today compared'
            ' with last, on %s (%s vs. %s)' % (
                this_flight_number, last_flight_time_string,
                RemoveParentheticals(ShorterPlaneName(this_aircraft)),
                RemoveParentheticals(ShorterPlaneName(last_aircraft))))

  return message


def FlightInsightNthFlight(flights, hours=1, min_multiple_flights=2):
  """Generates string about seeing frequent flights to the same dest.

  Generates text of the following form for the "focus" flight in the data.
  - ASA1337 was the 4th flight to PHX in the last 53 minutes, served by Alaska
    Airlines, American Airlines, Southwest and United
  - SWA3102 was the 2nd flight to SAN in the last 25 minutes, both with
    Southwest

  Args:
    flights: the list of the raw data from which the insights will be generated,
      where the flights are listed in order of observation - i.e.: flights[0]
      was the earliest seen, and flights[-1] is the most recent flight for
      which we are attempting to generate an insight.
    hours: the time horizon over which to look for flights with the same
      destination.




                            <----SKIPPED LINES---->





01234567890123456789012345678901234567890123456789012345678901234567890123456789









364365366367368369370371372373374375376377378379380381382383384385386387388389390391 392 393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436 437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569








2172217321742175217621772178217921802181218221832184218521862187218821892190219121922193   21942195219621972198219922002201220222032204220522062207220822092210221122122213








2823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877








305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107











                            <----SKIPPED LINES---->




# www.adsbexchange.com/forum/threads/
# units-in-the-dump1090-json-file.630617/#post-639541
CLIMB_RATE_UNITS = 'fpm'
#speed units from tracker are knots, based on dump-1090/track.c
#https://github.com/SDRplay/dump1090/blob/master/track.c
SPEED_UNITS = 'kn'
DISTANCE_UNITS = 'ft'  # altitude

# For displaying histograms
# If a key is not present, how should it be displayed in histograms?
KEY_NOT_PRESENT_STRING = 'Unknown'
OTHER_STRING = 'Other' # What key strings should be listed last in sequence?
# What key strings should be listed last in sequence?
SORT_AT_END_STRINGS = [OTHER_STRING, KEY_NOT_PRESENT_STRING]
# What is the sorted sequence of keys for days of week?
DAYS_OF_WEEK = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']

# AIRCRAFT_LENGTH[''] =
AIRCRAFT_LENGTH = {} # in meters

AIRCRAFT_LENGTH['Airbus A220-100'] = 35
AIRCRAFT_LENGTH['Airbus A220-300'] = 38.71
AIRCRAFT_LENGTH['Airbus A300F4-600'] = 54.08
AIRCRAFT_LENGTH['Airbus A319'] = 33.84
AIRCRAFT_LENGTH['Airbus A320'] = 37.57
AIRCRAFT_LENGTH['Airbus A320'] = 37.57
AIRCRAFT_LENGTH['Airbus A320neo'] = 37.57
AIRCRAFT_LENGTH['Airbus A321'] = 44.51

AIRCRAFT_LENGTH['Airbus A321neo'] = 44.51

AIRCRAFT_LENGTH['Airbus A330'] = 58.82  # assumed -200 or -300
AIRCRAFT_LENGTH['Airbus A330-200'] = 58.82
AIRCRAFT_LENGTH['Airbus A330-300'] = 63.67
AIRCRAFT_LENGTH['AIRBUS A-330-900'] = 63.66
AIRCRAFT_LENGTH['Airbus A330-900'] = 63.66
AIRCRAFT_LENGTH['Airbus A340-300'] = 63.69
AIRCRAFT_LENGTH['Airbus A350-1000'] = 73.79
AIRCRAFT_LENGTH['Airbus A350-900'] = 66.8
AIRCRAFT_LENGTH['Airbus A380-800'] = 72.72
AIRCRAFT_LENGTH['Antonov An-124 Ruslan'] = 69.1
AIRCRAFT_LENGTH['Beechcraft Beechjet'] = 14.76
AIRCRAFT_LENGTH['Beechcraft Bonanza (33)'] = 7.65
AIRCRAFT_LENGTH['Beechcraft Bonanza (36)'] = 8.38
AIRCRAFT_LENGTH['Beechcraft King Air 90'] = 10.82
AIRCRAFT_LENGTH['Beechcraft King Air F90'] = 12.14
AIRCRAFT_LENGTH['Beechcraft Premier 1'] = 14.02
AIRCRAFT_LENGTH['Beechcraft Super King Air 200'] = 13.31
AIRCRAFT_LENGTH['Beechcraft Super King Air 350'] = 14.22
AIRCRAFT_LENGTH['Bell JetRanger'] = 9.83  # helicopter
AIRCRAFT_LENGTH['Bell 429 GlobalRanger'] = 12.70  # helicopter
AIRCRAFT_LENGTH['Boeing 737-400'] = 36.4
AIRCRAFT_LENGTH['Boeing 737-500'] = 31.0
AIRCRAFT_LENGTH['Boeing 737-700'] = 33.63
AIRCRAFT_LENGTH['Boeing 737-800'] = 39.47
AIRCRAFT_LENGTH['Boeing 737-900'] = 42.11
AIRCRAFT_LENGTH['Boeing 737-900'] = 42.11
AIRCRAFT_LENGTH['Boeing 737 MAX 8'] = 39.47
AIRCRAFT_LENGTH['Boeing 737 MAX 9'] = 42.1
AIRCRAFT_LENGTH['Boeing 737 MAX 9'] = 42.1
AIRCRAFT_LENGTH['Boeing 747-100'] = 70.66
AIRCRAFT_LENGTH['Boeing 747-400'] = 70.66
AIRCRAFT_LENGTH['Boeing 747-8'] = 76.25
AIRCRAFT_LENGTH['Boeing 757-200'] = 47.3
AIRCRAFT_LENGTH['Boeing 757-300'] = 54.4
AIRCRAFT_LENGTH['Boeing 767-200'] = 48.51
AIRCRAFT_LENGTH['BOEING 767-300'] = 54.94
AIRCRAFT_LENGTH['Boeing 767-300'] = 54.94
AIRCRAFT_LENGTH['BOEING 767-400'] = 61.37
AIRCRAFT_LENGTH['Boeing 777'] = (63.73 + 73.86) / 2
AIRCRAFT_LENGTH['Boeing 777-200'] = 63.73
AIRCRAFT_LENGTH['BOEING 777-200ER'] = 63.73
AIRCRAFT_LENGTH['BOEING 777-200LR'] = 63.73
AIRCRAFT_LENGTH['Boeing 777-200LR/F'] = 63.73
AIRCRAFT_LENGTH['Boeing 777-300'] = 33.4

AIRCRAFT_LENGTH['BOEING 777-300ER'] = 73.86
AIRCRAFT_LENGTH['BOEING 777-300ER'] = 73.86
AIRCRAFT_LENGTH['Boeing 777-300ER'] = 73.86
AIRCRAFT_LENGTH['Boeing 787-10'] = 68.28
AIRCRAFT_LENGTH['Boeing 787-8'] = 56.72
AIRCRAFT_LENGTH['Boeing 787-9'] = 62.81
AIRCRAFT_LENGTH['Boeing 787-9 Dreamliner'] = 62.81
AIRCRAFT_LENGTH['BOEING 787-10 Dreamliner'] = 68.28
AIRCRAFT_LENGTH['BOEING BBJ (747-8)'] = 76.25
AIRCRAFT_LENGTH['BOEING BBJ (777-200LR)'] = 63.73
AIRCRAFT_LENGTH['BOEING BBJ (777-300ER)'] = 73.86
AIRCRAFT_LENGTH['BOEING BBJ3'] = 42.11
AIRCRAFT_LENGTH['Boeing Dreamliner (Srs.8)'] = 56.72
AIRCRAFT_LENGTH['BOEING Dreamliner (Srs.9)'] = 62.81
AIRCRAFT_LENGTH['Boeing MD-11'] = (61.2 + 61.6) / 2
AIRCRAFT_LENGTH['BOMBARDIER BD-700 Global 7500'] = 33.88
AIRCRAFT_LENGTH['Bombardier Challenger 300'] = 20.92
AIRCRAFT_LENGTH['Bombardier Global 5000'] = 29.5
AIRCRAFT_LENGTH['Bombardier Global Express'] = (29.5 + 30.3) / 2
AIRCRAFT_LENGTH['Bombardier Learjet 75'] = 17.7
AIRCRAFT_LENGTH['Canadair Challenger'] = 20.9
AIRCRAFT_LENGTH['Canadair Challenger 350'] = 20.9
AIRCRAFT_LENGTH['Canadair Regional Jet CRJ-200'] = 26.77
AIRCRAFT_LENGTH['Canadair Regional Jet CRJ-700'] = 32.3
AIRCRAFT_LENGTH['Canadair Regional Jet CRJ-900'] = 36.2
AIRCRAFT_LENGTH['Cessna 152'] = 7.34
AIRCRAFT_LENGTH['Cessna Caravan'] = 11.46
AIRCRAFT_LENGTH['Cessna Citation 1SP'] = 13.26
AIRCRAFT_LENGTH['Cessna Citation Bravo'] = 14.54
AIRCRAFT_LENGTH['Cessna Citation CJ1'] = 12.98
AIRCRAFT_LENGTH['Cessna Citation CJ2+'] = 14.53
AIRCRAFT_LENGTH['Cessna Citation CJ3'] = 15.59
AIRCRAFT_LENGTH['Cessna Citation CJ4'] = 16.26
AIRCRAFT_LENGTH['Cessna Citation M2'] = 12.98
AIRCRAFT_LENGTH['Cessna Citation Excel/XLS'] = 16.0
AIRCRAFT_LENGTH['Cessna Citation II'] = 14.54
AIRCRAFT_LENGTH['Cessna Citation Latitude'] = 18.97
AIRCRAFT_LENGTH['Cessna Citation Longitude'] = 22.3
AIRCRAFT_LENGTH['Cessna Citation Mustang'] = 12.37
AIRCRAFT_LENGTH['Cessna Citation Sovereign'] = 19.35
AIRCRAFT_LENGTH['Cessna Citation V'] = 14.91
AIRCRAFT_LENGTH['Cessna Citation X'] = 22.04
AIRCRAFT_LENGTH['Cessna Conquest 2'] = 11.89
AIRCRAFT_LENGTH['Cessna Skyhawk'] = 8.28
AIRCRAFT_LENGTH['Cessna Skylane'] = 8.84
AIRCRAFT_LENGTH['CESSNA T182 Turbo Skylane'] = 8.84
AIRCRAFT_LENGTH['Cessna T206 Turbo Stationair'] = 8.61
AIRCRAFT_LENGTH['Cessna 310 (twin-piston)'] = 8.23
AIRCRAFT_LENGTH['Cessna 421 (twin-piston)'] = 11.09
AIRCRAFT_LENGTH['Cirrus SR-20'] = 7.92
AIRCRAFT_LENGTH['Cirrus SR-22'] = 7.92
AIRCRAFT_LENGTH['Cirrus SR22 Turbo'] = 7.92
AIRCRAFT_LENGTH['Cirrus Vision SF50 (single-jet)'] = 9.42
AIRCRAFT_LENGTH['Daher-Socata TBM-900'] = 10.72
AIRCRAFT_LENGTH['Dassault Falcon 50'] = 18.52
AIRCRAFT_LENGTH['Dassault Falcon 7X'] = 23.38
AIRCRAFT_LENGTH['Dassault Falcon 2000'] = 20.23
AIRCRAFT_LENGTH['Dassault Falcon 900'] = 20.21
AIRCRAFT_LENGTH['de Havilland Dash 8-400'] = 32.8
AIRCRAFT_LENGTH['Diamond Star'] = 8.1
AIRCRAFT_LENGTH['Embraer 170/175'] = (29.90 + 31.68) / 2
AIRCRAFT_LENGTH['EMBRAER 175 (long wing)'] = 31.68
AIRCRAFT_LENGTH['EMBRAER 195'] = 38.66
AIRCRAFT_LENGTH['Embraer ERJ-135'] = 26.33
AIRCRAFT_LENGTH['Embraer ERJ-145'] = 29.87
AIRCRAFT_LENGTH['Embraer ERJ 175'] = 31.68
AIRCRAFT_LENGTH['Embraer ERJ 190'] = 36.25
AIRCRAFT_LENGTH['Embraer ERJ-190'] = 36.25
AIRCRAFT_LENGTH['Embraer Legacy 450'] = 19.69
AIRCRAFT_LENGTH['Embraer Legacy 550'] = 20.74
AIRCRAFT_LENGTH['Embraer Legacy 600/650'] = 26.33
AIRCRAFT_LENGTH['Embraer Phenom 100'] = 12.82
AIRCRAFT_LENGTH['Embraer Phenom 300'] = 15.9
AIRCRAFT_LENGTH['Epic Aircraft LT'] = 10.92
AIRCRAFT_LENGTH['Eurocopter EC-635'] = 10.21
AIRCRAFT_LENGTH['Fairchild Dornier 328JET'] = 21.11
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream 3'] = 25.32
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream G450'] = 27.23
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream G550'] = 29.39
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream G650'] = 30.41
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream G-7'] = 33.48
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream IV'] = 26.92
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream V'] = 29.4
AIRCRAFT_LENGTH['GULFSTREAM AEROSPACE G-7 Gulfstream G600'] = 29.29
AIRCRAFT_LENGTH['Hawker Beechcraft 4000'] = 21.08
AIRCRAFT_LENGTH['Honda HondaJet'] = 12.99
AIRCRAFT_LENGTH['IAI Gulfstream G100'] = 16.94
AIRCRAFT_LENGTH['IAI Gulfstream G150'] = 16.94
AIRCRAFT_LENGTH['IAI Gulfstream G200'] = 18.97
AIRCRAFT_LENGTH['IAI Gulfstream G280'] = 20.3
AIRCRAFT_LENGTH['Learjet 31'] = 14.83
AIRCRAFT_LENGTH['Learjet 35'] = 14.83
AIRCRAFT_LENGTH['Learjet 40'] = 16.92
AIRCRAFT_LENGTH['Learjet 45'] = 17.68
AIRCRAFT_LENGTH['Learjet 55'] = 16.79
AIRCRAFT_LENGTH['Learjet 60'] = 17.88
AIRCRAFT_LENGTH['McDonnell Douglas MD-11'] = 61.6
AIRCRAFT_LENGTH['McDonnell Douglas MD-83'] = 45.06
AIRCRAFT_LENGTH['Mooney M-20'] = 8.13
AIRCRAFT_LENGTH['North American Navion'] = 8.38
AIRCRAFT_LENGTH['North American Sabreliner'] = 13.41
AIRCRAFT_LENGTH['Piaggio P.180 Avanti'] = 47.3
AIRCRAFT_LENGTH['Pilatus PC-12'] = 14.4
AIRCRAFT_LENGTH['Pilatus PC-24'] = 16.85
AIRCRAFT_LENGTH['Piper Cherokee'] = 7.10
AIRCRAFT_LENGTH['Piper Malibu Meridian'] = 9.02
AIRCRAFT_LENGTH['Piper Navajo (twin-piston)'] = 9.94
AIRCRAFT_LENGTH['Raytheon Hawker 800'] = 15.60
AIRCRAFT_LENGTH['Raytheon Hawker 800XP'] = 15.60
AIRCRAFT_LENGTH['Raytheon Hawker 850XP'] = 15.60
AIRCRAFT_LENGTH['Raytheon Hawker 900XP'] = 15.60
AIRCRAFT_LENGTH['Raytheon Hawker 1000'] = 16.08
AIRCRAFT_LENGTH['Rockwell Turbo Commander 690'] = 11.22
for mixed_case_plane in list(AIRCRAFT_LENGTH.keys()):  # pylint: disable=C0201
  AIRCRAFT_LENGTH[mixed_case_plane.upper()] = AIRCRAFT_LENGTH[mixed_case_plane]
  AIRCRAFT_LENGTH.pop(mixed_case_plane)

# pylint: disable=line-too-long
SHORTER_AIRCRAFT_NAME = {}
SHORTER_AIRCRAFT_NAME['Boeing 787-9 Dreamliner (twin-jet)'] = 'Boeing 787-9 (twin-jet)'
SHORTER_AIRCRAFT_NAME['BOEING 787-10 Dreamliner (twin-jet)'] = 'Boeing 787-10 (twin-jet)'
SHORTER_AIRCRAFT_NAME['Canadair Regional Jet CRJ-200 (twin-jet)'] = 'Canadair CRJ-200 (twin-jet)'
SHORTER_AIRCRAFT_NAME['Canadair Regional Jet CRJ-700 (twin-jet)'] = 'Canadair CRJ-700 (twin-jet)'
SHORTER_AIRCRAFT_NAME['Canadair Regional Jet CRJ-900 (twin-jet)'] = 'Canadair CRJ-900 (twin-jet)'
SHORTER_AIRCRAFT_NAME['Gulfstream Aerospace Gulfstream 3 (twin-jet)'] = 'Gulfstream 3 (twin-jet)'
SHORTER_AIRCRAFT_NAME['Gulfstream Aerospace Gulfstream G450 (twin-jet)'] = 'Gulfstream G450 (twin-jet)'
SHORTER_AIRCRAFT_NAME['Gulfstream Aerospace Gulfstream G550 (twin-jet)'] = 'Gulfstream G550 (twin-jet)'
SHORTER_AIRCRAFT_NAME['Gulfstream Aerospace Gulfstream IV (twin-jet)'] = 'Gulfstream IV (twin-jet)'
SHORTER_AIRCRAFT_NAME['Gulfstream Aerospace Gulfstream V (twin-jet)'] = 'Gulfstream V (twin-jet)'
SHORTER_AIRCRAFT_NAME['GULFSTREAM AEROSPACE G-7 Gulfstream G600 (twin-jet)'] = 'Gulfstream G600 (twin-jet)'
SHORTER_AIRCRAFT_NAME['Gulfstream Aerospace Gulfstream G-7 (twin-jet)'] = 'Gulfstream G-7 (twin-jet)'
# pylint: enable=line-too-long





                            <----SKIPPED LINES---->





  fa_flight_number = list(parsed_json['flights'].keys())[0]
  parsed_flight_details = parsed_json['flights'][fa_flight_number]
  flight['fa_flight_number'] = fa_flight_number

  origin = parsed_flight_details.get('origin')
  if origin:
    flight['origin_friendly'] = origin.get('friendlyLocation')
    flight['origin_iata'] = origin.get('iata')

  destination = parsed_flight_details.get('destination')
  if destination:
    flight['destination_friendly'] = destination.get('friendlyLocation')
    flight['destination_iata'] = destination.get('iata')

  aircraft_type = parsed_flight_details.get('aircraft')
  if aircraft_type:
    flight['aircraft_type_code'] = aircraft_type.get('type')
    flight['aircraft_type_friendly'] = aircraft_type.get('friendlyType')
    if flight['aircraft_type_friendly']:
      flight['aircraft_type_friendly'] = RemoveLastParenthetical(
          flight['aircraft_type_friendly']).strip()



    flight['owner_location'] = Unidecode(aircraft_type.get('ownerLocation'))
    flight['owner'] = Unidecode(aircraft_type.get('owner'))
    flight['tail'] = Unidecode(aircraft_type.get('tail'))

  takeoff_time = parsed_flight_details.get('takeoffTimes')
  if takeoff_time:
    flight['scheduled_takeofftime'] = takeoff_time.get('scheduled')
    flight['actual_takeoff_time'] = takeoff_time.get('actual')

  gate_departure_time = parsed_flight_details.get('gateDepartureTimes')
  if gate_departure_time:
    flight['scheduled_departure_time'] = gate_departure_time.get('scheduled')
    flight['actual_departure_time'] = gate_departure_time.get('actual')

  gate_arrival_time = parsed_flight_details.get('gateArrivalTimes')
  if gate_arrival_time:
    flight['scheduled_arrival_time'] = gate_arrival_time.get('scheduled')
    flight['estimated_arrival_time'] = gate_arrival_time.get('estimated')

  landing_time = parsed_flight_details.get('landingTimes')




                            <----SKIPPED LINES---->




    line_elements.append('Alt:%d%s' % (altitude, DISTANCE_UNITS))
  if vert_rate:
    line_elements.append('%+d%s' % (vert_rate, CLIMB_RATE_UNITS))
  if line_elements:
    lines.append(EvenlySpace(line_elements))

  return lines


def EvenlySpace(l):
  """Converts list to string with equal space between each element in list."""
  if not l:
    return ''
  if len(l) == 1:
    return l[0]
  extra_space = SPLITFLAP_CHARS_PER_LINE - sum([len(str(s)) for s in l])
  last_gap = round(extra_space / (len(l) - 1))
  return EvenlySpace([*l[:-2], str(l[-2]) + ' '*last_gap + str(l[-1])])


def RemoveLastParenthetical(s):
  """Removes last instance of () and text contained within - from string."""

  # Find the index of the last opening parenthesis
  last_open_index = s.rfind('(')
  if last_open_index == -1:
    return s  # No parentheses found

  # Find the index of the closing parenthesis that matches the last opening one
  last_close_index = s.find(')', last_open_index)
  if last_close_index == -1:
    return s  # Unmatched parenthesis

  # Remove the parentheses and their contents
  return s[:last_open_index] + s[last_close_index + 1:]


def ShorterPlaneName(s):
  """Replaces full plane name with a shorter name, if it exists."""
  return SHORTER_AIRCRAFT_NAME.get(s, s)


def Ordinal(n):
  """Converts integer n to an ordinal string - i.e.: 2 -> 2nd; 5 -> 5th."""
  return '%d%s' % (n, 'tsnrhtdd'[(math.floor(n/10)%10 != 1)*(n%10 < 4)*n%10::4])


def Screenify(lines, splitflap):
  """Transforms a list of lines to a single text string for display / print.

  Given a list of lines that is a fully-formed message to send to the splitflap
  display, this function transforms the list of strings to a single string that
  is an easier-to-read and more faithful representation of how the message will
  be displayed. The transformations are to add blank lines to the message to
  make it consistent number of lines, and to add border to the sides & top /




                            <----SKIPPED LINES---->




    this_aircraft_bigger = False
    last_aircraft_bigger = False
    if (likely_same_commercial_flight and
        this_aircraft_length > last_aircraft_length * (
            1 + percent_size_difference)):
      this_aircraft_bigger = True
      comparative_text = 'larger'
    elif (likely_same_commercial_flight and
          last_aircraft_length > this_aircraft_length * (
              1 + percent_size_difference)):
      last_aircraft_bigger = True
      comparative_text = 'smaller'

    last_flight_time_string = DisplayTime(last_flight, '%b %-d')
    if this_aircraft and last_aircraft:
      if this_aircraft_bigger or last_aircraft_bigger:
        message = ('%s used a %s plane today compared with last, on %s '
                   '(%s @ %dft vs. %s @ %dft)' % (
                       this_flight_number, comparative_text,
                       last_flight_time_string,
                       RemoveLastParenthetical(this_aircraft),
                       this_aircraft_length*FEET_IN_METER,
                       RemoveLastParenthetical(last_aircraft),
                       last_aircraft_length*FEET_IN_METER))
      elif last_aircraft and this_aircraft and last_aircraft != this_aircraft:
        message = (
            '%s used a different aircraft today compared'
            ' with last, on %s (%s vs. %s)' % (
                this_flight_number, last_flight_time_string,
                RemoveLastParenthetical(ShorterPlaneName(this_aircraft)),
                RemoveLastParenthetical(ShorterPlaneName(last_aircraft))))

  return message


def FlightInsightNthFlight(flights, hours=1, min_multiple_flights=2):
  """Generates string about seeing frequent flights to the same dest.

  Generates text of the following form for the "focus" flight in the data.
  - ASA1337 was the 4th flight to PHX in the last 53 minutes, served by Alaska
    Airlines, American Airlines, Southwest and United
  - SWA3102 was the 2nd flight to SAN in the last 25 minutes, both with
    Southwest

  Args:
    flights: the list of the raw data from which the insights will be generated,
      where the flights are listed in order of observation - i.e.: flights[0]
      was the earliest seen, and flights[-1] is the most recent flight for
      which we are attempting to generate an insight.
    hours: the time horizon over which to look for flights with the same
      destination.




                            <----SKIPPED LINES---->