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

Module:Appearances: Difference between revisions

From Gensopedia
mNo edit summary
mNo edit summary
Line 1: Line 1:
-- Module:Appearances
-- Module:Appearances
-- Renders a character's appearances using short codes or full titles.
-- Renders a character's appearances using short codes or full titles.
-- Keeps order as defined in this file, not alphabetically.
-- Supports:
-- Supports:
--  - |appears=S1, Suikoden II, G1|
--  |appears=S1, Suikoden II, G1|
--  - |S1=yes|G1=yes| (legacy flags)
--  |S1=yes|G1=yes| (legacy)
--  - Mixed input (codes and names)
--  Mixed usage.
--  - Auto category linking and display names


local p = {}
local p = {}


-- Master lookup: code → { page name, category, optional display name }
-- Master order + lookup: code → { page, category, optional display name }
local games = {
local games = {
S1  = { "Suikoden", "Characters in Suikoden" },
S1  = { "Suikoden", "Characters in Suikoden" },
Line 38: Line 38:
}
}


-- Reverse lookup: full title → short code
-- Reverse lookup: title → short code
local titleToCode = {}
local titleToCode = {}
for code, data in pairs(games) do
for code, data in pairs(games) do
Line 55: Line 55:
function p.render(frame)
function p.render(frame)
local args = frame.args
local args = frame.args
local inputCodes = {}
local requested = {}
local seen = {}


-- 1️⃣ Read comma-separated list from |appears=
-- 1️⃣ Collect from |appears=
if args.appears and args.appears ~= "" then
if args.appears and args.appears ~= "" then
for _, token in ipairs(mw.text.split(args.appears, ",")) do
for _, token in ipairs(mw.text.split(args.appears, ",")) do
token = trim(token)
token = trim(token)
if token ~= "" then
if token ~= "" then
-- Normalize to short code if full name is given
local code = titleToCode[token] or token
local code = titleToCode[token] or token
if games[code] then
if games[code] and not seen[code] then
table.insert(inputCodes, code)
seen[code] = true
requested[code] = true
end
end
end
end
Line 71: Line 72:
end
end


-- 2️⃣ Legacy syntax: |S1=yes|G1=yes|
-- 2️⃣ Add legacy |S1=yes| flags
for code, _ in pairs(games) do
for code, _ in pairs(games) do
if (args[code] or ""):lower() == "yes" then
if (args[code] or ""):lower() == "yes" then
table.insert(inputCodes, code)
requested[code] = true
end
end
end
end


-- 3️⃣ Remove duplicates
-- 3️⃣ Output in canonical order (no alphabetical sort)
local seen, unique = {}, {}
local output = {}
for _, code in ipairs(inputCodes) do
for code, entry in pairs(games) do
if not seen[code] then
-- preserve insertion order: we’ll iterate over an ordered key list instead
seen[code] = true
table.insert(unique, code)
end
end
end


-- 4️⃣ Sort codes alphabetically for consistency
-- To preserve order, we must iterate in sequence as defined:
table.sort(unique, function(a, b) return a < b end)
local orderedKeys = {
"S1","S2","G1","G2","CS","S3","S4","ST","S5","HS","TK","PS","HT",
"SP","SL","kpc","SE","SE3","S2n","S2n4","SS1","SS2","SS3","SS4","S4n"
}


-- 5️⃣ Build output
for _, code in ipairs(orderedKeys) do
local output = {}
if requested[code] then
for _, code in ipairs(unique) do
table.insert(output, makeLine(games[code]))
table.insert(output, makeLine(games[code]))
end
end
end



Revision as of 13:27, 10 October 2025

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

-- Module:Appearances
-- Renders a character's appearances using short codes or full titles.
-- Keeps order as defined in this file, not alphabetically.
-- Supports:
--   |appears=S1, Suikoden II, G1|
--   |S1=yes|G1=yes| (legacy)
--   Mixed usage.

local p = {}

