Module:FindYDCportal

--[[

For a given 3- or 4-digit year or decade, find the most specific portal

which actually exists.

Takes one parameter, which must be either a year (e.g. "1879", "1123")

or a decade (e.g. "1940s", "790s").

If a portal is found, return its name without the namespace prefix

(e.g. for "Portal:1980s" return "1980s"); otherwise return an empty string.

If the parameter is missing, empty, or does not fit the required format,

an empty string is returned"

]]

local p = {}

-- This table of existing decade portals is the first check of whether a portal

-- exists for a given decade.

-- If the decade is listed in this table, then a system call is made to verify its existence

-- This approach has two advantages:

-- 1/ It reduces server load by reducing the number of expensive system calls

-- 2/ It avoids creating backlinks to non-existing portals, because a each .exists check

-- generates a backlink

local existingDecadePortals = {

["1920s"] = true,

["1950s"] = true,

["1960s"] = true,

["1970s"] = true,

["1980s"] = true,

["1990s"] = true,

["2000s"] = true,

["2010s"] = true,

["2020s"] = true

}

-- check for the existence of a portal with the given name

-- if it exists, returns the name

-- otherwise returns nil

function doesPortalExist(portalName)

local portalPage = mw.title.new( portalName, "Portal" )

if (portalPage.exists) then

return portalName

end

return nil

end

-- check for the existence of a portal with the name of that year

-- if it exists, returns the year

-- otherwise calls decadeCheck, and returns that result

-- otherwise returns nil

function checkYear(yearParam)

--[[

the year portals have all been deleted, so comment out this section

if doesPortalExist(yearParam) then

return yearParam

end

]]--

-- myDecade = the year, with the last digit stripped

-- e.g. "1694" → "1690"

-- Note that a decade is written as usul=ally written "YYY0s"

local myDecade = mw.ustring.gsub(yearParam, "%d$", "")

return checkDecade(myDecade)

end

-- check for the existence of a portal with the name of that decade

-- if it exists, returns the year

-- otherwise calls decadeCheck, and returns that result

-- otherwise returns nil

function checkDecade(decadeParam)

local mydecade = decadeParam .. "0s"

if (existingDecadePortals[mydecade] == true) then

if doesPortalExist(mydecade) then

return mydecade

end

end

-- We don't have a portal for the decade, so now try the century.

--[[

the century portals have all been deleted, so comment out this section

local myCenturyString = mw.ustring.gsub(decadeParam, "%d$", "")

local myCenturyNum = tonumber(myCenturyString)

local myCenturyNum = tonumber(myCenturyString)

-- increment by one, because we have now conveted e.g. "1870s" to "18"

-- but that's the 19th century

myCenturyNum = myCenturyNum + 1

-- the century portals have all been deleted, so disable the centeury checking

-- return checkCentury(tostring(myCenturyNum))

]]-- return ""

end

-- check for the existence of a portal with the name of that century

-- if it exists, returns the century

-- otherwise returns an empty string

function checkCentury(centuryParam)

local myCenturyString = ordinal_numbers(centuryParam) .. " century"

if doesPortalExist(myCenturyString) then

return myCenturyString

end

return ""

end

-- converts a string number to an string ordinal

-- e.g. 21 → 21st

-- 17 → 17th

-- code copied from https://stackoverflow.com/questions/20694133/how-to-to-add-th-or-rd-to-the-date (license:CC BY-SA 3.0 )

function ordinal_numbers(n)

local ordinal, digit = {"st", "nd", "rd"}, string.sub(n, -1)

if tonumber(digit) > 0 and tonumber(digit) <= 3 and string.sub(n,-2) ~= 11 and string.sub(n,-2) ~= 12 and string.sub(n,-2) ~= 13 then

return n .. ordinal[tonumber(digit)]

else

return n .. "th"

end

end

function trim(s)

return s:match "^%s*(.-)%s*$"

end

function p.findydcportal(frame)

-- Expects one parameter

-- {{{1}}} = a 3- or 4-digit year or deacde

-- e.g. 1916

-- 1504

-- 1630s

-- 920s

local arg1 = frame.args[1]

if arg1 == nil then

return ""

end

arg1 = trim(arg1) -- strip leading and trailing spaces

if (mw.ustring.match(arg1, "^%d%d%d%d?$")) then

-- it's a 3- or 4-digit-year

return checkYear(arg1)

elseif (mw.ustring.match(arg1, "^%d%d%d?0s$")) then

-- it's a 3- or 4-digit decade

-- so strip the trailing "0s"

local decadeArg = mw.ustring.gsub(arg1, "0s$", "")

return checkDecade(decadeArg)

end

-- If we get here, then arg1 was neither a year nor a decade

-- This is going to be a helper template, and diagnostics woud be intrusive

-- So just return an empty string

return ""

end

return p