urbanopt-scenario 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  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 +26 -0
  7. data/.rdoc_options +36 -0
  8. data/.rspec +3 -0
  9. data/.rubocop.yml +10 -0
  10. data/.travis.yml +23 -0
  11. data/CHANGELOG.md +19 -0
  12. data/Gemfile +43 -0
  13. data/Jenkinsfile +10 -0
  14. data/LICENSE.md +27 -0
  15. data/RDOC_MAIN.md +39 -0
  16. data/README.md +39 -0
  17. data/Rakefile +51 -0
  18. data/deploy_docs.sh +5 -0
  19. data/doc_templates/LICENSE.md +27 -0
  20. data/doc_templates/README.md.erb +42 -0
  21. data/doc_templates/copyright_erb.txt +31 -0
  22. data/doc_templates/copyright_js.txt +4 -0
  23. data/doc_templates/copyright_ruby.txt +29 -0
  24. data/docs/.gitignore +3 -0
  25. data/docs/.vuepress/components/InnerJsonSchema.vue +84 -0
  26. data/docs/.vuepress/components/JsonSchema.vue +12 -0
  27. data/docs/.vuepress/components/ScenarioSchema.vue +12 -0
  28. data/docs/.vuepress/components/StaticLink.vue +8 -0
  29. data/docs/.vuepress/config.js +15 -0
  30. data/docs/.vuepress/highlight.js +8 -0
  31. data/docs/.vuepress/public/custom_rdoc_styles.css +74 -0
  32. data/docs/.vuepress/utils.js +17 -0
  33. data/docs/README.md +39 -0
  34. data/docs/package-lock.json +11817 -0
  35. data/docs/package.json +26 -0
  36. data/docs/schemas/scenario-schema.md +3 -0
  37. data/lib/change_log.rb +147 -0
  38. data/lib/measures/.rubocop.yml +5 -0
  39. data/lib/measures/default_feature_reports/LICENSE.md +27 -0
  40. data/lib/measures/default_feature_reports/README.md +56 -0
  41. data/lib/measures/default_feature_reports/README.md.erb +42 -0
  42. data/lib/measures/default_feature_reports/measure.rb +742 -0
  43. data/lib/measures/default_feature_reports/measure.xml +139 -0
  44. data/lib/measures/default_feature_reports/tests/USA_CO_Golden-NREL.724666_TMY3.epw +8768 -0
  45. data/lib/measures/default_feature_reports/tests/default_feature_reports_test.rb +238 -0
  46. data/lib/measures/default_feature_reports/tests/example_model.osm +4378 -0
  47. data/lib/urbanopt-scenario.rb +31 -0
  48. data/lib/urbanopt/scenario.rb +45 -0
  49. data/lib/urbanopt/scenario/default_reports.rb +40 -0
  50. data/lib/urbanopt/scenario/default_reports/construction_cost.rb +169 -0
  51. data/lib/urbanopt/scenario/default_reports/date.rb +97 -0
  52. data/lib/urbanopt/scenario/default_reports/distributed_generation.rb +187 -0
  53. data/lib/urbanopt/scenario/default_reports/end_use.rb +159 -0
  54. data/lib/urbanopt/scenario/default_reports/end_uses.rb +140 -0
  55. data/lib/urbanopt/scenario/default_reports/feature_report.rb +213 -0
  56. data/lib/urbanopt/scenario/default_reports/generator.rb +92 -0
  57. data/lib/urbanopt/scenario/default_reports/location.rb +99 -0
  58. data/lib/urbanopt/scenario/default_reports/logger.rb +44 -0
  59. data/lib/urbanopt/scenario/default_reports/program.rb +261 -0
  60. data/lib/urbanopt/scenario/default_reports/reporting_period.rb +298 -0
  61. data/lib/urbanopt/scenario/default_reports/scenario_report.rb +300 -0
  62. data/lib/urbanopt/scenario/default_reports/schema/README.md +34 -0
  63. data/lib/urbanopt/scenario/default_reports/schema/scenario_csv_columns.txt +13 -0
  64. data/lib/urbanopt/scenario/default_reports/schema/scenario_schema.json +830 -0
  65. data/lib/urbanopt/scenario/default_reports/solar_pv.rb +92 -0
  66. data/lib/urbanopt/scenario/default_reports/storage.rb +105 -0
  67. data/lib/urbanopt/scenario/default_reports/timeseries_csv.rb +258 -0
  68. data/lib/urbanopt/scenario/default_reports/validator.rb +97 -0
  69. data/lib/urbanopt/scenario/default_reports/wind.rb +92 -0
  70. data/lib/urbanopt/scenario/extension.rb +63 -0
  71. data/lib/urbanopt/scenario/logger.rb +42 -0
  72. data/lib/urbanopt/scenario/scenario_base.rb +79 -0
  73. data/lib/urbanopt/scenario/scenario_csv.rb +122 -0
  74. data/lib/urbanopt/scenario/scenario_datapoint_base.rb +162 -0
  75. data/lib/urbanopt/scenario/scenario_post_processor_base.rb +69 -0
  76. data/lib/urbanopt/scenario/scenario_post_processor_default.rb +98 -0
  77. data/lib/urbanopt/scenario/scenario_runner_base.rb +63 -0
  78. data/lib/urbanopt/scenario/scenario_runner_osw.rb +158 -0
  79. data/lib/urbanopt/scenario/simulation_dir_base.rb +90 -0
  80. data/lib/urbanopt/scenario/simulation_dir_osw.rb +261 -0
  81. data/lib/urbanopt/scenario/simulation_mapper_base.rb +47 -0
  82. data/lib/urbanopt/scenario/version.rb +35 -0
  83. data/urbanopt-scenario-gem.gemspec +38 -0
  84. metadata +251 -0
