tbd 3.2.1 → 3.2.3

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.
data/lib/tbd/geo.rb CHANGED
@@ -218,42 +218,6 @@ module TBD
218
218
  true
219
219
  end
220
220
 
221
- ##
222
- # Validate whether an OpenStudio planar surface is safe for TBD to process.
223
- #
224
- # @param s [OpenStudio::Model::PlanarSurface] a surface
225
- #
226
- # @return [Bool] true if valid surface
227
- def validate(s = nil)
228
- mth = "TBD::#{__callee__}"
229
- cl = OpenStudio::Model::PlanarSurface
230
-
231
- return mismatch("surface", s, cl, mth, DBG, false) unless s.is_a?(cl)
232
-
233
- id = s.nameString
234
- size = s.vertices.size
235
- last = size - 1
236
-
237
- log(ERR, "#{id} #{size} vertices? need +3 (#{mth})") unless size > 2
238
- return false unless size > 2
239
-
240
- [0, last].each do |i|
241
- v1 = s.vertices[i]
242
- v2 = s.vertices[i + 1] unless i == last
243
- v2 = s.vertices.first if i == last
244
- vector = v2 - v1
245
- bad = vector.length < TOL
246
-
247
- # As is, this comparison also catches collinear vertices (< 10mm apart)
248
- # along an edge. Should avoid red-flagging such cases. TO DO.
249
- log(ERR, "#{id}: < #{TOL}m (#{mth})") if bad
250
- return false if bad
251
- end
252
-
253
- # Add as many extra tests as needed ...
254
- true
255
- end
256
-
257
221
  ##
258
222
  # Return site-specific (or true) Topolys normal vector of OpenStudio surface.
259
223
  #
@@ -290,30 +254,33 @@ module TBD
290
254
  cl2 = OpenStudio::Model::Surface
291
255
  cl3 = OpenStudio::Model::LayeredConstruction
292
256
 
293
- return mismatch("model", model, cl1, mth) unless model.is_a?(cl1)
294
- return mismatch("surface", surface, cl2, mth) unless surface.is_a?(cl2)
295
-
296
- return nil unless validate(surface)
257
+ return mismatch("model", model, cl1, mth) unless model.is_a?(cl1)
258
+ return mismatch("surface", surface, cl2, mth) unless surface.is_a?(cl2)
259
+ return nil unless surface_valid?(surface)
297
260
 
298
261
  nom = surface.nameString
299
262
  surf = {}
300
263
  subs = {}
301
264
  fd = false
302
265
  return empty("'#{nom}' space", mth, ERR) if surface.space.empty?
266
+
303
267
  space = surface.space.get
304
268
  stype = space.spaceType
305
269
  story = space.buildingStory
306
270
  tr = transforms(model, space)
307
271
  return invalid("'#{nom}' transform", mth, 0, FTL) unless tr[:t] && tr[:r]
272
+
308
273
  t = tr[:t]
309
274
  n = trueNormal(surface, tr[:r])
310
275
  return invalid("'#{nom}' normal", mth, 0, FTL) unless n
276
+
311
277
  type = surface.surfaceType.downcase
312
278
  facing = surface.outsideBoundaryCondition
313
279
 
314
280
  if facing.downcase == "surface"
315
281
  empty = surface.adjacentSurface.empty?
316
- return invalid("'#{nom}': adjacent surface", mth, 0, ERR) if empty
282
+ return invalid("'#{nom}': adjacent surface", mth, 0, ERR) if empty
283
+
317
284
  facing = surface.adjacentSurface.get.nameString
318
285
  end
319
286
 
@@ -350,9 +317,10 @@ module TBD
350
317
  surf[:story ] = story.get unless story.empty?
351
318
  surf[:n ] = n
352
319
  surf[:gross ] = surface.grossArea
320
+ surf[:filmRSI ] = surface.filmResistance
353
321
 
354
322
  surface.subSurfaces.sort_by { |s| s.nameString }.each do |s|
355
- next unless validate(s)
323
+ next unless surface_valid?(s)
356
324
 
357
325
  id = s.nameString
358
326
  valid = s.vertices.size == 3 || s.vertices.size == 4
data/lib/tbd/ua.rb CHANGED
@@ -39,13 +39,14 @@ module TBD
39
39
  cl1 = OpenStudio::Model::Model
40
40
  cl2 = OpenStudio::Model::LayeredConstruction
41
41
  cl3 = Numeric
