earth 0.5.4 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. data/Gemfile +1 -0
  2. data/TODO +2 -0
  3. data/bin/earth_tester.rb +62 -9
  4. data/earth.gemspec +7 -4
  5. data/lib/earth.rb +18 -17
  6. data/lib/earth/air.rb +2 -0
  7. data/lib/earth/air/aircraft.rb +76 -19
  8. data/lib/earth/air/aircraft/data_miner.rb +1 -63
  9. data/lib/earth/air/aircraft_class.rb +48 -12
  10. data/lib/earth/air/aircraft_class/data_miner.rb +3 -46
  11. data/lib/earth/air/aircraft_fuel_use_equation.rb +11 -13
  12. data/lib/earth/air/aircraft_instance.rb +9 -0
  13. data/lib/earth/air/aircraft_instance_seat_class.rb +12 -0
  14. data/lib/earth/air/airline.rb +6 -8
  15. data/lib/earth/air/airline/data_miner.rb +3 -3
  16. data/lib/earth/air/airport.rb +8 -10
  17. data/lib/earth/air/airport/data_miner.rb +1 -1
  18. data/lib/earth/air/bts_aircraft.rb +3 -5
  19. data/lib/earth/air/flight_distance_class.rb +4 -6
  20. data/lib/earth/air/flight_seat_class.rb +5 -7
  21. data/lib/earth/air/flight_segment.rb +58 -42
  22. data/lib/earth/air/flight_segment/data_miner.rb +11 -26
  23. data/lib/earth/automobile.rb +1 -0
  24. data/lib/earth/automobile/automobile_fuel.rb +78 -25
  25. data/lib/earth/automobile/automobile_fuel/data_miner.rb +5 -72
  26. data/lib/earth/automobile/automobile_make.rb +14 -6
  27. data/lib/earth/automobile/automobile_make/data_miner.rb +20 -35
  28. data/lib/earth/automobile/automobile_make_fleet_year.rb +39 -10
  29. data/lib/earth/automobile/automobile_make_fleet_year/data_miner.rb +0 -29
  30. data/lib/earth/automobile/automobile_make_model.rb +30 -9
  31. data/lib/earth/automobile/automobile_make_model/data_miner.rb +11 -26
  32. data/lib/earth/automobile/automobile_make_model_year.rb +41 -12
  33. data/lib/earth/automobile/automobile_make_model_year/data_miner.rb +14 -34
  34. data/lib/earth/automobile/automobile_make_model_year_variant.rb +56 -38
  35. data/lib/earth/automobile/automobile_make_model_year_variant/data_miner.rb +15 -61
  36. data/lib/earth/automobile/automobile_make_year.rb +15 -8
  37. data/lib/earth/automobile/automobile_make_year/data_miner.rb +17 -51
  38. data/lib/earth/automobile/automobile_size_class.rb +78 -14
  39. data/lib/earth/automobile/automobile_size_class/data_miner.rb +0 -66
  40. data/lib/earth/automobile/automobile_size_class_year.rb +38 -10
  41. data/lib/earth/automobile/automobile_size_class_year/data_miner.rb +0 -30
  42. data/lib/earth/automobile/automobile_type_fuel_age.rb +60 -11
  43. data/lib/earth/automobile/automobile_type_fuel_age/data_miner.rb +10 -65
  44. data/lib/earth/automobile/automobile_type_fuel_control.rb +41 -10
  45. data/lib/earth/automobile/automobile_type_fuel_control/data_miner.rb +0 -33
  46. data/lib/earth/automobile/automobile_type_fuel_year.rb +60 -15
  47. data/lib/earth/automobile/automobile_type_fuel_year/data_miner.rb +1 -52
  48. data/lib/earth/automobile/automobile_type_fuel_year_age.rb +64 -12
  49. data/lib/earth/automobile/automobile_type_fuel_year_age/data_miner.rb +1 -59
  50. data/lib/earth/automobile/automobile_type_fuel_year_control.rb +31 -10
  51. data/lib/earth/automobile/automobile_type_fuel_year_control/data_miner.rb +2 -32
  52. data/lib/earth/automobile/automobile_type_year.rb +51 -10
  53. data/lib/earth/automobile/automobile_type_year/data_miner.rb +1 -43
  54. data/lib/earth/automobile/data_miner.rb +1 -0
  55. data/lib/earth/bus/bus_class.rb +108 -28
  56. data/lib/earth/bus/bus_class/data_miner.rb +0 -88
  57. data/lib/earth/bus/bus_fuel.rb +83 -15
  58. data/lib/earth/bus/bus_fuel/data_miner.rb +0 -76
  59. data/lib/earth/bus/bus_fuel_control.rb +8 -10
  60. data/lib/earth/bus/bus_fuel_year_control.rb +7 -9
  61. data/lib/earth/bus/bus_fuel_year_control/data_miner.rb +1 -5
  62. data/lib/earth/computation/computation_carrier.rb +11 -5
  63. data/lib/earth/computation/computation_carrier/data_miner.rb +0 -7
  64. data/lib/earth/computation/computation_carrier_instance_class.rb +25 -8
  65. data/lib/earth/computation/computation_carrier_instance_class/data_miner.rb +0 -18
  66. data/lib/earth/computation/computation_carrier_region.rb +5 -7
  67. data/lib/earth/diet/diet_class.rb +14 -16
  68. data/lib/earth/diet/food_group.rb +7 -9
  69. data/lib/earth/fuel/fuel.rb +14 -16
  70. data/lib/earth/fuel/fuel/data_miner.rb +7 -3
  71. data/lib/earth/fuel/fuel_price.rb +4 -6
  72. data/lib/earth/fuel/fuel_type.rb +12 -14
  73. data/lib/earth/fuel/fuel_year.rb +57 -16
  74. data/lib/earth/fuel/fuel_year/data_miner.rb +0 -43
  75. data/lib/earth/fuel/greenhouse_gas.rb +46 -9
  76. data/lib/earth/fuel/greenhouse_gas/data_miner.rb +0 -38
  77. data/lib/earth/hospitality/lodging_class.rb +10 -12
  78. data/lib/earth/industry/industry.rb +3 -5
  79. data/lib/earth/industry/industry_product.rb +6 -8
  80. data/lib/earth/industry/industry_product_line.rb +5 -7
  81. data/lib/earth/industry/industry_sector.rb +5 -7
  82. data/lib/earth/industry/merchant.rb +4 -6
  83. data/lib/earth/industry/merchant_category.rb +3 -5
  84. data/lib/earth/industry/merchant_category_industry.rb +5 -7
  85. data/lib/earth/industry/product_line.rb +5 -7
  86. data/lib/earth/industry/product_line_industry_product.rb +5 -7
  87. data/lib/earth/industry/sector.rb +5 -7
  88. data/lib/earth/locality/census_division.rb +21 -23
  89. data/lib/earth/locality/census_region.rb +3 -5
  90. data/lib/earth/locality/climate_division.rb +5 -7
  91. data/lib/earth/locality/country.rb +13 -15
  92. data/lib/earth/locality/egrid_region.rb +14 -5
  93. data/lib/earth/locality/egrid_region/data_miner.rb +0 -10
  94. data/lib/earth/locality/egrid_subregion.rb +71 -18
  95. data/lib/earth/locality/egrid_subregion/data_miner.rb +0 -59
  96. data/lib/earth/locality/petroleum_administration_for_defense_district.rb +6 -8
  97. data/lib/earth/locality/state.rb +6 -8
  98. data/lib/earth/locality/urbanity.rb +2 -4
  99. data/lib/earth/locality/urbanity/data_miner.rb +7 -3
  100. data/lib/earth/locality/zip_code.rb +8 -10
  101. data/lib/earth/pet/breed.rb +5 -7
  102. data/lib/earth/pet/breed_gender.rb +6 -8
  103. data/lib/earth/pet/gender.rb +2 -4
  104. data/lib/earth/pet/species.rb +15 -17
  105. data/lib/earth/rail/rail_class.rb +64 -14
  106. data/lib/earth/rail/rail_class/data_miner.rb +0 -51
  107. data/lib/earth/residence/air_conditioner_use.rb +4 -6
  108. data/lib/earth/residence/air_conditioner_use/data_miner.rb +7 -3
  109. data/lib/earth/residence/clothes_machine_use.rb +4 -6
  110. data/lib/earth/residence/clothes_machine_use/data_miner.rb +11 -9
  111. data/lib/earth/residence/dishwasher_use.rb +4 -6
  112. data/lib/earth/residence/dishwasher_use/data_miner.rb +11 -9
  113. data/lib/earth/residence/residence_appliance.rb +4 -6
  114. data/lib/earth/residence/residence_class.rb +2 -4
  115. data/lib/earth/residence/residence_class/data_miner.rb +7 -3
  116. data/lib/earth/residence/residence_fuel_price.rb +12 -14
  117. data/lib/earth/residence/residence_fuel_price/data_miner.rb +7 -0
  118. data/lib/earth/residence/residence_fuel_type.rb +6 -8
  119. data/lib/earth/residence/residential_energy_consumption_survey_response.rb +91 -93
  120. data/lib/earth/residence/residential_energy_consumption_survey_response/data_miner.rb +9 -8
  121. data/lib/earth/shipping/carrier.rb +57 -10
  122. data/lib/earth/shipping/carrier/data_miner.rb +0 -48
  123. data/lib/earth/shipping/carrier_mode.rb +41 -10
  124. data/lib/earth/shipping/carrier_mode/data_miner.rb +0 -33
  125. data/lib/earth/shipping/shipment_mode.rb +30 -7
  126. data/lib/earth/shipping/shipment_mode/data_miner.rb +0 -23
  127. data/lib/earth/utils.rb +45 -0
  128. data/lib/earth/version.rb +1 -1
  129. data/spec/earth/air/aircraft_spec.rb +1 -1
  130. data/vendor/clean_find_in_batches/init.rb +35 -0
  131. metadata +74 -47
