Módulo:Infobox objeto/sandbox

De RuneScape Wiki
Ir para navegação Ir para pesquisar
Documentação do módulo
Esta documentação é transcluída de Módulo:Infobox objeto/sandbox/doc. [editar] [atualizar]
Módulo:Infobox objeto/sandbox transclui Predefinição:GEChart usando frame:preprocess().

Sandbox for Módulo:Infobox objeto


-- <nowiki>
-- Module for [[Predefinição:Infobox objeto]]
-- Test changes using [[Módulo:Infobox objeto/sandbox]] [[Predefinição:Infobox objeto/sandbox]]
local p = {}

-- "imports"
local infobox = require('Módulo:Infobox')
local onmain = require('Módulo:Mainonly').on_main
local paramtest = require('Módulo:Paramtest')
local commas = require('Módulo:Addcommas')._add
local exchange = require('Módulo:Mercado')
local yesno = require('Módulo:Yesno')
local externo = require('Módulo:Top icons')._main

local death_map = {
	allowed = {
		['recuperável'] = 'recuperável',
		nunca = 'nunca',
		sempre = 'sempre',
		semprewild = 'semprewild',
		largado = 'largado',
		seguro = 'seguro',
		gemwdegrade = 'gemwdegrade'
	},
	strings = {
		['recuperável'] = 'recuperável', --extra processing so no nice string
		nunca = 'Sempre é perdido',
		sempre = 'Sempre mantém fora da [[Terra Selvagem]]',
		semprewild = 'Sempre mantém',
		largado = 'Largado na morte',
		seguro = 'Sempre é morte segura',
		gemwdegrade = nil --intentional nil
	}
}

-- location restriction
local restriction_map = {
	surface = 'surface',
	dungeoneering = 'dungeoneering',
	dg = 'dungeoneering',
	daemonheim = 'dungeoneering',
	quest = 'quest',
	minigame = 'minigame',
	activity = 'minigame',
	beta = 'removed',
	gone = 'removed',
	removed = 'removed',
	limited = 'limited',
	['time limited'] = 'limited',
	th = 'microtransaction',
	sof = 'microtransaction',
	['treasure hunter'] = 'microtransaction',
	['squeal of fortune'] = 'microtransaction',
	cache = 'cache'
}