42
+ cl4 = String
42
43
 
43
- return mismatch("model", model, cl1, mth, DBG, res) unless model.is_a?(cl1)
44
- return mismatch("id", id, String, mth, DBG, res) unless id.is_a?(String)
45
- return mismatch("lc", lc, cl2, mth, DBG, res) unless lc.is_a?(cl2)
46
- return mismatch("hloss", hloss, cl3, mth, DBG, res) unless hloss.is_a?(cl3)
47
- return mismatch("film", film, cl3, mth, DBG, res) unless film.is_a?(cl3)
48
- return mismatch("Ut", ut, cl3, mth, DBG, res) unless ut.is_a?(cl3)
44
+ return mismatch("model", model, cl1, mth, DBG, res) unless model.is_a?(cl1)
45
+ return mismatch("id" , id, cl4, mth, DBG, res) unless id.is_a?(cl4)
46
+ return mismatch("lc" , lc, cl2, mth, DBG, res) unless lc.is_a?(cl2)
47
+ return mismatch("hloss", hloss, cl3, mth, DBG, res) unless hloss.is_a?(cl3)
48
+ return mismatch("film" , film, cl3, mth, DBG, res) unless film.is_a?(cl3)
49
+ return mismatch("Ut" , ut, cl3, mth, DBG, res) unless ut.is_a?(cl3)
49
50
 
50
51
  loss = 0.0 # residual heatloss (not assigned) [W/K]
51
52
  area = lc.getNetArea
@@ -54,12 +55,12 @@ module TBD
54
55
  lyr[:index] = nil unless lyr[:index] >= 0
55
56
  lyr[:index] = nil unless lyr[:index] < lc.layers.size
56
57
 
57
- return invalid("'#{id}' layer index", mth, 0, ERR, res) unless lyr[:index]
58
- return zero("'#{id}': heatloss", mth, WRN, res) unless hloss > TOL
59
- return zero("'#{id}': films", mth, WRN, res) unless film > TOL
60
- return zero("'#{id}': Ut", mth, WRN, res) unless ut > TOL
61
- return invalid("'#{id}': Ut", mth, 0, WRN, res) unless ut < 5.678
62
- return zero("'#{id}': net area (m2)", mth, ERR, res) unless area > TOL
58
+ return invalid("'#{id}' layer index", mth, 0, ERR, res) unless lyr[:index]
59
+ return zero("'#{id}': heatloss" , mth, WRN, res) unless hloss > TOL
60
+ return zero("'#{id}': films" , mth, WRN, res) unless film > TOL
61
+ return zero("'#{id}': Ut" , mth, WRN, res) unless ut > TOL
62
+ return invalid("'#{id}': Ut" , mth, 0, WRN, res) unless ut < 5.678
63
+ return zero("'#{id}': net area (m2)", mth, ERR, res) unless area > TOL
63
64
 
64
65
  # First, calculate initial layer RSi to initially meet Ut target.
65
66
  rt = 1 / ut # target construction Rt
@@ -76,7 +77,7 @@ module TBD
76
77
 
77
78
  if lyr[:type] == :massless
78
79
  m = lc.getLayer(lyr[:index]).to_MasslessOpaqueMaterial
79
- return invalid("'#{id}' massless layer?", mth, 0) if m.empty?
80
+ return invalid("'#{id}' massless layer?", mth, 0, DBG, res) if m.empty?
80
81
 
81
82
  m = m.get.clone(model).to_MasslessOpaqueMaterial.get
82
83
  m.setName("#{id} uprated")
@@ -85,7 +86,7 @@ module TBD
85
86
  m.setThermalResistance(new_r)
86
87
  else # type == :standard
87
88
  m = lc.getLayer(lyr[:index]).to_StandardOpaqueMaterial
88
- return invalid("'#{id}' standard layer?", mth, 0) if m.empty?
89
+ return invalid("'#{id}' standard layer?", mth, 0, DBG, res) if m.empty?
89
90
 
90
91
  m = m.get.clone(model).to_StandardOpaqueMaterial.get
91
92
  m.setName("#{id} uprated")
@@ -141,11 +142,12 @@ module TBD
141
142
  mth = "TBD::#{__callee__}"
142
143
  cl1 = OpenStudio::Model::Model
143
144
  cl2 = Hash
145
+ cl3 = OpenStudio::Model::LayeredConstruction
144
146
  a = false
145
147
 
