Modul:Gegner Ehemalige Spieler

Aus HuskyWiki
Version vom 6. Mai 2026, 11:32 Uhr von ChatBot (Diskussion | Beiträge) (Modul auf HuskyWiki-Spielerkategorie als gemeinsame Kassel-Basis umgestellt)

Die Dokumentation für dieses Modul kann unter Modul:Gegner Ehemalige Spieler/Doku erstellt werden

local p = {}

local DEFAULT_KASSEL_PLAYER_CATEGORIES = {
	"Spieler",
}

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

local function getArg(frame, name)
	local value = trim(frame.args[name])
	if value ~= "" then
		return value
	end

	local parent = frame:getParent()
	if parent then
		return trim(parent.args[name])
	end

	return ""
end

local function surnameSortKey(name)
	local clean = trim(name)
	if clean == "" then
		return ""
	end

	if clean:find(",", 1, true) then
		local last, first = clean:match("^([^,]+),%s*(.*)$")
		return mw.ustring.lower(trim((last or "") .. " " .. (first or "")))
	end

	local parts = {}
	for part in clean:gmatch("%S+") do
		table.insert(parts, part)
	end

	if #parts <= 1 then
		return mw.ustring.lower(clean)
	end

	local particles = {
		["de"] = true,
		["del"] = true,
		["der"] = true,
		["den"] = true,
		["di"] = true,
		["la"] = true,
		["le"] = true,
		["st."] = true,
		["st"] = true,
		["van"] = true,
		["von"] = true,
	}

	local last = table.remove(parts)
	local previous = parts[#parts]
	if previous and particles[mw.ustring.lower(previous)] then
		last = previous .. " " .. last
		table.remove(parts)
	end

	return mw.ustring.lower(last .. " " .. table.concat(parts, " "))
end

local function getCategoryMembers(category)
	if not (mw.ext and mw.ext.dpl and type(mw.ext.dpl.getPagenames) == "function") then
		mw.addWarning("DynamicPageListEngine/Lua ist nicht verfügbar.")
		return {}
	end

	category = trim(category):gsub("^Kategorie:%s*", "")
	if category == "" then
		return {}
	end

	local ok, pages = pcall(mw.ext.dpl.getPagenames, {
		category = category,
		namespace = "main",
		redirects = "exclude",
		ordermethod = "sortkey",
		order = "ascending",
		count = 500,
	})

	if not ok then
		mw.addWarning("DynamicPageListEngine-Fehler: " .. tostring(pages))
		return {}
	end

	return pages or {}
end

local function parseCategoryList(raw)
	local categories = {}
	local seen = {}
	for part in (raw or ""):gmatch("[^|]+") do
		local category = trim(part)
		if category ~= "" and not seen[category] then
			seen[category] = true
			table.insert(categories, category)
		end
	end
	return categories
end

local function buildIntersection(opponentCategory, kasselCategories)
	local kasselSet = {}
	for _, category in ipairs(kasselCategories) do
		for _, title in ipairs(getCategoryMembers(category)) do
			kasselSet[title] = true
		end
	end

	local entries = {}
	local seen = {}
	for _, title in ipairs(getCategoryMembers(opponentCategory)) do
		if kasselSet[title] and not seen[title] then
			seen[title] = true
			table.insert(entries, {
				title = title,
				label = title,
				sort = surnameSortKey(title),
			})
		end
	end

	table.sort(entries, function(a, b)
		return a.sort < b.sort
	end)

	return entries
end

local function renderLink(entry)
	return string.format("* [[%s|%s]]", entry.title, entry.label)
end

local function splitIntoColumns(entries, count)
	local columns = {}
	for i = 1, count do
		columns[i] = {}
	end

	if #entries == 0 then
		return columns
	end

	local perColumn = math.ceil(#entries / count)
	for index, entry in ipairs(entries) do
		local target = math.floor((index - 1) / perColumn) + 1
		if target > count then
			target = count
		end
		table.insert(columns[target], renderLink(entry))
	end

	return columns
end

local function renderColumn(lines)
	if #lines == 0 then
		return "&nbsp;"
	end
	return table.concat(lines, "<br>")
end

local function getStyleConfig(style)
	local normalized = mw.ustring.lower(trim(style))
	if normalized ~= "spielerstatistik" and normalized ~= "spielerstatistik2526" then
		return {
			tableClass = "wikitable",
			tableStyle = "font-size:95%; width:60%;",
			headerStyle = "background:#00205B; color:#FFFFFF; text-align:center;",
			cellStyles = {
				"width:10%; background:#eeeeee; vertical-align:top;",
				"width:10%; background:#eeeeee; vertical-align:top;",
			},
		}
	end

	return {
		tableClass = "wikitable plainrowheaders",
		tableStyle = "font-size:95%; width:60%;",
		headerStyle = "background-color:#eef3f8; text-align:center;",
		cellStyles = {
			"width:10%; background-color:#f8fafc; vertical-align:top;",
			"width:10%; background-color:#eef3f8; vertical-align:top;",
		},
	}
end

function p.render(frame)
	local opponentCategory = getArg(frame, "opponentPlayerCategory")
	if opponentCategory == "" then
		return "<strong>Fehler:</strong> Parameter <code>opponentPlayerCategory</code> fehlt."
	end

	local kasselRaw = getArg(frame, "kasselPlayerCategories")
	local kasselCategories = {}
	if kasselRaw == "" then
		for _, category in ipairs(DEFAULT_KASSEL_PLAYER_CATEGORIES) do
			table.insert(kasselCategories, category)
		end
	else
		kasselCategories = parseCategoryList(kasselRaw)
	end

	local entries = buildIntersection(opponentCategory, kasselCategories)
	local columns = splitIntoColumns(entries, 2)
	local title = getArg(frame, "title")
	if title == "" then
		title = string.format("Ehemalige Spieler beider Teams <small>(%d)</small>", #entries)
	end
	local emptyText = getArg(frame, "emptyText")
	if emptyText == "" then
		emptyText = "Keine gemeinsamen ehemaligen Spieler erfasst."
	end

	local styleConfig = getStyleConfig(getArg(frame, "style"))
	if #entries == 0 then
		return table.concat({
			string.format('{| class="%s" style="%s"', styleConfig.tableClass, styleConfig.tableStyle),
			string.format('! colspan=2 style="%s"|%s', styleConfig.headerStyle, title),
			"|-",
			string.format('| colspan=2 style="%s"|%s', styleConfig.cellStyles[1], emptyText),
			"|}",
		}, "\n")
	end

	return table.concat({
		string.format('{| class="%s" style="%s"', styleConfig.tableClass, styleConfig.tableStyle),
		string.format('! colspan=2 style="%s"|%s', styleConfig.headerStyle, title),
		"|-",
		'| style="' .. styleConfig.cellStyles[1] .. '"|' .. renderColumn(columns[1]),
		'| style="' .. styleConfig.cellStyles[2] .. '"|' .. renderColumn(columns[2]),
		"|}",
	}, "\n")
end

return p