01234567890123456789012345678901234567890123456789012345678901234567890123456789
36623663366436653666366736683669367036713672367336743675367636773678367936803681 36823683368436853686368736883689369036913692369336943695369636973698 36993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730 3731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764 39593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999 402940304031403240334034403540364037403840394040404140424043404440454046404740484049 405040514052 405340544055 40564057 40584059406040614062406340644065406640674068406940704071407240734074407540764077 | <----SKIPPED LINES----> flights: the list of the raw flight data. Returns: Percentage of flights with a delay, calculated as the count of flights with a positive delay divided by the total number of flights that have a calculable delay. If no flights have a calculable delay, returns None. """ calculable_delay_seconds = [ DisplayDepartureTimes(f)['delay_seconds'] for f in flights if DisplayDepartureTimes(f)['calculable_delay']] delay_count = sum([1 for s in calculable_delay_seconds if s > 0]) percent_delay = None if calculable_delay_seconds: percent_delay = delay_count / len(calculable_delay_seconds) return percent_delay def FlightInsightFirstInstance( flights, key, label, days=7, additional_descriptor_fcn=''): """Generates string for first time value seen of particular key. Generates text of the following form for the "focus" flight in the data. - N311CG is the first time aircraft GLF6 (Gulfstream Aerospace Gulfstream G650 (twin-jet)) has been seen since at least 7d5h ago - PCM8679 is the first time airline Westair Industries has been seen since 9d0h ago 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. key: the key of the attribute of interest - i.e.: 'destination_iata'. label: the human-readable string that should be displayed in the message - i.e.: 'destination'. days: the minimum time of interest for an insight - i.e.: we probably see LAX every hour, but we are only interested in particular attributes that have not been seen for at least some number of days. Note, however, that the code will go back even further to find the last time that attribute was observed, or if never observed, indicating "at least". additional_descriptor_fcn: a function that, when passed a flight, returns an additional parenthetical notation to include about the attribute or flight observed - such as expanding the IATA airport code to its full name, etc. Returns: Printable string message; if no message or insights to generate, then an empty string. """ message = '' this_flight = flights[-1] this_flight_number = DisplayFlightNumber(this_flight) first_timestamp = flights[0]['now'] last_timestamp = flights[-1]['now'] included_seconds = last_timestamp - first_timestamp if included_seconds > SECONDS_IN_DAY * days: this_instance = this_flight.get(key) matching = [f for f in flights[:-1] if f.get(key) == this_instance] last_potential_observation_sec = included_seconds if matching: last_potential_observation_sec = last_timestamp - matching[-1]['now'] if this_instance and last_potential_observation_sec > SECONDS_IN_DAY * days: additional_descriptor = '' if additional_descriptor_fcn: additional_descriptor = ' (%s)' % additional_descriptor_fcn(this_flight) last_potential_observation_string = SecondsToDdHh( last_potential_observation_sec) if matching: message = '%s is the first time %s %s%s has been seen since %s ago' % ( this_flight_number, label, this_instance, additional_descriptor, last_potential_observation_string) else: message = ( '%s is the first time %s %s%s has been ' 'seen since at least %s ago' % ( this_flight_number, label, this_instance, additional_descriptor, last_potential_observation_string)) return message def FlightInsightSuperlativeVertrate(flights, hours=HOURS_IN_DAY): """Generates string about the climb rate of the flight being an extreme value. Generates text of the following form for the "focus" flight in the data. - UAL631 has the fastest ascent rate (5248fpm, 64fpm faster than next fastest) in last 24 hours - CKS1820 has the fastest descent rate (-1152fpm, -1088fpm faster than next fastest) in last 24 hours While this is conceptually similar to the more generic FlightInsightSuperlativeVertrate function, vert_rate - because it can be either positive or negative, with different signs requiring different labeling and comparisons - it needs its own special handling. Args: flights: the list of the raw data from which the insights will be generated, <----SKIPPED LINES----> late_percentage = delay_late_count / len(relevant_flights) if (superlative and delay_late_avg_sec >= min_average_delay_minutes * SECONDS_IN_MINUTE): message = ( 'This %s delay is the %s for %s of the ' 'last %d days (%s avg delay); overall: %s' % ( SecondsToHhMm(this_delay_seconds), delay_keyword, this_flight_number, days_history, SecondsToHhMm(delay_late_avg_sec), overall_stats_text)) elif (late_percentage > min_late_percentage and delay_late_avg_sec >= min_average_delay_minutes * SECONDS_IN_MINUTE): # it's just been delayed frequently! message = ( 'With today''s delay of %s, %s is delayed %d%% of the time in' ' the last %d days for avg %s delay; overall: %s' % ( SecondsToHhMm(this_delay_seconds), this_flight_number, int(100 * late_percentage), days_history, SecondsToHhMm(delay_late_avg_sec), overall_stats_text)) return message def FlightInsights(flights): """Identifies all the insight messages about the most recently seen flight. Generates a possibly-empty list of messages about the flight. Args: flights: List of all flights where the last flight in the list is the focus flight for which we are trying to identify something interesting. Returns: List of 2-tuples, where the first element in the tuple is a flag indicating <----SKIPPED LINES----> # in the last 24 hours AppendMessageType(FLAG_INSIGHT_GROUNDSPEED, FlightInsightSuperlativeAttribute( flights, 'speed', 'groundspeed', SPEED_UNITS, ['slowest', 'fastest'], hours=HOURS_IN_DAY)) AppendMessageType(FLAG_INSIGHT_ALTITUDE, FlightInsightSuperlativeAttribute( flights, 'altitude', 'altitude', DISTANCE_UNITS, ['lowest', 'highest'], hours=HOURS_IN_DAY)) AppendMessageType( FLAG_INSIGHT_VERTRATE, FlightInsightSuperlativeVertrate(flights)) # First instances: destination, first aircraft, etc. AppendMessageType(FLAG_INSIGHT_FIRST_DEST, FlightInsightFirstInstance( flights, 'destination_iata', 'destination', days=7, additional_descriptor_fcn=lambda f: f['destination_friendly'])) AppendMessageType(FLAG_INSIGHT_FIRST_ORIGIN, FlightInsightFirstInstance( flights, 'origin_iata', 'origin', days=7, additional_descriptor_fcn=lambda f: f['origin_friendly'])) AppendMessageType(FLAG_INSIGHT_FIRST_AIRLINE, FlightInsightFirstInstance( flights, 'airline_short_name', 'airline', days=7)) AppendMessageType(FLAG_INSIGHT_FIRST_AIRCRAFT, FlightInsightFirstInstance( flights, 'aircraft_type_code', 'aircraft', days=7, additional_descriptor_fcn=lambda f: f['aircraft_type_friendly'])) # This is the longest / shortest delay this flight has seen in the last 30 # days at 2h5m; including today, this flight has been delayed x of the last y # times. AppendMessageType(FLAG_INSIGHT_LONGEST_DELAY, FlightInsightDelays( flights, min_late_percentage=0.75, min_this_delay_minutes=0, min_average_delay_minutes=0)) def DelayTimeAndFrequencyMessage( types_tuple, group_function, group_label, filter_function=lambda this, other: True, min_days=1, lookback_days=MAX_INSIGHT_HORIZON_DAYS, min_this_group_size=0, min_comparison_group_size=0, min_group_qty=0, <----SKIPPED LINES----> |
01234567890123456789012345678901234567890123456789012345678901234567890123456789
366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769 39643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004 4034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091 | <----SKIPPED LINES----> flights: the list of the raw flight data. Returns: Percentage of flights with a delay, calculated as the count of flights with a positive delay divided by the total number of flights that have a calculable delay. If no flights have a calculable delay, returns None. """ calculable_delay_seconds = [ DisplayDepartureTimes(f)['delay_seconds'] for f in flights if DisplayDepartureTimes(f)['calculable_delay']] delay_count = sum([1 for s in calculable_delay_seconds if s > 0]) percent_delay = None if calculable_delay_seconds: percent_delay = delay_count / len(calculable_delay_seconds) return percent_delay def FlightInsightFirstInstance( flights, key, readable_key_function, label, days=7, additional_descriptor_fcn=''): """Generates string for first time value seen of particular key. Generates text of the following form for the "focus" flight in the data. - N311CG is the first time aircraft GLF6 (Gulfstream Aerospace Gulfstream G650 (twin-jet)) has been seen since at least 7d5h ago - PCM8679 is the first time airline Westair Industries has been seen since 9d0h ago 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. key: the key of the attribute of interest - i.e.: 'destination_iata'. readable_key_function: a function that returns a readable version of the key which may be simply the key value itself, or an abbreviation of the key value. label: the human-readable string that should be displayed in the message - i.e.: 'destination'. days: the minimum time of interest for an insight - i.e.: we probably see LAX every hour, but we are only interested in particular attributes that have not been seen for at least some number of days. Note, however, that the code will go back even further to find the last time that attribute was observed, or if never observed, indicating "at least". additional_descriptor_fcn: a function that, when passed a flight, returns an additional parenthetical notation to include about the attribute or flight observed - such as expanding the IATA airport code to its full name, etc. Returns: Printable string message; if no message or insights to generate, then an empty string. """ message = '' this_flight = flights[-1] this_flight_number = DisplayFlightNumber(this_flight) first_timestamp = flights[0]['now'] last_timestamp = flights[-1]['now'] included_seconds = last_timestamp - first_timestamp if included_seconds > SECONDS_IN_DAY * days: this_instance = this_flight.get(key) matching = [f for f in flights[:-1] if f.get(key) == this_instance] last_potential_observation_sec = included_seconds if matching: last_potential_observation_sec = last_timestamp - matching[-1]['now'] if this_instance and last_potential_observation_sec > SECONDS_IN_DAY * days: additional_descriptor = '' readable_this_instance = readable_key_function(this_flight) if additional_descriptor_fcn: additional_descriptor = ' (%s)' % additional_descriptor_fcn(this_flight) last_potential_observation_string = SecondsToDdHh( last_potential_observation_sec) if matching: message = '%s is the first time %s %s%s has been seen since %s ago' % ( this_flight_number, label, readable_this_instance, additional_descriptor, last_potential_observation_string) else: message = ( '%s is the first time %s %s%s has been ' 'seen since at least %s ago' % ( this_flight_number, label, readable_this_instance, additional_descriptor, last_potential_observation_string)) return message def FlightInsightSuperlativeVertrate(flights, hours=HOURS_IN_DAY): """Generates string about the climb rate of the flight being an extreme value. Generates text of the following form for the "focus" flight in the data. - UAL631 has the fastest ascent rate (5248fpm, 64fpm faster than next fastest) in last 24 hours - CKS1820 has the fastest descent rate (-1152fpm, -1088fpm faster than next fastest) in last 24 hours While this is conceptually similar to the more generic FlightInsightSuperlativeVertrate function, vert_rate - because it can be either positive or negative, with different signs requiring different labeling and comparisons - it needs its own special handling. Args: flights: the list of the raw data from which the insights will be generated, <----SKIPPED LINES----> late_percentage = delay_late_count / len(relevant_flights) if (superlative and delay_late_avg_sec >= min_average_delay_minutes * SECONDS_IN_MINUTE): message = ( 'This %s delay is the %s for %s of the ' 'last %d days (%s avg delay); overall: %s' % ( SecondsToHhMm(this_delay_seconds), delay_keyword, this_flight_number, days_history, SecondsToHhMm(delay_late_avg_sec), overall_stats_text)) elif (late_percentage > min_late_percentage and delay_late_avg_sec >= min_average_delay_minutes * SECONDS_IN_MINUTE): # it's just been delayed frequently! message = ( 'With today''s delay of %s, %s is delayed %d%% of the time in' ' the last %d days for avg %s delay (%s)' % ( SecondsToHhMm(this_delay_seconds), this_flight_number, int(100 * late_percentage), days_history, SecondsToHhMm(delay_late_avg_sec), overall_stats_text)) return message def FlightInsights(flights): """Identifies all the insight messages about the most recently seen flight. Generates a possibly-empty list of messages about the flight. Args: flights: List of all flights where the last flight in the list is the focus flight for which we are trying to identify something interesting. Returns: List of 2-tuples, where the first element in the tuple is a flag indicating <----SKIPPED LINES----> # in the last 24 hours AppendMessageType(FLAG_INSIGHT_GROUNDSPEED, FlightInsightSuperlativeAttribute( flights, 'speed', 'groundspeed', SPEED_UNITS, ['slowest', 'fastest'], hours=HOURS_IN_DAY)) AppendMessageType(FLAG_INSIGHT_ALTITUDE, FlightInsightSuperlativeAttribute( flights, 'altitude', 'altitude', DISTANCE_UNITS, ['lowest', 'highest'], hours=HOURS_IN_DAY)) AppendMessageType( FLAG_INSIGHT_VERTRATE, FlightInsightSuperlativeVertrate(flights)) # First instances: destination, first aircraft, etc. AppendMessageType(FLAG_INSIGHT_FIRST_DEST, FlightInsightFirstInstance( flights, 'destination_iata', lambda f: f.get('destination_iata'), 'destination', days=7, additional_descriptor_fcn=lambda f: f['destination_friendly'])) AppendMessageType(FLAG_INSIGHT_FIRST_ORIGIN, FlightInsightFirstInstance( flights, 'origin_iata', lambda f: f.get('origin_iata'), 'origin', days=7, additional_descriptor_fcn=lambda f: f['origin_friendly'])) AppendMessageType(FLAG_INSIGHT_FIRST_AIRLINE, FlightInsightFirstInstance( flights, 'airline_short_name', lambda f: SHORTER_AIRCRAFT_NAME.get( f.get('airline_short_name'), f.get('airline_short_name')), 'airline', days=7)) AppendMessageType(FLAG_INSIGHT_FIRST_AIRCRAFT, FlightInsightFirstInstance( flights, 'aircraft_type_code', lambda f: f.get('aircraft_type_code'), 'aircraft', days=7, additional_descriptor_fcn=lambda f: f['aircraft_type_friendly'])) # This is the longest / shortest delay this flight has seen in the last 30 # days at 2h5m; including today, this flight has been delayed x of the last y # times. AppendMessageType(FLAG_INSIGHT_LONGEST_DELAY, FlightInsightDelays( flights, min_late_percentage=0.75, min_this_delay_minutes=0, min_average_delay_minutes=0)) def DelayTimeAndFrequencyMessage( types_tuple, group_function, group_label, filter_function=lambda this, other: True, min_days=1, lookback_days=MAX_INSIGHT_HORIZON_DAYS, min_this_group_size=0, min_comparison_group_size=0, min_group_qty=0, <----SKIPPED LINES----> |