Module:Sandbox/User:The Gaffer/Modules/Infobox Recipe: Difference between revisions

From Brighter Shores Wiki
Jump to navigation Jump to search
Content added Content deleted
No edit summary
No edit summary
 
(53 intermediate revisions by the same user not shown)
Line 1: Line 1:
require('strict')
-- Lua module to replicate the functionality of the Infobox Recipe template
require('Module:Mw.html extension')
local currency = require('Module:Currency')
local hc = require('Module:Param Parse').has_content
local yn = require('Module:Yesno')
local editButton = require('Module:Edit button')

local function currency_cell(amount)
return currency._cell(amount, { html = 'yes' })
end

local p = {}
local p = {}


function p.main(frame)
function p._main(frame)
local args = frame.args
local args = frame:getParent().args
local mw = require('mw')


--If set to true, will check if any of the items passed as a rawmaterialparam are actually intermediate materials. Will then change the display order of the infobox.
-- Define raw material costs based on Semantic MediaWiki queries
local showFullRecipe = yn(args.showFull or 'no', false)
-- local function getCost(queryResult)
-- if type(queryResult) == "table" and queryResult[1] then
-- return tonumber(queryResult[1]) or 0
-- end
-- return 0
-- end


-- local rawmat1cost = args.rawmat1 and mw.smw.ask('[[:+]][[Sold item::' .. args.rawmat1 .. ']]|?Shop buy price|sort=Shop buy price|order=asc|limit=1') or "0"
-- local rawmat2cost = args.rawmat2 and mw.smw.ask('[[:+]][[Sold item::' .. args.rawmat2 .. ']]|?Shop buy price|sort=Shop buy price|order=asc|limit=1') or "0"
-- local rawmat3cost = args.rawmat3 and mw.smw.ask('[[:+]][[Sold item::' .. args.rawmat3 .. ']]|?Shop buy price|sort=Shop buy price|order=asc|limit=1') or "0"


--Get each of the rawmatX parameters from params and store their values in a new table
-- Calculate total cost and output cost
local argsMaterials = p._extractRawMaterials(args)
-- local totalCost = (tonumber(rawmat1cost) or 0) * (tonumber(args.rawmat1qty) or 1) +
-- (tonumber(rawmat2cost) or 0) * (tonumber(args.rawmat2qty) or 1) +
--empty tables to hold materials
-- (tonumber(rawmat3cost) or 0) * (tonumber(args.rawmat3qty) or 1)
local rawMaterials = {}
-- local output1cost = args.output1 and mw.smw.ask('[[:+]][[' .. args.output1 .. ']]|?Value|limit=1') or "0"
local intermediateMaterials = {}
--counter for total price of raw materials
local rawMaterialCost = 0


--get the value for the output product
-- -- Calculate output cost total and profit
local output1Value = 0
-- local output1costTotal = (tonumber(output1cost) or 0) * (tonumber(args.output1qty) or 1)
if args.output1 then
-- local profit = output1costTotal - totalCost
output1Value = mw.smw.ask('[[:+]][[' .. args.output1 .. ']]|?Value|limit=1') or 0
end
--Calculate total value of output material(s)
local output1TotalValue = 0
if type(output1Value) == "table" then
if output1Value[1]['Value'] ~= nil then
output1TotalValue = output1Value[1]['Value'] * (tonumber(args.output1qty) or 1)
else
output1TotalValue = 0
end
end


-- -- Generate the output table
local out = {}
-- table.insert(out, '{| class="wikitable"')
-- table.insert(out, '! colspan="4" | Requirements')
-- table.insert(out, '|-')
-- table.insert(out, '! colspan="2" | Facility')
-- table.insert(out, '! colspan="2" | ' .. (args.facility and '[[' .. args.facility .. ']]' or 'Unknown'))
-- table.insert(out, '|-')
-- table.insert(out, '! colspan="2" | Profession')
-- table.insert(out, '! Level')
-- table.insert(out, '! XP')
-- table.insert(out, '|-')
-- table.insert(out, '| colspan="2" | ' .. (args.profession and '[[' .. args.profession .. ']]' or 'Unknown'))
-- table.insert(out, '| style="text-align: center;" | ' .. (args.level or 'Unknown'))
-- table.insert(out, '| style="text-align: center;" | ' .. (args.exp or 'Unknown'))
-- table.insert(out, '|-')
-- table.insert(out, '! colspan="2" | Raw Ingredient')
-- table.insert(out, '! Quantity')
-- table.insert(out, '! Cost')
-- table.insert(out, '|-')


