feat: Adds duct sizing calculations.
This commit is contained in:
@@ -10,3 +10,60 @@ extension Array where Element == EffectiveLengthGroup {
|
|||||||
reduce(0) { $0 + $1.effectiveLength }
|
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.")
|
||||||
|
}
|
||||||
|
|
||||||
|
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: Int, roundSize: Int) -> Int {
|
||||||
|
let cfm = Double(cfm)
|
||||||
|
let roundSize = Double(roundSize)
|
||||||
|
let velocity = cfm / (pow(roundSize / 24, 2) * 3.14)
|
||||||
|
return Int(round(velocity))
|
||||||
|
}
|
||||||
|
|
||||||
|
func flexSize(_ request: ManualDClient.DuctSizeRequest) throws -> Int {
|
||||||
|
let cfm = pow(Double(request.designCFM), 0.4)
|
||||||
|
let fr = pow(request.frictionRate / 1.76, 0.2)
|
||||||
|
let size = 0.55 * (cfm / fr)
|
||||||
|
return try roundSize(size)
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,21 @@ import ManualDCore
|
|||||||
|
|
||||||
extension ManualDClient: DependencyKey {
|
extension ManualDClient: DependencyKey {
|
||||||
public static let liveValue: Self = .init(
|
public static let liveValue: Self = .init(
|
||||||
|
ductSize: { request in
|
||||||
|
guard request.designCFM > 0 else {
|
||||||
|
throw ManualDError(message: "Design CFM should be greater than 0.")
|
||||||
|
}
|
||||||
|
let fr = pow(request.frictionRate, 0.5)
|
||||||
|
let ductulatorSize = pow(Double(request.designCFM) / (3.12 * fr), 0.38)
|
||||||
|
let finalSize = try roundSize(ductulatorSize)
|
||||||
|
let flexSize = try flexSize(request)
|
||||||
|
return .init(
|
||||||
|
ductulatorSize: ductulatorSize,
|
||||||
|
finalSize: finalSize,
|
||||||
|
flexSize: flexSize,
|
||||||
|
velocity: velocity(cfm: request.designCFM, roundSize: finalSize)
|
||||||
|
)
|
||||||
|
},
|
||||||
frictionRate: { request in
|
frictionRate: { request in
|
||||||
// Ensure the total effective length is greater than 0.
|
// Ensure the total effective length is greater than 0.
|
||||||
guard request.totalEffectiveLength > 0 else {
|
guard request.totalEffectiveLength > 0 else {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import ManualDCore
|
|||||||
|
|
||||||
@DependencyClient
|
@DependencyClient
|
||||||
public struct ManualDClient: Sendable {
|
public struct ManualDClient: Sendable {
|
||||||
|
public var ductSize: @Sendable (DuctSizeRequest) async throws -> DuctSizeResponse
|
||||||
public var frictionRate: @Sendable (FrictionRateRequest) async throws -> FrictionRateResponse
|
public var frictionRate: @Sendable (FrictionRateRequest) async throws -> FrictionRateResponse
|
||||||
public var totalEffectiveLength: @Sendable (TotalEffectiveLengthRequest) async throws -> Int
|
public var totalEffectiveLength: @Sendable (TotalEffectiveLengthRequest) async throws -> Int
|
||||||
public var equivalentRectangularDuct:
|
public var equivalentRectangularDuct:
|
||||||
@@ -21,6 +22,42 @@ extension DependencyValues {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: Duct Size
|
||||||
|
extension ManualDClient {
|
||||||
|
public struct DuctSizeRequest: Codable, Equatable, Sendable {
|
||||||
|
public let designCFM: Int
|
||||||
|
public let frictionRate: Double
|
||||||
|
|
||||||
|
public init(
|
||||||
|
designCFM: Int,
|
||||||
|
frictionRate: Double
|
||||||
|
) {
|
||||||
|
self.designCFM = designCFM
|
||||||
|
self.frictionRate = frictionRate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct DuctSizeResponse: Codable, Equatable, Sendable {
|
||||||
|
|
||||||
|
public let ductulatorSize: Double
|
||||||
|
public let finalSize: Int
|
||||||
|
public let flexSize: Int
|
||||||
|
public let velocity: Int
|
||||||
|
|
||||||
|
public init(
|
||||||
|
ductulatorSize: Double,
|
||||||
|
finalSize: Int,
|
||||||
|
flexSize: Int,
|
||||||
|
velocity: Int
|
||||||
|
) {
|
||||||
|
self.ductulatorSize = ductulatorSize
|
||||||
|
self.finalSize = finalSize
|
||||||
|
self.flexSize = flexSize
|
||||||
|
self.velocity = velocity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Friction Rate
|
// MARK: - Friction Rate
|
||||||
extension ManualDClient {
|
extension ManualDClient {
|
||||||
public struct FrictionRateRequest: Codable, Equatable, Sendable {
|
public struct FrictionRateRequest: Codable, Equatable, Sendable {
|
||||||
|
|||||||
@@ -22,6 +22,17 @@ struct ManualDClientTests {
|
|||||||
return formatter
|
return formatter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
func ductSize() async throws {
|
||||||
|
let response = try await manualD.ductSize(
|
||||||
|
.init(designCFM: 88, frictionRate: 0.06)
|
||||||
|
)
|
||||||
|
#expect(numberFormatter.string(for: response.ductulatorSize) == "6.07")
|
||||||
|
#expect(response.finalSize == 7)
|
||||||
|
#expect(response.flexSize == 7)
|
||||||
|
#expect(response.velocity == 329)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
func frictionRate() async throws {
|
func frictionRate() async throws {
|
||||||
let response = try await manualD.frictionRate(
|
let response = try await manualD.frictionRate(
|
||||||
|
|||||||
Reference in New Issue
Block a user