urbanopt-reporting 0.6.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/nightly_ci_build.yml +54 -0
  3. data/CHANGELOG.md +16 -0
  4. data/Gemfile +10 -5
  5. data/LICENSE.md +16 -11
  6. data/README.md +1 -0
  7. data/Rakefile +2 -37
  8. data/building_loads.csv +52561 -0
  9. data/doc_templates/LICENSE.md +16 -11
  10. data/doc_templates/copyright_erb.txt +22 -16
  11. data/doc_templates/copyright_js.txt +2 -2
  12. data/doc_templates/copyright_ruby.txt +2 -37
  13. data/lib/measures/.rubocop.yml +1 -2
  14. data/lib/measures/default_feature_reports/LICENSE.md +23 -18
  15. data/lib/measures/default_feature_reports/measure.rb +110 -61
  16. data/lib/measures/default_feature_reports/measure.xml +40 -45
  17. data/lib/measures/export_modelica_loads/LICENSE.md +23 -18
  18. data/lib/measures/export_modelica_loads/measure.rb +19 -54
  19. data/lib/measures/export_modelica_loads/measure.xml +31 -31
  20. data/lib/measures/export_time_series_modelica/LICENSE.md +23 -18
  21. data/lib/measures/export_time_series_modelica/measure.rb +2 -37
  22. data/lib/measures/export_time_series_modelica/measure.xml +48 -42
  23. data/lib/measures/export_time_series_modelica/resources/os_lib_helper_methods.rb +2 -37
  24. data/lib/urbanopt/reporting/default_reports/construction_cost.rb +2 -37
  25. data/lib/urbanopt/reporting/default_reports/date.rb +2 -37
  26. data/lib/urbanopt/reporting/default_reports/distributed_generation.rb +3 -38
  27. data/lib/urbanopt/reporting/default_reports/end_use.rb +2 -37
  28. data/lib/urbanopt/reporting/default_reports/end_uses.rb +2 -37
  29. data/lib/urbanopt/reporting/default_reports/extension.rb +2 -37
  30. data/lib/urbanopt/reporting/default_reports/feature_report.rb +7 -38
  31. data/lib/urbanopt/reporting/default_reports/generator.rb +2 -37
  32. data/lib/urbanopt/reporting/default_reports/location.rb +2 -37
  33. data/lib/urbanopt/reporting/default_reports/logger.rb +4 -37
  34. data/lib/urbanopt/reporting/default_reports/power_distribution.rb +2 -37
  35. data/lib/urbanopt/reporting/default_reports/program.rb +2 -37
  36. data/lib/urbanopt/reporting/default_reports/qaqc_flags.rb +147 -0
  37. data/lib/urbanopt/reporting/default_reports/reporting_period.rb +6 -41
  38. data/lib/urbanopt/reporting/default_reports/scenario_power_distribution.rb +2 -37
  39. data/lib/urbanopt/reporting/default_reports/scenario_power_distribution_cost.rb +177 -0
  40. data/lib/urbanopt/reporting/default_reports/scenario_report.rb +36 -52
  41. data/lib/urbanopt/reporting/default_reports/schema/scenario_schema.json +372 -31
  42. data/lib/urbanopt/reporting/default_reports/solar_pv.rb +2 -37
  43. data/lib/urbanopt/reporting/default_reports/storage.rb +2 -37
  44. data/lib/urbanopt/reporting/default_reports/thermal_storage.rb +2 -37
  45. data/lib/urbanopt/reporting/default_reports/timeseries_csv.rb +2 -37
  46. data/lib/urbanopt/reporting/default_reports/validator.rb +2 -37
  47. data/lib/urbanopt/reporting/default_reports/wind.rb +2 -37
  48. data/lib/urbanopt/reporting/default_reports.rb +2 -37
  49. data/lib/urbanopt/reporting/derived_extension.rb +2 -37
  50. data/lib/urbanopt/reporting/version.rb +3 -38
  51. data/lib/urbanopt/reporting.rb +2 -37
  52. data/urbanopt-reporting-gem.gemspec +3 -3
  53. metadata +14 -11
  54. data/.github/workflows/nightly_build.yml +0 -41
