Модул:List of the verified oldest people

This module has some functions to perform data calculations. It is not used directly from wikitext, but can be used by other lua modules. For age, a structure/table is used with the fields {years = x, days = y}.

Overview редактиране

-- Returns age in years and days. Input is two dates in numeric form as returned from os.time
function ageInYearsAndDays(date2N, date1N)

-- Returns age in years, months and days. Input is two dates in numeric form as returned from os.time
function ageInYearsMonthsAndDays(date2N, date1N)

-- Returns < 0 if ageA < ageB, 0 if ageA == ageB, > 0 if ageA > ageB
function compareAges(ageA, ageB)

-- Returns true if ageA == ageB
function equalAges(ageA, ageB)

-- Returns a date as a sortable string with age in years and days ("x years and y days")
function ageInYearsAndDaysFormat(age)

-- Returns a date as a sortable string with age in years, months and days ("y years, m months and d days")
function ageInYearsMonthsAndDaysFormat(age)

Example редактиране

local ageUtil = require('Module:Age utilities')
local ageInYearsAndDays = ageUtil.ageInYearsAndDays
local ageInYearsAndDaysFormat = ageUtil.ageInYearsAndDaysFormat

function something()
    local age = ageInYearsAndDays(os.time({year = 1997, month = 8, day = 4}), os.time({year = 1875, month = 2, day = 21}))
    return ageInYearsAndDaysFormat(age)
end

require('strict')
local getArgs = require('Module:Arguments').getArgs

local ageUtil = require('Module:Age utilities')
local ageInYearsMonthsAndDays = ageUtil.ageInYearsMonthsAndDays
local ageInYearsMonthsAndDaysFormat = ageUtil.ageInYearsMonthsAndDaysFormat
local compareAges = ageUtil.compareAges
local equalAges = ageUtil.equalAges
local displayMax = 100 -- Display max 100 entries

--local language = mw.language
--local language = mw.getLanguage('no')
local language = mw.getContentLanguage()

local p = {}

-- Returns true if personA is older than personB
local function comparePersons(personA, personB)
	local diffAge = compareAges(personA.age, personB.age)
	if diffAge == 0 then -- Same age, let the person who is born first "win"
		if personA.dateBirth ~= personB.dateBirth then return personA.dateBirth < personB.dateBirth end
	end
	return diffAge > 0
end

local function formatDateIso8061(year, month, day)
	return tostring(year) .. '-' .. string.format('%02d', month) .. '-' .. string.format('%02d', day)
end

local function formatDateSortable(dateN)
	local date = os.date('!*t', dateN)
	local dateIso = formatDateIso8061(date.year, date.month, date.day)
	local result = '<span style="display:none">' .. dateIso .. '</span>'
	-- https://en.wikipedia.org/wiki/Wikipedia:Comparable_Lua_functions_to_wikitext#Date_and_time
	result = result .. '<span style="white-space:nowrap">' .. language:formatDate('j F Y', dateIso) .. '</span>'
	return result
end

-- Expects a table of persons as input.
-- Returns a string with sorted and formatted output (as a sortable table)
function p.displaySortedTable(persons, frame)
	if #persons == 0 then return '' end

	table.sort(persons, comparePersons) -- Sort according to age and birth date

	local aliveColor = '#99FF99'
	local deadColor = '#F9F9F9'
	local result = ''
	local lastAge = nil
	local rank, keyLast = 0, 0
	local numberOfLiving = 0
	local row, rankCell = nil, nil
	local root = mw.html.create()
	for key, person in ipairs(persons) do
		if lastAge == nil or not equalAges(lastAge, person.age) then -- New age: increment rank
			if rankCell ~= nil and key > rank then
				rankCell:attr('rowspan', tostring(key - rank))
			end
			rankCell = nil
			if key > displayMax then break end -- Display max 100 entries
			rank = key
			lastAge = person.age
			row = root:tag('tr')
			rankCell = row:tag('th'):wikitext(tostring(rank) .. '.')
		else
			row = root:tag('tr')
		end
		keyLast = key

		row:tag('td'):wikitext(person.name)
		if not person.dateDeath then -- Not dead
			row:attr('bgcolor', aliveColor)
			numberOfLiving = numberOfLiving + 1
		end