-- -- Add each raw material to the table
-- if args.rawmat1 then
-- table.insert(out, '| [[File:' .. args.rawmat1 .. '.png|30px]]')
-- table.insert(out, '| [[' .. args.rawmat1 .. ']]')
-- table.insert(out, '| style="text-align: right;" | ' .. (args.rawmat1qty or 1))
-- table.insert(out, '| style="text-align: right;" | ' .. rawmat1cost)
-- table.insert(out, '|-')
-- end
-- if args.rawmat2 then
-- table.insert(out, '| [[File:' .. args.rawmat2 .. '.png|30px]]')
-- table.insert(out, '| [[' .. args.rawmat2 .. ']]')
-- table.insert(out, '| style="text-align: right;" | ' .. (args.rawmat2qty or 1))
-- table.insert(out, '| style="text-align: right;" | ' .. rawmat2cost)
-- table.insert(out, '|-')
-- end
-- if args.rawmat3 then
-- table.insert(out, '| [[File:' .. args.rawmat3 .. '.png|30px]]')
-- table.insert(out, '| [[' .. args.rawmat3 .. ']]')
-- table.insert(out, '| style="text-align: right;" | ' .. (args.rawmat3qty or 1))
-- table.insert(out, '| style="text-align: right;" | ' .. rawmat3cost)
-- table.insert(out, '|-')
-- end


--Check if any of the raw mats provided are intermediate products, if they are, return their own raw materials
-- -- Add total raw cost
if showFullRecipe then
-- table.insert(out, '! colspan="3" | Total Raw cost')
local Materials = p._getTrueRawMaterials(argsMaterials)
-- table.insert(out, '| style="text-align: right;" | ' .. totalCost)
if next(Materials) ~= nil then
-- table.insert(out, '|-')
rawMaterials = Materials.rawMaterials
intermediateMaterials = p._reverseTable(Materials.intermediateMaterials)
end
else
rawMaterials = argsMaterials
end


-- -- Add output data and profit
-- table.insert(out, '! colspan="2" | Output')
-- table.insert(out, '! Quantity')
-- table.insert(out, '! Value')
-- table.insert(out, '|-')
-- table.insert(out, '| ' .. (args.output1 and '[[' .. args.output1 .. ']]' or 'Unknown'))
-- table.insert(out, '| style="text-align: right;" | ' .. (args.output1qty or 1))
-- table.insert(out, '| style="text-align: right;" | ' .. output1costTotal)
-- table.insert(out, '|-')
-- table.insert(out, '! colspan="3" | Profit')
-- table.insert(out, '| style="text-align: right;" | ' .. profit)
-- table.insert(out, '|}')


-- Add debug information to the output as a simple paragraph
--Simple query to get the shop buy price for the provided material, if no buy price is available returns 0
local debugMessage = 'Debug Info:<br>' ..
local function getBuyPrice(material)
'facility: ' .. (args.facility) .. '<br>' ..
local queryResult = mw.smw.ask('[[:+]][[Sold item::' .. material['name'] .. ']]|?Shop buy price|sort=Shop buy price|order=asc|limit=1') or 0
'profession: ' .. (args.profession) .. '<br>' ..
if type(queryResult) == "table" and queryResult[1]['Shop buy price'] then
'level: ' .. (args.level) .. '<br>' ..
return tonumber(queryResult[1]['Shop buy price']) or 0
'exp: ' .. (args.exp) .. '<br>' ..
end
'rawmat1: ' .. (args.rawmat1) .. '<br>' ..
return 0
'rawmat1qty: ' .. (args.rawmat1qty) .. '<br>' ..
end
'rawmat2: ' .. (args.rawmat2) .. '<br>' ..
'rawmat2qty: ' .. (args.rawmat3qty) .. '<br>' ..
'rawmat3: ' .. (args.rawmat3) .. '<br>' ..
'rawmat3qty: ' .. (args.rawmat3qty) .. '<br>' ..
'preparedmat1: ' .. (args.preparedmat1) .. '<br>' ..
'preparedmat1qty: ' .. (args.preparedmat1qty) .. '<br>' ..
'preparedmat1fac: ' .. (args.preparedmat1fac) .. '<br>' ..
'output1: ' .. (args.output1) .. '<br>' ..
'output1qty: ' .. (args.output1qty) .. '<br>' ..
table.insert(out, debugMessage)