@@ -0,0 +1,147 @@
1
+ # *********************************************************************************
2
+ # URBANopt (tm), Copyright (c) Alliance for Sustainable Energy, LLC.
3
+ # See also https://github.com/urbanopt/urbanopt-reporting-gem/blob/develop/LICENSE.md
4
+ # *********************************************************************************
5
+
6
+ require 'json'
7
+ require 'json-schema'
8
+
9
+ module URBANopt
10
+ module Reporting
11
+ module DefaultReports
12
+ ##
13
+ # QAQC flags for each feature
14
+ ##
15
+ class QAQC
16
+ ##
17
+ # _Hash_ - Hash of flags raised by QAQC measure for this feature during this reporting period
18
+ #
19
+ attr_accessor :eui_reasonableness,:end_use_by_category,:mechanical_system_part_load_efficiency,
20
+ :simultaneous_heating_and_cooling , :internal_loads , :schedules, :envelope_r_value,
21
+ :domestic_hot_water , :mechanical_system_efficiency , :supply_and_zone_air_temperature,
22
+ :total_qaqc_flags
23
+
24
+ ##
25
+ # QAQC class initialize quaqc attributes: +:eui_reasonableness,+:end_use_by_category,+:mechanical_system_part_load_efficiency,
26
+ # +:simultaneous_heating_and_cooling , +:internal_loads , +:schedules, +:envelope_r_value,
27
+ # +:domestic_hot_water , +:mechanical_system_efficiency , +:supply_and_zone_air_temperature, +:total_qaqc_flags
28
+ ##
29
+ # [parameters:]
30
+ #
31
+ # * +hash+ - _Hash_ - A hash containing qaqc attributes listed above.
32
+ #
33
+ def initialize(hash = {})
34
+ hash.delete_if { |k, v| v.nil? }
35
+ hash = defaults.merge(hash)
36
+
37
+ @eui_reasonableness = hash[:eui_reasonableness]
38
+ @end_use_by_category = hash[:end_use_by_category]
39
+ @mechanical_system_part_load_efficiency = hash[:mechanical_system_part_load_efficiency]
40
+ @simultaneous_heating_and_cooling = hash[:simultaneous_heating_and_cooling]
41
+ @supply_and_zone_air_temperature = hash[:supply_and_zone_air_temperature]
42
+ @internal_loads = hash[:internal_loads]
43
+ @schedules = hash[:schedules]
44
+ @envelope_r_value = hash[:envelope_r_value]
45
+ @domestic_hot_water = hash[:domestic_hot_water]
46
+ @mechanical_system_efficiency = hash[:mechanical_system_efficiency]
47
+ @total_qaqc_flags = hash[:total_qaqc_flags]
48
+
49
+
50
+ # initialize class variables @@validator and @@schema
51
+ @@validator ||= Validator.new
52
+ @@schema ||= @@validator.schema
53
+
54
+ end
55
+
56
+
57
+ ##
58
+ # Assigns default values if values do not exist.
59
+ ##
60
+ def defaults
61
+ hash = {}
62
+
63
+ hash[:eui_reasonableness] = nil
64
+ hash[:end_use_by_category] = nil
65
+ hash[:mechanical_system_part_load_efficiency] = nil
66
+ hash[:simultaneous_heating_and_cooling] = nil
67
+ hash[:supply_and_zone_air_temperature] = nil
68
+ hash[:internal_loads] = nil
69
+ hash[:schedules] = nil
70
+ hash[:envelope_r_value] = nil
71
+ hash[:domestic_hot_water] = nil
72
+ hash[:mechanical_system_efficiency] = nil
73
+ hash[:total_qaqc_flags] = nil
74
+
75
+
76
+ return hash
77
+ end
78
+ ##
79
+ # Convert to a Hash equivalent for JSON serialization
80
+ ##
81
+ def to_hash
82
+ result = {}
83
+
84
+ result[:eui_reasonableness] = @eui_reasonableness
85
+ result[:end_use_by_category] = @end_use_by_category
86
+ result[:mechanical_system_part_load_efficiency] = @mechanical_system_part_load_efficiency
87
+ result[:simultaneous_heating_and_cooling] = @simultaneous_heating_and_cooling
88
+ result[:supply_and_zone_air_temperature] = @supply_and_zone_air_temperature
89
+ result[:internal_loads] = @internal_loads
90
+ result[:schedules] = @schedules
91
+ result[:envelope_r_value] = @envelope_r_value
92
+ result[:domestic_hot_water] = @domestic_hot_water
93
+ result[:mechanical_system_efficiency] = @mechanical_system_efficiency
94
+ result[:total_qaqc_flags] = @total_qaqc_flags
95
+
96
+ # validate program properties against schema
97
+ if @@validator.validate(@@schema[:definitions][:qaqc_flags][:properties], result).any?
98
+ raise "qaqc properties does not match schema: #{@@validator.validate(@@schema[:definitions][:qaqc_flags][:properties], result)}"
99
+ end
100
+
101
+ return result
102
+
103
+ end
104
+
105
+ ##
106
+ # Adds up +existing_value+ and +new_values+ if not nill.
107
+ ##
108
+ # [parameters:]
109
+ # +existing_value+ - _Float_ - A value corresponding to a qaqc_flags attribute.
110
+ ##
111
+ # +new_value+ - _Float_ - A value corresponding to a qaqc_flags attribute.
112
+ ##
113
+ def add_values(existing_value, new_value) #:nodoc:
114
+ if existing_value && new_value
115
+ existing_value += new_value
116
+ elsif new_value
117
+ existing_value = new_value
118
+ end
119
+ return existing_value
120
+ end
121
+
122
+ ##
123
+ # Merges qaqc_flags objects to each other by summing up values.
124
+ ##
125
+ # [parameters:]
126
+ # +other+ - _QAQC_ - An object of Program class.
127
+ ##
128
+ def add_qaqc_flags(other)
129
+
130
+ @eui_reasonableness = add_values(@eui_reasonableness, other.eui_reasonableness)
131
+ @end_use_by_category = add_values(@end_use_by_category, other.end_use_by_category)
132
+ @mechanical_system_part_load_efficiency = add_values(@mechanical_system_part_load_efficiency, other.mechanical_system_part_load_efficiency)
133
+ @simultaneous_heating_and_cooling = add_values(@simultaneous_heating_and_cooling, other.simultaneous_heating_and_cooling)
134
+ @supply_and_zone_air_temperature = add_values(@supply_and_zone_air_temperature, other.supply_and_zone_air_temperature)
135
+ @internal_loads = add_values(@internal_loads, other.internal_loads)
136
+ @schedules = add_values(@schedules, other.schedules)
137
+ @envelope_r_value = add_values(@envelope_r_value, other.envelope_r_value)
138
+ @domestic_hot_water = add_values(@domestic_hot_water, other.domestic_hot_water)
139
+ @mechanical_system_efficiency = add_values(@mechanical_system_efficiency, other.mechanical_system_efficiency)
140
+ @total_qaqc_flags = add_values(@total_qaqc_flags, other.total_qaqc_flags)
141
+
142
+ end
143
+
144
+ end
145
+ end
146
+ end
147
+ end
@@ -1,41 +1,6 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2022, 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
- # Redistribution of this software, without modification, must refer to the software
20
- # by the same designation. Redistribution of a modified version of this software
21
- # (i) may not refer to the modified version by the same designation, or by any
22
- # confusingly similar designation, and (ii) must refer to the underlying software
23
- # originally provided by Alliance as “URBANopt”. Except to comply with the foregoing,
24
- # the term “URBANopt”, or any confusingly similar designation may not be used to
25
- # refer to any modified version of this software or any modified version of the
26
- # underlying software originally provided by Alliance without the prior written
27
- # consent of Alliance.
28
-
29
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
30
- # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31
- # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
32
- # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33
- # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34
- # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35
- # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
36
- # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
37
- # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
38
- # OF THE POSSIBILITY OF SUCH DAMAGE.
2
+ # URBANopt (tm), Copyright (c) Alliance for Sustainable Energy, LLC.
3
+ # See also https://github.com/urbanopt/urbanopt-reporting-gem/blob/develop/LICENSE.md
39
4
  # *********************************************************************************