--		row:tag('td'):wikitext(person.sex)
		row:tag('td'):wikitext(formatDateSortable(person.dateBirth))
		if person.dateDeath ~= nil then -- Dead
			row:tag('td'):wikitext(formatDateSortable(person.dateDeath))
		else
			row:tag('td'):wikitext(person.sex == 'F' and 'жива' or 'жив')
		end
		row:tag('td'):wikitext(ageInYearsMonthsAndDaysFormat(person.age))
		row:tag('td'):wikitext(person.nation or '')
	end
	if rankCell ~= nil and keyLast > rank then
		rankCell:attr('rowspan', tostring(keyLast - rank + 1))
	end
	root:allDone()

	local header = frame:preprocess(
		'{{legend2|' .. aliveColor .. "|Живи: '''"
		.. tostring(numberOfLiving)
		.. "'''||border=1px solid #AAAAAA}}"
		.. '<br/>' ..
		'{{legend2|' .. deadColor .. "|Починали: '''"
		.. tostring(keyLast - numberOfLiving) 
		.. "'''||border=1px solid #AAAAAA}}")
		.. '\n' .. [[
{|class="wikitable sortable"
!#
!Име
!Дата на раждане
!Дата на смъртта
!Възраст
!Страна
]]
	return header .. '\n' .. result .. tostring(root) .. '\n|}'
end


-- Input string dateStr is expected on the format "YYYY-MM-DD"
-- Returns a numeric representation of the date or nil
local function decodeDate(dateStr)
	if dateStr == nil or #dateStr < 8 then return nil end
	
	local strings = mw.text.split(dateStr, '-', true)
	if strings == nil or #strings ~= 3 then return nil end
	
	local date = {}
	date.year = tonumber(strings[1]) or 0
	date.month = tonumber(strings[2]) or 1
	date.day = tonumber(strings[3]) or 1
	return os.time(date);
end

--[[ Input is expected as a table of arguments.
	Expects a semi colon seperated entry for each person on the format:
		"Name etc ; Sex ; Date of birth ; Date of death ; References etc"
			Name and DoB are mandatory, DoD and reference are optional.
			Dates should be in the format "YYYY-MM-DD". ]]
-- Returns a table with the persons
local function decodeArgs(args)
	local dateNow = os.time()
	local persons = {}
	
	for name, value in pairs(args) do
		local strings = mw.text.split(value, ';', true)
		if strings ~= nil and #strings >= 2 then -- Need at least name and birth date
			local person = {}
			person.name = strings[1] or ''
			person.sex = strings[2] or 'F'
			person.dateBirth = decodeDate(strings[3]) -- Date of birth
			if person.dateBirth ~= nil then
				person.dateDeath = decodeDate(strings[4]) -- Date of death
				person.age = ageInYearsMonthsAndDays(person.dateDeath or dateNow, person.dateBirth)
				person.nation = strings[5] or ''
				-- For templates and/or html codes with semicolon
				for k = 6, #strings do person.nation = person.nation .. ';' .. strings[k] or '' end
				table.insert(persons, person)
			end
		end
	end
	return persons
end

-- Decodes args from a frame and displas list
local function displaySorted_(frameArgs, frame)
	local args = getArgs(frameArgs)
	local persons = decodeArgs(args)
	return p.displaySortedTable(persons, frame) -- Display as a sortable table
end

-- To be used from a template. Uses args from parent to template
function p.displaySorted(frame)
	return displaySorted_(frame:getParent().args, frame)
end

-- To be used directly with #invoke
function p.displaySorted0(frame)
	return displaySorted_(frame.args, frame)
end

return p