earth 0.3.13 → 0.3.14

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+ doc
21
+
22
+ ## PROJECT::SPECIFIC
23
+ Gemfile.lock
data/Gemfile CHANGED
@@ -1,9 +1,10 @@
1
- gem 'data_miner', :path => ENV['LOCAL_DATA_MINER'] if ENV['LOCAL_DATA_MINER']
2
- gem 'sniff', :path => ENV['LOCAL_SNIFF'] if ENV['LOCAL_SNIFF']
3
-
4
1
  source :rubygems
5
2
 
6
- gemspec :path => '.'
3
+ # Specify your gem's dependencies in earth.gemspec
4
+ gemspec
5
+
6
+ gem 'data_miner', :path => ENV['LOCAL_DATA_MINER'] if ENV['LOCAL_DATA_MINER']
7
+ gem 'sniff', :path => ENV['LOCAL_SNIFF'] if ENV['LOCAL_SNIFF']
7
8
 
8
9
  if RUBY_VERSION =~ /^1\.8/
9
10
  gem 'fastercsv'
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ require 'bundler'
2
+ Bundler.setup
3
+ Bundler::GemHelper.install_tasks
4
+
5
+ require 'bueller'
6
+ Bueller::Tasks.new
7
+
8
+ begin
9
+ require 'rake/rdoctask'
10
+ Rake::RDocTask.new do |rdoc|
11
+ rdoc.rdoc_dir = 'rdoc'
12
+ rdoc.title = 'emitter'
13
+ rdoc.options << '--line-numbers' << '--inline-source'
14
+ rdoc.rdoc_files.include('README*')
15
+ rdoc.rdoc_files.include('lib/**/*.rb')
16
+ end
17
+ rescue LoadError
18
+ puts "Rdoc is not available"
19
+ end
20
+
21
+ require 'sniff'
22
+ require 'sniff/rake_tasks'
23
+ Sniff::RakeTasks.define_tasks do |t|
24
+ t.earth_domains = :all
25
+ t.cucumber = true
26
+ t.rspec = true
27
+ end
data/earth.gemspec ADDED
@@ -0,0 +1,41 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "earth/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "earth"
7
+ s.version = Earth::VERSION
8
+ s.date = "2011-01-27"
9
+ s.platform = Gem::Platform::RUBY
10
+ s.authors = ["Seamus Abshere", "Derek Kastner", "Andy Rossmeissl"]
11
+ s.email = %q{andy@rossmeissl.net}
12
+ s.homepage = "https://github.com/brighterplanet/earth"
13
+ s.summary = %Q{Land, sky, and sea}
14
+ s.description = %Q{An earth-simulation environment with ActiveRecord models and data}
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.extra_rdoc_files = [
20
+ "LICENSE",
21
+ "LICENSE-PREAMBLE",
22
+ "README.markdown"
23
+ ]
24
+ s.require_paths = ["lib"]
25
+
26
+ s.rdoc_options = ["--charset=UTF-8"]
27
+ s.require_paths = ["lib"]
28
+ s.rubygems_version = %q{1.3.7}
29
+
30
+ s.add_runtime_dependency 'activerecord', '~> 3'
31
+ s.add_runtime_dependency 'data_miner', '~> 1.1.1'
32
+ s.add_runtime_dependency 'errata'
33
+ s.add_runtime_dependency 'falls_back_on', '>= 0.0.3'
34
+ s.add_runtime_dependency 'geokit', '>= 1.5.0'
35
+ s.add_runtime_dependency 'cohort_scope', '>= 0.0.7'
36
+ s.add_runtime_dependency 'conversions', '>= 1.4.5'
37
+ s.add_runtime_dependency 'weighted_average', '>= 0.0.4'
38
+ s.add_runtime_dependency 'loose_tight_dictionary', '>= 0.0.8'
39
+ s.add_development_dependency 'sniff', '~> 0.5.3'
40
+ s.add_development_dependency 'bueller'
41
+ end
@@ -3,5 +3,8 @@ require 'bundler'
3
3
 
4
4
  Bundler.setup
5
5
 
6
+ require 'data_miner'
7
+ DataMiner.logger = Logger.new(nil)
8
+
6
9
  require 'sniff'
7
10
  Sniff.init File.expand_path('../..', File.dirname(__FILE__)), :earth => :all, :cucumber => true
