openstudio-analysis 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +20 -0
- data/Rakefile +51 -0
- data/lib/openstudio-analysis.rb +16 -0
- data/lib/openstudio/analysis/server_api.rb +302 -0
- data/lib/openstudio/analysis/translator/excel.rb +366 -0
- data/lib/openstudio/analysis/version.rb +6 -0
- data/lib/openstudio/helpers/string.rb +12 -0
- data/lib/openstudio/templates/analysis.json.erb +26 -0
- data/lib/openstudio/templates/argument.json.erb +10 -0
- data/lib/openstudio/templates/discrete_uncertain_variable.json.erb +32 -0
- data/lib/openstudio/templates/pivot_variable.json.erb +31 -0
- data/lib/openstudio/templates/static_variable.json.erb +22 -0
- data/lib/openstudio/templates/uncertain_variable.json.erb +42 -0
- data/lib/openstudio/templates/workflow_item.json.erb +19 -0
- data/spec/openstudio-analysis/server_api_spec.rb +24 -0
- data/spec/spec_helper.rb +8 -0
- metadata +133 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 900f442cddeeeaec5d3c46f05979c8e61c94df06
|
4
|
+
data.tar.gz: e4aa3cfea70f6b1a31730d5bd02b44e72ea7c254
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 957702d15cac0c9c264c4b375e1387cc15d1f228420e7eccdf18a28fcb525f5edb11dcf70995679d6a13d0e2f55683528c82501fd655b638b6da2eeba8030149
|
7
|
+
data.tar.gz: 1b02cd2c8560babad1d18a8d4c9653f32c40b755c9e4c3639da010eb8006829cfdc744078edcebaaa6f8f611847d4926351784191bb43f3c1a7db3c1eac26187
|
data/README.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
OpenStudio Analysis Gem
|
2
|
+
=======================
|
3
|
+
|
4
|
+
The OpenStudio Analysis Gem is used to communicate files to the OpenStudio Distributed Analysis.
|
5
|
+
|
6
|
+
The purpose of this gem is to generate the analysis.json file, analysis.zip, and communicate with the server to upload
|
7
|
+
the simulations.
|
8
|
+
|
9
|
+
The gem does not create the cluster (not launch it). Currently the only supported Cloud platform is
|
10
|
+
Amazon AWS using either [OpenStudio's PAT](https://openstudio.nrel.gov) the [openstudio-aws gem](https://rubygems.org/gems/openstudio-aws) or using [vagrant](http://www.vagrantup.com/).
|
11
|
+
|
12
|
+
Instructions
|
13
|
+
------------
|
14
|
+
|
15
|
+
Testing
|
16
|
+
-------
|
17
|
+
|
18
|
+
This gem used RSpec for testing. To test simple run `rspec` at the command line.
|
19
|
+
|
20
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require "bundler"
|
2
|
+
Bundler.setup
|
3
|
+
|
4
|
+
require "rake"
|
5
|
+
require "rspec/core/rake_task"
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
8
|
+
require "openstudio/analysis/version"
|
9
|
+
|
10
|
+
task :gem => :build
|
11
|
+
task :build do
|
12
|
+
system "gem build openstudio-analysis.gemspec"
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "build and install gem locally"
|
16
|
+
task :install => :build do
|
17
|
+
system "gem install openstudio-analysis-#{OpenStudio::Analysis::VERSION}.gem --no-ri --no-rdoc"
|
18
|
+
end
|
19
|
+
|
20
|
+
task :release => :build do
|
21
|
+
system "git tag -a v#{OpenStudio::Analysis::VERSION} -m 'Tagging #{OpenStudio::Analysis::VERSION}'"
|
22
|
+
system "git push --tags"
|
23
|
+
system "gem push openstudio-analysis-#{OpenStudio::Analysis::VERSION}.gem"
|
24
|
+
system "rm openstudio-analysis-#{OpenStudio::Analysis::VERSION}.gem"
|
25
|
+
end
|
26
|
+
|
27
|
+
RSpec::Core::RakeTask.new("spec") do |spec|
|
28
|
+
spec.pattern = "spec/**/*_spec.rb"
|
29
|
+
end
|
30
|
+
|
31
|
+
RSpec::Core::RakeTask.new('spec:progress') do |spec|
|
32
|
+
spec.rspec_opts = %w(--format progress)
|
33
|
+
spec.pattern = "spec/**/*_spec.rb"
|
34
|
+
end
|
35
|
+
|
36
|
+
task :default => :spec
|
37
|
+
|
38
|
+
desc "import files from other repos"
|
39
|
+
task :import_files do
|
40
|
+
# tbd
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "uninstall all openstudio-analysis gems"
|
44
|
+
task :uninstall do
|
45
|
+
|
46
|
+
system "gem uninstall openstudio-analysis -a"
|
47
|
+
end
|
48
|
+
|
49
|
+
desc "reinstall the gem (uninstall, build, and reinstall"
|
50
|
+
task :reinstall => [:uninstall, :install]
|
51
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'faraday'
|
3
|
+
require 'uuid'
|
4
|
+
require 'roo'
|
5
|
+
require 'erb'
|
6
|
+
require 'zip'
|
7
|
+
|
8
|
+
# core
|
9
|
+
require 'openstudio/analysis/server_api'
|
10
|
+
require 'openstudio/analysis/version'
|
11
|
+
|
12
|
+
# translators
|
13
|
+
require 'openstudio/analysis/translator/excel'
|
14
|
+
|
15
|
+
# helpers
|
16
|
+
require 'openstudio/helpers/string'
|
@@ -0,0 +1,302 @@
|
|
1
|
+
# Class manages the communication with the server.
|
2
|
+
# Presently, this class is simple and stores all information in hashs
|
3
|
+
module OpenStudio
|
4
|
+
module Analysis
|
5
|
+
class ServerApi
|
6
|
+
attr_reader :hostname
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
defaults = {:hostname => "http://localhost:8080"}
|
10
|
+
options = defaults.merge(options)
|
11
|
+
|
12
|
+
@hostname = options[:hostname]
|
13
|
+
|
14
|
+
raise "no host defined for server api class" if @hostname.nil?
|
15
|
+
|
16
|
+
# create connection with basic capabilities
|
17
|
+
@conn = Faraday.new(:url => @hostname) do |faraday|
|
18
|
+
faraday.request :url_encoded # form-encode POST params
|
19
|
+
faraday.response :logger # log requests to STDOUT
|
20
|
+
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
|
21
|
+
end
|
22
|
+
|
23
|
+
# create connection to server api with multipart capabilities
|
24
|
+
@conn_multipart = Faraday.new(:url => @hostname) do |faraday|
|
25
|
+
faraday.request :multipart
|
26
|
+
faraday.request :url_encoded # form-encode POST params
|
27
|
+
faraday.response :logger # log requests to STDOUT
|
28
|
+
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_projects()
|
33
|
+
response = @conn.get '/projects.json'
|
34
|
+
|
35
|
+
projects_json = nil
|
36
|
+
if response.status == 200
|
37
|
+
projects_json = JSON.parse(response.body, :symbolize_names => true, :max_nesting => false)
|
38
|
+
else
|
39
|
+
raise "did not receive a 200 in get_projects"
|
40
|
+
end
|
41
|
+
|
42
|
+
projects_json
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_project_ids()
|
46
|
+
ids = get_projects()
|
47
|
+
ids.map { |project| project[:uuid] }
|
48
|
+
end
|
49
|
+
|
50
|
+
def delete_all()
|
51
|
+
ids = get_project_ids()
|
52
|
+
puts "Deleting Projects #{ids}"
|
53
|
+
ids.each do |id|
|
54
|
+
response = @conn.delete "/projects/#{id}.json"
|
55
|
+
if response.status == 200
|
56
|
+
puts "Successfully deleted project #{id}"
|
57
|
+
else
|
58
|
+
puts "ERROR deleting project #{id}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def new_project(options = {})
|
64
|
+
defaults = {project_name: "project #{(rand()*1000).round}"}
|
65
|
+
options = defaults.merge(options)
|
66
|
+
project_id = nil
|
67
|
+
|
68
|
+
project_hash = {project: {name: "#{options[:project_name]}"}}
|
69
|
+
|
70
|
+
response = @conn.post do |req|
|
71
|
+
req.url "/projects.json"
|
72
|
+
req.headers['Content-Type'] = 'application/json'
|
73
|
+
req.body = project_hash.to_json
|
74
|
+
end
|
75
|
+
|
76
|
+
if response.status == 201
|
77
|
+
project_id = JSON.parse(response.body)["_id"]
|
78
|
+
|
79
|
+
puts "new project created with ID: #{project_id}"
|
80
|
+
#grab the project id
|
81
|
+
elsif response.code == 500
|
82
|
+
puts "500 Error"
|
83
|
+
puts response.inspect
|
84
|
+
end
|
85
|
+
|
86
|
+
project_id
|
87
|
+
end
|
88
|
+
|
89
|
+
def get_analyses(project_id)
|
90
|
+
analysis_ids = []
|
91
|
+
response = @conn.get "/projects/#{project_id}.json"
|
92
|
+
if response.status == 200
|
93
|
+
puts "received the list of analyses for the project"
|
94
|
+
|
95
|
+
analyses = JSON.parse(response.body, :symbolize_names => true, :max_nesting => false)
|
96
|
+
if analyses[:analyses]
|
97
|
+
analyses[:analyses].each do |analysis|
|
98
|
+
analysis_ids << analysis[:_id]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
analysis_ids
|
104
|
+
end
|
105
|
+
|
106
|
+
def new_analysis(project_id, options)
|
107
|
+
defaults = {analysis_name: nil, reset_uuids: false}
|
108
|
+
options = defaults.merge(options)
|
109
|
+
|
110
|
+
raise "No project id passed" if project_id.nil?
|
111
|
+
raise "no formulation passed to new_analysis" if !options[:formulation_file]
|
112
|
+
raise "No formation exists #{options[:formulation_file]}" if !File.exists?(options[:formulation_file])
|
113
|
+
|
114
|
+
formulation_json = JSON.parse(File.read(options[:formulation_file]), :symbolize_names => true)
|
115
|
+
|
116
|
+
# read in the analysis id from the analysis.json file
|
117
|
+
analysis_id = nil
|
118
|
+
if options[:reset_uuids]
|
119
|
+
analysis_id = UUID.new.generate
|
120
|
+
formulation_json[:analysis][:uuid] = analysis_id
|
121
|
+
|
122
|
+
formulation_json[:analysis][:problem][:workflow].each do |wf|
|
123
|
+
wf[:uuid] = UUID.new.generate
|
124
|
+
if wf[:arguments]
|
125
|
+
wf[:arguments].each do |arg|
|
126
|
+
arg[:uuid] = UUID.new.generate
|
127
|
+
end
|
128
|
+
end
|
129
|
+
if wf[:variables]
|
130
|
+
wf[:variables].each do |var|
|
131
|
+
var[:uuid] = UUID.new.generate
|
132
|
+
if var[:argument]
|
133
|
+
var[:argument][:uuid] = UUID.new.generate
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
else
|
139
|
+
analysis_id = formulation_json[:analysis][:uuid]
|
140
|
+
end
|
141
|
+
raise "No analysis id defined in analyis.json #{options[:formulation_file]}" if analysis_id.nil?
|
142
|
+
|
143
|
+
# set the analysis name
|
144
|
+
formulation_json[:analysis][:name] = "#{options[:analysis_name]}" unless options[:analysis_name].nil?
|
145
|
+
|
146
|
+
# save out this file to compare
|
147
|
+
#File.open('formulation_merge.json', 'w') { |f| f << JSON.pretty_generate(formulation_json) }
|
148
|
+
|
149
|
+
response = @conn.post do |req|
|
150
|
+
req.url "projects/#{project_id}/analyses.json"
|
151
|
+
req.headers['Content-Type'] = 'application/json'
|
152
|
+
req.body = formulation_json.to_json
|
153
|
+
end
|
154
|
+
|
155
|
+
if response.status == 201
|
156
|
+
puts "asked to create analysis with #{analysis_id}"
|
157
|
+
#puts resp.inspect
|
158
|
+
analysis_id = JSON.parse(response.body)["_id"]
|
159
|
+
|
160
|
+
puts "new analysis created with ID: #{analysis_id}"
|
161
|
+
else
|
162
|
+
raise "Could not create new analysis"
|
163
|
+
end
|
164
|
+
|
165
|
+
# check if we need to upload the analysis zip file
|
166
|
+
if options[:upload_file]
|
167
|
+
raise "upload file does not exist #{options[:upload_file]}" if !File.exists?(options[:upload_file])
|
168
|
+
|
169
|
+
payload = {:file => Faraday::UploadIO.new(options[:upload_file], 'application/zip')}
|
170
|
+
response = @conn_multipart.post "analyses/#{analysis_id}/upload.json", payload
|
171
|
+
|
172
|
+
if response.status == 201
|
173
|
+
puts "Successfully uploaded ZIP file"
|
174
|
+
else
|
175
|
+
raise response.inspect
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
analysis_id
|
180
|
+
end
|
181
|
+
|
182
|
+
def upload_datapoint(analysis_id, options)
|
183
|
+
defaults = {reset_uuids: false}
|
184
|
+
options = defaults.merge(options)
|
185
|
+
|
186
|
+
raise "No analysis id passed" if analysis_id.nil?
|
187
|
+
raise "No datapoints file passed to new_analysis" if !options[:datapoint_file]
|
188
|
+
raise "No datapoints_file exists #{options[:datapoint_file]}" if !File.exists?(options[:datapoint_file])
|
189
|
+
|
190
|
+
dp_hash = JSON.parse(File.open(options[:datapoint_file]).read, :symbolize_names => true)
|
191
|
+
|
192
|
+
if options[:reset_uuids]
|
193
|
+
dp_hash[:analysis_uuid] = analysis_id
|
194
|
+
dp_hash[:uuid] = UUID.new.generate
|
195
|
+
end
|
196
|
+
|
197
|
+
# merge in the analysis_id as it has to be what is in the database
|
198
|
+
response = @conn.post do |req|
|
199
|
+
req.url "analyses/#{analysis_id}/data_points.json"
|
200
|
+
req.headers['Content-Type'] = 'application/json'
|
201
|
+
req.body = dp_hash.to_json
|
202
|
+
end
|
203
|
+
|
204
|
+
if response.status == 201
|
205
|
+
puts "new datapoints created for analysis #{analysis_id}"
|
206
|
+
else
|
207
|
+
raise "could not create new datapoints #{response.body}"
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def upload_datapoints(analysis_id, options)
|
212
|
+
defaults = {}
|
213
|
+
options = defaults.merge(options)
|
214
|
+
|
215
|
+
raise "No analysis id passed" if analysis_id.nil?
|
216
|
+
raise "No datapoints file passed to new_analysis" if !options[:datapoints_file]
|
217
|
+
raise "No datapoints_file exists #{options[:datapoints_file]}" if !File.exists?(options[:datapoints_file])
|
218
|
+
|
219
|
+
dp_hash = JSON.parse(File.open(options[:datapoints_file]).read, :symbolize_names => true)
|
220
|
+
|
221
|
+
# merge in the analysis_id as it has to be what is in the database
|
222
|
+
response = @conn.post do |req|
|
223
|
+
req.url "analyses/#{analysis_id}/data_points/batch_upload.json"
|
224
|
+
req.headers['Content-Type'] = 'application/json'
|
225
|
+
req.body = dp_hash.to_json
|
226
|
+
end
|
227
|
+
|
228
|
+
if response.status == 201
|
229
|
+
puts "new datapoints created for analysis #{analysis_id}"
|
230
|
+
else
|
231
|
+
raise "could not create new datapoints #{response.body}"
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def run_analysis(analysis_id, options)
|
236
|
+
defaults = {analysis_action: "start", without_delay: false}
|
237
|
+
options = defaults.merge(options)
|
238
|
+
|
239
|
+
puts "Run analysis is configured with #{options.to_json}"
|
240
|
+
response = @conn.post do |req|
|
241
|
+
req.url "analyses/#{analysis_id}/action.json"
|
242
|
+
req.headers['Content-Type'] = 'application/json'
|
243
|
+
req.body = options.to_json
|
244
|
+
req.options[:timeout] = 1800 #seconds
|
245
|
+
end
|
246
|
+
|
247
|
+
if response.status == 200
|
248
|
+
puts "Recieved request to run analysis #{analysis_id}"
|
249
|
+
else
|
250
|
+
raise "Could not start the analysis"
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
def kill_analysis(analysis_id)
|
255
|
+
analysis_action = {analysis_action: "stop"}
|
256
|
+
|
257
|
+
response = @conn.post do |req|
|
258
|
+
req.url "analyses/#{analysis_id}/action.json"
|
259
|
+
req.headers['Content-Type'] = 'application/json'
|
260
|
+
req.body = analysis_action.to_json
|
261
|
+
end
|
262
|
+
|
263
|
+
if response.status == 200
|
264
|
+
puts "Killed analysis #{analysis_id}"
|
265
|
+
else
|
266
|
+
#raise "Could not kill the analysis with response of #{response.inspect}"
|
267
|
+
end
|
268
|
+
|
269
|
+
end
|
270
|
+
|
271
|
+
def kill_all_analyses
|
272
|
+
project_ids = get_project_ids
|
273
|
+
puts "List of projects ids are: #{project_ids}"
|
274
|
+
|
275
|
+
project_ids.each do |project_id|
|
276
|
+
analysis_ids = get_analyses(project_id)
|
277
|
+
puts analysis_ids
|
278
|
+
analysis_ids.each do |analysis_id|
|
279
|
+
puts "Trying to kill #{analysis_id}"
|
280
|
+
kill_analysis(analysis_id)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
|
286
|
+
def get_datapoint_status(analysis_id, filter = nil)
|
287
|
+
# get the status of all the entire analysis
|
288
|
+
if !analysis_id.nil?
|
289
|
+
if filter.nil? || filter == ""
|
290
|
+
resp = @conn.get "analyses/#{analysis_id}/status.json"
|
291
|
+
puts "Data points (all): #{resp}"
|
292
|
+
else
|
293
|
+
resp = @conn.get "#{@hostname}/analyses/#{analysis_id}/status.json", {jobs: filter}
|
294
|
+
puts "Data points (#{filter}): #{resp}"
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
end
|
@@ -0,0 +1,366 @@
|
|
1
|
+
module OpenStudio
|
2
|
+
module Analysis
|
3
|
+
module Translator
|
4
|
+
class Excel
|
5
|
+
attr_reader :variables
|
6
|
+
attr_reader :models
|
7
|
+
attr_reader :weather_files
|
8
|
+
|
9
|
+
# remove these once we have classes to construct the JSON file
|
10
|
+
attr_reader :name
|
11
|
+
attr_reader :number_of_samples
|
12
|
+
|
13
|
+
# pass in the filename to read
|
14
|
+
def initialize(xls_filename)
|
15
|
+
@root_path = File.expand_path(File.dirname(xls_filename))
|
16
|
+
|
17
|
+
@xls = nil
|
18
|
+
# try to read the spreadsheet as a roo object
|
19
|
+
if File.exists?(xls_filename)
|
20
|
+
@xls = Roo::Spreadsheet.open(xls_filename)
|
21
|
+
else
|
22
|
+
raise "File #{xls_filename} does not exist"
|
23
|
+
end
|
24
|
+
|
25
|
+
# Initialize some other instance variables
|
26
|
+
@weather_files = []
|
27
|
+
@models = []
|
28
|
+
@other_files = []
|
29
|
+
@export_path = "./export"
|
30
|
+
@measure_path = "./measures"
|
31
|
+
@number_of_samples = 0
|
32
|
+
|
33
|
+
@setup = parse_setup()
|
34
|
+
@variables = parse_variables()
|
35
|
+
|
36
|
+
# call validate to make sure everything that is needed exists (i.e. directories)
|
37
|
+
validate_analysis()
|
38
|
+
end
|
39
|
+
|
40
|
+
# Save off the legacy format of the JSON file
|
41
|
+
def save_variable_json(filename)
|
42
|
+
FileUtils.rm_f(filename) if File.exists?(filename)
|
43
|
+
File.open(filename, 'w') { |f| f << JSON.pretty_generate(@variables) }
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def validate_analysis
|
48
|
+
# Setup the paths and do some error checking
|
49
|
+
raise "Measures directory '#{@measure_path}' does not exist" unless Dir.exists?(@measure_path)
|
50
|
+
|
51
|
+
@models.uniq!
|
52
|
+
raise "No seed models defined in spreadsheet" if @models.empty?
|
53
|
+
|
54
|
+
@models.each do |model|
|
55
|
+
raise "Seed model does not exist: #{model[:path]}" unless File.exists?(model[:path])
|
56
|
+
end
|
57
|
+
|
58
|
+
@weather_files.uniq!
|
59
|
+
raise "No weather files found based on what is in the spreadsheet" if @weather_files.empty?
|
60
|
+
|
61
|
+
@weather_files.each do |wf|
|
62
|
+
raise "Weather file does not exist: #{wf}" unless File.exists?(wf)
|
63
|
+
end
|
64
|
+
|
65
|
+
# This can be a directory as well
|
66
|
+
@other_files.each do |of|
|
67
|
+
raise "Other files do not exist for: #{of[:path]}" unless File.exists?(of[:path])
|
68
|
+
end
|
69
|
+
|
70
|
+
FileUtils.mkdir_p(@export_path)
|
71
|
+
end
|
72
|
+
|
73
|
+
def save_analysis
|
74
|
+
# save the format in the OpenStudio analysis json format
|
75
|
+
new_json = translate_to_analysis_json()
|
76
|
+
|
77
|
+
# iterate over each model and save the zip and json
|
78
|
+
@models.each do |model|
|
79
|
+
save_analysis_zip(model)
|
80
|
+
save_analysis_json(new_json, model)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
protected
|
85
|
+
|
86
|
+
# helper method for ERB
|
87
|
+
def get_binding
|
88
|
+
binding
|
89
|
+
end
|
90
|
+
|
91
|
+
# TODO: move this into a new class that helps construct this file
|
92
|
+
def translate_to_analysis_json
|
93
|
+
# Load in the templates for constructing the JSON file
|
94
|
+
template_root = File.join(File.dirname(__FILE__), "../../templates")
|
95
|
+
analysis_template = ERB.new(File.open("#{template_root}/analysis.json.erb", 'r').read)
|
96
|
+
workflow_template = ERB.new(File.open("#{template_root}/workflow_item.json.erb", 'r').read)
|
97
|
+
uncertain_variable_template = ERB.new(File.open("#{template_root}/uncertain_variable.json.erb", 'r').read)
|
98
|
+
discrete_uncertain_variable_template = ERB.new(File.open("#{template_root}/discrete_uncertain_variable.json.erb", 'r').read)
|
99
|
+
static_variable_template = ERB.new(File.open("#{template_root}/static_variable.json.erb", 'r').read)
|
100
|
+
pivot_variable_template = ERB.new(File.open("#{template_root}/pivot_variable.json.erb", 'r').read)
|
101
|
+
argument_template = ERB.new(File.open("#{template_root}/argument.json.erb", 'r').read)
|
102
|
+
|
103
|
+
# Templated analysis json file (this is what is returned)
|
104
|
+
puts "Analysis name is #{@name}"
|
105
|
+
openstudio_analysis_json = JSON.parse(analysis_template.result(get_binding))
|
106
|
+
|
107
|
+
@measure_index = -1
|
108
|
+
@variables['data'].each do |measure|
|
109
|
+
# With OpenStudio server we need to create the workflow with all the measure instances
|
110
|
+
if measure['enabled'] && measure['name'] != 'baseline'
|
111
|
+
@measure_index += 1
|
112
|
+
|
113
|
+
puts " Adding measure item '#{measure['name']}'"
|
114
|
+
@measure = measure
|
115
|
+
@measure['measure_file_name_dir'] = @measure['measure_file_name'].underscore
|
116
|
+
|
117
|
+
# Grab the measure json file out of the right directory
|
118
|
+
wf = JSON.parse(workflow_template.result(get_binding))
|
119
|
+
|
120
|
+
# add in the variables
|
121
|
+
measure['variables'].each do |variable|
|
122
|
+
@variable = variable
|
123
|
+
|
124
|
+
# Determine if row is suppose to be an argument or a variable to be perturbed.
|
125
|
+
if @variable['variable_type'] == 'argument'
|
126
|
+
ag = nil
|
127
|
+
if @variable['method'] == 'static'
|
128
|
+
# add this as an argument
|
129
|
+
ag = JSON.parse(argument_template.result(get_binding))
|
130
|
+
elsif raise "can not have an argument without having a static value defined in which to set the argument"
|
131
|
+
end
|
132
|
+
wf['arguments'] << ag
|
133
|
+
else
|
134
|
+
vr = nil
|
135
|
+
if @variable['method'] == 'static'
|
136
|
+
# add this as an argument
|
137
|
+
vr = JSON.parse(static_variable_template.result(get_binding))
|
138
|
+
elsif @variable['method'] == 'lhs'
|
139
|
+
if @variable['type'] == 'enum'
|
140
|
+
@values_and_weights = @variable['distribution']['enumerations'].map { |v| {value: v} }.to_json
|
141
|
+
vr =JSON.parse(discrete_uncertain_variable_template.result(get_binding))
|
142
|
+
else
|
143
|
+
vr = JSON.parse(uncertain_variable_template.result(get_binding))
|
144
|
+
end
|
145
|
+
elsif @variable['method'] == 'pivot'
|
146
|
+
@values_and_weights = @variable['distribution']['enumerations'].map { |v| {value: v} }.to_json
|
147
|
+
vr =JSON.parse(pivot_variable_template.result(get_binding))
|
148
|
+
end
|
149
|
+
wf['variables'] << vr
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
openstudio_analysis_json['analysis']['problem']['workflow'] << wf
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
openstudio_analysis_json
|
158
|
+
end
|
159
|
+
|
160
|
+
# Package up the seed, weather files, and measures
|
161
|
+
def save_analysis_zip(model)
|
162
|
+
zipfile_name = "#{@export_path}/#{model[:name]}.zip"
|
163
|
+
FileUtils.rm_f(zipfile_name) if File.exists?(zipfile_name)
|
164
|
+
|
165
|
+
Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
|
166
|
+
@weather_files.each do |filename|
|
167
|
+
puts " Adding #{filename}"
|
168
|
+
zipfile.add("./weather/#{File.basename(filename)}", filename)
|
169
|
+
end
|
170
|
+
|
171
|
+
Dir.glob("#{@measure_path}/**/*.rb").each do |measure|
|
172
|
+
next if measure.include?("spec") # don't include the spec folders nor files
|
173
|
+
measure_name = measure.split(File::SEPARATOR).last(2).first
|
174
|
+
puts " Adding ./measures/#{measure_name}/#{File.basename(measure)}"
|
175
|
+
zipfile.add("./measures/#{measure_name}/#{File.basename(measure)}", measure)
|
176
|
+
end
|
177
|
+
|
178
|
+
puts "Adding #{model[:path]}"
|
179
|
+
zipfile.add("./seed/#{File.basename(model[:path])}", model[:path])
|
180
|
+
|
181
|
+
puts "Adding in other files #{@other_files.inspect}"
|
182
|
+
@other_files.each do |others|
|
183
|
+
Dir[File.join(others[:path], '**', '**')].each do |file|
|
184
|
+
zipfile.add(file.sub(others[:path], "./lib/#{others[:lib_zip_name]}/"), file)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def save_analysis_json(analysis_json, model)
|
191
|
+
# Set the seed model in the analysis_json
|
192
|
+
analysis_json['analysis']['seed']['file_type'] = model[:type]
|
193
|
+
# This is the path that will be seen on the server when this runs
|
194
|
+
analysis_json['analysis']['seed']['path'] = "./seed/#{File.basename(model[:path])}"
|
195
|
+
|
196
|
+
# Set the weather file as the first in the list -- this is optional
|
197
|
+
# TODO: check if epw or if zip file
|
198
|
+
analysis_json['analysis']['weather_file']['file_type'] = 'EPW'
|
199
|
+
analysis_json['analysis']['weather_file']['path'] = "./weather/#{File.basename(@weather_files.first, '.zip')}.epw"
|
200
|
+
|
201
|
+
json_file_name = "#{@export_path}/#{model[:name]}.json"
|
202
|
+
FileUtils.rm_f(json_file_name) if File.exists?(json_file_name)
|
203
|
+
|
204
|
+
File.open("#{@export_path}/#{model[:name]}.json", "w") { |f| f << JSON.pretty_generate(analysis_json) }
|
205
|
+
end
|
206
|
+
|
207
|
+
|
208
|
+
# parse_setup will pull out the data on the "setup" tab and store it in memory for later use
|
209
|
+
def parse_setup()
|
210
|
+
rows = @xls.sheet('Setup').parse()
|
211
|
+
b_run_setup = false
|
212
|
+
b_problem_setup = false
|
213
|
+
b_weather_files = false
|
214
|
+
b_models = false
|
215
|
+
b_other_libs = false
|
216
|
+
|
217
|
+
rows.each do |row|
|
218
|
+
if row[0] == "Running Setup"
|
219
|
+
b_run_setup = true
|
220
|
+
b_problem_setup = false
|
221
|
+
b_weather_files = false
|
222
|
+
b_models = false
|
223
|
+
b_other_libs = false
|
224
|
+
next
|
225
|
+
elsif row[0] == "Problem Definition"
|
226
|
+
b_run_setup = false
|
227
|
+
b_problem_setup = true
|
228
|
+
b_weather_files = false
|
229
|
+
b_models = false
|
230
|
+
b_other_libs = false
|
231
|
+
next
|
232
|
+
elsif row[0] == "Weather Files"
|
233
|
+
b_run_setup = false
|
234
|
+
b_problem_setup = false
|
235
|
+
b_weather_files = true
|
236
|
+
b_models = false
|
237
|
+
b_other_libs = false
|
238
|
+
next
|
239
|
+
elsif row[0] == "Models"
|
240
|
+
b_run_setup = false
|
241
|
+
b_problem_setup = false
|
242
|
+
b_weather_files = false
|
243
|
+
b_models = true
|
244
|
+
b_other_libs = false
|
245
|
+
next
|
246
|
+
elsif row[0] == "Other Library Files"
|
247
|
+
b_run_setup = false
|
248
|
+
b_problem_setup = false
|
249
|
+
b_weather_files = false
|
250
|
+
b_models = false
|
251
|
+
b_other_libs = true
|
252
|
+
next
|
253
|
+
end
|
254
|
+
|
255
|
+
next if row[0].nil?
|
256
|
+
|
257
|
+
if b_run_setup
|
258
|
+
@name = row[1].chomp if row[0] == "Analysis Name"
|
259
|
+
@export_path = File.expand_path(File.join(@root_path, row[1])) if row[0] == "Export Directory"
|
260
|
+
@measure_path = File.expand_path(File.join(@root_path, row[1])) if row[0] == "Measure Directory"
|
261
|
+
elsif b_problem_setup
|
262
|
+
@number_of_samples = row[1].to_i if row[0] == "Number of Samples"
|
263
|
+
elsif b_weather_files
|
264
|
+
if row[0] == "Weather File"
|
265
|
+
@weather_files += Dir.glob(File.expand_path(File.join(@root_path, row[1])))
|
266
|
+
end
|
267
|
+
elsif b_models
|
268
|
+
@models << {name: row[1], type: row[2], path: File.expand_path(File.join(@root_path, row[3]))}
|
269
|
+
elsif b_other_libs
|
270
|
+
@other_files << {lib_zip_name: row[1], path: row[2]}
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
|
276
|
+
# parse_variables will parse the XLS spreadsheet and save the data into
|
277
|
+
# a higher level JSON file. The JSON file is historic and it should really
|
278
|
+
# be omitted as an intermediate step
|
279
|
+
def parse_variables()
|
280
|
+
rows = @xls.sheet('Sensitivity').parse()
|
281
|
+
data = {}
|
282
|
+
data['data'] = []
|
283
|
+
|
284
|
+
icnt = 0
|
285
|
+
measure_index = -1
|
286
|
+
variable_index = -1
|
287
|
+
measure_name = nil
|
288
|
+
rows.each do |row|
|
289
|
+
icnt += 1
|
290
|
+
# puts "Parsing line: #{icnt}"
|
291
|
+
next if icnt <= 3 # skip the first 3 lines of the file
|
292
|
+
|
293
|
+
# check if we are a measure
|
294
|
+
if row[0].nil?
|
295
|
+
unless measure_name.nil?
|
296
|
+
variable_index += 1
|
297
|
+
|
298
|
+
var = {}
|
299
|
+
var['variable_type'] = row[1]
|
300
|
+
var['display_name'] = row[2].strip
|
301
|
+
var['machine_name'] = var['display_name'].downcase.strip.gsub("-", "_").gsub(" ", "_").strip
|
302
|
+
var['name'] = row[3].strip
|
303
|
+
var['index'] = variable_index #order of the variable (eventually use to force order of applying measures)
|
304
|
+
|
305
|
+
var['method'] = row[4]
|
306
|
+
var['type'] = row[5]
|
307
|
+
var['units'] = row[6]
|
308
|
+
|
309
|
+
var['distribution'] = {}
|
310
|
+
|
311
|
+
#parse the enums
|
312
|
+
if var['type'] == 'enum'
|
313
|
+
var['distribution']['enumerations'] = row[8].gsub("|", "").split(",").map { |v| v.strip }
|
314
|
+
elsif var['type'] == 'bool' #TODO: i think this has been deprecated
|
315
|
+
var['distribution']['enumerations'] = []
|
316
|
+
var['distribution']['enumerations'] << 'true'
|
317
|
+
var['distribution']['enumerations'] << 'false'
|
318
|
+
end
|
319
|
+
|
320
|
+
if var['method'] == 'lhs'
|
321
|
+
var['distribution']['min'] = row[9]
|
322
|
+
var['distribution']['max'] = row[10]
|
323
|
+
var['distribution']['mean'] = row[11]
|
324
|
+
var['distribution']['stddev'] = row[12]
|
325
|
+
var['distribution']['type'] = row[13]
|
326
|
+
var['distribution']['source'] = row[14]
|
327
|
+
elsif var['method'] == 'static'
|
328
|
+
var['distribution']['static_value'] = row[7]
|
329
|
+
#var['distribution']['apply_method'] = row[14]
|
330
|
+
var['distribution']['source'] = row[14]
|
331
|
+
end
|
332
|
+
|
333
|
+
var['notes'] = row[15]
|
334
|
+
var['relation_to_eui'] = row[16]
|
335
|
+
|
336
|
+
data['data'][measure_index]['apply_method'] ||= row[14]
|
337
|
+
data['data'][measure_index]['variables'] << var
|
338
|
+
end
|
339
|
+
else
|
340
|
+
measure_index += 1
|
341
|
+
variable_index = 0
|
342
|
+
data['data'][measure_index] = {}
|
343
|
+
|
344
|
+
#generate name id
|
345
|
+
puts "Parsing measure #{row[1]}"
|
346
|
+
display_name = row[1].chomp.strip
|
347
|
+
measure_name = display_name.downcase.strip.gsub("-", "_").gsub(" ", "_")
|
348
|
+
data['data'][measure_index]['display_name'] = display_name
|
349
|
+
data['data'][measure_index]['name'] = measure_name
|
350
|
+
data['data'][measure_index]['enabled'] = row[0] == "TRUE" ? true : false
|
351
|
+
data['data'][measure_index]['measure_file_name'] = row[2]
|
352
|
+
data['data'][measure_index]['measure_file_name_directory'] = row[2].underscore
|
353
|
+
data['data'][measure_index]['version'] = @version_id
|
354
|
+
|
355
|
+
data['data'][measure_index]['variables'] = []
|
356
|
+
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
data
|
361
|
+
end
|
362
|
+
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
{
|
2
|
+
"analysis": {
|
3
|
+
"display_name": "<%= @name %>",
|
4
|
+
"name": "<%= @name.downcase.gsub(" ", "_") %>",
|
5
|
+
"algorithm": {
|
6
|
+
"sample_method": "lhs",
|
7
|
+
"sensitivity_method": "single_measure",
|
8
|
+
"number_of_samples": <%= @number_of_samples %>
|
9
|
+
},
|
10
|
+
"parameter_space": [],
|
11
|
+
"problem": {
|
12
|
+
"number_of_samples_KEEP_HERE_UNTIL_ALGO_IS_IMPLEMENTED": <%= @number_of_samples %>,
|
13
|
+
"number_of_samples": <%= @number_of_samples %>,
|
14
|
+
"name": "Problem",
|
15
|
+
"workflow": []
|
16
|
+
},
|
17
|
+
"seed": {
|
18
|
+
"file_type": "xml",
|
19
|
+
"path": "unknown"
|
20
|
+
},
|
21
|
+
"weather_file": {
|
22
|
+
"file_type": "EPW",
|
23
|
+
"path": "unknown"
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
{
|
2
|
+
"display_name": "<%= @variable['display_name'] %>",
|
3
|
+
"machine_name": "<%= @variable['machine_name'] %>",
|
4
|
+
"name": "<%= @variable['name'] %>",
|
5
|
+
"value": "<%= @variable['distribution']['static_value'] %>",
|
6
|
+
"uuid_DELETEME": "<%= UUID.new.generate %>",
|
7
|
+
"uuid": "<%= UUID.new.generate %>",
|
8
|
+
"version_uuid_DELETEME": "<%= UUID.new.generate %>",
|
9
|
+
"version_uuid": "<%= UUID.new.generate %>"
|
10
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
{
|
2
|
+
"argument": {
|
3
|
+
"display_name": "<%= @variable['display_name'] %>",
|
4
|
+
"machine_name": "<%= @variable['machine_name'] %>",
|
5
|
+
"name": "<%= @variable['name'] %>",
|
6
|
+
"required": false,
|
7
|
+
"uuid": "a0618d15-bb0b-4494-a72f-8ad628693a7e",
|
8
|
+
"version_uuid": "b33cf6b0-f1aa-4706-afab-9470e6bd1912"
|
9
|
+
},
|
10
|
+
"display_name": "<%= @variable['display_name'] %>",
|
11
|
+
"machine_name": "<%= @variable['machine_name'] %>",
|
12
|
+
"name": "<%= @variable['machine_name'] %>",
|
13
|
+
"units": "<%= @variable['units'] %>",
|
14
|
+
"variable": true,
|
15
|
+
"variable_ADDME": true,
|
16
|
+
"relation_to_output": "<%= @variable['relation_to_eui'] %>",
|
17
|
+
"uncertainty_description": {
|
18
|
+
"attributes": [
|
19
|
+
{
|
20
|
+
"name": "discrete",
|
21
|
+
"values_and_weights":
|
22
|
+
<%= @values_and_weights %>
|
23
|
+
}
|
24
|
+
],
|
25
|
+
"type": "discrete_uncertain"
|
26
|
+
},
|
27
|
+
"uuid": "d157d709-b83e-42bd-bd30-1bc3a7979672",
|
28
|
+
"variable_type": "RubyContinuousVariable",
|
29
|
+
"version_uuid": "26e7d8de-83e3-4a53-938b-45d3e0f29953"
|
30
|
+
}
|
31
|
+
|
32
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
{
|
2
|
+
"argument": {
|
3
|
+
"display_name": "<%= @variable['display_name'] %>",
|
4
|
+
"name": "<%= @variable['name'] %>",
|
5
|
+
"required": false,
|
6
|
+
"uuid": "a0618d15-bb0b-4494-a72f-8ad628693a7e",
|
7
|
+
"version_uuid": "b33cf6b0-f1aa-4706-afab-9470e6bd1912"
|
8
|
+
},
|
9
|
+
"display_name": "<%= @variable['display_name'] %>",
|
10
|
+
"machine_name": "<%= @variable['machine_name'] %>",
|
11
|
+
"name": "<%= @variable['machine_name'] %>",
|
12
|
+
"units": "<%= @variable['units'] %>",
|
13
|
+
"pivot": true,
|
14
|
+
"pivot_ADDME": true,
|
15
|
+
"relation_to_output": null,
|
16
|
+
"uncertainty_description": {
|
17
|
+
"attributes": [
|
18
|
+
{
|
19
|
+
"name": "discrete",
|
20
|
+
"values_and_weights":
|
21
|
+
<%= @values_and_weights %>
|
22
|
+
}
|
23
|
+
],
|
24
|
+
"type": "discrete_uncertain"
|
25
|
+
},
|
26
|
+
"uuid": "d157d709-b83e-42bd-bd30-1bc3a7979672",
|
27
|
+
"variable_type": "RubyContinuousVariable",
|
28
|
+
"version_uuid": "26e7d8de-83e3-4a53-938b-45d3e0f29953"
|
29
|
+
}
|
30
|
+
|
31
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
{
|
2
|
+
"argument": {
|
3
|
+
"display_name": "<%= @variable['display_name'] %>",
|
4
|
+
"machine_name": "<%= @variable['machine_name'] %>",
|
5
|
+
"name": "<%= @variable['name'] %>",
|
6
|
+
"uuid": "<%= UUID.new.generate %>",
|
7
|
+
"version_uuid": "b33cf6b0-f1aa-4706-afab-9470e6bd1912"
|
8
|
+
},
|
9
|
+
"display_name": "<%= @variable['display_name'] %>",
|
10
|
+
"machine_name": "<%= @variable['machine_name'] %>",
|
11
|
+
"name": "<%= @variable['machine_name'] %>",
|
12
|
+
"units": "<%= @variable['units'] %>",
|
13
|
+
"static": true,
|
14
|
+
"static_ADDME": true,
|
15
|
+
"relation_to_output": "<%= @variable['relation_to_eui'] %>",
|
16
|
+
"relation_to_output_ADDME": "<%= @variable['relation_to_eui'] %>",
|
17
|
+
"static_value": <%= @variable['distribution']['static_value'].inspect %>,
|
18
|
+
"static_value_ADDME": <%= @variable['distribution']['static_value'].inspect %>,
|
19
|
+
"uuid": "d157d709-b83e-42bd-bd30-1bc3a7979672",
|
20
|
+
"variable_type": "RubyContinuousVariable",
|
21
|
+
"version_uuid": "26e7d8de-83e3-4a53-938b-45d3e0f29953"
|
22
|
+
}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
{
|
2
|
+
"argument": {
|
3
|
+
"display_name": "<%= @variable['display_name'] %>",
|
4
|
+
"machine_name": "<%= @variable['machine_name'] %>",
|
5
|
+
"name": "<%= @variable['name'] %>",
|
6
|
+
"uuid": "a0618d15-bb0b-4494-a72f-8ad628693a7e",
|
7
|
+
"version_uuid": "b33cf6b0-f1aa-4706-afab-9470e6bd1912"
|
8
|
+
},
|
9
|
+
"display_name": "<%= @variable['display_name'] %>",
|
10
|
+
"machine_name": "<%= @variable['machine_name'] %>",
|
11
|
+
"name": "<%= @variable['machine_name'] %>",
|
12
|
+
"minimum": <%= @variable['distribution']['min'].inspect %>,
|
13
|
+
"maximum": <%= @variable['distribution']['max'].inspect %>,
|
14
|
+
"units": "<%= @variable['units'] %>",
|
15
|
+
"variable": true,
|
16
|
+
"variable_ADDME": true,
|
17
|
+
"relation_to_output": "<%= @variable['relation_to_eui'] %>",
|
18
|
+
"uncertainty_description": {
|
19
|
+
"attributes": [
|
20
|
+
{
|
21
|
+
"name": "modes",
|
22
|
+
"value": <%= @variable['distribution']['mean'] %>
|
23
|
+
},
|
24
|
+
{
|
25
|
+
"name": "lower_bounds",
|
26
|
+
"value": <%= @variable['distribution']['min'] %>
|
27
|
+
},
|
28
|
+
{
|
29
|
+
"name": "upper_bounds",
|
30
|
+
"value": <%= @variable['distribution']['max'] %>
|
31
|
+
},
|
32
|
+
{
|
33
|
+
"name": "stddev",
|
34
|
+
"value": <%= @variable['distribution']['stddev'] %>
|
35
|
+
}
|
36
|
+
],
|
37
|
+
"type": <%= @variable['distribution']['type'].inspect %>
|
38
|
+
},
|
39
|
+
"uuid": "d157d709-b83e-42bd-bd30-1bc3a7979672",
|
40
|
+
"variable_type": "RubyContinuousVariable",
|
41
|
+
"version_uuid": "26e7d8de-83e3-4a53-938b-45d3e0f29953"
|
42
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"arguments": [],
|
3
|
+
"bcl_measure_directory": "./measures/<%= @measure['measure_file_name_directory'] %>",
|
4
|
+
"measure_definition_directory_CHANGE_TO_ME": "./measures/<%= @measure['measure_file_name_directory'] %>",
|
5
|
+
"bcl_measure_class_name_ADDME": "<%= @measure['measure_file_name'] %>",
|
6
|
+
"measure_definition_class_name_CHANGE_TO_ME": "<%= @measure['measure_file_name'] %>",
|
7
|
+
"bcl_measure_uuid": "<%= UUID.new.generate %>",
|
8
|
+
"measure_definition_uuid_CHANGE_TO_ME": "<%= UUID.new.generate %>",
|
9
|
+
"bcl_measure_version_uuid": "<%= UUID.new.generate %>",
|
10
|
+
"measure_definition_version_uuid_CHANGE_TO_ME": "<%= UUID.new.generate %>",
|
11
|
+
"measure_type": "XmlMeasure",
|
12
|
+
"name": "<%= @measure['name'] %>",
|
13
|
+
"display_name": "<%= @measure['display_name'] %>",
|
14
|
+
"uuid": "<%= UUID.new.generate %>",
|
15
|
+
"variables": [],
|
16
|
+
"version_uuid": "<%= UUID.new.generate %>",
|
17
|
+
"workflow_index": <%= @measure_index %>,
|
18
|
+
"workflow_step_type": "Measure"
|
19
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe OpenStudio::Analysis::ServerApi do
|
4
|
+
context "create a new localhost instance" do
|
5
|
+
before(:all) do
|
6
|
+
@api = OpenStudio::Analysis::ServerApi.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should set the default host to localhost" do
|
10
|
+
@api.hostname.should eq("http://localhost:8080")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "test not localhost" do
|
15
|
+
it "should have a not localhost URL" do
|
16
|
+
options = {hostname: "http://abc.def.ghi"}
|
17
|
+
api = OpenStudio::Analysis::ServerApi.new(options)
|
18
|
+
api.hostname.should eq(options[:hostname])
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: openstudio-analysis
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nicholas Long
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-11-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: uuid
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: roo
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.12.2
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.12.2
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubyzip
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.1.0
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.1.0
|
83
|
+
description: Basic classes for generating the files needed for OpenStudio-Server
|
84
|
+
email:
|
85
|
+
- Nicholas.Long@nrel.gov
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- lib/openstudio/analysis/server_api.rb
|
91
|
+
- lib/openstudio/analysis/translator/excel.rb
|
92
|
+
- lib/openstudio/analysis/version.rb
|
93
|
+
- lib/openstudio/helpers/string.rb
|
94
|
+
- lib/openstudio/templates/analysis.json.erb
|
95
|
+
- lib/openstudio/templates/argument.json.erb
|
96
|
+
- lib/openstudio/templates/discrete_uncertain_variable.json.erb
|
97
|
+
- lib/openstudio/templates/pivot_variable.json.erb
|
98
|
+
- lib/openstudio/templates/static_variable.json.erb
|
99
|
+
- lib/openstudio/templates/uncertain_variable.json.erb
|
100
|
+
- lib/openstudio/templates/workflow_item.json.erb
|
101
|
+
- lib/openstudio-analysis.rb
|
102
|
+
- README.md
|
103
|
+
- Rakefile
|
104
|
+
- spec/openstudio-analysis/server_api_spec.rb
|
105
|
+
- spec/spec_helper.rb
|
106
|
+
homepage: http://openstudio.nrel.gov
|
107
|
+
licenses:
|
108
|
+
- LGPL
|
109
|
+
metadata: {}
|
110
|
+
post_install_message:
|
111
|
+
rdoc_options: []
|
112
|
+
require_paths:
|
113
|
+
- lib
|
114
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '2.0'
|
119
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - '>='
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: 1.3.6
|
124
|
+
requirements: []
|
125
|
+
rubyforge_project:
|
126
|
+
rubygems_version: 2.0.2
|
127
|
+
signing_key:
|
128
|
+
specification_version: 4
|
129
|
+
summary: Create JSON, ZIP to communicate with OpenStudio Distributed Analysis in the
|
130
|
+
Cloud
|
131
|
+
test_files:
|
132
|
+
- spec/openstudio-analysis/server_api_spec.rb
|
133
|
+
- spec/spec_helper.rb
|