Module:Franchise: Difference between revisions

From Zelda Wiki, the Zelda encyclopedia
Jump to navigation Jump to search
No edit summary
No edit summary
Line 72: Line 72:
})
})
return wikitable
return wikitable
end
function p.ListAllTitles(frame)
local utilsLayout = require("Module:UtilsLayout")
local canonicityStatuses = {
["canon"] = "Canon",
["non-canon"] = "Non-canon",
["ambiguous"] = "Ambiguously-canon",
}
local rows = {}
for i, code in ipairs(p.enum()) do
local link = p.link(code)
local releaseDate = p.releaseDate(code)
local canonicity = p.canonicity(code)
local canonicityStatus = canonicityStatuses[canonicity]
local supersededBy = h.get(code, "supersededBy")
if supersededBy ~= nil and supersededBy ~= "" then
local supersederLink = p.link(supersededBy)
canonicityStatus = canonicityStatus .. string.format(" <small>(superseded by %s)</small>", supersederLink)
end
table.insert(rows, {link, code, releaseDate, canonicityStatus})
end
local wikitable = utilsLayout.table({
sortable = true,
headers = {"Media", "Abbreviation", "Release Date", "Status"},
rows = rows,
})
end
end



Revision as of 00:29, 4 October 2022

Allows modules to access the information stored in franchise code templates.

These functions return nil if passed an invalid code. This is not shown in the examples because it would add invalid codes to Special:WantedTemplates.

Codes are case-sensitive.

Lua error in package.lua at line 80: module 'Module:Franchise/Cache' not found.


local p = {}
local h = {}

local utilsString = require("Module:UtilsString")
local utilsTable = require("Module:UtilsTable")

local Constants = mw.loadData("Module:Constants/Data")
local cache = mw.loadData("Module:Franchise/Cache")

-- Many templates need "Series" as if it were a game. Since it does not fit into the data model of Data:Franchise, it is manually defined here.
local series = {
	article = "The Legend of Zelda (Series)",
	shortName = "The Legend of Zelda Series",
	logo = "File:Zelda Logo TP.png",
	link = "[[The Legend of Zelda (Series)|''The Legend of Zelda'' series]]",
	display = "''The Legend of Zelda'' series",
	canonicity = "canon",
	code = "Series",
}

function p.Article(frame)
	return h.templateQuery("article", frame)
end
function p.BaseGame(frame)
	return h.templateQuery("baseGame", frame)
end
function p.Link(frame)
	return h.templateQuery("link", frame)
end
function p.ShortName(frame)
	return h.templateQuery("shortName", frame)
end
function h.templateQuery(fn, frame)
	local args = frame.args
	local game, nowarn = args[1], args.nowarn
	if game == nil or game == "" then
		local Error = require("Module:Error")
		return "", Error.printError("No game provided", "Category:"..Constants.catInvalidArgs, nowarn)
	end
	game = utilsString.trim(game)
	local value = p[fn](game)
	if not value then
		local Error = require("Module:Error")
		return "", Error.printError(string.format("Invalid entry <code>%s</code>", game), "Category:"..Constants.catInvalidArgs, nowarn)
	end
	local correctGameCode = p.code(game)
	if game ~= correctGameCode then
		local Error = require("Module:Error")
		return value, Error.warn(string.format("<code>%s</code> should be written as <code>%s</code>.", game, correctGameCode), "Category:"..Constants.catInvalidArgs)
	else
		return value
	end
end

-- [[Guidelines:Main]]
function p.ListTitlesByCanonicity(frame)
	local utilsLayout = require("Module:UtilsLayout")

	local canonicity = frame.args[1]
	local rows = {}
	for i, code in ipairs(p.enum()) do
		if canonicity == p.canonicity(code) then
			local link = p.link(code)
			local releaseDate = p.releaseDate(code)
			table.insert(rows, {link, releaseDate})
		end
	end
	local wikitable = utilsLayout.table({
		sortable = true,
		headers = {"Media", "Release Date"},
		rows = rows,
	})
	return wikitable
