Módulo:GuiaDinheiro

De RuneScape Wiki
Ir para: navegação, pesquisa

A documentação para este módulo pode ser criada em Módulo:GuiaDinheiro/doc

local p = {}

--imports
local gePrice = require('Módulo:Mercado')._price
local minutesToTime = require('Módulo:Time')._m_to_c
local paramtest = require('Módulo:Paramtest')
local yesno = require('Módulo:Yesno')
local round = require('Módulo:Number')._round
local currency = require('Módulo:Moedas')
local sc = require('Módulo:Ícone')._main
local vdf = mw.ext.VariablesLua.vardefine
local lang = mw.getContentLanguage()

-- Config constants, change as needed
MAX_INPUTS = 50
MAX_OUTPUTS = 50
MAX_XP = 50
MEM_ICON = {
    [false] = "[[File:F2P ícone.png|20px|center|link=Jogadores gratuitos]]",
    [true]  = "[[File:P2P ícone.png|20px|center|link=Membros]]"
}

local cur_frame = mw.getCurrentFrame()

function p.testmmgtable(args)
	return p._mmgtable(cur_frame, args)
end

function p.mmgtable(frame)
	local args = frame:getParent().args
	return p._mmgtable(frame, args)
end

-- Create an MMG table.
-- Frame is the frame the module was invoked from.
-- Args are the template arguments used when creating the table.
function p._mmgtable(frame, args)
	local isperkill = yesno(args.isperkill)
	local tblattr, dyndef = {}, {}
	if isperkill then
		local tmpdyn = handleDynamics(args)
		tblattr = tmpdyn.attr
		dyndef = tmpdyn.defs
	end
    
	local parsedInput = handleInputs(args, dyndef)
	local parsedOutput = handleOutputs(args, dyndef)
	local parsedXP = handleXP(args)
    local ret = mw.html.create('')
    
    --mw.logObject(dyndef)
    --mw.logObject(parsedInput)
    --mw.logObject(parsedOutput)
    
	local tbl = ret:tag('table')
			:addClass('wikitable')
			:addClass('mmgtable')
			:attr('style', 'width: 100%; text-align: center;')
			:tag('caption')
                -- Members status (default to yes)
				:wikitext(MEM_ICON[yesno(args['Membros'] or 'yes', true)])
				:wikitext(args['Atividade'] or '{{{Atividade}}}')
			:done()
			:tag('tr')
				:tag('th')
					:wikitext('Requisitos')
				:done()
				:tag('td')
					:addClass('image-container')
					:attr('rowspan', '9')
					:wikitext(paramtest.default_to(args['Imagem'], '{{{Imagem}}}'))
				:done()
			:done()
			:tag('tr')
				:tag('th')
					:wikitext('Habilidades')
				:done()
			:done()
			:tag('tr')
				:tag('td')
                    -- Can leave blank if no reqs.
					:wikitext(paramtest.default_to(args['Habilidade'], 'Nenhuma')) 
				:done()
			:done()
			:tag('tr')
				:tag('th')
					:wikitext('Objetos')
				:done()
			:done()
			:tag('tr')
				:tag('td')
                    -- Can leave blank if no reqs.
					:wikitext(paramtest.default_to(args['Objeto'], 'Nenhum'))
				:done()
			:done()
			:tag('tr')
				:tag('th')
					:wikitext('Missão')
				:done()
			:done()
			:tag('tr')
				:tag('td')
                    -- Can leave blank if no reqs
					:wikitext(paramtest.default_to(args['Missão'], 'Nenhuma'))
				:done()
			:done()
			:tag('tr')
				:tag('th')
					:wikitext('Outros')
				:done()
			:done()
			:tag('tr')
				:tag('td')
                    -- Can leave blank if no reqs
					:wikitext(paramtest.default_to(args['Outros'], 'N/A'))
				:done()
			:done()
			:tag('tr')
				:tag('th')
					:attr('colspan', '2')
					:wikitext('Resultados')
				:done()
			:done()
			:tag('tr')
				:tag('th')
					:wikitext('Lucro')
				:done()
				:tag('th')
					:wikitext('Experiência ganha')
				:done()
			:done()
			:tag('tr')
				:tag('td')
					if args['Lucro'] then
						tbl:wikitext(coins(args['Lucro']))
					elseif isperkill then
                        tbl
                            :addClass('mmg-varieswithkph')
                            :attr('data-mmg-cost-ph', parsedOutput.valueph - parsedInput.valueph)
                            :attr('data-mmg-cost-pk', parsedOutput.valuepk - parsedInput.valuepk)
                            :wikitext(coins(autoround(parsedOutput.value - parsedInput.value)))
                    else
						tbl:wikitext(coins(autoround(parsedOutput.value - parsedInput.value)))
					end
    				tbl = tbl
				:done()
				:tag('td')
                    if args['Outros Benefícios'] then
                        tbl:wikitext(args['Outros Benefícios'])
                    elseif #parsedXP.spans > 0 then
                        for _, v in ipairs(parsedXP.spans) do
                            tbl:node(v)
                        end
                    else
                        tbl:wikitext('Nenhum')
                    end
    				tbl = tbl
				:done()
			:done()
			:tag('tr')
				:tag('th')
					:wikitext('Entradas')
					if parsedInput.value ~= 0 then
                        tbl:wikitext(' (')
                        if isperkill then
                            tbl
                                :tag('span')
                                    :addClass('mmg-varieswithkph')
                                    :addClass('mmg-input-sum')
                                    :attr('data-mmg-cost-ph', parsedInput.valueph)
                                    :attr('data-mmg-cost-pk', parsedInput.valuepk)
                                    :wikitext(coins(autoround(parsedInput.value)))
                                :done()
                        else
                            tbl:wikitext(coins(autoround(parsedInput.value)))
                        end
                        tbl:wikitext(')')
                    end
                    tbl = tbl
				:done()
				:tag('th')
					:wikitext('Saídas')
					if parsedOutput.value ~= 0 then
                        tbl:wikitext(' (')
                        if isperkill then
                            tbl
                                :tag('span')
                                    :addClass('mmg-varieswithkph')
                                    :addClass('mmg-output-sum')
                                    :attr('data-mmg-cost-ph', parsedOutput.valueph)
                                    :attr('data-mmg-cost-pk', parsedOutput.valuepk)
                                    :wikitext(coins(autoround(parsedOutput.value)))
                                :done()
                        else
                            tbl:wikitext(coins(autoround(parsedOutput.value)))
                        end
                        tbl:wikitext(')')
                    end
    				tbl = tbl
				:done()
			:done()
			:tag('tr')
				:tag('td')
                    if args['Entradas'] then
                        tbl:wikitext(args['Entradas'])
                    elseif #parsedInput.spans > 0 then
                        for _, v in ipairs(parsedInput.spans) do
                            tbl:node(v)
                        end
                    elseif parsedInput.text then
                        tbl:wikitext(parsedInput.text)
                    else
                        tbl:wikitext('Nenhum')
                    end
    				tbl = tbl
				:done()
				:tag('td')
                    if args['Saídas'] then
                        tbl:wikitext(args['Saídas'])
                    elseif #parsedOutput.spans > 0 then
                        for _, v in ipairs(parsedOutput.spans) do
                            tbl:node(v)
                        end
                    elseif parsedOutput.text then
                        tbl:wikitext(parsedOutput.text)
                    else
                        tbl:wikitext('Nenhum')
                    end
    				tbl = tbl
				:done()
			:done()
    
    if isperkill then
        tbl
            :addClass('mmg-isdynamic')
            --:attr('data-default-kph', args.kph)
            --:attr('data-default-kph-name', args['kph name'] or 'Kills per hour')
            :attr(tblattr)
    end
    
	if not(yesno(args.noexports)) then
		if yesno(args.isperkill) then
			vdf('kph', string.format('<span class="mmg-variable mmg-kph">%s</span>', args.kph))
			vdf('default_kph', args.kph)
			vdf('inputPH', string.format('<span class="mmg-variable mmg-input-ph" data-mmg-cost-ph="%s">%s</span>', parsedInput.valueph, nocoins(autoround(parsedInput.valueph))))
			vdf('inputPK', string.format('<span class="mmg-variable mmg-input-pk" data-mmg-cost-pk="%s">%s</span>', parsedInput.valuepk, nocoins(autoround(parsedInput.valuepk))))
			vdf('input', string.format('<span class="mmg-variable mmg-input" data-mmg-cost-ph="%s", data-mmg-cost-pk="%s">%s</span>', parsedInput.valueph, parsedInput.valuepk, nocoins(autoround(parsedInput.value))))
			vdf('outputPH', string.format('<span class="mmg-variable mmg-output-ph" data-mmg-cost-ph="%s">%s</span>', parsedOutput.valueph, nocoins(autoround(parsedOutput.valueph))))
			vdf('outputPK', string.format('<span class="mmg-variable mmg-output-pk" data-mmg-cost-pk="%s">%s</span>', parsedOutput.valuepk, nocoins(autoround(parsedOutput.valuepk))))
			vdf('output', string.format('<span class="mmg-variable mmg-varieswithkph mmg-output" data-mmg-cost-ph="%s", data-mmg-cost-pk="%s">%s</span>', parsedOutput.valueph, parsedOutput.valuepk, nocoins(autoround(parsedOutput.value))))
			vdf('profitPH', string.format('<span class="mmg-variable mmg-profit-ph" data-mmg-cost-ph="%s">%s</span>', parsedOutput.valueph-parsedInput.valueph, nocoins(autoround(parsedOutput.valueph-parsedInput.valueph))))
			vdf('profitPK', string.format('<span class="mmg-variable mmg-profit-pk" data-mmg-cost-pk="%s">%s</span>', parsedOutput.valuepk-parsedInput.valuepk, nocoins(autoround(parsedOutput.valuepk-parsedInput.valuepk))))
			vdf('profit', string.format('<span class="mmg-variable mmg-varieswithkph mmg-profit" data-mmg-cost-ph="%s", data-mmg-cost-pk="%s">%s</span>', parsedOutput.valueph-parsedInput.valueph, parsedOutput.valuepk-parsedInput.valuepk, nocoins(autoround(parsedOutput.value-parsedInput.value))))
		else
			vdf('input', string.format('<span class="mmg-input">%s</span>', parsedInput.value, nocoins(autoround(parsedInput.value))))
			vdf('output', string.format('<span class="mmg-input">%s</span>', parsedOutput.value, nocoins(autoround(parsedOutput.value))))
			vdf('profit', string.format('<span class="mmg-input">%s</span>', parsedOutput.value - parsedInput.value, nocoins(autoround(parsedOutput.value-parsedInput.value))))
			vdf('input_raw', parsedInput.value)
			vdf('output_raw', parsedOutput.value)
			vdf('profit_raw', parsedOutput.value-parsedInput.value)
		end
	end
	
	if args['Lucro'] or args['Entradas'] or args['Saídas'] then
		ret:wikitext('[[Categoria:Páginas com parâmetros depreciados]]')
	end
	
	return ret