@@ -1,56 +1,13 @@
1
1
  AircraftClass.class_eval do
2
2
  data_miner do
3
- process "Ensure Aircraft is populated" do
4
- Aircraft.run_data_miner!
5
- end
6
-
7
3
  process "Derive aircraft classes from Aircraft" do
8
- connection.select_values("SELECT DISTINCT class_code FROM aircraft WHERE aircraft.class_code IS NOT NULL").each do |class_code|
4
+ Aircraft.run_data_miner!
5
+ connection.select_values("SELECT DISTINCT class_code FROM aircraft WHERE class_code IS NOT NULL").each do |class_code|
9
6
  AircraftClass.find_or_create_by_code(class_code)
10
7
  end
11
8
  end
12
9
 
13
- process "Derive some average characteristics from Aircraft" do
14
- AircraftClass.find_each do |aircraft_class|
15
- %w{ m3 m2 m1 b }.each do |coefficient|
16
- value = AircraftFuelUseEquation.where("aircraft.class_code = '#{aircraft_class.code}'").
17
- weighted_average(:"#{coefficient}", :weighted_by => [:aircraft, :passengers])
18
- aircraft_class.send("#{coefficient}=", value)
19
- end
20
- # # do this in sql because we want to preserve nils and weighted_average returns 0 when it gets NULL
21
- # connection.execute %{
22
- # UPDATE aircraft_classes
23
- # SET aircraft_classes.#{coefficient} = (
24
- # SELECT sum(aircraft_fuel_use_equations.#{coefficient} * aircraft.passengers) / sum(aircraft.passengers)
25
- # FROM aircraft_fuel_use_equations
26
- # INNER JOIN aircraft
27
- # ON aircraft.fuel_use_code = aircraft_fuel_use_equations.code
28
- # WHERE aircraft.class_code = '#{aircraft_class.code}'
29
- # AND aircraft_fuel_use_equations.#{coefficient} IS NOT NULL
30
- # )
31
- # WHERE aircraft_classes.code = '#{aircraft_class.code}'
32
- # }
33
- # end
34
-
35
- aircraft_class.seats = aircraft_class.aircraft.weighted_average(:seats, :weighted_by => :passengers)
36
- # # do this in sql because we want to preserve nils and weighted_average returns 0 when it gets NULL
37
- # connection.execute %{
38
- # UPDATE aircraft_classes
39
- # SET aircraft_classes.seats = (
40
- # SELECT sum(aircraft.seats * aircraft.passengers) / sum(aircraft.passengers)
41
- # FROM aircraft
42
- # WHERE aircraft.class_code = '#{aircraft_class.code}'
43
- # )
44
- # WHERE aircraft_classes.code = '#{aircraft_class.code}'
45
- # }
46
-
47
- aircraft_class.m3_units = 'kilograms_per_cubic_nautical_mile'
48
- aircraft_class.m2_units = 'kilograms_per_square_nautical_mile'
49
- aircraft_class.m1_units = 'kilograms_per_nautical_mile'
50
- aircraft_class.b_units = 'kilograms'
51
- aircraft_class.save
52
- end
53
- end
10
+ process :update_averages!
54
11
 
