feat: Initial commit
This commit is contained in:
248
Sources/EstimatedPressureDependency/Key.swift
Normal file
248
Sources/EstimatedPressureDependency/Key.swift
Normal file
@@ -0,0 +1,248 @@
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user