Module:Franchise

local p = {} local h = {}

local utilsTable = require("Module:UtilsTable")

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", display = "The Legend of Zelda series", canonicity = "canon", }

-- 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 type == "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"):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"}, TV = {"type"}, Compilation = {"titles"}, 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.Compilation = utilsTable.concat(previewColumns.common, previewColumns.Compilation) 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 compilations = utilsLayout.table({		sortable = true,		headers = previewColumns.Compilation,		rows = utilsTable.map(rowGroups.Compilation or {}, utilsTable._toArray(previewColumns.Compilation, ""))	}) 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",			content = books,		},		{			label = "TV Shows",			content = tv,		},		{			label = "Compilations",			content = compilations		},		{			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"):format(args.article, display)		local authors = ListPages.main(utilsString.split(args.authors))		phraseLink = ("%s %s by %s"):format(args.article, subtitle, args.type, authors)	else		display = ("%s"):format(args.shortName)		link = ("%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.includeCompilations then local codes = utilsTable.map(cache.compilations, "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.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(frame) -- Performance optimization local utilsArg = require("Module:UtilsArg") local utilsMarkup = require("Module:UtilsMarkup")

local args, err = utilsArg.parse(frame.args, {		params = {			[1] = {				name = "code",				enum = p.enum({ includeSeries = true, includeCompilations = true, includeGroups = true, }),			}		}	})	if err then return utilsMarkup.categories(err.categories) end return p.shortName(args.code) 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") local hasBaseGame = baseGame ~= nil and baseGame ~= "" return hasBaseGame and baseGame or code 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