40
5
 
41
6
  require_relative 'end_uses'
@@ -60,7 +25,7 @@ module URBANopt
60
25
  :time_setpoint_not_met_during_occupied_heating, :time_setpoint_not_met_during_occupied_hours, :hours_out_of_comfort_bounds_PMV, :hours_out_of_comfort_bounds_PPD,
61
26
  :emissions, :future_annual_electricity_emissions_mt, :future_hourly_electricity_emissions_mt, :historical_annual_electricity_emissions_mt, :historical_hourly_electricity_emissions_mt,
62
27
  :future_annual_electricity_emissions_intensity_kg_per_ft2, :future_hourly_electricity_emissions_intensity_kg_per_ft2, :historical_annual_electricity_emissions_intensity_kg_per_ft2, :historical_hourly_electricity_emissions_intensity_kg_per_ft2 ,
63
- :natural_gas_emissions_mt, :natural_gas_emissions_intensity_kg_per_ft2, :propane_emissions_mt, :propane_emissions_intensity_kg_per_ft2,
28
+ :natural_gas_emissions_mt, :natural_gas_emissions_intensity_kg_per_ft2, :propane_emissions_mt, :propane_emissions_intensity_kg_per_ft2,
64
29
  :fueloil_no2_emissions_mt, :fueloil_no2_emissions_intensity_kg_per_ft2 #:nodoc:
