earth 0.12.3 → 0.12.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/Gemfile +1 -0
  2. data/TODO +1 -0
  3. data/bin/earth_tester.rb +39 -47
  4. data/data/air/airlines.csv +45 -0
  5. data/data/air/airports.csv +11 -0
  6. data/data/hospitality/lodging_classes.csv +4 -0
  7. data/data/locality/national_electricity_efs.csv +137 -0
  8. data/earth.gemspec +1 -1
  9. data/errata/airline/bts_carrier_codes_errata.csv +2 -0
  10. data/lib/earth.rb +3 -0
  11. data/lib/earth/active_record_base_class_methods.rb +25 -0
  12. data/lib/earth/air/aircraft.rb +5 -4
  13. data/lib/earth/air/airline.rb +5 -1
  14. data/lib/earth/air/airline/data_miner.rb +1 -1
  15. data/lib/earth/air/airport.rb +10 -2
  16. data/lib/earth/air/airport/data_miner.rb +11 -5
  17. data/lib/earth/air/bts_aircraft.rb +1 -1
  18. data/lib/earth/air/flight_segment.rb +14 -1
  19. data/lib/earth/air/flight_segment/data_miner.rb +6 -13
  20. data/lib/earth/automobile/automobile_activity_year/data_miner.rb +1 -1
  21. data/lib/earth/automobile/automobile_activity_year_type/data_miner.rb +1 -1
  22. data/lib/earth/automobile/automobile_fuel/data_miner.rb +5 -5
  23. data/lib/earth/automobile/automobile_make/data_miner.rb +1 -1
  24. data/lib/earth/automobile/automobile_make_model/data_miner.rb +1 -1
  25. data/lib/earth/automobile/automobile_make_model_year/data_miner.rb +1 -1
  26. data/lib/earth/automobile/automobile_make_model_year_variant/data_miner.rb +6 -6
  27. data/lib/earth/automobile/automobile_type_fuel/data_miner.rb +2 -2
  28. data/lib/earth/automobile/automobile_type_fuel_year/data_miner.rb +1 -1
  29. data/lib/earth/conversions_ext.rb +7 -6
  30. data/lib/earth/fuel/fuel.rb +1 -1
  31. data/lib/earth/fuel/fuel/data_miner.rb +1 -3
  32. data/lib/earth/hospitality/commercial_building_energy_consumption_survey_response.rb +3 -1
  33. data/lib/earth/hospitality/commercial_building_energy_consumption_survey_response/data_miner.rb +44 -11
  34. data/lib/earth/hospitality/lodging_class.rb +0 -1
  35. data/lib/earth/hospitality/lodging_class/data_miner.rb +3 -9
  36. data/lib/earth/industry/merchant_category/data_miner.rb +14 -0
  37. data/lib/earth/locality/country.rb +33 -7
  38. data/lib/earth/locality/country/data_miner.rb +46 -32
  39. data/lib/earth/locality/egrid_subregion.rb +1 -1
  40. data/lib/earth/locality/egrid_subregion/data_miner.rb +16 -31
  41. data/lib/earth/locality/electricity_mix.rb +37 -0
  42. data/lib/earth/locality/electricity_mix/data_miner.rb +87 -0
  43. data/lib/earth/locality/state.rb +12 -4
  44. data/lib/earth/locality/state/data_miner.rb +33 -18
  45. data/lib/earth/locality/zip_code.rb +9 -1
  46. data/lib/earth/locality/zip_code/data_miner.rb +4 -0
  47. data/lib/earth/rail/country_rail_traction/data_miner.rb +2 -2
  48. data/lib/earth/rail/country_rail_traction_class/data_miner.rb +2 -2
  49. data/lib/earth/rail/national_transit_database_record.rb +4 -0
  50. data/lib/earth/rail/rail_company/data_miner.rb +3 -3
  51. data/lib/earth/rail/rail_fuel/data_miner.rb +1 -1
  52. data/lib/earth/residence/clothes_machine_use/data_miner.rb +1 -1
  53. data/lib/earth/residence/dishwasher_use/data_miner.rb +1 -1
  54. data/lib/earth/residence/residence_fuel_price.rb +1 -1
  55. data/lib/earth/version.rb +1 -1
  56. data/spec/earth/air/airline_spec.rb +1 -1
  57. data/spec/earth/air/airport_spec.rb +7 -0
  58. data/spec/earth/air/flight_segment_spec.rb +26 -12
  59. data/spec/earth/automobile/automobile_type_fuel_spec.rb +1 -1
  60. data/spec/earth/automobile/automobile_type_fuel_year_spec.rb +3 -3
  61. data/spec/earth/fuel/fuel_spec.rb +1 -1
  62. data/spec/earth/hospitality/commercial_building_energy_consumption_survey_response_spec.rb +32 -19
  63. data/spec/earth/hospitality/lodging_class_spec.rb +18 -0
  64. data/spec/earth/industry/mecs_energy_spec.rb +2 -2
  65. data/spec/earth/industry/mecs_ratio_spec.rb +1 -1
  66. data/spec/earth/industry/merchant_category_spec.rb +17 -0
  67. data/spec/earth/locality/country_spec.rb +32 -16
  68. data/spec/earth/locality/egrid_subregion_spec.rb +40 -27
  69. data/spec/earth/locality/electricity_mix_spec.rb +70 -0
  70. data/spec/earth/locality/state_spec.rb +10 -11
  71. data/spec/earth/locality/zip_code_spec.rb +9 -5
  72. data/spec/earth_spec.rb +4 -4
  73. data/spec/spec_helper.rb +3 -0
  74. metadata +19 -10
  75. data/lib/earth/hospitality/country_lodging_class.rb +0 -18
  76. data/lib/earth/hospitality/country_lodging_class/data_miner.rb +0 -40
  77. data/lib/earth/industry/merchant.rb +0 -9
  78. data/spec/earth/hospitality/country_lodging_class_spec.rb +0 -30