end

-- Calculate the profit and do nothing else.
function p.profit(frame)
	local frame = frame or cur_frame
	local args = frame:getParent().args -- Template args, NOT #invoke args
	local isperkill = yesno(args.isperkill)
	local dyndef = {}
	if isperkill then
		local tmpdyn = handleDynamics(args)
		dyndef = tmpdyn.defs
	end
	local i = handleInputs(args, dyndef).value
	local o = handleOutputs(args, dyndef).value
	return o - i
end

-- Implements handleInputs and handleOutputs
-- See those functions for further details
function handleIteratedArgs(args, dyndef, prefix, max_iters)
	local items = {}
	local total_item_value = 0
	local textlines = {}
	local is_per_kill = yesno(args.isperkill)
	local has_dynam_inp = paramtest.has_content(args['UInput1text'])
	local defaultKPH = tonumber(args.kph) or 1
	local value_per_kill = 0
	local value_per_hour = 0
	
	for i=1,max_iters,1 do
		local pri = prefix..i
		if paramtest.is_empty(args[pri]) then break end
		
		local span = mw.html.create('div')
		span:addClass('mmg-itemline mmg-'..prefix:lower())
		
		local name = args[pri]
		local qty_param = args[pri..'num']
		local actual_qty = nil
		local value_param = args[pri..'value']
		local actual_value = nil
		local is_per_hour = not is_per_kill
		if is_per_kill and yesno(args[pri..'isph']) then
			is_per_hour = true
		end
		
		-- Keep track of sanity check states - we want to handle them gracefully later.
		local invalid_qty_present = false
		local invalid_value_present = false
		local failed_ge_lookup = false
		
		if paramtest.has_content(qty_param) then
			actual_qty = tonumber(qty_param) or expr(qty_param)
			invalid_qty_present = not actual_qty
			actual_qty = actual_qty or 1
			-- If the given quantity doesn't look like a number, we'll default to 1
			--   but we should probably alert the user
			--   since they might want to fix that
		else
			-- Default value of 1
			actual_qty = 1
		end
		
		if paramtest.has_content(value_param) then
			-- Again, if it was specified, it should be a number
			-- If it isn't, we pretend it wasn't specified
			--   but we alert the user because it's probably not what they want
			actual_value = tonumber(value_param) or expr(value_param)
			invalid_value_present = not actual_value
		end
		
		-- If we got the value earlier, skip this part
		if not actual_value then
			-- Here we try to find an exchange price
			-- If we get here, and we can't get an exchange price
			-- we default to 0.
			-- This is almost certainly not what the user wants,
			-- so we warn them about it.
			local success, price = pcall(gePrice, name)
			actual_value = success and tonumber(price) -- This is awful but still pleasant somehow
			failed_ge_lookup = not actual_value
			actual_value = actual_value or 0
		end
		local this_item_value, this_item_qty, attrName
		local attrVal = actual_qty * actual_value
		if is_per_kill and not is_per_hour then
			span:addClass('mmg-varieswithkph')
			if args[pri..'dynam'] then
				span:addClass('mmg-variesdynm')
				span:attr('data-dynam-inputs', args[pri..'dynam'])
				local mult = 1
				for j in string.gmatch(args[pri..'dynam'], "%d+") do
					--mw.logObject(dyndef)
					if dyndef['dyn'..j][3] then
						mult = mult * dyndef['dyn'..j][2] / dyndef['dyn'..j][1]
					else
						mult = mult * dyndef['dyn'..j][1] * dyndef['dyn'..j][2]
					end
				end
				this_item_qty = actual_qty * defaultKPH * mult
				this_item_value = attrVal * defaultKPH * mult
			else
				this_item_qty = actual_qty * defaultKPH
				this_item_value = attrVal * defaultKPH
			end
			value_per_kill = value_per_kill + attrVal
			attrName = 'data-mmg-cost-pk'
		else
			if args[pri..'dynam'] then
				span:addClass('mmg-variesdynm')
				span:attr('data-dynam-inputs', args[pri..'dynam'])
				local mult = 1
				for i in string.gmatch(args[pri..'dynam'], "%d+") do
					if dyndef['dyn'..i][3] then
						mult = mult * dyndef['dyn'..i][2] / dyndef['dyn'..i][1]
					else
						mult = mult * dyndef['dyn'..i][1] * dyndef['dyn'..i][2]
					end
				end
				this_item_qty = actual_qty * mult
				this_item_value = attrVal * mult
			else
				this_item_qty = actual_qty
				this_item_value = attrVal
			end
			value_per_hour = value_per_hour + attrVal
			attrName = 'data-mmg-cost-ph'
		end
		total_item_value = total_item_value + this_item_value
		
		span:tag('span'):addClass('mmg-quantity'):attr('data-mmg-qty', actual_qty):wikitext(autoround(this_item_qty, true))
		if invalid_qty_present then
			span:node(warning('Could not interpret \''..qty_param..'\' as a number, defaulting to 1'))
		end
		span:wikitext(string.format(' × [[File:%s.png|link=%s]] [[%s]] (', name, name, name))
		span:tag('span'):addClass('mmg-cost'):attr(attrName, attrVal):wikitext(nocoins(autoround(this_item_value)))
		span:wikitext(')')
		if invalid_value_present then
			span:node(warning('Could not interpret \''..value_param..'\' as a number, ignoring.'))
		end
		if failed_ge_lookup then
			span:node(warning('Could not find exchange price for item \''..name..'\', please double-check the spelling'))
			span:wikitext('[[Category:Money making guides with a failed GE lookup]]')
		end
		if paramtest.has_content(args[pri..'note']) then
			span:tag('span'):addClass('mmg-note'):wikitext(' ',args[pri..'note'])
		end
		
		table.insert(textlines, span)
			
		table.insert(items, {name = name, qty = actual_qty, value = actual_value, isph = is_per_hour})
	end
	
	return {value = total_item_value, valuepk = value_per_kill, valueph = value_per_hour, spans = textlines, list = items}
