lodging 0.0.12 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +26 -0
- data/Gemfile +9 -0
- data/LICENSE-PREAMBLE +52 -0
- data/Rakefile +8 -0
- data/VERSION +1 -0
- data/certification_changelog.markdown +11 -0
- data/dot.rvmrc +9 -0
- data/features/lodging_committees.feature +356 -171
- data/features/lodging_impacts.feature +74 -0
- data/features/support/db/fixtures/census_divisions.csv +2 -0
- data/features/support/db/fixtures/climate_divisions.csv +2 -0
- data/features/support/db/fixtures/commercial_building_energy_consumption_survey_responses.csv +11 -0
- data/features/support/db/fixtures/countries.csv +4 -0
- data/features/support/db/fixtures/egrid_countries.csv +2 -0
- data/features/support/db/fixtures/egrid_regions.csv +2 -0
- data/features/support/db/fixtures/egrid_subregions.csv +3 -0
- data/features/support/db/fixtures/fuel_years.csv +2 -0
- data/features/support/db/fixtures/fuels.csv +4 -0
- data/features/support/db/fixtures/lodging_classes.csv +4 -0
- data/features/support/db/fixtures/lodging_properties.csv +5 -0
- data/features/support/db/fixtures/states.csv +2 -0
- data/features/support/db/fixtures/zip_codes.csv +4 -0
- data/features/support/env.rb +18 -1
- data/features/support/lodging_property.rb +26 -0
- data/{lib/test_support → features/support}/lodging_record.rb +1 -4
- data/lib/lodging.rb +1 -0
- data/lib/lodging/cbecs.rb +31 -0
- data/lib/lodging/characterization.rb +19 -3
- data/lib/lodging/data.rb +22 -8
- data/lib/lodging/impact_model.rb +544 -0
- data/lib/lodging/relationships.rb +3 -1
- data/lib/lodging/version.rb +5 -0
- data/lodging.gemspec +31 -0
- data/todo.txt +5 -0
- metadata +76 -119
- data/features/lodging_emissions.feature +0 -53
- data/lib/lodging/carbon_model.rb +0 -265
- data/lib/lodging/fallback.rb +0 -10
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
Feature: Lodging Emissions Calculations
|
|
2
|
+
The lodging model should generate correct emission calculations
|
|
3
|
+
|
|
4
|
+
Background:
|
|
5
|
+
Given a Lodging
|
|
6
|
+
|
|
7
|
+
Scenario: Calculations starting from nothing
|
|
8
|
+
Given a lodging has nothing
|
|
9
|
+
When impacts are calculated
|
|
10
|
+
Then the amount of "carbon" should be within "0.005" of "28.62"
|
|
11
|
+
|
|
12
|
+
Scenario Outline: Calculations starting from date
|
|
13
|
+
Given it has "date" of "<date>"
|
|
14
|
+
And it has "timeframe" of "<timeframe>"
|
|
15
|
+
When impacts are calculated
|
|
16
|
+
Then the amount of "carbon" should be within "0.005" of "<carbon>"
|
|
17
|
+
Examples:
|
|
18
|
+
| date | timeframe | carbon |
|
|
19
|
+
| 2011-01-15 | 2011-01-01/2012-01-01 | 28.62 |
|
|
20
|
+
| 2012-01-15 | 2011-01-01/2012-01-01 | 0.0 |
|
|
21
|
+
|
|
22
|
+
Scenario: Calculations starting from rooms and duration
|
|
23
|
+
Given it has "rooms" of "2"
|
|
24
|
+
And it has "duration" of "172800"
|
|
25
|
+
When impacts are calculated
|
|
26
|
+
Then the amount of "carbon" should be within "0.005" of "114.47"
|
|
27
|
+
|
|
28
|
+
Scenario Outline: Calculations from fuzzy inference based on country degree days
|
|
29
|
+
Given it has "rooms" of "2"
|
|
30
|
+
And it has "duration" of "172800"
|
|
31
|
+
And it has "country.iso_3166_code" of "<country>"
|
|
32
|
+
And it has "state.postal_abbreviation" of "<state>"
|
|
33
|
+
When impacts are calculated
|
|
34
|
+
Then the amount of "carbon" should be within "0.005" of "<carbon>"
|
|
35
|
+
Examples:
|
|
36
|
+
| country | state | carbon |
|
|
37
|
+
| VI | | 114.47 |
|
|
38
|
+
| GB | | 189.56 |
|
|
39
|
+
| US | | 131.28 |
|
|
40
|
+
| | CA | 131.28 |
|
|
41
|
+
|
|
42
|
+
Scenario Outline: Calculations from fuzzy inference
|
|
43
|
+
Given it has "rooms" of "2"
|
|
44
|
+
And it has "duration" of "172800"
|
|
45
|
+
And it has "property.northstar_id" of "<id>"
|
|
46
|
+
And it has "zip_code.name" of "<zip>"
|
|
47
|
+
And it has "city" of "<city>"
|
|
48
|
+
And it has "state.postal_abbreviation" of "<state>"
|
|
49
|
+
When impacts are calculated
|
|
50
|
+
Then the amount of "carbon" should be within "0.005" of "<carbon>"
|
|
51
|
+
Examples:
|
|
52
|
+
| id | zip | city | state | carbon | notes |
|
|
53
|
+
| 1 | 94122 | | | 86.85 | dd from climate divizion; fuzzy from property attributes |
|
|
54
|
+
| 1 | | San Francisco | CA | 122.33 | dd from country; fuzzy from property attributes |
|
|
55
|
+
| 2 | 94133 | | | 94.24 | dd from country; fuzzy from property attributes |
|
|
56
|
+
| 2 | | San Francisco | CA | 94.24 | dd from country; fuzzy from property attributes |
|
|
57
|
+
| 3 | 94014 | | | 128.13 | dd from country; fuzzy from property attributes |
|
|
58
|
+
|
|
59
|
+
Scenario: Calculations from all user inputs
|
|
60
|
+
Given it has "rooms" of "2"
|
|
61
|
+
And it has "duration" of "172800"
|
|
62
|
+
And it has "country.iso_3166_code" of "GB"
|
|
63
|
+
And it has "heating_degree_days" of "2700"
|
|
64
|
+
And it has "cooling_degree_days" of "100"
|
|
65
|
+
And it has "property_rooms" of "100"
|
|
66
|
+
And it has "floors" of "3"
|
|
67
|
+
And it has "construction_year" of "1993"
|
|
68
|
+
And it has "ac_coverage" of "0.5"
|
|
69
|
+
And it has "refrigerator_coverage" of "0.6"
|
|
70
|
+
And it has "hot_tubs" of "6"
|
|
71
|
+
And it has "indoor_pools" of "5"
|
|
72
|
+
And it has "outdoor_pools" of "5"
|
|
73
|
+
When impacts are calculated
|
|
74
|
+
Then the amount of "carbon" should be within "0.005" of "208.83"
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
id,heating_degree_days,cooling_degree_days,lodging_rooms,floors,construction_year,percent_cooled,natural_gas_per_room_night,fuel_oil_per_room_night,electricity_per_room_night,district_heat_per_room_night,weighting
|
|
2
|
+
1,5500,400,10,1,1967,1,0,1.9,12,0,1700
|
|
3
|
+
2,1500,1200,35,2,1988,0.6,0,0,14,0,420
|
|
4
|
+
3,200,2700,100,4,2000,1,1.2,0,34,0,125
|
|
5
|
+
4,2300,900,2,1,1992,1,0,0,23,0,1770
|
|
6
|
+
5,2300,700,1000,25,1986,1,11,0.015,120,0,135
|
|
7
|
+
6,3800,200,7,4,1881,0,0,0,9.2,0,1925
|
|
8
|
+
7,800,1700,125,3,2002,1,1.9,0,27,0,240
|
|
9
|
+
8,3300,400,10,2,1920,0,0,6.1,11,0,1925
|
|
10
|
+
9,1000,1700,14,2,1950,1,9.7,0,83,180,365
|
|
11
|
+
10,2400,800,450,25,1929,1,0.74,0.00092,41,97,120
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
iso_3166_code,iso_3166_alpha_3_code,heating_degree_days,cooling_degree_days,electricity_emission_factor,electricity_loss_factor,lodging_occupancy_rate,lodging_natural_gas_intensity,lodging_fuel_oil_intensity,lodging_electricity_intensity,lodging_district_heat_intensity
|
|
2
|
+
US,USA,2200,880,0.59000,0.06025,0.6,2.0,0.4,33.9,1.8
|
|
3
|
+
GB,GBR,2800,60,0.9,0.1,0.5,3.0,0.5,60.0,0.0
|
|
4
|
+
VI,VIR
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
northstar_id,name,city,locality,postcode,country_iso_3166_alpha_3_code,lodging_rooms,floors,construction_year,ac_coverage,lodging_class_name,fridge_coverage,mini_bar_coverage,hot_tubs,pools_indoor,pools_outdoor
|
|
2
|
+
1,Courtyard by Marriott,San Francisco,California,94122,USA,100,3,1993,0.5,Motel,0.5,0.6,6,6,6
|
|
3
|
+
2,Hilton San Francisco,San Francisco,California,94133,USA,50,2,2002,1,Hotel,0.5,,0,0,0
|
|
4
|
+
3,Pacific Inn,Daly City,California,94014,USA,25,,,,Inn,,0.5,1,1,1
|
|
5
|
+
4,,,,,,,,,,,0.6,0.5,5,5,5
|
data/features/support/env.rb
CHANGED
|
@@ -3,6 +3,23 @@ Bundler.setup
|
|
|
3
3
|
|
|
4
4
|
require 'cucumber'
|
|
5
5
|
require 'cucumber/formatter/unicode'
|
|
6
|
+
require 'rspec'
|
|
7
|
+
require 'rspec/expectations'
|
|
8
|
+
require 'cucumber/rspec/doubles'
|
|
9
|
+
|
|
10
|
+
require 'data_miner'
|
|
11
|
+
DataMiner.logger = Logger.new(nil)
|
|
6
12
|
|
|
7
13
|
require 'sniff'
|
|
8
|
-
|
|
14
|
+
|
|
15
|
+
# need to require this before initializing Sniff for LodgingProperty fixture to be loaded
|
|
16
|
+
require File.expand_path('../lodging_property', __FILE__)
|
|
17
|
+
|
|
18
|
+
Sniff.init File.join(File.dirname(__FILE__), '..', '..'),
|
|
19
|
+
:adapter => 'mysql2',
|
|
20
|
+
:database => 'test_lodging',
|
|
21
|
+
:username => 'root',
|
|
22
|
+
:password => 'password',
|
|
23
|
+
:earth => [:hospitality, :fuel, :locality],
|
|
24
|
+
:cucumber => true,
|
|
25
|
+
:logger => 'log/test_log.txt'
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# LodgingProperty is defined in CM1 rather than Earth, so we need to define it here for testing
|
|
2
|
+
class LodgingProperty < ActiveRecord::Base
|
|
3
|
+
col :northstar_id
|
|
4
|
+
col :name
|
|
5
|
+
col :city
|
|
6
|
+
col :locality # state / province / etc.
|
|
7
|
+
col :postcode # zip code / postal code / etc.
|
|
8
|
+
col :country_iso_3166_alpha_3_code
|
|
9
|
+
col :chain_name
|
|
10
|
+
col :lodging_rooms, :type => :integer
|
|
11
|
+
col :floors, :type => :integer
|
|
12
|
+
col :construction_year, :type => :integer
|
|
13
|
+
col :lodging_class_name
|
|
14
|
+
col :ac_coverage, :type => :float
|
|
15
|
+
col :mini_bar_coverage, :type => :float
|
|
16
|
+
col :fridge_coverage, :type => :float
|
|
17
|
+
col :hot_tubs, :type => :float # float b/c fallback needs to be a float
|
|
18
|
+
col :pools_indoor, :type => :float # float b/c fallback needs to be a float
|
|
19
|
+
col :pools_outdoor, :type => :float # float b/c fallback needs to be a float
|
|
20
|
+
|
|
21
|
+
# based on LodgingProperty as of 2012-02-21
|
|
22
|
+
falls_back_on :fridge_coverage => 0.6,
|
|
23
|
+
:hot_tubs => 0.3,
|
|
24
|
+
:pools_indoor => 0.3,
|
|
25
|
+
:pools_outdoor => 0.6
|
|
26
|
+
end
|
data/lib/lodging.rb
CHANGED
|
@@ -3,5 +3,6 @@ require 'emitter'
|
|
|
3
3
|
module BrighterPlanet
|
|
4
4
|
module Lodging
|
|
5
5
|
extend BrighterPlanet::Emitter
|
|
6
|
+
scope 'The lodging emission estimate is the anthropogenic emissions from lodging room energy use. It includes CO2 emissions from direct fuel combustion and indirect fuel combustion to generate purchased electricity.'
|
|
6
7
|
end
|
|
7
8
|
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'fuzzy_infer'
|
|
2
|
+
|
|
3
|
+
class CommercialBuildingEnergyConsumptionSurveyResponse < ActiveRecord::Base
|
|
4
|
+
fuzzy_infer :target => [:natural_gas_per_room_night, :fuel_oil_per_room_night, :electricity_per_room_night, :district_heat_per_room_night], # list of columns that this model is designed to infer
|
|
5
|
+
:basis => [:heating_degree_days, :cooling_degree_days, :lodging_rooms, :floors, :construction_year, :percent_cooled], # list of columns that are believed to affect energy use (aka MU)
|
|
6
|
+
:sigma => "(STDDEV_SAMP(:column)/5)+(ABS(AVG(:column)-:value)/3)", # empirically determined formula (SQL!) that captures the desired sample size once all the weights are compiled, across the full range of possible mu values
|
|
7
|
+
:membership => :energy_use_membership, # name of instance method to be called on kernel
|
|
8
|
+
:weight => :weighting # (optional) a pre-existing row weighting, if any, provided by the dataset authors
|
|
9
|
+
|
|
10
|
+
# empirically determined formula that minimizes variance between real and predicted energy use
|
|
11
|
+
# SQL! - :heating_degree_days_n_w will be replaced with, for example, `tmp_table_9301293.hdd_normalized_weight`
|
|
12
|
+
def energy_use_membership(basis)
|
|
13
|
+
keys = basis.keys
|
|
14
|
+
|
|
15
|
+
unless keys.include?(:heating_degree_days) and keys.include?(:cooling_degree_days)
|
|
16
|
+
raise ArgumentError, "[lodging] Must provide at least :heating_degree_days and :cooling_degree_days"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
formula = ['(POW(:heating_degree_days_n_w, 0.8) + POW(:cooling_degree_days_n_w, 0.8))']
|
|
20
|
+
if keys.include?(:lodging_rooms) and keys.include?(:floors)
|
|
21
|
+
formula << '(POW(:lodging_rooms_n_w, 0.8) + POW(:floors_n_w, 0.8))'
|
|
22
|
+
elsif keys.include? :lodging_rooms
|
|
23
|
+
formula << 'POW(:lodging_rooms_n_w, 0.8)'
|
|
24
|
+
elsif keys.include? :floors
|
|
25
|
+
formula << 'POW(:floors_n_w, 0.8)'
|
|
26
|
+
end
|
|
27
|
+
formula << 'POW(:percent_cooled_n_w, 0.8)' if keys.include?(:percent_cooled)
|
|
28
|
+
formula << 'POW(:construction_year_n_w, 0.8)' if keys.include?(:construction_year)
|
|
29
|
+
formula.join(' * ')
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -3,11 +3,27 @@ module BrighterPlanet
|
|
|
3
3
|
module Characterization
|
|
4
4
|
def self.included(base)
|
|
5
5
|
base.characterize do
|
|
6
|
-
has :
|
|
6
|
+
has :date
|
|
7
|
+
has :rooms
|
|
8
|
+
has :duration, :measures => :time
|
|
7
9
|
has :zip_code
|
|
10
|
+
has :city
|
|
8
11
|
has :state
|
|
9
|
-
has :
|
|
10
|
-
has :
|
|
12
|
+
has :country
|
|
13
|
+
has :lodging_class
|
|
14
|
+
has :heating_degree_days
|
|
15
|
+
has :cooling_degree_days
|
|
16
|
+
has :property do |prop|
|
|
17
|
+
prop.name
|
|
18
|
+
end
|
|
19
|
+
has :property_rooms
|
|
20
|
+
has :floors
|
|
21
|
+
has :construction_year
|
|
22
|
+
has :ac_coverage
|
|
23
|
+
has :refrigerator_coverage
|
|
24
|
+
has :hot_tubs
|
|
25
|
+
has :outdoor_pools
|
|
26
|
+
has :indoor_pools
|
|
11
27
|
end
|
|
12
28
|
end
|
|
13
29
|
end
|
data/lib/lodging/data.rb
CHANGED
|
@@ -2,16 +2,30 @@ module BrighterPlanet
|
|
|
2
2
|
module Lodging
|
|
3
3
|
module Data
|
|
4
4
|
def self.included(base)
|
|
5
|
+
base.col :date, :type => :date
|
|
6
|
+
base.col :rooms, :type => :integer
|
|
7
|
+
base.col :duration, :type => :integer
|
|
8
|
+
base.col :zip_code_name
|
|
9
|
+
base.col :city
|
|
10
|
+
base.col :state_postal_abbreviation
|
|
11
|
+
base.col :country_iso_3166_code
|
|
12
|
+
base.col :lodging_class_name
|
|
13
|
+
base.col :heating_degree_days, :type => :float
|
|
14
|
+
base.col :cooling_degree_days, :type => :float
|
|
15
|
+
base.col :property_northstar_id
|
|
16
|
+
base.col :property_rooms, :type => :integer
|
|
17
|
+
base.col :floors, :type => :integer
|
|
18
|
+
base.col :construction_year, :type => :integer
|
|
19
|
+
base.col :ac_coverage, :type => :float
|
|
20
|
+
base.col :refrigerator_coverage, :type => :float
|
|
21
|
+
base.col :hot_tubs, :type => :integer
|
|
22
|
+
base.col :outdoor_pools, :type => :integer
|
|
23
|
+
base.col :indoor_pools, :type => :integer
|
|
24
|
+
|
|
5
25
|
base.data_miner do
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
string 'zip_code_name'
|
|
9
|
-
string 'state_postal_abbreviation'
|
|
10
|
-
integer 'rooms'
|
|
11
|
-
integer 'duration'
|
|
26
|
+
process 'pull orphans' do
|
|
27
|
+
Fuel.run_data_miner!
|
|
12
28
|
end
|
|
13
|
-
|
|
14
|
-
process :run_data_miner_on_belongs_to_associations
|
|
15
29
|
end
|
|
16
30
|
end
|
|
17
31
|
end
|
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
# Copyright © 2010 Brighter Planet.
|
|
2
|
+
# See LICENSE for details.
|
|
3
|
+
# Contact Brighter Planet for dual-license arrangements.
|
|
4
|
+
|
|
5
|
+
## Lodging impact model
|
|
6
|
+
# This model is used by the [Brighter Planet](http://brighterplanet.com) [CM1 web service](http://carbon.brighterplanet.com) to calculate the impacts of a lodging (e.g. a hotel stay), such as energy use, greenhouse gas emissions, and water use.
|
|
7
|
+
|
|
8
|
+
##### Timeframe
|
|
9
|
+
# The model calculates impacts that occured during a particular time period (`timeframe`).
|
|
10
|
+
# For example if the `timeframe` is February 2010, a lodging that occurred (`date`) on February 15, 2010 will have impacts, but a lodging that occurred on January 31, 2010 will have zero impacts.
|
|
11
|
+
#
|
|
12
|
+
# The default `timeframe` is the current calendar year.
|
|
13
|
+
|
|
14
|
+
##### Calculations
|
|
15
|
+
# The final impacts are the result of the calculations below. These are performed in reverse order, starting with the last calculation listed and finishing with the greenhouse gas emissions calculation.
|
|
16
|
+
#
|
|
17
|
+
# Each calculation listing shows:
|
|
18
|
+
#
|
|
19
|
+
# * value returned (*units of measurement*)
|
|
20
|
+
# * description of the value
|
|
21
|
+
# * calculation methods, listed from most to least preferred
|
|
22
|
+
#
|
|
23
|
+
# Some methods use `values` returned by prior calculations. If any of these `values` are unknown the method is skipped.
|
|
24
|
+
# If all the methods for a calculation are skipped, the value the calculation would return is unknown.
|
|
25
|
+
|
|
26
|
+
##### Standard compliance
|
|
27
|
+
# When compliance with a particular standard is requested, all methods that do not comply with that standard are ignored.
|
|
28
|
+
# Thus any `values` a method needs will have been calculated using a compliant method or will be unknown.
|
|
29
|
+
# To see which standards a method complies with, look at the `:complies =>` section of the code in the right column.
|
|
30
|
+
#
|
|
31
|
+
# Client input complies with all standards.
|
|
32
|
+
|
|
33
|
+
##### Collaboration
|
|
34
|
+
# Contributions to this impact model are actively encouraged and warmly welcomed. This library includes a comprehensive test suite to ensure that your changes do not cause regressions. All changes should include test coverage for new functionality. Please see [sniff](https://github.com/brighterplanet/sniff#readme), our emitter testing framework, for more information.
|
|
35
|
+
require 'lodging/cbecs'
|
|
36
|
+
|
|
37
|
+
module BrighterPlanet
|
|
38
|
+
module Lodging
|
|
39
|
+
module ImpactModel
|
|
40
|
+
def self.included(base)
|
|
41
|
+
base.decide :impact, :with => :characteristics do
|
|
42
|
+
# * * *
|
|
43
|
+
|
|
44
|
+
#### Carbon (*kg CO<sub>2</sub>e*)
|
|
45
|
+
# *The lodging's total anthropogenic greenhouse gas emissions during `timeframe`.*
|
|
46
|
+
committee :carbon do
|
|
47
|
+
# Multiply `natural gas use` (*m<sup>3</sup>*) by natural gas' emission factor (*kg CO<sub>2</sub> / m<sup>3</sup>*) to give *kg CO<sub>2</sub>.*
|
|
48
|
+
# Multiply `fuel oil use` (*l*) by fuel oil's emission factor (*kg CO<sub>2</sub> / l*) to give *kg CO<sub>2</sub>.*
|
|
49
|
+
# Multiply `electricity use` (*kWh*) by `electricity emission factor` (*kg CO<sub>2</sub> / kWh*) to give *kg CO<sub>2</sub>.*
|
|
50
|
+
# Multiply `district heat use` (*MJ*) by district heat's emission factor` (*kg CO<sub>2</sub> / MJ*) to give *kg CO<sub>2</sub>.*
|
|
51
|
+
# Sum to give *kg CO<sub>2</sub>e.*
|
|
52
|
+
quorum 'from natural gas use, fuel oil use, electricity use, district heat use, and electricity emission factor', :needs => [:natural_gas_use, :fuel_oil_use, :electricity_use, :district_heat_use, :electricity_emission_factor],
|
|
53
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
54
|
+
characteristics[:natural_gas_use] * Fuel.find_by_name('Pipeline Natural Gas').co2_emission_factor +
|
|
55
|
+
characteristics[:fuel_oil_use] * Fuel.find_by_name('Residual Fuel Oil No. 6').co2_emission_factor +
|
|
56
|
+
characteristics[:electricity_use] * characteristics[:electricity_emission_factor] +
|
|
57
|
+
characteristics[:district_heat_use] * Fuel.find_by_name('District Heat').co2_emission_factor
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
#### Electricity emission factor (*kg CO<sub>2</sub>e / kWh*)
|
|
62
|
+
# *A greenhouse gas emission factor for electricity used by the lodging.*
|
|
63
|
+
committee :electricity_emission_factor do
|
|
64
|
+
# Multiply the `eGRID subregion` electricity emission factors by 1 minus the the subregion's eGRID region loss factor (to account for transmission and distribution losses) to give *kg CO<sub>2</sub>e / kWh*.
|
|
65
|
+
quorum 'from eGRID subregion', :needs => :egrid_subregion,
|
|
66
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
67
|
+
characteristics[:egrid_subregion].electricity_emission_factor / (1 - characteristics[:egrid_subregion].egrid_region.loss_factor)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Otherwise look up the `country` electricity emission factor (*kg CO<sub>2</sub>e / kWh*).
|
|
71
|
+
quorum 'from country', :needs => :country,
|
|
72
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
73
|
+
if (emission_factor = characteristics[:country].electricity_emission_factor).present? and (loss_factor = characteristics[:country].electricity_loss_factor).present?
|
|
74
|
+
emission_factor / (1 - loss_factor)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Otherwise use a global average electricity emission factor (*kg CO<sub>2</sub>e / kWh*).
|
|
79
|
+
quorum 'default',
|
|
80
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do
|
|
81
|
+
Country.fallback.electricity_emission_factor / (1 - Country.fallback.electricity_loss_factor)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
#### Natural gas use (*m<sup>3</sup>*)
|
|
86
|
+
# *The lodging's natural gas use during `timeframe`.*
|
|
87
|
+
committee :natural_gas_use do
|
|
88
|
+
# Multiply `room nights` (*room-nights*) by `natural gas intensity` (*m<sup>3</sup> / occupied room-night*) to give *m<sup>3</sup>*.
|
|
89
|
+
quorum 'from adjusted fuel intensities and room nights', :needs => [:adjusted_fuel_intensities, :room_nights],
|
|
90
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
91
|
+
characteristics[:room_nights] * characteristics[:adjusted_fuel_intensities][:natural_gas]
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
#### Fuel oil use (*l*)
|
|
96
|
+
# *The lodging's fuel oil use during `timeframe`.*
|
|
97
|
+
committee :fuel_oil_use do
|
|
98
|
+
# Multiply `room nights` (*room-nights*) by `fuel oil intensity` (*l / occupied room-night*) to give *l*.
|
|
99
|
+
quorum 'from adjusted fuel intensities and room nights', :needs => [:adjusted_fuel_intensities, :room_nights],
|
|
100
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
101
|
+
characteristics[:room_nights] * characteristics[:adjusted_fuel_intensities][:fuel_oil]
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
#### Electricity use (*kWh*)
|
|
106
|
+
# *The lodging's electricity use during `timeframe`.*
|
|
107
|
+
committee :electricity_use do
|
|
108
|
+
# Multiply `room nights` (*room-nights*) by `electricity intensity` (*kWh / occupied room-night*) to give *kWh*.
|
|
109
|
+
quorum 'from adjusted fuel intensities and room nights', :needs => [:adjusted_fuel_intensities, :room_nights],
|
|
110
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
111
|
+
characteristics[:room_nights] * characteristics[:adjusted_fuel_intensities][:electricity]
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
#### District heat use (*MJ*)
|
|
116
|
+
# *The lodging's district heat use during `timeframe`.*
|
|
117
|
+
committee :district_heat_use do
|
|
118
|
+
# Multiply `room nights` (*room-nights*) by `district heat intensity` (*MJ / occupied room-night*) to give *MJ*.
|
|
119
|
+
quorum 'from adjusted fuel intensities and room nights', :needs => [:adjusted_fuel_intensities, :room_nights],
|
|
120
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
121
|
+
characteristics[:room_nights] * characteristics[:adjusted_fuel_intensities][:district_heat]
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
#### Adjusted fuel intensities (*various*)
|
|
126
|
+
# *The lodging's use per occupied room night of a variety of fuels, adjusted by number of pools, mini-fridges, etc.*
|
|
127
|
+
#
|
|
128
|
+
# - Natural gas intensity: *m<sup>3</sup> / occupied room-night*
|
|
129
|
+
# - Fuel oil intensity: *l / occupied room-night*
|
|
130
|
+
# - Electricity intensity: *kWh / occupied room-night*
|
|
131
|
+
# - District heat intensity: *MJ / occupied room-night*
|
|
132
|
+
committee :adjusted_fuel_intensities do
|
|
133
|
+
# Adjust `fuel intensities` based on any amenity adjustments:
|
|
134
|
+
quorum 'from fuel intensities and amenity adjustments',
|
|
135
|
+
:needs => :fuel_intensities, :appreciates => [:indoor_pool_adjustment, :outdoor_pool_adjustment, :refrigerator_adjustment, :hot_tub_adjustment],
|
|
136
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
137
|
+
gas = Fuel.find_by_name('Pipeline Natural Gas')
|
|
138
|
+
oil = Fuel.find_by_name('Residual Fuel Oil No. 6')
|
|
139
|
+
|
|
140
|
+
# Duplicate the current intensities so we don't overwrite them.
|
|
141
|
+
intensities = characteristics[:fuel_intensities].dup
|
|
142
|
+
|
|
143
|
+
# TODO combine pool adjustments - so if we're below average in indoor but above in outdoor we don't accidentally subtract, get less than zero, discard some energy use, and then add energy back for outdoor pools
|
|
144
|
+
|
|
145
|
+
# Cycle through each adjustment...
|
|
146
|
+
characteristics.each do |characteristic, value|
|
|
147
|
+
unless characteristic == :fuel_intensities
|
|
148
|
+
value.each do |fuel, adjustment|
|
|
149
|
+
if fuel == :pool_energy
|
|
150
|
+
# If the adjustment relates to pool energy, convert natural gas and fuel oil inensities from physical units to energy units.
|
|
151
|
+
gas_energy = intensities[:natural_gas] * gas.energy_content
|
|
152
|
+
oil_energy = intensities[:fuel_oil] * oil.energy_content
|
|
153
|
+
|
|
154
|
+
# Apply the adjustment to natural gas intensity.
|
|
155
|
+
# If adjusted natural gas intensity reaches zero, apply any remaining adjustment to fuel oil intensity.
|
|
156
|
+
# If adjusted fuel oil intensity also reaches zero, discard any remaining adjustment.
|
|
157
|
+
if (gas_energy += adjustment) < 0.0
|
|
158
|
+
if (oil_energy += gas_energy) < 0.0
|
|
159
|
+
oil_energy = 0.0
|
|
160
|
+
end
|
|
161
|
+
gas_energy = 0
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Convert adjusted natural gas and fuel oil intensities from energy units back to physical units.
|
|
165
|
+
intensities[:natural_gas] = gas_energy / gas.energy_content
|
|
166
|
+
intensities[:fuel_oil] = oil_energy / oil.energy_content
|
|
167
|
+
# Otherwise apply the adjustment to the appropriate fuel intensity. If adjusted fuel intensity reaches zero, discard any remaining adjustment.
|
|
168
|
+
elsif (intensities[fuel] += adjustment) < 0.0
|
|
169
|
+
intensities[fuel] = 0.0
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
intensities
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
#### Outdoor pools adjustment (*MJ / occupied room-night*)
|
|
179
|
+
# *Adjusts the natural gas intensity based on the number of outdoor pools.*
|
|
180
|
+
committee :outdoor_pool_adjustment do
|
|
181
|
+
# Assume outdoor pool energy intensity of 329,917 *BTU / night* per [Energy Star](http://www.energystar.gov/ia/business/evaluate_performance/swimming_pool_tech_desc.pdf).
|
|
182
|
+
# Calculate the difference between `outdoor pools` and average outdoor pools.
|
|
183
|
+
# Multiply the difference by outdoor pool energy intensity (*MJ / night*) and divide by `property rooms` and `occupancy rate` to give *MJ / occupied room-night*.
|
|
184
|
+
quorum 'from outdoor pools, property rooms, and occupancy rate', :needs => [:outdoor_pools, :property_rooms, :occupancy_rate],
|
|
185
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
186
|
+
difference = characteristics[:outdoor_pools] - LodgingProperty.fallback.pools_outdoor
|
|
187
|
+
{ :pool_energy => difference * 329_917.btus.to(:megajoules) / characteristics[:property_rooms] / characteristics[:occupancy_rate] }
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
#### Indoor pools adjustment (*MJ / occupied room-night*)
|
|
192
|
+
# *Adjusts the natural gas intensity based on the number of indoor pools.*
|
|
193
|
+
committee :indoor_pool_adjustment do
|
|
194
|
+
# Assume indoor pool energy intensity of 2,770,942 *BTU / night* per [Energy Star](http://www.energystar.gov/ia/business/evaluate_performance/swimming_pool_tech_desc.pdf).
|
|
195
|
+
# Calculate the difference between `indoor pools` and average indoor pools.
|
|
196
|
+
# Multiply the difference by indoor pool energy intensity (*MJ / night*) and divide by `property rooms` and `occupancy rate` to give *MJ / occupied room-night*.
|
|
197
|
+
quorum 'from indoor pools, property rooms, and occupancy rate', :needs => [:indoor_pools, :property_rooms, :occupancy_rate],
|
|
198
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
199
|
+
difference = characteristics[:indoor_pools] - LodgingProperty.fallback.pools_indoor
|
|
200
|
+
{ :pool_energy => difference * 2_770_942.btus.to(:megajoules) / characteristics[:property_rooms] / characteristics[:occupancy_rate] }
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
#### Hot tub adjustment (*kWh / occupied room-night*)
|
|
205
|
+
# *Adjusts the electricity intensity based on the number of hot tubs.*
|
|
206
|
+
committee :hot_tub_adjustment do
|
|
207
|
+
# Calculate the difference between `hot tubs` and average hot tubs.
|
|
208
|
+
# Assume hot tub electricity intensity of 6.3 *kWh / night* per [LBL residential energy data sourcebook, p128](http://enduse.lbl.gov/info/LBNL-40297.pdf).
|
|
209
|
+
# Multiply the difference by the hot tub electricity intensity (*kWh / night*) and divide by `property rooms` and `occupancy rate` to give *kWh / occupied room-night*.
|
|
210
|
+
quorum 'from hot tubs, property rooms, and occupancy rate', :needs => [:hot_tubs, :property_rooms, :occupancy_rate],
|
|
211
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
212
|
+
difference = characteristics[:hot_tubs] - LodgingProperty.fallback.hot_tubs
|
|
213
|
+
{ :electricity => difference * 6.3 / characteristics[:property_rooms] / characteristics[:occupancy_rate] }
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
#### Refrigerator adjustment (*kWh / occupied room-night*)
|
|
218
|
+
# *Adjusts the electricity intensity based on refrigerator coverage.*
|
|
219
|
+
committee :refrigerator_adjustment do
|
|
220
|
+
# Calculate the difference between `refrigerator coverage` (*refrigerators / room*) and average refrigerator coverage (*refrigerators / room*).
|
|
221
|
+
# Assume an auto-defrost compact fridge electricity intensity of 1.18 *kWh / refrigerator night* per [Energy Star](http://www.energystar.gov/ia/business/bulk_purchasing/bpsavings_calc/Bulk_Purchasing_CompactRefrig_Sav_Calc.xls).
|
|
222
|
+
# Multiply the difference (*refrigerators / room*) by the refrigerator electricity intensity (*kWh / refrigerator night*) and divide by `occupancy rate` to give *kWh / occupied room-night*.
|
|
223
|
+
quorum 'from refrigerator coverage and occupancy rate', :needs => [:refrigerator_coverage, :occupancy_rate],
|
|
224
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
225
|
+
difference = characteristics[:refrigerator_coverage] - LodgingProperty.fallback.fridge_coverage
|
|
226
|
+
{ :electricity => (difference * 1.18 / characteristics[:occupancy_rate]) }
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
#### Fuel intensities (*various*)
|
|
231
|
+
# *The lodging's use per occupied room night of a variety of fuels.*
|
|
232
|
+
#
|
|
233
|
+
# - Natural gas intensity: *m<sup>3</sup> / occupied room-night*
|
|
234
|
+
# - Fuel oil intensity: *l / occupied room-night*
|
|
235
|
+
# - Electricity intensity: *kWh / occupied room-night*
|
|
236
|
+
# - District heat intensity: *MJ / occupied room-night*
|
|
237
|
+
committee :fuel_intensities do
|
|
238
|
+
# If we know `heating degree days` and `cooling degree days`, calculate fuel intensities from [CBECS 2003](http://data.brighterplanet.com/commercial_building_energy_consumption_survey_responses) data using fuzzy inference and adjust the inferred values based on `occupancy rate`.
|
|
239
|
+
quorum 'from degree days, occupancy rate, and user inputs', :needs => [:heating_degree_days, :cooling_degree_days, :occupancy_rate], :appreciates => [:property_rooms, :floors, :construction_year, :ac_coverage],
|
|
240
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
241
|
+
inputs = characteristics.to_hash.inject({}) do |memo, (characteristic, value)|
|
|
242
|
+
case characteristic
|
|
243
|
+
when :property_rooms
|
|
244
|
+
memo[:lodging_rooms] = value
|
|
245
|
+
when :ac_coverage
|
|
246
|
+
memo[:percent_cooled] = value
|
|
247
|
+
when :occupancy_rate
|
|
248
|
+
# Don't include `occupancy rate` in inputs to fuzzy inference
|
|
249
|
+
else
|
|
250
|
+
memo[characteristic] = value
|
|
251
|
+
end
|
|
252
|
+
memo
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
kernel = CommercialBuildingEnergyConsumptionSurveyResponse.new(inputs)
|
|
256
|
+
n, f, e, d = kernel.fuzzy_infer(:natural_gas_per_room_night, :fuel_oil_per_room_night, :electricity_per_room_night, :district_heat_per_room_night)
|
|
257
|
+
{
|
|
258
|
+
:natural_gas => n / characteristics[:occupancy_rate],
|
|
259
|
+
:fuel_oil => f / characteristics[:occupancy_rate],
|
|
260
|
+
:electricity => e / characteristics[:occupancy_rate],
|
|
261
|
+
:district_heat => d / characteristics[:occupancy_rate]
|
|
262
|
+
}
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# Otherwise use global averages.
|
|
266
|
+
quorum 'default',
|
|
267
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
268
|
+
intensities = {
|
|
269
|
+
:natural_gas => Country.fallback.lodging_natural_gas_intensity,
|
|
270
|
+
:fuel_oil => Country.fallback.lodging_fuel_oil_intensity,
|
|
271
|
+
:electricity => Country.fallback.lodging_electricity_intensity,
|
|
272
|
+
:district_heat => Country.fallback.lodging_district_heat_intensity,
|
|
273
|
+
}
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
#### Occupancy rate
|
|
278
|
+
# *The percent of the proprety's rooms that are occupied on an average night.*
|
|
279
|
+
committee :occupancy_rate do
|
|
280
|
+
# Look up the `country` average lodging occupancy rate.
|
|
281
|
+
quorum 'from country', :needs => :country,
|
|
282
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
283
|
+
characteristics[:country].lodging_occupancy_rate
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
# Otherwise use a global average.
|
|
287
|
+
quorum 'default', :complies => [:ghg_protocol_scope_3, :iso, :tcr] do
|
|
288
|
+
Country.fallback.lodging_occupancy_rate
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
#### Outdoor pools
|
|
293
|
+
# *The number of outdoor pools.*
|
|
294
|
+
committee :outdoor_pools do
|
|
295
|
+
# Use client input, if available.
|
|
296
|
+
|
|
297
|
+
# Otherwise look up the `property` number of outdoor pools, but set a ceiling of 5 outdoor pools.
|
|
298
|
+
quorum 'from property', :needs => :property,
|
|
299
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
300
|
+
unless characteristics[:property].pools_outdoor.nil?
|
|
301
|
+
[characteristics[:property].pools_outdoor.to_f, 5].min
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
#### Indoor pools
|
|
307
|
+
# *The number of indoor pools.*
|
|
308
|
+
committee :indoor_pools do
|
|
309
|
+
# Use client input, if available.
|
|
310
|
+
|
|
311
|
+
# Otherwise look up the `property` number of indoor pools, but set a ceiling of 5 indoor pools.
|
|
312
|
+
quorum 'from property', :needs => :property,
|
|
313
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
314
|
+
unless characteristics[:property].pools_indoor.nil?
|
|
315
|
+
[characteristics[:property].pools_indoor.to_f, 5].min
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
#### Hot tubs
|
|
321
|
+
# *The number of hot tubs.*
|
|
322
|
+
committee :hot_tubs do
|
|
323
|
+
# Use client input, if available.
|
|
324
|
+
|
|
325
|
+
# Otherwise look up the `property` number of hot tubs.
|
|
326
|
+
quorum 'from property', :needs => :property,
|
|
327
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
328
|
+
characteristics[:property].hot_tubs
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
#### Refrigerator coverage
|
|
333
|
+
# *The percentage of property rooms that have refrigerators.*
|
|
334
|
+
committee :refrigerator_coverage do
|
|
335
|
+
# Use client input, if available.
|
|
336
|
+
# Otherwise take whichever is greater of the `property` refrigerator coverage and mini bar coverage.
|
|
337
|
+
quorum 'from property', :needs => :property,
|
|
338
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
339
|
+
if characteristics[:property].mini_bar_coverage || characteristics[:property].fridge_coverage
|
|
340
|
+
[characteristics[:property].mini_bar_coverage.to_f, characteristics[:property].fridge_coverage.to_f].max
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
#### A/C coverage
|
|
346
|
+
# *The percentage of property rooms that are air conditioned.*
|
|
347
|
+
committee :ac_coverage do
|
|
348
|
+
# Use client input, if available.
|
|
349
|
+
|
|
350
|
+
# Otherwise look up the `property` A/C coverage.
|
|
351
|
+
quorum 'from property', :needs => :property,
|
|
352
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
353
|
+
characteristics[:property].ac_coverage
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
#### Construction year
|
|
358
|
+
# *The year the property was built.*
|
|
359
|
+
committee :construction_year do
|
|
360
|
+
# Use client input, if available.
|
|
361
|
+
|
|
362
|
+
# Otherwise look up the year the `property` was built.
|
|
363
|
+
quorum 'from property', :needs => :property,
|
|
364
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
365
|
+
characteristics[:property].construction_year
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
#### Floors
|
|
370
|
+
# *The number of floors.*
|
|
371
|
+
committee :floors do
|
|
372
|
+
# Use client input, if available.
|
|
373
|
+
|
|
374
|
+
# Otherwise look up the `property` number of floors.
|
|
375
|
+
quorum 'from property', :needs => :property,
|
|
376
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
377
|
+
characteristics[:property].floors
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
#### Property rooms
|
|
382
|
+
# *The number of guest rooms in the property.*
|
|
383
|
+
committee :property_rooms do
|
|
384
|
+
# Use client input, if available.
|
|
385
|
+
|
|
386
|
+
# Otherwise look up the `property` number of rooms.
|
|
387
|
+
quorum 'from property', :needs => :property,
|
|
388
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
389
|
+
characteristics[:property].lodging_rooms
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
#### Property
|
|
394
|
+
# *The property where the stay occurred.*
|
|
395
|
+
#
|
|
396
|
+
# Use client input, if available
|
|
397
|
+
|
|
398
|
+
#### Heating degree days
|
|
399
|
+
# *The average number of annual heating degree days (base 18°C) at the lodging's location.*
|
|
400
|
+
committee :heating_degree_days do
|
|
401
|
+
# Use client input, if available
|
|
402
|
+
|
|
403
|
+
# Otherwise look up the `climate division` heating degree days.
|
|
404
|
+
quorum 'from climate division', :needs => :climate_division,
|
|
405
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
406
|
+
characteristics[:climate_division].heating_degree_days
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
# Otherwise look up the `country` heating degree days.
|
|
410
|
+
quorum 'from country', :needs => :country,
|
|
411
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
412
|
+
characteristics[:country].heating_degree_days
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
#### Cooling degree days
|
|
417
|
+
# *The average number of annual cooling degree days (base 18°C) at the lodging's location.*
|
|
418
|
+
committee :cooling_degree_days do
|
|
419
|
+
# Use client input, if available
|
|
420
|
+
|
|
421
|
+
# Otherwise look up the `climate division` cooling degree days.
|
|
422
|
+
quorum 'from climate division', :needs => :climate_division,
|
|
423
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
424
|
+
characteristics[:climate_division].cooling_degree_days
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
# Otherwise look up the `country` cooling degree days.
|
|
428
|
+
quorum 'from country', :needs => :country,
|
|
429
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
430
|
+
characteristics[:country].cooling_degree_days
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
#### eGRID subregion
|
|
435
|
+
# *The [eGRID subregion](http://data.brighterplanet.com/egrid_subregions).*
|
|
436
|
+
committee :egrid_subregion do
|
|
437
|
+
# Look up the `zip code` eGRID subregion.
|
|
438
|
+
quorum 'from zip code', :needs => :zip_code,
|
|
439
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
440
|
+
characteristics[:zip_code].egrid_subregion
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
#### Country
|
|
445
|
+
# *The [country](http://data.brighterplanet.com/countries).*
|
|
446
|
+
committee :country do
|
|
447
|
+
# Use client input, if available.
|
|
448
|
+
|
|
449
|
+
# Otherwise if state is defined then the country is the United States.
|
|
450
|
+
quorum 'from state', :needs => :state,
|
|
451
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
452
|
+
Country.united_states
|
|
453
|
+
end
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
#### State
|
|
457
|
+
# *The [US state](http://data.brighterplanet.com/states).*
|
|
458
|
+
committee :state do
|
|
459
|
+
# Use client input, if available.
|
|
460
|
+
|
|
461
|
+
# Otherwise look up the `zip code` state.
|
|
462
|
+
quorum 'from zip code', :needs => :zip_code,
|
|
463
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
464
|
+
characteristics[:zip_code].state
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
#### City
|
|
469
|
+
# *The city.*
|
|
470
|
+
committee :city do
|
|
471
|
+
# Use client input, if available.
|
|
472
|
+
|
|
473
|
+
# Otherwise look up the `zip code` description.
|
|
474
|
+
quorum 'from zip code', :needs => :zip_code,
|
|
475
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
476
|
+
characteristics[:zip_code].description
|
|
477
|
+
end
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
#### Climate division
|
|
481
|
+
# *The [US climate division](http://data.brighterplanet.com/climate_divisions).*
|
|
482
|
+
committee :climate_division do
|
|
483
|
+
# Look up the `zip code` climate division.
|
|
484
|
+
quorum 'from zip code', :needs => :zip_code,
|
|
485
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics|
|
|
486
|
+
characteristics[:zip_code].climate_division
|
|
487
|
+
end
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
#### Zip code
|
|
491
|
+
# *The [US zip code](http://data.brighterplanet.com/zip_codes).*
|
|
492
|
+
#
|
|
493
|
+
# Use client input, if available.
|
|
494
|
+
|
|
495
|
+
#### Room nights (*room-nights*)
|
|
496
|
+
# *The stay's room-nights that occurred during `timeframe`.*
|
|
497
|
+
committee :room_nights do
|
|
498
|
+
# If `date` falls within `timeframe`, divide `duration` (*seconds*) by 86,400 (*seconds / night*) and multiply by `rooms` to give *room-nights*.
|
|
499
|
+
# Otherwise `room nights` is zero.
|
|
500
|
+
quorum 'from rooms, duration, date, and timeframe', :needs => [:rooms, :duration, :date],
|
|
501
|
+
:complies => [:ghg_protocol_scope_3, :iso, :tcr] do |characteristics, timeframe|
|
|
502
|
+
date = characteristics[:date].is_a?(Date) ? characteristics[:date] : Date.parse(characteristics[:date].to_s)
|
|
503
|
+
timeframe.include?(date) ? characteristics[:duration] / 86400.0 * characteristics[:rooms] : 0
|
|
504
|
+
end
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
#### Duration (*seconds*)
|
|
508
|
+
# *The stay's duration.*
|
|
509
|
+
committee :duration do
|
|
510
|
+
# Use client input, if available.
|
|
511
|
+
|
|
512
|
+
# Otherwise use 86400 *seconds* (1 night).
|
|
513
|
+
quorum 'default' do
|
|
514
|
+
86400.0
|
|
515
|
+
end
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
#### Rooms
|
|
519
|
+
# *The number of rooms used.*
|
|
520
|
+
committee :rooms do
|
|
521
|
+
# Use client input, if available.
|
|
522
|
+
|
|
523
|
+
# Otherwise use 1 *room*.
|
|
524
|
+
quorum 'default' do
|
|
525
|
+
1
|
|
526
|
+
end
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
#### Date (*date*)
|
|
530
|
+
# *The day the stay occurred.*
|
|
531
|
+
committee :date do
|
|
532
|
+
# Use client input, if available.
|
|
533
|
+
|
|
534
|
+
# Otherwise use the first day of `timeframe`.
|
|
535
|
+
quorum 'from timeframe',
|
|
536
|
+
:complies => [:ghg_protocol_scope_3, :iso] do |characteristics, timeframe|
|
|
537
|
+
timeframe.from
|
|
538
|
+
end
|
|
539
|
+
end
|
|
540
|
+
end
|
|
541
|
+
end
|
|
542
|
+
end
|
|
543
|
+
end
|
|
544
|
+
end
|