Module:POTY
Jump to navigation
Jump to search
Lua
CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules
Usage
{{#invoke:POTY|function_name}}
Code
require('strict')
local p = {}
p.i18n = require('Module:POTY/i18n')
local msg, langModuleInit
local lang, userLang
local messagePrefix = 'com-poty-'
local function initLangModule()
--! From [[:de:Modul:Expr]]; by [[:de:User:PerfektesChaos]];
--! Derivative work: Rillke
if langModuleInit then return end
langModuleInit = true
userLang = mw.getCurrentFrame():callParserFunction('int', 'lang')
lang = mw.language.new(userLang)
msg = function( key, ... )
-- Retrieve localized message string in content language
-- Precondition:
-- key -- string; message ID
-- Postcondition:
-- Return some message string
-- Uses:
-- > messagePrefix
-- > p.i18n
-- > userLang
-- mw.message.new()
local m = mw.message.new( messagePrefix .. key, unpack(arg) )
local r = false
if m:isBlank() then
r = p.i18n[ key ]
-- reverse order, think of $12
if r then
local arglen = #arg
for i = arglen, 1, -1 do
r = r:gsub('$' .. tostring(i), arg[i])
end
end
else
m:inLanguage( userLang )
r = m:plain()
end
if not r then
r = '(((Error in [[Module:POTY]]. Message not found: '.. key .. ')))'
end
return r
end -- msg()
local langIsInit = true
end
local function deepmerge(t1, t2)
for k,v in pairs(t2) do
if type(v) == 'table' then
v = deepmerge(t1[k] or {}, v)
end
t1[k] = v
end
return t1
end
local function pad(inp, length, fill)
while #inp < length do
inp = fill .. inp
end
return inp
end
local function zero212(n)
if n == 0 then return 12 end
return n
end
local function getTableKey(t, val)
for i, v in pairs(t) do
if v == val then return i end
end
end
local function getNestedTableKey(t, val)
for k, v in pairs(t) do
local ret = getTableKey(v, val)
if ret then
return k
end
end
end
local function i18nTable(frame, i18nSource, pefix)
local langlist = mw.language.fetchLanguageNames()
local txt1 ='# First, select the language you would like to translate into from the languages-table. Your current choice is <b>{{#language:{{int:lang}}}}</b>.\n'
local txt2 = '# You may use the find-functionality of your browser ({{key press|Ctrl|F}}) for quickly searching your language.\n'
local txt3 = '# Click the appropriate link in the <i>contribute</i>-column of the messages-table.\n'
local ret = txt1 .. txt2 .. txt3 .. '\n<h2>Languages</h2>\n<div class="plainlinks">'
local langcodes = {}
local langtable = {}
local msgtable = {}
for lcode, lname in pairs(langlist) do
table.insert(langcodes, lcode)
end
table.sort(langcodes)
for _, lcode in ipairs(langcodes) do
table.insert(langtable, '[{{fullurl:{{FULLPAGENAME}}|uselang=' .. lcode .. '}} <span style="white-space:nowrap">' .. langlist[lcode] .. '</span>]')
end
for key, val in pairs(i18nSource) do
local msgFull = pefix .. key
local js = key:find('.js/', 1, true)
if js then
table.insert(msgtable, '<tr><td>[[MediaWiki:' .. msgFull .. '/en.js]]</td><td>{{#tag:syntaxhighlight|{{MediaWiki:' .. msgFull .. '/en.js}}|lang=JavaScript}}</td>' ..
'<td>{{#tag:syntaxhighlight|{{MediaWiki:' .. msgFull .. '/' .. userLang .. '.js}}|lang=JavaScript}}</td><td>[{{fullurl:MediaWiki:' .. msgFull .. '/' .. userLang .. '.js|action=edit&preload={{urlencode:MediaWiki:' .. msgFull .. '/en.js|WIKI}}}} Create] • ' ..
'[{{fullurl:MediaWiki talk:' .. msgFull .. '/' .. userLang .. '.js|action=edit§ion=new&preloadtitle=Translation%20edit%20request%20for%20POTY&editintro=Commons:Picture_of_the_Year/mw-message-edit-request&preload={{urlencode:MediaWiki:' .. msgFull .. '/en.js|WIKI}}}} Request edit]</td></tr>')
else
table.insert(msgtable, '<tr><td>[[MediaWiki:' .. msgFull .. ']]</td><td>{{msgnw:MediaWiki:' .. msgFull .. '}}</td>' ..
'<td>{{int:' .. msgFull .. '}}' .. '\n' .. '</td><td>[{{fullurl:MediaWiki:' .. msgFull .. '/' .. userLang .. '|action=edit&preload={{urlencode:MediaWiki:' .. msgFull .. '|WIKI}}}} Create] • ' ..
'[{{fullurl:MediaWiki talk:' .. msgFull .. '/' .. userLang .. '|action=edit§ion=new&preloadtitle=Translation%20edit%20request%20for%20POTY&editintro=Commons:Picture_of_the_Year/mw-message-edit-request&preload={{urlencode:MediaWiki:' .. msgFull .. '|WIKI}}}} Request edit]</td></tr>')
end
end
ret = frame:preprocess(ret .. table.concat(langtable, ' • ') .. '</div>\n' ..
'<h2>Messages</h2>\n<table class="wikitable sortable"><tr><th>Message</th><th>Source code</th><th>In your chosen language</th><th>Contribute</th></tr>' .. table.concat(msgtable, '\n') .. '</table>')
return ret
end
function p.i18nTable(frame)
initLangModule()
local i18n, prefix
if frame.args['misc'] then
i18n = require('Module:POTY/i18n/misc')
prefix = ''
else
i18n = p.i18n
prefix = 'com-poty-'
end
return i18nTable(frame, i18n, prefix)
end
function p.galleryOverview(frame)
initLangModule()
local title = frame:getParent():getTitle()
local titlesplit = mw.text.split(title, '/', true)
local year = titlesplit[2]
local gallerybase = table.concat(titlesplit, '/')
local defaults = require('Module:POTY/config')
local yconfig = require('Module:POTY/config/' .. year)
local parser = require('Module:POTY/parser')
local settings = {}
-- Merge specific into the default settings
deepmerge(settings, defaults)
deepmerge(settings, yconfig)
if not settings.candidateListing or 0 == #settings.candidateListing then
return msg('no-candidate-listing', 'Module:POTY/config/' .. year)
end
local candidates, headings = parser.parse(settings.candidateListing)
local thStyle = 'background:' .. (settings.stateColorTemplate or ('{{POTY' .. year .. '/state/color}}'))
local topicGalleryTable = ''
local topicGalleryMap = {}
local topicGalleryList = {}
local topicGalleryOut = {}
local monthGalleryTable = ''
local monthGalleryTableMap = {}
local allTable = ''
local indexTable = ''
local monthACount = 0
local monthBCount = 0
local h2Style = settings.galleryHeadingStyle .. '; margin-bottom:.22em'
local subHeader = '<tr><td style="' .. (settings.stateColorTemplate3 or ('{{POTY' .. year .. '/state/color3}}')) .. '"> </td></tr>'
local allTableFooter = subHeader:gsub(' ', msg('no-voting-on-these-pages'))
-- Topic table
for i, v in ipairs(headings) do
local tk = getNestedTableKey( settings.groups, v.hId:lower() )
if not tk then
return '<span class="error">Fatal: There is a heading id=<code>' .. v.hId .. '</code> which isn\'t known to [[Module:POTY/config]]. Please make sure it\'s listed under <code>groups=</code>.</span>'
end
if not topicGalleryMap[tk] then
topicGalleryMap[tk] = {}
table.insert( topicGalleryList, tk )
end
table.insert( topicGalleryMap[tk], v )
end
for i, v in ipairs(topicGalleryList) do
local currentTopic = topicGalleryMap[v]
for _, g in ipairs(currentTopic) do
local hId = g.hId:lower()
local f = settings.galleryIcons[hId]
local cat = msg('cat-' .. hId)
local tdG = '<td style="padding:.2em 1em">[[File:' .. (f or '1x1.png') .. '|25px|' .. cat .. '|link=' .. gallerybase .. '/' .. ']] [[' .. gallerybase .. '/' .. g.hId .. '|' .. cat .. ']] (' .. #candidates[g.hId] .. ')</td>'
if v then
table.insert( topicGalleryOut, '<tr><th rowspan="' .. #currentTopic .. '">' .. msg('group-' .. v) .. '</th>' .. tdG .. '</tr>' )
v = nil
else
table.insert( topicGalleryOut, '<tr>' .. tdG .. '</tr>')
end
end
end
topicGalleryTable = '<table style="width:90%" class="wikitable"><tr><th colspan="2" style="' .. thStyle ..
'"><h2 style="' .. h2Style .. '">' .. msg('galleries-by-categories') .. '</h2></th></tr><tr><th style="' .. (settings.stateColorTemplate3 or ('{{POTY' .. year .. '/state/color3}}')) .. '">' .. lang:ucfirst(msg('genre')) .. '</th><th style="' .. (settings.stateColorTemplate3 or ('{{POTY' .. year .. '/state/color3}}')) .. '">' .. lang:ucfirst(msg('categories')) .. '</th></tr>' ..
table.concat(topicGalleryOut, '\n') ..
'<tr><td colspan="2" style="font-size: x-small; ' .. (settings.stateColorTemplate3 or ('{{POTY' .. year .. '/state/color3}}')) .. '">[[' .. (settings.aboutIconPage or 'Special:MyLanguage/Commons:Picture of the Year/' .. year .. '/About Icons') .. '|<span style="' .. (settings.stateColorTemplate3 or ('{{POTY' .. year .. '/state/color3}}')) .. '">' .. msg('about-icons') .. '</span>]]</td></tr>' ..
'</table>'
-- Month table
local candidateList = {}
for hId, group in pairs(candidates) do
for i, file in ipairs(group) do
table.insert( candidateList, file )
end
end
table.sort( candidateList, function(a, b) return (a.fpId or '') < (b.fpId or '') end )
for i = 1, 12, 1 do
local month = pad(tostring(i), 2, '0')
local counter = 0
for x, file in ipairs(candidateList) do
local fpId = year .. '-' .. month
if (file.fpId or ''):find(fpId, 1, true) then
counter = counter + 1
if i < 7 then
monthACount = monthACount + 1
else
monthBCount = monthBCount + 1
end
end
end
local gLink = gallerybase .. '/M' .. pad(tostring(i), 2, '0')
local gDesc = '{{lang|tag=span|{{int:lang}}|{{int:' .. settings.months[i] .. '}}}}'
table.insert( monthGalleryTableMap, '<tr><td style="padding:.2em 1em">' ..
'[[File:' .. settings.monthIcons[i] .. '|25px|' .. gDesc .. '|link=' .. gLink .. ']] [[' .. gLink .. '|'.. gDesc ..']]\t(' .. tostring(counter) .. ')</td></tr>' )
end
monthGalleryTable = '<table style="min-width:70%" class="wikitable"><tr><th style="' .. thStyle ..
'"><h2 style="' .. h2Style .. '">' .. msg('fps-by-month', year) .. '</h2></th></tr>' ..
subHeader ..
table.concat(monthGalleryTableMap, '\n') ..
subHeader ..
'</table>'
allTable = '<table style="min-width:70%" class="wikitable"><tr><th style="' .. thStyle ..
'"><h2 style="' .. h2Style .. '">' .. msg('all-or-half-year', year) .. '</h2></th></tr>' ..
subHeader ..
'<tr><td style="padding:.2em 1em">[[' .. gallerybase .. '/' .. year .. '-A' .. '|' .. msg('from-to', '{{int:' .. settings.months[1] .. '}}', '{{int:' .. settings.months[6] .. '}}', year, tostring(monthACount)) .. ']]</td></tr>' ..
'<tr><td style="padding:.2em 1em">[[' .. gallerybase .. '/' .. year .. '-B' .. '|' .. msg('from-to', '{{int:' .. settings.months[7] .. '}}', '{{int:' .. settings.months[12] .. '}}', year, tostring(monthBCount)) .. ']]</td></tr>' ..
'<tr><td style="padding:.2em 1em">[[' .. gallerybase .. '/ALL' .. '|' .. msg('all-year-fp', year, tostring(monthACount + monthBCount)) .. ']]</td></tr>' ..
allTableFooter ..
'</table>'
return frame:preprocess(
'<div dir="{{#dir:{{int:lang}}}}" lang="{{int:lang}}">' ..
'<div style="float:inline-start; width:65%;">' .. topicGalleryTable .. '</div><div style="float:inline-start; width:33%;">' .. monthGalleryTable .. '</div><div style="float:inline-start; width:33%;">' .. allTable .. '</div>' .. indexTable ..
'</div>'
)
end
function p.iconCredits(frame)
initLangModule()
local defaults = require('Module:POTY/config')
-- note that we don't load year config, icons don't change
local settings = {}
local collection = {}
-- Merge specific into the default settings (no deep-merge!)
deepmerge(settings, defaults)
local galleryIcons = {}
for i, v in pairs(settings.galleryIcons) do
if (not galleryIcons[v]) then
galleryIcons[v] = true
table.insert(collection, '<div style="margin:0.5em">[[File:' .. v .. '|48px]] [[:File:' .. v .. ']]</div>')
end
end
return frame:preprocess(table.concat(collection, ''))
end
local function galleryHeader(gallerybase, headings, candidates, settings, year)
local g = {}
for i, v in ipairs(headings) do
local hId = v.hId:lower()
local f = settings.galleryIcons[hId]
local cat = msg('cat-' .. hId)
table.insert(g, '[[File:' .. (f or '1x1.png') .. '|25px|' .. cat .. '|link=' .. gallerybase .. '/' .. v.hId .. ']] [[' .. gallerybase .. '/' .. v.hId .. '|' .. cat .. ']] (' .. #candidates[v.hId] .. ')')
end
local tableContent = {}
for i = 0, (math.ceil(#headings / 4) - 1), 1 do
local b = 4*i
table.insert(tableContent, (g[b+1] or '') .. '</td><td>' .. (g[b+2] or '') .. '</td><td>' .. (g[b+3] or '') .. '</td><td>' .. (g[b+4] or ''))
end
return '<table class="wikitable" width=100%><tr><th colspan="4" style="background:' ..
(settings.stateColorTemplate or ('{{POTY' .. year .. '/state/color}}')) ..
'">' .. msg('galleries-by-categories') .. '</th></tr><tr><td>' .. table.concat(tableContent, '</td></tr><tr><td>') .. '</td></tr>' ..
'<tr><th colspan="4" style="' .. (settings.stateColorTemplate3 or ('{{POTY' .. year .. '/state/color3}}')) .. '">' .. '[[' .. (settings.helpPage or 'Special:MyLanguage/Commons:Picture of the Year/' .. year .. '/Help') .. '|<span style="' .. (settings.stateColorTemplate3 or ('{{POTY' .. year .. '/state/color3}}')) .. '">' .. lang:ucfirst(msg('help')) .. '</span>]] · [[' .. (settings.aboutIconPage or 'Special:MyLanguage/Commons:Picture of the Year/' .. year .. '/About Icons') .. '|<span style="' .. (settings.stateColorTemplate3 or ('{{POTY' .. year .. '/state/color3}}')) .. '">' .. msg('about-icons') .. '</span>]]' ..
'</th></tr></table>'
end
function p.galleryHeader(frame)
initLangModule()
local newLang = frame.args['lang']
if newLang then userLang = newLang end
local title = frame:getParent():getTitle()
local titlesplit = mw.text.split(title, '/', true)
local year = titlesplit[2]
table.remove(titlesplit)
-- TODO: This must not be hardcoded; use settings instead
local gallerybase = 'Commons:Picture of the Year/' .. year .. '/R1/Gallery'
local defaults = require('Module:POTY/config')
local yconfig = require('Module:POTY/config/' .. year)
local parser = require('Module:POTY/parser')
local settings = {}
-- Merge specific into the default settings (no deep-merge!)
deepmerge(settings, defaults)
deepmerge(settings, yconfig)
if not settings.candidateListing or 0 == #settings.candidateListing then
return msg('no-candidate-listing', 'Module:POTY/config/' .. year)
end
local candidates, headings = parser.parse(settings.candidateListing)
return frame:preprocess( galleryHeader(gallerybase, headings, candidates, settings, year) )
end
function p.cand2cat(frame)
initLangModule()
local title = frame:getParent():getTitle()
local titlesplit = mw.text.split(title, '/', true)
local year = titlesplit[2]
local defaults = require('Module:POTY/config')
local yconfig = require('Module:POTY/config/' .. year)
local parser = require('Module:POTY/parser')
local settings = {}
local candidateList, candidateList2 = {}, {}
-- Merge specific into the default settings (no deep-merge!)
deepmerge(settings, defaults)
deepmerge(settings, yconfig)
if not settings.candidateListing or 0 == #settings.candidateListing then
return msg('no-candidate-listing', 'Module:POTY/config/' .. year)
end
local candidates, headings = parser.parse(settings.candidateListing)
for hId, group in pairs(candidates) do
for i, file in ipairs(group) do
table.insert( candidateList, file.name .. '||' .. hId )
candidateList2[file.name] = hId
end
end
return '<pre>' .. table.concat( candidateList, '\n' ) .. '</pre>\n\n\n<pre style="white-space:pre-wrap">' .. mw.text.jsonEncode(candidateList2) .. '</pre>';
end
function p.gallery(frame)
initLangModule()
local title = frame:getParent():getTitle()
local titlesplit = mw.text.split(title, '/', true)
local year = titlesplit[2]
local galleryname = titlesplit[#titlesplit]
table.remove(titlesplit)
local gallerybase = table.concat(titlesplit, '/')
table.remove(titlesplit)
local roundbase = table.concat(titlesplit, '/')
local defaults = require('Module:POTY/config')
local yconfig = require('Module:POTY/config/' .. year)
local parser = require('Module:POTY/parser')
local settings = {}
local pano = frame.args.pano
-- Merge specific into the default settings (no deep-merge!)
deepmerge(settings, defaults)
deepmerge(settings, yconfig)
if not settings.candidateListing or 0 == #settings.candidateListing then
return msg('no-candidate-listing', 'Module:POTY/config/' .. year)
end
local candidates, headings = parser.parse(settings.candidateListing)
local sets = parser.parseSets(settings.candidateListing .. '/Sets')
local candidates4gallery = candidates[galleryname]
local galleryHeader = (settings.galleryHeaderTemplate or galleryHeader(gallerybase, headings, candidates, settings, year))
local headerTemplate = '__NOEDITSECTION__' .. (settings.headerTemplate or ('{{POTY' .. year .. '|header}}'))
local category = (settings.category or '[[Category:POTY ' .. year .. ']]')
local thumbSizeBar = '<div style="text-align:end"><span class="thumb-size-bar" style="display:none"><span class="thumb-size-text">{{int:com-poty-thumbsize}}</span></span></div>'
local setGalleries = {}
local addCandidate = function(c)
if not sets[c] then return end
local setGalleryContent = {}
for _, f in ipairs(sets[c]) do
table.insert( setGalleryContent, f .. ((f == c) and ('|listed above') or ('|belongs to file set')) )
end
table.insert( setGalleries, '<gallery ' .. (pano and #pano and 'widths=800 heights=175 perrow=1>' or 'widths=300 heights=300>') .. '\n' .. table.concat(setGalleryContent, '\n') .. '\n</gallery>' )
end
local getSetGallery = function()
return ((#setGalleries > 0) and ('<div class="poty-file-sets">\n<h2>' .. msg('file-sets') .. '</h2>\n' .. table.concat(setGalleries, '\n') .. '</div>') or (''))
end
if 'ALL' == galleryname then
local candidateList = {}
for hId, group in pairs(candidates) do
for i, file in ipairs(group) do
table.insert( candidateList, file )
end
end
table.sort( candidateList, function(a, b) return (a.fpId or '') < (b.fpId or '') end )
for i, file in ipairs(candidateList) do
candidateList[i] = file.name .. '|' .. (file.fpId or '<span class="error">Missing fpId!</span>')
end
return frame:preprocess(headerTemplate .. galleryHeader ..
'<div style="text-align:end">' .. msg('total', #candidateList .. ' | ' .. msg('no-voting-on-this-index-page')) .. '</div>' ..
'<gallery mode="packed">' .. '\n' .. table.concat(candidateList, '\n') .. '</gallery>' ..
galleryHeader ..
category)
elseif galleryname:find('%d%d%d%d%-[AB]') then
local candidateList, candidateList2 = {}, {}
local fpIdRegExpA = year .. '%-0[1-6]'
local isA = not not galleryname:find('%d%d%d%d%-A')
local add = isA and 0 or 6
for hId, group in pairs(candidates) do
for i, file in ipairs(group) do
table.insert( candidateList, file )
end
end
table.sort( candidateList, function(a, b) return (a.fpId or '') < (b.fpId or '') end )
for i, file in ipairs(candidateList) do
local matchesA = (file.fpId or ''):find(fpIdRegExpA)
if (matchesA and isA) or (not matchesA and not isA) then
table.insert( candidateList2, file.name .. '|' .. (file.fpId or '<span class="error">Missing fpId!</span>') )
end
end
return frame:preprocess(headerTemplate .. galleryHeader .. '\n' ..
'<h2 style="' .. settings.galleryHeadingStyle .. '" id="poty-gallery-heading"> ' .. msg('from-to-heading', '{{int:' .. settings.months[1+add] .. '}}', '{{int:' .. settings.months[6+add] .. '}}') .. ' </h2>\n' ..
'<div style="text-align:end">' .. msg('total', #candidateList2 .. ' | ' .. msg('no-voting-on-this-index-page')) .. '</div>' ..
'<gallery mode="packed">' .. '\n' .. table.concat(candidateList2, '\n') .. '</gallery>' ..
galleryHeader ..
category)
elseif galleryname:find('M%d%d') then
local candidateList, candidateList2 = {}, {}
local month = galleryname:match('M(%d%d)')
local nMonth = tonumber(month)
local prevMonth = 'M' .. pad(tostring( zero212( nMonth - 1 ) ), 2, '0')
local nextMonth = 'M' .. pad(tostring( zero212( (nMonth + 1) % 12 ) ), 2, '0')
local prevNext = '\n{{previous|' .. gallerybase .. '/' .. prevMonth .. '}}\n{{next|' .. gallerybase .. '/' .. nextMonth .. '}}'
local fpId = year .. '-' .. month
for hId, group in pairs(candidates) do
for i, file in ipairs(group) do
table.insert( candidateList, file )
end
end
table.sort( candidateList, function(a, b) return (a.fpId or '') < (b.fpId or '') end )
for i, file in ipairs(candidateList) do
if (file.fpId or ''):find(fpId, 1, true) then
table.insert(candidateList2, file.name .. '|' .. (file.fpId or '<span class="error">Missing fpId!</span>'))
addCandidate(file.name)
end
end
return frame:preprocess(headerTemplate .. galleryHeader .. prevNext ..
'\n<h2 style="' .. settings.galleryHeadingStyle .. '" id="poty-gallery-heading"> {{int:' .. settings.months[nMonth] .. '}} </h2>\n' ..
thumbSizeBar ..
'<div style="text-align:end">' .. msg('total', #candidateList2) .. '</div>' ..
'<div id="potyEasyVoteEnhanced" style="text-align:center"><gallery widths=300 heights=300>' .. '\n' .. table.concat(candidateList2, '\n') .. '</gallery></div>' ..
getSetGallery() .. prevNext.. galleryHeader ..
category)
else
-- TODO: Randomization?
if not candidates4gallery then
return msg('no-gallery-definition', settings.candidateListing)
end
local strlist = {}
for i, v in ipairs(candidates4gallery) do
table.insert(strlist, v.name .. '|{{' .. (settings.voteButton or ('POTY' .. year .. '/votebutton')) .. '|f=' .. v.name .. '|base=' .. roundbase .. '}}')
addCandidate(v.name)
end
table.insert(strlist, '</gallery></div>')
local desc, gPrev, gNext
for i, v in ipairs(headings) do
if v.hId == galleryname then
desc = v
gPrev = (headings[i-1] or headings[#headings]).hId
gNext = (headings[i+1] or headings[1]).hId
break
end
end
-- Make the header:
local prevNext = '\n{{previous|' .. gallerybase .. '/' .. gPrev .. '}}\n{{next|' .. gallerybase .. '/' .. gNext .. '}}'
local header = headerTemplate ..
prevNext ..
(pano and #pano and '<div id="potyWide"><!-- Make POTY js aware of that. --></div>' or '') ..
'\n<h2 style="' .. settings.galleryHeadingStyle .. '" id="poty-gallery-heading"> ' .. msg('cat-' .. desc.hId:lower()) .. '</h2>\n' ..
thumbSizeBar ..
'<div style="text-align:end">' .. msg('total', #candidates4gallery) .. '</div><div id="potyEasyVoteEnhanced" style="text-align:center">'
local footer = prevNext ..
galleryHeader ..
category
return frame:preprocess(header ..
'<gallery ' .. (pano and #pano and 'widths=800 heights=175 perrow=1>' or 'widths=300 heights=300>') .. '\n' .. table.concat(strlist, '\n') ..
getSetGallery() ..
footer)
end
end
function p.votePage(frame)
initLangModule()
local c = mw.text.decode(frame.args['for'])
local title = frame:preprocess('{{FULLPAGENAME}}')
local titlesplit = mw.text.split(title, '/', true)
local year = titlesplit[2]
local defaults = require('Module:POTY/config')
local yconfig = require('Module:POTY/config/' .. year)
local parser = require('Module:POTY/parser')
local settings = {}
-- Merge specific into the default settings (no deep-merge!)
deepmerge(settings, defaults)
deepmerge(settings, yconfig)
local sets = parser.parseSets(settings.candidateListing .. '/Sets')
if not sets[c] then return '[[File:' .. c .. '|thumb|500x500px|' .. c .. ']]' end
local setGalleryContent = {}
for _, f in ipairs(sets[c]) do
table.insert( setGalleryContent, '|File:' .. f .. '|' .. f .. ((f == c) and (' - listed') or ('- belongs to file set')) )
end
return frame:preprocess('\n<h2>' .. msg('file-sets') .. '</h2>\n{{Imagestack\n|width=500|loop=yes\n' .. table.concat(setGalleryContent, '\n') .. '\n}}')
end
function p.showOneWinner(frame)
local title = frame:preprocess('{{FULLPAGENAME}}')
local titlesplit = mw.text.split(title, '/', true)
local year = frame.args['year'] or titlesplit[2]
local defaults = require('Module:POTY/config')
local yconfig = require('Module:POTY/config/' .. year)
local parser = require('Module:POTY/parser')
local settings = {}
local to = tonumber(frame.args['to'] or 3)
local pattern = frame.args['pattern'] or '[[File:%filename%|350x400px|center|frameless|%caption%|alt=Picture of the Year Winner]]<div style="margin:0,1em,1em,1em; text-align:center">%caption%</div>'
pattern = mw.text.unstrip(pattern)
-- Merge specific into the default settings (no deep-merge!)
deepmerge(settings, defaults)
deepmerge(settings, yconfig)
local winners = parser.parseWinners(settings.winnerListing)
local winnerCount = #winners
if winnerCount == 0 then
return frame:preprocess('winner page [[' .. settings.winnerListing .. ']] could not be parsed')
end
to = math.min(winnerCount, to)
-- now choose a random winner within the range
-- lua has a very convenient function for that
-- but set the seed first
math.randomseed( os.time() )
local winnerIndex = math.random( 1, to )
local winner2show = winners[winnerIndex]
local caption = winner2show.caption:match('{{POTY/caption%|%d%d%d%d%-%d%d%-%d%d}}')
local filename = winner2show.name
return frame:preprocess(pattern:gsub('%%filename%%', filename):gsub('%%caption%%', caption))
end
return p