Jump to content

Module:Geological time

Permanently protected module
From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Hike395 (talk | contribs) at 06:32, 13 December 2021 (add some comments). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

require('Module:No globals')
local getArgs = require('Module:Arguments').getArgs
local hatnoteModule = require('Module:Hatnote')
local hatnote = hatnoteModule._hatnote
local formatLink = hatnoteModule._formatLink
local makeWikitextError = hatnoteModule.makeWikitextError

local p = {}

-- Ordered list of eons, era, periods, etc. The code will search through
-- these lists for a match, then return an appropriate link to the timespans
-- adjacent to those matches
p.eon = {'Hadean', 'Archean', 'Proterozoic', 'Phanerozoic'}
p.era = {'Eoarchean', 'Paleoarchean', 'Mesoarchean', 'Neoarchean',
	'Paleoproterozoic', 'Mesoproterozoic', 'Neoproterozoic',
	'Paleozoic', 'Mesozoic', 'Cenozoic'}
p.period = {'Siderian', 'Rhyacian', 'Orosirian', 'Statherian',
	'Calymmian', 'Ectasian', 'Stenian',
	'Tonian', 'Cryogenian', 'Ediacaran',
	'Cambrian', 'Ordovician', 'Silurian', 'Devonian', 'Carboniferous', 'Permian',
	'Triassic', 'Jurassic', 'Cretaceous', 'Paleogene', 'Neogene', 'Quaternary'}
p.epoch = {'Terreneuvian', 'Cambrian Series 2', 'Miaolingian', 'Furongian',
	'Early Ordovician', 'Middle Ordovician', 'Late Ordovician',
	{main='Llandovery', dab='epoch'}, {main='Wenlock', dab='epoch'},
	{main='Ludlow', dab='epoch'}, {main='Pridoli', dab='epoch'},
	'Early Devonian', 'Middle Devonian', 'Late Devonian',
	{main='Mississippian', dab='(geology)'}, {main='Pennsylvanian',dab='(geology)'},
	'Cisuralian', 'Guadalupian', 'Lopingian',
	'Early Triassic', 'Middle Triassic', 'Late Triassic',
	'Early Jurassic', 'Middle Jurassic', 'Late Jurassic',
	'Early Cretaceous', 'Late Cretaceous',
	'Paleocene', 'Eocene', 'Oligocene',
	'Miocene', 'Pliocene', 'Pleistocene', 'Holocene'}
p.series = {'Furongian',
	'Lower Ordovician', 'Middle Ordovician', 'Upper Ordovician',
	'Llandovery', 'Wenlock', 'Ludlow', 'Pridoli',
	'Lower Devonian', 'Middle Devonian', 'Upper Devonian',
	'Lower Carboniferous', 'Upper Carboniferous',
	'Cisuralian', 'Guadalupian', 'Lopingian',
	'Lower Triassic', 'Middle Triassic', 'Upper Triassic',
	'Lower Jurassic', 'Middle Jurassic', 'Upper Jurassic',
	'Lower Cretaceous', 'Upper Cretaceous','Paleocene'}
p.age = {'Fortunian', 'Cambrian Stage 2', 'Cambrian Stage 3', 'Cambrian Stage 4',
	'Wuliuan', 'Drumian', 'Guzhangian', 'Paibian', 'Jiangshanian', 'Cambrian Stage 10',
	'Tremadocian', 'Floian', 'Dapingian', 'Darriwilian', 'Sandbian', 'Katian', 'Hirnantian',
	'Rhuddanian', 'Aeronian', 'Telychian', 'Sheinwoodian', 'Homerian', 'Gorstian', 'Ludfordian',
	'Lochkovian', 'Pragian', 'Emsian', 'Eifelian', 'Givetian', 'Frasnian', 'Famennian',
	'Tournaisian', 'Viséan', 'Serpukhovian', 'Bashkirian', {main='Moscovian', dab='(Carboniferous)'}, 'Kasimovian', 'Gzhelian',
	'Asselian', 'Sakmarian', 'Artinskian', 'Kungurian', 'Roadian', 'Wordian', 'Capitanian', 'Wuchiapingian', 'Changhsingian',
	'Induan', 'Olenekian', 'Anisian', 'Ladinian', 'Carnian', 'Norian', 'Rhaetian',
	'Hettangian', 'Sinemurian', 'Pliensbachian', 'Toarcian', 'Aalenian', 'Bajocian',
	'Bathonian', 'Callovian', {main='Oxfordian', dab='(stage)'}, 'Kimmeridgian', 'Tithonian',
	'Berriasian','Valanginian','Hauterivian','Barremian','Aptian','Albian',
	'Cenomanian','Turonian','Coniacian','Santonian','Campanian','Maastrichtian',
	'Danian','Selandian','Thanetian','Ypresian','Lutetian','Bartonian','Priabonian','Rupelian','Chattian',
	{main='Aquitanian', dab='(stage)'},'Burdigalian','Langhian','Serravallian','Tortonian','Messinian','Zanclean','Piacenzian',
	'Gelasian',{main='Calabrian', dab='(stage)'},'Calabrian','Late Pleistocene','Greenlandian','Northgrippian','Meghalayan'}

