flight 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/features/flight_committees.feature +92 -130
- data/features/flight_emissions.feature +18 -18
- data/lib/flight/carbon_model.rb +339 -247
- data/lib/flight/data.rb +4 -5
- data/lib/flight/relationships.rb +9 -9
- metadata +19 -4
data/lib/flight/carbon_model.rb
CHANGED
@@ -2,33 +2,47 @@
|
|
2
2
|
# See LICENSE for details.
|
3
3
|
# Contact Brighter Planet for dual-license arrangements.
|
4
4
|
|
5
|
+
require 'leap'
|
6
|
+
require 'timeframe'
|
7
|
+
require 'date'
|
5
8
|
require 'weighted_average'
|
6
9
|
require 'builder'
|
7
10
|
|
8
|
-
## Flight
|
9
|
-
# This
|
11
|
+
## Flight carbon model
|
12
|
+
# This model is used by [Brighter Planet](http://brighterplanet.com)'s carbon emission [web service](http://carbon.brighterplanet.com) to estimate the **greenhouse gas emissions of passenger air travel**.
|
10
13
|
#
|
11
|
-
|
12
|
-
#
|
14
|
+
##### Timeframe and date
|
15
|
+
# The model estimates the emissions that occur during a particular `timeframe`. To do this it needs to know the `date` on which the flight occurred. For example, if the `timeframe` is January 2010, a flight that occured on January 5, 2010 will have emissions but a flight that occured on February 1, 2010 will not. If no `timeframe` is specified, the default is the current year. If no `date` is specified, the default is the first day of the `timeframe`.
|
13
16
|
#
|
14
|
-
|
17
|
+
##### Calculations
|
18
|
+
# The final estimate is the result of the **calculations** detailed below. These calculations are performed in reverse order, starting with the last calculation listed and finishing with the `emission` calculation. Each calculation is named according to the value it returns.
|
19
|
+
#
|
20
|
+
##### Methods
|
21
|
+
# To accomodate varying client input, each calculation may have one or more **methods**. These are listed under each calculation in order from most to least preferred. Each method is named according to the values it requires. If any of these values is not available the method will be ignored. If all the methods for a calculation are ignored, the calculation will not return a value. "Default" methods do not require any values, and so a calculation with a default method will always return a value.
|
22
|
+
#
|
23
|
+
##### Standard compliance
|
24
|
+
# Each method lists any established calculation standards with which it **complies**. When compliance with a standard is requested, all methods that do not comply with that standard are ignored. This means that any values a particular method requires will have been calculated using a compliant method, because those are the only methods available. If any value did not have a compliant method in its calculation then it would be undefined, and the current method would have been ignored.
|
25
|
+
#
|
26
|
+
##### Collaboration
|
27
|
+
# Contributions to this carbon 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 shold include test coverage for new functionality. Please see [sniff](http://github.com/brighterplanet/sniff#readme), our emitter testing framework, for more information.
|
15
28
|
module BrighterPlanet
|
16
29
|
module Flight
|
17
30
|
module CarbonModel
|
18
31
|
def self.included(base)
|
19
32
|
base.extend FastTimestamp
|
20
33
|
base.decide :emission, :with => :characteristics do
|
21
|
-
### Emission
|
22
|
-
#
|
23
|
-
#
|
34
|
+
### Emission calculation
|
35
|
+
# Returns the `emission` estimate in *kg CO<sub>2</sub>e*.
|
36
|
+
# This is the passenger's share of the total flight emissions that occured during the `timeframe`.
|
24
37
|
committee :emission do
|
25
|
-
|
26
|
-
#
|
38
|
+
#### Emission from fuel, emission factor, freight share, passengers, multipliers, and date
|
39
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
27
40
|
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
41
|
+
# - Checks whether the flight occured during the `timeframe`
|
42
|
+
# - Multiplies `fuel use` (*kg fuel*) by an `emission factor` (*kg CO<sub>2</sub>e / kg fuel*) and an `aviation multiplier` to give total flight emissions in *kg CO<sub>2</sub>e*
|
43
|
+
# - Multiplies by (1 - `freight share`) to take out emissions attributed to freight cargo and mail, leaving emissions attributed to passengers and their baggage
|
44
|
+
# - Divides by the number of `passengers` and multiplies by a `seat class multiplier` to give `emission` for the passenger
|
45
|
+
# - If the flight did not occur during the `timeframe`, `emission` is zero
|
32
46
|
quorum 'from fuel, emission factor, freight share, passengers, multipliers, and date',
|
33
47
|
:needs => [:fuel, :emission_factor, :freight_share, :passengers, :seat_class_multiplier, :aviation_multiplier, :date], :complies => [:ghg_protocol, :iso, :tcr] do |characteristics, timeframe|
|
34
48
|
date = characteristics[:date].is_a?(Date) ?
|
@@ -36,52 +50,60 @@ module BrighterPlanet
|
|
36
50
|
Date.parse(characteristics[:date].to_s)
|
37
51
|
if timeframe.include? date
|
38
52
|
characteristics[:fuel] * characteristics[:emission_factor] * characteristics[:aviation_multiplier] * (1 - characteristics[:freight_share]) / characteristics[:passengers] * characteristics[:seat_class_multiplier]
|
39
|
-
# If the flight did not occur during the `timeframe`, `emission` is zero.
|
40
53
|
else
|
41
54
|
0
|
42
55
|
end
|
43
56
|
end
|
44
|
-
|
45
|
-
quorum 'default' do
|
46
|
-
raise "The emission committee's default quorum should never be called"
|
47
|
-
end
|
48
57
|
end
|
49
58
|
|
50
|
-
### Emission factor
|
51
|
-
#
|
59
|
+
### Emission factor calculation
|
60
|
+
# Returns the `emission factor` in *kg CO<sub>2</sub>e / kg fuel*.
|
52
61
|
committee :emission_factor do
|
53
|
-
|
54
|
-
#
|
62
|
+
#### Emission factor from fuel type
|
63
|
+
# Complies: GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
64
|
+
#
|
65
|
+
# Looks up the [fuel type](http://data.brighterplanet.com/fuel_types) and divides its `emission factor` (*kg CO<sub>2</sub> / litre fuel*) by its `density` (*kg fuel / litre fuel*) to give *kg CO<sub>2</sub>e / kg fuel*.
|
55
66
|
quorum 'from fuel type', :needs => :fuel_type, :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
56
67
|
characteristics[:fuel_type].emission_factor.to_f / characteristics[:fuel_type].density.to_f
|
57
68
|
end
|
58
69
|
end
|
59
70
|
|
60
|
-
### Aviation multiplier
|
61
|
-
#
|
71
|
+
### Aviation multiplier calculation
|
72
|
+
# Returns the `aviation multiplier`. This approximates the extra climate impact of emissions high in the atmosphere.
|
62
73
|
committee :aviation_multiplier do
|
63
|
-
|
64
|
-
#
|
74
|
+
#### Aviation multiplier from client input
|
75
|
+
# **Complies:** All
|
76
|
+
#
|
77
|
+
# Uses the client-input `aviation multiplier`.
|
78
|
+
|
79
|
+
#### Default aviation multiplier
|
80
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
81
|
+
#
|
82
|
+
# Uses an `aviation multiplier` of **2.0** after [Kolmuss and Crimmins (2009)](http://sei-us.org/publications/id/13).
|
65
83
|
quorum 'default', :complies => [:ghg_protocol, :iso, :tcr] do
|
66
|
-
|
84
|
+
2.0
|
67
85
|
end
|
68
86
|
end
|
69
87
|
|
70
|
-
### Fuel
|
71
|
-
#
|
88
|
+
### Fuel calculation
|
89
|
+
# Returns the flight's total `fuel` use in *kg fuel*.
|
72
90
|
committee :fuel do
|
73
|
-
|
74
|
-
#
|
91
|
+
#### Fuel from fuel per segment and segments per trip and trips
|
92
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
93
|
+
#
|
94
|
+
# Multiplies the `fuel per segment` (*kg fuel*) by the `segments per trip` and the number of `trips` to give *kg fuel*.
|
75
95
|
quorum 'from fuel per segment and segments per trip and trips', :needs => [:fuel_per_segment, :segments_per_trip, :trips], :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
76
96
|
characteristics[:fuel_per_segment] * characteristics[:segments_per_trip].to_f * characteristics[:trips].to_f
|
77
97
|
end
|
78
98
|
end
|
79
99
|
|
80
|
-
### Fuel per segment
|
81
|
-
#
|
100
|
+
### Fuel per segment calculation
|
101
|
+
# Returns the `fuel per segment` in *kg fuel*.
|
82
102
|
committee :fuel_per_segment do
|
83
|
-
|
84
|
-
#
|
103
|
+
#### Fuel per segment from adjusted distance per segment and fuel use coefficients
|
104
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
105
|
+
#
|
106
|
+
# Uses a third-order polynomial equation to calculate the fuel used per segment:
|
85
107
|
#
|
86
108
|
# (m<sub>3</sub> * d^3 ) + (m<sub>2</sub> * d^2 ) + (m<sub>1</sub> * d) + endpoint fuel
|
87
109
|
#
|
@@ -94,32 +116,38 @@ module BrighterPlanet
|
|
94
116
|
end
|
95
117
|
end
|
96
118
|
|
97
|
-
### Adjusted distance per segment
|
98
|
-
#
|
119
|
+
### Adjusted distance per segment calculation
|
120
|
+
# Returns the `adjusted distance per segment` in *nautical miles*.
|
99
121
|
committee :adjusted_distance_per_segment do
|
100
|
-
|
101
|
-
#
|
122
|
+
#### Adjusted distance per segment from adjusted distance and segments per trip
|
123
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
124
|
+
#
|
125
|
+
# Divides the `adjusted distance` (*nautical miles*) by `segments per trip` to give *nautical miles*.
|
102
126
|
quorum 'from adjusted distance and segments per trip', :needs => [:adjusted_distance, :segments_per_trip], :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
103
127
|
characteristics[:adjusted_distance] / characteristics[:segments_per_trip]
|
104
128
|
end
|
105
129
|
end
|
106
130
|
|
107
|
-
### Adjusted distance
|
108
|
-
#
|
131
|
+
### Adjusted distance calculation
|
132
|
+
# Returns the `adjusted distance` in *nautical miles*.
|
109
133
|
# The `adjusted distance` accounts for factors that increase the actual distance traveled by real world flights.
|
110
134
|
committee :adjusted_distance do
|
111
|
-
|
112
|
-
#
|
135
|
+
#### Adjusted distance from distance, route inefficiency factor, and dogleg factor
|
136
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
137
|
+
#
|
138
|
+
# Multiplies `distance` (*nautical miles*) by a `route inefficiency factor` and a `dogleg factor` to give *nautical miles*.
|
113
139
|
quorum 'from distance, route inefficiency factor, and dogleg factor', :needs => [:distance, :route_inefficiency_factor, :dogleg_factor], :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
114
140
|
characteristics[:distance] * characteristics[:route_inefficiency_factor] * characteristics[:dogleg_factor]
|
115
141
|
end
|
116
142
|
end
|
117
143
|
|
118
|
-
### Distance
|
119
|
-
#
|
144
|
+
### Distance calculation
|
145
|
+
# Returns the flight's base `distance` in *nautical miles*.
|
120
146
|
committee :distance do
|
121
|
-
|
122
|
-
#
|
147
|
+
#### Distance from airports
|
148
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
149
|
+
#
|
150
|
+
# Calculates the great circle distance between the `origin airport` and `destination airport` and converts from *km* to *nautical miles*.
|
123
151
|
quorum 'from airports', :needs => [:origin_airport, :destination_airport], :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
124
152
|
if characteristics[:origin_airport].latitude and
|
125
153
|
characteristics[:origin_airport].longitude and
|
@@ -129,70 +157,88 @@ module BrighterPlanet
|
|
129
157
|
end
|
130
158
|
end
|
131
159
|
|
132
|
-
|
133
|
-
#
|
160
|
+
#### Distance from distance estimate
|
161
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
162
|
+
#
|
163
|
+
# Converts the `distance_estimate` in *km* to *nautical miles*.
|
134
164
|
quorum 'from distance estimate', :needs => :distance_estimate, :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
135
165
|
characteristics[:distance_estimate].kilometres.to :nautical_miles
|
136
166
|
end
|
137
167
|
|
138
|
-
|
139
|
-
#
|
168
|
+
#### Distance from distance class
|
169
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
170
|
+
#
|
171
|
+
# Looks up the [distance class](http://data.brighterplanet.com/flight_distance_classes)' `distance` and converts from *km* to *nautical miles*.
|
140
172
|
quorum 'from distance class', :needs => :distance_class, :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
141
173
|
characteristics[:distance_class].distance.kilometres.to :nautical_miles
|
142
174
|
end
|
143
175
|
|
144
|
-
|
145
|
-
#
|
176
|
+
#### Distance from cohort
|
177
|
+
# **Complies:**
|
178
|
+
#
|
179
|
+
# Calculates the average `distance` of the `cohort` segments, weighted by their passengers, and converts from *km* to *nautical miles*.
|
146
180
|
quorum 'from cohort', :needs => :cohort do |characteristics| # cohort here will be some combo of origin, airline, and aircraft
|
147
181
|
distance = characteristics[:cohort].weighted_average(:distance, :weighted_by => :passengers).kilometres.to(:nautical_miles)
|
148
182
|
distance > 0 ? distance : nil
|
149
183
|
end
|
150
184
|
|
151
|
-
|
152
|
-
#
|
185
|
+
#### Default distance
|
186
|
+
# **Complies:**
|
187
|
+
#
|
188
|
+
# Calculates the average `distance` of [all segments in the T-100 database](http://data.brighterplanet.com/flight_segments), weighted by their passengers, and converts from *km* to *nautical miles*.
|
153
189
|
quorum 'default' do
|
154
190
|
FlightSegment.fallback.distance.kilometres.to :nautical_miles
|
155
191
|
end
|
156
192
|
end
|
157
193
|
|
158
|
-
### Route inefficiency factor
|
159
|
-
# This calculation returns the `route inefficiency factor
|
194
|
+
### Route inefficiency factor calculation
|
195
|
+
# This calculation returns the `route inefficiency factor`.
|
196
|
+
# This is a measure of how much farther real world flights travel than the great circle distance between their origin and destination.
|
160
197
|
# It accounts for factors like flight path routing around controlled airspace and circling while waiting for clearance to land.
|
161
198
|
committee :route_inefficiency_factor do
|
162
|
-
|
163
|
-
#
|
199
|
+
#### Route inefficiency factor from country
|
200
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
201
|
+
#
|
202
|
+
# Looks up the `route inefficiency factor` for the [country](http://data.brighterplanet.com/countries) in which the flight occurs.
|
164
203
|
quorum 'from country', :needs => :country, :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
165
204
|
characteristics[:country].andand.flight_route_inefficiency_factor
|
166
205
|
end
|
167
206
|
|
168
|
-
|
169
|
-
#
|
207
|
+
#### Default route inefficiency factor
|
208
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
209
|
+
#
|
210
|
+
# Uses a `route inefficiency factor` of **10%** based on [Kettunen et al. (2005)](http://www.atmseminar.org/seminarContent/seminar6/papers/p_055_MPM.pdf)
|
170
211
|
quorum 'default', :complies => [:ghg_protocol, :iso, :tcr] do
|
171
212
|
Country.fallback.flight_route_inefficiency_factor
|
172
213
|
end
|
173
214
|
end
|
174
215
|
|
175
|
-
### Dogleg factor
|
176
|
-
#
|
216
|
+
### Dogleg factor calculation
|
217
|
+
# Returns the `dogleg factor`.
|
218
|
+
# This is a measure of how far out of the way the average layover is compared to a direct flight.
|
177
219
|
committee :dogleg_factor do
|
178
|
-
|
179
|
-
#
|
220
|
+
#### Dogleg factor from segments per trip
|
221
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
222
|
+
#
|
223
|
+
# Assumes that each layover increases the total flight distance by **25%**.
|
180
224
|
quorum 'from segments per trip', :needs => :segments_per_trip, :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
181
|
-
|
225
|
+
1.25 ** (characteristics[:segments_per_trip] - 1)
|
182
226
|
end
|
183
227
|
end
|
184
228
|
|
185
|
-
### Distance estimate
|
186
|
-
#
|
229
|
+
### Distance estimate calculation
|
230
|
+
# Returns the client-input `distance estimate` in *km*.
|
187
231
|
|
188
|
-
### Distance class
|
189
|
-
#
|
232
|
+
### Distance class calculation
|
233
|
+
# Returns the client-input [distance class](http://data.brighterplanet.com/distance_classes).
|
190
234
|
|
191
|
-
### Fuel use coefficients
|
192
|
-
#
|
235
|
+
### Fuel use coefficients calculation
|
236
|
+
# Returns the `fuel use coefficients`. These are the coefficients of the third-order polynomial equation that describes aircraft fuel use.
|
193
237
|
committee :fuel_use_coefficients do
|
194
|
-
|
195
|
-
#
|
238
|
+
#### Fuel use coefficients from aircraft
|
239
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
240
|
+
#
|
241
|
+
# Looks up the [aircraft](http://data.brighterplanet.com/aircraft)'s `fuel use coefficients`.
|
196
242
|
quorum 'from aircraft', :needs => :aircraft, :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
197
243
|
aircraft = characteristics[:aircraft]
|
198
244
|
fuel_use = FuelUseEquation.new aircraft.m3, aircraft.m2, aircraft.m1, aircraft.endpoint_fuel
|
@@ -203,15 +249,20 @@ module BrighterPlanet
|
|
203
249
|
end
|
204
250
|
end
|
205
251
|
|
206
|
-
|
207
|
-
#
|
252
|
+
#### Fuel use coefficients from aircraft class
|
253
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
254
|
+
#
|
255
|
+
# Looks up the [aircraft class](http://data.brighterplanet.com/aircraft_classes)' `fuel use coefficients`.
|
208
256
|
quorum 'from aircraft class', :needs => :aircraft_class, :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
209
257
|
aircraft_class = characteristics[:aircraft_class]
|
210
258
|
FuelUseEquation.new aircraft_class.m3, aircraft_class.m2, aircraft_class.m1, aircraft_class.endpoint_fuel
|
211
259
|
end
|
212
260
|
|
213
|
-
|
214
|
-
#
|
261
|
+
#### Fuel use coefficients from cohort
|
262
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
263
|
+
#
|
264
|
+
# Calculates the average `fuel use coefficients` of the aircraft used by the `cohort` segments, weighted by the segment passengers.
|
265
|
+
# If an aircraft does not have `fuel use coefficients`, it takes the `fuel use coefficients` for the aircraft's [aircraft class](http://data.brighterplanet.com/aircraft_classes).
|
215
266
|
quorum 'from cohort', :needs => :cohort, :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
216
267
|
flight_segments = characteristics[:cohort]
|
217
268
|
|
@@ -219,119 +270,102 @@ module BrighterPlanet
|
|
219
270
|
passengers + flight_segment.passengers
|
220
271
|
end
|
221
272
|
|
222
|
-
bts_codes = flight_segments.map(&:
|
223
|
-
relevant_aircraft = Aircraft.
|
224
|
-
hsh[aircraft.
|
273
|
+
bts_codes = flight_segments.map(&:aircraft_bts_code).uniq
|
274
|
+
relevant_aircraft = Aircraft.find_all_by_bts_code(bts_codes).inject({}) do |hsh, aircraft|
|
275
|
+
hsh[aircraft.bts_code] = aircraft
|
225
276
|
hsh
|
226
277
|
end
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
aircraft = flight_segment_aircraft[flight_segment.row_hash]
|
238
|
-
aircraft_m3 = aircraft.andand.m3 || 0
|
239
|
-
m3 + (aircraft_m3 * flight_segment.passengers)
|
240
|
-
end
|
241
|
-
else
|
242
|
-
m3 = Aircraft.fallback.m3
|
243
|
-
end
|
244
|
-
|
245
|
-
if flight_segment_aircraft.values.map(&:m2).any?
|
246
|
-
m2 = flight_segments.inject(0) do |m2, flight_segment|
|
247
|
-
aircraft = flight_segment_aircraft[flight_segment.row_hash]
|
248
|
-
aircraft_m2 = aircraft.andand.m2 || 0
|
249
|
-
m2 + (aircraft_m2 * flight_segment.passengers)
|
250
|
-
end
|
251
|
-
else
|
252
|
-
m2 = Aircraft.fallback.m2
|
253
|
-
end
|
254
|
-
|
255
|
-
if flight_segment_aircraft.values.map(&:m1).any?
|
256
|
-
m1 = flight_segments.inject(0) do |m1, flight_segment|
|
257
|
-
aircraft = flight_segment_aircraft[flight_segment.row_hash]
|
258
|
-
aircraft_m1 = aircraft.andand.m1 || 0
|
259
|
-
m1 + (aircraft_m1 * flight_segment.passengers)
|
260
|
-
end
|
261
|
-
else
|
262
|
-
m1 = Aircraft.fallback.m1
|
263
|
-
end
|
264
|
-
|
265
|
-
if flight_segment_aircraft.values.map(&:endpoint_fuel).any?
|
266
|
-
endpoint_fuel = flight_segments.inject(0) do |endpoint_fuel, flight_segment|
|
267
|
-
aircraft = flight_segment_aircraft[flight_segment.row_hash]
|
268
|
-
aircraft_epfuel = aircraft.andand.endpoint_fuel || 0
|
269
|
-
endpoint_fuel + (aircraft_epfuel * flight_segment.passengers)
|
278
|
+
|
279
|
+
sum_coefficients = lambda do |name|
|
280
|
+
flight_segments.inject(0) do |coefficient, flight_segment|
|
281
|
+
bts_code = flight_segment.aircraft_bts_code.to_s
|
282
|
+
aircraft = relevant_aircraft[bts_code]
|
283
|
+
aircraft_coefficient = aircraft.send(name)
|
284
|
+
if aircraft_coefficient.nil? or aircraft_coefficient.zero?
|
285
|
+
aircraft_coefficient = aircraft.aircraft_class.send(name)
|
286
|
+
end
|
287
|
+
coefficient + (aircraft_coefficient * flight_segment.passengers)
|
270
288
|
end
|
271
|
-
else
|
272
|
-
endpoint_fuel = Aircraft.fallback.endpoint_fuel
|
273
289
|
end
|
290
|
+
|
291
|
+
m3 = sum_coefficients.call(:m3) / passengers
|
292
|
+
m2 = sum_coefficients.call(:m2) / passengers
|
293
|
+
m1 = sum_coefficients.call(:m1) / passengers
|
294
|
+
endpoint_fuel = sum_coefficients.call(:endpoint_fuel) / passengers
|
274
295
|
|
275
|
-
|
276
|
-
m3 = m3 / passengers
|
277
|
-
m2 = m2 / passengers
|
278
|
-
m1 = m1 / passengers
|
279
|
-
endpoint_fuel = endpoint_fuel / passengers
|
280
|
-
|
281
|
-
FuelUseEquation.new m3, m2, m1, endpoint_fuel
|
282
|
-
end
|
296
|
+
FuelUseEquation.new m3, m2, m1, endpoint_fuel
|
283
297
|
end
|
284
298
|
|
285
|
-
|
286
|
-
#
|
299
|
+
#### Default fuel use coefficients
|
300
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
301
|
+
#
|
302
|
+
# Calculates the average `fuel use coefficients` of the aircraft used by [all segments in the T-100 database](http://data.brighterplanet.com/flight_segments), weighted by the segment passengers.
|
303
|
+
# If an aircraft does not have `fuel use coefficients`, it takes the `fuel use coefficients` for the aircraft's [aircraft class](http://data.brighterplanet.com/aircraft_classes).
|
287
304
|
quorum 'default', :complies => [:ghg_protocol, :iso, :tcr] do
|
288
|
-
fallback
|
289
|
-
if fallback
|
290
|
-
FuelUseEquation.new fallback.m3, fallback.m2, fallback.m1, fallback.endpoint_fuel
|
291
|
-
end
|
305
|
+
FuelUseEquation.new Aircraft.fallback.m3, Aircraft.fallback.m2, Aircraft.fallback.m1, Aircraft.fallback.endpoint_fuel
|
292
306
|
end
|
293
307
|
end
|
294
308
|
|
295
|
-
### Fuel type
|
296
|
-
#
|
309
|
+
### Fuel type calculation
|
310
|
+
# Returns the `fuel type`.
|
297
311
|
committee :fuel_type do
|
298
|
-
|
299
|
-
#
|
312
|
+
#### Fuel type from client input
|
313
|
+
# **Complies:** All
|
314
|
+
#
|
315
|
+
# Uses the client-input [fuel type](http://data.brighterplanet.com/fuel_types).
|
300
316
|
|
301
|
-
|
302
|
-
#
|
303
|
-
|
317
|
+
#### Default fuel type
|
318
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
319
|
+
#
|
320
|
+
# Assumes the flight uses **Jet Fuel**.
|
321
|
+
quorum 'default', :complies => [:ghg_protocol, :ico, :tcr] do
|
304
322
|
FuelType.find_by_name 'Jet Fuel'
|
305
323
|
end
|
306
324
|
end
|
307
325
|
|
308
|
-
### Passengers
|
309
|
-
#
|
326
|
+
### Passengers calculation
|
327
|
+
# Returns the number of `passengers`.
|
310
328
|
committee :passengers do
|
311
|
-
|
312
|
-
#
|
329
|
+
#### Passengers from seats and load factor
|
330
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
331
|
+
#
|
332
|
+
# Multiplies the number of `seats` by the `load factor`.
|
313
333
|
quorum 'from seats and load factor', :needs => [:seats, :load_factor], :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
314
334
|
(characteristics[:seats] * characteristics[:load_factor]).round
|
315
335
|
end
|
316
336
|
end
|
317
337
|
|
318
|
-
### Seats
|
319
|
-
#
|
338
|
+
### Seats calculation
|
339
|
+
# Returns the number of `seats`.
|
320
340
|
committee :seats do
|
321
|
-
|
322
|
-
#
|
341
|
+
#### Seats from seats estimate
|
342
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
343
|
+
#
|
344
|
+
# Uses the client-input estimate of the number of `seats`.
|
345
|
+
quorum 'from seats estimate', :needs => :seats_estimate, :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
346
|
+
characteristics[:seats_estimate]
|
347
|
+
end
|
348
|
+
|
349
|
+
#### Seats from aircraft
|
350
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
351
|
+
#
|
352
|
+
# Looks up the [aircraft](http://data.brighterplanet.com/aircraft)'s average number of `seats`.
|
323
353
|
quorum 'from aircraft', :needs => :aircraft, :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
324
354
|
characteristics[:aircraft].seats
|
325
355
|
end
|
326
356
|
|
327
|
-
|
328
|
-
#
|
329
|
-
|
330
|
-
|
357
|
+
#### Seats from aircraft class
|
358
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
359
|
+
#
|
360
|
+
# Looks up the [aircraft class](http://data.brighterplanet.com/aircraft_classes)' average number of `seats`.
|
361
|
+
quorum 'from aircraft class', :needs => :aircraft_class, :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
362
|
+
characteristics[:aircraft_class].seats
|
331
363
|
end
|
332
364
|
|
333
|
-
|
334
|
-
#
|
365
|
+
#### Seats from cohort
|
366
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
367
|
+
#
|
368
|
+
# Calculates the average number of `seats` of the `cohort` segments, weighted by their passengers.
|
335
369
|
quorum 'from cohort', :needs => :cohort, :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
336
370
|
seats = characteristics[:cohort].weighted_average :seats, :weighted_by => :passengers
|
337
371
|
if seats.nil? or seats.zero?
|
@@ -341,121 +375,156 @@ module BrighterPlanet
|
|
341
375
|
end
|
342
376
|
end
|
343
377
|
|
344
|
-
|
345
|
-
#
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
##### Default
|
351
|
-
# This default method calculates the average number of `seats` of [all segments in the T-100 database](http://data.brighterplanet.com/flight_segments), weighted by their passengers.
|
352
|
-
quorum 'default' do
|
353
|
-
FlightSegment.fallback.seats.to_f # need before_type_cast b/c seats is an integer but the fallback value is a float
|
378
|
+
#### Default seats
|
379
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
380
|
+
#
|
381
|
+
# Calculates the average number of `seats` of [all segments in the T-100 database](http://data.brighterplanet.com/flight_segments), weighted by their passengers.
|
382
|
+
quorum 'default', :complies => [:ghg_protocol, :iso, :tcr] do
|
383
|
+
FlightSegment.fallback.seats
|
354
384
|
end
|
355
385
|
end
|
356
386
|
|
357
|
-
### Seats estimate
|
358
|
-
#
|
387
|
+
### Seats estimate calculation
|
388
|
+
# Returns the client-input `seats estimate`.
|
359
389
|
|
360
|
-
### Load factor
|
361
|
-
#
|
362
|
-
#
|
390
|
+
### Load factor calculation
|
391
|
+
# Returns the `load factor`.
|
392
|
+
# This is the portion of available seats that are occupied.
|
363
393
|
committee :load_factor do
|
364
|
-
|
365
|
-
#
|
394
|
+
#### Load factor from client input
|
395
|
+
# **Complies:** All
|
396
|
+
#
|
397
|
+
# Uses the client-input `load factor`.
|
366
398
|
|
367
|
-
|
368
|
-
#
|
399
|
+
#### Load factor from cohort
|
400
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
401
|
+
#
|
402
|
+
# Calculates the average `load factor` of the `cohort` segments, weighted by their passengers.
|
369
403
|
quorum 'from cohort', :needs => :cohort, :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
370
404
|
characteristics[:cohort].weighted_average(:load_factor, :weighted_by => :passengers)
|
371
405
|
end
|
372
406
|
|
373
|
-
|
374
|
-
#
|
407
|
+
#### Default load factor
|
408
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
409
|
+
#
|
410
|
+
# Calculates the average `load factor` of [all segments in the T-100 database](http://data.brighterplanet.com/flight_segments), weighted by their passengers.
|
375
411
|
quorum 'default', :complies => [:ghg_protocol, :iso, :tcr] do
|
376
412
|
FlightSegment.fallback.load_factor
|
377
413
|
end
|
378
414
|
end
|
379
415
|
|
380
|
-
### Freight share
|
381
|
-
#
|
382
|
-
#
|
416
|
+
### Freight share calculation
|
417
|
+
# Returns the `freight share`.
|
418
|
+
# This is the percent of the total aircraft weight that is freight cargo and mail (as opposed to passengers and their baggage).
|
383
419
|
committee :freight_share do
|
384
|
-
|
385
|
-
#
|
420
|
+
#### Freight share from cohort
|
421
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
422
|
+
#
|
423
|
+
# Calculates the average `freight share` of the `cohort` segments, weighted by their passengers.
|
386
424
|
quorum 'from cohort', :needs => :cohort, :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
387
425
|
characteristics[:cohort].weighted_average(:freight_share, :weighted_by => :passengers)
|
388
426
|
end
|
389
427
|
|
390
|
-
|
391
|
-
#
|
428
|
+
#### Default freight share
|
429
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
430
|
+
#
|
431
|
+
# Calculates the average `freight share` of [all segments in the T-100 database](http://data.brighterplanet.com/flight_segments), weighted by their passengers.
|
392
432
|
quorum 'default', :complies => [:ghg_protocol, :iso, :tcr] do
|
393
433
|
FlightSegment.fallback.freight_share
|
394
434
|
end
|
395
435
|
end
|
396
436
|
|
397
|
-
### Trips
|
398
|
-
#
|
437
|
+
### Trips calculation
|
438
|
+
# Returns the number of `trips`.
|
399
439
|
# A one-way flight has one trip; a round-trip flight has two trips.
|
400
440
|
committee :trips do
|
401
|
-
|
402
|
-
#
|
441
|
+
#### Trips from client input
|
442
|
+
# **Complies:** All
|
443
|
+
#
|
444
|
+
# Uses the client-input number of `trips`.
|
403
445
|
|
404
|
-
|
405
|
-
#
|
446
|
+
#### Default trips
|
447
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
448
|
+
#
|
449
|
+
# Uses an average number of `trips` of **1.941**, taken from the [U.S. National Household Travel Survey](http://www.bts.gov/publications/america_on_the_go/long_distance_transportation_patterns/html/table_07.html).
|
406
450
|
quorum 'default', :complies => [:ghg_protocol, :iso, :tcr] do
|
407
|
-
|
451
|
+
1.941
|
408
452
|
end
|
409
453
|
end
|
410
454
|
|
411
|
-
### Seat class multiplier
|
412
|
-
#
|
455
|
+
### Seat class multiplier calculation
|
456
|
+
# Returns the `seat class multiplier`. This reflects the amount of cabin space occupied by the passenger's seat.
|
413
457
|
committee :seat_class_multiplier do
|
414
|
-
|
415
|
-
#
|
458
|
+
#### Seat class multiplier from seat class
|
459
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
460
|
+
#
|
461
|
+
# Looks up the [seat class](http://data.brighterplanet.com/flight_seat_classes)' `seat class multiplier`.
|
416
462
|
quorum 'from seat class', :needs => :seat_class, :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
417
463
|
characteristics[:seat_class].multiplier
|
418
464
|
end
|
419
465
|
|
420
|
-
|
421
|
-
#
|
466
|
+
#### Default seat class multiplier
|
467
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
468
|
+
#
|
469
|
+
# Uses a `seat class multiplier` of **1**.
|
422
470
|
quorum 'default', :complies => [:ghg_protocol, :iso, :tcr] do
|
423
471
|
FlightSeatClass.fallback.multiplier
|
424
472
|
end
|
425
473
|
end
|
426
474
|
|
427
|
-
### Seat class
|
428
|
-
#
|
475
|
+
### Seat class calculation
|
476
|
+
# Returns the client-input [seat class](http://data.brighterplanet.com/seat_classes).
|
429
477
|
|
430
|
-
### Country
|
431
|
-
#
|
478
|
+
### Country calculation
|
479
|
+
# Returns the [country](http://data.brighterplanet.com/countries) in which a flight occurs.
|
432
480
|
committee :country do
|
433
|
-
|
434
|
-
#
|
481
|
+
#### Country from client input
|
482
|
+
# **Complies:** All
|
483
|
+
#
|
484
|
+
# Uses the client-input [country](http://data.brighterplanet.com/countries).
|
485
|
+
|
486
|
+
#### Country from origin airport and destination airport
|
487
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
488
|
+
#
|
489
|
+
# Checks whether the flight's `origin airport` and `destination airport` are within the same country.
|
435
490
|
# If so, that country is the `country`.
|
436
491
|
quorum 'from origin airport and destination airport', :needs => [:origin_airport, :destination_airport], :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
437
492
|
if characteristics[:origin_airport].country == characteristics[:destination_airport].country
|
438
493
|
characteristics[:origin_airport].country
|
439
494
|
end
|
440
495
|
end
|
496
|
+
end
|
497
|
+
|
498
|
+
### Aircraft Class calculation
|
499
|
+
# This calculation returns the [aircraft class](http://data.brighterplanet.com/aircraft_classes).
|
500
|
+
committee :aircraft_class do
|
501
|
+
#### Aircraft class from client input
|
502
|
+
# **Complies:** All
|
503
|
+
#
|
504
|
+
# Uses the client-input [aircraft_class](http://data.brighterplanet.com/aircraft_classes).
|
441
505
|
|
442
|
-
|
443
|
-
#
|
506
|
+
#### Aircraft class from aircraft
|
507
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
508
|
+
#
|
509
|
+
# Looks up the [aircraft](http://data.brighterplanet.com/aircraft)'s [aircraft_class](http://data.brighterplanet.com/aircraft_classes).
|
510
|
+
quorum 'from aircraft', :needs => :aircraft, :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
511
|
+
characteristics[:aircraft].aircraft_class
|
512
|
+
end
|
444
513
|
end
|
445
514
|
|
446
|
-
### Cohort
|
447
|
-
#
|
515
|
+
### Cohort calculation
|
516
|
+
# Returns the `cohort`.
|
517
|
+
# This is a set of flight segment records in the [T-100 database](http://data.brighterplanet.com/flight_segments) that match certain client-input values.
|
448
518
|
committee :cohort do
|
449
|
-
|
450
|
-
#
|
451
|
-
#
|
452
|
-
# 1. Checks that the flight is direct
|
453
|
-
# 2. Takes the input values for `origin airport`, `destination airport`, `aircraft`, and `airline`
|
454
|
-
# 3. Selects all the records in the T-100 database that match the available input values
|
455
|
-
# 4. Drops the last input value (initially `airline`, then `aircraft`, etc.) if no records match all of the available input values
|
456
|
-
# 5. Repeats steps 3 and 4 until some records match or no input values remain
|
519
|
+
#### Cohort from segments per trip and input
|
520
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
457
521
|
#
|
458
|
-
#
|
522
|
+
# - Checks whether the flight is direct
|
523
|
+
# - Takes the input values for `origin airport`, `destination airport`, `aircraft`, and `airline`
|
524
|
+
# - Selects all the records in the T-100 database that match the available input values
|
525
|
+
# - Drops the last input value (initially `airline`, then `aircraft`, etc.) if no records match all of the available input values
|
526
|
+
# - Repeats steps 3 and 4 until some records match or no input values remain
|
527
|
+
# - If no records match any of the input values, or if the flight is indirect, then `cohort` is undefined.
|
459
528
|
quorum 'from segments per trip and input', :needs => :segments_per_trip, :appreciates => [:origin_airport, :destination_airport, :aircraft, :airline], :complies => [:ghg_protocol, :iso, :tcr] do |characteristics|
|
460
529
|
cohort = {}
|
461
530
|
if characteristics[:segments_per_trip] == 1
|
@@ -474,53 +543,76 @@ module BrighterPlanet
|
|
474
543
|
end
|
475
544
|
end
|
476
545
|
|
477
|
-
### Origin airport
|
478
|
-
#
|
546
|
+
### Origin airport calculation
|
547
|
+
# Returns the client-input [origin airport](http://data.brighterplanet.com/airports).
|
479
548
|
|
480
|
-
### Destination airport
|
481
|
-
#
|
549
|
+
### Destination airport calculation
|
550
|
+
# Returns the client-input [destination airport](http://data.brighterplanet.com/airports).
|
482
551
|
|
483
|
-
### Aircraft
|
484
|
-
#
|
552
|
+
### Aircraft calculation
|
553
|
+
# Returns the client-input type of [aircraft](http://data.brighterplanet.com/aircraft).
|
485
554
|
|
486
|
-
###
|
487
|
-
#
|
555
|
+
### Airline calculation
|
556
|
+
# Returns the client-input [airline](http://data.brighterplanet.com/airlines) operating the flight.
|
488
557
|
|
489
|
-
###
|
490
|
-
#
|
491
|
-
|
492
|
-
### Segments per trip
|
493
|
-
# This calculation returns the `segments per trip`.
|
558
|
+
### Segments per trip calculation
|
559
|
+
# Returns the `segments per trip`.
|
494
560
|
# Direct flights have a single segment per trip. Indirect flights with one or more layovers have two or more segments per trip.
|
495
561
|
committee :segments_per_trip do
|
496
|
-
|
497
|
-
#
|
562
|
+
#### Segments per trip from client input
|
563
|
+
# **Complies:** All
|
564
|
+
#
|
565
|
+
# Uses the client-input `segments per trip`.
|
498
566
|
|
499
|
-
|
500
|
-
#
|
567
|
+
#### Default segments per trip
|
568
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
569
|
+
#
|
570
|
+
# Uses an average `segments per trip` of **1.67**, calculated from the [U.S. National Household Travel Survey](http://nhts.ornl.gov/).
|
501
571
|
quorum 'default', :complies => [:ghg_protocol, :iso, :tcr] do
|
502
|
-
|
572
|
+
1.67
|
503
573
|
end
|
504
574
|
end
|
505
575
|
|
506
|
-
### Date
|
507
|
-
#
|
576
|
+
### Date calculation
|
577
|
+
# Returns the `date` on which the flight occured.
|
508
578
|
committee :date do
|
509
|
-
|
510
|
-
#
|
579
|
+
#### Date from client input
|
580
|
+
# **Complies:** All
|
581
|
+
#
|
582
|
+
# Uses the client-input value for `date`.
|
511
583
|
|
512
|
-
|
513
|
-
#
|
584
|
+
#### Date from timeframe
|
585
|
+
# **Complies:** GHG Protocol, ISO-14064-1, Climate Registry Protocol
|
586
|
+
#
|
587
|
+
# Assumes the flight occured on the first day of the `timeframe`.
|
514
588
|
quorum 'from timeframe', :complies => [:ghg_protocol, :iso, :tcr] do |characteristics, timeframe|
|
515
589
|
timeframe.from
|
516
590
|
end
|
517
591
|
end
|
592
|
+
|
593
|
+
### Timeframe calculation
|
594
|
+
# Returns the `timeframe`.
|
595
|
+
# This is the period over which to calculate emissions.
|
596
|
+
|
597
|
+
#### Timeframe from client input
|
598
|
+
# **Complies:** All
|
599
|
+
#
|
600
|
+
# Uses the client-input value for `timeframe`.
|
601
|
+
|
602
|
+
#### Default timeframe
|
603
|
+
# **Complies:** All
|
604
|
+
#
|
605
|
+
# Uses the current calendar year.
|
518
606
|
end
|
519
607
|
end
|
520
608
|
|
521
609
|
class FuelUseEquation < Struct.new(:m3, :m2, :m1, :endpoint_fuel)
|
522
610
|
def empty?
|
523
|
-
|
611
|
+
values.all?(&:nil?) or values.all?(&:zero?)
|
612
|
+
end
|
613
|
+
|
614
|
+
def values
|
615
|
+
[m3, m2, m1, endpoint_fuel]
|
524
616
|
end
|
525
617
|
|
526
618
|
def to_xml(options = {})
|