WIP: Adds more tagged types for rectangular size calculations.

This commit is contained in:
2026-01-29 20:50:33 -05:00
parent 9379774fae
commit 9b618d55fa
9 changed files with 75 additions and 39 deletions

View File

@@ -103,7 +103,7 @@ extension TrunkSize.Create {
.init(
projectID: projectID,
type: type,
height: height,
height: height?.rawValue,
name: name
)
}
@@ -270,7 +270,7 @@ final class TrunkModel: Model, @unchecked Sendable {
projectID: $project.id,
type: .init(rawValue: type)!,
rooms: rooms,
height: height,
height: height.map { .init(rawValue: $0) },
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, height != self.height {
if let height = updates.height?.rawValue, height != self.height {
self.height = height
}
if let name = updates.name, name != self.name {

View File

@@ -18,8 +18,7 @@ extension DependencyValues {
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 (RectangularSizeRequest) async throws -> RectangularSizeResponse
public var rectangularSize: @Sendable (RoundSize, Height) async throws -> RectangularSizeResponse
public func ductSize(
cfm designCFM: Int,
@@ -34,6 +33,21 @@ public struct ManualDClient: Sendable {
) async throws -> DuctSizeResponse {
try await ductSize(.init(rawValue: Int(designCFM)), .init(rawValue: designFrictionRate))
}
public func rectangularSize(
round roundSize: RoundSize,
height: Height
) async throws -> RectangularSizeResponse {
try await rectangularSize(roundSize, height)
}
public func rectangularSize(
round roundSize: Int,
height: Int
) async throws -> RectangularSizeResponse {
try await rectangularSize(.init(rawValue: roundSize), .init(rawValue: height))
}
}
extension ManualDClient: TestDependencyKey {
@@ -90,23 +104,31 @@ extension ManualDClient {
}
}
public struct RectangularSizeRequest: 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 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: Int
public let width: Int
public let height: Height
public let width: Width
public init(height: Int, width: Int) {
public init(height: Height, width: Width) {
self.height = height
self.width = width
}
public init(height: Int, width: Int) {
self.init(height: .init(rawValue: height), width: .init(rawValue: width))
}
}
}

View File

@@ -39,9 +39,12 @@ extension ManualDClient: DependencyKey {
// let groupLengths = request.effectiveLengthGroups.totalEffectiveLength
// return trunkLengths + runoutLengths + groupLengths
// },
rectangularSize: { request in
let width = (Double.pi * (pow(Double(request.roundSize) / 2.0, 2.0))) / Double(request.height)
return .init(height: request.height, width: Int(width.rounded(.toNearestOrEven)))
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)))
)
}
)
}

View File

@@ -1,7 +1,16 @@
import Tagged
public enum CFMTag {}
public typealias CFM = Tagged<CFMTag, Int>
/// 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 enum DesignFrictionRateTag {}
public typealias DesignFrictionRate = Tagged<DesignFrictionRateTag, Double>
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>

View File

@@ -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: Int?
public let height: Height?
/// 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: Int? = nil,
height: Height? = 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: Int?
public let height: Height?
/// 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: Int? = nil,
height: Height? = 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: Int?
public let height: Height?
/// An optional name / label used for identifying the trunk.
public let name: String?
public init(
type: TrunkType? = nil,
rooms: [Room.ID: [Int]]? = nil,
height: Int? = nil,
height: Height? = nil,
name: String? = nil
) {
self.type = type

View File

@@ -64,9 +64,10 @@ extension ManualDClient {
if let rectangularSize {
let response = try await self.rectangularSize(
.init(round: sizes.finalSize, height: rectangularSize.height)
round: sizes.finalSize,
height: rectangularSize.height
)
rectangularWidth = response.width
rectangularWidth = response.width.rawValue
}
retval.append(
@@ -118,9 +119,10 @@ extension ManualDClient {
var width: Int? = nil
if let height = trunk.height {
let rectangularSize = try await self.rectangularSize(
.init(round: sizes.finalSize, height: height)
round: .init(rawValue: sizes.finalSize),
height: height
)
width = rectangularSize.width
width = rectangularSize.width.rawValue
}
retval.append(
@@ -129,7 +131,7 @@ extension ManualDClient {
ductSize: .init(
designCFM: designCFM,
sizes: sizes,
height: trunk.height,
height: trunk.height?.rawValue,
width: width
)
)

View File

@@ -9,7 +9,7 @@ extension SiteRoute.View.ProjectRoute.DuctSizingRoute.TrunkSizeForm {
projectID: projectID,
type: type,
rooms: makeRooms(logger: logger),
height: height,
height: height.map { .init(rawValue: $0) },
name: name
)
}
@@ -18,7 +18,7 @@ extension SiteRoute.View.ProjectRoute.DuctSizingRoute.TrunkSizeForm {
try .init(
type: type,
rooms: makeRooms(logger: logger),
height: height,
height: height.map { .init(rawValue: $0) },
name: name
)
}

View File

@@ -67,7 +67,7 @@ struct TrunkSizeForm: HTML, Sendable {
"Height",
.type(.text),
.name("height"),
.value(trunk?.height),
.value(trunk?.height?.rawValue),
.placeholder("8 (Optional)"),
)
}