return table.concat(out, '\n')

--If one of the raw materials provided as a param has been identified as an intermediate material then get the facility it is created at to display in the intermediate Ingredient row
local function getFacility(material)
local result = mw.smw.ask('[[:+]][[' .. material .. ']]|?Uses facility|limit=1') or 'unknown'
local pageName = ''
if result and result[1] and result[1]["Uses facility"] then
local usesFac = result[1]["Uses facility"]
pageName = usesFac:gsub("%[%[", ""):gsub("%]%]", ""):gsub("|.*", ""):gsub("^:", "")
end
return pageName
end



--Set SMW properties
for _,material in ipairs(argsMaterials) do
mw.smw.set({
["Uses item"] = material.name,
["Uses item_and_quantity"] = material.name .. ',' .. tostring(material.quantity)
})
end
if args.facility then
mw.smw.set({
["Uses facility"] = args.facility
})
end



--Creates a row suitable for the raw materials section of the infobox.
local function createRawMaterialRow(item)
local materialBuyPrice = getBuyPrice(item) * (item.quantity or 1)
rawMaterialCost = rawMaterialCost + materialBuyPrice
return mw.html.create('tr')
:tag('td')
:css{ ['border-right'] = 'none' }
:wikitext('[[File:' .. item.name .. '.png|30px|link=' .. item.name .. ']]')
:done()
:tag('td')
:css{ ['border-left'] = 'none' }
:wikitext('[[' .. item.name .. ']]')
:done()
:tag('td')
:css{ ['text-align'] = 'right' }
:wikitext(item.quantity or 1)
:done()
:wikitext(currency_cell(materialBuyPrice))
:done()
end



--Creates a row suitable for the intermediate materials section of the infobox.
local function createIntermediateMaterialRow(item)
local facility = getFacility(item.name)
return mw.html.create('tr')
:tag('td')
:css{ ['border-right'] = 'none' }
:wikitext('[[File:' .. item.name .. '.png|30px|link=' .. item.name .. ']]')
:done()
:tag('td')
:css{ ['border-left'] = 'none' }
:wikitext('[[' .. item.name .. ']]')
:done()
:tag('td')
:css{ ['text-align'] = 'right' }
:wikitext(item.quantity or 1)
:done()
:tag('td')
:attr{ colspan = '10' }
:css{ ['text-align'] = 'left' }
:wikitext('[[File:' .. facility .. '.png|30px|link=' .. facility .. ']] [[' .. facility .. ']]')
:done()
:done()
end



-- Recipe Table Head
local out = mw.html.create('table')
:addClass('wikitable')
:tag('tr')
:tag('th')
:attr{ colspan = '13' }
:wikitext('Requirements')
:done()
:done()
:tag('tr')
:tag('th')
:attr{ colspan = '2' }
:wikitext('Facility')
:done()
:tag('td')
:attr{ colspan = '11' }
:wikitext(hc(args.facility) and ('[[File:%s.png|link=%s|30px]] [[%s]]'):format(args.facility, args.facility, args.facility) or editButton("'''?''' (edit)"))

:done()
:done()
:tag('tr')
:tag('th')
:attr{ colspan = '2' }
:wikitext('Profession')
:done()
:tag('th')
:wikitext('Level')
:done()
:tag('th')
:attr{ colspan = '10' }
:wikitext('XP')
:done()
:done()
:tag('tr')
:tag('td')
:attr{ colspan = '2' }
:css{ ['text-align'] = 'center' }
:wikitext(hc(args.profession) and ('[[' .. args.profession .. ']]') or editButton("'''?''' (edit)"))
:done()
:tag('td')
:css{ ['text-align'] = 'center' }
:wikitext(hc(args.level) and (args.level) or editButton("'''?''' (edit)"))
:done()
:tag('td')
:attr{ colspan = '10' }
:css{ ['text-align'] = 'center' }
:wikitext(hc(args.exp) and (args.exp) or editButton("'''?''' (edit)"))
:done()
:done()

-- Add raw materials
-- Headers
:tag('tr')
:tag('th')
:attr{ colspan = '2' }
:wikitext('Raw Ingredient')
:done()
:tag('th')
:wikitext('Quantity')
:done()
:tag('th')
:attr{ colspan = '10' }
:wikitext('Cost')
:done()
:done()