-- Main function called with invokes
function p.main(frame)
	local args = frame:getParent().args
	local ret = infobox.new(args)
	
	mw.log('starting infobox module')

	-- Parameter definitions
	ret:defineParams{
		{ name = 'nome', func = 'name' },
		{ name = 'inglês', func = { name = inglesarg, params = { 'inglês', 'nome', 'id' }, flag = { 'd' } } },
		{ name = 'aka', func = 'has_content' },
		{ name = 'imagem', func = 'image' },
		{ name = 'vanchor', func = { name = 'has_content', params = { 'version' }, flag = 'p' } },

		-- release and removal
		-- removal only shown if it exists
		{ name = 'lançamento', func = 'release' },
		{ name = 'descontinuado', func = 'removal' },
		{ name = 'removaldisp', func = { name = removaldisp, params = { 'descontinuado' } }, dupes = true },

		{ name = 'membros', func = { name = membrosarg, params = { 'membros' } } },
		{ name = 'membrossmw', func = { name = yesno, params = { 'membros' }, flag = 'p' }, dupes = true },
		{ name = 'examinar', func = 'has_content' },
		{ name = 'missão', func = 'has_content' },
		{ name = 'negociável', func = tradeablearg },
		{ name = 'tradeablesmw', func = { name = yesno, params = { 'negociável', false }, flag = { 'd', 'r' } } },
		{ name = 'equipável', func = 'has_content' },

		-- depositável; only show if "No"; default to "Yes"
		{ name = 'depositável', func = { name = 'has_content', params = { 'depositável', 'sim'}, flag = { 'd', 'r' } } },
		{ name = 'depositáveldisp', func = { name = yesnodisp, params = { 'depositável', 'não' }, flag = { 'd', 'r' } }, dupes = true },
		{ name = 'depositávelsmw', func = { name = yesno, params = { 'depositável', false }, flag = { 'd', 'r' } }, dupes = true },

		-- stacksinbank; only show if "No"; default to "Yes"
		{ name = 'acumulável banco', func = { name = 'has_content', params = { 'acumulável banco', 'sim'}, flag = { 'd', 'r' } } },
		{ name = 'stacksinbankdisp', func = { name = yesnodisp, params = { 'acumulável banco', 'não' }, flag = { 'd', 'r' } }, dupes = true },
		{ name = 'stacksinbanksmw', func = { name = yesno, params = { 'acumulável banco', false }, flag = { 'd', 'r' } }, dupes = true },

		-- emprestar; only show if "Yes"; default to "No"
		{ name = 'emprestar', func = { name = 'has_content', params = { 'emprestar', 'não'}, flag = { 'd', 'r' } } },
		{ name = 'emprestardisp', func = { name = yesnodisp, params = { 'emprestar' } }, dupes = true },
		{ name = 'emprestarsmw', func = { name = yesno, params = { 'emprestar', false }, flag = { 'd', 'r' } }, dupes = true },
		
		{ name = 'acumulável mochila', func = 'has_content' },
		{ name = 'stackablesmw', func = { name = yesno, params = { 'acumulável mochila', false }, flag = { 'd', 'r' } }, dupes = true },
		{ name = 'stackabledisplay', func = { name = stackabledisplay, params = { 'acumulável mochila', 'acumulável banco' } } },
		{ name = 'desmontável', func = disassemblyarg },
		{ name = 'disassemblysmw', func = { name = disassemblysmwarg, params = { 'desmontável' }, flag = 'p' } },

		-- edible; only show if "Yes"; default to "No"
		{ name = 'edible', func = { name = 'has_content', params = { 'edible', 'não'}, flag = { 'd', 'r' } } },
		{ name = 'edibledisp', func = { name = yesnodisp, params = { 'edible' } }, dupes = true },

		-- cupom; only show if "Yes"; default to "No"
		{ name = 'cupom', func = { name = 'has_content', params = { 'cupom', 'não'}, flag = { 'd', 'r' } } },
		{ name = 'cupomdisp', func = { name = yesnodisp, params = { 'cupom' } }, dupes = true },
		{ name = 'cupomsmw', func = { name = yesno, params = { 'cupom', true }, flag = { 'd', 'r' }, dupes = true } },
		{ name = 'destruir', func = 'has_content' },
		{ name = 'loja', func = storearg },
		-- gemw prices
		-- only displayed if they exist
		--dupes must exist for individual prices to have them display properly
		{ name = 'gemw', func = { name = gemwarg, params = { 'mercado', 'negociável' }, flag = {'p', 'd'} } },
		{ name = 'gemwname', func = { name = gemwnamearg, params = { 'nome', 'gemwname' } } },
		{ name = 'gemwprice', func = { name = gemwpricearg, params = { 'gemw', 'gemwname' } }, dupes = true },
		{ name = 'gemwpage', func = { name = gemwpagearg, params = { 'gemwprice', 'gemwname' } } },
		{ name = 'mercado', func = { name = exchangearg, params = { 'gemwprice', 'gemwname' } }, dupes = true },
		{ name = 'graph', func = { name = gemwgrapharg, params = { 'gemwprice', 'gemwname' } }, dupes = true },
		{ name = 'buylimit', func = { name = buylimitarg, params = { 'gemwprice', 'gemwname' } }, dupes = true },
		{ name = 'buylimitsmw', func = { name = buylimitsmwarg, params = { 'buylimit' } }, dupes = true },
		{ name = 'exgvalue', func = { name = exgvaluearg, params = { 'gemwprice', 'gemwname' } }, dupes = true },
		{ name = 'val', func = { name = valraw, params = { 'valor', 'exgvalue' }, flag = {'p', 'd'} }, dupes = true },
		{ name = 'valor', func = { name = valuearg, params = { 'val', 'convert' }, flag = { 'd', 'p' } } },
		-- used for both exchange and graphs
		{ name = 'gemwdisp', func = { name = gemwdisp, params = { 'gemwprice' } }, dupes = true },
		{ name = 'deathstatus', func = { name = deathstatusarg, params = { 'em morte' }, flag = 'p' } },
		{ name = 'ikodvalue', func = { name = ikodarg, params = { 'deathstatus', 'ikod', 'val', 'gemwprice' }, flag = { 'd', 'p', 'd', 'd' } } },
		{ name = 'reclaimvalue', func = { name = reclaimvaluearg, params = { 'ikodvalue', 'reclaim', }, flag = { 'd', 'p' } } },
		{ name = 'sacrificevalue', func = { name = sacrificevaluearg, params = { 'reclaimvalue', 'sacrifice' }, flag = { 'd', 'p' } } },
		{ name = 'em morte', func = { name = keptondeatharg, params = { 'deathstatus', 'ikod', 'reclaimvalue', 'sacrificevalue' }, flag = {'d', 'p', 'd', 'd'} } },

		-- alchemy
		{ name = 'gemwalchable', func = { name = gemwalchablearg, params = { 'gemwprice', 'gemwname' } }, dupes = true },
		{ name = 'gemwalchmultiplier', func = { name = gemwalchmultiplierarg, params = { 'gemwprice', 'gemwname' } }, dupes = true },
		{ name = 'alquimia', func = { name = alchablearg, params = { 'alquimia', 'alquimia avançada', 'alquimia básica', 'gemwalchable' }, flag = {'p', 'p', 'p', 'd' } }, dupes = true },
		{ name = 'alchmultiplier', func = 'numbers' },
		{ name = 'alchmultiplier_final', func = { name = multiplierarg, params = { 'alchmultiplier', 'gemwalchmultiplier' }, flag = {'p','d'} } },
		{ name = 'highraw', func = { name = alchvaluesraw, params = { 'val', 'alquimia avançada', 'alchmultiplier_final', 1, 'alquimia' }, flag = { 'd', 'p', 'd', 'r', 'd' } } },
		{ name = 'lowraw', func = { name = alchvaluesraw, params = { 'val', 'alquimia básica', 'alchmultiplier_final', 2/3, 'alquimia' }, flag = { 'd', 'p', 'd', 'r', 'd' } } },
		{ name = 'alquimia avançada', func = { name = alchvalues, params = { 'val', 'alquimia avançada', 'alchmultiplier_final', 1, 'alquimia' }, flag = { 'd', 'p', 'd', 'r', 'd' } } },
		{ name = 'alquimia básica', func = { name = alchvalues, params = { 'val', 'alquimia básica', 'alchmultiplier_final', 2/3, 'alquimia' }, flag = { 'd', 'p', 'd', 'r', 'd' } } },
		{ name = 'alchdisplay', func = { name = alchdisplay, params = { 'alquimia básica', 'alquimia avançada', 'alquimia' } } },

		{ name = 'peso', func = weightarg },
		{ name = 'weightraw', func = { name = weightargraw, params = { 'peso' }, flag = 'p' } },

		{ name = 'restriction', func = restrictionarg },
		{ name = 'restrictionsurface', func = { name = restrsurfarg , params = { 'restriction', 'restriction', 'missão' }, flag = { 'd', 'p', 'd' } } },
		-- not used; only for categories
		{ name = 'id', func = 'has_content' },
		{ name = 'id_smw', func = { name = idsmw, params = { 'id' }, flag = 'p' } },
		{ name = 'chisel_links', func = { name = make_chisel_links, params = { 'id_smw', 'nome' }, flag = 'd' } },
		{ name = 'rscid', func = 'numbers' },
		{ name = 'SMWarg', func = { name = SMWarg, params = {
				'nome', 'version', 'id', 'membros', 'lançamento', 'descontinuado', 'examinar', 'missão', 'destruir', 'restriction', -- strings
				'deathstatus', 'ikodvalue', 'reclaimvalue', 'sacrificevalue', -- death
				'negociável', 'equipável', 'depositável', 'acumulável banco', 'emprestar', 'acumulável mochila', 'desmontável', 'edible', 'cupom', --generally boolean or tri-lean
				'val', 'alquimia avançada', 'alquimia básica', 'weightraw', -- numbers
				'gemw', 'gemwname', 'buylimit' -- gemw
			}, flag = 'd' } }
	}

	ret:setMaxButtons(7)
	ret:create()
	ret:cleanParams()
	ret:customButtonPlacement(true)

	-- parameter linkings for hidden rows
	ret:linkParams{
		{ 'descontinuado', 'removaldisp' },
		{ 'mercado', 'gemwdisp' },
		{ 'graph', 'gemwdisp' },
		{ 'buylimit', 'gemwdisp' },
		{ 'depositável', 'depositáveldisp' },
		{ 'acumulável banco', 'stacksinbankdisp' },
		{ 'emprestar', 'emprestardisp' },
		{ 'cupom', 'cupomdisp' },
		{ 'edible', 'edibledisp' }
	}

	-- ret:defineLinks({ links = {{ 'Predefinição:%s/FAQ', 'FAQ' },
	-- 		{ 'Predefinição:%s/doc', 'doc' }}, colspan = 2 })

	ret:useSMW({
		id_smw = 'ID do objeto',
		membrossmw = 'É somente para membros'
	})

	ret:useSMWElement({
		buylimitsmw = 'Limite de compra',
		SMWarg = 'JSON de objeto',
	})

	ret:useSMWSubobject({
		id_smw = 'ID do objeto',
		vanchor = 'Version anchor',
		name = 'Nome do objeto',
		examinar = 'Examinar',
		val = 'Valor',
		highraw = 'Alquimia Avançada',
		lowraw = 'Alquimia Básica',
		weightraw = 'Peso',
		membrossmw = 'É somente para membros',
		tradeablesmw = 'Negociável',
		stackablesmw = 'Acumulável',
		['depositávelsmw'] = 'Depositável',
		stacksinbanksmw = 'Acumulávelbanco',
		emprestarsmw = 'Emprestar',
		disassemblysmw = 'Desmontável',
		cupomsmw = 'Cupom',
		gemwpage = 'Exchange page',
		buylimitsmw = 'Limite de compra',
		restriction = 'Location restriction',
		deathstatus = 'Em morte',
		-- ['lançamento'] = 'Data de lançamento',
		-- ['atualização'] = 'Release update',
		-- --removal = 'Removal date',
		-- removalupdate = 'Removal update',
	})
	if onmain() then
		local a2 = ret:categoryData()
		if not a2['restriction'].all_defined then
			ret:useSMWSubobject({
				restrictionsurface = 'Location restriction',
			})
		end
	end

	ret:addButtonsCaption()

	ret:defineName('Infobox objeto')
	ret:addClass('infobox-item')

	ret:addRow{
		{ tag = 'argh', content = 'nome', class='infobox-header', colspan = '2' }
	}

	:addRow{
		{ tag = 'argd', content = 'imagem', class = 'infobox-image', colspan = '2' }
	}

	-- :addRow{
	-- 	{ tag = 'th', content = '[[Examinar]]', class = 'infobox-subheader', colspan = '2' }
	-- }

	:addRow{
		{ tag = 'argd', content = 'examinar', class = 'infobox-image', colspan = '2', css = { ['max-width'] = '300px', ['text-align'] = 'center', ['font-style'] = 'italic' } }
	}

	:addRow{
		{ tag = 'th', content = 'Inglês' },
		{ tag = 'argd', content = 'inglês' }
	}

	:addRow{
		{ tag = 'th', content = '[[Membros]]' },
		{ tag = 'argd', content = 'membros' }
	}

	:addRow{
		{ tag = 'th', content = 'Lançamento' },
		{ tag = 'argd', content = 'lançamento' }
	}

	if ret:paramDefined('descontinuado') then
		ret:addRow{
			{ tag = 'th', content = 'Removido' },
			{ tag = 'argd', content = 'descontinuado' }
		}
	end

	if ret:paramDefined('aka') then
		ret:addRow{
			{ tag = 'th', content = '[[Dicionário|AKA]]' },
			{ tag = 'argd', content = 'aka' }
		}
	end

	ret:addRow{
		{ tag = 'th', content = '[[Missões|De missão]]' },
		{ tag = 'argd', content = 'missão' }
	}

	-- :addRow{
	-- 	{ tag = 'th', content = 'Propriedades', class = 'infobox-subheader', colspan = '2' }
	-- }

	:addRow{
		{ tag = 'th', content = 'Negociável' },
		{ tag = 'argd', content = 'negociável' }
	}

	if ret:paramGrep('depositável','Não') then
		ret:addRow{
			{ tag = 'th', content = 'Depositável' },
			{ tag = 'argd', content = 'depositável' }
		}
	end

	-- if ret:paramGrep('acumulável banco','não') then
	-- 	ret:addRow{
	-- 		{ tag = 'th', content = 'Stacks in bank' },
	-- 		{ tag = 'argd', content = 'acumulável banco' }
	-- 	}
	-- end

	if ret:paramGrep('emprestar','sim') then
		ret:addRow{
			{ tag = 'th', content = 'Emprestável' },
			{ tag = 'argd', content = 'emprestar' }
		}
	end

	ret:addRow{
		{ tag = 'th', content = 'Equipável' },
		{ tag = 'argd', content = 'equipável' }
	}

	:addRow{
		{ tag = 'th', content = 'Acumulável' },
		{ tag = 'argd', content = 'stackabledisplay' }
	}

	:addRow{
		{ tag = 'th', content = '[[Desmontar|Desmontável]]' },
		{ tag = 'argd', content = 'desmontável' }
	}

	if ret:paramGrep('cupom','sim') then
		ret:addRow{
			{ tag = 'th', content = 'Cupom' },
			{ tag = 'argd', content = 'cupom' }
		}
	end

	if ret:paramGrep('edible','sim') then
		ret:addRow{
			{ tag = 'th', content = '[[Comida|Consumível]]' },
			{ tag = 'argd', content = 'edible' }
		}
	end

	-- ret:addRow{
	-- 	{ tag = 'th', content = 'Valores', class = 'infobox-subheader', colspan = '2' }
	-- }

	ret:addRow{
		{ tag = 'th', content = 'Valor' },
		{ tag = 'argd', content = 'valor' }
	}

	ret:addRow{
		{ tag = 'th', content = '[[Alquimia]]' },
		{ tag = 'argd', content = 'alchdisplay' }
	}

	ret:addRow{
		{ tag = 'th', content = 'Destruir' },
		{ tag = 'argd', content = 'destruir', css = { ['max-width'] = '200px' } }
	}

	:addRow{
		{ tag = 'th', content = 'Em Morte' },
		{ tag = 'argd', content = 'em morte' }
	}

	-- Include GE section if we have any exchange prices
	local anygemw = ret:paramGrep('gemwprice', function(_arg) return _arg > 0 end)
	if anygemw == true then
		-- ret:addRow{
		-- 	{ tag = 'th', content = '[[Mercado Geral]]', class = 'infobox-subheader', colspan = '2' }
		-- }

		ret:addRow{
			{ tag = 'th', content = '[[Mercado Geral|Preço do MG]]' },
			{ tag = 'argd', content = 'mercado' }
		}

		:addRow{
			{ tag = 'th', content = 'Limite de compra' },
			{ tag = 'argd', content = 'buylimit' }
		}

		:addRow{
			{ tag = 'argd', content = 'graph', colspan = '2', css = { ['text-align'] = 'center', ['padding'] = '0'} }
		}
	end

	ret:addRow{
		{ tag = 'th', content = 'Peso' },
		{ tag = 'argd', content = 'peso' }
	}

	ret:addRow{
		{ tag = 'th', content = 'Dados avançados', class = 'infobox-subheader', colspan = '2' },
		meta = {addClass = 'advanced-data'}
	}

	:addRow{
		{ tag = 'th', content = 'ID do objeto' },
		{ tag = 'argd', content = 'id' },
		meta = {addClass = 'advanced-data'}
	}

	:addRow{
		{ tag = 'th', content = 'Links' },
		{ tag = 'argd', content = 'chisel_links' },
		meta = {addClass = 'advanced-data'}
	}

	if onmain() then
		local a1 = ret:param('all')
		local a2 = ret:categoryData()
		ret:wikitext(addcategories(ret, a1,a2))
	end

	return ret:tostring()
