Module: BrighterPlanet::Flight::CarbonModel

Defined in:
lib/flight/carbon_model.rb

Class Method Summary collapse

Class Method Details

.included(base) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/flight/carbon_model.rb', line 8

def self.included(base)
  base.extend ::Leap::Subject
  base.extend FastTimestamp
  base.decide :emission, :with => :characteristics do
    committee :emission do
      quorum 'from fuel and passengers with coefficients', 
        :needs => [:fuel, :passengers, :seat_class_multiplier, :emission_factor, 
                   :radiative_forcing_index, :freight_share, :date] do |characteristics, timeframe|
        if timeframe.include? characteristics[:date]
          #( kg fuel ) * ( kg CO2 / kg fuel ) = kg CO2
          (characteristics[:fuel] / characteristics[:passengers] * characteristics[:seat_class_multiplier]) * characteristics[:emission_factor] * characteristics[:radiative_forcing_index] * (1 - characteristics[:freight_share])
        else
          0
        end
      end
      
      quorum 'default' do
        raise "The emission committee's default quorum should never be called"
      end
    end
    
    committee :fuel do # returns kg fuel
      quorum 'from fuel per segment and emplanements and trips', :needs => [:fuel_per_segment, :emplanements_per_trip, :trips] do |characteristics|
        characteristics[:fuel_per_segment] * characteristics[:emplanements_per_trip].to_f * characteristics[:trips].to_f
      end
    end
    
    committee :fuel_per_segment do # returns kg fuel
      quorum 'from adjusted distance and fuel use formula and emplanements and trips', :needs => [:adjusted_distance_per_segment, :fuel_use_coefficients, :endpoint_fuel] do |characteristics|
        characteristics[:fuel_use_coefficients][:m3].to_f * characteristics[:adjusted_distance_per_segment].to_f ** 3 +
          characteristics[:fuel_use_coefficients][:m2].to_f * characteristics[:adjusted_distance_per_segment].to_f ** 2 +
          characteristics[:fuel_use_coefficients][:m1].to_f * characteristics[:adjusted_distance_per_segment].to_f +
          characteristics[:endpoint_fuel].to_f
      end
    end
    
    committee :adjusted_distance_per_segment do
      quorum 'from adjusted distance and emplanements', :needs => [:adjusted_distance, :emplanements_per_trip] do |characteristics|
        characteristics[:adjusted_distance] / characteristics[:emplanements_per_trip]
      end
    end
    
    committee :endpoint_fuel do
      quorum 'from aircraft', :needs => :aircraft do |characteristics|
        characteristics[:aircraft].endpoint_fuel
      end
      
      quorum 'from aircraft class', :needs => :aircraft_class do |characteristics|
        characteristics[:aircraft_class].endpoint_fuel
      end
      
      quorum 'default' do
        Aircraft.fallback.andand.endpoint_fuel
      end
    end
    
    committee :fuel_use_coefficients do
      quorum 'from aircraft', :needs => :aircraft do |characteristics|
        characteristics[:aircraft].attributes.symbolize_keys.slice(:m1, :m2, :m3)
      end
      
      quorum 'from aircraft class', :needs => :aircraft_class do |characteristics|
        characteristics[:aircraft_class].attributes.symbolize_keys.slice(:m1, :m2, :m3)
      end
      
      quorum 'default' do
        fallback = Aircraft.fallback
        if fallback
          fallback.attributes.symbolize_keys.slice(:m1, :m2, :m3)
        end
      end
    end
    
    committee :passengers do
      quorum 'from seats and load factor', :needs => [:seats, :load_factor] do |characteristics|
        (characteristics[:seats] * characteristics[:load_factor]).round
      end
    end
    
    committee :seats do