-- Values
for _, material in ipairs(rawMaterials) do
out:node(createRawMaterialRow(material))
end

-- Add total raw cost
out
:tag('tr')
:tag('th')
:attr{ colspan = '3' }
:wikitext('Total Raw cost')
:done()
:wikitext(currency_cell(rawMaterialCost))
:done()

-- Add Intermediate steps if required
-- Headers
if next(intermediateMaterials) ~= nil then
-- Headers
out
:tag('tr')
:tag('th')
:attr{ colspan = '2' }
:wikitext('Intermediate Ingredient')
:done()
:tag('th')
:wikitext('Quantity')
:done()
:tag('th')
:attr{ colspan = '10' }
:wikitext('Faciltity')
:done()
:done()

-- Values
for _, material in ipairs(intermediateMaterials) do
out:node(createIntermediateMaterialRow(material))
end
end

-- Add output data
-- Headers
out
:tag('tr')
:tag('th')
:attr{ colspan = '2' }
:wikitext('Output')
:done()
:tag('th')
:wikitext('Quantity')
:done()
:tag('th')
:attr{ colspan = '10' }
:wikitext('Value')
:done()
:done()
:IF(args.output1)

-- Values
:tag('tr')
:tag('td')
:css{ ['border-right'] = 'none' }
:wikitext('[[File:' .. args.output1 .. '.png|30px|link=' .. args.output1 .. ']]' or 'Unknown')
:done()
:tag('td')
:css{ ['border-left'] = 'none' }
:wikitext('[[' .. args.output1 .. ']]' or 'Unknown')
:done()
:tag('td')
:css{ ['text-align'] = 'right' }
:wikitext(args.output1qty or 1)
:done()
:wikitext(currency_cell(output1TotalValue))
:done()
:END()
-- Add profit data
:tag('tr')
:addClass('currency')
:tag('th')
:attr{ colspan = '3' }
:wikitext('Profit')
:done()
:wikitext(currency_cell(output1TotalValue - rawMaterialCost))
:done()

return out
end
end



function p._extractRawMaterials(args)
local rawMaterials = {}

for i = 1, 9 do
local materialKey = "rawmat" .. i
local quantityKey = "rawmat" .. i .. "qty"

local materialValue = args[materialKey]
if materialValue and materialValue ~= "" then
local quantityValue = tonumber(args[quantityKey]) or 1
table.insert(rawMaterials, { name = materialValue, quantity = quantityValue })
end
end
return rawMaterials
end



--This function takes a table containing the raw materials params received from the calling template.
--For each of the raw materials, a query will be executed to see if it has the property 'Uses item'.
--If it does, that means that the 'raw material' is actually an 'intermediate material' as it is itself created.
--The materials required to create this intermediate material will be retrieved and added to the rawMaterials table.
--This allows for a full recipe to be shown where only intermediate ingredients were provided.
function p._getTrueRawMaterials(argsMaterials)
local rawMaterials = {}
local intermediateMaterials = {}

local function _processMaterial(material, quantity)
if material then
local result = mw.smw.ask('[[:+]][[' .. material .. ']]|?Uses item|?Uses item_and_quantity')
if result and result[1] and result[1]["Uses item"] then
-- The item is an intermediate material, add it to intermediateMaterials
table.insert(intermediateMaterials, { ["name"] = material, ["quantity"] = quantity })
-- Add the raw materials used by this intermediate material to rawMaterials
local usesItems = result[1]["Uses item"]
local quantities = result[1]["Uses item and quantity"]

if type(usesItems) == "table" then
for index, usedItem in ipairs(usesItems) do
local pageName = usedItem:gsub("%[%[", ""):gsub("%]%]", ""):gsub("|.*", ""):gsub("^:", "")
local qty = 1
if quantities and type(quantities) == "table" then
local quantityString = quantities[index]
local _, q = quantityString:match("(.-),(%d+)")
qty = tonumber(q) or 1
end
_processMaterial(pageName, qty)
end
else
local pageName = usesItems:gsub("%[%[", ""):gsub("%]%]", ""):gsub("|.*", ""):gsub("^:", "")
local qty = 1
if quantities and type(quantities) == "string" then
local _, q = quantities:match("(.-),(%d+)")
qty = tonumber(q) or 1
end
_processMaterial(pageName, qty)
end
else
-- The item is a raw material, add it to rawMaterials
table.insert(rawMaterials, { ["name"] = material, ["quantity"] = quantity })
end
end
end

