@_exported import ApiController import Dependencies import Logging @preconcurrency import PsychrometricClient import Routes extension ApiController: DependencyKey { public static var liveValue: ApiController { @Dependency(\.psychrometricClient) var psychrometricClient return .init(json: { route, logger in switch route { case let .calculateMoldRisk(request): logger.info("Calculating mold risk: \(request)") return try await psychrometricClient.resond(request, logger) } }) } } private extension PsychrometricClient { private func calculateProperties(_ request: MoldRisk.Request) async throws -> PsychrometricProperties { try await psychrometricProperties(.dryBulb(request.temperature, relativeHumidity: request.humidity)) } func resond(_ request: MoldRisk.Request, _ logger: Logger) async throws -> MoldRisk.Response { let properties = try await calculateProperties(request) let riskLevel = MoldRisk.RiskLevel(humidity: request.humidity) return .init( psychrometricProperties: properties, riskLevel: riskLevel, daysToMold: riskLevel.daysToMold, recommendations: .recommendations(for: request, dewPoint: properties.dewPoint, riskLevel: riskLevel) ) } } private extension MoldRisk.RiskLevel { init(humidity: RelativeHumidity) { if humidity < 60 { self = .low } else if humidity < 70 { self = .moderate } else if humidity < 80 { self = .high } else { self = .severe } } var daysToMold: Int? { switch self { case .low: return nil case .moderate: return 30 case .high: return 14 case .severe: return 7 } } } private extension Array where Element == String { static func recommendations( for request: MoldRisk.Request, dewPoint: DewPoint, riskLevel: MoldRisk.RiskLevel ) -> Self { var recommendations = [String]() if request.humidity < 60 { recommendations.append( "Reduce indoor relative humidity below 60% using dehumidification" ) } if (request.temperature.fahrenheit - dewPoint.fahrenheit) < 4 { recommendations.append( "Increase air temperature or improve insulation to prevent condensation" ) } if riskLevel != .low { recommendations.append(contentsOf: [ "Improve ventilation to reduce moisture accumulation", "Inspect for and repair any water leaks or intrusion" ]) } return recommendations } }