55
12
  # FIXME TODO verify this
56
13
  end
@@ -20,16 +20,14 @@ class AircraftFuelUseEquation < ActiveRecord::Base
20
20
  fuel_use_coefficients.all?(&:present?) and fuel_use_coefficients.any?(&:nonzero?)
21
21
  end
22
22
 
23
- force_schema do
24
- string 'code'
25
- string 'aircraft_description'
26
- float 'm3'
27
- string 'm3_units'
28
- float 'm2'
29
- string 'm2_units'
30
- float 'm1'
31
- string 'm1_units'
32
- float 'b'
33
- string 'b_units'
34
- end
35
- end
23
+ col :code
24
+ col :aircraft_description
25
+ col :m3, :type => :float
26
+ col :m3_units
27
+ col :m2, :type => :float
28
+ col :m2_units
29
+ col :m1, :type => :float
30
+ col :m1_units
31
+ col :b, :type => :float
32
+ col :b_units
33
+ end
@@ -0,0 +1,9 @@
1
+ class AircraftInstance < ActiveRecord::Base
2
+ set_primary_key :id
3
+
4
+ col :id
5
+ col :registration
6
+ col :serial_number
7
+ col :aircraft_description
8
+ col :airline_name
9
+ end
@@ -0,0 +1,12 @@
1
+ class AircraftInstanceSeatClass < ActiveRecord::Base
2
+ set_primary_key :row_hash
3
+
4
+ col :row_hash
5
+ col :seat_class_name
6
+ col :aircraft_instance_id
7
+ col :seats, :type => :integer
8
+ col :seat_pitch, :type => :float
9
+ col :seat_pitch_units
10
+ col :seat_width, :type => :float
11
+ col :seat_width_units
12
+ end
@@ -1,10 +1,8 @@
1
1
  class Airline < ActiveRecord::Base
