urbanopt-scenario 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CONTRIBUTING.md +58 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +27 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
  5. data/.github/pull_request_template.md +23 -0
  6. data/.gitignore +1 -0
  7. data/CHANGELOG.md +16 -2
  8. data/Gemfile +1 -0
  9. data/LICENSE.md +1 -1
  10. data/doc_templates/LICENSE.md +1 -1
  11. data/doc_templates/copyright_erb.txt +1 -1
  12. data/doc_templates/copyright_js.txt +1 -1
  13. data/doc_templates/copyright_ruby.txt +1 -1
  14. data/docs/package-lock.json +142 -116
  15. data/docs/package.json +5 -1
  16. data/lib/change_log.rb +147 -0
  17. data/lib/measures/default_feature_reports/measure.rb +16 -5
  18. data/lib/measures/default_feature_reports/tests/default_feature_reports_test.rb +1 -1
  19. data/lib/urbanopt-scenario.rb +1 -1
  20. data/lib/urbanopt/scenario.rb +1 -1
  21. data/lib/urbanopt/scenario/default_reports.rb +1 -1
  22. data/lib/urbanopt/scenario/default_reports/construction_cost.rb +1 -1
  23. data/lib/urbanopt/scenario/default_reports/date.rb +1 -1
  24. data/lib/urbanopt/scenario/default_reports/distributed_generation.rb +187 -0
  25. data/lib/urbanopt/scenario/default_reports/end_use.rb +1 -1
  26. data/lib/urbanopt/scenario/default_reports/end_uses.rb +1 -1
  27. data/lib/urbanopt/scenario/default_reports/feature_report.rb +8 -2
  28. data/lib/urbanopt/scenario/default_reports/generator.rb +92 -0
  29. data/lib/urbanopt/scenario/default_reports/location.rb +2 -2
  30. data/lib/urbanopt/scenario/default_reports/logger.rb +1 -1
  31. data/lib/urbanopt/scenario/default_reports/program.rb +2 -2
  32. data/lib/urbanopt/scenario/default_reports/reporting_period.rb +2 -2
  33. data/lib/urbanopt/scenario/default_reports/scenario_report.rb +36 -12
  34. data/lib/urbanopt/scenario/default_reports/schema/README.md +16 -15
  35. data/lib/urbanopt/scenario/default_reports/schema/scenario_schema.json +88 -0
  36. data/lib/urbanopt/scenario/default_reports/solar_pv.rb +92 -0
  37. data/lib/urbanopt/scenario/default_reports/storage.rb +105 -0
  38. data/lib/urbanopt/scenario/default_reports/timeseries_csv.rb +32 -5
  39. data/lib/urbanopt/scenario/default_reports/validator.rb +2 -2
  40. data/lib/urbanopt/scenario/default_reports/wind.rb +92 -0
  41. data/lib/urbanopt/scenario/extension.rb +1 -1
  42. data/lib/urbanopt/scenario/logger.rb +1 -1
  43. data/lib/urbanopt/scenario/scenario_base.rb +1 -1
  44. data/lib/urbanopt/scenario/scenario_csv.rb +1 -1
  45. data/lib/urbanopt/scenario/scenario_datapoint_base.rb +1 -1
  46. data/lib/urbanopt/scenario/scenario_post_processor_base.rb +1 -1
  47. data/lib/urbanopt/scenario/scenario_post_processor_default.rb +7 -6
  48. data/lib/urbanopt/scenario/scenario_runner_base.rb +1 -1
  49. data/lib/urbanopt/scenario/scenario_runner_osw.rb +1 -1
  50. data/lib/urbanopt/scenario/simulation_dir_base.rb +1 -1
  51. data/lib/urbanopt/scenario/simulation_dir_osw.rb +1 -1
  52. data/lib/urbanopt/scenario/simulation_mapper_base.rb +1 -1
  53. data/lib/urbanopt/scenario/version.rb +2 -2
  54. data/urbanopt-scenario-gem.gemspec +2 -0
  55. metadata +26 -2