@@ -20,7 +20,7 @@ Airline.class_eval do
20
20
  end
21
21
 
22
22
  import "a Brighter Planet-curated list of airlines and codes not included in our proprietary sources",
23
- :url => 'https://spreadsheets.google.com/spreadsheet/pub?key=0AoQJbWqPrREqdGJoaFpENXRqMEM2NW42am5tNURGU2c&output=csv' do
23
+ :url => "#{Earth::DATA_DIR}/air/airlines.csv" do
24
24
  key 'name'
25
25
  store 'secondary_name', :nullify => true
26
26
  store 'iata_code', :nullify => true
@@ -4,7 +4,15 @@ require 'earth/locality'
4
4
  class Airport < ActiveRecord::Base
5
5
  self.primary_key = "iata_code"
6
6
 
7
- belongs_to :country, :foreign_key => 'country_iso_3166_code', :primary_key => 'iso_3166_code'
7
+ belongs_to :country,
8
+ :foreign_key => 'country_iso_3166_code',
9
+ :primary_key => 'iso_3166_code'
10
+ has_many :departing_flight_segments,
11
+ :class_name => 'FlightSegment',
12
+ :foreign_key => :origin_airport_iata_code
13
+ has_many :arriving_flight_segments,
14
+ :class_name => 'FlightSegment',
15
+ :foreign_key => :destination_airport_iata_code
8
16
 
9
17
  acts_as_mappable :default_units => :nms,
10
18
  :lat_column_name => :latitude,
@@ -18,5 +26,5 @@ class Airport < ActiveRecord::Base
18
26
  col :latitude, :type => :float
19
27
  col :longitude, :type => :float
20
28
 
21
- warn_unless_size 5149
29
+ warn_unless_size 5324
22
30
  end
@@ -37,14 +37,14 @@ Airport.class_eval do
37
37
  :responder => "Airport::Guru" } do
38
38
  key 'iata_code'
39
39
  store 'name'
40
- store 'city'
40
+ store 'city', :nullify => true
41
41
  store 'country_name', :synthesize => proc { |row| Airport.countries_dictionary.find(row['country_name'], :must_match_at_least_one_word => true).try(:name) }
42
42
  store 'latitude'
43
43
  store 'longitude'
44
44
  end
45
45
 
46
46
  import "airports missing from the OpenFlights.org database",
47
- :url => 'https://spreadsheets.google.com/pub?key=0AoQJbWqPrREqdHpyR3NudEl5V21ZcEdXQXFDNU8zTWc&output=csv' do
47
+ :url => "#{Earth::DATA_DIR}/air/airports.csv" do
48
48
  key 'iata_code'
49
49
  store 'name'
50
50
  store 'city'
@@ -53,10 +53,16 @@ Airport.class_eval do
53
53
  store 'longitude'
54
54
  end
55
55
 
56
+ process "Fill in blank cities (assume airport name is city name)" do
57
+ t = Airport.arel_table
58
+ where(:city => nil).update_all(t[:city].eq(t[:name]).to_sql)
59
+ end
60
+
56
61
  process "Fill in blank country codes" do
57
- Country.find_each do |country|
58
- next unless country.name.present? and country.iso_3166_code.present?
59
- where(:country_name => country.name).update_all :country_iso_3166_code => country.iso_3166_code
62
+ Country.safe_find_each do |country|
63
+ if country.name.present? and country.iso_3166_code.present?
64
+ where(:country_name => country.name).update_all :country_iso_3166_code => country.iso_3166_code
65
+ end
60
66
  end
61
67
  end
62
68
  end
@@ -3,5 +3,5 @@ class BtsAircraft < ActiveRecord::Base
3
3
  col :bts_code
4
4
  col :description
5
5
 
6
- warn_unless_size 376
6
+ warn_unless_size 379
7
7
  end
@@ -3,6 +3,19 @@ require 'fuzzy_match/cached_result'
3
3
 
4
4
  class FlightSegment < ActiveRecord::Base
5
5
  self.primary_key = "row_hash"
6
+
7
+ belongs_to :airline,
8
+ :primary_key => :bts_code,
9
+ :foreign_key => :airline_bts_code
10
+
11
+ belongs_to :origin_airport,
12
+ :class_name => 'Airport',
13
+ :primary_key => :iata_code,
14
+ :foreign_key => :origin_airport_iata_code
15
+ belongs_to :destination_airport,
16
+ :class_name => 'Airport',
17
+ :primary_key => :iata_code,
18
+ :foreign_key => :destination_airport_iata_code
6
19
 
7
20
  # Cutting this for now because if iata code is missing we have to look up airports using both city and country; don't know how to do this with ActiveRecord
8
21
  # - Ian 6/12/2011
@@ -84,5 +97,5 @@ class FlightSegment < ActiveRecord::Base
84
97
  :freight_share
85
98
  )
86
99
 
87
- warn_unless_size 966913
100
+ warn_unless_size 1_254_412
88
101
  end
@@ -180,11 +180,12 @@ FlightSegment.class_eval do
180
180
  end
181
181
 
182
182
  data_miner do
183
- process "Start from scratch" do
184
- delete_all
185
- end
186
- FlightSegment.form_data_per_month.each do |month, form_data|
187
- import "T100 flight segment data for #{month.strftime('%B %Y')}",
183
+ FlightSegment.form_data_per_month.each do |date, form_data|
184
+ process "Clear current data from #{date.strftime('%B %Y')}" do
185
+ where(:year => date.year, :month => date.month).delete_all
186
+ end
187
+
188
+ import "T100 flight segment data for #{date.strftime('%B %Y')}",
188
189
  :url => URL,