2
2
  set_primary_key :name
3
-
4
- force_schema do
5
- string 'name'
6
- string 'bts_code'
7
- string 'iata_code'
8
- string 'icao_code'
9
- end
10
- end
3
+
4
+ col :name
5
+ col :bts_code
6
+ col :iata_code
7
+ col :icao_code
8
+ end
@@ -1,10 +1,10 @@
1
1
  Airline.class_eval do
2
2
  data_miner do
3
- import "a Brighter Planet-curated list of airlines",
4
- :url => 'https://spreadsheets.google.com/pub?key=0AoQJbWqPrREqdDhoVHZmSTlZcHBsRUtPR0dPd0prMkE&output=csv' do
3
+ import "a Brighter Planet-curated list of airlines and codes not included in our other sources",
4
+ :url => 'https://spreadsheets.google.com/spreadsheet/pub?key=0AoQJbWqPrREqdGJoaFpENXRqMEM2NW42am5tNURGU2c&output=csv' do
5
5
  key 'name'
6
6
  store 'bts_code', :nullify => true
7
- store 'iata_code', :nullify => true
7
+ store 'iata_code', :nullify => true
8
8
  store 'icao_code', :nullify => true
9
9
  end
10
10
  end
@@ -7,13 +7,11 @@ class Airport < ActiveRecord::Base
7
7
  :lat_column_name => :latitude,
8
8
  :lng_column_name => :longitude
9
9
 
10
- force_schema do
11
- string 'iata_code'
12
- string 'name'
13
- string 'city'
14
- string 'country_name'
15
- string 'country_iso_3166_code'
16
- float 'latitude'
17
- float 'longitude'
18
- end
19
- end
10
+ col :iata_code
11
+ col :name
12
+ col :city
13
+ col :country_name
14
+ col :country_iso_3166_code
15
+ col :latitude, :type => :float
16
+ col :longitude, :type => :float
17
+ end
@@ -46,7 +46,7 @@ Airport.class_eval do
46
46
  process "Fill in blank country codes" do
47
47
  Country.find_each do |country|
48
48
  next unless country.name.present? and country.iso_3166_code.present?
49
- update_all %{country_iso_3166_code = "#{country.iso_3166_code}"}, %{country_name LIKE "#{country.name}"}
49
+ update_all({ :country_iso_3166_code => country.iso_3166_code }, [ "country_name LIKE ?", country.name ])
50
50
  end
51
51
  end
52
52
 
@@ -1,7 +1,5 @@
1
1
  class BtsAircraft < ActiveRecord::Base
2
2
  set_primary_key :bts_code
