Module:Figurines

local p = {} local h = {}

local DataTable = require("Module:Data Table") local File = require("Module:File") local Franchise = require("Module:Franchise") local GalleryList = require("Module:Gallery List") local TransclusionArguments = require("Module:Transclusion Arguments") local utilsArg = require("Module:UtilsArg") local utilsCargo = require("Module:UtilsCargo") local utilsString = require("Module:UtilsString") local utilsTable = require("Module:UtilsTable")

local CARGO_TABLE = "Figurines" local CATEGORY_INVALID_ARGS = require("Module:Constants/category/invalidArgs") local FIGURINE_LIST_PAGE_FORMAT = "Figurines in %s" local COLUMN_DESCRIPTION = "Description" local COLUMN_FIGURINE = "Figurine" local COLUMN_NUMBER = "Number" local COLUMN_SUBJECTS = "Subject(s)"

local GAMES = { ["TWW"] = { gallery = "Nintendo Gallery", size = "x150px", },	["TMC"] = { gallery = "Figurine Gallery", scale = 2, hasNumbers = true, }, }

function h.warn(msg, ...) local utilsError = require("Module:UtilsError") msg = string.format(msg, ...) utilsError.warn(msg) end function h.warnEmpty(column, rowIndex) h.warn("The value for column  in row %d should not be empty.", column, rowIndex) return "" end

function p.Main(frame) local args, err = utilsArg.parse(frame:getParent.args, p.Templates["Figurines"]) local categories = err and err.categoryText or "" if err then return "", categories end TransclusionArguments.store({		module = "Module:Figurines",		isValid = true,		args = {args.game}	}) local page = args.page or mw.title.getCurrentTitle.subpageText local figurineListPage = string.format(FIGURINE_LIST_PAGE_FORMAT, Franchise.shortName(args.game)) local queryResults = utilsCargo.query(CARGO_TABLE, "figurine, name, number, description", {		where = utilsCargo.allOf( string.format("_pageName = '%s'", figurineListPage), utilsCargo.holdsAny("subjects", {page}) ),		orderBy = "number, name, _ID" -- sort by ID so that figurines with the same name are listed in the order stored (see Silver Darknut)	}) if #queryResults == 0 then h.warn("No figurines found for subject  in game  .", page, args.game) categories = categories.."" return "", categories end local gameData = GAMES[args.game] or {} local columns = {COLUMN_FIGURINE, COLUMN_DESCRIPTION .. " [Description]"} if gameData.hasNumbers then table.insert(columns, 2, COLUMN_NUMBER) end local dataRows = {} for i, figurine in ipairs(queryResults) do		local image = File.image(figurine.figurine, {			scale = gameData.scale,			size = gameData.size,		}) local figurineDisplayName = string.gsub(figurine.name, "Link", frame:expandTemplate({ title = "Player Name" }))		local link = string.format(" %s ", figurineListPage, figurine.name, figurineDisplayName) local row = { cells = {image..link, figurine.description} }		if gameData.hasNumbers then table.insert(row.cells, 2, figurine.number) end table.insert(dataRows, row) end local dataTable = DataTable.printTable(dataRows, {		columns = columns,		sortable = false,	})

local collapsibleHeader = gameData.gallery or #dataRows > 1 and "Figurines" or "Figurine" local collapsible = frame:expandTemplate({		title = "Collapsible",		args = {			header = collapsibleHeader,			frame = "true",			collapse = #dataRows > 1 and "true" or "false",			content = dataTable,		}	}) return collapsible, categories end

function p.DataTable(frame) local game = frame:getParent.args.game return DataTable.Main(frame, h.store, h.extensionArgs) end function h.extensionArgs(args) local columns = GAMES[args.game] or DEFAULT_COLUMNS table.insert(columns, COLUMN_SUBJECTS) return { requiredColumns = columns } end function h.store(args, rows) local categories = "" for i, row in ipairs(rows) do		local isValid = true local figurine = row[COLUMN_FIGURINE] local subjects = row[COLUMN_SUBJECTS] local description = row[COLUMN_DESCRIPTION] local number = row[COLUMN_NUMBER] if figurine == nil or figurine == "" then isValid = false categories = categories..h.warnEmpty(COLUMN_FIGURINE, i)		end if description == nil or description == "" then isValid = false categories = categories..h.warnEmpty(COLUMN_DESCRIPTION, i)		end if isValid and mw.title.getCurrentTitle.nsText == "" then figurine = figurine and string.gsub(figurine, "%[Player Name%]", "Link") local fileType = "Figurine " .. (Franchise.graphics(args.game) == "2D" and "Sprite" or "Model") local entry = GalleryList.entry(args.game, fileType, figurine, {				useTerms = false,			}) local figurineName = entry.subject local figurineFile = entry.file

