Модуль:NumberOf
Документація модуля[перегляд] [редагувати] [історія] [очистити кеш]
Цей модуль позначений як К:реліз, готовий до загального вжитку (26). Він досягнув стадії готовності і вважається, що вільний від помилок і може використовуватись всюди, де знадобиться. Його можна вживати на допоміжних сторінках та інших сторінках Вікіпедії як можливість для навчання новачків. Аби зменшити навантаження на сервери та некоректний показ сторінок, його можна вдосконалювати в рамцях чернеткового тестування, а не з застосуванням спроб і помилок. |
Цей модуль використовується для робити шаблонів {{NUMBEROF}} та {{TODAYNUMBEROF}}, що відображають статистичні дані про інші мовні розділи Вікіпедії. Підсторінки даного модуля періодично оновлюються ботом.
Функція і параметри ред.
Функції:
Editions
— функція (без параметрів) для виводу таблиці з мовними розділами Вікіпедії, відсортованими за кількістю статей. Використовує сторінку commons:Data:Wikipedia_statistics/daily.tab як список даних (оновлюється ботом кожен день) і сторінку Модуль:NumberOf/lang.json для відображення назв мов.Now
— функція для виводу найактуальнішої статистики (застосовується в шаблоні {{NUMBEROF}}). Використовує сторінку commons:Data:Wikipedia_statistics/hourly.tab(оновлюється ботом кожні 2 години) як список даних.Today
— функція для виводу статистики станом на початок UTC-доби (застосовується в шаблоні {{TODAYNUMBEROF}}). Використовує сторінку commons:Data:Wikipedia_statistics/daily.tab (оновлюється ботом кожен день) як список даних.
Параметри, що використовуються функціями Now
і Today
:
wiki
— код розділу Вікіпедії (обов'язковий параметр; список усіх кодів міститься в списку розділів Вікіпедії);param
— необхідні дані (обов'язковий параметр):articles
— кількість статей у розділі,admins
— кількість адміністраторів,activeusers
— кількість активних користувачів,date
— дата оновлення даних у модулі,depth
— глибина розділу,edits
— кількість редагувань у розділі,files
— кількість файлів,pages
— кількість сторінок,pos
— розташування розділу на основі кількості статей (дет. Вікіпедія:Список Вікіпедій),users
— кількість користувачів.
fmt
— форматування числа (будь-яке непусте значення).
Використання ред.
Формат використання:
{{#invoke:NumberOf|Editions}}
{{#invoke:NumberOf|Now|wiki=
— 6816956 (неформатоване значення)en
|param=articles
}}{{#invoke:NumberOf|Now|wiki=
— 6 816 956 (форматоване значення)en
|param=articles
|fmt=N
}}
Дату останнього оновлення сторінки з даними можна дізнатися за допомогою конструкції {{#invoke:NumberOf|Now|wiki=
(26 квітня 2024, 3:47 (UTC); параметр en
|param=date
}}wiki
може містити будь-яке непусте значення). На сторінках з даними дата оновлення шаблона виводиться в UNIX-часі.
Приклади використання функції Now
також працюють і з функцією Today
.
Документація вище включена з Модуль:NumberOf/документація. (ред. | історія) Дописувачі можуть експериментувати на підсторінках пісочниця (створити | дзеркало) та тести (створити) цього шаблону. Будь ласка, додавайте категорії до підсторінки /документація. Підсторінки цієї сторінки. |
-- Модуль для шаблонов серии NUMBEROF и страницы [[Википедия:Список Википедий]]
local p = {}
-- Важнейшие переменные
local mwlang = mw.getContentLanguage()
local langs = {}
local cache = {}
-- Разделы Википедии, закрытые от редактирования
local readOnly = {
ak = true,
aa = true,
cho = true,
ho = true,
hz = true,
ii = true,
kj = true,
kr = true,
na = true,
lrc = true,
mh = true,
mus = true,
ng = true
}
-- Проверка пустоты параметра
local function isEmpty(s)
return s == nil or s == ''
end
-- Округление до сотых
local function round(n)
return math.floor(n * 100) / 100
end
-- Форматирование даты
local function formatDate(val)
return mwlang:formatDate('j xg Y, G:i', val) .. ' (UTC)'
end
-- Длина таблицы
local function tableLength(t)
local count = 0
for _ in pairs(t) do count = count + 1 end
return count
end
-- Вычисление вики по переданному номеру
local function calculatePosition(pos, info)
pos = tonumber(pos)
for key in pairs(info) do
if key ~= 'total' and info[key]['pos'] == pos then
return key
end
end
return ''
end
-- Подгрузка и кэширование табличных данных с Викисклада
local function loadTabData( name )
if cache[ name ] then
return cache[ name ]
end
local tab = mw.ext.data.get( name )
local fields = {}
for index, field in ipairs( tab[ 'schema' ][ 'fields' ] ) do
fields[ index ] = field[ 'name' ]
end
cache[ name ] = {}
for _, row in ipairs( tab[ 'data' ] ) do
local langData = {}
for index, value in ipairs( row ) do
langData[ fields[ index ] ] = value
end
cache[ name ][ langData[ 'lang' ] ] = langData
end
return cache[ name ]
end
-- Рендеринг необходимого параметра из страницы с данными
local function getParam(f, info)
-- Парсинг параметров шаблона
local wiki = f.wiki
local param = f.param
local fmt = f.fmt
-- Если нет обязательных параметров, выводится ноль
local result
if isEmpty(wiki) or isEmpty(param) then
result = 0
else
-- Убираем NUMBEROF из легаси-кода параметров
param = param:lower():gsub('numberof','')
if param == 'date' then
result = formatDate(info['total']['date'])
return result
end
if param == 'pos' and tonumber(wiki) ~= nil then
--
result = calculatePosition(wiki, info)
return result
end
-- Расчёты для общего числа разделов
if wiki == 'total' then
if param == 'all' then
result = tableLength(info) - 1
end
if param == 'active' then
result = tableLength(info) - 1 - tableLength(readOnly)
end
end
local obj = info[wiki]
if obj ~= nil then
if param ~= nil and info[wiki][param] ~= nil then
result = info[wiki][param]
-- Форматируем значение, если задан параметр
if not isEmpty(fmt) and type(result) == 'number' then
if param == 'depth' then
result = math.floor(result * 100) / 100
end
result = mwlang:formatNum(result)
end
end
else
result = 0
end
end
return tostring(result)
end
-- Вывод ссылки на языковой раздел
local function renderLink(val, text)
local text = (isEmpty(text) and val or text)
local result = ''
if val ~= mwlang:getCode() then
result = result .. '[[:' .. val .. ':|'
if readOnly[val] == true then
result = result .. string.format('<s title="Цей розділ закритий і доступний лише для читання">%s</s>', text)
else
result = result .. text
end
result = result .. ']]'
else
result = result .. text
end
return result
end
-- Вывод названия языка
local function renderLang(val, frame)
local text = langs[val] and langs[val][1] or mwlang:ucfirst(mw.language.fetchLanguageName(val))
local link = langs[val] and langs[val][2] or nil
local result = text
if readOnly[val] == true then
result = '<s title="Цей розділ закритий і доступний лише для читання">' .. text .. '</s> (закрито)'
end
if not isEmpty(link) then
result = string.format('[[:%s|%s]]', link, result)
end
if val == mwlang:getCode() then
result = result .. ' [[File:Mw-unwatch-icon.svg|16px|text-top|alt=(поточний розділ)|link=]]'
end
return result
end
-- Функция для вывода ячейки
local function renderNum(val, key, stats)
local text = mwlang:formatNum(val)
if isEmpty(stats) or val == 0 then
return text
end
return string.format(
'[[:%s:%s|%s]]',
key,
stats,
text
)
end
-- Функция для вывода ряда таблицы
local function createRow(key, val, frame)
local result = mw.html.create('tr')
:css('text-align', 'right')
if key == mwlang:getCode() then
result
:css('background', '#d5fdf4')
:css('font-weight', 'bold')
end
result:tag('td')
:wikitext(val['pos'])
result:tag('td')
:wikitext(renderLink(key))
result:tag('td')
:wikitext(renderLang(key, frame))
:css('text-align', 'left')
result:tag('td')
:wikitext(renderNum(val['articles'], key, 'Special:Statistics'))
result:tag('td')
:wikitext(renderNum(val['pages']))
result:tag('td')
:wikitext(renderNum(val['edits']))
result:tag('td')
:wikitext(renderNum(round(val['depth'])))
result:tag('td')
:wikitext(renderNum(val['users'], key, 'Special:ListUsers'))
result:tag('td')
:wikitext(renderNum(val['activeusers'], key, 'Special:ActiveUsers'))
result:tag('td')
:wikitext(renderNum(val['admins'], key, 'Special:ListAdmins'))
result:tag('td')
:wikitext(renderNum(val['files'], key, 'Special:ListFiles'))
return result
end
-- Функция для вывода шапки таблицы
local function createHeader()
local result = mw.html.create('table')
:addClass('wikitable sortable')
:attr('style', 'font-feature-settings:"tnum" 1; margin:0.25em 0; width:100%;')
:css('width', '100%')
:css('margin', '0.25em 0')
result:tag('tr')
local cells = {
'№',
'Код',
'Мова',
'Статей',
'Сторінок',
'<abbr title="Кількість редагувань">Редагув.</abbr>',
'<abbr title="Глибина">Глиб.</abbr>',
'Користувачів',
'<abbr title="Активних користувачів">(акт.)</abbr>',
'<abbr title="Адміністраторів">Адм.</abbr>',
'Файлів',
}
for i, val in ipairs(cells) do
result
:tag('th')
:attr('scope', 'col')
:css('text-align', (val == 'Мова' and 'left' or 'right'))
:css('width', (val == 'Мова' and '25%' or nil))
:wikitext(val)
end
return result
end
-- Функция для вывода подвала таблицы
local function createFooter(frame, hide)
-- Параметр hide отвечает за оптическое выравнивание таблиц
local val = frame['total']
local cellStyle = 'text-align:right;'
local cellStyleHide = 'color:transparent; padding-top:0; padding-bottom:0; white-space:nowrap;'
if hide then
cellStyle = 'padding-top:0; padding-bottom:0;' .. cellStyle
end
-- aa — закрытый раздел с самой большой глубиной
local num = tableLength(frame) - 1
local depth = (hide and round(frame['aa']['depth']) or round(val['depth']))
local result = mw.html.create('tr')
:addClass('sortbottom' .. (hide and ' nomobile' or ''))
:attr('style', (hide and ' line-height:0; visibility:hidden; white-space:nowrap;' or ''))
if hide then
result:attr('aria-hidden', 'true')
end
result:tag('th')
:wikitext(string.format('<span aria-hidden="true">%s</span>', num))
:attr('style', cellStyleHide)
-- zh-classical — самое длинное название раздела
result:tag('th')
:wikitext('<span aria-hidden="true">zh-classical</span>')
:attr('style', cellStyleHide)
result:tag('th')
:attr('scope', 'col')
:wikitext('Разом')
:attr('style', cellStyle)
:css('text-align', 'left')
result:tag('th')
:attr('scope', 'col')
:wikitext(renderNum(val['articles']))
:attr('style', cellStyle)
result:tag('th')
:attr('scope', 'col')
:wikitext(renderNum(val['pages']))
:attr('style', cellStyle)
result:tag('th')
:attr('scope', 'col')
:wikitext(renderNum(val['edits']))
:attr('style', cellStyle)
result:tag('th')
:attr('scope', 'col')
:wikitext(renderNum(depth))
:attr('style', cellStyle)
result:tag('th')
:attr('scope', 'col')
:wikitext(renderNum(val['users']))
:attr('style', cellStyle)
result:tag('th')
:attr('scope', 'col')
:wikitext(renderNum(val['activeusers']))
:attr('style', cellStyle)
result:tag('th')
:attr('scope', 'col')
:wikitext(renderNum(val['admins']))
:attr('style', cellStyle)
result:tag('th')
:attr('scope', 'col')
:wikitext(renderNum(val['files']))
:attr('style', cellStyle)
return result
end
-- Функция для вывода в {{NUMBEROF}}
function p.Now(frame)
local data = loadTabData( "Wikipedia_statistics/hourly.tab" )
return getParam(frame.args, data)
end
-- Функция для вывода в {{TODAYNUMBEROF}}
function p.Today(frame)
local data = loadTabData( "Wikipedia_statistics/daily.tab" )
return getParam(frame.args, data)
end
-- Функция для вывода в [[Википедия:Список Википедий]]
function p.Editions(frame)
langs = mw.loadJsonData( "Модуль:NumberOf/lang.json" )
local data = loadTabData( "Wikipedia_statistics/daily.tab" )
local single = frame.args.single or false
local length = tableLength(data)
local result = ''
-- Таблицы для сбора разделов по величине
local sorted = {
[1000000] = {},
[100000] = {},
[10000] = {},
[1000] = {},
[0] = {}
}
local sortedKeys = { 0, 1000, 10000, 100000, 1000000 }
if single then
sortedKeys = { 0 }
end
-- Заполняем пустыми элементами каждую таблицу
for i = #sortedKeys, 1, -1 do
local n = sortedKeys[i]
for j = 1, length, 1 do
table.insert(sorted[n], false)
end
end
-- Сортировка разделов по позиции и величине
for key, val in pairs(data) do
local curr = data[key]
if single and key ~= 'total' then
sorted[ 0 ][ tonumber( curr[ 'pos' ] ) ] = key
elseif key ~= 'total' then
if curr['articles'] <= 1000 then
sorted[ 0 ][ tonumber( curr[ 'pos' ] ) ] = key
else
for i = #sortedKeys, 2, -1 do
local n = sortedKeys[ i ]
if curr['articles'] / n > 1 then
sorted[ n ][ tonumber( curr[ 'pos' ] ) ] = key
break
end
end
end
end
end
-- Вывод таблицы
for i = #sortedKeys, 1, -1 do
if not single and i ~= #sortedKeys then
result = result .. '\n'
end
local n = sortedKeys[i]
if not single then
if n == 0 then
result = result .. '=== Менше 1000 статей ==='
else
result = result .. string.format('=== Понад %s статей ===', mwlang:formatNum(n))
end
end
-- Автоматический скролл для недостаточно широких мониторов
local section = mw.html.create('div')
:attr('style', 'overflow-x:auto; overflow-y:hidden;')
local sectionTable = createHeader()
-- Вывод рядов таблицы
for _, val in ipairs(sorted[ n ]) do
if val ~= false then
local curr = data[ val ]
sectionTable:node(createRow(val, curr, frame))
end
end
-- Вывод подвала таблицы
sectionTable:node(createFooter(data, (n ~= 0)))
section:node(sectionTable)
result = result .. '\n' .. tostring(section)
end
return result
end
return p