115 lines
3.3 KiB
Swift
115 lines
3.3 KiB
Swift
import DatabaseClient
|
|
import Dependencies
|
|
import ManualDClient
|
|
import ManualDCore
|
|
|
|
extension DatabaseClient {
|
|
|
|
func calculateDuctSizes(
|
|
projectID: Project.ID
|
|
) async throws -> DuctSizes {
|
|
@Dependency(\.manualD) var manualD
|
|
|
|
return try await manualD.calculateDuctSizes(
|
|
rooms: rooms.fetch(projectID),
|
|
trunks: trunkSizes.fetch(projectID),
|
|
sharedRequest: sharedDuctRequest(projectID)
|
|
)
|
|
}
|
|
|
|
func calculateRoomDuctSizes(
|
|
projectID: Project.ID
|
|
) async throws -> [DuctSizes.RoomContainer] {
|
|
@Dependency(\.manualD) var manualD
|
|
|
|
return try await manualD.calculateRoomSizes(
|
|
rooms: rooms.fetch(projectID),
|
|
sharedRequest: sharedDuctRequest(projectID)
|
|
)
|
|
}
|
|
|
|
func calculateTrunkDuctSizes(
|
|
projectID: Project.ID
|
|
) async throws -> [DuctSizes.TrunkContainer] {
|
|
@Dependency(\.manualD) var manualD
|
|
|
|
return try await manualD.calculateTrunkSizes(
|
|
rooms: rooms.fetch(projectID),
|
|
trunks: trunkSizes.fetch(projectID),
|
|
sharedRequest: sharedDuctRequest(projectID)
|
|
)
|
|
}
|
|
|
|
func sharedDuctRequest(_ projectID: Project.ID) async throws -> DuctSizeSharedRequest {
|
|
|
|
guard let dfrResponse = try await designFrictionRate(projectID: projectID) else {
|
|
throw ProjectClientError("Project not complete.")
|
|
}
|
|
|
|
let ensuredTEL = try dfrResponse.ensureMaxContainer()
|
|
|
|
return try await .init(
|
|
equipmentInfo: dfrResponse.equipmentInfo,
|
|
maxSupplyLength: ensuredTEL.supply,
|
|
maxReturnLenght: ensuredTEL.return,
|
|
designFrictionRate: dfrResponse.designFrictionRate,
|
|
projectSHR: ensuredSHR(projectID)
|
|
)
|
|
|
|
}
|
|
|
|
// Fetches the project sensible heat ratio or throws an error if it's nil.
|
|
func ensuredSHR(_ projectID: Project.ID) async throws -> Double {
|
|
guard let projectSHR = try await projects.getSensibleHeatRatio(projectID) else {
|
|
throw ProjectClientError("Project sensible heat ratio not set.")
|
|
}
|
|
return projectSHR
|
|
}
|
|
|
|
// Internal container.
|
|
struct DesignFrictionRateResponse: Equatable, Sendable {
|
|
|
|
typealias EnsuredTEL = (supply: EffectiveLength, return: EffectiveLength)
|
|
|
|
let designFrictionRate: Double
|
|
let equipmentInfo: EquipmentInfo
|
|
let telMaxContainer: EffectiveLength.MaxContainer
|
|
|
|
func ensureMaxContainer() throws -> EnsuredTEL {
|
|
|
|
guard let maxSupplyLength = telMaxContainer.supply else {
|
|
throw ProjectClientError("Max supply TEL not found")
|
|
}
|
|
guard let maxReturnLength = telMaxContainer.return else {
|
|
throw ProjectClientError("Max supply TEL not found")
|
|
}
|
|
|
|
return (maxSupplyLength, maxReturnLength)
|
|
|
|
}
|
|
}
|
|
|
|
func designFrictionRate(
|
|
projectID: Project.ID
|
|
) async throws -> DesignFrictionRateResponse? {
|
|
guard let equipmentInfo = try await equipment.fetch(projectID) else {
|
|
return nil
|
|
}
|
|
|
|
let equivalentLengths = try await effectiveLength.fetchMax(projectID)
|
|
guard let tel = equivalentLengths.total else { return nil }
|
|
|
|
let componentLosses = try await componentLoss.fetch(projectID)
|
|
guard componentLosses.count > 0 else { return nil }
|
|
|
|
let availableStaticPressure =
|
|
equipmentInfo.staticPressure - componentLosses.total
|
|
|
|
return .init(
|
|
designFrictionRate: (availableStaticPressure * 100) / tel,
|
|
equipmentInfo: equipmentInfo,
|
|
telMaxContainer: equivalentLengths
|
|
)
|
|
}
|
|
}
|