urbanopt-reporting 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c05852788af7d42e924ebbc180c721c4f21fe0dec668732acfa09e4a2909f4f0
4
- data.tar.gz: 807e962c78c6af22fa5f15af8c3ec1f45b534a65b19fa6212073deb253ff9be2
3
+ metadata.gz: 186e2233b38a2f167fadd907eb6d768a589ca55dfc0a11e238b363bbc9574c27
4
+ data.tar.gz: 5cdb0f89a17ea078ef7ed61ed5710892ae956620a5370fe140fd4c8107ab73e8
5
5
  SHA512:
6
- metadata.gz: 0e187629e9ebcf371b55186e5c5765384667d09a29ecbc91cb112af8368d3719e4dbe63f21aed8ba7a6a5ffe5a2bcc110bb76dcb0d5e83e888eee4f7dd2144f4
7
- data.tar.gz: f7b23ae1f1a8d769f550553efc6ef824eae83075d838a3247772c67725c1fb079d863cf28e1d1661d9cf81363a43b8870d3375c38cf094328d7060ef80ecaba6
6
+ metadata.gz: 2bce9e36d7098ceb88b559d01b4e2eeeb5a30b78c0cacfd476a9501592df3b65b2d9807c45203fb3b2bccb53b3e8334e35acd362f5c848ac089635ce3f9ff932
7
+ data.tar.gz: 218468f4c8beb0b2dc4c4afa7ef4b7e05410d42bf7898236e58de93048f32c1b3be290a47260bd7d457811821562223e3fbd49845cb77334c5a7e3a9a256bdea
@@ -15,7 +15,7 @@ on:
15
15
 
16
16
  env:
17
17
  # This env var should enforce develop branch of all dependencies
18
- FAVOR_LOCAL_GEMS: true
18
+ # FAVOR_LOCAL_GEMS: true
19
19
  GEM_DEVELOPER_KEY: ${{ secrets.GEM_DEVELOPER_KEY }}
20
20
 
21
21
  jobs:
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # URBANopt Reporting Gem
2
2
 