@@ -0,0 +1,92 @@
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 'json-schema'
33
+
34
+ module URBANopt
35
+ module Scenario
36
+ module DefaultReports
37
+ ##
38
+ # Onsite generator system attributes
39
+ ##
40
+ class Generator
41
+ ##
42
+ # _Float_ - power capacity in kilowatts
43
+ #
44
+ attr_accessor :size_kw
45
+
46
+ ##
47
+ # Intialize Generator attributes from a hash. Generator attributes currently are limited to power capacity.
48
+ ##
49
+ # [parameters:]
50
+ #
51
+ # * +hash+ - _Hash_ - A hash containting a +:size_kw+ key/value pair which represents the nameplate capacity in kilowatts (kW)
52
+ #
53
+ def initialize(hash = {})
54
+ hash.delete_if { |k, v| v.nil? }
55
+
56
+ @size_kw = hash[:size_kw]
57
+
58
+ # initialize class variables @@validator and @@schema
59
+ @@validator ||= Validator.new
60
+ @@schema ||= @@validator.schema
61
+
62
+ # initialize @@logger
63
+ @@logger ||= URBANopt::Scenario::DefaultReports.logger
64
+ end
65
+
66
+ ##
67
+ # Convert to a Hash equivalent for JSON serialization
68
+ ##
69
+ def to_hash
70
+ result = {}
71
+
72
+ result[:size_kw] = @size_kw if @size_kw
73
+
74
+ return result
75
+ end
76
+
77
+ ##
78
+ # Merge Generator systems
79
+ ##
80
+ def self.add_generator(existing_generator, new_generator)
81
+ if existing_generator.size_kw.nil? && new_generator.size_kw.nil?
82
+ existing_generator.size_kw = nil
83
+ else
84
+ existing_generator.size_kw = (existing_generator.size_kw || 0) + (new_generator.size_kw || 0)
85
+ end
86
+
87
+ return existing_generator
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -41,7 +41,7 @@ module URBANopt
41
41
  class Location
42
42
  attr_accessor :latitude, :longitude, :surface_elevation, :weather_filename #:nodoc:
43
43
  ##
44
- # Location class intialize location attributes: +:latitude+ , +:longitude+ , +:surface_elevation+ , +:weather_filename+
44
+ # Location class initialize location attributes: +:latitude+ , +:longitude+ , +:surface_elevation+ , +:weather_filename+
45
45
  ##
46
46
  # [parameters:]
47
47
  # +hash+ - _Hash_ - A hash which may contain a deserialized location.
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -45,7 +45,7 @@ module URBANopt
45
45
  :maximum_number_of_parking_stories_above_ground, :number_of_residential_units, :building_types, :building_type, :maximum_occupancy,
46
46
  :area, :window_area, :north_window_area, :south_window_area, :east_window_area, :west_window_area, :wall_area, :roof_area, :equipment_roof_area,
47
47
  :photovoltaic_roof_area, :available_roof_area, :total_roof_area, :orientation, :aspect_ratio # :nodoc:
48
- # Program class intialize building program attributes: +:site_area+ , +:floor_area+ , +:conditioned_area+ , +:unconditioned_area+ ,
48
+ # Program class initialize building program attributes: +:site_area+ , +:floor_area+ , +:conditioned_area+ , +:unconditioned_area+ ,
49
49
  # +:footprint_area+ , +:maximum_roof_height, +:maximum_number_of_stories+ , +:maximum_number_of_stories_above_ground+ , +:parking_area+ ,
50
50
  # +:number_of_parking_spaces+ , +:number_of_parking_spaces_charging+ , +:parking_footprint_area+ , +:maximum_parking_height+ , +:maximum_number_of_parking_stories+ ,
51
51
  # +:maximum_number_of_parking_stories_above_ground+ , +:number_of_residential_units+ , +:building_types+ , +:building_type+ , +:maximum_occupancy+ ,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -47,7 +47,7 @@ module URBANopt
47
47
  :district_heating, :water, :electricity_produced, :end_uses, :energy_production, :photovoltaic, :utility_costs,
48
48
  :fuel_type, :total_cost, :usage_cost, :demand_cost, :comfort_result, :time_setpoint_not_met_during_occupied_cooling,
49
49
  :time_setpoint_not_met_during_occupied_heating, :time_setpoint_not_met_during_occupied_hours #:nodoc:
50
- # ReportingPeriod class intializes the reporting period attributes:
50
+ # ReportingPeriod class initializes the reporting period attributes:
51
51
  # +:id+ , +:name+ , +:multiplier+ , +:start_date+ , +:end_date+ , +:month+ , +:day_of_month+ , +:year+ , +:total_site_energy+ , +:total_source_energy+ ,
52
52
  # +:net_site_energy+ , +:net_source_energy+ , +:net_utility_cost+ , +:electricity+ , +:natural_gas+ , +:additional_fuel+ , +:district_cooling+ ,
