feat: implement auto-discard feature for excess stock management
This commit is contained in:
@@ -765,6 +765,92 @@ function O.autoCompost()
|
||||
return didWork
|
||||
end
|
||||
|
||||
-------------------------------------------------
|
||||
-- Auto-discard excess stock
|
||||
-------------------------------------------------
|
||||
|
||||
function O.discardExcess()
|
||||
if #cfg.TRASH_DROPPERS == 0 then return false end
|
||||
|
||||
local catalogue = cache.catalogue
|
||||
local didWork = false
|
||||
|
||||
-- Build a flat list of dropper handles + free capacity
|
||||
local droppers = {}
|
||||
for _, dName in ipairs(cfg.TRASH_DROPPERS) do
|
||||
local d = O.wrapCached(dName)
|
||||
if d then
|
||||
local used = 0
|
||||
local contents = d.list()
|
||||
if contents then
|
||||
for _, item in pairs(contents) do used = used + item.count end
|
||||
end
|
||||
local free = (d.size() * 64) - used
|
||||
if free > 0 then
|
||||
table.insert(droppers, { name = dName, handle = d, free = free })
|
||||
end
|
||||
end
|
||||
end
|
||||
if #droppers == 0 then return false end
|
||||
|
||||
-- Round-robin index across droppers
|
||||
local dIdx = 1
|
||||
|
||||
for itemName, maxCount in pairs(cfg.STOCK_LIMITS) do
|
||||
if catalogue[itemName] then
|
||||
local totalInStorage = 0
|
||||
for _, src in ipairs(catalogue[itemName]) do
|
||||
totalInStorage = totalInStorage + src.total
|
||||
end
|
||||
|
||||
local excess = totalInStorage - maxCount
|
||||
if excess > 0 then
|
||||
log.info("DISCARD", "%s: %d in stock, limit %d, discarding %d",
|
||||
itemName, totalInStorage, maxCount, excess)
|
||||
local discarded = 0
|
||||
local srcSnapshot = { table.unpack(catalogue[itemName]) }
|
||||
for _, source in ipairs(srcSnapshot) do
|
||||
if discarded >= excess then break end
|
||||
if source.total > 0 then
|
||||
local chest = O.wrapCached(source.chest)
|
||||
if chest then
|
||||
for slot, slotItem in pairs(chest.list()) do
|
||||
if slotItem.name == itemName then
|
||||
-- Find a dropper with free space (round-robin)
|
||||
local startIdx = dIdx
|
||||
local dropper = nil
|
||||
repeat
|
||||
if droppers[dIdx].free > 0 then
|
||||
dropper = droppers[dIdx]
|
||||
end
|
||||
dIdx = (dIdx % #droppers) + 1
|
||||
until dropper or dIdx == startIdx
|
||||
if not dropper then break end -- all droppers full
|
||||
|
||||
local batch = math.min(slotItem.count, excess - discarded, dropper.free)
|
||||
local n = chest.pushItems(dropper.name, slot, batch)
|
||||
if n and n > 0 then
|
||||
state.adjustCache(itemName, source.chest, -n)
|
||||
dropper.free = dropper.free - n
|
||||
discarded = discarded + n
|
||||
didWork = true
|
||||
end
|
||||
if discarded >= excess then break end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if discarded > 0 then
|
||||
log.info("DISCARD", "Discarded %s x%d", itemName, discarded)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return didWork
|
||||
end
|
||||
|
||||
-------------------------------------------------
|
||||
-- Low-stock alert checker
|
||||
-------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user