end

-- args are the args supplied to the template, (or a subset of them contining all input arguments)
-- Returns a table. The table has three keys: 'value', 'text', and 'as_table'
---- 'value' contains the total value of the inputs specified by args
---- 'text' contains a formatted string based on the inputs specified by args. This can be directly plugged into the HTML table.
---- 'list' contains all the inputs as a Lua list. Each input is represented by a table with the following keys
------ 'name' being the name of the item
------ 'value' being the value of the item in question
------ 'qty' being the quantity specified for the item
function handleInputs(args, dyndef)
	return handleIteratedArgs(args, dyndef, 'Entrada', MAX_INPUTS)
end

-- args are the args supplied to the template, (or a subset of them contining all output arguments)
-- Returns a table. The table has two keys: 'value', and 'text'
---- 'value' contains the total value of the outputs specified by args
---- 'text' contains a formatted string based on the outputs specified by args. This can be directly plugged into the HTML table.
---- 'list' contains all the outputs as a Lua list. Each output is represented by a table with the following keys
------ 'name' being the name of the item
------ 'value' being the value of the item in question
------ 'qty' being the quantity specified for the item
function handleOutputs(args, dyndef)
	return handleIteratedArgs(args, dyndef, 'Saída', MAX_OUTPUTS)
end

function handleDynamics(args)
	local attr = { ['data-default-kph'] = args.kph }
	attr['data-default-kph-name'] = args['kph name'] or 'Mortes por hora'
	
	local defs = {}
	
	if paramtest.has_content(args['UInput1text']) then
		local i = 1
		while paramtest.has_content(args['UInput'..i..'text']) do
			attr['data-dynam'..i..'-text'] = args['UInput'..i..'text']
			attr['data-dynam'..i..'-def'] = tonumber(args['UInput'..i..'def']) or 1
			attr['data-dynam'..i..'-fact'] = tonumber(args['UInput'..i..'fact']) or 1
			
			local isdiv = yesno(args['UInput'..i..'isdiv'], false)
			attr['data-dynam'..i..'-isdiv'] = tostring(isdiv)
			
			defs['dyn'..i] = {(tonumber(args['UInput'..i..'def']) or 1), (tonumber(args['UInput'..i..'fact']) or 1), isdiv}
			
			attr['data-num-dynamics'] = i
			
			i = i + 1
		end
	end
    
    return { defs = defs, attr = attr }
