feat(kæde): forslag samlet øverst uden dubletter; kæder sorteret efter status, bygning, produkt (v1.61.3.0)

This commit is contained in:
2026-09-30 17:16:05 +02:00
parent bd106a2176
commit d2970a1bda
5 changed files with 46 additions and 8 deletions
+42 -7
View File
@@ -20,7 +20,7 @@ ADChainView.TEXT_ROW_CHARS = 70
-- "stramt": lager for en mark-afgrøde under så mange måneders behov -> gul
ADChainView.TIGHT_MONTHS = 3
-- nøgler rækkerne bruger (til l10n-testen)
ADChainView.TEXT_KEYS = {"spu_chain_empty", "spu_chain_approve", "spu_chain_dismiss", "spu_chain_auto",
ADChainView.TEXT_KEYS = {"spu_chain_suggestHeader", "spu_chain_empty", "spu_chain_approve", "spu_chain_dismiss", "spu_chain_auto",
"spu_chain_flowOk", "spu_chain_flowMissing", "spu_chain_flowPallet", "spu_chain_flowNone", "spu_chain_flowStopped", "spu_chain_bottleneck",
"spu_chain_buy", "spu_chain_cycle", "spu_chain_fieldShort", "spu_chain_tight", "spu_chain_noField", "spu_chain_buySource", "spu_chain_fromFields",
"spu_chain_pause", "spu_chain_resume", "spu_chain_scanning", "spu_chain_rootOk", "spu_chain_rootError", "spu_chain_rootWaiting",
@@ -270,6 +270,39 @@ local function actionsFor(last, fruit, modes)
return list
end
-- Alle forslag (mode "suggest") én gang pr. mark, efter marknummer (in-game 30/9: samme forslag stod under
-- hver kæde der bruger afgrøden, spredt mellem kæderne).
function ADChainView.suggestionList(last)
local byField, list = {}, {}
for _, action in ipairs((last or {}).actions or {}) do
if action.mode == "suggest" and action.fieldId ~= nil and not byField[action.fieldId] then
byField[action.fieldId] = true
table.insert(list, action)
end
end
table.sort(list, function(a, b) return (tonumber(a.fieldId) or 0) < (tonumber(b.fieldId) or 0) end)
return list
end
-- Kæder efter status (fejl/mangel, venter, dækket, pause), så bygning, så produkt.
local LEVEL_RANK = {error = 1, waiting = 2, running = 3, stopped = 4}
function ADChainView.sortRoots(roots, last)
local keyed = {}
for index, root in ipairs(roots or {}) do
table.insert(keyed, {root = root, rank = LEVEL_RANK[ADChainView.rootLevel(root, last)] or 5,
building = tostring(root.buildingName or ""), name = tostring(root.name or ""), index = index})
end
table.sort(keyed, function(a, b)
if a.rank ~= b.rank then return a.rank < b.rank end
if a.building ~= b.building then return a.building < b.building end
if a.name ~= b.name then return a.name < b.name end
return a.index < b.index
end)
local sorted = {}
for _, item in ipairs(keyed) do table.insert(sorted, item.root) end
return sorted
end
local function rootRows(rows, root, last, ctx, isExpanded)
local level = ADChainView.rootLevel(root, last)
local paused = (last.paused or {})[root.key] == true
@@ -283,10 +316,7 @@ local function rootRows(rows, root, last, ctx, isExpanded)
table.insert(rows, makeRow("root", 0, level, {marker .. ctx.titleOf(root.name), tostring(root.buildingName or ""), "", status,
ctx.textOf(paused and "spu_chain_resume" or "spu_chain_pause")},
{[5] = {kind = paused and "resume" or "pause", rootKey = root.key}}, root.key))
if not isExpanded then
for _, action in ipairs(suggestions) do table.insert(rows, suggestRow(action, 1, ctx.titleOf, ctx.textOf)) end
return
end
if not isExpanded then return end
local shown, problems, told = {}, {}, {}
for _, problem in ipairs((last.chain or {}).problems or {}) do
if problem.rootKey == root.key then table.insert(problems, problem) end
@@ -311,7 +341,7 @@ local function rootRows(rows, root, last, ctx, isExpanded)
problemRows(node.fillType, depth + 1)
if node.source == "field" and node.fruit ~= nil and not shown[node.fruit] then
shown[node.fruit] = true
for _, action in ipairs(actionsFor(last, node.fruit, {suggest = true, auto = true})) do
for _, action in ipairs(actionsFor(last, node.fruit, {auto = true})) do
table.insert(rows, suggestRow(action, depth + 1, ctx.titleOf, ctx.textOf))
end
end
@@ -385,7 +415,12 @@ function ADChainView.rows(last, titleOf, fmt, textOf, expanded)
textOf("spu_chain_col_perMonth"), textOf("spu_chain_col_status"), textOf("spu_chain_col_stock")}))
end
local ctx = {titleOf = titleOf, fmt = fmt, textOf = textOf, short = shortageByFruit(last)}
for _, root in ipairs(roots) do rootRows(rows, root, last, ctx, expanded[root.key] == true) end
local suggestions = ADChainView.suggestionList(last)
if #suggestions > 0 then
table.insert(rows, {kind = "info", indent = 0, text = textOf("spu_chain_suggestHeader")})
for _, action in ipairs(suggestions) do table.insert(rows, suggestRow(action, 0, titleOf, textOf)) end
end
for _, root in ipairs(ADChainView.sortRoots(roots, last)) do rootRows(rows, root, last, ctx, expanded[root.key] == true) end
pausedRows(rows, last, ctx)
footerRows(rows, last, textOf)
return rows
+1
View File
@@ -577,6 +577,7 @@
<text name="spu_item_balanced" text="i balance"/>
<text name="spu_item_share" text="%d %% af varen"/>
<text name="spu_tab_chains" text="Kæder"/>
<text name="spu_chain_suggestHeader" text="Forslag til ny afgrøde"/>
<text name="spu_chain_empty" text="Ingen kæder: slå et produkt til i en fabrik"/>
<text name="spu_chain_col_item" text="Vare"/>
<text name="spu_chain_col_source" text="Kilde"/>
+1
View File
@@ -577,6 +577,7 @@
<text name="spu_item_balanced" text="balanced"/>
<text name="spu_item_share" text="%d %% of the good"/>
<text name="spu_tab_chains" text="Chains"/>
<text name="spu_chain_suggestHeader" text="Crop change suggestions"/>
<text name="spu_chain_empty" text="No chains: enable a product in a factory"/>
<text name="spu_chain_col_item" text="Goods"/>
<text name="spu_chain_col_source" text="Source"/>
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<modDesc descVersion="107">
<author>masterdraco</author>
<version>1.61.2.0</version>
<version>1.61.3.0</version>
<title>
<en>AD Smart Pickup</en>
</title>