urbanopt-geojson 0.1.0 → 0.2.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +19 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +15 -0
- data/.github/pull_request_template.md +13 -0
- data/CONTRIBUTING.md +58 -0
- data/Gemfile +3 -3
- data/Jenkinsfile +2 -2
- data/LICENSE.md +1 -1
- data/Rakefile +1 -1
- data/doc_templates/LICENSE.md +1 -1
- data/doc_templates/copyright_erb.txt +1 -1
- data/doc_templates/copyright_js.txt +1 -1
- data/doc_templates/copyright_ruby.txt +1 -1
- data/docs/package-lock.json +2291 -2205
- data/docs/package.json +8 -1
- data/lib/change_log.rb +147 -0
- data/lib/measures/urban_geometry_creation/LICENSE.md +1 -1
- data/lib/measures/urban_geometry_creation/measure.rb +1 -3
- data/lib/measures/urban_geometry_creation/tests/shadowed_tests.rb +1 -1
- data/lib/measures/urban_geometry_creation/tests/urban_geometry_creation_test.rb +3 -7
- data/lib/measures/urban_geometry_creation_zoning/LICENSE.md +1 -1
- data/lib/measures/urban_geometry_creation_zoning/measure.rb +5 -6
- data/lib/measures/urban_geometry_creation_zoning/tests/{urban_geometry_creation_test.rb → urban_geometry_creation_zoning_test.rb} +3 -7
- data/lib/urbanopt-geojson.rb +31 -0
- data/lib/urbanopt/geojson.rb +1 -1
- data/lib/urbanopt/geojson/building.rb +90 -18
- data/lib/urbanopt/geojson/district_system.rb +1 -1
- data/lib/urbanopt/geojson/extension.rb +1 -1
- data/lib/urbanopt/geojson/feature.rb +9 -7
- data/lib/urbanopt/geojson/files/electrical_database.json +28 -0
- data/lib/urbanopt/geojson/geo_file.rb +213 -31
- data/lib/urbanopt/geojson/helper.rb +10 -8
- data/lib/urbanopt/geojson/logging.rb +1 -1
- data/lib/urbanopt/geojson/mapper_classes.rb +1 -1
- data/lib/urbanopt/geojson/model.rb +1 -1
- data/lib/urbanopt/geojson/region.rb +1 -1
- data/lib/urbanopt/geojson/schema/building_properties.json +28 -5
- data/lib/urbanopt/geojson/schema/district_system_properties.json +29 -28
- data/lib/urbanopt/geojson/schema/electrical_connector_properties.json +150 -10
- data/lib/urbanopt/geojson/schema/electrical_junction_properties.json +3 -2
- data/lib/urbanopt/geojson/schema/thermal_connector_properties.json +2 -1
- data/lib/urbanopt/geojson/update_areas.rb +1 -1
- data/lib/urbanopt/geojson/validate_geojson.rb +1 -1
- data/lib/urbanopt/geojson/version.rb +2 -2
- data/lib/urbanopt/geojson/zoning.rb +1 -1
- data/urbanopt-geojson-gem.gemspec +4 -1
- metadata +14 -8
- data/.travis.yml +0 -35
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -177,19 +177,21 @@ module URBANopt
|
|
177
177
|
end
|
178
178
|
|
179
179
|
if feature[:geometry].nil?
|
180
|
-
raise("No geometry found in '#{feature}'")
|
180
|
+
raise("No geometry found in '#{feature[:properties][:name]}'")
|
181
181
|
return false
|
182
182
|
end
|
183
183
|
|
184
184
|
if feature[:properties].nil?
|
185
|
-
raise("No properties found in '#{feature}'")
|
185
|
+
raise("No properties found in '#{feature[:properties][:name]}'")
|
186
186
|
return false
|
187
187
|
end
|
188
188
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
189
|
+
unless feature[:properties][:detailed_model_filename]
|
190
|
+
errors = JSON::Validator.fully_validate(schema, feature[:properties])
|
191
|
+
if !errors.empty?
|
192
|
+
raise("Invalid properties for '#{feature[:properties][:name]}'\n #{errors.join('\n ')}")
|
193
|
+
return false
|
194
|
+
end
|
193
195
|
end
|
194
196
|
|
195
197
|
geometry_type = feature[:geometry][:type]
|
@@ -0,0 +1,28 @@
|
|
1
|
+
{
|
2
|
+
"transformer_properties": {
|
3
|
+
"nameclass": "Transformer--25KVA CT",
|
4
|
+
"kva": 25,
|
5
|
+
"resistance": 0.1,
|
6
|
+
"phases": ["A"],
|
7
|
+
"high_voltage": 13.2,
|
8
|
+
"low_voltage": 0.24,
|
9
|
+
"is_center_tap": true,
|
10
|
+
"connection": "Delta-Wye"
|
11
|
+
},
|
12
|
+
"capacitor_properties": {
|
13
|
+
"nameclass": "Capacitor--150KVAR",
|
14
|
+
"kvar": 150,
|
15
|
+
"resistance": 0.1,
|
16
|
+
"phases": ["A","B","C"],
|
17
|
+
"control_type": "Voltage",
|
18
|
+
"connection": "Delta-Wye"
|
19
|
+
},
|
20
|
+
"wire": {
|
21
|
+
"nameclass": "OH AL 4/0",
|
22
|
+
"phase": "A",
|
23
|
+
"height": 50,
|
24
|
+
"x": 0,
|
25
|
+
"amapcity": 200
|
26
|
+
}
|
27
|
+
|
28
|
+
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -42,17 +42,15 @@ module URBANopt
|
|
42
42
|
@@schema_file_lock = Mutex.new
|
43
43
|
|
44
44
|
##
|
45
|
-
#
|
45
|
+
# Initialize GeoJSON file and path.
|
46
46
|
#
|
47
47
|
# [Parameters]
|
48
48
|
#
|
49
|
-
# * +
|
50
|
-
|
49
|
+
# * +path+ - _Type:String_ GeoJSON File path.
|
50
|
+
# * +data+ - _Type:Hash_ Contains the GeoJSON File.
|
51
|
+
def initialize(geojson_file, path = nil)
|
51
52
|
@path = path
|
52
|
-
@
|
53
|
-
if !valid?
|
54
|
-
raise 'GeoJSON file does not adhere to schema'
|
55
|
-
end
|
53
|
+
@geojson_file = geojson_file
|
56
54
|
end
|
57
55
|
|
58
56
|
##
|
@@ -69,15 +67,69 @@ module URBANopt
|
|
69
67
|
raise "GeoJSON file '#{path}' does not exist"
|
70
68
|
end
|
71
69
|
|
72
|
-
|
70
|
+
geojson_file = JSON.parse(
|
73
71
|
File.open(path, 'r', &:read),
|
74
72
|
symbolize_names: true
|
75
73
|
)
|
76
|
-
|
74
|
+
|
75
|
+
# validate geojson file against schema
|
76
|
+
geojson_errors = validate(@@geojson_schema, geojson_file)
|
77
|
+
unless geojson_errors.empty?
|
78
|
+
raise "GeoJSON file does not adhere to the schema: \n #{geojson_errors.join('\n ')}"
|
79
|
+
end
|
80
|
+
|
81
|
+
# initialize @@logger
|
82
|
+
@@logger ||= URBANopt::GeoJSON.logger
|
83
|
+
|
84
|
+
# validate each feature against schema
|
85
|
+
geojson_file[:features].each do |feature|
|
86
|
+
properties = feature[:properties]
|
87
|
+
type = properties[:type]
|
88
|
+
|
89
|
+
errors = []
|
90
|
+
|
91
|
+
case type
|
92
|
+
when 'Building'
|
93
|
+
# Incase detailed_model_filename present check for fewer properties
|
94
|
+
if feature[:properties][:detailed_model_filename]
|
95
|
+
if feature[:properties][:id].nil?
|
96
|
+
raise("No id found for Building Feature")
|
97
|
+
end
|
98
|
+
if feature[:properties][:name].nil?
|
99
|
+
raise("No name found for Building Feature")
|
100
|
+
end
|
101
|
+
if feature[:properties][:number_of_stories].nil?
|
102
|
+
@@logger.warn("Number of stories is required to calculate shading using the UrbanGeometryCreation measure...ignoring #{feature[:properties][:id]} in shading calculations")
|
103
|
+
end
|
104
|
+
feature[:additionalProperties] = true
|
105
|
+
# Else validate for all required properties in the schema
|
106
|
+
else
|
107
|
+
errors = validate(@@building_schema, properties)
|
108
|
+
end
|
109
|
+
when 'District System'
|
110
|
+
errors = validate(@@district_system_schema, properties)
|
111
|
+
when 'Region'
|
112
|
+
error = validate(@@district_system_schema, properties)
|
113
|
+
when 'ElectricalJunction'
|
114
|
+
errors = validate(@@electrical_junction_schema, properties)
|
115
|
+
when 'ElectricalConnector'
|
116
|
+
errors = validate(@@electrical_connector_schema, properties)
|
117
|
+
when 'ElectricalJunction'
|
118
|
+
errors = validate(@@thermal_junction_schema, properties)
|
119
|
+
when 'ThermalConnector'
|
120
|
+
errors = validate(@@thermal_connector_schema, properties)
|
121
|
+
end
|
122
|
+
|
123
|
+
unless errors.empty?
|
124
|
+
raise ("#{type} does not adhere to schema: \n #{errors.join('\n ')}")
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
return new(geojson_file, path)
|
77
129
|
end
|
78
130
|
|
79
131
|
def json
|
80
|
-
@
|
132
|
+
@geojson_file
|
81
133
|
end
|
82
134
|
|
83
135
|
attr_reader :path
|
@@ -88,7 +140,7 @@ module URBANopt
|
|
88
140
|
#
|
89
141
|
def features
|
90
142
|
result = []
|
91
|
-
@
|
143
|
+
@geojson_file[:features].each do |f|
|
92
144
|
if f[:properties] && f[:properties][:type] == 'Building'
|
93
145
|
result << URBANopt::GeoJSON::Building.new(f)
|
94
146
|
elsif f[:properties] && f[:properties][:type] == 'District System'
|
@@ -101,13 +153,15 @@ module URBANopt
|
|
101
153
|
##
|
102
154
|
# Returns feature object by feature_id from specified GeoJSON file and creates a
|
103
155
|
# new +URBANopt::GeoJSON::Building+ or +URBANopt::GeoJSON::DistrictSystem+ based on the
|
104
|
-
# feature type.
|
156
|
+
# feature type. Before returning the feature, merge 'Site Origin' properties into the feature
|
105
157
|
#
|
106
158
|
# [Parameters]
|
107
159
|
# * +feature_id+ - _Type:String/Number_ - Id affiliated with feature object.
|
108
160
|
def get_feature_by_id(feature_id)
|
109
|
-
@
|
161
|
+
@geojson_file[:features].each do |f|
|
110
162
|
if f[:properties] && f[:properties][:id] == feature_id
|
163
|
+
# merge site origin properties
|
164
|
+
f = merge_site_properties(f)
|
111
165
|
if f[:properties][:type] == 'Building'
|
112
166
|
return URBANopt::GeoJSON::Building.new(f)
|
113
167
|
elsif f[:properties] && f[:properties][:type] == 'District System'
|
@@ -118,37 +172,165 @@ module URBANopt
|
|
118
172
|
return nil
|
119
173
|
end
|
120
174
|
|
121
|
-
##
|
122
|
-
# Returns
|
123
|
-
|
124
|
-
|
175
|
+
##
|
176
|
+
# Merge Site Properties in Feature. Returns feature with site properties added to its properties section. Does not overwrite existing properties.
|
177
|
+
#
|
178
|
+
# [Parameters]
|
179
|
+
# +feature+ - _Type:Hash_ - feature object.
|
180
|
+
def merge_site_properties(feature)
|
181
|
+
site_origins = @geojson_file[:features].select {|f| f[:properties][:type] == 'Site Origin'}
|
182
|
+
if site_origins.size > 0
|
183
|
+
site_origin = site_origins[0]
|
184
|
+
# site origin found, do some merging
|
185
|
+
# this maps site properties to building/district system properties.
|
186
|
+
add_props = [
|
187
|
+
{site: :surface_elevation, feature: :surface_elevation},
|
188
|
+
{site: :timesteps_per_hour, feature: :timesteps_per_hour},
|
189
|
+
{site: :begin_date, feature: :begin_date},
|
190
|
+
{site: :end_date, feature: :end_date},
|
191
|
+
{site: :cec_climate_zone, feature: :cec_climate_zone},
|
192
|
+
{site: :climate_zone, feature: :climate_zone},
|
193
|
+
{site: :default_template, feature: :template},
|
194
|
+
{site: :weather_filename, feature: :weather_filename},
|
195
|
+
{site: :tariff_filename, feature: :tariff_filename}
|
196
|
+
]
|
197
|
+
|
198
|
+
add_props.each do |prop|
|
199
|
+
if site_origin[:properties].key?(prop[:site]) and site_origin[:properties][prop[:site]]
|
200
|
+
# property exists in site
|
201
|
+
if !feature[:properties].key?(prop[:feature]) or feature[:properties][prop[:feature]].nil? or feature[:properties][prop[:feature]].empty?
|
202
|
+
# property does not exist in feature or is nil: add site property (don't overwrite)
|
203
|
+
feature[:properties][prop[:feature]] = site_origin[:properties][prop[:site]]
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
return feature
|
125
209
|
end
|
126
210
|
|
127
211
|
##
|
128
|
-
#
|
129
|
-
|
212
|
+
# Validate GeoJSON against schema
|
213
|
+
#
|
214
|
+
# [Parameters]
|
215
|
+
# * +data+ - + - _Type:Hash_ - Input GeoJSON file
|
216
|
+
def self.validate(schema_json, data)
|
217
|
+
errors = JSON::Validator.fully_validate(schema_json, data, errors_as_objects: true)
|
218
|
+
return errors
|
219
|
+
end
|
220
|
+
|
221
|
+
def self.get_geojson_schema(strict)
|
222
|
+
result = nil
|
130
223
|
if @@geojson_schema.nil?
|
131
224
|
@@schema_file_lock.synchronize do
|
132
|
-
File.open(
|
133
|
-
|
225
|
+
File.open(File.dirname(__FILE__) + '/schema/geojson_schema.json') do |f|
|
226
|
+
result = JSON.parse(f.read, symbolize_names: true)
|
134
227
|
end
|
135
228
|
end
|
136
229
|
end
|
230
|
+
return result
|
231
|
+
end
|
137
232
|
|
138
|
-
|
233
|
+
def self.get_building_schema(strict)
|
234
|
+
result = nil
|
235
|
+
File.open(File.dirname(__FILE__) + '/schema/building_properties.json') do |f|
|
236
|
+
result = JSON.parse(f.read)
|
237
|
+
end
|
238
|
+
if strict
|
239
|
+
result['additionalProperties'] = true
|
240
|
+
else
|
241
|
+
result['additionalProperties'] = false
|
242
|
+
end
|
243
|
+
return result
|
244
|
+
end
|
245
|
+
|
246
|
+
def self.get_district_system_schema(strict)
|
247
|
+
result = nil
|
248
|
+
File.open(File.dirname(__FILE__) + '/schema/district_system_properties.json') do |f|
|
249
|
+
result = JSON.parse(f.read)
|
250
|
+
end
|
251
|
+
if strict
|
252
|
+
result['additionalProperties'] = true
|
253
|
+
else
|
254
|
+
result['additionalProperties'] = false
|
255
|
+
end
|
256
|
+
return result
|
257
|
+
end
|
258
|
+
|
259
|
+
def self.get_region_schema(strict)
|
260
|
+
result = nil
|
261
|
+
File.open(File.dirname(__FILE__) + '/schema/region_properties.json') do |f|
|
262
|
+
result = JSON.parse(f.read)
|
263
|
+
end
|
264
|
+
if strict
|
265
|
+
result['additionalProperties'] = true
|
266
|
+
else
|
267
|
+
result['additionalProperties'] = false
|
268
|
+
end
|
269
|
+
return result
|
139
270
|
end
|
140
271
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
272
|
+
def self.get_electrical_connector_schema(strict)
|
273
|
+
result = nil
|
274
|
+
File.open(File.dirname(__FILE__) + '/schema/electrical_connector_properties.json') do |f|
|
275
|
+
result = JSON.parse(f.read)
|
276
|
+
end
|
277
|
+
if strict
|
278
|
+
result['additionalProperties'] = true
|
279
|
+
else
|
280
|
+
result['additionalProperties'] = false
|
281
|
+
end
|
282
|
+
return result
|
145
283
|
end
|
146
284
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
285
|
+
def self.get_electrical_junction_schema(strict)
|
286
|
+
result = nil
|
287
|
+
File.open(File.dirname(__FILE__) + '/schema/electrical_junction_properties.json') do |f|
|
288
|
+
result = JSON.parse(f.read)
|
289
|
+
end
|
290
|
+
if strict
|
291
|
+
result['additionalProperties'] = true
|
292
|
+
else
|
293
|
+
result['additionalProperties'] = false
|
294
|
+
end
|
295
|
+
return result
|
151
296
|
end
|
297
|
+
|
298
|
+
def self.get_thermal_connector_schema(strict)
|
299
|
+
result = nil
|
300
|
+
File.open(File.dirname(__FILE__) + '/schema/thermal_connector_properties.json') do |f|
|
301
|
+
result = JSON.parse(f.read)
|
302
|
+
end
|
303
|
+
if strict
|
304
|
+
result['additionalProperties'] = true
|
305
|
+
else
|
306
|
+
result['additionalProperties'] = false
|
307
|
+
end
|
308
|
+
return result
|
309
|
+
end
|
310
|
+
|
311
|
+
def self.get_thermal_junction_schema(strict)
|
312
|
+
result = nil
|
313
|
+
File.open(File.dirname(__FILE__) + '/schema/thermal_junction_properties.json') do |f|
|
314
|
+
result = JSON.parse(f.read)
|
315
|
+
end
|
316
|
+
if strict
|
317
|
+
result['additionalProperties'] = true
|
318
|
+
else
|
319
|
+
result['additionalProperties'] = false
|
320
|
+
end
|
321
|
+
return result
|
322
|
+
end
|
323
|
+
|
324
|
+
strict = true
|
325
|
+
@@geojson_schema = get_geojson_schema(strict)
|
326
|
+
@@building_schema = get_building_schema(strict)
|
327
|
+
@@district_system_schema = get_district_system_schema(strict)
|
328
|
+
@@region_schema = get_region_schema(strict)
|
329
|
+
@@electrical_connector_schema = get_electrical_connector_schema(strict)
|
330
|
+
@@electrical_junction_schema = get_electrical_junction_schema(strict)
|
331
|
+
@@thermal_connector_schema = get_thermal_connector_schema(strict)
|
332
|
+
@@thermal_junction_schema = get_thermal_junction_schema(strict)
|
333
|
+
|
152
334
|
end
|
153
335
|
end
|
154
336
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -216,7 +216,7 @@ module URBANopt
|
|
216
216
|
#
|
217
217
|
# [Parameters]
|
218
218
|
# * +building+ - _Type:URBANopt::GeoJSON::Building_ - The core building that other buildings will be referenced.
|
219
|
-
# * +other_building_type+ - _Type:String_ - Describes the surrounding buildings.
|
219
|
+
# * +other_building_type+ - _Type:String_ - Describes the surrounding buildings.
|
220
220
|
# * +other_buildings+ - _Type:URBANopt::GeoJSON::FeatureCollection_ - List of surrounding buildings to include (self will be ignored if present in list).
|
221
221
|
# * +model+ - _Type:OpenStudio::Model::Model_ - An instance of an OpenStudio Model.
|
222
222
|
# * +origin_lat_lon+ - _Type:Float_ - An instance of +OpenStudio::PointLatLon+ indicating the latitude and longitude of the origin.
|
@@ -255,14 +255,16 @@ module URBANopt
|
|
255
255
|
# find the polygon of the other_building by passing it to the get_multi_polygons method
|
256
256
|
other_building_points = building.other_points(other_building, other_height, origin_lat_lon, runner, zoning)
|
257
257
|
shadowed = URBANopt::GeoJSON::Helper.is_shadowed(feature_points, other_building_points, origin_lat_lon)
|
258
|
-
next unless shadowed
|
259
|
-
|
258
|
+
next unless shadowed
|
259
|
+
new_building = building.create_other_building(:space_per_building, model, origin_lat_lon, runner, zoning, other_building)
|
260
|
+
if new_building.nil? || new_building.empty?
|
261
|
+
runner.registerWarning("Failed to create spaces for other building '#{name}'")
|
262
|
+
end
|
263
|
+
other_spaces.concat(new_building)
|
260
264
|
|
261
|
-
|
262
|
-
if new_building.nil? || new_building.empty?
|
263
|
-
runner.registerWarning("Failed to create spaces for other building '#{name}'")
|
265
|
+
elsif other_building_type == 'None'
|
264
266
|
end
|
265
|
-
|
267
|
+
|
266
268
|
end
|
267
269
|
return other_spaces
|
268
270
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|