urbanopt-scenario 0.2.0 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +5 -5
  2. data/.github/pull_request_template.md +2 -2
  3. data/.gitignore +2 -0
  4. data/.rubocop.yml +1 -1
  5. data/CHANGELOG.md +53 -0
  6. data/CONTRIBUTING.md +1 -1
  7. data/Gemfile +27 -14
  8. data/Jenkinsfile +1 -1
  9. data/LICENSE.md +1 -1
  10. data/RDOC_MAIN.md +1 -1
  11. data/README.md +1 -1
  12. data/Rakefile +2 -2
  13. data/docs/README.md +1 -1
  14. data/docs/package-lock.json +2499 -2322
  15. data/docs/package.json +13 -9
  16. data/lib/urbanopt-scenario.rb +1 -1
  17. data/lib/urbanopt/scenario.rb +2 -1
  18. data/lib/urbanopt/scenario/default_reports.rb +3 -8
  19. data/lib/urbanopt/scenario/extension.rb +1 -1
  20. data/lib/urbanopt/scenario/logger.rb +1 -1
  21. data/lib/urbanopt/scenario/scenario_base.rb +1 -1
  22. data/lib/urbanopt/scenario/scenario_csv.rb +22 -9
  23. data/lib/urbanopt/scenario/scenario_datapoint_base.rb +8 -1
  24. data/lib/urbanopt/scenario/scenario_post_processor_base.rb +1 -1
  25. data/lib/urbanopt/scenario/scenario_post_processor_default.rb +110 -8
  26. data/lib/urbanopt/scenario/scenario_post_processor_opendss.rb +6 -7
  27. data/lib/urbanopt/scenario/scenario_runner_base.rb +2 -2
  28. data/lib/urbanopt/scenario/scenario_runner_osw.rb +23 -9
  29. data/lib/urbanopt/scenario/scenario_visualization.rb +236 -0
  30. data/lib/urbanopt/scenario/simulation_dir_base.rb +1 -1
  31. data/lib/urbanopt/scenario/simulation_dir_osw.rb +2 -9
  32. data/lib/urbanopt/scenario/simulation_mapper_base.rb +1 -1
  33. data/lib/urbanopt/scenario/version.rb +2 -2
  34. data/package-lock.json +3 -0
  35. data/urbanopt-scenario-gem.gemspec +14 -14
  36. metadata +71 -77
  37. data/doc_templates/LICENSE.md +0 -27
  38. data/doc_templates/README.md.erb +0 -42
  39. data/doc_templates/copyright_erb.txt +0 -31
  40. data/doc_templates/copyright_js.txt +0 -4
  41. data/doc_templates/copyright_ruby.txt +0 -29
  42. data/lib/change_log.rb +0 -147
  43. data/lib/measures/.rubocop.yml +0 -5
  44. data/lib/measures/default_feature_reports/LICENSE.md +0 -27
  45. data/lib/measures/default_feature_reports/README.md +0 -56
  46. data/lib/measures/default_feature_reports/README.md.erb +0 -42
  47. data/lib/measures/default_feature_reports/measure.rb +0 -979
  48. data/lib/measures/default_feature_reports/measure.xml +0 -143
  49. data/lib/measures/default_feature_reports/tests/USA_CO_Golden-NREL.724666_TMY3.epw +0 -8768
  50. data/lib/measures/default_feature_reports/tests/default_feature_reports_test.rb +0 -238
  51. data/lib/measures/default_feature_reports/tests/example_model.osm +0 -4378
  52. data/lib/urbanopt/scenario/default_reports/construction_cost.rb +0 -169
  53. data/lib/urbanopt/scenario/default_reports/date.rb +0 -97
  54. data/lib/urbanopt/scenario/default_reports/distributed_generation.rb +0 -379
  55. data/lib/urbanopt/scenario/default_reports/end_use.rb +0 -159
  56. data/lib/urbanopt/scenario/default_reports/end_uses.rb +0 -140
  57. data/lib/urbanopt/scenario/default_reports/feature_report.rb +0 -267
  58. data/lib/urbanopt/scenario/default_reports/generator.rb +0 -92
  59. data/lib/urbanopt/scenario/default_reports/location.rb +0 -99
  60. data/lib/urbanopt/scenario/default_reports/logger.rb +0 -44
  61. data/lib/urbanopt/scenario/default_reports/power_distribution.rb +0 -102
  62. data/lib/urbanopt/scenario/default_reports/program.rb +0 -266
  63. data/lib/urbanopt/scenario/default_reports/reporting_period.rb +0 -301
  64. data/lib/urbanopt/scenario/default_reports/scenario_report.rb +0 -317
  65. data/lib/urbanopt/scenario/default_reports/schema/README.md +0 -33
  66. data/lib/urbanopt/scenario/default_reports/schema/scenario_csv_columns.txt +0 -32
  67. data/lib/urbanopt/scenario/default_reports/schema/scenario_schema.json +0 -853
  68. data/lib/urbanopt/scenario/default_reports/solar_pv.rb +0 -93
  69. data/lib/urbanopt/scenario/default_reports/storage.rb +0 -105
  70. data/lib/urbanopt/scenario/default_reports/timeseries_csv.rb +0 -299
  71. data/lib/urbanopt/scenario/default_reports/validator.rb +0 -97
  72. data/lib/urbanopt/scenario/default_reports/wind.rb +0 -92
