Module:RecipeDetails: Difference between revisions

From IdleOn MMO Wiki
mNo edit summary
mNo edit summary
 
(99 intermediate revisions by the same user not shown)
Line 1: Line 1:
local p = {}
local p = {}
local cargo = mw.ext.cargo
local cargo = mw.ext.cargo
 
local allRecipes = require("Module:RecipeDetails/data").allRecipes
 
local function appendTable(tableA, tableB)
local aLen = #tableA
for n=1, #tableB do
tableA[aLen+n] = tableB[n]
end
return tableA
end


local function fuseBaseIngredients(oldTable, newTable)
local function fuseBaseIngredients(oldTable, newTable)
local newItem
local old = oldTable
for n=1, #newTable do -- For each item in the new table
local new = newTable
newItem = true   -- Initialize newItem boolean
for n=1, #new do -- For each item in the new table
for o=1, #oldTable do  -- Check each item in the old table
local newItem = true   -- Initialize newItem boolean
if oldTable[o].Item == newTable[n].Item then  -- If the there is a match
for o=1, #old do  -- Check each item in the old table
if old[o].Item == new[n].Item then  -- If the there is a match
-- Add value, set boolean to false, and break loop.
-- Add value, set boolean to false, and break loop.
oldTable[o].Amount = oldTable[o].Amount + newTable[n].Amount  
old[o].Amount = old[o].Amount + new[n].Amount  
newItem = false
newItem = false
break
break
end
end
end
end
if newItem == true then oldTable[#oldTable+1] = newTable[n].Amount end -- If it is a new item then add new item.
if newItem == true then old[#old+1] = new[n] end -- If it is a new item then add new item.
end
end
return oldTable
return old
end
end


local function sortByKey(key)
local function getRecipeItems( inItem, multi, pad )
     return function(a, b)
local item = inItem
        return a[key] < b[key]
local multiplier = multi or 1
local ingredients = {}
local indent = pad or 1
 
     if allRecipes[item] == nil then return {} end -- if no results, exit with an empty table.
    local recipe = {}
    for _, v in pairs(allRecipes[item]) do
    recipe[#recipe+1] = v
     end
     end
    for n=1, #recipe / 2 do
    local tuple = {}
    local i = 1 + ((n-1) * 2) -- Need to go by twos instead of ones.
    tuple.Padding = indent
    tuple.Item = recipe[i]
    tuple.Amount = tonumber(recipe[i+1]) * multiplier
ingredients[n] = tuple
    end
-- Return table of items and values.
    return ingredients
end
end


-- Takes a list of items and an optional iterator for indentation.
-- Takes a list of items and an optional iterator for indentation.
local function RecipeBreakdownRecursive(items, i)
local function RecipeBreakdownRecursive(inItems, i, inFullTable)
local indent = i or 1 -- Used to set padding later.
local fullTableStruct = inFullTable or {}
local fullTableStruct = { --[[ inserted as (padding, item, amount) ]] }
local items = inItems
local tuple = {}
local indent = i or 1
local reciItems = {}
local baseIngredients = { --[[ insereted as (name, amount) ]] }
for n = 1, #items do  
for n = 1, #items do
tuple = {Padding = indent, Item = items[n].item, Amount = items[n].amount}
local tuple = {Padding = indent, Item = items[n].Item, Amount = items[n].Amount}
-- Insert item into fullTableStruct.
-- Insert item into fullTableStruct.
fullTableStruct[#fullTableStruct+1] = tuple
fullTableStruct[#fullTableStruct+1] = tuple
-- Query smithing table for the recipe and retrieve the ingeredients
-- Query smithing table for the recipe and retrieve the ingeredients
reciItems = getRecipeItems(items[n].item, items[n].amount) or {}
local reciItems = getRecipeItems(items[n].Item, items[n].Amount)
-- If previous line's result is not nil then recursively call this function and increment i.
-- If previous line's result is not empty then recursively call this function and increment i.
if #reciItems == 0 then
if #reciItems ~= 0 then
-- If item has value in baseingredients then increase, otherwise set to the value.
baseIngredients = fuseBaseIngredients(baseIngredients, {Item = items[n].item, Amount = items[n].amount})
else
-- If reciItems is not nil then recursively call this function and increment i.
-- If reciItems is not nil then recursively call this function and increment i.
local retTable = RecipeBreakdownRecursive(reciItems, indent + 1)
local retTable = RecipeBreakdownRecursive(reciItems, indent + 1, fullTableStruct)
fullTableStruct = appendTable(fullTableStruct, retTable[1])
baseIngredients = fuseBaseIngredients(baseIngredients, retTable[2])
end
end
end
end
return {fullTableStruct, baseIngredients}
return fullTableStruct
end
end


local function RecipeBreakdownFormatter(fullTable)
-- Takes a list of items and an optional iterator for indentation.
local results = {}
local function RecipeBreakdownLoop(inItems)
local Row = [==[<tr><td style="padding-left:%spx">{{CraftReq|%s}}</td><td>{{Numdisplay|%s}}</td></tr>]==]
local items = inItems
-- Format output rows.
local fullTable = items
local padding = 0
for n=1, #fullTable do
local function insertItems(newItems, index)
    -- Index is 6 for the first tier, and 20n+5 for the rest.
local newTable = {}
if fullTable[n].Padding > 1 then padding = fullTable[n].Padding * 20 + 5 else padding = 6 end
local o = 1
results[n] = string.format(Row, padding, fullTable[n].Item, fullTable[n].Amount)
while o <= index do newTable[#newTable+1] = items[o]; o = o + 1 end
for n=1, #newItems do newTable[#newTable+1] = newItems[n] end
while o <= #items do newTable[#newTable+1] = items[o]; o = o + 1 end
fullTable = newTable
end
local indent = 1
local deepest = 1
-- For each item in a growing table, check if the item at current indent level has a recipe.
-- If it does, set deepest to index +1 and add items to table at index.
-- Repeat until indent equals deepest after processing full table.
while true do
for n=1, #items do
if items[n].Padding == indent then
-- Check if item has a recipe: (Name, Multi, Padding)
local recipe = getRecipeItems(items[n].Item, items[n].Amount, indent + 1)
if #recipe >= 1 then
deepest = indent + 1
-- insert recipe into items table at n with padding indent + 1.
insertItems(recipe, n)
end
end
end
if deepest == indent then break else indent = indent + 1; items = fullTable end
end
end
-- Concatenate strings together.
return table.concat(results, "")
return items
end
end


local function RecipeTotalsFormatter(baseIngTable)
local function ParseBaseItemsTable(fullTableStruct)
local result = {}
local fullList = fullTableStruct
local sortedTable = {}
local baseList = {}
local Row = [==[<tr><td style="text-align:right">{{CraftReq|%s}}</td><td>{{Numdisplay|%s}}</td></tr>]==]
-- Sort list
for n=1, #fullList do
sortedTable = table.sort(baseIngTable, sortByKey("Item")) or {}
local itemRecipe = getRecipeItems(fullList[n].Item, 1, 1)
-- Format output rows.
if #itemRecipe < 1 then
for n=1, #sortedTable do
local addBaseItem = { {Item = fullList[n].Item, Amount = fullList[n].Amount} } -- A Table with 1 inner Table
result[n] = string.format(Row, sortedTable.Item, sortedTable.Amount)
baseList = fuseBaseIngredients(baseList, addBaseItem)
end
end
end
return table.concat(result, "")
return baseList
end
end


-- Query smithing table for the recipe and retrieve the ingeredients
local function checkDeepestLevel(inRecipesTable)
local function getRecipeItems( item, multi )
local items = inRecipesTable
local multiplier = multi or 1
for n=1, #items do
local ingredients = {}
local item = items[n].Item
-- Query
local ret = getRecipeItems(item, 1, 1)
    local args = {
if #ret >= 1 then  
        where = 'AnvilCraft.Item="'.. item ..'"',
return 2 -- If it goes deeper than the first level then return 2.
        orderBy = 'AnvilCraft.Item'
end
    }
end
    local results = cargo.query('AnvilCraft', 'Resource1, Quantity1, Resource2, Quantity2, Resource3, Quantity3, Resource4, Quantity4', args )
return 1 -- If it is not deeper than the first level then return 1.
    if #results == 0 then return 0 end -- if no results, exit with 0
   
    local tuple = {}
    for n=1, 4 do
    if results['Resource'..n] == nil or results['Resource'..n] == '' then break end -- If an empty cell is encountered, stop processing items.
    tuple.item = results['Resource'..n]
    tuple.amount = tonumber(results['Quantity'..n]) * multiplier
ingredients[n] = tuple
    end
-- Return table of items and values.
    return ingredients
end
end


function p.Builder( frame )
function p.Builder( frame )
local item = frame.args[1]
local item = frame.args.Item
local items = getRecipeItems(item)
local items = getRecipeItems(item)
local doubleTable = RecipeBreakdownRecursive(items)
-- Check if deepest level is greater than 1. If it is then continue.
local fullTableStruct = doubleTable[1]
if checkDeepestLevel(items) > 1 then
local baseIngredients = doubleTable[2]
-- local fullTableStruct = RecipeBreakdownRecursive(items, 1, {})
local fullTableStruct = RecipeBreakdownLoop(items)
-- build the data.
local baseIngredients = ParseBaseItemsTable(fullTableStruct)
local breakdown = RecipeBreakdownFormatter(fullTableStruct)
local function appendNestedTables(tableName, tableType)  
local totals    = RecipeTotalsFormatter(baseIngredients)
local newTable= {}
for n=1, #tableName do
-- Declare the Cargo Table: item, breakdown, totals.
local pad = ''
local cargoTable = 'DetailedRecipes'
if tableType == 0 then pad = tableName[n].Padding .. ", " end
    local args = {
newTable[#newTable+1] = pad .. tableName[n].Item ..  ", " .. tableName[n].Amount
        Item = 'String',
end
        Breakdown = 'Wikitext',
return table.concat(newTable, ", ")
        Totals = 'Wikitext' }
end
    local results = cargo.declare( cargoTable, args )
local breakdown = appendNestedTables(fullTableStruct, 0)
   
local totals = appendNestedTables(baseIngredients, 1)
-- Store it in the Cargo Table: item, breakdown, totals.
-- Store it in the Cargo Table: item, breakdown, totals.
    local args = {
frame:callParserFunction{ name = '#cargo_store', args = {"_table=DetailedRecipes", Item = item, Breakdown = breakdown, Totals = totals} }
        Item = item,
return '<br/>Stored data for the item: ' .. item
        Breakdown = breakdown,
end
        Totals = totals }
    local results = cargo.store( cargoTable, args )
end
end


function p.Main( frame )
function p.cargo_attach( frame )
local item = frame.args[1]
frame:callParserFunction{ name = '#cargo_attach', args = {"_table=DetailedRecipes"} }
-- frame:extensionTag{ name = 'cargo_attach', args= {_table = "DetailedRecipes"} }
-- Query 'DetailedRecipes' table for the recipe and retrieve the outputs
return 'Attach script ran. <br/>'
local tables = 'DetailedRecipes'
    local fields = 'Breakdown, Totals'
    local args = {
        where = 'Item = "' .. item .. '"'
    }
    local results = cargo.query( tables, fields, args )
    if #results == 0 then return end
   
-- return table data for item
    return string.format("{{Detrecipe/tab|reci=%s|tot=%s}}", results.Breakdown, results.Totals)
end
end


return p
return p

Latest revision as of 02:25, 17 April 2024

Documentation for this module may be created at Module:RecipeDetails/doc

local p = {}
local cargo = mw.ext.cargo
local allRecipes = require("Module:RecipeDetails/data").allRecipes 

local function fuseBaseIngredients(oldTable, newTable)
	local old = oldTable
	local new = newTable
	for n=1, #new do -- For each item in the new table
		local newItem = true   -- Initialize newItem boolean
		for o=1, #old do  -- Check each item in the old table
			if old[o].Item == new[n].Item then  -- If the there is a match
				-- Add value, set boolean to false, and break loop.
				old[o].Amount = old[o].Amount + new[n].Amount 
				newItem = false
				break
			end
		end
		if newItem == true then old[#old+1] = new[n] end -- If it is a new item then add new item.
	end
	return old
end

local function getRecipeItems( inItem, multi, pad )
	local item = inItem
	local multiplier = multi or 1
	local ingredients = {}
	local indent = pad or 1

    if allRecipes[item] == nil then return {} end -- if no results, exit with an empty table.
    local recipe = {}
    for _, v in pairs(allRecipes[item]) do
    	recipe[#recipe+1] = v
    end
    for n=1, #recipe / 2 do
    	local tuple = {}
    	local i = 1 + ((n-1) * 2) -- Need to go by twos instead of ones.
    	tuple.Padding = indent
    	tuple.Item = recipe[i]
    	tuple.Amount = tonumber(recipe[i+1]) * multiplier
		ingredients[n] = tuple
    end
	
	-- Return table of items and values.
    return ingredients
end

-- Takes a list of items and an optional iterator for indentation.
local function RecipeBreakdownRecursive(inItems, i, inFullTable)
	local fullTableStruct = inFullTable or {}
	local items = inItems
	local indent = i or 1
	
	for n = 1, #items do
		local tuple = {Padding = indent, Item = items[n].Item, Amount = items[n].Amount}
		-- Insert item into fullTableStruct.
		fullTableStruct[#fullTableStruct+1] = tuple
		-- Query smithing table for the recipe and retrieve the ingeredients
		local reciItems = getRecipeItems(items[n].Item, items[n].Amount)
		-- If previous line's result is not empty then recursively call this function and increment i.
		if #reciItems ~= 0 then
			-- If reciItems is not nil then recursively call this function and increment i.
			local retTable = RecipeBreakdownRecursive(reciItems, indent + 1, fullTableStruct)
		end
	end
	
	return fullTableStruct
end

-- Takes a list of items and an optional iterator for indentation.
local function RecipeBreakdownLoop(inItems)
	local items = inItems
	local fullTable = items
	
	local function insertItems(newItems, index)
		local newTable = {}
		local o = 1
		while o <= index do newTable[#newTable+1] = items[o]; o = o + 1 end
		for n=1, #newItems do newTable[#newTable+1] = newItems[n] end
		while o <= #items do newTable[#newTable+1] = items[o]; o = o + 1 end
		fullTable = newTable
	end
	
	local indent = 1
	local deepest = 1
	-- For each item in a growing table, check if the item at current indent level has a recipe. 
	-- If it does, set deepest to index +1 and add items to table at index.
	-- Repeat until indent equals deepest after processing full table.
	while true do
		for n=1, #items do
			if items[n].Padding == indent then
				-- Check if item has a recipe: (Name, Multi, Padding)
				local recipe = getRecipeItems(items[n].Item, items[n].Amount, indent + 1)
				if #recipe >= 1 then
					deepest = indent + 1
					-- insert recipe into items table at n with padding indent + 1.
					insertItems(recipe, n)
				end
			end
		end
		if deepest == indent then break else indent = indent + 1; items = fullTable end
	end
	
	return items
end

local function ParseBaseItemsTable(fullTableStruct)
	local fullList = fullTableStruct
	local baseList = {}
	
	for n=1, #fullList do
		local itemRecipe = getRecipeItems(fullList[n].Item, 1, 1)
		if #itemRecipe < 1 then
			local addBaseItem = { {Item = fullList[n].Item, Amount = fullList[n].Amount} } -- A Table with 1 inner Table
			baseList = fuseBaseIngredients(baseList, addBaseItem)
		end
	end
	
	return baseList
end

local function checkDeepestLevel(inRecipesTable)
	local items = inRecipesTable
	for n=1, #items do 
		local item = items[n].Item
		local ret = getRecipeItems(item, 1, 1)
		if #ret >= 1 then 
			return 2 -- If it goes deeper than the first level then return 2.
		end
	end
	return 1 -- If it is not deeper than the first level then return 1.
end

function p.Builder( frame )
	local item = frame.args.Item
	local items = getRecipeItems(item)
	-- Check if deepest level is greater than 1. If it is then continue.
	if checkDeepestLevel(items) > 1 then
		-- local fullTableStruct = RecipeBreakdownRecursive(items, 1, {})
		local fullTableStruct = RecipeBreakdownLoop(items)
		local baseIngredients = ParseBaseItemsTable(fullTableStruct)
		local function appendNestedTables(tableName, tableType) 
			local newTable= {}
			for n=1, #tableName do 
				local pad = ''
				if tableType == 0 then pad = tableName[n].Padding .. ", " end
				newTable[#newTable+1] = pad .. tableName[n].Item ..  ", " .. tableName[n].Amount
			end
			return table.concat(newTable, ", ")
		end
		local breakdown = appendNestedTables(fullTableStruct, 0)
		local totals = appendNestedTables(baseIngredients, 1)
		-- Store it in the Cargo Table: item, breakdown, totals.
		frame:callParserFunction{ name = '#cargo_store', args = {"_table=DetailedRecipes", Item = item, Breakdown = breakdown, Totals = totals} }
		return '<br/>Stored data for the item: ' .. item
	end
end

function p.cargo_attach( frame )
	frame:callParserFunction{ name = '#cargo_attach', args = {"_table=DetailedRecipes"} }
	-- frame:extensionTag{ name = 'cargo_attach', args= {_table = "DetailedRecipes"} }
	return 'Attach script ran. <br/>'
end

return p