-- Smart Pickup — "Kræver handling" -> flow (v1.60) -- En "løber tør"-linje i lagerfanerne kan klikkes: findes der et flow der leverer varen til forbrugerne, åbnes -- det; ligger varen andre steder på gården, åbnes "Nyt flow" udfyldt (ind til forbrugerne, varen valgt); ellers -- siges det at et flow ikke hjælper (producér/køb). Afgørelsen er ADStorageStats.flowAdvice (testet). -- Funktionerne lægges på SmartPickupFrame (indlæses efter SmartPickupFrame.lua). -- Lagerfanen for en bygningstype (TAB_KINDS), fx "factory" -> fanen Fabrikker. function SmartPickupFrame.tabOfKind(kind) for tab, tabKind in pairs(SmartPickupFrame.TAB_KINDS or {}) do if tabKind == kind then return tab end end return SmartPickupFrame.TAB_OVERVIEW end local function fillTypeName(fillType) return g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(fillType) or tostring(fillType) end -- Forsyningsflow der allerede leverer varen til en af forbrugerne -> run eller nil. local function existingSupplyRun(consumerIds, name) for _, run in ipairs(ADRunsController.store.runs) do if run.kind ~= "outbound" then local carries = run.ingredientMode ~= "manual" for _, ingredient in ipairs(run.ingredients or {}) do if ingredient == name then carries = true end end if carries then for _, id in ipairs(run.targetBuildingIds or {}) do if consumerIds[id] then return run end end end end end return nil end -- Udkørselsflow der allerede sælger varen fra en af bygningerne -> run eller nil. local function existingSellRun(sourceIds, name) for _, run in ipairs(ADRunsController.store.runs) do if run.kind == "outbound" then local sells = false for _, product in ipairs(run.products or {}) do if product.fillType == name and (product.policy == "sell" or product.policy == "sellElseStore") then sells = true end end if sells then for _, id in ipairs(run.sourceBuildingIds or {}) do if sourceIds[id] then return run end end end end end return nil end -- "Sælg nu": kilder = fanens bygninger med varen. local function sellAdviceFor(stat) local sourceIds, ids = {}, {} for _, building in ipairs(stat.buildings or {}) do local id = building.placeable ~= nil and ADBuildings.getId(building.placeable) or nil if id ~= nil and not sourceIds[id] then sourceIds[id] = true table.insert(ids, id) end end local name = fillTypeName(stat.fillType) local run = existingSellRun(sourceIds, name) local advice = ADStorageStats.sellAdvice({sourceCount = #ids, existingRunId = run ~= nil and run.id or nil}) return advice, {buildingIds = ids, run = run, name = name, stat = stat, sell = true} end -- entry fra ADStorageStats.attentionList -> advice ("open"|"flow"|"produce"|"none"), info function SmartPickupFrame:attentionAdvice(entry) -- kæde-forslag og manglende led har ingen vare (stat): klik fører til fanen Kæder if entry ~= nil and (entry.kind == "chainSuggest" or entry.kind == "chainProblem") then return "chain", nil end -- slukket men nødvendig: fanen Fabrikker (Kæder når kun en kæde bruger varen) if entry ~= nil and entry.kind == "dependencyOff" then return entry.onlyChain and "chain" or "factories", nil end if entry ~= nil and entry.kind == "sell" and entry.stat ~= nil then return sellAdviceFor(entry.stat) end if entry == nil or entry.kind ~= "empty" or entry.stat == nil then return "none", nil end local stat = entry.stat local consumers = ADStorageStats.consumersOf(self.lastFullInventory, stat.fillType) local consumerIds, consumerLevel, ids = {}, 0, {} for _, consumer in ipairs(consumers) do consumerLevel = consumerLevel + consumer.level local id = consumer.placeable ~= nil and ADBuildings.getId(consumer.placeable) or nil if id ~= nil and not consumerIds[id] then consumerIds[id] = true table.insert(ids, id) end end local name = fillTypeName(stat.fillType) local run = existingSupplyRun(consumerIds, name) local advice = ADStorageStats.flowAdvice({farmLevel = stat.farmLevel or stat.level, consumerLevel = consumerLevel, perDay = stat.consumption, consumerCount = #ids, existingRunId = run ~= nil and run.id or nil}) return advice, {consumers = consumers, buildingIds = ids, run = run, name = name, stat = stat} end function SmartPickupFrame:attentionHint(advice, info) if advice == "chain" then return self.i18n:getText("spu_attention_hintChain") end if advice == "factories" then return self.i18n:getText("spu_attention_hintFactories") end if advice == "open" then return string.format(self.i18n:getText("spu_attention_hintOpen"), tostring(info.run.name)) end if advice == "flow" then return self.i18n:getText(info.sell and "spu_attention_hintSellFlow" or "spu_attention_hintFlow") end if advice == "produce" then return self.i18n:getText("spu_attention_hintProduce") end return "" end function SmartPickupFrame:onAttentionClick(entry) self:safe(function(frame) 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 if entry.kind == "chainProblem" and entry.rootKey ~= nil then frame.chainExpanded = frame.chainExpanded or {} frame.chainExpanded[entry.rootKey] = true end frame:switchTab(SmartPickupFrame.TAB_CHAINS) return end if entry ~= nil and entry.kind == "dependencyOff" then frame:switchTab(entry.onlyChain and SmartPickupFrame.TAB_CHAINS or SmartPickupFrame.tabOfKind("factory")) return end local adEnv = frame.getAdEnv() local advice, info = frame:attentionAdvice(entry) if adEnv == nil or advice == "none" then return end if advice == "open" then frame.selectedRunId = info.run.id frame:switchTab(SmartPickupFrame.TAB_FLOWS) frame:openEditPanel("flow", info.run.id) return end if advice == "produce" then local text = string.format(frame.i18n:getText("spu_attention_produce"), tostring(info.stat.title), SmartPickupFrame.formatCompact(info.stat.farmLevel or 0)) frame.statusOverride, frame.statusOverrideTicks = text, SmartPickupFrame.STATUS_OVERRIDE_TICKS if ADFieldJobs ~= nil and ADFieldJobs.notify ~= nil then ADFieldJobs.notify(text, false) end return end local guide if info.sell then -- udfyldt "Nyt flow": ud af bygningerne med varen, varen til salg local name = string.format(frame.i18n:getText("spu_attention_sellFlowName"), tostring(info.stat.title)) guide = ADFlowGuide.openNew(name, {}) guide.draft.kind = "outbound" guide.draft.sourceBuildingIds = info.buildingIds guide.draft.products = {{fillType = info.name, policy = "sell"}} else -- udfyldt "Nyt flow": ind til forbrugerne, kun denne vare; guiden åbnes på oversigten (Gem/Start eller [Ret]) local name = string.format(frame.i18n:getText("spu_attention_flowName"), tostring(info.stat.title), tostring(info.consumers[1].name)) guide = ADFlowGuide.openNew(name, {}) guide.draft.targetBuildingIds = info.buildingIds guide.draft.ingredientMode = "manual" guide.draft.ingredients = {info.name} end guide = ADGuide.new(ADFlowGuide.DEF, guide.draft, frame:flowGuideContext(adEnv, guide.draft), {step = "summary"}) frame:switchTab(SmartPickupFrame.TAB_FLOWS) frame:openGuide("flow", guide) end) end