Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Module:Shop

From The Petit Planet Wiki
Revision as of 19:13, 10 November 2025 by ReisuDesign (talk | contribs)

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

local p = {}
local lib = require('Module:Feature')
local Item = require('Module:Item')._main
local category = mw.html.create():wikitext('[[Category:Shops]]')
local TS = lib.thousandsSeparator
local total = {}

function p.main(frame)
	local args = require('Module:Arguments').getArgs(frame)
	if tonumber(frame:callParserFunction('#var:transclude', '') or '0') == 1 then
		args.nocat = 1
	end
	
	return p._main(args)
end

function p._main(args)
	local out = mw.html.create('table'):addClass('article-table fandom-table sortable ' .. (args.class or ''))
	local delim = args.delim or ';;'
	local currency = args.currency or 'Dough'
	local stock = args.stock or 'Stock'
	
	-- Header row
	local tr = out:tag('tr')
	tr:tag('th'):wikitext('Item')
	tr:tag('th'):wikitext('Cost')
	tr:tag('th'):wikitext(stock)
	if tonumber(args.total) == 1 then tr:tag('th'):attr('data-sort-type', 'number'):wikitext('Total Cost') end
	if lib.isNotEmpty(args.refresh) then tr:tag('th'):wikitext('Refresh') end
	if lib.isNotEmpty(args.note) then tr:tag('th'):wikitext('Notes') end
	
	-- Table body
	for _, raw in ipairs(args) do
		local data = p.splitParams(raw, delim)
		data.size = data.size or args.size or '35' -- first column image size
		data.currency = data.currency or currency
		data.cost_delim = data.cost_delim or args.cost_delim or ','
		out:tag('tr'):node(p.ItemRow(data, args))
	end
	
	-- Footer row
	if next(total) ~= nil and tonumber(args.total) == 1 then
		local tr = out:tag('tr')
		tr:tag('th'):wikitext('Total cost for all items')
		local th = tr:tag('th'):attr('colspan', 3 + (lib.isNotEmpty(args.refresh) and 1 or 0) + (lib.isNotEmpty(args.note) and 1 or 0))
		local discount = false
		for name, info in lib.spairs(total) do
			if not discount and info.discounted and info.discounted>0 and info.discounted<info.base then discount=true end
			th:node(Item{
				name = name,
				link = name,
				count = TS(info.base) .. (info.base2>0 and (' (' .. TS(info.base2) .. ')') or ''),
				size = 25
			}):wikitext('<br />')
		end
		if discount then
			th:tag('u'):tag('small'):wikitext('Discounted:<br />')
			for name, info in lib.spairs(total) do
				th:node(Item{
					name = name,
					link = name,
					count = TS(info.discounted) .. (info.discounted2>0 and (' (' .. TS(info.discounted2) .. ')') or ''),
					size = 25
				}):wikitext('<br />')
			end
		end
	end
	
	if not args.shop or mw.title.getCurrentTitle().rootText == args.shop then
		out:node(require('Module:Namespace detect').main{main=category})
	end
	
	return out
end