end

-- Creates a neat little warning message
function warning(msg)
	return cur_frame:expandTemplate{title='Hover', args={'*', msg, 'border-bottom: 1px red dotted; color: red; cursor: help;'}}
end

function p.recurringTable(frame)
	return p._recurringTable(frame, frame:getParent().args)	
end

function p._recurringTable(frame, args)
	local parsedInput = handleInputs(args)
	local parsedOutput = handleOutputs(args)
	local timeAsString = nil
	local numMinutes = tonumber(expr(args['Tempo de Atividade'])) or 1
    local ret = mw.html.create('')
    local tbl = ret:tag('table')
	
	if numMinutes < 1 then
		local seconds = numMinutes * 60
		timeAsString = seconds..' '..lang:plural(seconds, 'segundo', 'segundos')
	else
		timeAsString = numMinutes..' '..lang:plural(numMinutes, 'minuto', 'minutos')
	end
	
	
	tbl = tbl
		:addClass('wikitable')
		:addClass('mmgtable')
		:attr('style', 'width: 100%; text-align: center;')
		:tag('tr')
			:tag('th')
				:attr('colspan', '2')
				:wikitext(MEM_ICON[yesno(args['Membros'] or 'yes' or 'sim', true)])
				:wikitext(args['Atividade'])
			:done()
		:done()
		:tag('tr')
			:tag('th')
				:wikitext('Lucro por unidade')
			:done()
			:tag('td')
				:addClass('image-container')
				:attr('rowspan', '8')
				:wikitext(args['Imagem'])
			:done()
		:done()
		:tag('tr')
			:tag('td')
				if args['Lucro'] then
					tbl:wikitext(coins(round(args['Lucro'], 0)))
				else
					tbl:wikitext(coins(round(parsedOutput.value - parsedInput.value), 0), ' por unidade')
				end
                tbl = tbl
			:done()
		:done()
		:tag('tr')
			:tag('th')
				:wikitext('Tempo de atividade')
			:done()
		:done()
		:tag('tr')
			:tag('td')
				:wikitext(timeAsString)
			:done()
		:done()
		:tag('tr')
			:tag('th')
				:wikitext('Tempo de recorrência mínimo')
			:done()
		:done()
		:tag('tr')
			:tag('td')
				:wikitext(args['Tempo de Recorrência'])
			:done()
		:done()
		:tag('tr')
			:tag('th')
				:wikitext('Lucro efetivo')
			:done()
		:done()
		:tag('tr')
			:tag('td')
				if args['Lucro'] then
					tbl:wikitext(coins('('..args['Lucro']..') * 60 / ('..args['Tempo de Atividade']..') round 0'))
				else
                    -- A bit messy but it should do the job. Assuming Activity Time is a well-behaved number, of course.
					tbl:wikitext(coins(tostring(parsedOutput.value - parsedInput.value)..' * 60 / ('..args['Tempo de Atividade']..') round 0'))
				end
				tbl = tbl:wikitext(' por hora')
			:done()
		:done()
		:tag('tr')
			:tag('th')
				:wikitext('Requisitos de habilidade')
			:done()
			:tag('th')
				:wikitext('Requisitos de missões')
			:done()
		:done()
		:tag('tr')
			:tag('td')
				:wikitext(paramtest.default_to(args['Habilidade'], 'Nenhum'))
			:done()
			:tag('td')
				:wikitext(paramtest.default_to(args['Missão'], 'Nenhum'))
			:done()
		:done()
		:tag('tr')
			:tag('th')
				:wikitext('Requisitos de objetos')
			:done()
			:tag('th')
				:wikitext('Outros requisitos')
			:done()
		:done()
		:tag('tr')
			:tag('td')
				:wikitext(paramtest.default_to(args['Objeto'], 'Nenhum'))
			:done()
			:tag('td')
				:wikitext(paramtest.default_to(args['Outro'], 'Nenhum'))
			:done()
		:done()
		:tag('tr')
			:tag('th')
				:wikitext('Experiência ganha')
			:done()
			:tag('th')
				:wikitext('Local')
			:done()
		:done()
		:tag('tr')
			:tag('td')
				:wikitext(paramtest.default_to(args['Outros Benefícios'], 'Nenhum'))
			:done()
			:tag('td')
                -- Sensible enough as a default
				:wikitext(paramtest.default_to(args['Local'], 'Qualquer um'))
			:done()
		:done()
		:tag('tr')
			:tag('th')
				:wikitext('Entradas')
				if parsedInput.value ~= 0 then
                    tbl:wikitext(' (', coins(round(parsedInput.value, 0)), ')')
                end
                tbl = tbl
			:done()
			:tag('th')
				:wikitext('Saídas')
				if parsedOutput.value ~= 0 then
                    tbl:wikitext(' (', coins(round(parsedOutput.value, 0)), ')')
                end
				tbl = tbl
			:done()
		:done()
		:tag('tr')
			:tag('td')
                if args['Entradas'] then
                    tbl:wikitext(args['Entradas'])
                elseif #parsedInput.spans > 0 then
                    for _, v in ipairs(parsedInput.spans) do
                        tbl:node(v)
                    end
                elseif parsedInput.text then
                    tbl:wikitext(parsedInput.text)
                else
                    tbl:wikitext('Nenhum')
                end
				tbl = tbl
			:done()
			:tag('td')
                if args['Saídas'] then
                    tbl:wikitext(args['Entradas'])
                elseif #parsedOutput.spans > 0 then
                    for _, v in ipairs(parsedOutput.spans) do
                        tbl:node(v)
                    end
                elseif parsedOutput.text then
                    tbl:wikitext(parsedOutput.text)
                else
                    tbl:wikitext('Nenhum')
                end
				tbl = tbl
			:done()
		:done()
		:tag('tr')
			:tag('th')
				:attr('colspan', '2')
				:wikitext('Detalhes')
			:done()
		:done()
	:done()
	
	if args['Lucro'] or args['Entradas'] or args['Saídas'] then
		ret:wikitext('[[Categoria:Páginas com parâmetros depreciados]]')
	end
	
	return ret