@@ -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 'urbanopt/scenario/default_reports/validator'
32
+ require 'json-schema'
33
+
34
+ module URBANopt
35
+ module Scenario
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
@@ -0,0 +1,140 @@
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/end_use'
32
+ require 'urbanopt/scenario/default_reports/validator'
33
+ require 'json-schema'
34
+
35
+ module URBANopt
36
+ module Scenario
37
+ module DefaultReports
38
+ ##
39
+ # Enduses class inlclude results for each fuel type.
40
+ ##
41
+ class EndUses
42
+ attr_accessor :electricity, :natural_gas, :additional_fuel, :district_cooling, :district_heating, :water # :nodoc:
43
+ ##
44
+ # EndUses class intialize end_uses(fuel type) attributes: +:electricity+ , +:natural_gas+ , +:additional_fuel+ ,
45
+ # +:district_cooling+ , +:district_heating+ , +:water+
46
+ ##
47
+ # [parameters:]
48
+ # +hash+ - _Hash_ - A hash which may contain a deserialized end_uses.
49
+ ##
50
+ def initialize(hash = {})
51
+ hash.delete_if { |k, v| v.nil? }
52
+ hash = defaults.merge(hash)
53
+
54
+ @electricity = EndUse.new(hash[:electricity])
55
+ @natural_gas = EndUse.new(hash[:natural_gas])
56
+ @additional_fuel = EndUse.new(hash[:additional_fuel])
57
+ @district_cooling = EndUse.new(hash[:district_cooling])
58
+ @district_heating = EndUse.new(hash[:district_heating])
59
+ @water = EndUse.new(hash[:water])
60
+
61
+ # initialize class variables @@validator and @@schema
62
+ @@validator ||= Validator.new
63
+ @@schema ||= @@validator.schema
64
+ end
65
+
66
+ ##
67
+ # Converts to a Hash equivalent for JSON serialization.
68
+ ##
69
+ # - Exclude attributes with nil values.
70
+ # - Validate end_uses hash properties against schema.
71
+ ##
72
+ def to_hash
73
+ result = {}
74
+
75
+ electricity_hash = @electricity.to_hash if @electricity.to_hash
76
+ electricity_hash.delete_if { |k, v| v.nil? }
77
+ result[:electricity] = electricity_hash if @electricity
78
+
79
+ natural_gas_hash = @natural_gas.to_hash if @natural_gas
80
+ natural_gas_hash.delete_if { |k, v| v.nil? }
81
+ result[:natural_gas] = natural_gas_hash if @natural_gas
82
+
83
+ additional_fuel_hash = @additional_fuel.to_hash if @additional_fuel
84
+ additional_fuel_hash.delete_if { |k, v| v.nil? }
85
+ result[:additional_fuel] = additional_fuel_hash if @additional_fuel
86
+
87
+ district_cooling_hash = @district_cooling.to_hash if @district_cooling
88
+ district_cooling_hash.delete_if { |k, v| v.nil? }
89
+ result[:district_cooling] = district_cooling_hash if @district_cooling
90
+
91
+ district_heating_hash = @district_heating.to_hash if @district_heating
92
+ district_heating_hash.delete_if { |k, v| v.nil? }
93
+ result[:district_heating] = district_heating_hash if @district_heating
94
+
95
+ water_hash = @water.to_hash if @water
96
+ water_hash.delete_if { |k, v| v.nil? }
97
+ result[:water] = water_hash if @water
98
+
99
+ # validate end_uses properties against schema
100
+ if @@validator.validate(@@schema[:definitions][:EndUses][:properties], result).any?
101
+ raise "end_uses properties does not match schema: #{@@validator.validate(@@schema[:definitions][:EndUses][:properties], result)}"
102
+ end
103
+
104
+ return result
105
+ end
106
+
107
+ ##
108
+ # Assigns default values if values do not exist.
109
+ ##
110
+ def defaults
111
+ hash = {}
112
+ hash[:electricity] = EndUse.new.to_hash
113
+ hash[:natural_gas] = EndUse.new.to_hash
114
+ hash[:additional_fuel] = EndUse.new.to_hash
115
+ hash[:district_cooling] = EndUse.new.to_hash
116
+ hash[:district_heating] = EndUse.new.to_hash
117
+ hash[:water] = EndUse.new.to_hash
118
+
119
+ return hash
120
+ end
121
+
122
+ ##
123
+ # Aggregates the values of each EndUse attribute.
124
+ ##
125
+ # [Parameters:]
126
+ # +new_end_uses+ - _EndUses_ - An object of EndUses class.
127
+ ##
128
+ def merge_end_uses!(new_end_uses)
129
+ # modify the existing_period by summing up the results ; # sum results only if they exist
130
+ @electricity.merge_end_use!(new_end_uses.electricity)
131
+ @natural_gas.merge_end_use!(new_end_uses.natural_gas)
132
+ @additional_fuel.merge_end_use!(new_end_uses.additional_fuel)
133
+ @district_cooling.merge_end_use!(new_end_uses.district_cooling)
134
+ @district_heating.merge_end_use!(new_end_uses.district_heating)
135
+ return self
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,213 @@
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/construction_cost'
32
+ require 'urbanopt/scenario/default_reports/program'
33
+ require 'urbanopt/scenario/default_reports/location'
34
+ require 'urbanopt/scenario/default_reports/reporting_period'
35
+ require 'urbanopt/scenario/default_reports/timeseries_csv'
36
+ require 'urbanopt/scenario/default_reports/validator'
37
+ require 'urbanopt/scenario/default_reports/distributed_generation'
38
+
39
+ require 'json-schema'
40
+
41
+ require 'json'
42
+
43
+ module URBANopt
44
+ module Scenario
45
+ module DefaultReports
46
+ ##
47
+ # FeatureReport generates two types of reports in a simulation_dir.
48
+ # The default_feature_reports measure writes a 'default_feature_reports.json' file containing
49
+ # information on all features in the simulation. It also writes a 'default_feature_reports.csv'
50
+ # containing timeseries data for all features in the simulation.
51
+ # The DefaultPostProcessor reads these feature reports and aggregates them to create a ScenarioReport.
52
+ ##
53
+ class FeatureReport
54
+ attr_accessor :id, :name, :directory_name, :feature_type, :timesteps_per_hour, :simulation_status,
55
+ :timeseries_csv, :location, :program, :design_parameters, :construction_costs, :reporting_periods, :distributed_generation # :nodoc:
56
+ ##
57
+ # Each FeatureReport object corresponds to a single Feature.
58
+ ##
59
+ # [parameters:]
60
+ # +hash+ - _Hash_ - A hash which may contain a deserialized feature_report.
61
+ ##
62
+ def initialize(hash = {})
63
+ hash.delete_if { |k, v| v.nil? }
64
+ hash = defaults.merge(hash)
65
+
66
+ @id = hash[:id]
67
+ @name = hash[:name]
68
+ @directory_name = hash[:directory_name]
69
+ @feature_type = hash[:feature_type]
70
+ @timesteps_per_hour = hash[:timesteps_per_hour]
71
+ @simulation_status = hash[:simulation_status]
72
+ @timeseries_csv = TimeseriesCSV.new(hash[:timeseries_csv])
73
+ @timeseries_csv.run_dir_name(@directory_name)
74
+ @location = Location.new(hash[:location])
75
+ @program = Program.new(hash[:program])
76
+ # design_parameters to add later
77
+ @construction_costs = []
78
+ hash[:construction_costs].each do |cc|
79
+ @constructiion_costs << ConstructionCost.new(cc)
80
+ end
81
+
82
+ @reporting_periods = []
83
+ hash[:reporting_periods].each do |rp|
84
+ @reporting_periods << ReportingPeriod.new(rp)
85
+ end
86
+
87
+ @distributed_generation = DistributedGeneration.new(hash[:distributed_generation] || {})
88
+
89
+ # initialize class variables @@validator and @@schema
90
+ @@validator ||= Validator.new
91
+ @@schema ||= @@validator.schema
92
+ end
93
+
94
+ ##
95
+ # Assign default values if values does not exist.
96
+ ##
97
+ def defaults
98
+ hash = {}
99
+ hash[:timeseries_csv] = {}
100
+ hash[:location] = {}
101
+ hash[:program] = {}
102
+ hash[:construction_costs] = []
103
+ hash[:reporting_periods] = []
104
+ return hash
105
+ end
106
+
107
+ ##
108
+ # Return an Array of FeatureReports for the simulation_dir as multiple Features can be simulated together in a single simulation directory.
109
+ ##
110
+ # - Ensure that +simulation_dir+ include only one feature.
111
+ # - Read in the reports written by measure if they exist.
112
+ ##
113
+ # [parameters:]
114
+ # +simulation_dir+ - _SimulationDirOSW_ - A simulation directory from an OSW simulation, must include 'default_feature_reports' measure.
115
+ ##
116
+ def self.from_simulation_dir(simulation_dir)
117
+ result = []
118
+
119
+ # simulation dir can include only one feature
120
+ features = simulation_dir.features
121
+ if features.size != 1
122
+ raise 'FeatureReport cannot support multiple features per OSW'
123
+ end
124
+
125
+ # read in the reports written by measure
126
+ default_feature_reports_json = nil
127
+ default_feature_reports_csv = nil
128
+
129
+ simulation_status = simulation_dir.simulation_status
130
+ if simulation_status == 'Complete' || simulation_status == 'Failed'
131
+
132
+ # read in the scenario reports JSON and CSV
133
+ Dir.glob(File.join(simulation_dir.run_dir, '*_default_feature_reports/')).each do |dir|
134
+ scenario_reports_json_path = File.join(dir, 'default_feature_reports.json')
135
+ if File.exist?(scenario_reports_json_path)
136
+ File.open(scenario_reports_json_path, 'r') do |file|
137
+ default_feature_reports_json = JSON.parse(file.read, symbolize_names: true)
138
+ end
139
+ end
140
+ scenario_reports_csv_path = File.join(dir, 'default_feature_reports.csv')
141
+ if File.exist?(scenario_reports_csv_path)
142
+ default_feature_reports_csv = scenario_reports_csv_path
143
+ end
144
+ end
145
+
146
+ end
147
+
148
+ # if we loaded the json
149
+ if default_feature_reports_json # && default_feature_reports_json[:feature_reports]
150
+ # default_feature_reports_json.each do |feature_report|
151
+ # result << FeatureReport.new(feature_report)
152
+ # end
153
+ result << FeatureReport.new(default_feature_reports_json) # should we keep it as an array !? or each each report can only include 1 feature
154
+
155
+ else
156
+ # we did not find a report
157
+ features.each do |feature|
158
+ hash = {}
159
+ hash[:id] = feature.id
160
+ hash[:name] = feature.name
161
+ hash[:directory_name] = simulation_dir.run_dir
162
+ hash[:simulation_status] = simulation_status
163
+ result << FeatureReport.new(hash)
164
+ end
165
+ end
166
+
167
+ # validate feature_report json against schema
168
+ if @@validator.validate(@@schema[:definitions][:FeatureReport][:properties], default_feature_reports_json).any?
169
+ raise "default_feature_report_json properties does not match schema: #{@@validator.validate(@@schema[:definitions][:FeatureReport][:properties], default_feature_reports_json)}"
170
+ end
171
+
172
+ return result
173
+ end
174
+
175
+ ##
176
+ # Convert to a Hash equivalent for JSON serialization
177
+ ##
178
+ # - Exclude attributes with nil values.
179
+ # - Validate feature_report hash properties against schema.
180
+ ##
181
+ def to_hash
182
+ result = {}
183
+ result[:id] = @id if @id
184
+ result[:name] = @name if @name
185
+ result[:directory_name] = @directory_name if @directory_name
186
+ result[:feature_type] = @feature_type if @feature_type
187
+ result[:timesteps_per_hour] = @timesteps_per_hour if @timesteps_per_hour
188
+ result[:simulation_status] = @simulation_status if @simulation_status
189
+ result[:timeseries_csv] = @timeseries_csv.to_hash
190
+
191
+ result[:location] = @location.to_hash if @location
192
+
193
+ result[:program] = @program.to_hash
194
+
195
+ result[:construction_costs] = []
196
+ @construction_costs.each { |cc| result[:construction_costs] << cc.to_hash }
197
+
198
+ result[:reporting_periods] = []
199
+ @reporting_periods.each { |rp| result[:reporting_periods] << rp.to_hash }
200
+
201
+ result[:distributed_generation] = @distributed_generation.to_hash if @distributed_generation
202
+
203
+ # validate feature_report properties against schema
204
+ if @@validator.validate(@@schema[:definitions][:FeatureReport][:properties], result).any?
205
+ raise "feature_report properties does not match schema: #{@@validator.validate(@@schema[:definitions][:FeatureReport][:properties], result)}"
206
+ end
207
+
208
+ return result
209
+ end
210
+ end
211
+ end
212
+ end
213
+ end