carbon 2.0.3 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ --no-private
2
+ --readme README.markdown
data/CHANGELOG CHANGED
@@ -1,3 +1,14 @@
1
+ 2.1.0 / 2012-03-14
2
+
3
+ * Enhancements
4
+
5
+ * Simplified API down to just Carbon.query. It has three method signatures.
6
+ * Simplified EventMachine reactor
7
+
8
+ * Breaking changes
9
+
10
+ * Simplified API down to just Carbon.query :)
11
+
1
12
  2.0.3 / 2012-03-13
2
13
 
3
14
  * Enhancements
data/Gemfile CHANGED
@@ -10,3 +10,4 @@ gem 'webmock'
10
10
  gem 'aruba'
11
11
  gem 'cucumber'
12
12
  gem 'yard'
13
+ gem 'avro'
@@ -176,10 +176,10 @@ This library includes a special console for performing calculations interactivel
176
176
  : Set the [developer key](http://keys.brighterplanet.com) that should be used for this session. Alternatively, put this key in `~/.brighter_planet` and it will be auto-selected on console startup.
177
177
 
178
178
  _emitter_
179
- : (e.g. `Flight`) Enters emitter mode using this emitter type.
179
+ : (e.g. `flight`) Enters emitter mode using this emitter type.
180
180
 
181
181
  _emitter num_
182
- : (e.g. `Flight 0`) Recalls a previous emitter from this session.
182
+ : (e.g. `flight 0`) Recalls a previous emitter from this session.
183
183
 
184
184
  `exit`
185
185
  : Quits.
data/Rakefile CHANGED
@@ -18,3 +18,32 @@ YARD::Rake::YardocTask.new do |y|
18
18
  end
19
19
 
20
20
  task :default => [:test, :cucumber]
21
+
22
+ namespace :avro do
23
+ task :setup do
24
+ require 'rubygems'
25
+ require 'bundler/setup'
26
+ require File.expand_path("../developer/avro_helper", __FILE__)
27
+ require File.expand_path("../developer/cm1_avro", __FILE__)
28
+ @cm1 = Cm1Avro::Impact.new
29
+ end
30
+ task :api_paths => 'avro:setup' do
31
+ ary = []
32
+ AvroHelper.api_paths(@cm1.avro_response_schema) { |path| ary << path }
33
+ $stdout.write ary.sort.join("\n")
34
+ end
35
+ task :json => 'avro:setup' do
36
+ $stdout.write MultiJson.encode(@cm1.avro_response_schema)
37
+ end
38
+ task :example => 'avro:setup' do
39
+ require 'tempfile'
40
+ file = Tempfile.new('com.brighterplanet.Cm1.example.avr')
41
+ parsed_schema = Avro::Schema.parse(MultiJson.encode(@cm1.avro_response_schema))
42
+ writer = Avro::IO::DatumWriter.new(parsed_schema)
43
+ dw = Avro::DataFile::Writer.new(file, writer, parsed_schema)
44
+ dw << AvroHelper.recursively_stringify_keys(@cm1.example)
45
+ dw.close
46
+ file.close
47
+ $stdout.write File.read(file.path)
48
+ end
49
+ end
@@ -0,0 +1,81 @@
1
+ require 'hashie/mash'
2
+ require 'avro'
3
+ require 'multi_json'
4
+ require 'active_support/core_ext'
5
+
6
+ module AvroHelper
7
+ SCALAR = ['boolean', 'int', 'float', 'string' ]
8
+ OPTIONAL_SCALAR = SCALAR + [ 'null' ]
9
+ OPTIONAL_STRING = ['string', 'null']
10
+
11
+ def AvroHelper.api_paths(schema, parents = nil, last_type = nil, &blk)
12
+ return unless schema.is_a?(::Hash)
13
+
14
+ schema = ::Hashie::Mash.new(schema) unless schema.is_a?(::Hashie::Mash)
15
+
16
+ my_name = schema.name
17
+
18
+ my_type = if schema.type == 'record'
19
+ my_schema = schema
20
+ schema.type
21
+ elsif schema.type.is_a?(::Hash)
22
+ my_schema = schema.type
23
+ schema.type.type
24
+ end
25
+
26
+ nested_schemas = if my_schema
27
+ case my_type
28
+ when 'array'
29
+ my_schema.items
30
+ when 'map'
31
+ my_schema.values
32
+ when 'record'
33
+ my_schema.fields
34
+ end
35
+ end
36
+ nested_schemas = Array.wrap nested_schemas
37
+
38
+ # if the last type was enumerable, then i'm anonymous
39
+ me = case last_type
40
+ when 'array'
41
+ '[]'
42
+ when 'map'
43
+ '{}'
44
+ when NilClass
45
+ nil
46
+ else
47
+ my_name
48
+ end
49
+
50
+ nested_schemas.each { |x| api_paths(x, [parents, me].flatten.compact, my_type, &blk) }
51
+
52
+ # don't try to print the top leve which will be 'v2' depending on the api version number
53
+ return unless parents
54
+
55
+ if my_name.present? and nested_schemas.none? { |x| x.is_a?(::Hash) }
56
+ children = case my_type
57
+ when 'array'
58
+ '[]'
59
+ when 'map'
60
+ '{}'
61
+ end
62
+ blk.call [parents, me, children].flatten.compact.join('.')
63
+ end
64
+ end
65
+
66
+ def AvroHelper.recursively_stringify_keys(hash)
67
+ hash.inject({}) do |result, (key, value)|
68
+ new_key = case key
69
+ when ::Symbol then key.to_s
70
+ else key
71
+ end
72
+ new_value = case value
73
+ when ::Hash then recursively_stringify_keys(value)
74
+ when ::Array then value.map { |i| i.is_a?(::Hash) ? recursively_stringify_keys(i) : i }
75
+ else value
76
+ end
77
+ result[new_key] = new_value
78
+ result
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,955 @@
1
+ require 'active_support/core_ext'
2
+ require File.expand_path('../avro_helper', __FILE__)
3
+
4
+ module Cm1Avro
5
+ class Impact
6
+ def notes
7
+ [
8
+ "All emitters return carbon (@impact_response.decisions.carbon).",
9
+ "Check emitter documentation to see what other impacts (energy, waste, etc.) are returned."
10
+ ]
11
+ end
12
+
13
+ def dns_name
14
+ 'impact.brighterplanet.com'
15
+ end
16
+
17
+ def namespace
18
+ dns_name.split('.').reverse.join('.')
19
+ end
20
+
21
+ def example
22
+ {"compliance"=>[],
23
+ "decisions"=>
24
+ {"carbon"=>
25
+ {"description"=>"78.7 kg",
26
+ "object"=>{"value"=>78.67540811299375, "units"=>"kilograms"},
27
+ "methodology"=>"from fuel use and greenhouse gas emission factor"},
28
+ "ghg_emission_factor"=>
29
+ {"description"=>"5.15214",
30
+ "object"=>5.15214,
31
+ "methodology"=>"from fuel and aviation multiplier"},
32
+ "aviation_multiplier"=>
33
+ {"description"=>"2.0", "object"=>2.0, "methodology"=>"default"},
34
+ "energy"=>
35
+ {"description"=>"574.6 MJ",
36
+ "object"=>{"value"=>574.5759972448694, "units"=>"megajoules"},
37
+ "methodology"=>"from fuel use and fuel"},
38
+ "fuel_use"=>
39
+ {"description"=>"15.270432890603466",
40
+ "object"=>15.270432890603466,
41
+ "methodology"=>
42
+ "from fuel per segment, segments per trip, trips, freight_share, passengers, seat class multiplier, fuel, date, and timeframe"},
43
+ "fuel_per_segment"=>
44
+ {"description"=>"1480.9925950502234",
45
+ "object"=>1480.9925950502234,
46
+ "methodology"=>
47
+ "from adjusted distance per segment and fuel use coefficients"},
48
+ "seat_class_multiplier"=>
49
+ {"description"=>"1.0", "object"=>1.0, "methodology"=>"default"},
50
+ "distance_class"=>
51
+ {"description"=>"short haul",
52
+ "object"=>
53
+ {"flight_distance_class"=>
54
+ {"distance"=>1108.0,
55
+ "distance_units"=>"kilometres",
56
+ "max_distance"=>3700.0,
57
+ "max_distance_units"=>"kilometres",
58
+ "min_distance"=>0.0,
59
+ "min_distance_units"=>"kilometres",
60
+ "name"=>"short haul"}},
61
+ "methodology"=>"from adjusted distance per segment"},
62
+ "adjusted_distance_per_segment"=>
63
+ {"description"=>"100.8961154095222",
64
+ "object"=>100.8961154095222,
65
+ "methodology"=>"from adjusted distance and segments per trip"},
66
+ "adjusted_distance"=>
67
+ {"description"=>"100.8961154095222",
68
+ "object"=>100.8961154095222,
69
+ "methodology"=>
70
+ "from distance, route inefficiency factor, and dogleg factor"},
71
+ "distance"=>
72
+ {"description"=>"94.29543496217028",
73
+ "object"=>94.29543496217028,
74
+ "methodology"=>"from airports"},
75
+ "route_inefficiency_factor"=>
76
+ {"description"=>"1.07", "object"=>1.07, "methodology"=>"from country"},
77
+ "dogleg_factor"=>
78
+ {"description"=>"1.0",
79
+ "object"=>1.0,
80
+ "methodology"=>"from segments per trip"},
81
+ "fuel_use_coefficients"=>
82
+ {"description"=>
83
+ "BrighterPlanet::Flight::ImpactModel::FuelUseEquation::Given",
84
+ "object"=>{"m3"=>4.986e-08, "m2"=>8.255e-05, "m1"=>5.246, "b"=>950.8},
85
+ "methodology"=>"from aircraft"},
86
+ "fuel"=>
87
+ {"description"=>"Jet Fuel",
88
+ "object"=>
89
+ {"fuel"=>
90
+ {"biogenic_fraction"=>0.0,
91
+ "carbon_content"=>18.672,
92
+ "carbon_content_units"=>"grams_per_megajoule",
93
+ "co2_biogenic_emission_factor"=>0.0,
94
+ "co2_biogenic_emission_factor_units"=>"kilograms_per_litre",
95
+ "co2_emission_factor"=>2.57607,
96
+ "co2_emission_factor_units"=>"kilograms_per_litre",
97
+ "density"=>0.8156,
98
+ "density_units"=>"kilograms_per_litre",
99
+ "energy_content"=>37.6267,
100
+ "energy_content_units"=>"megajoules_per_litre",
101
+ "name"=>"Jet Fuel",
102
+ "oxidation_factor"=>1.0,
103
+ "physical_units"=>nil}},
104
+ "methodology"=>"default"},
105
+ "passengers"=>
106
+ {"description"=>"111",
107
+ "object"=>111,
108
+ "methodology"=>"from seats and load factor"},
109
+ "seats"=>
110
+ {"description"=>"143.096",
111
+ "object"=>143.096,
112
+ "methodology"=>"from aircraft"},
113
+ "load_factor"=>
114
+ {"description"=>"0.7734122348583675",
115
+ "object"=>0.7734122348583675,
116
+ "methodology"=>"default"},
117
+ "freight_share"=>
118
+ {"description"=>"0.0665336701213722",
119
+ "object"=>0.0665336701213722,
120
+ "methodology"=>"default"},
121
+ "country"=>
122
+ {"description"=>"US",
123
+ "object"=>
124
+ {"country"=>
125
+ {"automobile_city_speed"=>32.0259,
126
+ "automobile_city_speed_units"=>"kilometres_per_hour",
127
+ "automobile_fuel_efficiency"=>9.2669,
128
+ "automobile_fuel_efficiency_units"=>"kilometres_per_litre",
129
+ "automobile_highway_speed"=>91.8935,
130
+ "automobile_highway_speed_units"=>"kilometres_per_hour",
131
+ "automobile_trip_distance"=>16.3348,
132
+ "automobile_trip_distance_units"=>"kilometres",
133
+ "automobile_urbanity"=>0.43,
134
+ "cooling_degree_days"=>882.0,
135
+ "cooling_degree_days_units"=>"degrees_celsius",
136
+ "electricity_emission_factor"=>0.589455,
137
+ "electricity_emission_factor_units"=>
138
+ "kilograms_co2e_per_kilowatt_hour",
139
+ "electricity_loss_factor"=>0.0615633,
140
+ "flight_route_inefficiency_factor"=>1.07,
141
+ "heating_degree_days"=>2159.0,
142
+ "heating_degree_days_units"=>"degrees_celsius",
143
+ "iso_3166_alpha_3_code"=>"USA",
144
+ "iso_3166_code"=>"US",
145
+ "iso_3166_numeric_code"=>840,
146
+ "lodging_district_heat_intensity"=>1.73952,
147
+ "lodging_district_heat_intensity_units"=>"megajoules_per_room_night",
148
+ "lodging_electricity_intensity"=>33.3145,
149
+ "lodging_electricity_intensity_units"=>
150
+ "kilowatt_hours_per_room_night",
151
+ "lodging_fuel_oil_intensity"=>0.411674,
152
+ "lodging_fuel_oil_intensity_units"=>"gallons_per_room_night",
153
+ "lodging_natural_gas_intensity"=>1.96714,
154
+ "lodging_natural_gas_intensity_units"=>"cubic_metres_per_room_night",
155
+ "lodging_occupancy_rate"=>0.601,
156
+ "name"=>"United States",
157
+ "rail_passengers"=>4467000000.0,
158
+ "rail_speed"=>32.4972,
159
+ "rail_speed_units"=>"kilometres_per_hour",
160
+ "rail_trip_co2_emission_factor"=>0.0957617,
161
+ "rail_trip_co2_emission_factor_units"=>
162
+ "kilograms_per_passenger_kilometre",
163
+ "rail_trip_diesel_intensity"=>0.0194247,
164
+ "rail_trip_diesel_intensity_units"=>"litres_per_passenger_kilometre",
165
+ "rail_trip_distance"=>12.9952,
166
+ "rail_trip_distance_units"=>"kilometres",
167
+ "rail_trip_electricity_intensity"=>0.140512,
168
+ "rail_trip_electricity_intensity_units"=>
169
+ "kilowatt_hours_per_passenger_kilometre"}},
170
+ "methodology"=>"from origin airport and destination airport"},
171
+ "date"=>
172
+ {"description"=>"2012-01-01",
173
+ "object"=>"2012-01-01",
174
+ "methodology"=>"from timeframe"}},
175
+ "emitter"=>"Flight",
176
+ "equivalents"=>
177
+ {"cars_off_the_road_for_a_year"=>0.014318924276564863,
178
+ "cars_off_the_road_for_a_month"=>0.17166974050255235,
179
+ "cars_off_the_road_for_a_week"=>0.743875983708356,
180
+ "cars_off_the_road_for_a_day"=>5.221372134826943,
181
+ "cars_to_priuses_for_a_year"=>0.028637848553129727,
182
+ "cars_to_priuses_for_a_month"=>0.3433394810051047,
183
+ "cars_to_priuses_for_a_week"=>1.487751967416712,
184
+ "cars_to_priuses_for_a_day"=>10.442744269653886,
185
+ "one_way_domestic_flight"=>0.25569507636722966,
186
+ "round_trip_domestic_flight"=>0.12784753818361483,
187
+ "one_way_cross_country_flight"=>0.08984731606503886,
188
+ "round_trip_cross_country_flight"=>0.04492365803251943,
189
+ "vegan_meals_instead_of_non_vegan_ones"=>63.309078128220605,
190
+ "days_of_veganism"=>21.1030260427402,
191
+ "weeks_of_veganism"=>3.014684288073694,
192
+ "months_of_veganism"=>0.7034368239382771,
193
+ "years_of_veganism"=>0.057826424963050405,
194
+ "barrels_of_petroleum"=>0.18299899927082347,
195
+ "canisters_of_bbq_propane"=>3.278168229844111,
196
+ "railroad_cars_full_of_coal"=>0.0003933770405649688,
197
+ "homes_energy_in_a_year"=>0.007631514586960394,
198
+ "homes_energy_in_a_month"=>0.09118479800295977,
199
+ "homes_energy_in_a_week"=>0.39502922413534164,
200
+ "homes_energy_in_a_day"=>2.7730721097586906,
201
+ "homes_electricity_in_a_year"=>0.011565284992610081,
202
+ "homes_electricity_in_a_month"=>0.138390042870756,
203
+ "homes_electricity_in_a_week"=>0.5996639606372384,
204
+ "homes_electricity_in_a_day"=>4.209055658637053,
205
+ "homes_with_lowered_thermostat_2_degrees_for_a_winter"=>0.4129672171851042,
206
+ "homes_with_raised_thermostat_3_degrees_for_a_summer"=>0.18567396314666526,
207
+ "replaced_refrigerators"=>0.07922613596978471,
208
+ "loads_of_cold_laundry"=>36.077552495110645,
209
+ "lightbulbs_for_a_year"=>0.14523480337658645,
210
+ "lightbulbs_for_a_month"=>1.7674430432584045,
211
+ "lightbulbs_for_a_week"=>7.574710942302812,
212
+ "lightbulbs_for_a_day"=>53.023212622344026,
213
+ "lightbulbs_for_an_evening"=>318.1393544094722,
214
+ "lightbulbs_to_CFLs_for_a_day"=>902.523055958413,
215
+ "lightbulbs_to_CFLs_for_a_week"=>128.93184265822813,
216
+ "lightbulbs_to_CFLs_for_a_month"=>30.08413858047089,
217
+ "lightbulbs_to_CFLs_for_a_year"=>2.4726894015832803,
218
+ "days_with_lightbulbs_to_CFLs"=>20.05609238698059,
219
+ "weeks_with_lightbulbs_to_CFLs"=>2.8651223372508934,
220
+ "months_with_lightbulbs_to_CFLs"=>0.6685049427361078,
221
+ "years_with_lightbulbs_to_CFLs"=>0.05491543486286964,
222
+ "recycled_kgs_of_trash"=>54.258888582166705,
223
+ "recycled_bags_of_trash"=>30.064627079258866},
224
+ "methodology"=>
225
+ "http://impact.brighterplanet.com/flights?aircraft[icao_code]=B737&airline[iata_code]=UA&destination_airport[iata_code]=ORD&origin_airport[iata_code]=MSN&segments_per_trip=1&trips=1",
226
+ "scope"=>
227
+ "The flight greenhouse gas emission is the anthropogenic greenhouse gas emissions attributed to a single passenger on this flight. It includes CO2 emissions from combustion of non-biogenic fuel and extra forcing effects of high-altitude fuel combustion.",
228
+ "timeframe"=>{"startDate"=>"2012-01-01", "endDate"=>"2013-01-01"},
229
+ "characteristics"=>
230
+ {"segments_per_trip"=>{"description"=>"1", "object"=>1},
231
+ "trips"=>{"description"=>"1", "object"=>1},
232
+ "origin_airport"=>
233
+ {"description"=>"MSN",
234
+ "object"=>
235
+ {"airport"=>
236
+ {"city"=>"Madison",
237
+ "country_iso_3166_code"=>"US",
238
+ "country_name"=>"United States",
239
+ "iata_code"=>"MSN",
240
+ "latitude"=>43.1399,
241
+ "longitude"=>-89.3375,
242
+ "name"=>"Dane County Regional Truax Field"}}},
243
+ "destination_airport"=>
244
+ {"description"=>"ORD",
245
+ "object"=>
246
+ {"airport"=>
247
+ {"city"=>"Chicago",
248
+ "country_iso_3166_code"=>"US",
249
+ "country_name"=>"United States",
250
+ "iata_code"=>"ORD",
251
+ "latitude"=>41.9786,
252
+ "longitude"=>-87.9048,
253
+ "name"=>"Chicago Ohare International"}}},
254
+ "airline"=>
255
+ {"description"=>"United Airlines",
256
+ "object"=>
257
+ {"airline"=>
258
+ {"bts_code"=>"UA",
259
+ "iata_code"=>"UA",
260
+ "icao_code"=>"UAL",
261
+ "name"=>"United Airlines"}}},
262
+ "aircraft"=>
263
+ {"description"=>"B737",
264
+ "object"=>
265
+ {"aircraft"=>
266
+ {"aircraft_type"=>"Landplane",
267
+ "b"=>950.8,
268
+ "b_units"=>"kilograms",
269
+ "class_code"=>"Medium 2 engine Jet",
270
+ "description"=>"boeing 737-700",
271
+ "engine_type"=>"Jet",
272
+ "engines"=>2,
273
+ "fuel_use_specificity"=>"aircraft",
274
+ "icao_code"=>"B737",
275
+ "m1"=>5.246,
276
+ "m1_units"=>"kilograms_per_nautical_mile",
277
+ "m2"=>8.255e-05,
278
+ "m2_units"=>"kilograms_per_square_nautical_mile",
279
+ "m3"=>4.986e-08,
280
+ "m3_units"=>"kilograms_per_cubic_nautical_mile",
281
+ "manufacturer_name"=>"BOEING",
282
+ "model_name"=>"737-700",
283
+ "passengers"=>322259000.0,
284
+ "seats"=>143.096,
285
+ "seats_specificity"=>"aircraft",
286
+ "weight_class"=>"Large"}}}},
287
+ "errors"=>[]}
288
+ end
289
+
290
+ def avro_response_schema
291
+ timeframe = {
292
+ :type => 'record',
293
+ :name => 'Timeframe',
294
+ :fields => [
295
+ { :name => 'startDate', :type => 'string' },
296
+ { :name => 'endDate', :type => 'string' },
297
+ ]
298
+ }
299
+
300
+ decision_object = {
301
+ :namespace => namespace,
302
+ :type => 'record',
303
+ :name => 'DecisionObject',
304
+ :fields => [
305
+ { :name => 'value', :type => AvroHelper::OPTIONAL_SCALAR },
306
+ { :name => 'units', :type => AvroHelper::OPTIONAL_STRING },
307
+ ]
308
+ }
309
+
310
+ characteristic_object = {
311
+ :namespace => namespace,
312
+ :type => 'record',
313
+ :name => 'CharacteristicObject',
314
+ :fields => [
315
+ { :name => 'value', :type => AvroHelper::OPTIONAL_SCALAR },
316
+ { :name => 'units', :type => AvroHelper::OPTIONAL_STRING },
317
+ ]
318
+ }
319
+
320
+
321
+ # { :type => 'map', :values => AvroHelper::OPTIONAL_SCALAR }
322
+
323
+ decision = {
324
+ :namespace => namespace,
325
+ :type => 'record',
326
+ :name => 'Decision',
327
+ :fields => [
328
+ { :name => 'description', :type => 'string' },
329
+ { :name => 'object', :type => (AvroHelper::SCALAR+[decision_object]) }, # should really be optional map
330
+ { :name => 'methodology', :type => 'string' }
331
+ ]
332
+ }
333
+
334
+ characteristic = {
335
+ :namespace => namespace,
336
+ :type => 'record',
337
+ :name => 'Characteristic',
338
+ :fields => [
339
+ { :name => 'description', :type => 'string' },
340
+ { :name => 'object', :type => (AvroHelper::SCALAR+[characteristic_object]) }, # should really be optional map
341
+ ]
342
+ }
343
+
344
+ {
345
+ :namespace => namespace,
346
+ :type => 'record',
347
+ :name => 'Response',
348
+ :fields => [
349
+ { :name => 'emitter', :type => 'string' },
350
+ { :name => 'characteristics', :type => { :type => 'map', :values => characteristic } },
351
+ { :name => 'decisions', :type => { :type => 'map', :values => decision } },
352
+ { :name => 'errors', :type => { :type => 'array', :items => 'string' } },
353
+ { :name => 'timeframe', :type => timeframe },
354
+ { :name => 'methodology', :type => 'string' },
355
+ # { :name => 'audit_id', :type => 'string' }, # paid extra
356
+ { :name => 'scope', :type => 'string' },
357
+ { :name => 'compliance', :type => { :type => 'array', :items => 'string' } },
358
+ { :name => 'equivalents', :type => { :type => 'map', :values => 'float' } },
359
+ { :name => 'certification', :type => AvroHelper::OPTIONAL_STRING },
360
+ ]
361
+ }
362
+ end
363
+ end
364
+
365
+ class Carbon
366
+ def notes
367
+ [
368
+ "DEPRECATED. Use impact.brighterplanet.com, which will give you @impact_response.decisions.carbon",
369
+ "Characteristics are mixed into the root of the response. For example: @carbon_response.origin_airport",
370
+ "Used by Brighter Planet carbon library versions < 1.2"
371
+ ]
372
+ end
373
+
374
+ def dns_name
375
+ 'carbon.brighterplanet.com'
376
+ end
377
+
378
+ def namespace
379
+ dns_name.split('.').reverse.join('.')
380
+ end
381
+
382
+ def avro_response_schema
383
+ quorum = {
384
+ :namespace => namespace,
385
+ :type => 'record',
386
+ :name => 'Quorum',
387
+ :fields => [
388
+ { :name => 'name', :type => 'string' },
389
+ { :name => 'requirements', :type => { :type => 'array', :items => 'string' } },
390
+ { :name => 'appreciates', :type => { :type => 'array', :items => 'string' } },
391
+ { :name => 'complies', :type => { :type => 'array', :items => 'string' } }
392
+ ]
393
+ }
394
+ committee_stub = {
395
+ :namespace => namespace,
396
+ :type => 'record',
397
+ :name => 'Committee',
398
+ :fields => [
399
+ { :name => 'name', :type => 'string' }
400
+ ]
401
+ }
402
+ report = {
403
+ :namespace => namespace,
404
+ :type => 'record',
405
+ :name => 'Report',
406
+ :fields => [
407
+ { :name => 'committee', :type => committee_stub },
408
+ { :name => 'conclusion', :type => AvroHelper::SCALAR },
409
+ { :name => 'quorum', :type => quorum }
410
+ ]
411
+ }
412
+ {
413
+ :namespace => namespace,
414
+ :type => 'record',
415
+ :name => 'Response',
416
+ :fields => [
417
+ # { :name => '*', :type => OPTIONAL_SCALAR }, # the characteristics mixed in with the root
418
+ { :name => 'emission', :type => 'float' },
419
+ { :name => 'emitter', :type => 'string' },
420
+ { :name => 'timeframe', :type => 'string' },
421
+ { :name => 'emission_units', :type => 'string' },
422
+ { :name => 'methodology', :type => 'string' },
423
+ { :name => 'execution_id', :type => 'string' },
424
+ { :name => 'scope', :type => 'string' },
425
+ { :name => 'complies', :type => { :type => 'array', :items => 'string' } },
426
+ { :name => 'errors', :type => { :type => 'array', :items => 'string' } },
427
+ { :name => 'equivalents', :type => { :type => 'map', :values => 'float' } },
428
+ { :name => 'reports', :type => { :type => 'array', :items => report } },
429
+ { :name => 'certification', :type => AvroHelper::OPTIONAL_STRING },
430
+ ]
431
+ }
432
+ end
433
+
434
+ def example
435
+ ActiveSupport::JSON.decode <<-EOS
436
+ {
437
+ "emission": 619.3139931256935,
438
+ "emitter": "Flight",
439
+ "timeframe": "2011-01-01/2012-01-01",
440
+ "emission_units": "kilograms",
441
+ "methodology": "http://carbon.brighterplanet.com/flights.html?destination_airport[iata_code]=SFO&origin_airport[iata_code]=JAC&timeframe=2011-01-01%2F2012-01-01",
442
+ "execution_id": "ae70601773dab95c67665d6bfbba71006c03bd9e",
443
+ "scope": "The flight emission estimate is the anthropogenic emissions per passenger from aircraft fuel combustion and radiative forcing. It includes CO2 emissions from combustion of non-biogenic fuel and extra forcing effects of high-altitude combustion.",
444
+ "complies": [],
445
+ "errors": [],
446
+ "equivalents": {
447
+ "cars_off_the_road_for_a_year": 0.11271514674887623,
448
+ "cars_off_the_road_for_a_month": 1.3513431330002632,
449
+ "cars_off_the_road_for_a_week": 5.855613805003432,
450
+ "cars_off_the_road_for_a_day": 41.101392467779775,
451
+ "cars_to_priuses_for_a_year": 0.22543029349775245,
452
+ "cars_to_priuses_for_a_month": 2.7026862660005264,
453
+ "cars_to_priuses_for_a_week": 11.711227610006864,
454
+ "cars_to_priuses_for_a_day": 82.20278493555955,
455
+ "one_way_domestic_flight": 2.012770477658504,
456
+ "round_trip_domestic_flight": 1.006385238829252,
457
+ "one_way_cross_country_flight": 0.707256580149542,
458
+ "round_trip_cross_country_flight": 0.353628290074771,
459
+ "vegan_meals_instead_of_non_vegan_ones": 498.35391918633496,
460
+ "days_of_veganism": 166.11797306211164,
461
+ "weeks_of_veganism": 23.730873588590324,
462
+ "months_of_veganism": 5.537286412536825,
463
+ "years_of_veganism": 0.4551957849473847,
464
+ "barrels_of_petroleum": 1.440524348010363,
465
+ "canisters_of_bbq_propane": 25.804956151568273,
466
+ "railroad_cars_full_of_coal": 0.0030965699656284678,
467
+ "homes_energy_in_a_year": 0.06007345733319227,
468
+ "homes_energy_in_a_month": 0.7177849180326789,
469
+ "homes_energy_in_a_week": 3.1095755594841075,
470
+ "homes_energy_in_a_day": 21.82896031570132,
471
+ "homes_electricity_in_a_year": 0.09103915698947694,
472
+ "homes_electricity_in_a_month": 1.0893733139080948,
473
+ "homes_electricity_in_a_week": 4.720411255604036,
474
+ "homes_electricity_in_a_day": 33.132679318231474,
475
+ "homes_with_lowered_thermostat_2_degrees_for_a_winter": 3.2507791499167653,
476
+ "homes_with_raised_thermostat_3_degrees_for_a_summer": 1.4615810237766367,
477
+ "replaced_refrigerators": 0.6236491910775734,
478
+ "loads_of_cold_laundry": 283.9938633157043,
479
+ "lightbulbs_for_a_year": 1.1432536313100303,
480
+ "lightbulbs_for_a_month": 13.912888855568704,
481
+ "lightbulbs_for_a_week": 59.626312630155525,
482
+ "lightbulbs_for_a_day": 417.386046353068,
483
+ "lightbulbs_for_an_evening": 2504.3168974324008,
484
+ "lightbulbs_to_CFLs_for_a_day": 7104.445608605558,
485
+ "lightbulbs_to_CFLs_for_a_week": 1014.9206242825103,
486
+ "lightbulbs_to_CFLs_for_a_month": 236.81514263338204,
487
+ "lightbulbs_to_CFLs_for_a_year": 19.46441948994742,
488
+ "days_with_lightbulbs_to_CFLs": 157.87676175558803,
489
+ "weeks_with_lightbulbs_to_CFLs": 22.55355768765838,
490
+ "months_with_lightbulbs_to_CFLs": 5.262310999589017,
491
+ "years_with_lightbulbs_to_CFLs": 0.4322811672017341,
492
+ "recycled_kgs_of_trash": 427.1129919291002,
493
+ "recycled_bags_of_trash": 236.6615527630869
494
+ },
495
+ "origin_airport": {
496
+ "airport": {
497
+ "city": "Jacksn Hole",
498
+ "country_iso_3166_code": "US",
499
+ "country_name": "United States",
500
+ "iata_code": "JAC",
501
+ "latitude": 43.6073,
502
+ "longitude": -110.738,
503
+ "name": "Jackson Hole"
504
+ }
505
+ },
506
+ "destination_airport": {
507
+ "airport": {
508
+ "city": "San Francisco",
509
+ "country_iso_3166_code": "US",
510
+ "country_name": "United States",
511
+ "iata_code": "SFO",
512
+ "latitude": 37.619,
513
+ "longitude": -122.375,
514
+ "name": "San Francisco International"
515
+ }
516
+ },
517
+ "date": "2011-01-01",
518
+ "segments_per_trip": 1.68,
519
+ "country": {
520
+ "country": {
521
+ "automobile_city_speed": 32.0259,
522
+ "automobile_city_speed_units": "kilometres_per_hour",
523
+ "automobile_fuel_efficiency": 9.2669,
524
+ "automobile_fuel_efficiency_units": "kilometres_per_litre",
525
+ "automobile_highway_speed": 91.8935,
526
+ "automobile_highway_speed_units": "kilometres_per_hour",
527
+ "automobile_trip_distance": 16.3348,
528
+ "automobile_trip_distance_units": "kilometres",
529
+ "automobile_urbanity": 0.43,
530
+ "flight_route_inefficiency_factor": 1.07,
531
+ "iso_3166_code": "US",
532
+ "name": "UNITED STATES"
533
+ }
534
+ },
535
+ "trips": 1.7,
536
+ "freight_share": 0.070644984859677,
537
+ "load_factor": 0.76992050796823,
538
+ "seats": 171.0530182753,
539
+ "passengers": 132,
540
+ "fuel": {
541
+ "fuel": {
542
+ "biogenic_fraction": 0,
543
+ "carbon_content": 18.672,
544
+ "carbon_content_units": "grams_per_megajoule",
545
+ "co2_biogenic_emission_factor": 0,
546
+ "co2_biogenic_emission_factor_units": "kilograms_per_litre",
547
+ "co2_emission_factor": 2.57607,
548
+ "co2_emission_factor_units": "kilograms_per_litre",
549
+ "density": 0.808,
550
+ "density_units": "kilograms_per_litre",
551
+ "energy_content": 37.6267,
552
+ "energy_content_units": "megajoules_per_litre",
553
+ "name": "Jet Fuel",
554
+ "oxidation_factor": 1
555
+ }
556
+ },
557
+ "fuel_use_coefficients": [
558
+ 1.0886676283223e-7,
559
+ -0.00017055946628547,
560
+ 6.9195725633675,
561
+ 1572.3367918346
562
+ ],
563
+ "dogleg_factor": 1.1638548181950328,
564
+ "route_inefficiency_factor": 1.07,
565
+ "distance": 640.3861758339607,
566
+ "adjusted_distance": 797.4886937873359,
567
+ "adjusted_distance_per_segment": 474.69565106389047,
568
+ "seat_class_multiplier": 1,
569
+ "fuel_per_segment": 4830.2396558575165,
570
+ "fuel_use": 13795.164457129067,
571
+ "aviation_multiplier": 2,
572
+ "emission_factor": 3.1882054455445545,
573
+ "reports": [
574
+ {
575
+ "committee": {
576
+ "name": "emission"
577
+ },
578
+ "conclusion": "619.3139931256935",
579
+ "quorum": {
580
+ "name": "from fuel use, emission factor, freight share, passengers, multipliers, and date",
581
+ "requirements": [
582
+ "fuel_use",
583
+ "emission_factor",
584
+ "freight_share",
585
+ "passengers",
586
+ "seat_class_multiplier",
587
+ "aviation_multiplier",
588
+ "date"
589
+ ],
590
+ "appreciates": [],
591
+ "complies": [
592
+ "ghg_protocol_scope_3",
593
+ "iso",
594
+ "tcr"
595
+ ]
596
+ }
597
+ },
598
+ {
599
+ "committee": {
600
+ "name": "emission_factor"
601
+ },
602
+ "conclusion": "3.1882054455445545",
603
+ "quorum": {
604
+ "name": "from fuel",
605
+ "requirements": [
606
+ "fuel"
607
+ ],
608
+ "appreciates": [],
609
+ "complies": [
610
+ "ghg_protocol_scope_3",
611
+ "iso",
612
+ "tcr"
613
+ ]
614
+ }
615
+ },
616
+ {
617
+ "committee": {
618
+ "name": "aviation_multiplier"
619
+ },
620
+ "conclusion": "2.0",
621
+ "quorum": {
622
+ "name": "default",
623
+ "requirements": [],
624
+ "appreciates": [],
625
+ "complies": [
626
+ "ghg_protocol_scope_3",
627
+ "iso",
628
+ "tcr"
629
+ ]
630
+ }
631
+ },
632
+ {
633
+ "committee": {
634
+ "name": "fuel_use"
635
+ },
636
+ "conclusion": "13795.164457129067",
637
+ "quorum": {
638
+ "name": "from fuel per segment and segments per trip and trips",
639
+ "requirements": [
640
+ "fuel_per_segment",
641
+ "segments_per_trip",
642
+ "trips"
643
+ ],
644
+ "appreciates": [],
645
+ "complies": [
646
+ "ghg_protocol_scope_3",
647
+ "iso",
648
+ "tcr"
649
+ ]
650
+ }
651
+ },
652
+ {
653
+ "committee": {
654
+ "name": "fuel_per_segment"
655
+ },
656
+ "conclusion": "4830.2396558575165",
657
+ "quorum": {
658
+ "name": "from adjusted distance per segment and fuel use coefficients",
659
+ "requirements": [
660
+ "adjusted_distance_per_segment",
661
+ "fuel_use_coefficients"
662
+ ],
663
+ "appreciates": [],
664
+ "complies": [
665
+ "ghg_protocol_scope_3",
666
+ "iso",
667
+ "tcr"
668
+ ]
669
+ }
670
+ },
671
+ {
672
+ "committee": {
673
+ "name": "seat_class_multiplier"
674
+ },
675
+ "conclusion": "1.0",
676
+ "quorum": {
677
+ "name": "from adjusted distance per segment",
678
+ "requirements": [
679
+ "adjusted_distance_per_segment"
680
+ ],
681
+ "appreciates": [],
682
+ "complies": [
683
+ "ghg_protocol_scope_3",
684
+ "iso",
685
+ "tcr"
686
+ ]
687
+ }
688
+ },
689
+ {
690
+ "committee": {
691
+ "name": "adjusted_distance_per_segment"
692
+ },
693
+ "conclusion": "474.69565106389047",
694
+ "quorum": {
695
+ "name": "from adjusted distance and segments per trip",
696
+ "requirements": [
697
+ "adjusted_distance",
698
+ "segments_per_trip"
699
+ ],
700
+ "appreciates": [],
701
+ "complies": [
702
+ "ghg_protocol_scope_3",
703
+ "iso",
704
+ "tcr"
705
+ ]
706
+ }
707
+ },
708
+ {
709
+ "committee": {
710
+ "name": "adjusted_distance"
711
+ },
712
+ "conclusion": "797.4886937873359",
713
+ "quorum": {
714
+ "name": "from distance, route inefficiency factor, and dogleg factor",
715
+ "requirements": [
716
+ "distance",
717
+ "route_inefficiency_factor",
718
+ "dogleg_factor"
719
+ ],
720
+ "appreciates": [],
721
+ "complies": [
722
+ "ghg_protocol_scope_3",
723
+ "iso",
724
+ "tcr"
725
+ ]
726
+ }
727
+ },
728
+ {
729
+ "committee": {
730
+ "name": "distance"
731
+ },
732
+ "conclusion": "640.3861758339607",
733
+ "quorum": {
734
+ "name": "from airports",
735
+ "requirements": [
736
+ "origin_airport",
737
+ "destination_airport"
738
+ ],
739
+ "appreciates": [],
740
+ "complies": [
741
+ "ghg_protocol_scope_3",
742
+ "iso",
743
+ "tcr"
744
+ ]
745
+ }
746
+ },
747
+ {
748
+ "committee": {
749
+ "name": "route_inefficiency_factor"
750
+ },
751
+ "conclusion": "1.07",
752
+ "quorum": {
753
+ "name": "from country",
754
+ "requirements": [
755
+ "country"
756
+ ],
757
+ "appreciates": [],
758
+ "complies": [
759
+ "ghg_protocol_scope_3",
760
+ "iso",
761
+ "tcr"
762
+ ]
763
+ }
764
+ },
765
+ {
766
+ "committee": {
767
+ "name": "dogleg_factor"
768
+ },
769
+ "conclusion": "1.1638548181950328",
770
+ "quorum": {
771
+ "name": "from segments per trip",
772
+ "requirements": [
773
+ "segments_per_trip"
774
+ ],
775
+ "appreciates": [],
776
+ "complies": [
777
+ "ghg_protocol_scope_3",
778
+ "iso",
779
+ "tcr"
780
+ ]
781
+ }
782
+ },
783
+ {
784
+ "committee": {
785
+ "name": "fuel_use_coefficients"
786
+ },
787
+ "conclusion": "#<struct BrighterPlanet::Flight::CarbonModel::FuelUseEquation m3=1.0886676283223e-07, m2=-0.00017055946628547, m1=6.9195725633675, b=1572.3367918346>",
788
+ "quorum": {
789
+ "name": "default",
790
+ "requirements": [],
791
+ "appreciates": [],
792
+ "complies": [
793
+ "ghg_protocol_scope_3",
794
+ "iso",
795
+ "tcr"
796
+ ]
797
+ }
798
+ },
799
+ {
800
+ "committee": {
801
+ "name": "fuel"
802
+ },
803
+ "conclusion": "Jet Fuel",
804
+ "quorum": {
805
+ "name": "default",
806
+ "requirements": [],
807
+ "appreciates": [],
808
+ "complies": [
809
+ "ghg_protocol_scope_3",
810
+ "iso",
811
+ "tcr"
812
+ ]
813
+ }
814
+ },
815
+ {
816
+ "committee": {
817
+ "name": "passengers"
818
+ },
819
+ "conclusion": "132",
820
+ "quorum": {
821
+ "name": "from seats and load factor",
822
+ "requirements": [
823
+ "seats",
824
+ "load_factor"
825
+ ],
826
+ "appreciates": [],
827
+ "complies": [
828
+ "ghg_protocol_scope_3",
829
+ "iso",
830
+ "tcr"
831
+ ]
832
+ }
833
+ },
834
+ {
835
+ "committee": {
836
+ "name": "seats"
837
+ },
838
+ "conclusion": "171.0530182753",
839
+ "quorum": {
840
+ "name": "default",
841
+ "requirements": [],
842
+ "appreciates": [],
843
+ "complies": [
844
+ "ghg_protocol_scope_3",
845
+ "iso",
846
+ "tcr"
847
+ ]
848
+ }
849
+ },
850
+ {
851
+ "committee": {
852
+ "name": "load_factor"
853
+ },
854
+ "conclusion": "0.76992050796823",
855
+ "quorum": {
856
+ "name": "default",
857
+ "requirements": [],
858
+ "appreciates": [],
859
+ "complies": [
860
+ "ghg_protocol_scope_3",
861
+ "iso",
862
+ "tcr"
863
+ ]
864
+ }
865
+ },
866
+ {
867
+ "committee": {
868
+ "name": "freight_share"
869
+ },
870
+ "conclusion": "0.070644984859677",
871
+ "quorum": {
872
+ "name": "default",
873
+ "requirements": [],
874
+ "appreciates": [],
875
+ "complies": [
876
+ "ghg_protocol_scope_3",
877
+ "iso",
878
+ "tcr"
879
+ ]
880
+ }
881
+ },
882
+ {
883
+ "committee": {
884
+ "name": "trips"
885
+ },
886
+ "conclusion": "1.7",
887
+ "quorum": {
888
+ "name": "default",
889
+ "requirements": [],
890
+ "appreciates": [],
891
+ "complies": [
892
+ "ghg_protocol_scope_3",
893
+ "iso",
894
+ "tcr"
895
+ ]
896
+ }
897
+ },
898
+ {
899
+ "committee": {
900
+ "name": "country"
901
+ },
902
+ "conclusion": "#<Country:0xb035ac4>",
903
+ "quorum": {
904
+ "name": "from origin airport and destination airport",
905
+ "requirements": [
906
+ "origin_airport",
907
+ "destination_airport"
908
+ ],
909
+ "appreciates": [],
910
+ "complies": [
911
+ "ghg_protocol_scope_3",
912
+ "iso",
913
+ "tcr"
914
+ ]
915
+ }
916
+ },
917
+ {
918
+ "committee": {
919
+ "name": "segments_per_trip"
920
+ },
921
+ "conclusion": "1.68",
922
+ "quorum": {
923
+ "name": "default",
924
+ "requirements": [],
925
+ "appreciates": [],
926
+ "complies": [
927
+ "ghg_protocol_scope_3",
928
+ "iso",
929
+ "tcr"
930
+ ]
931
+ }
932
+ },
933
+ {
934
+ "committee": {
935
+ "name": "date"
936
+ },
937
+ "conclusion": "2011-01-01",
938
+ "quorum": {
939
+ "name": "from timeframe",
940
+ "requirements": [],
941
+ "appreciates": [],
942
+ "complies": [
943
+ "ghg_protocol_scope_3",
944
+ "iso",
945
+ "tcr"
946
+ ]
947
+ }
948
+ }
949
+ ]
950
+ }
951
+ EOS
952
+ end
953
+ end
954
+
955
+ end