3
- force_schema do
4
- string 'bts_code'
5
- string 'description'
6
- end
7
- end
3
+ col :bts_code
4
+ col :description
5
+ end
@@ -1,8 +1,6 @@
1
1
  class FlightDistanceClass < ActiveRecord::Base
2
2
  set_primary_key :name
3
- force_schema do
4
- string 'name'
5
- float 'distance'
6
- string 'distance_units'
7
- end
8
- end
3
+ col :name
4
+ col :distance, :type => :float
5
+ col :distance_units
6
+ end
@@ -3,10 +3,8 @@ class FlightSeatClass < ActiveRecord::Base
3
3
 
4
4
  falls_back_on :multiplier => 1
5
5
 
6
- force_schema do
7
- string 'name'
8
- string 'distance_class_name'
9
- string 'seat_class_name'
10
- float 'multiplier'
11
- end
12
- end
6
+ col :name
7
+ col :distance_class_name
8
+ col :seat_class_name
9
+ col :multiplier, :type => :float
10
+ end
@@ -19,46 +19,62 @@ class FlightSegment < ActiveRecord::Base
19
19
  :load_factor => lambda { weighted_average(:load_factor, :weighted_by => :passengers) }, # 0.78073233770097 data1 10-12-2010
20
20
  :freight_share => lambda { weighted_average(:freight_share, :weighted_by => :passengers) } # 0.022567224170157 data1 10-12-2010
21
21
 
22
- force_schema do
23
- string 'row_hash' # auto-generated primary key
24
- string 'origin_airport_iata_code' # iata code
25
- string 'origin_airport_city' # city
26
- string 'origin_country_iso_3166_code' # iso code
27
- string 'destination_airport_iata_code' # iata code
28
- string 'destination_airport_city' # city
29
- string 'destination_country_iso_3166_code' # iso code
30
- string 'airline_bts_code' # bts code
31
- string 'airline_icao_code' # icao code
32
- string 'airline_name' # text description derived from bts or icao code
33
- string 'aircraft_bts_code' # bts code
34
- string 'aircraft_description' # text description derived from BTS T100 or ICAO TFS
35
- integer 'flights' # number of flights over month or year
36
- integer 'passengers' # total passengers on all flights
37
- integer 'seats' # total seats on all flights
38
- float 'seats_per_flight' # average seats per flight; make this a float
39
- float 'load_factor' # passengers / seats
40
- float 'freight_share' # (freight + mail) / (freight + mail + (passengers * average passenger weight))
41
- float 'distance' # flight distance
42
- string 'distance_units' # 'kilometres'
43
- float 'payload_capacity' # aircraft maximum payload capacity rating; float b/c unit conversion
44
- string 'payload_capacity_units' # 'kilograms'
45
- float 'freight' # total freight on all flights performed; float b/c unit conversion
46
- string 'freight_units' # 'kilograms'
47
- float 'mail' # total mail on all flights performed; float b/c unit conversion
48
- string 'mail_units' # 'kilograms'
49
- integer 'month' # month of flight
50
- integer 'year' # year of flight
51
- date 'approximate_date' # assumed 14th day of month
52
- string 'source' # 'BTS T100' or 'ICAO TFS'
53
- index 'origin_airport_iata_code' # index for faster lookup by origin airport
54
- index 'origin_airport_city' # index for faster lookup by origin city
55
- index 'destination_airport_iata_code' # index for faster lookup by destination airport
56
- index 'destination_airport_city' # index for faster lookup by destination city
57
- index 'airline_bts_code' # index for faster lookup by airline bts code
58
- index 'airline_icao_code' # index for faster lookup by airline icao code
59
- index 'airline_name' # index for faster lookup by airline name
60
- index 'aircraft_bts_code' # index for faster lookup by aircraft bts code
61
- index 'aircraft_description' # index for faster lookup by aircraft
62
- index 'year' # index for faster lookup by year
22
+ col :row_hash # auto-generated primary key
23
+ col :origin_airport_iata_code # iata code
24
+ col :origin_airport_city # city
25
+ col :origin_country_iso_3166_code # iso code
26
+ col :destination_airport_iata_code # iata code
27
+ col :destination_airport_city # city
28
+ col :destination_country_iso_3166_code # iso code
29
+ col :airline_bts_code # bts code
30
+ col :airline_icao_code # icao code
31
+ col :airline_name # text description derived from bts or icao code
32
+ col :aircraft_bts_code # bts code
33
+ col :aircraft_description # text description derived from BTS T100 or ICAO TFS
34
+ col :flights, :type => :integer # number of flights over month or year
35
+ col :passengers, :type => :integer # total passengers on all flights
36
+ col :seats, :type => :integer # total seats on all flights
37
+ col :seats_per_flight, :type => :float # average seats per flight; make this a float
38
+ col :load_factor, :type => :float # passengers / seats
39
+ col :freight_share, :type => :float # (freight + mail) / (freight + mail + (passengers * average passenger weight))
40
+ col :distance, :type => :float # flight distance
41
+ col :distance_units # 'kilometres'
42
+ col :payload_capacity, :type => :float # aircraft maximum payload capacity rating; float b/c unit conversion
43
+ col :payload_capacity_units # 'kilograms'
44
+ col :freight, :type => :float # total freight on all flights performed; float b/c unit conversion
45
+ col :freight_units # 'kilograms'
46
+ col :mail, :type => :float # total mail on all flights performed; float b/c unit conversion
47
+ col :mail_units # 'kilograms'
48
+ col :month, :type => :integer # month of flight
49
+ col :year, :type => :integer # year of flight
50
+ col :approximate_date, :type => :date # assumed 14th day of month
51
+ col :source # 'BTS T100' or 'ICAO TFS'
52
+ add_index :origin_airport_iata_code
53
+ add_index :origin_airport_city
54
+ add_index :destination_airport_iata_code
55
+ add_index :destination_airport_city
56
+ add_index :airline_bts_code
57
+ add_index :airline_icao_code
58
+ add_index :airline_name
59
+ add_index :aircraft_bts_code
60
+ add_index :aircraft_description
61
+ add_index :year
62
+
63
+ def self.update_averages!
64
+ # Derive load factor, which is passengers divided by available seats
65
+ update_all 'load_factor = passengers / seats', 'seats > 0'
66
+
67
+ # Assume a load factor of 1 where passengers > available seats
68
+ update_all 'load_factor = 1', 'passengers > seats AND seats > 0'
69
+
70
+ # TODO: what is 90.718474
71
+ # Derive freight share as a fraction of the total weight carried
72
+ update_all 'freight_share = (freight + mail) / (freight + mail + (passengers * 90.718474))', '(freight + mail + passengers) > 0'
73
+
74
+ # Derive average seats per flight
75
+ update_all 'seats_per_flight = seats / flights', 'flights > 0'
76
+
77
+ # Add a useful date field
78
+ update_all 'approximate_date = DATE(year || "-" || month || "-" || "14")', 'month IS NOT NULL'
63
79
  end