data/lib/earth.rb CHANGED
@@ -8,6 +8,8 @@ require 'falls_back_on'
8
8
  require 'falls_back_on/active_record_ext'
9
9
  require 'weighted_average'
10
10
  require 'loose_tight_dictionary'
11
+ require 'slither'
12
+ require 'errata'
11
13
 
12
14
  # The earth module is an interface for establishing a taps server (used to fetch
13
15
  # data) and for loading data models from various domains.
@@ -15,7 +17,7 @@ module Earth
15
17
  extend self
16
18
 
17
19
  def taps_server
18
- @taps_server || 'http://carbon:neutral@data.brighterplanet.com:5001'
20
+ @taps_server || 'http://carbon:neutral@data.brighterplanet.com:5000'
19
21
  end
20
22
 
21
23
  # taps_server is a URL. See the data_miner gem docs
@@ -126,8 +126,8 @@ Aircraft.class_eval do
126
126
  # ('A'..'Z').each do |letter|
127
127
  # import( "ICAO manufacturers and names for aircraft with an ICAO code starting with the letter #{letter} from the FAA",
128
128
  # :url => "http://www.faa.gov/air_traffic/publications/atpubs/CNT/5-2-#{letter}.htm",
129
- # :errata => Errata.new(:url => 'http://spreadsheets.google.com/pub?key=tObVAGyqOkCBtGid0tJUZrw',
130
- # :responder => Aircraft::Guru.new),
129
+ # :errata => { :url => 'http://spreadsheets.google.com/pub?key=tObVAGyqOkCBtGid0tJUZrw',
130
+ # :responder => Aircraft::Guru.new },
131
131
  # :encoding => 'windows-1252',
132
132
  # :row_xpath => '//table/tr[2]/td/table/tr',
133
133
  # :column_xpath => 'td' ) do
@@ -146,7 +146,7 @@ Aircraft.class_eval do
146
146
 
147
147
  # import "aircraft BTS names",
148
148
  # :url => 'http://www.transtats.bts.gov/Download_Lookup.asp?Lookup=L_AIRCRAFT_TYPE',
149
- # :errata => Errata.new(:url => 'https://spreadsheets.google.com/pub?key=0AoQJbWqPrREqdEZ2d3JQMzV5T1o1T3JmVlFyNUZxdEE&hl=en&single=true&gid=0&output=csv') do
149
+ # :errata => { :url => 'https://spreadsheets.google.com/pub?key=0AoQJbWqPrREqdEZ2d3JQMzV5T1o1T3JmVlFyNUZxdEE&hl=en&single=true&gid=0&output=csv'} do
150
150
  # key 'bts_code', :field_name => 'Code'
151
151
  # store 'bts_name', :field_name => 'Description'
152
152
  # end
@@ -1,3 +1,5 @@
1
+ require 'errata'
2
+
1
3
  Airline.class_eval do
2
4
  class Airline::Guru
3
5
  # needed by errata
@@ -27,8 +29,7 @@ Airline.class_eval do
27
29
 
28
30
  import "the T100 AIRLINE_ID lookup table, which also includes IATA codes",
29
31
  :url => 'http://www.transtats.bts.gov/Download_Lookup.asp?Lookup=L_AIRLINE_ID',
30
- :errata => Errata.new(:url => 'http://static.brighterplanet.com/science/data/transport/air/airlines/errata.csv',
31
- :responder => Airline::Guru.new) do
32
+ :errata => { :url => 'http://static.brighterplanet.com/science/data/transport/air/airlines/errata.csv', :responder => Airline::Guru.new } do
32
33
  key 'iata_code', :field_name => 'Description', :split => { :pattern => /:/, :keep => 1 }
33
34
  store 'dot_airline_id_code', :field_name => 'Code'
34
35
  store 'name', :field_name => 'Description', :split => { :pattern => /:/, :keep => 0 }
@@ -48,7 +48,7 @@ AutomobileFuelType.class_eval do
48
48
  AutomobileFuelType.all.each do |fuel_type|
49
49
  current_name = fuel_type.fuel_name_for_efs
50
50
 
51
- unless current_name.nil?
51
+ if current_name.present?
52
52
  co2_factor_sql = fuel_years.project(fuel_years[:co2_emission_factor]).where(fuel_years[:fuel_common_name].eq(fuel_types[:fuel_name_for_efs]).and(fuel_years[:year].eq(latest_year))).to_sql