end

-- English name
function inglesarg(name, ptname, id)
	mw.log('inglesarg ('..name..', '..ptname..', '..id..')')
    if infobox.isDefined(name) then
    	mw.log('isDefined(name) == true')
        return externo({rsw=name}, pagename) .. string.gsub('[[:en:%s|%s]]', '%%s', name)
    else
    	mw.log('isDefined(name) == false')
    	local translate = require('Módulo:Traduções')._simple
    	local engl = false
    	if infobox.isDefined(ptname) then
    		mw.log('isDefined(ptname) == true')
    		engl = translate(ptname, 'pt', 'objecto', 'en')
    		mw.log('engl = ')
    		mw.	log(engl)
    	end
    	if infobox.isDefined(id) and not engl then
    		mw.log('isDefined(id) and not engl')
    		local id1 = string.match(id, '%d+')
    		mw.log('id1 = '..id1)
    		if id1 then
    			id1 = tonumber(id1)
    			engl = translate(id1, 'id', 'objecto', 'en')
    		end
    		mw.log('engl = ')
    		mw.log(engl)
    	end
    	mw.log('end engl = ')
    	mw.log(engl)
    	if engl then
    		mw.log('return: '.. externo({rsw=engl}, pagename) .. string.gsub('[[:en:%s|%s]]', '%%s', engl))
    		return externo({rsw=engl}, pagename) .. string.gsub('[[:en:%s|%s]]', '%%s', engl)
    	end
    end
