215 lines
7.0 KiB
Lua
215 lines
7.0 KiB
Lua
-- AD Runs
|
|
-- Rene funktioner (ingen spil-API) for "runs": navn, aflæsningsmål, varer, Wait-pulje,
|
|
-- loop-tæller og tildelte traktorer. Alle funktioner returnerer en NY store —
|
|
-- input røres aldrig, så GUI og controller kan holde referencer uden overraskelser.
|
|
|
|
ADRuns = {}
|
|
|
|
ADRuns.MAX_LOOPS = 99
|
|
-- "Kør hjem fra Wait når målet er under X %": 10..90, standard 50 (= den gamle 50 %-regel).
|
|
ADRuns.DEFAULT_RETURN_BELOW_PERCENT = 50
|
|
ADRuns.MIN_RETURN_BELOW_PERCENT, ADRuns.MAX_RETURN_BELOW_PERCENT = 10, 90
|
|
ADRuns.XML_VERSION = 1
|
|
ADRuns.INGREDIENT_MODES = {auto = true, manual = true}
|
|
|
|
local function copyList(list)
|
|
local copy = {}
|
|
for index, value in ipairs(list or {}) do
|
|
copy[index] = value
|
|
end
|
|
return copy
|
|
end
|
|
|
|
local function copyRun(run)
|
|
return {
|
|
id = run.id,
|
|
name = run.name,
|
|
targetWayPointId = run.targetWayPointId,
|
|
ingredientMode = run.ingredientMode,
|
|
ingredients = copyList(run.ingredients),
|
|
waitPoolGroup = run.waitPoolGroup,
|
|
loops = run.loops,
|
|
returnBelowPercent = run.returnBelowPercent,
|
|
vehicleIds = copyList(run.vehicleIds),
|
|
}
|
|
end
|
|
|
|
local function copyStore(store)
|
|
local runs = {}
|
|
for index, run in ipairs(store.runs) do
|
|
runs[index] = copyRun(run)
|
|
end
|
|
return {nextId = store.nextId, runs = runs}
|
|
end
|
|
|
|
local function clampPercent(percent)
|
|
local value = tonumber(percent) or ADRuns.DEFAULT_RETURN_BELOW_PERCENT
|
|
return math.max(ADRuns.MIN_RETURN_BELOW_PERCENT, math.min(ADRuns.MAX_RETURN_BELOW_PERCENT, math.floor(value)))
|
|
end
|
|
|
|
local function clampLoops(loops)
|
|
local value = tonumber(loops) or 0
|
|
return math.max(0, math.min(ADRuns.MAX_LOOPS, math.floor(value)))
|
|
end
|
|
|
|
function ADRuns.newStore()
|
|
return {nextId = 1, runs = {}}
|
|
end
|
|
|
|
function ADRuns.createRun(store, name)
|
|
local new = copyStore(store)
|
|
local run = {
|
|
id = new.nextId,
|
|
name = name,
|
|
targetWayPointId = nil,
|
|
ingredientMode = "auto",
|
|
ingredients = {},
|
|
waitPoolGroup = "",
|
|
loops = 0,
|
|
returnBelowPercent = ADRuns.DEFAULT_RETURN_BELOW_PERCENT,
|
|
vehicleIds = {},
|
|
}
|
|
new.nextId = new.nextId + 1
|
|
table.insert(new.runs, run)
|
|
return new, run
|
|
end
|
|
|
|
function ADRuns.getRun(store, runId)
|
|
for _, run in ipairs(store.runs) do
|
|
if run.id == runId then
|
|
return run
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
function ADRuns.deleteRun(store, runId)
|
|
local new = copyStore(store)
|
|
for index, run in ipairs(new.runs) do
|
|
if run.id == runId then
|
|
table.remove(new.runs, index)
|
|
break
|
|
end
|
|
end
|
|
return new
|
|
end
|
|
|
|
-- changes: delmængde af {name, targetWayPointId, ingredientMode, ingredients, waitPoolGroup, loops}.
|
|
function ADRuns.updateRun(store, runId, changes)
|
|
local new = copyStore(store)
|
|
local run = ADRuns.getRun(new, runId)
|
|
if run == nil then
|
|
return new
|
|
end
|
|
if changes.name ~= nil then run.name = changes.name end
|
|
-- false = ryd målet (nil i changes betyder "rør ikke")
|
|
if changes.targetWayPointId == false then
|
|
run.targetWayPointId = nil
|
|
elseif changes.targetWayPointId ~= nil then
|
|
run.targetWayPointId = changes.targetWayPointId
|
|
end
|
|
if ADRuns.INGREDIENT_MODES[changes.ingredientMode] then run.ingredientMode = changes.ingredientMode end
|
|
if changes.ingredients ~= nil then run.ingredients = copyList(changes.ingredients) end
|
|
if changes.waitPoolGroup ~= nil then run.waitPoolGroup = changes.waitPoolGroup end
|
|
if changes.loops ~= nil then run.loops = clampLoops(changes.loops) end
|
|
if changes.returnBelowPercent ~= nil then run.returnBelowPercent = clampPercent(changes.returnBelowPercent) end
|
|
return new
|
|
end
|
|
|
|
function ADRuns.findRunByVehicle(store, vehicleId)
|
|
for _, run in ipairs(store.runs) do
|
|
for _, id in ipairs(run.vehicleIds) do
|
|
if id == vehicleId then
|
|
return run
|
|
end
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
function ADRuns.unassignVehicle(store, vehicleId)
|
|
local new = copyStore(store)
|
|
for _, run in ipairs(new.runs) do
|
|
for index, id in ipairs(run.vehicleIds) do
|
|
if id == vehicleId then
|
|
table.remove(run.vehicleIds, index)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
return new
|
|
end
|
|
|
|
-- En traktor er kun i ét run. Returnerer ny store + id på det run den blev flyttet FRA (nil = ingen).
|
|
function ADRuns.assignVehicle(store, runId, vehicleId)
|
|
local previous = ADRuns.findRunByVehicle(store, vehicleId)
|
|
if previous ~= nil and previous.id == runId then
|
|
return copyStore(store), nil
|
|
end
|
|
local new = ADRuns.unassignVehicle(store, vehicleId)
|
|
local run = ADRuns.getRun(new, runId)
|
|
if run == nil then
|
|
return new, nil
|
|
end
|
|
table.insert(run.vehicleIds, vehicleId)
|
|
return new, previous ~= nil and previous.id or nil
|
|
end
|
|
|
|
-- Varer gemmes som mellemrumsadskilte fillType-NAVNE ("STRAW FORAGE") — navne er
|
|
-- stabile på tværs af mods/kort, fillType-indeks er det ikke.
|
|
function ADRuns.serializeIngredients(list)
|
|
return table.concat(list or {}, " ")
|
|
end
|
|
|
|
function ADRuns.parseIngredients(text)
|
|
local list = {}
|
|
for name in string.gmatch(tostring(text or ""), "%S+") do
|
|
table.insert(list, name)
|
|
end
|
|
return list
|
|
end
|
|
|
|
-- Flade poster (kun strenge/tal) til XML-laget, i store'ens rækkefølge.
|
|
function ADRuns.toRecords(store)
|
|
local records = {}
|
|
for index, run in ipairs(store.runs) do
|
|
records[index] = {
|
|
id = run.id,
|
|
name = run.name,
|
|
target = run.targetWayPointId or 0,
|
|
ingredientMode = run.ingredientMode,
|
|
ingredients = ADRuns.serializeIngredients(run.ingredients),
|
|
waitPool = run.waitPoolGroup,
|
|
loops = run.loops,
|
|
returnBelow = run.returnBelowPercent,
|
|
vehicleIds = copyList(run.vehicleIds),
|
|
}
|
|
end
|
|
return records
|
|
end
|
|
|
|
-- Poster uden gyldigt id/navn eller med dublet-id springes over; nextId = højeste id + 1.
|
|
function ADRuns.fromRecords(records)
|
|
local store = ADRuns.newStore()
|
|
for _, record in ipairs(records or {}) do
|
|
local id = tonumber(record.id)
|
|
local isValid = id ~= nil and id >= 1 and record.name ~= nil and record.name ~= ""
|
|
if isValid and ADRuns.getRun(store, id) == nil then
|
|
local target = tonumber(record.target)
|
|
table.insert(store.runs, {
|
|
id = id,
|
|
name = record.name,
|
|
targetWayPointId = target ~= nil and target > 0 and target or nil,
|
|
ingredientMode = ADRuns.INGREDIENT_MODES[record.ingredientMode] and record.ingredientMode or "auto",
|
|
ingredients = ADRuns.parseIngredients(record.ingredients),
|
|
waitPoolGroup = record.waitPool or "",
|
|
loops = clampLoops(record.loops),
|
|
returnBelowPercent = clampPercent(record.returnBelow),
|
|
vehicleIds = copyList(record.vehicleIds),
|
|
})
|
|
store.nextId = math.max(store.nextId, id + 1)
|
|
end
|
|
end
|
|
return store
|
|
end
|