structuraid_core 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +38 -0
  4. data/CHANGELOG.md +5 -0
  5. data/CODE_OF_CONDUCT.md +84 -0
  6. data/Gemfile +2 -0
  7. data/Guardfile +5 -0
  8. data/LICENSE +21 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +37 -0
  11. data/Rakefile +12 -0
  12. data/lib/structuraid_core/db/base.rb +13 -0
  13. data/lib/structuraid_core/db/rebars.yml +36 -0
  14. data/lib/structuraid_core/design_codes/aci_318_19/rc/elastic_modulus.rb +17 -0
  15. data/lib/structuraid_core/design_codes/base.rb +15 -0
  16. data/lib/structuraid_core/design_codes/nsr_10/rc/elastic_modulus.rb +17 -0
  17. data/lib/structuraid_core/design_codes/resolver.rb +21 -0
  18. data/lib/structuraid_core/design_codes/schemas/empty_schema.rb +12 -0
  19. data/lib/structuraid_core/design_codes/schemas/rc/elastic_modulus_schema.rb +14 -0
  20. data/lib/structuraid_core/design_codes/utils/code_requirement.rb +39 -0
  21. data/lib/structuraid_core/design_codes/utils/schema_definition.rb +56 -0
  22. data/lib/structuraid_core/elements/base.rb +10 -0
  23. data/lib/structuraid_core/elements/column/base.rb +10 -0
  24. data/lib/structuraid_core/elements/column/rectangular.rb +16 -0
  25. data/lib/structuraid_core/elements/footing.rb +83 -0
  26. data/lib/structuraid_core/elements/reinforcement/base.rb +14 -0
  27. data/lib/structuraid_core/elements/reinforcement/rebar.rb +45 -0
  28. data/lib/structuraid_core/elements/reinforcement/rebar_hook.rb +18 -0
  29. data/lib/structuraid_core/elements/reinforcement/straight_longitudinal.rb +44 -0
  30. data/lib/structuraid_core/elements/reinforcement/straight_longitudinal_layer.rb +89 -0
  31. data/lib/structuraid_core/elements/reinforcement/utils/rebar_data.rb +14 -0
  32. data/lib/structuraid_core/engineering/analysis/footing/centric_isolated.rb +60 -0
  33. data/lib/structuraid_core/engineering/base.rb +10 -0
  34. data/lib/structuraid_core/engineering/locations/absolute.rb +19 -0
  35. data/lib/structuraid_core/engineering/locations/base.rb +11 -0
  36. data/lib/structuraid_core/engineering/locations/relative.rb +15 -0
  37. data/lib/structuraid_core/engineering/vector.rb +35 -0
  38. data/lib/structuraid_core/errors/base.rb +12 -0
  39. data/lib/structuraid_core/errors/design_codes/missing_param_error.rb +9 -0
  40. data/lib/structuraid_core/errors/design_codes/unknown_design_code_error.rb +11 -0
  41. data/lib/structuraid_core/errors/engineering/analysis/section_direction_error.rb +13 -0
  42. data/lib/structuraid_core/errors/reinforcement/empty_layers.rb +13 -0
  43. data/lib/structuraid_core/errors/reinforcement/invalid_distribution_direction.rb +13 -0
  44. data/lib/structuraid_core/loads/base.rb +9 -0
  45. data/lib/structuraid_core/loads/point_load.rb +13 -0
  46. data/lib/structuraid_core/loads/uniform_load.rb +15 -0
  47. data/lib/structuraid_core/materials/base.rb +10 -0
  48. data/lib/structuraid_core/materials/concrete.rb +13 -0
  49. data/lib/structuraid_core/materials/soil.rb +11 -0
  50. data/lib/structuraid_core/materials/steel.rb +14 -0
  51. data/lib/structuraid_core/version.rb +5 -0
  52. data/lib/structuraid_core.rb +14 -0
  53. data/sig/structuraid_core.rbs +4 -0
  54. data/structuraid_core.gemspec +50 -0
  55. metadata +212 -0
