From e08d896758a2af5b8bfe245fa1aed61b4fae6d98 Mon Sep 17 00:00:00 2001 From: Michael Housh Date: Mon, 26 Jan 2026 13:39:27 -0500 Subject: [PATCH] feat: Adds better mock support for models to aid in testing / viewing a mock project for the pdf client. --- Package.swift | 1 + Sources/App/configure.swift | 6 - .../ManualDCore/ComponentPressureLosses.swift | 55 +++++++++ Sources/ManualDCore/DuctSizes.swift | 108 ++++++++++++++++++ Sources/ManualDCore/EffectiveLength.swift | 38 ++++++ Sources/ManualDCore/EquipmentInfo.swift | 15 +++ Sources/ManualDCore/FrictionRate.swift | 6 + Sources/ManualDCore/Room.swift | 80 +++++++++++++ Sources/ManualDCore/TrunkSize.swift | 23 +++- Sources/PdfClient/Interface.swift | 24 ++++ Sources/ViewController/Live.swift | 29 +++-- 11 files changed, 366 insertions(+), 19 deletions(-) diff --git a/Package.swift b/Package.swift index 4213637..1daa49f 100644 --- a/Package.swift +++ b/Package.swift @@ -136,6 +136,7 @@ let package = Package( dependencies: [ .target(name: "AuthClient"), .target(name: "DatabaseClient"), + .target(name: "PdfClient"), .target(name: "ProjectClient"), .target(name: "ManualDClient"), .target(name: "ManualDCore"), diff --git a/Sources/App/configure.swift b/Sources/App/configure.swift index c3a99c3..ce48122 100644 --- a/Sources/App/configure.swift +++ b/Sources/App/configure.swift @@ -129,12 +129,6 @@ private func siteHandler( case .health: return HTTPStatus.ok case .view(let route): - // FIX: Remove. - if route == .test { - let projectID = UUID(uuidString: "E796C96C-F527-4753-A00A-EBCF25630663")! - // return try await projectClient.toMarkdown(projectID) - return try await AnyHTMLResponse(value: projectClient.toHTML(projectID)) - } return try await viewController.respond(route: route, request: request) } } diff --git a/Sources/ManualDCore/ComponentPressureLosses.swift b/Sources/ManualDCore/ComponentPressureLosses.swift index f316095..b719e70 100644 --- a/Sources/ManualDCore/ComponentPressureLosses.swift +++ b/Sources/ManualDCore/ComponentPressureLosses.swift @@ -1,3 +1,4 @@ +import Dependencies import Foundation public struct ComponentPressureLoss: Codable, Equatable, Identifiable, Sendable { @@ -89,7 +90,61 @@ public typealias ComponentPressureLosses = [String: Double] } } + extension Array where Element == ComponentPressureLoss { + public static func mock(projectID: Project.ID) -> Self { + ComponentPressureLoss.mock(projectID: projectID) + } + } + extension ComponentPressureLoss { + public static func mock(projectID: Project.ID) -> [Self] { + @Dependency(\.uuid) var uuid + @Dependency(\.date.now) var now + + return [ + .init( + id: uuid(), + projectID: projectID, + name: "evaporator-coil", + value: 0.2, + createdAt: now, + updatedAt: now + ), + .init( + id: uuid(), + projectID: projectID, + name: "filter", + value: 0.1, + createdAt: now, + updatedAt: now + ), + .init( + id: uuid(), + projectID: projectID, + name: "supply-outlet", + value: 0.03, + createdAt: now, + updatedAt: now + ), + .init( + id: uuid(), + projectID: projectID, + name: "return-grille", + value: 0.03, + createdAt: now, + updatedAt: now + ), + .init( + id: uuid(), + projectID: projectID, + name: "balancing-damper", + value: 0.03, + createdAt: now, + updatedAt: now + ), + ] + } + public static var mock: [Self] { [ .init( diff --git a/Sources/ManualDCore/DuctSizes.swift b/Sources/ManualDCore/DuctSizes.swift index 9e56ee7..14eb011 100644 --- a/Sources/ManualDCore/DuctSizes.swift +++ b/Sources/ManualDCore/DuctSizes.swift @@ -146,3 +146,111 @@ extension DuctSizes { } } } + +#if DEBUG + extension DuctSizes { + public static func mock( + equipmentInfo: EquipmentInfo, + rooms: [Room], + trunks: [TrunkSize] + ) -> Self { + + let totalHeatingLoad = rooms.totalHeatingLoad + let totalCoolingLoad = rooms.totalCoolingLoad + + let roomContainers = rooms.reduce(into: [RoomContainer]()) { array, room in + array += RoomContainer.mock( + room: room, + totalHeatingLoad: totalHeatingLoad, + totalCoolingLoad: totalCoolingLoad, + totalHeatingCFM: Double(equipmentInfo.heatingCFM), + totalCoolingCFM: Double(equipmentInfo.coolingCFM) + ) + } + + return .init( + rooms: roomContainers, + trunks: TrunkContainer.mock( + trunks: trunks, + totalHeatingLoad: totalHeatingLoad, + totalCoolingLoad: totalCoolingLoad, + totalHeatingCFM: Double(equipmentInfo.heatingCFM), + totalCoolingCFM: Double(equipmentInfo.coolingCFM) + ) + ) + } + } + + extension DuctSizes.RoomContainer { + public static func mock( + room: Room, + totalHeatingLoad: Double, + totalCoolingLoad: Double, + totalHeatingCFM: Double, + totalCoolingCFM: Double + ) -> [Self] { + var retval = [DuctSizes.RoomContainer]() + let heatingLoad = room.heatingLoad / Double(room.registerCount) + let heatingFraction = heatingLoad / totalHeatingLoad + let heatingCFM = totalHeatingCFM * heatingFraction + // Not really accurate, but works for mocks. + let coolingLoad = room.coolingTotal / Double(room.registerCount) + let coolingFraction = coolingLoad / totalCoolingLoad + let coolingCFM = totalCoolingCFM * coolingFraction + + for n in 1...room.registerCount { + + retval.append( + .init( + roomID: room.id, + roomName: room.name, + roomRegister: n, + heatingLoad: heatingLoad, + coolingLoad: coolingLoad, + heatingCFM: heatingCFM, + coolingCFM: coolingCFM, + ductSize: .init( + rectangularID: nil, + designCFM: .init(heating: heatingCFM, cooling: coolingCFM), + roundSize: 7, + finalSize: 8, + velocity: 489, + flexSize: 8, + height: nil, + width: nil + ) + ) + ) + } + return retval + } + + } + + extension DuctSizes.TrunkContainer { + + public static func mock( + trunks: [TrunkSize], + totalHeatingLoad: Double, + totalCoolingLoad: Double, + totalHeatingCFM: Double, + totalCoolingCFM: Double + ) -> [Self] { + trunks.reduce(into: []) { array, trunk in + array.append( + .init( + trunk: trunk, + ductSize: .init( + designCFM: .init(heating: totalHeatingCFM, cooling: totalCoolingCFM), + roundSize: 18, + finalSize: 20, + velocity: 987, + flexSize: 20 + ) + ) + ) + } + } + } + +#endif diff --git a/Sources/ManualDCore/EffectiveLength.swift b/Sources/ManualDCore/EffectiveLength.swift index 7056715..86c42d2 100644 --- a/Sources/ManualDCore/EffectiveLength.swift +++ b/Sources/ManualDCore/EffectiveLength.swift @@ -142,6 +142,44 @@ extension Array where Element == EffectiveLength.Group { #if DEBUG extension EffectiveLength { + + public static func mock(projectID: Project.ID) -> [Self] { + @Dependency(\.uuid) var uuid + @Dependency(\.date.now) var now + + return [ + .init( + id: uuid(), + projectID: projectID, + name: "Supply - 1", + type: .supply, + straightLengths: [10, 25], + groups: [ + .init(group: 1, letter: "a", value: 20), + .init(group: 2, letter: "b", value: 30, quantity: 1), + .init(group: 3, letter: "a", value: 10, quantity: 1), + .init(group: 12, letter: "a", value: 10, quantity: 1), + ], + createdAt: now, + updatedAt: now + ), + .init( + id: uuid(), + projectID: projectID, + name: "Return - 1", + type: .return, + straightLengths: [10, 20, 5], + groups: [ + .init(group: 5, letter: "a", value: 10), + .init(group: 6, letter: "a", value: 15, quantity: 1), + .init(group: 7, letter: "a", value: 20, quantity: 1), + ], + createdAt: now, + updatedAt: now + ), + ] + } + public static let mocks: [Self] = [ .init( id: UUID(0), diff --git a/Sources/ManualDCore/EquipmentInfo.swift b/Sources/ManualDCore/EquipmentInfo.swift index e2b6fb6..a4d9c8e 100644 --- a/Sources/ManualDCore/EquipmentInfo.swift +++ b/Sources/ManualDCore/EquipmentInfo.swift @@ -70,6 +70,21 @@ extension EquipmentInfo { #if DEBUG extension EquipmentInfo { + + public static func mock(projectID: Project.ID) -> Self { + @Dependency(\.uuid) var uuid + @Dependency(\.date.now) var now + + return .init( + id: uuid(), + projectID: projectID, + heatingCFM: 900, + coolingCFM: 1000, + createdAt: now, + updatedAt: now + ) + } + public static let mock = Self( id: UUID(0), projectID: UUID(0), diff --git a/Sources/ManualDCore/FrictionRate.swift b/Sources/ManualDCore/FrictionRate.swift index 2f26ff5..83f1be7 100644 --- a/Sources/ManualDCore/FrictionRate.swift +++ b/Sources/ManualDCore/FrictionRate.swift @@ -49,3 +49,9 @@ public struct FrictionRateError: Error, Equatable, Sendable { self.resolutions = resolutions } } + +#if DEBUG + extension FrictionRate { + public static let mock = Self(availableStaticPressure: 0.21, value: 0.11) + } +#endif diff --git a/Sources/ManualDCore/Room.swift b/Sources/ManualDCore/Room.swift index ad886b2..de12d32 100644 --- a/Sources/ManualDCore/Room.swift +++ b/Sources/ManualDCore/Room.swift @@ -171,6 +171,86 @@ extension Array where Element == Room { updatedAt: Date() ), ] + + public static func mock(projectID: Project.ID) -> [Self] { + @Dependency(\.uuid) var uuid + @Dependency(\.date.now) var now + + return [ + .init( + id: uuid(), + projectID: projectID, + name: "Bed-1", + heatingLoad: 3913, + coolingTotal: 2472, + coolingSensible: nil, + registerCount: 1, + rectangularSizes: nil, + createdAt: now, + updatedAt: now + ), + .init( + id: uuid(), + projectID: projectID, + name: "Entry", + heatingLoad: 8284, + coolingTotal: 2916, + coolingSensible: nil, + registerCount: 2, + rectangularSizes: nil, + createdAt: now, + updatedAt: now + ), + .init( + id: uuid(), + projectID: projectID, + name: "Family Room", + heatingLoad: 9785, + coolingTotal: 7446, + coolingSensible: nil, + registerCount: 3, + rectangularSizes: nil, + createdAt: now, + updatedAt: now + ), + .init( + id: uuid(), + projectID: projectID, + name: "Kitchen", + heatingLoad: 4518, + coolingTotal: 5096, + coolingSensible: nil, + registerCount: 2, + rectangularSizes: nil, + createdAt: now, + updatedAt: now + ), + .init( + id: uuid(), + projectID: projectID, + name: "Living Room", + heatingLoad: 7553, + coolingTotal: 6829, + coolingSensible: nil, + registerCount: 2, + rectangularSizes: nil, + createdAt: now, + updatedAt: now + ), + .init( + id: uuid(), + projectID: projectID, + name: "Master", + heatingLoad: 8202, + coolingTotal: 2076, + coolingSensible: nil, + registerCount: 2, + rectangularSizes: nil, + createdAt: now, + updatedAt: now + ), + ] + } } #endif diff --git a/Sources/ManualDCore/TrunkSize.swift b/Sources/ManualDCore/TrunkSize.swift index 819b7f4..ad1eaa4 100644 --- a/Sources/ManualDCore/TrunkSize.swift +++ b/Sources/ManualDCore/TrunkSize.swift @@ -1,3 +1,4 @@ +import Dependencies import Foundation // Represents the database model. @@ -71,7 +72,6 @@ extension TrunkSize { } } - // TODO: Make registers non-optional public struct RoomProxy: Codable, Equatable, Identifiable, Sendable { public var id: Room.ID { room.id } @@ -91,3 +91,24 @@ extension TrunkSize { public static let allCases = [Self.supply, .return] } } + +#if DEBUG + extension TrunkSize { + public static func mock(projectID: Project.ID, rooms: [Room]) -> [Self] { + @Dependency(\.uuid) var uuid + + let allRooms = rooms.reduce(into: [TrunkSize.RoomProxy]()) { array, room in + var registers = [Int]() + for n in 1...room.registerCount { + registers.append(n) + } + array.append(.init(room: room, registers: registers)) + } + + return [ + .init(id: uuid(), projectID: projectID, type: .supply, rooms: allRooms), + .init(id: uuid(), projectID: projectID, type: .return, rooms: allRooms), + ] + } + } +#endif diff --git a/Sources/PdfClient/Interface.swift b/Sources/PdfClient/Interface.swift index 5900232..3ca398e 100644 --- a/Sources/PdfClient/Interface.swift +++ b/Sources/PdfClient/Interface.swift @@ -67,3 +67,27 @@ extension PdfClient { } } } + +#if DEBUG + extension PdfClient.Request { + public static func mock(project: Project = .mock) -> Self { + let rooms = Room.mock(projectID: project.id) + let trunks = TrunkSize.mock(projectID: project.id, rooms: rooms) + let equipmentInfo = EquipmentInfo.mock(projectID: project.id) + let equivalentLengths = EffectiveLength.mock(projectID: project.id) + + return .init( + project: project, + rooms: rooms, + componentLosses: ComponentPressureLoss.mock(projectID: project.id), + ductSizes: .mock(equipmentInfo: equipmentInfo, rooms: rooms, trunks: trunks), + equipmentInfo: equipmentInfo, + maxSupplyTEL: equivalentLengths.first { $0.type == .supply }!, + maxReturnTEL: equivalentLengths.first { $0.type == .return }!, + frictionRate: .mock, + projectSHR: 0.83 + ) + + } + } +#endif diff --git a/Sources/ViewController/Live.swift b/Sources/ViewController/Live.swift index 13142e2..0fdf10e 100644 --- a/Sources/ViewController/Live.swift +++ b/Sources/ViewController/Live.swift @@ -3,6 +3,7 @@ import Dependencies import Elementary import Foundation import ManualDCore +import PdfClient import ProjectClient import Styleguide @@ -12,22 +13,26 @@ extension ViewController.Request { @Dependency(\.database) var database @Dependency(\.projectClient) var projectClient + @Dependency(\.pdfClient) var pdfClient switch route { case .test: // let projectID = UUID(uuidString: "E796C96C-F527-4753-A00A-EBCF25630663")! - return await view { - await ResultView { - - // return ( - // try await database.projects.getCompletedSteps(projectID), - // try await projectClient.calculateDuctSizes(projectID) - // ) - } onSuccess: { - TestPage() - // TestPage(trunks: result.trunks, rooms: result.rooms) - } - } + // return await view { + // await ResultView { + // + // // return ( + // // try await database.projects.getCompletedSteps(projectID), + // // try await projectClient.calculateDuctSizes(projectID) + // // ) + // return try await pdfClient.html(.mock()) + // } onSuccess: { + // $0 + // // TestPage() + // // TestPage(trunks: result.trunks, rooms: result.rooms) + // } + // } + return try! await pdfClient.html(.mock()) case .login(let route): switch route { case .index(let next):