53
53
  ch4_factor_sql = AutomobileTypeFuelYear.weighted_average_relation(:ch4_emission_factor, :weighted_by => :total_travel).where(type_fuel_years[:fuel_common_name].eq(fuel_types[:fuel_name_for_efs]).and(type_fuel_years[:year].eq(latest_year))).to_sql
54
54
  n2o_factor_sql = AutomobileTypeFuelYear.weighted_average_relation(:n2o_emission_factor, :weighted_by => :total_travel).where(type_fuel_years[:fuel_common_name].eq(fuel_types[:fuel_name_for_efs]).and(type_fuel_years[:year].eq(latest_year))).to_sql
@@ -13,7 +13,7 @@ AutomobileMakeFleetYear.class_eval do
13
13
 
14
14
  import "annual corporate average fuel economy data for domestic and imported vehicle fleets from the NHTSA",
15
15
  :url => 'https://spreadsheets.google.com/pub?key=0AoQJbWqPrREqdEdXWXB6dkVLWkowLXhYSFVUT01sS2c&hl=en&single=true&gid=0&output=csv',
16
- :errata => 'http://static.brighterplanet.com/science/data/transport/automobiles/make_fleet_years/errata.csv',
16
+ :errata => { 'url' => 'http://static.brighterplanet.com/science/data/transport/automobiles/make_fleet_years/errata.csv' },
17
17
  :select => lambda { |row| row['volume'].to_i > 0 } do
18
18
  key 'name', :synthesize => lambda { |row| [ row['manufacturer_name'], row['year_content'], row['fleet'][2,2] ].join ' ' }
19
19
  store 'make_year_name', :synthesize => lambda { |row| [ row['manufacturer_name'], row['year_content'] ].join ' ' }
@@ -106,11 +106,58 @@ AutomobileMakeModelYearVariant.class_eval do
106
106
  }
107
107
 
108
108
  class AutomobileMakeModelYearVariant::ParserB
