Modul:NumberOf
Bu modul istifadəyə hazır olaraq dəyərləndirilib. Bütün səhvlərin düzəldildiyi və geniş istifadəyə hazır olduğu güman edilir. Modul kömək səhifələrində göstərilə və yeni üzvlərin istifadəsi üçün tövsiyə edilə bilər. Modulu dəyişdirmək və ya sınamaq üçün zəhmət olmasa qaralama səhifəsindən istifadə edin. |
NUMBEROF modulu digər Vikipediya bölmələrində statistik məlumatları göstərmək üçün istifadə edilən {{NUMBEROF}} şablonunda istifadə olunur. Bu modul həmçinin Vikipediya:Bütün Vikipediyaların siyahısında istifadə olunur. Bu modulun məlumat səhifələri olan c:Data:Wikipedia statistics/hourly.tab və c:Data:Wikipedia statistics/daily.tab, mütəmadi olaraq bot tərəfindən yenilənir.
-- Модуль для шаблонов серии 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="Bu bölmə bağlıdır və yalnız oxu rejimində mövcuddur">%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="Bu bölmə bağlıdır və yalnız oxu rejimində mövcuddur">' .. text .. '</s> (bağlıdır)'
end
if not isEmpty(link) then
result = string.format('[[:%s|%s]]', link, result)
end
if val == mwlang:getCode() then
result = result .. ' [[Fayl:Mw-unwatch-icon.svg|16px|text-top|alt=(Bu bölmə)|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 = {
's/s',
'Kod',
'Dil',
'Məqalələr',
'Səhifələr',
'Redaktələr',
'Dərinlik',
'İstifadəçilər',
'<abbr title="Aktiv istifadəçilər">Aktiv</abbr>',
'İnzibatçılar',
'Fayllar',
}
for i, val in ipairs(cells) do
result
:tag('th')
:attr('scope', 'col')
:css('text-align', (val == 'Dil' and 'left' or 'right'))
:css('width', (val == 'Dil' 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('Cəmi')
: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( "Modul: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 məqalədən az ==='
else
result = result .. string.format('=== %s məqalədən çox ===', 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