64
- end
80
+ end
@@ -10,24 +10,6 @@ FlightSegment.class_eval do
10
10
  end
11
11
  end
12
12
 
13
- def self.update_averages!
14
- # Derive load factor, which is passengers divided by available seats
15
- update_all 'load_factor = passengers / seats', 'seats > 0'
16
-
17
- # Assume a load factor of 1 where passengers > available seats
18
- update_all 'load_factor = 1', 'passengers > seats AND seats > 0'
19
-
20
- # TODO: what is 90.718474
21
- # Derive freight share as a fraction of the total weight carried
22
- update_all 'freight_share = (freight + mail) / (freight + mail + (passengers * 90.718474))', '(freight + mail + passengers) > 0'
23
-
24
- # Derive average seats per flight
25
- update_all 'seats_per_flight = seats / flights', 'flights > 0'
26
-
27
- # Add a useful date field
28
- update_all 'approximate_date = DATE(CONCAT_WS("-", year, month, "14"))', 'month IS NOT NULL'
29
- end
30
-
31
13
  URL = 'http://www.transtats.bts.gov/DownLoad_Table.asp?Table_ID=293&Has_Group=3&Is_Zipped=0'
32
14
  FORM_DATA = %{
33
15
  UserTableName=T_100_Segment__All_Carriers&
@@ -187,11 +169,11 @@ FlightSegment.class_eval do
187
169
  VarType=Char
188
170
  }.gsub /[\s]+/,''
189
171
 
190
- data_miner do
191
- months = Hash.new
192
- (2009..2011).each do |year|
172
+ def self.form_data_per_month(year_range)
173
+ months = {}
174
+ year_range.each do |year|
193
175
  (1..12).each do |month|
194
- time = Time.gm year, month
176
+ time = ::Time.gm year, month
195
177
  form_data = FORM_DATA.dup
196
178
  form_data.gsub! '__YEAR__', time.year.to_s
