diff --git a/.gitignore b/.gitignore
index 2e9aab16..b80896f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,11 @@
/pkg/
/spec/reports/
/tmp/
+.DS_Store
+
+# local dev IDE settings
+.vscode/
+.idea/
# rbenv virtualenv management file
.ruby-version
@@ -13,4 +18,8 @@
# rspec failure tracking
.rspec_status
-Gemfile.lock
\ No newline at end of file
+# rspec test folder
+spec/test_directory
+
+Gemfile.lock
+.rubocop*
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6bdcf500..33c35429 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,19 @@
# Changelog
+## Version 0.2.3
+
+Date Range: 04/01/20 - 04/23/20:
+
+- Fixed [#65]( https://github.com/urbanopt/urbanopt-cli/issues/65 ), Add more tests
+- Fixed [#81]( https://github.com/urbanopt/urbanopt-cli/issues/81 ), Mappers weren't updated for version 0.2
+- Fixed [#83]( https://github.com/urbanopt/urbanopt-cli/issues/83 ), Recommend using absolute paths
+- Fixed [#85]( https://github.com/urbanopt/urbanopt-cli/issues/85 ), reopt dependency not installed
+- Fixed [#88]( https://github.com/urbanopt/urbanopt-cli/issues/88 ), Reopt tests are failing
+- Fixed [#90]( https://github.com/urbanopt/urbanopt-cli/issues/90 ), Update baseline mapper
+- Fixed [#92]( https://github.com/urbanopt/urbanopt-cli/issues/92 ), baseline mapper bug reading json file
+
## Version 0.2.2
+
Date Range: 3/31/20 - 3/31/20
- Fixing simplecov / json native extension dependency
diff --git a/Gemfile b/Gemfile
index 0a7c0791..3fe63f31 100644
--- a/Gemfile
+++ b/Gemfile
@@ -6,7 +6,6 @@ gemspec
# simplecov has a dependency on native json gem, use fork that does not require this
gem 'certified'
gem 'simplecov', github: 'NREL/simplecov'
-gem 'urbanopt-reopt', '0.2.0'
# Local gems are useful when developing and integrating the various dependencies.
# To favor the use of local gems, set the following environment variable:
@@ -38,23 +37,31 @@ allow_local = ENV['FAVOR_LOCAL_GEMS']
# gem 'openstudio-model-articulation', github: 'NREL/openstudio-model-articulation-gem', branch: 'develop'
# end
-if allow_local && File.exist?('../urbanopt-scenario-gem')
- gem 'urbanopt-scenario', path: '../urbanopt-scenario-gem'
-elsif allow_local
- gem 'urbanopt-scenario', github: 'URBANopt/urbanopt-scenario-gem', branch: 'develop'
-else
- gem 'urbanopt-scenario', '0.2.0'
- # temporary
- # gem 'urbanopt-scenario', github: 'URBANopt/urbanopt-scenario-gem', branch: 'develop'
-end
-
-if allow_local && File.exist?('../urbanopt-geojson-gem')
- # gem 'openstudio-extension', github: 'NREL/OpenStudio-extension-gem', branch: 'develop'
- gem 'urbanopt-geojson', path: '../urbanopt-geojson-gem'
-elsif allow_local
- gem 'urbanopt-geojson', github: 'URBANopt/urbanopt-geojson-gem', branch: 'develop'
-else
- gem 'urbanopt-geojson', '0.2.0'
- # temporary
- # gem 'urbanopt-scenario', github: 'URBANopt/urbanopt-scenario-gem', branch: 'develop'
-end
+# if allow_local && File.exist?('../urbanopt-scenario-gem')
+# gem 'urbanopt-scenario', path: '../urbanopt-scenario-gem'
+# elsif allow_local
+# gem 'urbanopt-scenario', github: 'URBANopt/urbanopt-scenario-gem', branch: 'develop'
+# else
+# gem 'urbanopt-scenario', '0.2.0'
+# # temporary
+# # gem 'urbanopt-scenario', github: 'URBANopt/urbanopt-scenario-gem', branch: 'develop'
+# end
+
+# if allow_local && File.exist?('../urbanopt-geojson-gem')
+# # gem 'openstudio-extension', github: 'NREL/OpenStudio-extension-gem', branch: 'develop'
+# gem 'urbanopt-geojson', path: '../urbanopt-geojson-gem'
+# elsif allow_local
+# gem 'urbanopt-geojson', github: 'URBANopt/urbanopt-geojson-gem', branch: 'develop'
+# else
+# gem 'urbanopt-geojson', '0.2.0'
+# # temporary
+# # gem 'urbanopt-scenario', github: 'URBANopt/urbanopt-scenario-gem', branch: 'develop'
+# end
+
+# if allow_local && File.exist?('../urbanopt-reopt-gem')
+# gem 'urbanopt-reopt', path: '../urbanopt-reopt-gem'
+# elsif allow_local
+# gem 'urbanopt-reopt', github: 'URBANopt/urbanopt-reopt-gem', branch: 'develop'
+# else
+# gem 'urbanopt-reopt', '0.2.1'
+# end
diff --git a/example_files/Gemfile b/example_files/Gemfile
index 2fbe399b..995aaa03 100644
--- a/example_files/Gemfile
+++ b/example_files/Gemfile
@@ -46,7 +46,7 @@ allow_local = ENV['FAVOR_LOCAL_GEMS']
# gem 'openstudio-model-articulation', '0.1.0'
# end
-gem 'urbanopt-reopt', '0.2.0'
+gem 'urbanopt-reopt', '0.2.1'
if allow_local && File.exist?('../urbanopt-scenario-gem')
gem 'urbanopt-scenario', path: '../urbanopt-scenario-gem'
@@ -54,21 +54,18 @@ elsif allow_local
gem 'urbanopt-scenario', github: 'URBANopt/urbanopt-scenario-gem', branch: 'develop'
else
gem 'urbanopt-scenario', '0.2.0'
- # gem 'urbanopt-scenario', github: 'URBANopt/urbanopt-scenario-gem', branch: 'develop'
end
if allow_local && File.exist?('../urbanopt-geojson-gem')
- # gem 'openstudio-extension', github: 'NREL/OpenStudio-extension-gem', branch: 'develop'
gem 'urbanopt-geojson', path: '../urbanopt-geojson-gem'
elsif allow_local
gem 'urbanopt-geojson', github: 'URBANopt/urbanopt-geojson-gem', branch: 'develop'
else
gem 'urbanopt-geojson', '0.2.0'
- # gem 'urbanopt-geojson', github: 'URBANopt/urbanopt-geojson-gem', branch: 'develop'
end
# simplecov has an unneccesary dependency on native json gem, use fork that does not require this
gem 'simplecov', github: 'NREL/simplecov'
-# Fix rack version temporarily to work with Ruby 2.2.4
+# Specify exact rack version temporarily to work with Ruby 2.2.4
gem 'rack', '2.1.2'
diff --git a/example_files/example_project.json b/example_files/example_project.json
index d329944f..0e945828 100644
--- a/example_files/example_project.json
+++ b/example_files/example_project.json
@@ -13,7 +13,7 @@
"cec_climate_zone": null,
"climate_zone": "6A",
"default_template": "90.1-2013",
- "end_date": "2017-13-31T07:00:00.000Z",
+ "end_date": "2017-12-31T07:00:00.000Z",
"id": "53340c2c-ab20-40db-aba1-11ac607c52a7",
"import_surrounding_buildings_as_shading": null,
"name": "Site Origin",
diff --git a/example_files/mappers/Baseline.rb b/example_files/mappers/Baseline.rb
index 2932687d..f9e8b3f7 100644
--- a/example_files/mappers/Baseline.rb
+++ b/example_files/mappers/Baseline.rb
@@ -67,61 +67,61 @@ def lookup_building_type(building_type, template, footprint_area, number_of_stor
if template.include? 'DEER'
case building_type
when 'Education'
- 'EPr'
+ return 'EPr'
when 'Enclosed mall'
- 'RtL'
+ return 'RtL'
when 'Food sales'
- 'RSD'
+ return 'RSD'
when 'Food service'
- 'RSD'
+ return 'RSD'
when 'Inpatient health care'
- 'Nrs'
+ return 'Nrs'
when 'Laboratory'
- 'Hsp'
+ return 'Hsp'
when 'Lodging'
- 'Htl'
+ return 'Htl'
when 'Mixed use'
- 'ECC'
+ return 'ECC'
when 'Mobile Home'
- 'DMo'
+ return 'DMo'
when 'Multifamily (2 to 4 units)'
- 'MFm'
+ return 'MFm'
when 'Multifamily (5 or more units)'
- 'MFm'
+ return 'MFm'
when 'Nonrefrigerated warehouse'
- 'SUn'
+ return 'SUn'
when 'Nursing'
- 'Nrs'
+ return 'Nrs'
when 'Office'
if footprint_area
- if footprint_area.to_f > 100_000
- 'OfL'
+ if footprint_area.to_f > 100000
+ return 'OfL'
else
- 'OfS'
+ return 'OfS'
end
else
raise 'footprint_area required to map office building type'
end
when 'Outpatient health care'
- 'Nrs'
+ return 'Nrs'
when 'Public assembly'
- 'Asm'
+ return 'Asm'
when 'Public order and safety'
- 'Asm'
+ return 'Asm'
when 'Refrigerated warehouse'
- 'WRf'
+ return 'WRf'
when 'Religious worship'
- 'Asm'
+ return 'Asm'
when 'Retail other than mall'
- 'RtS'
+ return 'RtS'
when 'Service'
- 'MLI'
+ return 'MLI'
when 'Single-Family'
- 'MFm'
+ return 'MFm'
when 'Strip shopping mall'
- 'RtL'
+ return 'RtL'
when 'Vacant'
- 'SUn'
+ return 'SUn'
else
raise "building type #{building_type} cannot be mapped to a DEER building type"
end
@@ -130,17 +130,17 @@ def lookup_building_type(building_type, template, footprint_area, number_of_stor
# default: ASHRAE
case building_type
when 'Education'
- 'SecondarySchool'
+ return 'SecondarySchool'
when 'Enclosed mall'
- 'RetailStripmall'
+ return 'RetailStripmall'
when 'Food sales'
- 'FullServiceRestaurant'
+ return 'FullServiceRestaurant'
when 'Food service'
- 'FullServiceRestaurant'
+ return 'FullServiceRestaurant'
when 'Inpatient health care'
- 'Hospital'
+ return 'Hospital'
when 'Laboratory'
- 'Hospital'
+ return 'Hospital'
when 'Lodging'
if number_of_stories
if number_of_stories.to_i > 3
@@ -149,51 +149,51 @@ def lookup_building_type(building_type, template, footprint_area, number_of_stor
return 'SmallHotel'
end
end
- 'LargeHotel'
+ return 'LargeHotel'
when 'Mixed use'
- 'Mixed use'
+ return 'Mixed use'
when 'Mobile Home'
- 'MidriseApartment'
+ return 'MidriseApartment'
when 'Multifamily (2 to 4 units)'
- 'MidriseApartment'
+ return 'MidriseApartment'
when 'Multifamily (5 or more units)'
- 'MidriseApartment'
+ return 'MidriseApartment'
when 'Nonrefrigerated warehouse'
- 'Warehouse'
+ return 'Warehouse'
when 'Nursing'
- 'Outpatient'
+ return 'Outpatient'
when 'Office'
if footprint_area
- value = if footprint_area.to_f < 20_000
- 'SmallOffice'
- elsif footprint_area.to_f > 100_000
- 'LargeOffice'
- else
- 'MediumOffice'
- end
+ if footprint_area.to_f < 20000
+ value = 'SmallOffice'
+ elsif footprint_area.to_f > 100000
+ value = 'LargeOffice'
+ else
+ value = 'MediumOffice'
+ end
else
raise 'Floor area required to map office building type'
end
when 'Outpatient health care'
- 'Outpatient'
+ return 'Outpatient'
when 'Public assembly'
- 'MediumOffice'
+ return 'MediumOffice'
when 'Public order and safety'
- 'MediumOffice'
+ return 'MediumOffice'
when 'Refrigerated warehouse'
- 'Warehouse'
+ return 'Warehouse'
when 'Religious worship'
- 'MediumOffice'
+ return 'MediumOffice'
when 'Retail other than mall'
- 'RetailStandalone'
+ return 'RetailStandalone'
when 'Service'
- 'MediumOffice'
+ return 'MediumOffice'
when 'Single-Family'
- 'MidriseApartment'
+ return 'MidriseApartment'
when 'Strip shopping mall'
- 'RetailStripmall'
+ return 'RetailStripmall'
when 'Vacant'
- 'Warehouse'
+ return 'Warehouse'
else
raise "building type #{building_type} cannot be mapped to an ASHRAE building type"
end
@@ -203,38 +203,38 @@ def lookup_building_type(building_type, template, footprint_area, number_of_stor
def lookup_template_by_year_built(template, year_built)
if template.include? 'DEER'
if year_built <= 1996
- 'DEER 1985'
+ return 'DEER 1985'
elsif year_built <= 2003
- 'DEER 1996'
+ return 'DEER 1996'
elsif year_built <= 2007
- 'DEER 2003'
+ return 'DEER 2003'
elsif year_built <= 2011
- 'DEER 2007'
+ return 'DEER 2007'
elsif year_built <= 2014
- 'DEER 2011'
+ return 'DEER 2011'
elsif year_built <= 2015
- 'DEER 2014'
+ return 'DEER 2014'
elsif year_built <= 2017
- 'DEER 2015'
+ return 'DEER 2015'
elsif year_built <= 2020
- 'DEER 2017'
+ return 'DEER 2017'
else
- 'DEER 2020'
+ return 'DEER 2020'
end
else
# ASHRAE
if year_built < 1980
- 'DOE Ref Pre-1980'
+ return 'DOE Ref Pre-1980'
elsif year_built <= 2004
- 'DOE Ref 1980-2004'
+ return 'DOE Ref 1980-2004'
elsif year_built <= 2007
- '90.1-2004'
+ return '90.1-2004'
elsif year_built <= 2010
- '90.1-2007'
+ return '90.1-2007'
elsif year_built <= 2013
- '90.1-2010'
+ return '90.1-2010'
else
- '90.1-2013'
+ return '90.1-2013'
end
end
end
@@ -247,7 +247,9 @@ def create_osw(scenario, features, feature_names)
feature_id = feature.id
feature_type = feature.type
feature_name = feature.name
- feature_name = feature_names[0] if feature_names.size == 1
+ if feature_names.size == 1
+ feature_name = feature_names[0]
+ end
# deep clone of @@osw before we configure it
osw = Marshal.load(Marshal.dump(@@osw))
@@ -261,17 +263,17 @@ def create_osw(scenario, features, feature_names)
# set_run_period
begin
timesteps_per_hour = feature.timesteps_per_hour
- unless timesteps_per_hour.empty?
+ if timesteps_per_hour
OpenStudio::Extension.set_measure_argument(osw, 'set_run_period', 'timesteps_per_hour', timesteps_per_hour)
end
rescue StandardError
end
begin
begin_date = feature.begin_date
- unless feature.begin_date.empty?
+ if begin_date
# check date-only YYYY-MM-DD
- if feature.begin_date.length > 10
- feature.begin_date = feature.begin_date[0, 10]
+ if begin_date.length > 10
+ begin_date = begin_date[0, 10]
end
OpenStudio::Extension.set_measure_argument(osw, 'set_run_period', 'begin_date', begin_date)
end
@@ -279,10 +281,10 @@ def create_osw(scenario, features, feature_names)
end
begin
end_date = feature.end_date
- unless feature.end_date.empty?
+ if end_date
# check date-only YYYY-MM-DD
- if feature.end_date.length > 10
- feature.end_date = feature.end_date[0, 10]
+ if end_date.length > 10
+ end_date = end_date[0, 10]
end
OpenStudio::Extension.set_measure_argument(osw, 'set_run_period', 'end_date', end_date)
end
@@ -366,11 +368,21 @@ def create_osw(scenario, features, feature_names)
end
floor_height = 10
- system_type = if building_hash.key?(:system_type)
- building_hash[:system_type]
- else
- 'Inferred'
- end
+ # Map system type to openstudio system types
+ # TODO: Map all system types
+ if building_hash.key?(:system_type)
+ system_type = building_hash[:system_type]
+ case system_type
+ when 'Fan coil district hot and chilled water'
+ system_type = 'Fan coil district chilled water with district hot water'
+ when 'Fan coil air-cooled chiller and boiler'
+ system_type = 'Fan coil air-cooled chiller with boiler'
+ when 'VAV with gas reheat'
+ system_type = 'VAV air-cooled chiller with gas boiler reheat'
+ end
+ else
+ system_type = 'Inferred'
+ end
def time_mapping(time)
hour = time.split(':')[0]
@@ -379,7 +391,7 @@ def time_mapping(time)
fraction_roundup = fraction.round(2)
minute_fraction = fraction_roundup.to_s.split('.')[1]
new_time = [hour, minute_fraction].join('.')
- new_time
+ return new_time
end
# ChangeBuildingLocation
@@ -390,17 +402,23 @@ def time_mapping(time)
cec_found = false
begin
cec_climate_zone = feature.cec_climate_zone
- unless cec_climate_zone.empty?
+ if !cec_climate_zone.empty?
cec_climate_zone = 'T24-CEC' + cec_climate_zone
OpenStudio::Extension.set_measure_argument(osw, 'ChangeBuildingLocation', 'climate_zone', cec_climate_zone)
cec_found = true
+ # Temporary fix for CEC climate zone:
+ cec_modified_zone = 'CEC ' + cec_climate_zone
+ OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'climate_zone', cec_modified_zone)
+ OpenStudio::Extension.set_measure_argument(osw, 'create_typical_building_from_model', 'climate_zone', cec_modified_zone, 'create_typical_building_from_model 1')
+ OpenStudio::Extension.set_measure_argument(osw, 'create_typical_building_from_model', 'climate_zone', cec_modified_zone, 'create_typical_building_from_model 2')
+
end
rescue StandardError
end
- unless cec_found
+ if !cec_found
begin
climate_zone = feature.climate_zone
- unless climate_zone.empty?
+ if !climate_zone.empty?
climate_zone = 'ASHRAE 169-2013-' + climate_zone
OpenStudio::Extension.set_measure_argument(osw, 'ChangeBuildingLocation', 'climate_zone', climate_zone)
end
@@ -430,7 +448,7 @@ def time_mapping(time)
# set weekday start time
begin
weekday_start_time = feature.weekday_start_time
- unless feature.weekday_start_time.empty?
+ if !feature.weekday_start_time.empty?
new_weekday_start_time = time_mapping(weekday_start_time)
OpenStudio::Extension.set_measure_argument(osw, 'create_typical_building_from_model', 'wkdy_op_hrs_start_time', new_weekday_start_time, 'create_typical_building_from_model 1')
end
@@ -440,7 +458,7 @@ def time_mapping(time)
# set weekday duration
begin
weekday_duration = feature.weekday_duration
- unless feature.weekday_duration.empty?
+ if !feature.weekday_duration.empty?
new_weekday_duration = time_mapping(weekday_duration)
OpenStudio::Extension.set_measure_argument(osw, 'create_typical_building_from_model', 'wkdy_op_hrs_duration', new_weekday_duration, 'create_typical_building_from_model 1')
end
@@ -450,7 +468,7 @@ def time_mapping(time)
# set weekend start time
begin
weekend_start_time = feature.weekend_start_time
- unless feature.weekend_start_time.empty?
+ if !feature.weekend_start_time.empty?
new_weekend_start_time = time_mapping(weekend_start_time)
OpenStudio::Extension.set_measure_argument(osw, 'create_typical_building_from_model', 'wknd_op_hrs_start_time', new_weekend_start_time, 'create_typical_building_from_model 1')
end
@@ -460,7 +478,7 @@ def time_mapping(time)
# set weekend duration
begin
weekend_duration = feature.weekend_duration
- unless feature.weekend_duration.empty?
+ if !feature.weekend_duration.empty?
new_weekend_duration = time_mapping(weekend_duration)
OpenStudio::Extension.set_measure_argument(osw, 'create_typical_building_from_model', 'wknd_op_hrs_duration', new_weekend_duration, 'create_typical_building_from_model 1')
end
@@ -546,7 +564,7 @@ def time_mapping(time)
OpenStudio::Extension.set_measure_argument(osw, 'default_feature_reports', 'feature_type', feature_type)
end
- osw
+ return osw
end
end # BaselineMapper
end # Scenario
diff --git a/example_files/mappers/HighEfficiency.rb b/example_files/mappers/HighEfficiency.rb
index 32e7e60e..81c3a391 100644
--- a/example_files/mappers/HighEfficiency.rb
+++ b/example_files/mappers/HighEfficiency.rb
@@ -51,7 +51,7 @@ def create_osw(scenario, features, feature_names)
OpenStudio::Extension.set_measure_argument(osw, 'ReduceLightingLoadsByPercentage', '__SKIP__', false)
OpenStudio::Extension.set_measure_argument(osw, 'ReduceLightingLoadsByPercentage', 'lighting_power_reduction_percent', 10)
- osw
+ return osw
end
end
end
diff --git a/lib/uo_cli.rb b/lib/uo_cli.rb
index e2a36d30..19a2d408 100755
--- a/lib/uo_cli.rb
+++ b/lib/uo_cli.rb
@@ -46,7 +46,7 @@ module CLI
# Set up user interface
@user_input = {}
the_parser = OptionParser.new do |opts|
- opts.banner = "Usage: uo [-peomrgdsfitv]\n" \
+ opts.banner = "\nUsage: uo [-peomrgdsfitv]\n" \
"\n" \
"URBANopt CLI\n" \
"First create a project folder with -p, then run additional commands as desired\n" \
@@ -54,60 +54,60 @@ module CLI
opts.separator ''
opts.on('-p', '--project_folder
', String, "Create project directory named in your current folder\n" \
- ' You must be inside the project directory you just created for all following commands to work') do |folder|
+ " Fewer warnings are presented when using full paths and the user is not inside the project folder\n\n") do |folder|
@user_input[:project_folder] = folder
end
opts.on('-e', '--empty_project_folder', String, "Use with -p argument to create an empty project folder\n" \
" Example: uo -e -p \n" \
" Then add your own Feature file in the project directory you created,\n" \
- " add Weather files in the weather folder and add OpenStudio models of Features \n" \
- " in the Feature File, if any in the osm_building folder \n" \
- ' You must be inside the project directory you just created for all following commands to work') do
+ " add Weather files in the weather folder and add OpenStudio models of Features\n" \
+ " in the Feature File, if any, in the osm_building folder\n" \
+ " Fewer warnings are presented when using full paths and the user is not inside the project folder\n\n") do
@user_input[:empty_project_folder] = 'Create empty project folder' # This text does not get displayed to the user
end
opts.on('-o', '--overwrite_project_folder', String, "Use with -p argument to overwrite existing project folder and replace with new project folder.\n" \
- " Or, use with -e and -p argument to overwrite existing project folder and replace with new empty project folder.\n" \
+ " Or use with -e and -p argument to overwrite existing project folder and replace with new empty project folder.\n" \
" Usage: uo -o -p \n" \
- " or, uo -o -e -p \n" \
- ' Where, is the existing project folder') do
+ " or uo -o -e -p \n" \
+ " Where is the existing project folder\n\n") do
@user_input[:overwrite_project_folder] = 'Overwriting existing project folder' # This text does not get displayed to the user
end
opts.on('-m', '--make_scenario', String, "Create ScenarioCSV files for each MapperFile using the Feature file path. Must specify -f argument\n" \
" Example: uo -m -f example_project.json\n" \
" Or, Create Scenario CSV for each MapperFile for a single Feature from Feature File. Must specify -f and -i argument\n" \
- ' Example: uo -m -f example_project.json -i 1') do
+ " Example: uo -m -f example_project.json -i 1\n\n") do
@user_input[:make_scenario_from] = "Create scenario files from FeatureFiles or for single Feature according to the MapperFiles in the 'mappers' directory" # This text does not get displayed to the user
end
opts.on('-r', '--run', String, "Run simulations. Must specify -s & -f arguments\n" \
- ' Example: uo -r -s baseline_scenario.csv -f example_project.json') do
+ " Example: uo -r -s baseline_scenario.csv -f example_project.json\n\n") do
@user_input[:run_scenario] = 'Run simulations' # This text does not get displayed to the user
end
opts.on('-g', '--gather', String, "group individual feature results to scenario-level results. Must specify -t, -s, & -f arguments\n" \
- ' Example: uo -g -t default -s baseline_scenario.csv -f example_project.json') do
+ " Example: uo -g -t default -s baseline_scenario.csv -f example_project.json\n\n") do
@user_input[:gather] = 'Aggregate all features to a whole Scenario' # This text does not get displayed to the user
end
opts.on('-d', '--delete_scenario', String, "Delete results from scenario. Must specify -s argument\n" \
- ' Example: uo -d -s baseline_scenario.csv') do
+ " Example: uo -d -s baseline_scenario.csv\n\n") do
@user_input[:delete_scenario] = 'Delete scenario results that were created from ' # This text does not get displayed to the user
end
- opts.on('-s', '--scenario_file ', String, 'Specify (ScenarioCSV file path). Used as input for other commands') do |scenario|
+ opts.on('-s', '--scenario_file ', String, "Specify (ScenarioCSV file path). Used as input for other commands\n\n") do |scenario|
@user_input[:scenario] = scenario
@root_dir, @scenario_file_name = File.split(File.absolute_path(@user_input[:scenario]))
end
- opts.on('-f', '--feature_file ', String, 'Specify (Feature file path). Used as input for other commands') do |feature|
+ opts.on('-f', '--feature_file ', String, "Specify (Feature file path). Used as input for other commands\n\n") do |feature|
@user_input[:feature] = feature
@feature_path, @feature_name = File.split(File.absolute_path(@user_input[:feature]))
end
- opts.on('-i', '--feature_id ', Integer, 'Specify (Feature ID). Used as input for other commands') do |feature_id|
+ opts.on('-i', '--feature_id ', Integer, "Specify (Feature ID). Used as input for other commands\n\n") do |feature_id|
@user_input[:feature_id] = feature_id
end
@@ -115,11 +115,11 @@ module CLI
" default\n" \
" reopt-scenario\n" \
" reopt-feature\n" \
- " opendss\n") do |type|
+ " opendss\n\n") do |type|
@user_input[:type] = type
end
- opts.on('-v', '--version', 'Show CLI version and exit') do
+ opts.on('-v', '--version', "Show CLI version and exit\n") do
@user_input[:version_request] = VERSION
end
end
@@ -176,10 +176,10 @@ def self.create_scenario_csv_file(feature_id)
if feature_id == 'SKIP'
# ensure that feature is a building
if feature[:properties][:type] == 'Building'
- csv << [feature[:properties][:id], feature[:properties][:name], "URBANopt::Scenario::#{mapper_name}Mapper", 'base_assumptions.json']
- end
+ csv << [feature[:properties][:id], feature[:properties][:name], "URBANopt::Scenario::#{mapper_name}Mapper", 'multiPV_assumptions.json']
+ end
elsif feature_id == feature[:properties][:id].to_i
- csv << [feature[:properties][:id], feature[:properties][:name], "URBANopt::Scenario::#{mapper_name}Mapper", 'base_assumptions.json']
+ csv << [feature[:properties][:id], feature[:properties][:name], "URBANopt::Scenario::#{mapper_name}Mapper", 'multiPV_assumptions.json']
elsif
# If Feature ID specified does not exist in the Feature File raise error
unless feature_file_json[:features].any? { |hash| hash[:properties][:id].include?(feature_id.to_s) }
@@ -201,14 +201,12 @@ def self.create_project_folder(dir_name, empty_folder = false, overwrite_project
if overwrite_project == true
if Dir.exist?(dir_name)
FileUtils.rm_rf(dir_name)
- puts "Overwriting project directory: #{dir_name}\n"
end
elsif overwrite_project == false
if Dir.exist?(dir_name)
abort("\nERROR: there is already a directory here named #{dir_name}... aborting\n---\n\n")
end
end
- puts "CREATING NEW URBANopt project directory: #{dir_name}\n"
Dir.mkdir dir_name
Dir.mkdir File.join(dir_name, 'mappers')
Dir.mkdir File.join(dir_name, 'weather')
@@ -298,28 +296,30 @@ def self.create_project_folder(dir_name, empty_folder = false, overwrite_project
# Perform CLI actions
if @user_input[:project_folder] && @user_input[:empty_project_folder].nil?
if @user_input[:overwrite_project_folder]
+ puts "\nOverwriting existing project folder: #{@user_input[:project_folder]}...\n\n"
+ puts "Creating a new project folder...\n"
create_project_folder(@user_input[:project_folder], empty_folder = false, overwrite_project = true)
- puts "\nOverwriting exiting project folder #{@user_input[:project_folder]}."
- puts "Creating a new project folder.\n"
elsif @user_input[:overwrite_project_folder].nil?
create_project_folder(@user_input[:project_folder], empty_folder = false, overwrite_project = false)
end
puts "\nAn example FeatureFile is included: 'example_project.json'. You may place your own FeatureFile alongside the example."
puts 'Weather data is provided for the example FeatureFile. Additional weather data files may be downloaded from energyplus.net/weather for free'
puts "If you use additional weather files, ensure they are added to the 'weather' directory. You will need to configure your mapper file and your osw file to use the desired weather file"
- puts "Next, move inside your new folder ('cd ') and create ScenarioFiles using this CLI call: 'uo -m -f '\n"
+ puts "Next, create ScenarioFiles using this CLI call: 'uo -m -f '\n"
+ puts "We recommend using absolute paths for all commands, for cleaner output\n"
elsif @user_input[:project_folder] && @user_input[:empty_project_folder]
if @user_input[:overwrite_project_folder]
+ puts "\nOverwriting existing project folder: #{@user_input[:project_folder]}...\n\n"
+ puts "Creating a new project folder...\n\n"
create_project_folder(@user_input[:project_folder], empty_folder = true, overwrite_project = true)
- puts "\nOverwriting exiting project folder #{@user_input[:project_folder]}."
- puts "Creating a new project folder.\n"
elsif @user_input[:overwrite_project].nil?
create_project_folder(@user_input[:project_folder], empty_folder = true, overwrite_project = false)
end
puts 'Add your FeatureFile in the Project directory you just created.'
puts 'Add your weather data files in the Weather folder. They may be downloaded from energyplus.net/weather for free'
puts 'Add your OpenStudio models for Features in your Feature file, if any in the osm_building folder'
- puts "Next, move inside your new folder ('cd ') and create ScenarioFiles using this CLI call: 'uo -m -f '\n"
+ puts "Next, create ScenarioFiles using this CLI call: 'uo -m -f '\n"
+ puts "We recommend using absolute paths for all commands, for cleaner output\n"
end
if @user_input[:make_scenario_from]
@@ -365,10 +365,14 @@ def self.create_project_folder(dir_name, empty_folder = false, overwrite_project
if @user_input[:feature].nil?
abort("\nYou must provide '-f' flag and a valid path to a FeatureFile!\n---\n\n")
end
- if @user_input[:type].nil?
+
+ valid_postprocessors = ['default', 'reopt-scenario', 'reopt-feature', 'opendss']
+ # Abort if is nil or not in valid list
+ if @user_input[:type].nil? || valid_postprocessors.none? { |needle| @user_input[:type].include? needle }
abort("\nYou must provide '-t' flag and a valid Gather type!\n" \
- "Valid types include: 'default', 'reopt-scenario', 'reopt-feature', or 'opendss'\n---\n\n")
+ "Valid types include: #{valid_postprocessors}\n---\n\n")
end
+
@scenario_folder = @scenario_file_name.split('.')[0].capitalize.to_s
default_post_processor = URBANopt::Scenario::ScenarioDefaultPostProcessor.new(run_func)
@@ -378,11 +382,11 @@ def self.create_project_folder(dir_name, empty_folder = false, overwrite_project
# save feature reports
scenario_report.feature_reports.each(&:save_feature_report)
- if @user_input[:type].to_s.casecmp('default').zero?
+ if @user_input[:type] == valid_postprocessors[0]
puts "\nDone\n"
- elsif @user_input[:type].to_s.casecmp('opendss').zero?
+ elsif @user_input[:type] == valid_postprocessors[3]
puts "\nPost-processing OpenDSS results\n"
- opendss_folder = File.join(@root_dir, 'run', @scenario_name.split('.')[0], 'opendss')
+ opendss_folder = File.join(@root_dir, 'run', @scenario_file_name.split('.')[0], 'opendss')
if File.directory?(opendss_folder)
opendss_folder_name = File.basename(opendss_folder)
opendss_post_processor = URBANopt::Scenario::OpenDSSPostProcessor.new(scenario_report, opendss_results_dir_name = opendss_folder_name)
@@ -391,25 +395,23 @@ def self.create_project_folder(dir_name, empty_folder = false, overwrite_project
else
abort("\nNo OpenDSS results available in folder '#{opendss_folder}'\n")
end
- elsif @user_input[:type].to_s.downcase.include?('reopt')
+ elsif @user_input[:type].to_s.include?('reopt')
scenario_base = default_post_processor.scenario_base
reopt_post_processor = URBANopt::REopt::REoptPostProcessor.new(scenario_report, scenario_base.scenario_reopt_assumptions_file, scenario_base.reopt_feature_assumptions, DEVELOPER_NREL_KEY)
# Optimize REopt outputs for the whole Scenario
- if @user_input[:type].to_s.casecmp('reopt-scenario').zero?
+ if @user_input[:type] == valid_postprocessors[1]
puts "\nOptimizing renewable energy for the scenario\n"
scenario_report_scenario = reopt_post_processor.run_scenario_report(scenario_report: scenario_report, save_name: 'scenario_optimization')
puts "\nDone\n"
# Optimize REopt outputs for each feature individually
- elsif @user_input[:type].to_s.casecmp('reopt-feature').zero?
+ elsif @user_input[:type] == valid_postprocessors[2]
puts "\nOptimizing renewable energy for each feature\n"
scenario_report_features = reopt_post_processor.run_scenario_report_features(scenario_report: scenario_report, save_names_feature_reports: ['feature_optimization'] * scenario_report.feature_reports.length, save_name_scenario_report: 'feature_optimization')
puts "\nDone\n"
- else
- abort("\nError: did not use type 'reopt-scenario', 'reopt-feature'. Aborting...\n---\n\n")
end
else
- abort("\nError: did not use type 'default', 'reopt-scenario', 'reopt-feature', or 'opendss'. Aborting...\n---\n\n")
+ abort("\nError: did not use one of these valid types: #{valid_postprocessors} Aborting...\n---\n\n")
end
end
diff --git a/lib/uo_cli/version.rb b/lib/uo_cli/version.rb
index 89502454..8233d3ba 100644
--- a/lib/uo_cli/version.rb
+++ b/lib/uo_cli/version.rb
@@ -1,5 +1,5 @@
module URBANopt
module CLI
- VERSION = '0.2.2'.freeze
+ VERSION = '0.2.3'.freeze
end
end
diff --git a/spec/spec_files/opendss/results/Features/1.csv b/spec/spec_files/opendss/results/Features/1.csv
new file mode 100644
index 00000000..48c57c41
--- /dev/null
+++ b/spec/spec_files/opendss/results/Features/1.csv
@@ -0,0 +1,25 @@
+Datetime,p.u. voltage,overvoltage,undervoltage
+6/1/2012 1:00,4.555190233,TRUE,FALSE
+6/1/2012 2:00,4.576724363,TRUE,FALSE
+6/1/2012 3:00,4.575198032,TRUE,FALSE
+6/1/2012 4:00,4.58951716,TRUE,FALSE
+6/1/2012 5:00,4.576724363,TRUE,FALSE
+6/1/2012 6:00,4.575198032,TRUE,FALSE
+6/1/2012 7:00,4.58951716,TRUE,FALSE
+6/1/2012 8:00,4.740247423,TRUE,FALSE
+6/1/2012 9:00,4.575198032,TRUE,FALSE
+6/1/2012 10:00,4.58951716,TRUE,FALSE
+6/1/2012 11:00,4.740247423,TRUE,FALSE
+6/1/2012 12:00,4.555190233,TRUE,FALSE
+6/1/2012 13:00,4.576724363,TRUE,FALSE
+6/1/2012 14:00,4.575198032,TRUE,FALSE
+6/1/2012 15:00,4.58951716,TRUE,FALSE
+6/1/2012 16:00,4.576724363,TRUE,FALSE
+6/1/2012 17:00,4.575198032,TRUE,FALSE
+6/1/2012 18:00,4.58951716,TRUE,FALSE
+6/1/2012 19:00,4.740247423,TRUE,FALSE
+6/1/2012 20:00,4.575198032,TRUE,FALSE
+6/1/2012 21:00,4.58951716,TRUE,FALSE
+6/1/2012 22:00,4.740247423,TRUE,FALSE
+6/1/2012 23:00,4.58951716,TRUE,FALSE
+6/2/2012 0:00,4.576724363,TRUE,FALSE
diff --git a/spec/spec_files/opendss/results/Features/2.csv b/spec/spec_files/opendss/results/Features/2.csv
new file mode 100644
index 00000000..caa4197a
--- /dev/null
+++ b/spec/spec_files/opendss/results/Features/2.csv
@@ -0,0 +1,25 @@
+Datetime,p.u. voltage,overvoltage,undervoltage
+6/1/2012 1:00,0.207776119,FALSE,TRUE
+6/1/2012 2:00,0.207561748,FALSE,TRUE
+6/1/2012 3:00,0.207828168,FALSE,TRUE
+6/1/2012 4:00,0.200926181,FALSE,TRUE
+6/1/2012 5:00,0.207561748,FALSE,TRUE
+6/1/2012 6:00,0.207828168,FALSE,TRUE
+6/1/2012 7:00,0.200926181,FALSE,TRUE
+6/1/2012 8:00,0.19949719,FALSE,TRUE
+6/1/2012 9:00,0.207828168,FALSE,TRUE
+6/1/2012 10:00,0.200926181,FALSE,TRUE
+6/1/2012 11:00,0.19949719,FALSE,TRUE
+6/1/2012 12:00,0.207776119,FALSE,TRUE
+6/1/2012 13:00,0.207561748,FALSE,TRUE
+6/1/2012 14:00,0.207828168,FALSE,TRUE
+6/1/2012 15:00,0.200926181,FALSE,TRUE
+6/1/2012 16:00,0.207561748,FALSE,TRUE
+6/1/2012 17:00,0.207828168,FALSE,TRUE
+6/1/2012 18:00,0.200926181,FALSE,TRUE
+6/1/2012 19:00,0.19949719,FALSE,TRUE
+6/1/2012 20:00,0.207828168,FALSE,TRUE
+6/1/2012 21:00,0.200926181,FALSE,TRUE
+6/1/2012 22:00,0.19949719,FALSE,TRUE
+6/1/2012 23:00,0.194419535,FALSE,TRUE
+6/2/2012 0:00,0.190254047,FALSE,TRUE
diff --git a/spec/spec_files/opendss/results/Features/3.csv b/spec/spec_files/opendss/results/Features/3.csv
new file mode 100644
index 00000000..b60d0b9f
--- /dev/null
+++ b/spec/spec_files/opendss/results/Features/3.csv
@@ -0,0 +1,25 @@
+Datetime,p.u. voltage,overvoltage,undervoltage
+6/1/2012 1:00,4.555190233,TRUE,FALSE
+6/1/2012 2:00,4.576724363,TRUE,FALSE
+6/1/2012 3:00,4.575198032,TRUE,FALSE
+6/1/2012 4:00,4.58951716,TRUE,FALSE
+6/1/2012 5:00,4.576724363,TRUE,FALSE
+6/1/2012 6:00,4.575198032,TRUE,FALSE
+6/1/2012 7:00,4.58951716,TRUE,FALSE
+6/1/2012 8:00,4.740247423,TRUE,FALSE
+6/1/2012 9:00,4.575198032,TRUE,FALSE
+6/1/2012 10:00,4.58951716,TRUE,FALSE
+6/1/2012 11:00,4.740247423,TRUE,FALSE
+6/1/2012 12:00,4.555190233,TRUE,FALSE
+6/1/2012 13:00,0.207561748,FALSE,TRUE
+6/1/2012 14:00,0.207828168,FALSE,TRUE
+6/1/2012 15:00,0.200926181,FALSE,TRUE
+6/1/2012 16:00,0.207561748,FALSE,TRUE
+6/1/2012 17:00,0.207828168,FALSE,TRUE
+6/1/2012 18:00,0.200926181,FALSE,TRUE
+6/1/2012 19:00,0.19949719,FALSE,TRUE
+6/1/2012 20:00,0.207828168,FALSE,TRUE
+6/1/2012 21:00,0.200926181,FALSE,TRUE
+6/1/2012 22:00,0.19949719,FALSE,TRUE
+6/1/2012 23:00,0.194419535,FALSE,TRUE
+6/2/2012 0:00,0.190254047,FALSE,TRUE
diff --git a/spec/spec_files/opendss/results/Lines/Line.10e9de09-902c-4373-8fa3-06a3e19e8b38.csv b/spec/spec_files/opendss/results/Lines/Line.10e9de09-902c-4373-8fa3-06a3e19e8b38.csv
new file mode 100644
index 00000000..648afa17
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.10e9de09-902c-4373-8fa3-06a3e19e8b38.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,0.0003881576008966183,False
+2019/06/01 00:30:00,0.0003246387244612409,False
+2019/06/01 00:45:00,0.0003221156439635388,False
+2019/06/01 01:00:00,0.0003183032111099563,False
+2019/06/01 01:15:00,0.0003246387244612409,False
+2019/06/01 01:30:00,0.0003221156439635388,False
+2019/06/01 01:45:00,0.0003183032111099563,False
+2019/06/01 02:00:00,0.0003599974412840784,False
+2019/06/01 02:15:00,0.0003221156439635388,False
+2019/06/01 02:30:00,0.0003183032111099563,False
+2019/06/01 02:45:00,0.0003599974412840784,False
diff --git a/spec/spec_files/opendss/results/Lines/Line.11abf04c-1002-4d48-9f1d-edb4872cf9c3.csv b/spec/spec_files/opendss/results/Lines/Line.11abf04c-1002-4d48-9f1d-edb4872cf9c3.csv
new file mode 100644
index 00000000..347808fb
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.11abf04c-1002-4d48-9f1d-edb4872cf9c3.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,61.154421680750666,True
+2019/06/01 00:30:00,61.19619439723044,True
+2019/06/01 00:45:00,61.15331585437514,True
+2019/06/01 01:00:00,61.65091448709588,True
+2019/06/01 01:15:00,61.19619439723044,True
+2019/06/01 01:30:00,61.15331585437514,True
+2019/06/01 01:45:00,61.65091448709588,True
+2019/06/01 02:00:00,61.752976255089905,True
+2019/06/01 02:15:00,61.15331585437514,True
+2019/06/01 02:30:00,61.65091448709588,True
+2019/06/01 02:45:00,61.752976255089905,True
diff --git a/spec/spec_files/opendss/results/Lines/Line.1324f2a2-4fc9-4020-b144-b027f2633991.csv b/spec/spec_files/opendss/results/Lines/Line.1324f2a2-4fc9-4020-b144-b027f2633991.csv
new file mode 100644
index 00000000..901b6c6c
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.1324f2a2-4fc9-4020-b144-b027f2633991.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,40.762545952058495,True
+2019/06/01 00:30:00,40.76743483501793,True
+2019/06/01 00:45:00,40.76173552898731,True
+2019/06/01 01:00:00,40.88997663263541,True
+2019/06/01 01:15:00,40.76743483501793,True
+2019/06/01 01:30:00,40.76173552898731,True
+2019/06/01 01:45:00,40.88997663263541,True
+2019/06/01 02:00:00,40.91545906991567,True
+2019/06/01 02:15:00,40.76173552898731,True
+2019/06/01 02:30:00,40.88997663263541,True
+2019/06/01 02:45:00,40.91545906991567,True
diff --git a/spec/spec_files/opendss/results/Lines/Line.16e5aef9-56d0-478e-a9b2-903c7e6f7222.csv b/spec/spec_files/opendss/results/Lines/Line.16e5aef9-56d0-478e-a9b2-903c7e6f7222.csv
new file mode 100644
index 00000000..2f8b9e2b
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.16e5aef9-56d0-478e-a9b2-903c7e6f7222.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,33.78291963595312,True
+2019/06/01 00:30:00,33.760188722701734,True
+2019/06/01 00:45:00,33.78499250832337,True
+2019/06/01 01:00:00,33.34560209244707,True
+2019/06/01 01:15:00,33.760188722701734,True
+2019/06/01 01:30:00,33.78499250832337,True
+2019/06/01 01:45:00,33.34560209244707,True
+2019/06/01 02:00:00,33.24901846655432,True
+2019/06/01 02:15:00,33.78499250832337,True
+2019/06/01 02:30:00,33.34560209244707,True
+2019/06/01 02:45:00,33.24901846655432,True
diff --git a/spec/spec_files/opendss/results/Lines/Line.17f547a3-aad9-4cc3-98be-327aefe6a1d6.csv b/spec/spec_files/opendss/results/Lines/Line.17f547a3-aad9-4cc3-98be-327aefe6a1d6.csv
new file mode 100644
index 00000000..202e53ae
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.17f547a3-aad9-4cc3-98be-327aefe6a1d6.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,40.76253874147287,True
+2019/06/01 00:30:00,40.76742762661302,True
+2019/06/01 00:45:00,40.761728317860275,True
+2019/06/01 01:00:00,40.889969496588044,True
+2019/06/01 01:15:00,40.76742762661302,True
+2019/06/01 01:30:00,40.761728317860275,True
+2019/06/01 01:45:00,40.889969496588044,True
+2019/06/01 02:00:00,40.91545194859233,True
+2019/06/01 02:15:00,40.761728317860275,True
+2019/06/01 02:30:00,40.889969496588044,True
+2019/06/01 02:45:00,40.91545194859233,True
diff --git a/spec/spec_files/opendss/results/Lines/Line.36fd2f4e-8305-4f45-ae4a-5a7a3cc95013.csv b/spec/spec_files/opendss/results/Lines/Line.36fd2f4e-8305-4f45-ae4a-5a7a3cc95013.csv
new file mode 100644
index 00000000..fdfd66eb
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.36fd2f4e-8305-4f45-ae4a-5a7a3cc95013.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,33.78290102110617,True
+2019/06/01 00:30:00,33.760170149896084,True
+2019/06/01 00:45:00,33.784973661367005,True
+2019/06/01 01:00:00,33.34558497888935,True
+2019/06/01 01:15:00,33.760170149896084,True
+2019/06/01 01:30:00,33.784973661367005,True
+2019/06/01 01:45:00,33.34558497888935,True
+2019/06/01 02:00:00,33.24900176895076,True
+2019/06/01 02:15:00,33.784973661367005,True
+2019/06/01 02:30:00,33.34558497888935,True
+2019/06/01 02:45:00,33.24900176895076,True
diff --git a/spec/spec_files/opendss/results/Lines/Line.40c59858-58c3-4b8c-8521-f7a251f06740.csv b/spec/spec_files/opendss/results/Lines/Line.40c59858-58c3-4b8c-8521-f7a251f06740.csv
new file mode 100644
index 00000000..0e9cff91
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.40c59858-58c3-4b8c-8521-f7a251f06740.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,0.5406728899740245,False
+2019/06/01 00:30:00,0.540863758921489,False
+2019/06/01 00:45:00,0.5430364131838421,False
+2019/06/01 01:00:00,0.5377316600654587,False
+2019/06/01 01:15:00,0.540863758921489,False
+2019/06/01 01:30:00,0.5430364131838421,False
+2019/06/01 01:45:00,0.5377316600654587,False
+2019/06/01 02:00:00,0.5363869723798321,False
+2019/06/01 02:15:00,0.5430364131838421,False
+2019/06/01 02:30:00,0.5377316600654587,False
+2019/06/01 02:45:00,0.5363869723798321,False
diff --git a/spec/spec_files/opendss/results/Lines/Line.44c05d80-7a90-4229-94f7-0ef2787b2cc7.csv b/spec/spec_files/opendss/results/Lines/Line.44c05d80-7a90-4229-94f7-0ef2787b2cc7.csv
new file mode 100644
index 00000000..4e8f4151
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.44c05d80-7a90-4229-94f7-0ef2787b2cc7.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,0.09236984552530263,False
+2019/06/01 00:30:00,0.09281000038243281,False
+2019/06/01 00:45:00,0.09007496335449869,False
+2019/06/01 01:00:00,0.09308944731014279,False
+2019/06/01 01:15:00,0.09281000038243281,False
+2019/06/01 01:30:00,0.09007496335449869,False
+2019/06/01 01:45:00,0.09308944731014279,False
+2019/06/01 02:00:00,0.09345558983360461,False
+2019/06/01 02:15:00,0.09007496335449869,False
+2019/06/01 02:30:00,0.09308944731014279,False
+2019/06/01 02:45:00,0.09345558983360461,False
diff --git a/spec/spec_files/opendss/results/Lines/Line.59f65367-c852-40ab-9d7f-dc30822570f7.csv b/spec/spec_files/opendss/results/Lines/Line.59f65367-c852-40ab-9d7f-dc30822570f7.csv
new file mode 100644
index 00000000..53d060a6
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.59f65367-c852-40ab-9d7f-dc30822570f7.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,0.0002332110312419084,False
+2019/06/01 00:30:00,0.00023248674300960958,False
+2019/06/01 00:45:00,0.0002331804137368649,False
+2019/06/01 01:00:00,0.00020472502359997633,False
+2019/06/01 01:15:00,0.00023248674300960958,False
+2019/06/01 01:30:00,0.0002331804137368649,False
+2019/06/01 01:45:00,0.00020472502359997633,False
+2019/06/01 02:00:00,0.00020664891873504367,False
+2019/06/01 02:15:00,0.0002331804137368649,False
+2019/06/01 02:30:00,0.00020472502359997633,False
+2019/06/01 02:45:00,0.00020664891873504367,False
diff --git a/spec/spec_files/opendss/results/Lines/Line.5b3d3f0c-0c14-4c3d-9080-0fb5bbea5470.csv b/spec/spec_files/opendss/results/Lines/Line.5b3d3f0c-0c14-4c3d-9080-0fb5bbea5470.csv
new file mode 100644
index 00000000..0b187915
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.5b3d3f0c-0c14-4c3d-9080-0fb5bbea5470.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,22.316483896454272,True
+2019/06/01 00:30:00,21.111590821812953,True
+2019/06/01 00:45:00,22.297097848523077,True
+2019/06/01 01:00:00,16.949676340249898,True
+2019/06/01 01:15:00,21.111590821812953,True
+2019/06/01 01:30:00,22.297097848523077,True
+2019/06/01 01:45:00,16.949676340249898,True
+2019/06/01 02:00:00,16.64657433340466,True
+2019/06/01 02:15:00,22.297097848523077,True
+2019/06/01 02:30:00,16.949676340249898,True
+2019/06/01 02:45:00,16.64657433340466,True
diff --git a/spec/spec_files/opendss/results/Lines/Line.68c17aed-1c16-4a75-b0a7-7cf2db5d605d.csv b/spec/spec_files/opendss/results/Lines/Line.68c17aed-1c16-4a75-b0a7-7cf2db5d605d.csv
new file mode 100644
index 00000000..7fe26a9c
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.68c17aed-1c16-4a75-b0a7-7cf2db5d605d.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,0.02790970306750502,False
+2019/06/01 00:30:00,0.02561712217720309,False
+2019/06/01 00:45:00,0.027801776504403054,False
+2019/06/01 01:00:00,0.03281313679697618,False
+2019/06/01 01:15:00,0.02561712217720309,False
+2019/06/01 01:30:00,0.027801776504403054,False
+2019/06/01 01:45:00,0.03281313679697618,False
+2019/06/01 02:00:00,0.021915087492895474,False
+2019/06/01 02:15:00,0.027801776504403054,False
+2019/06/01 02:30:00,0.03281313679697618,False
+2019/06/01 02:45:00,0.021915087492895474,False
diff --git a/spec/spec_files/opendss/results/Lines/Line.6cdda038-b853-4a8e-bf6d-304c49d93688.csv b/spec/spec_files/opendss/results/Lines/Line.6cdda038-b853-4a8e-bf6d-304c49d93688.csv
new file mode 100644
index 00000000..57e66ed1
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.6cdda038-b853-4a8e-bf6d-304c49d93688.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,0.00013574421312050842,False
+2019/06/01 00:30:00,0.00013741495394791443,False
+2019/06/01 00:45:00,0.00013760941523850001,False
+2019/06/01 01:00:00,0.00013448867777673615,False
+2019/06/01 01:15:00,0.00013741495394791443,False
+2019/06/01 01:30:00,0.00013760941523850001,False
+2019/06/01 01:45:00,0.00013448867777673615,False
+2019/06/01 02:00:00,0.00012263124346418295,False
+2019/06/01 02:15:00,0.00013760941523850001,False
+2019/06/01 02:30:00,0.00013448867777673615,False
+2019/06/01 02:45:00,0.00012263124346418295,False
diff --git a/spec/spec_files/opendss/results/Lines/Line.861ae659-79c7-45f7-9933-bed0a2560e7c.csv b/spec/spec_files/opendss/results/Lines/Line.861ae659-79c7-45f7-9933-bed0a2560e7c.csv
new file mode 100644
index 00000000..8e21db74
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.861ae659-79c7-45f7-9933-bed0a2560e7c.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,0.0002478938224916952,False
+2019/06/01 00:30:00,0.00024999965072799177,False
+2019/06/01 00:45:00,0.00025002559928595416,False
+2019/06/01 01:00:00,0.0002497202624742827,False
+2019/06/01 01:15:00,0.00024999965072799177,False
+2019/06/01 01:30:00,0.00025002559928595416,False
+2019/06/01 01:45:00,0.0002497202624742827,False
+2019/06/01 02:00:00,0.00024826376224806646,False
+2019/06/01 02:15:00,0.00025002559928595416,False
+2019/06/01 02:30:00,0.0002497202624742827,False
+2019/06/01 02:45:00,0.00024826376224806646,False
diff --git a/spec/spec_files/opendss/results/Lines/Line.96ac00ff-1369-472b-b8cd-d8721355f4c5.csv b/spec/spec_files/opendss/results/Lines/Line.96ac00ff-1369-472b-b8cd-d8721355f4c5.csv
new file mode 100644
index 00000000..b802cd99
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.96ac00ff-1369-472b-b8cd-d8721355f4c5.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,0.8176430638920928,False
+2019/06/01 00:30:00,0.8233757154222654,False
+2019/06/01 00:45:00,0.8454098537209395,False
+2019/06/01 01:00:00,0.8206228753058639,False
+2019/06/01 01:15:00,0.8233757154222654,False
+2019/06/01 01:30:00,0.8454098537209395,False
+2019/06/01 01:45:00,0.8206228753058639,False
+2019/06/01 02:00:00,0.8249488391105355,False
+2019/06/01 02:15:00,0.8454098537209395,False
+2019/06/01 02:30:00,0.8206228753058639,False
+2019/06/01 02:45:00,0.8249488391105355,False
diff --git a/spec/spec_files/opendss/results/Lines/Line.9e3fff1f-2625-4f3f-b510-f4e51683c941.csv b/spec/spec_files/opendss/results/Lines/Line.9e3fff1f-2625-4f3f-b510-f4e51683c941.csv
new file mode 100644
index 00000000..83d2dd7e
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.9e3fff1f-2625-4f3f-b510-f4e51683c941.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,0.16267837021247192,False
+2019/06/01 00:30:00,0.15268452589518644,False
+2019/06/01 00:45:00,0.16210995637157377,False
+2019/06/01 01:00:00,0.011530123007345048,False
+2019/06/01 01:15:00,0.15268452589518644,False
+2019/06/01 01:30:00,0.16210995637157377,False
+2019/06/01 01:45:00,0.011530123007345048,False
+2019/06/01 02:00:00,0.10291679915350609,False
+2019/06/01 02:15:00,0.16210995637157377,False
+2019/06/01 02:30:00,0.011530123007345048,False
+2019/06/01 02:45:00,0.10291679915350609,False
diff --git a/spec/spec_files/opendss/results/Lines/Line.a0ba7300-0264-4450-8a1b-6f8045ee7cfe.csv b/spec/spec_files/opendss/results/Lines/Line.a0ba7300-0264-4450-8a1b-6f8045ee7cfe.csv
new file mode 100644
index 00000000..61dd3fdf
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.a0ba7300-0264-4450-8a1b-6f8045ee7cfe.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,0.14300654373003865,False
+2019/06/01 00:30:00,0.1313747655068514,False
+2019/06/01 00:45:00,0.14311125781104844,False
+2019/06/01 01:00:00,0.1352482523139778,False
+2019/06/01 01:15:00,0.1313747655068514,False
+2019/06/01 01:30:00,0.14311125781104844,False
+2019/06/01 01:45:00,0.1352482523139778,False
+2019/06/01 02:00:00,0.09062897866870054,False
+2019/06/01 02:15:00,0.14311125781104844,False
+2019/06/01 02:30:00,0.1352482523139778,False
+2019/06/01 02:45:00,0.09062897866870054,False
diff --git a/spec/spec_files/opendss/results/Lines/Line.bbb1f6a0-394e-4b38-bd51-1fa8f70d89dd.csv b/spec/spec_files/opendss/results/Lines/Line.bbb1f6a0-394e-4b38-bd51-1fa8f70d89dd.csv
new file mode 100644
index 00000000..31cc2681
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.bbb1f6a0-394e-4b38-bd51-1fa8f70d89dd.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,0.01999090583342565,False
+2019/06/01 00:30:00,0.01637889289057861,False
+2019/06/01 00:45:00,0.01994142241779324,False
+2019/06/01 01:00:00,0.0854083607286207,False
+2019/06/01 01:15:00,0.01637889289057861,False
+2019/06/01 01:30:00,0.01994142241779324,False
+2019/06/01 01:45:00,0.0854083607286207,False
+2019/06/01 02:00:00,0.057416815207186875,False
+2019/06/01 02:15:00,0.01994142241779324,False
+2019/06/01 02:30:00,0.0854083607286207,False
+2019/06/01 02:45:00,0.057416815207186875,False
diff --git a/spec/spec_files/opendss/results/Lines/Line.bf23c675-d787-4994-803b-18d8d4900699.csv b/spec/spec_files/opendss/results/Lines/Line.bf23c675-d787-4994-803b-18d8d4900699.csv
new file mode 100644
index 00000000..5caaf671
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.bf23c675-d787-4994-803b-18d8d4900699.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,0.01957955926327284,False
+2019/06/01 00:30:00,0.016091314620048182,False
+2019/06/01 00:45:00,0.01960238980286143,False
+2019/06/01 01:00:00,0.02325547687399226,False
+2019/06/01 01:15:00,0.016091314620048182,False
+2019/06/01 01:30:00,0.01960238980286143,False
+2019/06/01 01:45:00,0.02325547687399226,False
+2019/06/01 02:00:00,0.014657311898480107,False
+2019/06/01 02:15:00,0.01960238980286143,False
+2019/06/01 02:30:00,0.02325547687399226,False
+2019/06/01 02:45:00,0.014657311898480107,False
diff --git a/spec/spec_files/opendss/results/Lines/Line.bfdf4e28-5baf-4d54-9d0a-5a7dc3fbd4f3.csv b/spec/spec_files/opendss/results/Lines/Line.bfdf4e28-5baf-4d54-9d0a-5a7dc3fbd4f3.csv
new file mode 100644
index 00000000..ddd4da8a
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.bfdf4e28-5baf-4d54-9d0a-5a7dc3fbd4f3.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,22.31648389645426,True
+2019/06/01 00:30:00,21.111590874230032,True
+2019/06/01 00:45:00,22.297097848523055,True
+2019/06/01 01:00:00,16.949676577378025,True
+2019/06/01 01:15:00,21.111590874230032,True
+2019/06/01 01:30:00,22.297097848523055,True
+2019/06/01 01:45:00,16.949676577378025,True
+2019/06/01 02:00:00,16.64657454813445,True
+2019/06/01 02:15:00,22.297097848523055,True
+2019/06/01 02:30:00,16.949676577378025,True
+2019/06/01 02:45:00,16.64657454813445,True
diff --git a/spec/spec_files/opendss/results/Lines/Line.db1a87fb-d770-4939-b747-7cadf1f304f8.csv b/spec/spec_files/opendss/results/Lines/Line.db1a87fb-d770-4939-b747-7cadf1f304f8.csv
new file mode 100644
index 00000000..d2635f35
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.db1a87fb-d770-4939-b747-7cadf1f304f8.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,33.782920097221535,True
+2019/06/01 00:30:00,33.760189179625335,True
+2019/06/01 00:45:00,33.78499296950095,True
+2019/06/01 01:00:00,33.3456025287354,True
+2019/06/01 01:15:00,33.760189179625335,True
+2019/06/01 01:30:00,33.78499296950095,True
+2019/06/01 01:45:00,33.3456025287354,True
+2019/06/01 02:00:00,33.249018899385014,True
+2019/06/01 02:15:00,33.78499296950095,True
+2019/06/01 02:30:00,33.3456025287354,True
+2019/06/01 02:45:00,33.249018899385014,True
diff --git a/spec/spec_files/opendss/results/Lines/Line.de88d8f3-d596-4088-8ee7-d96326ab083c.csv b/spec/spec_files/opendss/results/Lines/Line.de88d8f3-d596-4088-8ee7-d96326ab083c.csv
new file mode 100644
index 00000000..32532f62
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.de88d8f3-d596-4088-8ee7-d96326ab083c.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,0.007871161472699246,False
+2019/06/01 00:30:00,0.007873089360972783,False
+2019/06/01 00:45:00,0.007871428445214821,False
+2019/06/01 01:00:00,0.007858456444897322,False
+2019/06/01 01:15:00,0.007873089360972783,False
+2019/06/01 01:30:00,0.007871428445214821,False
+2019/06/01 01:45:00,0.007858456444897322,False
+2019/06/01 02:00:00,0.00785495265141455,False
+2019/06/01 02:15:00,0.007871428445214821,False
+2019/06/01 02:30:00,0.007858456444897322,False
+2019/06/01 02:45:00,0.00785495265141455,False
diff --git a/spec/spec_files/opendss/results/Lines/Line.e2dcff78-1f88-496b-9111-66ea2cc6c889.csv b/spec/spec_files/opendss/results/Lines/Line.e2dcff78-1f88-496b-9111-66ea2cc6c889.csv
new file mode 100644
index 00000000..32307924
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.e2dcff78-1f88-496b-9111-66ea2cc6c889.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,0.8180636642297237,False
+2019/06/01 00:30:00,0.8073249069721483,False
+2019/06/01 00:45:00,0.787421495488698,False
+2019/06/01 01:00:00,0.8149858988039503,False
+2019/06/01 01:15:00,0.8073249069721483,False
+2019/06/01 01:30:00,0.787421495488698,False
+2019/06/01 01:45:00,0.8149858988039503,False
+2019/06/01 02:00:00,0.8116740332788329,False
+2019/06/01 02:15:00,0.787421495488698,False
+2019/06/01 02:30:00,0.8149858988039503,False
+2019/06/01 02:45:00,0.8116740332788329,False
diff --git a/spec/spec_files/opendss/results/Lines/Line.f2d0448f-aab3-4da0-8aca-17564c8e3a58.csv b/spec/spec_files/opendss/results/Lines/Line.f2d0448f-aab3-4da0-8aca-17564c8e3a58.csv
new file mode 100644
index 00000000..dfcad658
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.f2d0448f-aab3-4da0-8aca-17564c8e3a58.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,0.0038731476658697217,False
+2019/06/01 00:30:00,0.003924386596964254,False
+2019/06/01 00:45:00,0.003929577215236253,False
+2019/06/01 01:00:00,0.003863557286874198,False
+2019/06/01 01:15:00,0.003924386596964254,False
+2019/06/01 01:30:00,0.003929577215236253,False
+2019/06/01 01:45:00,0.003863557286874198,False
+2019/06/01 02:00:00,0.003503018448803092,False
+2019/06/01 02:15:00,0.003929577215236253,False
+2019/06/01 02:30:00,0.003863557286874198,False
+2019/06/01 02:45:00,0.003503018448803092,False
diff --git a/spec/spec_files/opendss/results/Lines/Line.f57d88d3-925f-4d5d-b25c-b3b9475f1ea7.csv b/spec/spec_files/opendss/results/Lines/Line.f57d88d3-925f-4d5d-b25c-b3b9475f1ea7.csv
new file mode 100644
index 00000000..21a06bd7
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.f57d88d3-925f-4d5d-b25c-b3b9475f1ea7.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,40.779447683686826,True
+2019/06/01 00:30:00,40.767397968777416,True
+2019/06/01 00:45:00,40.761699248916194,True
+2019/06/01 01:00:00,40.889940418073856,True
+2019/06/01 01:15:00,40.767397968777416,True
+2019/06/01 01:30:00,40.761699248916194,True
+2019/06/01 01:45:00,40.889940418073856,True
+2019/06/01 02:00:00,40.91542400926487,True
+2019/06/01 02:15:00,40.761699248916194,True
+2019/06/01 02:30:00,40.889940418073856,True
+2019/06/01 02:45:00,40.91542400926487,True
diff --git a/spec/spec_files/opendss/results/Lines/Line.f912d33f-f017-4ba5-b2fd-2ed2eec38b71.csv b/spec/spec_files/opendss/results/Lines/Line.f912d33f-f017-4ba5-b2fd-2ed2eec38b71.csv
new file mode 100644
index 00000000..ebad8919
--- /dev/null
+++ b/spec/spec_files/opendss/results/Lines/Line.f912d33f-f017-4ba5-b2fd-2ed2eec38b71.csv
@@ -0,0 +1,12 @@
+Datetime,p.u. loading,overloaded
+2019/06/01 00:15:00,40.76250820083001,True
+2019/06/01 00:30:00,40.76739629862129,True
+2019/06/01 00:45:00,40.76169757438438,True
+2019/06/01 01:00:00,40.889938882726746,True
+2019/06/01 01:15:00,40.76739629862129,True
+2019/06/01 01:30:00,40.76169757438438,True
+2019/06/01 01:45:00,40.889938882726746,True
+2019/06/01 02:00:00,40.915422501275195,True
+2019/06/01 02:15:00,40.76169757438438,True
+2019/06/01 02:30:00,40.889938882726746,True
+2019/06/01 02:45:00,40.915422501275195,True
diff --git a/spec/spec_files/opendss/results/Transformers/Transformer.1b4b5dcf-8d18-4954-b655-a93634542733.csv b/spec/spec_files/opendss/results/Transformers/Transformer.1b4b5dcf-8d18-4954-b655-a93634542733.csv
new file mode 100644
index 00000000..cb1810be
--- /dev/null
+++ b/spec/spec_files/opendss/results/Transformers/Transformer.1b4b5dcf-8d18-4954-b655-a93634542733.csv
@@ -0,0 +1,25 @@
+Datetime,p.u. loading,overloaded
+6/1/2012 1:00,149.1749429,TRUE
+6/1/2012 2:00,149.1308639,TRUE
+6/1/2012 3:00,149.1100175,TRUE
+6/1/2012 4:00,149.5791354,TRUE
+6/1/2012 5:00,149.1308639,TRUE
+6/1/2012 6:00,149.1100175,TRUE
+6/1/2012 7:00,149.5791354,TRUE
+6/1/2012 8:00,149.6723567,TRUE
+6/1/2012 9:00,149.1100175,TRUE
+6/1/2012 10:00,149.5791354,TRUE
+6/1/2012 11:00,149.6723567,TRUE
+6/1/2012 12:00,149.1749429,TRUE
+6/1/2012 13:00,149.1308639,TRUE
+6/1/2012 14:00,149.1100175,TRUE
+6/1/2012 15:00,149.5791354,TRUE
+6/1/2012 16:00,149.1308639,TRUE
+6/1/2012 17:00,149.1100175,TRUE
+6/1/2012 18:00,149.5791354,TRUE
+6/1/2012 19:00,149.6723567,TRUE
+6/1/2012 20:00,149.1100175,TRUE
+6/1/2012 21:00,149.5791354,TRUE
+6/1/2012 22:00,149.6723567,TRUE
+6/1/2012 23:00,149.6723567,TRUE
+6/2/2012 0:00,149.6723567,TRUE
diff --git a/spec/spec_files/opendss/results/Transformers/Transformer.502e96e3-853a-4b3d-b88d-fe59af4d7b65.csv b/spec/spec_files/opendss/results/Transformers/Transformer.502e96e3-853a-4b3d-b88d-fe59af4d7b65.csv
new file mode 100644
index 00000000..4c5f344c
--- /dev/null
+++ b/spec/spec_files/opendss/results/Transformers/Transformer.502e96e3-853a-4b3d-b88d-fe59af4d7b65.csv
@@ -0,0 +1,25 @@
+Datetime,p.u. loading,overloaded
+6/1/2012 1:00,17.30321915,TRUE
+6/1/2012 2:00,16.22341634,TRUE
+6/1/2012 3:00,17.28360263,TRUE
+6/1/2012 4:00,14.67874647,TRUE
+6/1/2012 5:00,16.22341634,TRUE
+6/1/2012 6:00,17.28360263,TRUE
+6/1/2012 7:00,14.67874647,TRUE
+6/1/2012 8:00,15.11325504,TRUE
+6/1/2012 9:00,17.28360263,TRUE
+6/1/2012 10:00,14.67874647,TRUE
+6/1/2012 11:00,15.11325504,TRUE
+6/1/2012 12:00,15.01646523,TRUE
+6/1/2012 13:00,14.8546093,TRUE
+6/1/2012 14:00,14.69275337,TRUE
+6/1/2012 15:00,14.53089743,TRUE
+6/1/2012 16:00,14.3690415,TRUE
+6/1/2012 17:00,14.20718557,TRUE
+6/1/2012 18:00,14.04532963,TRUE
+6/1/2012 19:00,13.8834737,TRUE
+6/1/2012 20:00,13.72161776,TRUE
+6/1/2012 21:00,13.55976183,TRUE
+6/1/2012 22:00,13.3979059,TRUE
+6/1/2012 23:00,13.23604996,TRUE
+6/2/2012 0:00,13.07419403,TRUE
diff --git a/spec/spec_files/opendss/results/Transformers/Transformer.54cd0a5a-2ebe-4b39-936a-f238b503c221.csv b/spec/spec_files/opendss/results/Transformers/Transformer.54cd0a5a-2ebe-4b39-936a-f238b503c221.csv
new file mode 100644
index 00000000..a0aac97a
--- /dev/null
+++ b/spec/spec_files/opendss/results/Transformers/Transformer.54cd0a5a-2ebe-4b39-936a-f238b503c221.csv
@@ -0,0 +1,25 @@
+Datetime,p.u. loading,overloaded
+6/1/2012 1:00,0.006827765,FALSE
+6/1/2012 2:00,0.006911801,FALSE
+6/1/2012 3:00,0.006921582,FALSE
+6/1/2012 4:00,0.006764613,FALSE
+6/1/2012 5:00,0.006911801,FALSE
+6/1/2012 6:00,0.006921582,FALSE
+6/1/2012 7:00,0.006764613,FALSE
+6/1/2012 8:00,0.006168199,FALSE
+6/1/2012 9:00,0.006921582,FALSE
+6/1/2012 10:00,0.006764613,FALSE
+6/1/2012 11:00,0.006168199,FALSE
+6/1/2012 12:00,0.006446399,FALSE
+6/1/2012 13:00,0.006398885,FALSE
+6/1/2012 14:00,0.00635137,FALSE
+6/1/2012 15:00,0.006303856,FALSE
+6/1/2012 16:00,0.006256341,FALSE
+6/1/2012 17:00,0.006208827,FALSE
+6/1/2012 18:00,0.006161312,FALSE
+6/1/2012 19:00,0.006113798,FALSE
+6/1/2012 20:00,0.006066283,FALSE
+6/1/2012 21:00,0.006018768,FALSE
+6/1/2012 22:00,0.005971254,FALSE
+6/1/2012 23:00,0.005923739,FALSE
+6/2/2012 0:00,0.005876225,FALSE
diff --git a/spec/spec_files/opendss/results/Transformers/Transformer.897530f5-a6d6-446f-94fd-4087196fceaf.csv b/spec/spec_files/opendss/results/Transformers/Transformer.897530f5-a6d6-446f-94fd-4087196fceaf.csv
new file mode 100644
index 00000000..57ba0dec
--- /dev/null
+++ b/spec/spec_files/opendss/results/Transformers/Transformer.897530f5-a6d6-446f-94fd-4087196fceaf.csv
@@ -0,0 +1,25 @@
+Datetime,p.u. loading,overloaded
+6/1/2012 1:00,0.016625001,FALSE
+6/1/2012 2:00,0.016766228,FALSE
+6/1/2012 3:00,0.016767969,FALSE
+6/1/2012 4:00,0.016747491,FALSE
+6/1/2012 5:00,0.016766228,FALSE
+6/1/2012 6:00,0.016767969,FALSE
+6/1/2012 7:00,0.016747491,FALSE
+6/1/2012 8:00,0.016649811,FALSE
+6/1/2012 9:00,0.016767969,FALSE
+6/1/2012 10:00,0.016747491,FALSE
+6/1/2012 11:00,0.016649811,FALSE
+6/1/2012 12:00,0.016718587,FALSE
+6/1/2012 13:00,0.016717087,FALSE
+6/1/2012 14:00,0.016715587,FALSE
+6/1/2012 15:00,0.016714088,FALSE
+6/1/2012 16:00,0.016712588,FALSE
+6/1/2012 17:00,0.016711088,FALSE
+6/1/2012 18:00,0.016709588,FALSE
+6/1/2012 19:00,0.016708088,FALSE
+6/1/2012 20:00,0.016706588,FALSE
+6/1/2012 21:00,0.016705088,FALSE
+6/1/2012 22:00,0.016703588,FALSE
+6/1/2012 23:00,0.016702088,FALSE
+6/2/2012 0:00,0.016700588,FALSE
diff --git a/spec/spec_files/opendss/results/Transformers/Transformer.b02e3fe9-77d0-47f9-86cb-e4db960afd62.csv b/spec/spec_files/opendss/results/Transformers/Transformer.b02e3fe9-77d0-47f9-86cb-e4db960afd62.csv
new file mode 100644
index 00000000..ea479951
--- /dev/null
+++ b/spec/spec_files/opendss/results/Transformers/Transformer.b02e3fe9-77d0-47f9-86cb-e4db960afd62.csv
@@ -0,0 +1,25 @@
+Datetime,p.u. loading,overloaded
+6/1/2012 1:00,22.28309274,TRUE
+6/1/2012 2:00,22.30531032,TRUE
+6/1/2012 3:00,22.28538152,TRUE
+6/1/2012 4:00,22.2049006,TRUE
+6/1/2012 5:00,22.30531032,TRUE
+6/1/2012 6:00,22.28538152,TRUE
+6/1/2012 7:00,22.2049006,TRUE
+6/1/2012 8:00,22.1704519,TRUE
+6/1/2012 9:00,22.28538152,TRUE
+6/1/2012 10:00,22.2049006,TRUE
+6/1/2012 11:00,22.1704519,TRUE
+6/1/2012 12:00,22.18408849,TRUE
+6/1/2012 13:00,22.17377804,TRUE
+6/1/2012 14:00,22.16346758,TRUE
+6/1/2012 15:00,22.15315712,TRUE
+6/1/2012 16:00,22.14284667,TRUE
+6/1/2012 17:00,22.13253621,TRUE
+6/1/2012 18:00,22.12222575,TRUE
+6/1/2012 19:00,22.1119153,TRUE
+6/1/2012 20:00,22.10160484,TRUE
+6/1/2012 21:00,22.09129438,TRUE
+6/1/2012 22:00,22.08098393,TRUE
+6/1/2012 23:00,22.07067347,TRUE
+6/2/2012 0:00,22.06036302,TRUE
diff --git a/spec/spec_files/two_building_scenario.csv b/spec/spec_files/two_building_scenario.csv
new file mode 100644
index 00000000..7c24c012
--- /dev/null
+++ b/spec/spec_files/two_building_scenario.csv
@@ -0,0 +1,3 @@
+Feature Id,Feature Name,Mapper Class,REopt Assumptions
+1,Mixed_use 1,URBANopt::Scenario::BaselineMapper,multiPV_assumptions.json
+2,Restaurant 1,URBANopt::Scenario::BaselineMapper,multiPV_assumptions.json
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index d66fbcdb..8f38a6bb 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -3,7 +3,7 @@
RSpec.configure do |config|
# Enable flags like --only-failures and --next-failure
- config.example_status_persistence_file_path = '.rspec_status'
+ config.example_status_persistence_file_path = 'spec/.rspec_status'
# Disable RSpec exposing methods globally on `Module` and `main`
config.disable_monkey_patching!
diff --git a/spec/uo_cli_spec.rb b/spec/uo_cli_spec.rb
index edc78af5..78274053 100644
--- a/spec/uo_cli_spec.rb
+++ b/spec/uo_cli_spec.rb
@@ -1,11 +1,133 @@
RSpec.describe URBANopt::CLI do
- it 'has a version number' do
- expect(URBANopt::CLI::VERSION).not_to be nil
+ test_directory = File.join('spec', 'test_directory')
+ test_scenario = File.join(test_directory, 'two_building_scenario.csv')
+ test_feature = File.join(test_directory, 'example_project.json')
+ call_cli = "ruby #{File.join('lib', 'uo_cli.rb')}"
+
+ # Ensure clean slate for testing
+ # +dir_or_file+ string - path to a file or folder
+ def delete_directory_or_file(dir_or_file)
+ if File.exist?(dir_or_file)
+ FileUtils.rm_rf(dir_or_file)
+ end
+ end
+
+ context 'Admin' do
+ it 'displays the correct version number' do
+ expect { system("#{call_cli} -v") }
+ .to output(a_string_including(URBANopt::CLI::VERSION))
+ .to_stdout_from_any_process
+ end
+
+ it 'returns help' do
+ expect { system("#{call_cli} -h") }
+ .to output(a_string_including('Usage: uo'))
+ .to_stdout_from_any_process
+ end
+ end
+
+ context 'Create project' do
+ before :each do
+ delete_directory_or_file(test_directory)
+ end
+
+ it 'creates an example project directory' do
+ system("#{call_cli} -p #{test_directory}")
+ expect(File.exist?(test_feature)).to be true
+ end
+
+ it 'creates an empty project directory' do
+ system("#{call_cli} -e -p #{test_directory}")
+ expect(File.exist?(test_feature)).to be false
+ expect(File.exist?(File.join(test_directory, 'mappers', 'Baseline.rb'))).to be true
+ end
+
+ it 'does not overwrite a project directory without -o' do
+ system("#{call_cli} -p #{test_directory}")
+ expect(File.exist?(test_feature)).to be true
+ expect { system("#{call_cli} -p #{test_directory}") }
+ .to output(a_string_including('already a directory here'))
+ .to_stderr_from_any_process
+ end
+
+ it 'overwrites a project directory with -o' do
+ system("#{call_cli} -p #{test_directory}")
+ expect(File.exist?(test_feature)).to be true
+ expect { system("#{call_cli} -o -p #{test_directory}") }
+ .to output(a_string_including('Overwriting'))
+ .to_stdout_from_any_process
+ expect(File.exist?(test_feature)).to be true
+ end
+
+ it 'overwrites an existing project directory with an empty directory' do
+ system("#{call_cli} -p #{test_directory}")
+ expect(File.exist?(test_feature)).to be true
+ system("#{call_cli} -e -o -p #{test_directory}")
+ expect(File.exist?(test_feature)).to be false
+ expect(File.exist?(File.join(test_directory, 'mappers', 'Baseline.rb'))).to be true
+ end
end
- it 'returns help' do
- expect { system %(ruby lib/uo_cli.rb -h) }
- .to output(a_string_including('Usage: uo'))
- .to_stdout_from_any_process
+ context 'Run and work with a small simulation' do
+ before :all do
+ delete_directory_or_file(test_directory)
+ system("#{call_cli} -p #{test_directory}")
+ end
+
+ it 'creates a scenario file from a feature file' do
+ expect(File.exist?(File.join(test_directory, 'baseline_scenario.csv'))).to be false
+ system("#{call_cli} -m -f #{test_feature}")
+ expect(File.exist?(File.join(test_directory, 'baseline_scenario.csv'))).to be true
+ end
+
+ it 'creates a scenario file for a single feature from a feature file' do
+ expect(File.exist?(File.join(test_directory, 'baseline_scenario-1.csv'))).to be false
+ system("uo -m -f #{test_feature} -i 1")
+ expect(File.exist?(File.join(test_directory, 'baseline_scenario-1.csv'))).to be true
+ end
+
+ it 'actually runs a 2 building scenario' do
+ # Copy in a scenario file with only the first 2 buildings in it
+ system("cp #{File.join('spec', 'spec_files', 'two_building_scenario.csv')} #{test_scenario}")
+ system("#{call_cli} -r -s #{test_scenario} -f #{test_feature}")
+ expect(File.exist?(File.join(test_directory, 'run', 'two_building_scenario', '1', 'finished.job'))).to be true
+ expect(File.exist?(File.join(test_directory, 'run', 'two_building_scenario', '2', 'finished.job'))).to be true
+ expect(File.exist?(File.join(test_directory, 'run', 'two_building_scenario', '3', 'finished.job'))).to be false
+ end
+
+ it 'post-processor exits gracefully if given an invalid type' do
+ expect { system("#{call_cli} -g -t foobar -s #{test_scenario} -f #{test_feature}") }
+ .to output(a_string_including('valid Gather type!'))
+ .to_stderr_from_any_process
+ end
+
+ it 'post-processes a scenario' do
+ system("#{call_cli} -g -t default -s #{test_scenario} -f #{test_feature}")
+ expect(File.exist?(File.join(test_directory, 'run', 'two_building_scenario', 'default_scenario_report.csv'))).to be true
+ end
+
+ it 'reopt post-processes a scenario' do
+ expect(File.exist?(File.join(test_directory, 'run', 'two_building_scenario', 'scenario_optimization.json'))).to be false
+ system("#{call_cli} -g -t reopt-scenario -s #{test_scenario} -f #{test_feature}")
+ expect(File.exist?(File.join(test_directory, 'run', 'two_building_scenario', 'scenario_optimization.json'))).to be true
+ end
+
+ it 'reopt post-processes each feature' do
+ system("#{call_cli} -g -t reopt-feature -s #{test_scenario} -f #{test_feature}")
+ expect(File.exist?(File.join(test_directory, 'run', 'two_building_scenario', '1', 'feature_reports', 'feature_optimization.csv'))).to be true
+ end
+
+ it 'opendss post-processes a scenario' do
+ expect(File.exist?(File.join(test_directory, 'run', 'two_building_scenario', 'opendss'))).to be false
+ system("cp -R #{File.join('spec', 'spec_files', 'opendss')} #{File.join(test_directory, 'run', 'two_building_scenario', 'opendss')}")
+ system("#{call_cli} -g -t opendss -s #{test_scenario} -f #{test_feature}")
+ expect(File.exist?(File.join(test_directory, 'run', 'two_building_scenario', '1', 'feature_reports', 'default_feature_report_opendss.csv'))).to be true
+ end
+
+ it 'deletes a scenario' do
+ expect(File.exist?(File.join(test_directory, 'run', 'two_building_scenario', '1', 'data_point_out.json'))).to be true
+ system("#{call_cli} -d -s #{test_scenario}")
+ expect(File.exist?(File.join(test_directory, 'run', 'two_building_scenario', '1', 'data_point_out.json'))).to be false
+ end
end
end
diff --git a/uo_cli.gemspec b/uo_cli.gemspec
index 040a951c..4a91aa19 100644
--- a/uo_cli.gemspec
+++ b/uo_cli.gemspec
@@ -36,6 +36,7 @@ Gem::Specification.new do |spec|
# use specific versions of urbanopt and openstudio dependencies while under heavy development
spec.add_dependency 'urbanopt-geojson', '0.2.0'
+ spec.add_dependency 'urbanopt-reopt', '0.2.1'
spec.add_dependency 'urbanopt-scenario', '0.2.0'
spec.add_development_dependency 'bundler', '~> 1.17'