Moduł:Kalendarium
Moduł wspomagający automatyzację treści strony głównej Wikipedii i niektórych portali.
Raport
edytuj
Funkcja do przygotowania podglądu z listą wszystkich dostępnych wydarzeń na zadany dzień.
Pole | Do czego służy? | Jak wypełnić? |
---|---|---|
1 | Data dzienna | Np. 2024-11-3 .
|
Rocznice
edytuj
Funkcja generująca treść do sekcji Rocznice na stronie głównej.
Pole | Do czego służy? | Jak wypełnić? |
---|---|---|
1 | Data dzienna | Np. 2024-11-3 .
|
Imieniny
edytuj
Funkcja generująca listę imion na zadany dzień.
Pole | Do czego służy? | Jak wypełnić? |
---|---|---|
1 | Data dzienna | Np. 2024-11-3 .
|
2 | Liczba losowanych imion | Np. 4 , domyślnie 3.
|
3 | Separator między imionami | Można nie wypełniać, domyślnie przecinek. |
4 | Separator przed ostatnim imieniem | Można nie wypełniać, domyślnie „i”. |
Święta
edytuj
Funkcja generująca listę świąt na zadany dzień.
Pole | Do czego służy? | Jak wypełnić? |
---|---|---|
1 | Data dzienna | Np. 2024-11-3 .
|
2 | Separator między świętami | Najlepiej ;
|
3 | Separator przed ostatnim świętem | Najlepiej ; .
|
Wydarzenia
edytuj
Funkcja generująca listę wydarzeń, których możliwie okrągła rocznica wypada z zadanym dniu.
Pole | Do czego służy? | Jak wypełnić? |
---|---|---|
1 | Data dzienna | Np. 2024-11-3 .
|
2 | Minimalna liczba wydarzeń | domyślnie 5 |
3 | Maksymalna liczba obrazków? (do sprawdzenia) | domyślnie 2. |
4 | Maksymalna liczba wydarzeń | domyślnie minimalna liczba wydarzeń |
Statystyka
edytuj
Funkcja generująca statystykę dla dokumentacji modułu z listą wydarzeń dla konkretnego dnia.
Pole | Do czego służy? | Jak wypełnić? |
---|---|---|
1 | Data dzienna | Np. 2024-11-3 .
|
ministat
edytuj
Funkcja generująca linię z ministatystyką dla wybranego dnia.
Pole | Do czego służy? | Jak wypełnić? |
---|---|---|
1 | Data dzienna | Np. 2024-11-3 .
|
leap
edytuj
Funkcja generująca najbliższy rok przestępny względem podanego roku.
Pole | Do czego służy? | Jak wypełnić? |
---|---|---|
1 | Rok. Jeśli jest przestępny to jest wynikiem funkcji. Jeśli nie jest przestępny to wynikiem jest najbliższy przyszły rok przestępny. | Np. 2024 .
|
Wybierz z listy
edytuj
Implementacja {{Wybierz z listy}}.
Ilustracja na medal
edytuj
Funkcja „losująca” ilustrację na medal używana w przypadku, gdy nie jest zdefiniowana zaplanowana ilustracja na zadany dzień.
Pole | Do czego służy? | Jak wypełnić? |
---|---|---|
1 | Data dzienna | Np. 2024-11-3 .
|
Ilustracje wybierane są z galerii Wikipedia:Ilustracje na Medal. Bardzo płaskie lub wysokie i wąskie obrazy należy oznaczyć komentarzem <-- PANORAMA szerokość_x_wysokość -->
, dzięki któremu pod lub obok ilustracji umieszczany jest pomocniczy pasek przewijania co pozwala na lepszą prezentację. Przykłady można obejrzeć w Wikipedia:Ilustracje na Medal/geografia.
Błędy
edytujBłędy należy zgłaszać na stronie Wikipedia:Kawiarenka/Kwestie techniczne.
Zobacz też
edytujZobacz podstrony tego modułu.
local resources = {
removedFileMatch = "%s?%(%(%-%-%s*(.-)||(.-)%)%)",
fileMatch = "%s?%(%(%s*(.-)||(.-)%)%)",
fileMark = "%s?%(%(%s*.-||.-%)%)",
fileHeight = "^%s*(%d%d?%d?)%s*|(.-)$",
formatAnniversaries = '<div class="floatright" style="width: 102px; line-height: 1.5ex; overflow: hidden;">[[Plik:%2|border|100px|%1]]<small>[[:c:File:%2|%1]]</small></div>',
formatReport = '<div class="floatright" style="width: 60px; line-height: 1.5ex; overflow: hidden;">[[Plik:%2|border|60px|%1]]<small>[[:c:File:%2|%1]]</small></div>',
yearBCmatch = "^(%d%d?%d?%d?) p%.n%.e%.$",
}
local function isLeap(year)
return ((year % 4) == 0) and (((year % 100) ~= 0) or ((year % 400) == 0))
end
local function loadOffsetDay(offset)
if offset < -1 then
return string.format(" %d days", offset)
elseif offset == -1 then
return " -1 day"
elseif offset == 0 then
return ""
elseif offset == 1 then
return " +1 day"
else -- if offset > 1 then
return string.format(" +%d days", offset)
end
end
local function loadFeasts(params)
local lang = mw.getContentLanguage()
local feasts = mw.loadData( 'Module:Kalendarium/święta' )
local date = params.year.."-"..params.base
local romanEaster = false
local orthodoxEaster = false
local result = {}
for _, v in ipairs(feasts) do
if v.type == "fixed" then
local info = v[params.base]
if info then
for _, w in ipairs(info) do
table.insert(result, w)
end
end
elseif v.type == "hebrew" then
local info0 = v[params.hebrew0]
if info0 then
table.insert(result, info0)
end
local info1 = v[params.hebrew1]
if info1 then
table.insert(result, info1)
end
elseif v.type == "islamic" then
local info0 = v[params.islamic0]
if info0 then
table.insert(result, info0)
end
local info1 = v[params.islamic1]
if info1 then
table.insert(result, info1)
end
elseif v.type == "other" then
-- standard fixed date
for _, w in ipairs(v) do
if w == date then
table.insert(result, v.info)
break
end
end
elseif (v.type == "easter") and (params.year >= 326) and (params.year <= 4099) then
local date1 = false
if v.info1 then
if not orthodoxEaster then
orthodoxEaster = require("Moduł:Wielkanoc").Wyznacz({args = { tostring(params.year), metoda = "wschodnia", format="nie", ["dzień"]=0, },})
end
date1 = lang:formatDate("Y-m-d", orthodoxEaster..loadOffsetDay(v.offset)) == date
end
local date2 = false
if v.info2 then
if not romanEaster then
romanEaster = require("Moduł:Wielkanoc").Wyznacz({args = { tostring(params.year), metoda = "zachodnia", format="nie", ["dzień"]=0, },})
end
date2 = lang:formatDate("Y-m-d", romanEaster..loadOffsetDay(v.offset)) == date
end
if date1 and date2 and v.info3 then
table.insert(result, v.info3)
else
if date1 then
table.insert(result, v.info1)
end
if date2 then
table.insert(result, v.info2)
end
end
else
-- type not supported
end
end
return #result > 0 and mw.text.listToText(result, params.feastSeparator, params.feastConjunction) or ""
end
local function prepareDataIndex(data, except)
-- prepare set of excluded values
local exceptions = {}
for _, v in ipairs(except or {}) do
exceptions[v] = true
end
local result = {}
for i, _ in ipairs(data or {}) do
if not exceptions[i] then
table.insert(result, i)
end
end
return result
end
local function selectRandomItems(index, count)
if #index <= count then
return index
end
local result = {}
while count > 0 do
local i = math.random(1, #index)
table.insert(result, index[i])
table.remove(index, i)
count = count - 1
end
return result
end
local function selectRandomData(data, count, except)
-- prepare source index
local fullIndex = prepareDataIndex(data, except)
local index = selectRandomItems(fullIndex, count)
table.sort(index)
-- prepare result
local result = {}
for _, i in ipairs(index) do
table.insert(result, data[i])
end
return result
end
local function loadDate(date)
local lang = mw.getContentLanguage()
-- minimize usage of #time function due to 6000 limit of output characters
local stamp = lang:formatDate("U", date, true)
local ymd = lang:formatDate("Ymd", date or ("@"..stamp), true)
local year = tonumber(string.sub(ymd, 1, 4))
return {
date = date,
seed = tonumber(stamp) + year, -- better seed
year = year,
base = string.sub(ymd, 5, 6).."-"..string.sub(ymd, 7, 8),
hebrew0 = lang:formatDate("xjn-xjj", date, true),
hebrew1 = lang:formatDate("xjn+xjj", date.." +1 day", true),
islamic0 = lang:formatDate("xmn+xmj", date, true),
islamic1 = lang:formatDate("xmn-xmj", date.." +1 day", true),
}
end
local function chooseNames(params)
local data = mw.loadData("Module:Kalendarium/imieniny")
math.randomseed(params.seed)
local result = {}
for _, v in ipairs(data[params.base].zawsze or {}) do
table.insert(result, v)
end
local count = params.namesCount - #result
for _, v in ipairs(count <= 0 and {} or selectRandomData(data[params.base], count)) do
table.insert(result, v)
end
if #result > 1 then
local sort = function(a,b)
local lang = mw.getContentLanguage()
return lang:caseFold(a or "") < lang:caseFold(b or "")
end
table.sort(result, sort)
end
return mw.text.listToText(result, params.namesSeparator, params.namesConjunction)
end
local function loadYear(year)
if type(year) == "number" then
return ((year > 0) and (year <= 9999)) and year or false
elseif type(year) ~= "string" then
return false
end
local yearpne = string.match(year, resources.yearBCmatch)
if not yearpne then
return false
end
return 1-tonumber(yearpne)
end
local function loadEvents(events, data, accept, maximumFiles, maximumEvents, fileFormat)
-- extract events that satisfy the selection rule
local files = {}
local candidates = {}
for _, v in ipairs(data) do
local event = {}
event.year = loadYear(v.rok)
event.priority = v.priorytet
event.alone = v.oddzielny or false
event.files = {}
if event.year and v.tekst and accept(event) then
table.insert(candidates, event)
local text = v.tekst
while true do
local info, file = mw.ustring.match(text, resources.fileMatch)
if not file then
event.text = text
break
end
local size = false
local size2, info2 = mw.ustring.match(info, resources.fileHeight)
size2 = tonumber(size2)
if size2 then
size = size2 / 140 -- normalize the scale
info = info2
end
local fileInfo = {
index = #candidates,
info = info,
size = size or 1,
file = file,
}
text = mw.ustring.gsub(text, resources.fileMark, "(**)", 1)
table.insert(files, fileInfo)
table.insert(event.files, fileInfo)
end
end
end
local currentFiles = 0
for _, v in ipairs(events) do
currentFiles = currentFiles + v.size
end
local selected = {}
-- select files for presentation
local usedEventsWithImagesMap = {}
while (#events < maximumEvents) and (currentFiles < maximumFiles) and (#files > 0) do
local i = (#files > 1) and math.random(1, #files) or 1
local f = files[i]
table.remove(files,i)
local space = maximumFiles - currentFiles
if (f.size <= space) or (currentFiles == 0) then
-- use the file
f.used = true
currentFiles = currentFiles + f.size
local event = candidates[f.index]
if not usedEventsWithImagesMap[f.index] then
usedEventsWithImagesMap[f.index] = true
table.insert(events, event)
table.insert(selected, event)
end
-- render the final info and files
f.info = " <small>(''"..f.info.."'')</small>"
f.file = mw.ustring.gsub(f.file, "([^|]+)|([^|]+)|?", fileFormat)
end
end
-- select remaining events for presentation
if #events < maximumEvents then
local index = {}
for i, _ in ipairs(candidates) do
if not usedEventsWithImagesMap[i] then
table.insert(index, i)
end
end
while (#events < maximumEvents) and (#index > 0) do
local i = (#index > 1) and math.random(1, #index) or 1
local e = candidates[index[i]]
table.remove(index, i)
table.insert(events, e)
table.insert(selected, e)
end
end
-- render selected events
for i, v in ipairs(selected) do
local size = 0
local files = {}
for j, f in ipairs(v.files) do
if f.used then
v.text = mw.ustring.gsub(v.text, "%(%*%*%)", f.info, 1)
table.insert(files, f.file)
size = size + f.size
else
v.text = mw.ustring.gsub(v.text, "%(%*%*%)", "", 1)
end
end
v.size = size
if #files > 0 then
v.image = table.concat(files, "")
end
end
return #selected
end
local function compactEvents(events)
local function join(i,j)
if i == j then
-- nothing to compact - simple copy is enough
return events[i]
end
-- split events into merge categories
local bi = {} local bt = {} local bf=0 local bm=0
local di = {} local dt = {} local df=0 local dm=0
local oi = {} local ot = {}
while i <= j do
local text = events[i].text
local ba, b = mw.ustring.match(text, "^urodził(a?) się(.+)$")
local da, d = mw.ustring.match(text, "^zmarł(a?)(.+)$")
if b then
if ba == "a" then bf = bf + 1 else bm = bm + 1 end
table.insert(bi, i)
table.insert(bt, b)
elseif d then
if da == "a" then df = df + 1 else dm = dm + 1 end
table.insert(di, i)
table.insert(dt, d)
else
table.insert(oi, i)
table.insert(ot, text)
end
i = i + 1
end
local images = {}
for _, v in ipairs(bi) do
local image = events[v].image
if image then
table.insert(images, image)
end
end
for _, v in ipairs(di) do
local image = events[v].image
if image then
table.insert(images, image)
end
end
for _, v in ipairs(oi) do
local image = events[v].image
if image then
table.insert(images, image)
end
end
local buffer = {}
if #bt == 1 then
table.insert(buffer, events[bi[1]].text)
elseif #bt > 1 then
local phrase = (bm ~= 0 and "urodzili się: " or "urodziły się: ")..mw.text.listToText(bt, ", ", ", oraz ")
table.insert(buffer, phrase)
end
if #dt == 1 then
table.insert(buffer, events[di[1]].text)
elseif #dt > 1 then
local phrase = (dm ~= 0 and "zmarli: " or "zmarły: ")..mw.text.listToText(dt, ", ", ", oraz ")
table.insert(buffer, phrase)
end
for _, v in ipairs(ot) do
table.insert(buffer, v)
end
return {
year = events[j].year,
text = mw.text.listToText(buffer, "; ", "; tegoż dnia "),
image = #images > 0 and table.concat(images, "") or nil,
}
end
local result = {}
local i0 = false
local lastYear = false
for i, v in ipairs(events) do
if v.alone or v.year ~= lastYear then
if i0 then
table.insert(result, join(i0, i-1))
end
i0 = i
lastYear = not v.alone and v.year
end
end
if i0 then
table.insert(result, join(i0,#events))
end
return result
end
local function expandEmbeddedTemplates(events)
local frame = mw.getCurrentFrame()
local function expand(substring)
return mw.getCurrentFrame():preprocess(substring)
end
for i, v in ipairs(events) do
v.text = mw.ustring.gsub(v.text, "{{.-}}", expand)
end
end
local function chooseEvents(params)
local data = {}
for _, v in ipairs(mw.loadData( 'Module:Kalendarium/'..params.base )) do
local event = {
rok = v.rok,
oddzielny = v.oddzielny,
priorytet = v.priorytet,
}
if v.tekst then
event.tekst = mw.ustring.gsub(v.tekst, resources.removedFileMatch, "")
end
table.insert(data, event)
end
math.randomseed(params.seed)
local events = {}
local count10 = loadEvents(events, data, function(event) local delta = params.year - event.year return (delta > 0) and ((delta % 10) == 0) and event.priority end, params.maximumImages, params.maximumEvents, params.format)
local count5 = loadEvents(events, data, function(event) local delta = params.year - event.year return (delta > 0) and ((delta % 10) == 5) and event.priority end, params.maximumImages, params.maximumEvents, params.format)
local count1 = 0
if #events < params.minimumEvents then
count10 = count10 + loadEvents(events, data, function(event) local delta = params.year - event.year return (delta > 0) and ((delta % 10) == 0) and not event.priority end, params.maximumImages, params.maximumEvents, params.format)
end
if #events < params.minimumEvents then
count5 = count5 + loadEvents(events, data, function(event) local delta = params.year - event.year return (delta > 0) and ((delta % 10) == 5) and not event.priority end, params.maximumImages, params.maximumEvents, params.format)
end
if #events < params.minimumEvents then
count1 = loadEvents(events, data, function(event) local delta = params.year - event.year return (delta > 0) and ((delta % 5) ~= 0) end, params.maximumImages, params.maximumEvents, params.format)
end
local info = "Wybrane rocznice:"
if count1 > 0 then
elseif count5 > 0 then
info = "Okrągłe, pięcioletnie rocznice:"
elseif count10 > 0 then
info = "Okrągłe, dziesięcioletnie rocznice:"
end
-- sort events by year, move "alone" events to first position
table.sort(events, function(a,b) return (a and (a.year+(a.alone and 0 or 0.5)) or 0) < (b and (b.year+(b.alone and 0 or 0.5)) or 0) end)
local events = compactEvents(events)
expandEmbeddedTemplates(events)
-- convert years to text
for _, v in ipairs(events) do
v.year = v.year > 0 and tostring(v.year) or tostring(1-v.year).." p.n.e."
end
-- format output
local result = {}
if #events > 0 then
-- print header
table.insert(result, info)
-- print images
for i, v in ipairs(events) do
if v.image then
table.insert(result,"\n")
table.insert(result,v.image)
end
end
-- print events
local lastYear = nil
for i, v in ipairs(events) do
table.insert(result, "\n* ")
if v.year ~= lastYear then
table.insert(result, "[[")
end
table.insert(result, v.year)
if v.year ~= lastYear then
table.insert(result, "]]")
end
table.insert(result, " – ")
table.insert(result, v.text)
lastYear = v.year
end
end
return table.concat(result, "")
end
local function anniversaries(params)
params.namesSeparator = ", "
params.namesConjunction = " i "
params.feastSeparator = "; "
params.feastConjunction = "; "
-- format output
local result = {}
table.insert(result, "'''[[")
table.insert(result, mw.getContentLanguage():formatDate("j xg", params.year.."-"..params.base, true))
table.insert(result, "]]''': [[imieniny]] obchodzą m.in.: ")
table.insert(result, chooseNames(params))
local feasts = loadFeasts(params)
if #feasts > 0 then
table.insert(result, params.feastSeparator)
table.insert(result, feasts)
end
local events = chooseEvents(params)
if #events > 0 then
table.insert(result, "<br/>")
table.insert(result, events)
end
table.insert(result, "<br style=\"clear:right;\" />")
return table.concat(result, "")
end
local function statistics(params)
local success, data = pcall(mw.loadData, 'Module:Kalendarium/'..params.base)
if not success then
data = {}
end
local stats =
{
[0] = { count = 0, text = 0, images = 0 },
[1] = { count = 0, text = 0, images = 0 },
[2] = { count = 0, text = 0, images = 0 },
[3] = { count = 0, text = 0, images = 0 },
[4] = { count = 0, text = 0, images = 0 },
[5] = { count = 0, text = 0, images = 0 },
}
for _, v in ipairs(data) do
local year = loadYear(v.rok)
local stat = stats[year and (((year - params.year) % 5) + 1) or 0]
local text, count = mw.ustring.gsub(v.tekst, "%(%(.-%)%)", "")
text = mw.ustring.gsub(text, "{{.-}}", "")
stat.count = stat.count + 1
stat.text = stat.text + mw.ustring.len(text)
stat.images = stat.images + count
end
local years = {
params.year,
params.year + 1,
params.year + 2,
params.year + 3,
params.year + 4,
}
if params.base == "02-29" then
for i = 0, 4 do
local baseYear = params.year
while not isLeap(baseYear) or (((baseYear - params.year) % 5) ~= i) do
baseYear = baseYear + 1
end
years[i + 1] = baseYear
end
end
local infos = {}
local lang = mw.getContentLanguage()
for i, v in ipairs(stats) do
local year = tostring(years[i])
local hint = string.format(params.statisticsHint, year % 5, 5 + (year % 5))
local count = params.statisticsCount and string.format(lang:convertPlural(v.count, params.statisticsCount), v.count) or tostring(v.count)
local text = params.statisticsSize and string.format(lang:convertPlural(v.text, params.statisticsSize), v.text) or tostring(v.text)
local images = params.statisticsFile and string.format(lang:convertPlural(v.images, params.statisticsFile), v.images) or tostring(v.images)
local status = v.count < params.minimumEvents and params.statisticsNotReady or v.images <= 0 and params.statisticsNoFiles or v.count <= params.maximumEvents and params.statisticsMinimum or params.statisticsReady
local info = string.format(params.statisticsFormat, year, hint, count, images, text, status)
table.insert(infos, { year, info })
end
table.sort(infos, function(a,b) return a[1] < b[1] end)
local result = {}
for _, v in ipairs(infos) do
table.insert(result, v[2])
end
if stats[0].count > 0 then
local v = stats[0]
local count = params.statisticsCount and string.format(lang:convertPlural(v.count, params.statisticsCount), v.count) or tostring(v.count)
local text = params.statisticsSize and string.format(lang:convertPlural(v.text, params.statisticsSize), v.text) or tostring(v.text)
local images = params.statisticsFile and string.format(lang:convertPlural(v.images, params.statisticsFile), v.images) or tostring(v.images)
local info = string.format(params.statisticsOther, count, images, text)
table.insert(result, info)
end
return table.concat(result, params.statisticsSeparator)
end
function selectFewFromList(params)
if not params.text then
return nil
end
local lines = mw.text.split(params.text, params.splitter, false)
if params.trimPrefix then
if #lines[1] == 0 then
table.remove(lines,1)
elseif #params.trimPrefix > 0 then
lines[1] = mw.ustring.gsub(lines[1], params.trimPrefix, "", 1)
end
end
if (#lines > 1) and params.trimSuffix then
lines[#lines] = mw.ustring.gsub(lines[#lines], params.trimSuffix, "", 1)
end
local i = 1
while i <= #lines do
if params.drop and mw.ustring.match(lines[i], params.drop) then
table.remove(lines, i)
elseif params.accept and not mw.ustring.match(lines[i], params.accept) then
table.remove(lines, i)
else
i = i + 1
end
end
local count = #lines <= params.count and #lines or params.count
if not params.seed then
return params.prefix..table.concat(lines, params.joiner, 1, count)..params.suffix
end
math.randomseed(params.seed)
local result = selectRandomItems(lines, count)
return params.prefix..table.concat(result, params.joiner)..params.suffix
end
return {
["Raport"] = function(frame)
local params = loadDate(frame.args[1])
params.namesCount = 1e10
params.minimumEvents = 1e10
params.maximumImages = 1e10
params.maximumEvents = 1e10
params.format = resources.formatReport
return anniversaries(params)
end,
["Rocznice"] = function(frame)
local params = loadDate(frame.args[1])
params.namesCount = 3
params.minimumEvents = 6
params.maximumImages = 2
params.maximumEvents = 7
params.format = resources.formatAnniversaries
return anniversaries(params)
end,
["Imieniny"] = function(frame)
local params = loadDate(frame.args[1])
params.namesCount = tonumber(frame.args[2]) or 3
params.namesSeparator = frame.args[3]
params.namesConjunction = frame.args[4]
return chooseNames(params)
end,
["Święta"] = function(frame)
local params = loadDate(frame.args[1])
params.feastSeparator = frame.args[2]
params.feastConjunction = frame.args[3]
return loadFeasts(params)
end,
["Wydarzenia"] = function(frame)
local params = loadDate(frame.args[1])
params.minimumEvents = tonumber(frame.args[2]) or 5
params.maximumImages = tonumber(frame.args[3]) or 2
params.maximumEvents = tonumber(frame.args[4]) or params.minimumEvents
params.format = resources.formatAnniversaries
return chooseEvents(params)
end,
["Statystyka"] = function(frame)
local params = loadDate(frame.args[1])
params.minimumEvents = 6
params.maximumEvents = 7
params.statisticsFormat = "\n*'''%s'''%s – %s, %s, %s%s"
params.statisticsOther = "\n*'''INNE''' – %s, %s, %s"
params.statisticsHint = " (<small>lata zakończone na</small> '''%d''' <small>lub</small> '''%d''')"
params.statisticsSeparator = ""
params.statisticsCount = { "%d wydarzenie", "%d wydarzenia", "%d wydarzeń" }
params.statisticsSize = { "%d znak", "%d znaki", "%d znaków" }
params.statisticsFile = { "%d grupa plików", "%d grupy plików", "%d grup plików" }
params.statisticsReady = ""
params.statisticsMinimum = " → wymagane minimum"
params.statisticsNotReady = " → <span style=\"color:red\">WYMAGA UZUPEŁNIENIA</span>"
params.statisticsNoFiles = " → <span style=\"color:blue\">BRAK PLIKÓW</span>"
return statistics(params)
end,
["ministat"] = function(frame)
local params = loadDate(frame.args[1])
params.minimumEvents = 6
params.maximumEvents = 7
params.statisticsFormat = "'''%s'''%s: %s, %s, <small>%s</small> %s"
params.statisticsOther = "'''INNE''': %s, %s, <small>%s</small>"
params.statisticsHint = ""
params.statisticsSeparator = "; "
params.statisticsReady = ""
params.statisticsMinimum = " → <span style=\"color:#2EB82E\">MINI</span>"
params.statisticsNotReady = " → <span style=\"color:red\">UZUPEŁNIĆ</span>"
params.statisticsNoFiles = " → <span style=\"color:blue\">BRAK PLIKÓW</span>"
return statistics(params)
end,
["leap"] = function(frame)
local year = tonumber(frame.args[1])
if not year or ((year % 1) ~= 0) then
return
end
while not isLeap(year) do
year = year + 1
end
return year
end,
["Wybierz z listy"] = function(frame)
local f = frame:getParent()
local params = {}
params.seed = tonumber(f.args.los)
params.count = tonumber(f.args.ile) or 5
params.accept = f.args.akceptuj
params.drop = f.args["odrzuć"]
params.text = f.args[1]
params.splitter = "%s-\n%*%s*"
params.joiner = "\n*"
params.prefix = params.count > 1 and "*" or ""
params.suffix = ""
params.trimPrefix = "^%*%s*"
params.trimSuffix = "%s+$"
return selectFewFromList(params)
end,
["Ilustracja na medal"] = function (frame)
local function PrepareDisplayQueue(sources)
local buffer = {}
for _, v in ipairs(sources) do
table.insert(buffer, v)
end
table.sort(buffer, function(a,b) return a.frequency < b.frequency end)
local result = {}
for _, v in ipairs(buffer) do
local c = v.frequency
local n = c + #result
local d = n/c
local i = 0
while i < c do
local t = math.floor(i*d) + 1
table.insert(result, t, { frequency=v.frequency, index=i, namespace=v.namespace, title=v.title})
i = i + 1
end
end
return result
end
local function LoadGalleries(source)
local sections = mw.text.split(mw.title.makeTitle(source.namespace, source.title):getContent(), "=+[^=]+=+\n")
local result = {}
for i, v in ipairs(sections) do
local gallery = string.match(v, "<gallery.->(.+)</gallery>")
if gallery then
table.insert(result, gallery)
end
end
return result
end
local function LoadFiles(gallery)
local files = mw.text.split(gallery, "\n")
local result = {}
for i, v in ipairs(files) do
local file, description = string.match(v, "^(Plik:.-)|(.+)")
if file then
table.insert(result, { file = file, description = description })
end
end
return result
end
local function ChooseImage(date, sources)
local lang = mw.getContentLanguage()
local timestamp = lang:formatDate("U", date, true)
local daystamp = math.floor(math.abs(timestamp) / 86400) -- seconds per day -> number of days since epoch
local queue = PrepareDisplayQueue(sources)
local sourceIndex = 1 + math.fmod(daystamp, #queue)
local gallerystamp = math.floor(daystamp / #queue) -- number of full periods
local selectedSource = queue[sourceIndex]
mw.log(selectedSource.title.." ("..daystamp..", "..gallerystamp..", "..sourceIndex..")")
local galleries = LoadGalleries(selectedSource)
local sourceDisplays = (gallerystamp * selectedSource.frequency) + selectedSource.index
local galleryIndex = 1 + math.fmod(sourceDisplays, #galleries)
local filestamp = math.floor(sourceDisplays / #galleries) -- number of full periods in selected source
mw.log("frequency: "..selectedSource.frequency..", index: "..selectedSource.index..", displays: "..sourceDisplays..", galleryIndex: "..galleryIndex..", filestamp: "..filestamp)
local files = LoadFiles(galleries[galleryIndex])
local fileIndex = 1 + math.fmod(filestamp, #files)
local filerecord = files[fileIndex]
mw.log(filerecord.file.."|"..filerecord.description.."| ("..galleryIndex..", "..filestamp..", "..fileIndex..")")
local width, height = string.match(filerecord.description, "<!%-%-PANORAMA ([1-9]%d?%d?%d?%d?)x([1-9]%d?%d?%d?%d?)%-%->")
if width then
width = tonumber(width)
height = tonumber(height)
end
local image = false
if width and (height > 0) and (width > (2 * height)) then
image = string.format("<div class=\"thumb\" style=\"width:100%%;margin-left: auto; margin-right:auto;\"><div class=\"thumbinner\"><div style=\"overflow:auto; overflow-y:hidden; overflow-x:auto;\">[[%s|%dpx]]</div></div></div>", filerecord.file, math.floor(250*tonumber(width)/tonumber(height)))
elseif width and ((2 * width) < height) then
image = string.format("<div class=\"thumb\" style=\"width:280px; margin-left: auto; margin-right:auto;\"><div class=\"thumbinner\"><div style=\"height:400px; overflow:auto; overflow-x:hidden; overflow-x:auto;\">[[%s|250px]]</div></div></div>", filerecord.file)
else
image = string.format("[[%s|400x400px]]", filerecord.file)
end
return string.format("<div style=\"text-align:center; clear:both;\">%s<div style=\"margin-top:5px;\">%s<br /></div></div>", image, filerecord.description)
end
local sources = {
{ frequency = 2, namespace = "Wikipedia", title = "Ilustracje na Medal/ubanistyka", },
{ frequency = 6, namespace = "Wikipedia", title = "Ilustracje na Medal/architektura", },
{ frequency = 9, namespace = "Wikipedia", title = "Ilustracje na Medal/architektura/budynki", },
{ frequency = 1, namespace = "Wikipedia", title = "Ilustracje na Medal/sztuka", },
{ frequency = 5, namespace = "Wikipedia", title = "Ilustracje na Medal/technika", },
{ frequency = 4, namespace = "Wikipedia", title = "Ilustracje na Medal/geografia fizyczna", },
{ frequency = 2, namespace = "Wikipedia", title = "Ilustracje na Medal/fizyka i chemia", },
{ frequency = 5, namespace = "Wikipedia", title = "Ilustracje na Medal/biologia", },
{ frequency = 1, namespace = "Wikipedia", title = "Ilustracje na Medal/ludzie", },
{ frequency = 4, namespace = "Wikipedia", title = "Ilustracje na Medal/rysunki i animacje", },
{ frequency = 1, namespace = "Wikipedia", title = "Ilustracje na Medal/inne ilustracje", }
}
local status, result = pcall(ChooseImage, frame.args[1], sources)
mw.log("status: "..(status and "SUCCEEDED" or "FAILED")..", result: "..(result or ""))
return status and result or nil
end,
}