109
- attr_accessor :year
109
+ ::Slither.define :fuel_economy_guide_b do |d|
110
+ d.rows do |row|
111
+ row.trap { true } # there's only one section
112
+ row.column 'active_year' , 4, :type => :integer # ACTIVE YEAR
113
+ row.column 'state_code' , 1, :type => :string # STATE CODE: F=49-STATE,C=CALIFORNIA
114
+ row.column 'carline_clss' , 2, :type => :integer # CARLINE CLASS CODE
115
+ row.column 'carline_mfr_code' , 3, :type => :integer # CARLINE MANUFACTURER CODE
116
+ row.column 'carline_name' , 28, :type => :string # CARLINE NAME
117
+ row.column 'disp_cub_in' , 4, :type => :integer # DISP CUBIC INCHES
118
+ row.column 'fuel_system' , 2, :type => :string # FUEL SYSTEM: 'FI' FOR FUEL INJECTION, 2-DIGIT INTEGER VALUE FOR #OF VENTURIES IF CARBURETOR SYSTEM.
119
+ row.column 'model_trans' , 6, :type => :string # TRANSMISSION TYPE
120
+ row.column 'no_cyc' , 2, :type => :integer # NUMBER OF ENGINE CYLINDERS
121
+ row.column 'date_time' , 12, :type => :string # DATE AND TIME RECORD ENTERED -YYMMDDHHMMSS (YEAR, MONTH, DAY, HOUR, MINUTE, SECOND)
122
+ row.column 'release_date' , 6, :type => :string # RELEASE DATE - YYMMDD (YEAR, MONTH, DAY)
123
+ row.column 'vi_mfr_code' , 3, :type => :integer # VI MANUFACTURER CODE
124
+ row.column 'carline_code' , 5, :type => :integer # CARLINE CODE
125
+ row.column 'basic_eng_id' , 5, :type => :integer # BASIC ENGINE INDEX
126
+ row.column 'carline_mfr_name' , 32, :type => :string # CARLINE MANUFACTURER NAME
127
+ row.column 'suppress_code' , 1, :type => :integer # SUPPRESSION CODE (NO SUPPRESSED RECORD IF FOR PUBLIC ACCESS)
128
+ row.column 'est_city_mpg' , 3, :type => :integer # ESTIMATED (CITY) MILES PER GALLON - 90% OF UNADJUSTED VALUE
129
+ row.spacer 2
130
+ row.column 'highway_mpg' , 3, :type => :integer # ESTIMATED (HWY) MILES PER GALLON - 78% OF UNADJUSTED VALUE
131
+ row.spacer 2
132
+ row.column 'combined_mpg' , 3, :type => :integer # COMBINED MILES PER GALLON
133
+ row.spacer 2
134
+ row.column 'unadj_city_mpg' , 3, :type => :integer # UNADJUSTED CITY MILES PER GALLON
135
+ row.spacer 2
136
+ row.column 'unadj_hwy_mpg' , 3, :type => :integer # UNADJUSTED HIGHWAY MILES PER GALLON
137
+ row.spacer 2
138
+ row.column 'unadj_comb_mpg' , 3, :type => :integer # UNADJUSTED COMBINED MILES PER GALLON
139
+ row.spacer 2
140
+ row.column 'ave_anl_fuel' , 6, :type => :integer # "$" in col 147, Annual Fuel Cost starting col 148 in I5
141
+ row.column 'opt_disp' , 8, :type => :string # OPTIONAL DISPLACEMENT
142
+ row.column 'engine_desc1' , 10, :type => :string # ENGINE DESCRIPTION 1
143
+ row.column 'engine_desc2' , 10, :type => :string # ENGINE DESCRIPTION 2
144
+ row.column 'engine_desc3' , 10, :type => :string # ENGINE DESCRIPTION 3
145
+ row.column 'body_type_2d' , 10, :type => :string # BODY TYPE 2 DOOR - IF THE BODY TYPE APPLIES IT WILL TAKE THE FORM '2DR-PPP/LL' WHERE PPP=PASSENGER INTERIOR VOLUME AND LL=LUGGAGE INTERIOR VOLUME.
146
+ row.column 'body_type_4d' , 10, :type => :string # BODY TYPE 4 DOOR - IF THE BODY TYPE APPLIES IT WILL TAKE THE FORM '4DR-PPP/LL' WHERE PPP=PASSENGER INTERIOR VOLUME AND LL=LUGGAGE INTERIOR VOLUME.
147
+ row.column 'body_type_hbk' , 10, :type => :string # BODY TYPE HBK - IF THE BODY TYPE APPLIES IT WILL TAKE THE FORM 'HBK-PPP/LL' WHERE PPP=PASSENGER INTERIOR VOLUME AND LL=LUGGAGE INTERIOR VOLUME.
148
+ row.column 'puerto_rico' , 1, :type => :string # '*' IF FOR PUERTO RICO SALES ONLY
149
+ row.column 'overdrive' , 4, :type => :string # OVERDRIVE: ' OD ' FOR OVERDRIVE, 'EOD ' FOR ELECTRICALLY OPERATED OVERDRIVE AND 'AEOD' FOR AUTOMATIC OVERDRIVE
150
+ row.column 'drive_system' , 3, :type => :string # FWD=FRONT WHEEL DRIVE, RWD=REAR, 4WD=4-WHEEL
151
+ row.column 'filler' , 1, :type => :string # NOT USED
152
+ row.column 'fuel_type' , 1, :type => :string # R=REGULAR(UNLEADED), P=PREMIUM, D=DIESEL
153
+ row.column 'trans_desc' , 15, :type => :string # TRANSMISSION DESCRIPTORS
154
+ end
155
+ end
156
+ attr_reader :year
110
157
  def initialize(options = {})
111
- @year = options[:year]
158
+ options = options.stringify_keys
159
+ @year = options['year']
112
160
  end
113
-
114
161
  def apply(row)
115
162
  row.merge!({
116
163
  'make' => row['carline_mfr_name'], # make it line up with the errata
@@ -125,7 +172,6 @@ AutomobileMakeModelYearVariant.class_eval do
125
172
  })
126
173
  row
127
174
  end
128
-
129
175
  def _displacement(str)
130
176
  str = str.gsub(/[\(\)]/, '').strip
131
177
  if str =~ /^(.+)L$/
@@ -134,73 +180,14 @@ AutomobileMakeModelYearVariant.class_eval do
134
180
  $1.to_f / 1000
135
181
  end
136
182
  end