53
53
  # +:district_heating+ , +:water+ , +:electricity_produced+ , +:end_uses+ , +:energy_production+ , +:photovoltaic+ , +:utility_costs+ ,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -34,6 +34,7 @@ require 'urbanopt/scenario/default_reports/logger'
34
34
  require 'urbanopt/scenario/default_reports/program'
35
35
  require 'urbanopt/scenario/default_reports/reporting_period'
36
36
  require 'urbanopt/scenario/default_reports/timeseries_csv'
37
+ require 'urbanopt/scenario/default_reports/distributed_generation'
37
38
  require 'urbanopt/scenario/default_reports/validator'
38
39
  require 'json-schema'
39
40
 
@@ -51,7 +52,7 @@ module URBANopt
51
52
  class ScenarioReport
52
53
  attr_accessor :id, :name, :directory_name, :timesteps_per_hour, :number_of_not_started_simulations,
53
54
  :number_of_started_simulations, :number_of_complete_simulations, :number_of_failed_simulations,
54
- :timeseries_csv, :location, :program, :construction_costs, :reporting_periods, :feature_reports # :nodoc:
55
+ :timeseries_csv, :location, :program, :construction_costs, :reporting_periods, :feature_reports, :distributed_generation # :nodoc:
55
56
  # ScenarioReport class intializes the scenario report attributes:
56
57
  # +:id+ , +:name+ , +:directory_name+, +:timesteps_per_hour+ , +:number_of_not_started_simulations+ ,
57
58
  # +:number_of_started_simulations+ , +:number_of_complete_simulations+ , +:number_of_failed_simulations+ ,
@@ -88,12 +89,14 @@ module URBANopt
88
89
  @reporting_periods << ReportingPeriod.new(rp)
89
90
  end
90
91
 
91
- # intialized here to be used in the add_feature_report method
92
+ # feature_report is intialized here to be used in the add_feature_report method
92
93
  @feature_reports = []
93
94
  hash[:feature_reports].each do |fr|
94
95
  @feature_reports << FeatureReport.new(fr)
95
96
  end
96
97
 
98
+ @distributed_generation = DistributedGeneration.new(hash[:distributed_generation] || {})
99
+ @file_name = 'default_scenario_report'
97
100
  # initialize class variables @@validator and @@schema
98
101
  @@validator ||= Validator.new
99
102
  @@schema ||= @@validator.schema
@@ -128,20 +131,34 @@ module URBANopt
128
131
  # Gets the saved JSON file path.
129
132
  ##
130
133
  def json_path
131
- File.join(@directory_name, 'default_scenario_report.json')
134
+ File.join(@directory_name, @file_name + '.json')
132
135
  end
133
136
 
134
137
  ##
135
138
  # Gets the saved CSV file path.
136
139
  ##
137
140
  def csv_path
138
- File.join(@directory_name, 'default_scenario_report.csv')
141
+ File.join(@directory_name, @file_name + '.csv')
139
142
  end
140
143
 
141
144
  ##
142
145
  # Saves the 'default_feature_report.json' and 'default_scenario_report.csv' files
143
146
  ##
144
- def save
147
+ # [parameters]:
148
+ # +file_name+ - _String_ - Assign a name to the saved scenario results file
149
+ def save(file_name = 'default_scenario_report')
150
+ # reassign the initialize local variable @file_name to the file name input.
151
+ @file_name = file_name
152
+
153
+ # save the csv data
154
+ old_timeseries_path = nil
155
+ if !@timeseries_csv.path.nil?
156
+ old_timeseries_path = @timeseries_csv.path
157
+ end
158
+
159
+ @timeseries_csv.path = File.join(@directory_name, file_name + '.csv')
160
+ @timeseries_csv.save_data
161
+
145
162
  hash = {}
146
163
  hash[:scenario_report] = to_hash
147
164
  hash[:feature_reports] = []
@@ -149,9 +166,11 @@ module URBANopt
149
166
  hash[:feature_reports] << feature_report.to_hash
150
167
  end
151
168
 
152
- File.open(json_path, 'w') do |f|
169
+ json_name_path = File.join(@directory_name, file_name + '.json')
170
+
171
+ File.open(json_name_path, 'w') do |f|
153
172
  f.puts JSON.pretty_generate(hash)
154
- # make sure data is written to the disk one way or the other #:nodoc:
173
+ # make sure data is written to the disk one way or the other
155
174
  begin
