120 lines
4.3 KiB
Lua
120 lines
4.3 KiB
Lua
-- AD Flow View
|
|
-- Rene regler for Flows-fanens oprydning (ingen spil-API): tavlens grupper og rækkefølge, hvilke
|
|
-- traktorer og bygninger der vises som standard, og hvad "Vis alle" tilføjer.
|
|
|
|
ADFlowView = {}
|
|
|
|
-- Naturlig sortering: tal i navne sammenlignes som tal ("Biogas 9" < "Biogas 10").
|
|
local function naturalKey(text)
|
|
local parts = {}
|
|
local value = string.lower(tostring(text or ""))
|
|
local position = 1
|
|
while position <= #value do
|
|
local digits = string.match(value, "^%d+", position)
|
|
if digits ~= nil then
|
|
table.insert(parts, {number = tonumber(digits)})
|
|
position = position + #digits
|
|
else
|
|
local chunk = string.match(value, "^%D+", position)
|
|
table.insert(parts, {text = chunk})
|
|
position = position + #chunk
|
|
end
|
|
end
|
|
return parts
|
|
end
|
|
|
|
function ADFlowView.naturalLess(a, b)
|
|
local ka, kb = naturalKey(a), naturalKey(b)
|
|
for index = 1, math.max(#ka, #kb) do
|
|
local pa, pb = ka[index], kb[index]
|
|
if pa == nil then return true end
|
|
if pb == nil then return false end
|
|
if pa.number ~= nil and pb.number ~= nil then
|
|
if pa.number ~= pb.number then return pa.number < pb.number end
|
|
elseif pa.number ~= nil or pb.number ~= nil then
|
|
return pa.number ~= nil
|
|
elseif pa.text ~= pb.text then
|
|
return pa.text < pb.text
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function sortedBy(list, field)
|
|
local copy = {}
|
|
for _, item in ipairs(list or {}) do table.insert(copy, item) end
|
|
table.sort(copy, function(a, b)
|
|
if a[field] ~= b[field] then return ADFlowView.naturalLess(a[field], b[field]) end
|
|
return tostring(a.id) < tostring(b.id)
|
|
end)
|
|
return copy
|
|
end
|
|
|
|
-- Tavlen: forsyning ("Ind til bygning") først, så udkørsel ("Ud fra bygning"); hver gruppe efter navn.
|
|
-- {{kind, runs}, ...}; tomme grupper udelades.
|
|
function ADFlowView.boardGroups(runs)
|
|
local byKind = {supply = {}, outbound = {}}
|
|
for _, run in ipairs(runs or {}) do
|
|
table.insert(byKind[run.kind == "outbound" and "outbound" or "supply"], run)
|
|
end
|
|
local groups = {}
|
|
for _, kind in ipairs({"supply", "outbound"}) do
|
|
if #byKind[kind] > 0 then
|
|
table.insert(groups, {kind = kind, runs = sortedBy(byKind[kind], "name")})
|
|
end
|
|
end
|
|
return groups
|
|
end
|
|
|
|
-- Samme rækkefølge som tavlen, som én liste (flow-vælgeren).
|
|
function ADFlowView.orderedRuns(runs)
|
|
local result = {}
|
|
for _, group in ipairs(ADFlowView.boardGroups(runs)) do
|
|
for _, run in ipairs(group.runs) do table.insert(result, run) end
|
|
end
|
|
return result
|
|
end
|
|
|
|
-- Traktorer: vehicles = {{id, label, state = "in"|"free"|"other"|"blocked"}}. Standard: flowets egne,
|
|
-- så ledige der kan bruges. showAll tilføjer traktorer i andre flows og låste (vogn passer ikke).
|
|
local STATE_ORDER = {"in", "free", "other", "blocked"}
|
|
|
|
function ADFlowView.vehicleRows(vehicles, showAll)
|
|
local byState = {}
|
|
for _, entry in ipairs(vehicles or {}) do
|
|
byState[entry.state] = byState[entry.state] or {}
|
|
table.insert(byState[entry.state], entry)
|
|
end
|
|
local rows = {}
|
|
for _, state in ipairs(STATE_ORDER) do
|
|
if showAll or state == "in" or state == "free" then
|
|
for _, entry in ipairs(sortedBy(byState[state], "label")) do table.insert(rows, entry) end
|
|
end
|
|
end
|
|
return rows
|
|
end
|
|
|
|
function ADFlowView.hiddenCount(all, shown)
|
|
return #(all or {}) - #(shown or {})
|
|
end
|
|
|
|
-- Bygninger: buildings = {{id, name, hasMarker}}, chosen = {[id] = true}. Valgte først; bygninger uden
|
|
-- markør kun hvis valgte eller showAll (de kan alligevel ikke bruges før en markør er sat).
|
|
function ADFlowView.buildingRows(buildings, chosen, showAll)
|
|
local picked, withMarker, withoutMarker = {}, {}, {}
|
|
for _, building in ipairs(buildings or {}) do
|
|
if chosen ~= nil and chosen[building.id] then
|
|
table.insert(picked, building)
|
|
elseif building.hasMarker then
|
|
table.insert(withMarker, building)
|
|
elseif showAll then
|
|
table.insert(withoutMarker, building)
|
|
end
|
|
end
|
|
local rows = {}
|
|
for _, list in ipairs({sortedBy(picked, "name"), sortedBy(withMarker, "name"), sortedBy(withoutMarker, "name")}) do
|
|
for _, building in ipairs(list) do table.insert(rows, building) end
|
|
end
|
|
return rows
|
|
end
|