137
-
138
- def add_hints!(bus)
139
- bus[:format] = :fixed_width
140
- bus[:cut] = '13-' if year == 1995
141
- bus[:schema_name] = :fuel_economy_guide_b
142
- bus[:select] = lambda do |row|
143
- (row['suppress_code'].blank? or row['suppress_code'].to_f == 0) and row['state_code'] == 'F'
144
- end
145
- Slither.define :fuel_economy_guide_b do |d|
146
- d.rows do |row|
147
- row.trap { true } # there's only one section
148
- row.column 'active_year' , 4, :type => :integer # ACTIVE YEAR
149
- row.column 'state_code' , 1, :type => :string # STATE CODE: F=49-STATE,C=CALIFORNIA
150
- row.column 'carline_clss' , 2, :type => :integer # CARLINE CLASS CODE
151
- row.column 'carline_mfr_code' , 3, :type => :integer # CARLINE MANUFACTURER CODE
152
- row.column 'carline_name' , 28, :type => :string # CARLINE NAME
153
- row.column 'disp_cub_in' , 4, :type => :integer # DISP CUBIC INCHES
154
- row.column 'fuel_system' , 2, :type => :string # FUEL SYSTEM: 'FI' FOR FUEL INJECTION, 2-DIGIT INTEGER VALUE FOR #OF VENTURIES IF CARBURETOR SYSTEM.
155
- row.column 'model_trans' , 6, :type => :string # TRANSMISSION TYPE
156
- row.column 'no_cyc' , 2, :type => :integer # NUMBER OF ENGINE CYLINDERS
157
- row.column 'date_time' , 12, :type => :string # DATE AND TIME RECORD ENTERED -YYMMDDHHMMSS (YEAR, MONTH, DAY, HOUR, MINUTE, SECOND)
158
- row.column 'release_date' , 6, :type => :string # RELEASE DATE - YYMMDD (YEAR, MONTH, DAY)
159
- row.column 'vi_mfr_code' , 3, :type => :integer # VI MANUFACTURER CODE
160
- row.column 'carline_code' , 5, :type => :integer # CARLINE CODE
161
- row.column 'basic_eng_id' , 5, :type => :integer # BASIC ENGINE INDEX
162
- row.column 'carline_mfr_name' , 32, :type => :string # CARLINE MANUFACTURER NAME
163
- row.column 'suppress_code' , 1, :type => :integer # SUPPRESSION CODE (NO SUPPRESSED RECORD IF FOR PUBLIC ACCESS)
164
- row.column 'est_city_mpg' , 3, :type => :integer # ESTIMATED (CITY) MILES PER GALLON - 90% OF UNADJUSTED VALUE
165
- row.spacer 2
166
- row.column 'highway_mpg' , 3, :type => :integer # ESTIMATED (HWY) MILES PER GALLON - 78% OF UNADJUSTED VALUE
167
- row.spacer 2
168
- row.column 'combined_mpg' , 3, :type => :integer # COMBINED MILES PER GALLON
169
- row.spacer 2
170
- row.column 'unadj_city_mpg' , 3, :type => :integer # UNADJUSTED CITY MILES PER GALLON
171
- row.spacer 2
172
- row.column 'unadj_hwy_mpg' , 3, :type => :integer # UNADJUSTED HIGHWAY MILES PER GALLON
173
- row.spacer 2
174
- row.column 'unadj_comb_mpg' , 3, :type => :integer # UNADJUSTED COMBINED MILES PER GALLON
175
- row.spacer 2
176
- row.column 'ave_anl_fuel' , 6, :type => :integer # "$" in col 147, Annual Fuel Cost starting col 148 in I5
177
- row.column 'opt_disp' , 8, :type => :string # OPTIONAL DISPLACEMENT
178
- row.column 'engine_desc1' , 10, :type => :string # ENGINE DESCRIPTION 1
179
- row.column 'engine_desc2' , 10, :type => :string # ENGINE DESCRIPTION 2
180
- row.column 'engine_desc3' , 10, :type => :string # ENGINE DESCRIPTION 3
181
- row.column 'body_type_2d' , 10, :type => :string # BODY TYPE 2 DOOR - IF THE BODY TYPE APPLIES IT WILL TAKE THE FORM '2DR-PPP/LL' WHERE PPP=PASSENGER INTERIOR VOLUME AND LL=LUGGAGE INTERIOR VOLUME.
182
- row.column 'body_type_4d' , 10, :type => :string # BODY TYPE 4 DOOR - IF THE BODY TYPE APPLIES IT WILL TAKE THE FORM '4DR-PPP/LL' WHERE PPP=PASSENGER INTERIOR VOLUME AND LL=LUGGAGE INTERIOR VOLUME.
183
- row.column 'body_type_hbk' , 10, :type => :string # BODY TYPE HBK - IF THE BODY TYPE APPLIES IT WILL TAKE THE FORM 'HBK-PPP/LL' WHERE PPP=PASSENGER INTERIOR VOLUME AND LL=LUGGAGE INTERIOR VOLUME.
184
- row.column 'puerto_rico' , 1, :type => :string # '*' IF FOR PUERTO RICO SALES ONLY
185
- row.column 'overdrive' , 4, :type => :string # OVERDRIVE: ' OD ' FOR OVERDRIVE, 'EOD ' FOR ELECTRICALLY OPERATED OVERDRIVE AND 'AEOD' FOR AUTOMATIC OVERDRIVE
186
- row.column 'drive_system' , 3, :type => :string # FWD=FRONT WHEEL DRIVE, RWD=REAR, 4WD=4-WHEEL
187
- row.column 'filler' , 1, :type => :string # NOT USED
188
- row.column 'fuel_type' , 1, :type => :string # R=REGULAR(UNLEADED), P=PREMIUM, D=DIESEL
189
- row.column 'trans_desc' , 15, :type => :string # TRANSMISSION DESCRIPTORS
190
- end
191
- end
192
- end
193
183
  end