end

-- Membros
function membrosarg(arg)
	if infobox.isDefined(arg) then
		if yesno(arg) then
			return '[[Arquivo:P2P ícone.png|26px|link=Membros|alt=Membros]]&nbsp;Sim'
		else
			return '[[Arquivo:F2P ícone.png|26px|link=Jogadores gratuitos|alt=Jogadores gratuitos]]&nbsp;Não'
		end
	end
end

-- Yesno string
function yesnostr(arg, default)
	arg = yesno(arg, default)
	if type(arg) == 'boolean' then
		return tostring(arg)
	end
	return arg
end

-- Preço de loja
function storearg(store, currency, seller)
	-- remove any commas
	store = string.gsub(store or '',',','')

	-- no for não vendido
	if string.lower(store) == 'não' then
		return 'Não se vende'
	else
		store = tonumber(store,10)
	end

	if type(store) == 'number' then
		return store
	else
		return nil
	end
end

-- tradeable
-- tradeablearg(value)
function tradeablearg(v)
	v = string.lower(v or '')
	if v == 'sim' or v == 'não' then
		v = mw.text.split(v,'')
		v[1] = string.upper(v[1])
		return table.concat(v,'')
	elseif v == 'restricted' then
		return 'Restrito'
	else
		return nil
	end
end

-- Stackable
function stackabledisplay(inBackpack,inBank)
	local backpackOutput = ''
	local bankOutput = ''
	if infobox.isDefined(inBackpack) then
		if yesno(inBackpack) then
			backpackOutput = '[[Arquivo:Mochila ícone.png|19px|link=Mochila]]&nbsp;Sim'
		else
			backpackOutput = '[[Arquivo:Mochila ícone.png|19px|link=Mochila]]&nbsp;Não'
		end
	end
	if infobox.isDefined(inBank) then
		if yesno(inBank) == false then
			bankOutput = '<br />[[Arquivo:Banco ícone mapa.png|link=Banco]]&nbsp;Não'
		end
	end
	return backpackOutput .. bankOutput
end

-- disassembly
-- disassemblyarg(yes/no)
local allowed_disassembly = {
	yes = 'true',
	sim = 'true',
	no = 'false',
	['não'] = 'false',
	restricted = 'restricted',
	na = 'N/A',
	['n/a'] = 'N/A',
	discontinued = 'N/A',
	irrelevant = 'N/A'
}
function disassemblyarg(d)
	d = string.lower(d or '')
	d = allowed_disassembly[d]
	if d == 'true' then
		return '[[#Desmontagem|Sim]]' -- Unique anchor ID created by {{Disassembly}}
	elseif d == 'false' then
		return 'Não'
	elseif d == 'restricted' then
		return '[[:Categoria:Location restricted disassembly|Restricted]]'
	elseif d == 'N/A' then
		return 'N/A'
	else
		return nil
	end
end
-- disassemblysmwarg(yes/no)
function disassemblysmwarg(d)
	d = string.lower(d or '')
	return allowed_disassembly[d]
end

-- value
-- separate number storage for operation
-- pulls the exchange value first, and prefers that if it exists
-- valraw(value, exchange value)
function valraw(v, ex)
	if type(ex) == 'number' then
		return ex
	else
		return tonumber(string.gsub(v or '', ',', ''), 10)
	end
end

-- value
-- valuearg(value, convert)
-- actual value already parsed
function valuearg(v,c)
	-- replace commas and turn into a number
	if paramtest.has_content(c) then
		c = string.gsub(c,',','')
		c = tonumber(c,10)
	else
		c = nil
	end

	v = tonumber(v,10)

	-- if both are defined, show both, value first
	if v and c then
		return string.format('%s<br/><b>Cash out:</b><br/>%s',plural('moeda',v),plural('moeda',c))
	-- if only value is defined, show just that
	elseif v and not c then
		return plural('moeda',v)
	-- if only convert is defined, show just that
	-- may need to change this so that value is requested
	elseif c and not v then
		return string.format('<b>Cash out:</b><br/>%s',plural('moeda',c))
	else
		return nil
	end
end

-- ge alchable boolean
-- gemwalchablearg(gemw price, name)
-- uses the already fetched ge price to operate
-- values less than 1 are used for parsing instructions
function gemwalchablearg(g,n)
	if type(g) ~= 'number' then
		g = tonumber(g,10) or 0
	end

	-- 0 for não vendido an
	-- -1 for error
	-- call to hide the graph
	if g == 0 or g == -1 then
		return '-'
	-- all other numbers
	elseif g > 0 then
		local ret = exchange._alchable(n)
		if ret == nil then
			return '-'
		elseif ret == false then
			return 'false' --not very good at handling false
		else
			return true
		end
	-- not a number = nil
	-- shouldn't be used, but it's a fallback
	else
		return '-'
	end