146
- return mismatch("model", model, cl1, mth, DBG, a) unless model.is_a?(cl1)
147
- return mismatch("surfaces", s, cl2, mth, DBG, a) unless s.is_a?(cl2)
148
- return mismatch("argh", model, cl1, mth, DBG, a) unless argh.is_a?(cl2)
148
+ return mismatch("model" , model, cl1, mth, DBG, a) unless model.is_a?(cl1)
149
+ return mismatch("surfaces", s, cl2, mth, DBG, a) unless s.is_a?(cl2)
150
+ return mismatch("argh" , model, cl1, mth, DBG, a) unless argh.is_a?(cl2)
149
151
 
150
152
  argh[:uprate_walls ] = false unless argh.key?(:uprate_walls )
151
153
  argh[:uprate_roofs ] = false unless argh.key?(:uprate_roofs )
@@ -168,11 +170,13 @@ module TBD
168
170
  groups[:roof ][:op] = argh[:roof_option ]
169
171
  groups[:floor][:op] = argh[:floor_option ]
170
172
 
171
- groups.each do |label, g|
173
+ groups.each do |type, g|
172
174
  next unless g[:up]
173
175
  next unless g[:ut].is_a?(Numeric)
174
176
  next unless g[:ut] < 5.678
175
177
 
178
+ typ = type
179
+ typ = :ceiling if typ == :roof # fix in future revision. TO-DO.
176
180
  coll = {}
177
181
  area = 0
178
182
  film = 100000000000000
@@ -183,86 +187,81 @@ module TBD
183
187
  g[:op].downcase == "all floor constructions"
184
188
 
185
189
  if g[:op].empty?
186
- log(ERR, "Construction to uprate? (#{mth})")
190
+ log(ERR, "Construction (#{type}) to uprate? (#{mth})")
187
191
  elsif all
188
- model.getSurfaces.each do |sss|
189
- next unless sss.surfaceType.downcase.include?(label.to_s)
190
- next unless sss.outsideBoundaryCondition.downcase == "outdoors"
191
- next if sss.construction.empty?
192
- next if sss.construction.get.to_LayeredConstruction.empty?
193
-
194
- c = sss.construction.get.to_LayeredConstruction.get
195
- i = c.nameString
196
-
197
- # Reliable unless referenced by other surface types e.g. floor vs wall.
198
- if c.getNetArea > area
199
- area = c.getNetArea
192
+ s.each do |nom, surface|
193
+ next unless surface.key?(:deratable )
194
+ next unless surface.key?(:type )
195
+ next unless surface.key?(:construction)
196
+ next unless surface.key?(:filmRSI )
197
+ next unless surface.key?(:index )
198
+ next unless surface.key?(:ltype )
199
+ next unless surface.key?(:r )
200
+ next unless surface[:deratable ]
201
+ next unless surface[:type ] == typ
202
+ next unless surface[:construction].is_a?(cl3)
203
+ next if surface[:index ].nil?
204
+
205
+ # Retain lowest surface film resistance (e.g. tilted surfaces).
206
+ c = surface[:construction]
207
+ i = c.nameString
208
+ aire = c.getNetArea
209
+ film = surface[:filmRSI] if surface[:filmRSI] < film
210
+
211
+ # Retain construction covering largest area. The following conditional
212
+ # is reliable UNLESS linked to other deratable surface types e.g. both
213
+ # floors AND walls (see "elsif lc" corrections below).
214
+ if aire > area
200
215
  lc = c
216
+ area = aire
201
217
  id = i
202
218
  end
203
219
 
204
- film = sss.filmResistance if sss.filmResistance < film
205
- nom = sss.nameString
206
- coll[i] = { area: c.getNetArea, lc: c, s: {} } unless coll.key?(i)
207
- coll[i][:s][nom] = { a: sss.netArea } unless coll[i][:s].key?(nom)
220
+ coll[i] = { area: aire, lc: c, s: {} } unless coll.key?(i)
221
+ coll[i][:s][nom] = { a: surface[:net] } unless coll[i][:s].key?(nom)
208
222
  end
209
223
  else
210
224
  id = g[:op]