184
+
194
185
  class AutomobileMakeModelYearVariant::ParserC
195
- attr_accessor :year
186
+ attr_reader :year
196
187
  def initialize(options = {})
197
- @year = options[:year]
198
- end
199
-
200
- def add_hints!(bus)
201
- # File will decide format based on filename
188
+ options = options.stringify_keys
189
+ @year = options['year']
202
190
  end
203
-
204
191
  def apply(row)
205
192
  row.merge!({
206
193
  'make' => row['Manufacturer'], # make it line up with the errata
@@ -216,15 +203,13 @@ AutomobileMakeModelYearVariant.class_eval do
216
203
  row
217
204
  end
218
205
  end
206
+
219
207
  class AutomobileMakeModelYearVariant::ParserD
220
- attr_accessor :year
208
+ attr_reader :year
221
209
  def initialize(options = {})
222
- @year = options[:year]
210
+ options = options.stringify_keys
211
+ @year = options['year']
223
212
  end
224
-
225
- def add_hints!(bus)
226
- end
227
-
228
213
  def apply(row)
229
214
  row.merge!({
230
215
  'make' => row['MFR'], # make it line up with the errata
@@ -240,6 +225,7 @@ AutomobileMakeModelYearVariant.class_eval do
240
225
  row
241
226
  end
242
227
  end
228
+
243
229
  class AutomobileMakeModelYearVariant::ParserE
244
230
  OLD_FUEL_CODES = {
245
231
  'CNG' => 'C',
@@ -248,15 +234,11 @@ AutomobileMakeModelYearVariant.class_eval do
248
234
  'GP' => 'P',
249
235
  'GPR' => 'P'
250
236
  }
251
-
252
- attr_accessor :year
237
+ attr_reader :year
253
238
  def initialize(options = {})
254
- @year = options[:year]
239
+ options = options.stringify_keys
240
+ @year = options['year']
255
241
  end
256
-
257
- def add_hints!(bus)
258
- end
259
-
260
242
  def apply(row)
261
243
  row.merge!({
262
244
  'make' => row['Division'], # make it line up with the errata
@@ -317,12 +299,17 @@ AutomobileMakeModelYearVariant.class_eval do
317
299
  # FIXME TODO one Jaguar in the 1990 FEG has no model name
318
300
  # FIXME TODO 14 records in the 1995 FEG are missing fuel efficiencies
319
301
  (85..97).each do |yy|
302
+ # [85, 95, 96].each do |yy|
320
303
  filename = (yy == 96) ? "#{yy}MFGUI.ASC" : "#{yy}MFGUI.DAT"
321
304
  import("19#{ yy } Fuel Economy Guide",
322
305
  :url => "http://www.fueleconomy.gov/FEG/epadata/#{yy}mfgui.zip",
306
+ :format => :fixed_width,
307
+ :cut => ((yy == 95) ? '13-' : nil),
308
+ :schema_name => :fuel_economy_guide_b,
309
+ :select => lambda { |row| (row['suppress_code'].blank? or row['suppress_code'].to_f == 0) and row['state_code'] == 'F' },
323
310
  :filename => filename,
324
311
  :transform => { :class => AutomobileMakeModelYearVariant::ParserB, :year => "19#{yy}".to_i },
325
- :errata => 'http://static.brighterplanet.com/science/data/transport/automobiles/fuel_economy_guide/errata.csv') do
312
+ :errata => { 'url' => 'http://static.brighterplanet.com/science/data/transport/automobiles/fuel_economy_guide/errata.csv' }) do
326
313
  key 'row_hash'
327
314
  store 'name', :field_name => 'model'
328
315
  store 'make_name', :field_name => 'make'
@@ -360,7 +347,7 @@ AutomobileMakeModelYearVariant.class_eval do
360
347
  }.sort { |a, b| a.first <=> b.first }.each do |year, options|
361
348
  import "#{ year } Fuel Economy Guide",
362
349
  options.merge(:transform => { :class => AutomobileMakeModelYearVariant::ParserC, :year => year },
363
- :errata => 'http://static.brighterplanet.com/science/data/transport/automobiles/fuel_economy_guide/errata.csv') do
350
+ :errata => { 'url' => 'http://static.brighterplanet.com/science/data/transport/automobiles/fuel_economy_guide/errata.csv' }) do
364
351
  key 'row_hash'
365
352
  store 'name', :field_name => 'model'
366
353
  store 'make_name', :field_name => 'make'
@@ -393,7 +380,7 @@ AutomobileMakeModelYearVariant.class_eval do
393
380
  }.sort { |a, b| a.first <=> b.first }.each do |year, options|
394
381
  import "#{ year } Fuel Economy Guide",
395
382
  options.merge(:transform => { :class => AutomobileMakeModelYearVariant::ParserD, :year => year },
396
- :errata => 'http://static.brighterplanet.com/science/data/transport/automobiles/fuel_economy_guide/errata.csv') do
383
+ :errata => { 'url' => 'http://static.brighterplanet.com/science/data/transport/automobiles/fuel_economy_guide/errata.csv' }) do
397
384
  key 'row_hash'
398
385
  store 'name', :field_name => 'model'
399
386
  store 'make_name', :field_name => 'make'
@@ -422,7 +409,7 @@ AutomobileMakeModelYearVariant.class_eval do
422
409
  }.sort { |a, b| a.first <=> b.first }.each do |year, options|
