feat: Finishes economic balance point.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import CoreModels
|
||||
import Foundation
|
||||
import Logging
|
||||
import OpcostAnalysis
|
||||
import Routes
|
||||
|
||||
public extension HeatingBalancePoint.Request {
|
||||
@@ -10,6 +11,42 @@ public extension HeatingBalancePoint.Request {
|
||||
case let .thermal(request):
|
||||
logger.debug("Calculating thermal balance point: \(request)")
|
||||
return try await request.respond(logger: logger)
|
||||
case let .economic(request):
|
||||
logger.debug("Calculating economic balance point: \(request)")
|
||||
return try await request.respond(logger: logger)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension HeatingBalancePoint.Request.Economic {
|
||||
|
||||
func respond(logger: Logger) async throws -> HeatingBalancePoint.Response {
|
||||
try validate()
|
||||
let fuelCostPerMMBTU = fuelType.costPerMMBTU(afue: fuelAFUE, costPerUnit: fuelCostPerUnit)
|
||||
logger.debug("Fuel cost per mmBTU: \(fuelCostPerMMBTU)")
|
||||
let electricCostPerMMBTU = 1_000_000 / 3412 * costPerKW
|
||||
let electricFuelRatio = electricCostPerMMBTU / fuelCostPerMMBTU
|
||||
let balancePointTemperature = (electricFuelRatio - 1.8273) / 0.0413
|
||||
let copAtBalancePoint = 0.0413 * balancePointTemperature + 1.8273
|
||||
|
||||
return .economic(.init(
|
||||
balancePointTemperature: balancePointTemperature,
|
||||
fuelCostPerMMBTU: fuelCostPerMMBTU,
|
||||
electricCostPerMMBTU: electricCostPerMMBTU,
|
||||
copAtBalancePoint: copAtBalancePoint,
|
||||
electricFuelRatio: electricFuelRatio
|
||||
))
|
||||
}
|
||||
|
||||
func validate() throws {
|
||||
guard fuelCostPerUnit > 0 else {
|
||||
throw ValidationError(message: "Fuel cost should be greater than 0.")
|
||||
}
|
||||
guard fuelAFUE > 0, fuelAFUE < 100 else {
|
||||
throw ValidationError(message: "AFUE is outside of range 0-100%.")
|
||||
}
|
||||
guard costPerKW > 0 else {
|
||||
throw ValidationError(message: "Electric cost per KW should be greater than 0.")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -144,6 +181,35 @@ extension ClimateZone {
|
||||
case .seven: return -15
|
||||
}
|
||||
}
|
||||
|
||||
var averageHeatingLoadHours: Double {
|
||||
switch self {
|
||||
case .one: return 1000
|
||||
case .two: return 2250
|
||||
case .three: return 3750
|
||||
case .four: return 5250
|
||||
case .five: return 6750
|
||||
case .six: return 8250
|
||||
case .seven: return 10000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension HeatingBalancePoint.FuelType {
|
||||
var btuPerUnit: Double {
|
||||
switch self {
|
||||
case .naturalGas: return 100_000
|
||||
case .propane: return 91333
|
||||
case .oil: return 138_690
|
||||
}
|
||||
}
|
||||
|
||||
func costPerMMBTU(afue: Double, costPerUnit: Double) -> Double {
|
||||
if self == .naturalGas {
|
||||
return costPerUnit * 10 / afue * 100
|
||||
}
|
||||
return (1_000_000 / btuPerUnit) * costPerUnit / afue * 100
|
||||
}
|
||||
}
|
||||
|
||||
private func thermalBalancePoint(
|
||||
|
||||
Reference in New Issue
Block a user