Class: Aircraft
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- Aircraft
- Extended by:
- Earth::Model
- Defined in:
- lib/earth/air/aircraft.rb
Constant Summary collapse
- TABLE_STRUCTURE =
"\nCREATE TABLE aircraft\n (\n icao_code CHARACTER VARYING(255) NOT NULL PRIMARY KEY,\n manufacturer_name CHARACTER VARYING(255),\n model_name CHARACTER VARYING(255),\n description CHARACTER VARYING(255),\n aircraft_type CHARACTER VARYING(255),\n engine_type CHARACTER VARYING(255),\n engines INTEGER,\n weight_class CHARACTER VARYING(255),\n class_code CHARACTER VARYING(255),\n passengers FLOAT,\n seats FLOAT,\n seats_specificity CHARACTER VARYING(255),\n m3 FLOAT,\n m3_units CHARACTER VARYING(255),\n m2 FLOAT,\n m2_units CHARACTER VARYING(255),\n m1 FLOAT,\n m1_units CHARACTER VARYING(255),\n b FLOAT,\n b_units CHARACTER VARYING(255),\n fuel_use_specificity CHARACTER VARYING(255)\n );\nCREATE INDEX index_aircraft_on_description ON aircraft (description);\n\n"
Class Method Summary collapse
-
.fuzzy_match ⇒ Object
set up a fuzzy_match for matching Aircraft description with FlightSegment aircraft_description.
-
.manually_cache_flight_segments! ⇒ Object
Cache fuzzy matches between FlightSegment aircraft_description and Aircraft description.
-
.update_averages! ⇒ Object
FIXME TODO do we want to restrict this to certain years? Derive some average characteristics from flight segments.
Instance Method Summary collapse
Methods included from Earth::Model
extend_mining, extended, registry
Class Method Details
.fuzzy_match ⇒ Object
set up a fuzzy_match for matching Aircraft description with FlightSegment aircraft_description
47 48 49 50 51 52 53 54 55 |
# File 'lib/earth/air/aircraft.rb', line 47 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'] }, :identities => RemoteTable.new(:url => 'https://spreadsheets.google.com/spreadsheet/pub?key=0AoQJbWqPrREqdDlRR2NmdzE2ZjZwTy1ucjh4cWFYOFE&gid=1&output=csv').map { |record| record['identity'] }, :tighteners => RemoteTable.new(:url => 'https://spreadsheets.google.com/spreadsheet/pub?key=0AoQJbWqPrREqdDlRR2NmdzE2ZjZwTy1ucjh4cWFYOFE&gid=2&output=csv').map { |record| record['tightener'] }, :must_match_blocking => true, :first_blocking_decides => true) end |
.manually_cache_flight_segments! ⇒ Object
Cache fuzzy matches between FlightSegment aircraft_description and Aircraft description
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/earth/air/aircraft.rb', line 100 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! ⇒ Object
FIXME TODO do we want to restrict this to certain years? Derive some average characteristics from flight segments
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/earth/air/aircraft.rb', line 59 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 |
Instance Method Details
#valid_fuel_use_equation? ⇒ Boolean
148 149 150 |
# File 'lib/earth/air/aircraft.rb', line 148 def valid_fuel_use_equation? [m3, m2, m1, b].all?(&:present?) and [m3, m2, m1, b].any?(&:nonzero?) end |