271 lines
8.5 KiB
Swift
271 lines
8.5 KiB
Swift
import Foundation
|
|
import SwiftUI
|
|
import SwiftData
|
|
|
|
struct SystemComponentsPersistence {
|
|
static func createDefaultLoad(
|
|
for system: ElectricalSystem,
|
|
in context: ModelContext,
|
|
existingLoads: [SavedLoad],
|
|
existingBatteries: [SavedBattery],
|
|
existingChargers: [SavedCharger]
|
|
) -> SavedLoad {
|
|
let defaultName = String(
|
|
localized: "default.load.new",
|
|
comment: "Default name when creating a new load from system view"
|
|
)
|
|
let loadName = uniqueName(
|
|
startingWith: defaultName,
|
|
loads: existingLoads,
|
|
batteries: existingBatteries,
|
|
chargers: existingChargers
|
|
)
|
|
let newLoad = SavedLoad(
|
|
name: loadName,
|
|
voltage: 12.0,
|
|
current: 5.0,
|
|
power: 60.0,
|
|
length: 10.0,
|
|
crossSection: 1.0,
|
|
iconName: "lightbulb",
|
|
colorName: "blue",
|
|
isWattMode: false,
|
|
system: system,
|
|
remoteIconURLString: nil
|
|
)
|
|
context.insert(newLoad)
|
|
return newLoad
|
|
}
|
|
|
|
static func createLoad(
|
|
from item: ComponentLibraryItem,
|
|
for system: ElectricalSystem,
|
|
in context: ModelContext,
|
|
existingLoads: [SavedLoad],
|
|
existingBatteries: [SavedBattery],
|
|
existingChargers: [SavedCharger]
|
|
) -> SavedLoad {
|
|
let localizedName = item.localizedName
|
|
let baseName = localizedName.isEmpty ? "Library Load" : localizedName
|
|
let loadName = uniqueName(
|
|
startingWith: baseName,
|
|
loads: existingLoads,
|
|
batteries: existingBatteries,
|
|
chargers: existingChargers
|
|
)
|
|
let voltage = item.displayVoltage ?? 12.0
|
|
let power = item.watt ?? (item.current != nil ? item.current! * voltage : 0)
|
|
let current: Double
|
|
if let explicitCurrent = item.current {
|
|
current = explicitCurrent
|
|
} else if voltage > 0 {
|
|
current = power / voltage
|
|
} else {
|
|
current = 0
|
|
}
|
|
|
|
let affiliateLink = item.primaryAffiliateLink
|
|
|
|
let newLoad = SavedLoad(
|
|
name: loadName,
|
|
voltage: voltage,
|
|
current: current,
|
|
power: power,
|
|
length: 10.0,
|
|
crossSection: 1.0,
|
|
iconName: "lightbulb",
|
|
colorName: "blue",
|
|
isWattMode: item.watt != nil,
|
|
system: system,
|
|
remoteIconURLString: item.iconURL?.absoluteString,
|
|
affiliateURLString: affiliateLink?.url.absoluteString,
|
|
affiliateCountryCode: affiliateLink?.country
|
|
)
|
|
|
|
context.insert(newLoad)
|
|
return newLoad
|
|
}
|
|
|
|
static func makeBatteryDraft(
|
|
for system: ElectricalSystem,
|
|
existingLoads: [SavedLoad],
|
|
existingBatteries: [SavedBattery],
|
|
existingChargers: [SavedCharger]
|
|
) -> BatteryConfiguration {
|
|
let defaultName = NSLocalizedString(
|
|
"battery.editor.default_name",
|
|
bundle: .main,
|
|
value: "New Battery",
|
|
comment: "Default name when configuring a new battery"
|
|
)
|
|
let batteryName = uniqueName(
|
|
startingWith: defaultName,
|
|
loads: existingLoads,
|
|
batteries: existingBatteries,
|
|
chargers: existingChargers
|
|
)
|
|
return BatteryConfiguration(
|
|
name: batteryName,
|
|
iconName: "battery.100.bolt",
|
|
colorName: system.colorName,
|
|
system: system
|
|
)
|
|
}
|
|
|
|
static func makeChargerDraft(
|
|
for system: ElectricalSystem,
|
|
existingLoads: [SavedLoad],
|
|
existingBatteries: [SavedBattery],
|
|
existingChargers: [SavedCharger]
|
|
) -> ChargerConfiguration {
|
|
let defaultName = NSLocalizedString(
|
|
"charger.editor.default_name",
|
|
bundle: .main,
|
|
value: "New Charger",
|
|
comment: "Default name when configuring a new charger"
|
|
)
|
|
let chargerName = uniqueName(
|
|
startingWith: defaultName,
|
|
loads: existingLoads,
|
|
batteries: existingBatteries,
|
|
chargers: existingChargers
|
|
)
|
|
return ChargerConfiguration(
|
|
name: chargerName,
|
|
iconName: "bolt.fill",
|
|
colorName: system.colorName,
|
|
system: system
|
|
)
|
|
}
|
|
|
|
static func saveBattery(
|
|
_ configuration: BatteryConfiguration,
|
|
for system: ElectricalSystem,
|
|
existingBatteries: [SavedBattery],
|
|
in context: ModelContext
|
|
) {
|
|
if let existing = existingBatteries.first(where: { $0.id == configuration.id }) {
|
|
configuration.apply(to: existing)
|
|
} else {
|
|
let newBattery = SavedBattery(
|
|
id: configuration.id,
|
|
name: configuration.name,
|
|
nominalVoltage: configuration.nominalVoltage,
|
|
capacityAmpHours: configuration.capacityAmpHours,
|
|
chemistry: configuration.chemistry,
|
|
usableCapacityOverrideFraction: configuration.usableCapacityOverrideFraction,
|
|
chargeVoltage: configuration.chargeVoltage,
|
|
cutOffVoltage: configuration.cutOffVoltage,
|
|
minimumTemperatureCelsius: configuration.minimumTemperatureCelsius,
|
|
maximumTemperatureCelsius: configuration.maximumTemperatureCelsius,
|
|
iconName: configuration.iconName,
|
|
colorName: configuration.colorName,
|
|
system: system
|
|
)
|
|
context.insert(newBattery)
|
|
}
|
|
}
|
|
|
|
static func saveCharger(
|
|
_ configuration: ChargerConfiguration,
|
|
for system: ElectricalSystem,
|
|
existingChargers: [SavedCharger],
|
|
in context: ModelContext
|
|
) {
|
|
if let existing = existingChargers.first(where: { $0.id == configuration.id }) {
|
|
configuration.apply(to: existing)
|
|
} else {
|
|
let newCharger = SavedCharger(
|
|
id: configuration.id,
|
|
name: configuration.name,
|
|
inputVoltage: configuration.inputVoltage,
|
|
outputVoltage: configuration.outputVoltage,
|
|
maxCurrentAmps: configuration.maxCurrentAmps,
|
|
maxPowerWatts: configuration.maxPowerWatts,
|
|
iconName: configuration.iconName,
|
|
colorName: configuration.colorName,
|
|
system: system
|
|
)
|
|
context.insert(newCharger)
|
|
}
|
|
}
|
|
|
|
static func deleteBatteries(
|
|
at offsets: IndexSet,
|
|
from batteries: [SavedBattery],
|
|
in context: ModelContext
|
|
) {
|
|
for index in offsets {
|
|
context.delete(batteries[index])
|
|
}
|
|
}
|
|
|
|
static func deleteChargers(
|
|
at offsets: IndexSet,
|
|
from chargers: [SavedCharger],
|
|
in context: ModelContext
|
|
) {
|
|
for index in offsets {
|
|
context.delete(chargers[index])
|
|
}
|
|
}
|
|
|
|
static func uniqueName(
|
|
startingWith baseName: String,
|
|
loads: [SavedLoad],
|
|
batteries: [SavedBattery],
|
|
chargers: [SavedCharger]
|
|
) -> String {
|
|
let existingNames = Set(
|
|
loads.map { $0.name } +
|
|
batteries.map { $0.name } +
|
|
chargers.map { $0.name }
|
|
)
|
|
|
|
if !existingNames.contains(baseName) {
|
|
return baseName
|
|
}
|
|
|
|
var counter = 2
|
|
var candidate = "\(baseName) \(counter)"
|
|
|
|
while existingNames.contains(candidate) {
|
|
counter += 1
|
|
candidate = "\(baseName) \(counter)"
|
|
}
|
|
|
|
return candidate
|
|
}
|
|
|
|
static func createDefaultCharger(
|
|
for system: ElectricalSystem,
|
|
in context: ModelContext,
|
|
existingLoads: [SavedLoad],
|
|
existingBatteries: [SavedBattery],
|
|
existingChargers: [SavedCharger]
|
|
) -> SavedCharger {
|
|
let defaultName = String(
|
|
localized: "charger.default.new",
|
|
bundle: .main,
|
|
comment: "Default name when creating a new charger from system view"
|
|
)
|
|
let chargerName = uniqueName(
|
|
startingWith: defaultName,
|
|
loads: existingLoads,
|
|
batteries: existingBatteries,
|
|
chargers: existingChargers
|
|
)
|
|
let charger = SavedCharger(
|
|
name: chargerName,
|
|
inputVoltage: 230,
|
|
outputVoltage: 14.4,
|
|
maxCurrentAmps: 30,
|
|
iconName: "bolt.fill",
|
|
colorName: system.colorName,
|
|
system: system
|
|
)
|
|
context.insert(charger)
|
|
return charger
|
|
}
|
|
}
|