Interested Article - NumberOf
- 2020-02-15
- 1
Этот модуль оценён как
готовый к использованию
. Предполагается, что все баги устранены и он готов для широкого использования. Его можно указывать на справочных страницах и рекомендовать к использованию новым участникам. Для его изменения и тестирования, пожалуйста,
используйте песочницу
.
|
Модуль используется для отображения и обновления шаблонов {{ NUMBEROF }} и {{ TODAYNUMBEROF }} , использующихся для отображения статистики по другим разделам Википедии. С помощью данного модуля также отображается список Википедий . Страницы с данными для этого модуля, и , обновляются ботом на Викискладе.
Функции и параметры
Доступные функции:
-
Editions
— функция (без параметров) для вывода таблиц с языковыми разделами Википедии, отсортированными по количеству статей (используется на странице Википедия:Список Википедий ). Использует в качестве списка данных (обновляется ботом ежедневно) и страницу Модуль:NumberOf/lang.json для отображения названий языков. -
Now
— функция для вывода наиболее актуальной статистики (используется в шаблоне {{ NUMBEROF }}). Использует (обновляется ботом раз в два часа) в качестве списка данных. -
Today
— функция для вывода статистики по состоянию на начало текущего UTC-дня (используется в шаблоне {{ TODAYNUMBEROF }}). Использует в качестве списка данных.
Параметры, используемые функциями
Now
и
Today
:
-
wiki
— код раздела Википедии ( обязательный параметр ; список кодов доступен в списке разделов Википедии ); -
param
— необходимые данные ( обязательный параметр ):-
articles
— количество статей в разделе, -
admins
— количество администраторов, -
activeusers
— количество активных участников, -
date
— дата обновления данных в модуле, -
depth
— глубина раздела , -
edits
— количество правок в разделе, -
files
— количество файлов, -
pages
— количество страниц, -
pos
— место раздела по количеству статей (см. список Википедий ), -
users
— количество участников.
-
-
fmt
— форматирование числа (принимает любое непустое значение).
Использование
Формат использования:
-
{{#invoke:NumberOf|Editions|single=1}}
-
{{#invoke:NumberOf|Now|wiki=en|param=articles}}
— 6756701 (неформатированное значение) -
{{#invoke:NumberOf|Now|wiki=en|param=articles|fmt=N}}
— 6 756 701 (форматированное значение)
Дату последнего обновления страницы с данными можно узнать с помощью конструкции
{{#invoke:NumberOf|Now|wiki=en|param=date}}
(13 декабря 2023, 19:47 (UTC); параметр
wiki
может содержать любое непустое значение). На страницах с данными дата обновления шаблона представлена в
UNIX-времени
.
Представленные примеры с функцией
Now
работают и с функцией
Today
.
-- Модуль для шаблонов серии 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>', 'Файлов', } 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
- 2020-02-15
- 1