Module:AgesEras
Documentation [edit]
This page is a stub - it only covers the very basics of its subject. More information should be added to make the page informative and useful. If no more information is available, the page should be considered for a merge, redirect, or deletion.
Details: documentation to be written
If you can correct the issue, please edit the page to do so, then remove this notice.
Please see Template:AgesEras for usage information. Use the template rather than invoking the module. Data for this module is imported from Module:AgesEras/list.Details: documentation to be written
If you can correct the issue, please edit the page to do so, then remove this notice.
The above documentation is transcluded from Module:AgesEras/doc.
local p = {}
local list = mw.loadData('Module:AgesEras/list')
local time = mw.language.getContentLanguage()
--note: if multiple ranges match the same age/era, the tag will duplicate, but will have the same name so won't be shown
--note: ages come before eras due to alphabetical sorting, but this could be changed in icon
--caution: pairs/ipairs and direct access are about the only things that will work on loadData tables
local function icon(kind, data, game, matchNum, gameNum)
if not data[1] or not data[2] or not data[3] or data[4] then
return '<span class="error">' ..
'invalid ' .. game .. ' ' .. kind .. ' data in [[Module:AgesEras/list]]' ..
'</span>'
end
local name = data[2]
local desc = data[3]
game = mw.ustring.upper(game)
local prefix
if kind == 'game' then
name = 'NPO'
prefix = '!' .. kind
kind = 'era'
else
prefix = kind
end
--[=[ Use this instead for console debugging:
return '<indicator name="' .. gameNum .. '-' .. mw.ustring.lower(game) .. '-' .. prefix .. '-' .. matchNum .. '-' .. mw.ustring.lower(name) .. '">' ..
'[' .. '[' .. 'File:' .. kind .. ' icon ' .. game .. ' ' .. name .. '.png|30px|' .. desc .. ']]' ..
'</indicator>'
]=]
return mw.getCurrentFrame():extensionTag(
'indicator',
'[' .. '[' .. 'File:' .. kind .. ' icon ' .. game .. ' ' .. name .. '.png|30px|' .. desc .. ']]',
{ name = gameNum .. '-' .. mw.ustring.lower(game) .. '-' .. prefix .. '-' .. matchNum .. '-' .. mw.ustring.lower(name) }
)
end
--Returns { { start, end }, ... }
local function argToTable(arg)
if not arg or mw.text.trim(arg) == '' then return {} end
local parsed = {}
arg = mw.ustring.lower(arg)
local rangeSep = ','
if mw.ustring.find(arg, ';', 1, true) then
rangeSep = ';'
elseif not mw.ustring.find(arg, '-', 1, true) and #mw.text.split(arg, ',', true) == 2 then
--This looks like a single date, don't want to split on comma
rangeSep = '&'
end
dateSep = ' - '
if mw.ustring.find(arg, ' to ', 1, true) then
dateSep = ' to '
end
mw.ustring.gsub(arg, ' until ', dateSep)
local ranges = mw.text.split(arg, rangeSep, true)
local dates
for i, range in ipairs(ranges) do
dates = mw.text.split(mw.text.trim(range), dateSep, true)
if #dates == 1 then
table.insert(dates, 'present')
elseif #dates > 2 then
dates = { 'invalid date range: ' .. range }
else
dates[1] = mw.text.trim(dates[1])
dates[2] = mw.text.trim(dates[2])
if dates[1] == '' then dates[1] = 'unknown' end
if dates[2] == '' then dates[2] = 'unknown' end
if dates[1] == 'present' then dates[1] = 'unknown' end
if dates[1] == 'unknown' then
dates[1] = dates[2]
end
if dates[2] == 'unknown' then
if dates[1] == 'unknown' then
dates = { 'invalid date range: ' .. range }
else
dates[2] = dates[1]
end
end
end
table.insert(parsed, dates)
end
return parsed
end
local function findMatches(itemList, dates)
if not itemList or not itemList[1] then return {} end
local matches = {}
local start = dates[1]
--Note: start can be present if it was unknown and finish is present
if start == 'present' then start = '' end
local finish = dates[2]
if finish == 'present' then finish = '' end
--formatDate works same as #time, U is Unix time
start = time:formatDate('U', start)
finish = time:formatDate('U', finish)
local itemStart, itemFinish, nextItem
for i, item in ipairs(itemList) do
itemStart = time:formatDate('U', item[1])
nextItem = itemList[i + 1]
if nextItem then
nextItem = nextItem[1]
else
nextItem = ''
end
itemFinish = time:formatDate('U', nextItem)
--Note: this won't count being present for only the first or last day
if (start <= itemStart and finish > itemStart) or (start > itemStart and start < itemFinish) then
table.insert(matches, item)
end
end
return matches
end
local function generateCode(dates, game, num)
if #dates == 0 then return '' end
local code = ''
local gameList = list[game]
if not gameList then return '' end
for i, range in ipairs(dates) do
if #range == 1 then
code = code .. '<span class="error">' .. range[1] .. '</span>'
else
if i == 1 and gameList.game then
code = code .. icon('game', gameList.game, game, i, num)
end
for j, ageMatch in ipairs(findMatches(gameList.ages, range)) do
code = code .. icon('age', ageMatch, game, j, num)
end
for k, eraMatch in ipairs(findMatches(gameList.eras, range)) do
code = code .. icon('era', eraMatch, game, k, num)
end
end
end
return code
end
function p.main(frame)
return p.call(frame:getParent().args)
end
function p.call(args)
local code = ''
--Should be in order of branch establishment, this will determine display order.
local games = {
argToTable(args.ns),
argToTable(args.cn),
}
--This is a map to /list keys, must be in same order as above.
local gameCodes = { 'ns', 'cn', }
for i, gameTable in ipairs(games) do
code = code .. generateCode(gameTable, gameCodes[i], i)
end
return code
end
return p