189
190
  :form_data => form_data,
190
191
  :compression => :zip,
@@ -237,13 +238,5 @@ FlightSegment.class_eval do
237
238
  process "Data mine Aircraft because it's like a belongs-to association" do
238
239
  Aircraft.run_data_miner!
239
240
  end
240
-
241
- # verify origin_airport_iata_code is in airports
242
- # verify destination_airport_iata_code is in airports
243
- # verify origin_country_iso_3166_code is in countries
244
- # verify destination_country_iso_3166_code is in countries
245
- # verify airline_name is never missing
246
- # verify aircraft_description is never missing
247
- # verify year is never missing
248
241
  end
249
242
  end
@@ -17,7 +17,7 @@ AutomobileActivityYear.class_eval do
17
17
  end
18
18
 
19
19
  process "Derive hfc emission factor from AutomobileActivityYearType" do
20
- find_each do |ay|
20
+ safe_find_each do |ay|
21
21
  ay.update_attributes!(
22
22
  :hfc_emission_factor => ay.activity_year_types.sum(&:hfc_emissions) / ay.activity_year_types.sum{ |ayt| ayt.activity_year_type_fuels.sum(&:distance) },
23
23
  :hfc_emission_factor_units => ay.activity_year_types.first.hfc_emission_factor_units
@@ -17,7 +17,7 @@ AutomobileActivityYearType.class_eval do
17
17
  end
18
18
 
19
19
  process "Derive hfc emission factor from AutomobileActivityYearTypeFuel" do
20
- find_each do |ayt|
20
+ safe_find_each do |ayt|
21
21
  ayt.update_attributes!(
22
22
  :hfc_emission_factor => ayt.hfc_emissions / ayt.activity_year_type_fuels.sum(:distance),
23
23
  :hfc_emission_factor_units => ayt.hfc_emissions_units + '_per_' + ayt.activity_year_type_fuels.first.distance_units.singularize
@@ -36,8 +36,8 @@ AutomobileFuel.class_eval do
36
36
  end
37
37
 
38
38
  auto_fuel.update_attributes!(
39
- :"#{method}" => value,
40
- :"#{method}_units" => auto_fuel.base_fuel.send("#{method}_units")
39
+ "#{method}" => value,
40
+ "#{method}_units" => auto_fuel.base_fuel.send("#{method}_units")
41
41
  )
42
42
  end
43
43
  end
@@ -55,12 +55,12 @@ AutomobileFuel.class_eval do
55
55
  end
56
56
 
57
57
  process "Derive annual distance, emission factors, and total consumption from AutomobileTypeFuel" do
58
- find_each do |record|
58
+ safe_find_each do |record|
59
59
  if (type_fuels = record.type_fuels).any?
60
60
  %w{ annual_distance ch4_emission_factor n2o_emission_factor }.each do |item|
61
61
  record.update_attributes!(
62
- :"#{item}" => type_fuels.weighted_average(item, :weighted_by => :vehicles),
63
- :"#{item}_units" => type_fuels.first.send("#{item}_units")
62
+ "#{item}" => type_fuels.weighted_average(item, :weighted_by => :vehicles),
63
+ "#{item}_units" => type_fuels.first.send("#{item}_units")
64
64
  )
65
65
  end
66
66
  unless record.name =~ / gasoline/
@@ -17,7 +17,7 @@ AutomobileMake.class_eval do
17
17
  end
18
18
 
19
19
  process "Derive fuel efficiency from AutomobileMakeYear" do
20
- find_each do |make|
20
+ safe_find_each do |make|
21
21
  make.update_attributes!(
22
22
  :fuel_efficiency => make.make_years.weighted_average(:fuel_efficiency),
23
23
  :fuel_efficiency_units => make.make_years.first.fuel_efficiency_units
@@ -22,7 +22,7 @@ AutomobileMakeModel.class_eval do
22
22
  end
23
23
 
24
24
  process "Derive fuel codes and type name from AutomobileMakeModelYear" do
25
- find_each do |amm|
25
+ safe_find_each do |amm|
26
26
  codes = amm.model_years.map(&:fuel_code).uniq
27
27
  if codes.count == 1
28
28
  amm.update_attributes! :fuel_code => codes.first
@@ -61,7 +61,7 @@ AutomobileMakeModelYear.class_eval do
61
61
  end
62
62
 
63
63
  process "Derive type name from AutomobileMakeModelYearVariant" do
64
- find_each do |ammy|
64
+ safe_find_each do |ammy|
65
65
  type_names = AutomobileMakeModelYearVariant.where(:make_name => ammy.make_name, :model_name => ammy.model_name, :year => ammy.year).map(&:type_name).uniq
66
66
  ammy.update_attributes! :type_name => (type_names.first if type_names.one?)
67
67
  end
@@ -2,21 +2,21 @@ AutomobileMakeModelYearVariant.class_eval do
2
2
  # For errata
3
3
  class AutomobileMakeModelYearVariant::Guru
4
4
  %w{ alpina bentley chevrolet chrysler dodge ferrari ford gmc jaguar kia lexus maybach mercedes-benz mitsubishi porsche toyota tvr volvo yugo }.each do |make|
5
- method_name = :"is_a_#{make.gsub('-', '_')}?"
5
+ method_name = "is_a_#{make.gsub('-', '_')}?"
6
6
  define_method method_name do |row|
7
7
  row['make_name'].downcase == make
8
8
  end
9
9
  end
10
10
 
11
11
  %w{ alpina bentley marquis maybach milan mystique scion smart }.each do |model_name|
12
- method_name = :"model_contains_#{model_name}?"
12
+ method_name = "model_contains_#{model_name}?"
13
13
  define_method method_name do |row|
14
14
  row['model_name'].to_s =~ /#{model_name}/i
15
15
  end
16
16
  end
17
17
 
18
18
  [["ford", "contour"], ["hyundai", "sonata"], ["jaguar", "xjr"], ["jaguar", "xjs convertible"], ["jaguar", "xjs coupe"], ["mercury", "mystique"], ["mitsubishi", "mirage"], ["volvo", "850"], ["volvo", "850 wagon"], ["volvo", "940"], ["volvo", "940 wagon"]].each do |make_name, model_name|
19
- method_name = :"is_a_1995_#{make_name}_#{model_name.gsub(' ', '_')}_missing_fuel_efficiency?"
19
+ method_name = "is_a_1995_#{make_name}_#{model_name.gsub(' ', '_')}_missing_fuel_efficiency?"
20
20
  define_method method_name do |row|
21
21
  row['year'] == 1995 and row['make_name'].downcase == make_name and row['model_name'].downcase == model_name and (row['fuel_efficiency_city'] == 0 or row['fuel_efficiency_highway'] == 0)
22
22
  end
@@ -64,7 +64,7 @@ AutomobileMakeModelYearVariant.class_eval do
64
64
  end
65
65
 
66
66
  %w{ 5 hatchback justy loyale loyale_wagon odyssey pt_cruiser_convertible space_wagon stanza_wagon wagon xt }.each do |model_name|
67
- method_name = :"is_a_#{model_name}?"
67
+ method_name = "is_a_#{model_name}?"
68
68
  define_method method_name do |row|
69
69
  row['model_name'] =~ /^#{model_name.gsub('_', ' ')}$/i
70
70
  end
@@ -399,7 +399,7 @@ AutomobileMakeModelYearVariant.class_eval do
399
399
  where(:make_name => 'Chevrolet', :model_name => 'CAVALIER DUAL-FUEL', :fuel_code => 'C').each do |cng_variant|
400
400
  gasoline_variant = where(:make_name => 'Chevrolet', :model_name => 'CAVALIER DUAL-FUEL', :fuel_code => ['R', 'P'], :alt_fuel_code => nil).find_by_year(cng_variant.year)
401
401
  %w{ fuel_code fuel_efficiency_city fuel_efficiency_city_units fuel_efficiency_highway fuel_efficiency_highway_units }.each do |attribute|
402
- gasoline_variant.update_attributes! :"alt_#{attribute}" => cng_variant.send(attribute)
402
+ gasoline_variant.update_attributes! "alt_#{attribute}" => cng_variant.send(attribute)
403
403
  end
404
404
  cng_variant.destroy
405
405
  end
@@ -437,7 +437,7 @@ AutomobileMakeModelYearVariant.class_eval do
437
437
 
438
438
  if gasoline_variant.present?
439
439
  %w{ fuel_code fuel_efficiency_city fuel_efficiency_city_units fuel_efficiency_highway fuel_efficiency_highway_units }.each do |attribute|
440
- gasoline_variant.update_attributes! :"alt_#{attribute}" => ethanol_variant.send(attribute)
440
+ gasoline_variant.update_attributes! "alt_#{attribute}" => ethanol_variant.send(attribute)
441
441
  end
442
442
  ethanol_variant.destroy
443
443
  end
@@ -26,7 +26,7 @@ AutomobileTypeFuel.class_eval do
26
26
  join_relation = type_fuel_years[:type_name].eq(type_fuels[:type_name]).and(type_fuel_years[:fuel_family].eq(type_fuels[:fuel_family]))
27
27
 
28
28
  %w{ annual_distance ch4_emission_factor n2o_emission_factor }.each do |item|
29
- item_sql = AutomobileTypeFuelYear.where(join_relation).weighted_average_relation(:"#{item}", :weighted_by => :share_of_type).to_sql
29
+ item_sql = AutomobileTypeFuelYear.where(join_relation).weighted_average_relation("#{item}", :weighted_by => :share_of_type).to_sql
30
30
  item_units = AutomobileTypeFuelYear.first.send("#{item}_units")
31
31
 
32
32
  update_all %{
@@ -41,7 +41,7 @@ AutomobileTypeFuel.class_eval do
41
41
  end
42
42
 
43
43
  process "Derive number of vehicles and fuel consumption from AutomobileActivityYearTypeFuel" do
44
- find_each do |atf|
44
+ safe_find_each do |atf|
45
45
  atf.update_attributes!(
46
46
  :vehicles => atf.latest_activity_year_type_fuel.distance / atf.annual_distance,
47
47
  :fuel_consumption => atf.latest_activity_year_type_fuel.fuel_consumption,
@@ -39,7 +39,7 @@ AutomobileTypeFuelYear.class_eval do
39
39
 
40
40
  # Can't use an update all here b/c efs are methods defined on ATFYC that look up the ef from ATFC
41
41
  process "Derive ch4 and n2o emission factor from AutomobileTypeFuelYearControl" do
42
- find_each do |atfy|
42
+ safe_find_each do |atfy|
43
43
  atfy.update_attributes!(
44
44
  :ch4_emission_factor => atfy.type_fuel_year_controls.sum{ |atfyc| atfyc.total_travel_percent * atfyc.ch4_emission_factor },
45
45
  :n2o_emission_factor => atfy.type_fuel_year_controls.sum{ |atfyc| atfyc.total_travel_percent * atfyc.n2o_emission_factor },
@@ -20,10 +20,10 @@ Conversions.register :cubic_metres, :hundred_cubic_feet, (1.cubic_metres.to(:cub
20
20
  Conversions.register :cubic_metres, :billion_cubic_feet, (1.cubic_metres.to(:cubic_feet) / 1_000_000_000)
21
21
 
22
22
  # Mass: base unit = kilogram
23
- Conversions.register :kilograms, :grams, 1_000.0
24
- Conversions.register :kilograms, :metric_tonnes, 0.001
25
- Conversions.register :kilograms, :pounds, 2.20462262
26
- Conversions.register :kilograms, :tons, 0.00110231131
23
+ Conversions.register :kilograms, :grams, 1_000.0
24
+ Conversions.register :kilograms, :tonnes, 0.001
25
+ Conversions.register :kilograms, :pounds, 2.20462262
26
+ Conversions.register :kilograms, :short_tons, 0.00110231131
27
27
 
28
28
  # Energy: base unit = megajoule
29
29
  Conversions.register :btus, :megajoules, 0.00105505585
@@ -60,7 +60,8 @@ Conversions.register :million_btu_per_barrel, :megajoules_per_litr
60
60
  Conversions.register :btus_per_cubic_foot, :megajoules_per_cubic_metre, (1.btus.to(:megajoules) / 1.cubic_feet.to(:cubic_metres)) # Fuel
61
61
  Conversions.register :teragrams_per_quadrillion_btu, :grams_per_megajoule, (1_000_000_000_000 / 1_000_000_000_000_000.btus.to(:megajoules)) # Fuel
62
62
  Conversions.register :kilometres_per_hour, :miles_per_hour, 1.kilometres.to(:miles)
63
-
63
+ Conversions.register :kilograms_per_kilowatt_hour, :pounds_per_megawatt_hour, 1.kilograms.to(:pounds) * 1_000
64
+ Conversions.register :kilograms_per_kilowatt_hour, :pounds_per_gigawatt_hour, 1.kilograms.to(:pounds) * 1_000_000
64
65
 
65
66
  # Odd units for EPA fuel economy guide
66
67
  # Conversions.register :epa_gallon_gasoline_equivalents, :kilowatt_hours, 33.705
@@ -98,7 +99,7 @@ Conversions.register :trillion_btus_per_million_square_feet, :megajoules_per_squ
98
99
  Conversions.register :kilowatt_hours_per_square_foot, :megajoules_per_square_metre, (1.kilowatt_hours.to(:megajoules) / 1.square_feet.to(:square_metres))
99
100
  Conversions.register :billion_cubic_feet_of_natural_gas, :megajoules, (1_000_000_000.cubic_feet.to(:cubic_metres) * 38.3395) # 2003 NatGas energy content MJ/m3
100
101
  Conversions.register :cubic_feet_of_natural_gas_per_square_foot, :megajoules_per_square_metre, ((1.cubic_feet.to(:cubic_metres) * 38.3395) / 1.square_feet.to(:square_metres))
101
- Conversions.register :million_gallons_of_fuel_oil, :megajoules, (1_000_000.gallons.to(:litres) * 41.9203) # Residual Fuel Oil No. 6 energy content MJ/l from Fuels
102
+ Conversions.register :million_gallons_of_fuel_oil, :megajoules, (1_000_000.gallons.to(:litres) * 38.5491) # Distillate Fuel Oil No. 2 energy content MJ/l from Fuels
102
103
  Conversions.register :gallons_of_fuel_oil_per_square_foot, :megajoules_per_square_metre, ((41.9203 * 1.gallons.to(:litres)) / 1.square_feet.to(:square_metres))
103
104
 
104
105
  # Only used in app1
@@ -110,5 +110,5 @@ class Fuel < ActiveRecord::Base
110
110
  end
111
111
  end
112
112
 
113
- warn_unless_size 21
113
+ warn_unless_size 23
114
114
  end
@@ -57,7 +57,7 @@ Fuel.class_eval do
57
57
 
58
58
  process "Create district heat" do
59
59
  natural_gas = find_by_name 'Pipeline Natural Gas'
60
- fuel_oil = find_by_name 'Residual Fuel Oil No. 6'
60
+ fuel_oil = find_by_name 'Distillate Fuel Oil No. 2'
61
61
  district_heat = find_or_create_by_name "District Heat"
62
62
 
63
63
  # Assumptions: half nat gas at 81.7% efficiency half fuel oil at 84.6% efficiency 5% transmission losses
@@ -79,7 +79,5 @@ Fuel.class_eval do
79
79
  co2_biogenic_emission_factor_units = 'kilograms_per_' || physical_units
80
80
  })
81
81
  end
82
-
83
- # FIXME TODO verify this stuff
84
82
  end
85
83
  end
@@ -1,4 +1,3 @@
1
- require 'earth/locality'
2
1
  class CommercialBuildingEnergyConsumptionSurveyResponse < ActiveRecord::Base
3
2
  self.primary_key = "id"
4
3
  self.table_name = :cbecs_responses
@@ -21,6 +20,9 @@ class CommercialBuildingEnergyConsumptionSurveyResponse < ActiveRecord::Base
21
20
  col :floors, :type => :integer
22
21
  col :lodging_rooms, :type => :integer
23
22
  col :percent_cooled, :type => :float
23
+ col :food_prep_room, :type => :boolean
24
+ col :laundry_onsite, :type => :boolean
25
+ col :indoor_pool, :type => :boolean
24
26
  col :principal_activity
25
27
  col :detailed_activity
26
28
  col :first_activity
@@ -1,10 +1,13 @@
1
- require 'earth/locality/data_miner'
2
1
  CommercialBuildingEnergyConsumptionSurveyResponse.class_eval do
3
2
  data_miner do
3
+ process "Start from scratch" do
4
+ delete_all
5
+ end
6
+
4
7
  import 'building characteristics from the 2003 EIA CBECS - part 1',
5
8
  :url => 'http://www.eia.gov/emeu/cbecs/cbecs2003/public_use_2003/data/FILE01.csv',
6
9
  :skip => 1,
7
- :headers => ["PUBID8", "REGION8", "CENDIV8", "SQFT8", "SQFTC8", "YRCONC8", "PBA8", "ELUSED8", "NGUSED8", "FKUSED8", "PRUSED8", "STUSED8", "HWUSED8", "CLIMATE8", "FREESTN8", "WLCNS8", "RFCNS8", "GLSSPC8", "EQGLSS8", "SUNGLS8", "BLDSHP8", "NFLOOR8", "ELEVTR8", "NELVTR8", "ESCLTR8", "NESLTR8", "YRCON8", "MONCON8", "RENOV8", "RENADD8", "RENRDC8", "RENCOS8", "RENEXT8", "RENINT8", "RENHVC8", "RENLGT8", "RENWIN8", "RENPLB8", "RENINS8", "RENOTH8", "GOVOWN8", "GOVTYP8", "OWNER8", "OWNOCC8", "NOCC8", "NOCCAT8", "MONUSE8", "PORVAC8", "OPEN248", "OPNMF8", "OPNWE8", "WKHRS8", "WKHRSC8", "NWKER8", "NWKERC8", "HT18", "HT28", "COOL8", "WATR8", "COOK8", "MANU8", "GENR8", "ADJWT8", "STRATUM8", "PAIR8"] do
10
+ :headers => %w{ PUBID8 REGION8 CENDIV8 SQFT8 SQFTC8 YRCONC8 PBA8 ELUSED8 NGUSED8 FKUSED8 PRUSED8 STUSED8 HWUSED8 CLIMATE8 FREESTN8 WLCNS8 RFCNS8 GLSSPC8 EQGLSS8 SUNGLS8 BLDSHP8 NFLOOR8 ELEVTR8 NELVTR8 ESCLTR8 NESLTR8 YRCON8 MONCON8 RENOV8 RENADD8 RENRDC8 RENCOS8 RENEXT8 RENINT8 RENHVC8 RENLGT8 RENWIN8 RENPLB8 RENINS8 RENOTH8 GOVOWN8 GOVTYP8 OWNER8 OWNOCC8 NOCC8 NOCCAT8 MONUSE8 PORVAC8 OPEN248 OPNMF8 OPNWE8 WKHRS8 WKHRSC8 NWKER8 NWKERC8 HT18 HT28 COOL8 WATR8 COOK8 MANU8 GENR8 ADJWT8 STRATUM8 PAIR8 } do
8
11
  key 'id', :field_name => 'PUBID8'
9
12
  store 'census_region_number', :field_name => 'REGION8'
10
13
  store 'census_division_number', :field_name => 'CENDIV8'
@@ -23,7 +26,7 @@ CommercialBuildingEnergyConsumptionSurveyResponse.class_eval do
23
26
  import 'building characteristics from the 2003 EIA CBECS - part 2',
24
27
  :url => 'http://www.eia.gov/emeu/cbecs/cbecs2003/public_use_2003/data/FILE02.csv',
25
28
  :skip => 1,
26
- :headers => ["PUBID8","REGION8","CENDIV8","SQFT8","SQFTC8","YRCONC8","PBA8","ELUSED8","NGUSED8","FKUSED8","PRUSED8","STUSED8","HWUSED8","ONEACT8","ACT18","ACT28","ACT38","ACT1PCT8","ACT2PCT8","ACT3PCT8","PBAPLUS8","VACANT8","RWSEAT8","PBSEAT8","EDSEAT8","FDSEAT8","HCBED8","NRSBED8","LODGRM8","FACIL8","FEDFAC8","FACACT8","MANIND8","PLANT8","FACDST8","FACDHW8","FACDCW8","FACELC8","BLDPLT8","ADJWT8","STRATUM8","PAIR8"] do
29
+ :headers => %w{ PUBID8 REGION8 CENDIV8 SQFT8 SQFTC8 YRCONC8 PBA8 ELUSED8 NGUSED8 FKUSED8 PRUSED8 STUSED8 HWUSED8 ONEACT8 ACT18 ACT28 ACT38 ACT1PCT8 ACT2PCT8 ACT3PCT8 PBAPLUS8 VACANT8 RWSEAT8 PBSEAT8 EDSEAT8 FDSEAT8 HCBED8 NRSBED8 LODGRM8 FACIL8 FEDFAC8 FACACT8 MANIND8 PLANT8 FACDST8 FACDHW8 FACDCW8 FACELC8 BLDPLT8 ADJWT8 STRATUM8 PAIR8 } do
27
30
  key 'id', :field_name => 'PUBID8'
28
31
  store 'detailed_activity', :field_name => 'PBAPLUS8', :dictionary => { :input => 'detailed_activity_code', :output => 'detailed_activity', :url => 'https://docs.google.com/spreadsheet/pub?&key=0AoQJbWqPrREqdHRGVHczYXRoU2dFLV90aDdET0dQLUE&single=true&gid=3&output=csv' }
29
32
  store 'first_activity', :field_name => 'ACT18', :dictionary => { :input => 'activity_code', :output => 'activity', :url => 'https://docs.google.com/spreadsheet/pub?&key=0AoQJbWqPrREqdHRGVHczYXRoU2dFLV90aDdET0dQLUE&single=true&gid=4&output=csv' }
@@ -38,15 +41,25 @@ CommercialBuildingEnergyConsumptionSurveyResponse.class_eval do
38
41
  import 'building characteristics from the 2003 EIA CBECS - part 3',
39
42
  :url => 'http://www.eia.gov/emeu/cbecs/cbecs2003/public_use_2003/data/FILE03.csv',
40
43
  :skip => 1,
41
- :headers => ["PUBID8","REGION8","CENDIV8","SQFT8","SQFTC8","YRCONC8","PBA8","ELUSED8","NGUSED8","FKUSED8","PRUSED8","STUSED8","HWUSED8","HEATP8","HTLS508","FURNAC8","BOILER8","PKGHT8","SLFCON8","HTPMPH8","STHW8","OTHTEQ8","FURNP8","BOILP8","PKGHP8","SLFCNP8","HTPHP8","STHWP8","OTHTP8","MAINHT8","PKGHPS8","SPLHPS8","RMHPS8","AIRHPT8","GRDHPT8","WTRHPT8","NWMNHT8","RDHTNF8","HWRDHT8","COOLP8","PKGCL8","RCAC8","ACWNWL8","HTPMPC8","CHWT8","CHILLR8","EVAPCL8","OTCLEQ8","PKGCP8","RCACP8","ACWNWP8","HTPCP8","CHWTP8","CHILP8","EVAPP8","OTCLP8","MAINCL8","PKGCPS8","SPLCPS8","RMCPS8","AIRCPT8","GRDCPT8","WTRCPT8","NWMNCL8","RDCLNF8","HWRDCL8","VAV8","ECN8","MAINT8","EMCS8","ADJWT8","STRATUM8","PAIR8"] do
44
+ :headers => %w{ PUBID8 REGION8 CENDIV8 SQFT8 SQFTC8 YRCONC8 PBA8 ELUSED8 NGUSED8 FKUSED8 PRUSED8 STUSED8 HWUSED8 HEATP8 HTLS508 FURNAC8 BOILER8 PKGHT8 SLFCON8 HTPMPH8 STHW8 OTHTEQ8 FURNP8 BOILP8 PKGHP8 SLFCNP8 HTPHP8 STHWP8 OTHTP8 MAINHT8 PKGHPS8 SPLHPS8 RMHPS8 AIRHPT8 GRDHPT8 WTRHPT8 NWMNHT8 RDHTNF8 HWRDHT8 COOLP8 PKGCL8 RCAC8 ACWNWL8 HTPMPC8 CHWT8 CHILLR8 EVAPCL8 OTCLEQ8 PKGCP8 RCACP8 ACWNWP8 HTPCP8 CHWTP8 CHILP8 EVAPP8 OTCLP8 MAINCL8 PKGCPS8 SPLCPS8 RMCPS8 AIRCPT8 GRDCPT8 WTRCPT8 NWMNCL8 RDCLNF8 HWRDCL8 VAV8 ECN8 MAINT8 EMCS8 ADJWT8 STRATUM8 PAIR8 } do
42
45
  key 'id', :field_name => 'PUBID8'
43
46
  store 'percent_cooled', :synthesize => proc { |row| row['COOLP8'].to_f / 100.0 }
44
47
  end
45
48
 
49
+ import 'building characteristics from the 2003 EIA CBECS - part 4',
50
+ :url => 'http://www.eia.gov/emeu/cbecs/cbecs2003/public_use_2003/data/FILE04.csv',
51
+ :skip => 1,
52
+ :headers => %w{ PUBID8 REGION8 CENDIV8 SQFT8 SQFTC8 YRCONC8 PBA8 ELUSED8 NGUSED8 FKUSED8 PRUSED8 STUSED8 HWUSED8 WTHTEQ8 INSTWT8 FDRM8 SNACK8 FASTFD8 CAF8 FDPREP8 KITCHN8 OTFDRM8 HWTRM8 LAUNDR8 MEDEQP8 LABEQP8 MCHEQP8 POOL8 HTPOOL8 PLSRC8 RFGEQP8 RFGWI8 RFGOP8 RFGCL8 RFGRES8 RFGVEN8 RFGWIN8 RFGOPN8 RFGRSN8 RFGCLN8 RFGVNN8 PCTERM8 SERVER8 MNFRM8 SRVFRM8 TRNGRM8 STDNRM8 OTPCRM8 PCRMP8 SRVNUM8 SRVRC8 PCNUM8 PCTRMC8 FLAT8 FLATC8 PRNTRN8 PRNTYP8 RGSTRN8 COPIER8 COPRN8 FAX8 RDOFEQ8 ADJWT8 STRATUM8 PAIR8 } do
53
+ key 'id', :field_name => 'PUBID8'
54
+ store 'food_prep_room', :synthesize => proc { |row| row['FDRM8'] == '1' }
55
+ store 'laundry_onsite', :synthesize => proc { |row| row['LAUNDR8'] == '1' }
56
+ store 'indoor_pool', :synthesize => proc { |row| row['POOL8'] == '1' or row['HTPOOL8'] == '1' }
57
+ end
58
+
46
59
  import 'electricity use from the 2003 EIA CBECS',
47
60
  :url => 'http://www.eia.gov/emeu/cbecs/cbecs2003/public_use_2003/data/FILE15.csv',
48
61
  :skip => 1,
49
- :headers => ["PUBID8", "REGION8", "CENDIV8", "SQFT8", "SQFTC8", "YRCONC8", "PBA8", "ELUSED8", "NGUSED8", "FKUSED8", "PRUSED8", "STUSED8", "HWUSED8", "ADJWT8", "STRATUM8", "PAIR8", "HDD658", "CDD658", "MFUSED8", "MFBTU8", "MFEXP8", "ELCNS8", "ELBTU8", "ELEXP8", "ZELCNS8", "ZELEXP8"] do
62
+ :headers => %w{ PUBID8 REGION8 CENDIV8 SQFT8 SQFTC8 YRCONC8 PBA8 ELUSED8 NGUSED8 FKUSED8 PRUSED8 STUSED8 HWUSED8 ADJWT8 STRATUM8 PAIR8 HDD658 CDD658 MFUSED8 MFBTU8 MFEXP8 ELCNS8 ELBTU8 ELEXP8 ZELCNS8 ZELEXP8 } do
50
63
  key 'id', :field_name => 'PUBID8'
51
64
  store 'heating_degree_days', :field_name => 'HDD658', :from_units => :degrees_fahrenheit, :to_units => :degrees_celsius
52
65
  store 'cooling_degree_days', :field_name => 'CDD658', :from_units => :degrees_fahrenheit, :to_units => :degrees_celsius
@@ -57,7 +70,7 @@ CommercialBuildingEnergyConsumptionSurveyResponse.class_eval do
57
70
  import 'fuel use characteristics from the 2003 EIA CBECS',
58
71
  :url => 'http://www.eia.gov/emeu/cbecs/cbecs2003/public_use_2003/data/FILE16.csv',
59
72
  :skip => 1,
60
- :headers => ["PUBID8", "REGION8", "CENDIV8", "SQFT8", "SQFTC8", "YRCONC8", "PBA8", "ELUSED8", "NGUSED8", "FKUSED8", "PRUSED8", "STUSED8", "HWUSED8", "ADJWT8", "STRATUM8", "PAIR8", "NGCNS8", "NGBTU8", "NGEXP8", "ZNGCNS8", "ZNGEXP8", "FKCNS8", "FKBTU8", "FKEXP8", "ZFKCNS8", "ZFKEXP8", "DHUSED8", "DHHT18", "DHHT28", "DHCOOL8", "DHWATR8", "DHCOOK8", "DHMANU8", "DHOTH8", "DHCNS8", "DHBTU8", "DHEXP8", "ZDHCNS8", "ZDHEXP8"] do
73
+ :headers => %w{ PUBID8 REGION8 CENDIV8 SQFT8 SQFTC8 YRCONC8 PBA8 ELUSED8 NGUSED8 FKUSED8 PRUSED8 STUSED8 HWUSED8 ADJWT8 STRATUM8 PAIR8 NGCNS8 NGBTU8 NGEXP8 ZNGCNS8 ZNGEXP8 FKCNS8 FKBTU8 FKEXP8 ZFKCNS8 ZFKEXP8 DHUSED8 DHHT18 DHHT28 DHCOOL8 DHWATR8 DHCOOK8 DHMANU8 DHOTH8 DHCNS8 DHBTU8 DHEXP8 ZDHCNS8 ZDHEXP8 } do
61
74
  key 'id', :field_name => 'PUBID8'
62
75
  store 'natural_gas_use', :synthesize => proc { |row| row['NGCNS8'].to_i.hundred_cubic_feet.to(:cubic_metres) }, :units => :cubic_metres
63
76
  store 'fuel_oil_use', :synthesize => proc { |row| row['FKCNS8'].to_i.gallons.to(:litres) }, :units => :litres
@@ -74,11 +87,31 @@ CommercialBuildingEnergyConsumptionSurveyResponse.class_eval do
74
87
  update_all "room_nights = (365.0 * (1 / 7.0) * (1 / 12.0) * months_used * weekly_hours * (1 / 24.0) * lodging_rooms)"
75
88
  end
76
89
 
77
- process "Derive fuel intensities per room night for lodging records" do
78
- [:natural_gas, :fuel_oil, :electricity, :district_heat].each do |fuel|
79
- lodging_records.update_all %{
80
- #{fuel}_per_room_night = #{fuel}_use / room_nights,
81
- #{fuel}_per_room_night_units = #{fuel}_use_units || '_per_room_night'
90
+ process "Derive fuel intensities (including outsourced laundry energy) per room night for lodging records" do
91
+ # from Hotel Carbon Measurement Initiative guidelines 1.0
92
+ # 5.12 kg laundry / occupied room-night
93
+ # 180 kWh elec / kg laundry
94
+ # 1560 kWh nat gas / kg laundry
95
+ # 111 l fuel oil / kg laundry
96
+ # from PWC and Smith Travel Research (http://www.pwc.com/us/en/press-releases/2012/pwc-us-lodging-industry-forecast.jhtml)
97
+ # 59.2% average hotel occupancy rate in 2003
98
+
99
+ laundry_energy = {
100
+ 'electricity' => 0.592 * 5.12.kilograms.to(:tonnes) * 180.kilowatt_hours.to(:megajoules),
101
+ 'natural_gas' => 0.592 * 5.12.kilograms.to(:tonnes) * 1560.kilowatt_hours.to(:megajoules),
102
+ 'fuel_oil' => 0.592 * 5.12.kilograms.to(:tonnes) * 111 * 38.549, # 38.549 megajoules / litre distillate fuel oil
103
+ 'district_heat' => 0
104
+ }
105
+
106
+ %w{ natural_gas fuel_oil electricity district_heat }.each do |fuel|
107
+ lodging_records.where(:laundry_onsite => true).update_all %{
108
+ #{fuel}_per_room_night = #{fuel}_energy / room_nights,
109
+ #{fuel}_per_room_night_units = #{fuel}_energy_units || '_per_room_night'
110
+ }
111
+
112
+ lodging_records.where(:laundry_onsite => false).update_all %{
113
+ #{fuel}_per_room_night = (#{fuel}_energy / room_nights) + #{laundry_energy[fuel]},
114
+ #{fuel}_per_room_night_units = #{fuel}_energy_units || '_per_room_night'
82
115
  }
83
116
  end
84
117
  end