urbanopt-reporting 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.
- checksums.yaml +7 -0
- data/.gitignore +24 -0
- data/.rubocop.yml +10 -0
- data/CHANGELOG.md +7 -0
- data/CONTRIBUTING.md +58 -0
- data/Gemfile +18 -0
- data/Jenkinsfile +10 -0
- data/LICENSE.md +27 -0
- data/README.md +40 -0
- data/Rakefile +45 -0
- data/doc_templates/LICENSE.md +27 -0
- data/doc_templates/README.md.erb +42 -0
- data/doc_templates/copyright_erb.txt +31 -0
- data/doc_templates/copyright_js.txt +4 -0
- data/doc_templates/copyright_ruby.txt +29 -0
- data/lib/measures/.rubocop.yml +5 -0
- data/lib/measures/default_feature_reports/LICENSE.md +27 -0
- data/lib/measures/default_feature_reports/README.md +26 -0
- data/lib/measures/default_feature_reports/README.md.erb +42 -0
- data/lib/measures/default_feature_reports/measure.rb +1012 -0
- data/lib/measures/default_feature_reports/measure.xml +160 -0
- data/lib/urbanopt/reporting.rb +37 -0
- data/lib/urbanopt/reporting/default_reports.rb +44 -0
- data/lib/urbanopt/reporting/default_reports/construction_cost.rb +169 -0
- data/lib/urbanopt/reporting/default_reports/date.rb +97 -0
- data/lib/urbanopt/reporting/default_reports/distributed_generation.rb +379 -0
- data/lib/urbanopt/reporting/default_reports/end_use.rb +159 -0
- data/lib/urbanopt/reporting/default_reports/end_uses.rb +140 -0
- data/lib/urbanopt/reporting/default_reports/extension.rb +15 -0
- data/lib/urbanopt/reporting/default_reports/feature_report.rb +266 -0
- data/lib/urbanopt/reporting/default_reports/generator.rb +92 -0
- data/lib/urbanopt/reporting/default_reports/location.rb +99 -0
- data/lib/urbanopt/reporting/default_reports/logger.rb +44 -0
- data/lib/urbanopt/reporting/default_reports/power_distribution.rb +103 -0
- data/lib/urbanopt/reporting/default_reports/program.rb +265 -0
- data/lib/urbanopt/reporting/default_reports/reporting_period.rb +300 -0
- data/lib/urbanopt/reporting/default_reports/scenario_report.rb +317 -0
- data/lib/urbanopt/reporting/default_reports/schema/README.md +33 -0
- data/lib/urbanopt/reporting/default_reports/schema/scenario_csv_columns.txt +34 -0
- data/lib/urbanopt/reporting/default_reports/schema/scenario_schema.json +857 -0
- data/lib/urbanopt/reporting/default_reports/solar_pv.rb +93 -0
- data/lib/urbanopt/reporting/default_reports/storage.rb +105 -0
- data/lib/urbanopt/reporting/default_reports/timeseries_csv.rb +300 -0
- data/lib/urbanopt/reporting/default_reports/validator.rb +112 -0
- data/lib/urbanopt/reporting/default_reports/wind.rb +92 -0
- data/lib/urbanopt/reporting/derived_extension.rb +63 -0
- data/lib/urbanopt/reporting/version.rb +35 -0
- data/urbanopt-reporting-gem.gemspec +33 -0
- metadata +176 -0
@@ -0,0 +1,379 @@
|
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
|
+
# contributors. All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# Redistributions of source code must retain the above copyright notice, this list
|
9
|
+
# of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
|
+
# list of conditions and the following disclaimer in the documentation and/or other
|
13
|
+
# materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
|
+
# used to endorse or promote products derived from this software without specific
|
17
|
+
# prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
20
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
22
|
+
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
23
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
24
|
+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
25
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
26
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
27
|
+
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
28
|
+
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
# *********************************************************************************
|
30
|
+
|
31
|
+
require 'json'
|
32
|
+
require_relative 'solar_pv'
|
33
|
+
require_relative 'wind'
|
34
|
+
require_relative 'generator'
|
35
|
+
require_relative 'storage'
|
36
|
+
require 'json-schema'
|
37
|
+
|
38
|
+
module URBANopt
|
39
|
+
module Reporting
|
40
|
+
module DefaultReports
|
41
|
+
##
|
42
|
+
# Onsite distributed generation system (i.e. SolarPV, Wind, Storage, Generator) design attributes and financial metrics.
|
43
|
+
##
|
44
|
+
class DistributedGeneration
|
45
|
+
##
|
46
|
+
# _Float_ - Lifecycle costs for the complete distributed generation system in US Dollars
|
47
|
+
#
|
48
|
+
attr_accessor :lcc_us_dollars
|
49
|
+
|
50
|
+
##
|
51
|
+
# _Float_ - Net present value of the complete distributed generation system in US Dollars
|
52
|
+
#
|
53
|
+
attr_accessor :npv_us_dollars
|
54
|
+
|
55
|
+
##
|
56
|
+
# _Float_ - Total amount paid for utility energy in US Dollars in the first year of operation
|
57
|
+
#
|
58
|
+
attr_accessor :year_one_energy_cost_us_dollars
|
59
|
+
|
60
|
+
##
|
61
|
+
# _Float_ - Total amount paid in utility demand charges in US Dollars in the first year of operation
|
62
|
+
#
|
63
|
+
attr_accessor :year_one_demand_cost_us_dollars
|
64
|
+
|
65
|
+
##
|
66
|
+
# _Float_ - Total amount paid to the utility in US Dollars in the first year of operation
|
67
|
+
#
|
68
|
+
attr_accessor :year_one_bill_us_dollars
|
69
|
+
|
70
|
+
##
|
71
|
+
# _Float_ - Total amount paid to the utility in US Dollars over the life of the system
|
72
|
+
#
|
73
|
+
attr_accessor :total_energy_cost_us_dollars
|
74
|
+
|
75
|
+
##
|
76
|
+
# _Array_ - List of _SolarPV_ systems
|
77
|
+
#
|
78
|
+
attr_accessor :solar_pv
|
79
|
+
|
80
|
+
##
|
81
|
+
# _Array_ - List of _Wind_ systems
|
82
|
+
#
|
83
|
+
attr_accessor :wind
|
84
|
+
|
85
|
+
##
|
86
|
+
# _Array_ - List of _Generator_ systems
|
87
|
+
#
|
88
|
+
attr_accessor :generator
|
89
|
+
|
90
|
+
##
|
91
|
+
# _Array_ - List of _Storage_ systems
|
92
|
+
#
|
93
|
+
attr_accessor :storage
|
94
|
+
|
95
|
+
##
|
96
|
+
# _Float_ - Installed solar PV capacity
|
97
|
+
#
|
98
|
+
attr_accessor :total_solar_pv_kw
|
99
|
+
|
100
|
+
##
|
101
|
+
# _Float_ - Installed wind capacity
|
102
|
+
#
|
103
|
+
attr_accessor :total_wind_kw
|
104
|
+
|
105
|
+
##
|
106
|
+
# _Float_ - Installed storage capacity
|
107
|
+
#
|
108
|
+
attr_accessor :total_storage_kw
|
109
|
+
|
110
|
+
##
|
111
|
+
# _Float_ - Installed storage capacity
|
112
|
+
#
|
113
|
+
attr_accessor :total_storage_kwh
|
114
|
+
|
115
|
+
##
|
116
|
+
# _Float_ - Installed generator capacity
|
117
|
+
#
|
118
|
+
attr_accessor :total_generator_kw
|
119
|
+
|
120
|
+
##
|
121
|
+
# Initialize distributed generation system design and financial metrics.
|
122
|
+
#
|
123
|
+
# * Technologies include +:solar_pv+, +:wind+, +:generator+, and +:storage+.
|
124
|
+
# * Financial metrics include +:lcc_us_dollars+, +:npv_us_dollars+, +:year_one_energy_cost_us_dollars+, +:year_one_demand_cost_us_dollars+,
|
125
|
+
# +:year_one_bill_us_dollars+, and +:total_energy_cost_us_dollars+
|
126
|
+
##
|
127
|
+
# [parameters:]
|
128
|
+
#
|
129
|
+
# * +hash+ - _Hash_ - A hash containting key/value pairs for the distributed generation system attributes listed above.
|
130
|
+
#
|
131
|
+
def initialize(hash = {})
|
132
|
+
hash.delete_if { |k, v| v.nil? }
|
133
|
+
|
134
|
+
@lcc_us_dollars = hash[:lcc_us_dollars]
|
135
|
+
@npv_us_dollars = hash[:npv_us_dollars]
|
136
|
+
@year_one_energy_cost_us_dollars = hash[:year_one_energy_cost_us_dollars]
|
137
|
+
@year_one_demand_cost_us_dollars = hash[:year_one_demand_cost_us_dollars]
|
138
|
+
@year_one_bill_us_dollars = hash[:year_one_bill_us_dollars]
|
139
|
+
@total_energy_cost_us_dollars = hash[:total_energy_cost_us_dollars]
|
140
|
+
|
141
|
+
@total_solar_pv_kw = nil
|
142
|
+
@total_wind_kw = nil
|
143
|
+
@total_generator_kw = nil
|
144
|
+
@total_storage_kw = nil
|
145
|
+
@total_storage_kwh = nil
|
146
|
+
|
147
|
+
@solar_pv = []
|
148
|
+
if hash[:solar_pv].class == Hash
|
149
|
+
hash[:solar_pv] = [hash[:solar_pv]]
|
150
|
+
elsif hash[:solar_pv].nil?
|
151
|
+
hash[:solar_pv] = []
|
152
|
+
end
|
153
|
+
|
154
|
+
hash[:solar_pv].each do |s|
|
155
|
+
if !s[:size_kw].nil? && (s[:size_kw] != 0)
|
156
|
+
@solar_pv.push SolarPV.new(s)
|
157
|
+
if @total_solar_pv_kw.nil?
|
158
|
+
@total_solar_pv_kw = @solar_pv[-1].size_kw
|
159
|
+
else
|
160
|
+
@total_solar_pv_kw += @solar_pv[-1].size_kw
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
@wind = []
|
166
|
+
if hash[:wind].class == Hash
|
167
|
+
hash[:wind] = [hash[:wind]]
|
168
|
+
elsif hash[:wind].nil?
|
169
|
+
hash[:wind] = []
|
170
|
+
end
|
171
|
+
|
172
|
+
hash[:wind].each do |s|
|
173
|
+
if !s[:size_kw].nil? && (s[:size_kw] != 0)
|
174
|
+
@wind.push Wind.new(s)
|
175
|
+
if @total_wind_kw.nil?
|
176
|
+
@total_wind_kw = @wind[-1].size_kw
|
177
|
+
else
|
178
|
+
@total_wind_kw += @wind[-1].size_kw
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
@generator = []
|
184
|
+
if hash[:generator].class == Hash
|
185
|
+
hash[:generator] = [hash[:generator]]
|
186
|
+
elsif hash[:generator].nil?
|
187
|
+
hash[:generator] = []
|
188
|
+
end
|
189
|
+
|
190
|
+
hash[:generator].each do |s|
|
191
|
+
if !s[:size_kw].nil? && (s[:size_kw] != 0)
|
192
|
+
@generator.push Generator.new(s)
|
193
|
+
if @total_generator_kw.nil?
|
194
|
+
@total_generator_kw = @generator[-1].size_kw
|
195
|
+
else
|
196
|
+
@total_generator_kw += @generator[-1].size_kw
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
@storage = []
|
202
|
+
if hash[:storage].class == Hash
|
203
|
+
hash[:storage] = [hash[:storage]]
|
204
|
+
elsif hash[:storage].nil?
|
205
|
+
hash[:storage] = []
|
206
|
+
end
|
207
|
+
|
208
|
+
hash[:storage].each do |s|
|
209
|
+
if !s[:size_kw].nil? && (s[:size_kw] != 0)
|
210
|
+
@storage.push Storage.new(s)
|
211
|
+
if @total_storage_kw.nil?
|
212
|
+
@total_storage_kw = @storage[-1].size_kw
|
213
|
+
@total_storage_kwh = @storage[-1].size_kwh
|
214
|
+
else
|
215
|
+
@total_storage_kw += @storage[-1].size_kw
|
216
|
+
@total_storage_kwh += @storage[-1].size_kwh
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# initialize class variables @@validator and @@schema
|
222
|
+
@@validator ||= Validator.new
|
223
|
+
@@schema ||= @@validator.schema
|
224
|
+
|
225
|
+
# initialize @@logger
|
226
|
+
@@logger ||= URBANopt::Reporting::DefaultReports.logger
|
227
|
+
end
|
228
|
+
|
229
|
+
##
|
230
|
+
# Add a tech
|
231
|
+
##
|
232
|
+
def add_tech(name, tech)
|
233
|
+
if name == 'solar_pv'
|
234
|
+
@solar_pv.push tech
|
235
|
+
if @total_solar_pv_kw.nil?
|
236
|
+
@total_solar_pv_kw = tech.size_kw
|
237
|
+
else
|
238
|
+
@total_solar_pv_kw += tech.size_kw
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
if name == 'wind'
|
243
|
+
@wind.push tech
|
244
|
+
if @total_wind_kw.nil?
|
245
|
+
@total_wind_kw = tech.size_kw
|
246
|
+
else
|
247
|
+
@total_wind_kw += tech.size_kw
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
if name == 'storage'
|
252
|
+
@storage.push tech
|
253
|
+
if @total_storage_kw.nil?
|
254
|
+
@total_storage_kw = tech.size_kw
|
255
|
+
@total_storage_kwh = tech.size_kwh
|
256
|
+
else
|
257
|
+
@total_storage_kw += tech.size_kw
|
258
|
+
@total_storage_kwh += tech.size_kwh
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
if name == 'generator'
|
263
|
+
@generator.push tech
|
264
|
+
if @total_generator_kw.nil?
|
265
|
+
@total_generator_kw = tech.size_kw
|
266
|
+
else
|
267
|
+
@total_generator_kw += tech.size_kw
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
##
|
273
|
+
# Convert to a Hash equivalent for JSON serialization
|
274
|
+
##
|
275
|
+
def to_hash
|
276
|
+
result = {}
|
277
|
+
|
278
|
+
result[:lcc_us_dollars] = @lcc_us_dollars if @lcc_us_dollars
|
279
|
+
result[:npv_us_dollars] = @npv_us_dollars if @npv_us_dollars
|
280
|
+
result[:year_one_energy_cost_us_dollars] = @year_one_energy_cost_us_dollars if @year_one_energy_cost_us_dollars
|
281
|
+
result[:year_one_demand_cost_us_dollars] = @year_one_demand_cost_us_dollars if @year_one_demand_cost_us_dollars
|
282
|
+
result[:year_one_bill_us_dollars] = @year_one_bill_us_dollars if @year_one_bill_us_dollars
|
283
|
+
result[:total_solar_pv_kw] = @total_solar_pv_kw if @total_solar_pv_kw
|
284
|
+
result[:total_wind_kw] = @total_wind_kw if @total_wind_kw
|
285
|
+
result[:total_generator_kw] = @total_generator_kw if @total_generator_kw
|
286
|
+
result[:total_storage_kw] = @total_storage_kw if @total_storage_kw
|
287
|
+
result[:total_storage_kwh] = @total_storage_kwh if @total_storage_kwh
|
288
|
+
|
289
|
+
result[:solar_pv] = []
|
290
|
+
@solar_pv.each do |pv|
|
291
|
+
result[:solar_pv].push pv.to_hash
|
292
|
+
end
|
293
|
+
result[:wind] = []
|
294
|
+
@wind.each do |wind|
|
295
|
+
result[:wind].push wind.to_hash
|
296
|
+
end
|
297
|
+
result[:generator] = []
|
298
|
+
@generator.each do |generator|
|
299
|
+
result[:generator].push generator.to_hash
|
300
|
+
end
|
301
|
+
result[:storage] = []
|
302
|
+
@storage.each do |storage|
|
303
|
+
result[:storage].push storage.to_hash
|
304
|
+
end
|
305
|
+
return result
|
306
|
+
end
|
307
|
+
|
308
|
+
### get keys ...not needed
|
309
|
+
# def self.get_all_keys(h)
|
310
|
+
# h.each_with_object([]){|(k,v),a| v.is_a?(Hash) ? a.push(k,*get_all_keys(v)) : a << k }
|
311
|
+
# end
|
312
|
+
|
313
|
+
##
|
314
|
+
# Add up old and new values
|
315
|
+
##
|
316
|
+
def self.add_values(existing_value, new_value) #:nodoc:
|
317
|
+
if existing_value && new_value
|
318
|
+
existing_value += new_value
|
319
|
+
elsif new_value
|
320
|
+
existing_value = new_value
|
321
|
+
end
|
322
|
+
return existing_value
|
323
|
+
end
|
324
|
+
|
325
|
+
##
|
326
|
+
# Merge a distributed generation system with a new system
|
327
|
+
##
|
328
|
+
def self.merge_distributed_generation(existing_dgen, new_dgen)
|
329
|
+
existing_dgen.lcc_us_dollars = add_values(existing_dgen.lcc_us_dollars, new_dgen.lcc_us_dollars)
|
330
|
+
existing_dgen.npv_us_dollars = add_values(existing_dgen.npv_us_dollars, new_dgen.npv_us_dollars)
|
331
|
+
existing_dgen.year_one_energy_cost_us_dollars = add_values(existing_dgen.year_one_energy_cost_us_dollars, new_dgen.year_one_energy_cost_us_dollars)
|
332
|
+
existing_dgen.year_one_demand_cost_us_dollars = add_values(existing_dgen.year_one_demand_cost_us_dollars, new_dgen.year_one_demand_cost_us_dollars)
|
333
|
+
existing_dgen.year_one_bill_us_dollars = add_values(existing_dgen.year_one_bill_us_dollars, new_dgen.year_one_bill_us_dollars)
|
334
|
+
existing_dgen.total_energy_cost_us_dollars = add_values(existing_dgen.total_energy_cost_us_dollars, new_dgen.total_energy_cost_us_dollars)
|
335
|
+
|
336
|
+
new_dgen.solar_pv.each do |pv|
|
337
|
+
existing_dgen.solar_pv.push pv
|
338
|
+
if existing_dgen.total_solar_pv_kw.nil?
|
339
|
+
existing_dgen.total_solar_pv_kw = pv.size_kw
|
340
|
+
else
|
341
|
+
existing_dgen.total_solar_pv_kw += pv.size_kw
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
new_dgen.wind.each do |wind|
|
346
|
+
existing_dgen.wind.push wind
|
347
|
+
if existing_dgen.total_wind_kw.nil?
|
348
|
+
existing_dgen.total_wind_kw = wind.size_kw
|
349
|
+
else
|
350
|
+
existing_dgen.total_wind_kw += wind.size_kw
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
new_dgen.storage.each do |storage|
|
355
|
+
existing_dgen.storage.push storage
|
356
|
+
if existing_dgen.total_wind_kw.nil?
|
357
|
+
existing_dgen.total_storage_kw = storage.size_kw
|
358
|
+
existing_dgen.total_storage_kwh = storage.size_kwh
|
359
|
+
else
|
360
|
+
existing_dgen.total_storage_kw += storage.size_kw
|
361
|
+
existing_dgen.total_storage_kwh += storage.size_kwh
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
new_dgen.generator.each do |generator|
|
366
|
+
existing_dgen.generator.push generator
|
367
|
+
if existing_dgen.total_wind_kw.nil?
|
368
|
+
existing_dgen.total_generator_kw = generator.size_kw
|
369
|
+
else
|
370
|
+
existing_dgen.total_generator_kw += generator.size_kw
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
return existing_dgen
|
375
|
+
end
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
|
+
# contributors. All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# Redistributions of source code must retain the above copyright notice, this list
|
9
|
+
# of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
|
+
# list of conditions and the following disclaimer in the documentation and/or other
|
13
|
+
# materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
|
+
# used to endorse or promote products derived from this software without specific
|
17
|
+
# prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
20
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
22
|
+
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
23
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
24
|
+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
25
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
26
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
27
|
+
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
28
|
+
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
# *********************************************************************************
|
30
|
+
|
31
|
+
require_relative 'validator'
|
32
|
+
require 'json-schema'
|
33
|
+
|
34
|
+
module URBANopt
|
35
|
+
module Reporting
|
36
|
+
module DefaultReports
|
37
|
+
##
|
38
|
+
# Enduse class all enduse energy consumption results.
|
39
|
+
##
|
40
|
+
class EndUse
|
41
|
+
attr_accessor :heating, :cooling, :interior_lighting, :exterior_lighting, :interior_equipment, :exterior_equipment,
|
42
|
+
:fans, :pumps, :heat_rejection, :humidification, :heat_recovery, :water_systems, :refrigeration, :generators # :nodoc:
|
43
|
+
|
44
|
+
##
|
45
|
+
# EndUse class intialize all enduse atributes: +:heating+ , +:cooling+ , +:interior_lighting+ ,
|
46
|
+
# +:exterior_lighting+ , +:interior_equipment+ , +:exterior_equipment+ ,
|
47
|
+
# +:fans+ , +:pumps+ , +:heat_rejection+ , +:humidification+ , +:heat_recovery+ , +:water_systems+ , +:refrigeration+ , +:generators+
|
48
|
+
##
|
49
|
+
# [parameters:]
|
50
|
+
# +hash+ - _Hash_ - A hash which may contain a deserialized end_use.
|
51
|
+
##
|
52
|
+
def initialize(hash = {})
|
53
|
+
hash.delete_if { |k, v| v.nil? }
|
54
|
+
hash = defaults.merge(hash)
|
55
|
+
|
56
|
+
@heating = hash[:heating]
|
57
|
+
@cooling = hash[:cooling]
|
58
|
+
@interior_lighting = hash[:interior_lighting]
|
59
|
+
@exterior_lighting = hash[:exterior_lighting]
|
60
|
+
@interior_equipment = hash[:interior_equipment]
|
61
|
+
@exterior_equipment = hash[:exterior_equipment]
|
62
|
+
@fans = hash[:fans]
|
63
|
+
@pumps = hash[:pumps]
|
64
|
+
@heat_rejection = hash[:heat_rejection]
|
65
|
+
@humidification = hash[:humidification]
|
66
|
+
@heat_recovery = hash[:heat_recovery]
|
67
|
+
@water_systems = hash[:water_systems]
|
68
|
+
@refrigeration = hash[:refrigeration]
|
69
|
+
@generators = hash[:generators]
|
70
|
+
|
71
|
+
# initialize class variables @@validator and @@schema
|
72
|
+
@@validator ||= Validator.new
|
73
|
+
@@schema ||= @@validator.schema
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Assign default values if values does not exist
|
78
|
+
##
|
79
|
+
def defaults
|
80
|
+
hash = {}
|
81
|
+
|
82
|
+
hash[:heating] = nil
|
83
|
+
hash[:cooling] = nil
|
84
|
+
hash[:interior_lighting] = nil
|
85
|
+
hash[:exterior_lighting] = nil
|
86
|
+
hash[:interior_equipment] = nil
|
87
|
+
hash[:exterior_equipment] = nil
|
88
|
+
hash[:fans] = nil
|
89
|
+
hash[:pumps] = nil
|
90
|
+
hash[:heat_rejection] = nil
|
91
|
+
hash[:humidification] = nil
|
92
|
+
hash[:heat_recovery] = nil
|
93
|
+
hash[:water_systems] = nil
|
94
|
+
hash[:refrigeration] = nil
|
95
|
+
hash[:generators] = nil
|
96
|
+
|
97
|
+
return hash
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# Convert to a Hash equivalent for JSON serialization.
|
102
|
+
##
|
103
|
+
# - Exclude attributes with nil values.
|
104
|
+
# - Validate end_use hash properties against schema.
|
105
|
+
##
|
106
|
+
def to_hash
|
107
|
+
result = {}
|
108
|
+
|
109
|
+
result[:heating] = @heating
|
110
|
+
result[:cooling] = @cooling
|
111
|
+
result[:interior_lighting] = @interior_lighting
|
112
|
+
result[:exterior_lighting] = @exterior_lighting
|
113
|
+
result[:interior_equipment] = @interior_equipment
|
114
|
+
result[:exterior_equipment] = @exterior_equipment
|
115
|
+
result[:fans] = @fans
|
116
|
+
result[:pumps] = @pumps
|
117
|
+
result[:heat_rejection] = @heat_rejection
|
118
|
+
result[:humidification] = @humidification
|
119
|
+
result[:heat_recovery] = @heat_recovery
|
120
|
+
result[:water_systems] = @water_systems
|
121
|
+
result[:refrigeration] = @refrigeration
|
122
|
+
result[:generators] = @generators
|
123
|
+
|
124
|
+
# validate end_use properties against schema
|
125
|
+
if @@validator.validate(@@schema[:definitions][:EndUse][:properties], result).any?
|
126
|
+
raise "end_use properties does not match schema: #{@@validator.validate(@@schema[:definitions][:EndUse][:properties], result)}"
|
127
|
+
end
|
128
|
+
|
129
|
+
return result
|
130
|
+
end
|
131
|
+
|
132
|
+
##
|
133
|
+
# Aggregate values of each EndUse attribute.
|
134
|
+
##
|
135
|
+
# [Parameters:]
|
136
|
+
# +new_end_use+ - _EndUse_ - An object of EndUse class.
|
137
|
+
##
|
138
|
+
def merge_end_use!(new_end_use)
|
139
|
+
@heating += new_end_use.heating if new_end_use.heating
|
140
|
+
@cooling += new_end_use.cooling if new_end_use.cooling
|
141
|
+
@interior_lighting += new_end_use.interior_lighting if new_end_use.interior_lighting
|
142
|
+
@exterior_lighting += new_end_use.exterior_lighting if new_end_use.exterior_lighting
|
143
|
+
@interior_equipment += new_end_use.interior_equipment if new_end_use.interior_equipment
|
144
|
+
@exterior_equipment += new_end_use.exterior_equipment if new_end_use.exterior_equipment
|
145
|
+
@fans += new_end_use.fans if new_end_use.fans
|
146
|
+
@pumps += new_end_use.pumps if new_end_use.pumps
|
147
|
+
@heat_rejection += new_end_use.heat_rejection if new_end_use.heat_rejection
|
148
|
+
@humidification += new_end_use.humidification if new_end_use.humidification
|
149
|
+
@heat_recovery += new_end_use.heat_recovery if new_end_use.heat_recovery
|
150
|
+
@water_systems += new_end_use.water_systems if new_end_use.water_systems
|
151
|
+
@refrigeration += new_end_use.refrigeration if new_end_use.refrigeration
|
152
|
+
@generators += new_end_use.generators if new_end_use.generators
|
153
|
+
|
154
|
+
return self
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|