WIP: Cleans up ManualDClient and adds some more document strings.
Some checks failed
CI / Linux Tests (push) Failing after 7m3s
Some checks failed
CI / Linux Tests (push) Failing after 7m3s
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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<Tag.CFM, Int>
|
||||
public typealias DesignFrictionRate = Tagged<Tag.DesignFrictionRate, Double>
|
||||
public typealias Height = Tagged<Tag.Height, Int>
|
||||
public typealias RoundSize = Tagged<Tag.Round, Int>
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<Tag.CFM, Int>
|
||||
public typealias DesignFrictionRate = Tagged<Tag.DesignFrictionRate, Double>
|
||||
public typealias Height = Tagged<Tag.Height, Int>
|
||||
public typealias RoundSize = Tagged<Tag.Round, Int>
|
||||
public typealias Width = Tagged<Tag.Width, Int>
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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?
|
||||
) {
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ struct TrunkSizeForm: HTML, Sendable {
|
||||
"Height",
|
||||
.type(.text),
|
||||
.name("height"),
|
||||
.value(trunk?.height?.rawValue),
|
||||
.value(trunk?.height),
|
||||
.placeholder("8 (Optional)"),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ extension ManualDClient {
|
||||
.init(
|
||||
externalStaticPressure: staticPressure,
|
||||
componentPressureLosses: componentLosses,
|
||||
totalEffectiveLength: Int(totalEquivalentLength)
|
||||
totalEquivalentLength: Int(totalEquivalentLength)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user