Ruby Script Item for Calculating Occupancy Load


Recommended Posts

Morning all... I'm trying to create a macro to calculate the occupancy load of a room by taking the interior square footage of the room and dividing it by the occupancy load for occupancy type.  Using ChatGPT I got the result of this macro that should help me get the result I need but it's not working.  I assume I first have to get rid of the unit text in order to divide by the occupant load I want to divide by.  So this is the code it came up with.  Anyone ruby script people know what is wrong here?  Does this need to be different because it's in CA?  Any help would be appreciated.

 

source_information = %room.area.internal%

numeric_part = source_information.match(/\d+/)[0]

numeric_value = numeric_part.to_i

result = numeric_value / 20

puts result

 

 

Link to comment
Share on other sites

I don't typically donate time to troubleshoot or advise on scripting issues on here anymore, but I decided to make a one time exception this morning: 

 

There are all sorts of little problems:

 

source_information = %room.area.internal%

numeric_part = source_information.match(/\d+/)[0]

numeric_value = numeric_part.to_i

result = numeric_value / 20

puts result

 

1.  %room.area.internal% isn't a Ruby accessible object attribute (name:value pair).  It's just a Chief Architect string substitution macro.  If you want to use this macro in a text box placed in the room, the name:value pair you should be using is simply room.internal_area without the percentage signs.

2.  The match method is a Ruby method used to parse a string.  The internal area attribute however is not a string.  Its a Measurement.  If you want to use the match method, you first need to convert the source_information to a string using the .to_s method.

3.  Just an observation, but you may not be getting the results you think.  The .to_i method is converting your results to an integer which is the whole number rounded down.  0.999 would become zero, 559.9 becomes 559, etc.  What's worse though is that because you're diving by another integer (20) the results of your calculation would also become another integer.  So, instead of 559.9/20 = 27.995 you would get an even 27.  This one can be solved by just converting to a float (which contains decimal values) and then rounding the result.  This can be done a number of ways, but one of the easiest would simply be to replace .to_i with .to_f.

4.  puts isn't used in Chief's text macro environment.  It's simply not needed.  If you try to use it, your results will by nil (empty).  

 

So, the corrected macro becomes:

source_information = room.internal_area

numeric_part = source_information.to_s.match(/\d+/)[0]

numeric_value = numeric_part.to_f

result = numeric_value / 20

result.round

 

Although the above macro would work, it still has a handful of totally unnecessary code and could be reduced all the way down to:

(room.internal_area.to_f/20).round

 

 

  • Upvote 1
Link to comment
Share on other sites

3 hours ago, amddrafting said:

Morning

first off, mike is the man, love it when I get to read through his approach on anything macros...I believe he may still do ruby training so hit him up :)
I would add in some variables in the beginning in case you ever expand your method and maybe some conditions.
 



# Copyright Rabbitt Design 2024
##########################################################################################
# Rabbitt Design assumes no liability for the accuracy of the occupancy calculations or 
# any consequences arising from the use of this script. Users are responsible for verifying 
# the appropriateness of the occupancy loads and ensuring the script functions as intended 
# in their specific use case.
##########################################################################################

#Use by putting a statement in your text box/polyline label/room_label
#%$occupancy="Educational"%
#Occupant Load:%occupancy_load%

##########################################################################################
# Occupancy Load Constants
# Note: Load values are in square feet per person
OCCUPANCY_LOADS = {
  assembly: 15,    # Areas for public gatherings (e.g., auditoriums, dining areas)
  business: 100,   # Typical office spaces
  educational: 20, # Classrooms and educational facilities
  factory: 50,     # Industrial and manufacturing spaces
  high_hazard: 500,# High hazard areas with minimal occupancy
  institutional: 240, # Hospitals, care facilities
  mercantile: 30,  # Retail and sales floors
  residential: 200,# Living areas in residential settings
  storage: 300,    # Storage areas with limited occupancy
  utility: 500     # Miscellaneous and utility buildings
}

# Calculate Occupancy based on predefined occupancy type and defined area
def calculate_occupancy(room_area)
  # Normalize occupancy type
  load_factor = OCCUPANCY_LOADS[$occupancy.downcase.to_sym] rescue nil
  if load_factor.nil?
    raise "Occupancy type '#{$occupancy}' is not defined or incorrect."
  end

  # Calculate occupancy
  occupancy = (room_area.to_f / load_factor).round
  occupancy
end

