Skip to content

Design Codes System

Miguel Prada edited this page Apr 30, 2023 · 2 revisions

In Structuraid we need to have a system where we centralize all the information regarding design requirements coming from codes and standards. Since these codes are usually mandatory on a regional/country basis, it would be useful to offer the feature of supporting multiple design codes and use one of them according to the project setup.

Here’s the following diagram that explains how the DesignCodes system will work

Untitled

The system is composed of the following abstractions

  • A Resolver class that will provide the functionality to point to the namespace that corresponds to the desired design code
  • A namespace for each design code that the app will support. As examples, the diagram above illustrates namespaces for the Colombian NSR-10 and US ACI 318-19
  • Inside each code namespace there will be a series of abstractions, each one will correspond to one requirement or process that needs to be performed following each design code. The file structure of these abstractions needs to be identical on each design code namespace.
  • A namespace of Schemas that will ensure that the contract of each requirement abstraction is kept the same no matter which design code is going to be followed.

System Usage

The first thing to do before using the design codes system is to call the resolver in order to point to the right namespace that the project will need to use:

design_code = DesignCodes::Resolver.use('nsr_10')

The resolver will return as a result the namespace that should be used later to call any requirement that needs to be made. For example, if you need to compute the elastic modulus according to the design code, do this:

design_code::RC::ElasticModulus.call(design_compression_strength: 28)

Error Handling

Each Code Requirement abstraction will raise one of the following errors if something went wrong:

  • DesignCodes::MissingParamError

    This one will be thrown if the params contract wasn’t respected. That is, if you forgot to pass a required param in the call method. If you need to see what are the required params for a given requirement, do the following

    design_code::RC::ElasticModulus.schema_klass.required
  • TBD: Error to throw if a requirement is not met

Creating a new Code Requirement

Before creating a new code requirement, please consider the following:

  • You’ll need to create the requirement in all design codes namespaces. For example, if you need to add a requirement about specific weight of concrete according to NSR-10, you have to create the same abstraction in both NSR10 and ACI31819 namespaces. So, please do the investigation on all supported codes to make sure that you add the requirement for each one accordingly.
    • If the requirement only applies to a specific code, create the abstraction in all code namespaces and just return nil in the ones that don’t have that requirement.
  • You’ll need to create a schema for the requirement. The schema is used to specify the required and optional parameters that your abstraction will receive. This schema must be used for the same requirement in all design codes, that way we can ensure that when we call the abstraction at any point in the program, we are being compatible with all the design codes.

Defining the Schema

The schema file must be located in lib/design_codes/schemas/ and the file name should end with _schema.rb

The file should look something like this

require 'design_codes/utils/schema_definition'

module DesignCodes
  module Schemas
    module RC
      class ElasticModulusSchema
        include DesignCodes::Utils::SchemaDefinition

        required_params %i[design_compression_strength]
        optional_params []
      end
    end
  end
end

It must have the following:

  • Include the DesignCodes::Utils::SchemaDefinition module to do the magic
  • Add a required_params call passing an array of symbols, each symbol being a param name
  • Add a optional_params call passing a similar array of symbols
    • If there is no required param or optional param, do the calls but pass an empty array
  • Use enum to specify params that should receive one value among a given list of options. If the requirement is called and the param is passed with an invalid value it will raise a DesignCodes::UnrecognizedValueError

A required_param will throw an error whenever the requirement is called and it’s missing. An optional_param will just throw a warning on the terminal

Defining the Requirement Abstraction

Each abstraction should look something like this

require 'design_codes/utils/code_requirement'
require 'design_codes/schemas/rc/elastic_modulus_schema'

module DesignCodes
  module NSR10
    module RC
      class ElasticModulus
        include DesignCodes::Utils::CodeRequirement
        use_schema DesignCodes::Schemas::RC::ElasticModulusSchema

        # NSR-10 C.8.5.1
        def call
          4700 * Math.sqrt(params.design_compression_strength)
        end
      end
    end
  end
end

It must have the following:

  • Include the DesignCodes::Utils::CodeRequirement module to do all the magic
  • Add a use_schema call to associate the abstraction with its corresponding schema
  • Define a call method which should do all the procedure according to the design code.
    • The abstraction will have a params struct available to be able to access the params that are being passed when the abstraction is invoked. These params are sanitized, it means that only the params defined in the schema will be available in this object.
  • Remember to create the same abstraction on each design code namespace.

Related PRs