fix(kæde): højst 3 beskeder og samlede poster i Kræver handling
notifyProblems sender højst 3 beskeder pr. tick og samler resten i én
("+N manglende led — se fanen Kæder"). Alle kædeproblemer står i én rød post
("Kæder: N manglende led", scoret under rød fuld; klik folder kæderne ud) og
slukkede nødvendige fabrikker i højst én post ("Slukket men nødvendig: X +k").
This commit is contained in:
@@ -391,6 +391,8 @@ end
|
|||||||
|
|
||||||
-- Engangsbesked pr. nyt manglende led (kun fra tick). Ikke i opstartsfristen og ikke mens gården er læst delvist
|
-- Engangsbesked pr. nyt manglende led (kun fra tick). Ikke i opstartsfristen og ikke mens gården er læst delvist
|
||||||
-- eller markscanningen kører (ellers falske alarmer lige efter indlæsning) — så huskes intet, og det meldes senere.
|
-- eller markscanningen kører (ellers falske alarmer lige efter indlæsning) — så huskes intet, og det meldes senere.
|
||||||
|
-- Højst MAX_PROBLEM_NOTES beskeder pr. tick; resten samles i én besked (alle logges stadig).
|
||||||
|
ADChain.MAX_PROBLEM_NOTES = 3
|
||||||
function ADChain.notifyProblems(last)
|
function ADChain.notifyProblems(last)
|
||||||
if last == nil or ADChain.now < ADChain.STARTUP_GRACE_MS then return 0 end
|
if last == nil or ADChain.now < ADChain.STARTUP_GRACE_MS then return 0 end
|
||||||
if last.fieldsIncomplete or (last.data ~= nil and last.data.partial) then return 0 end
|
if last.fieldsIncomplete or (last.data ~= nil and last.data.partial) then return 0 end
|
||||||
@@ -403,11 +405,16 @@ function ADChain.notifyProblems(last)
|
|||||||
for _, root in ipairs(last.chain ~= nil and last.chain.roots or {}) do
|
for _, root in ipairs(last.chain ~= nil and last.chain.roots or {}) do
|
||||||
rootNames[root.key] = tostring((last.titles or {})[root.name] or root.name)
|
rootNames[root.key] = tostring((last.titles or {})[root.name] or root.name)
|
||||||
end
|
end
|
||||||
for _, problem in ipairs(fresh) do
|
for index, problem in ipairs(fresh) do
|
||||||
-- kædens navn foran, så to kæder der mangler samme vare kan skelnes
|
-- kædens navn foran, så to kæder der mangler samme vare kan skelnes
|
||||||
local text = tostring(rootNames[problem.rootKey] or problem.rootKey) .. ": " .. ADChainView.problemText(problem, last, textOf, nil, fmt)
|
local text = tostring(rootNames[problem.rootKey] or problem.rootKey) .. ": " .. ADChainView.problemText(problem, last, textOf, nil, fmt)
|
||||||
Logging.info(ADChain.LOG_PREFIX .. "manglende led: %s", text)
|
Logging.info(ADChain.LOG_PREFIX .. "manglende led: %s", text)
|
||||||
ADFieldJobs.notify(text, true)
|
if index <= ADChain.MAX_PROBLEM_NOTES then ADFieldJobs.notify(text, true) end
|
||||||
|
end
|
||||||
|
-- resten samles i én besked (fx mange fermenteringssiloer efter indlæsning); alle står i fanen Kæder
|
||||||
|
if #fresh > ADChain.MAX_PROBLEM_NOTES then
|
||||||
|
local ok, text = pcall(string.format, textOf("spu_chain_notifyMore"), #fresh - ADChain.MAX_PROBLEM_NOTES)
|
||||||
|
ADFieldJobs.notify(ok and text or ("+" .. tostring(#fresh - ADChain.MAX_PROBLEM_NOTES)), true)
|
||||||
end
|
end
|
||||||
return #fresh
|
return #fresh
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -279,13 +279,11 @@ end
|
|||||||
-- "Kræver handling" fra kæden (ADChain.last): ÉT gult punkt "Kæde: N forslag" (klik -> fanen Kæder), så
|
-- "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".
|
-- forslagene ikke fylder listen. Rangeres under alle røde punkter (>= 3000), øverst blandt de gule, over "sælg nu".
|
||||||
ADStorageStats.CHAIN_SCORE = 2000
|
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
|
-- Manglende led: ALLE kædeproblemer i ÉN rød post ("Kæder: N manglende led", klik -> fanen Kæder med kæderne
|
||||||
-- fanen Kæder; den sidste viste post får more = antal skjulte). Score CHAIN_PROBLEM_SCORE + alvor (0-99): under
|
-- foldet ud), så en gård med mange kæder (fx fermenteringssiloer) ikke fylder "Kræver handling". N = unikke
|
||||||
-- "rød tom" (3900-4000: løber tør inden et døgn), over "rød fuld" (3000-3100). Alvor = manglende andel af behovet;
|
-- (kæde, vare). Score CHAIN_PROBLEM_SCORE + alvor (0-99): under "rød fuld" (3000-3100), så lagerets røde poster
|
||||||
-- kredsløb (kan ikke beregnes) = 99.
|
-- altid vises først, og over de gule (<= 2000). Alvor = manglende andel af behovet; kredsløb = 99.
|
||||||
ADStorageStats.CHAIN_PROBLEM_SCORE = 3500
|
ADStorageStats.CHAIN_PROBLEM_SCORE = 2900
|
||||||
ADStorageStats.MAX_CHAIN_PROBLEMS = 2
|
|
||||||
ADStorageStats.MAX_CHAIN_PROBLEM_ITEMS = 2
|
|
||||||
|
|
||||||
local function severity(problems)
|
local function severity(problems)
|
||||||
local missing, need = 0, 0
|
local missing, need = 0, 0
|
||||||
@@ -297,50 +295,33 @@ local function severity(problems)
|
|||||||
return math.floor(99 * math.min(1, missing / need))
|
return math.floor(99 * math.min(1, missing / need))
|
||||||
end
|
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 function chainProblemEntries(last)
|
||||||
local titles = last.titles or {}
|
local known = {}
|
||||||
local titleOf = function(name) return tostring(titles[name] or name) end
|
for _, root in ipairs(last.chain ~= nil and last.chain.roots or {}) do known[root.key] = true end
|
||||||
local byRoot = {}
|
local problems, seen, rootKeys, rootSeen = {}, {}, {}, {}
|
||||||
for _, problem in ipairs(last.chain ~= nil and last.chain.problems or {}) do
|
for _, problem in ipairs(last.chain ~= nil and last.chain.problems or {}) do
|
||||||
if problem.rootKey ~= nil then
|
if problem.rootKey ~= nil and known[problem.rootKey] then
|
||||||
byRoot[problem.rootKey] = byRoot[problem.rootKey] or {}
|
table.insert(problems, problem)
|
||||||
table.insert(byRoot[problem.rootKey], problem)
|
seen[tostring(problem.rootKey) .. "|" .. tostring(problem.fillType)] = true
|
||||||
|
if not rootSeen[problem.rootKey] then
|
||||||
|
rootSeen[problem.rootKey] = true
|
||||||
|
table.insert(rootKeys, problem.rootKey)
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
entries = ADStorageStats.rankAttention(entries)
|
if #problems == 0 then return {} end
|
||||||
local result = {}
|
local count = 0
|
||||||
for index = 1, math.min(#entries, ADStorageStats.MAX_CHAIN_PROBLEMS) do result[index] = entries[index] end
|
for _ in pairs(seen) do count = count + 1 end
|
||||||
if #entries > #result then result[#result].more = #entries - #result end
|
table.sort(rootKeys, function(a, b) return tostring(a) < tostring(b) end)
|
||||||
return result
|
return {{kind = "chainProblem", level = "red", score = ADStorageStats.CHAIN_PROBLEM_SCORE + severity(problems), count = count,
|
||||||
|
rootKeys = rootKeys, text = string.format("Kæder: %d", count)}}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- "Slukket men nødvendig" (ADChain.last.dependency.offNeeded): én rød post pr. fabrik, højst MAX_DEPENDENCY_ENTRIES
|
-- "Slukket men nødvendig" (ADChain.last.dependency.offNeeded): højst MAX_DEPENDENCY_ENTRIES post (den mest hastende
|
||||||
-- (den sidste får more = antal skjulte). Score DEPENDENCY_SCORE + hast (0-99, færre lagerdage = højere; ukendt = 50):
|
-- fabrik; more = antal skjulte, vist som "+k"). Score DEPENDENCY_SCORE + hast (0-99, færre lagerdage = højere;
|
||||||
-- over manglende led (3500-3599), under "rød tom" (3900-4000).
|
-- ukendt = 50): over "rød fuld" (3000-3100), under "rød tom" (3900-4000).
|
||||||
ADStorageStats.DEPENDENCY_SCORE = 3700
|
ADStorageStats.DEPENDENCY_SCORE = 3700
|
||||||
ADStorageStats.MAX_DEPENDENCY_ENTRIES = 2
|
ADStorageStats.MAX_DEPENDENCY_ENTRIES = 1
|
||||||
|
|
||||||
local function urgency(days)
|
local function urgency(days)
|
||||||
if days == nil then return 50 end
|
if days == nil then return 50 end
|
||||||
|
|||||||
@@ -106,10 +106,10 @@ end
|
|||||||
function SmartPickupFrame:onAttentionClick(entry)
|
function SmartPickupFrame:onAttentionClick(entry)
|
||||||
self:safe(function(frame)
|
self:safe(function(frame)
|
||||||
if entry ~= nil and (entry.kind == "chainSuggest" or entry.kind == "chainProblem") then
|
if entry ~= nil and (entry.kind == "chainSuggest" or entry.kind == "chainProblem") then
|
||||||
-- manglende led: kæden foldes ud, så problemteksten står under den røde linje
|
-- manglende led: kæderne med problemer foldes ud, så problemteksten står under den røde linje
|
||||||
if entry.kind == "chainProblem" and entry.rootKey ~= nil then
|
if entry.kind == "chainProblem" then
|
||||||
frame.chainExpanded = frame.chainExpanded or {}
|
frame.chainExpanded = frame.chainExpanded or {}
|
||||||
frame.chainExpanded[entry.rootKey] = true
|
for _, rootKey in ipairs(entry.rootKeys or {}) do frame.chainExpanded[rootKey] = true end
|
||||||
end
|
end
|
||||||
frame:switchTab(SmartPickupFrame.TAB_CHAINS)
|
frame:switchTab(SmartPickupFrame.TAB_CHAINS)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -202,14 +202,13 @@ function SmartPickupFrame:alertText(entry)
|
|||||||
return string.format(i18n:getText("spu_attention_chainSuggests"), entry.count or 0)
|
return string.format(i18n:getText("spu_attention_chainSuggests"), entry.count or 0)
|
||||||
end
|
end
|
||||||
if entry.kind == "chainProblem" then
|
if entry.kind == "chainProblem" then
|
||||||
local text = string.format(i18n:getText("spu_attention_chainProblem"), tostring(entry.rootTitle), tostring(entry.itemsText))
|
return string.format(i18n:getText("spu_attention_chainProblems"), entry.count or 0)
|
||||||
if (entry.more or 0) > 0 then text = text .. string.format(" (+%d)", entry.more) end
|
|
||||||
return text
|
|
||||||
end
|
end
|
||||||
if entry.kind == "dependencyOff" then
|
if entry.kind == "dependencyOff" then
|
||||||
local text = string.format(i18n:getText("spu_attention_depOff"), tostring(entry.buildingName))
|
if (entry.more or 0) > 0 then
|
||||||
if (entry.more or 0) > 0 then text = text .. string.format(" (+%d)", entry.more) end
|
return string.format(i18n:getText("spu_attention_depOffMore"), tostring(entry.buildingName), entry.more)
|
||||||
return text
|
end
|
||||||
|
return string.format(i18n:getText("spu_attention_depOff"), tostring(entry.buildingName))
|
||||||
end
|
end
|
||||||
if entry.kind == "empty" then
|
if entry.kind == "empty" then
|
||||||
return string.format(i18n:getText("spu_alert_empty"), stat.title, self:formatDays(stat.days), fc(stat.farmLevel or 0), fc(math.abs(stat.net or 0)))
|
return string.format(i18n:getText("spu_alert_empty"), stat.title, self:formatDays(stat.days), fc(stat.farmLevel or 0), fc(math.abs(stat.net or 0)))
|
||||||
|
|||||||
@@ -599,6 +599,7 @@
|
|||||||
<text name="spu_chain_noField" text="ingen mark"/>
|
<text name="spu_chain_noField" text="ingen mark"/>
|
||||||
<text name="spu_chain_buySource" text="køb"/>
|
<text name="spu_chain_buySource" text="køb"/>
|
||||||
<text name="spu_chain_fromFields" text="fra marker"/>
|
<text name="spu_chain_fromFields" text="fra marker"/>
|
||||||
|
<text name="spu_chain_notifyMore" text="+%d manglende led — se fanen Kæder"/>
|
||||||
<text name="spu_chain_pause" text="[Pause]"/>
|
<text name="spu_chain_pause" text="[Pause]"/>
|
||||||
<text name="spu_chain_resume" text="[Start]"/>
|
<text name="spu_chain_resume" text="[Start]"/>
|
||||||
<text name="spu_chain_rootOk" text="dækket"/>
|
<text name="spu_chain_rootOk" text="dækket"/>
|
||||||
@@ -616,7 +617,7 @@
|
|||||||
<text name="spu_chain_problem_bottleneck" text="%s kan kun lave %s af %s/md"/>
|
<text name="spu_chain_problem_bottleneck" text="%s kan kun lave %s af %s/md"/>
|
||||||
<text name="spu_chain_problem_off" text="%s (%s) er slukket af dig — tænd den eller sæt kæden på pause"/>
|
<text name="spu_chain_problem_off" text="%s (%s) er slukket af dig — tænd den eller sæt kæden på pause"/>
|
||||||
<text name="spu_chain_problem_cycle" text="Kredsløb omkring %s — kæden kan ikke beregnes"/>
|
<text name="spu_chain_problem_cycle" text="Kredsløb omkring %s — kæden kan ikke beregnes"/>
|
||||||
<text name="spu_attention_chainProblem" text="%s mangler et led: %s"/>
|
<text name="spu_attention_chainProblems" text="Kæder: %d manglende led"/>
|
||||||
<text name="input_SPU_TOGGLE_STATUS" text="AD Smart Pickup: statusvindue"/>
|
<text name="input_SPU_TOGGLE_STATUS" text="AD Smart Pickup: statusvindue"/>
|
||||||
<text name="spu_status_flows" text="Flows"/>
|
<text name="spu_status_flows" text="Flows"/>
|
||||||
<text name="spu_status_fields" text="Marker"/>
|
<text name="spu_status_fields" text="Marker"/>
|
||||||
@@ -636,6 +637,7 @@
|
|||||||
<text name="spu_dep_warn" text="Advarsel: du slukkede %s (%s) — %s bruger det. Lageret rækker ca. %d dage."/>
|
<text name="spu_dep_warn" text="Advarsel: du slukkede %s (%s) — %s bruger det. Lageret rækker ca. %d dage."/>
|
||||||
<text name="spu_dep_warnNoDays" text="Advarsel: du slukkede %s (%s) — %s bruger det."/>
|
<text name="spu_dep_warnNoDays" text="Advarsel: du slukkede %s (%s) — %s bruger det."/>
|
||||||
<text name="spu_attention_depOff" text="Slukket men nødvendig: %s"/>
|
<text name="spu_attention_depOff" text="Slukket men nødvendig: %s"/>
|
||||||
|
<text name="spu_attention_depOffMore" text="Slukket men nødvendig: %s +%d"/>
|
||||||
<text name="spu_attention_hintFactories" text=" → klik: se Fabrikker"/>
|
<text name="spu_attention_hintFactories" text=" → klik: se Fabrikker"/>
|
||||||
</texts>
|
</texts>
|
||||||
</l10n>
|
</l10n>
|
||||||
|
|||||||
@@ -599,6 +599,7 @@
|
|||||||
<text name="spu_chain_noField" text="no field"/>
|
<text name="spu_chain_noField" text="no field"/>
|
||||||
<text name="spu_chain_buySource" text="buy"/>
|
<text name="spu_chain_buySource" text="buy"/>
|
||||||
<text name="spu_chain_fromFields" text="from fields"/>
|
<text name="spu_chain_fromFields" text="from fields"/>
|
||||||
|
<text name="spu_chain_notifyMore" text="+%d more missing links — see the Chains tab"/>
|
||||||
<text name="spu_chain_pause" text="[Pause]"/>
|
<text name="spu_chain_pause" text="[Pause]"/>
|
||||||
<text name="spu_chain_resume" text="[Resume]"/>
|
<text name="spu_chain_resume" text="[Resume]"/>
|
||||||
<text name="spu_chain_rootOk" text="covered"/>
|
<text name="spu_chain_rootOk" text="covered"/>
|
||||||
@@ -616,7 +617,7 @@
|
|||||||
<text name="spu_chain_problem_bottleneck" text="%s can only make %s of %s/mo"/>
|
<text name="spu_chain_problem_bottleneck" text="%s can only make %s of %s/mo"/>
|
||||||
<text name="spu_chain_problem_off" text="%s (%s) was turned off by you — turn it on or pause the chain"/>
|
<text name="spu_chain_problem_off" text="%s (%s) was turned off by you — turn it on or pause the chain"/>
|
||||||
<text name="spu_chain_problem_cycle" text="Loop around %s — the chain cannot be calculated"/>
|
<text name="spu_chain_problem_cycle" text="Loop around %s — the chain cannot be calculated"/>
|
||||||
<text name="spu_attention_chainProblem" text="%s is missing a link: %s"/>
|
<text name="spu_attention_chainProblems" text="Chains: %d missing links"/>
|
||||||
<text name="input_SPU_TOGGLE_STATUS" text="AD Smart Pickup: status window"/>
|
<text name="input_SPU_TOGGLE_STATUS" text="AD Smart Pickup: status window"/>
|
||||||
<text name="spu_status_flows" text="Flows"/>
|
<text name="spu_status_flows" text="Flows"/>
|
||||||
<text name="spu_status_fields" text="Fields"/>
|
<text name="spu_status_fields" text="Fields"/>
|
||||||
@@ -636,6 +637,7 @@
|
|||||||
<text name="spu_dep_warn" text="Warning: you switched off %s (%s) — %s uses it. Stock lasts about %d days."/>
|
<text name="spu_dep_warn" text="Warning: you switched off %s (%s) — %s uses it. Stock lasts about %d days."/>
|
||||||
<text name="spu_dep_warnNoDays" text="Warning: you switched off %s (%s) — %s uses it."/>
|
<text name="spu_dep_warnNoDays" text="Warning: you switched off %s (%s) — %s uses it."/>
|
||||||
<text name="spu_attention_depOff" text="Switched off but needed: %s"/>
|
<text name="spu_attention_depOff" text="Switched off but needed: %s"/>
|
||||||
|
<text name="spu_attention_depOffMore" text="Switched off but needed: %s +%d"/>
|
||||||
<text name="spu_attention_hintFactories" text=" → click: see Factories"/>
|
<text name="spu_attention_hintFactories" text=" → click: see Factories"/>
|
||||||
</texts>
|
</texts>
|
||||||
</l10n>
|
</l10n>
|
||||||
|
|||||||
Reference in New Issue
Block a user