end

-- ge alch multiplier
-- gemwalchmultiplierarg(gemw price, name)
-- uses the already fetched ge price to operate
-- values less than 1 are used for parsing instructions
function gemwalchmultiplierarg(g,n)
	if type(g) ~= 'number' then
		g = tonumber(g,10) or 0
	end

	-- 0 for não vendido an
	-- -1 for error
	-- call to hide the graph
	if g == 0 or g == -1 then
		return '-'
	-- all other numbers
	elseif g > 0 then
		local ret = exchange._alchmultiplier(n)
		if ret == nil then
			return '-'
		else
			return ret
		end
	-- not a number = nil
	-- shouldn't be used, but it's a fallback
	else
		return '-'
	end
end

-- Alchables
-- alchablearg(alchable, high, low)
function alchablearg(a,h,l,ex)
	if ex == true then
		return true
	elseif ex == 'false' then
		return 'false'
	end
	-- not alchable if both are false, or if "alchable" is false
	if string.lower(a or '') == 'não' then
		return 'false'
	elseif string.lower(h or '') == 'não' and string.lower(l or '') == 'não' then
		return 'false'
	else
		return  true
	end
end

-- alch multiplier arg
-- only accepts numbers
-- defaults to .6
function multiplierarg(v, ex)
	if type(ex) == 'number' then
		return ex
	end
	return tonumber(v) or 0.6
end

-- high/low alch
-- alchvalues(value, override value, multiplier, alchable)
-- actual value already parsed
-- value, template param, alch multiplier, override multiplier, not alchable bool
function alchvalues(v,_p,a,m,n)
	-- if you can't alch it, return this
	-- used in the case of 1 version being alchable and the other not
	if not infobox.isDefined(n) or n == 'false' then
		return 'Não é possível usar alquimia'
	end
	-- remove commas and turn into a number
	v = tonumber(v,10)
	if paramtest.has_content(_p) then
		_p = string.gsub(_p,',','')
		_p = tonumber(_p,10)
	else
		_p = nil
	end

	-- return override always
	if type(_p) == 'number' then
		return alchicon(m,_p)
	end

	-- otherwise try the value and multiply it
	if v then
		local r = math.floor(killRoundingError(v * m * a))
		-- both high and low alch have a lower bound of one coin
		r = math.max(r, 1)
		return alchicon(m,r)
	end

	return nil
end
-- alchvaluesraw(value, override value, multiplier, alchable)
-- actual value already parsed
-- value, template param, alch multiplier, override multiplier, not alchable bool
function alchvaluesraw(v,_p,a,m,n)
	-- if you can't alch it, return nil
	if not infobox.isDefined(n) or n == 'false' then
		return nil
	end
	-- remove commas and turn into a number
	v = tonumber(v,10)
	if paramtest.has_content(_p) then
		_p = string.gsub(_p,',','')
		_p = tonumber(_p,10)
	else
		_p = nil
	end

	-- return override always
	if type(_p) == 'number' then
		return _p
	end
	-- otherwise try the value and multiply it
	if v then
		local r = math.floor(killRoundingError(v * m * a))
		-- both high and low alch have a lower bound of one coin
		r = math.max(r, 1)
		return r
	end

	return nil
end
-- Get alch icon based on multiplier
function alchicon(mult, val)
	local val = commas(tonumber(val,10) or 1)
	if mult == 1 then
		return '<br />[[Arquivo:Alquimia avançada.png|22px|link=Alquimia avançada]]&nbsp;' .. val
	else
		return '[[Arquivo:Alquimia básica.png|22px|link=Alquimia básica]]&nbsp;' .. val
	end
end
-- Display alch values
function alchdisplay(low, high, isAlchable)
	if yesno(isAlchable) then
		return low .. high
	else
		return 'Não é possível usar alquimia'
	end
end

-- weight
-- weightarg(weight)
function weightarg(w)
	if paramtest.has_content(w) then
		-- replace all "kg" and spaces here
		w = string.gsub(w or '','[kg ]','')

		-- replace hyphen with minus sign
		w = string.gsub(w,'-','&minus;')

		-- use non-breaking spaces and html entities for display
		-- still necessary to convert the "kg" to html?
		return string.format('%s&nbsp;%s&nbsp;&#107;&#103;','[[Arquivo:Peso ícone.png|Peso|link=]]',w)
	end
	return nil
end

-- weightargraw(weight)
function weightargraw(w)
	if paramtest.has_content(w) then
		-- replace all "kg" and spaces here
		w = string.gsub(w or '','[kg ]','')
		return tonumber(w)
	end
	return nil
end

-- on ge or not
-- only accepts "gemw"
-- gemwarg(exchange,tradeable)
function gemwarg(arg,arg2)
	g = string.lower(arg or '')
	return arg2 == 'Sim' and g == 'gemw'
end

-- gemw names
-- gemwnamearg(name, override name)
function gemwnamearg(n,a)
	-- return override
	if a and a:find('%S') then
		return string.gsub(a,'</?span>','')
	-- otherwise use the "name" parameter
	elseif n and n:find('%S') then
		return string.gsub(n,'</?span>','')
	-- default to page name
	else
		return mw.title.getCurrentTitle().fullText
	end
end

-- separate thing to hold all the prices as raw numbers
-- gemwpricearg(gemw, name)
function gemwpricearg(g,n)
	if g == true then
		-- return price if page is found
		-- -1 for errors
		if exchange._exists(n) then
			return tonumber(exchange._price(n),10) or -1
		else
			return -1
		end
	-- 0 for no price
	else
		return 0
	end
end

-- gemwpricearg(gemw price, name)
-- exchange page name for SMW
-- uses the already fetched ge price to operate
-- values less than 1 are used for parsing instructions
function gemwpagearg(g,n)
	if type(g) ~= 'number' then
		g = tonumber(g,10) or 0
	end
	if g < 1 then
		return nil
	else
		return 'Mercado:'..n
	end
end

-- exchange display
-- exchangearg(gemw price, name)
-- uses the already fetched ge price to operate
-- values less than 1 are used for parsing instructions
function exchangearg(g,n)
	if type(g) ~= 'number' then
		g = tonumber(g,10) or 0
	end
	-- 0 for não vendido
	if g == 0 then
		return '<span class="infobox-quantity" data-val-each="0">Não se vende</span>'
	-- -1 for no page found
	elseif g == -1 then 
		return badarg('mercado','estava definido para «gemw» mas nenhuma página foi encontrada para «'..n..'».')
	-- all other numbers
	elseif g > 0 then
		-- plural done in format because we need a span around the value
		return string.format('<span class="infobox-quantity" data-val-each="%s"><span class="infobox-quantity-replace">%s</span> moeda%s ([[Mercado:%s|info]])</span>',g,commas(g),g>1 and 's' or '',n)
	-- not a number = nil
	-- shouldn't be used, but it's a fallback
	else
		return 0
	end
