Module:Infobox cooking

Revision as of 21:22, 4 November 2021 by Admin (talk | contribs) (1 revision imported)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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

--<nowiki>

--[=[<pre>
-- Implements [[Template:Databox Cooking]]
--]=]

local p = {}

local yesno = require('Module:Yesno')
local params = require('Module:Paramtest')
local commas = require('Module:Addcommas')
local geprice = require('Module:Exchange')._price
local skillpic = require('Module:Skill_clickpic')._main
local mapicons = require('Module:Map_clickpic')
local editbutton = require('Module:Edit button')
local onmain = require('Module:Mainonly').on_main

local cookimg = '[[File:Cooking-icon.png|21x21px|link=Cooking|alt=Cooking]]'

function p.main(frame)
	local args = frame:getParent().args
	--[[
	Function to handle all the materials listed
	Creates a table to pass to _main() consisting of
	* Item name, as a wikilink
	* Item image, as a wikilink, includes link to page
	* Quantity
	* Formatted price for display
	* Clean price for calculations
	If the parameter mat# is defined and not blank
	Every parameter (mat#img, mat#qty, mat#price) will be looked for as well
	--]]
	local function mat_list()
		local ret_list = {}
		for i=1,10,1 do
			local mat = args['mat'..i]
			if mat and params.has_content(mat) then
				local name = mat
				-- 2 separate prices
				-- 1 for display
				-- 1 for calculation
				local price,price_raw
				local qty = params.default_to(args['mat'..i..'qty'],'1')
				local img = params.default_to(args['mat'..i..'img'],
					name..'.png')
					:gsub('File:','')
				local price_v = params.default_to(args['mat'..i..'price'],'/')
				-- gemw = use exchange price
				if price_v:lower() == 'gemw' then
					price_raw = geprice(name)
					price = commas._add(price_raw)
				-- parseable as number = use that
				elseif tonumber(commas._strip(price_v),10) then
					price_raw = tonumber(commas._strip(price_v),10)
					price = commas._add(price_raw)
				-- Some untradeables have a distinct market price
				-- because of their materials
				-- The template {{GETotal}} will help here
				-- Look for template call
				elseif price_v:find('{{.*}}') then
					price_raw = frame:preprocess(price_v)
					price = commas._add(price_raw)
				-- price disabled
				-- use N/A for display and 0 for calculations
				elseif yesno(price_v, true) == false then
					price_raw = 0
					price = 'N/A'
				-- everything else
				else
					price_raw = geprice(name)
					price = commas._add(price_raw)
				end

				table.insert(ret_list, {
					name = '[['..name..']]',
					name_raw = name,
					price = price,
					price_raw = price_raw,
					quantity = qty,
					image = '[[File:'..img..'|link='..name..']]',
					image_raw = img
				} )
			end
		end
		return ret_list
	end
	
	-- Fetching and formatting parameters starting here
	local item_name,item_image,
		ticks,level,
		burnlevel,gauntlets,
		fireburn,firegaunt,
		cookmatic,
		experience,xpfire,
		tools,method,
		quest,
		servings,lphealed,
		instructions,totalvar = params.defaults{
				{args.name,mw.title.getCurrentTitle().text},
				{args.image,nil},
				{args.ticks,editbutton('?')},
				{args.level,editbutton('?')},
				{args.noburnlevel,nil},
				{args.gauntlets,nil},
				{args.fireburn,nil},
				{args.firegaunt,nil},
				{args.cookmatic,nil},
				{args.xp,editbutton('?')},
				{args.xpfire,nil},
				{args.tools,nil},
				{args.method,nil},
				{args.quest,nil},
				{args.servings,1},
				{args.lphealed,nil},
				{args.instructions,nil},
				{args.totalvar,nil}
			}
	local item_link = mw.title.getCurrentTitle().text
	local members = yesno(args.members) and '[[File:P2P icon.png|21px|link=]] Members only' or '[[File:F2P icon.png|21px|link=]] Free-to-play'
	
	-- Add [[File: and |link=...]] to image, if it's defined
	if item_image then
		item_image = '[[File:'..item_image:gsub('File:','')..'|link='..item_link..']]'
	-- anti-redlink
	elseif mw.title.getCurrentTitle().text == 'Databox Recipe/preload'
			or mw.title.getCurrentTitle().text == 'PreloadPage/Orphanage' then
		item_image = ''
	else
		item_image = '[[File:'..item_name..'.png|link='..item_name..']]'
	end
	
	-- Heat source
	local heat = yesno(args.heat,true)
	if heat == nil then
		heat = true
	end
	-- Requires range or fire
	if yesno(args.range,false) == true then
		heat = 'range'
	elseif yesno(args.range,false) == false then
		heat = 'fire'
	end
	-- Brewing
	local brewing = false
	if yesno(args.brewing,false) then
		brewing = true
		heat = false
	end
	-- Water source
	local water = false
	if yesno(args.water,false) then
		water = true
	end

	-- Tables to pass; call above functions
	local materials = mat_list()
	
	-- Check servings  and lp are numbers
	if tonumber(servings,10) then
		servings = tonumber(servings,10)
	else
		servings = 1
	end
	if lphealed and tonumber(lphealed,10) then
		lphealed = tonumber(lphealed,10)
	else
		lphealed = nil
	end
	
	-- Burn level
	if burnlevel then
		if tonumber(burnlevel,10) then
			burnlevel = tonumber(burnlevel,10)
		elseif string.lower(burnlevel) == 'none' or yesno(burnlevel) == false then
			burnlevel = nil
		end
	else
		burnlevel = nil
	end
	
	-- Look for GE price unless disabled, nil if disabled
	local item_ge_v = string.lower(args.geValue or 'yes')
	local item_gep
	if item_ge_v == 'gemw' then
		item_gep = geprice(item_name)
	elseif tonumber(item_ge_v,10) then
		item_gep = tonumber(item_ge_v,10)
	elseif yesno(item_ge_v) == false then
		item_gep = nil
	else
		item_gep = geprice(item_name)
	end
	
	return p._main{ frame,
		item_name,
		item_image,
		item_link,
		item_gep,
		level,
		burnlevel,
		gauntlets,
		fireburn,
		firegaunt,
		cookmatic,
		experience,
		xpfire,
		tools,
		brewing,
		water,
		heat,
		quest,
		members,
		ticks,
		method,
		materials,
		instructions,
		servings,
		lphealed,
		totalvar
	}
end

function p._main(...)
	-- Unpack parameters
	local frame,
		item_name,item_image,
		item_link,item_gep,
		level,burnlevel,
		gauntlets,fireburn,
		firegaunt,cookmatic,
		experience,xpfire,
		tools,brewing,water,
		heat,quest,members,
		ticks,method,
		materials,instructions,
		servings,lphealed,
		totalvar = unpack(...)
	
	local ret = mw.html.create('table')
	ret:addClass('wikitable')
		:css({ width = '50%',
			['max-width'] = '450px' })
	
	-- Caption header
	local caption = item_image..' '..item_name
	if method then
		caption = caption..string.format('<br /><i>(%s)</i>', method)
	end
	ret:tag('caption'):wikitext(caption):done()
	
	ret	:tag('tr')
			:css('text-align','center')
			:tag('th')
				:css('width','20%')
				:wikitext(cookimg..' Level')
			:done()
			:tag('th')
				:css('width','20%')
				:wikitext(cookimg..' XP')
			:done()
			:tag('th')
				:css('width','30%')
				:attr('title','Ticks per action')
				:attr('colspan','2')
				:css('cursor', 'help')
				:wikitext('[[File:Hourglass.png|link=]]')
			:done()
			:tag('th')
				:css('width','30%')
				:css('cursor', 'help')
				:attr('title','Grand Exchange median price')
				:attr('colspan','2')
				:wikitext('[[File:Make-X GE icon.png|link=]]')
			:done()
		:done()
	
	
	local xpdisp = experience
	if xpfire then
		xpdisp = '<span title="Normal xp" style="cursor: help;">'..experience..' </span><span title="Cooking on bonfire" style="cursor: help;"> ('..xpfire..')</span>'
	end
	local ticktd = mw.html.create('td')
		:attr('colspan','2')
	if tonumber(ticks,10) then
		local secs = tonumber(ticks,10) * 0.6
		ticktd:attr('title',ticks..' ticks ('..secs..' seconds) per action')
			:css('cursor', 'help')
			:wikitext(ticks..' ('..secs..'s) ')
	else
		ticktd:wikitext(ticks)
	end
	local gedisp = '-'
	if item_gep then
		gedisp = commas._add(item_gep)
	end
	ret	:tag('tr')
			:css('text-align','center')
			:tag('td')	:wikitext(level)						:done()
			:tag('td')	:wikitext(xpdisp)						:done()
			:node(ticktd)
			:tag('td')	:attr('colspan','2'):wikitext(gedisp)	:done()
		:done()
	
	if lphealed then
		local lptxt = '<span title="Life points healed" style="cursor: help;">'..lphealed..'</span>'
		if servings > 1 then
			lptxt = '<span title="Per serving" style="cursor: help;">'..commas._add(lphealed)..' </span><span title="Total" style="cursor: help;"> ('..commas._add(lphealed * servings)..')</span>'
		end
		ret:tag('tr')
			:tag('th')
				:wikitext('Servings')
			:done()
			:tag('td')
				:attr('colspan','2')
				:wikitext(servings)
			:done()
			:tag('th')
				:attr('title','Life points')
				:css('cursor', 'help')
				:wikitext('[[File:Constitution-icon.png|21x21px|link=Life points|alt=Life points]] LP')
			:done()
			:tag('td')
				:attr('colspan','2')
				:wikitext(lptxt)
			:done()
	elseif servings > 1 then
		ret:tag('tr')
			:tag('th')
				:wikitext('Servings')
			:done()
			:tag('td')
				:attr('colspan','5')
				:wikitext(servings)
			:done()
	end
	
	ret:tag('tr')
			:css('text-align','center')
			:tag('th')
				:attr('colspan','6')
				:wikitext('Requirements')
			:done()
		:done()
	
	if gauntlets or cookmatic then
		local gctitle = '[[File:Cooking gauntlets.png|21x21px|link=Cooking gauntlets|alt=Cooking gauntlets]] Gauntlets'
		if cookmatic then
			gctitle = '[[File:Cooking range (Lumbridge Castle).png|21x21px|link=Cooking range (Lumbridge Castle)|alt=Cook-o-matic 25]] Cook-o-matic 25'
		end
		ret:tag('tr')
			:tag('td')
				:attr('colspan','2')
				:wikitext('Burn level')
			:done()
			:tag('td')
				:css('text-align','center')
				:wikitext(burnlevel or editbutton('?'))
			:done()
			:tag('td')
				:attr('colspan','2')
				:wikitext(gctitle)
			:done()
			:tag('td')
				:css('text-align','center')
				:wikitext(gauntlets or cookmatic)
			:done()
	elseif burnlevel or heat then
		ret:tag('tr')
			:tag('td')
				:attr('colspan','5')
				:wikitext('Burn Level')
			:done()
			:tag('td')
				:css('text-align','center')
				:wikitext(burnlevel or editbutton('?'))
			:done()
	end
	if fireburn or firegaunt then
		if firegaunt then
			ret:tag('tr')
				:tag('td')
					:attr('colspan','2')
					:wikitext('[[File:Bonfire map icon.png|21x21px|link=Fire|alt=Fire]] Burn level (fire)')
				:done()
				:tag('td')
					:css('text-align','center')
					:wikitext(fireburn or editbutton('?'))
				:done()
				:tag('td')
					:attr('colspan','2')
					:wikitext('[[File:Bonfire map icon.png|21x21px|link=Fire|alt=Fire]][[File:Cooking gauntlets.png|21x21px|link=Cooking gauntlets|alt=Cooking gauntlets]] Gauntlets (f)')
				:done()
				:tag('td')
					:css('text-align','center')
					:wikitext(firegaunt or editbutton('?'))
				:done()
		else
			ret:tag('tr')
				:tag('td')
					:attr('colspan','5')
					:wikitext('[[File:Bonfire map icon.png|21x21px|link=Fire|alt=Fire]] Burn level (fire)')
				:done()
				:tag('td')
					:css('text-align','center')
					:wikitext(fireburn or editbutton('?'))
				:done()
		end
	end
	-- Quest requirement
	if quest then
		ret:tag('tr')
			:tag('td')
				:attr('colspan','6')
				:wikitext(skillpic('quest')..' '..quest)
			:done()
		:done()
	end
	ret:tag('tr'):
			tag('td')
				:attr('colspan','6')
				:wikitext(members)
			:done()
		:done()
	if heat == 'range' then
		ret:tag('tr')
			:tag('td')
				:attr('colspan','6')
				:wikitext(mapicons._main('Range')..' Can only be cooked at a [[Range]]')
	elseif heat == 'fire' then
		ret:tag('tr')
			:tag('td')
				:attr('colspan','6')
				:wikitext(mapicons._main('Bonfire')..' Can only be cooked at a [[fire]]')
	elseif heat then
		ret:tag('tr')
			:tag('td')
				:attr('colspan','6')
				:wikitext('Requires a [[Range|range]] '..mapicons._main('Range')..' or a [[Fire|fire]] '..mapicons._main('Bonfire'))
	end
	if brewing then
		ret:tag('tr')
			:tag('td')
				:attr('colspan','6')
				:wikitext(mapicons._main('Brewing')..' Can only be brewed at a [[Brewery]]')
	end
	if water then
		ret:tag('tr')
			:tag('td')
				:attr('colspan','6')
				:wikitext(mapicons._main('Water source')..' Must be made at a [[water source]]')
	end
	if tools then
		ret:tag('tr')
			:tag('td')
				:wikitext('Tools')
			:done()
			:tag('td')
				:attr('colspan','5')
				:wikitext(tools)
	end
	
	ret:tag('tr')
		:tag('th')
			:attr('colspan','6')
			:css('text-align','center')
			:wikitext('Ingredients')
		:done()
	:done()
	:tag('tr')
		:tag('th')
			:attr('colspan','3')
			:wikitext('Item')
		:done()
		:tag('th')
			:css('width','15%')
			:wikitext('Quantity')
		:done()
		:tag('th')
			:css('width','15%')
			:wikitext('Price')
		:done()
		:tag('th')
			:wikitext('Total')
		:done()
	:done()
	
	-- Materials
	local total_price = 0
	local valued_items = 0
	-- Iterates through the tables in the table of materials
	for i, v in ipairs(materials) do
		-- Fetch all the variables
		local mat_name = v.name
		local mat_price = v.price
		local mat_raw = v.price_raw
		local mat_ttl
		local mat_qty = v.quantity
		local mat_img = v.image
		-- If no price is given for item, delete total
		-- Otherwise quantity * price each
		if mat_raw == 0 then
			mat_ttl = '-'
		else
			mat_ttl = mat_qty * mat_raw
		end
		-- If item total is a number
		-- Add it to the overall total
		-- Indicate this by incrementing valued item count
		-- Done with total calculations, add commas to total for formatting
		if type(mat_ttl) == 'number' then
			total_price = total_price + mat_ttl
			mat_ttl = commas._add(mat_ttl)
			if mat_raw > 0 then
				valued_items = valued_items + 1
			end
		end
		ret:tag('tr')
			:tag('td')
				:css({ ['border-right'] = 'none',
					['text-align'] = 'center' })
				:wikitext(mat_img)
			:done()
			:tag('td')
				:attr('colspan','2')
				:css({ ['border-left'] = 'none',
					['border-right'] = 'none',
					['text-align'] = 'left' })
				:wikitext(mat_name)
			:done()
			:tag('td')
				:css({ ['border-left'] = 'none',
					['border-right'] = 'none',
					['text-align'] = 'right' })
				:wikitext(commas._add(mat_qty))
			:done()
			:tag('td')
				:css({ ['border-left'] = 'none',
					['text-align'] = 'right' })
				:wikitext(mat_price)
			:done()
			:tag('td')
				:css('text-align','right')
				:wikitext(mat_ttl)
			:done()
		:done()
	end

	-- If no materials found
	-- Indicate nothing listed, add an edit button for the page
	if #materials == 0 then
		ret:tag('tr')
				:tag('td')
					:attr('colspan','6')
					:css({ ['font-style'] = 'italic',
						['text-align'] = 'center' })
					:wikitext('Ingredients unlisted '..editbutton())
				:done()
			:done()
	end

	-- Total
	-- Hide if less than 2 items have a value
	if valued_items > 1 then
		ret:tag('tr')
			:tag('th')
				:attr('colspan','5')
				:css('text-align','right')
				:wikitext('Total price')
			:done()
			:tag('td')
				:css('text-align','right')
				:wikitext(commas._add(total_price))
			:done()
		:done()
	end
	if type(totalvar) == 'string' and #totalvar > 0 then
		mw.ext.VariablesLua.vardefine(totalvar, total_price)
	end
	
	-- Profit
	if valued_items >= 1 and item_gep then
		local profit = item_gep - total_price
		local profclass = 'text-green'
		if profit < 0 then
			profclass = 'text-red'
		end
		ret:tag('tr')
			:tag('th')
				:attr('colspan','5')
				:css('text-align','right')
				:wikitext('Profit')
			:done()
			:tag('td')
				:css('text-align','right')
				:addClass(profclass)
				:wikitext(commas._add(profit))
			:done()
		:done()
	end
	
	if instructions then
		ret:tag('tr')
			:tag('th')
				:attr('colspan','6')
				:css('text-align','center')
				:wikitext('Instructions')
			:done()
		:done()
		:tag('tr')
			:tag('td')
				:attr('colspan','6')
				:wikitext(instructions)
	end
	
	-- SMW
	if onmain then
		local smw = {}
		local jsonmats = {}
		if materials then
			smw['Made from item'] = {}
			for _, v in ipairs(materials) do
				table.insert(jsonmats, {
					name = v.name_raw,
					quantity = v.quantity,
					image = v.image_raw
				})
				table.insert(smw['Made from item'],v.name_raw)
			end
		end
		
		if tonumber(ticks,10) then
			smw['Production ticks'] = ticks
		end
		
		local facilities = ''
		if heat == 'range' then
			facilities = 'Range'
		elseif heat == 'fire' then
			facilities = 'Fire'
		elseif heat then
			facilities = 'Range or Fire'
		end
		if brewing then
			facilities = 'Brewing'
		end
		if water then
			facilities = 'Water source'
		end
		
		local prodjson = {
			product = item_name,
			link = item_link,
			image = item_image,
			ticks = ticks,
			improved = '',
			method = method or '',
			facility = facilities,
			mats = jsonmats,
			skill = 'Cooking',
			level = tonumber(level) or '?',
			exp = tonumber(experience) or '?',
			skill2 = '?',
			exp2 = '?',
			level2 = '?',
			skill3 = '?',
			exp3 = '?',
			level3 = '?',
			quantity = 1
		}
		
		prodjson = mw.text.jsonEncode( prodjson )
		smw['Production JSON'] = prodjson
		
		mw.smw.set(smw)
	end
	
	-- Add categories
	cats = {}
	if not experience then
		table.insert(cats,'Recipes missing xp')
	end
	if not tonumber(level,10) then
		table.insert(cats,'Recipes missing skill level')
	end
	if not tonumber(ticks,10) and string.lower(ticks) ~= 'varies' then
		table.insert(cats,'Recipes missing ticks')
	end
	for i, v in ipairs(cats) do
		if (v ~= '') then
			cats[i] = string.format('[[Category:%s]]',v)
		end
	end
	
	return tostring(ret)..table.concat(cats,'')
end

return p