From 4f3cc2c7ea0d57ea003141047b20b3a268b1723f Mon Sep 17 00:00:00 2001 From: Michael Housh Date: Thu, 29 Jan 2026 22:56:39 -0500 Subject: [PATCH] WIP: Cleans up ManualDClient and adds some more document strings. --- Package.swift | 2 +- .../DatabaseClient/Internal/TrunkSizes.swift | 6 +- Sources/ManualDClient/Helpers.swift | 6 +- Sources/ManualDClient/Interface.swift | 97 ++++++++++--------- Sources/ManualDClient/Live.swift | 12 +-- Sources/ManualDCore/FrictionRate.swift | 4 +- Sources/ManualDCore/TaggedTypes.swift | 16 --- Sources/ManualDCore/TrunkSize.swift | 12 +-- Sources/ProjectClient/Interface.swift | 3 +- .../ManualDClient+calculateDuctSizes.swift | 12 +-- .../Internal/ManualDClient+frictionRate.swift | 4 +- .../Extensions/TrunkSizeForm+extensions.swift | 4 +- .../Views/DuctSizing/TrunkSizeForm.swift | 2 +- .../Views/Project/ProjectView.swift | 2 +- 14 files changed, 86 insertions(+), 96 deletions(-) delete mode 100644 Sources/ManualDCore/TaggedTypes.swift diff --git a/Package.swift b/Package.swift index 3eddbe8..985690c 100644 --- a/Package.swift +++ b/Package.swift @@ -147,7 +147,6 @@ let package = Package( .product(name: "CasePaths", package: "swift-case-paths"), .product(name: "Dependencies", package: "swift-dependencies"), .product(name: "Fluent", package: "fluent"), - .product(name: "Tagged", package: "swift-tagged"), .product(name: "URLRouting", package: "swift-url-routing"), ] ), @@ -157,6 +156,7 @@ let package = Package( .target(name: "ManualDCore"), .product(name: "Dependencies", package: "swift-dependencies"), .product(name: "DependenciesMacros", package: "swift-dependencies"), + .product(name: "Tagged", package: "swift-tagged"), ] ), .target( diff --git a/Sources/DatabaseClient/Internal/TrunkSizes.swift b/Sources/DatabaseClient/Internal/TrunkSizes.swift index 1ea7d03..c764d73 100644 --- a/Sources/DatabaseClient/Internal/TrunkSizes.swift +++ b/Sources/DatabaseClient/Internal/TrunkSizes.swift @@ -103,7 +103,7 @@ extension TrunkSize.Create { .init( projectID: projectID, type: type, - height: height?.rawValue, + height: height, name: name ) } @@ -270,7 +270,7 @@ final class TrunkModel: Model, @unchecked Sendable { projectID: $project.id, type: .init(rawValue: type)!, rooms: rooms, - height: height.map { .init(rawValue: $0) }, + height: height, name: name ) @@ -283,7 +283,7 @@ final class TrunkModel: Model, @unchecked Sendable { if let type = updates.type, type.rawValue != self.type { self.type = type.rawValue } - if let height = updates.height?.rawValue, height != self.height { + if let height = updates.height, height != self.height { self.height = height } if let name = updates.name, name != self.name { diff --git a/Sources/ManualDClient/Helpers.swift b/Sources/ManualDClient/Helpers.swift index 79d45bd..88b8292 100644 --- a/Sources/ManualDClient/Helpers.swift +++ b/Sources/ManualDClient/Helpers.swift @@ -97,16 +97,16 @@ func roundSize(_ size: Double) throws -> Int { } } -func velocity(cfm: CFM, roundSize: Int) -> Int { +func velocity(cfm: ManualDClient.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 { +func flexSize(_ cfm: ManualDClient.CFM, _ frictionRate: Double) throws -> Int { let cfm = pow(Double(cfm.rawValue), 0.4) - let fr = pow(frictionRate.rawValue / 1.76, 0.2) + let fr = pow(frictionRate / 1.76, 0.2) let size = 0.55 * (cfm / fr) return try roundSize(size) } diff --git a/Sources/ManualDClient/Interface.swift b/Sources/ManualDClient/Interface.swift index 370dc80..a071463 100644 --- a/Sources/ManualDClient/Interface.swift +++ b/Sources/ManualDClient/Interface.swift @@ -2,6 +2,7 @@ import Dependencies import DependenciesMacros import Logging import ManualDCore +import Tagged extension DependencyValues { /// Dependency that performs manual-d duct sizing calculations. @@ -16,38 +17,61 @@ extension DependencyValues { /// @DependencyClient public struct ManualDClient: Sendable { - public var ductSize: @Sendable (CFM, DesignFrictionRate) async throws -> DuctSizeResponse - public var frictionRate: @Sendable (FrictionRateRequest) async throws -> FrictionRate - public var rectangularSize: @Sendable (RoundSize, Height) async throws -> RectangularSizeResponse + /// Calculates the duct size for the given cfm and friction rate. + public var ductSize: @Sendable (CFM, DesignFrictionRate) async throws -> DuctSize + /// Calculates the design friction rate for the given request. + public var frictionRate: @Sendable (FrictionRateRequest) async throws -> FrictionRate + /// Calculates the equivalent rectangular size for the given round duct and rectangular height. + public var rectangularSize: @Sendable (RoundSize, Height) async throws -> RectangularSize + + /// Calculates the duct size for the given cfm and friction rate. + /// + /// - Paramaters: + /// - designCFM: The design cfm for the duct. + /// - designFrictionRate: The design friction rate for the system. public func ductSize( cfm designCFM: Int, frictionRate designFrictionRate: Double - ) async throws -> DuctSizeResponse { + ) async throws -> DuctSize { try await ductSize(.init(rawValue: designCFM), .init(rawValue: designFrictionRate)) } + /// Calculates the duct size for the given cfm and friction rate. + /// + /// - Paramaters: + /// - designCFM: The design cfm for the duct. + /// - designFrictionRate: The design friction rate for the system. public func ductSize( cfm designCFM: Double, frictionRate designFrictionRate: Double - ) async throws -> DuctSizeResponse { + ) async throws -> DuctSize { try await ductSize(.init(rawValue: Int(designCFM)), .init(rawValue: designFrictionRate)) } + /// Calculates the equivalent rectangular size for the given round duct and rectangular height. + /// + /// - Paramaters: + /// - roundSize: The round duct size. + /// - height: The rectangular height of the duct. public func rectangularSize( round roundSize: RoundSize, height: Height - ) async throws -> RectangularSizeResponse { + ) async throws -> RectangularSize { try await rectangularSize(roundSize, height) } + /// Calculates the equivalent rectangular size for the given round duct and rectangular height. + /// + /// - Paramaters: + /// - roundSize: The round duct size. + /// - height: The rectangular height of the duct. public func rectangularSize( round roundSize: Int, height: Int - ) async throws -> RectangularSizeResponse { + ) async throws -> RectangularSize { try await rectangularSize(.init(rawValue: roundSize), .init(rawValue: height)) } - } extension ManualDClient: TestDependencyKey { @@ -55,8 +79,20 @@ extension ManualDClient: TestDependencyKey { } extension ManualDClient { + /// A name space for tags used by the ManualDClient. + public enum Tag { + public enum CFM {} + public enum DesignFrictionRate {} + public enum Height {} + public enum Round {} + } - public struct DuctSizeResponse: Codable, Equatable, Sendable { + public typealias CFM = Tagged + public typealias DesignFrictionRate = Tagged + public typealias Height = Tagged + public typealias RoundSize = Tagged + + public struct DuctSize: Codable, Equatable, Sendable { public let calculatedSize: Double public let finalSize: Int @@ -80,55 +116,26 @@ extension ManualDClient { public let externalStaticPressure: Double public let componentPressureLosses: [ComponentPressureLoss] - public let totalEffectiveLength: Int + public let totalEquivalentLength: Int public init( externalStaticPressure: Double, componentPressureLosses: [ComponentPressureLoss], - totalEffectiveLength: Int + totalEquivalentLength: Int ) { self.externalStaticPressure = externalStaticPressure self.componentPressureLosses = componentPressureLosses - self.totalEffectiveLength = totalEffectiveLength + self.totalEquivalentLength = totalEquivalentLength } } - public struct FrictionRateResponse: Codable, Equatable, Sendable { + public struct RectangularSize: Codable, Equatable, Sendable { + public let height: Int + public let width: Int - public let availableStaticPressure: Double - public let frictionRate: DesignFrictionRate - - public init(availableStaticPressure: Double, frictionRate: DesignFrictionRate) { - self.availableStaticPressure = availableStaticPressure - self.frictionRate = frictionRate - } - } - - // public struct RectangularSizeRequest: Codable, Equatable, Sendable { - // public let roundSize: RoundSize - // public let height: Height - // - // public init(round roundSize: RoundSize, height: Height) { - // self.roundSize = roundSize - // self.height = height - // } - // - // public init(round roundSize: Int, height: Int) { - // self.init(round: .init(rawValue: roundSize), height: .init(rawValue: height)) - // } - // } - - public struct RectangularSizeResponse: Codable, Equatable, Sendable { - public let height: Height - public let width: Width - - public init(height: Height, width: Width) { + public init(height: Int, width: Int) { self.height = height self.width = width } - - public init(height: Int, width: Int) { - self.init(height: .init(rawValue: height), width: .init(rawValue: width)) - } } } diff --git a/Sources/ManualDClient/Live.swift b/Sources/ManualDClient/Live.swift index 56f2eaa..6783518 100644 --- a/Sources/ManualDClient/Live.swift +++ b/Sources/ManualDClient/Live.swift @@ -11,7 +11,7 @@ extension ManualDClient: DependencyKey { let fr = pow(frictionRate.rawValue, 0.5) let ductulatorSize = pow(Double(cfm.rawValue) / (3.12 * fr), 0.38) let finalSize = try roundSize(ductulatorSize) - let flexSize = try flexSize(cfm, frictionRate) + let flexSize = try flexSize(cfm, frictionRate.rawValue) return .init( calculatedSize: ductulatorSize, finalSize: finalSize, @@ -21,16 +21,16 @@ extension ManualDClient: DependencyKey { }, frictionRate: { request in // Ensure the total effective length is greater than 0. - guard request.totalEffectiveLength > 0 else { + guard request.totalEquivalentLength > 0 else { throw ManualDError(message: "Total Effective Length should be greater than 0.") } let totalComponentLosses = request.componentPressureLosses.total let availableStaticPressure = request.externalStaticPressure - totalComponentLosses - let frictionRate = availableStaticPressure * 100.0 / Double(request.totalEffectiveLength) + let frictionRate = availableStaticPressure * 100.0 / Double(request.totalEquivalentLength) return .init( availableStaticPressure: availableStaticPressure, - value: .init(rawValue: frictionRate) + value: frictionRate ) }, // totalEquivalentLength: { request in @@ -42,8 +42,8 @@ extension ManualDClient: DependencyKey { rectangularSize: { round, height in let width = (Double.pi * (pow(Double(round.rawValue) / 2.0, 2.0))) / Double(height.rawValue) return .init( - height: height, - width: .init(rawValue: Int(width.rounded(.toNearestOrEven))) + height: height.rawValue, + width: Int(width.rounded(.toNearestOrEven)) ) } ) diff --git a/Sources/ManualDCore/FrictionRate.swift b/Sources/ManualDCore/FrictionRate.swift index 79d2acd..5491529 100644 --- a/Sources/ManualDCore/FrictionRate.swift +++ b/Sources/ManualDCore/FrictionRate.swift @@ -7,13 +7,13 @@ public struct FrictionRate: Codable, Equatable, Sendable { /// minus the ``ComponentPressureLoss``es for the project. public let availableStaticPressure: Double /// The calculated design friction rate value. - public let value: DesignFrictionRate + public let value: Double /// Whether the design friction rate is within a valid range. public var hasErrors: Bool { error != nil } public init( availableStaticPressure: Double, - value: DesignFrictionRate + value: Double ) { self.availableStaticPressure = availableStaticPressure self.value = value diff --git a/Sources/ManualDCore/TaggedTypes.swift b/Sources/ManualDCore/TaggedTypes.swift deleted file mode 100644 index 9ae8c07..0000000 --- a/Sources/ManualDCore/TaggedTypes.swift +++ /dev/null @@ -1,16 +0,0 @@ -import Tagged - -/// A name space for general tag types. -public enum Tag { - public enum CFM {} - public enum DesignFrictionRate {} - public enum Height {} - public enum Round {} - public enum Width {} -} - -public typealias CFM = Tagged -public typealias DesignFrictionRate = Tagged -public typealias Height = Tagged -public typealias RoundSize = Tagged -public typealias Width = Tagged diff --git a/Sources/ManualDCore/TrunkSize.swift b/Sources/ManualDCore/TrunkSize.swift index ad0483c..dc16d70 100644 --- a/Sources/ManualDCore/TrunkSize.swift +++ b/Sources/ManualDCore/TrunkSize.swift @@ -16,7 +16,7 @@ public struct TrunkSize: Codable, Equatable, Identifiable, Sendable { public let rooms: [RoomProxy] /// An optional rectangular height used to calculate the equivalent /// rectangular size of the trunk. - public let height: Height? + public let height: Int? /// An optional name / label used for identifying the trunk. public let name: String? @@ -25,7 +25,7 @@ public struct TrunkSize: Codable, Equatable, Identifiable, Sendable { projectID: Project.ID, type: TrunkType, rooms: [RoomProxy], - height: Height? = nil, + height: Int? = nil, name: String? = nil ) { self.id = id @@ -49,7 +49,7 @@ extension TrunkSize { public let rooms: [Room.ID: [Int]] /// An optional rectangular height used to calculate the equivalent /// rectangular size of the trunk. - public let height: Height? + public let height: Int? /// An optional name / label used for identifying the trunk. public let name: String? @@ -57,7 +57,7 @@ extension TrunkSize { projectID: Project.ID, type: TrunkType, rooms: [Room.ID: [Int]], - height: Height? = nil, + height: Int? = nil, name: String? = nil ) { self.projectID = projectID @@ -79,14 +79,14 @@ extension TrunkSize { public let rooms: [Room.ID: [Int]]? /// An optional rectangular height used to calculate the equivalent /// rectangular size of the trunk. - public let height: Height? + public let height: Int? /// An optional name / label used for identifying the trunk. public let name: String? public init( type: TrunkType? = nil, rooms: [Room.ID: [Int]]? = nil, - height: Height? = nil, + height: Int? = nil, name: String? = nil ) { self.type = type diff --git a/Sources/ProjectClient/Interface.swift b/Sources/ProjectClient/Interface.swift index 2fffe2d..41d798b 100644 --- a/Sources/ProjectClient/Interface.swift +++ b/Sources/ProjectClient/Interface.swift @@ -15,7 +15,7 @@ extension DependencyValues { /// Useful helper utilities for project's. /// /// This is primarily used for implementing logic required to get the needed data -/// for the view controller client to render views. +/// for the view controller to render views. @DependencyClient public struct ProjectClient: Sendable { public var calculateDuctSizes: @Sendable (Project.ID) async throws -> DuctSizes @@ -28,7 +28,6 @@ public struct ProjectClient: Sendable { @Sendable (User.ID, Project.Create) async throws -> CreateProjectResponse public var frictionRate: @Sendable (Project.ID) async throws -> FrictionRateResponse - public var generatePdf: @Sendable (Project.ID) async throws -> Response } extension ProjectClient: TestDependencyKey { diff --git a/Sources/ProjectClient/Internal/ManualDClient+calculateDuctSizes.swift b/Sources/ProjectClient/Internal/ManualDClient+calculateDuctSizes.swift index 8a0ae2f..fd63b6d 100644 --- a/Sources/ProjectClient/Internal/ManualDClient+calculateDuctSizes.swift +++ b/Sources/ProjectClient/Internal/ManualDClient+calculateDuctSizes.swift @@ -67,7 +67,7 @@ extension ManualDClient { round: sizes.finalSize, height: rectangularSize.height ) - rectangularWidth = response.width.rawValue + rectangularWidth = response.width } retval.append( @@ -119,10 +119,10 @@ extension ManualDClient { var width: Int? = nil if let height = trunk.height { let rectangularSize = try await self.rectangularSize( - round: .init(rawValue: sizes.finalSize), + round: sizes.finalSize, height: height ) - width = rectangularSize.width.rawValue + width = rectangularSize.width } retval.append( @@ -131,7 +131,7 @@ extension ManualDClient { ductSize: .init( designCFM: designCFM, sizes: sizes, - height: trunk.height?.rawValue, + height: trunk.height, width: width ) ) @@ -146,7 +146,7 @@ extension ManualDClient { extension DuctSizes.SizeContainer { init( designCFM: DuctSizes.DesignCFM, - sizes: ManualDClient.DuctSizeResponse, + sizes: ManualDClient.DuctSize, height: Int?, width: Int? ) { @@ -164,7 +164,7 @@ extension DuctSizes.SizeContainer { init( designCFM: DuctSizes.DesignCFM, - sizes: ManualDClient.DuctSizeResponse, + sizes: ManualDClient.DuctSize, rectangularSize: Room.RectangularSize?, width: Int? ) { diff --git a/Sources/ProjectClient/Internal/ManualDClient+frictionRate.swift b/Sources/ProjectClient/Internal/ManualDClient+frictionRate.swift index fa504b4..6259ebd 100644 --- a/Sources/ProjectClient/Internal/ManualDClient+frictionRate.swift +++ b/Sources/ProjectClient/Internal/ManualDClient+frictionRate.swift @@ -19,7 +19,7 @@ extension ManualDClient { .init( externalStaticPressure: details.equipmentInfo.staticPressure, componentPressureLosses: details.componentLosses, - totalEffectiveLength: Int(totalEquivalentLength) + totalEquivalentLength: Int(totalEquivalentLength) ) ) ) @@ -47,7 +47,7 @@ extension ManualDClient { .init( externalStaticPressure: staticPressure, componentPressureLosses: componentLosses, - totalEffectiveLength: Int(totalEquivalentLength) + totalEquivalentLength: Int(totalEquivalentLength) ) ) ) diff --git a/Sources/ViewController/Extensions/TrunkSizeForm+extensions.swift b/Sources/ViewController/Extensions/TrunkSizeForm+extensions.swift index f18fac1..b1057c2 100644 --- a/Sources/ViewController/Extensions/TrunkSizeForm+extensions.swift +++ b/Sources/ViewController/Extensions/TrunkSizeForm+extensions.swift @@ -9,7 +9,7 @@ extension SiteRoute.View.ProjectRoute.DuctSizingRoute.TrunkSizeForm { projectID: projectID, type: type, rooms: makeRooms(logger: logger), - height: height.map { .init(rawValue: $0) }, + height: height, name: name ) } @@ -18,7 +18,7 @@ extension SiteRoute.View.ProjectRoute.DuctSizingRoute.TrunkSizeForm { try .init( type: type, rooms: makeRooms(logger: logger), - height: height.map { .init(rawValue: $0) }, + height: height, name: name ) } diff --git a/Sources/ViewController/Views/DuctSizing/TrunkSizeForm.swift b/Sources/ViewController/Views/DuctSizing/TrunkSizeForm.swift index fc2a00e..8f281ef 100644 --- a/Sources/ViewController/Views/DuctSizing/TrunkSizeForm.swift +++ b/Sources/ViewController/Views/DuctSizing/TrunkSizeForm.swift @@ -67,7 +67,7 @@ struct TrunkSizeForm: HTML, Sendable { "Height", .type(.text), .name("height"), - .value(trunk?.height?.rawValue), + .value(trunk?.height), .placeholder("8 (Optional)"), ) } diff --git a/Sources/ViewController/Views/Project/ProjectView.swift b/Sources/ViewController/Views/Project/ProjectView.swift index 9a70a4f..eb12e6d 100644 --- a/Sources/ViewController/Views/Project/ProjectView.swift +++ b/Sources/ViewController/Views/Project/ProjectView.swift @@ -245,7 +245,7 @@ extension ManualDClient { .init( externalStaticPressure: staticPressure, componentPressureLosses: componentLosses, - totalEffectiveLength: Int(totalEquivalentLength) + totalEquivalentLength: Int(totalEquivalentLength) ) ) }