211
- c = model.getConstructionByName(id)
212
-
213
- if c.empty?
214
- log(ERR, "Construction '#{id}'? (#{mth})")
215
- else
216
- c = c.get.to_LayeredConstruction
217
-
218
- if c.empty?
219
- log(ERR, "'#{id}' layered construction? (#{mth})")
220
- else
221
- lc = c.get
222
- area = lc.getNetArea
223
- coll[id] = { area: area, lc: lc, s: {} }
224
-
225
- model.getSurfaces.each do |sss|
226
- next unless sss.surfaceType.downcase.include?(label.to_s)
227
- next unless sss.outsideBoundaryCondition.downcase == "outdoors"
228
- next if sss.construction.empty?
229
- next if sss.construction.get.to_LayeredConstruction.empty?
230
- lc = sss.construction.get.to_LayeredConstruction.get
231
- next unless id == lc.nameString
232
- nom = sss.nameString
233
- film = sss.filmResistance if sss.filmResistance < film
234
- ok = coll[id][:s].key?(nom)
235
- coll[id][:s][nom] = { a: sss.netArea } unless ok
236
- end
237
- end
225
+ lc = model.getConstructionByName(id)
226
+ log(ERR, "Construction '#{id}'? (#{mth})") if lc.empty?
227
+ next if lc.empty?
228
+
229
+ lc = lc.get.to_LayeredConstruction
230
+ log(ERR, "'#{id}' layered construction? (#{mth})") if lc.empty?
231
+ next if lc.empty?
232
+
233
+ lc = lc.get
234
+ area = lc.getNetArea
235
+ coll[id] = { area: area, lc: lc, s: {} }
236
+
237
+ s.each do |nom, surface|
238
+ next unless surface.key?(:deratable )
239
+ next unless surface.key?(:type )
240
+ next unless surface.key?(:construction)
241
+ next unless surface.key?(:filmRSI )
242
+ next unless surface.key?(:index )
243
+ next unless surface.key?(:ltype )
244
+ next unless surface.key?(:r )
245
+ next unless surface[:deratable ]
246
+ next unless surface[:type ] == typ
247
+ next unless surface[:construction].is_a?(cl3)
248
+ next if surface[:index ].nil?
249
+
250
+ i = surface[:construction].nameString
251
+ next unless i == id
252
+
253
+ # Retain lowest surface film resistance (e.g. tilted surfaces).
254
+ film = surface[:filmRSI] if surface[:filmRSI] < film
255
+
256
+ coll[i][:s][nom] = { a: surface[:net] } unless coll[i][:s].key?(nom)
238
257
  end
239
258
  end
240
259
 
241
260
  if coll.empty?
242
- log(ERR, "No #{label} construction to uprate - skipping (#{mth})")
261
+ log(ERR, "No #{type} construction to uprate - skipping (#{mth})")
243
262
  next
244
- elsif lc # valid layered construction - good to uprate!
245
- # Ensure lc is referenced by surface types == label.
246
- model.getSurfaces.each do |sss|
247
- next if sss.construction.empty?
248
- next if sss.construction.get.to_LayeredConstruction.empty?
249
- c = sss.construction.get.to_LayeredConstruction.get
250
- i = c.nameString
251
- next unless coll.key?(i)
252
-
253
- unless sss.surfaceType.downcase.include?(label.to_s)
254
- log(ERR, "Uprating #{label.to_s}, not '#{sss.nameString}' (#{mth})")
255
- cloned = c.clone(model).to_LayeredConstruction.get
256
- cloned.setName("'#{i}' cloned")
257
- sss.setConstruction(cloned)
258
- ok = s.key?(sss.nameString)
259
- s[sss.nameString][:construction] = cloned if ok
260
- coll[i][:s].delete(sss.nameString)
261
- coll[i][:area] = c.getNetArea
262
- next
263
- end
264
- end
265
-
263
+ elsif lc
264
+ # Valid layered construction - good to uprate!
266
265
  lyr = insulatingLayer(lc)
267
266
  lyr[:index] = nil unless lyr[:index].is_a?(Numeric)
268
267
  lyr[:index] = nil unless lyr[:index] >= 0
@@ -270,64 +269,81 @@ module TBD
270
269
 
271
270
  log(ERR, "Insulation index for '#{id}'? (#{mth})") unless lyr[:index]
272
271
  next unless lyr[:index]
273
- hloss = 0 # sum of applicable psi & khi effects [W/K]
274
272
 
