249 lines
7.6 KiB
Swift
249 lines
7.6 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 {
|
|
|
|
public var estimatedAirflow: (EstimatedAirflowRequest) async throws -> Positive<Double>
|
|
public var estimatedPressure: (EstimatedPressureRequest) async throws -> Positive<Double>
|
|
|
|
public struct EstimatedPressureRequest: Equatable {
|
|
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 {
|
|
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: Double,
|
|
targetAirflow: Double
|
|
) async throws -> Positive<Double> {
|
|
try await self.estimatedPressure(
|
|
.init(
|
|
existingPressure: existingPressure.positiveValue ?? 0,
|
|
existingAirflow: existingAirflow,
|
|
targetAirflow: targetAirflow
|
|
)
|
|
)
|
|
}
|
|
|
|
public func estimatedPressure(
|
|
for equipmentMeasurement: EquipmentMeasurement,
|
|
at upgradedAirflow: Double
|
|
) async throws -> EquipmentMeasurement {
|
|
switch equipmentMeasurement {
|
|
case let .airHandler(airHandler):
|
|
guard let airflow = airHandler.airflow else {
|
|
throw InvalidAirflow()
|
|
}
|
|
return try await .airHandler(
|
|
.init(
|
|
airflow: upgradedAirflow,
|
|
returnPlenumPressure: self.estimatedPressure(
|
|
existingPressure: airHandler.$returnPlenumPressure,
|
|
existingAirflow: airflow,
|
|
targetAirflow: upgradedAirflow
|
|
),
|
|
postFilterPressure: self.estimatedPressure(
|
|
existingPressure: airHandler.$postFilterPressure,
|
|
existingAirflow: airflow,
|
|
targetAirflow: upgradedAirflow
|
|
),
|
|
postCoilPressure: self.estimatedPressure(
|
|
existingPressure: airHandler.$postCoilPressure,
|
|
existingAirflow: airflow,
|
|
targetAirflow: upgradedAirflow
|
|
),
|
|
supplyPlenumPressure: self.estimatedPressure(
|
|
existingPressure: airHandler.$supplyPlenumPressure,
|
|
existingAirflow: airflow,
|
|
targetAirflow: upgradedAirflow
|
|
)
|
|
)
|
|
)
|
|
|
|
case let .furnaceAndCoil(furnaceAndCoil):
|
|
guard let airflow = furnaceAndCoil.airflow else {
|
|
throw InvalidAirflow()
|
|
}
|
|
return try await .furnaceAndCoil(
|
|
.init(
|
|
airflow: upgradedAirflow,
|
|
returnPlenumPressure: self.estimatedPressure(
|
|
existingPressure: furnaceAndCoil.$returnPlenumPressure,
|
|
existingAirflow: airflow,
|
|
targetAirflow: upgradedAirflow
|
|
),
|
|
postFilterPressure: self.estimatedPressure(
|
|
existingPressure: furnaceAndCoil.$postFilterPressure,
|
|
existingAirflow: airflow,
|
|
targetAirflow: upgradedAirflow
|
|
),
|
|
preCoilPressure: self.estimatedPressure(
|
|
existingPressure: furnaceAndCoil.$preCoilPressure,
|
|
existingAirflow: airflow,
|
|
targetAirflow: upgradedAirflow
|
|
),
|
|
supplyPlenumPressure: self.estimatedPressure(
|
|
existingPressure: furnaceAndCoil.$supplyPlenumPressure,
|
|
existingAirflow: airflow,
|
|
targetAirflow: upgradedAirflow
|
|
)
|
|
)
|
|
)
|
|
|
|
}
|
|
}
|
|
|
|
public func estimatedPressure(
|
|
for equipmentMeasurement: EquipmentMeasurement,
|
|
at upgradedAirflow: Double,
|
|
with filterPressureDrop: Positive<Double>
|
|
) async throws -> EquipmentMeasurement {
|
|
let estimate = try await estimatedPressure(
|
|
for: equipmentMeasurement,
|
|
at: upgradedAirflow
|
|
)
|
|
|
|
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)
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
fileprivate extension EquipmentMeasurement.AirHandler {
|
|
init(
|
|
airflow: Double? = nil,
|
|
returnPlenumPressure: Positive<Double>,
|
|
postFilterPressure: Positive<Double>,
|
|
postCoilPressure: Positive<Double>,
|
|
supplyPlenumPressure: Positive<Double>
|
|
) {
|
|
self.init(
|
|
airflow: airflow,
|
|
returnPlenumPressure: returnPlenumPressure.positiveValue,
|
|
postFilterPressure: postFilterPressure.positiveValue,
|
|
postCoilPressure: postCoilPressure.positiveValue,
|
|
supplyPlenumPressure: supplyPlenumPressure.positiveValue
|
|
)
|
|
}
|
|
}
|
|
|
|
fileprivate extension EquipmentMeasurement.FurnaceAndCoil {
|
|
init(
|
|
airflow: Double? = nil,
|
|
returnPlenumPressure: Positive<Double>,
|
|
postFilterPressure: Positive<Double>,
|
|
preCoilPressure: Positive<Double>,
|
|
supplyPlenumPressure: Positive<Double>
|
|
) {
|
|
self.init(
|
|
airflow: airflow,
|
|
returnPlenumPressure: returnPlenumPressure.positiveValue,
|
|
postFilterPressure: postFilterPressure.positiveValue,
|
|
preCoilPressure: preCoilPressure.positiveValue,
|
|
supplyPlenumPressure: supplyPlenumPressure.positiveValue
|
|
)
|
|
}
|
|
}
|
|
|
|
struct InvalidAirflow: Error { }
|
|
|
|
enum LessThanZeroError: Error {
|
|
case existingAirflow
|
|
case existingPressure
|
|
}
|
|
|