end

-- ge graphs
-- gemwgrapharg(gemw price, name)
-- uses the already fetched ge price to operate
-- values less than 1 are used for parsing instructions
function gemwgrapharg(g,n)
	if type(g) ~= 'number' then
		g = tonumber(g,10) or 0
	end

	-- 0 for não vendido an
	-- -1 for error
	-- call to hide the graph
	if g == 0 or g == -1 then
		return 'Sem dados para exibir'
	-- all other numbers
	elseif g > 0 then
		-- TODO: Change Module:ExchangeData and give it a proper graph function
		-- remove reliance on frame
		return mw.getCurrentFrame():preprocess(string.format('{{GEChart|%s|size=small}}',n))
	-- not a number = nil
	-- shouldn't be used, but it's a fallback
	else
		return nil
	end
end

-- ge buy limits
-- buylimitarg(gemw price, name)
-- uses the already fetched ge price to operate
-- values less than 1 are used for parsing instructions
function buylimitarg(g,n)
	if type(g) ~= 'number' then
		g = tonumber(g,10) or 0
	end

	-- 0 for não vendido an
	-- -1 for error
	-- call to hide the graph
	if g == 0 or g == -1 then
		return '-'
	-- all other numbers
	elseif g > 0 then
		local ret = exchange._limit(n)
		if ret == nil then
			return '-'
		else
			return commas(ret)
		end
	-- not a number = nil
	-- shouldn't be used, but it's a fallback
	else
		return nil
	end
end

function buylimitsmwarg(b)
	if type(b) == 'string' then
		b = b:gsub('[ ,]', '')
	end
	if tonumber(b) then
		return tonumber(b)
	end
	return infobox.donotsetsmw
end

-- ge value
-- exgvaluearg(gemw price, name)
-- uses the already fetched ge price to operate
-- values less than 1 are used for parsing instructions
function exgvaluearg(g,n)
	if type(g) ~= 'number' then
		g = tonumber(g,10) or 0
	end

	-- 0 for não vendido an
	-- -1 for error
	-- call to hide the graph
	if g == 0 or g == -1 then
		return '-'
	-- all other numbers
	elseif g > 0 then
		local ret = exchange._value(n)
		if ret == nil then
			return '-'
		else
			return ret
		end
	-- not a number = nil
	-- shouldn't be used, but it's a fallback
	else
		return '-'
	end
end

-- class names based on value
-- gemwdisp(price)
function gemwdisp(_p)
	if _p == 0 then
		return ''
	else
		return 'infobox-cell-shown'
	end
end

-- Shows if the param matches the alt
-- alt defaults to yes
-- Everything else = hide
function yesnodisp(arg, alt)
	arg = string.lower(arg or '')
	alt = string.lower(alt or 'sim')
	if arg == alt then
		return 'infobox-cell-shown'
	else
		return ''
	end
end

-- Shows if has a date
function removaldisp(arg)
	if string.find(arg or '','%[%[') then
		return 'infobox-cell-shown'
	else
		return ''
	end
end

-- death
-- deathstatusarg(death)
function deathstatusarg(d)
	d = string.lower(d or '')
	return death_map.allowed[d]
end

-- ikodarg()
function ikodarg(d, _i, v, g)
	if d == 'recuperável' then
		v = tonumber(v)
		local i
		-- replace commas and convert to number
		if paramtest.has_content(_i) then
			i = string.gsub(_i,',','')
			i = tonumber(i,10)
		else
			i = nil
		end

		-- if i is defined, show that value
		if i then
			return i
		-- test geprice next
		elseif (tonumber(g,10) or 0) > 0 then
			i = tonumber(g,10)
		-- test value next
		elseif v then
			i = v
		end
		return i
	end
	return -1
end

-- reclaimvaluearg(ikodvalue, reclaim)
function reclaimvaluearg(i, _r)
	i = tonumber(i or -1) or -1
	if i > 0 then
		local r

		-- test for overridden reclaim
		if paramtest.has_content(_r) then
			_r = string.gsub(_r,',','')
			r = tonumber(_r)
		end

		-- if no number, use formula
		if not r then
			-- less than 10,000: .15x
			if i < 10000 then
				r = math.floor(i * .15)
				-- all items cost at least 1 coin, so round back up if 0
				if r == 0 then
					r = 1
				end

			--[[
				Death formula
			]]
			-- 10,000 to 49,999: 500 + 0.1x
			elseif i >= 10000 and i < 50000 then
				r = 500 + i * 0.1

			-- 50,000 to 249,999: 3000 + 0.05x
			elseif i >= 50000 and i < 250000 then
				r = 3000 + i * 0.05

			-- 250,000 to 999,999: 10500 + 0.02x
			elseif i >= 250000 and i < 1000000 then
				r = 10500 + i * 0.02

			-- 1,000,000 to 9,999,999: 20500 + 0.01x
			elseif i >= 1000000 and i < 10000000 then
				r = 20500 + i * 0.01

			-- 10,000,000 and greater: 70,500 + 0.005x
			elseif i >= 10000000 then
				r = 70500 + i * 0.005

			-- this shouldn't happen, but fallback to 1
			else
				r = 1
			end
		end

		r = math.floor(killRoundingError(r))
		return r
	end
	return -1
end

-- sacrificevaluearg(reclaimvalue, sacrifice)
function sacrificevaluearg(r, _s)
	if r > 0 then
		if paramtest.has_content(_s) then
			_s = string.gsub(_s,',','')
			_s = tonumber(_s,10)
		end

			-- if overridden, use _s for sacrifice
		if tonumber(_s,10) then
			s = _s
		else
			-- otherwise include sacrifice as 4r
			s = r * 4
		end
		return s
	end
	return -1
end

-- keptondeatharg(deathstatus, ikod, reclaimvalue, sacrificevalue)
function keptondeatharg(d,_i,r,s)
	if d == 'recuperável' then
		local ret = { 'Recuperável' }
		local i
		-- replace commas and convert to number
		if paramtest.has_content(_i) then
			i = string.gsub(_i,',','')
			i = tonumber(i,10)
		else
			i = nil
		end
		if i then
			table.insert(ret,string.format('<b>Valor:</b> %s',commas(i)))
		end

		table.insert(ret,string.format('<b>Recuperar:</b> %s',commas(r)))
		table.insert(ret,string.format('<b>Sacrificar:</b> %s',commas(s)))

		return table.concat(ret,'<br/>')
	else
		return death_map.strings[d]
	end
