import CoreFoundation import Models import Validations extension HeatPumpHeatingInterpolation.Request { func respond() async throws -> HeatPumpHeatingInterpolation.Response { try await validate() let altitudeAdjustmentMultiplier = try await altitudeAdjustmentMultiplier() let finalCapacity = finalCapacity(altitudeAdjustmentMultiplier) let balancePointTemperature = try await balancePoint(finalCapacity) let capacityAtDesign = capacityAtDesign(finalCapacity) let requiredKW = try await requiredKW(capacityAtDesign) return .init( altitudeAdjustmentMultiplier: altitudeAdjustmentMultiplier, balancePointTemperature: balancePointTemperature, capacityAtDesign: capacityAtDesign, finalCapacity: finalCapacity, supplementalHeatRequired: requiredKW ) } private func balancePoint(_ finalCapacity: Capacity.HeatPumpHeating) async throws -> Int { let response = try await BalancePoint.Request( winterDesignTemperature: winterDesignTemperature, heatLoss: heatLoss, heatPumpCapacity: finalCapacity ).respond() return Int(response.balancePointTemperature) } private func altitudeAdjustmentMultiplier() async throws -> Double? { guard let elevation else { return nil } let response = try await Derating.Request( elevation: elevation, systemType: .airToAir(type: .heatPump, compressor: .singleSpeed, climate: climateType) ).respond() return response.heating } private func finalCapacity( _ adjustmentMultiplier: Double? ) -> Capacity.HeatPumpHeating { guard let adjustmentMultiplier else { return capacity } return .init( at47: Int(Double(capacity.at47) * adjustmentMultiplier), at17: Int(Double(capacity.at17) * adjustmentMultiplier) ) } private func capacityAtDesign( _ finalCapacity: Capacity.HeatPumpHeating ) -> Int { let outdoorTemperature = Double(winterDesignTemperature) let derating = Double((finalCapacity.at47 - finalCapacity.at17) / 30) * (17 - outdoorTemperature) return Int(Double(finalCapacity.at17) - derating) } private func requiredKW(_ capacityAtDesign: Int) async throws -> Int { let response = try await RequiredKW.Request( capacityAtDesign: capacityAtDesign, heatLoss: heatLoss ).respond() return Int(response.requiredKW) } } extension HeatPumpHeatingInterpolation.Request: AsyncValidatable { public var body: some AsyncValidation { AsyncValidator.accumulating { AsyncValidator.greaterThan(\.heatLoss, 0) AsyncValidator.validate(\.capacity) } } }