end
function p.ListAllTitles(frame)
	local utilsLayout = require("Module:UtilsLayout")
	local canonicityStatuses = {
		["canon"] = "Canon",
		["non-canon"] = "Non-canon",
		["ambiguous"] = "Ambiguously-canon",
	}
	
	local rows = {}
	for i, code in ipairs(p.enum()) do
		local link = p.link(code)
		local releaseDate = p.releaseDate(code)
		local canonicity = p.canonicity(code)
		local canonicityStatus = canonicityStatuses[canonicity]
		local supersededBy = h.get(code, "supersededBy")
		if supersededBy ~= nil and supersededBy ~= "" then
			local supersederLink = p.link(supersededBy)
			canonicityStatus = canonicityStatus .. string.format(" <small>(superseded by %s)</small>", supersederLink)
		end
		table.insert(rows, {link, code, releaseDate, canonicityStatus})
	end
	local wikitable = utilsLayout.table({
		sortable = true,
		headers = {"Media", "Abbreviation", "Release Date", "Status"},
		rows = rows,
	})
end

-- Template:Franchise/Store *
function p.AddToPreview(frame)
	-- Performance optimization
	local utilsArg = require("Module:UtilsArg")
	local utilsVar = require("Module:UtilsVar")
	local utilsMarkup = require("Module:UtilsMarkup")
	local doc = mw.loadData("Module:Franchise/Documentation/Data")
	local orderCounter = utilsVar.counter("canonOrder")
	
	local entryType = frame.args[1]
	local args, err = utilsArg.parse(frame:getParent().args, doc.Templates["Franchise/Store " .. entryType])
	if err then
		return utilsMarkup.categories(err.categories)
	end
	args = utilsTable.merge({}, args, {
		entryType = entryType,
		link = p.deriveLink(entryType, args),
		display = p.deriveDisplay(entryType, args),
	})
	if entryType == "Game" or entryType == "Book" or entryType == "TV" then
		args.canonOrder = orderCounter.value()
	else
		args.canonOrder = "—"
	end
	if entryType == "Book" then
		args.phraseLink = p.derivePhraseLink(args)
	end
	utilsVar.add("rows", args)
end
function p.StoreOrder(frame)
	-- Performance optimization
	local utilsVar = require("Module:UtilsVar")
	local orderCounter = utilsVar.counter("canonOrder")
	return orderCounter.increment()
end
function p.StoreLink(frame)
	return p.deriveLink(frame.args[1], frame:getParent().args)
end
function p.StoreDisplay(frame)
	return p.deriveDisplay(frame.args[1], frame:getParent().args)
end
function p.StorePhraseLink(frame)
	return p.derivePhraseLink(frame:getParent().args)
end
function p.deriveDisplay(entryType, args)
	if args.display ~= nil and args.display ~= "" then
		return args.display
	elseif entryType == "Book" then
		return h.deriveBookFields(args).display
	else
		return ("''%s''"):format(args.shortName)
	end
end
function p.deriveLink(entryType, args)
	if args.display ~= nil and args.display ~= "" then
		return args.link
	elseif entryType == "Book" then
		return h.deriveBookFields(args).link
	else
		return ("''[[%s|%s]]''"):format(args.article, args.shortName)
	end
end
function p.derivePhraseLink(args)
	return h.deriveBookFields(args).phraseLink
end