197
179
  form_data.gsub! '__MONTH_NUMBER__', time.month.to_s
@@ -199,8 +181,11 @@ FlightSegment.class_eval do
199
181
  months[time] = form_data
200
182
  end
201
183
  end
202
-
203
- months.each do |month, form_data|
184
+ months
185
+ end
186
+
187
+ data_miner do
188
+ form_data_per_month(2009..2011).each do |month, form_data|
204
189
  import "T100 flight segment data for #{month.strftime('%B %Y')}",
205
190
  :url => URL,
206
191
  :form_data => form_data,
@@ -237,7 +222,7 @@ FlightSegment.class_eval do
237
222
  process "Look up airline name based on BTS code" do
238
223
  connection.select_values("SELECT DISTINCT airline_bts_code FROM flight_segments WHERE airline_bts_code IS NOT NULL").each do |bts_code|
239
224
  if airline = Airline.find_by_bts_code(bts_code)
240
- update_all %{ airline_name = "#{airline.name}" }, %{ airline_bts_code = "#{bts_code}" }
225
+ update_all({ :airline_name => airline.name }, :airline_bts_code => bts_code)
241
226
  end
242
227
  end
243
228
  end
@@ -245,7 +230,7 @@ FlightSegment.class_eval do
245
230
  process "Look up aircraft description based on BTS code" do
246
231
  connection.select_values("SELECT DISTINCT aircraft_bts_code FROM flight_segments WHERE aircraft_bts_code IS NOT NULL").each do |bts_code|
247
232
  if aircraft = BtsAircraft.find_by_bts_code(bts_code)
248
- update_all %{ aircraft_description = "#{aircraft.description.downcase}" }, %{ aircraft_bts_code = "#{bts_code}" }
233
+ update_all({ :aircraft_description => aircraft.description.downcase }, :aircraft_bts_code => bts_code)
249
234
  end
250
235
  end
251
236
  end
@@ -13,3 +13,4 @@ require 'earth/automobile/automobile_type_fuel_control'
13
13
  require 'earth/automobile/automobile_type_fuel_year'
14
14
  require 'earth/automobile/automobile_type_fuel_year_age'
15
15
  require 'earth/automobile/automobile_type_fuel_year_control'
16
+ require 'earth/fuel'
@@ -1,7 +1,6 @@
1
1
  require 'earth/automobile/automobile_type_fuel_year_age'
2
2
  require 'earth/automobile/automobile_type_fuel_year'
3
3
  require 'earth/automobile/automobile_type_year'
4
- require 'earth/fuel/greenhouse_gas'
5
4
 
6
5
  class AutomobileFuel < ActiveRecord::Base
7
6
  set_primary_key :name
@@ -10,6 +9,62 @@ class AutomobileFuel < ActiveRecord::Base
10
9
  has_many :type_fuel_years, :class_name => 'AutomobileTypeFuelYear', :foreign_key => 'fuel_common_name', :primary_key => 'ef_key'
11
10
  belongs_to :base_fuel, :class_name => 'Fuel', :foreign_key => 'base_fuel_name'
12
11
  belongs_to :blend_fuel, :class_name => 'Fuel', :foreign_key => 'blend_fuel_name'