# Conditionally determine the room_area based on whether 'room' is defined
room_area = if defined?(room)
              room.internal_area
            elsif defined?(internal_area)
              internal_area
            else
              area  # Fallback to just 'area' if the other two are not available
            end

# Call the function with room_area, assuming $occupancy is defined elsewhere
final_occupancy = calculate_occupancy(room_area)
final_occupancy  # This line implicitly outputs the result

You could use this in your room label or in a text box or in a polyline label

In either you could need:

%$occupancy="Educational"%

Occupant Load:%occupancy_load%


 

For instance. this will set the appropriate variable call
image.png.14f31ea5506cb456c1264888aa80e114.png

  • Upvote 1
Link to comment
Share on other sites

2 hours ago, Alaskan_Son said:

There are all sorts of little problems:

 

source_information = %room.area.internal%

numeric_part = source_information.match(/\d+/)[0]

numeric_value = numeric_part.to_i

result = numeric_value / 20

puts result

 

1.  %room.area.internal% isn't a Ruby accessible object attribute (name:value pair).  It's just a Chief Architect string substitution macro.  If you want to use this macro in a text box placed in the room, the name:value pair you should be using is simply room.internal_area without the percentage signs.

2.  The match method is a Ruby method used to parse a string.  The internal area attribute however is not a string.  Its a Measurement.  If you want to use the match method, you first need to convert the source_information to a string using the .to_s method.

3.  Just an observation, but you may not be getting the results you think.  The .to_i method is converting your results to an integer which is the whole number rounded down.  0.999 would become zero, 559.9 becomes 559, etc.  What's worse though is that because you're diving by another integer (20) the results of your calculation would also become another integer.  So, instead of 559.9/20 = 27.995 you would get an even 27.  This one can be solved by just converting to a float (which contains decimal values) and then rounding the result.  This can be done a number of ways, but one of the easiest would simply be to replace .to_i with .to_f.

4.  puts isn't used in Chief's text macro environment.  It's simply not needed.  If you try to use it, your results will by nil (empty).  

 

So, the corrected macro becomes:

source_information = room.internal_area

numeric_part = source_information.to_s.match(/\d+/)[0]

numeric_value = numeric_part.to_f

result = numeric_value / 20

result.round

 

Although the above macro would work, it still has a handful of totally unnecessary code and could be reduced all the way down to:

(room.internal_area.to_f/20).round

Amazing!  Thank you so much!  This works perfectly.

 

Now the next step will be taking that result and multiplying it by .2 to get inches required for openable door clearance code requirement.  Any thoughts?  It would be an if / then scenario.

Ultimate goal would be to get the second number in this graph to display required door opening clearance.  Minimum is 32" but if it exceeds 32" then I would want it to show the actual required amount.

Then I'll need a macro that will count width of doors provided (if labeled "egress') in the room

 

The end goal would be to just have these in the library that I could paste into the room depending on the room type.  But I'd love to take it a step further and only need one object that could be place in any room and pick up the room type and change the calculation as needed based on the room type definition.  (see my post below in response to Rabbit)

image.png.303ab75b328fa556028cb4cb1acbab84.png

Link to comment
Share on other sites

34 minutes ago, Renerabbitt said:

first off, mike is the man, love it when I get to read through his approach on anything macros...I believe he may still do ruby training so hit him up :)
I would add in some variables in the beginning in case you ever expand your method and maybe some conditions.
 



# Copyright Rabbitt Design 2024
##########################################################################################
# Rabbitt Design assumes no liability for the accuracy of the occupancy calculations or 
# any consequences arising from the use of this script. Users are responsible for verifying 
# the appropriateness of the occupancy loads and ensuring the script functions as intended 
# in their specific use case.
##########################################################################################

#Use by putting a statement in your text box/polyline label/room_label
#%$occupancy="Educational"%
#Occupant Load:%occupancy_load%

##########################################################################################
# Occupancy Load Constants
# Note: Load values are in square feet per person
OCCUPANCY_LOADS = {
  assembly: 15,    # Areas for public gatherings (e.g., auditoriums, dining areas)
  business: 100,   # Typical office spaces
  educational: 20, # Classrooms and educational facilities
  factory: 50,     # Industrial and manufacturing spaces
  high_hazard: 500,# High hazard areas with minimal occupancy
  institutional: 240, # Hospitals, care facilities
  mercantile: 30,  # Retail and sales floors
  residential: 200,# Living areas in residential settings
  storage: 300,    # Storage areas with limited occupancy
  utility: 500     # Miscellaneous and utility buildings
}