end

-- Local utility functions
function coins(v)
    return currency._amount(v, 'coins')
end

function nocoins(v)
    return currency._amount(v, 'nocoins')
end

function expr(x)
	local e_g, e = pcall(mw.ext.ParserFunctions.expr, x)
	if e_g then
		return e
	end
	return nil
end

function sigfig(x, p)
	local x_sign = x < 0 and -1 or 1
	local x = math.abs(x)
	local n = math.floor(math.log10(x)) + 1 - p
	return x_sign * math.pow(10, n) * round(x / math.pow(10, n), 0)
end

function autoround(x, f)
	x = tonumber(x) or 0
	local _x
	if x == 0 then
		_x = 0
	elseif x < 0.1 and x > -0.1 then
		_x = sigfig(x, 2)
	elseif x > 99 and x < -99 then
		_x = round(x, 0)
	else
		_x = round(x, 2)
	end
	if f then
		return lang:formatNum(_x)
	end
	return _x
end

function handleXP(args)
	local items = {}
	local textlines = {}
	local is_per_kill = yesno(args.isperkill)
	local defaultKPH = tonumber(args.kph) or 1
	
	for i=1,MAX_XP,1 do
		if not args['Experiência'..i] then break end
		local pri = 'Experiência'..i
		local span = mw.html.create('div')
		span:addClass('mmg-xpline')
		
		local skill = args[pri]
		local qty_param = args[pri..'num']
		local actual_qty = tonumber(qty_param) or expr(qty_param) or 0
		local is_per_hour = not is_per_kill
		if is_per_kill and yesno(args[pri..'isph']) then
			is_per_hour = true
		end
		local this_item_value, attrName
		if is_per_kill and not is_per_hour then
			span:addClass('mmg-varieswithkph')
			this_item_value = actual_qty * defaultKPH
			attrName = 'data-mmg-xp-pk'
		else
			this_item_value = actual_qty
			attrName = 'data-mmg-xp-ph'
		end
		
		span:attr(attrName, actual_qty)
			:wikitext(sc(skill, autoround(this_item_value, true)))
		
		if paramtest.has_content(args[pri..'note']) then
			span:tag('span'):addClass('mmg-note'):wikitext(' ',args[pri..'note'])
		end
		
		table.insert(textlines, span)
		table.insert(items, { skill = skill, xp = actual_qty, isph = is_per_hour })
	end
	
	return { spans = textlines, items = items }
end

return p