156
175
  f.fsync
157
176
  rescue StandardError
@@ -159,9 +178,11 @@ module URBANopt
159
178
  end
160
179
  end
161
180
 
162
- # save the csv data #:nodoc:
163
- timeseries_csv.save_data(csv_path)
164
-
181
+ if !old_timeseries_path.nil?
182
+ @timeseries_csv.path = old_timeseries_path
183
+ else
184
+ @timeseries_csv.path = File.join(@directory_name, 'default_scenario_report.csv')
185
+ end
165
186
  return true
166
187
  end
167
188
 
@@ -184,6 +205,7 @@ module URBANopt
184
205
  result[:timeseries_csv] = @timeseries_csv.to_hash if @timeseries_csv
185
206
  result[:location] = @location.to_hash if @location
186
207
  result[:program] = @program.to_hash if @program
208
+ result[:distributed_generation] = @distributed_generation.to_hash if @distributed_generation
187
209
 
188
210
  result[:construction_costs] = []
189
211
  @construction_costs.each { |cc| result[:construction_costs] << cc.to_hash } if @construction_costs
@@ -264,7 +286,9 @@ module URBANopt
264
286
  # merge reporting_periods information
265
287
  @reporting_periods = ReportingPeriod.merge_reporting_periods(@reporting_periods, feature_report.reporting_periods)
266
288
 
267
- # add the array of feature_reports
289
+ @distributed_generation = DistributedGeneration.merge_distributed_generation(@distributed_generation, feature_report.distributed_generation)
290
+
291
+ # add feature_report
268
292
  @feature_reports << feature_report
269
293
 
270
294
  # scenario report location takes the location of the first feature in the list
@@ -16,18 +16,19 @@ The URBANopt Scenario Gem includes functionality for defining scenarios, running
16
16
 
17
17
  **CSV Output Units**
18
18
 
19
- | output | unit |
20
- | ----------------------------------- | ------- |
21
- | Electricity:Facility | kbtu |
22
- | ElectricityProduced:Facility | kbtu |
23
- | Gas:Facility | kbtu |
24
- | DistrictCooling:Facility | kbtu |
25
- | DistrictHeating:Facility | kbtu |
26
- | District Cooling Chilled Water Rate | GPM |
27
- | District Cooling Mass Flow Rate | lbs/min |
28
- | District Cooling Inlet Temperature | &deg;F |
29
- | District Cooling Outlet Temperature | &deg;F |
30
- | District Heating Hot Water Rate | GPM |
31
- | District Heating Mass Flow Rate | lbs/min |
32
- | District Heating Inlet Temperature | &deg;F |
33
- | District Heating Outlet Temperature | &deg;F |
19
+ | output | unit |
20
+ | -----------------------------------------| ------- |
21
+ | Electricity:Facility | kbtu |
22
+ | ElectricityProduced:Facility | kbtu |
23
+ | Gas:Facility | kbtu |
24
+ | DistrictCooling:Facility | kbtu |
25
+ | DistrictHeating:Facility | kbtu |
26
+ | District Cooling Chilled Water Rate | GPM |
27
+ | District Cooling Mass Flow Rate | lbs/min |
28
+ | District Cooling Inlet Temperature | &deg;F |
29
+ | District Cooling Outlet Temperature | &deg;F |
30
+ | District Heating Hot Water Rate | GPM |
31
+ | District Heating Mass Flow Rate | lbs/min |
32
+ | District Heating Inlet Temperature | &deg;F |
33
+ | District Heating Outlet Temperature | &deg;F |
34
+ | Electricity:Grid:ToLoad | kWh. |
@@ -60,7 +60,11 @@
60
60
  },
61
61
  "reporting_periods": {
62
62
  "$ref": "#/definitions/ReportingPeriods"
63
+ },
64
+ "distributed_generation": {
65
+ "$ref": "#/definitions/DistributedGeneration"
63
66
  }
67
+
64
68
  },
65
69
  "required": [
66
70
  "id",
@@ -75,6 +79,87 @@
75
79
  ],
76
80
  "additionalProperties": false
77
81
  },