@@ -1,169 +0,0 @@
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 'urbanopt/scenario/default_reports/validator'
33
- require 'json-schema'
34
-
35
- module URBANopt
36
- module Scenario
37
- module DefaultReports
38
- ##
39
- # ConstructionCost include construction cost information.
40
- ##
41
- class ConstructionCost
42
- attr_accessor :category, :item_name, :unit_cost, :cost_units, :item_quantity, :total_cost # :nodoc:
43
- ##
44
- # ConstructionCost class intialize all construction_cost attributes:
45
- # +:category+ , +:item_name+ , +:unit_cost+ , +:cost_units+ , +:item_quantity+ , +:total_cost+
46
- ##
47
- # [parameters:]
48
- # +hash+ - _Hash_ - A hash which may contain a deserialized construction_cost.
49
- ##
50
- def initialize(hash = {})
51
- hash.delete_if { |k, v| v.nil? }
52
- hash = defaults.merge(hash)
53
-
54
- @category = hash[:category]
55
- @item_name = hash[:item_name]
56
- @unit_cost = hash[:unit_cost]
57
- @cost_units = hash[:cost_units]
58
- @item_quantity = hash[:item_quantity]
59
- @total_cost = hash[:total_cost]
60
-
61
- # initialize class variables @@validator and @@schema
62
- @@validator ||= Validator.new
63
- @@schema ||= @@validator.schema
64
- end
65
-
66
- ##
67
- # Assigns default values if attribute values do not exist.
68
- ##
69
- def defaults
70
- hash = {}
71
- hash[:category] = nil
72
- hash[:item_name] = nil
73
- hash[:unit_cost] = nil
74
- hash[:cost_units] = nil
75
- hash[:item_quantity] = nil
76
- hash[:total_cost] = nil
77
-
78
- return hash
79
- end
80
-
81
- ##
82
- # Converts to a Hash equivalent for JSON serialization.
83
- ##
84
- # - Exclude attributes with nil values.
85
- # - Validate construct_cost hash properties against schema.
86
- ##
87
- def to_hash
88
- result = {}
89
- result[:category] = @category if @category
90
- result[:item_name] = @item_name if @item_name
91
- result[:unit_cost] = @unit_cost if @unit_cost
92
- result[:cost_units] = @cost_units if @cost_units
93
- result[:item_quantity] = @item_quantity if @item_quantity
94
- result[:total_cost] = @total_cost if @total_cost
95
-
96
- # validate construct_cost properties against schema
97
- if @@validator.validate(@@schema[:definitions][:ConstructionCost][:properties], result).any?
98
- raise "construction_cost properties does not match schema: #{@@validator.validate(@@schema[:definitions][:ConstructionCost][:properties], result)}"
99
- end
100
-
101
- return result
102
- end
103
-
104
- ##
105
- # Merges an +existing_cost+ with a +new_cost+:
106
- # - modify the existing_cost by summing the +:total_cost+ and +:item_quantity+ of new_cost and existing_cost.
107
- # - raise an error if +:category+ , +:cost_units+ and +:unit_cost+ are not identical
108
- ##
109
- # [Parameters:]
110
- # +existing_cost+ - _ConstructionCost_ - An object of ConstructionCost class.
111
- ##
112
- # +new_cost+ - _ConstructionCost_ - An object of ConstructionCost class.
113
- ##
114
- def self.merge_construction_cost(existing_cost, new_cost)
115
- # modify the existing_cost by adding the :total_cost and :item_quantity
116
- existing_cost.total_cost += new_cost.total_cost
117
- existing_cost.item_quantity += new_cost.item_quantity
118
-
119
- if existing_cost.category != new_cost.category
120
- raise "Cannot merge existing cost of category \"#{existing_cost.category}\" with new cost of category \"#{new_cost.category}\"."
121
- end
122
-
123
- if existing_cost.cost_units != new_cost.cost_units
124
- raise "Cannot merge existing cost with cost units \"#{existing_cost.cost_units}\" with new cost with cost units \"#{new_cost.cost_units}\". "
125
- end
126
-
127
- if existing_cost.unit_cost != new_cost.unit_cost
128
- raise "Cannot merge existing cost with unit cost \"#{existing_cost.unit_cost}\" with new cost with unit cost \"#{new_cost.unit_cost}\"; identical items should have identical unit cost."
129
- end
130
-
131
- return existing_cost
132
- end
133
-
134
- ##
135
- # Merges muliple construction costs together.
136
- # - loops over the new_costs and find the index of the cost with identical +:item_name+.
137
- # - if +item_name+ is identical then modify the existing_cost array by summing the :total_cost and :item_quantity. Else add the new_cost to existing_costs array.
138
- ##
139
- # [Parameters:]
140
- # +existing_costs+ - _Array_ - An array of ConstructionCost objects.
141
- ##
142
- # +new_costs+ - _Array_ - An array of ConstructionCost objects.
143
- def self.merge_construction_costs(existing_costs, new_costs)
144
- item_name_list = []
145
- item_name_list = existing_costs.collect(&:item_name)
146
-
147
- new_costs.each do |x_new|
148
- if item_name_list.include?(x_new.item_name)
149
-
150
- # when looping over the new_cost item_names find the index of the item_name_list with the same item name
151
- id = item_name_list.find_index(x_new.item_name) # the order of the item_name_list is the same as the order of the existing_cost hash-array
152
-
153
- # modify the existing_cost array by adding the :total_cost and :item_quantity when looping over costs
154
- existing_costs[id] = merge_construction_cost(existing_costs[id], x_new)
155
-
156
- else
157
-
158
- # insert the new hash in to the array
159
- existing_costs << x_new
160
-
161
- end
162
- end
163
-
164
- return existing_costs
165
- end
166
- end
167
- end
168
- end
169
- end
@@ -1,97 +0,0 @@
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 'urbanopt/scenario/default_reports/validator'
32
- require 'json-schema'
33
- require 'json'
34
-
35
- module URBANopt
36
- module Scenario
37
- module DefaultReports
38
- ##
39
- # Date class include information of simulation run date.
40
- ##
41
- class Date
42
- attr_accessor :month, :day_of_month, :year #:nodoc:
43
- ##
44
- # Date class intialize all date attributes:
45
- # +:month+ , +:day_of_month+ , +:year+
46
- ##
47
- # [parameters:]
48
- # +hash+ - _Hash_ - A hash which may contain a deserialized date.
49
- ##
50
- def initialize(hash = {})
51
- hash.delete_if { |k, v| v.nil? }
52
- hash = defaults.merge(hash)
53
-
54
- @month = hash[:month].to_i
55
- @day_of_month = hash[:day_of_month].to_i
56
- @year = hash[:year].to_i
57
-
58
- # initialize class variables @@validator and @@schema
59
- @@validator ||= Validator.new
60
- @@schema ||= @@validator.schema
61
- end
62
-
63
- ##
64
- # Converts to a hash equivalent for JSON serialization.
65
- ##
66
- # - Exclude attributes with nil values.
67
- # - Validate date properties against schema.
68
- ##
69
- def to_hash
70
- result = {}
71
- result[:month] = @month if @month
72
- result[:day_of_month] = @day_of_month if @day_of_month
73
- result[:year] = @year if @year
74
-
75
- # validate date hash properties against schema
76
- if @@validator.validate(@@schema[:definitions][:Date][:properties], result).any?
77
- raise "end_uses properties does not match schema: #{@@validator.validate(@@schema[:definitions][:Date][:properties], result)}"
78
- end
79
-
80
- return result
81
- end
82
-
83
- ##
84
- # Assigns default values if values do not exist.
85
- ##
86
- def defaults
87
- hash = {}
88
- hash[:month] = nil
89
- hash[:day_of_month] = nil
90
- hash[:year] = nil
91
-
92
- return hash
93
- end
94
- end
95
- end
96
- end
97
- end
@@ -1,379 +0,0 @@
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 'urbanopt/scenario/default_reports/solar_pv'
33
- require 'urbanopt/scenario/default_reports/wind'
34
- require 'urbanopt/scenario/default_reports/generator'
35
- require 'urbanopt/scenario/default_reports/storage'
36
- require 'json-schema'
37
-
38
- module URBANopt
39
- module Scenario
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::Scenario::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