275
- coll.each do |i, col|
276
- next unless col.key?(:s)
277
- next unless col.is_a?(Hash)
273
+ # Ensure lc is exclusively linked to deratable surfaces of right type.
274
+ # If not, assign new lc clone to non-targeted surfaces.
275
+ s.each do |nom, surface|
276
+ next unless surface.key?(:type )
277
+ next unless surface.key?(:deratable )
278
+ next unless surface.key?(:construction)
279
+ next unless surface[:construction].is_a?(cl3)
280
+ next unless surface[:construction] == lc
281
+
282
+ ok = true
283
+ ok = false unless surface[:type ] == typ
284
+ ok = false unless surface[:deratable]
285
+ ok = false unless coll.key?(id)
286
+ ok = false unless coll[id][:s].key?(nom)
287
+
288
+ unless ok
289
+ log(WRN, "Cloning '#{nom}' construction - not '#{id}' (#{mth})")
290
+ sss = model.getSurfaceByName(nom)
291
+ next if sss.empty?
292
+
293
+ sss = sss.get
294
+ cloned = lc.clone(model).to_LayeredConstruction.get
295
+ cloned.setName("#{nom} - cloned")
296
+ sss.setConstruction(cloned)
297
+ surface[:construction] = cloned
298
+ coll[id][:s].delete(nom)
299
+ end
300
+ end
301
+
302
+ hloss = 0 # sum of applicable psi & khi effects [W/K]
278
303
 
304
+ # Tally applicable psi + khi losses. Possible construction reassignment.
305
+ coll.each do |i, col|
279
306
  col[:s].keys.each do |nom|
280
307
  next unless s.key?(nom)
281
- next unless s[nom].key?(:deratable )
282
308
  next unless s[nom].key?(:construction)
283
309
  next unless s[nom].key?(:index )
284
310
  next unless s[nom].key?(:ltype )
285
311
  next unless s[nom].key?(:r )
286
- next unless s[nom].key?(:type )
287
-
288
- next unless s[nom][:deratable]
289
- type = s[nom][:type].to_s.downcase
290
- type = "roof" if type == "ceiling"
291
- next unless type.include?(label.to_s)
292
312
 
293
313
  # Tally applicable psi + khi.
294
- hloss += s[nom][:heatloss] if s[nom].key?(:heatloss)
295
-
296
- # Skip construction reassignment if already referencing right one.
297
- unless s[nom][:construction] == lc
298
- sss = model.getSurfaceByName(nom)
299
- next if sss.empty?
300
- sss = sss.get
301
-
302
- if sss.isConstructionDefaulted
303
- set = defaultConstructionSet(model, sss)
304
- constructions = set.defaultExteriorSurfaceConstructions.get
305
-
306
- case sss.surfaceType.downcase
307
- when "roofceiling"
308
- constructions.setRoofCeilingConstruction(lc)
309
- when "floor"
310
- constructions.setFloorConstruction(lc)
311
- else
312
- constructions.setWallConstruction(lc)
313
- end
314
- else
315
- sss.setConstruction(lc)
316
- end
314
+ hloss += s[nom][:heatloss ] if s[nom].key?(:heatloss)
315
+ next if s[nom][:construction] == lc
316
+
317
+ # Reassign construction unless referencing lc.
318
+ sss = model.getSurfaceByName(nom)
319
+ next if sss.empty?
317
320
 
318
- s[nom][:construction] = lc # reset TBD attributes
319
- s[nom][:index ] = lyr[:index]
320
- s[nom][:ltype ] = lyr[:type ]
321
- s[nom][:r ] = lyr[:r ] # temporary
321
+ sss = sss.get
322
+
323
+ if sss.isConstructionDefaulted
324
+ set = defaultConstructionSet(model, sss) # building? story?
325
+ constructions = set.defaultExteriorSurfaceConstructions
326
+
327
+ unless constructions.empty?
328
+ constructions = constructions.get
329
+ constructions.setWallConstruction(lc) if typ == :wall
330
+ constructions.setFloorConstruction(lc) if typ == :floor
331
+ constructions.setRoofCeilingConstruction(lc) if typ == :ceiling
332
+ end
333
+ else
334
+ sss.setConstruction(lc)
322
335
  end
336
+
337
+ s[nom][:construction] = lc # reset TBD attributes
338
+ s[nom][:index ] = lyr[:index]
339
+ s[nom][:ltype ] = lyr[:type ]
340
+ s[nom][:r ] = lyr[:r ] # temporary
323
341
  end
324
342
  end
325
343
 
326
344
  # Merge to ensure a single entry for coll Hash.
327
345
  coll.each do |i, col|
328
346
  next if i == id
329
- next unless coll.key?(id)
330
- coll[id][:area] += col[:area]
331
347
 