mw.getCurrentFrame:expandTemplate({				title = "Figurines/Store",				args = {					game = Franchise.baseGame(args.game) or args.game,					number = number,					name = figurineName,					subjects = subjects,					figurine = figurineFile,					description = description,				}			}) end end return categories end

function p.Report(frame) local report = "" report = report..h.report("TWW") report = report..h.report("TMC") if report == "" then report = "Good No issues detected—All subjects which have figurines in TWW or TMC have this template on their respective articles." elseif mw.title.getCurrentTitle.subpageText ~= "Documentation" then report = report.."" end return frame:preprocess(report) end function h.report(game) local utilsMarkup = require("Module:UtilsMarkup") local report = ""

local articlesWithFigurines = TransclusionArguments.query({		template = "Template:Figurines",		parameter = "1",		argument = game,	}) articlesWithFigurines = utilsTable.map(articlesWithFigurines, "_pageName") local subjectsWithFigurines = utilsCargo.query("Figurines", "subjects", {		where = string.format("game = '%s'", game)	}) subjectsWithFigurines = utilsTable.map(subjectsWithFigurines, "subjects") subjectsWithFigurines = utilsTable.flatMap(subjectsWithFigurines, utilsString.split) subjectsWithFigurines = utilsTable.filter(subjectsWithFigurines, function(subject)		return subject ~= "" and subject ~= "N/A"	end) local articlesMissingFigurines = utilsTable.difference(subjectsWithFigurines, articlesWithFigurines) if #articlesMissingFigurines > 0 then local listArticles = utilsTable.map(articlesMissingFigurines, utilsMarkup.link) listArticles = utilsMarkup.bulletList(listArticles) report = report..string.format(" should be added to the following articles as they have Figurines in %s:", game, Franchise.shortName(game), Franchise.display(game)) report = report..listArticles end return report end

p.Templates = { ["Figurines"] = { purpose = "Displays the figurines of a particular subject by retrieving data stored at Figurines in The Wind Waker or Figurines in The Minish Cap.", usesData = true, categories = {"Comment Templates"}, params = { [1] = {				name = "game", desc = "A game code.", enum = utilsTable.keys(GAMES), required = true, },			[2] = {				name = "page", type = "wiki-page-name", desc = "A wiki page name. Should usually be left blank, in which case it default to the current page.", trim = true, nilIfEmpty = true, },		},		examples = { vertical = true, {"TWW", "Link"}, {				desc = "Collapsed by default when there is more than one figurine.", args = {"TMC", "Vaati"}, },			{				desc = "Different figurines can have the same name.", args = {"TWW", "Silver Darknut"}, },			{				desc = "Error handling", args = {"TWW", "Not a Page"}, },			{				args = {"Not a Game"}, },		},	},	["Data Table/Figurines"] = { purpose = string.format("An extension of Template:Data Table for Figurine listings. Data is stored in the %s Cargo table for retrieval by Template:Figurines.", CARGO_TABLE, CARGO_TABLE), usage = "See Template:Data Table for more information", format = "block", paramOrder = {"name", "game", "columns", "..."}, params = { name = { type = "string", required = true, desc = "See the  parameter of Template:Data Table.", },			game = { type = "string", required = true, desc = "See the  parameter of Template:Data Table.", },			columns = { type = "string", desc = string.format("See the  parameter of Template:Data Table. For Template:Figurines to function correctly, there must be columns named ,  , and  . ", COLUMN_FIGURINE, COLUMN_SUBJECTS, COLUMN_DESCRIPTION), },			["..."] = {				name = "cells", placeholder = "cell", desc = "See the  parameter of Template:Data Table.", },		}	}, }

return p