ce-bucketize 0.1.0

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.
@@ -0,0 +1,341 @@
1
+ # Copyright (C) 2015 TopCoder Inc., All Rights Reserved.
2
+
3
+ require 'date'
4
+ require 'json'
5
+ require 'ce-greenbutton'
6
+ require 'ce-bucketize/bucketizer'
7
+ require 'ce-bucketize/model/tariff_rule'
8
+
9
+ # This module aggregates consumption data with heterogeneous granularity
10
+ # across time into systematic intervals. These intervals are then either
11
+ # multiplied with a relevant tariff value then summed into daily totals, or
12
+ # directly summed into daily totals. The simplest example would be to sum
13
+ # hourly data into daily totals, subject to data completeness checks and
14
+ # multiply them with a single tariff number.
15
+ #
16
+ #
17
+ # Example
18
+ # see demo/demo.rb for detailed usage example.
19
+ #
20
+ # Author: ahmed.seddiq
21
+ # Version: 1.0
22
+ module Bucketize
23
+
24
+ # The consumption intervals should be summed by the hours of the day
25
+ # and summed to daily values.
26
+ #
27
+ # month - a Time representing the first hour of the first day in the month
28
+ # to which the data will be aggregated. (required)
29
+ # download_options - options used to download GreenButton data
30
+ #
31
+ # Supported download options:
32
+ # use_ftp - a Boolean flag to switch between ftp and API modes.
33
+ # API (HTTP) options
34
+ # access_token - the OAuth2 token used by the GreenButton gem to
35
+ # authenticate to the GreenButton custodians.
36
+ # subscription_url - the url used by the GreenButton gem to retrieve the data
37
+ # FTP options
38
+ # application_id - represents the GreenButton 3rd party application id.
39
+ # time - used to construct file name. (optional, defaults
40
+ # to current time)
41
+ # utility_name - represents the utility name, used to construct the
42
+ # XML file name.
43
+ #
44
+ #
45
+ # Returns an array in the form [{date1 => value, date2 => value}]
46
+ #
47
+ # Raises ArgumentError if month is not the first hour of first day of a month.
48
+ def self.consumption_from_month_start(month, download_options)
49
+ check_first_day_of_month(month)
50
+
51
+ first_day = month
52
+ last_day = DateTime.new(month.year, month.month, -1, -1, -1, -1,
53
+ first_day.gmt_offset)
54
+ # convert to time with the same zone offset of the first day
55
+ last_day = Time.new(last_day.year, last_day.month, last_day.day,
56
+ last_day.hour, last_day.min, last_day.sec,
57
+ first_day.gmt_offset) + 1
58
+ Bucketize::Bucketizer
59
+ .new(download_options, first_day, last_day)
60
+ .daily_consumption_values
61
+ end
62
+
63
+ # The consumption is calculated by summing the consumption data in totals
64
+ # of hours groups and summed to daily values.
65
+ #
66
+ # date - a Date representing the day to which the data will
67
+ # be aggregated, it must be Time object referring to the first hour
68
+ # of the required day (required).
69
+ #
70
+ # download_options - options used to download GreenButton data
71
+ #
72
+ # Supported download options:
73
+ # use_ftp - a Boolean flag to switch between ftp and API modes.
74
+ # API (HTTP) options
75
+ # access_token - the OAuth2 token used by the GreenButton gem to
76
+ # authenticate to the GreenButton custodians.
77
+ # subscription_url - the url used by the GreenButton gem to retrieve the data
78
+ # FTP options
79
+ # application_id - represents the GreenButton 3rd party application id.
80
+ # time - used to construct file name. (optional, defaults
81
+ # to current time)
82
+ # utility_name - represents the utility name, used to construct the
83
+ # XML file name.
84
+ #
85
+ #
86
+ # Returns an array in the form [{date1 => value, date2 => value}]
87
+ def self.consumption_by_date(date, download_options)
88
+ check_first_hour(date)
89
+
90
+ first_hour = date
91
+ last_hour = DateTime.new(date.year, date.month, date.day, -1, -1, -1,
92
+ first_hour.gmt_offset)
93
+ last_hour = Time.new(last_hour.year, last_hour.month, last_hour.day,
94
+ last_hour.hour, last_hour.min, last_hour.sec,
95
+ first_hour.gmt_offset) + 1
96
+
97
+ Bucketize::Bucketizer
98
+ .new(download_options, first_hour, last_hour).daily_consumption_values
99
+ end
100
+
101
+ # daily consumption should be calculated by summing the consumption data
102
+ # into totals for the hour groups. These hour groups are summed to daily
103
+ # values.
104
+ #
105
+ # date1 - a Time representing the first hour of the start day of the
106
+ # range to which the data will be aggregated.
107
+ # It must be in the timezone of the consumer (required).
108
+ # date2 - a Time representing the last second of the end day of the range
109
+ # to which the data will be aggregated. (required).
110
+ # It must be in the timezone of the consumer (required).
111
+ # download_options - options used to download GreenButton data
112
+ #
113
+ # Supported download options:
114
+ # use_ftp - a Boolean flag to switch between ftp and API modes.
115
+ # API (HTTP) options
116
+ # access_token - the OAuth2 token used by the GreenButton gem to
117
+ # authenticate to the GreenButton custodians.
118
+ # subscription_url - the url used by the GreenButton gem to retrieve the data
119
+ # FTP options
120
+ # application_id - represents the GreenButton 3rd party application id.
121
+ # time - used to construct file name. (optional, defaults
122
+ # to current time)
123
+ # utility_name - represents the utility name, used to construct the
124
+ # XML file name.
125
+ #
126
+ # Returns an array in the form [{date1 => value, date2 => value}]
127
+ #
128
+ def self.consumption_date_range(date1, date2, download_options)
129
+ check_first_hour(date1)
130
+ check_last_second(date2)
131
+
132
+ first_day = date1
133
+ last_day = date2 + 1
134
+
135
+ Bucketize::Bucketizer
136
+ .new(download_options, first_day, last_day).daily_consumption_values
137
+ end
138
+
139
+
140
+ # The consumption intervals should be summed by the hours of the day
141
+ # relevant to the tariff, and summed to daily values. Daily consumption
142
+ # values are multiplied with the appropriate tariff for the day of the week
143
+ # to get costs. Tariff selection varies depending on the consumption total
144
+ # since when the beginning of the month falls
145
+ #
146
+ # month - a Time representing the first hour of the first day in the month
147
+ # to which the data will be aggregated. (required)
148
+ # tariff - The tariff rules (json string).
149
+ #
150
+ # download_options - options used to download GreenButton data
151
+ #
152
+ # Supported download options:
153
+ # use_ftp - a Boolean flag to switch between ftp and API modes.
154
+ # API (HTTP) options
155
+ # access_token - the OAuth2 token used by the GreenButton gem to
156
+ # authenticate to the GreenButton custodians.
157
+ # subscription_url - the url used by the GreenButton gem to retrieve the data
158
+ # FTP options
159
+ # application_id - represents the GreenButton 3rd party application id.
160
+ # time - used to construct file name. (optional, defaults
161
+ # to current time)
162
+ # utility_name - represents the utility name, used to construct the
163
+ # XML file name.
164
+ #
165
+ #
166
+ # Returns an array in the form [{date1 => cost, date2 => cost}]
167
+ #
168
+ def self.cost_from_month_start(month, tariff, download_options)
169
+ check_first_day_of_month(month)
170
+
171
+ first_day = month
172
+ last_day = DateTime.new(month.year, month.month, -1, -1, -1, -1,
173
+ first_day.gmt_offset)
174
+ # convert to time with the same zone offset of the first day
175
+ last_day = Time.new(last_day.year, last_day.month, last_day.day,
176
+ last_day.hour, last_day.min, last_day.sec,
177
+ first_day.gmt_offset) + 1
178
+ tariff_rules = JSON.parse(tariff, :object_class => Bucketize::TariffRule)
179
+
180
+ Bucketize::Bucketizer
181
+ .new(download_options, first_day, last_day)
182
+ .daily_consumption_costs(tariff_rules)
183
+ end
184
+
185
+ # The consumption is calculated by summing the consumption data in totals of
186
+ # hours groups and summed to daily values. Daily values are multiplied with
187
+ # the appropriate tariff for the day of the week.
188
+ #
189
+ # date - a Date representing the day to which the data will
190
+ # be aggregated, it must be Time object referring to the first hour
191
+ # of the required day (required).
192
+ # tariff - The tariff rules (json string).
193
+ #
194
+ # download_options - options used to download GreenButton data
195
+ #
196
+ # Supported download options:
197
+ # use_ftp - a Boolean flag to switch between ftp and API modes.
198
+ # API (HTTP) options
199
+ # access_token - the OAuth2 token used by the GreenButton gem to
200
+ # authenticate to the GreenButton custodians.
201
+ # subscription_url - the url used by the GreenButton gem to retrieve the data
202
+ # FTP options
203
+ # application_id - represents the GreenButton 3rd party application id.
204
+ # time - used to construct file name. (optional, defaults
205
+ # to current time)
206
+ # utility_name - represents the utility name, used to construct the
207
+ # XML file name.
208
+ #
209
+ #
210
+ # Returns an array in the form [{date1 => cost, date2 => cost}]
211
+ #
212
+ def self.cost_by_date(date, tariff, download_options)
213
+ check_first_hour(date)
214
+
215
+ first_hour = date
216
+ last_hour = DateTime.new(date.year, date.month, date.day, -1, -1, -1,
217
+ first_hour.gmt_offset)
218
+ last_hour = Time.new(last_hour.year, last_hour.month, last_hour.day,
219
+ last_hour.hour, last_hour.min, last_hour.sec,
220
+ first_hour.gmt_offset) + 1
221
+ tariff_rules = JSON.parse(tariff, :object_class => Bucketize::TariffRule)
222
+
223
+ Bucketize::Bucketizer
224
+ .new(download_options, first_hour, last_hour)
225
+ .daily_consumption_costs(tariff_rules)
226
+ end
227
+
228
+
229
+ # Daily cost should be calculated by summing the consumption data into
230
+ # totals for the hour groups, and using the appropriate tariff based on the
231
+ # day of the week and hour group.
232
+ #
233
+ # date1 - a Time representing the first hour of the start day of the
234
+ # range to which the data will be aggregated.
235
+ # It must be in the timezone of the consumer (required).
236
+ # date2 - a Time representing the last second of the end day of the range
237
+ # to which the data will be aggregated. (required).
238
+ # It must be in the timezone of the consumer (required).
239
+ # tariff - The tariff rules (json string).
240
+ #
241
+ # download_options - options used to download GreenButton data
242
+ #
243
+ # Supported download options:
244
+ # use_ftp - a Boolean flag to switch between ftp and API modes.
245
+ # API (HTTP) options
246
+ # access_token - the OAuth2 token used by the GreenButton gem to
247
+ # authenticate to the GreenButton custodians.
248
+ # subscription_url - the url used by the GreenButton gem to retrieve the data
249
+ # FTP options
250
+ # application_id - represents the GreenButton 3rd party application id.
251
+ # time - used to construct file name. (optional, defaults
252
+ # to current time)
253
+ # utility_name - represents the utility name, used to construct the
254
+ # XML file name.
255
+ #
256
+ # Returns an array in the form [{date1 => cost, date2 => cost}]
257
+ def self.cost_date_range(date1, date2, tariff, download_options)
258
+ check_first_hour(date1)
259
+ check_last_second(date2)
260
+
261
+ first_day = date1
262
+ last_day = date2 + 1
263
+
264
+ tariff_rules = JSON.parse(tariff, :object_class => Bucketize::TariffRule)
265
+
266
+ Bucketize::Bucketizer
267
+ .new(download_options, first_day, last_day)
268
+ .daily_consumption_costs(tariff_rules)
269
+ end
270
+
271
+ # Public: configures the Bucketize module. It must be called before usage.
272
+ #
273
+ # For example:
274
+ # Bucketize.config(reg_access_token: "your access token"
275
+ # application_information_url: "http://app_info_url")
276
+ #
277
+ # Returns nothing.
278
+ #
279
+ def self.config(options = {})
280
+ GreenButton.config(options)
281
+ end
282
+
283
+ # Internal: Checks if the given time is a Time object referring to a first
284
+ # hour of the first day of a month.
285
+ #
286
+ # Raises ArgumentError if invalid.
287
+ def self.check_first_day_of_month(time)
288
+ check_time(time)
289
+ unless time.day == 1
290
+ raise ArgumentError, "#{time} is not the first day of Month #{time.month}"
291
+ end
292
+ check_first_hour(time)
293
+ end
294
+
295
+ # Internal: Checks if the given time is a Time object referring to a first
296
+ # hour of a day.
297
+ #
298
+ # Raises ArgumentError if invalid.
299
+ def self.check_first_hour(time)
300
+ check_time(time)
301
+ if time.hour != 0 or time.min != 0 or time.sec != 0
302
+ raise ArgumentError, "#{time} is not the first hour of the day"
303
+ end
304
+ end
305
+
306
+ # Internal: Checks if the given time is a Time object referring to the last
307
+ # second of a day.
308
+ #
309
+ # Raises ArgumentError if invalid.
310
+ def self.check_last_second(time)
311
+ check_time(time)
312
+ next_sec = time + 1
313
+ if next_sec.hour != 0 or next_sec.min != 0 or next_sec.sec != 0
314
+ raise ArgumentError, "#{time} is not the last second of the day"
315
+ end
316
+
317
+ end
318
+
319
+ # Internal: Checks if the given time is a Time object.
320
+ #
321
+ # Raises ArgumentError if invalid.
322
+ def self.check_time(time)
323
+ raise ArgumentError, "#{time} is not a Time object" unless time.is_a? Time
324
+ end
325
+
326
+ private_class_method :check_time
327
+ private_class_method :check_first_hour
328
+ private_class_method :check_last_second
329
+ private_class_method :check_first_day_of_month
330
+
331
+
332
+ # This error will be raised if an invalid tariff json is provided.
333
+ #
334
+ # Author: ahmed.seddiq
335
+ # Version: 1.0
336
+ class InvalidTariffError < Exception
337
+
338
+ end
339
+
340
+
341
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ce-bucketize
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - TCSASSEMBLER
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-05-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.8'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.2'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.2
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.9.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: yard-tomdoc
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.7.1
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.7.1
83
+ - !ruby/object:Gem::Dependency
84
+ name: interpolate
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.3.0
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.3.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: ce-greenbutton
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.1.0
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.1.0
111
+ description: |-
112
+ aggregate consumption data with heterogeneous granularity across time into systematic intervals.
113
+ These intervals are then either multiplied with a relevant tariff value then summed into daily totals,
114
+ or directly summed into daily totals. The simplest example would be to sum hourly data into daily totals,
115
+ subject to data completeness checks and multiply them with a single tariff number.
116
+ email:
117
+ - TCSASSEMBLER@topcoder.com
118
+ executables: []
119
+ extensions: []
120
+ extra_rdoc_files: []
121
+ files:
122
+ - Gemfile
123
+ - LICENSE.txt
124
+ - README.md
125
+ - Rakefile
126
+ - ce-bucketize.gemspec
127
+ - lib/ce-bucketize.rb
128
+ - lib/ce-bucketize/bucketizer.rb
129
+ - lib/ce-bucketize/daily_data.rb
130
+ - lib/ce-bucketize/hourly_values.rb
131
+ - lib/ce-bucketize/model/hour_cost.rb
132
+ - lib/ce-bucketize/model/hour_value.rb
133
+ - lib/ce-bucketize/model/tariff_rule.rb
134
+ - lib/ce-bucketize/tariffed_hourly_costs.rb
135
+ - lib/ce-bucketize/tariffed_hourly_values.rb
136
+ - lib/ce-bucketize/version.rb
137
+ homepage: http://greenbuttondata.org
138
+ licenses:
139
+ - MIT
140
+ metadata: {}
141
+ post_install_message:
142
+ rdoc_options: []
143
+ require_paths:
144
+ - lib
145
+ required_ruby_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ requirements: []
156
+ rubyforge_project:
157
+ rubygems_version: 2.2.2
158
+ signing_key:
159
+ specification_version: 4
160
+ summary: Aggregates consumption data and calculates costs based on predefined tariffs.
161
+ test_files: []