# Calculate Occupancy based on predefined occupancy type and defined area
def calculate_occupancy(room_area)
  # Normalize occupancy type
  load_factor = OCCUPANCY_LOADS[$occupancy.downcase.to_sym] rescue nil
  if load_factor.nil?
    raise "Occupancy type '#{$occupancy}' is not defined or incorrect."
  end

  # Calculate occupancy
  occupancy = (room_area.to_f / load_factor).round
  occupancy
end

# Conditionally determine the room_area based on whether 'room' is defined
room_area = if defined?(room)
              room.internal_area
            elsif defined?(internal_area)
              internal_area
            else
              area  # Fallback to just 'area' if the other two are not available
            end

# Call the function with room_area, assuming $occupancy is defined elsewhere
final_occupancy = calculate_occupancy(room_area)
final_occupancy  # This line implicitly outputs the result

You could use this in your room label or in a text box or in a polyline label

In either you could need:

%$occupancy="Educational"%

Occupant Load:%occupancy_load%


 

For instance. this will set the appropriate variable call
image.png.14f31ea5506cb456c1264888aa80e114.png

Wow man, this was my next thought on how I could use "Room Type" and define them in a commercial template as such.  Then if the "Room Type" was "Business", "Assembly", "Educational", etc.  It would automatically update the label and update the occupancy calculation.  Super powerful tool and kicking myself for nothing thinking of this stuff sooner.

Link to comment
Share on other sites

7 minutes ago, amddrafting said:

Wow man, this was my next thought on how I could use "Room Type" and define them in a commercial template as such.  Then if the "Room Type" was "Business", "Assembly", "Educational", etc.  It would automatically update the label and update the occupancy calculation.  Super powerful tool and kicking myself for nothing thinking of this stuff sooner.

you could take it even further and make it dependent on a suffix in your file name or change by zip code or many other approaches.
ChatGPT will take you so far but also more complex macros chatgpt butchers..still recommend training with Mike :)

Link to comment
Share on other sites

  • 2 months later...
On 4/19/2024 at 1:57 PM, Renerabbitt said:

first off, mike is the man, love it when I get to read through his approach on anything macros...I believe he may still do ruby training so hit him up :)
I would add in some variables in the beginning in case you ever expand your method and maybe some conditions.
 



# Copyright Rabbitt Design 2024
##########################################################################################
# Rabbitt Design assumes no liability for the accuracy of the occupancy calculations or 
# any consequences arising from the use of this script. Users are responsible for verifying 
# the appropriateness of the occupancy loads and ensuring the script functions as intended 
# in their specific use case.
##########################################################################################

#Use by putting a statement in your text box/polyline label/room_label
#%$occupancy="Educational"%
#Occupant Load:%occupancy_load%

##########################################################################################
# Occupancy Load Constants
# Note: Load values are in square feet per person
OCCUPANCY_LOADS = {
  assembly: 15,    # Areas for public gatherings (e.g., auditoriums, dining areas)
  business: 100,   # Typical office spaces
  educational: 20, # Classrooms and educational facilities
  factory: 50,     # Industrial and manufacturing spaces
  high_hazard: 500,# High hazard areas with minimal occupancy
  institutional: 240, # Hospitals, care facilities
  mercantile: 30,  # Retail and sales floors
  residential: 200,# Living areas in residential settings
  storage: 300,    # Storage areas with limited occupancy
  utility: 500     # Miscellaneous and utility buildings
}

# Calculate Occupancy based on predefined occupancy type and defined area
def calculate_occupancy(room_area)
  # Normalize occupancy type
  load_factor = OCCUPANCY_LOADS[$occupancy.downcase.to_sym] rescue nil
  if load_factor.nil?
    raise "Occupancy type '#{$occupancy}' is not defined or incorrect."
  end

  # Calculate occupancy
  occupancy = (room_area.to_f / load_factor).round
  occupancy
end

# Conditionally determine the room_area based on whether 'room' is defined
room_area = if defined?(room)
              room.internal_area
            elsif defined?(internal_area)
              internal_area
            else
              area  # Fallback to just 'area' if the other two are not available
            end

# Call the function with room_area, assuming $occupancy is defined elsewhere
final_occupancy = calculate_occupancy(room_area)
final_occupancy  # This line implicitly outputs the result

You could use this in your room label or in a text box or in a polyline label

In either you could need:

%$occupancy="Educational"%

Occupant Load:%occupancy_load%


 

For instance. this will set the appropriate variable call
image.png.14f31ea5506cb456c1264888aa80e114.png

:o

Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share