feat: Finishes economic balance point.

This commit is contained in:
2025-03-04 17:17:55 -05:00
parent 6c31a9db09
commit b58d053ba1
8 changed files with 226 additions and 15 deletions

View File

@@ -41,11 +41,7 @@ struct HeatingBalancePointForm: HTML, Sendable {
case .thermal:
ThermalFields(heatLossMode: heatLossMode)
case .economic:
div {
// FIX:
WarningBox("This is still under development and may not be fully functional.")
.attributes(.class("mb-6"))
}
EconomicFields()
}
div {
@@ -61,6 +57,29 @@ struct HeatingBalancePointForm: HTML, Sendable {
}
}
struct EconomicFields: HTML, Sendable {
var content: some HTML {
div(.class("grid grid-cols-1 lg:grid-cols-2 gap-4")) {
div {
InputLabel(for: "fuelType") { "Fuel Type" }
Select(for: HeatingBalancePoint.FuelType.self, id: "fuelType") { $0.label }
}
LabeledContent(label: "AFUE (%)") {
Input(id: "fuelAFUE", placeholder: "AFUE")
.attributes(.type(.number), .min("1"), .max("100"), .step("0.5"), .value("90"), .required)
}
LabeledContent(label: "Fuel Cost (gallon or therm)") {
Input(id: "fuelCostPerUnit", placeholder: "Fuel cost per unit")
.attributes(.type(.number), .min("0.1"), .step("0.01"), .value("1.33"), .required)
}
LabeledContent(label: "Electric Cost (kw/h)") {
Input(id: "costPerKW", placeholder: "Electric cost per kw/h")
.attributes(.type(.number), .min("0.01"), .step("0.01"), .value("0.13"), .required)
}
}
}
}
struct ThermalFields: HTML, Sendable {
let heatLossMode: HeatingBalancePoint.HeatLoss.Mode
@@ -175,6 +194,8 @@ struct HeatingBalancePointResponse: HTML, Sendable {
}
}
switch response {
case let .economic(result):
economicResult(result)
case let .thermal(result):
thermalResult(result)
}
@@ -184,6 +205,40 @@ struct HeatingBalancePointResponse: HTML, Sendable {
}
}
func economicResult(_ result: HeatingBalancePoint.Response.Economic) -> some HTML {
div {
VerticalGroup(
label: "Balance Point",
value: "\(double: result.balancePointTemperature, fractionDigits: 1)",
valueLabel: "°F"
)
.attributes(.class("mb-8"))
div(.class("grid grid-cols-2 space-y-6")) {
div {
VerticalGroup(
label: "Electric Cost",
value: "$\(double: result.electricCostPerMMBTU, fractionDigits: 2)",
valueLabel: "/ MMBTU"
)
}
div {
VerticalGroup(
label: "Fuel Cost",
value: "$\(double: result.fuelCostPerMMBTU, fractionDigits: 2)",
valueLabel: "/ MMBTU"
)
}
}
div {
VerticalGroup(
label: "COP at Balance Point",
value: "\(double: result.copAtBalancePoint, fractionDigits: 2)"
)
}
}
}
func thermalResult(_ result: HeatingBalancePoint.Response.Thermal) -> some HTML {
div {
VerticalGroup(
@@ -239,12 +294,14 @@ private extension HeatingBalancePoint.HeatLoss.Mode {
private extension HeatingBalancePoint.Response {
var mode: HeatingBalancePoint.Mode {
switch self {
case .economic: return .economic
case .thermal: return .thermal
}
}
var warnings: [String] {
switch self {
case .economic: return []
case let .thermal(result): return result.warnings
}
}