Module:Release

Jump to navigation Jump to search

sortableDate

Accepts a date and outputs that date with an invisible YMD-formatted sort key for tables. Can have whatever arbitrary text after the year number (such as citations and footnotes). Dates must be in one of the following formats:

  • January 1, 2000
  • January 1st, 2000
  • 1 January 2000
  • 1st January 2000
  • January 2000
  • 2000

If day or day and month are omitted, they sort as 00 though nothing is displayed for them.

main

Similar to the above but shows regions, for which dates can be inputted per region. The invisible sort key is whatever regional date is the earliest. Regions are sorted by release date. For more information, see Template:Release/Documentation.

region

Like main but doesn't require dates or put a sort key.


local getArgs = require('Module:Arguments').getArgs
local p = {}

local regions = {
	"JP", "WW", "US", "AU", "BR", "CA", "CN", "DE", "EU", "ES", "FR", "GB", "HK", "IT", "KR", "MO", "MY", "PH", "PL", "PT", "RU", "SEA", "SG", "TH", "TR", "TW"
}
local regionNames = {
	JP = "Japan",
	WW = "Worldwide",
	US = "United States of America",
	AU = "Australia",
	BR = "Brazil",
	CA = "Canada",
	CN = "China",
	DE = "Germany",
	EU = "Europe",
	ES = "Spain",
	FR = "France",
	GB = "United Kingdom",
	HK = "Hong Kong",
	MO = "Macao",
	IT = "Italy",
	KR = "South Korea",
	PL = "Poland",
	PT = "Portugal",
	RU = "Russia",
	TR = "Turkey",
	TW = "Taiwan",
	SEA = "Southeast Asia",
	SG = "Singapore",
	MY = "Malaysia",
	PH = "Philippines",
	TH = "Thailand",
}

local monthNumbers = {
	Null = "00",
	January = "01",
	February = "02",
	March = "03",
	April = "04",
	May = "05",
	June = "06",
	July = "07",
	August = "08",
	September = "09",
	October = "10",
	November = "11",
	December = "12"
}
local monthNames = {
	[0] = "Null",
	[1] = "January",
	[2] = "February",
	[3] = "March",
	[4] = "April",
	[5] = "May",
	[6] = "June",
	[7] = "July",
	[8] = "August",
	[9] = "September",
	[10] = "October",
	[11] = "November",
	[12] = "December"
}

local function parseDate(initialInput)
	local dateInput, suffix = initialInput:match("(.-%d%d%d%d)(.*)")
	local dateTable = {}
	for word in string.gmatch(string.gsub(dateInput, ",", ""), "([^ ]+)") do
		table.insert(dateTable,word)
	end
	local year = 0
	local monthName = "Null"
	local day = 0
	local sortableDay = "00"
	
	if dateTable[2] then
		if monthNumbers[dateTable[2]] then
			dateTable[1], dateTable[2] = dateTable[2], dateTable[1]
		end
		
		if dateTable[2]:sub(2,3) == "st" or dateTable[2]:sub(2,3) == "nd" or dateTable[2]:sub(2,3) == "rd" or dateTable[2]:sub(2,3) == "th" then
			dateTable[2] = dateTable[2]:sub(1,1)
		elseif dateTable[2]:sub(3,4) == "st" or dateTable[2]:sub(3,4) == "nd" or dateTable[2]:sub(3,4) == "rd" or dateTable[2]:sub(3,4) == "th" then
			dateTable[2] = dateTable[2]:sub(1,2)
		end
	end

	if #dateTable == 3 then
		year = tonumber(dateTable[3])
		monthName = dateTable[1]
		day = tonumber(dateTable[2])
		sortableDay = string.format("%02d",day)
	elseif #dateTable == 2 then
		year = tonumber(dateTable[2])
		monthName = dateTable[1]
	elseif #dateTable == 1 then
		year = tonumber(dateTable[1])
	end
	
	return {
		[1] = year .. "-" .. monthNumbers[monthName] .. "-" .. sortableDay,
		[2] = suffix
	}
end

local function toMDY(ymdDate)
	local year = ymdDate:sub(1,4)
	local month = monthNames[tonumber(ymdDate:sub(6,7))]
	local day = tonumber(ymdDate:sub(9,10))
	if month == "Null" and day == 0 then
		return year
	elseif day == 0 then
		return month .. " " .. year
	else
		return month .. " " .. day .. ", " .. year
	end
end

function p.main(frame)
	local args = getArgs(frame)
	local releases = { }
	local sortKey = "9999-99-99"
	local output = ""
	if args["header"] then
		output = "'''" .. args["header"] .. "'''<br/>"
	end
	
	--Fallback region order is for if multiple regions share a date
	local fallbackRegionOrder = {}
	for i, region in ipairs(regions) do
		fallbackRegionOrder[region] = i
	end
	
	--Parse date and store it in regions table
	for _, region in ipairs(regions) do
		if args[region] then
			local parsed = parseDate(args[region])
			local date = parsed[1]
			local suffix = parsed[2]
			if sortKey > date then
				sortKey = date
			end
			--Releases table is an array of tables
			table.insert(releases, { ["region"] = region, ["date"] = date, ["suffix"] = suffix })
		end
	end
	
	--Sort dates, falling back to fallbackRegionOrder if two or more dates are the same
	table.sort(releases, function(a, b)
		if a["date"] == b["date"] then
			return fallbackRegionOrder[a.region] < fallbackRegionOrder[b.region]
		else
			return a["date"] < b["date"]
		end
	end)
	
	--Produce output
	for _, release in ipairs(releases) do
		local displayRegion = ""
		if release.region == "WW" then
			displayRegion = frame:expandTemplate{ title = "Tt", args = { "'''WW'''", regionNames[release.region] } }
		else
			displayRegion = frame:expandTemplate{ title = "Tt", args = { frame:expandTemplate{ title = "Flag", args = { release.region } }, regionNames[release.region] } }
		end
		output = output .. displayRegion .. " " .. toMDY(release.date) .. release.suffix .. "<br/>"
	end

	output = '<span data-sort-value="' .. sortKey .. '"></span>' .. output
	return output
end

function p.sortableDate(frame)
	local args = getArgs(frame)
	return '<span data-sort-value="' .. parseDate(args[1])[1] .. '"></span>' .. toMDY(parseDate(args[1])[1]) .. parseDate(args[1])[2]
end

function p.region(frame)
	local args = getArgs(frame)
	local output = ""
	if args["header"] then
		output = "'''" .. args["header"] .. "'''<br/>"
	end
	
	for i, region in ipairs(regions) do
		local displayRegion = ""
		if region == "WW" then
			displayRegion = frame:expandTemplate{ title = "Tt", args = { "'''WW'''", regionNames[region] } }
		else
			displayRegion = frame:expandTemplate{ title = "Tt", args = { frame:expandTemplate{ title = "Flag", args = { region } }, regionNames[region] } }
		end
		if args[region] then
			output = output .. displayRegion .. " " ..  args[region] .. "<br/>"
		end
	end

	output = output
	return output
end

return p