diff --git a/Sources/DatabaseClient/Internal/Rooms.swift b/Sources/DatabaseClient/Internal/Rooms.swift index 000517f..2002ea2 100644 --- a/Sources/DatabaseClient/Internal/Rooms.swift +++ b/Sources/DatabaseClient/Internal/Rooms.swift @@ -87,8 +87,7 @@ extension Room.Create { return .init( name: name, heatingLoad: heatingLoad, - coolingTotal: coolingTotal, - coolingSensible: coolingSensible, + coolingLoad: coolingLoad, registerCount: registerCount, projectID: projectID ) @@ -104,8 +103,7 @@ extension Room { .id() .field("name", .string, .required) .field("heatingLoad", .double, .required) - .field("coolingTotal", .double, .required) - .field("coolingSensible", .double) + .field("coolingLoad", .dictionary, .required) .field("registerCount", .int8, .required) .field("rectangularSizes", .array) .field("createdAt", .datetime) @@ -136,11 +134,8 @@ final class RoomModel: Model, @unchecked Sendable, Validatable { @Field(key: "heatingLoad") var heatingLoad: Double - @Field(key: "coolingTotal") - var coolingTotal: Double - - @Field(key: "coolingSensible") - var coolingSensible: Double? + @Field(key: "coolingLoad") + var coolingLoad: Room.CoolingLoad @Field(key: "registerCount") var registerCount: Int @@ -163,8 +158,7 @@ final class RoomModel: Model, @unchecked Sendable, Validatable { id: UUID? = nil, name: String, heatingLoad: Double, - coolingTotal: Double, - coolingSensible: Double? = nil, + coolingLoad: Room.CoolingLoad, registerCount: Int, rectangularSizes: [Room.RectangularSize]? = nil, createdAt: Date? = nil, @@ -174,8 +168,7 @@ final class RoomModel: Model, @unchecked Sendable, Validatable { self.id = id self.name = name self.heatingLoad = heatingLoad - self.coolingTotal = coolingTotal - self.coolingSensible = coolingSensible + self.coolingLoad = coolingLoad self.registerCount = registerCount self.rectangularSizes = rectangularSizes self.createdAt = createdAt @@ -189,8 +182,7 @@ final class RoomModel: Model, @unchecked Sendable, Validatable { projectID: $project.id, name: name, heatingLoad: heatingLoad, - coolingTotal: coolingTotal, - coolingSensible: coolingSensible, + coolingLoad: coolingLoad, registerCount: registerCount, rectangularSizes: rectangularSizes, createdAt: createdAt!, @@ -206,11 +198,8 @@ final class RoomModel: Model, @unchecked Sendable, Validatable { if let heatingLoad = updates.heatingLoad, heatingLoad != self.heatingLoad { self.heatingLoad = heatingLoad } - if let coolingTotal = updates.coolingTotal, coolingTotal != self.coolingTotal { - self.coolingTotal = coolingTotal - } - if let coolingSensible = updates.coolingSensible, coolingSensible != self.coolingSensible { - self.coolingSensible = coolingSensible + if let coolingLoad = updates.coolingLoad, coolingLoad != self.coolingLoad { + self.coolingLoad = coolingLoad } if let registerCount = updates.registerCount, registerCount != self.registerCount { self.registerCount = registerCount @@ -229,11 +218,8 @@ final class RoomModel: Model, @unchecked Sendable, Validatable { Validator.validate(\.heatingLoad, with: .greaterThanOrEquals(0)) .errorLabel("Heating Load", inline: true) - Validator.validate(\.coolingTotal, with: .greaterThanOrEquals(0)) - .errorLabel("Cooling Total", inline: true) - - Validator.validate(\.coolingSensible, with: Double.greaterThanOrEquals(0).optional()) - .errorLabel("Cooling Sensible", inline: true) + Validator.validate(\.coolingLoad) + .errorLabel("Cooling Load", inline: true) Validator.validate(\.registerCount, with: .greaterThanOrEquals(1)) .errorLabel("Register Count", inline: true) @@ -244,6 +230,25 @@ final class RoomModel: Model, @unchecked Sendable, Validatable { } } +extension Room.CoolingLoad: Validatable { + + public var body: some Validation { + Validator.accumulating { + // Ensure that at least one of the values is not nil. + Validator.oneOf { + Validator.validate(\.total, with: .notNil()) + .errorLabel("Total or Sensible", inline: true) + Validator.validate(\.sensible, with: .notNil()) + .errorLabel("Total or Sensible", inline: true) + } + + Validator.validate(\.total, with: Double.greaterThan(0).optional()) + Validator.validate(\.sensible, with: Double.greaterThan(0).optional()) + } + } + +} + extension Room.RectangularSize: Validatable { public var body: some Validation { diff --git a/Sources/ManualDClient/Helpers.swift b/Sources/ManualDClient/Helpers.swift index 88b8292..fc5b2aa 100644 --- a/Sources/ManualDClient/Helpers.swift +++ b/Sources/ManualDClient/Helpers.swift @@ -3,13 +3,12 @@ import ManualDCore extension Room { - var heatingLoadPerRegister: Double { - + public var heatingLoadPerRegister: Double { heatingLoad / Double(registerCount) } - func coolingSensiblePerRegister(projectSHR: Double) -> Double { - let sensible = coolingSensible ?? (coolingTotal * projectSHR) + public func coolingSensiblePerRegister(projectSHR: Double) throws -> Double { + let sensible = try coolingLoad.ensured(shr: projectSHR).sensible return sensible / Double(registerCount) } } @@ -30,8 +29,8 @@ extension TrunkSize.RoomProxy { room.heatingLoadPerRegister * Double(actualRegisterCount) } - func totalCoolingSensible(projectSHR: Double) -> Double { - room.coolingSensiblePerRegister(projectSHR: projectSHR) * Double(actualRegisterCount) + func totalCoolingSensible(projectSHR: Double) throws -> Double { + try room.coolingSensiblePerRegister(projectSHR: projectSHR) * Double(actualRegisterCount) } } @@ -41,8 +40,8 @@ extension TrunkSize { rooms.reduce(into: 0) { $0 += $1.totalHeatingLoad } } - func totalCoolingSensible(projectSHR: Double) -> Double { - rooms.reduce(into: 0) { $0 += $1.totalCoolingSensible(projectSHR: projectSHR) } + func totalCoolingSensible(projectSHR: Double) throws -> Double { + try rooms.reduce(into: 0) { $0 += try $1.totalCoolingSensible(projectSHR: projectSHR) } } } diff --git a/Sources/ManualDCore/CoolingLoad.swift b/Sources/ManualDCore/CoolingLoad.swift index 02b95d7..2c93cc4 100644 --- a/Sources/ManualDCore/CoolingLoad.swift +++ b/Sources/ManualDCore/CoolingLoad.swift @@ -1,13 +1,14 @@ -import Foundation +// import Foundation -public struct CoolingLoad: Codable, Equatable, Sendable { - public let total: Double - public let sensible: Double - public var latent: Double { total - sensible } - public var shr: Double { sensible / total } - - public init(total: Double, sensible: Double) { - self.total = total - self.sensible = sensible - } -} +// +// public struct CoolingLoad: Codable, Equatable, Sendable { +// public let total: Double +// public let sensible: Double +// public var latent: Double { total - sensible } +// public var shr: Double { sensible / total } +// +// public init(total: Double, sensible: Double) { +// self.total = total +// self.sensible = sensible +// } +// } diff --git a/Sources/ManualDCore/DuctSizes.swift b/Sources/ManualDCore/DuctSizes.swift index 14eb011..d0f1789 100644 --- a/Sources/ManualDCore/DuctSizes.swift +++ b/Sources/ManualDCore/DuctSizes.swift @@ -152,11 +152,12 @@ extension DuctSizes { public static func mock( equipmentInfo: EquipmentInfo, rooms: [Room], - trunks: [TrunkSize] + trunks: [TrunkSize], + shr: Double ) -> Self { let totalHeatingLoad = rooms.totalHeatingLoad - let totalCoolingLoad = rooms.totalCoolingLoad + let totalCoolingLoad = try! rooms.totalCoolingLoad(shr: shr) let roomContainers = rooms.reduce(into: [RoomContainer]()) { array, room in array += RoomContainer.mock( @@ -164,7 +165,8 @@ extension DuctSizes { totalHeatingLoad: totalHeatingLoad, totalCoolingLoad: totalCoolingLoad, totalHeatingCFM: Double(equipmentInfo.heatingCFM), - totalCoolingCFM: Double(equipmentInfo.coolingCFM) + totalCoolingCFM: Double(equipmentInfo.coolingCFM), + shr: shr ) } @@ -187,14 +189,15 @@ extension DuctSizes { totalHeatingLoad: Double, totalCoolingLoad: Double, totalHeatingCFM: Double, - totalCoolingCFM: Double + totalCoolingCFM: Double, + shr: 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 coolingLoad = (try! room.coolingLoad.ensured(shr: shr).total) / Double(room.registerCount) let coolingFraction = coolingLoad / totalCoolingLoad let coolingCFM = totalCoolingCFM * coolingFraction diff --git a/Sources/ManualDCore/Room.swift b/Sources/ManualDCore/Room.swift index 54130e6..09ab414 100644 --- a/Sources/ManualDCore/Room.swift +++ b/Sources/ManualDCore/Room.swift @@ -9,19 +9,19 @@ import Foundation public struct Room: Codable, Equatable, Identifiable, Sendable { /// The unique id of the room. public let id: UUID + /// The project this room is associated with. public let projectID: Project.ID + /// A unique name for the room in the project. public let name: String + /// The heating load required for the room (from Manual-J). public let heatingLoad: Double - /// The total cooling load required for the room (from Manual-J). - public let coolingTotal: Double - /// An optional sensible cooling load for the room. - /// - /// **NOTE:** This is generally not set, but calculated from the project wide - /// sensible heat ratio. - public let coolingSensible: Double? + + /// The cooling load required for the room (from Manual-J). + public let coolingLoad: CoolingLoad + /// The number of registers for the room. public let registerCount: Int /// The rectangular duct size calculations for a room. @@ -29,8 +29,10 @@ public struct Room: Codable, Equatable, Identifiable, Sendable { /// **NOTE:** These are optionally set after the round sizes have been calculate /// for a room. public let rectangularSizes: [RectangularSize]? + /// When the room was created in the database. public let createdAt: Date + /// When the room was updated in the database. public let updatedAt: Date @@ -39,8 +41,7 @@ public struct Room: Codable, Equatable, Identifiable, Sendable { projectID: Project.ID, name: String, heatingLoad: Double, - coolingTotal: Double, - coolingSensible: Double? = nil, + coolingLoad: CoolingLoad, registerCount: Int = 1, rectangularSizes: [RectangularSize]? = nil, createdAt: Date, @@ -50,13 +51,46 @@ public struct Room: Codable, Equatable, Identifiable, Sendable { self.projectID = projectID self.name = name self.heatingLoad = heatingLoad - self.coolingTotal = coolingTotal - self.coolingSensible = coolingSensible + self.coolingLoad = coolingLoad self.registerCount = registerCount self.rectangularSizes = rectangularSizes self.createdAt = createdAt self.updatedAt = updatedAt } + + /// Represents the cooling load of a room. + /// + /// Generally only one of the values is provided by a Manual-J room x room + /// calculation. + /// + public struct CoolingLoad: Codable, Equatable, Sendable { + + public let total: Double? + public let sensible: Double? + + public init(total: Double? = nil, sensible: Double? = nil) { + self.total = total + self.sensible = sensible + } + + /// Calculates the cooling load based on the shr. + /// + /// Generally Manual-J room x room loads provide either the total load or the + /// sensible load, so this allows us to calculate whichever is not provided. + public func ensured(shr: Double) throws -> (total: Double, sensible: Double) { + switch (total, sensible) { + case (.none, .none): + throw CoolingLoadError("Both the total and sensible loads are nil.") + case (.some(let total), .some(let sensible)): + return (total, sensible) + case (.some(let total), .none): + return (total, total * shr) + case (.none, .some(let sensible)): + return (sensible / shr, sensible) + } + + } + } } extension Room { @@ -69,17 +103,21 @@ extension Room { /// The heating load required for the room (from Manual-J). public let heatingLoad: Double /// The total cooling load required for the room (from Manual-J). - public let coolingTotal: Double + public let coolingTotal: Double? /// An optional sensible cooling load for the room. public let coolingSensible: Double? /// The number of registers for the room. public let registerCount: Int + public var coolingLoad: Room.CoolingLoad { + .init(total: coolingTotal, sensible: coolingSensible) + } + public init( projectID: Project.ID, name: String, heatingLoad: Double, - coolingTotal: Double, + coolingTotal: Double? = nil, coolingSensible: Double? = nil, registerCount: Int = 1 ) { @@ -118,7 +156,7 @@ extension Room { /// Represents field that can be updated on a room after it's been created in the database. /// - /// Only fields that are supplied get updated. + /// Onlly fields that are supplied get updated. public struct Update: Codable, Equatable, Sendable { /// A unique name for the room in the project. public let name: String? @@ -133,6 +171,13 @@ extension Room { /// The rectangular duct size calculations for a room. public let rectangularSizes: [RectangularSize]? + public var coolingLoad: CoolingLoad? { + guard coolingTotal != nil || coolingSensible != nil else { + return nil + } + return .init(total: coolingTotal, sensible: coolingSensible) + } + public init( name: String? = nil, heatingLoad: Double? = nil, @@ -169,22 +214,30 @@ extension Array where Element == Room { } /// The sum of total cooling loads for an array of rooms. - public var totalCoolingLoad: Double { - reduce(into: 0) { $0 += $1.coolingTotal } + public func totalCoolingLoad(shr: Double) throws -> Double { + try reduce(into: 0) { $0 += try $1.coolingLoad.ensured(shr: shr).total } } /// The sum of sensible cooling loads for an array of rooms. /// /// - Parameters: /// - shr: The project wide sensible heat ratio. - public func totalCoolingSensible(shr: Double) -> Double { - reduce(into: 0) { - let sensible = $1.coolingSensible ?? ($1.coolingTotal * shr) - $0 += sensible + public func totalCoolingSensible(shr: Double) throws -> Double { + try reduce(into: 0) { + // let sensible = $1.coolingSensible ?? ($1.coolingTotal * shr) + $0 += try $1.coolingLoad.ensured(shr: shr).sensible } } } +public struct CoolingLoadError: Error, Equatable, Sendable { + public let reason: String + + public init(_ reason: String) { + self.reason = reason + } +} + #if DEBUG extension Room { @@ -199,8 +252,8 @@ extension Array where Element == Room { projectID: projectID, name: "Bed-1", heatingLoad: 3913, - coolingTotal: 2472, - coolingSensible: nil, + coolingLoad: .init(total: 2472), + // coolingSensible: nil, registerCount: 1, rectangularSizes: nil, createdAt: now, @@ -211,8 +264,8 @@ extension Array where Element == Room { projectID: projectID, name: "Entry", heatingLoad: 8284, - coolingTotal: 2916, - coolingSensible: nil, + coolingLoad: .init(total: 2916), + // coolingSensible: nil, registerCount: 2, rectangularSizes: nil, createdAt: now, @@ -223,8 +276,8 @@ extension Array where Element == Room { projectID: projectID, name: "Family Room", heatingLoad: 9785, - coolingTotal: 7446, - coolingSensible: nil, + coolingLoad: .init(total: 7446), + // coolingSensible: nil, registerCount: 3, rectangularSizes: nil, createdAt: now, @@ -235,8 +288,8 @@ extension Array where Element == Room { projectID: projectID, name: "Kitchen", heatingLoad: 4518, - coolingTotal: 5096, - coolingSensible: nil, + coolingLoad: .init(total: 5096), + // coolingSensible: nil, registerCount: 2, rectangularSizes: nil, createdAt: now, @@ -247,8 +300,8 @@ extension Array where Element == Room { projectID: projectID, name: "Living Room", heatingLoad: 7553, - coolingTotal: 6829, - coolingSensible: nil, + coolingLoad: .init(total: 6829), + // coolingSensible: nil, registerCount: 2, rectangularSizes: nil, createdAt: now, @@ -259,8 +312,8 @@ extension Array where Element == Room { projectID: projectID, name: "Master", heatingLoad: 8202, - coolingTotal: 2076, - coolingSensible: nil, + coolingLoad: .init(total: 2076), + // coolingSensible: nil, registerCount: 2, rectangularSizes: nil, createdAt: now, diff --git a/Sources/ManualDCore/Routes/ViewRoute.swift b/Sources/ManualDCore/Routes/ViewRoute.swift index 7424c52..e88dc3f 100644 --- a/Sources/ManualDCore/Routes/ViewRoute.swift +++ b/Sources/ManualDCore/Routes/ViewRoute.swift @@ -218,9 +218,11 @@ extension SiteRoute.View.ProjectRoute { Field("projectID") { Project.ID.parser() } Field("name", .string) Field("heatingLoad") { Double.parser() } - Field("coolingTotal") { Double.parser() } Optionally { - Field("coolingSensible", default: nil) { Double.parser() } + Field("coolingTotal") { Double.parser() } + } + Optionally { + Field("coolingSensible") { Double.parser() } } Field("registerCount") { Digits() } } diff --git a/Sources/PdfClient/Interface.swift b/Sources/PdfClient/Interface.swift index aabfcf2..b43d2aa 100644 --- a/Sources/PdfClient/Interface.swift +++ b/Sources/PdfClient/Interface.swift @@ -150,7 +150,12 @@ extension PdfClient { project: project, rooms: rooms, componentLosses: ComponentPressureLoss.mock(projectID: project.id), - ductSizes: .mock(equipmentInfo: equipmentInfo, rooms: rooms, trunks: trunks), + ductSizes: .mock( + equipmentInfo: equipmentInfo, + rooms: rooms, + trunks: trunks, + shr: project.sensibleHeatRatio ?? 0.83 + ), equipmentInfo: equipmentInfo, maxSupplyTEL: equivalentLengths.first { $0.type == .supply }!, maxReturnTEL: equivalentLengths.first { $0.type == .return }!, diff --git a/Sources/PdfClient/Views/RoomTable.swift b/Sources/PdfClient/Views/RoomTable.swift index 2cd07bc..de54540 100644 --- a/Sources/PdfClient/Views/RoomTable.swift +++ b/Sources/PdfClient/Views/RoomTable.swift @@ -21,10 +21,9 @@ struct RoomsTable: HTML, Sendable { tr { td { room.name } td { room.heatingLoad.string(digits: 0) } - td { room.coolingTotal.string(digits: 0) } + td { try! room.coolingLoad.ensured(shr: projectSHR).total.string(digits: 0) } td { - (room.coolingSensible - ?? (room.coolingTotal * projectSHR)).string(digits: 0) + try! room.coolingLoad.ensured(shr: projectSHR).sensible.string(digits: 0) } td { room.registerCount.string() } } @@ -37,10 +36,10 @@ struct RoomsTable: HTML, Sendable { rooms.totalHeatingLoad.string(digits: 0) } td(.class("coolingTotal label")) { - rooms.totalCoolingLoad.string(digits: 0) + try! rooms.totalCoolingLoad(shr: projectSHR).string(digits: 0) } td(.class("coolingSensible label")) { - rooms.totalCoolingSensible(shr: projectSHR).string(digits: 0) + try! rooms.totalCoolingSensible(shr: projectSHR).string(digits: 0) } td {} } diff --git a/Sources/ProjectClient/Internal/ManualDClient+calculateDuctSizes.swift b/Sources/ProjectClient/Internal/ManualDClient+calculateDuctSizes.swift index fd63b6d..6fd3e72 100644 --- a/Sources/ProjectClient/Internal/ManualDClient+calculateDuctSizes.swift +++ b/Sources/ProjectClient/Internal/ManualDClient+calculateDuctSizes.swift @@ -41,11 +41,11 @@ extension ManualDClient { var retval: [DuctSizes.RoomContainer] = [] let totalHeatingLoad = rooms.totalHeatingLoad - let totalCoolingSensible = rooms.totalCoolingSensible(shr: sharedRequest.projectSHR) + let totalCoolingSensible = try rooms.totalCoolingSensible(shr: sharedRequest.projectSHR) for room in rooms { let heatingLoad = room.heatingLoadPerRegister - let coolingLoad = room.coolingSensiblePerRegister(projectSHR: sharedRequest.projectSHR) + let coolingLoad = try room.coolingSensiblePerRegister(projectSHR: sharedRequest.projectSHR) let heatingPercent = heatingLoad / totalHeatingLoad let coolingPercent = coolingLoad / totalCoolingSensible let heatingCFM = heatingPercent * Double(sharedRequest.equipmentInfo.heatingCFM) @@ -102,11 +102,11 @@ extension ManualDClient { var retval = [DuctSizes.TrunkContainer]() let totalHeatingLoad = rooms.totalHeatingLoad - let totalCoolingSensible = rooms.totalCoolingSensible(shr: sharedRequest.projectSHR) + let totalCoolingSensible = try rooms.totalCoolingSensible(shr: sharedRequest.projectSHR) for trunk in trunks { let heatingLoad = trunk.totalHeatingLoad - let coolingLoad = trunk.totalCoolingSensible(projectSHR: sharedRequest.projectSHR) + let coolingLoad = try trunk.totalCoolingSensible(projectSHR: sharedRequest.projectSHR) let heatingPercent = heatingLoad / totalHeatingLoad let coolingPercent = coolingLoad / totalCoolingSensible let heatingCFM = heatingPercent * Double(sharedRequest.equipmentInfo.heatingCFM) @@ -181,18 +181,18 @@ extension DuctSizes.SizeContainer { } } -extension Room { - - var heatingLoadPerRegister: Double { - - heatingLoad / Double(registerCount) - } - - func coolingSensiblePerRegister(projectSHR: Double) -> Double { - let sensible = coolingSensible ?? (coolingTotal * projectSHR) - return sensible / Double(registerCount) - } -} +// extension Room { +// +// var heatingLoadPerRegister: Double { +// +// heatingLoad / Double(registerCount) +// } +// +// func coolingSensiblePerRegister(projectSHR: Double) -> Double { +// let sensible = coolingSensible ?? (coolingTotal * projectSHR) +// return sensible / Double(registerCount) +// } +// } extension TrunkSize.RoomProxy { @@ -210,8 +210,8 @@ extension TrunkSize.RoomProxy { room.heatingLoadPerRegister * Double(actualRegisterCount) } - func totalCoolingSensible(projectSHR: Double) -> Double { - room.coolingSensiblePerRegister(projectSHR: projectSHR) * Double(actualRegisterCount) + func totalCoolingSensible(projectSHR: Double) throws -> Double { + try room.coolingSensiblePerRegister(projectSHR: projectSHR) * Double(actualRegisterCount) } } @@ -221,7 +221,7 @@ extension TrunkSize { rooms.reduce(into: 0) { $0 += $1.totalHeatingLoad } } - func totalCoolingSensible(projectSHR: Double) -> Double { - rooms.reduce(into: 0) { $0 += $1.totalCoolingSensible(projectSHR: projectSHR) } + func totalCoolingSensible(projectSHR: Double) throws -> Double { + try rooms.reduce(into: 0) { $0 += try $1.totalCoolingSensible(projectSHR: projectSHR) } } } diff --git a/Sources/ViewController/Views/Rooms/RoomForm.swift b/Sources/ViewController/Views/Rooms/RoomForm.swift index 398b98d..ef6cfa6 100644 --- a/Sources/ViewController/Views/Rooms/RoomForm.swift +++ b/Sources/ViewController/Views/Rooms/RoomForm.swift @@ -73,14 +73,15 @@ struct RoomForm: HTML, Sendable { .value(room?.heatingLoad) ) + // TODO: Add description that only one is required (cooling total or sensible) + LabeledInput( "Cooling Total", .name("coolingTotal"), .type(.number), - .placeholder("1234"), - .required, + .placeholder("1234 (Optional)"), .min("0"), - .value(room?.coolingTotal) + .value(room?.coolingLoad.total) ) LabeledInput( @@ -89,7 +90,7 @@ struct RoomForm: HTML, Sendable { .type(.number), .placeholder("1234 (Optional)"), .min("0"), - .value(room?.coolingSensible) + .value(room?.coolingLoad.sensible) ) LabeledInput( diff --git a/Sources/ViewController/Views/Rooms/RoomsView.swift b/Sources/ViewController/Views/Rooms/RoomsView.swift index acc8085..c7021fb 100644 --- a/Sources/ViewController/Views/Rooms/RoomsView.swift +++ b/Sources/ViewController/Views/Rooms/RoomsView.swift @@ -54,13 +54,15 @@ struct RoomsView: HTML, Sendable { div(.class("flex justify-center items-end space-x-4 my-auto font-bold")) { span(.class("text-lg")) { "Cooling Total" } - Badge(number: rooms.totalCoolingLoad, digits: 0) + // TODO: ResultView ?? + Badge(number: try! rooms.totalCoolingLoad(shr: sensibleHeatRatio ?? 1.0), digits: 0) .attributes(.class("badge-success")) } div(.class("flex grow justify-end items-end space-x-4 me-4 my-auto font-bold")) { span(.class("text-lg")) { "Cooling Sensible" } - Badge(number: rooms.totalCoolingSensible(shr: sensibleHeatRatio ?? 1.0), digits: 0) + // TODO: ResultView ?? + Badge(number: try! rooms.totalCoolingSensible(shr: sensibleHeatRatio ?? 1.0), digits: 0) .attributes(.class("badge-info")) } } @@ -125,10 +127,11 @@ struct RoomsView: HTML, Sendable { let shr: Double var coolingSensible: Double { - guard let value = room.coolingSensible else { - return room.coolingTotal * shr - } - return value + try! room.coolingLoad.ensured(shr: shr).sensible + // guard let value = room.coolingSensible else { + // return room.coolingTotal * shr + // } + // return value } init(room: Room, shr: Double?) { @@ -147,7 +150,7 @@ struct RoomsView: HTML, Sendable { } td { div(.class("flex justify-center")) { - Number(room.coolingTotal, digits: 0) + Number(try! room.coolingLoad.ensured(shr: shr).total, digits: 0) // .attributes(.class("text-success")) } } diff --git a/Tests/DatabaseClientTests/RoomTests.swift b/Tests/DatabaseClientTests/RoomTests.swift index 51ebd6c..50c1127 100644 --- a/Tests/DatabaseClientTests/RoomTests.swift +++ b/Tests/DatabaseClientTests/RoomTests.swift @@ -132,12 +132,20 @@ struct RoomTests { coolingSensible: -1, registerCount: -1 ), + Room.Create( + projectID: UUID(0), + name: "Test", + heatingLoad: 12345, + coolingTotal: nil, + coolingSensible: nil, + registerCount: 1 + ), ] ) func validations(room: Room.Create) throws { #expect(throws: (any Error).self) { // do { - try room.toModel().validate() + try room.toModel().validate() // } catch { // print("\(error)") // throw error diff --git a/Tests/ViewControllerTests/ViewControllerTests.swift b/Tests/ViewControllerTests/ViewControllerTests.swift index 682fd65..2eab389 100644 --- a/Tests/ViewControllerTests/ViewControllerTests.swift +++ b/Tests/ViewControllerTests/ViewControllerTests.swift @@ -103,7 +103,8 @@ struct ViewControllerTests { let mockDuctSizes = DuctSizes.mock( equipmentInfo: equipment, rooms: rooms, - trunks: trunks + trunks: trunks, + shr: project.sensibleHeatRatio ?? 0.83 ) try await withDefaultDependencies { diff --git a/Tests/ViewControllerTests/__Snapshots__/ViewControllerTests/projectDetail.2.html b/Tests/ViewControllerTests/__Snapshots__/ViewControllerTests/projectDetail.2.html index 12a954d..b3257ad 100644 --- a/Tests/ViewControllerTests/__Snapshots__/ViewControllerTests/projectDetail.2.html +++ b/Tests/ViewControllerTests/__Snapshots__/ViewControllerTests/projectDetail.2.html @@ -158,7 +158,7 @@ p-6 w-full"> Heating Load