@@ -0,0 +1,45 @@
1
+ module StructuraidCore
2
+ module Elements
3
+ module Reinforcement
4
+ class Rebar < Base
5
+ include Utils::RebarData
6
+
7
+ attr_reader :start_hook, :end_hook, :diameter, :number, :material
8
+
9
+ def initialize(number:, material:)
10
+ @start_hook = nil
11
+ @end_hook = nil
12
+ @number = number
13
+ @material = material
14
+ @diameter = find_standard_diameter(rebar_number: number)
15
+ end
16
+
17
+ def area
18
+ rebar_area = Math::PI * (diameter**2) / 4
19
+ rebar_area.to_f
20
+ end
21
+
22
+ def perimeter
23
+ rebar_perimeter = Math::PI * diameter
24
+ rebar_perimeter.to_f
25
+ end
26
+
27
+ def add_start_hook(hook)
28
+ @start_hook = hook
29
+ end
30
+
31
+ def add_end_hook(hook)
32
+ @end_hook = hook
33
+ end
34
+
35
+ def delete_start_hook
36
+ @start_hook = nil
37
+ end
38
+
39
+ def delete_end_hook
40
+ @end_hook = nil
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,18 @@
1
+ module StructuraidCore
2
+ module Elements
3
+ module Reinforcement
4
+ class RebarHook < Base
5
+ include Utils::RebarData
6
+
7
+ attr_reader :angle
8
+
9
+ def initialize(number:, material:)
10
+ @angle = nil
11
+ @number = number
12
+ @material = material
13
+ @diameter = find_standard_diameter(rebar_number: number)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,44 @@
1
+ module StructuraidCore
2
+ module Elements
3
+ module Reinforcement
4
+ class StraightLongitudinal < Base
5
+ attr_reader :layers
6
+
7
+ def initialize(distribution_direction:, above_middle: false)
8
+ @above_middle = above_middle
9
+ @layers = []
10
+ @distribution_direction = distribution_direction
11
+ end
12
+
13
+ def add_layer(start_location:, end_location:, amount_of_rebars:, rebar:)
14
+ new_layer = Elements::Reinforcement::StraightLongitudinalLayer.new(
15
+ start_location:,
16
+ end_location:,
17
+ amount_of_rebars:,
18
+ rebar:,
19
+ distribution_direction: @distribution_direction
20
+ )
21
+
22
+ new_layer.reposition(above_middle: @above_middle)
23
+ @layers << new_layer
24
+
25
+ new_layer
26
+ end
27
+
28
+ def centroid_height
29
+ return inertia / area unless @layers.empty?
30
+
31
+ raise Elements::Reinforcement::EmptyLayers, "can't complete centroid height calculation"
32
+ end
33
+
34
+ def area
35
+ @layers.map(&:area).reduce(:+)
36
+ end
37
+
38
+ def inertia
39
+ @layers.map(&:inertia).reduce(:+)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,89 @@
1
+ module StructuraidCore
2
+ module Elements
3
+ module Reinforcement
4
+ class StraightLongitudinalLayer < Base
5
+ attr_reader :rebar, :amount_of_rebars
6
+
7
+ VALID_DIRECTIONS = %i[length_1 length_2 length_3].freeze
8
+
9
+ def initialize(
10
+ start_location:,
11
+ end_location:,
12
+ amount_of_rebars:,
13
+ rebar:,
14
+ distribution_direction:
15
+ )
16
+ if VALID_DIRECTIONS.none?(distribution_direction)
17
+ raise Elements::Reinforcement::InvalidDistributionDirection.new(distribution_direction, VALID_DIRECTIONS)
18
+ end
19
+
20
+ @start_location = start_location
21
+ @end_location = end_location
22
+ @amount_of_rebars = amount_of_rebars
23
+ @rebar = rebar
24
+ @distribution_direction = distribution_direction
25
+ end
26
+
27
+ def modify_rebar_configuration(
28
+ amount_of_new_rebars:,
29
+ new_rebar:,
30
+ above_middle:
31
+ )
32
+
33
+ offset = (diameter - new_rebar.diameter) / 2
34
+ offset *= -1 unless above_middle
35
+
36
+ @amount_of_rebars = amount_of_new_rebars
37
+ @rebar = new_rebar
38
+
39
+ reposition(above_middle:, offset:)
40
+ @rebar
41
+ end
42
+
43
+ def reposition(above_middle:, offset: nil)
44
+ offset ||= 0.5 * diameter
45
+
46
+ [@start_location, @end_location].each do |location|
47
+ location.value_3 = above_middle ? location.value_3 - offset : location.value_3 + offset
48
+ end
49
+ end
50
+
51
+ def area
52
+ @amount_of_rebars * @rebar.area
53
+ end
54
+
55
+ def inertia
56
+ area * centroid_height
57
+ end
58
+
59
+ def centroid_height
60
+ @start_location.value_3
61
+ end
62
+
63
+ def diameter
64
+ @rebar.diameter
65
+ end
66
+
67
+ def length
68
+ vector = length_vector
69
+
70
+ vector.value_x = 0 if @distribution_direction == :length_1
71
+ vector.value_y = 0 if @distribution_direction == :length_2
72
+ vector.value_z = 0 if @distribution_direction == :length_3
73
+
74
+ vector.magnitude
75
+ end
76
+
77
+ private
78
+
79
+ def length_vector
80
+ Engineering::Vector.new(
81
+ value_x: @end_location.value_1 - @start_location.value_1,
82
+ value_y: @end_location.value_2 - @start_location.value_2,
83
+ value_z: @end_location.value_3 - @start_location.value_3
84
+ )
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,14 @@
1
+ module StructuraidCore
2
+ module Elements
3
+ module Reinforcement
4
+ module Utils
5
+ module RebarData
6
+ def find_standard_diameter(rebar_number:)
7
+ standard_rebar_data = DB::Base.find_standard_rebar(number: rebar_number)
8
+ standard_rebar_data['diameter'].to_f
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,60 @@
1
+ module StructuraidCore
2
+ module Engineering
3
+ module Analysis
4
+ module Footing
5
+ class CentricIsolated
6
+ ORTHOGONALITIES = %i[length_1 length_2].freeze
7
+
8
+ def initialize(footing:, load_from_column:, section_direction:)
9
+ if ORTHOGONALITIES.none?(section_direction)
10
+ raise Engineering::Analysis::SectionDirectionError.new(section_direction, ORTHOGONALITIES)
11
+ end
12
+
13
+ @footing = footing
14
+ @load_from_column = load_from_column
15
+ @section_direction = section_direction
16
+ end
17
+
18
+ def solicitation_load
19
+ solicitation * orthogonal_length
20
+ end
21
+
22
+ def max_shear_solicitation
23
+ solicitation_load * section_length
24
+ end
25
+
26
+ def shear_solicitation_at(distance_from_footing_center:)
27
+ footing_section_length = section_length
28
+
29
+ solicitation_load * (footing_section_length - distance_from_footing_center)
30
+ end
31
+
32
+ def bending_solicitation
33
+ 0.25 * max_shear_solicitation * section_length
34
+ end
35
+
36
+ private
37
+
38
+ attr_reader :footing, :load_from_column, :section_direction
39
+
40
+ def section_length
41
+ footing.public_send(section_direction)
42
+ end
43
+
44
+ def orthogonal_length
45
+ footing.public_send(orthogonal_direction)
46
+ end
47
+
48
+ def solicitation
49
+ load_from_column.value / footing.horizontal_area
50
+ end
51
+
52
+ def orthogonal_direction
53
+ orthogonal = ORTHOGONALITIES - [section_direction]
54
+ orthogonal.last
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,10 @@
1
+ module StructuraidCore
2
+ module Engineering
3
+ class Base
4
+ end
5
+ end
6
+ end
7
+
8
+ require_relative 'vector'
9
+ require_relative 'analysis/footing/centric_isolated'
10
+ require_relative 'locations/base'
@@ -0,0 +1,19 @@
1
+ module StructuraidCore
2
+ module Engineering
3
+ module Locations
4
+ class Absolute < Base
5
+ attr_accessor :value_x, :value_y, :value_z
6
+
7
+ def initialize(value_x:, value_y:, value_z:)
8
+ @value_x = value_x.to_f
9
+ @value_y = value_y.to_f
10
+ @value_z = value_z.to_f
11
+ end
12
+
13
+ def to_a
14
+ [@value_x, @value_y, @value_z]
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ module StructuraidCore
2
+ module Engineering
3
+ module Locations
4
+ class Base
5
+ end
6
+ end
7
+ end
8
+ end
9
+
10
+ require_relative 'absolute'
11
+ require_relative 'relative'
@@ -0,0 +1,15 @@
1
+ module StructuraidCore
2
+ module Engineering
3
+ module Locations
4
+ class Relative < Base
5
+ attr_accessor :value_1, :value_2, :value_3
6
+
7
+ def initialize(value_1:, value_2:, value_3:)
8
+ @value_1 = value_1.to_f
9
+ @value_2 = value_2.to_f
10
+ @value_3 = value_3.to_f
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,35 @@
1
+ module StructuraidCore
2
+ module Engineering
3
+ class Vector < Base
4
+ attr_accessor :value_x, :value_y, :value_z
5
+
6
+ def self.with_value(value:, direction:)
7
+ new(
8
+ value_x: value.to_f * direction[0],
9
+ value_y: value.to_f * direction[1],
10
+ value_z: value.to_f * direction[2]
11
+ )
12
+ end
13
+
14
+ def initialize(value_x:, value_y:, value_z:)
15
+ @value_x = value_x.to_f
16
+ @value_y = value_y.to_f
17
+ @value_z = value_z.to_f
18
+ end
19
+
20
+ def magnitude
21
+ Math.sqrt(value_x**2 + value_y**2 + value_z**2)
22
+ end
23
+
24
+ def direction
25
+ vector_magnitude = magnitude
26
+
27
+ [
28
+ @value_x / vector_magnitude,
29
+ @value_y / vector_magnitude,
30
+ @value_z / vector_magnitude
31
+ ]
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,12 @@
1
+ module StructuraidCore
2
+ module Errors
3
+ class Base < StandardError
4
+ end
5
+ end
6
+ end
7
+
8
+ require_relative 'design_codes/missing_param_error'
9
+ require_relative 'design_codes/unknown_design_code_error'
10
+ require_relative 'engineering/analysis/section_direction_error'
11
+ require_relative 'reinforcement/empty_layers'
12
+ require_relative 'reinforcement/invalid_distribution_direction'
@@ -0,0 +1,9 @@
1
+ module StructuraidCore
2
+ module DesignCodes
3
+ class MissingParamError < StandardError
4
+ def initialize(param)
5
+ super("#{param} param is required")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ module StructuraidCore
2
+ module DesignCodes
3
+ class UnknownDesignCodeError < StandardError
4
+ def initialize(code_name)
5
+ message = "Design code #{code_name} is unknown. Must select one of #{DesignCodes::Resolver::CODES_NAMESPACES}"
6
+
7
+ super(message)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module StructuraidCore
2
+ module Engineering
3
+ module Analysis
4
+ class SectionDirectionError < StandardError
5
+ def initialize(section_direction, valid_options)
6
+ message = "#{section_direction} is not a valid direction, should one of #{valid_options}"
7
+
8
+ super(message)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module StructuraidCore
2
+ module Elements
3
+ module Reinforcement
4
+ class EmptyLayers < StandardError
5
+ def initialize(complement)
6
+ message = "There are no layers #{complement}"
7
+
8
+ super(message)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module StructuraidCore
2
+ module Elements
3
+ module Reinforcement
4
+ class InvalidDistributionDirection < StandardError
5
+ def initialize(distribution_direction, valid_directions)
6
+ message = "#{distribution_direction} is not a valid direction, should one of #{valid_directions}"
7
+
8
+ super(message)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ module StructuraidCore
2
+ module Loads
3
+ class Base
4
+ end
5
+ end
6
+ end
7
+
8
+ require_relative 'point_load'
9
+ require_relative 'uniform_load'
@@ -0,0 +1,13 @@
1
+ module StructuraidCore
2
+ module Loads
3
+ class PointLoad < Base
4
+ attr_accessor :value
5
+ attr_reader :location
6
+
7
+ def initialize(value:, location:)
8
+ @value = value.to_f
9
+ @location = location
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ module StructuraidCore
2
+ module Loads
3
+ class UniformLoad < Base
4
+ attr_accessor :start_value, :end_value
5
+ attr_reader :start_location
6
+
7
+ def initialize(start_value:, end_value:, start_location:, end_location:)
8
+ @start_value = start_value.to_f
9
+ @end_value = end_value.to_f
10
+ @start_location = start_location
11
+ @end_location = end_location
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ module StructuraidCore
2
+ module Materials
3
+ class Base
4
+ end
5
+ end
6
+ end
7
+
8
+ require_relative 'concrete'
9
+ require_relative 'soil'
10
+ require_relative 'steel'
@@ -0,0 +1,13 @@
1
+ module StructuraidCore
2
+ module Materials
3
+ class Concrete < Base
4
+ attr_reader :elastic_module, :design_compression_strength, :specific_weight
5
+
6
+ def initialize(elastic_module:, design_compression_strength:, specific_weight:)
7
+ @elastic_module = elastic_module.to_f
8
+ @design_compression_strength = design_compression_strength.to_f
9
+ @specific_weight = specific_weight.to_f
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ module StructuraidCore
2
+ module Materials
3
+ class Soil < Base
4
+ attr_reader :bearing_capacity
5
+
6
+ def initialize(bearing_capacity:)
7
+ @bearing_capacity = bearing_capacity.to_f
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ module StructuraidCore
2
+ module Materials
3
+ class Steel < Base
4
+ DEFAULT_ELASTIC_MODULE = 200_000
5
+
6
+ attr_reader :elastic_module, :yield_stress
7
+
8
+ def initialize(yield_stress:, elastic_module: DEFAULT_ELASTIC_MODULE)
9
+ @elastic_module = elastic_module.to_f
10
+ @yield_stress = yield_stress.to_f
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StructuraidCore
4
+ VERSION = '0.1.1'
5
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'structuraid_core/version'
4
+
5
+ module StructuraidCore
6
+ end
7
+
8
+ require_relative 'structuraid_core/db/base'
9
+ require_relative 'structuraid_core/errors/base'
10
+ require_relative 'structuraid_core/design_codes/base'
11
+ require_relative 'structuraid_core/loads/base'
12
+ require_relative 'structuraid_core/materials/base'
13
+ require_relative 'structuraid_core/engineering/base'
14
+ require_relative 'structuraid_core/elements/base'
@@ -0,0 +1,4 @@
1
+ module StructuraidCore
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/structuraid_core/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'structuraid_core'
7
+ spec.version = StructuraidCore::VERSION
8
+ spec.authors = ['Pradaing']
9
+ spec.email = ['engineering@pradic.co']
10
+
11
+ spec.summary = 'Gem with core utilities and functionality to design building structures'
12
+
13
+ description = <<-DESCRIPTION
14
+ structuraid_core is a gem that offers a set of functionalities to assist in the design building structures.
15
+ DESCRIPTION
16
+ spec.description = description.strip
17
+
18
+ spec.homepage = 'https://github.com/PradaIng/structuraid-core'
19
+ spec.license = 'MIT'
20
+ spec.required_ruby_version = '>= 3.1.2'
21
+
22
+ # spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
23
+ spec.metadata['homepage_uri'] = spec.homepage
24
+ spec.metadata['source_code_uri'] = spec.homepage
25
+ spec.metadata['changelog_uri'] = 'https://github.com/PradaIng/structuraid-core/blob/main/CHANGELOG.md'
26
+
27
+ # Specify which files should be added to the gem when it is released.
28
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
29
+ spec.files = Dir.chdir(__dir__) do
30
+ `git ls-files -z`.split("\x0").reject do |f|
31
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
32
+ end
33
+ end
34
+ spec.bindir = 'exe'
35
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
36
+ spec.require_paths = ['lib']
37
+
38
+ spec.add_development_dependency 'byebug', '~> 11.1.3'
39
+ spec.add_development_dependency 'guard-rspec', '~> 4.7.3'
40
+ spec.add_development_dependency 'rspec', '~> 3.11.0'
41
+ spec.add_development_dependency 'rubocop', '~> 1.41.1'
42
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.16.0'
43
+ spec.add_development_dependency 'simplecov', '~> 0.22.0'
44
+
45
+ spec.add_dependency 'rake', '~> 13.0.6'
46
+ spec.add_dependency 'require_all', '~> 3.0.0'
47
+
48
+ # For more information and examples about making a new gem, check out our
49
+ # guide at: https://bundler.io/guides/creating_gem.html
50
+ end