226 lines
7.3 KiB
Swift
226 lines
7.3 KiB
Swift
import Dependencies
|
|
import DependenciesMacros
|
|
import Foundation
|
|
@_exported import SharedModels
|
|
|
|
extension DependencyValues {
|
|
|
|
public var estimatedPressuresClient: EstimatedPressureDependency {
|
|
get { self[EstimatedPressureDependency.self] }
|
|
set { self[EstimatedPressureDependency.self] = newValue }
|
|
}
|
|
}
|
|
|
|
@DependencyClient
|
|
public struct EstimatedPressureDependency: Sendable {
|
|
|
|
public var estimatedAirflow: @Sendable (EstimatedAirflowRequest) async throws -> Positive<Double>
|
|
public var estimatedPressure: @Sendable (EstimatedPressureRequest) async throws -> Positive<Double>
|
|
|
|
public struct EstimatedPressureRequest: Equatable, Sendable {
|
|
public let existingPressure: Positive<Double>
|
|
public let existingAirflow: Positive<Double>
|
|
public let targetAirflow: Positive<Double>
|
|
|
|
public init(
|
|
existingPressure: Double,
|
|
existingAirflow: Double,
|
|
targetAirflow: Double
|
|
) {
|
|
self.existingPressure = .init(wrappedValue: existingPressure)
|
|
self.existingAirflow = .init(wrappedValue: existingAirflow)
|
|
self.targetAirflow = .init(wrappedValue: targetAirflow)
|
|
}
|
|
}
|
|
|
|
public struct EstimatedAirflowRequest: Equatable, Sendable {
|
|
public let existingAirflow: Positive<Double>
|
|
public let existingPressure: Positive<Double>
|
|
public let targetPressure: Positive<Double>
|
|
|
|
public init(
|
|
existingAirflow: Double,
|
|
existingPressure: Double,
|
|
targetPressure: Double
|
|
) {
|
|
self.existingPressure = .init(wrappedValue: existingPressure)
|
|
self.existingAirflow = .init(wrappedValue: existingAirflow)
|
|
self.targetPressure = .init(wrappedValue: targetPressure)
|
|
}
|
|
}
|
|
|
|
public func estimatedPressure(
|
|
existingPressure: Double,
|
|
existingAirflow: Double,
|
|
targetAirflow: Double
|
|
) async throws -> Positive<Double> {
|
|
try await self.estimatedPressure(
|
|
.init(
|
|
existingPressure: existingPressure,
|
|
existingAirflow: existingAirflow,
|
|
targetAirflow: targetAirflow
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
extension EstimatedPressureDependency {
|
|
private func estimatedPressure(
|
|
existingPressure: Positive<Double>,
|
|
existingAirflow: Positive<Double>,
|
|
targetAirflow: Positive<Double>
|
|
) async throws -> Positive<Double> {
|
|
try await self.estimatedPressure(
|
|
.init(
|
|
existingPressure: existingPressure.positiveValue,
|
|
existingAirflow: existingAirflow.positiveValue,
|
|
targetAirflow: targetAirflow.positiveValue
|
|
)
|
|
)
|
|
}
|
|
|
|
public func estimatedPressure(
|
|
equipmentMeasurement: EquipmentMeasurement,
|
|
airflow updatedAirflow: Double
|
|
) async throws -> EquipmentMeasurement {
|
|
let updatedAirflow = Positive(updatedAirflow)
|
|
|
|
switch equipmentMeasurement {
|
|
case let .airHandler(airHandler):
|
|
return try await .airHandler(
|
|
.init(
|
|
airflow: updatedAirflow,
|
|
manufacturersIncludedFilterPressureDrop: airHandler.$manufacturersIncludedFilterPressureDrop,
|
|
returnPlenumPressure: self.estimatedPressure(
|
|
existingPressure: airHandler.$returnPlenumPressure,
|
|
existingAirflow: airHandler.$airflow,
|
|
targetAirflow: updatedAirflow
|
|
),
|
|
postFilterPressure: self.estimatedPressure(
|
|
existingPressure: airHandler.$postFilterPressure,
|
|
existingAirflow: airHandler.$airflow,
|
|
targetAirflow: updatedAirflow
|
|
),
|
|
postCoilPressure: self.estimatedPressure(
|
|
existingPressure: airHandler.$postCoilPressure,
|
|
existingAirflow: airHandler.$airflow,
|
|
targetAirflow: updatedAirflow
|
|
),
|
|
supplyPlenumPressure: self.estimatedPressure(
|
|
existingPressure: airHandler.$supplyPlenumPressure,
|
|
existingAirflow: airHandler.$airflow,
|
|
targetAirflow: updatedAirflow
|
|
)
|
|
)
|
|
)
|
|
|
|
case let .furnaceAndCoil(furnaceAndCoil):
|
|
return try await .furnaceAndCoil(
|
|
.init(
|
|
airflow: updatedAirflow,
|
|
manufacturersIncludedFilterPressureDrop: furnaceAndCoil.$manufacturersIncludedFilterPressureDrop,
|
|
returnPlenumPressure: self.estimatedPressure(
|
|
existingPressure: furnaceAndCoil.$returnPlenumPressure,
|
|
existingAirflow: furnaceAndCoil.$airflow,
|
|
targetAirflow: updatedAirflow
|
|
),
|
|
postFilterPressure: self.estimatedPressure(
|
|
existingPressure: furnaceAndCoil.$postFilterPressure,
|
|
existingAirflow: furnaceAndCoil.$airflow,
|
|
targetAirflow: updatedAirflow
|
|
),
|
|
preCoilPressure: self.estimatedPressure(
|
|
existingPressure: furnaceAndCoil.$preCoilPressure,
|
|
existingAirflow: furnaceAndCoil.$airflow,
|
|
targetAirflow: updatedAirflow
|
|
),
|
|
supplyPlenumPressure: self.estimatedPressure(
|
|
existingPressure: furnaceAndCoil.$supplyPlenumPressure,
|
|
existingAirflow: furnaceAndCoil.$airflow,
|
|
targetAirflow: updatedAirflow
|
|
)
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
public func estimatedPressure(
|
|
equipmentMeasurement: EquipmentMeasurement,
|
|
airflow updatedAirflow: Positive<Double>,
|
|
filterPressureDrop: Positive<Double>
|
|
) async throws -> EquipmentMeasurement {
|
|
let estimate = try await estimatedPressure(
|
|
equipmentMeasurement: equipmentMeasurement,
|
|
airflow: updatedAirflow.positiveValue
|
|
)
|
|
|
|
switch estimate {
|
|
|
|
case var .airHandler(airHandler):
|
|
airHandler.postFilterPressure = airHandler.returnPlenumPressure + filterPressureDrop.positiveValue
|
|
return .airHandler(airHandler)
|
|
|
|
case var .furnaceAndCoil(furnaceAndCoil):
|
|
furnaceAndCoil.postFilterPressure = furnaceAndCoil.returnPlenumPressure + filterPressureDrop.positiveValue
|
|
return .furnaceAndCoil(furnaceAndCoil)
|
|
}
|
|
}
|
|
|
|
public func estimatedPressure(
|
|
equipmentMeasurement: EquipmentMeasurement,
|
|
airflow updatedAirflow: Double,
|
|
filterPressureDrop: Positive<Double>?
|
|
) async throws -> EquipmentMeasurement {
|
|
guard let filterPressureDrop else {
|
|
return try await estimatedPressure(
|
|
equipmentMeasurement: equipmentMeasurement,
|
|
airflow: updatedAirflow
|
|
)
|
|
}
|
|
return try await estimatedPressure(
|
|
equipmentMeasurement: equipmentMeasurement,
|
|
airflow: updatedAirflow,
|
|
filterPressureDrop: Positive(filterPressureDrop.positiveValue)
|
|
)
|
|
}
|
|
}
|
|
|
|
extension EstimatedPressureDependency: DependencyKey {
|
|
|
|
public static var testValue: EstimatedPressureDependency { Self() }
|
|
|
|
public static var liveValue: EstimatedPressureDependency {
|
|
.init(
|
|
estimatedAirflow: { request in
|
|
guard request.existingPressure.positiveValue > 0 else {
|
|
throw LessThanZeroError.existingPressure
|
|
}
|
|
let value = request.existingAirflow.positiveValue * sqrt(
|
|
request.targetPressure.positiveValue / request.existingPressure.positiveValue
|
|
)
|
|
return .init(wrappedValue: value)
|
|
},
|
|
estimatedPressure: { request in
|
|
guard request.existingAirflow.positiveValue > 0 else {
|
|
throw LessThanZeroError.existingAirflow
|
|
}
|
|
|
|
let value = pow(
|
|
request.targetAirflow.positiveValue / request.existingAirflow.positiveValue,
|
|
2
|
|
) * request.existingPressure.positiveValue
|
|
|
|
return .init(wrappedValue: value)
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
struct InvalidAirflow: Error { }
|
|
|
|
enum LessThanZeroError: Error {
|
|
case existingAirflow
|
|
case existingPressure
|
|
}
|
|
|