65
30
 
66
31
  # ReportingPeriod class initializes the reporting period attributes:
@@ -71,7 +36,7 @@ module URBANopt
71
36
  # +:time_setpoint_not_met_during_occupied_heating+ , +:time_setpoint_not_met_during_occupied_hours+ , +:hours_out_of_comfort_bounds_PMV+ , +:hours_out_of_comfort_bounds_PPD+ ,
72
37
  # +:emissions, +:future_annual_electricity_emissions_mt+, +:future_hourly_electricity_emissions_mt+, +:historical_annual_electricity_emissions_mt+, +:historical_hourly_electricity_emissions_mt+,
73
38
  # +:future_annual_electricity_emissions_intensity_kg_per_ft2+, +:future_hourly_electricity_emissions_intensity_kg_per_ft2+, +:historical_annual_electricity_emissions_intensity_kg_per_ft2+, +:historical_hourly_electricity_emissions_intensity_kg_per_ft2+,
74
- # +:natural_gas_emissions_mt+, +:natural_gas_emissions_intensity_kg_per_ft2+, +:propane_emissions_mt+, +:propane_emissions_intensity_kg_per_ft2+,
39
+ # +:natural_gas_emissions_mt+, +:natural_gas_emissions_intensity_kg_per_ft2+, +:propane_emissions_mt+, +:propane_emissions_intensity_kg_per_ft2+,
75
40
  # +:fueloil_no2_emissions_mt+, +:fueloil_no2_emissions_intensity_kg_per_ft2+
76
41
  ##
77
42
  # [parameters:]
@@ -157,7 +122,7 @@ module URBANopt
157
122
  hash[:utility_costs_dollar] = [{ fuel_type: nil, total_cost_dollar: nil, usage_cost_dollar: nil, demand_cost_dollar: nil }]
158
123
  hash[:comfort_result] = { time_setpoint_not_met_during_occupied_cooling: nil, time_setpoint_not_met_during_occupied_heating: nil,
159
124
  time_setpoint_not_met_during_occupied_hours: nil, hours_out_of_comfort_bounds_PMV: nil, hours_out_of_comfort_bounds_PPD: nil }
