Files
swift-estimated-pressures-core/Sources/PressureEstimationsFeature/SharedPressureEstimationState.swift
2024-06-17 11:46:42 -04:00

131 lines
4.3 KiB
Swift

import ComposableArchitecture
import Foundation
import SharedModels
/// Holds onto shared values for several of the views in this feature.
@dynamicMemberLookup
public struct SharedPressureEstimationState: Equatable, Sendable {
public var budgets: BudgetedPercentEnvelope?
public var equipmentMeasurement: EquipmentMeasurement?
public var equipmentMetadata: EquipmentMetadata
public var flaggedEquipmentMeasurement: EquipmentMeasurement.FlaggedMeasurement?
public var flaggedEstimations: IdentifiedArrayOf<FlaggedEstimationContainer>
public var heatingCapacity: Double?
public var manufacturersIncludedFilterPressureDrop: Double?
public init(
budgets: BudgetedPercentEnvelope? = nil,
equipmentMeasurement: EquipmentMeasurement? = nil,
equipmentMetadata: EquipmentMetadata = .init(),
flaggedEquipmentMeasurement: EquipmentMeasurement.FlaggedMeasurement? = nil,
flaggedEstimations: IdentifiedArrayOf<FlaggedEstimationContainer> = [],
heatingCapacity: Double? = nil,
manufacturersIncludedFilterPressureDrop: Double? = nil
) {
self.budgets = budgets
self.equipmentMeasurement = equipmentMeasurement
self.equipmentMetadata = equipmentMetadata
self.flaggedEquipmentMeasurement = flaggedEquipmentMeasurement
self.flaggedEstimations = flaggedEstimations
self.heatingCapacity = heatingCapacity
self.manufacturersIncludedFilterPressureDrop = manufacturersIncludedFilterPressureDrop
}
public subscript<T>(dynamicMember keyPath: WritableKeyPath<EquipmentMetadata, T>) -> T {
get { equipmentMetadata[keyPath: keyPath] }
set { equipmentMetadata[keyPath: keyPath] = newValue }
}
@dynamicMemberLookup
public struct FlaggedEstimationContainer: Equatable, Identifiable, Sendable {
public let id: UUID
public var estimationState: EstimationState
public var flaggedMeasurement: EquipmentMeasurement.FlaggedMeasurement
public init(
id: UUID,
estimationState: EstimationState,
flaggedMeasurement: EquipmentMeasurement.FlaggedMeasurement
) {
self.id = id
self.estimationState = estimationState
self.flaggedMeasurement = flaggedMeasurement
}
public subscript<T>(dynamicMember keyPath: WritableKeyPath<EstimationState, T>) -> T {
get { estimationState[keyPath: keyPath] }
set { estimationState[keyPath: keyPath] = newValue }
}
public subscript<T>(dynamicMember keyPath: KeyPath<EstimationState, T>) -> T {
get { estimationState[keyPath: keyPath] }
}
public struct EstimationState: Equatable, Sendable {
public var cfm: CFMContainer
public var filterPressureDrop: Double?
public var name: String?
public init(
cfm: CFMContainer,
filterPressureDrop: Double? = nil,
name: String? = nil
) {
self.cfm = cfm
self.filterPressureDrop = filterPressureDrop
self.name = name
}
internal init(state: EstimationForm.State) {
self.init(
cfm: .init(state: state),
filterPressureDrop: state.filterPressureDrop,
name: state.name.isEmpty ? nil : state.name
)
}
var displayName: String {
guard let name else {
return "@\(Int(cfm.airflow)) CFM"
}
return name
}
// Compare relevant values on if two states have changes.
func hasChanges(_ other: Self) -> Bool {
cfm != other.cfm || filterPressureDrop != other.filterPressureDrop
}
public enum CFMContainer: Equatable, Sendable {
case cfm(Int)
case cfmPerTon(Int, EquipmentMetadata.CoolingCapacity)
init(state: EstimationForm.State) {
switch state.airflowSelection {
case .cfmPerTon:
self = .cfmPerTon(state.cfmTextField ?? 0, state.coolingCapacity)
case .cfm:
self = .cfm(state.cfmTextField ?? 0)
}
}
var airflow: Double {
switch self {
case let .cfm(cfm):
return Double(cfm)
case let .cfmPerTon(cfmPerTon, capacity):
return Double(cfmPerTon) * capacity.rawValue
}
}
}
}
}
}
extension PersistenceReaderKey where Self == InMemoryKey<SharedPressureEstimationState> {
static var pressureEstimationState: Self {
.inMemory("sharedPressureEstimationState")
}
}