flight 0.0.2 → 0.0.4

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/LICENSE CHANGED
@@ -1,20 +1,20 @@
1
- Copyright (c) 2009 Andy Rossmeissl
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ Copyright (c) 2009 Andy Rossmeissl
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc CHANGED
@@ -1,17 +1,17 @@
1
- = flight
2
-
3
- Description goes here.
4
-
5
- == Note on Patches/Pull Requests
6
-
7
- * Fork the project.
8
- * Make your feature addition or bug fix.
9
- * Add tests for it. This is important so I don't break it in a
10
- future version unintentionally.
11
- * Commit, do not mess with rakefile, version, or history.
12
- (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
- * Send me a pull request. Bonus points for topic branches.
14
-
15
- == Copyright
16
-
17
- Copyright (c) 2010 Andy Rossmeissl. See LICENSE for details.
1
+ = flight
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 Andy Rossmeissl. See LICENSE for details.
@@ -0,0 +1,20 @@
1
+ Feature: Flight Committee Calculations
2
+ The flight model should generate correct committee calculations
3
+
4
+ Scenario Outline: Standard Calculations for origin/destination airport, airline, and craft
5
+ Given a flight has "origin_airport.iata_code" of "<source>"
6
+ And it has "destination_airport.iata_code" of "<dest>"
7
+ And it has "airline.iata_code" of "<airline>"
8
+ And it has "date" of "<date>"
9
+ And it used "aircraft.icao_code" "<aircraft>"
10
+ When emissions are calculated
11
+ Then the fuel committee should be close to <fuel>, +/-1
12
+ And the fuel_per_segment committee should be close to <fuel_per_segment>, +/-10
13
+ And the adjusted_distance_per_segment committee should be close to <adjusted_distance_per_segment>, +/-1
14
+ And the load_factor committee should be close to <load_factor>, +/-0.001
15
+ And the passengers committee should be exactly <passengers>
16
+ And the adjusted_distance committee should be close to <adjusted_distance>, +/-1
17
+ Examples:
18
+ | source | dest | airline | date | aircraft | fuel | fuel_per_segment | adjusted_distance_per_segment | load_factor | passengers | adjusted_distance |
19
+ | DTW | SFO | UA | 2010-06-25 | A320 | 24676 | 7612 | 1341 | 0.801 | 120 | 2241 |
20
+ | IAD | CDG | AF | 2010-06-25 | A320 | 43477 | 13413 | 2492 | 0.800 | 120 | 4161 |
@@ -0,0 +1,15 @@
1
+ Feature: Flight Emissions Calculations
2
+ The flight model should generate correct emission calculations
3
+
4
+ Scenario Outline: Standard Calculations for origin/destination airport, airline, and craft
5
+ Given a flight has "origin_airport.iata_code" of "<source>"
6
+ And it has "destination_airport.iata_code" of "<dest>"
7
+ And it has "airline.iata_code" of "<airline>"
8
+ And it has "date" of "<date>"
9
+ And it used "aircraft.icao_code" "<aircraft>"
10
+ When emissions are calculated
11
+ Then the emission value should be within 10 kgs of <emission>
12
+ Examples:
13
+ | source | dest | airline | date | aircraft | emission |
14
+ | DTW | SFO | UA | 2010-06-25 | A320 | 1153 |
15
+ | IAD | CDG | AF | 2010-06-25 | A320 | 2070 |
@@ -0,0 +1,57 @@
1
+ require 'time'
2
+
3
+ Given /^(a flight|it) (has|used) "(.+)" (of\s?)?"(.*)"$/ do |_, __, field, ___, value|
4
+ @activity_hash ||= {}
5
+ if value.present?
6
+ methods = field.split('.')
7
+ context = @activity_hash
8
+ methods.each do |method|
9
+ method = method.to_sym
10
+ context[method] ||= {}
11
+ value = Date.parse(value) if value =~ /\d{4}-\d{2}-\d{2}/
12
+ context[method] = value if method == methods.last.to_sym
13
+ context = context[method]
14
+ end
15
+ end
16
+ end
17
+
18
+ Given /^the current date is (.+)$/ do |current_date|
19
+ @current_date = Time.parse(current_date)
20
+ end
21
+
22
+ When /^emissions are calculated$/ do
23
+ @activity = FlightRecord.from_params_hash @activity_hash
24
+ if @current_date
25
+ Timecop.travel(@current_date) do
26
+ @emission = @activity.emission Sniff::Timeframe.this_year
27
+ end
28
+ else
29
+ @emission = @activity.emission Sniff::Timeframe.this_year
30
+ end
31
+ @characteristics = @activity.deliberations[:emission].characteristics
32
+ end
33
+
34
+ Then /^the emission value should be within (\d+) kgs of (\d+)$/ do |cusion, emissions|
35
+ @emission.should be_close(emissions.to_f, cusion.to_f)
36
+ end
37
+
38
+ Then /^the calculation should have used committees (.*)$/ do |committee_list|
39
+ committees = committee_list.split(/,\s*/)
40
+ committees.each do |committee|
41
+ @characteristics.keys.should include(committee)
42
+ end
43
+ end
44
+
45
+ Then /^the (.+) committee should be close to ([^,]+), \+\/-(.+)$/ do |committee, value, cusion|
46
+ @characteristics[committee.to_sym].to_f.should be_close(value.to_f, cusion.to_f)
47
+ end
48
+
49
+ Then /^the (.+) committee should be exactly (.*)$/ do |committee, value|
50
+ @characteristics[committee.to_sym].to_s.should == value
51
+ end
52
+
53
+ Then /^the active_subtimeframe committee should have timeframe (.*)$/ do |tf_string|
54
+ days, start, finish = tf_string.split(/,\s*/)
55
+ @characteristics[:active_subtimeframe].to_s.should =~ /#{days} days starting #{start} ending #{finish}/
56
+ end
57
+
@@ -0,0 +1,19 @@
1
+ require 'bundler'
2
+ Bundler.setup
3
+
4
+ require 'cucumber'
5
+ require 'cucumber/formatter/unicode' # Remove this line if you don't want Cucumber Unicode support
6
+
7
+ require 'sniff'
8
+
9
+ Sniff.init File.join(File.dirname(__FILE__), '..', '..')
10
+
11
+ ## How to clean your database when transactions are turned off. See
12
+ ## http://github.com/bmabey/database_cleaner for more info.
13
+ #if defined?(ActiveRecord::Base)
14
+ # begin
15
+ # require 'database_cleaner'
16
+ # DatabaseCleaner.strategy = :truncation
17
+ # rescue LoadError => ignore_if_database_cleaner_not_present
18
+ # end
19
+ #end
data/lib/flight.rb CHANGED
@@ -1,256 +1,26 @@
1
+ require 'flight/carbon_model'
2
+ require 'flight/characterization'
3
+ require 'flight/data'
4
+ require 'flight/summarization'
5
+
1
6
  module BrighterPlanet
2
7
  module Flight
3
- def self.included(base)
4
- base.extend ::Leap::Subject
5
- base.decide :emission, :with => :characteristics do
6
- committee :emission do
7
- quorum 'from fuel and passengers with coefficients', :needs => [:fuel, :passengers, :seat_class_multiplier, :emission_factor, :radiative_forcing_index, :freight_share, :date] do |characteristics, timeframe|
8
- if timeframe.include? characteristics[:date]
9
- #( kg fuel ) * ( kg CO2 / kg fuel ) = kg CO2
10
- (characteristics[:fuel] / characteristics[:passengers] * characteristics[:seat_class_multiplier]) * characteristics[:emission_factor] * characteristics[:radiative_forcing_index] * (1 - characteristics[:freight_share])
11
- else
12
- 0
13
- end
14
- end
15
-
16
- quorum 'default' do
17
- raise "The emission committee's default quorum should never be called"
18
- end
19
- end
20
-
21
- committee :fuel do # returns kg fuel
22
- quorum 'from fuel per segment and emplanements and trips', :needs => [:fuel_per_segment, :emplanements_per_trip, :trips] do |characteristics|
23
- characteristics[:fuel_per_segment] * characteristics[:emplanements_per_trip].to_f * characteristics[:trips].to_f
24
- end
25
- end
26
-
27
- committee :fuel_per_segment do # returns kg fuel
28
- quorum 'from adjusted distance and fuel use formula and emplanements and trips', :needs => [:adjusted_distance_per_segment, :fuel_use_coefficients, :endpoint_fuel] do |characteristics|
29
- characteristics[:fuel_use_coefficients][:m3].to_f * characteristics[:adjusted_distance_per_segment].to_f ** 3 +
30
- characteristics[:fuel_use_coefficients][:m2].to_f * characteristics[:adjusted_distance_per_segment].to_f ** 2 +
31
- characteristics[:fuel_use_coefficients][:m1].to_f * characteristics[:adjusted_distance_per_segment].to_f +
32
- characteristics[:endpoint_fuel].to_f
33
- end
34
- end
35
-
36
- committee :adjusted_distance_per_segment do
37
- quorum 'from adjusted distance and emplanements', :needs => [:adjusted_distance, :emplanements_per_trip] do |characteristics|
38
- characteristics[:adjusted_distance] / characteristics[:emplanements_per_trip]
39
- end
40
- end
41
-
42
- committee :endpoint_fuel do
43
- quorum 'from aircraft', :needs => :aircraft do |characteristics|
44
- characteristics[:aircraft].endpoint_fuel
45
- end
46
-
47
- quorum 'from aircraft class', :needs => :aircraft_class do |characteristics|
48
- characteristics[:aircraft_class].endpoint_fuel
49
- end
50
-
51
- quorum 'default' do
52
- Aircraft.fallback.endpoint_fuel
53
- end
54
- end
55
-
56
- committee :fuel_use_coefficients do
57
- quorum 'from aircraft', :needs => :aircraft do |characteristics|
58
- characteristics[:aircraft].attributes.symbolize_keys.slice(:m1, :m2, :m3)
59
- end
60
-
61
- quorum 'from aircraft class', :needs => :aircraft_class do |characteristics|
62
- characteristics[:aircraft_class].attributes.symbolize_keys.slice(:m1, :m2, :m3)
63
- end
64
-
65
- quorum 'default' do
66
- Aircraft.fallback.attributes.symbolize_keys.slice(:m1, :m2, :m3)
67
- end
68
- end
69
-
70
- committee :passengers do
71
- quorum 'from seats and load factor', :needs => [:seats, :load_factor] do |characteristics|
72
- (characteristics[:seats] * characteristics[:load_factor]).round
73
- end
74
- end
75
-
76
- committee :seats do
77
- # leaving this here to explain how someday we might lookup seat count based on both airline AND aircraft
78
- #SE quorum 'from_airline_and_aircraft', :needs => [:airline, :aircraft] do |characteristics, timeframe|
79
- #SE if aircraft = AirlineAircraft.memoized_find_by_airline_id_and_aircraft_id(characteristics[:airline].id, characteristics[:aircraft].id)
80
- #SE aircraft.seats
81
- #SE end
82
- #SE end
83
-
84
- quorum 'from aircraft', :needs => :aircraft do |characteristics|
85
- characteristics[:aircraft].seats
86
- end
87
-
88
- quorum 'from seats estimate', :needs => :seats_estimate do |characteristics|
89
- characteristics[:seats_estimate]
90
- end
91
-
92
- quorum 'from cohort', :needs => :cohort do |characteristics|
93
- seats = characteristics[:cohort].weighted_average :seats, :weighted_by => :passengers
94
- if seats.nil? or seats.zero?
95
- nil
96
- else
97
- seats
98
- end
99
- end
100
-
101
- quorum 'from aircraft class', :needs => :aircraft_class do |characteristics|
102
- characteristics[:aircraft_class].seats
103
- end
104
-
105
- quorum 'default' do
106
- FlightSegment.fallback.seats
107
- end
108
- end
109
-
110
- committee :load_factor do
111
- quorum 'from cohort', :needs => :cohort do |characteristics|
112
- characteristics[:cohort].weighted_average(:load_factor, :weighted_by => :passengers)
113
- end
114
-
115
- quorum 'default' do
116
- ::Flight.fallback.load_factor
117
- end
118
- end
119
-
120
- committee :adjusted_distance do # returns nautical miles
121
- quorum 'from distance', :needs => [:distance, :emplanements_per_trip] do |characteristics|
122
- characteristics[:distance] * research(:route_inefficiency_factor) * ( research(:dogleg_factor) ** (characteristics[:emplanements_per_trip] - 1) )
123
- end
124
- end
125
-
126
- committee :distance do # returns nautical miles
127
- quorum 'from airports', :needs => [:origin_airport, :destination_airport] do |characteristics|
128
- if characteristics[:origin_airport].latitude and
129
- characteristics[:origin_airport].longitude and
130
- characteristics[:destination_airport].latitude and
131
- characteristics[:destination_airport].longitude
132
- characteristics[:origin_airport].distance_to(characteristics[:destination_airport], :units => :kms).kilometres.to :nautical_miles
133
- end
134
- end
135
-
136
- quorum 'from distance estimate', :needs => :distance_estimate do |characteristics|
137
- characteristics[:distance_estimate].kilometres.to :nautical_miles
138
- end
139
-
140
- quorum 'from distance class', :needs => :distance_class do |characteristics|
141
- characteristics[:distance_class].distance.kilometres.to :nautical_miles
142
- end
143
-
144
- quorum 'from cohort', :needs => :cohort do |characteristics|
145
- distance = characteristics[:cohort].weighted_average(:distance, :weighted_by => :passengers).to_f.kilometres.to(:nautical_miles)
146
- distance > 0 ? distance : nil
147
- end
148
-
149
- quorum 'default' do
150
- ::Flight.fallback.distance_estimate.kilometres.to :nautical_miles
151
- end
152
- end
153
-
154
- committee :emplanements_per_trip do # per trip
155
- quorum 'default' do
156
- ::Flight.fallback.emplanements_per_trip_before_type_cast
157
- end
158
- end
159
-
160
- committee :radiative_forcing_index do
161
- quorum 'from fuel type', :needs => :fuel_type do |characteristics|
162
- characteristics[:fuel_type].radiative_forcing_index
163
- end
164
- end
165
-
166
- committee :emission_factor do # returns kg CO2 / kg fuel
167
- quorum 'from fuel type', :needs => :fuel_type do |characteristics|
168
- #( kg CO2 / litres fuel ) * ( litres fuel / kg fuel )
169
- characteristics[:fuel_type].emission_factor * ( 1 / characteristics[:fuel_type].density).gallons.to(:litres)
170
- end
171
- end
172
-
173
- committee :fuel_type do
174
- quorum 'default' do
175
- FlightFuelType.fallback
176
- end
177
- end
178
-
179
- committee :freight_share do
180
- quorum 'from cohort', :needs => :cohort do |characteristics|
181
- characteristics[:cohort].weighted_average(:freight_share, :weighted_by => :passengers)
182
- end
183
-
184
- quorum 'default' do
185
- FlightSegment.fallback.freight_share
186
- end
187
- end
188
-
189
- committee :trips do
190
- quorum 'default' do
191
- ::Flight.fallback.trips_before_type_cast
192
- end
193
- end
194
-
195
- committee :domesticity do
196
- quorum 'from airports', :needs => [:origin_airport, :destination_airport] do |characteristics|
197
- if [characteristics[:origin_airport], characteristics[:destination_airport]].all?(&:united_states?)
198
- FlightDomesticity.find_by_name('domestic')
199
- elsif [characteristics[:origin_airport], characteristics[:destination_airport]].any?(&:united_states?)
200
- FlightDomesticity.find_by_name('international')
201
- end
202
- end
203
-
204
- quorum 'from origin', :needs => :origin_airport do |characteristics|
205
- if characteristics[:origin_airport].all_flights_from_here_domestic?
206
- FlightDomesticity.find_by_name('domestic')
207
- end
208
- end
209
-
210
- quorum 'from destination', :needs => :destination_airport do |characteristics|
211
- if characteristics[:destination_airport].all_flights_to_here_domestic?
212
- FlightDomesticity.find_by_name('domestic')
213
- end
214
- end
215
-
216
- quorum 'from airline', :needs => :airline do |characteristics|
217
- if characteristics[:airline].all_flights_domestic?
218
- FlightDomesticity.find_by_name('domestic')
219
- end
220
- end
221
- end
222
-
223
- committee :seat_class_multiplier do
224
- quorum 'from seat class', :needs => :seat_class do |characteristics|
225
- characteristics[:seat_class].multiplier
226
- end
227
-
228
- quorum 'default' do
229
- FlightSeatClass.fallback.multiplier
230
- end
231
- end
232
-
233
- committee :date do
234
- quorum 'from creation date', :needs => :creation_date do |characteristics|
235
- characteristics[:creation_date]
236
- end
237
-
238
- quorum 'from timeframe' do |characteristics, timeframe|
239
- timeframe.from
240
- end
241
- end
242
-
243
- committee :cohort do
244
- quorum 'from t100', :appreciates => FlightSegment::INPUT_CHARACTERISTICS do |characteristics|
245
- cohort = FlightSegment.big_cohort characteristics
246
- if cohort.any?
247
- cohort
248
- else
249
- nil
250
- end
251
- end
252
- end
8
+ extend self
9
+
10
+ def included(base)
11
+ base.send :include, BrighterPlanet::Flight::CarbonModel
12
+ base.send :include, BrighterPlanet::Flight::Characterization
13
+ # base.send :include, BrighterPlanet::Flight::Data
14
+ base.send :include, BrighterPlanet::Flight::Summarization
15
+ end
16
+ def flight_model
17
+ if Object.const_defined? 'Flight'
18
+ Flight
19
+ elsif Object.const_defined? 'FlightRecord'
20
+ FlightRecord
21
+ else
22
+ raise 'There is no flight model'
253
23
  end
254
24
  end
255
25
  end
256
- end
26
+ end