-- Iterate over the initial argsMaterials
for _, item in pairs(argsMaterials) do
if item["name"] then
_processMaterial(item["name"], item["quantity"])
end
end

return { rawMaterials = rawMaterials, intermediateMaterials = intermediateMaterials }
end



function p._reverseTable(t)
local reversed = {}
for i = #t, 1, -1 do
table.insert(reversed, t[i])
end
return reversed
end




return p
return p

Latest revision as of 20:03, 24 November 2024

Module documentation
This documentation is transcluded from Module:Sandbox/User:The Gaffer/Modules/Infobox Recipe/doc. [edit] [history] [purge]
Module:Sandbox/User:The Gaffer/Modules/Infobox Recipe requires .

TODO


require('strict')
require('Module:Mw.html extension')
local currency = require('Module:Currency')
local hc = require('Module:Param Parse').has_content
local yn = require('Module:Yesno')
local editButton = require('Module:Edit button')

local function currency_cell(amount)
	return currency._cell(amount, { html = 'yes' })
end

local p = {}

function p._main(frame)
	local args = frame:getParent().args

	--If set to true, will check if any of the items passed as a rawmaterialparam are actually intermediate materials. Will then change the display order of the infobox.
	local showFullRecipe = yn(args.showFull or 'no', false)


	--Get each of the rawmatX parameters from params and store their values in a new table
	local argsMaterials = p._extractRawMaterials(args)
	
	--empty tables to hold materials
	local rawMaterials = {}
	local intermediateMaterials = {}
	
	--counter for total price of raw materials
	local rawMaterialCost = 0

	--get the value for the output product
	local output1Value = 0
	if args.output1 then
		output1Value = mw.smw.ask('[[:+]][[' .. args.output1 .. ']]|?Value|limit=1') or 0
	end
		
	--Calculate total value of output material(s)
	local output1TotalValue = 0
	if type(output1Value) == "table" then
		if output1Value[1]['Value'] ~= nil then
			output1TotalValue = output1Value[1]['Value'] * (tonumber(args.output1qty) or 1)
		else
			output1TotalValue = 0
		end
	end



	--Check if any of the raw mats provided are intermediate products, if they are, return their own raw materials
	if showFullRecipe then
		local Materials = p._getTrueRawMaterials(argsMaterials)
		if next(Materials) ~= nil then
			rawMaterials = Materials.rawMaterials
			intermediateMaterials = p._reverseTable(Materials.intermediateMaterials)
		end
	else
			rawMaterials = argsMaterials
	end


	
	--Simple query to get the shop buy price for the provided material, if no buy price is available returns 0
	local function getBuyPrice(material)
		local queryResult = mw.smw.ask('[[:+]][[Sold item::' .. material['name'] .. ']]|?Shop buy price|sort=Shop buy price|order=asc|limit=1') or 0
		if type(queryResult) == "table" and queryResult[1]['Shop buy price'] then
			return tonumber(queryResult[1]['Shop buy price']) or 0
		end
		return 0
	end



	--If one of the raw materials provided as a param has been identified as an intermediate material then get the facility it is created at to display in the intermediate Ingredient row
	local function getFacility(material)
		local result = mw.smw.ask('[[:+]][[' .. material .. ']]|?Uses facility|limit=1') or 'unknown'
		local pageName = ''
		if result and result[1] and result[1]["Uses facility"] then
			local usesFac = result[1]["Uses facility"]
			pageName = usesFac:gsub("%[%[", ""):gsub("%]%]", ""):gsub("|.*", ""):gsub("^:", "")
		end
		return pageName
	end



	--Set SMW properties
	for _,material in ipairs(argsMaterials) do
			mw.smw.set({
			["Uses item"] = material.name,
			["Uses item_and_quantity"] = material.name .. ',' .. tostring(material.quantity)
		})
	end
	
	if args.facility then
		mw.smw.set({
			["Uses facility"] = args.facility
		})
	end



	--Creates a row suitable for the raw materials section of the infobox.
	local function createRawMaterialRow(item)
		local materialBuyPrice = getBuyPrice(item) * (item.quantity or 1)
		rawMaterialCost = rawMaterialCost + materialBuyPrice
		return mw.html.create('tr')
			:tag('td')
				:css{ ['border-right'] = 'none' }
				:wikitext('[[File:' .. item.name .. '.png|30px|link=' .. item.name .. ']]')
			:done()
			:tag('td')
				:css{ ['border-left'] = 'none' }
				:wikitext('[[' .. item.name .. ']]')
			:done()
			:tag('td')
				:css{ ['text-align'] = 'right' }
				:wikitext(item.quantity or 1)
			:done()
			:wikitext(currency_cell(materialBuyPrice))
		:done()
	end



	--Creates a row suitable for the intermediate materials section of the infobox.
	local function createIntermediateMaterialRow(item)
		local facility = getFacility(item.name)
		return mw.html.create('tr')
			:tag('td')
				:css{ ['border-right'] = 'none' }
				:wikitext('[[File:' .. item.name .. '.png|30px|link=' .. item.name .. ']]')
			:done()
			:tag('td')
				:css{ ['border-left'] = 'none' }
				:wikitext('[[' .. item.name .. ']]')
			:done()
			:tag('td')
				:css{ ['text-align'] = 'right' }
				:wikitext(item.quantity or 1)
			:done()
			:tag('td')
				:attr{ colspan = '10' }
				:css{ ['text-align'] = 'left' }
				:wikitext('[[File:' .. facility .. '.png|30px|link=' .. facility .. ']] [[' .. facility .. ']]')
			:done()
		:done()
	end