-- Master order + lookup: code → { page, category, optional display name }
local games = {
	S1  = { "Suikoden", "Characters in Suikoden" },
	S2  = { "Suikoden II", "Characters in Suikoden II" },
	G1  = { "Genso Suikogaiden Vol.1", "Characters in Genso Suikogaiden Vol.1" },
	G2  = { "Genso Suikogaiden Vol.2", "Characters in Genso Suikogaiden Vol.2" },
	CS  = { "Genso Suikoden Card Stories", "Characters in Genso Suikoden Card Stories" },
	S3  = { "Suikoden III", "Characters in Suikoden III" },
	S4  = { "Suikoden IV", "Characters in Suikoden IV" },
	ST  = { "Suikoden Tactics", "Characters in Suikoden Tactics" },
	S5  = { "Suikoden V", "Characters in Suikoden V" },
	HS  = { "Genso Suikoden Tierkreis Hoshikuzu no Shiro", "Characters in Genso Suikoden Tierkreis Hoshikuzu no Shiro" },
	TK  = { "Suikoden Tierkreis", "Characters in Suikoden Tierkreis" },
	PS  = { "Pachislot Genso Suikoden", "Characters in Pachislot Genso Suikoden" },
	HT  = { "Genso Suikoden Tsumugareshi Hyakunen no Toki", "Characters in Genso Suikoden Tsumugareshi Hyakunen no Toki" },
	SP  = { "Suikoden STAR LEAP", "Characters in Suikoden STAR LEAP" },
	SL  = { "Suikoden STAR LEAP", "Characters in Suikoden STAR LEAP" },
	kpc = { "Konami Parody Comic Series Genso Suikoden", "Characters from Konami Parody Comic Series Genso Suikoden" },
	SE  = { "Genso Suikoden: Soul Eater 1", "Characters from Genso Suikoden Soul Eater", "Soul Eater 1" },
	SE3 = { "Genso Suikoden: Soul Eater 3", "Characters from Genso Suikoden Soul Eater", "Soul Eater 3" },
	S2n = { "Genso Suikoden II: 1 (novel)", "Characters from the Genso Suikoden II novel" },
	S2n4= { "Genso Suikoden II: 4 (novel)", "Characters from the Genso Suikoden II novel" },
	SS1 = { "Genso Suikoden Short Story Collection 1", "Characters from Genso Suikoden Short Story Collection 1" },
	SS2 = { "Genso Suikoden Short Story Collection 2", "Characters from Genso Suikoden Short Story Collection 2" },
	SS3 = { "Genso Suikoden Short Story Collection 3", "Characters from Genso Suikoden Short Story Collection 3" },
	SS4 = { "Genso Suikoden Short Story Collection 4", "Characters from Genso Suikoden Short Story Collection 4" },
	S4n = { "Genso Suikoden IV: 1 (novel)", "Characters from the Genso Suikoden IV novel" },
}

-- Reverse lookup: title → short code
local titleToCode = {}
for code, data in pairs(games) do
	titleToCode[data[1]] = code
end

local function trim(s)
	return (s:gsub("^%s*(.-)%s*$", "%1"))
end

local function makeLine(entry)
	local title, category, display = entry[1], entry[2], entry[3]
	return string.format("* [[%s|%s]] [[Category:%s]]", title, display or title, category)
end

function p.render(frame)
	local args = frame.args
	local requested = {}
	local seen = {}

	-- 1️⃣ Collect from |appears=
	if args.appears and args.appears ~= "" then
		for _, token in ipairs(mw.text.split(args.appears, ",")) do
			token = trim(token)
			if token ~= "" then
				local code = titleToCode[token] or token
				if games[code] and not seen[code] then
					seen[code] = true
					requested[code] = true
				end
			end
		end
	end

	-- 2️⃣ Add legacy |S1=yes| flags
	for code, _ in pairs(games) do
		if (args[code] or ""):lower() == "yes" then
			requested[code] = true
		end
	end

	-- 3️⃣ Output in canonical order (no alphabetical sort)
	local output = {}
	for code, entry in pairs(games) do
		-- preserve insertion order: we’ll iterate over an ordered key list instead
	end

	-- To preserve order, we must iterate in sequence as defined:
	local orderedKeys = {
		"S1","S2","G1","G2","CS","S3","S4","ST","S5","HS","TK","PS","HT",
		"SP","SL","kpc","SE","SE3","S2n","S2n4","SS1","SS2","SS3","SS4","S4n"
	}

	for _, code in ipairs(orderedKeys) do
		if requested[code] then
			table.insert(output, makeLine(games[code]))
		end
	end

	return table.concat(output, "<br />\n")
end

return p