82
+ "DistributedGeneration": {
83
+ "type": "object",
84
+ "properties": {
85
+ "lcc_us_dollars": {
86
+ "type": "number",
87
+ "description": "Optimal lifecycle cost"
88
+ },
89
+ "npv_us_dollars": {
90
+ "type": "number",
91
+ "description": "Net present value of savings realized by the project"
92
+ },
93
+ "year_one_energy_cost_us_dollars": {
94
+ "type": "number",
95
+ "description": "Optimal year one utility energy cost"
96
+ },
97
+ "year_one_demand_cost_us_dollars": {
98
+ "type": "number",
99
+ "description": "Optimal year one utility demand cost"
100
+ },
101
+ "year_one_bill_us_dollars": {
102
+ "type": "number",
103
+ "description": "Optimal year one utility bill"
104
+ },
105
+ "total_energy_cost_us_dollars": {
106
+ "type": "number",
107
+ "description": "Total utility energy cost over the lifecycle, after-tax"
108
+ },
109
+ "SolarPV" : {
110
+ "$ref": "#/definitions/SolarPV"
111
+ },
112
+ "Wind" : {
113
+ "$ref": "#/definitions/Wind"
114
+ },
115
+ "Generator" : {
116
+ "$ref": "#/definitions/Generator"
117
+ },
118
+ "Storage" : {
119
+ "$ref": "#/definitions/Storage"
120
+ }
121
+ }
122
+ },
123
+ "SolarPV": {
124
+ "type": "object",
125
+ "properties": {
126
+ "size_kw": {
127
+ "description": "rated power in kW",
128
+ "type": "string"
129
+ }
130
+ }
131
+ },
132
+ "Wind": {
133
+ "type": "object",
134
+ "properties": {
135
+ "size_kw": {
136
+ "description": "rated power in kW",
137
+ "type": "string"
138
+ }
139
+ }
140
+ },
141
+ "Generator": {
142
+ "type": "object",
143
+ "properties": {
144
+ "size_kw": {
145
+ "description": "rated power in kW",
146
+ "type": "string"
147
+ }
148
+ }
149
+ },
150
+ "Storage": {
151
+ "type": "object",
152
+ "properties": {
153
+ "size_kw": {
154
+ "description": "rated power in kW",
155
+ "type": "string"
156
+ },
157
+ "size_kw": {
158
+ "description": "rated capacity in kWh",
159
+ "type": "string"
160
+ }
161
+ }
162
+ },
78
163
  "FeatureReport": {
79
164
  "type": "object",
80
165
  "properties": {
@@ -126,6 +211,9 @@
126
211
  },
127
212
  "reporting_periods": {
128
213
  "$ref": "#/definitions/ReportingPeriods"
214
+ },
215
+ "distributed_generation": {
216
+ "$ref": "#/definitions/DistributedGeneration"
129
217
  }
130
218
  },
131
219
  "required": [
@@ -0,0 +1,92 @@
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 'json-schema'
33
+
34
+ module URBANopt
35
+ module Scenario
36
+ module DefaultReports
37
+ ##
38
+ # Onsite solar PV system attributes
39
+ ##
40
+ class SolarPV
41
+ ##
42
+ # _Float_ - power capacity in kilowatts
43
+ #
44
+ attr_accessor :size_kw
45
+
46
+ ##
47
+ # Initialize SolarPV attributes from a hash. Solar PV attributes currently are limited to power capacity.
48
+ ##
49
+ # [parameters:]
50
+ #
51
+ # * +hash+ - _Hash_ - A hash containting a +:size_kw+ key/value pair which represents the nameplate capacity in kilowatts (kW)
52
+ #
53
+ def initialize(hash = {})
54
+ hash.delete_if { |k, v| v.nil? }
55
+
56
+ @size_kw = hash[:size_kw]
57
+
58
+ # initialize class variables @@validator and @@schema
59
+ @@validator ||= Validator.new
60
+ @@schema ||= @@validator.schema
61
+
62
+ # initialize @@logger
63
+ @@logger ||= URBANopt::Scenario::DefaultReports.logger
64
+ end
65
+
66
+ ##
67
+ # Convert to a Hash equivalent for JSON serialization
68
+ ##
69
+ def to_hash
70
+ result = {}
71
+
72
+ result[:size_kw] = @size_kw if @size_kw
73
+
74
+ return result
75
+ end
76
+
77
+ ##
78
+ # Merge PV systems
79
+ ##
80
+ def self.add_pv(existing_pv, new_pv)
81
+ if existing_pv.size_kw.nil? && new_pv.size_kw.nil?
82
+ existing_pv.size_kw = nil
83
+ else
84
+ existing_pv.size_kw = (existing_pv.size_kw || 0) + (new_pv.size_kw || 0)
85
+ end
86
+
87
+ return existing_pv
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end