12
+
13
+ warn_if_blanks_in :distance_key
14
+ warn_if_blanks_in :ef_key
15
+ warn do
16
+ catch :culprit do
17
+ find_each do |record|
18
+ throw :culprit, %{Records exist without base_fuel (possibly invalid key "#{record.base_fuel_name}")} unless record.base_fuel
19
+ end
20
+ false
21
+ end
22
+ end
23
+ warn do
24
+ if exists?(['blend_portion IS NOT NULL AND (blend_portion < ? OR blend_portion > ?)', 0, 1])
25
+ "Blend portions less than 0 or greater than 1"
26
+ end
27
+ end
28
+ warn do
29
+ %w{co2_emission_factor co2_biogenic_emission_factor}.map do |col|
30
+ if exists?(["#{col} IS NULL OR #{col} < ?", 0])
31
+ "Records non-positive #{col}"
32
+ end
33
+ end
34
+ end
35
+
36
+ # FIXME TODO verify that base_fuel_name and blend_fuel_name are found in Fuel if present
37
+ # FIXME TODO verify that distance_key is found in AutomobileTypeFuelYearAge
38
+ # FIXME TODO verify that ef_key is found in AutomobileTypeFuelYear
39
+
40
+ # TODO convert these to warn blocks
41
+ # ["ch4_emission_factor", "n2o_emission_factor", "hfc_emission_factor"].each do |attribute|
42
+ # verify "#{attribute.humanize} should be > 0" do
43
+ # find_each do |fuel|
44
+ # value = fuel.send(attribute)
45
+ # unless value > 0
46
+ # raise "Invalid #{attribute.humanize.downcase} for AutomobileFuel #{fuel.name}: #{value} (should be > 0)"
47
+ # end
48
+ # end
49
+ # end
50
+ # end
51
+ #
52
+ # [["co2_emission_factor_units", "kilograms_per_litre"],
53
+ # ["co2_biogenic_emission_factor_units", "kilograms_per_litre"],
54
+ # ["ch4_emission_factor_units", "kilograms_co2e_per_litre"],
55
+ # ["n2o_emission_factor_units", "kilograms_co2e_per_litre"],
56
+ # ["hfc_emission_factor_units", "kilograms_co2e_per_litre"]].each do |pair|
57
+ # attribute = pair[0]
58
+ # proper_units = pair[1]
59
+ # verify "#{attribute.humanize} should be #{proper_units.humanize.downcase}" do
60
+ # find_each do |fuel|
61
+ # units = fuel.send(attribute)
62
+ # unless units == proper_units
63
+ # raise "Invalid #{attribute.humanize.downcase} for AutomobileFuel #{fuel.name}: #{units} (should be #{proper_units})"
64
+ # end
65
+ # end
66
+ # end
67
+ # end
13
68
 
14
69
  class << self
15
70
  def fallback_latest_type_fuel_year_ages
@@ -98,32 +153,30 @@ class AutomobileFuel < ActiveRecord::Base
98
153
  :hfc_emission_factor => lambda { AutomobileFuel.fallback_hfc_emission_factor },
99
154
  :hfc_emission_factor_units => lambda { AutomobileFuel.fallback_hfc_emission_factor_units }
100
155
 
101
- force_schema do
102
- string 'name'
103
- string 'code'
104
- string 'base_fuel_name'
105
- string 'blend_fuel_name'
106
- float 'blend_portion' # the portion of the blend that is the blend fuel
107
- string 'distance_key' # used to look up annual distance from AutomobileTypeFuelYear
108
- string 'ef_key' # used to look up ch4 n2o and hfc emission factors from AutomobileTypeFuelYear
109
- float 'annual_distance'
110
- string 'annual_distance_units'
111
- float 'co2_emission_factor'
112
- string 'co2_emission_factor_units'
113
- float 'co2_biogenic_emission_factor'
114
- string 'co2_biogenic_emission_factor_units'
115
- float 'ch4_emission_factor'
116
- string 'ch4_emission_factor_units'
117
- float 'n2o_emission_factor'
118
- string 'n2o_emission_factor_units'
119
- float 'hfc_emission_factor'
120
- string 'hfc_emission_factor_units'
121
- float 'emission_factor' # DEPRECATED but motorcycle needs this
122
- string 'emission_factor_units' # DEPRECATED but motorcycle needs this
123
- end
156
+ col :name
157
+ col :code
158
+ col :base_fuel_name
159
+ col :blend_fuel_name
160
+ col :blend_portion, :type => :float # the portion of the blend that is the blend fuel
161
+ col :distance_key # used to look up annual distance from AutomobileTypeFuelYear
162
+ col :ef_key # used to look up ch4 n2o and hfc emission factors from AutomobileTypeFuelYear
163
+ col :annual_distance, :type => :float
164
+ col :annual_distance_units
165
+ col :co2_emission_factor, :type => :float
166
+ col :co2_emission_factor_units
167
+ col :co2_biogenic_emission_factor, :type => :float
168
+ col :co2_biogenic_emission_factor_units
169
+ col :ch4_emission_factor, :type => :float
170
+ col :ch4_emission_factor_units
171
+ col :n2o_emission_factor, :type => :float
172
+ col :n2o_emission_factor_units
173
+ col :hfc_emission_factor, :type => :float
174
+ col :hfc_emission_factor_units
175
+ col :emission_factor, :type => :float # DEPRECATED but motorcycle needs this
176
+ col :emission_factor_units # DEPRECATED but motorcycle needs this
124
177
 
125
178
  CODES = {
126
179
  :electricity => 'El',
127
180
  :diesel => 'D'
128
181
  }
129
- end
182
+ end