function p.Preview(frame)
	-- Performance optimization
	local utilsMarkup = require("Module:UtilsMarkup")
	local utilsLayout = require("Module:UtilsLayout")
	local utilsVar = require("Module:UtilsVar")
	
	local previewColumns = {
		common = {"canonOrder", "code", "link", "display", "logo", "releaseDate", "canonicity"},
		Game = {"type", "graphics", "family", "remakeOf", "supersededBy"},
		Book = {"type", "phraseLink", "authors", "basedOn"},
		Nonfiction = {"titles"},
		TV = {"type"},
		Group = {"games"},
	}
	previewColumns.Game = utilsTable.concat(previewColumns.common, previewColumns.Game)
	previewColumns.Book = utilsTable.concat(previewColumns.common, previewColumns.Book)
	previewColumns.TV = utilsTable.concat(previewColumns.common, previewColumns.TV)
	previewColumns.Nonfiction = utilsTable.concat(previewColumns.common, previewColumns.Nonfiction)
	previewColumns.Group = utilsTable.concat(previewColumns.common, previewColumns.Group)
	
	local rows = utilsVar.get("rows")
	for _, row in ipairs(rows) do
		row.logo = utilsMarkup.link(row.logo)
	end
	local rowGroups = utilsTable.groupBy(rows, "entryType")
	local titles = utilsLayout.table({
		sortable = true,
		headers = previewColumns.common,
		rows = utilsTable.map(rows, utilsTable._toArray(previewColumns.common, ""))
	})
	local games = utilsLayout.table({
		sortable = true,
		headers = previewColumns.Game,
		rows = utilsTable.map(rowGroups.Game, utilsTable._toArray(previewColumns.Game, ""))
	})
	local books = utilsLayout.table({
		sortable = true,
		headers = previewColumns.Book,
		rows = utilsTable.map(rowGroups.Book, utilsTable._toArray(previewColumns.Book, ""))
	})
	local tv = utilsLayout.table({
		sortable = true,
		headers = previewColumns.TV,
		rows = utilsTable.map(rowGroups.TV, utilsTable._toArray(previewColumns.TV, ""))
	})
	local nonfiction = utilsLayout.table({
		sortable = true,
		headers = previewColumns.Nonfiction,
		rows = utilsTable.map(rowGroups.Nonfiction or {}, utilsTable._toArray(previewColumns.Nonfiction, ""))
	})
	local groups = utilsLayout.table({
		sortable = true,
		headers = previewColumns.Group,
		rows = utilsTable.map(rowGroups.Group or {}, utilsTable._toArray(previewColumns.Group, ""))
	})
	local preview = utilsLayout.tabs({
		{
			label = "All Titles",
			content = titles,
		},
		{
			label = "Games",
			content = games,
		},
		{
			label = "Books (fiction)",
			content = books,
		},
		{
			label = "Books (nonfiction)",
			content = nonfiction
		},
		{
			label = "TV Shows",
			content = tv,
		},
		{
			label = "Groups",
			content = groups,
		}
	}, { columns = 15 })
	return preview
end

function p.UploadField(frame)
	-- Performance optimization
	local utilsMarkup = require("Module:UtilsMarkup")
	local utilsVar = require("Module:UtilsVar")
	
	local rows = utilsVar.get("rows")
	local groups = utilsTable.groupBy(rows, "entryType")
	local mainGames, otherGames = utilsTable.partition(groups["Game"], {
		canonicity = "canon"
	})
	local remakes = utilsTable.groupBy(mainGames, "remakeOf")
	local books = groups["Book"]
	local tvShows = groups["TV"]
	
	local sortedMainGames = {}
	for _, mainGame in ipairs(utilsTable.reverse(mainGames)) do
		if not mainGame.remakeOf then
			table.insert(sortedMainGames, mainGame)
			for _, remake in ipairs(remakes[mainGame.code] or {}) do
				table.insert(sortedMainGames, remake)
			end
		end
	end
	
	local result = ""
	result = result .. "**|None\n"
	result = result .. "**Series|The Legend of Zelda Series\n"
	
	result = h.append(result, "Main Series", sortedMainGames)
	result = h.append(result, "Other Games", otherGames)
	result = h.append(result, "Books, Comics, and Manga", books)
	result = h.append(result, "TV Shows", tvShows)
	return utilsMarkup.pre(result)
