urbanopt-reporting 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|