332
348
  col[:s].each do |nom, sss|
333
349
  coll[id][:s][nom] = sss unless coll[id][:s].key?(nom)
@@ -338,6 +354,8 @@ module TBD
338
354
  log(DBG, "Collection == 1? for '#{id}' (#{mth})") unless coll.size == 1
339
355
  next unless coll.size == 1
340
356
 
357
+ area = lc.getNetArea
358
+ coll[id][:area] = area
341
359
  res = uo(model, lc, id, hloss, film, g[:ut])
342
360
  log(ERR, "Unable to uprate '#{id}' (#{mth})") unless res[:uo] && res[:m]
343
361
  next unless res[:uo] && res[:m]
@@ -347,27 +365,18 @@ module TBD
347
365
  # Loop through coll :s, and reset :r - likely modified by uo().
348
366
  coll.values.first[:s].keys.each do |nom|
349
367
  next unless s.key?(nom)
350
- next unless s[nom].key?(:deratable )
351
- next unless s[nom].key?(:construction)
352
- next unless s[nom].key?(:index )
353
- next unless s[nom].key?(:ltype )
354
- next unless s[nom].key?(:type )
355
-
356
- next unless s[nom][:deratable ]
357
- next unless s[nom][:construction] == lc
358
- next unless s[nom][:index ] == lyr[:index]
359
- next unless s[nom][:ltype ] == lyr[:type]
360
-
361
- type = s[nom][:type].to_s.downcase
362
- type = "roof" if type == "ceiling"
363
- next unless type.include?(label.to_s)
364
- next unless s[nom].key?(:r)
365
- s[nom][:r] = lyr[:r] # final
368
+ next unless s[nom].key?(:index)
369
+ next unless s[nom].key?(:ltype)
370
+ next unless s[nom].key?(:r )
371
+ next unless s[nom][:index] == lyr[:index]
372
+ next unless s[nom][:ltype] == lyr[:type ]
373
+
374
+ s[nom][:r] = lyr[:r] # uprated insulating RSi factor, before derating
366
375
  end
367
376
 
368
- argh[:wall_uo ] = res[:uo] if label == :wall
369
- argh[:roof_uo ] = res[:uo] if label == :roof
370
- argh[:floor_uo] = res[:uo] if label == :floor
377
+ argh[:wall_uo ] = res[:uo] if typ == :wall
378
+ argh[:roof_uo ] = res[:uo] if typ == :ceiling
379
+ argh[:floor_uo] = res[:uo] if typ == :floor
371
380
  else
372
381
  log(ERR, "Nilled construction to uprate - (#{mth})")
373
382
  return false
@@ -920,7 +929,7 @@ module TBD
920
929
  model = "* modèle : #{ua[:file]}" if ua.key?(:file) && lang == :fr
921
930
  model += " (v#{ua[:version]})" if ua.key?(:version)
922
931
  report << model unless model.empty?
923
- report << "* TBD : v3.2.1"
932
+ report << "* TBD : v3.2.3"
924
933
  report << "* date : #{ua[:date]}"
925
934
 
926
935
  if lang == :en
data/lib/tbd/version.rb CHANGED
@@ -21,5 +21,5 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  module TBD
24
- VERSION = "3.2.1".freeze
24
+ VERSION = "3.2.3".freeze
25
25
  end
data/tbd.gemspec CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |s|
29
29
  s.metadata = {}
30
30
 
31
31
  s.add_dependency "topolys", "~> 0"
32
- s.add_dependency "osut", "~> 0"
32
+ s.add_dependency "osut", "~> 0.3.0"
33
33
  s.add_dependency "json-schema", "~> 2.7.0"
34
34
 
35
35
  s.add_development_dependency "bundler", "~> 2.1"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tbd
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.1
4
+ version: 3.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis Bourgeois & Dan Macumber
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-02-16 00:00:00.000000000 Z
11
+ date: 2023-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: topolys
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: 0.3.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: 0.3.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: json-schema
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -161,7 +161,7 @@ licenses:
161
161
  - MIT
162
162
  metadata:
163
163
  homepage_uri: https://github.com/rd2/tbd
164
- source_code_uri: https://github.com/rd2/tbd/tree/v3.2.1
164
+ source_code_uri: https://github.com/rd2/tbd/tree/v3.2.3
165
165
  bug_tracker_uri: https://github.com/rd2/tbd/issues
166
166
  post_install_message:
167
167
  rdoc_options: []