fix(kæde): ingen markskift eller forslag før markscanningen har set alle marker

This commit is contained in:
2026-09-30 14:25:14 +02:00
parent 605c4e8d45
commit d2453f78fb
6 changed files with 39 additions and 8 deletions
+8 -4
View File
@@ -270,9 +270,13 @@ local function plan(data, state)
protected = ADChainModel.build(ADChain.modelRecipes(data.recipes, {}, state.userOff), data.husbandry, data.crops).needRecipes
end
local used = ADChain.unionFruits(data.usedFruits, chain.fieldDemand)
local shortages = ADCropPlan.shortages(chain.fieldDemand, data.stock, data.fields, data.yields)
state.dismissed = ADChain.pruneDismissed(state.dismissed, shortages)
local actions = ADCropPlan.choose(shortages, data.fields, used, data.yields, data.prices, ADChain.dismissedFruits(state.dismissed))
-- ufuldstændig markliste: udbuddet ville være undervurderet -> ingen mangler, forslag eller markskift endnu
local shortages, actions = {}, {}
if not data.fieldsIncomplete then
shortages = ADCropPlan.shortages(chain.fieldDemand, data.stock, data.fields, data.yields)
state.dismissed = ADChain.pruneDismissed(state.dismissed, shortages)
actions = ADCropPlan.choose(shortages, data.fields, used, data.yields, data.prices, ADChain.dismissedFruits(state.dismissed))
end
-- de ægte opskrifter (ikke kopien): en pauset rod er stadig tændt og må ikke "tændes" og overtages af kæden
local prod = ADChainActions.productions(data.recipes, chain.needRecipes, protected)
return {chain = chain, shortages = shortages, actions = actions, prod = prod, edges = ADChainActions.edges(chain)}
@@ -318,7 +322,7 @@ function ADChain.evaluate(adEnv, act)
for key in pairs(state.paused) do paused[key] = true end
ADChain.last = {chain = result.chain, shortages = result.shortages, actions = result.actions, edges = result.edges,
missingFlows = ADChainActions.missingFlows(result.edges, runs), flowStatus = ADChain.flowStatus(result.edges, runs, ADChain.noVehicle),
paused = paused, data = data, fields = data.fields, titles = data.fillTitles, at = ADChain.now, switchCount = ADChain.switchCount}
paused = paused, data = data, fields = data.fields, fieldsIncomplete = data.fieldsIncomplete == true, titles = data.fillTitles, at = ADChain.now, switchCount = ADChain.switchCount}
return ADChain.last
end
+7 -1
View File
@@ -187,7 +187,12 @@ local function readUsedFruits(data, adEnv, farmId, nameOf)
if not ok then failed(data, "rates", "staldforbrug kunne ikke læses: %s", tostring(err)) end
end
-- Markscanningen har ikke nået alle marker endnu (efter indlæsning ~én mark pr. 2 s): marklisten er ufuldstændig,
-- så udbud undervurderes -> fieldsIncomplete (kæden rører ingen marker) og partial (intet slukkes/stoppes).
local function readFields(data)
if ADFields.isScanComplete ~= nil and not ADFields.isScanComplete() then
data.partial, data.fieldsIncomplete = true, true
end
for _, info in ipairs(ADFields.list() or {}) do
local ok, entry = pcall(function()
local field = ADFieldJobs.getField(info.id)
@@ -208,7 +213,8 @@ end
-- ---- samlet ----
-- byChain = {[recipeKey] = true} for produktioner kæden selv har tændt (ikke rødder).
-- data.partial = true når noget ikke kunne læses i dette kald.
-- data.partial = true når noget ikke kunne læses i dette kald; data.fieldsIncomplete = true mens markscanningen
-- ikke har nået alle marker.
function ADChainData.collect(adEnv, farmId, byChain)
local data = {recipes = {}, husbandry = {}, crops = {}, stock = {}, fields = {}, yields = {}, prices = {},
usedFruits = {}, points = {}, fillTitles = {}, fillIndex = {}}
+3 -2
View File
@@ -2,7 +2,7 @@
-- Rækkerne til fanen Kæder ud fra ADChain.last. Hver rod er foldet sammen som standard (én linje med samlet
-- status + antal forslag); foldet ud vises varerne rekursivt (kilde, behov pr. måned, status, lager). Forslag
-- vises altid (under roden eller under afgrøden). Pausede rødder (som modellen ikke længere ser som rødder)
-- får en grå linje med [Genoptag]. Nederst frie marker + antal automatiske skift. Ingen spiladgang:
-- får en grå linje med [Genoptag]. Nederst frie marker + antal automatiske skift (+ "marker scannes endnu"). Ingen spiladgang:
-- titleOf(navn) -> titel, fmt(liter) -> kompakt tal, textOf(l10n-nøgle) -> tekst gives udefra.
-- Række: {kind="header"|"root"|"node"|"suggest"|"auto"|"info"|"empty", indent, level, cells={c1..c5}, text,
-- actions={[celle]={kind="approve"|"dismiss"|"pause"|"resume", fieldId|rootKey}}, toggle=rootKey, fillType}
@@ -19,7 +19,7 @@ ADChainView.TIGHT_MONTHS = 3
ADChainView.TEXT_KEYS = {"spu_chain_empty", "spu_chain_approve", "spu_chain_dismiss", "spu_chain_auto",
"spu_chain_flowOk", "spu_chain_flowMissing", "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_pause", "spu_chain_resume", "spu_chain_rootOk", "spu_chain_rootError", "spu_chain_rootWaiting",
"spu_chain_pause", "spu_chain_resume", "spu_chain_scanning", "spu_chain_rootOk", "spu_chain_rootError", "spu_chain_rootWaiting",
"spu_chain_rootPaused", "spu_chain_rootSummary", "spu_chain_free", "spu_chain_switches", "spu_chain_gone", "spu_chain_col_item",
"spu_chain_col_source", "spu_chain_col_perMonth", "spu_chain_col_status", "spu_chain_col_stock"}
@@ -270,6 +270,7 @@ local function footerRows(rows, last, textOf)
local freeText = string.format(textOf("spu_chain_free"), #names > 0 and table.concat(names, ", ") or "-")
table.insert(rows, {kind = "info", indent = 0, text = freeText})
table.insert(rows, {kind = "info", indent = 0, text = string.format(textOf("spu_chain_switches"), last.switchCount or 0)})
if last.fieldsIncomplete then table.insert(rows, {kind = "info", indent = 0, text = textOf("spu_chain_scanning")}) end
end
-- expanded = {[rodnøgle] = true} for udfoldede rødder (alle andre er foldet sammen).
+19 -1
View File
@@ -10,6 +10,9 @@ ADFields.MARKER_MAX_DISTANCE = 400
ADFields.cache = {}
ADFields.order = {}
ADFields.scanIndex = 0
-- {[markId] = true}: marker hvis scanning er afsluttet (med resultat) eller fejlede — til isScanComplete
ADFields.scanFailed = {}
ADFields.ownedDone = false
ADFields.mowable = nil
-- markliste og F-markører ændrer sig sjældent: slås op igen efter så lang tid (ikke hvert scan)
ADFields.OWNED_REFRESH_MS = 30000
@@ -566,9 +569,20 @@ local function finishOwnedScan(scan)
if not ids[id] then ADFields.cache[id] = nil end
end
ADFields.order = scan.result
ADFields.ownedDone = true
ADFields.listCache = nil
end
-- Har scanningen nået alle ejede marker mindst én gang (resultat i cachen, eller scanningen fejlede)?
-- Indtil da er marklisten ufuldstændig (efter indlæsning fyldes den ~én mark pr. SCAN_INTERVAL_MS).
function ADFields.isScanComplete()
if not ADFields.ownedDone then return false end
for _, entry in ipairs(ADFields.order) do
if ADFields.cache[entry.id] == nil and not ADFields.scanFailed[entry.id] then return false end
end
return true
end
-- Kaldes HVERT frame: kører én opgave af den aktuelle scanning. En ny mark påbegyndes højst hvert
-- SCAN_INTERVAL_MS; marklisten opdateres hvert OWNED_REFRESH_MS.
ADFields.SCAN_INTERVAL_MS = 2000
@@ -612,6 +626,7 @@ function ADFields.scanStep(adEnv, farmId, now)
local ok, err = pcall(task)
if not ok then
Logging.warning("ADSmartPickup: F%s kunne ikke scannes: %s", tostring(scan.id or "-"), tostring(err))
if scan.id ~= nil then ADFields.scanFailed[scan.id] = true end
ADFields.activeScan = nil
return
end
@@ -628,7 +643,10 @@ function ADFields.scanStep(adEnv, farmId, now)
else
ok, err = pcall(finishScan, adEnv, scan)
end
if not ok then Logging.warning("ADSmartPickup: F%s scanning kunne ikke afsluttes: %s", tostring(scan.id or "-"), tostring(err)) end
if not ok then
Logging.warning("ADSmartPickup: F%s scanning kunne ikke afsluttes: %s", tostring(scan.id or "-"), tostring(err))
if scan.id ~= nil then ADFields.scanFailed[scan.id] = true end
end
end
-- Samme liste indtil næste scanning (list() kaldes hvert sekund; ingen ny tabel hver gang).
+1
View File
@@ -606,6 +606,7 @@
<text name="spu_chain_rootSummary" text="%s · %d forslag"/>
<text name="spu_chain_free" text="Marker fri til kæden: %s"/>
<text name="spu_chain_switches" text="Automatiske skift siden indlæsning: %d"/>
<text name="spu_chain_scanning" text="Marker scannes endnu – kæden skifter ingen marker før alle er set"/>
<text name="spu_attention_chainSuggest" text="Kæde: F%d %s → %s"/>
<text name="spu_attention_hintChain" text=" → klik: se Kæder"/>
</texts>
+1
View File
@@ -606,6 +606,7 @@
<text name="spu_chain_rootSummary" text="%s · %d sugg."/>
<text name="spu_chain_free" text="Fields free for the chain: %s"/>
<text name="spu_chain_switches" text="Automatic switches since load: %d"/>
<text name="spu_chain_scanning" text="Fields still being scanned – no field changes until all are seen"/>
<text name="spu_attention_chainSuggest" text="Chain: F%d %s → %s"/>
<text name="spu_attention_hintChain" text=" → click: see Chains"/>
</texts>