<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.runerealm.org/index.php?action=history&amp;feed=atom&amp;title=Module%3AMmgtable</id>
	<title>Module:Mmgtable - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.runerealm.org/index.php?action=history&amp;feed=atom&amp;title=Module%3AMmgtable"/>
	<link rel="alternate" type="text/html" href="https://wiki.runerealm.org/index.php?title=Module:Mmgtable&amp;action=history"/>
	<updated>2026-04-30T14:59:14Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.41.1</generator>
	<entry>
		<id>https://wiki.runerealm.org/index.php?title=Module:Mmgtable&amp;diff=35051&amp;oldid=prev</id>
		<title>Alex: Created page with &quot;local p = {}  -- imports local gePrice = require(&#039;Module:Exchange&#039;)._price local yn = require(&#039;Module:Yesno&#039;) local round = require(&#039;Module:Number&#039;)._round local _coins = require(&#039;Module:Currency&#039;)._amount local vdf = mw.ext.VariablesLua.vardefine local lang = mw.getContentLanguage() local title = mw.title.getCurrentTitle() local onmain = require(&#039;Module:Mainonly&#039;).on_main  TAX_EXEMPT = mw.smw.ask({&#039;Category:Items exempt from Grand Exchange tax&#039;})  function expr(x)...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.runerealm.org/index.php?title=Module:Mmgtable&amp;diff=35051&amp;oldid=prev"/>
		<updated>2024-10-16T23:12:41Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;local p = {}  -- imports local gePrice = require(&amp;#039;Module:Exchange&amp;#039;)._price local yn = require(&amp;#039;Module:Yesno&amp;#039;) local round = require(&amp;#039;Module:Number&amp;#039;)._round local _coins = require(&amp;#039;Module:Currency&amp;#039;)._amount local vdf = mw.ext.VariablesLua.vardefine local lang = mw.getContentLanguage() local title = mw.title.getCurrentTitle() local onmain = require(&amp;#039;Module:Mainonly&amp;#039;).on_main  TAX_EXEMPT = mw.smw.ask({&amp;#039;&lt;a href=&quot;/w/Category:Items_exempt_from_Grand_Exchange_tax&quot; title=&quot;Category:Items exempt from Grand Exchange tax&quot;&gt;Category:Items exempt from Grand Exchange tax&lt;/a&gt;&amp;#039;})  function expr(x)...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local p = {}&lt;br /&gt;
&lt;br /&gt;
-- imports&lt;br /&gt;
local gePrice = require(&amp;#039;Module:Exchange&amp;#039;)._price&lt;br /&gt;
local yn = require(&amp;#039;Module:Yesno&amp;#039;)&lt;br /&gt;
local round = require(&amp;#039;Module:Number&amp;#039;)._round&lt;br /&gt;
local _coins = require(&amp;#039;Module:Currency&amp;#039;)._amount&lt;br /&gt;
local vdf = mw.ext.VariablesLua.vardefine&lt;br /&gt;
local lang = mw.getContentLanguage()&lt;br /&gt;
local title = mw.title.getCurrentTitle()&lt;br /&gt;
local onmain = require(&amp;#039;Module:Mainonly&amp;#039;).on_main&lt;br /&gt;
&lt;br /&gt;
TAX_EXEMPT = mw.smw.ask({&amp;#039;[[Category:Items exempt from Grand Exchange tax]]&amp;#039;})&lt;br /&gt;
&lt;br /&gt;
function expr(x)&lt;br /&gt;
	local e_g, e = pcall(mw.ext.ParserFunctions.expr, x)&lt;br /&gt;
	if e_g then&lt;br /&gt;
		return e&lt;br /&gt;
	end&lt;br /&gt;
	return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function sigfig(x, p)&lt;br /&gt;
	local x_sign = x &amp;lt; 0 and &amp;#039;-1&amp;#039; or &amp;#039;1&amp;#039;&lt;br /&gt;
	local x = math.abs(x)&lt;br /&gt;
	if x == 0 then&lt;br /&gt;
		return 0&lt;br /&gt;
	end&lt;br /&gt;
	local n = math.floor(math.log10(x)) + 1 - p&lt;br /&gt;
	return tonumber(x_sign) * math.pow(10,n) * round(x/math.pow(10, n), 0)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function autoround(x, f)&lt;br /&gt;
	x = tonumber(x) or 0&lt;br /&gt;
	local _x&lt;br /&gt;
	if x &amp;lt; 0.1 and x &amp;gt; -0.1 then&lt;br /&gt;
		_x = sigfig(x,2)&lt;br /&gt;
	elseif x &amp;gt;= 100 or x &amp;lt;= -100 then&lt;br /&gt;
		_x = round(x, 0)&lt;br /&gt;
	else&lt;br /&gt;
		_x = round(x, 2)&lt;br /&gt;
	end&lt;br /&gt;
	if f then&lt;br /&gt;
		return lang:formatNum(_x)&lt;br /&gt;
	end&lt;br /&gt;
	return _x&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function deduct_tax(name, val)&lt;br /&gt;
	local tax_excluded = false&lt;br /&gt;
	for _, v in ipairs(TAX_EXEMPT) do&lt;br /&gt;
		local item = string.match(v[1], &amp;#039;%|(.*)]]$&amp;#039;)&lt;br /&gt;
		if item == name then&lt;br /&gt;
			tax_excluded = true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if not tax_excluded then&lt;br /&gt;
		return val - math.min(math.floor(val * 0.01), 5000000)&lt;br /&gt;
	end&lt;br /&gt;
	return val&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Config constants, change as needed&lt;br /&gt;
MAX_INPUTS = 75&lt;br /&gt;
MAX_OUTPUTS = 75&lt;br /&gt;
MAX_XP = 75&lt;br /&gt;
&lt;br /&gt;
function p.testmmgtable(args)&lt;br /&gt;
	return p._mmgtable(mw.getCurrentFrame(), args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.mmgtable(frame)&lt;br /&gt;
	local args = frame:getParent().args&lt;br /&gt;
	return p._mmgtable(frame, args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Create an MMG table.&lt;br /&gt;
-- Frame is the frame the module was invoked from.&lt;br /&gt;
-- Args are the template arguments used when creating the table.&lt;br /&gt;
function p._mmgtable(frame, args)&lt;br /&gt;
	local parsedInput = handleInputs(args)&lt;br /&gt;
	local parsedOutput = handleOutputs(args)&lt;br /&gt;
	local parsedXP = handleXP(args)&lt;br /&gt;
	local is_per_kill = yn(args.isperkill)&lt;br /&gt;
	local ret = mw.html.create(&amp;#039;&amp;#039;)&lt;br /&gt;
	&lt;br /&gt;
	mw.logObject(parsedInput)&lt;br /&gt;
	mw.logObject(parsedOutput)&lt;br /&gt;
	mw.logObject(parsedXP)&lt;br /&gt;
	&lt;br /&gt;
	local tbl = ret:tag(&amp;#039;table&amp;#039;):addClass(&amp;#039;wikitable mmg-table&amp;#039;)&lt;br /&gt;
			:cssText(&amp;#039;width:100%;text-align:center;&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;caption&amp;#039;)&lt;br /&gt;
				:wikitext(args[&amp;#039;Activity&amp;#039;])&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
				:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
					:wikitext(&amp;#039;Requirements&amp;#039;)&lt;br /&gt;
				:done()&lt;br /&gt;
				:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
					:attr(&amp;#039;rowspan&amp;#039;, &amp;#039;9&amp;#039;)&lt;br /&gt;
					:wikitext(args[&amp;#039;Image&amp;#039;] or &amp;#039;{{{Image}}}&amp;#039;)&lt;br /&gt;
				:done()&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
				:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
					:wikitext(&amp;#039;Skills&amp;#039;)&lt;br /&gt;
					:cssText(&amp;#039;font-weight:normal&amp;#039;)&lt;br /&gt;
				:done()&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
				:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
					:addClass(&amp;#039;plainlist&amp;#039;)&lt;br /&gt;
					:newline()&lt;br /&gt;
					:wikitext(args[&amp;#039;Skill&amp;#039;] or &amp;#039;None&amp;#039;) -- Can leave blank if no reqs.&lt;br /&gt;
				:done()&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
				:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
					:wikitext(&amp;#039;Items&amp;#039;)&lt;br /&gt;
					:cssText(&amp;#039;font-weight:normal&amp;#039;)&lt;br /&gt;
				:done()&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
				:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
					:addClass(&amp;#039;plainlist&amp;#039;)&lt;br /&gt;
					:newline()&lt;br /&gt;
					:wikitext(args[&amp;#039;Item&amp;#039;] or &amp;#039;None&amp;#039;) -- Can leave blank if no reqs.&lt;br /&gt;
				:done()&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
				:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
					:wikitext(&amp;#039;Quest&amp;#039;)&lt;br /&gt;
					:cssText(&amp;#039;font-weight:normal&amp;#039;)&lt;br /&gt;
				:done()&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
				:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
					:addClass(&amp;#039;plainlist&amp;#039;)&lt;br /&gt;
					:newline()&lt;br /&gt;
					:wikitext(args[&amp;#039;Quest&amp;#039;] or &amp;#039;None&amp;#039;) -- Can leave blank if no reqs&lt;br /&gt;
				:done()&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
				:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
					:wikitext(&amp;#039;Other&amp;#039;)&lt;br /&gt;
					:cssText(&amp;#039;font-weight:normal&amp;#039;)&lt;br /&gt;
				:done()&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
				:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
					:addClass(&amp;#039;plainlist&amp;#039;)&lt;br /&gt;
					:newline()&lt;br /&gt;
					:wikitext(args[&amp;#039;Other&amp;#039;] or &amp;#039;None&amp;#039;) -- Can leave blank if no reqs&lt;br /&gt;
				:done()&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
				:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
					:attr(&amp;#039;colspan&amp;#039;, &amp;#039;2&amp;#039;)&lt;br /&gt;
					:wikitext(&amp;#039;Results&amp;#039;)&lt;br /&gt;
				:done()&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
				:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
					:wikitext(&amp;#039;Profit&amp;#039;)&lt;br /&gt;
					:cssText(&amp;#039;font-weight:normal&amp;#039;)&lt;br /&gt;
				:done()&lt;br /&gt;
				:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
					:wikitext(&amp;#039;Experience gained&amp;#039;)&lt;br /&gt;
					:cssText(&amp;#039;font-weight:normal&amp;#039;)&lt;br /&gt;
				:done()&lt;br /&gt;
			:done()&lt;br /&gt;
			&lt;br /&gt;
	local xpTR = tbl:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
	local profitTD = xpTR:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
	profitTD:addClass(&amp;#039;mmg-varieswithkph&amp;#039;)&lt;br /&gt;
		:attr({[&amp;#039;data-mmg-cost-ph&amp;#039;] = parsedOutput.valueph-parsedInput.valueph, [&amp;#039;data-mmg-cost-pk&amp;#039;] = parsedOutput.valuepk-parsedInput.valuepk})&lt;br /&gt;
		:wikitext(_coins(autoround(parsedOutput.value - parsedInput.value), &amp;#039;coins&amp;#039;)..&amp;#039;, after [[Grand Exchange#Convenience fee and item sink|tax]]&amp;#039;)&lt;br /&gt;
	&lt;br /&gt;
	local xpTD = xpTR:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
	if args[&amp;#039;Other Benefits&amp;#039;] then&lt;br /&gt;
		xpTD:newline():wikitext(args[&amp;#039;Other Benefits&amp;#039;]):addClass(&amp;#039;plainlist&amp;#039;)&lt;br /&gt;
	elseif #parsedXP.spans &amp;gt; 0 then&lt;br /&gt;
		for i,v in ipairs(parsedXP.spans) do&lt;br /&gt;
			xpTD:node(v)&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		xpTD:wikitext(&amp;#039;None&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local putsTRH = tbl:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
	local inputTH = putsTRH:tag(&amp;#039;th&amp;#039;):cssText(&amp;#039;font-weight:normal&amp;#039;)&lt;br /&gt;
	inputTH:wikitext(&amp;#039;Inputs&amp;#039;)&lt;br /&gt;
	if parsedInput.value ~= 0 then&lt;br /&gt;
		inputTH:wikitext(&amp;#039; (&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;span&amp;#039;)&lt;br /&gt;
				:addClass(&amp;#039;mmg-varieswithkph&amp;#039;)&lt;br /&gt;
				:attr({[&amp;#039;data-mmg-cost-ph&amp;#039;] = parsedInput.valueph, [&amp;#039;data-mmg-cost-pk&amp;#039;] = parsedInput.valuepk})&lt;br /&gt;
				:wikitext(_coins(autoround(parsedInput.value), &amp;#039;coins&amp;#039;))&lt;br /&gt;
			:done()&lt;br /&gt;
			:wikitext(&amp;#039;)&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local outputTH = putsTRH:tag(&amp;#039;th&amp;#039;):cssText(&amp;#039;font-weight:normal&amp;#039;)&lt;br /&gt;
	outputTH:wikitext(&amp;#039;Outputs&amp;#039;)&lt;br /&gt;
	if parsedOutput.value ~= 0 then&lt;br /&gt;
		outputTH:wikitext(&amp;#039; (&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;span&amp;#039;)&lt;br /&gt;
				:addClass(&amp;#039;mmg-varieswithkph&amp;#039;)&lt;br /&gt;
				:attr({[&amp;#039;data-mmg-cost-ph&amp;#039;] = parsedOutput.valueph, [&amp;#039;data-mmg-cost-pk&amp;#039;] = parsedOutput.valuepk})&lt;br /&gt;
				:wikitext(_coins(autoround(parsedOutput.value), &amp;#039;coins&amp;#039;))&lt;br /&gt;
			:done()&lt;br /&gt;
			:wikitext(&amp;#039;, after [[Grand Exchange#Convenience fee and item sink|tax]])&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local inputTR = tbl:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
	local inputTD = inputTR:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
	local outputTD = inputTR:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
	for i,v in ipairs(parsedInput.spans) do&lt;br /&gt;
		inputTD:node(v)&lt;br /&gt;
	end&lt;br /&gt;
	for i,v in ipairs(parsedOutput.spans) do&lt;br /&gt;
		outputTD:node(v)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local kph_text = args[&amp;#039;kph name&amp;#039;] or &amp;#039;Kills per hour&amp;#039;&lt;br /&gt;
	if is_per_kill then&lt;br /&gt;
		tbl:addClass(&amp;#039;mmg-isperkill&amp;#039;)&lt;br /&gt;
			:attr(&amp;#039;data-default-kph&amp;#039;, args.kph)&lt;br /&gt;
			:attr(&amp;#039;data-default-kph-name&amp;#039;, kph_text)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if not(yn(args.noexports)) then&lt;br /&gt;
		if is_per_kill then&lt;br /&gt;
			vdf(&amp;#039;kph&amp;#039;, string.format(&amp;#039;&amp;lt;span class=&amp;quot;mmg-variable mmg-kph&amp;quot;&amp;gt;%s&amp;lt;/span&amp;gt;&amp;#039;, args.kph))&lt;br /&gt;
			vdf(&amp;#039;default_kph&amp;#039;, args.kph)&lt;br /&gt;
			vdf(&amp;#039;inputPH&amp;#039;, string.format(&amp;#039;&amp;lt;span class=&amp;quot;mmg-variable mmg-input-ph&amp;quot; data-mmg-cost-ph=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/span&amp;gt;&amp;#039;, parsedInput.valueph, _coins(autoround(parsedInput.valueph), &amp;#039;nocoins&amp;#039;)))&lt;br /&gt;
			vdf(&amp;#039;inputPK&amp;#039;, string.format(&amp;#039;&amp;lt;span class=&amp;quot;mmg-variable mmg-input-pk&amp;quot; data-mmg-cost-pk=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/span&amp;gt;&amp;#039;, parsedInput.valuepk, _coins(autoround(parsedInput.valuepk), &amp;#039;nocoins&amp;#039;)))&lt;br /&gt;
			vdf(&amp;#039;input&amp;#039;, string.format(&amp;#039;&amp;lt;span class=&amp;quot;mmg-variable mmg-input&amp;quot; data-mmg-cost-ph=&amp;quot;%s&amp;quot;, data-mmg-cost-pk=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/span&amp;gt;&amp;#039;, parsedInput.valueph, parsedInput.valuepk, _coins(autoround(parsedInput.value), &amp;#039;nocoins&amp;#039;)))&lt;br /&gt;
			vdf(&amp;#039;outputPH&amp;#039;, string.format(&amp;#039;&amp;lt;span class=&amp;quot;mmg-variable mmg-output-ph&amp;quot; data-mmg-cost-ph=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/span&amp;gt;&amp;#039;, parsedOutput.valueph, _coins(autoround(parsedOutput.valueph), &amp;#039;nocoins&amp;#039;)))&lt;br /&gt;
			vdf(&amp;#039;outputPK&amp;#039;, string.format(&amp;#039;&amp;lt;span class=&amp;quot;mmg-variable mmg-output-pk&amp;quot; data-mmg-cost-pk=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/span&amp;gt;&amp;#039;, parsedOutput.valuepk, _coins(autoround(parsedOutput.valuepk), &amp;#039;nocoins&amp;#039;)))&lt;br /&gt;
			vdf(&amp;#039;output&amp;#039;, string.format(&amp;#039;&amp;lt;span class=&amp;quot;mmg-variable mmg-varieswithkph mmg-output&amp;quot; data-mmg-cost-ph=&amp;quot;%s&amp;quot;, data-mmg-cost-pk=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/span&amp;gt;&amp;#039;, parsedOutput.valueph, parsedOutput.valuepk, _coins(autoround(parsedOutput.value), &amp;#039;nocoins&amp;#039;)))&lt;br /&gt;
			vdf(&amp;#039;profitPH&amp;#039;, string.format(&amp;#039;&amp;lt;span class=&amp;quot;mmg-variable mmg-profit-ph&amp;quot; data-mmg-cost-ph=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/span&amp;gt;&amp;#039;, parsedOutput.valueph-parsedInput.valueph, _coins(autoround(parsedOutput.valueph-parsedInput.valueph), &amp;#039;nocoins&amp;#039;)))&lt;br /&gt;
			vdf(&amp;#039;profitPK&amp;#039;, string.format(&amp;#039;&amp;lt;span class=&amp;quot;mmg-variable mmg-profit-pk&amp;quot; data-mmg-cost-pk=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/span&amp;gt;&amp;#039;, parsedOutput.valuepk-parsedInput.valuepk, _coins(autoround(parsedOutput.valuepk-parsedInput.valuepk), &amp;#039;nocoins&amp;#039;)))&lt;br /&gt;
			vdf(&amp;#039;profit&amp;#039;, string.format(&amp;#039;&amp;lt;span class=&amp;quot;mmg-variable mmg-varieswithkph mmg-profit&amp;quot; data-mmg-cost-ph=&amp;quot;%s&amp;quot;, data-mmg-cost-pk=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/span&amp;gt;&amp;#039;, parsedOutput.valueph-parsedInput.valueph, parsedOutput.valuepk-parsedInput.valuepk, _coins(autoround(parsedOutput.value-parsedInput.value), &amp;#039;nocoins&amp;#039;)))&lt;br /&gt;
		else&lt;br /&gt;
			vdf(&amp;#039;input&amp;#039;, string.format(&amp;#039;&amp;lt;span class=&amp;quot;mmg-input&amp;quot;&amp;gt;%s&amp;lt;/span&amp;gt;&amp;#039;, parsedInput.value, _coins(autoround(parsedInput.value), &amp;#039;nocoins&amp;#039;)))&lt;br /&gt;
			vdf(&amp;#039;output&amp;#039;, string.format(&amp;#039;&amp;lt;span class=&amp;quot;mmg-input&amp;quot;&amp;gt;%s&amp;lt;/span&amp;gt;&amp;#039;, parsedOutput.value, _coins(autoround(parsedOutput.value), &amp;#039;nocoins&amp;#039;)))&lt;br /&gt;
			vdf(&amp;#039;profit&amp;#039;, string.format(&amp;#039;&amp;lt;span class=&amp;quot;mmg-input&amp;quot;&amp;gt;%s&amp;lt;/span&amp;gt;&amp;#039;, parsedOutput.value-parsedInput.value, _coins(autoround(parsedOutput.value-parsedInput.value), &amp;#039;nocoins&amp;#039;)))&lt;br /&gt;
			vdf(&amp;#039;input_raw&amp;#039;, parsedInput.value)&lt;br /&gt;
			vdf(&amp;#039;output_raw&amp;#039;, parsedOutput.value)&lt;br /&gt;
			vdf(&amp;#039;profit_raw&amp;#039;, parsedOutput.value-parsedInput.value)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	frame:callParserFunction(&amp;#039;DISPLAYTITLE&amp;#039;, title.subpageText)&lt;br /&gt;
	frame:callParserFunction(&amp;#039;DEFAULTSORT&amp;#039;, title.subpageText)&lt;br /&gt;
	&lt;br /&gt;
	local cats = &amp;#039;[[Category:Money making guides]]&amp;#039;&lt;br /&gt;
	&lt;br /&gt;
	if args[&amp;#039;Members&amp;#039;] == nil then&lt;br /&gt;
		cats = cats .. &amp;#039;[[Category:Money making guides without a membership status]]&amp;#039;&lt;br /&gt;
	elseif not(yn(args[&amp;#039;Members&amp;#039;])) then&lt;br /&gt;
		cats = cats .. &amp;#039;[[Category:MMG/F2P]]&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local final_profit = parsedOutput.value - parsedInput.value&lt;br /&gt;
	&lt;br /&gt;
	local set_smw = true&lt;br /&gt;
 	if final_profit &amp;lt;= 100000 and yn(args[&amp;#039;Members&amp;#039;]) then&lt;br /&gt;
		cats = cats .. &amp;#039;[[Category:Obsolete money making guides]]&amp;#039;&lt;br /&gt;
	elseif ((final_profit &amp;lt;= 20000) and (parsedInput.value&amp;gt;0) ) then&lt;br /&gt;
		cats = cats .. &amp;#039;[[Category:Obsolete money making guides]]&amp;#039;&lt;br /&gt;
	elseif final_profit &amp;lt;= 15000 then&lt;br /&gt;
		cats = cats .. &amp;#039;[[Category:Obsolete money making guides]]&amp;#039;&lt;br /&gt;
	elseif yn(args.Exclude) then&lt;br /&gt;
		cats = cats .. &amp;#039;[[Category:Obsolete money making guides]]&amp;#039;&lt;br /&gt;
	else&lt;br /&gt;
		cats = cats .. &amp;#039;[[Category:Worthwhile money making guides]]&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if args[&amp;quot;Category&amp;quot;] then&lt;br /&gt;
		local mmgcat = ({&lt;br /&gt;
			[&amp;quot;Combat/Low&amp;quot;] = &amp;quot;[[Category:MMG/Combat]]&amp;quot;,&lt;br /&gt;
			[&amp;quot;Combat/Mid&amp;quot;] = &amp;quot;[[Category:MMG/Combat]]&amp;quot;,&lt;br /&gt;
			[&amp;quot;Combat/High&amp;quot;] = &amp;quot;[[Category:MMG/Combat]]&amp;quot;,&lt;br /&gt;
			[&amp;quot;Combat&amp;quot;] = &amp;quot;[[Category:MMG/Combat]]&amp;quot;,&lt;br /&gt;
			[&amp;quot;Skilling&amp;quot;] = &amp;quot;[[Category:MMG/Skilling]]&amp;quot;,&lt;br /&gt;
			[&amp;quot;Processing&amp;quot;] = &amp;quot;[[Category:MMG/Processing]]&amp;quot;,&lt;br /&gt;
			[&amp;quot;Recurring&amp;quot;] = &amp;quot;[[Category:MMG/Recurring]]&amp;quot;,&lt;br /&gt;
			[&amp;quot;Collecting&amp;quot;] = &amp;quot;[[Category:MMG/Collecting]]&amp;quot;&lt;br /&gt;
		})[args[&amp;quot;Category&amp;quot;]]&lt;br /&gt;
		if mmgcat == nil then&lt;br /&gt;
			cats = cats .. &amp;#039;[[Category:Money making guides with an invalid category]]&amp;#039;&lt;br /&gt;
		else&lt;br /&gt;
			cats = cats .. mmgcat&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		cats = cats .. &amp;#039;[[Category:Money making guides without a category]]&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if not onmain() then&lt;br /&gt;
		set_smw = false&lt;br /&gt;
		cats = &amp;#039;&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if set_smw then&lt;br /&gt;
		local smw_data = {&lt;br /&gt;
			members = yn(args.Members or &amp;#039;yes&amp;#039;, true),&lt;br /&gt;
			skill = args.Skill,&lt;br /&gt;
			quest = args.Quest,&lt;br /&gt;
			activity = args.Activity,&lt;br /&gt;
			category = args.Category,&lt;br /&gt;
			skillcategory = args.SkillCategory,&lt;br /&gt;
			intensity = args.Intensity,&lt;br /&gt;
			isperkill = is_per_kill,&lt;br /&gt;
			version = args.Version,&lt;br /&gt;
			inputs = parsedInput.list,&lt;br /&gt;
			outputs = parsedOutput.list&lt;br /&gt;
		}&lt;br /&gt;
		if is_per_kill then&lt;br /&gt;
			smw_data.prices = {&lt;br /&gt;
				input_perhour=parsedInput.valueph,&lt;br /&gt;
				input_perkill=parsedInput.valuepk,&lt;br /&gt;
				output_perhour=parsedOutput.valueph,&lt;br /&gt;
				output_perkill=parsedOutput.valuepk,&lt;br /&gt;
				default_kph=tonumber(args.kph) or 1,&lt;br /&gt;
				kph_text=kph_text,&lt;br /&gt;
				default_value=parsedOutput.value - parsedInput.value,&lt;br /&gt;
			}&lt;br /&gt;
		else&lt;br /&gt;
			smw_data.prices = {&lt;br /&gt;
				input=parsedInput.value,&lt;br /&gt;
				output=parsedOutput.value,&lt;br /&gt;
				value=parsedOutput.value - parsedInput.value&lt;br /&gt;
			}&lt;br /&gt;
		end&lt;br /&gt;
		smw_data = mw.text.killMarkers(mw.text.nowiki(mw.text.jsonEncode(smw_data)))&lt;br /&gt;
		mw.smw.set({&lt;br /&gt;
			[&amp;#039;MMG value&amp;#039;]=parsedOutput.value - parsedInput.value,&lt;br /&gt;
			[&amp;#039;MMG JSON&amp;#039;]=smw_data&lt;br /&gt;
		})&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return ret, cats&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Calculate the profit and do nothing else.&lt;br /&gt;
function p.profit(frame)&lt;br /&gt;
	local frame = frame or mw.getCurrentFrame()&lt;br /&gt;
	local args = frame:getParent().args -- Template args, NOT #invoke args&lt;br /&gt;
	&lt;br /&gt;
	return handleOutputs(args).value - handleInputs(args).value&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Implements handleInputs and handleOutputs&lt;br /&gt;
-- See those functions for further details&lt;br /&gt;
function handleIteratedArgs(args, prefix, max_iters)&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
	local items = {}&lt;br /&gt;
	local total_item_value = 0&lt;br /&gt;
	local textlines = {}&lt;br /&gt;
	local is_per_kill = yn(args.isperkill)&lt;br /&gt;
	local defaultKPH = tonumber(args.kph) or 1&lt;br /&gt;
	local value_per_kill = 0&lt;br /&gt;
	local value_per_hour = 0&lt;br /&gt;
	&lt;br /&gt;
	for i=1,max_iters,1 do&lt;br /&gt;
		if not args[prefix..i] then break end&lt;br /&gt;
		local pri = prefix..i&lt;br /&gt;
		local span = mw.html.create(&amp;#039;span&amp;#039;)&lt;br /&gt;
		span:addClass(&amp;#039;mmg-itemline mmg-&amp;#039;..prefix:lower())&lt;br /&gt;
		&lt;br /&gt;
		local name = args[pri]&lt;br /&gt;
		local qty_param = args[pri..&amp;#039;num&amp;#039;]&lt;br /&gt;
		local actual_qty = nil&lt;br /&gt;
		local value_param = args[pri..&amp;#039;value&amp;#039;]&lt;br /&gt;
		local actual_value = nil&lt;br /&gt;
		local is_per_hour = not is_per_kill&lt;br /&gt;
		if is_per_kill and yn(args[pri..&amp;#039;isph&amp;#039;]) then&lt;br /&gt;
			is_per_hour = true&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- Keep track of sanity check states - we want to handle them gracefully later.&lt;br /&gt;
		local invalid_qty_present = false&lt;br /&gt;
		local invalid_value_present = false&lt;br /&gt;
		local failed_ge_lookup = false&lt;br /&gt;
		local pricetype = &amp;#039;&amp;#039;&lt;br /&gt;
		&lt;br /&gt;
		if qty_param then&lt;br /&gt;
			actual_qty = tonumber(qty_param) or expr(qty_param)&lt;br /&gt;
			invalid_qty_present = not actual_qty&lt;br /&gt;
			actual_qty = actual_qty or 1&lt;br /&gt;
			-- If the given quantity doesn&amp;#039;t look like a number, we&amp;#039;ll default to 1&lt;br /&gt;
			--   but we should probably alert the user&lt;br /&gt;
			--   since they might want to fix that&lt;br /&gt;
		else&lt;br /&gt;
			-- Default value of 1&lt;br /&gt;
			actual_qty = 1&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if value_param then&lt;br /&gt;
			-- Again, if it was specified, it should be a number&lt;br /&gt;
			-- If it isn&amp;#039;t, we pretend it wasn&amp;#039;t specified&lt;br /&gt;
			--   but we alert the user because it&amp;#039;s probably not what they want&lt;br /&gt;
			actual_value = tonumber(value_param) or expr(value_param)&lt;br /&gt;
			invalid_value_present = not actual_value&lt;br /&gt;
			pricetype = &amp;#039;value&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- If we got the value earlier, skip this part&lt;br /&gt;
		if not actual_value then&lt;br /&gt;
			-- Here we try to find an exchange price&lt;br /&gt;
			-- If we get here, and we can&amp;#039;t get an exchange price&lt;br /&gt;
			-- we default to 0.&lt;br /&gt;
			-- This is almost certainly not what the user wants,&lt;br /&gt;
			-- so we warn them about it.&lt;br /&gt;
			local success, price = pcall(gePrice, name)&lt;br /&gt;
			actual_value = success and tonumber(price) -- This is awful but still pleasant somehow&lt;br /&gt;
			failed_ge_lookup = not actual_value&lt;br /&gt;
			actual_value = actual_value or 0&lt;br /&gt;
			&lt;br /&gt;
			-- GE takes 1% (rounding down) tax on items sold for &amp;gt; 99gp&lt;br /&gt;
			-- except for a few random ones (chisel, spade, etc)&lt;br /&gt;
			if prefix == &amp;#039;Output&amp;#039; and actual_value &amp;gt; 99 then&lt;br /&gt;
				actual_value = deduct_tax(name, actual_value)&lt;br /&gt;
			end&lt;br /&gt;
			pricetype = &amp;#039;gemw&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
	&lt;br /&gt;
		local this_item_value, this_item_qty, attrName&lt;br /&gt;
		local attrVal = actual_qty * actual_value&lt;br /&gt;
		if is_per_kill and not is_per_hour then&lt;br /&gt;
			span:addClass(&amp;#039;mmg-varieswithkph&amp;#039;)&lt;br /&gt;
			this_item_qty = actual_qty * defaultKPH&lt;br /&gt;
			this_item_value = attrVal * defaultKPH&lt;br /&gt;
			value_per_kill = value_per_kill + attrVal&lt;br /&gt;
			attrName = &amp;#039;data-mmg-cost-pk&amp;#039;&lt;br /&gt;
		else&lt;br /&gt;
			this_item_qty = actual_qty&lt;br /&gt;
			this_item_value = attrVal&lt;br /&gt;
			value_per_hour = value_per_hour + attrVal&lt;br /&gt;
			attrName = &amp;#039;data-mmg-cost-ph&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
		total_item_value = total_item_value + this_item_value&lt;br /&gt;
		&lt;br /&gt;
		span:tag(&amp;#039;span&amp;#039;):addClass(&amp;#039;mmg-quantity&amp;#039;):attr(&amp;#039;data-mmg-qty&amp;#039;, actual_qty):wikitext(autoround(this_item_qty, true))&lt;br /&gt;
		if invalid_qty_present then&lt;br /&gt;
			span:node(warning(&amp;#039;Could not interpret \&amp;#039;&amp;#039;..qty_param..&amp;#039;\&amp;#039; as a number, defaulting to 1&amp;#039;))&lt;br /&gt;
		end&lt;br /&gt;
		span:wikitext(string.format(&amp;#039; × [[File:%s.png|link=%s]] [[%s]] (&amp;#039;, name, name, name))&lt;br /&gt;
		span:tag(&amp;#039;span&amp;#039;):addClass(&amp;#039;mmg-cost&amp;#039;):attr(attrName, attrVal):wikitext(_coins(autoround(this_item_value), &amp;#039;nocoins&amp;#039;))&lt;br /&gt;
		span:wikitext(&amp;#039;)&amp;#039;)&lt;br /&gt;
		if invalid_value_present then&lt;br /&gt;
			span:node(warning(&amp;#039;Could not interpret \&amp;#039;&amp;#039;..value_param..&amp;#039;\&amp;#039; as a number, ignoring.&amp;#039;))&lt;br /&gt;
		end&lt;br /&gt;
		if failed_ge_lookup then&lt;br /&gt;
			span:node(warning(&amp;#039;Could not find exchange price for item \&amp;#039;&amp;#039;..name..&amp;#039;\&amp;#039;, please double-check the spelling&amp;#039;))&lt;br /&gt;
			span:wikitext(&amp;#039;[[Category:Money making guides with a failed GE lookup]]&amp;#039;)&lt;br /&gt;
		end&lt;br /&gt;
		if args[pri..&amp;#039;note&amp;#039;] then&lt;br /&gt;
			span:tag(&amp;#039;span&amp;#039;):addClass(&amp;#039;mmg-note&amp;#039;):wikitext(&amp;#039; &amp;#039;,args[pri..&amp;#039;note&amp;#039;])&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		table.insert(textlines, span)&lt;br /&gt;
			&lt;br /&gt;
		table.insert(items, {name = name, qty = actual_qty, value = actual_value, isph = is_per_hour, pricetype=pricetype})&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return {value = total_item_value, valuepk = value_per_kill, valueph = value_per_hour, spans = textlines, list = items}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- args are the args supplied to the template, (or a subset of them contining all input arguments)&lt;br /&gt;
-- Returns a table. The table has three keys: &amp;#039;value&amp;#039;, &amp;#039;text&amp;#039;, and &amp;#039;as_table&amp;#039;&lt;br /&gt;
---- &amp;#039;value&amp;#039; contains the total value of the inputs specified by args&lt;br /&gt;
---- &amp;#039;text&amp;#039; contains a formatted string based on the inputs specified by args. This can be directly plugged into the HTML table.&lt;br /&gt;
---- &amp;#039;list&amp;#039; contains all the inputs as a Lua list. Each input is represented by a table with the following keys&lt;br /&gt;
------ &amp;#039;name&amp;#039; being the name of the item&lt;br /&gt;
------ &amp;#039;value&amp;#039; being the value of the item in question&lt;br /&gt;
------ &amp;#039;qty&amp;#039; being the quantity specified for the item&lt;br /&gt;
function handleInputs(args)&lt;br /&gt;
	return handleIteratedArgs(args, &amp;#039;Input&amp;#039;, MAX_INPUTS)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- args are the args supplied to the template, (or a subset of them contining all output arguments)&lt;br /&gt;
-- Returns a table. The table has two keys: &amp;#039;value&amp;#039;, and &amp;#039;text&amp;#039;&lt;br /&gt;
---- &amp;#039;value&amp;#039; contains the total value of the outputs specified by args&lt;br /&gt;
---- &amp;#039;text&amp;#039; contains a formatted string based on the outputs specified by args. This can be directly plugged into the HTML table.&lt;br /&gt;
---- &amp;#039;list&amp;#039; contains all the outputs as a Lua list. Each output is represented by a table with the following keys&lt;br /&gt;
------ &amp;#039;name&amp;#039; being the name of the item&lt;br /&gt;
------ &amp;#039;value&amp;#039; being the value of the item in question&lt;br /&gt;
------ &amp;#039;qty&amp;#039; being the quantity specified for the item&lt;br /&gt;
function handleOutputs(args)&lt;br /&gt;
	return handleIteratedArgs(args, &amp;#039;Output&amp;#039;, MAX_OUTPUTS)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function handleXP(args)&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
	local items = {}&lt;br /&gt;
	local textlines = {}&lt;br /&gt;
	local is_per_kill = yn(args.isperkill)&lt;br /&gt;
	local defaultKPH = tonumber(args.kph) or 1&lt;br /&gt;
	&lt;br /&gt;
	for i=1,MAX_XP,1 do&lt;br /&gt;
		if not args[&amp;#039;Experience&amp;#039;..i] then break end&lt;br /&gt;
		local pri = &amp;#039;Experience&amp;#039;..i&lt;br /&gt;
		local span = mw.html.create(&amp;#039;span&amp;#039;)&lt;br /&gt;
		span:addClass(&amp;#039;mmg-xpline&amp;#039;)&lt;br /&gt;
		&lt;br /&gt;
		local skill = args[pri]&lt;br /&gt;
		local qty_param = args[pri..&amp;#039;num&amp;#039;]&lt;br /&gt;
		local actual_qty = tonumber(qty_param) or expr(qty_param) or 0&lt;br /&gt;
		local is_per_hour = not is_per_kill&lt;br /&gt;
		if is_per_kill and yn(args[pri..&amp;#039;isph&amp;#039;]) then&lt;br /&gt;
			is_per_hour = true&lt;br /&gt;
		end&lt;br /&gt;
		local this_item_value, attrName&lt;br /&gt;
		if is_per_kill and not is_per_hour then&lt;br /&gt;
			span:addClass(&amp;#039;mmg-varieswithkph&amp;#039;)&lt;br /&gt;
			this_item_value = actual_qty * defaultKPH&lt;br /&gt;
			attrName = &amp;#039;data-mmg-xp-pk&amp;#039;&lt;br /&gt;
		else&lt;br /&gt;
			this_item_value = actual_qty&lt;br /&gt;
			attrName = &amp;#039;data-mmg-xp-ph&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- TODO modulise SCP&lt;br /&gt;
		span:attr(attrName, actual_qty)&lt;br /&gt;
			:wikitext(frame:expandTemplate{title=&amp;#039;SCP&amp;#039;, args = { skill, autoround(this_item_value, true) }})&lt;br /&gt;
		&lt;br /&gt;
		table.insert(textlines, span)&lt;br /&gt;
		table.insert(items, { skill = skill, xp = actual_qty, isph = is_per_hour })&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return { spans = textlines, items = items }&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Creates a neat little warning message&lt;br /&gt;
function warning(msg)&lt;br /&gt;
	return mw.html.create(&amp;#039;span&amp;#039;)&lt;br /&gt;
				:addClass(&amp;#039;mmg-warning&amp;#039;)&lt;br /&gt;
				:css({&lt;br /&gt;
					[&amp;#039;border-bottom&amp;#039;] = &amp;#039;1px red dotted&amp;#039;,&lt;br /&gt;
					color = &amp;#039;red&amp;#039;,&lt;br /&gt;
					cursor = &amp;#039;help&amp;#039;&lt;br /&gt;
				})&lt;br /&gt;
				:attr(&amp;#039;title&amp;#039;, msg)&lt;br /&gt;
				:wikitext(&amp;#039;*&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.recurringTable(frame)&lt;br /&gt;
	return p._recurringTable(frame, frame:getParent().args)	&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._recurringTable(frame, args)&lt;br /&gt;
	local parsedInput = handleInputs(args)&lt;br /&gt;
	local parsedOutput = handleOutputs(args)&lt;br /&gt;
	local timeAsString = nil&lt;br /&gt;
	local num_good, numMinutes = pcall(mw.ext.ParserFunctions.expr, args[&amp;#039;Activity Time&amp;#039;])&lt;br /&gt;
	numMinutes = tonumber(numMinutes)&lt;br /&gt;
	if not num_good or not numMinutes then&lt;br /&gt;
		numMinutes = 1&lt;br /&gt;
	end&lt;br /&gt;
	if numMinutes &amp;lt; 1 then&lt;br /&gt;
		local seconds = numMinutes * 60&lt;br /&gt;
		timeAsString = seconds..&amp;#039; &amp;#039;..lang:plural(seconds, &amp;#039;second&amp;#039;, &amp;#039;seconds&amp;#039;)&lt;br /&gt;
	else&lt;br /&gt;
		timeAsString = numMinutes..&amp;#039; &amp;#039;..lang:plural(numMinutes, &amp;#039;minute&amp;#039;, &amp;#039;minutes&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	local tbl = mw.html.create(&amp;#039;table&amp;#039;)&lt;br /&gt;
	local inputTR = mw.html.create(&amp;#039;tr&amp;#039;)&lt;br /&gt;
	local inputTD = inputTR:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
	local outputTD = inputTR:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
	for i,v in ipairs(parsedInput.spans) do&lt;br /&gt;
		inputTD:node(v)&lt;br /&gt;
	end&lt;br /&gt;
	for i,v in ipairs(parsedOutput.spans) do&lt;br /&gt;
		outputTD:node(v)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	-- This is one statement, defining a single variable. It goes on for 120 lines. I don&amp;#039;t know how I feel about this tbh.&lt;br /&gt;
	 -- I mean how the heck would you even document this, for a start?&lt;br /&gt;
	tbl:addClass(&amp;#039;wikitable&amp;#039;) -- I guess it&amp;#039;s pretty self-documenting if you know HTML&lt;br /&gt;
		:cssText(&amp;#039;width:100%;text-align:center;&amp;#039;) -- But like...&lt;br /&gt;
		:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;caption&amp;#039;)&lt;br /&gt;
				:wikitext(args[&amp;#039;Activity&amp;#039;])&lt;br /&gt;
			:done()&lt;br /&gt;
		:done()&lt;br /&gt;
		:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
				:wikitext(&amp;#039;Profit per instance&amp;#039;)&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
				:attr(&amp;#039;rowspan&amp;#039;, &amp;#039;8&amp;#039;)&lt;br /&gt;
				:wikitext(args[&amp;#039;Image&amp;#039;])&lt;br /&gt;
			:done()&lt;br /&gt;
		:done()&lt;br /&gt;
		:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
				:wikitext(_coins(round(parsedOutput.value - parsedInput.value, 0), &amp;#039;coins&amp;#039;), &amp;#039; per instance, after [[Grand Exchange#Convenience fee and item sink|tax]]&amp;#039;)&lt;br /&gt;
			:done()&lt;br /&gt;
		:done()&lt;br /&gt;
		:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
				:wikitext(&amp;#039;Activity time&amp;#039;)&lt;br /&gt;
			:done()&lt;br /&gt;
		:done()&lt;br /&gt;
		:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
				:wikitext(timeAsString)&lt;br /&gt;
			:done()&lt;br /&gt;
		:done()&lt;br /&gt;
		:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
				:wikitext(&amp;#039;Minimum recurrence time&amp;#039;)&lt;br /&gt;
			:done()&lt;br /&gt;
		:done()&lt;br /&gt;
		:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
				:wikitext(args[&amp;#039;Recurrence Time&amp;#039;])&lt;br /&gt;
			:done()&lt;br /&gt;
		:done()&lt;br /&gt;
		:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
				:wikitext(&amp;#039;Effective profit&amp;#039;)&lt;br /&gt;
			:done()&lt;br /&gt;
		:done()&lt;br /&gt;
		:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
				:wikitext(_coins(tostring(parsedOutput.value - parsedInput.value)..&amp;#039; * 60 / (&amp;#039;..args[&amp;#039;Activity Time&amp;#039;]..&amp;#039;) round 0&amp;#039;, &amp;#039;coins&amp;#039;) .. &amp;#039; per hour, after [[Grand Exchange#Convenience fee and item sink|tax]]&amp;#039;) -- A bit messy but it should do the job. Assuming Activity Time is a well-behaved number, of course.&lt;br /&gt;
			:done()&lt;br /&gt;
		:done()&lt;br /&gt;
		:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
				:wikitext(&amp;#039;Skill requirements&amp;#039;)&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
				:wikitext(&amp;#039;Quest requirements&amp;#039;)&lt;br /&gt;
			:done()&lt;br /&gt;
		:done()&lt;br /&gt;
		:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
				:addClass(&amp;#039;plainlist&amp;#039;)&lt;br /&gt;
				:newline()&lt;br /&gt;
				:wikitext(args[&amp;#039;Skill&amp;#039;] or &amp;#039;None&amp;#039;)&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
				:addClass(&amp;#039;plainlist&amp;#039;)&lt;br /&gt;
				:newline()&lt;br /&gt;
				:wikitext(args[&amp;#039;Quest&amp;#039;] or &amp;#039;None&amp;#039;)&lt;br /&gt;
			:done()&lt;br /&gt;
		:done()&lt;br /&gt;
		:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
				:wikitext(&amp;#039;Item requirements&amp;#039;)&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
				:wikitext(&amp;#039;Other requirements&amp;#039;)&lt;br /&gt;
			:done()&lt;br /&gt;
		:done()&lt;br /&gt;
		:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
				:addClass(&amp;#039;plainlist&amp;#039;)&lt;br /&gt;
				:newline()&lt;br /&gt;
				:wikitext(args[&amp;#039;Item&amp;#039;] or &amp;#039;None&amp;#039;)&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
				:addClass(&amp;#039;plainlist&amp;#039;)&lt;br /&gt;
				:newline()&lt;br /&gt;
				:wikitext(args[&amp;#039;Other&amp;#039;] or &amp;#039;None&amp;#039;)&lt;br /&gt;
			:done()&lt;br /&gt;
		:done()&lt;br /&gt;
		:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
				:wikitext(&amp;#039;Experience gained&amp;#039;)&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
				:wikitext(&amp;#039;Location&amp;#039;)&lt;br /&gt;
			:done()&lt;br /&gt;
		:done()&lt;br /&gt;
		:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
				:wikitext(args[&amp;#039;Other Benefits&amp;#039;] or &amp;#039;None&amp;#039;)&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
				:wikitext(args[&amp;#039;Location&amp;#039;] or &amp;#039;Anywhere&amp;#039;) -- Sensible enough as a default&lt;br /&gt;
			:done()&lt;br /&gt;
		:done()&lt;br /&gt;
		:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
				:wikitext(&amp;#039;Inputs&amp;#039;)&lt;br /&gt;
				:wikitext(&amp;#039; (&amp;#039;, _coins(round(parsedInput.value, 0), &amp;#039;coins&amp;#039;), &amp;#039;)&amp;#039;)&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
				:wikitext(&amp;#039;Outputs&amp;#039;)&lt;br /&gt;
				:wikitext(&amp;#039; (&amp;#039;, _coins(round(parsedOutput.value, 0), &amp;#039;coins&amp;#039;), &amp;#039;, after [[Grand Exchange#Convenience fee and item sink|tax]])&amp;#039;)&lt;br /&gt;
			:done()&lt;br /&gt;
		:done()&lt;br /&gt;
		:node(inputTR)&lt;br /&gt;
	:done()&lt;br /&gt;
	&lt;br /&gt;
	frame:callParserFunction(&amp;#039;DISPLAYTITLE&amp;#039;, title.subpageText)&lt;br /&gt;
	frame:callParserFunction(&amp;#039;DEFAULTSORT&amp;#039;, title.subpageText)&lt;br /&gt;
	&lt;br /&gt;
	local cats = &amp;#039;[[Category:Money making guides]][[Category:MMG/Recurring]]&amp;#039;&lt;br /&gt;
	&lt;br /&gt;
	local final_profit = parsedOutput.value - parsedInput.value&lt;br /&gt;
	&lt;br /&gt;
	local set_smw = true&lt;br /&gt;
	if final_profit &amp;lt;= 0 then&lt;br /&gt;
		cats = cats .. &amp;#039;[[Category:Obsolete money making guides]]&amp;#039;&lt;br /&gt;
	else&lt;br /&gt;
		cats = cats .. &amp;#039;[[Category:Worthwhile money making guides]]&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if not onmain() then&lt;br /&gt;
		set_smw = false&lt;br /&gt;
		cats = &amp;#039;&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if set_smw then&lt;br /&gt;
		local smw_data = {&lt;br /&gt;
			members = yn(args.Members or &amp;#039;yes&amp;#039;, true),&lt;br /&gt;
			skill = args.Skill,&lt;br /&gt;
			quest = args.Quest,&lt;br /&gt;
			other = args.Other,&lt;br /&gt;
			activity = args.Activity,&lt;br /&gt;
			category = args.Category,&lt;br /&gt;
			version = args.Version,&lt;br /&gt;
			time = numMinutes,&lt;br /&gt;
			recurrence = args[&amp;#039;Recurrence Time&amp;#039;],&lt;br /&gt;
			prices = {&lt;br /&gt;
				input=parsedInput.value,&lt;br /&gt;
				output=parsedOutput.value,&lt;br /&gt;
				value=parsedOutput.value - parsedInput.value&lt;br /&gt;
			},&lt;br /&gt;
			inputs = parsedInput.list,&lt;br /&gt;
			outputs = parsedOutput.list&lt;br /&gt;
		}&lt;br /&gt;
		smw_data = mw.text.killMarkers(mw.text.nowiki(mw.text.jsonEncode(smw_data)))&lt;br /&gt;
		mw.smw.set({&lt;br /&gt;
			[&amp;#039;MMG value&amp;#039;]=parsedOutput.value - parsedInput.value,&lt;br /&gt;
			[&amp;#039;MMG recurring JSON&amp;#039;]=smw_data&lt;br /&gt;
		})&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return tbl, cats&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Alex</name></author>
	</entry>
</feed>