Begin implementing fuzzy ingredient matching

This commit is contained in:
Gabriel Tofvesson 2025-05-15 23:33:55 +02:00
parent 4785e22f30
commit 75896b9304
3 changed files with 55 additions and 6 deletions

View File

@ -18,20 +18,20 @@ function prototype:getCost()
return costs return costs
end end
-- Returns table of item -> missing-count mappings. Empty table if recipe can be afforded -- Returns table of insufficient items. Empty table if recipe can be afforded
function prototype:canAfford(chests) function prototype:canAfford(chests)
local storage = stackgroup.fromChests(table.unpack(chests)) local storage = stackgroup.fromChests(table.unpack(chests))
local costs = self:getCost() local costs = self:getCost()
local missing = {} local missing = {}
for item,cost in pairs(costs) do for item,cost in pairs(costs) do
local group = storage:findGroup(item) local group = storage:findAllGroups({ item = item, total = function(checkTotal) return checkTotal >= cost end })
if group == nil or group.total < cost then if #group == 0 then
local totalMissing = cost local totalMissing = cost
if group ~= nil then if group ~= nil then
totalMissing = totalMissing - group.total totalMissing = totalMissing - group.total
end end
missing[item] = totalMissing table.insert(missing, item)
end end
end end
@ -42,7 +42,7 @@ function prototype:beginCrafting(chests)
local storage = stackgroup.fromChests(table.unpack(chests)) local storage = stackgroup.fromChests(table.unpack(chests))
for _,input in pairs(self.inputs) do for _,input in pairs(self.inputs) do
local group = storage:findGroup(input.item) local group = storage:findAllGroups({ item = input.item, total = function(checkTotal) return checkTotal >= input.cost end })[1]
group:moveItemsToPeripheral(chests, input.count, input.machine, input.slot) group:moveItemsToPeripheral(chests, input.count, input.machine, input.slot)
end end
@ -51,7 +51,7 @@ function prototype:beginCrafting(chests)
for _,output in pairs(self.outputs) do for _,output in pairs(self.outputs) do
local stackdata = itemstack.fromSlot(output.machine, output.slot) local stackdata = itemstack.fromSlot(output.machine, output.slot)
if output.item ~= stackdata.item or output.count > stackdata.count then if util.fuzzyEquals(stackdata.item, output.item) or output.count > stackdata.count then
return false return false
end end
end end

View File

@ -93,6 +93,10 @@ function stackgroupSetPrototype:findGroup(item)
return util.find(self, function(group) return group.item == item end) return util.find(self, function(group) return group.item == item end)
end end
function stackgroupSetPrototype:findAllGroups(groupPattern)
return util.findAll(self, function(group) return util.fuzzyEquals(group, groupPattern) end)
end
function stackgroup.fromChests(...) function stackgroup.fromChests(...)
local chests = { ... } local chests = { ... }
local groups = {} local groups = {}

View File

@ -34,9 +34,54 @@ function util.find(array, f)
return nil return nil
end end
function util.findAll(array, f)
local matches = {}
for k,v in pairs(array) do
if f(v, k) then
table.insert(matches, v)
end
end
return matches
end
function util.isEmpty(tbl) function util.isEmpty(tbl)
local next, t = pairs(tbl) local next, t = pairs(tbl)
return next(t) == nil return next(t) == nil
end end
function util.fuzzyEquals(value, pattern)
local valueType = type(value)
local patternType = type(pattern)
if patternType == "nil" then
return true
end
if patternType == "function" then
return pattern(value)
end
if valueType ~= patternType then
return false
end
if valueType == "table" then
for k,_ in pairs(pattern) do
if value[k] == nil then
return false
end
end
for k,v in pairs(value) do
if not util.compareValue(v, pattern[k]) then
return false
end
end
return true
end
return value == pattern
end
return util return util