Jump to content

Module:SongContestData

From Wikipedia, the free encyclopedia

local getArgs = require('Module:Arguments').getArgs

local p = {}

local function makeInvokeFunc(funcName)
	return function (frame)
		local args = getArgs(frame)
		return p[funcName](args)
	end
end

local function processOutput(o)
	if type(o) == "table" then
	    local result = {}
	    for _, v in pairs(o) do
	        table.insert(result, tostring(v))
	    end
	    return table.concat(result, ";")
	end
	return o
end

local function getData(contest, year)
	return mw.loadData('Module:SongContestData/'..contest..'/'..year)
end

local function filterData(data, att, excludeAtt, excludeVal, excludeInvert)
	-- copy data table and filter entries that have exclude
	local filtered_data = {}
	for k, v in pairs(data) do
		local shouldExclude = (excludeAtt and v[excludeAtt] == nil) or
			(excludeAtt and v[excludeAtt] and excludeVal and (
				(not excludeInvert and v[excludeAtt] == excludeVal) or -- normal exclusion
				(excludeInvert and v[excludeAtt] ~= excludeVal)        -- inverted exclusion
			))
	    if (v[att] or not att) and not shouldExclude then
	        filtered_data[k] = v
	    end
	end
	return filtered_data
end

local function sortEntries(data, att, desc)
	-- store original keys for sorting
	local keys = {}
	for k in pairs(data) do
		table.insert(keys, k)
	end

	if not att then
		-- use the common country name for sorting instead of ISO country code when no attribute is provided
		local isoName = require('Module:ISO 3166').luaname
		local nameMap = {}
		for _, k in ipairs(keys) do
			nameMap[k] = isoName({k}) or k -- precompute names
		end

		-- sort keys alphabetically
		table.sort(keys, function(a, b)
			local aName = nameMap[a]
			local bName = nameMap[b]
			return desc and aName > bName or aName < bName
		end)
	else
		-- sort keys based on the corresponding attribute values
		table.sort(keys, function(a, b)
			local aVal, bVal = data[a][att], data[b][att]
			return desc and aVal > bVal or aVal < bVal
		end)
	end

	return keys
end

p.main = makeInvokeFunc('_main')
function p._main(args)
	local data = getData(args[1], args[2])
	local entryData = data[args[3]]
	
	if entryData and entryData[args[4]] then
        return processOutput(entryData[args[4]])
    end

    return ""
end

p.entryAmount = makeInvokeFunc('_entryAmount')
function p._entryAmount(args)
	local data = getData(args[1], args[2])
	local show = args[3]
	if show then
		local code = string.match(show, "[a-zA-Z]+")
		local num  = tonumber(string.match(show, "%d+"))
		data = filterData(data, nil, code, num, true)
	end
	local amount = 0
	for _ in pairs(data) do amount = amount + 1 end
	return amount
end

p.order = makeInvokeFunc('_order')
function p._order(args)
	local data = getData(args[1], args[2])
	local att = args[3]
	local filtered_data = filterData(data, att, args['excludeAtt'], args['excludeVal'], args['excludeInvert'] or false)
	return sortEntries(filtered_data, att, args['desc'] or false)
end

p.getEntryData = makeInvokeFunc('_getEntryData')
function p._getEntryData(args)
	local data = getData(args[1], args[2])
	return data[args[3]]
end

return p