earth 0.5.4 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +1 -0
- data/TODO +2 -0
- data/bin/earth_tester.rb +62 -9
- data/earth.gemspec +7 -4
- data/lib/earth.rb +18 -17
- data/lib/earth/air.rb +2 -0
- data/lib/earth/air/aircraft.rb +76 -19
- data/lib/earth/air/aircraft/data_miner.rb +1 -63
- data/lib/earth/air/aircraft_class.rb +48 -12
- data/lib/earth/air/aircraft_class/data_miner.rb +3 -46
- data/lib/earth/air/aircraft_fuel_use_equation.rb +11 -13
- data/lib/earth/air/aircraft_instance.rb +9 -0
- data/lib/earth/air/aircraft_instance_seat_class.rb +12 -0
- data/lib/earth/air/airline.rb +6 -8
- data/lib/earth/air/airline/data_miner.rb +3 -3
- data/lib/earth/air/airport.rb +8 -10
- data/lib/earth/air/airport/data_miner.rb +1 -1
- data/lib/earth/air/bts_aircraft.rb +3 -5
- data/lib/earth/air/flight_distance_class.rb +4 -6
- data/lib/earth/air/flight_seat_class.rb +5 -7
- data/lib/earth/air/flight_segment.rb +58 -42
- data/lib/earth/air/flight_segment/data_miner.rb +11 -26
- data/lib/earth/automobile.rb +1 -0
- data/lib/earth/automobile/automobile_fuel.rb +78 -25
- data/lib/earth/automobile/automobile_fuel/data_miner.rb +5 -72
- data/lib/earth/automobile/automobile_make.rb +14 -6
- data/lib/earth/automobile/automobile_make/data_miner.rb +20 -35
- data/lib/earth/automobile/automobile_make_fleet_year.rb +39 -10
- data/lib/earth/automobile/automobile_make_fleet_year/data_miner.rb +0 -29
- data/lib/earth/automobile/automobile_make_model.rb +30 -9
- data/lib/earth/automobile/automobile_make_model/data_miner.rb +11 -26
- data/lib/earth/automobile/automobile_make_model_year.rb +41 -12
- data/lib/earth/automobile/automobile_make_model_year/data_miner.rb +14 -34
- data/lib/earth/automobile/automobile_make_model_year_variant.rb +56 -38
- data/lib/earth/automobile/automobile_make_model_year_variant/data_miner.rb +15 -61
- data/lib/earth/automobile/automobile_make_year.rb +15 -8
- data/lib/earth/automobile/automobile_make_year/data_miner.rb +17 -51
- data/lib/earth/automobile/automobile_size_class.rb +78 -14
- data/lib/earth/automobile/automobile_size_class/data_miner.rb +0 -66
- data/lib/earth/automobile/automobile_size_class_year.rb +38 -10
- data/lib/earth/automobile/automobile_size_class_year/data_miner.rb +0 -30
- data/lib/earth/automobile/automobile_type_fuel_age.rb +60 -11
- data/lib/earth/automobile/automobile_type_fuel_age/data_miner.rb +10 -65
- data/lib/earth/automobile/automobile_type_fuel_control.rb +41 -10
- data/lib/earth/automobile/automobile_type_fuel_control/data_miner.rb +0 -33
- data/lib/earth/automobile/automobile_type_fuel_year.rb +60 -15
- data/lib/earth/automobile/automobile_type_fuel_year/data_miner.rb +1 -52
- data/lib/earth/automobile/automobile_type_fuel_year_age.rb +64 -12
- data/lib/earth/automobile/automobile_type_fuel_year_age/data_miner.rb +1 -59
- data/lib/earth/automobile/automobile_type_fuel_year_control.rb +31 -10
- data/lib/earth/automobile/automobile_type_fuel_year_control/data_miner.rb +2 -32
- data/lib/earth/automobile/automobile_type_year.rb +51 -10
- data/lib/earth/automobile/automobile_type_year/data_miner.rb +1 -43
- data/lib/earth/automobile/data_miner.rb +1 -0
- data/lib/earth/bus/bus_class.rb +108 -28
- data/lib/earth/bus/bus_class/data_miner.rb +0 -88
- data/lib/earth/bus/bus_fuel.rb +83 -15
- data/lib/earth/bus/bus_fuel/data_miner.rb +0 -76
- data/lib/earth/bus/bus_fuel_control.rb +8 -10
- data/lib/earth/bus/bus_fuel_year_control.rb +7 -9
- data/lib/earth/bus/bus_fuel_year_control/data_miner.rb +1 -5
- data/lib/earth/computation/computation_carrier.rb +11 -5
- data/lib/earth/computation/computation_carrier/data_miner.rb +0 -7
- data/lib/earth/computation/computation_carrier_instance_class.rb +25 -8
- data/lib/earth/computation/computation_carrier_instance_class/data_miner.rb +0 -18
- data/lib/earth/computation/computation_carrier_region.rb +5 -7
- data/lib/earth/diet/diet_class.rb +14 -16
- data/lib/earth/diet/food_group.rb +7 -9
- data/lib/earth/fuel/fuel.rb +14 -16
- data/lib/earth/fuel/fuel/data_miner.rb +7 -3
- data/lib/earth/fuel/fuel_price.rb +4 -6
- data/lib/earth/fuel/fuel_type.rb +12 -14
- data/lib/earth/fuel/fuel_year.rb +57 -16
- data/lib/earth/fuel/fuel_year/data_miner.rb +0 -43
- data/lib/earth/fuel/greenhouse_gas.rb +46 -9
- data/lib/earth/fuel/greenhouse_gas/data_miner.rb +0 -38
- data/lib/earth/hospitality/lodging_class.rb +10 -12
- data/lib/earth/industry/industry.rb +3 -5
- data/lib/earth/industry/industry_product.rb +6 -8
- data/lib/earth/industry/industry_product_line.rb +5 -7
- data/lib/earth/industry/industry_sector.rb +5 -7
- data/lib/earth/industry/merchant.rb +4 -6
- data/lib/earth/industry/merchant_category.rb +3 -5
- data/lib/earth/industry/merchant_category_industry.rb +5 -7
- data/lib/earth/industry/product_line.rb +5 -7
- data/lib/earth/industry/product_line_industry_product.rb +5 -7
- data/lib/earth/industry/sector.rb +5 -7
- data/lib/earth/locality/census_division.rb +21 -23
- data/lib/earth/locality/census_region.rb +3 -5
- data/lib/earth/locality/climate_division.rb +5 -7
- data/lib/earth/locality/country.rb +13 -15
- data/lib/earth/locality/egrid_region.rb +14 -5
- data/lib/earth/locality/egrid_region/data_miner.rb +0 -10
- data/lib/earth/locality/egrid_subregion.rb +71 -18
- data/lib/earth/locality/egrid_subregion/data_miner.rb +0 -59
- data/lib/earth/locality/petroleum_administration_for_defense_district.rb +6 -8
- data/lib/earth/locality/state.rb +6 -8
- data/lib/earth/locality/urbanity.rb +2 -4
- data/lib/earth/locality/urbanity/data_miner.rb +7 -3
- data/lib/earth/locality/zip_code.rb +8 -10
- data/lib/earth/pet/breed.rb +5 -7
- data/lib/earth/pet/breed_gender.rb +6 -8
- data/lib/earth/pet/gender.rb +2 -4
- data/lib/earth/pet/species.rb +15 -17
- data/lib/earth/rail/rail_class.rb +64 -14
- data/lib/earth/rail/rail_class/data_miner.rb +0 -51
- data/lib/earth/residence/air_conditioner_use.rb +4 -6
- data/lib/earth/residence/air_conditioner_use/data_miner.rb +7 -3
- data/lib/earth/residence/clothes_machine_use.rb +4 -6
- data/lib/earth/residence/clothes_machine_use/data_miner.rb +11 -9
- data/lib/earth/residence/dishwasher_use.rb +4 -6
- data/lib/earth/residence/dishwasher_use/data_miner.rb +11 -9
- data/lib/earth/residence/residence_appliance.rb +4 -6
- data/lib/earth/residence/residence_class.rb +2 -4
- data/lib/earth/residence/residence_class/data_miner.rb +7 -3
- data/lib/earth/residence/residence_fuel_price.rb +12 -14
- data/lib/earth/residence/residence_fuel_price/data_miner.rb +7 -0
- data/lib/earth/residence/residence_fuel_type.rb +6 -8
- data/lib/earth/residence/residential_energy_consumption_survey_response.rb +91 -93
- data/lib/earth/residence/residential_energy_consumption_survey_response/data_miner.rb +9 -8
- data/lib/earth/shipping/carrier.rb +57 -10
- data/lib/earth/shipping/carrier/data_miner.rb +0 -48
- data/lib/earth/shipping/carrier_mode.rb +41 -10
- data/lib/earth/shipping/carrier_mode/data_miner.rb +0 -33
- data/lib/earth/shipping/shipment_mode.rb +30 -7
- data/lib/earth/shipping/shipment_mode/data_miner.rb +0 -23
- data/lib/earth/utils.rb +45 -0
- data/lib/earth/version.rb +1 -1
- data/spec/earth/air/aircraft_spec.rb +1 -1
- data/vendor/clean_find_in_batches/init.rb +35 -0
- metadata +74 -47
data/Gemfile
CHANGED
data/TODO
ADDED
data/bin/earth_tester.rb
CHANGED
|
@@ -14,19 +14,72 @@ end
|
|
|
14
14
|
require 'active_support/all'
|
|
15
15
|
require 'active_record'
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
case ENV['EARTH_DB_ADAPTER']
|
|
18
|
+
when 'mysql'
|
|
19
|
+
adapter = 'mysql'
|
|
20
|
+
database = 'test_earth'
|
|
21
|
+
username = 'root'
|
|
22
|
+
password = 'password'
|
|
23
|
+
|
|
24
|
+
# system %{mysql -u #{username} -p#{password} -e "DROP DATABASE #{database}"}
|
|
25
|
+
# system %{mysql -u #{username} -p#{password} -e "CREATE DATABASE #{database}"}
|
|
26
|
+
when 'sqlite'
|
|
27
|
+
adapter = 'sqlite3'
|
|
28
|
+
database = ':memory:'
|
|
29
|
+
username = nil
|
|
30
|
+
password = nil
|
|
31
|
+
else
|
|
32
|
+
adapter = 'postgresql'
|
|
33
|
+
username = ENV['EARTH_POSTGRES_USERNAME'] || `whoami`.chomp
|
|
34
|
+
password = ENV['EARTH_POSTGRES_PASSWORD']
|
|
35
|
+
database = ENV['EARTH_POSTGRES_DATABASE'] || 'test_earth'
|
|
36
|
+
|
|
37
|
+
createdb_bin = ENV['EARTH_CREATEDB_BIN'] || 'createdb'
|
|
38
|
+
dropdb_bin = ENV['EARTH_DROPDB_BIN'] || 'dropdb'
|
|
39
|
+
# system %{#{dropdb_bin} #{database}}
|
|
40
|
+
# system %{#{createdb_bin} #{database}}
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
config = {
|
|
44
|
+
'encoding' => 'utf8',
|
|
45
|
+
'adapter' => adapter,
|
|
46
|
+
'database' => database,
|
|
47
|
+
}
|
|
48
|
+
config['username'] = username if username
|
|
49
|
+
config['password'] = password if password
|
|
50
|
+
|
|
51
|
+
ActiveRecord::Base.establish_connection config
|
|
24
52
|
|
|
25
53
|
require 'earth'
|
|
26
54
|
|
|
27
|
-
|
|
55
|
+
domain = ARGV[0]
|
|
56
|
+
|
|
57
|
+
Earth.init domain, :load_data_miner => true, :apply_schemas => true
|
|
28
58
|
|
|
29
59
|
ActiveRecord::Base.logger = Logger.new $stderr
|
|
30
60
|
ActiveRecord::Base.logger.level = Logger::INFO
|
|
31
61
|
|
|
32
|
-
|
|
62
|
+
def show_resource(resource)
|
|
63
|
+
resource_model = resource.constantize
|
|
64
|
+
if (warnings = resource_model.table_warnings).any?
|
|
65
|
+
$stderr.puts
|
|
66
|
+
$stderr.puts '#'*50
|
|
67
|
+
$stderr.puts "# #{resource}"
|
|
68
|
+
$stderr.puts '#'*50
|
|
69
|
+
$stderr.puts
|
|
70
|
+
warnings.each do |warning|
|
|
71
|
+
$stderr.puts "* #{warning}"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
if (resource = ARGV[1].to_s.camelcase).present?
|
|
77
|
+
resource.constantize.run_data_miner!
|
|
78
|
+
show_resource resource
|
|
79
|
+
else
|
|
80
|
+
DataMiner.run
|
|
81
|
+
Earth.search(domain).each do |resource|
|
|
82
|
+
show_resource resource
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
# ARGV[1].split(/[^a-z_]/i).each { |underscore| underscore.camelcase.constantize.run_data_miner! }
|
data/earth.gemspec
CHANGED
|
@@ -27,23 +27,26 @@ Gem::Specification.new do |s|
|
|
|
27
27
|
s.require_paths = ["lib"]
|
|
28
28
|
s.rubygems_version = %q{1.3.7}
|
|
29
29
|
|
|
30
|
-
s.add_runtime_dependency 'data_miner'
|
|
30
|
+
s.add_runtime_dependency 'data_miner', '>=1.3'
|
|
31
31
|
s.add_runtime_dependency 'to_regexp'
|
|
32
32
|
s.add_runtime_dependency 'cohort_scope'
|
|
33
|
+
s.add_runtime_dependency 'table_warnings', '>=0.0.6'
|
|
33
34
|
s.add_runtime_dependency 'remote_table', '>=1.2.3'
|
|
34
35
|
s.add_runtime_dependency 'falls_back_on'
|
|
35
36
|
s.add_runtime_dependency 'fixed_width-multibyte'
|
|
36
37
|
s.add_runtime_dependency 'geokit-rails'
|
|
37
38
|
s.add_runtime_dependency 'loose_tight_dictionary', '>=0.2.3'
|
|
38
|
-
s.add_runtime_dependency 'weighted_average'
|
|
39
|
-
s.add_runtime_dependency '
|
|
39
|
+
s.add_runtime_dependency 'weighted_average', '>=1'
|
|
40
|
+
# s.add_runtime_dependency 'mini_record' # need https://github.com/DAddYE/mini_record/pull/7 - for now install manually from https://github.com/seamusabshere/mini_record
|
|
41
|
+
s.add_runtime_dependency 'activesupport'
|
|
42
|
+
s.add_runtime_dependency 'activerecord'
|
|
40
43
|
s.add_development_dependency 'bundler'
|
|
41
44
|
s.add_development_dependency 'bueller'
|
|
42
45
|
s.add_development_dependency 'cucumber'
|
|
43
46
|
s.add_development_dependency 'rake'
|
|
44
47
|
s.add_development_dependency 'rdoc'
|
|
45
|
-
s.add_development_dependency 'rdoc'
|
|
46
48
|
s.add_development_dependency 'rspec'
|
|
47
49
|
s.add_development_dependency 'sqlite3-ruby'
|
|
48
50
|
s.add_development_dependency 'mysql' # for bin/earth_tester.rb
|
|
51
|
+
s.add_development_dependency 'pg'
|
|
49
52
|
end
|
data/lib/earth.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require 'active_support/core_ext'
|
|
1
2
|
require 'active_record'
|
|
2
3
|
require 'cohort_scope'
|
|
3
4
|
require 'earth/conversions_ext'
|
|
@@ -7,22 +8,15 @@ require 'falls_back_on'
|
|
|
7
8
|
require 'weighted_average'
|
|
8
9
|
require 'fixed_width'
|
|
9
10
|
require 'errata'
|
|
10
|
-
require '
|
|
11
|
+
require 'mini_record'
|
|
12
|
+
require 'table_warnings'
|
|
11
13
|
require 'loose_tight_dictionary'
|
|
12
14
|
require 'loose_tight_dictionary/cached_result'
|
|
13
15
|
|
|
14
|
-
# hackety hack
|
|
15
|
-
def INSERT_IGNORE(cmd)
|
|
16
|
-
if ActiveRecord::Base.connection.adapter_name.downcase == 'sqlite'
|
|
17
|
-
prefix = 'INSERT'
|
|
18
|
-
else
|
|
19
|
-
prefix = 'INSERT IGNORE'
|
|
20
|
-
end
|
|
21
|
-
ActiveRecord::Base.connection.execute "#{prefix} #{cmd}"
|
|
22
|
-
end
|
|
23
|
-
|
|
24
16
|
# The earth module is an interface for loading data models from various domains.
|
|
25
17
|
module Earth
|
|
18
|
+
autoload :Utils, 'earth/utils'
|
|
19
|
+
|
|
26
20
|
extend self
|
|
27
21
|
|
|
28
22
|
# Takes argument like Earth.search(['air'])
|
|
@@ -78,6 +72,7 @@ module Earth
|
|
|
78
72
|
options = args.last.is_a?(Hash) ? args.pop.symbolize_keys : {}
|
|
79
73
|
domains = args.empty? ? [ :all ] : args.map(&:to_sym)
|
|
80
74
|
|
|
75
|
+
_configure_database_connection
|
|
81
76
|
_load_plugins
|
|
82
77
|
_load_domains domains, options
|
|
83
78
|
_decorate_resources options
|
|
@@ -86,6 +81,12 @@ module Earth
|
|
|
86
81
|
|
|
87
82
|
private
|
|
88
83
|
|
|
84
|
+
def _configure_database_connection
|
|
85
|
+
if ActiveRecord::Base.connection.adapter_name =~ /mysql/i
|
|
86
|
+
ActiveRecord::Base.connection.execute("SET SQL_MODE = 'PIPES_AS_CONCAT'")
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
89
90
|
# TODO sabshere don't use directories to specify domains
|
|
90
91
|
# * you have 20 million data_miner.rb files which are easy to confuse
|
|
91
92
|
# * you have to go all over the filesystem to figure things out
|
|
@@ -119,13 +120,13 @@ module Earth
|
|
|
119
120
|
resource_model.data_miner_config.steps.push pull_dependencies_step
|
|
120
121
|
end
|
|
121
122
|
|
|
122
|
-
def
|
|
123
|
+
def _prepend_auto_upgrade_step_to_data_miner(resource)
|
|
123
124
|
resource_model = resource.constantize
|
|
124
|
-
return if resource_model.data_miner_config.steps.any? { |step| step.description == :
|
|
125
|
+
return if resource_model.data_miner_config.steps.any? { |step| step.description == :auto_upgrade! }
|
|
125
126
|
|
|
126
|
-
|
|
127
|
+
auto_upgrade_step = DataMiner::Process.new resource_model.data_miner_config, :auto_upgrade!
|
|
127
128
|
|
|
128
|
-
resource_model.data_miner_config.steps.unshift
|
|
129
|
+
resource_model.data_miner_config.steps.unshift auto_upgrade_step
|
|
129
130
|
end
|
|
130
131
|
|
|
131
132
|
TAPS_STEP = 'Tap the Brighter Planet data server'
|
|
@@ -144,7 +145,7 @@ module Earth
|
|
|
144
145
|
next unless ::Object.const_defined?(resource)
|
|
145
146
|
_append_pull_dependencies_step_to_data_miner resource
|
|
146
147
|
if options[:apply_schemas] or options[:load_data_miner]
|
|
147
|
-
|
|
148
|
+
_prepend_auto_upgrade_step_to_data_miner resource
|
|
148
149
|
else
|
|
149
150
|
_prepend_taps_step_to_data_miner resource
|
|
150
151
|
end
|
|
@@ -154,7 +155,7 @@ module Earth
|
|
|
154
155
|
def _load_schemas(selected_resources, options)
|
|
155
156
|
return unless options[:apply_schemas]
|
|
156
157
|
selected_resources.each do |resource|
|
|
157
|
-
resource.constantize.
|
|
158
|
+
resource.constantize.auto_upgrade!
|
|
158
159
|
end
|
|
159
160
|
end
|
|
160
161
|
end
|
data/lib/earth/air.rb
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
require 'earth/air/aircraft'
|
|
2
2
|
require 'earth/air/aircraft_class'
|
|
3
3
|
require 'earth/air/aircraft_fuel_use_equation'
|
|
4
|
+
require 'earth/air/aircraft_instance'
|
|
5
|
+
require 'earth/air/aircraft_instance_seat_class'
|
|
4
6
|
require 'earth/air/airline'
|
|
5
7
|
require 'earth/air/airport'
|
|
6
8
|
require 'earth/air/bts_aircraft'
|
data/lib/earth/air/aircraft.rb
CHANGED
|
@@ -4,8 +4,24 @@ class Aircraft < ActiveRecord::Base
|
|
|
4
4
|
belongs_to :aircraft_class, :foreign_key => 'class_code', :primary_key => 'code'
|
|
5
5
|
belongs_to :fuel_use_equation, :foreign_key => 'fuel_use_code', :primary_key => 'code', :class_name => 'AircraftFuelUseEquation'
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
col :icao_code
|
|
8
|
+
col :manufacturer_name
|
|
9
|
+
col :model_name
|
|
10
|
+
col :description
|
|
11
|
+
col :aircraft_type
|
|
12
|
+
col :engine_type
|
|
13
|
+
col :engines, :type => :integer
|
|
14
|
+
col :weight_class
|
|
15
|
+
col :class_code
|
|
16
|
+
col :fuel_use_code
|
|
17
|
+
col :seats, :type => :float
|
|
18
|
+
col :passengers, :type => :float
|
|
19
|
+
|
|
20
|
+
# Enable aircraft.flight_segments
|
|
21
|
+
cache_loose_tight_dictionary_matches_with :flight_segments, :primary_key => :description, :foreign_key => :aircraft_description
|
|
22
|
+
|
|
8
23
|
class << self
|
|
24
|
+
# set up a loose_tight_dictionary for matching Aircraft description with FlightSegment aircraft_description
|
|
9
25
|
def loose_tight_dictionary
|
|
10
26
|
@loose_tight_dictionary ||= LooseTightDictionary.new(Aircraft.all,
|
|
11
27
|
:haystack_reader => lambda { |record| record.description },
|
|
@@ -15,23 +31,64 @@ class Aircraft < ActiveRecord::Base
|
|
|
15
31
|
:must_match_blocking => true,
|
|
16
32
|
:first_blocking_decides => true)
|
|
17
33
|
end
|
|
18
|
-
end
|
|
19
34
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
string 'fuel_use_code'
|
|
31
|
-
float 'seats'
|
|
32
|
-
float 'passengers'
|
|
33
|
-
end
|
|
35
|
+
# FIXME TODO do we want to restrict this to certain years?
|
|
36
|
+
# Derive some average characteristics from flight segments
|
|
37
|
+
def update_averages!
|
|
38
|
+
manually_cache_flight_segments!
|
|
39
|
+
find_each do |aircraft|
|
|
40
|
+
aircraft.seats = aircraft.flight_segments.weighted_average :seats_per_flight, :weighted_by => :passengers
|
|
41
|
+
aircraft.passengers = aircraft.flight_segments.sum :passengers
|
|
42
|
+
aircraft.save!
|
|
43
|
+
end
|
|
44
|
+
end
|
|
34
45
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
46
|
+
# Cache fuzzy matches between FlightSegment aircraft_description and Aircraft description
|
|
47
|
+
def manually_cache_flight_segments!
|
|
48
|
+
FlightSegment.run_data_miner!
|
|
49
|
+
LooseTightDictionary::CachedResult.setup
|
|
50
|
+
connection.select_values("SELECT DISTINCT(aircraft_description) FROM flight_segments WHERE aircraft_description IS NOT NULL").each do |original_description|
|
|
51
|
+
# If the flight segment's aircraft_description contains '/' then it describes multiple aircraft.
|
|
52
|
+
# We need to synthesize descriptions for those aircraft, find all Aircraft that fuzzily match the
|
|
53
|
+
# synthesized descriptions, and associate those Aircraft with the original aircraft_description.
|
|
54
|
+
# e.g. boeing 747-100/200
|
|
55
|
+
if original_description.include?('/')
|
|
56
|
+
# Pull out the complete first aircraft description
|
|
57
|
+
# e.g. 'boeing 747-100'
|
|
58
|
+
first_description = original_description.split('/')[0]
|
|
59
|
+
|
|
60
|
+
# Pull out the root of the description - the text up to and including the last ' ' or '-'
|
|
61
|
+
# e.g. 'boeing 747-'
|
|
62
|
+
root_length = first_description.rindex(/[ \-]/)
|
|
63
|
+
root = first_description.slice(0..root_length)
|
|
64
|
+
|
|
65
|
+
# Pull out the suffixes - the text separated by forward slashes
|
|
66
|
+
# e.g. ['100', '200']
|
|
67
|
+
suffixes = original_description.split(root)[1].split('/')
|
|
68
|
+
|
|
69
|
+
# Create an array of synthesized descriptions by appending each suffix to the root
|
|
70
|
+
# e.g. ['boeing 747-100', 'boeing 747-200']
|
|
71
|
+
suffixes.map{ |suffix| root + suffix }.each do |synthesized_description|
|
|
72
|
+
# Look up the Aircraft that match each synthesized description and associate
|
|
73
|
+
# them with the original flight segment aircraft_description
|
|
74
|
+
Aircraft.loose_tight_dictionary.find_all(synthesized_description).each do |aircraft|
|
|
75
|
+
attrs = {
|
|
76
|
+
:a_class => "Aircraft",
|
|
77
|
+
:a => aircraft.description,
|
|
78
|
+
:b_class => "FlightSegment",
|
|
79
|
+
:b => original_description
|
|
80
|
+
}
|
|
81
|
+
unless ::LooseTightDictionary::CachedResult.exists? attrs
|
|
82
|
+
::LooseTightDictionary::CachedResult.create! attrs
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
# If the flight segment's aircraft_description doesn't contain '/' we can use
|
|
87
|
+
# a method provided by loose_tight_dictionary to associate it with Aircraft
|
|
88
|
+
else
|
|
89
|
+
FlightSegment.find_by_aircraft_description(original_description).cache_aircraft!
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -21,68 +21,6 @@ Aircraft.class_eval do
|
|
|
21
21
|
@manufacturer_whitelist.any? { |manufacturer_regexp| manufacturer_regexp.match candidate }
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
# FIXME TODO do we want to restrict this to certain years?
|
|
25
|
-
# Derive some average characteristics from flight segments
|
|
26
|
-
def self.update_averages!
|
|
27
|
-
FlightSegment.run_data_miner!
|
|
28
|
-
manually_cache_flight_segments!
|
|
29
|
-
find_each do |aircraft|
|
|
30
|
-
aircraft.seats = aircraft.flight_segments.weighted_average :seats_per_flight, :weighted_by => :passengers
|
|
31
|
-
aircraft.passengers = aircraft.flight_segments.sum :passengers
|
|
32
|
-
aircraft.save
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Cache fuzzy matches between FlightSegment aircraft_description and Aircraft description
|
|
37
|
-
def self.manually_cache_flight_segments!
|
|
38
|
-
FlightSegment.run_data_miner!
|
|
39
|
-
LooseTightDictionary::CachedResult.setup
|
|
40
|
-
FlightSegment.find_by_sql("SELECT * FROM flight_segments GROUP BY aircraft_description HAVING aircraft_description IS NOT NULL").each do |flight_segment|
|
|
41
|
-
original_description = flight_segment.aircraft_description
|
|
42
|
-
|
|
43
|
-
# If the flight segment's aircraft_description contains '/' then it describes multiple aircraft.
|
|
44
|
-
# We need to synthesize descriptions for those aircraft, find all Aircraft that fuzzily match the
|
|
45
|
-
# synthesized descriptions, and associate those Aircraft with the original aircraft_description.
|
|
46
|
-
# e.g. boeing 747-100/200
|
|
47
|
-
if original_description.include?("/")
|
|
48
|
-
# Pull out the complete first aircraft description
|
|
49
|
-
# e.g. 'boeing 747-100'
|
|
50
|
-
first_description = original_description.split('/')[0]
|
|
51
|
-
|
|
52
|
-
# Pull out the root of the description - the text up to and including the last ' ' or '-'
|
|
53
|
-
# e.g. 'boeing 747-'
|
|
54
|
-
root_length = first_description.rindex(/[ \-]/)
|
|
55
|
-
root = first_description.slice(0..root_length)
|
|
56
|
-
|
|
57
|
-
# Pull out the suffixes - the text separated by forward slashes
|
|
58
|
-
# e.g. ['100', '200']
|
|
59
|
-
suffixes = original_description.split(root)[1].split('/')
|
|
60
|
-
|
|
61
|
-
# Create an array of synthesized descriptions by appending each suffix to the root
|
|
62
|
-
# e.g. ['boeing 747-100', 'boeing 747-200']
|
|
63
|
-
suffixes.map{ |suffix| root + suffix }.each do |synthesized_description|
|
|
64
|
-
# Look up the Aircraft that match each synthesized description and associate
|
|
65
|
-
# them with the original flight segment aircraft_description
|
|
66
|
-
Aircraft.loose_tight_dictionary.find_all(synthesized_description).each do |aircraft|
|
|
67
|
-
attrs = {
|
|
68
|
-
:a_class => "Aircraft",
|
|
69
|
-
:a => aircraft.description,
|
|
70
|
-
:b_class => "FlightSegment",
|
|
71
|
-
:b => original_description
|
|
72
|
-
}
|
|
73
|
-
unless ::LooseTightDictionary::CachedResult.exists? attrs
|
|
74
|
-
::LooseTightDictionary::CachedResult.create! attrs
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
# If the flight segment's aircraft_description doesn't contain '/' we can use
|
|
79
|
-
# a method provided by loose_tight_dictionary to associate it with Aircraft
|
|
80
|
-
else
|
|
81
|
-
flight_segment.cache_aircraft!
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
24
|
data_miner do
|
|
87
25
|
('A'..'Z').each do |letter|
|
|
88
26
|
import("aircraft made by whitelisted manufacturers whose ICAO code starts with '#{letter}' from the FAA",
|
|
@@ -140,7 +78,7 @@ Aircraft.class_eval do
|
|
|
140
78
|
end
|
|
141
79
|
|
|
142
80
|
process :update_averages!
|
|
143
|
-
|
|
81
|
+
|
|
144
82
|
# FIXME TODO verify this
|
|
145
83
|
end
|
|
146
84
|
end
|
|
@@ -2,6 +2,17 @@ class AircraftClass < ActiveRecord::Base
|
|
|
2
2
|
set_primary_key :code
|
|
3
3
|
|
|
4
4
|
has_many :aircraft, :foreign_key => 'class_code', :primary_key => 'code'
|
|
5
|
+
|
|
6
|
+
col :code
|
|
7
|
+
col :m3, :type => :float
|
|
8
|
+
col :m3_units
|
|
9
|
+
col :m2, :type => :float
|
|
10
|
+
col :m2_units
|
|
11
|
+
col :m1, :type => :float
|
|
12
|
+
col :m1_units
|
|
13
|
+
col :b, :type => :float
|
|
14
|
+
col :b_units
|
|
15
|
+
col :seats, :type => :float
|
|
5
16
|
|
|
6
17
|
def fuel_use_coefficients
|
|
7
18
|
[m3, m2, m1, b]
|
|
@@ -10,17 +21,42 @@ class AircraftClass < ActiveRecord::Base
|
|
|
10
21
|
def valid_fuel_use_equation?
|
|
11
22
|
fuel_use_coefficients.all?(&:present?) and fuel_use_coefficients.any?(&:nonzero?)
|
|
12
23
|
end
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
|
|
25
|
+
class << self
|
|
26
|
+
def update_averages!
|
|
27
|
+
Aircraft.run_data_miner!
|
|
28
|
+
AircraftFuelUseEquation.run_data_miner!
|
|
29
|
+
find_each do |aircraft_class|
|
|
30
|
+
cumulative_passengers = 0
|
|
31
|
+
aircraft_class.m3 = 0
|
|
32
|
+
aircraft_class.m2 = 0
|
|
33
|
+
aircraft_class.m1 = 0
|
|
34
|
+
aircraft_class.b = 0
|
|
35
|
+
|
|
36
|
+
aircraft_class.aircraft.where('passengers > 0 AND fuel_use_code IS NOT NULL').each do |a|
|
|
37
|
+
cumulative_passengers += a.passengers
|
|
38
|
+
aircraft_class.m3 += a.fuel_use_equation.m3 * a.passengers
|
|
39
|
+
aircraft_class.m2 += a.fuel_use_equation.m2 * a.passengers
|
|
40
|
+
aircraft_class.m1 += a.fuel_use_equation.m1 * a.passengers
|
|
41
|
+
aircraft_class.b += a.fuel_use_equation.b * a.passengers
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
if cumulative_passengers > 0
|
|
45
|
+
aircraft_class.m3 /= cumulative_passengers
|
|
46
|
+
aircraft_class.m2 /= cumulative_passengers
|
|
47
|
+
aircraft_class.m1 /= cumulative_passengers
|
|
48
|
+
aircraft_class.b /= cumulative_passengers
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
aircraft_class.seats = aircraft_class.aircraft.weighted_average(:seats, :weighted_by => :passengers)
|
|
52
|
+
|
|
53
|
+
aircraft_class.m3_units = 'kilograms_per_cubic_nautical_mile'
|
|
54
|
+
aircraft_class.m2_units = 'kilograms_per_square_nautical_mile'
|
|
55
|
+
aircraft_class.m1_units = 'kilograms_per_nautical_mile'
|
|
56
|
+
aircraft_class.b_units = 'kilograms'
|
|
57
|
+
|
|
58
|
+
aircraft_class.save!
|
|
59
|
+
end
|
|
60
|
+
end
|
|
25
61
|
end
|
|
26
62
|
end
|