residence 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ Feature: Residence Committee Calculations
2
+ The residence model should generate correct committee calculations
3
+
4
+ Scenario Outline: Bathrooms committee
5
+ Given a residence has "full_bathrooms" of "<full_baths>"
6
+ And it has "half_bathrooms" of "<half_baths>"
7
+ When emissions are calculated
8
+ Then the bathrooms committee should be exactly <bathrooms>
9
+ Examples:
10
+ | full_baths | half_baths | bathrooms |
11
+ | 2 | 0.5 | 2.5 |
@@ -0,0 +1,14 @@
1
+ Feature: Residence Emissions Calculations
2
+ The residence model should generate correct emission calculations
3
+
4
+ Scenario Outline: Standard Calculations for residence
5
+ Given a residence has "zip_code.name" of "<zip_code>"
6
+ And it has "floorspace_estimate" of "<floorspace>"
7
+ And it has "residence_class.name" of "<residence_class>"
8
+ And it has "urbanity.name" of "<urbanity>"
9
+ And it has "dishwasher_use.name" of "<dishwasher_use>"
10
+ When emissions are calculated
11
+ Then the emission value should be within 0.1 kgs of <emission>
12
+ Examples:
13
+ | zip_code | floorspace | residence_class | urbanity | dishwasher_use | emission |
14
+ | 48915 | 1400 | Single-family detached house (a one-family house detached from any other house) | City | 4 to 6 times a week | 6068.6 |
@@ -0,0 +1,8 @@
1
+ require 'bundler'
2
+ Bundler.setup
3
+
4
+ require 'cucumber'
5
+ require 'cucumber/formatter/unicode'
6
+
7
+ require 'sniff'
8
+ Sniff.init File.join(File.dirname(__FILE__), '..', '..'), :earth => [:residence, :locality]
@@ -0,0 +1,549 @@
1
+ require 'leap'
2
+ require 'weighted_average'
3
+
4
+ module BrighterPlanet
5
+ module Residence
6
+ module CarbonModel
7
+ def self.included(base)
8
+ base.extend ::Leap::Subject
9
+ base.decide :emission, :with => :characteristics do
10
+ committee :emission do
11
+ quorum 'from fuel and electricity use and occupation and residents', :needs => [:fuel_oil_consumed, :natural_gas_consumed, :dirty_electricity_generated, :propane_consumed, :biomass_consumed, :kerosene_consumed, :coal_consumed, :residents, :electricity_emission_factor, :floorspace_estimate, :air_conditioner_use, :active_subtimeframe, :occupation] do |characteristics, timeframe|
12
+ ( characteristics[:fuel_oil_consumed] * ResidenceFuelType.find_by_name('fuel oil').emission_factor +
13
+ characteristics[:natural_gas_consumed] * ResidenceFuelType.find_by_name('natural gas').emission_factor +
14
+ characteristics[:propane_consumed] * ResidenceFuelType.find_by_name('propane').emission_factor +
15
+ characteristics[:biomass_consumed] * ResidenceFuelType.find_by_name('biomass').emission_factor +
16
+ characteristics[:kerosene_consumed] * ResidenceFuelType.find_by_name('kerosene').emission_factor +
17
+ characteristics[:coal_consumed] * ResidenceFuelType.find_by_name('coal').emission_factor +
18
+ characteristics[:dirty_electricity_generated] * characteristics[:electricity_emission_factor] +
19
+ characteristics[:floorspace_estimate] * characteristics[:air_conditioner_use].fugitive_emission * (timeframe / timeframe.year) * characteristics[:occupation]
20
+ ) *
21
+ (characteristics[:active_subtimeframe] / timeframe) / characteristics[:residents]
22
+ end
23
+
24
+ quorum 'default' do
25
+ raise "Residence's default emission quorum should never be called"
26
+ end
27
+ end
28
+
29
+ committee :fuel_oil_consumed do # returns litres
30
+ quorum 'from reports', :needs => :reported_annual_fuel_oil_consumption do |characteristics, timeframe|
31
+ characteristics[:reported_annual_fuel_oil_consumption] * (timeframe / timeframe.year)
32
+ end
33
+ quorum 'from research', :needs => [:predicted_annual_fuel_oil_consumption, :predicted_fuel_shares, :missing_annual_energy, :occupation] do |characteristics, timeframe|
34
+ (characteristics[:predicted_annual_fuel_oil_consumption] + (characteristics[:missing_annual_energy] * characteristics[:predicted_fuel_shares][:fuel_oil]).joules.to(:litres_of_fuel_oil) ) * (timeframe / timeframe.year) * characteristics[:occupation] / Residence.residence_model.fallback.occupation
35
+ end
36
+ end
37
+
38
+ committee :natural_gas_consumed do # returns joules
39
+ quorum 'from reports', :needs => :reported_annual_natural_gas_consumption do |characteristics, timeframe|
40
+ characteristics[:reported_annual_natural_gas_consumption] * (timeframe / timeframe.year)
41
+ end
42
+ quorum 'from research', :needs => [:predicted_annual_natural_gas_consumption, :predicted_fuel_shares, :missing_annual_energy, :occupation] do |characteristics, timeframe|
43
+ (characteristics[:predicted_annual_natural_gas_consumption] + (characteristics[:missing_annual_energy] * characteristics[:predicted_fuel_shares][:natural_gas])) * (timeframe / timeframe.year) * characteristics[:occupation] / Residence.residence_model.fallback.occupation
44
+ end
45
+ end
46
+
47
+ committee :propane_consumed do # returns litres
48
+ quorum 'from reports', :needs => :reported_annual_propane_consumption do |characteristics, timeframe|
49
+ characteristics[:reported_annual_propane_consumption] * (timeframe / timeframe.year)
50
+ end
51
+ quorum 'from research', :needs => [:predicted_annual_propane_consumption, :predicted_fuel_shares, :missing_annual_energy, :occupation] do |characteristics, timeframe|
52
+ (characteristics[:predicted_annual_propane_consumption] + (characteristics[:missing_annual_energy] * characteristics[:predicted_fuel_shares][:propane]).joules.to(:litres_of_propane)) * (timeframe / timeframe.year) * characteristics[:occupation] / Residence.residence_model.fallback.occupation
53
+ end
54
+ end
55
+
56
+ committee :biomass_consumed do # returns joules
57
+ quorum 'from reports', :needs => :reported_annual_biomass_consumption do |characteristics, timeframe|
58
+ characteristics[:reported_annual_biomass_consumption] * (timeframe / timeframe.year)
59
+ end
60
+ quorum 'from research', :needs => [:predicted_annual_biomass_consumption, :predicted_fuel_shares, :missing_annual_energy, :occupation] do |characteristics, timeframe|
61
+ (characteristics[:predicted_annual_biomass_consumption] + (characteristics[:missing_annual_energy] * characteristics[:predicted_fuel_shares][:biomass])) * (timeframe / timeframe.year) * characteristics[:occupation] / Residence.residence_model.fallback.occupation
62
+ end
63
+ end
64
+
65
+ committee :kerosene_consumed do # returns litres
66
+ quorum 'from reports', :needs => :reported_annual_kerosene_consumption do |characteristics, timeframe|
67
+ characteristics[:reported_annual_kerosene_consumption] * (timeframe / timeframe.year)
68
+ end
69
+ quorum 'from research', :needs => [:predicted_annual_kerosene_consumption, :predicted_fuel_shares, :missing_annual_energy, :occupation] do |characteristics, timeframe|
70
+ (characteristics[:predicted_annual_kerosene_consumption] + (characteristics[:missing_annual_energy] * characteristics[:predicted_fuel_shares][:kerosene]).joules.to(:litres_of_kerosene)) * (timeframe / timeframe.year) * characteristics[:occupation] / Residence.residence_model.fallback.occupation
71
+ end
72
+ end
73
+
74
+ committee :coal_consumed do # returns kg
75
+ quorum 'from reports', :needs => :reported_annual_coal_consumption do |characteristics, timeframe|
76
+ characteristics[:reported_annual_coal_consumption] * (timeframe / timeframe.year)
77
+ end
78
+ quorum 'from research', :needs => [:predicted_annual_coal_consumption, :predicted_fuel_shares, :missing_annual_energy, :occupation] do |characteristics, timeframe|
79
+ (characteristics[:predicted_annual_coal_consumption] + (characteristics[:missing_annual_energy] * characteristics[:predicted_fuel_shares][:coal]).joules.to(:kilograms_of_coal)) * (timeframe / timeframe.year) * characteristics[:occupation] / Residence.residence_model.fallback.occupation
80
+ end
81
+ end
82
+
83
+ committee :dirty_electricity_generated do
84
+ quorum 'from electricity generated and green electricity', :needs => [:electricity_generated, :green_electricity] do |characteristics|
85
+ characteristics[:electricity_generated] * (1.0 - characteristics[:green_electricity])
86
+ end
87
+ end
88
+
89
+ committee :green_electricity do
90
+ quorum 'default' do
91
+ Residence.residence_model.fallback.green_electricity
92
+ end
93
+ end
94
+
95
+ committee :electricity_generated do # returns kWh
96
+ quorum 'from electricity used and loss rate', :needs => [:electricity_used, :electricity_loss_rate] do |characteristics|
97
+ characteristics[:electricity_used] / (1.0 - characteristics[:electricity_loss_rate])
98
+ end
99
+ end
100
+
101
+ committee :electricity_used do # returns kWh
102
+ quorum 'from reports', :needs => :reported_annual_electricity_use do |characteristics, timeframe|
103
+ characteristics[:reported_annual_electricity_use] * (timeframe / timeframe.year)
104
+ end
105
+
106
+ quorum 'from research', :needs => [:predicted_annual_electricity_use, :predicted_fuel_shares, :missing_annual_energy, :occupation] do |characteristics, timeframe|
107
+ (characteristics[:predicted_annual_electricity_use] + ((characteristics[:missing_annual_energy] * characteristics[:predicted_fuel_shares][:electricity]).joules.to(:kilowatt_hours))) * (timeframe / timeframe.year) * characteristics[:occupation] / Residence.residence_model.fallback.occupation
108
+ end
109
+ end
110
+
111
+ committee :missing_annual_energy do # returns joules
112
+ quorum 'from fuel reports', :needs => [:predicted_annual_fuel_oil_consumption, :predicted_annual_natural_gas_consumption, :predicted_annual_propane_consumption, :predicted_annual_kerosene_consumption, :predicted_annual_biomass_consumption, :predicted_annual_coal_consumption, :predicted_annual_electricity_use], :appreciates => [:reported_annual_fuel_oil_consumption, :reported_annual_natural_gas_consumption, :reported_annual_propane_consumption, :reported_annual_kerosene_consumption, :reported_annual_biomass_consumption, :reported_annual_coal_consumption, :reported_annual_electricity_use] do |characteristics|
113
+ energy = 0
114
+ if characteristics[:reported_annual_fuel_oil_consumption] and characteristics[:reported_annual_fuel_oil_consumption].zero?
115
+ energy += characteristics[:predicted_annual_fuel_oil_consumption].litres_of_fuel_oil.to :joules
116
+ end
117
+ if characteristics[:reported_annual_natural_gas_consumption] and characteristics[:reported_annual_natural_gas_consumption].zero?
118
+ energy += characteristics[:predicted_annual_natural_gas_consumption]
119
+ end
120
+ if characteristics[:reported_annual_propane_consumption] and characteristics[:reported_annual_propane_consumption].zero?
121
+ energy += characteristics[:predicted_annual_propane_consumption].litres_of_propane.to :joules
122
+ end
123
+ if characteristics[:reported_annual_kerosene_consumption] and characteristics[:reported_annual_kerosene_consumption].zero?
124
+ energy += characteristics[:predicted_annual_kerosene_consumption].litres_of_kerosene.to :joules
125
+ end
126
+ if characteristics[:reported_annual_biomass_consumption] and characteristics[:reported_annual_biomass_consumption].zero?
127
+ energy += characteristics[:predicted_annual_biomass_consumption]
128
+ end
129
+ if characteristics[:reported_annual_coal_consumption] and characteristics[:reported_annual_coal_consumption].zero?
130
+ energy += characteristics[:predicted_annual_coal_consumption].kilograms_of_coal.to :joules
131
+ end
132
+ if characteristics[:reported_annual_electricity_use] and characteristics[:reported_annual_electricity_use].zero?
133
+ energy += characteristics[:predicted_annual_electricity_use].kilowatt_hours.to :joules
134
+ end
135
+ energy
136
+ end
137
+ end
138
+
139
+ committee :electricity_loss_rate do # returns percentage
140
+ quorum 'from egrid region', :needs => :egrid_region do |characteristics|
141
+ characteristics[:egrid_region].loss_factor
142
+ end
143
+
144
+ quorum 'default' do
145
+ EgridRegion.fallback.loss_factor
146
+ end
147
+ end
148
+
149
+ committee :electricity_emission_factor do # returns kg CO2 / kWh
150
+ quorum 'from egrid subregion', :needs => :egrid_subregion do |characteristics|
151
+ characteristics[:egrid_subregion].electricity_emission_factor
152
+ end
153
+
154
+ quorum 'default' do
155
+ EgridSubregion.fallback.electricity_emission_factor
156
+ end
157
+ end
158
+
159
+ committee :egrid_region do
160
+ quorum 'from egrid subregion', :needs => :egrid_subregion do |characteristics|
161
+ characteristics[:egrid_subregion].egrid_region
162
+ end
163
+ end
164
+
165
+ committee :egrid_subregion do
166
+ quorum 'from_zip_code', :needs => :zip_code do |characteristics|
167
+ characteristics[:zip_code].egrid_subregion
168
+ end
169
+ end
170
+
171
+ committee :occupation do
172
+ quorum 'default' do
173
+ Residence.residence_model.fallback.occupation
174
+ end
175
+ end
176
+
177
+ committee :residents do
178
+ quorum 'from cohort', :needs => :cohort do |characteristics|
179
+ characteristics[:cohort].weighted_average :residents
180
+ end
181
+
182
+ quorum 'default' do
183
+ Residence.residence_model.fallback.residents_before_type_cast
184
+ end
185
+ end
186
+
187
+ committee :air_conditioner_use do
188
+ quorum 'default' do
189
+ AirConditionerUse.fallback
190
+ end
191
+ end
192
+
193
+ committee :predicted_fuel_shares do # returns an array of percentages
194
+ quorum 'from research', :needs => [:predicted_annual_energy_consumption, :predicted_annual_fuel_oil_consumption, :predicted_annual_natural_gas_consumption, :predicted_annual_propane_consumption, :predicted_annual_kerosene_consumption, :predicted_annual_biomass_consumption, :predicted_annual_coal_consumption, :predicted_annual_electricity_use] do |characteristics|
195
+ {
196
+ :fuel_oil => characteristics[:predicted_annual_fuel_oil_consumption].litres_of_fuel_oil.to(:joules) / characteristics[:predicted_annual_energy_consumption],
197
+ :natural_gas => characteristics[:predicted_annual_natural_gas_consumption] / characteristics[:predicted_annual_energy_consumption],
198
+ :propane => characteristics[:predicted_annual_propane_consumption].litres_of_propane.to(:joules) / characteristics[:predicted_annual_energy_consumption],
199
+ :kerosene => characteristics[:predicted_annual_kerosene_consumption].litres_of_kerosene.to(:joules) / characteristics[:predicted_annual_energy_consumption],
200
+ :biomass => characteristics[:predicted_annual_biomass_consumption] / characteristics[:predicted_annual_energy_consumption],
201
+ :coal => characteristics[:predicted_annual_coal_consumption].kilograms_of_coal.to(:joules) / characteristics[:predicted_annual_energy_consumption],
202
+ :electricity => characteristics[:predicted_annual_electricity_use].kilowatt_hours.to(:joules) / characteristics[:predicted_annual_energy_consumption]
203
+ }
204
+ end
205
+ end
206
+
207
+ committee :predicted_annual_energy_consumption do # returns BTUs
208
+ quorum 'from research', :needs => [:predicted_annual_fuel_oil_consumption, :predicted_annual_natural_gas_consumption, :predicted_annual_propane_consumption, :predicted_annual_kerosene_consumption, :predicted_annual_biomass_consumption, :predicted_annual_coal_consumption, :predicted_annual_electricity_use] do |characteristics|
209
+ energy = 0
210
+ energy += characteristics[:predicted_annual_fuel_oil_consumption].litres_of_fuel_oil.to :joules
211
+ energy += characteristics[:predicted_annual_natural_gas_consumption]
212
+ energy += characteristics[:predicted_annual_propane_consumption].litres_of_propane.to :joules
213
+ energy += characteristics[:predicted_annual_kerosene_consumption].litres_of_kerosene.to :joules
214
+ energy += characteristics[:predicted_annual_biomass_consumption]
215
+ energy += characteristics[:predicted_annual_coal_consumption].kilograms_of_coal.to :joules
216
+ energy += characteristics[:predicted_annual_electricity_use].kilowatt_hours.to :joules
217
+ end
218
+ end
219
+
220
+ committee :reported_annual_fuel_oil_consumption do # returns litres
221
+ quorum 'from volume estimate', :needs => :annual_fuel_oil_volume_estimate do |characteristics|
222
+ characteristics[:annual_fuel_oil_volume_estimate]
223
+ end
224
+
225
+ quorum 'from cost', :needs => :annual_fuel_oil_cost, :appreciates => :state do |characteristics, timeframe|
226
+ relaxations = []
227
+ relaxations << { :timeframe => timeframe, :location => characteristics[:state] } if characteristics[:state]
228
+ relaxations << { :timeframe => timeframe.last_year, :location => characteristics[:state] } if characteristics[:state]
229
+ relaxations << { :timeframe => timeframe, :location => Country.united_states }
230
+ relaxations << { :timeframe => timeframe.last_year, :location => Country.united_states }
231
+ if price_per_unit = ResidenceFuelType[:fuel_oil].price_per_unit(relaxations)
232
+ characteristics[:annual_fuel_oil_cost] / price_per_unit
233
+ else
234
+ nil
235
+ end
236
+ end
237
+ end
238
+
239
+ committee :predicted_annual_fuel_oil_consumption do # returns litres
240
+ quorum 'from cohort', :needs => :cohort do |characteristics|
241
+ characteristics[:cohort].weighted_average(%w(heating_space heating_water appliances).map { |purpose| "annual_energy_from_fuel_oil_for_#{purpose}".to_sym }).to_f.joules.to(:litres_of_fuel_oil)
242
+ end
243
+
244
+ quorum 'default' do
245
+ Residence.residence_model.fallback.annual_fuel_oil_volume_estimate
246
+ end
247
+ end
248
+
249
+ committee :reported_annual_natural_gas_consumption do # returns joules
250
+ quorum 'from volume estimate', :needs => :monthly_natural_gas_volume_estimate do |characteristics|
251
+ characteristics[:monthly_natural_gas_volume_estimate] * 12
252
+ end
253
+
254
+ quorum 'from cost', :needs => :monthly_natural_gas_cost, :appreciates => :state do |characteristics, timeframe|
255
+ relaxations = []
256
+ relaxations << { :timeframe => timeframe, :location => characteristics[:state] } if characteristics[:state]
257
+ relaxations << { :timeframe => timeframe.last_year, :location => characteristics[:state] } if characteristics[:state]
258
+ relaxations << { :timeframe => timeframe, :location => Country.united_states }
259
+ relaxations << { :timeframe => timeframe.last_year, :location => Country.united_states }
260
+ if price_per_unit = ResidenceFuelType[:natural_gas].price_per_unit(relaxations) #FIXME joules vs. cubic metres issue
261
+ characteristics[:monthly_natural_gas_cost] * 12 / price_per_unit
262
+ else
263
+ nil
264
+ end
265
+ end
266
+ end
267
+
268
+ committee :predicted_annual_natural_gas_consumption do # returns joules
269
+ quorum 'from cohort', :needs => :cohort do |characteristics|
270
+ characteristics[:cohort].weighted_average(%w(heating_space heating_water appliances).map { |purpose| "annual_energy_from_natural_gas_for_#{purpose}".to_sym }).to_f
271
+ end
272
+
273
+ quorum 'default' do
274
+ Residence.residence_model.fallback.monthly_natural_gas_volume_estimate * 12
275
+ end
276
+ end
277
+
278
+ committee :reported_annual_propane_consumption do # returns litres
279
+ quorum 'from volume estimate', :needs => :annual_propane_volume_estimate do |characteristics|
280
+ characteristics[:annual_propane_volume_estimate]
281
+ end
282
+
283
+ quorum 'from cost', :needs => :annual_propane_cost, :appreciates => :state do |characteristics, timeframe|
284
+ relaxations = []
285
+ relaxations << { :timeframe => timeframe, :location => characteristics[:state].petroleum_administration_for_defense_district } if characteristics[:state]
286
+ relaxations << { :timeframe => timeframe.last_year, :location => characteristics[:state].petroleum_administration_for_defense_district } if characteristics[:state]
287
+ relaxations << { :timeframe => timeframe, :location => Country.united_states }
288
+ relaxations << { :timeframe => timeframe.last_year, :location => Country.united_states }
289
+ if price_per_unit = ResidenceFuelType[:propane].price_per_unit(relaxations)
290
+ characteristics[:annual_propane_cost] / price_per_unit
291
+ else
292
+ nil
293
+ end
294
+ end
295
+ end
296
+
297
+ committee :predicted_annual_propane_consumption do # returns litres
298
+ quorum 'from cohort', :needs => :cohort do |characteristics|
299
+ characteristics[:cohort].weighted_average(%w(heating_space heating_water appliances).map { |purpose| "annual_energy_from_propane_for_#{purpose}".to_sym }).to_f.joules.to(:litres_of_propane)
300
+ end
301
+
302
+ quorum 'default' do
303
+ Residence.residence_model.fallback.annual_propane_volume_estimate
304
+ end
305
+ end
306
+
307
+ committee :reported_annual_kerosene_consumption do # returns litres
308
+ quorum 'from volume estimate', :needs => :annual_kerosene_volume_estimate do |characteristics|
309
+ characteristics[:annual_kerosene_volume_estimate]
310
+ end
311
+ end
312
+
313
+ committee :predicted_annual_kerosene_consumption do # returns litres
314
+ quorum 'from cohort', :needs => :cohort do |characteristics|
315
+ characteristics[:cohort].weighted_average(:annual_energy_from_kerosene).to_f.joules.to(:litres_of_kerosene)
316
+ end
317
+
318
+ quorum 'default' do
319
+ Residence.residence_model.fallback.annual_kerosene_volume_estimate
320
+ end
321
+ end
322
+
323
+ committee :reported_annual_biomass_consumption do # returns joules
324
+ quorum 'from volume estimate', :needs => :annual_wood_volume_estimate do |characteristics|
325
+ characteristics[:annual_wood_volume_estimate]
326
+ end
327
+ end
328
+
329
+ committee :predicted_annual_biomass_consumption do # returns joules
330
+ quorum 'from cohort', :needs => :cohort do |characteristics|
331
+ characteristics[:cohort].weighted_average(:annual_energy_from_wood)
332
+ end
333
+
334
+ quorum 'default' do
335
+ Residence.residence_model.fallback.annual_wood_volume_estimate
336
+ end
337
+ end
338
+
339
+ committee :reported_annual_coal_consumption do # returns kg
340
+ quorum 'from volume estimate', :needs => :annual_coal_volume_estimate do |characteristics|
341
+ characteristics[:annual_coal_volume_estimate]
342
+ end
343
+ end
344
+
345
+ committee :predicted_annual_coal_consumption do # returns kg
346
+ quorum 'default' do
347
+ Residence.residence_model.fallback.annual_coal_volume_estimate
348
+ end
349
+ end
350
+
351
+ committee :reported_annual_electricity_use do # returns kWh
352
+ quorum 'from use estimate', :needs => :monthly_electricity_use_estimate do |characteristics|
353
+ characteristics[:monthly_electricity_use_estimate] * 12
354
+ end
355
+
356
+ quorum 'from cost', :needs => :monthly_electricity_cost, :appreciates => :state do |characteristics, timeframe|
357
+ relaxations = []
358
+ relaxations << { :timeframe => timeframe, :location => characteristics[:state] } if characteristics[:state]
359
+ relaxations << { :timeframe => timeframe.last_year, :location => characteristics[:state] } if characteristics[:state]
360
+ relaxations << { :timeframe => timeframe, :location => Country.united_states }
361
+ relaxations << { :timeframe => timeframe.last_year, :location => Country.united_states }
362
+ if price_per_unit = ResidenceFuelType[:electricity].price_per_unit(relaxations)
363
+ characteristics[:monthly_electricity_cost] * 12 / price_per_unit
364
+ else
365
+ nil
366
+ end
367
+ end
368
+ end
369
+
370
+ committee :predicted_annual_electricity_use do # returns kWh
371
+ quorum 'from cohort', :needs => :cohort, :appreciates => [:clothes_machine_use, :refrigerator_count, :freezer_count, :dishwasher_use, :lighting_efficiency] do |characteristics|
372
+ cohort = characteristics[:cohort]
373
+ energy = cohort.weighted_average([:annual_energy_from_electricity_for_clothes_driers,
374
+ :annual_energy_from_electricity_for_dishwashers,
375
+ :annual_energy_from_electricity_for_freezers,
376
+ :annual_energy_from_electricity_for_refrigerators,
377
+ :annual_energy_from_electricity_for_air_conditioners,
378
+ :annual_energy_from_electricity_for_heating_space,
379
+ :annual_energy_from_electricity_for_heating_water,
380
+ :annual_energy_from_electricity_for_other_appliances]).to_f
381
+
382
+ if clothes_machine_use = characteristics[:clothes_machine_use]
383
+ energy -= cohort.weighted_average(:annual_energy_from_electricity_for_clothes_driers)
384
+ clothes_machine_use_cohort = ResidentialEnergyConsumptionSurveyResponse.big_cohort(characteristics.slice(*([:clothes_machine_use].push(*ResidentialEnergyConsumptionSurveyResponse::INPUT_CHARACTERISTICS))), ResidentialEnergyConsumptionSurveyResponse::SUBCOHORT_THRESHOLD)
385
+ if clothes_machine_use_cohort.any?
386
+ energy += clothes_machine_use_cohort.weighted_average(:annual_energy_from_electricity_for_clothes_driers).to_f
387
+ else
388
+ energy += charcteristics[:clothes_machine_use].annual_energy_from_electricity_for_clothes_driers
389
+ end
390
+ end
391
+
392
+ if refrigerator_count = characteristics[:refrigerator_count]
393
+ energy -= cohort.weighted_average(:annual_energy_from_electricity_for_refrigerators)
394
+ if refrigerator_count == 0
395
+ energy += 0
396
+ else
397
+ refrigerator_count_subcohort = ResidentialEnergyConsumptionSurveyResponse.big_cohort(characteristics.slice(*([:refrigerator_count].push(*ResidentialEnergyConsumptionSurveyResponse::INPUT_CHARACTERISTICS))), ResidentialEnergyConsumptionSurveyResponse::SUBCOHORT_THRESHOLD)
398
+ if refrigerator_count_subcohort.any?
399
+ energy += refrigerator_count_subcohort.weighted_average(:annual_energy_from_electricity_for_refrigerators).to_f
400
+ else
401
+ energy += refrigerator_count * ResidenceAppliance.annual_energy_from_electricity_for(:refrigerators)
402
+ end
403
+ end
404
+ end
405
+
406
+ if freezer_count = characteristics[:freezer_count]
407
+ energy -= cohort.weighted_average(:annual_energy_from_electricity_for_freezers)
408
+ if freezer_count == 0
409
+ energy += 0
410
+ else
411
+ freezer_count_subcohort = ResidentialEnergyConsumptionSurveyResponse.big_cohort(characteristics.slice(*([:freezer_count].push(*ResidentialEnergyConsumptionSurveyResponse::INPUT_CHARACTERISTICS))), ResidentialEnergyConsumptionSurveyResponse::SUBCOHORT_THRESHOLD)
412
+ if freezer_count_subcohort.any?
413
+ energy += freezer_count_subcohort.weighted_average(:annual_energy_from_electricity_for_freezers).to_f
414
+ else
415
+ energy += freezer_count * ResidenceAppliance.annual_energy_from_electricity_for(:freezers)
416
+ end
417
+ end
418
+ end
419
+
420
+ if dishwasher_use = characteristics[:dishwasher_use]
421
+ energy -= cohort.weighted_average(:annual_energy_from_electricity_for_dishwashers)
422
+ dishwasher_use_cohort = ResidentialEnergyConsumptionSurveyResponse.big_cohort(characteristics.slice(*([:dishwasher_use].push(*ResidentialEnergyConsumptionSurveyResponse::INPUT_CHARACTERISTICS))), ResidentialEnergyConsumptionSurveyResponse::SUBCOHORT_THRESHOLD)
423
+ if dishwasher_use_cohort.any?
424
+ energy += dishwasher_use_cohort.weighted_average(:annual_energy_from_electricity_for_dishwashers).to_f
425
+ else
426
+ energy += characteristics[:dishwasher_use].annual_energy_from_electricity_for_dishwashers
427
+ end
428
+ end
429
+
430
+ if lighting_efficiency = characteristics[:lighting_efficiency]
431
+ lighting_electricity_use_in_cohort =
432
+ cohort.weighted_average(:lighting_efficiency) * cohort.weighted_average(:lighting_use) * research(:efficient_lightbulb_power) +
433
+ (1 - cohort.weighted_average(:lighting_efficiency)) * cohort.weighted_average(:lighting_use) * research(:standard_lightbulb_power)
434
+ energy -= lighting_electricity_use_in_cohort.watt_hours.to :joules
435
+ lighting_electricity_use_in_residence =
436
+ lighting_efficiency * cohort.weighted_average(:lighting_use) * research(:efficient_lightbulb_power) +
437
+ (1 - lighting_efficiency) * cohort.weighted_average(:lighting_use) * research(:standard_lightbulb_power)
438
+ energy += lighting_electricity_use_in_residence.watt_hours.to :joules
439
+ end
440
+
441
+ energy.joules.to(:kilowatt_hours)
442
+ end
443
+
444
+ quorum 'default' do
445
+ Residence.residence_model.fallback.monthly_electricity_use_estimate * 12
446
+ end
447
+ end
448
+
449
+ committee :active_subtimeframe do
450
+ quorum 'from acquisition and retirement', :needs => [:acquisition, :retirement] do |characteristics, timeframe|
451
+ Timeframe.constrained_new characteristics[:acquisition].to_date, characteristics[:retirement].to_date, timeframe
452
+ end
453
+ end
454
+
455
+ committee :acquisition do
456
+ quorum 'from construction year', :needs => :construction_year do |characteristics|
457
+ #FIXME this is an imperfect substitution for a line in https://app1.yerba.brighterplanet.com/changesets/9463
458
+ characteristics[:construction_year] - 1.year
459
+ end
460
+ quorum 'from retirement', :appreciates => :retirement do |characteristics, timeframe|
461
+ [ timeframe.from, characteristics[:retirement] ].compact.min
462
+ end
463
+ end
464
+
465
+ committee :retirement do
466
+ quorum 'from acquisition', :appreciates => :acquisition do |characteristics, timeframe|
467
+ [ timeframe.to, characteristics[:acquisition] ].compact.max
468
+ end
469
+ end
470
+
471
+ # This is kindof "hacky"
472
+ # As implemented, this needs to be above floorspace committee or else cohort will always
473
+ # use the Residence.residence_model.fallback
474
+ committee :floorspace_estimate do
475
+ quorum 'from cohort', :needs => :cohort do |characteristics|
476
+ characteristics[:cohort].weighted_average :floorspace
477
+ end
478
+
479
+ quorum 'default' do
480
+ Residence.residence_model.fallback.floorspace_estimate
481
+ end
482
+ end
483
+
484
+ committee :cohort do
485
+ quorum 'from residential energy consumption survey', :appreciates => ResidentialEnergyConsumptionSurveyResponse::INPUT_CHARACTERISTICS do |characteristics|
486
+ cohort = ResidentialEnergyConsumptionSurveyResponse.big_cohort characteristics
487
+ if cohort.any?
488
+ cohort
489
+ else
490
+ nil
491
+ end
492
+ end
493
+ end
494
+
495
+ committee :bathrooms do
496
+ quorum 'from fractional bathroom counts', :needs => [:full_bathrooms, :half_bathrooms] do |characteristics|
497
+ characteristics[:full_bathrooms] + 0.5 * characteristics[:half_bathrooms]
498
+ end
499
+ end
500
+
501
+ committee :census_region do
502
+ quorum 'from census division', :needs => :census_division do |characteristics|
503
+ characteristics[:census_division].census_region
504
+ end
505
+ end
506
+
507
+ committee :census_division do
508
+ quorum 'from state', :needs => :state do |characteristics|
509
+ characteristics[:state].census_division
510
+ end
511
+ end
512
+
513
+ committee :state do
514
+ quorum 'from climate division', :needs => :climate_division do |characteristics|
515
+ characteristics[:climate_division].state
516
+ end
517
+ end
518
+
519
+ committee :floorspace do # returns a Range of floorspaces
520
+ quorum 'from floorspace estimate', :needs => :floorspace_estimate do |characteristics|
521
+ floorspace_estimate = characteristics[:floorspace_estimate]
522
+ (floorspace_estimate - 50)..(floorspace_estimate + 50)
523
+ end
524
+ end
525
+
526
+ committee :heating_degree_days do # returns a Range of degree-days
527
+ quorum 'from climate division', :needs => :climate_division do |characteristics|
528
+ days = characteristics[:climate_division].heating_degree_days
529
+ (days - ClimateDivision::RADIUS)..(days + ClimateDivision::RADIUS)
530
+ end
531
+ end
532
+
533
+ committee :cooling_degree_days do
534
+ quorum 'from climate division', :needs => :climate_division do |characteristics|
535
+ days = characteristics[:climate_division].cooling_degree_days
536
+ (days - ClimateDivision::RADIUS)..(days + ClimateDivision::RADIUS)
537
+ end
538
+ end
539
+
540
+ committee :climate_division do
541
+ quorum 'from zip code', :needs => :zip_code do |characteristics|
542
+ characteristics[:zip_code].climate_division
543
+ end
544
+ end
545
+ end
546
+ end
547
+ end
548
+ end
549
+ end
@@ -0,0 +1,49 @@
1
+ require 'characterizable'
2
+
3
+ module BrighterPlanet
4
+ module Residence
5
+ module Characterization
6
+ def self.included(base)
7
+ base.send :include, Characterizable
8
+ base.characterize do
9
+ has :zip_code
10
+ has :urbanity
11
+ has :ownership
12
+ has :residence_class
13
+ has :residents
14
+ has :clothes_machine_use
15
+ has :dishwasher_use
16
+ has :air_conditioner_use
17
+ has :refrigerator_count
18
+ has :freezer_count
19
+ has :lighting_efficiency, :measures => :percentage
20
+ has :floorspace_estimate, :trumps => :rooms, :measures => :area
21
+ has :floors # not used
22
+ has :bathrooms
23
+ has :bedrooms
24
+ has :full_bathrooms, :hidden => true
25
+ has :half_bathrooms, :hidden => true
26
+ has :rooms, :trumps => [:bathrooms, :bedrooms, :full_bathrooms, :half_bathrooms]
27
+ has :acquisition
28
+ has :retirement
29
+ has :construction_year # TODO show year only
30
+ has :occupation, :measures => :percentage
31
+ has :annual_fuel_oil_volume_estimate, :trumps => :annual_fuel_oil_cost, :measures => :volume
32
+ has :annual_fuel_oil_cost, :trumps => :annual_fuel_oil_volume_estimate, :measures => :cost
33
+ has :monthly_natural_gas_volume_estimate, :trumps => :monthly_natural_gas_cost, :measurement_options => { :external => :therms, :internal => :joules }
34
+ has :monthly_natural_gas_cost, :trumps => :monthly_natural_gas_volume_estimate, :measures => :cost
35
+ has :monthly_electricity_use_estimate, :trumps => :monthly_electricity_cost, :measures => :electrical_energy
36
+ has :monthly_electricity_cost, :trumps => :monthly_electricity_use_estimate, :measures => :cost
37
+ has :green_electricity, :measures => :percentage
38
+ has :annual_propane_volume_estimate, :trumps => :annual_propane_cost, :measures => :volume
39
+ has :annual_propane_cost, :trumps => :annual_propane_volume_estimate, :measures => :cost
40
+ has :annual_wood_volume_estimate, :measures => :biomass
41
+ has :annual_kerosene_volume_estimate, :trumps => :annual_kerosene_cost, :measures => :volume
42
+ has :annual_coal_volume_estimate, :trumps => :annual_coal_cost, :measures => :mass # it says volume, but it wants mass
43
+ # has :annual_coal_cost, :trumps => :annual_coal_volume_estimate, :measures => :cost
44
+ end
45
+ base.add_implicit_characteristics
46
+ end
47
+ end
48
+ end
49
+ end