PC Gaming Shelter
An archive dedicated to preserving PC Gaming history and more

Module:ResourceList

From PC Gaming Shelter
Revision as of 11:23, 10 July 2026 by WikiVisor (talk | contribs)

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

local p = {}

local FIELDS = {
	{
		key = "resources",
		title = "Resources",
		property = "Has resource type",
	},
	{
		key = "types",
		title = "Types",
		property = "Has content type",
	},
	{
		key = "langs",
		title = "Languages",
		property = "Has language",
	},
	{
		key = "years",
		title = "Years",
		property = "Has date",
	},
}

local function trim(value)
	return mw.text.trim(tostring(value or ""))
end

local function valueText(value)
	if type(value) ~= "table" then
		return trim(value)
	end

	return trim(
		value.fulltext
			or value.fullText
			or value.label
			or value.text
			or value.displaytitle
			or value[1]
			or ""
	)
end

local function addValue(bucket, rawValue)
	local value = valueText(rawValue)

	if value == "" then
		return
	end

	local key = mw.ustring.lower(value)

	if bucket.counts[key] == nil then
		bucket.counts[key] = 0
		bucket.labels[key] = value
	end

	bucket.counts[key] = bucket.counts[key] + 1
end

local function collect(rows)
	local buckets = {}

	for _, field in ipairs(FIELDS) do
		buckets[field.key] = {
			counts = {},
			labels = {},
		}
	end

	for _, row in ipairs(rows) do
		for _, field in ipairs(FIELDS) do
			local values = row[field.key]
			local bucket = buckets[field.key]

			if type(values) == "table" then
				for _, value in ipairs(values) do
					addValue(bucket, value)
				end
			else
				addValue(bucket, values)
			end
		end
	end

	return buckets
end

local function sortedKeys(bucket)
	local keys = {}

	for key in pairs(bucket.counts) do
		table.insert(keys, key)
	end

	table.sort(keys, function(a, b)
		return mw.ustring.lower(bucket.labels[a]) < mw.ustring.lower(bucket.labels[b])
	end)

	return keys
end

local function queryFormLink(frame, game, propertyName, item)
	return frame:preprocess(string.format(
		"{{#queryformlink: form=Resource filter" ..
		"|link text=%s" ..
		"|Resource filter[Related game]=%s" ..
		"|Resource filter[%s]=%s" ..
		"|Resource filter[Has filter]=%s" ..
		"|_run=1" ..
		"}}",
		item,
		game,
		propertyName,
		item,
		propertyName
	))
end

local function renderList(frame, field, bucket, game, showCounts)
	local lines = {
		"==" .. field.title .. "==",
	}

	local keys = sortedKeys(bucket)

	if #keys == 0 then
		table.insert(lines, "''None found.''")
		return table.concat(lines, "\n")
	end

	for _, key in ipairs(keys) do
		local label = bucket.labels[key]
		local link = queryFormLink(frame, game, field.property, label)

		if showCounts then
			table.insert(lines, "* " .. link .. " (" .. bucket.counts[key] .. ")")
		else
			table.insert(lines, "* " .. link)
		end
	end

	return table.concat(lines, "\n")
end

local function askRows(args)
	local game = args.game or "Half-Life"
	local limit = args.limit or "5000"

	return mw.smw.ask({
		"[[Resource:+]]",
		"[[Related game::" .. game .. "]]",
		"?Has resource type=resources",
		"?Has content type=types",
		"?Has language=langs",
		"?Has date#-F[Y]=years",
		"limit=" .. limit,
		"mainlabel=-",
	}) or {}
end

function p.render(frame)
	local parent = frame:getParent()
	local args = setmetatable(frame.args, {
		__index = parent and parent.args or {},
	})

	local game = args.game or "Half-Life"
	local showCounts = args.counts ~= "no"
	local rows = askRows(args)
	local buckets = collect(rows)

	local output = {}

	for _, field in ipairs(FIELDS) do
		table.insert(output, renderList(frame, field, buckets[field.key], game, showCounts))
	end

	return table.concat(output, "\n\n")
end

function p.filtered(frame)
	local item   = frame.args['item']
	local parent = frame:getParent()
	local args = setmetatable(frame.args, {
		__index = parent and parent.args or {},
	})

	local game   = args['Related game']
	local filter = args['Has filter']

	local query = frame:callParserFunction({ '#ask', { 
		"[[Resource:+]]",
		"[[Related game::" .. game .. "]]",
		"[[" .. filter .. "::~" .. item .. "]]",
		"mainlabel=-",
		"?#-=",
		"format=embedded",
		"embedonly=yes",
		"limit=5000"
		}
	}) or {}

	return query
end

p.main = p.render

return p