feat: Adds equivalent rectangular duct conversion.
This commit is contained in:
@@ -29,7 +29,10 @@ let package = Package(
|
|||||||
),
|
),
|
||||||
.testTarget(
|
.testTarget(
|
||||||
name: "ManualDClientTests",
|
name: "ManualDClientTests",
|
||||||
dependencies: ["ManualDClient"]
|
dependencies: [
|
||||||
|
"ManualDClient",
|
||||||
|
.product(name: "DependenciesTestSupport", package: "swift-dependencies"),
|
||||||
|
]
|
||||||
),
|
),
|
||||||
.testTarget(
|
.testTarget(
|
||||||
name: "swift-manual-dTests",
|
name: "swift-manual-dTests",
|
||||||
|
|||||||
@@ -4,3 +4,9 @@ import ManualDCore
|
|||||||
extension ComponentPressureLosses {
|
extension ComponentPressureLosses {
|
||||||
var totalLosses: Double { values.reduce(0) { $0 + $1 } }
|
var totalLosses: Double { values.reduce(0) { $0 + $1 } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension Array where Element == EffectiveLengthGroup {
|
||||||
|
var totalEffectiveLength: Int {
|
||||||
|
reduce(0) { $0 + $1.effectiveLength }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import Dependencies
|
import Dependencies
|
||||||
|
import Foundation
|
||||||
import ManualDCore
|
import ManualDCore
|
||||||
|
|
||||||
extension ManualDClient: DependencyKey {
|
extension ManualDClient: DependencyKey {
|
||||||
@@ -13,6 +14,31 @@ extension ManualDClient: DependencyKey {
|
|||||||
let availableStaticPressure = request.externalStaticPressure - totalComponentLosses
|
let availableStaticPressure = request.externalStaticPressure - totalComponentLosses
|
||||||
let frictionRate = availableStaticPressure * 100.0 / Double(request.totalEffectiveLength)
|
let frictionRate = availableStaticPressure * 100.0 / Double(request.totalEffectiveLength)
|
||||||
return .init(availableStaticPressure: availableStaticPressure, frictionRate: frictionRate)
|
return .init(availableStaticPressure: availableStaticPressure, frictionRate: frictionRate)
|
||||||
|
},
|
||||||
|
totalEffectiveLength: { request in
|
||||||
|
let trunkLengths = request.trunkLengths.reduce(0) { $0 + $1 }
|
||||||
|
let runoutLengths = request.runoutLengths.reduce(0) { $0 + $1 }
|
||||||
|
let groupLengths = request.effectiveLengthGroups.totalEffectiveLength
|
||||||
|
return trunkLengths + runoutLengths + groupLengths
|
||||||
|
},
|
||||||
|
equivalentRectangularDuct: { request in
|
||||||
|
let width = (Double.pi * (pow(Double(request.roundSize) / 2.0, 2.0))) / Double(request.height)
|
||||||
|
guard let widthStr = numberFormatter.string(for: width),
|
||||||
|
let widthInt = Int(widthStr)
|
||||||
|
else {
|
||||||
|
throw ManualDError(
|
||||||
|
message: "Failed to convert to to rectangular duct size, width: \(width)"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return .init(height: request.height, width: widthInt)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private let numberFormatter: NumberFormatter = {
|
||||||
|
let formatter = NumberFormatter()
|
||||||
|
formatter.maximumFractionDigits = 0
|
||||||
|
formatter.minimumFractionDigits = 0
|
||||||
|
formatter.roundingMode = .ceiling
|
||||||
|
return formatter
|
||||||
|
}()
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ import ManualDCore
|
|||||||
@DependencyClient
|
@DependencyClient
|
||||||
public struct ManualDClient: Sendable {
|
public struct ManualDClient: Sendable {
|
||||||
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 equivalentRectangularDuct:
|
||||||
|
@Sendable (EquivalentRectangularDuctRequest) async throws -> EquivalentRectangularDuctResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ManualDClient: TestDependencyKey {
|
extension ManualDClient: TestDependencyKey {
|
||||||
@@ -48,3 +51,46 @@ extension ManualDClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: Total Effective Length
|
||||||
|
extension ManualDClient {
|
||||||
|
public struct TotalEffectiveLengthRequest: Codable, Equatable, Sendable {
|
||||||
|
|
||||||
|
public let trunkLengths: [Int]
|
||||||
|
public let runoutLengths: [Int]
|
||||||
|
public let effectiveLengthGroups: [EffectiveLengthGroup]
|
||||||
|
|
||||||
|
public init(
|
||||||
|
trunkLengths: [Int],
|
||||||
|
runoutLengths: [Int],
|
||||||
|
effectiveLengthGroups: [EffectiveLengthGroup]
|
||||||
|
) {
|
||||||
|
self.trunkLengths = trunkLengths
|
||||||
|
self.runoutLengths = runoutLengths
|
||||||
|
self.effectiveLengthGroups = effectiveLengthGroups
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Equivalent Rectangular Duct
|
||||||
|
extension ManualDClient {
|
||||||
|
public struct EquivalentRectangularDuctRequest: Codable, Equatable, Sendable {
|
||||||
|
public let roundSize: Int
|
||||||
|
public let height: Int
|
||||||
|
|
||||||
|
public init(round roundSize: Int, height: Int) {
|
||||||
|
self.roundSize = roundSize
|
||||||
|
self.height = height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct EquivalentRectangularDuctResponse: Codable, Equatable, Sendable {
|
||||||
|
public let height: Int
|
||||||
|
public let width: Int
|
||||||
|
|
||||||
|
public init(height: Int, width: Int) {
|
||||||
|
self.height = height
|
||||||
|
self.width = width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
import Dependencies
|
import Dependencies
|
||||||
|
import DependenciesTestSupport
|
||||||
import Foundation
|
import Foundation
|
||||||
import ManualDClient
|
import ManualDClient
|
||||||
import ManualDCore
|
import ManualDCore
|
||||||
import Testing
|
import Testing
|
||||||
|
|
||||||
@Suite("ManualDClient Tests")
|
@Suite(
|
||||||
|
.dependencies {
|
||||||
|
$0.manualD = ManualDClient.liveValue
|
||||||
|
}
|
||||||
|
)
|
||||||
struct ManualDClientTests {
|
struct ManualDClientTests {
|
||||||
|
|
||||||
|
@Dependency(\.manualD) var manualD
|
||||||
|
|
||||||
var numberFormatter: NumberFormatter {
|
var numberFormatter: NumberFormatter {
|
||||||
let formatter = NumberFormatter()
|
let formatter = NumberFormatter()
|
||||||
formatter.minimumFractionDigits = 2
|
formatter.minimumFractionDigits = 2
|
||||||
@@ -17,7 +24,6 @@ struct ManualDClientTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
func frictionRate() async throws {
|
func frictionRate() async throws {
|
||||||
let manualD = ManualDClient.liveValue
|
|
||||||
let response = try await manualD.frictionRate(
|
let response = try await manualD.frictionRate(
|
||||||
.init(
|
.init(
|
||||||
externalStaticPressure: 0.5,
|
externalStaticPressure: 0.5,
|
||||||
@@ -32,7 +38,6 @@ struct ManualDClientTests {
|
|||||||
@Test
|
@Test
|
||||||
func frictionRateFails() async throws {
|
func frictionRateFails() async throws {
|
||||||
await #expect(throws: ManualDError.self) {
|
await #expect(throws: ManualDError.self) {
|
||||||
let manualD = ManualDClient.liveValue
|
|
||||||
_ = try await manualD.frictionRate(
|
_ = try await manualD.frictionRate(
|
||||||
.init(
|
.init(
|
||||||
externalStaticPressure: 0.5,
|
externalStaticPressure: 0.5,
|
||||||
@@ -42,4 +47,29 @@ struct ManualDClientTests {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
func totalEffectiveLength() async throws {
|
||||||
|
let response = try await manualD.totalEffectiveLength(
|
||||||
|
.init(
|
||||||
|
trunkLengths: [25],
|
||||||
|
runoutLengths: [10],
|
||||||
|
effectiveLengthGroups: [
|
||||||
|
// NOTE: These are made up and may not correspond to actual manual-d group tel's.
|
||||||
|
EffectiveLengthGroup(group: 1, letter: "a", effectiveLength: 20, category: .supply),
|
||||||
|
EffectiveLengthGroup(group: 2, letter: "a", effectiveLength: 30, category: .supply),
|
||||||
|
EffectiveLengthGroup(group: 3, letter: "a", effectiveLength: 10, category: .supply),
|
||||||
|
EffectiveLengthGroup(group: 12, letter: "a", effectiveLength: 10, category: .supply),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
#expect(response == 105)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
func equivalentRectangularDuct() async throws {
|
||||||
|
let response = try await manualD.equivalentRectangularDuct(.init(round: 7, height: 8))
|
||||||
|
#expect(response.height == 8)
|
||||||
|
#expect(response.width == 5)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user