purchase 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +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.
data/README.markdown ADDED
@@ -0,0 +1,17 @@
1
+ # purchase
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: Purchase Committee Calculations
2
+ The purchase model should generate correct committee calculations
3
+
4
+ Scenario Outline: Standard Calculations for
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.788 | 118 | 2241 |
20
+ | IAD | CDG | AF | 2010-06-25 | A320 | 43477 | 13413 | 2492 | 0.800 | 120 | 4161 |
@@ -0,0 +1,11 @@
1
+ Feature: Purchase Emissions Calculations
2
+ The purchase model should generate correct emission calculations
3
+
4
+ Scenario Outline: Standard Calculations for a MCC
5
+ Given a purchase has "merchant_category_code" of "<mcc>"
6
+ When emissions are calculated
7
+ Then the emission value should be within 1 kgs of <emission>
8
+ Examples:
9
+ | mcc | emission |
10
+ | 1771 | 1153 |
11
+ | 3007 | 2070 |
@@ -0,0 +1,8 @@
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
+ Sniff.init File.join(File.dirname(__FILE__), '..', '..'), :earth => :all
@@ -0,0 +1,70 @@
1
+ require 'leap'
2
+ require 'timeframe'
3
+
4
+ module BrighterPlanet
5
+ module Purchase
6
+ module CarbonModel
7
+ def self.included(base)
8
+ base.extend ::Leap::Subject
9
+ base.extend FastTimestamp
10
+ base.decide :emission, :with => :characteristics do
11
+ committee :emission do |provides|
12
+ provides.quorum :from_emission_factor_and_adjusted_cost, :needs => [:emission_factor, :adjusted_cost] do |characteristics|
13
+ # lbs CO2e / 2002 US $ 2002 US $
14
+ characteristics[:emission_factor] * characteristic[:adjusted_cost]
15
+ end
16
+
17
+ provides.quorum :default do
18
+ raise "The purchase's default emission quorum should never be called"
19
+ end
20
+ end
21
+
22
+ committee :emission_factor do |provides|
23
+ # FIXME TODO this actually has to access the io model and return a whole array of data
24
+ provides.quorum :from_io_sector, :needs => [:io_sector] do |characteristics|
25
+ characteristics[:io_sector]
26
+
27
+ provides.quorum :default do
28
+ # fallback emission_factor
29
+ end
30
+ end
31
+ end
32
+
33
+ committee :io_sector do |provides|
34
+ provides.quorum :from_industry, :needs => [:industry] do |characteristics|
35
+ if characteristics[:industry].io_sector != #FIXME TODO the io sectors for wholesale and retail trade
36
+ characteristics[:industry].io_sector
37
+ else
38
+ characteristics[:industry].product_line.industry # FIXME TODO look up the industries that make the product lines that are made by the original industry
39
+ end
40
+ end
41
+ end
42
+
43
+ committee :industry do |provides|
44
+ provides.quorum :from_merchant_category, :needs => [:merchant_category] do |characteristics|
45
+ characteristics[:merchant_category].industry
46
+ end
47
+ end
48
+
49
+ committee :merchant_category do |provides|
50
+ provides.quorum :from_merchant, :needs => [:merchant] do |characteristics|
51
+ characteristics[:merchant].merchant_category
52
+ end
53
+ end
54
+
55
+ committee :adjusted_cost do |provides|
56
+ # for now assuming is always US $ - later may need to figure out currency
57
+ provides.quorum :from_cost_and_date, :needs => [:cost, :date] do |characteristics|
58
+ # convert to 2002 US $ based on date and cost
59
+ end
60
+
61
+ provides.quorum :from_purchase_amount_and_date, :needs => [:purchase_amount, :date] do |characteristics|
62
+ # adjust for tax and then convert to 2002 US $ based on date and cost
63
+ end
64
+ end
65
+ end
66
+ # FIXME TODO make other committees to report emissions by gas, by io sector, etc.
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,26 @@
1
+ require 'characterizable'
2
+
3
+ module BrighterPlanet
4
+ module Purchase
5
+ module Characterization
6
+ def self.included(base)
7
+ base.send :include, Characterizable
8
+ base.characterize do
9
+ has :merchant do |merchant|
10
+ merchant.reveals :merchant_category
11
+ end
12
+ has :industry
13
+ has :product_line
14
+ has :io_sector
15
+ has :purchase_amount # full purchase amount
16
+ has :tax # tax portion of purchase
17
+ has :cost # cost before tax
18
+ has :line_item
19
+ has :customer_code
20
+ has :zip_code
21
+ has :date
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,34 @@
1
+ require 'data_miner'
2
+
3
+ module BrighterPlanet
4
+ module Purchase
5
+ module Data
6
+ def self.included(base)
7
+ base.data_miner do
8
+ schema do
9
+ integer 'merchant_id'
10
+ string 'mcc'
11
+ string 'naics_code' # FIXME TODO not sure how to deal with the fact that a single purchase may have multiple industries, product lines, and io sectors
12
+ string 'pscode' # FIXME TODO not sure how to deal with the fact that a single purchase may have multiple industries, product lines, and io sectors
13
+ string 'io_code' # FIXME TODO not sure how to deal with the fact that a single purchase may have multiple industries, product lines, and io sectors
14
+ float 'purchase_amount'
15
+ float 'tax'
16
+ float 'cost'
17
+ string 'line_item'
18
+ string 'customer_code'
19
+ string 'zip_code_name'
20
+ date 'date'
21
+ float 'adjusted_cost'
22
+ string 'adjusted_cost_units'
23
+ float 'emission_factor'
24
+ string 'emission_factor_units'
25
+ end
26
+
27
+ process "Pull dependencies" do
28
+ run_data_miner_on_belongs_to_associations
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,22 @@
1
+ require 'summary_judgement'
2
+
3
+ module BrighterPlanet
4
+ module Purchase
5
+ module Summarization
6
+ def self.included(base)
7
+ base.extend SummaryJudgement
8
+ base.summarize do |has|
9
+ has.identity 'purchase'
10
+
11
+ has.verb :take
12
+ has.aspect :perfect
13
+
14
+ has.modifier lambda { |purchase| "from #{flight.merchant}" }, :if => :merchant
15
+ has.modifier lambda { |purchase| "(#{purchase.inudstry} industry)" }, :if => :industry
16
+ has.modifier lambda { |purchase| "for $#{purchase.purchase_amount}" }, :if => :purchase_amount
17
+ has.modifier lambda { |purchase| "on #{date.to_formatted_s(:archive)}" }, :if => :date
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
data/lib/purchase.rb ADDED
@@ -0,0 +1,33 @@
1
+ module BrighterPlanet
2
+ module Purchase
3
+ attr_accessor :merchant_category_code
4
+
5
+ module ClassMethods
6
+ def included(base)
7
+ require 'cohort_scope'
8
+ require 'falls_back_on'
9
+ require 'falls_back_on/active_record_ext'
10
+
11
+ require 'purchase/carbon_model'
12
+ require 'purchase/characterization'
13
+ require 'purchase/data'
14
+ require 'purchase/summarization'
15
+
16
+ base.send :include, BrighterPlanet::Purchase::CarbonModel
17
+ base.send :include, BrighterPlanet::Purchase::Characterization
18
+ base.send :include, BrighterPlanet::Purchase::Data
19
+ base.send :include, BrighterPlanet::Purchase::Summarization
20
+ end
21
+ def flight_model
22
+ if Object.const_defined? 'Purchase'
23
+ ::Purchase
24
+ elsif Object.const_defined? 'PurchaseRecord'
25
+ PurchaseRecord
26
+ else
27
+ raise 'There is no purchase model'
28
+ end
29
+ end
30
+ end
31
+ extend ClassMethods
32
+ end
33
+ end
@@ -0,0 +1,22 @@
1
+ require 'sniff/database'
2
+
3
+ Sniff::Database.define_schema do
4
+ create_table "purchase_records", :force => true do |t|
5
+ t.integer 'merchant_id'
6
+ t.string 'mcc'
7
+ t.string 'naics_code' # FIXME TODO not sure how to deal with the fact that a single purchase may have multiple industries, product lines, and io sectors
8
+ t.string 'pscode' # FIXME TODO not sure how to deal with the fact that a single purchase may have multiple industries, product lines, and io sectors
9
+ t.string 'io_code' # FIXME TODO not sure how to deal with the fact that a single purchase may have multiple industries, product lines, and io sectors
10
+ t.float 'purchase_amount'
11
+ t.float 'tax'
12
+ t.float 'cost'
13
+ t.string 'line_item'
14
+ t.string 'customer_code'
15
+ t.string 'zip_code_name'
16
+ t.date 'date'
17
+ t.float 'adjusted_cost'
18
+ t.string 'adjusted_cost_units'
19
+ t.float 'emission_factor'
20
+ t.string 'emission_factor_units'
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ require 'active_record'
2
+ require 'falls_back_on'
3
+ require 'purchase'
4
+ require 'sniff'
5
+
6
+ class PurchaseRecord < ActiveRecord::Base
7
+ include Sniff::Emitter
8
+ include BrighterPlanet::Purchase
9
+ end
metadata ADDED
@@ -0,0 +1,343 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: purchase
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Andy Rossmeissl
14
+ - Seamus Abshere
15
+ - Ian Hough
16
+ - Matt Kling
17
+ - Derek Kastner
18
+ autorequire:
19
+ bindir: bin
20
+ cert_chain: []
21
+
22
+ date: 2010-07-27 00:00:00 -04:00
23
+ default_executable:
24
+ dependencies:
25
+ - !ruby/object:Gem::Dependency
26
+ type: :development
27
+ prerelease: false
28
+ name: activerecord
29
+ version_requirements: &id001 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - "="
33
+ - !ruby/object:Gem::Version
34
+ hash: -1848230024
35
+ segments:
36
+ - 3
37
+ - 0
38
+ - 0
39
+ - beta4
40
+ version: 3.0.0.beta4
41
+ requirement: *id001
42
+ - !ruby/object:Gem::Dependency
43
+ type: :development
44
+ prerelease: false
45
+ name: bundler
46
+ version_requirements: &id002 !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ hash: 62196359
52
+ segments:
53
+ - 1
54
+ - 0
55
+ - 0
56
+ - beta
57
+ - 2
58
+ version: 1.0.0.beta.2
59
+ requirement: *id002
60
+ - !ruby/object:Gem::Dependency
61
+ type: :development
62
+ prerelease: false
63
+ name: cucumber
64
+ version_requirements: &id003 !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - "="
68
+ - !ruby/object:Gem::Version
69
+ hash: 57
70
+ segments:
71
+ - 0
72
+ - 8
73
+ - 3
74
+ version: 0.8.3
75
+ requirement: *id003
76
+ - !ruby/object:Gem::Dependency
77
+ type: :development
78
+ prerelease: false
79
+ name: jeweler
80
+ version_requirements: &id004 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - "="
84
+ - !ruby/object:Gem::Version
85
+ hash: 7
86
+ segments:
87
+ - 1
88
+ - 4
89
+ - 0
90
+ version: 1.4.0
91
+ requirement: *id004
92
+ - !ruby/object:Gem::Dependency
93
+ type: :development
94
+ prerelease: false
95
+ name: rake
96
+ version_requirements: &id005 !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ hash: 3
102
+ segments:
103
+ - 0
104
+ version: "0"
105
+ requirement: *id005
106
+ - !ruby/object:Gem::Dependency
107
+ type: :development
108
+ prerelease: false
109
+ name: rdoc
110
+ version_requirements: &id006 !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ hash: 3
116
+ segments:
117
+ - 0
118
+ version: "0"
119
+ requirement: *id006
120
+ - !ruby/object:Gem::Dependency
121
+ type: :development
122
+ prerelease: false
123
+ name: rspec
124
+ version_requirements: &id007 !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - "="
128
+ - !ruby/object:Gem::Version
129
+ hash: 62196417
130
+ segments:
131
+ - 2
132
+ - 0
133
+ - 0
134
+ - beta
135
+ - 17
136
+ version: 2.0.0.beta.17
137
+ requirement: *id007
138
+ - !ruby/object:Gem::Dependency
139
+ type: :development
140
+ prerelease: false
141
+ name: sniff
142
+ version_requirements: &id008 !ruby/object:Gem::Requirement
143
+ none: false
144
+ requirements:
145
+ - - "="
146
+ - !ruby/object:Gem::Version
147
+ hash: 11
148
+ segments:
149
+ - 0
150
+ - 0
151
+ - 10
152
+ version: 0.0.10
153
+ requirement: *id008
154
+ - !ruby/object:Gem::Dependency
155
+ type: :runtime
156
+ prerelease: false
157
+ name: characterizable
158
+ version_requirements: &id009 !ruby/object:Gem::Requirement
159
+ none: false
160
+ requirements:
161
+ - - "="
162
+ - !ruby/object:Gem::Version
163
+ hash: 7
164
+ segments:
165
+ - 0
166
+ - 0
167
+ - 12
168
+ version: 0.0.12
169
+ requirement: *id009
170
+ - !ruby/object:Gem::Dependency
171
+ type: :runtime
172
+ prerelease: false
173
+ name: data_miner
174
+ version_requirements: &id010 !ruby/object:Gem::Requirement
175
+ none: false
176
+ requirements:
177
+ - - "="
178
+ - !ruby/object:Gem::Version
179
+ hash: 15
180
+ segments:
181
+ - 0
182
+ - 5
183
+ - 2
184
+ version: 0.5.2
185
+ requirement: *id010
186
+ - !ruby/object:Gem::Dependency
187
+ type: :runtime
188
+ prerelease: false
189
+ name: earth
190
+ version_requirements: &id011 !ruby/object:Gem::Requirement
191
+ none: false
192
+ requirements:
193
+ - - "="
194
+ - !ruby/object:Gem::Version
195
+ hash: 17
196
+ segments:
197
+ - 0
198
+ - 0
199
+ - 7
200
+ version: 0.0.7
201
+ requirement: *id011
202
+ - !ruby/object:Gem::Dependency
203
+ type: :runtime
204
+ prerelease: false
205
+ name: falls_back_on
206
+ version_requirements: &id012 !ruby/object:Gem::Requirement
207
+ none: false
208
+ requirements:
209
+ - - "="
210
+ - !ruby/object:Gem::Version
211
+ hash: 27
212
+ segments:
213
+ - 0
214
+ - 0
215
+ - 2
216
+ version: 0.0.2
217
+ requirement: *id012
218
+ - !ruby/object:Gem::Dependency
219
+ type: :runtime
220
+ prerelease: false
221
+ name: fast_timestamp
222
+ version_requirements: &id013 !ruby/object:Gem::Requirement
223
+ none: false
224
+ requirements:
225
+ - - "="
226
+ - !ruby/object:Gem::Version
227
+ hash: 23
228
+ segments:
229
+ - 0
230
+ - 0
231
+ - 4
232
+ version: 0.0.4
233
+ requirement: *id013
234
+ - !ruby/object:Gem::Dependency
235
+ type: :runtime
236
+ prerelease: false
237
+ name: leap
238
+ version_requirements: &id014 !ruby/object:Gem::Requirement
239
+ none: false
240
+ requirements:
241
+ - - "="
242
+ - !ruby/object:Gem::Version
243
+ hash: 13
244
+ segments:
245
+ - 0
246
+ - 4
247
+ - 1
248
+ version: 0.4.1
249
+ requirement: *id014
250
+ - !ruby/object:Gem::Dependency
251
+ type: :runtime
252
+ prerelease: false
253
+ name: summary_judgement
254
+ version_requirements: &id015 !ruby/object:Gem::Requirement
255
+ none: false
256
+ requirements:
257
+ - - "="
258
+ - !ruby/object:Gem::Version
259
+ hash: 11
260
+ segments:
261
+ - 1
262
+ - 3
263
+ - 8
264
+ version: 1.3.8
265
+ requirement: *id015
266
+ - !ruby/object:Gem::Dependency
267
+ type: :runtime
268
+ prerelease: false
269
+ name: timeframe
270
+ version_requirements: &id016 !ruby/object:Gem::Requirement
271
+ none: false
272
+ requirements:
273
+ - - "="
274
+ - !ruby/object:Gem::Version
275
+ hash: 15
276
+ segments:
277
+ - 0
278
+ - 0
279
+ - 8
280
+ version: 0.0.8
281
+ requirement: *id016
282
+ description: A software model in Ruby for the greenhouse gas emissions of a purchase
283
+ email: seamus@brighterplanet.com
284
+ executables: []
285
+
286
+ extensions: []
287
+
288
+ extra_rdoc_files:
289
+ - LICENSE
290
+ - README.markdown
291
+ files:
292
+ - LICENSE
293
+ - README.markdown
294
+ - lib/purchase.rb
295
+ - lib/purchase/carbon_model.rb
296
+ - lib/purchase/characterization.rb
297
+ - lib/purchase/data.rb
298
+ - lib/purchase/summarization.rb
299
+ - lib/test_support/db/schema.rb
300
+ - lib/test_support/purchase_record.rb
301
+ - features/support/env.rb
302
+ - features/purchase_committees.feature
303
+ - features/purchase_emissions.feature
304
+ has_rdoc: true
305
+ homepage: http://github.com/brighterplanet/purchase
306
+ licenses: []
307
+
308
+ post_install_message:
309
+ rdoc_options:
310
+ - --charset=UTF-8
311
+ require_paths:
312
+ - lib
313
+ required_ruby_version: !ruby/object:Gem::Requirement
314
+ none: false
315
+ requirements:
316
+ - - ">="
317
+ - !ruby/object:Gem::Version
318
+ hash: 3
319
+ segments:
320
+ - 0
321
+ version: "0"
322
+ required_rubygems_version: !ruby/object:Gem::Requirement
323
+ none: false
324
+ requirements:
325
+ - - ">="
326
+ - !ruby/object:Gem::Version
327
+ hash: 3
328
+ segments:
329
+ - 0
330
+ version: "0"
331
+ requirements: []
332
+
333
+ rubyforge_project:
334
+ rubygems_version: 1.3.7
335
+ signing_key:
336
+ specification_version: 3
337
+ summary: A carbon model
338
+ test_files:
339
+ - features/support/env.rb
340
+ - features/purchase_committees.feature
341
+ - features/purchase_emissions.feature
342
+ - lib/test_support/db/schema.rb
343
+ - lib/test_support/purchase_record.rb