-- Determine whether a query string matches a stored timespan string
-- Arguments:
--   s: query string
--   sub: standard name of timespan
-- Returns:
--   false if there is no match
--   remainder of query string after match, otherwise
local function startsWith(s, sub)
	local sLen = mw.ustring.len(s)
	local subLen = mw.ustring.len(sub)
	if subLen > sLen then
		return false
	end
	if mw.ustring.sub(s:lower(),1,subLen) == sub:lower() then
		return mw.ustring.sub(s,subLen+1) or ""
	end
	return false
end

-- Create list of strings to search corresponding to a standard timespan
-- Some timespans are disambiguated: first search for the dabbed title, then
-- the plain one. Otherwise just search for the standard timespan string
-- Argument:
--   span = value in timespan lists (above)
-- Returns:
--   list of strings to search in query string
local function searchStringList(span)
	if type(span) == "table" then
		return {span.main.." "..span.dab, span.main}
	end
	return {span}
end

local function matchedString(span, suffix)
	if type(span) == "table" then
		if suffix == "" then
			return span.main.." "..span.dab
		end
		return span.main..suffix
	end
	return span..suffix
end

local function find(s)
	for _, list in ipairs({p.age, p.epoch, p.series, p.period, p.era, p.eon}) do
		local listLen = #list
		for i, span in ipairs(list) do
			for _, searchString in ipairs(searchStringList(span)) do
				local suffix = startsWith(s, searchString)
				if suffix then
					local prevSpan = i > 1 and matchedString(list[i-1], suffix)
					local nextSpan = i < listLen and matchedString(list[i+1], suffix)
					return {prev=prevSpan, next=nextSpan}
				end
			end
		end
	end
	return nil		
end

function p._pair(namespace, prevSpan, nextSpan)
	local prevTitle = prevSpan and mw.title.new(prevSpan,namespace)
	local nextTitle = nextSpan and mw.title.new(nextSpan,namespace)
	if not prevTitle and not nextTitle then
		return ""
	end
	prevTitle = prevTitle and prevTitle.exists and prevTitle
	nextTitle = nextTitle and nextTitle.exists and nextTitle
	if not prevTitle and not nextTitle then
		return ""
	end
	local note = "See also the"
	if prevTitle then
		note = note.." preceding "..formatLink{link=prevTitle.fullText}
	end
	if prevTitle and nextTitle then
		note = note.." and the"
	end
	if nextTitle then
		note = note.." succeeding "..formatLink{link=nextTitle.fullText}
	end
	return hatnote(note,{extraclasses="seealso"})
end

function p._seeAlso(args)
	local title = args[1] and mw.title.new(args[1]) or mw.title.getCurrentTitle()
	if not title then
		return makeWikitextError("Title failure in Module:Geological time")
	end
	local basetext = title.baseText
	local namespace = title.namespace
	local adjacent = find(basetext)
	if not adjacent then
		return mw.title.getCurrentTitle().nsText == "Template" and "" or makeWikitextError("Cannot find geological time frame in "..basetext)
	end
	return p._pair(namespace, adjacent.prev, adjacent.next)
end

function p.seeAlso(frame)
	local args = getArgs(frame)
	return p._seeAlso(args)
end

return p