import Foundation import ManualDCore extension Room { var heatingLoadPerRegister: Double { heatingLoad / Double(registerCount) } func coolingSensiblePerRegister(projectSHR: Double) -> Double { let sensible = coolingSensible ?? (coolingTotal * projectSHR) return sensible / Double(registerCount) } } extension TrunkSize.RoomProxy { // We need to make sure if registers got removed after a trunk // was already made / saved that we do not include registers that // no longer exist. private var actualRegisterCount: Int { guard registers.count <= room.registerCount else { return room.registerCount } return registers.count } var totalHeatingLoad: Double { room.heatingLoadPerRegister * Double(actualRegisterCount) } func totalCoolingSensible(projectSHR: Double) -> Double { room.coolingSensiblePerRegister(projectSHR: projectSHR) * Double(actualRegisterCount) } } extension TrunkSize { var totalHeatingLoad: Double { rooms.reduce(into: 0) { $0 += $1.totalHeatingLoad } } func totalCoolingSensible(projectSHR: Double) -> Double { rooms.reduce(into: 0) { $0 += $1.totalCoolingSensible(projectSHR: projectSHR) } } } extension Array where Element == EffectiveLengthGroup { var totalEffectiveLength: Int { reduce(0) { $0 + $1.effectiveLength } } } func roundSize(_ size: Double) throws -> Int { guard size > 0 else { throw ManualDError(message: "Size should be greater than 0.") } guard size <= 24 else { throw ManualDError(message: "Size should be less than 24.") } // let size = size.rounded(.toNearestOrEven) switch size { case 0..<4: return 4 case 4..<5: return 5 case 5..<6: return 6 case 6..<7: return 7 case 7..<8: return 8 case 8..<9: return 9 case 9..<10: return 10 case 10..<12: return 12 case 12..<14: return 14 case 14..<16: return 16 case 16..<18: return 18 case 18..<20: return 20 case 20..<22: return 2 case 22..<24: return 24 default: throw ManualDError(message: "Size '\(size)' not in range.") } } func velocity(cfm: CFM, roundSize: Int) -> Int { let cfm = Double(cfm.rawValue) let roundSize = Double(roundSize) let velocity = cfm / (pow(roundSize / 24, 2) * 3.14) return Int(round(velocity)) } func flexSize(_ cfm: CFM, _ frictionRate: DesignFrictionRate) throws -> Int { let cfm = pow(Double(cfm.rawValue), 0.4) let fr = pow(frictionRate.rawValue / 1.76, 0.2) let size = 0.55 * (cfm / fr) return try roundSize(size) }