Files
fs25-adsmartpickup/FS25_ADSmartPickup/adFieldSilos.lua
T

527 lines
25 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- AD Field Silos
-- Marksilo-flowet i spillet: samler marksiloer, gårdlagre og ledige vogne, lader ADFieldSiloPlanner vælge,
-- med "kør til produktion" går overskud ud over gårdens foderreserve til gårdens fabrikker;
-- låner vogne (AutoDrive "Hent og aflever", én tur, parkering bagefter) og frigiver dem igen.
-- Lån ligger kun i hukommelsen; opsætningen gemmes i ADSmartPickup_fieldsilos.xml.
ADFieldSilos = {}
ADFieldSilos.PLAN_INTERVAL_MS = 60000
ADFieldSilos.CHECK_INTERVAL_MS = 2000
ADFieldSilos.STUCK_MS = 120000
ADFieldSilos.PAUSE_MS = 600000
ADFieldSilos.FAIL_MS = 30000 -- AD slukket inden for 30 s uden fremdrift = turen kunne ikke køres
ADFieldSilos.CARGO_MIN_LITERS = 100 -- rest under dette tæller ikke som last
-- Silo så tæt på et gårdlager er en del af gården (Farma-siloer deler lager inden for 50 m): ikke marksilo.
-- (in-game 27/9: sukkerroer blev kørt fra én Farma-silo til nabosiloen i samme klynge)
ADFieldSilos.FARM_RADIUS = 100
-- Siloer højst så langt fra en nabo hører til samme klynge (Farma-rækker: 15 m mellem siloer, 18 m mellem rækker)
ADFieldSilos.CLUSTER_LINK = 60
ADFieldSilos.MOVING_SPEED = 0.00028 -- m/ms, samme grænse som AutoDrive
ADFieldSilos.FILE_NAME = "ADSmartPickup_fieldsilos.xml"
ADFieldSilos.ROOT = "ADSmartPickupFieldSilos"
ADFieldSilos.LOG_PREFIX = "ADSmartPickup: marksilo: "
ADFieldSilos.config = ADFieldSiloConfig.new()
ADFieldSilos.lastPlan = nil
local loans = setmetatable({}, {__mode = "k"}) -- vehicle -> {siloId, siloName, fillType, liters, startedMs, lastProgressMs, lastFill}
local paused = {} -- key -> untilMs
local planTimerMs, checkTimerMs, nowMs = ADFieldSilos.PLAN_INTERVAL_MS, 0, 0
-- ---- ren frigivelsesregel ----
-- vehicleState = {adActive, controlled, fill, moving}. Fremdrift = kører, eller fyldningen ændrer sig (læsser
-- eller aflæsser). Vagten gælder kun før turen er kommet i gang — kø ved siloen/lageret er normalt.
function ADFieldSilos.releaseReason(loan, vehicleState, now)
if vehicleState.controlled then return "player" end
local progressing = vehicleState.moving or (vehicleState.fill or 0) ~= (loan.lastFill or 0)
local hasProgressed = loan.hasProgressed or progressing
local age = now - (loan.startedMs or 0)
if not vehicleState.adActive then
return (not hasProgressed and age < ADFieldSilos.FAIL_MS) and "failed" or "done"
end
if hasProgressed then return nil end
if age > ADFieldSilos.STUCK_MS then return "stuck" end
return nil
end
-- ---- opsætning ----
function ADFieldSilos.setConfig(cfg)
local wasEnabled = ADFieldSilos.config.enabled
ADFieldSilos.config = cfg
if wasEnabled and not cfg.enabled then ADFieldSilos.stopAll(ADFieldSilos.adEnv) end
planTimerMs = ADFieldSilos.PLAN_INTERVAL_MS -- planlæg straks ved næste tick
end
function ADFieldSilos.isLoaned(vehicle)
return loans[vehicle] ~= nil
end
function ADFieldSilos.loanCount()
local n = 0
for _ in pairs(loans) do n = n + 1 end
return n
end
-- ---- spil-input ----
local function farmId()
return g_currentMission ~= nil and g_currentMission.getFarmId ~= nil and g_currentMission:getFarmId() or 1
end
local function position(node)
if node == nil then return 0, 0 end
local x, _, z = getWorldTranslation(node)
return x, z
end
local function siloStock(placeable)
local stock = {}
local spec = placeable ~= nil and placeable.spec_silo or nil
for _, storage in pairs(spec ~= nil and spec.storages or {}) do
for fillType, level in pairs(storage.fillLevels or {}) do
if (level or 0) > 0 then stock[fillType] = (stock[fillType] or 0) + level end
end
end
return stock
end
local function siloFree(placeable)
local free = {}
local spec = placeable ~= nil and placeable.spec_silo or nil
for _, storage in pairs(spec ~= nil and spec.storages or {}) do
for fillType in pairs(storage.fillTypes or {}) do
local amount = storage.getFreeCapacity ~= nil and (storage:getFreeCapacity(fillType) or 0) or 0
free[fillType] = (free[fillType] or 0) + amount
end
end
return free
end
local function firstMarker(building, role)
local markers = ADBuildings.getMarkers(building, role)
return markers[1] ~= nil and markers[1].id or nil
end
-- Bygninger der er kilde, mål eller lager i et flow: dem tømmer marksilo-flowet ikke (de hører til den drift).
local function runBuildingIds()
local ids = {}
local store = ADRunsController ~= nil and ADRunsController.store or nil
for _, run in ipairs(store ~= nil and store.runs or {}) do
for _, list in ipairs({run.sourceBuildingIds or {}, run.targetBuildingIds or {}, run.storeBuildingIds or {}}) do
for _, id in ipairs(list) do ids[id] = true end
end
end
return ids
end
-- Alle siloer i samme klynge som et gårdlager (kæde af naboer ≤ CLUSTER_LINK): gårdens, aldrig marksiloer.
-- (in-game 27/9: gårdens Farma-klynge er ~300 m lang; siloer over 100 m fra et valgt lager blev marksiloer)
local function farmCluster(allSilos, storeIds)
local farm, queue = {}, {}
for _, silo in ipairs(allSilos) do
if storeIds[silo.id] then farm[silo.id] = true; table.insert(queue, silo) end
end
local link2 = ADFieldSilos.CLUSTER_LINK ^ 2
while #queue > 0 do
local current = table.remove(queue)
for _, silo in ipairs(allSilos) do
if not farm[silo.id] and (silo.x - current.x) ^ 2 + (silo.z - current.z) ^ 2 <= link2 then
farm[silo.id] = true
table.insert(queue, silo)
end
end
end
return farm
end
local function nearStore(stores, x, z)
for _, store in ipairs(stores) do
if (store.x - x) ^ 2 + (store.z - z) ^ 2 <= ADFieldSilos.FARM_RADIUS ^ 2 then return true end
end
return false
end
-- Fabrikkens input-varer (dem aflæsningen tager imod) med fri plads i dens lager.
local function factoryFree(placeable)
local spec = placeable ~= nil and placeable.spec_productionPoint or nil
local point = spec ~= nil and spec.productionPoint or nil
local storage = point ~= nil and point.storage or nil
if storage == nil or storage.getFreeCapacity == nil then return {} end
local inputs = {}
for fillType in pairs(point.inputFillTypeIds or {}) do inputs[fillType] = true end
for _, production in ipairs(point.productions or {}) do
for _, input in ipairs(production.inputs or {}) do inputs[input.type] = true end
end
local free = {}
for fillType in pairs(inputs) do free[fillType] = storage:getFreeCapacity(fillType) or 0 end
return free
end
-- "Kør til produktion": gårdens fabrikker med aflæsningsmarkør bliver mål ved siden af gårdlagrene.
local function addFactories(stores, buildings)
for _, building in ipairs(buildings) do
local markerId = building.kind == "factory" and firstMarker(building, "unload") or nil
if markerId ~= nil then
local x, z = position(building.placeable ~= nil and building.placeable.rootNode or nil)
table.insert(stores, {id = building.id, name = building.name, kind = "production", markerId = markerId,
x = x, z = z, free = factoryFree(building.placeable)})
end
end
end
-- Foderreserve (staldenes døgnforbrug × døgn) og gårdlagrenes beholdning pr. vare.
function ADFieldSilos.collectFeed(stores, byId, fid, reserveDays)
local reserve, stock = {}, {}
local rates = ADSources ~= nil and ADSources.getFarmRates ~= nil and ADSources.getFarmRates(ADFieldSilos.adEnv, fid, true) or {}
for fillType, rate in pairs(rates) do reserve[fillType] = (rate.consumption or 0) * reserveDays end
local counted = {} -- Farma-siloer i samme klynge deler lager: tæl hvert lager én gang
for _, store in ipairs(stores) do
local building = byId[store.id]
local spec = store.kind ~= "production" and building ~= nil and building.placeable ~= nil and building.placeable.spec_silo or nil
for _, storage in pairs(spec ~= nil and spec.storages or {}) do
if not counted[storage] then
counted[storage] = true
for fillType, level in pairs(storage.fillLevels or {}) do stock[fillType] = (stock[fillType] or 0) + (level or 0) end
end
end
end
return reserve, stock
end
-- Gårdlagre fra opsætningen + marksiloer (alle markers marksiloer, uden dubletter og uden gårdlagre).
function ADFieldSilos.collectBuildings(adEnv)
local fid = farmId()
local stores, byId, allSilos, storeIds = {}, {}, {}, {}
for _, building in ipairs(ADBuildings.list(adEnv, fid)) do
byId[building.id] = building
if building.kind == "silo" then
local sx, sz = position(building.placeable ~= nil and building.placeable.rootNode or nil)
table.insert(allSilos, {id = building.id, x = sx, z = sz})
if ADFieldSiloConfig.hasStore(ADFieldSilos.config, building.id) then storeIds[building.id] = true end
end
if building.kind == "silo" and ADFieldSiloConfig.hasStore(ADFieldSilos.config, building.id) then
local x, z = position(building.placeable ~= nil and building.placeable.rootNode or nil)
table.insert(stores, {id = building.id, name = building.name, markerId = firstMarker(building, "unload"),
x = x, z = z, free = siloFree(building.placeable)})
end
end
if ADFieldSilos.config.toProduction then addFactories(stores, ADBuildings.list(adEnv, fid)) end
local silos, seen = {}, runBuildingIds()
for id in pairs(farmCluster(allSilos, storeIds)) do seen[id] = true end
for _, info in ipairs(ADFields.list()) do
for _, building in ipairs(ADFields.fieldSilos(adEnv, fid, info)) do
local x, z = position(building.placeable ~= nil and building.placeable.rootNode or nil)
if not seen[building.id] and not ADFieldSiloConfig.hasStore(ADFieldSilos.config, building.id) and not nearStore(stores, x, z) then
seen[building.id] = true
-- marknummeret først: navnet skæres af i fanen, og mange siloer hedder ens ("Farma 500 …")
-- marknummeret først (medmindre navnet allerede starter med det, fx "F22 marksilo")
local siloName = tostring(building.name)
if not siloName:match("^F" .. tostring(info.id) .. "%f[%D]") then siloName = string.format("F%s %s", tostring(info.id), siloName) end
table.insert(silos, {id = building.id, name = siloName, markerId = firstMarker(building, "load"),
x = x, z = z, stock = siloStock(building.placeable)})
end
end
end
return silos, stores, byId
end
local function trailerInfo(adEnv, vehicle)
local capacity, carries, cargo = 0, {}, nil
for _, unit in ipairs(adEnv.AutoDrive.getAllDischargeableUnits(vehicle) or {}) do
local object, index = unit.object, unit.fillUnitIndex
if object ~= nil and object.getFillUnitCapacity ~= nil then
capacity = capacity + (object:getFillUnitCapacity(index) or 0)
for fillType in pairs(object.getFillUnitSupportedFillTypes ~= nil and object:getFillUnitSupportedFillTypes(index) or {}) do
carries[fillType] = true
end
if (object:getFillUnitFillLevel(index) or 0) >= ADFieldSilos.CARGO_MIN_LITERS then cargo = object:getFillUnitFillType(index) end
end
end
return capacity, carries, cargo
end
local function fillLevel(adEnv, vehicle)
local ok, level = pcall(function() return (adEnv.AutoDrive.getAllFillLevels(adEnv.AutoDrive.getAllUnits(vehicle))) end)
return ok and tonumber(level) or 0
end
function ADFieldSilos.collectVehicles(adEnv)
local vehicles, byId = {}, {}
-- hvorfor tømmevogne ikke kan lånes (til fanens statuslinje)
local why = {notEnabled = 0, busy = 0, controlled = 0, noPark = 0}
local rigs = ADFieldWork.getRigs(adEnv)
for _, rig in ipairs(rigs) do
-- uden AD-parkeringspunkt bliver vognen holdende på lagerets markør og spærrer for de næste
local canPark = ADFieldWork.parkMarkerId == nil or ADFieldWork.parkMarkerId(adEnv, rig.vehicle) ~= nil
if rig.role == "unloader" then
if not rig.enabled then why.notEnabled = why.notEnabled + 1
elseif rig.controlled then why.controlled = why.controlled + 1
elseif rig.busy then why.busy = why.busy + 1
elseif not canPark then why.noPark = why.noPark + 1 end
end
if rig.role == "unloader" and rig.enabled and not rig.busy and not rig.controlled and canPark then
local capacity, carries, cargo = trailerInfo(adEnv, rig.vehicle)
table.insert(vehicles, {id = rig.id, x = rig.x, z = rig.z, capacity = capacity, carries = carries, cargo = cargo})
byId[rig.id] = rig.vehicle
end
end
local ok, needs = pcall(ADFieldSilos.harvestNeeds, adEnv, rigs)
if ok and #needs > 0 then
local before = #vehicles
vehicles = ADFieldSiloPlanner.withoutHarvestReserve(vehicles, needs)
why.harvest = before - #vehicles
elseif not ok then
Logging.warning(ADFieldSilos.LOG_PREFIX .. "høstreserve kunne ikke beregnes: %s", tostring(needs))
end
why.eligible = #vehicles
ADFieldSilos.lastVehicleReasons = why
return vehicles, byId
end
-- Høsten først: pr. høster der arbejder (CP kører) holdes dens planlagte antal tømmevogne tilbage, minus dem
-- markarbejdet allerede har sendt til marken. (in-game 28/9: marksilo-flowet havde lånt begge kartoffelvogne,
-- og ingen kom til roeoptagerne.)
function ADFieldSilos.harvestNeeds(adEnv, rigs)
local assignments = ADFieldJobs ~= nil and ADFieldJobs.state ~= nil and ADFieldJobs.state.assignments or {}
local sent = {}
for _, assignment in pairs(assignments) do
if assignment.role == "unloader" and assignment.fieldId ~= nil then sent[assignment.fieldId] = (sent[assignment.fieldId] or 0) + 1 end
end
local needs = {}
for _, rig in ipairs(rigs) do
if rig.role == "harvester" and ADCpBridge.isWorking(rig.vehicle) then
local assignment = assignments[rig.id]
local fieldId = assignment ~= nil and assignment.fieldId or nil
local field = fieldId ~= nil and ADFieldJobs.getField(fieldId) or nil
local info = fieldId ~= nil and ADFields.getInfo(fieldId) or nil
local count = field ~= nil and ADFieldModel.maxHelpers("harvesting", field.plan) or 1
count = count - (fieldId ~= nil and (sent[fieldId] or 0) or 0)
local fillTypes = {}
if info ~= nil and info.harvestFillType ~= nil then
fillTypes[info.harvestFillType] = true
else
for fruitIndex in pairs(rig.fruits or {}) do
local fruit = g_fruitTypeManager ~= nil and g_fruitTypeManager:getFruitTypeByIndex(fruitIndex) or nil
if fruit ~= nil and fruit.fillType ~= nil then fillTypes[fruit.fillType.index] = true end
end
end
for fillType in pairs(fillTypes) do
if count > 0 then table.insert(needs, {fillType = fillType, count = count}) end
end
end
end
return needs
end
-- ---- lån ----
local function fillTypeName(fillType)
local desc = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeByIndex(fillType) or nil
return desc ~= nil and (desc.title or desc.name) or tostring(fillType)
end
local function dispatchOne(adEnv, order, vehicle, silosById, storesById)
local module = vehicle.ad.stateModule
module:setMode(adEnv.AutoDrive.MODE_PICKUPANDDELIVER)
module:setFirstMarkerByWayPointId(order.siloMarkerId)
module:setSecondMarkerByWayPointId(order.storeMarkerId)
module.selectedFillTypes = {order.fillType}
module:setFillType(order.fillType)
module.loopCounter = 1
if module.setLoopsDone ~= nil then module:setLoopsDone(0) end
ADFieldWork.enableParkAtJobFinished(vehicle)
-- rotation fra: ellers kan modens egne pickup-hooks sende vognen til en anden silo i mappen
if ADRunsController ~= nil and ADRunsController.setSetting ~= nil then
ADRunsController.setSetting(adEnv, vehicle, "rotateTargets", adEnv.AutoDrive.RT_NONE)
end
module:raiseDirtyFlag()
ADFieldWork.startAd(adEnv, vehicle, adEnv.AutoDrive.MODE_PICKUPANDDELIVER, order.siloMarkerId, order.storeMarkerId, order.fillType)
local silo, store = silosById[order.siloId], storesById[order.storeId]
loans[vehicle] = {siloId = order.siloId, storeId = order.storeId, siloName = silo ~= nil and silo.name or order.siloId, fillType = order.fillType,
liters = order.liters, startedMs = nowMs, lastProgressMs = nowMs, lastFill = fillLevel(adEnv, vehicle)}
Logging.info(ADFieldSilos.LOG_PREFIX .. "'%s' henter %d l %s i %s -> %s", tostring(ADRuns.vehicleLabel(vehicle)),
math.floor(order.liters), fillTypeName(order.fillType), tostring(silo ~= nil and silo.name or order.siloId),
tostring(store ~= nil and store.name or order.storeId))
end
local function release(adEnv, vehicle, reason)
local loan = loans[vehicle]
loans[vehicle] = nil
if loan == nil then return end
if reason == "stuck" or reason == "failed" then
local k = ADFieldSiloPlanner.key(loan.siloId, loan.fillType)
paused[k] = nowMs + ADFieldSilos.PAUSE_MS
pcall(vehicle.stopAutoDrive, vehicle)
local why = reason == "stuck" and "kom ikke i gang på 2 min — stoppet" or "AutoDrive stoppede turen med det samme (rute/læssested?)"
Logging.warning(ADFieldSilos.LOG_PREFIX .. "'%s' ved %s (%s): %s; siloen springes over i 10 min",
tostring(ADRuns.vehicleLabel(vehicle)), tostring(loan.siloName), fillTypeName(loan.fillType), why)
elseif reason == "stopped" then
pcall(vehicle.stopAutoDrive, vehicle)
end
Logging.info(ADFieldSilos.LOG_PREFIX .. "'%s' frigivet (%s)", tostring(ADRuns.vehicleLabel(vehicle)), tostring(reason))
end
function ADFieldSilos.stopAll(adEnv)
local list = {}
for vehicle in pairs(loans) do table.insert(list, vehicle) end
for _, vehicle in ipairs(list) do release(adEnv, vehicle, "stopped") end
end
local function checkLoans(adEnv)
local list = {}
for vehicle in pairs(loans) do table.insert(list, vehicle) end
for _, vehicle in ipairs(list) do
if vehicle.isDeleted then
loans[vehicle] = nil -- solgt/slettet mens den var lånt
else
local ok, err = pcall(function()
local loan = loans[vehicle]
local stateModule = vehicle.ad ~= nil and vehicle.ad.stateModule or nil
local fill = fillLevel(adEnv, vehicle)
local vehicleState = {
adActive = stateModule ~= nil and stateModule:isActive(),
controlled = vehicle.getIsControlled ~= nil and vehicle:getIsControlled() or false,
fill = fill, moving = (vehicle.lastSpeedReal or 0) >= ADFieldSilos.MOVING_SPEED,
}
local reason = ADFieldSilos.releaseReason(loan, vehicleState, nowMs)
if vehicleState.moving or fill ~= (loan.lastFill or 0) then loan.hasProgressed = true end
loan.lastFill = fill
if reason ~= nil then release(adEnv, vehicle, reason) end
end)
if not ok then
loans[vehicle] = nil
Logging.warning(ADFieldSilos.LOG_PREFIX .. "lån opgivet (fejl): %s", tostring(err))
end
end
end
end
local function currentPaused()
local result = {}
for k, untilMs in pairs(paused) do
if untilMs > nowMs then result[k] = true else paused[k] = nil end
end
return result
end
local function loanList()
local list = {}
for _, loan in pairs(loans) do table.insert(list, {siloId = loan.siloId, storeId = loan.storeId, fillType = loan.fillType, liters = loan.liters}) end
return list
end
-- Rute fra vognen til siloen og videre til lageret (samme opslag som Wait-punkterne); én advarsel pr. kombination.
local warnedRoute = {}
local function hasRoutes(adEnv, vehicle, order)
if ADUnloadWait == nil or ADUnloadWait.hasRouteTo == nil then return true end
local ok = ADUnloadWait.hasRouteTo(adEnv, vehicle, order.siloMarkerId) and ADUnloadWait.hasRouteTo(adEnv, vehicle, order.storeMarkerId)
local warnKey = tostring(order.vehicleId) .. ">" .. tostring(order.siloMarkerId)
if not ok and not warnedRoute[warnKey] then
warnedRoute[warnKey] = true
Logging.warning(ADFieldSilos.LOG_PREFIX .. "ingen AutoDrive-rute for '%s' til marksilo-markør %s eller gårdlager-markør %s",
tostring(ADRuns.vehicleLabel(vehicle)), tostring(order.siloMarkerId), tostring(order.storeMarkerId))
end
return ok
end
function ADFieldSilos.planNow(adEnv)
local cfg = ADFieldSilos.config
local silos, stores, byId = ADFieldSilos.collectBuildings(adEnv)
local vehicles, vehiclesById = ADFieldSilos.collectVehicles(adEnv)
local feedReserve, farmStock = nil, nil
if cfg.toProduction then
local ok, reserve, stock = pcall(ADFieldSilos.collectFeed, stores, byId, farmId(), cfg.reserveDays)
if ok then feedReserve, farmStock = reserve, stock
else Logging.warning(ADFieldSilos.LOG_PREFIX .. "foderreserve kunne ikke beregnes: %s", tostring(reserve)) end
end
local plan = ADFieldSiloPlanner.plan({silos = silos, stores = stores, loans = loanList(), vehicles = vehicles,
paused = currentPaused(), maxVehicles = cfg.maxVehicles, minLiters = cfg.minLiters,
feedReserve = feedReserve, farmStock = farmStock})
ADFieldSilos.lastFeed = {reserve = feedReserve, stock = farmStock}
ADFieldSilos.lastPlan = plan
local paused = ADFieldJobs ~= nil and ADFieldJobs.state ~= nil and ADFieldJobs.state.paused
if not cfg.enabled or paused then return plan end
local silosById, storesById = {}, {}
for _, silo in ipairs(silos) do silosById[silo.id] = silo end
for _, store in ipairs(stores) do storesById[store.id] = store end
for _, order in ipairs(plan.dispatch) do
local vehicle = vehiclesById[order.vehicleId]
if vehicle ~= nil and not hasRoutes(adEnv, vehicle, order) then
vehicle = nil
end
if vehicle ~= nil then
local ok, err = pcall(dispatchOne, adEnv, order, vehicle, silosById, storesById)
if not ok then
loans[vehicle] = nil
Logging.warning(ADFieldSilos.LOG_PREFIX .. "kunne ikke sende '%s': %s", tostring(ADRuns.vehicleLabel(vehicle)), tostring(err))
end
end
end
return plan
end
function ADFieldSilos.tick(adEnv, dt)
if adEnv == nil then return end
ADFieldSilos.adEnv = adEnv
nowMs = nowMs + (dt or 0)
checkTimerMs = checkTimerMs + (dt or 0)
if checkTimerMs >= ADFieldSilos.CHECK_INTERVAL_MS then
checkTimerMs = 0
checkLoans(adEnv)
end
planTimerMs = planTimerMs + (dt or 0)
if planTimerMs >= ADFieldSilos.PLAN_INTERVAL_MS then
planTimerMs = 0
ADFieldSilos.planNow(adEnv)
end
end
-- ---- gem / indlæs (samme sti-opslag som runs) ----
local function getPath()
local path = ADRunsStorage ~= nil and ADRunsStorage.getPath() or nil
if path == nil then return nil end
return (path:gsub(ADRunsStorage.FILE_NAME .. "$", ADFieldSilos.FILE_NAME))
end
function ADFieldSilos.save()
local path = getPath()
if path == nil then return false end
local xmlFile = XMLFile.create("ADSmartPickupFieldSilos", path, ADFieldSilos.ROOT)
if xmlFile == nil then return false end
local record = ADFieldSiloConfig.toRecord(ADFieldSilos.config)
xmlFile:setInt(ADFieldSilos.ROOT .. "#enabled", record.enabled)
xmlFile:setString(ADFieldSilos.ROOT .. "#stores", record.stores)
xmlFile:setInt(ADFieldSilos.ROOT .. "#maxVehicles", record.maxVehicles)
xmlFile:setInt(ADFieldSilos.ROOT .. "#minLiters", record.minLiters)
xmlFile:setInt(ADFieldSilos.ROOT .. "#toProduction", record.toProduction)
xmlFile:setInt(ADFieldSilos.ROOT .. "#reserveDays", record.reserveDays)
xmlFile:save()
xmlFile:delete()
return true
end
function ADFieldSilos.load()
local path = getPath()
if path == nil or not fileExists(path) then
ADFieldSilos.config = ADFieldSiloConfig.new()
return
end
local xmlFile = XMLFile.load("ADSmartPickupFieldSilos", path)
if xmlFile == nil then
ADFieldSilos.config = ADFieldSiloConfig.new()
return
end
ADFieldSilos.config = ADFieldSiloConfig.fromRecord({
enabled = xmlFile:getInt(ADFieldSilos.ROOT .. "#enabled"),
stores = xmlFile:getString(ADFieldSilos.ROOT .. "#stores"),
maxVehicles = xmlFile:getInt(ADFieldSilos.ROOT .. "#maxVehicles"),
minLiters = xmlFile:getInt(ADFieldSilos.ROOT .. "#minLiters"),
toProduction = xmlFile:getInt(ADFieldSilos.ROOT .. "#toProduction"),
reserveDays = xmlFile:getInt(ADFieldSilos.ROOT .. "#reserveDays"),
})
xmlFile:delete()
end