feat: Completes hvac-system-performance views and api call.
This commit is contained in:
56
Sources/Routes/Models/DehumidifierSizing.swift
Normal file
56
Sources/Routes/Models/DehumidifierSizing.swift
Normal file
@@ -0,0 +1,56 @@
|
||||
import Foundation
|
||||
|
||||
public enum DehumidifierSize {
|
||||
|
||||
/// Represents the request for determining dehumidifier size based on
|
||||
/// latent load and indoor conditions.
|
||||
public struct Request: Codable, Equatable, Sendable {
|
||||
|
||||
public let latentLoad: Double
|
||||
public let temperature: Double
|
||||
public let humidity: Double
|
||||
|
||||
public init(latentLoad: Double, temperature: Double, humidity: Double) {
|
||||
self.latentLoad = latentLoad
|
||||
self.temperature = temperature
|
||||
self.humidity = humidity
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the response for determining dehumidifier size based on
|
||||
/// latent load and indoor conditions.
|
||||
public struct Response: Codable, Equatable, Sendable {
|
||||
|
||||
public let requiredCapacity: Double
|
||||
public let pintsPerDay: Double
|
||||
public let recommendedSize: Int
|
||||
public let recommendedUrl: String?
|
||||
public let warnings: [String]
|
||||
|
||||
public init(
|
||||
requiredCapacity: Double,
|
||||
pintsPerDay: Double,
|
||||
recommendedSize: Int,
|
||||
recommendedUrl: String? = nil,
|
||||
warnings: [String] = []
|
||||
) {
|
||||
self.requiredCapacity = requiredCapacity
|
||||
self.pintsPerDay = pintsPerDay
|
||||
self.recommendedSize = recommendedSize
|
||||
self.recommendedUrl = recommendedUrl
|
||||
self.warnings = warnings
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
public extension DehumidifierSize.Response {
|
||||
|
||||
static var mock: Self {
|
||||
.init(requiredCapacity: 100, pintsPerDay: 100, recommendedSize: 100, recommendedUrl: "#", warnings: [
|
||||
"A warning.", "B warning"
|
||||
])
|
||||
}
|
||||
}
|
||||
#endif
|
||||
29
Sources/Routes/Models/HTMXExtensions.swift
Normal file
29
Sources/Routes/Models/HTMXExtensions.swift
Normal file
@@ -0,0 +1,29 @@
|
||||
import Elementary
|
||||
import ElementaryHTMX
|
||||
|
||||
public extension HTMLAttribute.hx {
|
||||
@Sendable
|
||||
static func get(route: SiteRoute.View) -> HTMLAttribute {
|
||||
get(SiteRoute.View.router.path(for: route))
|
||||
}
|
||||
|
||||
@Sendable
|
||||
static func patch(route: SiteRoute.View) -> HTMLAttribute {
|
||||
patch(SiteRoute.View.router.path(for: route))
|
||||
}
|
||||
|
||||
@Sendable
|
||||
static func post(route: SiteRoute.View) -> HTMLAttribute {
|
||||
post(SiteRoute.View.router.path(for: route))
|
||||
}
|
||||
|
||||
@Sendable
|
||||
static func put(route: SiteRoute.View) -> HTMLAttribute {
|
||||
put(SiteRoute.View.router.path(for: route))
|
||||
}
|
||||
|
||||
@Sendable
|
||||
static func delete(route: SiteRoute.Api) -> HTMLAttribute {
|
||||
delete(SiteRoute.Api.router.path(for: route))
|
||||
}
|
||||
}
|
||||
123
Sources/Routes/Models/HVACSystemPerformance.swift
Normal file
123
Sources/Routes/Models/HVACSystemPerformance.swift
Normal file
@@ -0,0 +1,123 @@
|
||||
import Dependencies
|
||||
import PsychrometricClient
|
||||
|
||||
public enum HVACSystemPerformance {
|
||||
|
||||
public struct Request: Codable, Equatable, Sendable {
|
||||
|
||||
public let altitude: Double?
|
||||
public let airflow: Double
|
||||
public let returnAirTemperature: Double
|
||||
public let returnAirHumidity: Double
|
||||
public let supplyAirTemperature: Double
|
||||
public let supplyAirHumidity: Double
|
||||
public let systemSize: Double
|
||||
|
||||
public init(
|
||||
altitude: Double? = nil,
|
||||
airflow: Double,
|
||||
returnAirTemperature: Double,
|
||||
returnAirHumidity: Double,
|
||||
supplyAirTemperature: Double,
|
||||
supplyAirHumidity: Double,
|
||||
systemSize: Double
|
||||
) {
|
||||
self.altitude = altitude
|
||||
self.airflow = airflow
|
||||
self.returnAirTemperature = returnAirTemperature
|
||||
self.returnAirHumidity = returnAirHumidity
|
||||
self.supplyAirTemperature = supplyAirTemperature
|
||||
self.supplyAirHumidity = supplyAirHumidity
|
||||
self.systemSize = systemSize
|
||||
}
|
||||
}
|
||||
|
||||
public struct Response: Codable, Equatable, Sendable {
|
||||
|
||||
public let returnAirProperties: PsychrometricProperties
|
||||
public let supplyAirProperties: PsychrometricProperties
|
||||
public let capacity: Capacity
|
||||
public let systemMetrics: SystemMetrics
|
||||
|
||||
public init(
|
||||
returnAirProperties: PsychrometricProperties,
|
||||
supplyAirProperties: PsychrometricProperties,
|
||||
capacity: HVACSystemPerformance.Capacity,
|
||||
systemMetrics: HVACSystemPerformance.SystemMetrics
|
||||
) {
|
||||
self.returnAirProperties = returnAirProperties
|
||||
self.supplyAirProperties = supplyAirProperties
|
||||
self.capacity = capacity
|
||||
self.systemMetrics = systemMetrics
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add delta-enthalpy.
|
||||
public struct Capacity: Codable, Equatable, Sendable {
|
||||
|
||||
public let total: Double
|
||||
public let sensible: Double
|
||||
public let latent: Double
|
||||
public var shr: Double { sensible / total }
|
||||
|
||||
public init(total: Double, sensible: Double, latent: Double) {
|
||||
self.total = total
|
||||
self.sensible = sensible
|
||||
self.latent = latent
|
||||
}
|
||||
}
|
||||
|
||||
public struct SystemMetrics: Codable, Equatable, Sendable {
|
||||
|
||||
public let cfmPerTon: Double
|
||||
public let targetTemperatureSplit: Double
|
||||
public let actualTemperatureSplit: Double
|
||||
public let condensationRatePoundsPerHour: Double // lb/hr
|
||||
public let condensationRateGallonsPerHour: Double // gal/hr
|
||||
|
||||
public init(
|
||||
cfmPerTon: Double,
|
||||
targetTemperatureSplit: Double,
|
||||
actualTemperatureSplit: Double,
|
||||
condensationRatePoundsPerHour: Double
|
||||
) {
|
||||
self.cfmPerTon = cfmPerTon
|
||||
self.targetTemperatureSplit = targetTemperatureSplit
|
||||
self.actualTemperatureSplit = actualTemperatureSplit
|
||||
self.condensationRatePoundsPerHour = condensationRatePoundsPerHour
|
||||
self.condensationRateGallonsPerHour = condensationRatePoundsPerHour * 0.12
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
public extension HVACSystemPerformance.Response {
|
||||
|
||||
static func mock() async throws -> Self {
|
||||
@Dependency(\.psychrometricClient) var psychrometricClient
|
||||
|
||||
return try await .init(
|
||||
returnAirProperties: psychrometricClient.psychrometricProperties(.dryBulb(75, relativeHumidity: 50%)),
|
||||
supplyAirProperties: psychrometricClient.psychrometricProperties(.dryBulb(55, relativeHumidity: 87%)),
|
||||
capacity: .mock,
|
||||
systemMetrics: .mock
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public extension HVACSystemPerformance.Capacity {
|
||||
static var mock: Self {
|
||||
.init(total: 24000, sensible: 19000, latent: 5000)
|
||||
}
|
||||
}
|
||||
|
||||
public extension HVACSystemPerformance.SystemMetrics {
|
||||
static let mock = Self(
|
||||
cfmPerTon: 400,
|
||||
targetTemperatureSplit: 20.8,
|
||||
actualTemperatureSplit: 18.7,
|
||||
condensationRatePoundsPerHour: 16981.3
|
||||
)
|
||||
}
|
||||
#endif
|
||||
11
Sources/Routes/Models/HVACSystemSize.swift
Normal file
11
Sources/Routes/Models/HVACSystemSize.swift
Normal file
@@ -0,0 +1,11 @@
|
||||
public enum HVACSystemSize: Double, Codable, Equatable, Sendable {
|
||||
case one = 1
|
||||
case oneAndAHalf = 1.5
|
||||
case two = 2
|
||||
case twoAndAHalf = 2.5
|
||||
case three = 3
|
||||
case threeAndAHalf = 3.5
|
||||
case four = 4
|
||||
case fourAndAHalf = 4.5
|
||||
case five = 5
|
||||
}
|
||||
80
Sources/Routes/Models/MoldRisk.swift
Normal file
80
Sources/Routes/Models/MoldRisk.swift
Normal file
@@ -0,0 +1,80 @@
|
||||
import Foundation
|
||||
import PsychrometricClient
|
||||
|
||||
public enum MoldRisk {
|
||||
public struct Request: Codable, Equatable, Sendable {
|
||||
|
||||
public let temperature: Double
|
||||
public let humidity: Double
|
||||
|
||||
public init(temperature: Double, humidity: Double) {
|
||||
self.temperature = temperature
|
||||
self.humidity = humidity
|
||||
}
|
||||
}
|
||||
|
||||
public struct Response: Codable, Equatable, Sendable {
|
||||
|
||||
public let psychrometricProperties: PsychrometricProperties
|
||||
public let riskLevel: RiskLevel
|
||||
public let daysToMold: Int?
|
||||
public let recommendations: [String]
|
||||
|
||||
public init(
|
||||
psychrometricProperties: PsychrometricProperties,
|
||||
riskLevel: MoldRisk.RiskLevel,
|
||||
daysToMold: Int? = nil,
|
||||
recommendations: [String]
|
||||
) {
|
||||
self.psychrometricProperties = psychrometricProperties
|
||||
self.riskLevel = riskLevel
|
||||
self.daysToMold = daysToMold
|
||||
self.recommendations = recommendations
|
||||
}
|
||||
}
|
||||
|
||||
public enum RiskLevel: String, Codable, Equatable, Sendable {
|
||||
case low
|
||||
case moderate
|
||||
case high
|
||||
case severe
|
||||
}
|
||||
}
|
||||
|
||||
public extension MoldRisk.Request {
|
||||
|
||||
var dryBulb: DryBulb {
|
||||
.fahrenheit(temperature)
|
||||
}
|
||||
|
||||
var relativeHumidity: RelativeHumidity { humidity% }
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
import Dependencies
|
||||
|
||||
public extension MoldRisk.Response {
|
||||
static var mock: Self {
|
||||
return .init(
|
||||
psychrometricProperties: .init(
|
||||
absoluteHumidity: .zero,
|
||||
atmosphericPressure: .zero,
|
||||
degreeOfSaturation: .zero,
|
||||
density: .zero, dewPoint: 59.4,
|
||||
dryBulb: 75,
|
||||
enthalpy: .zero,
|
||||
grainsOfMoisture: .zero,
|
||||
humidityRatio: .zero,
|
||||
relativeHumidity: 50%,
|
||||
specificVolume: .zero,
|
||||
vaporPressure: .zero,
|
||||
wetBulb: .zero,
|
||||
units: .imperial
|
||||
),
|
||||
riskLevel: .low,
|
||||
recommendations: []
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user