function p.ItemRow(data, args)
	local row = mw.html.create()
	local cost = data[2]
	local stock = data[3] or data.stock
	local currency = data.currency or args.currency or 'Dough'
	
	function getCost(i)
		i.mult = tonumber(i.mult) or 1
		i.mult2 = tonumber(i.mult2) or 0
		if not data[1] and lib.isNotEmpty(data.x) and data.x ~= '1' then i.cell:wikitext('&times;', data.x, ' per ') end
		if tonumber(i.value) == nil then
			local items = lib.split(i.value, data.cost_delim)
			for a, item in ipairs(items) do
				local name, amount = string.match(item, '^(.-)%*(.-)$')
				amount = tonumber((amount:gsub(',', '')))
				if name == currency then i.cell:attr('data-sort-value', amount) end
				i.cell:node(Item{
					name = name,
					link = name,
					count = TS(amount*i.mult) .. (i.mult2>0 and (' (' .. TS(amount*i.mult2) .. ')') or ''),
					notext = 1,
					size = 25
				}):wikitext('<br />')
				if (args.nocat == nil and i.nocat == nil) then category:wikitext('[[Category:', name, ' Shops]]') end
				if i.store_total and not args.nototal then
					total[name] = total[name] or {base=0, base2=0, discounted=0, discounted2=0}
					total[name][i.store_total] = total[name][i.store_total] + amount*i.mult
					total[name][i.store_total..'2'] = total[name][i.store_total..'2'] + amount*i.mult2
				end
			end
		else
			i.value = tonumber((i.value:gsub(',', '')))
			i.cell
			:attr('data-sort-value', i.value)
			:node(Item{
					name = currency,
					link = currency,
					count = TS(i.value*i.mult) .. (i.mult2>0 and (' (' .. TS(i.value*i.mult2) .. ')') or ''),
					notext = 1,
					size = 25
				})
			if (args.nocat == nil and i.nocat == nil) then category:wikitext('[[Category:', currency, ' Shops]]') end
			if i.store_total and not args.nototal then
				total[currency] = total[currency] or {base=0, base2=0, discounted=0, discounted2=0}
				total[currency][i.store_total] = total[currency][i.store_total] + i.value*i.mult
				total[currency][i.store_total..'2'] = total[currency][i.store_total..'2'] + i.value*i.mult2
			end
		end
	end
	if data[1] then
		local info = {}
		local specific = data.specific or lib.ternary(tonumber(data.blueprint)==1, 'Blueprint: ' .. data[1], data[1])
		info.name = data[1]
		info.size = data.size
		info.count = data.x
		info.link = data.link or specific
		info.text = data.text or specific
		info['type'] = data['type']
		if (data['type'] == 'Light Cone') then
			info.suffix = 'Icon'
		end
		row:tag('td'):node(Item(info))
		if (not args.nocat) then category:wikitext('[[Category:Sells ', specific:gsub('&', 'and'), '|', specific, ']]') end
	end
	if cost then
		local cell = row:tag('td')
		getCost{cell=cell, value=cost}
		if data.discount then
			cell:tag('div'):tag('u'):tag('small'):wikitext('Discounted:<br />')
			getCost{cell=cell, value=data.discount}
		end
	end
	if stock then
		local cell = row:tag('td')
		if stock == 'inf' then cell:wikitext('∞')
		else cell:wikitext(stock)
		end
		if data.stock2 then cell:wikitext(' (', data.stock2, ')') end
	end
	if tonumber(args.total) == 1 and cost and stock then
		local cell = row:tag('td')
		if stock == 'inf' then cell:wikitext('&mdash;')
		else 
			getCost{cell=cell, value=cost, mult=stock, mult2=data.stock2, nocat=true, store_total='base'}
			if data.discount then 
				cell:tag('div'):tag('u'):tag('small'):wikitext('Discounted:<br />')
				getCost{cell=cell, value=data.discount, mult=stock, mult2=data.stock2, nocat=true, store_total='discounted'}
			else
				-- Sum non-discounted to discount for those who dont have a discounted version
				local mult = tonumber(stock) or 1
				local mult2 = tonumber(data.stock2) or 0
				if cost:find('%*%d') then
					local items = lib.split(cost, data.cost_delim)
					for a, item in ipairs(items) do
						local name, amount = string.match(item, '^(.-)*(.-)$')
						amount = tonumber((amount:gsub(',', '')))
						total[name] = total[name] or {base=0, base2=0, discounted=0, discounted2=0}
						total[name]['discounted'] = total[name]['discounted'] + amount*mult
						total[name]['discounted2'] = total[name]['discounted2'] + amount*mult2
					end
				else
					local value = tonumber((cost:gsub(',', '')))
					total[currency] = total[currency] or {base=0, base2=0, discounted=0, discounted2=0}
					total[currency]['discounted'] = total[currency]['discounted'] + value*mult
					total[currency]['discounted2'] = total[currency]['discounted2'] + value*mult2
				end
			end
		end
	end
	if data.refresh or args.refresh then
		refreshKeys = {d = 'Daily', w = 'Weekly', m = 'Monthly', v = 'Per Version'}
		row:tag('td'):wikitext(refreshKeys[data.refresh or 1] or data.refresh or '')
	end
	if data.note or args.note then row:tag('td'):wikitext(data.note or '') end
	
	return row
end

function p.splitParams(entry, paramDelim)
	entry = lib.split(entry, paramDelim)
	local returns = {}
	for i, param in ipairs(entry) do
		local name, val = string.match(param, '^%s*(.-)%s*{?{?=}?}?%s*(.-)%s*$')
		if name ~= nil and name ~= '' and val ~= nil then --named params
			returns[name] = val
		elseif param ~= nil and param ~= '' then --unnamed params
			table.insert(returns, param)
		end
	end
	return returns
end

return p