423
410
  import "#{ year } Fuel Economy Guide",
424
411
  options.merge(:transform => { :class => AutomobileMakeModelYearVariant::ParserE, :year => year },
425
- :errata => 'http://static.brighterplanet.com/science/data/transport/automobiles/fuel_economy_guide/errata.csv') do
412
+ :errata => { 'url' => 'http://static.brighterplanet.com/science/data/transport/automobiles/fuel_economy_guide/errata.csv' }) do
426
413
  key 'row_hash'
427
414
  store 'name', :field_name => 'model'
428
415
  store 'make_name', :field_name => 'make'
@@ -4,7 +4,7 @@ class Species < ActiveRecord::Base
4
4
  scope :thoroughly_researched, :conditions => 'marginal_dietary_requirement IS NOT NULL'
5
5
 
6
6
  falls_back_on :diet_emission_intensity => lambda { weighted_average :diet_emission_intensity, :weighted_by => :population }, # kg CO2 / joule
7
- :marginal_dietary_requirement => lambda { (thoroughly_researched.map(&:weighted_diet_size).sum / thoroughly_researched.sum(:population) ) / thoroughly_researched.weighted_average(:weight, :weighted_by => :population)}, # joules
7
+ :marginal_dietary_requirement => lambda { Species.marginal_dietary_requirement_fallback },
8
8
  :fixed_dietary_requirement => 0, # force a zero intercept to be respectful of our tiny tiny animal friends
9
9
  :weight => lambda { weighted_average :weight, :weighted_by => :population } # kg
10
10
 
@@ -16,6 +16,15 @@ class Species < ActiveRecord::Base
16
16
  def [](name)
17
17
  find_by_name name.to_s
18
18
  end
19
+
20
+ def marginal_dietary_requirement_fallback
21
+ total_diet_size = thoroughly_researched.map(&:weighted_diet_size).sum
22
+ total_population = thoroughly_researched.sum(:population)
23
+ return 0.0 unless total_population > 0.0
24
+ average_weight = thoroughly_researched.weighted_average(:weight, :weighted_by => :population)
25
+ return 0.0 unless average_weight > 0.0
26
+ (total_diet_size / total_population) / average_weight
27
+ end
19
28
  end
20
29
 
21
30
  def diet_size