160
- hash[:emissions] = { future_annual_electricity_emissions_mt: nil, future_hourly_electricity_emissions_mt: nil, historical_annual_electricity_emissions_mt: nil,
125
+ hash[:emissions] = { future_annual_electricity_emissions_mt: nil, future_hourly_electricity_emissions_mt: nil, historical_annual_electricity_emissions_mt: nil,
161
126
  historical_hourly_electricity_emissions_mt: nil, future_annual_electricity_emissions_intensity_kg_per_ft2: nil,
162
127
  future_hourly_electricity_emissions_intensity_kg_per_ft2: nil, historical_annual_electricity_emissions_intensity_kg_per_ft2: nil,
163
128
  historical_hourly_electricity_emissions_intensity_kg_per_ft2: nil, natural_gas_emissions_mt: nil,
@@ -307,7 +272,7 @@ module URBANopt
307
272
  existing_period.emissions[:natural_gas_emissions_mt] = add_values(existing_period.emissions[:natural_gas_emissions_mt], new_period.emissions[:natural_gas_emissions_mt])
308
273
  existing_period.emissions[:propane_emissions_mt] = add_values(existing_period.emissions[:propane_emissions_mt], new_period.emissions[:propane_emissions_mt])
309
274
  existing_period.emissions[:fueloil_no2_emissions_mt] = add_values(existing_period.emissions[:fueloil_no2_emissions_mt], new_period.emissions[:fueloil_no2_emissions_mt])
310
-
275
+
311
276
  existing_period.emissions[:future_annual_electricity_emissions_intensity_kg_per_ft2] = add_values(existing_period.emissions[:future_annual_electricity_emissions_intensity_kg_per_ft2], new_period.emissions[:future_annual_electricity_emissions_intensity_kg_per_ft2])
312
277
  existing_period.emissions[:future_hourly_electricity_emissions_intensity_kg_per_ft2] = add_values(existing_period.emissions[:future_hourly_electricity_emissions_intensity_kg_per_ft2], new_period.emissions[:future_hourly_electricity_emissions_intensity_kg_per_ft2])
313
278
  existing_period.emissions[:historical_annual_electricity_emissions_intensity_kg_per_ft2] = add_values(existing_period.emissions[:historical_annual_electricity_emissions_intensity_kg_per_ft2], new_period.emissions[:historical_annual_electricity_emissions_intensity_kg_per_ft2])
@@ -1,41 +1,6 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2022, 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
- # Redistribution of this software, without modification, must refer to the software
20
- # by the same designation. Redistribution of a modified version of this software
21
- # (i) may not refer to the modified version by the same designation, or by any
22
- # confusingly similar designation, and (ii) must refer to the underlying software
23
- # originally provided by Alliance as “URBANopt”. Except to comply with the foregoing,
24
- # the term “URBANopt”, or any confusingly similar designation may not be used to
25
- # refer to any modified version of this software or any modified version of the
26
- # underlying software originally provided by Alliance without the prior written
27
- # consent of Alliance.
28
-
29
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
30
- # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31
- # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
32
- # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33
- # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34
- # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35
- # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
36
- # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
37
- # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
38
- # OF THE POSSIBILITY OF SUCH DAMAGE.
2
+ # URBANopt (tm), Copyright (c) Alliance for Sustainable Energy, LLC.
3
+ # See also https://github.com/urbanopt/urbanopt-reporting-gem/blob/develop/LICENSE.md
39
4
  # *********************************************************************************
40
5
 
41
6
  require_relative 'validator'
@@ -0,0 +1,177 @@
1
+ # *********************************************************************************
2
+ # URBANopt (tm), Copyright (c) Alliance for Sustainable Energy, LLC.
3
+ # See also https://github.com/urbanopt/urbanopt-reporting-gem/blob/develop/LICENSE.md
4
+ # *********************************************************************************
5
+
6
+ require_relative 'validator'
7
+
8
+ require 'json'
9
+ require 'json-schema'
10
+
11
+ module URBANopt
12
+ module Reporting
13
+ module DefaultReports
14
+ ##
15
+ # scenario_power_distribution_cost include eletrical power distribution system violation and
16
+ # upgrade cost information.
17
+ ##
18
+ class ScenarioPowerDistributionCost
19
+ attr_accessor :results, :outputs, :violation_summary, :costs_per_equipment, :equipment
20
+
21
+ ##
22
+ # ScenarioPowerDistributionCost class initializes all
23
+ # scenario_power_distribution_cost attributes:
24
+ # +:results+, +:outputs+, +:violation_summary+, +:costs_per_equipment+, +:equipment+
25
+ ##
26
+ def initialize(hash = {})
27
+ hash.delete_if { |k, v| v.nil? }
28
+ hash = defaults.merge(hash)
29
+
30
+ @results = hash[:results]
31
+ @outputs = hash[:outputs]
32
+ @violation_summary = hash[:violation_summary]
33
+ @costs_per_equipment = hash[:costs_per_equipment]
34
+ @equipment = hash[:equipment]
35
+
36
+ # initialize class variables @@validator and @@schema
37
+ @@validator ||= Validator.new
38
+ @@schema ||= @@validator.schema
39
+ end
40
+
41
+ ##
42
+ # Assigns default values if attribute values do not exist.##
43
+ def defaults
44
+ hash = {}
45
+ hash[:results] = []
46
+ hash[:outputs] = {}
47
+ hash[:violation_summary] = []
48
+ hash[:costs_per_equipment] = []
49
+ hash[:equipment] = []
50
+
51
+ return hash
52
+ end
53
+
54
+ ##
55
+ # Converts to a Hash equivalent for JSON serialization.
56
+ ##
57
+ # - Exclude attributes with nil values.
58
+ # - Validate power_distribution_cost hash properties against schema.
59
+ ##
60
+ def to_hash
61
+ result = {}
62
+ result[:results] = @results if @results
63
+ result[:outputs] = @outputs if !@outputs.empty?
64
+ result[:violation_summary] = @violation_summary if @violation_summary
65
+ result[:costs_per_equipment] = @costs_per_equipment if @costs_per_equipment
66
+ result[:equipment] = @equipment if @equipment
67
+
68
+ # validate power_distribution_cost properties against schema
69
+ if @@validator.validate(@@schema[:definitions][:ScenarioPowerDistributionCost][:properties], result).any?
70
+ raise "scenario_power_distribution_cost properties does not match schema: #{@@validator.validate(@@schema[:definitions][:ScenarioPowerDistributionCost][:properties], result)}"
71
+ end
72
+
73
+ return result
74
+ end
75
+
76
+ ##
77
+ # Add a result
78
+ ##
79
+ def add_result(hash = {})
80
+ hash.delete_if { |k, v| v.nil? }
81
+ hash = defaults.merge(hash)
82
+ result = {}
83
+ result['num_violations'] = hash[:num_violations]
84
+ @results << result
85
+ end
86
+
87
+ ##
88
+ ## Add outputs
89
+ ##
90
+ def add_outputs(hash = {})
91
+ hash.delete_if { |k, v| v.nil? }
92
+ hash = defaults.merge(hash)
93
+ output = {}
94
+ output['log_file'] = hash[:log_file]
95
+ output['jobs'] = []
96
+ hash[:jobs].each do |job|
97
+ output['jobs'] << job
98
+ end
99
+ @outputs = output
100
+ end
101
+
102
+ ##
103
+ ## Add a violation summary
104
+ ##
105
+ def add_violation_summary(hash = {})
106
+ hash.delete_if { |k, v| v.nil? }
107
+ hash = defaults.merge(hash)
108
+ violation_summary = {}
109
+ violation_summary['scenario'] = hash[:scenario]
110
+ violation_summary['stage'] = hash[:stage]
111
+ violation_summary['upgrade_type'] = hash[:upgrade_type]
112
+ violation_summary['simulation_time_s'] = hash[:simulation_time_s]
113
+ violation_summary['thermal_violations_present'] = hash[:thermal_violations_present]
114
+ violation_summary['voltage_violations_present'] = hash[:voltage_violations_present]
115
+ violation_summary['max_bus_voltage'] = hash[:max_bus_voltage]
116
+ violation_summary['min_bus_voltage'] = hash[:min_bus_voltage]
117
+ violation_summary['num_voltage_violation_buses'] = hash[:num_voltage_violation_buses]
118
+ violation_summary['num_overvoltage_violation_buses'] = hash[:num_overvoltage_violation_buses]
119
+ violation_summary['voltage_upper_limit'] = hash[:voltage_upper_limit]
120
+ violation_summary['num_undervoltage_violation_buses'] = hash[:num_undervoltage_violation_buses]
121
+ violation_summary['voltage_lower_limit'] = hash[:voltage_lower_limit]
122
+ violation_summary['max_line_loading'] = hash[:max_line_loading]
123
+ violation_summary['max_transformer_loading'] = hash[:max_transformer_loading]
124
+ violation_summary['num_line_violations'] = hash[:num_line_violations]
125
+ violation_summary['line_upper_limit'] = hash[:line_upper_limit]
126
+ violation_summary['num_transformer_violations'] = hash[:num_transformer_violations]
127
+ violation_summary['transformer_upper_limit'] = hash[:transformer_upper_limit]
128
+
129
+ @violation_summary << violation_summary
130
+ end
131
+
132
+ ##
133
+ # Add costs per equipment
134
+ ##
135
+ def add_costs_per_equipment
136
+ hash.delete_if { |k, v| v.nil? }
137
+ hash = defaults.merge(hash)
138
+ costs_per_equipment = {}
139
+ costs_per_equipment['name'] = hash[:name]
140
+ costs_per_equipment['type'] = hash[:type]
141
+ costs_per_equipment['count'] = hash[:count]
142
+ costs_per_equipment['total_cost_usd'] = hash[:costs_per_equipment]
143
+
144
+ @costs_per_equipment << costs_per_equipment
145
+ end
146
+
147
+ ##
148
+ # Add equipment
149
+ ##
150
+ def add_equipment
151
+ hash.delete_if { |k, v| v.nil? }
152
+ hash = defaults.merge(hash)
153
+ equipment = {}
154
+ equipment['equipment_type'] = hash[:equipment_type]
155
+ equipment['equipment_name'] = hash[:equipment_name]
156
+ equipment['status'] = hash[:status]
157
+ equipment['parameter1_name'] = hash[:parameter1_name]
158
+ equipment['parameter1_original'] = hash[:parameter1_original]
159
+ equipment['parameter1_upgraded'] = hash[:parameter1_upgraded]
160
+ equipment['parameter2_name'] = hash[:parameter2_name]
161
+ equipment['parameter2_original'] = hash[:parameter2_original]
162
+ equipment['parameter2_upgraded'] = hash[:parameter2_upgraded]
163
+ equipment['parameter3_name'] = hash[:parameter3_name]
164
+ equipment['parameter3_original'] = hash[:parameter3_original]
165
+ equipment['parameter3_upgraded'] = hash[:parameter3_upgraded]
166
+ equipment['name'] = hash[:name]
167
+
168
+ @equipment << equipment
169
+ end
170
+
171
+
172
+
173
+ end # ScenarioPowerDistributionCost
174
+
175
+ end # DefaultReports
176
+ end # Reporting
177
+ end # URBANopt
@@ -1,41 +1,6 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2022, 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
- # Redistribution of this software, without modification, must refer to the software
20
- # by the same designation. Redistribution of a modified version of this software
21
- # (i) may not refer to the modified version by the same designation, or by any
22
- # confusingly similar designation, and (ii) must refer to the underlying software
23
- # originally provided by Alliance as “URBANopt”. Except to comply with the foregoing,
24
- # the term “URBANopt”, or any confusingly similar designation may not be used to
25
- # refer to any modified version of this software or any modified version of the
26
- # underlying software originally provided by Alliance without the prior written
27
- # consent of Alliance.
28
-
29
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
30
- # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31
- # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
32
- # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33
- # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34
- # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35
- # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
36
- # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
37
- # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
38
- # OF THE POSSIBILITY OF SUCH DAMAGE.
2
+ # URBANopt (tm), Copyright (c) Alliance for Sustainable Energy, LLC.
3
+ # See also https://github.com/urbanopt/urbanopt-reporting-gem/blob/develop/LICENSE.md
39
4
  # *********************************************************************************
40
5
 
41
6
  require_relative 'construction_cost'
@@ -47,6 +12,8 @@ require_relative 'timeseries_csv'
47
12
  require_relative 'distributed_generation'
48
13
  require_relative 'validator'
49
14
  require_relative 'scenario_power_distribution'
15
+ require_relative 'scenario_power_distribution_cost'
16
+ require_relative 'qaqc_flags'
50
17
 
51
18
  require 'json'
52
19
  require 'json-schema'
@@ -64,12 +31,13 @@ module URBANopt
64
31
  attr_accessor :id, :name, :directory_name, :timesteps_per_hour, :number_of_not_started_simulations,
65
32
  :number_of_started_simulations, :number_of_complete_simulations, :number_of_failed_simulations,
66
33
  :timeseries_csv, :location, :program, :construction_costs, :reporting_periods, :feature_reports, :distributed_generation,
67
- :scenario_power_distribution # :nodoc:
34
+ :scenario_power_distribution, :scenario_power_distribution_cost, :qaqc_flags # :nodoc:
68
35
 
69
36
  # ScenarioReport class intializes the scenario report attributes:
70
37
  # +:id+ , +:name+ , +:directory_name+, +:timesteps_per_hour+ , +:number_of_not_started_simulations+ ,
71
38
  # +:number_of_started_simulations+ , +:number_of_complete_simulations+ , +:number_of_failed_simulations+ ,
72
- # +:timeseries_csv+ , +:location+ , +:program+ , +:construction_costs+ , +:reporting_periods+ , +:feature_reports+
39
+ # +:timeseries_csv+ , +:location+ , +:program+ , +:construction_costs+ , +:reporting_periods+ , +:feature_reports+,
40
+ # +:distributed_generation+, +:scenario_power_distribution+, +:qaqc_flags+
73
41
  ##
74
42
  # Each ScenarioReport object corresponds to a single Scenario.
75
43
  ##
@@ -93,6 +61,8 @@ module URBANopt
93
61
  @program = Program.new(hash[:program])
94
62
  @distributed_generation = DistributedGeneration.new(hash[:distributed_generation] || {})
95
63
  @scenario_power_distribution = ScenarioPowerDistribution.new(hash[:scenario_power_distribution] || {})
64
+ @scenario_power_distribution_cost = ScenarioPowerDistributionCost.new(hash[:scenario_power_distribution_cost] || {})
65
+ @qaqc_flags = QAQC.new(hash[:qaqc_flags])
96
66
 
97
67
  @construction_costs = []
98
68
  hash[:construction_costs].each do |cc|
@@ -136,6 +106,7 @@ module URBANopt
136
106
  hash[:timeseries_csv] = TimeseriesCSV.new.to_hash
137
107
  hash[:location] = Location.new.defaults
138
108
  hash[:program] = Program.new.to_hash
109
+ hash[:qaqc_flags] = QAQC.new.to_hash
139
110
  hash[:construction_costs] = []
140
111
  hash[:reporting_periods] = []
141
112
  hash[:feature_reports] = []
@@ -161,18 +132,20 @@ module URBANopt
161
132
  ##
162
133
  # [parameters]:
163
134
  # +file_name+ - _String_ - Assign a name to the saved scenario results file without an extension
164
- def save(file_name = 'default_scenario_report', save_feature_reports = true)
135
+ def save(file_name = 'default_scenario_report', save_feature_reports = true, save_csv_reports = true)
165
136
  # reassign the initialize local variable @file_name to the file name input.
166
137
  @file_name = file_name
167
138
 
168
- # save the scenario reports csv and json data
169
- old_timeseries_path = nil
170
- if !@timeseries_csv.path.nil?
171
- old_timeseries_path = @timeseries_csv.path
172
- end
139
+ if save_csv_reports == true
140
+ # save the scenario reports csv and json data
141
+ old_timeseries_path = nil
142
+ if !@timeseries_csv.path.nil?
143
+ old_timeseries_path = @timeseries_csv.path
144
+ end
173
145
 
174
- @timeseries_csv.path = File.join(@directory_name, "#{file_name}.csv")
175
- @timeseries_csv.save_data
146
+ @timeseries_csv.path = File.join(@directory_name, "#{file_name}.csv")
147
+ @timeseries_csv.save_data
148
+ end
176
149
 
177
150
  hash = {}
178
151
  hash[:scenario_report] = to_hash
@@ -193,10 +166,12 @@ module URBANopt
193
166
  end
194
167
  end
195
168
 
196
- if !old_timeseries_path.nil?
197
- @timeseries_csv.path = old_timeseries_path
198
- else
199
- @timeseries_csv.path = File.join(@directory_name, "#{file_name}.csv")
169
+ if save_csv_reports == true
170
+ if !old_timeseries_path.nil?
171
+ @timeseries_csv.path = old_timeseries_path
172
+ else
173
+ @timeseries_csv.path = File.join(@directory_name, "#{file_name}.csv")
174
+ end
200
175
  end
201
176
 
202
177
  if save_feature_reports
@@ -233,6 +208,8 @@ module URBANopt
233
208
  result[:program] = @program.to_hash if @program
234
209
  result[:distributed_generation] = @distributed_generation.to_hash if @distributed_generation
235
210
  result[:scenario_power_distribution] = @scenario_power_distribution.to_hash if @scenario_power_distribution
211
+ result[:scenario_power_distribution_cost] = @scenario_power_distribution_cost.to_hash if @scenario_power_distribution_cost
212
+ result[:qaqc_flags] = @qaqc_flags.to_hash if @qaqc_flags
236
213
 
237
214
  result[:construction_costs] = []
238
215
  @construction_costs&.each { |cc| result[:construction_costs] << cc.to_hash }
@@ -249,7 +226,9 @@ module URBANopt
249
226
  end
250
227
 
251
228
  # have to use the module method because we have not yet initialized the class one
252
- @@logger.info("Scenario name: #{@name}")
229
+ unless @name == '' || @name.nil?
230
+ @@logger.info("Scenario name: #{@name}")
231
+ end
253
232
 
254
233
  return result
255
234
  end
@@ -261,6 +240,7 @@ module URBANopt
261
240
  # - check feature simulation status
262
241
  # - merge timeseries_csv information
263
242
  # - merge program information
243
+ # - merge qaqc_flags information
264
244
  # - merge construction_cost information
265
245
  # - merge reporting_periods information
266
246
  # - add the array of feature_reports
@@ -324,8 +304,12 @@ module URBANopt
324
304
  # merge reporting_periods information
325
305
  @reporting_periods = ReportingPeriod.merge_reporting_periods(@reporting_periods, feature_report.reporting_periods)
326
306
 
307
+ # merge distributed_generation information
327
308
  @distributed_generation = DistributedGeneration.merge_distributed_generation(@distributed_generation, feature_report.distributed_generation)
328
309
 
310
+ # merge qaqc_flags information
311
+ @qaqc_flags.add_qaqc_flags(feature_report.qaqc_flags)
312
+
329
313
  # add feature_report
330
314
  @feature_reports << feature_report
331
315