class Aircraft

Constants

TABLE_STRUCTURE

Public Class Methods

fuzzy_match() click to toggle source

set up a fuzzy_match for matching Aircraft description with FlightSegment aircraft_description

# File lib/earth/air/aircraft.rb, line 48
def fuzzy_match
  @fuzzy_match ||= FuzzyMatch.new(Aircraft.all,
      :haystack_reader => lambda { |record| record.description },
      :blockings  => RemoteTable.new(:url => 'https://spreadsheets.google.com/spreadsheet/pub?key=0AoQJbWqPrREqdDlRR2NmdzE2ZjZwTy1ucjh4cWFYOFE&gid=0&output=csv').map { |record| record['blocking'].to_regexp },
      :identities => RemoteTable.new(:url => 'https://spreadsheets.google.com/spreadsheet/pub?key=0AoQJbWqPrREqdDlRR2NmdzE2ZjZwTy1ucjh4cWFYOFE&gid=1&output=csv').map { |record| record['identity'].to_regexp },
      :tighteners => RemoteTable.new(:url => 'https://spreadsheets.google.com/spreadsheet/pub?key=0AoQJbWqPrREqdDlRR2NmdzE2ZjZwTy1ucjh4cWFYOFE&gid=2&output=csv').map { |record| record['tightener'].to_regexp },
      :must_match_blocking => true,
      :first_blocking_decides => true)
end
manually_cache_flight_segments!() click to toggle source

Cache fuzzy matches between FlightSegment aircraft_description and Aircraft description

# File lib/earth/air/aircraft.rb, line 101
def manually_cache_flight_segments!
  FlightSegment.run_data_miner!
  FuzzyMatch::CachedResult.auto_upgrade!
  connection.select_values("SELECT DISTINCT(aircraft_description) FROM flight_segments WHERE aircraft_description IS NOT NULL").each do |original_description|
    # If the flight segment's aircraft_description contains '/' then it describes multiple aircraft.
    # We need to synthesize descriptions for those aircraft, find all Aircraft that fuzzily match the
    # synthesized descriptions, and associate those Aircraft with the original aircraft_description.
    # e.g. boeing 747-100/200
    if original_description.include?('/')
      # Pull out the complete first aircraft description
      # e.g. 'boeing 747-100'
      first_description = original_description.split('/')[0]
      
      # Pull out the root of the description - the text up to and including the last ' ' or '-'
      # e.g. 'boeing 747-'
      root_length = first_description.rindex(/[ \-]/)
      root = first_description.slice(0..root_length)
      
      # Pull out the suffixes - the text separated by forward slashes
      # e.g. ['100', '200']
      suffixes = original_description.split(root)[1].split('/')
      
      # Create an array of synthesized descriptions by appending each suffix to the root
      # e.g. ['boeing 747-100', 'boeing 747-200']
      suffixes.map{ |suffix| root + suffix }.each do |synthesized_description|
        # Look up the Aircraft that match each synthesized description and associate
        # them with the original flight segment aircraft_description
        Aircraft.fuzzy_match.find_all(synthesized_description).each do |aircraft|
          attrs = {
            :a_class => "Aircraft",
            :a => aircraft.description,
            :b_class => "FlightSegment",
            :b => original_description
          }
          unless ::FuzzyMatch::CachedResult.exists? attrs
            ::FuzzyMatch::CachedResult.create! attrs
          end
        end
      end
    # If the flight segment's aircraft_description doesn't contain '/' we can use
    # a method provided by fuzzy_match to associate it with Aircraft
    else
      FlightSegment.find_by_aircraft_description(original_description).cache_aircraft!
    end
  end
end
update_averages!() click to toggle source

FIXME TODO do we want to restrict this to certain years? Derive some average characteristics from flight segments

# File lib/earth/air/aircraft.rb, line 60
def update_averages!
  # Setup fuzzy matches with FlightSegment
  manually_cache_flight_segments!
  
  # Calculate seats and passengers for each aircraft based on associated flight_segments
  safe_find_each do |a|
    if a.seats = a.flight_segments.weighted_average(:seats_per_flight, :weighted_by => :passengers)
      a.seats_specificity = 'aircraft'
    end
    if (passengers = a.flight_segments.sum(:passengers)) > 0
      a.passengers = passengers
    end
    a.save!
  end
  
  # Calculate seats for any aircraft that don't have any flight_segments by averaging across all aircraft with flight segments in the aircraft class
  where(:seats => nil).safe_find_each do |a|
    if a.seats = where(:class_code => a.class_code, :seats_specificity => 'aircraft').weighted_average(:seats, :weighted_by => :passengers)
      a.seats_specificity = 'aircraft_class'
      a.save!
    end
  end
  
  # Calculate any missing fuel use coefficients by averaging across all aircraft with fuel use coefficients in the same aircraft class
  where(:m3 => nil).safe_find_each do |a|
    a.m3 = where(:class_code => a.class_code, :fuel_use_specificity => 'aircraft').weighted_average(:m3, :weighted_by => :passengers)
    a.m2 = where(:class_code => a.class_code, :fuel_use_specificity => 'aircraft').weighted_average(:m2, :weighted_by => :passengers)
    a.m1 = where(:class_code => a.class_code, :fuel_use_specificity => 'aircraft').weighted_average(:m1, :weighted_by => :passengers)
    a.b =  where(:class_code => a.class_code, :fuel_use_specificity => 'aircraft').weighted_average(:b,  :weighted_by => :passengers)
    if a.valid_fuel_use_equation?
      a.m3_units = 'kilograms_per_cubic_nautical_mile'
      a.m2_units = 'kilograms_per_square_nautical_mile'
      a.m1_units = 'kilograms_per_nautical_mile'
      a.b_units =  'kilograms'
      a.fuel_use_specificity = 'aircraft_class'
      a.save!
    end
  end
end

Public Instance Methods

valid_fuel_use_equation?() click to toggle source
# File lib/earth/air/aircraft.rb, line 149
def valid_fuel_use_equation?
  [m3, m2, m1, b].all?(&:present?) and [m3, m2, m1, b].any?(&:nonzero?)
end