end
function h.append(result, title, entries)
	result = result .. "\n*"..title.."\n"
	for _, entry in ipairs(entries) do
		result = result .. string.format("**%s|%s\n", entry.code, entry.shortName)
	end
	return result
end

function h.deriveBookFields(args)
	local ListPages = require("Module:List Pages")
	local utilsString = require("Module:UtilsString")

	local subtitle, display, link, phraseLink
	local parens = string.find(args.shortName, "%s%([^)]+%)")
	if parens then
		subtitle = string.sub(args.shortName, 1, parens - 1)
		local descriptor = string.sub(args.shortName, parens)
		display = ("''%s''%s"):format(subtitle, descriptor)
		link = ("[[%s|%s]]"):format(args.article, display)
		local authors = ListPages.main(utilsString.split(args.authors))
		phraseLink = ("[[%s|''%s'' %s]] by %s"):format(args.article, subtitle, args.type, authors)
	else
		display = ("''%s''"):format(args.shortName)
		link = ("''[[%s|%s]]''"):format(args.article, args.shortName)
		phraseLink = link
	end
	return {
		display = display,
		link = link,
		phraseLink = phraseLink,
	}
end

-- QUERIES: ALL

function p.enum(options)
	if not options then
		return cache.enum
	end
	enum = utilsTable.clone(cache.enum) -- clone the read-only cache item so that we can modify it
	if options.includeSeries then
		table.insert(enum, 1, "Series")
	end
	if options.includeNonfiction then
		local codes = utilsTable.map(cache.nonfiction, "code")
		enum = utilsTable.concat(codes, enum)
	end
	if options.includeGroups then
		-- insert "groups" so as to not disrupt the release order. This matters for Template:Media (e.g. the Figher page, which uses SSB4)
		for _, group in ipairs(cache.groups) do
			local i = 1
			repeat
				i = i + 1
			until i == #enum or p.isCanon(enum[i]) == p.isCanon(group.code) and p.releaseDate(enum[i]) >= p.releaseDate(group.code)
			table.insert(enum, i, group.code)
		end
	end
	enum.reference = "[[Data:Franchise]]"
	return enum
end

function p.article(code)
	return h.get(code, "article")
end

function p.canonicity(code)
	return h.get(code, "canonicity")
end

function p.code(code)
	return h.get(code, "code")
end

function p.display(code)
	return h.get(code, "display")
end

function p.isCanon(code)
	return p.canonicity(code) == "canon"
end

function p.link(code)
	return h.get(code, "link")
end

function p.logo(code)
	return h.get(code, "logo")
end

function p.releaseDate(code)
	return h.get(code, "releaseDate")
end

function p.shortName(code)
	return h.get(code, "shortName")
end

function p.type(code)
	return h.get(code, "type")
end

-- QUERIES: GAMES

function p.enumGames(includeSeries)
	if includeSeries then
		local enum = utilsTable.concat({"Series"}, cache.enumGames)
		enum.reference = "[[Data:Franchise]]"
		return enum
	end
	return cache.enumGames
end

function p.baseGame(code)
	local baseGame = h.get(code, "remakeOf")
	if baseGame == nil then -- game not found
		return nil
	elseif baseGame == "" then -- game has no remake
		return code
	else
		return baseGame
	end
end

function p.family(code)
	return h.get(code, "family")
end

function p.graphics(code)
	return h.get(code, "graphics")
end

function p.hasRemakes(code)
	return utilsTable.hasKey(cache.remakes, string.lower(code))
end

function p.isRemake(code)
	return p.type(code) == "remake"
end

function p.remakes(code)
	return utilsTable.clone(cache.remakes[string.lower(code)]) or {}
end

-- QUERIES: BOOKS

function p.phraseLink(code)
	return h.get(code, "phraseLink")
end

function h.get(code, prop)
	code = string.lower(code)
	if code == "series" then
		return series[prop]
	end
	local title = cache.titlesByCode[code]
	return title and title[prop]
end

return p