3
+ ## Version 0.7.0
4
+ Date Range: 08/18/22 - 12/12/22
5
+
6
+ - Update Dependencies for OpenStudio 3.5.0
7
+ - Fixed [#106]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/106 ), Update UO reporting schema to include DISCO outputs
8
+ - Fixed [#107]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/107 ), QAQC reporting rollup in feature report and scenario report
9
+ - Fixed [#127]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/127 ), Clean up log output to stdout
10
+
11
+
3
12
  ## Version 0.6.2
4
13
  Date Range: 06/28/22 - 08/17/22
5
14
 
data/Gemfile CHANGED
@@ -11,8 +11,8 @@ gemspec
11
11
  # checkout the latest version (develop) from github.
12
12
  allow_local = ENV['FAVOR_LOCAL_GEMS']
13
13
 
14
- if allow_local && File.exist?('../openstudio-extension-gem')
15
- gem 'openstudio-extension', path: '../openstudio-extension-gem'
16
- elsif allow_local
17
- gem 'openstudio-extension', github: 'NREL/openstudio-extension-gem', branch: 'develop'
18
- end
14
+ # if allow_local && File.exist?('../openstudio-extension-gem')
15
+ # gem 'openstudio-extension', path: '../openstudio-extension-gem'
16
+ # elsif allow_local
17
+ # gem 'openstudio-extension', github: 'NREL/openstudio-extension-gem', branch: 'develop'
18
+ # end
@@ -41,12 +41,12 @@
41
41
  require 'urbanopt/reporting/default_reports'
42
42
  require 'csv'
43
43
  require 'benchmark'
44
+ require 'json'
44
45
  require 'logger'
45
46
 
46
- @@logger = Logger.new($stdout)
47
-
48
47
  # start the measure
49
48
  class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
49
+ @@logger = Logger.new($stdout)
50
50
  # human readable name
51
51
  def name
52
52
  return 'DefaultFeatureReports'
@@ -233,7 +233,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
233
233
  # result << OpenStudio::IdfObject.load("Output:Variable,*,Exterior Equipment:Electric Vehicles,#{reporting_frequency};").get
234
234
 
235
235
  ## add environmental factor outputs
236
- #result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,Output:EnvironmentalImpactFactors,#{reporting_frequency};").get
236
+ # result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,Output:EnvironmentalImpactFactors,#{reporting_frequency};").get
237
237
  # result << OpenStudio::IdfObject.load("Output:Variable,*,Environmental Impact Total N2O Emissions Carbon Equivalent Mass,#{reporting_frequency}; !- HVAC Sum [kg];").get
238
238
  # result << OpenStudio::IdfObject.load("Output:Variable,*,Environmental Impact Total CH4 Emissions Carbon Equivalent Mass,#{reporting_frequency}; !- HVAC Sum [kg];").get
239
239
  # result << OpenStudio::IdfObject.load("Output:Variable,*,Environmental Impact Total CO2 Emissions Carbon Equivalent Mass,#{reporting_frequency}; !- HVAC Sum [kg];").get
@@ -252,11 +252,9 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
252
252
  ev_timeseries_data = ['Exterior Equipment:Electric Vehicles']
253
253
 
254
254
  emissions_timeseries_data = ['Future_Annual_Electricity_Emissions', 'Future_Hourly_Electricity_Emissions',
255
- 'Historical_Annual_Electricity_Emissions', 'Historical_Hourly_Electricity_Emissions',
256
- 'Future_Annual_Electricity_Emissions_Intensity', 'Future_Hourly_Electricity_Emissions_Intensity',
257
- 'Historical_Annual_Electricity_Emissions_Intensity', 'Historical_Hourly_Electricity_Emissions_Intensity']
258
-
259
-
255
+ 'Historical_Annual_Electricity_Emissions', 'Historical_Hourly_Electricity_Emissions',
256
+ 'Future_Annual_Electricity_Emissions_Intensity', 'Future_Hourly_Electricity_Emissions_Intensity',
257
+ 'Historical_Annual_Electricity_Emissions_Intensity', 'Historical_Hourly_Electricity_Emissions_Intensity']
260
258
 
261
259
  timeseries_data += tes_timeseries_data
262
260
  timeseries_data += emissions_timeseries_data
@@ -291,6 +289,85 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
291
289
  return val
292
290
  end
293
291
 
292
+ def feature_qaqc_flags(runner)
293
+ # QAQC flags by category
294
+ qaqc_flags_hash = {} # Make a hash for count of flags of each category
295
+
296
+ runner.workflow.workflowSteps.each do |step| # Go through all the steps
297
+
298
+ if step.to_MeasureStep.is_initialized
299
+ measure_step = step.to_MeasureStep.get
300
+
301
+ measure_name = measure_step.measureDirName
302
+
303
+ if measure_step.name.is_initialized
304
+ measure_name = measure_step.name.get
305
+ end
306
+
307
+ if measure_name.include? 'qaqc'
308
+ puts "measure_name = #{measure_name}"
309
+ if measure_step.result.is_initialized
310
+ result = measure_step.result.get
311
+ puts " result = #{result}"
312
+
313
+ ## Adding quaqc_flags_list to check the step value name since units key is missing from the result
314
+ ## It does show in the out.osw but not in the runner.workflow.workflowSteps object
315
+ # use this list to define the flags you want to report
316
+ qaqc_flags_list = ['eui_reasonableness' , 'end_use_by_category',
317
+ 'mechanical_system_part_load_efficiency', 'simultaneous_heating_and_cooling',
318
+ 'internal_loads', 'schedules', 'envelope_r_value', 'domestic_hot_water',
319
+ 'mechanical_system_efficiency', 'supply_and_zone_air_temperature', 'total_qaqc_flags' ]
320
+
321
+ result.stepValues.each do |step_value|
322
+
323
+ #get name
324
+ name = step_value.name
325
+
326
+ if qaqc_flags_list.include? name
327
+
328
+ # get value
329
+ # check if value, double, int, or bool
330
+ value_type = step_value.variantType.valueDescription
331
+ if value_type == "Double"
332
+ value = step_value.valueAsDouble
333
+ elsif value_type == "Integer"
334
+ value = step_value.valueAsInteger
335
+ elsif value_type == "Boolean"
336
+ value = step_value.valueAsBoolean
337
+ elsif value_type == "String"
338
+ value = step_value.valueAsString
339
+ else
340
+ # catchall for unexpected value types
341
+ value = step_value.valueAsVariant.to_s
342
+ end
343
+
344
+ if qaqc_flags_hash[name]
345
+ qaqc_flags_hash[name] += value
346
+ else
347
+ qaqc_flags_hash[name] = value
348
+ end
349
+
350
+ end
351
+
352
+ end
353
+
354
+ puts "qaqc_flags_hash = #{qaqc_flags_hash}"
355
+
356
+ # Hack to put 'total_qaqc_flags' at the end of the hash
357
+ temp_hash_for_ordering = { 'total_qaqc_flags' => qaqc_flags_hash['total_qaqc_flags'] }
358
+ qaqc_flags_hash.delete('total_qaqc_flags')
359
+ qaqc_flags_hash['total_qaqc_flags'] = temp_hash_for_ordering['total_qaqc_flags']
360
+
361
+ end
362
+
363
+ end
364
+
365
+ end
366
+
367
+ end
368
+ return qaqc_flags_hash
369
+ end
370
+
294
371
  # unit conversion method
295
372
  def convert_units(value, from_units, to_units)
296
373
  if value.nil?
@@ -836,7 +913,6 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
836
913
 
837
914
  # electricity emissions
838
915
  begin
839
-
840
916
  # future_annual_emissions
841
917
  future_annual_emissions_ts = sql_file.timeSeries(ann_env_pd.to_s, reporting_frequency.to_s, 'Future_Annual_Electricity_Emissions', 'EMS')
842
918
  feature_report.reporting_periods[0].emissions[:future_annual_electricity_emissions_mt] = future_annual_emissions_ts.get.values.sum
@@ -868,11 +944,24 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
868
944
  # historical_hourly_emissions_intensity
869
945
  historical_hourly_emissions_intensity_ts = sql_file.timeSeries(ann_env_pd.to_s, reporting_frequency.to_s, 'Historical_Hourly_Electricity_Emissions_Intensity', 'EMS')
870
946
  feature_report.reporting_periods[0].emissions[:historical_hourly_electricity_emissions_intensity_kg_per_ft2] = historical_hourly_emissions_intensity_ts.get.values.sum
871
-
872
947
  rescue StandardError
873
948
  @@logger.info('Emissions are not reported for this feature')
874
949
  end
875
950
 
951
+ # add qaqc results to feature report
952
+ qaqc_flags_hash = feature_qaqc_flags(runner)
953
+ feature_report.qaqc_flags.eui_reasonableness = qaqc_flags_hash['eui_reasonableness']
954
+ feature_report.qaqc_flags.end_use_by_category = qaqc_flags_hash['end_use_by_category']
955
+ feature_report.qaqc_flags.mechanical_system_part_load_efficiency = qaqc_flags_hash['mechanical_system_part_load_efficiency']
956
+ feature_report.qaqc_flags.simultaneous_heating_and_cooling = qaqc_flags_hash['simultaneous_heating_and_cooling']
957
+ feature_report.qaqc_flags.internal_loads = qaqc_flags_hash['internal_loads']
958
+ feature_report.qaqc_flags.schedules = qaqc_flags_hash['schedules']
959
+ feature_report.qaqc_flags.envelope_r_value = qaqc_flags_hash['envelope_r_value']
960
+ feature_report.qaqc_flags.domestic_hot_water = qaqc_flags_hash['domestic_hot_water']
961
+ feature_report.qaqc_flags.mechanical_system_efficiency = qaqc_flags_hash['mechanical_system_efficiency']
962
+ feature_report.qaqc_flags.supply_and_zone_air_temperature = qaqc_flags_hash['supply_and_zone_air_temperature']
963
+ feature_report.qaqc_flags.total_qaqc_flags = qaqc_flags_hash['total_qaqc_flags']
964
+
876
965
  ##########################################################################################################################
877
966
  # set conversion variables
878
967
  conv_J_mwh = 1000000 * 60 * 60 # J to MWh (1000000J/MJ * 60hr/min * 60 min/sec)
@@ -888,7 +977,6 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
888
977
  fo1_val = 294.962046
889
978
  fo2_val = 294.962046
890
979
 
891
-
892
980
  ##########################################################################################################################
893
981
  ######################################## Reporting TImeseries Results FOR CSV File #######################################
894
982
 
@@ -948,7 +1036,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
948
1036
  'Historical_Hourly_Electricity_Emissions_Intensity',
949
1037
  'Natural_Gas_Emissions',
950
1038
  'Natural_Gas_Emissions_Intensity',
951
- 'Propane_Emissions',
1039
+ 'Propane_Emissions',
952
1040
  'Propane_Emissions_Intensity',
953
1041
  'FuelOilNo2_Emissions',
954
1042
  'FuelOilNo2_Emissions_Intensity',
@@ -980,7 +1068,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
980
1068
  runner.registerInfo("All timeseries: #{requested_timeseries_names}")
981
1069
 
982
1070
  # timeseries variables to keep to calculate power
983
- tsToKeep = ['Electricity:Facility', 'ElectricityProduced:Facility','Propane:Facility', 'NaturalGas:Facility', 'FuelOilNo2:Facility', 'FuelOilNo1:Facility']
1071
+ tsToKeep = ['Electricity:Facility', 'ElectricityProduced:Facility', 'Propane:Facility', 'NaturalGas:Facility', 'FuelOilNo2:Facility', 'FuelOilNo1:Facility']
984
1072
  tsToKeepIndexes = {}
985
1073
 
986
1074
  ### powerFactor ###
@@ -1145,7 +1233,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
1145
1233
  if timeseries_name == 'Natural_Gas_Emissions'
1146
1234
  newVals = Array.new(n, 0)
1147
1235
  (0..n - 1).each do |j|
1148
- newVals[j] = (nat_gas_val * (values[tsToKeepIndexes['NaturalGas:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f ) * conv_kg_mt.to_f
1236
+ newVals[j] = (nat_gas_val * (values[tsToKeepIndexes['NaturalGas:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f) * conv_kg_mt.to_f
1149
1237
  j += 1
1150
1238
  end
1151
1239
  new_unit = 'MT'
@@ -1158,7 +1246,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
1158
1246
  if timeseries_name == 'Propane_Emissions'
1159
1247
  newVals = Array.new(n, 0)
1160
1248
  (0..n - 1).each do |j|
1161
- newVals[j] = (lpg_val * (values[tsToKeepIndexes['Propane:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f ) * conv_kg_mt.to_f
1249
+ newVals[j] = (lpg_val * (values[tsToKeepIndexes['Propane:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f) * conv_kg_mt.to_f
1162
1250
  j += 1
1163
1251
  end
1164
1252
  new_unit = 'MT'
@@ -1171,7 +1259,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
1171
1259
  if timeseries_name == 'FuelOilNo2_Emissions'
1172
1260
  newVals = Array.new(n, 0)
1173
1261
  (0..n - 1).each do |j|
1174
- newVals[j] = (fo2_val * (values[tsToKeepIndexes['FuelOilNo2:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f ) * conv_kg_mt.to_f
1262
+ newVals[j] = (fo2_val * (values[tsToKeepIndexes['FuelOilNo2:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f) * conv_kg_mt.to_f
1175
1263
  j += 1
1176
1264
  end
1177
1265
  new_unit = 'MT'
@@ -1183,12 +1271,12 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
1183
1271
 
1184
1272
  ### calculate emissions intensity metric
1185
1273
  # get flr_area
1186
- flr_area = building.floorArea * 10.764 #change from m2 to ft2
1274
+ flr_area = building.floorArea * 10.764 # change from m2 to ft2
1187
1275
 
1188
1276
  if timeseries_name == 'Natural_Gas_Emissions_Intensity'
1189
1277
  newVals = Array.new(n, 0)
1190
1278
  (0..n - 1).each do |j|
1191
- newVals[j] = (((nat_gas_val * (values[tsToKeepIndexes['NaturalGas:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f ) * conv_kg_mt.to_f ) * 1000 / flr_area) # unit: kg/ft2 - changed mt to kg
1279
+ newVals[j] = (((nat_gas_val * (values[tsToKeepIndexes['NaturalGas:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f) * conv_kg_mt.to_f) * 1000 / flr_area) # unit: kg/ft2 - changed mt to kg
1192
1280
  j += 1
1193
1281
  end
1194
1282
  new_unit = 'KG/FT2'
@@ -1201,7 +1289,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
1201
1289
  if timeseries_name == 'Propane_Emissions_Intensity'
1202
1290
  newVals = Array.new(n, 0)
1203
1291
  (0..n - 1).each do |j|
1204
- newVals[j] = (((lpg_val * (values[tsToKeepIndexes['Propane:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f ) * conv_kg_mt.to_f ) * 1000 / flr_area) # unit: kg/ft2 - changed mt to kg
1292
+ newVals[j] = (((lpg_val * (values[tsToKeepIndexes['Propane:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f) * conv_kg_mt.to_f) * 1000 / flr_area) # unit: kg/ft2 - changed mt to kg
1205
1293
  j += 1
1206
1294
  end
1207
1295
  new_unit = 'KG/FT2'
@@ -1214,7 +1302,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
1214
1302
  if timeseries_name == 'FuelOilNo2_Emissions_Intensity'
1215
1303
  newVals = Array.new(n, 0)
1216
1304
  (0..n - 1).each do |j|
1217
- newVals[j] = (((fo2_val * (values[tsToKeepIndexes['FuelOilNo2:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f ) * conv_kg_mt.to_f ) * 1000 / flr_area) # unit: kg/ft2 - changed mt to kg
1305
+ newVals[j] = (((fo2_val * (values[tsToKeepIndexes['FuelOilNo2:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f) * conv_kg_mt.to_f) * 1000 / flr_area) # unit: kg/ft2 - changed mt to kg
1218
1306
  j += 1
1219
1307
  end
1220
1308
  new_unit = 'KG/FT2'
@@ -1280,8 +1368,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
1280
1368
  end
1281
1369
  end
1282
1370
  end
1283
- end
1284
-
1371
+ end
1285
1372
 
1286
1373
  # append units to headers
1287
1374
  new_timeseries_name += "(#{new_unit})"
@@ -1414,7 +1501,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
1414
1501
  end
1415
1502
  end
1416
1503
 
1417
- puts "values = #{values}"
1504
+ #puts "values = #{values}"
1418
1505
 
1419
1506
  # closing the sql file
1420
1507
  sql_file.close
@@ -1425,8 +1512,8 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
1425
1512
  feature_report.timeseries_csv.first_report_datetime = '0'
1426
1513
  feature_report.timeseries_csv.column_names = final_timeseries_names
1427
1514
 
1428
- ##### Save the 'default_feature_reports.json' file
1429
1515
 
1516
+ ##### Save the 'default_feature_reports.json' file
1430
1517
  feature_report_hash = feature_report.to_hash
1431
1518
 
1432
1519
  File.open('default_feature_reports.json', 'w') do |f|
@@ -210,7 +210,7 @@ module URBANopt
210
210
  ##
211
211
  # [parameters:]
212
212
  #
213
- # * +hash+ - _Hash_ - A hash containting key/value pairs for the distributed generation system attributes listed above.
213
+ # * +hash+ - _Hash_ - A hash containing key/value pairs for the distributed generation system attributes listed above.
214
214
  #
215
215
  def initialize(hash = {})
216
216
  hash.delete_if { |k, v| v.nil? }
@@ -63,7 +63,7 @@ module URBANopt
63
63
  # The DefaultPostProcessor reads these feature reports and aggregates them to create a ScenarioReport.
64
64
  ##
65
65
  class FeatureReport
66
- attr_accessor :id, :name, :directory_name, :feature_type, :timesteps_per_hour, :simulation_status,
66
+ attr_accessor :id, :name, :directory_name, :feature_type, :timesteps_per_hour, :simulation_status, :qaqc_flags,
67
67
  :timeseries_csv, :location, :program, :design_parameters, :construction_costs, :reporting_periods, :distributed_generation, :power_distribution, :thermal_storage # :nodoc:
68
68
 
69
69
  ##
@@ -82,6 +82,7 @@ module URBANopt
82
82
  @feature_type = hash[:feature_type]
83
83
  @timesteps_per_hour = hash[:timesteps_per_hour]
84
84
  @simulation_status = hash[:simulation_status]
85
+ @qaqc_flags = QAQC.new(hash[:qaqc_flags])
85
86
  @timeseries_csv = TimeseriesCSV.new(hash[:timeseries_csv])
86
87
  @timeseries_csv.run_dir_name(@directory_name)
87
88
  @location = Location.new(hash[:location])
@@ -124,6 +125,7 @@ module URBANopt
124
125
  hash[:distributed_generation] = {}
125
126
  hash[:power_distribution] = {}
126
127
  hash[:thermal_storage] = {}
128
+ hash[:qaqc_flags] = {}
127
129
  return hash
128
130
  end
129
131
 
@@ -227,6 +229,8 @@ module URBANopt
227
229
 
228
230
  result[:thermal_storage] = @thermal_storage.to_hash if @thermal_storage
229
231
 
232
+ result[:qaqc_flags] = @qaqc_flags.to_hash if @qaqc_flags
233
+
230
234
  # validate feature_report properties against schema
231
235
  if @@validator.validate(@@schema[:definitions][:FeatureReport][:properties], result).any?
232
236
  raise "feature_report properties does not match schema: #{@@validator.validate(@@schema[:definitions][:FeatureReport][:properties], result)}"
@@ -44,6 +44,8 @@ module URBANopt
44
44
  module Reporting
45
45
  module DefaultReports
46
46
  @@logger = Logger.new($stdout)
47
+
48
+ @@logger.level = Logger::WARN
47
49
  ##
48
50
  # Definining class variable "@@logger" to log errors, info and warning messages.
49
51
  def self.logger
@@ -0,0 +1,182 @@
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.
39
+ # *********************************************************************************
40
+
41
+ require 'json'
42
+ require 'json-schema'
43
+
44
+ module URBANopt
45
+ module Reporting
46
+ module DefaultReports
47
+ ##
48
+ # QAQC flags for each feature
49
+ ##
50
+ class QAQC
51
+ ##
52
+ # _Hash_ - Hash of flags raised by QAQC measure for this feature during this reporting period
53
+ #
54
+ attr_accessor :eui_reasonableness,:end_use_by_category,:mechanical_system_part_load_efficiency,
55
+ :simultaneous_heating_and_cooling , :internal_loads , :schedules, :envelope_r_value,
56
+ :domestic_hot_water , :mechanical_system_efficiency , :supply_and_zone_air_temperature,
57
+ :total_qaqc_flags
58
+
59
+ ##
60
+ # QAQC class initialize quaqc attributes: +:eui_reasonableness,+:end_use_by_category,+:mechanical_system_part_load_efficiency,
61
+ # +:simultaneous_heating_and_cooling , +:internal_loads , +:schedules, +:envelope_r_value,
62
+ # +:domestic_hot_water , +:mechanical_system_efficiency , +:supply_and_zone_air_temperature, +:total_qaqc_flags
63
+ ##
64
+ # [parameters:]
65
+ #
66
+ # * +hash+ - _Hash_ - A hash containing qaqc attributes listed above.
67
+ #
68
+ def initialize(hash = {})
69
+ hash.delete_if { |k, v| v.nil? }
70
+ hash = defaults.merge(hash)
71
+
72
+ @eui_reasonableness = hash[:eui_reasonableness]
73
+ @end_use_by_category = hash[:end_use_by_category]
74
+ @mechanical_system_part_load_efficiency = hash[:mechanical_system_part_load_efficiency]
75
+ @simultaneous_heating_and_cooling = hash[:simultaneous_heating_and_cooling]
76
+ @supply_and_zone_air_temperature = hash[:supply_and_zone_air_temperature]
77
+ @internal_loads = hash[:internal_loads]
78
+ @schedules = hash[:schedules]
79
+ @envelope_r_value = hash[:envelope_r_value]
80
+ @domestic_hot_water = hash[:domestic_hot_water]
81
+ @mechanical_system_efficiency = hash[:mechanical_system_efficiency]
82
+ @total_qaqc_flags = hash[:total_qaqc_flags]
83
+
84
+
85
+ # initialize class variables @@validator and @@schema
86
+ @@validator ||= Validator.new
87
+ @@schema ||= @@validator.schema
88
+
89
+ end
90
+
91
+
92
+ ##
93
+ # Assigns default values if values do not exist.
94
+ ##
95
+ def defaults
96
+ hash = {}
97
+
98
+ hash[:eui_reasonableness] = nil
99
+ hash[:end_use_by_category] = nil
100
+ hash[:mechanical_system_part_load_efficiency] = nil
101
+ hash[:simultaneous_heating_and_cooling] = nil
102
+ hash[:supply_and_zone_air_temperature] = nil
103
+ hash[:internal_loads] = nil
104
+ hash[:schedules] = nil
105
+ hash[:envelope_r_value] = nil
106
+ hash[:domestic_hot_water] = nil
107
+ hash[:mechanical_system_efficiency] = nil
108
+ hash[:total_qaqc_flags] = nil
109
+
110
+
111
+ return hash
112
+ end
113
+ ##
114
+ # Convert to a Hash equivalent for JSON serialization
115
+ ##
116
+ def to_hash
117
+ result = {}
118
+
119
+ result[:eui_reasonableness] = @eui_reasonableness
120
+ result[:end_use_by_category] = @end_use_by_category
121
+ result[:mechanical_system_part_load_efficiency] = @mechanical_system_part_load_efficiency
122
+ result[:simultaneous_heating_and_cooling] = @simultaneous_heating_and_cooling
123
+ result[:supply_and_zone_air_temperature] = @supply_and_zone_air_temperature
124
+ result[:internal_loads] = @internal_loads
125
+ result[:schedules] = @schedules
126
+ result[:envelope_r_value] = @envelope_r_value
127
+ result[:domestic_hot_water] = @domestic_hot_water
128
+ result[:mechanical_system_efficiency] = @mechanical_system_efficiency
129
+ result[:total_qaqc_flags] = @total_qaqc_flags
130
+
131
+ # validate program properties against schema
132
+ if @@validator.validate(@@schema[:definitions][:qaqc_flags][:properties], result).any?
133
+ raise "qaqc properties does not match schema: #{@@validator.validate(@@schema[:definitions][:qaqc_flags][:properties], result)}"
134
+ end
135
+
136
+ return result
137
+
138
+ end
139
+
140
+ ##
141
+ # Adds up +existing_value+ and +new_values+ if not nill.
142
+ ##
143
+ # [parameters:]
144
+ # +existing_value+ - _Float_ - A value corresponding to a qaqc_flags attribute.
145
+ ##
146
+ # +new_value+ - _Float_ - A value corresponding to a qaqc_flags attribute.
147
+ ##
148
+ def add_values(existing_value, new_value) #:nodoc:
149
+ if existing_value && new_value
150
+ existing_value += new_value
151
+ elsif new_value
152
+ existing_value = new_value
153
+ end
154
+ return existing_value
155
+ end
156
+
157
+ ##
158
+ # Merges qaqc_flags objects to each other by summing up values.
159
+ ##
160
+ # [parameters:]
161
+ # +other+ - _QAQC_ - An object of Program class.
162
+ ##
163
+ def add_qaqc_flags(other)
164
+
165
+ @eui_reasonableness = add_values(@eui_reasonableness, other.eui_reasonableness)
166
+ @end_use_by_category = add_values(@end_use_by_category, other.end_use_by_category)
167
+ @mechanical_system_part_load_efficiency = add_values(@mechanical_system_part_load_efficiency, other.mechanical_system_part_load_efficiency)
168
+ @simultaneous_heating_and_cooling = add_values(@simultaneous_heating_and_cooling, other.simultaneous_heating_and_cooling)
169
+ @supply_and_zone_air_temperature = add_values(@supply_and_zone_air_temperature, other.supply_and_zone_air_temperature)
170
+ @internal_loads = add_values(@internal_loads, other.internal_loads)
171
+ @schedules = add_values(@schedules, other.schedules)
172
+ @envelope_r_value = add_values(@envelope_r_value, other.envelope_r_value)
173
+ @domestic_hot_water = add_values(@domestic_hot_water, other.domestic_hot_water)
174
+ @mechanical_system_efficiency = add_values(@mechanical_system_efficiency, other.mechanical_system_efficiency)
175
+ @total_qaqc_flags = add_values(@total_qaqc_flags, other.total_qaqc_flags)
176
+
177
+ end
178
+
179
+ end
180
+ end
181
+ end
182
+ end