end

-- red ERR span with title hover for explanation
function badarg(argname, argmessage)
	return '<span '..
			'title="O parâmetro «'..argname..'» '..argmessage..'" '..
			'style="color:red; font-weight:bold; cursor:help; border-bottom:1px dotted red;">'..
			'ERR</span>'
end

-- plural
-- returns number with the word
function plural(arg,n,alt)
	local _n = commas(tonumber(n,10) or 1)
	if tonumber(n,10) == 1 then
		return string.format('%s %s',_n,arg)
	elseif alt then
		return string.format('%s %s',_n,alt)
	else
		return string.format('%s %ss',_n,arg)
	end
end

-- Does exactly what's on the tin
function killRoundingError(n)
	return math.floor(n*1000+0.0000099)/1000
end

function restrictionarg(arg)
	if paramtest.is_empty(arg) then
		return nil
	end
	return restriction_map[string.lower(arg)]
end
function restrsurfarg(cleaned, passed)
	if infobox.isDefined(cleaned) then
		return nil
	end
	return restriction_map.surface
end

function idsmw(id)
	if infobox.isDefined(id) then
		local r = string.gsub(id, ', *', infobox.splitpoint)
		return r
	end
	return nil
end

function make_chisel_links(id, name)
	local link1 = 'https://chisel.weirdgloop.org/gazproj/mrid'
	local link2 = 'https://chisel.weirdgloop.org/gazproj/recipe/'
	if infobox.isDefined(id) then
		local ids = mw.text.split(id, infobox.splitpoint)
		id1 = tonumber(ids[1])
		if id1 then
			if #ids == 1 then
				link1 = string.format('%sid?%s#%s-%s', link1, id1, id1-15, id1+15)
				link2 = link2 .. id1
			else
				for i,j in ipairs(ids) do
					if i == 1 then
						link1 = string.format('%sid?%s#%s', link1, j, j)
						link2 = link2 .. j
					else
						link1 = link1 .. '@' .. j
					end
				end
			end
		else
			link1 = string.format('%sid#%s', link1, ids[1])
			link2 = link2 .. ids[1]
		end
	else
		local _name = name:gsub(' ', '%%20')
		link1 = string.format('%s#%s', link1, _name)
		link2 = nil
	end
	if link2 then
		return string.format('[%s MRID]&nbsp;&bull;&nbsp;[%s recipe]', link1, link2)
	else
		return string.format('[%s MRID]', link1)
	end
end

-- SMW JSON
function SMWarg(name, version, id, membros, release, removal, examine, quest, destroy, restriction, deathstatus, ikodvalue, reclaimvalue, sacrificevalue, tradeable, equipable, bankable, stacksinbank, emprestar, stackable, disassembly, edible, cupom, value, high, low, weight, gemw, gemwname, buylimit)
	local toJSON = {
		name = name,
		version = version,
		id = id,
		membros = string.lower(tostring(membros) or ''),
		examine = examine,
		death = deathstatus,
		destroy = destroy,
		tradeable = string.lower(tostring(tradeable) or ''),
		equipable = string.lower(tostring(equipable) or ''),
		bankable = string.lower(tostring(bankable) or ''),
		stacksinbank = string.lower(tostring(stacksinbank) or ''),
		emprestar = string.lower(tostring(emprestar) or ''),
		stackable = string.lower(tostring(stackable) or ''),
		edible = string.lower(tostring(edible) or ''),
		cupom = string.lower(tostring(cupom) or ''),
		value = val,
		weight = weight,
	}

	local w
	if high == 'Não é possível usar alquimia' then
		toJSON.highalch = false
	else
		w = high:gsub(',',''):gsub('moedas?','')
		toJSON.highalch = tonumber(w) or false
	end
	if low == 'Não é possível usar alquimia' then
		toJSON.lowalch = false
	else
		w = low:gsub(',',''):gsub('moedas?','')
		toJSON.highalch = tonumber(w) or false
	end

	if toJSON.tradeable == 'yes' and gemw then
		toJSON.gemw = { name = gemwname }
		if buylimit ~= '-' then
			w = buylimit:gsub(',','')
			toJSON.gemw.limit = tonumber(w)
		end
	else
		toJSON.gemw = false
	end

	if disassembly:find('[Ss]im') then
		toJSON.disassembly = 'yes'
	elseif disassembly:find('restricted') then
		toJSON.disassembly = 'restricted'
	else
		toJSON.disassembly = string.lower(tostring(disassembly) or '')
	end

	if paramtest.is_empty(restriction) and tostring(restriction):find('action=edit') then
		toJSON.restriction = restriction_map.surface
	else
		toJSON.restriction = restriction
	end

	local rel, upd, rem, updr
	rel, upd = release:match('(.-) %(%[%[Notícia:(.-)|notícia%]%]%)')
	if rel == nil then
		rel = release:match('(.-) %(Atualização desconhecida%)')
	end
	if rel then
		toJSON.release_date = rel:gsub('%[',''):gsub('%]','')
		if upd then
			toJSON.release_update_post = upd
		end
	end

	rem, updr = removal:match('(.-) %(%[%[Notícia:(.-)|notícia%]%]%)')
	if rem == nil then
		rem = removal:match('(.-) %(Atualização desconhecida%)')
	end
	if rem then
		toJSON.removal_date = rem:gsub('%[',''):gsub('%]','')
		if updr then
			toJSON.removal_update_post = updr
		end
	end

	for k,v in pairs(toJSON) do
		if v == '' or (type(v) == 'string' and string.find(v,'action=edit')) then
			toJSON[k] = nil
		end
	end

	return mw.text.killMarkers(mw.text.nowiki(mw.text.jsonEncode(toJSON)))
end