# leaving this here to explain how someday we might lookup seat count based on both airline AND aircraft
#SE      quorum 'from_airline_and_aircraft', :needs => [:airline, :aircraft] do |characteristics, timeframe|
#SE        if aircraft = AirlineAircraft.memoized_find_by_airline_id_and_aircraft_id(characteristics[:airline].id, characteristics[:aircraft].id)
#SE          aircraft.seats
#SE        end
#SE      end
      
      quorum 'from aircraft', :needs => :aircraft do |characteristics|
        characteristics[:aircraft].seats
      end
      
      quorum 'from seats estimate', :needs => :seats_estimate do |characteristics|
        characteristics[:seats_estimate]
      end
      
      quorum 'from cohort', :needs => :cohort do |characteristics|
        seats = characteristics[:cohort].weighted_average :seats, :weighted_by => :passengers
        if seats.nil? or seats.zero?
          nil
        else
          seats
        end
      end
      
      quorum 'from aircraft class', :needs => :aircraft_class do |characteristics|
        characteristics[:aircraft_class].seats
      end
      
      quorum 'default' do
        FlightSegment.fallback.andand.seats
      end
    end
    
    committee :load_factor do
      quorum 'from cohort', :needs => :cohort do |characteristics|
        characteristics[:cohort].weighted_average(:load_factor, :weighted_by => :passengers)
      end

      quorum 'default' do
        BrighterPlanet::Flight.flight_model.fallback.andand.load_factor
      end
    end
    
    committee :adjusted_distance do # returns nautical miles
      quorum 'from distance', :needs => [:distance, :emplanements_per_trip] do |characteristics|
        route_inefficiency_factor = BrighterPlanet::Flight.flight_model.research(:route_inefficiency_factor)
        dogleg_factor = BrighterPlanet::Flight.flight_model.research(:dogleg_factor)
        characteristics[:distance] * route_inefficiency_factor * ( dogleg_factor ** (characteristics[:emplanements_per_trip] - 1) )
      end
    end
    
    committee :distance do # returns nautical miles
      quorum 'from airports', :needs => [:origin_airport, :destination_airport] do |characteristics|
        if  characteristics[:origin_airport].latitude and
            characteristics[:origin_airport].longitude and
            characteristics[:destination_airport].latitude and
            characteristics[:destination_airport].longitude
          characteristics[:origin_airport].distance_to(characteristics[:destination_airport], :units => :kms).kilometres.to :nautical_miles
        end
      end
      
      quorum 'from distance estimate', :needs => :distance_estimate do |characteristics|
        characteristics[:distance_estimate].kilometres.to :nautical_miles
      end
      
      quorum 'from distance class', :needs => :distance_class do |characteristics|
        characteristics[:distance_class].distance.kilometres.to :nautical_miles
      end
      
      quorum 'from cohort', :needs => :cohort do |characteristics|
        distance = characteristics[:cohort].weighted_average(:distance, :weighted_by => :passengers).to_f.kilometres.to(:nautical_miles)
        distance > 0 ? distance : nil
      end
      
      quorum 'default' do
        BrighterPlanet::Flight.flight_model.fallback.distance_estimate.kilometres.to :nautical_miles
      end
    end
    
    committee :emplanements_per_trip do # per trip
      quorum 'default' do
        BrighterPlanet::Flight.flight_model.fallback.emplanements_per_trip_before_type_cast
      end
    end
    
    committee :radiative_forcing_index do
      quorum 'from fuel type', :needs => :fuel_type do |characteristics|
        characteristics[:fuel_type].radiative_forcing_index
      end
    end
    
    committee :emission_factor do # returns kg CO2 / kg fuel
      quorum 'from fuel type', :needs => :fuel_type do |characteristics|
        #(            kg CO2 / litres fuel        ) * (                 litres fuel / kg fuel                      )
        characteristics[:fuel_type].emission_factor * ( 1 / characteristics[:fuel_type].density).gallons.to(:litres)
      end
    end
    
    committee :fuel_type do
      quorum 'default' do
        FlightFuelType.fallback
      end
    end
    
    committee :freight_share do
      quorum 'from cohort', :needs => :cohort do |characteristics|
        characteristics[:cohort].weighted_average(:freight_share, :weighted_by => :passengers)
      end
      
      quorum 'default' do
        FlightSegment.fallback.andand.freight_share
      end
    end
    
    committee :trips do
      quorum 'default' do
        BrighterPlanet::Flight.flight_model.fallback.andand.trips_before_type_cast
      end
    end
    
    committee :domesticity do
      quorum 'from airports', :needs => [:origin_airport, :destination_airport] do |characteristics|
        if [characteristics[:origin_airport], characteristics[:destination_airport]].all?(&:united_states?)
          FlightDomesticity.find_by_name('domestic')
        elsif [characteristics[:origin_airport], characteristics[:destination_airport]].any?(&:united_states?)
          FlightDomesticity.find_by_name('international')
        end
      end
      
      quorum 'from origin', :needs => :origin_airport do |characteristics|
        if characteristics[:origin_airport].all_flights_from_here_domestic?
          FlightDomesticity.find_by_name('domestic')
        end
      end
      
      quorum 'from destination', :needs => :destination_airport do |characteristics|
        if characteristics[:destination_airport].all_flights_to_here_domestic?
          FlightDomesticity.find_by_name('domestic')
        end
      end
      
      quorum 'from airline', :needs => :airline do |characteristics|
        if characteristics[:airline].all_flights_domestic?
          FlightDomesticity.find_by_name('domestic')
        end
      end
    end
    
    committee :seat_class_multiplier do
      quorum 'from seat class', :needs => :seat_class do |characteristics|
        characteristics[:seat_class].multiplier
      end
      
      quorum 'default' do
        FlightSeatClass.fallback.andand.multiplier
      end
    end
    
    committee :date do
      quorum 'from creation date', :needs => :creation_date do |characteristics|
        characteristics[:creation_date]
      end
      
      quorum 'from timeframe' do |characteristics, timeframe|
        timeframe.andand.from
      end
    end
    
    committee :cohort do
      quorum 'from t100', :appreciates => FlightSegment::INPUT_CHARACTERISTICS do |characteristics|
        needed_characteristics = characteristics
        needed_characteristics.
          reject! { |k,v| !FlightSegment::INPUT_CHARACTERISTICS.include?(k) }
        cohort = FlightSegment.big_cohort needed_characteristics
        if cohort.any?
          cohort
        else
          nil
        end
      end
    end
  end
end