feat(kæde): manglende led forklares i Kræver handling, fanen og som besked

problemText giver årsag og råd for køb/flaskehals/kredsløb og 'slukket af dig'
(userOff-kopi på ADChain.last); modellens problemer får need. Fanen Kæder viser
teksten som rød tekstrække under varen (foldet ud). Kræver handling får én rød
post pr. kæde (højst 2, score 3500+alvor mellem rød tom og rød fuld); klik åbner
fanen med kæden foldet ud. Engangsbesked pr. nyt led (rod|vare|art) kun fra
tick, ikke i opstartsfristen eller på delvise data/ufærdig markscanning.
Manualer og CHANGELOG opdateret.
This commit is contained in:
2026-09-30 14:40:29 +02:00
parent 1e7b2ec699
commit 19a10ab67c
12 changed files with 254 additions and 20 deletions
+64 -4
View File
@@ -279,15 +279,75 @@ end
-- "Kræver handling" fra kæden (ADChain.last): ÉT gult punkt "Kæde: N forslag" (klik -> fanen Kæder), så
-- forslagene ikke fylder listen. Rangeres under alle røde punkter (>= 3000), øverst blandt de gule, over "sælg nu".
ADStorageStats.CHAIN_SCORE = 2000
-- Manglende led: én rød post pr. kæde ("Brød mangler et led: Mel"), højst MAX_CHAIN_PROBLEMS (resten står i
-- fanen Kæder; den sidste viste post får more = antal skjulte). Score CHAIN_PROBLEM_SCORE + alvor (0-99): under
-- "rød tom" (3900-4000: løber tør inden et døgn), over "rød fuld" (3000-3100). Alvor = manglende andel af behovet;
-- kredsløb (kan ikke beregnes) = 99.
ADStorageStats.CHAIN_PROBLEM_SCORE = 3500
ADStorageStats.MAX_CHAIN_PROBLEMS = 2
ADStorageStats.MAX_CHAIN_PROBLEM_ITEMS = 2
local function severity(problems)
local missing, need = 0, 0
for _, problem in ipairs(problems) do
if problem.kind == "cycle" then return 99 end
missing, need = missing + (problem.detail or 0), need + (problem.need or 0)
end
if need <= 0 then return 99 end
return math.floor(99 * math.min(1, missing / need))
end
local function problemEntry(root, problems, titleOf)
local items, seen = {}, {}
for _, problem in ipairs(problems) do
local title = titleOf(problem.fillType)
if not seen[title] then
seen[title] = true
table.insert(items, title)
end
end
local shown = {}
for index = 1, math.min(#items, ADStorageStats.MAX_CHAIN_PROBLEM_ITEMS) do shown[index] = items[index] end
local itemsText = table.concat(shown, ", ")
if #items > #shown then itemsText = itemsText .. " +" .. tostring(#items - #shown) end
local rootTitle = titleOf(root.name)
return {kind = "chainProblem", level = "red", score = ADStorageStats.CHAIN_PROBLEM_SCORE + severity(problems), rootKey = root.key,
rootTitle = rootTitle, itemsText = itemsText, text = rootTitle .. ": " .. itemsText}
end
local function chainProblemEntries(last)
local titles = last.titles or {}
local titleOf = function(name) return tostring(titles[name] or name) end
local byRoot = {}
for _, problem in ipairs(last.chain ~= nil and last.chain.problems or {}) do
if problem.rootKey ~= nil then
byRoot[problem.rootKey] = byRoot[problem.rootKey] or {}
table.insert(byRoot[problem.rootKey], problem)
end
end
local entries = {}
for _, root in ipairs(last.chain ~= nil and last.chain.roots or {}) do
if byRoot[root.key] ~= nil then table.insert(entries, problemEntry(root, byRoot[root.key], titleOf)) end
end
entries = ADStorageStats.rankAttention(entries)
local result = {}
for index = 1, math.min(#entries, ADStorageStats.MAX_CHAIN_PROBLEMS) do result[index] = entries[index] end
if #entries > #result then result[#result].more = #entries - #result end
return result
end
function ADStorageStats.chainEntries(last)
if last == nil then return {} end
local result = chainProblemEntries(last)
local count = 0
for _, action in ipairs(last ~= nil and last.actions or {}) do
for _, action in ipairs(last.actions or {}) do
if action.mode == "suggest" then count = count + 1 end
end
if count == 0 then return {} end
return {{kind = "chainSuggest", level = "yellow", score = ADStorageStats.CHAIN_SCORE, count = count,
text = string.format("Kæde: %d", count)}}
if count > 0 then
table.insert(result, {kind = "chainSuggest", level = "yellow", score = ADStorageStats.CHAIN_SCORE, count = count,
text = string.format("Kæde: %d", count)})
end
return result
end
-- Varepunkterne (allerede rangeret) + kædens punkter, samme loft.