bcl 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,479 +0,0 @@
1
- ######################################################################
2
- # Copyright (c) 2008-2013, Alliance for Sustainable Energy.
3
- # All rights reserved.
4
- #
5
- # This library is free software; you can redistribute it and/or
6
- # modify it under the terms of the GNU Lesser General Public
7
- # License as published by the Free Software Foundation; either
8
- # version 2.1 of the License, or (at your option) any later version.
9
- #
10
- # This library is distributed in the hope that it will be useful,
11
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
- # Lesser General Public License for more details.
14
- #
15
- # You should have received a copy of the GNU Lesser General Public
16
- # License along with this library; if not, write to the Free Software
17
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
- ######################################################################
19
-
20
- # Provides programmatic access to the component.xsd schema needed for
21
- # generating the component information that will be uploaded to
22
- # the Building Component Library.
23
-
24
- require 'rubygems'
25
-
26
- require 'pathname'
27
- require 'csv'
28
- require 'builder' #gem install builder (creates xml files)
29
- require 'uuid' # gem install uuid
30
- require 'fileutils'
31
-
32
- require 'bcl/TarBall'
33
-
34
- module BCL
35
-
36
- SCHEMA_LOCATION = "component.xsd"
37
-
38
- ProvStruct = Struct.new(:author, :datetime, :comment)
39
- TagsStruct = Struct.new(:descriptor)
40
- AttrStruct = Struct.new(:name, :value, :datatype, :units)
41
- FileStruct = Struct.new(:version_software_program, :version_id, :fqp_file, :filename, :filetype)
42
- #cost_type is an enumeration (not enforced) of installation, material, operations and maintenance,
43
- #variable operations and maintenance, salvage
44
- CostStruct = Struct.new(:cost_name, :cost_type, :category, :value, :interval,
45
- :interval_units, :year, :location, :units, :currency, :source,
46
- :reference_component_name, :reference_component_id)
47
- ObjectStruct = Struct.new(:obj_type, :obj_instance)
48
-
49
- class Component
50
- attr_accessor :name
51
- attr_accessor :uid
52
- attr_accessor :comp_version_id
53
- attr_accessor :description
54
- attr_accessor :comment
55
- attr_accessor :fidelity_level
56
- attr_accessor :source_manufacturer
57
- attr_accessor :source_model
58
- attr_accessor :source_serial_no
59
- attr_accessor :source_year
60
- attr_accessor :source_url
61
- attr_accessor :tags
62
- attr_accessor :provenance
63
- attr_accessor :attributes
64
- attr_accessor :files
65
- attr_accessor :costs
66
- attr_accessor :objects
67
-
68
- public
69
-
70
- #the save path is where the component will be saved
71
- def initialize(save_path)
72
- @name = "" #this is also a unique identifier to the component...
73
- @uid = UUID.new.generate
74
- @comp_version_id = UUID.new.generate
75
- @description = ""
76
- @comment = ""
77
- @fidelity_level = 0 #restricted to level_1 to level_5
78
- @source_manufacturer = ""
79
- @source_model = ""
80
- @source_serial_no = ""
81
- @source_year = ""
82
- @source_url = ""
83
-
84
- #these items have multiple instances
85
- @provenance = []
86
- @tags = []
87
- @attributes = []
88
- @files = []
89
- @costs = []
90
- @objects = [] #container for saving the idf/osm snippets
91
-
92
- @path = save_path
93
-
94
- #puts "[ComponentXml] " + @path
95
- #need to hit a webservice to validate which tags and attributes are
96
- #available (including units?)
97
-
98
- #todo: validate against master taxonomy
99
- end
100
-
101
- def open_component(filename)
102
- read_component_xml(filename)
103
- end
104
-
105
- # savefile, save the component xml along with
106
- # the files that have been added to the object
107
- def save_tar_gz(delete_files = true)
108
- current_d = Dir.pwd
109
- paths = []
110
-
111
- save_component_xml
112
-
113
- paths << "./component.xml"
114
-
115
- #copy over the files to the directory
116
- @files.each do |file|
117
- src_path = Pathname.new(file.fqp_file)
118
- dest_path = Pathname.new("#{resolve_path}/#{file.filename}")
119
- if File.exists?(src_path)
120
- if src_path == dest_path
121
- #do nothing, file is already where it needs to be
122
- else
123
- #move the file where it needs to go
124
- FileUtils.cp(src_path, dest_path)
125
- end
126
- else
127
- puts "#{src_path} -> File does not exist"
128
- end
129
- paths << "./#{file.filename}"
130
- end
131
-
132
- #take all the files and tar.gz them -- name the file the same as
133
- #the directory
134
-
135
- Dir.chdir("#{resolve_path}")
136
- destination = "#{@name.gsub(" ","_").gsub("/","_").gsub("-","_").gsub("___","_").gsub("__","_").gsub("in.","in").gsub(",","").strip}.tar.gz"
137
-
138
- File.delete(destination) if File.exists?(destination)
139
-
140
- BCL.tarball(destination, paths)
141
-
142
- Dir.chdir(current_d)
143
-
144
- if (delete_files)
145
- @files.each do |file|
146
- if File.exists?(File.dirname(file.fqp_file))
147
- puts "[ComponentXml] Deleting: #{File.dirname(file.fqp_file)}"
148
- FileUtils.rm_rf(File.dirname(file.fqp_file))
149
- end
150
- end
151
- end
152
-
153
- #puts "[ComponentXml] " + Dir.pwd
154
- end
155
-
156
- def add_provenance(author, datetime, comment)
157
- prov = ProvStruct.new
158
- prov.author = author
159
- prov.datetime = datetime
160
- prov.comment = comment
161
-
162
- @provenance << prov
163
- end
164
-
165
- def add_tag(tag_name)
166
- tag = TagsStruct.new
167
- tag.descriptor = tag_name
168
-
169
- @tags << tag
170
- end
171
-
172
- def add_attribute(name, value, units, datatype = nil)
173
- attr = AttrStruct.new
174
- attr.name = name
175
- attr.value = value
176
-
177
- if !datatype.nil?
178
- attr.datatype = datatype
179
- else
180
- attr.datatype = get_datatype(value)
181
- end
182
- attr.units = units
183
-
184
- @attributes << attr
185
- end
186
-
187
- def add_file(version_sp, version_id, fqp_file, filename, filetype)
188
- fs = FileStruct.new
189
- fs.version_software_program = version_sp
190
- fs.version_id = version_id
191
- fs.fqp_file = fqp_file
192
- fs.filename = filename
193
- fs.filetype = filetype
194
-
195
- @files << fs
196
- end
197
-
198
-
199
- def add_cost(cost_name, cost_type, category, value, units, interval, interval_units, year, location, currency,
200
- source, reference_component_name, reference_component_id)
201
- cs = CostStruct.new
202
- cs.cost_name = cost_name
203
- cs.cost_type = cost_type
204
- cs.category = category
205
- cs.value = value
206
- cs.interval = interval
207
- cs.interval_units = interval_units
208
- cs.year = year
209
- cs.location = location
210
- cs.units = units
211
- cs.currency = currency
212
- cs.source = source
213
- cs.reference_component_name = reference_component_name
214
- cs.reference_component_id = reference_component_id
215
-
216
- @costs << cs
217
- end
218
-
219
- def add_object(object_type, object_instance)
220
- ob = ObjectStruct.new
221
- ob.obj_type = object_type
222
- ob.obj_instance = object_instance
223
-
224
- @objects << ob
225
- end
226
-
227
- def resolve_path
228
- FileUtils.mkdir_p(@path) unless File.directory?(@path)
229
- new_path = "#{@path}/#{name.gsub(" ","_").gsub("/","_").gsub("-","_").gsub("___","_").gsub("__","_").gsub("in.","in").gsub(",","").strip}"
230
- FileUtils.mkdir_p(new_path) unless File.directory?(new_path)
231
- result = new_path
232
- end
233
-
234
- def osm_resolve_path
235
- FileUtils.mkdir_p(@path) unless File.directory?(@path)
236
- new_path = "#{@path}/osm_#{name.gsub(" ","_").gsub("/","_").gsub("-","_").gsub("___","_").gsub("__","_").gsub("in.","in").gsub(",","").strip}"
237
- FileUtils.mkdir_p(new_path) unless File.directory?(new_path)
238
- result = new_path
239
- end
240
-
241
- def osc_resolve_path
242
- FileUtils.mkdir_p(@path) unless File.directory?(@path)
243
- new_path = "#{@path}/osc_#{name.gsub(" ","_").gsub("/","_").gsub("-","_").gsub("___","_").gsub("__","_").gsub("in.","in").gsub(",","").strip}"
244
- FileUtils.mkdir_p(new_path) unless File.directory?(new_path)
245
- result = new_path
246
- end
247
-
248
- def resolve_component_path(component_type)
249
- FileUtils.mkdir_p(@path) unless File.directory?(@path)
250
- new_path = @path + '/OpenStudio'
251
- FileUtils.mkdir_p(new_path) unless File.directory?(new_path)
252
- new_path = new_path + "/#{component_type}"
253
- FileUtils.mkdir_p(new_path) unless File.directory?(new_path)
254
- return new_path
255
- end
256
-
257
- def tmp_resolve_path
258
- FileUtils.mkdir_p(@path) unless File.directory?(@path)
259
- new_path = "#{@path}/tmp_#{name.gsub(" ","_").gsub("/","_").gsub("-","_").gsub("___","_").gsub("__","_").gsub("in.","in").gsub(",","").strip}"
260
- FileUtils.mkdir_p(new_path) unless File.directory?(new_path)
261
- result = new_path
262
- end
263
-
264
-
265
- def create_os_component(osobj)
266
- osobj.getCostLineItems.each do |os|
267
- @costs.each do |cost|
268
- #figure out costs for constructions
269
- os.setMaterialCost(cost.value.to_f) if cost.category == "material"
270
- if cost.category == "installation"
271
- os.setInstallationCost(cost.value.to_f)
272
- os.setExpectedLife(cost.interval.to_i)
273
- end
274
- os.setFixedOM(cost.value.to_f) if cost.category == "operations and maintenance"
275
- os.setVariableOM(cost.value.to_f) if cost.category == "variable operations and maintenance"
276
- os.setSalvageCost(cost.value.to_f) if cost.category == "salvage"
277
- end
278
- end
279
- newcomp = osobj.createComponent
280
-
281
- cd = newcomp.componentData
282
- cd.setDescription(@description)
283
- cd.setFidelityLevel(@fidelity_level)
284
-
285
- at = newcomp.componentData.componentDataAttributes
286
- @attributes.each do |attrib|
287
- if (attrib.value.to_s != "") and (attrib.name.to_s != "")
288
- if attrib.units != ""
289
- at.addAttribute(tc(attrib.name), attrib.value, attrib.units)
290
- else
291
- at.addAttribute(tc(attrib.name), attrib.value)
292
- end
293
- end
294
- end
295
-
296
- tg = newcomp.componentData.componentDataTags
297
- comp_tag = ""
298
- @tags.each do |tag|
299
- tg.addTag(tc(tag.descriptor))
300
- if (tag.descriptor != "energyplus") and (tag.descriptor != "construction")
301
- #create a map of component tags to directories
302
- comp_tag = tag.descriptor
303
- if comp_tag == "interior wall"
304
- comp_tag = "interiorwalls"
305
- elsif comp_tag == "exterior wall"
306
- comp_tag = "exteriorwalls"
307
- elsif comp_tag == "exterior slab"
308
- comp_tag = "exteriorslabs"
309
- elsif comp_tag == "exposed floor"
310
- comp_tag = "exposedfloors"
311
- elsif comp_tag == "attic floor"
312
- comp_tag = "atticfloors"
313
- elsif comp_tag == "roof"
314
- comp_tag = "roofs"
315
- elsif comp_tag == "door"
316
- comp_tag = "doors"
317
- elsif comp_tag == "skylight"
318
- comp_tag = "skylights"
319
- elsif comp_tag == "window"
320
- comp_tag = "windows"
321
- end
322
- puts comp_tag
323
- end
324
- end
325
-
326
- return newcomp
327
- end
328
-
329
- def save_component_xml(dir_path = resolve_path)
330
- xmlfile = File.new(dir_path + '/component.xml', 'w')
331
- comp_xml = Builder::XmlMarkup.new(:target => xmlfile, :indent=>2)
332
-
333
- #setup the xml file
334
- comp_xml.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
335
- comp_xml.component("xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
336
- "xsi:noNamespaceSchemaLocation"=>"#{SCHEMA_LOCATION}") {
337
- comp_xml.name @name
338
- comp_xml.uid @uid
339
- comp_xml.version_id @comp_version_id
340
- comp_xml.description @description if @description != ""
341
- comp_xml.comment @comment if @comment != ""
342
- comp_xml.fidelity_level @fidelity_level
343
-
344
- comp_xml.provenances {
345
- @provenance.each do |prov|
346
- comp_xml.provenance {
347
- comp_xml.author prov.author
348
- comp_xml.datetime prov.datetime
349
- comp_xml.comment prov.comment
350
- }
351
- end
352
- }
353
-
354
- comp_xml.tags {
355
- @tags.each do |tag|
356
- comp_xml.tag tag.descriptor
357
- end
358
- }
359
-
360
- comp_xml.attributes {
361
- @attributes.each do |attrib|
362
- if (attrib.value.to_s != "") and (attrib.name.to_s != "") then
363
- comp_xml.attribute {
364
- comp_xml.name attrib.name
365
- comp_xml.value attrib.value
366
- comp_xml.datatype attrib.datatype
367
- comp_xml.units attrib.units if attrib.units != ""
368
- }
369
- end
370
- end
371
- }
372
-
373
- comp_xml.source {
374
- comp_xml.manufacturer @source_manufacturer if @source_manufacturer != ""
375
- comp_xml.model @source_model if @source_model != ""
376
- comp_xml.serial_no @source_serial_no if @source_serial_no != ""
377
- comp_xml.year @source_year if @source_year != ""
378
- comp_xml.url @source_url if @source_url != ""
379
- }
380
-
381
- if not @files.nil?
382
- comp_xml.files {
383
- @files.each do |file|
384
- comp_xml.file {
385
- comp_xml.version {
386
- comp_xml.software_program file.version_software_program
387
- comp_xml.identifier file.version_id
388
- }
389
-
390
- comp_xml.filename file.filename
391
- comp_xml.filetype file.filetype
392
- }
393
- end
394
- }
395
- end
396
-
397
- #check if we should write out costs, don't write if all values are 0 or nil
398
- #DLM: schema always expects costs
399
- write_costs = true
400
- #if not @costs.nil?
401
- # @costs.each do |cost|
402
- # if (cost.value.nil?) && (not cost.value == 0)
403
- # write_costs = true
404
- # break
405
- # end
406
- # end
407
- #end
408
-
409
- if write_costs
410
- comp_xml.costs {
411
- @costs.each do |cost|
412
- comp_xml.cost {
413
- comp_xml.instance_name cost.cost_name
414
- comp_xml.cost_type cost.cost_type
415
- comp_xml.category cost.category
416
- comp_xml.value cost.value
417
- comp_xml.units cost.units if cost.units != ""
418
- comp_xml.interval cost.interval if cost.interval != ""
419
- comp_xml.interval_units cost.interval_units if cost.interval_units != ""
420
- comp_xml.year cost.year if cost.year != ""
421
- comp_xml.currency cost.currency if cost.currency != ""
422
- comp_xml.source cost.source if cost.source != ""
423
- comp_xml.reference_component_name cost.reference_component_name if cost.reference_component_name != ""
424
- comp_xml.reference_component_id cost.reference_component_id if cost.reference_component_id != ""
425
- }
426
- end
427
- }
428
- end
429
-
430
- }
431
-
432
- xmlfile.close
433
- end
434
-
435
- def get_attribute(attribute_name)
436
- result = nil
437
- @attributes.each do |attr|
438
- if attr.name == attribute_name
439
- result = attr
440
- end
441
- end
442
-
443
- result
444
-
445
- end
446
-
447
- #return the title case of the string
448
- def tc(input)
449
- val = input.gsub(/\b\w/){$&.upcase}
450
- if val.downcase == "energyplus"
451
- val = "EnergyPlus"
452
- end
453
- return val
454
- end
455
-
456
- private
457
-
458
- def get_datatype(input_value)
459
- dt = 'undefined'
460
-
461
- # simple method to test if the input_value is a string, float, or integer.
462
- # First convert the value back to a string for testing (in case it was passed as a float/integer)
463
- test = input_value.to_s
464
- input_value = test.match('\.').nil? ? Integer(test) : Float(test) rescue test.to_s
465
-
466
- if input_value.is_a?(Fixnum) || input_value.is_a?(Bignum)
467
- dt = "int"
468
- elsif input_value.is_a?(Float)
469
- dt = "float"
470
- else
471
- dt = "string"
472
- end
473
-
474
- dt
475
- end
476
-
477
- end
478
-
479
- end # module BCL
@@ -1,94 +0,0 @@
1
- ######################################################################
2
- # Copyright (c) 2008-2013, Alliance for Sustainable Energy.
3
- # All rights reserved.
4
- #
5
- # This library is free software; you can redistribute it and/or
6
- # modify it under the terms of the GNU Lesser General Public
7
- # License as published by the Free Software Foundation; either
8
- # version 2.1 of the License, or (at your option) any later version.
9
- #
10
- # This library is distributed in the hope that it will be useful,
11
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
- # Lesser General Public License for more details.
14
- #
15
- # You should have received a copy of the GNU Lesser General Public
16
- # License along with this library; if not, write to the Free Software
17
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
- ######################################################################
19
-
20
- require 'rubygems'
21
- require 'pathname'
22
- require 'fileutils'
23
- require 'enumerator'
24
-
25
- require 'bcl/TarBall'
26
-
27
- module BCL
28
- module_function
29
-
30
- def gather_components(component_dir)
31
- #store the starting directory
32
- current_dir = Dir.pwd
33
-
34
- #an array to hold reporting info about the batches
35
- gather_components_report = []
36
-
37
- #go to the directory containing the components
38
- Dir.chdir(component_dir)
39
-
40
- #delete old gather files first
41
- gather_dest_base = "components.tar.gz"
42
- #File.delete("./gather/" + gather_dest_base) if File.exists?("./0gather/" + gather_dest_base)
43
-
44
- #copy all the components' tar.gz files into a single directory
45
- targzs = Pathname.glob("./**/*.tar.gz")
46
- targzs.each do |targz|
47
- destination = "./0gather/#{File.basename(targz.to_s)}"
48
- puts "copying #{targz.to_s} to #{destination}"
49
- Dir.mkdir("./0gather") unless File.directory?("./0gather") #named so it will be at top of directory list
50
- File.delete(destination) if File.exists?(destination)
51
- FileUtils.cp(targz.to_s, destination)
52
- end
53
-
54
- #go into that directory
55
- Dir.chdir("./0gather")
56
-
57
- #get a list of all the tar.gz files in the new directory
58
- targzs = Pathname.glob("*.tar.gz")
59
-
60
- #report the total number of components in the directory
61
- gather_components_report << "Total components = #{targzs.length}"
62
-
63
- #define an iterator to keep track of the number of batches
64
- batch_num = 0
65
-
66
- #package all the tar.gzs in the directory into a few master tar.gz files of 1000 components or less
67
- targzs.each_slice(1000) do |batch|
68
-
69
- gather_components_report << " batch #{batch_num} contains #{batch.length} components"
70
-
71
- #put all the paths in the batch into an array
72
- paths = []
73
- batch.each do |targz|
74
- paths << File.basename(targz.to_s)
75
- end
76
-
77
- #path where the batch tarball is going
78
- gather_dest = "0_#{batch_num}_#{gather_dest_base}" #prefix to move to top of directory
79
-
80
- #tar up the batch
81
- tarball(gather_dest, paths)
82
-
83
- batch_num += 1
84
- end
85
-
86
- #report out
87
- puts gather_components_report
88
-
89
- #change back to the directory where we started
90
- Dir.chdir(current_dir)
91
-
92
- end
93
-
94
- end # module BCL
@@ -1,116 +0,0 @@
1
- ######################################################################
2
- # Copyright (c) 2008-2013, Alliance for Sustainable Energy.
3
- # All rights reserved.
4
- #
5
- # This library is free software; you can redistribute it and/or
6
- # modify it under the terms of the GNU Lesser General Public
7
- # License as published by the Free Software Foundation; either
8
- # version 2.1 of the License, or (at your option) any later version.
9
- #
10
- # This library is distributed in the hope that it will be useful,
11
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
- # Lesser General Public License for more details.
14
- #
15
- # You should have received a copy of the GNU Lesser General Public
16
- # License along with this library; if not, write to the Free Software
17
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
- ######################################################################
19
-
20
- #Mongo Record to Component
21
- require 'rubygems'
22
- require 'bcl/ComponentXml'
23
-
24
- module BCL
25
-
26
- class MongoToComponent
27
- attr_accessor :component
28
- attr_accessor :error_message
29
-
30
- def initialize(record)
31
- @component = nil
32
- @error_message = ""
33
-
34
- if record.has_key? "general"
35
- @component = BCL::Component.new('tmp')
36
- general = record["general"]
37
-
38
- #add uid/vid
39
- if record.has_key? "unique_id"
40
- component.uid = record["unique_id"]
41
- else
42
- @error_message = "Invalid Mongo record: no unique_id"
43
- end
44
- if record.has_key? "version_id"
45
- component.comp_version_id = record["version_id"]
46
- else
47
- @error_message = "Invalid Mongo record: no version_id"
48
- end
49
-
50
- #add general info
51
- if general.has_key? "name"
52
- component.name = general["name"]
53
- end
54
- if general.has_key? "description"
55
- @component.description = general["description"]
56
- end
57
- if general.has_key? "fidelity_level"
58
- @component.fidelity_level = general["fidelity_level"]
59
- end
60
- if general.has_key? "source_manufacturer"
61
- @component.source_manufacturer = general["source_manufacturer"]
62
- end
63
- if general.has_key? "source_url"
64
- @component.source_url = general["source_url"]
65
- end
66
-
67
- #add tags
68
- if general.has_key? "tags"
69
- tags = general["tags"]
70
- tags.each do |name,value|
71
- @component.add_tag(value)
72
- end
73
- end
74
-
75
- #add attributes
76
- if general.has_key? "attributes"
77
- attribute_container = general["attributes"]
78
- attribute_container.each do |a,attributes|
79
- #attributes iterator is an array of hashes
80
- #NOTE: double check this...could be old messed-up structure?
81
- attributes.each do |attribute|
82
- name = ""
83
- units = ""
84
- value = ""
85
- datatype = ""
86
- if attribute.has_key? "name"
87
- name = attribute["name"]
88
- end
89
- if attribute.has_key? "value"
90
- value = attribute["value"]
91
- end
92
- if attribute.has_key? "units"
93
- units = attribute["units"]
94
- end
95
- @component.add_attribute(name, value, units)
96
-
97
- #TODO: eventually find a way to validate the datatype in record with datatype in component
98
- end
99
- end
100
- end
101
-
102
- #todo: add provenance
103
-
104
- else
105
- @error_message = "Invalid Mongo record: no 'general' section"
106
- end
107
- #set component to NIL if there were errors
108
- if !@error_message == nil
109
- @component = nil
110
- end
111
- end
112
-
113
- end
114
-
115
- end # module BCL
116
-