Module:Sandbox/User:Csp713

From WIDEVERSE Wiki
Jump to navigation Jump to search

Documentation for this module may be created at Module:Sandbox/User:Csp713/doc

-- <pre>
local p = {}

local commas = require("Module:Addcommas")._add
local yesno = require("Module:Yesno")
local is_empty = require("Module:Paramtest").is_empty
local has_content = require("Module:Paramtest").has_content
local currency_image = require("Module:Currency Image")
local purge = require("Module:Purge")._purge

function p.main(frame)
	local args = frame:getParent().args
	local item = mw.text.trim(args[1]) or mw.title.getCurrentTitle().text
	mw.log(string.format('Searching for shops that sell: %s', item))

	-- Get parsed smw data
	local data = getData(item)

	-- Create the header of the output
	local headerText = ":''This list was created dynamically. For help, see [[Template:Store locations list/FAQ|the FAQ]].''\n"
		.. ":''To force an update of this list, click " .. purge('res', 'here', 'span') .. ".''\n"
	local restbl = mw.html.create('table')
	restbl:addClass('wikitable sortable align-right-3 align-right-4 align-right-5 align-center-6')
		:tag('tr')
			:tag('th'):wikitext('Seller'):done()
			:tag('th'):wikitext('Location'):done()
			:tag('th'):wikitext('Cost'):attr('data-sort-type', 'number'):done()
			:tag('th'):wikitext('Currency'):done()
			:tag('th'):wikitext('Base stock'):attr('data-sort-type', 'number'):done()
			:tag('th'):wikitext('Members?'):done()
		:done()

	-- Create the rows for the output table
	for _, shop in ipairs(data) do
		restbl:tag('tr')
			:tag('td'):wikitext(shop.seller):done()
			:tag('td'):wikitext(shop.location):done()
			:tag('td'):wikitext(shop.cost):attr('data-sort-value', shop.costSortValue):done()
			:tag('td'):wikitext(shop.currency):done()
			:tag('td'):wikitext(shop.stock):attr('data-sort-value', shop.stockSortValue):done()
			:tag('td'):wikitext(shop.members):done()
		:done()
	end

	return headerText .. tostring(restbl)
end

function getData(itemName)
	-- Query smw
	local smwdata = mw.smw.ask{"[[Sells item::" .. itemName .. "]]", "?Store JSON", "?Is members only", "?Store location"}
	local data = {}

	if smwdata == nil then
		error('The item "' .. itemName .. '" is not sold in any shop, please check for typos', 0)
	end
	-- Loop over the array of returned shops
	for _, shop in ipairs(smwdata) do
		-- Retrieve shop name
		local seller = string.match(shop[1], "%[%[.+%|(.+)%]%]")
		-- Make a edit button that links to the shops edit page incase some data is unknown
		local editbtn = editbutton(seller)
		seller = '[[' .. seller .. ']]'

		-- Find the relevant Store JSON in case the shop sells more than one item
		local itemjson = {}
        -- Escape special characters
        local escapedName = string.gsub(itemName,'[().%+-*?[^$]','%%%1')
		if (type(shop["Store JSON"]) == "table") then
			for _, d in ipairs(shop["Store JSON"]) do
				if (string.match(d, '%"name%": %"' .. escapedName .. '%"')) then
					itemjson = mw.text.jsonDecode( mw.text.decode(d) )
					break
				end
			end
		else
			itemjson = mw.text.jsonDecode( mw.text.decode( shop["Store JSON"] ) )
		end

		-- Shop location
		local location = shop["Store location"] or editbtn
		if type(location) == 'table' then
			location = table.concat(location, ', ')
		end

		-- members only?
		local members = shop["Is members only"]
		local p2pIcon = '[[File:P2P icon.png|25px|link=Pay-to-play]]'
		local f2pIcon = '[[File:F2P icon.png|25px|link=Free-to-play]]'
		if type(members) == 'table' then
			-- contains yes and no
			local hasYes, hasNo = false, false
			for _, value in pairs(members) do
				if yesno(value) ~= nil then
					if yesno(value) then
						hasYes = true
					else
						hasNo = true
					end
				end
			end
			if hasYes and hasNo then
				members = f2pIcon.."/"..p2pIcon
			elseif hasYes then
				members = p2pIcon
			elseif hasNo then
				members = f2pIcon
			else
				members = editbtn
			end
		-- Unsupported type for yesno, default to editbtn
		elseif yesno(members) == nil then
			members = editbtn
		elseif yesno(members) then
			members = p2pIcon
		else
			members = f2pIcon
		end

		-- base amount in stock
		local stock = itemjson["stock"] or ''
		local stockSortValue = 0
		stock = string.lower(string.gsub(stock, ',', ''))
		if stock == '∞' or stock == 'inf' or stock == 'infinite' then
			stock = '<span style="font-size:120%;">∞</span>'
			stockSortValue = '10e99'
		else
			stock = tonumber(stock)
			if stock then
				stockSortValue = stock
				stock = commas(stock)
			else
				stock = editbtn		-- If stock can't be converted to a number it will default to the edit button
			end
		end

		-- item cost
		local cost = itemjson["price"] or ''
		local costSortValue = 0
		cost = string.lower(string.gsub(cost, ',', ''))
		if cost == 'free' or cost == '0' or cost == 'sample' then
			cost = 'Free sample'
		else
			cost = tonumber(cost)
			if cost then
				costSortValue = cost
				cost = commas(cost)
			else
				cost = editbtn
			end
		end

		-- currency
		local currency = itemjson["currency"]
		if is_empty(currency) then
			currency = editbtn
		elseif cost == 'Free sample' then
			currency = "-"
		else
			local displayVal = currency:gsub("^%l", string.upper) -- first letter uppercase
			local imageName = currency_image(currency, costSortValue) or ''
			if(has_content(imageName)) then
				currency = string.format('[[File:%s|link=]]%s', imageName, displayVal)
			else
				currency = displayVal
			end
		end
		
		-- Store a line in the final data table
		local dataline = {
			seller = seller,
			location = location,
			members = members,
			stock = stock,
			stockSortValue = stockSortValue,
			cost = cost,
			costSortValue = costSortValue,
			currency = currency
		}
		table.insert(data, dataline)
	end

	return data
end

function editbutton(title)
	local link = string.gsub(mw.title.getCurrentTitle():fullUrl("action=edit"), mw.title.getCurrentTitle().fullText, title)
	link = string.gsub(link, ' ', '_')
	link = string.format("<span class='plainlinks'>[%s '''?''' (edit)]</span>", link)
	return link
end

return p