-- Recipe Table Head 
	local out = mw.html.create('table')
		:addClass('wikitable')
		:tag('tr')
			:tag('th')
				:attr{ colspan = '13' }
				:wikitext('Requirements')
			:done()
		:done()
		:tag('tr')
			:tag('th')
				:attr{ colspan = '2' }
				:wikitext('Facility')
			:done()
			:tag('td')
				:attr{ colspan = '11' }
				:wikitext(hc(args.facility) and ('[[File:%s.png|link=%s|30px]] [[%s]]'):format(args.facility, args.facility, args.facility) or editButton("'''?''' (edit)"))

			:done()
		:done()
		:tag('tr')
			:tag('th')
				:attr{ colspan = '2' }
				:wikitext('Profession')
			:done()
			:tag('th')
				:wikitext('Level')
			:done()
			:tag('th')
				:attr{ colspan = '10' }
				:wikitext('XP')
			:done()
		:done()
		:tag('tr')
			:tag('td')
				:attr{ colspan = '2' }
				:css{ ['text-align'] = 'center' }
				:wikitext(hc(args.profession) and ('[[' .. args.profession .. ']]') or editButton("'''?''' (edit)"))
			:done()
			:tag('td')
				:css{ ['text-align'] = 'center' }
				:wikitext(hc(args.level) and (args.level) or editButton("'''?''' (edit)"))
			:done()
			:tag('td')
				:attr{ colspan = '10' }
				:css{ ['text-align'] = 'center' }
				:wikitext(hc(args.exp) and (args.exp) or editButton("'''?''' (edit)"))
			:done()
		:done()

-- Add raw materials
	-- Headers
		:tag('tr')
			:tag('th')
				:attr{ colspan = '2' }
				:wikitext('Raw Ingredient')
			:done()
			:tag('th')
				:wikitext('Quantity')
			:done()
			:tag('th')
				:attr{ colspan = '10' }
				:wikitext('Cost')
			:done()
		:done()

	-- Values
	for _, material in ipairs(rawMaterials) do
		out:node(createRawMaterialRow(material))
	end

-- Add total raw cost
	out
		:tag('tr')
			:tag('th')
				:attr{ colspan = '3' }
				:wikitext('Total Raw cost')
			:done()
			:wikitext(currency_cell(rawMaterialCost))
		:done()

-- Add Intermediate steps if required
	-- Headers
	if next(intermediateMaterials) ~= nil then
		-- Headers
		out
			:tag('tr')
				:tag('th')
					:attr{ colspan = '2' }
					:wikitext('Intermediate Ingredient')
				:done()
				:tag('th')
					:wikitext('Quantity')
				:done()
				:tag('th')
					:attr{ colspan = '10' }
					:wikitext('Faciltity')
				:done()
			:done()

	-- Values
		for _, material in ipairs(intermediateMaterials) do
			out:node(createIntermediateMaterialRow(material))
		end
	end