-- Categories
-- oman this is still blatant copy pasta
function addcategories(ibox, args, catargs)
	local ret = { 'Objetos' }
	local cat_map = {
		-- Added if the parameter has content
		defined = {
			aka = 'Pages with AKA',
			alchmultiplier = 'Has Alchemy Multiplier'
			},
		-- Added if the parameter has no content
		notdefined = {
			imagem = 'Precisa de imagem',
			membros = 'Precisa de estado de membros',
			['lançamento'] = 'Precisa de data de lançamento',
			examinar = 'Precisa de texto de examinar',
			level = 'Precisa de nível de combate',
			peso = 'Precisa de peso',
			valor = 'Precisa de valor',
			['missão'] = 'Precisa de missão',
			destruir = 'Precisa de destruir',
			['em morte'] = 'Precisa de em morte',
			['desmontável'] = 'Precisa de desmontável'
			},
		-- Parameters that have text
		-- map a category to a value
		grep = {
			membros = { sim = 'Objetos de membros', ['não'] = 'Objetos de jogadores gratuitos' },
			['acumulável mochila'] = { sim = 'Objetos acumuláveis' },
			emprestar = { sim = 'Objetos emprestáveis' },
			['equipável'] = { sim = 'Objetos equipáveis' },
			gemw = { ['true'] = 'Objetos do Mercado Geral' },
			mercado = { ['but no page was found for'] = 'Exchange page not found' },
			['negociável'] = { sim = 'Objetos negociáveis', ['não'] = 'Objetos não-negociáveis', restricted = 'Objetos negociáveis restritos' },
			['depositável'] = { ['não'] = 'Objetos não-depositáveis' },
			['desmontável'] = { sim = 'Objetos desmontáveis', ['não'] = 'Objetos não-desmontáveis', restricted = 'Location restricted disassembly', ['n/a'] = 'Items with N/A disassembly' },
			['em morte'] = { ['sempre perdido'] = 'Objetos que não são mantidos em morte', ['sempre mantido fora'] = 'Objetos que sempre são mantidos em morte fora da Terra Selvagem', ['recuperável'] = 'Objetos recuperáveis em morte' }
		}
	}

	-- Run and add mapped categories

	-- defined categories
	for n, v in pairs(cat_map.defined) do
		if catargs[n] and catargs[n].one_defined then
			table.insert(ret,v)
		end
	end

	-- undefined categories
	for n, v in pairs(cat_map.notdefined) do
		if catargs[n] and catargs[n].all_defined == false then
			table.insert(ret,v)
		end
	end

	-- searches
	for n, v in pairs(cat_map.grep) do
		for m, w in pairs(v) do
			if args[n] then
				if string.find(string.lower(tostring(args[n].d) or ''),m) then
					table.insert(ret,w)
				end
				if args[n].switches then
					for _, x in ipairs(args[n].switches) do
						if string.find(string.lower(tostring(x)),m) then
							table.insert(ret,w)
						end
					end
				end
			end
		end
	end

	-- quest items
	-- just look for a link
	if args['missão'].d:find('%[%[') then
		table.insert(ret,'Objetos de missão')
	elseif args['missão'].switches then
		for _, v in ipairs(args['missão'].switches) do
			if v:find('%[%[') then
				table.insert(ret,'Objetos de missão')
				break
			end
		end
	end

	-- extra func for death
	-- searching for 'always kept' would match more than what we want
	if args['em morte'].d == 'Sempre mantido' then
		table.insert(ret,'Objetos que são sempre mantidos em morte')
	elseif args['em morte'].switches then
		for _, v in ipairs(args['em morte'].switches) do
			if v == 'Sempre mantido' then
				table.insert(ret,'Objetos que são sempre mantidos em morte')
				break
			end
		end
	end
	-- ids
	if not catargs.id.all_defined then
		-- rsc ids have no id
		if catargs.rscid.all_defined then
			-- do nothing
		else
			table.insert(ret,'Precisa de ID')
		end
	end

	-- loja
	if string.lower(args.loja.d or '') ~= 'não se vende' and not string.lower(args.loja.d or 'edit'):find('edit') then
		table.insert(ret,'Páginas que usam Lojas')
	elseif args.loja.switches then
		for _, v in ipairs(args.loja.switches) do
			if string.lower(v or '') ~= 'não se vende' and string.lower(v or '') ~= infobox.nil_param() and not string.lower(v or 'edit'):find('edit') then
				table.insert(ret,'Páginas que usam Lojas')
			end
		end
	end

	-- alchemy
	-- non alchable
	if args.alquimia.d ~= true then
		table.insert(ret,'Objetos que não podem ser alquimizados')
	elseif args.alquimia.switches then
		for _, v in ipairs(args.alquimia.switches) do
			if v ~= true then
				table.insert(ret,'Objetos que não podem ser alquimizados')
				break
			end
		end
	end

	-- gemw
	-- if item is both (not untradeable) and (not GEMW) then add Non-GE items
	if not args.gemw.d and string.lower(args['negociável'].d) ~= 'não' then
		table.insert(ret, 'Objetos indisponíveis no MG')
	end
	-- switches; if tradeable switches exist, if gemwX and tradeableX are as above, add Non-GE items
	--						if no switches, gemwX and tradeable (default)
	if args.gemw.switches then
		if args['negociável'].switches then
			for i, v in ipairs(args.gemw.switches) do
				if not v and string.lower(args['negociável'].switches[i] or args['negociável'].d) ~= 'não' then
					table.insert(ret, 'Objetos indisponíveis no MG')
				end
			end
		else
			for i, v in ipairs(args.gemw.switches) do
				if not v and string.lower(args['negociável'].d) ~= 'não' then
					table.insert(ret, 'Objetos indisponíveis no MG')
				end
			end
		end
	end

	local limit = string.gsub(tostring(args.buylimit.d), ',', '')
	if tonumber(limit) then
		if tonumber(limit) < 1000 then
			table.insert(ret, 'Baixo limite de compra')
		end
	end
	if args.buylimit.switches then
		for i,v in ipairs(args.buylimit.switches) do
			limit = string.gsub(tostring(args.buylimit.switches[i] or args.buylimit.d), ',', '')
			if tonumber(limit) then
				if tonumber(limit) < 1000 then
					table.insert(ret, 'Baixo limite de compra')
				end
			end
		end
	end

	-- special addition for location restriction
	-- if everything is the same then add to the base page as well
	-- only matters if is a switchfo
	if ibox.switchfo then
		if not catargs.restriction.one_defined then
			-- no restriction set == all of them are surface
			mw.smw.set({['Restrição de local'] = 'surface'}) --check need to translate 'surface' part
		else
			if args.restriction.switches then
				local val = args.restriction.switches[1] or args.restriction.d or restriction_map.surface
				local all_the_same = true
				for i,v in ipairs(args.restriction.switches) do
					local curr = v or args.restriction.d or restriction_map.surface
					if val ~= curr then
						all_the_same = false
						break
					end
				end
				if all_the_same then
					mw.smw.set({['Restrição de local'] = val})
				else
					table.insert(ret, 'Objetos com restrições mistas')
				end
			else
				-- not a switchable param
				-- set to d
				mw.smw.set({['Restrição de local'] = args.restriction.d or restriction_map.surface})
			end
		end
	end

	-- combine table and format category wikicode
	for i, v in ipairs(ret) do
		ret[i] = string.format('[[Categoria:%s]]',v)
	end

	return table.concat(ret,'')
end

return p
--</nowiki>