diff --git a/FS25_ADSmartPickup/adChain.lua b/FS25_ADSmartPickup/adChain.lua index 84be85d..b23c890 100644 --- a/FS25_ADSmartPickup/adChain.lua +++ b/FS25_ADSmartPickup/adChain.lua @@ -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 diff --git a/FS25_ADSmartPickup/adChainData.lua b/FS25_ADSmartPickup/adChainData.lua index a4b5789..6d2b486 100644 --- a/FS25_ADSmartPickup/adChainData.lua +++ b/FS25_ADSmartPickup/adChainData.lua @@ -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 = {}} diff --git a/FS25_ADSmartPickup/adChainView.lua b/FS25_ADSmartPickup/adChainView.lua index 51d94b7..b489b67 100644 --- a/FS25_ADSmartPickup/adChainView.lua +++ b/FS25_ADSmartPickup/adChainView.lua @@ -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). diff --git a/FS25_ADSmartPickup/adFields.lua b/FS25_ADSmartPickup/adFields.lua index f5e7450..a5c0a38 100644 --- a/FS25_ADSmartPickup/adFields.lua +++ b/FS25_ADSmartPickup/adFields.lua @@ -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). diff --git a/FS25_ADSmartPickup/l10n/l10n_da.xml b/FS25_ADSmartPickup/l10n/l10n_da.xml index d2ade53..840833c 100644 --- a/FS25_ADSmartPickup/l10n/l10n_da.xml +++ b/FS25_ADSmartPickup/l10n/l10n_da.xml @@ -606,6 +606,7 @@ + diff --git a/FS25_ADSmartPickup/l10n/l10n_en.xml b/FS25_ADSmartPickup/l10n/l10n_en.xml index 64adee8..56754d8 100644 --- a/FS25_ADSmartPickup/l10n/l10n_en.xml +++ b/FS25_ADSmartPickup/l10n/l10n_en.xml @@ -606,6 +606,7 @@ +