-- Add output data
	-- Headers
	out
		:tag('tr')
			:tag('th')
				:attr{ colspan = '2' }
				:wikitext('Output')
			:done()
			:tag('th')
				:wikitext('Quantity')
			:done()
			:tag('th')
				:attr{ colspan = '10' }
				:wikitext('Value')
			:done()
		:done()
		:IF(args.output1)

	-- Values
			:tag('tr')
				:tag('td')
					:css{ ['border-right'] = 'none' }
					:wikitext('[[File:' .. args.output1 .. '.png|30px|link=' .. args.output1 .. ']]' or 'Unknown')
				:done()
				:tag('td')
					:css{ ['border-left'] = 'none' }
					:wikitext('[[' .. args.output1 .. ']]' or 'Unknown')
				:done()
				:tag('td')
					:css{ ['text-align'] = 'right' }
					:wikitext(args.output1qty or 1)
				:done()
				:wikitext(currency_cell(output1TotalValue))
			:done()
		:END()
	-- Add profit data
		:tag('tr')
			:addClass('currency')
			:tag('th')
				:attr{ colspan = '3' }
				:wikitext('Profit')
			:done()
			:wikitext(currency_cell(output1TotalValue - rawMaterialCost))
		:done()

	return out
end



function p._extractRawMaterials(args)
	local rawMaterials = {}

	for i = 1, 9 do
		local materialKey = "rawmat" .. i
		local quantityKey = "rawmat" .. i .. "qty"

		local materialValue = args[materialKey]
		if materialValue and materialValue ~= "" then
			local quantityValue = tonumber(args[quantityKey]) or 1
			table.insert(rawMaterials, { name = materialValue, quantity = quantityValue })
		end
	end
	return rawMaterials
end



--This function takes a table containing the raw materials params received from the calling template. 
--For each of the raw materials, a query will be executed to see if it has the property 'Uses item'.
--If it does, that means that the 'raw material' is actually an 'intermediate material' as it is itself created.
--The materials required to create this intermediate material will be retrieved and added to the rawMaterials table.
--This allows for a full recipe to be shown where only intermediate ingredients were provided.
function p._getTrueRawMaterials(argsMaterials)
    local rawMaterials = {}
    local intermediateMaterials = {}

    local function _processMaterial(material, quantity)
        if material then
            local result = mw.smw.ask('[[:+]][[' .. material .. ']]|?Uses item|?Uses item_and_quantity')
            if result and result[1] and result[1]["Uses item"] then
                -- The item is an intermediate material, add it to intermediateMaterials
                table.insert(intermediateMaterials, { ["name"] = material, ["quantity"] = quantity })
                
                -- Add the raw materials used by this intermediate material to rawMaterials
                local usesItems = result[1]["Uses item"]
                local quantities = result[1]["Uses item and quantity"]

                if type(usesItems) == "table" then
                    for index, usedItem in ipairs(usesItems) do
                        local pageName = usedItem:gsub("%[%[", ""):gsub("%]%]", ""):gsub("|.*", ""):gsub("^:", "")
                        local qty = 1
                        if quantities and type(quantities) == "table" then
                            local quantityString = quantities[index]
                            local _, q = quantityString:match("(.-),(%d+)")
                            qty = tonumber(q) or 1
                        end
                        _processMaterial(pageName, qty)
                    end
                else
                    local pageName = usesItems:gsub("%[%[", ""):gsub("%]%]", ""):gsub("|.*", ""):gsub("^:", "")
                    local qty = 1
                    if quantities and type(quantities) == "string" then
                        local _, q = quantities:match("(.-),(%d+)")
                        qty = tonumber(q) or 1
                    end
                    _processMaterial(pageName, qty)
                end
            else
                -- The item is a raw material, add it to rawMaterials
                table.insert(rawMaterials, { ["name"] = material, ["quantity"] = quantity })
            end
        end
    end

    -- Iterate over the initial argsMaterials
    for _, item in pairs(argsMaterials) do
        if item["name"] then
            _processMaterial(item["name"], item["quantity"])
        end
    end

    return { rawMaterials = rawMaterials, intermediateMaterials = intermediateMaterials }
end



function p._reverseTable(t)
    local reversed = {}
    for i = #t, 1, -1 do
        table.insert(reversed, t[i])
    end
    return reversed
end



return p