Данный модуль используется для отображения и обновления шаблонов {{NUMBEROF}} и {{TODAYNUMBEROF}}, использующихся для отображения статистики по другим разделам Википедии. Помимо этого, с помощью данного модуля отображается список Википедий. Подстраницы с данными этого модуля периодично обновляются ботом MBHbot-erz.

Функции и параметры

витнемс

Доступные функции:

  • Editions — функция (без параметров) для вывода таблиц с языковыми разделами Википедии, отсортированными по количеству статей (используется на странице Википедия:Список Википедий). Использует страницу Module:NumberOf/today в качестве списка данных (обновляется ботом ежедневно) и страницу Module:NumberOf/lang для отображения названий языков.
  • Now — функция для вывода наиболее актуальной статистики (используется в шаблоне {{NUMBEROF}}). Использует Module:NumberOf/data (обновляется ботом раз в 3 часа) в качестве списка данных.
  • Today — функция для вывода статистики по состоянию на начало текущего UTC-дня (используется в шаблоне {{TODAYNUMBEROF}}). Использует Module:NumberOf/today (обновляется ботом ежедневно) в качестве списка данных.

Параметры, используемые функциями Now и Today:

  • wiki — код раздела Википедии (обязательный параметр; список кодов доступен в списке разделов Википедии);
  • param — необходимые данные (обязательный параметр):
    articles — количество статей в разделе,
    admins — количество администраторов,
    activeusers — количество активных участников,
    date — дата обновления данных в модуле,
    depthглубина раздела,
    edits — количество правок в разделе,
    files — количество файлов,
    pages — количество страниц,
    pos — место раздела по количеству статей (см. список Википедий),
    users — количество участников.
  • fmt — форматирование числа (принимает любое непустое значение).

Использование

витнемс

Формат использования:

  • {{#invoke:NumberOf|Editions}}
  • {{#invoke:NumberOf|Now|wiki=en|param=articles}} — 5970339 (неформатированное значение)
  • {{#invoke:NumberOf|Now|wiki=en|param=articles|fmt=N}} — 5 970 339 (форматированное значение)

Дату последнего обновления страницы с данными можно узнать с помощью конструкции {{#invoke:NumberOf|Now|wiki=en|param=date}} (15 Сундерьковонь 2019, 15:03 (UTC); параметр wiki может содержать любое непустое значение). На страницах с данными дата обновления шаблона представлена в UNIX-времени.

Представленные примеры с функцией Now работают и с функцией Today.


-- Модуль для шаблонов серии NUMBEROF и страницы [[Википедия:Список Википедий]]
local p = {}

-- Важнейшие переменные
local mwlang = mw.getContentLanguage()
local langs = mw.loadData('Module:NumberOf/lang')

-- Разделы Википедии, закрытые от редактирования
local readOnly = {
	aa = true,
	cho = true,
	ho = true,
	hz = true,
	ii = true,
	kj = true,
	kr = true,
	mh = true,
	mo = 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 renderNum(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
		if param == 'date' then
			result = formatDate(info['total']['date'])
			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
			-- Убираем NUMBEROF из легаси-кода параметров
			param = param:lower():gsub('numberof','')
			
			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

-- Функция для вывода в {{NUMBEROF}}
function p.Now(frame)
	local data = mw.loadData('Модуль:NumberOf/data')
	
	return renderNum(frame.args,data)
end

-- Функция для вывода в {{TODAYNUMBEROF}}
function p.Today(frame)
	local data = mw.loadData('Модуль:NumberOf/today')
	
	return renderNum(frame.args,data)
end

-- Вывод ссылки на языковой раздел
local function renderLink(val,text)
	local text = (isEmpty(text) and val or text)
	
	local result = ''
	if val ~= 'ru' then
		result = result .. '[[:' .. val ..  ':|'
		
		if readOnly[val] == true then
			result = result .. '<s style="color:#252525;" title="Данный раздел закрыт и доступен только в режиме для чтения">' .. text .. '</s>'
		else
			result = result .. text
		end
		
		result = result .. ']]'
	else
		result = result .. text
	end
	return result
end

-- Вывод названия языка
local function renderLang(val)
	local text = ''
	if not isEmpty(langs[val]) then
		text = langs[val][1]
	else
		text = mwlang:ucfirst(mw.language.fetchLanguageName(val))
	end
	
	local result
	if not isEmpty(langs[val][2]) then
		result = '[[' .. langs[val][2] .. '|'
	else
		result = '[[:' .. val ..  ':|'
	end
	
	if val == 'ru' then
		result = result .. '<span style="color:#252525; margin-right:4px;">' .. text .. '</span>]]<span class="nomobile">[[File:Mw-unwatch-icon.svg|16px|text-top|alt=★|link=]]</span>'
	else
		if readOnly[val] == true then
			result = result .. '<s style="color:#252525;" title="Данный раздел закрыт и доступен только в режиме для чтения">' .. text .. '</s>'
		else
			result = result .. text
		end
		result = result .. ']]'
	end
	
	return result
end

-- Функция для вывода ячейки
local function createCell(val,style,fmt,stats)
	local result = '|'
	if not isEmpty(fmt) then
		result = result .. 'data-sort-value="' .. val .. '" '
	end
	result = result .. 'style="' .. (not isEmpty(style) and style or 'padding:4px 24px 4px 0;') .. '"| '
	
	if not isEmpty(stats) then
		result = result .. '[[:' .. stats .. '|<span style="color:#252525;">'
	end
	
	result = result .. (not isEmpty(fmt) and mwlang:formatNum(val) or val) .. ' '
	if not isEmpty(stats) then
		result = result .. '</span>]]'
	end
	
	return result
end

-- Функция для вывода ряда таблицы
local function createRow(key,val)
	local result = '|- style="'
	if key == 'ru' then
		result = result .. 'background:#e2fff9; font-weight:bold; '
	end
	result = result .. 'text-align:right; vertical-align:top;"\n'
	
	result = result .. createCell(val['pos'],'font-weight:normal; padding:4px 24px 4px 0;')
					.. '|' .. createCell(renderLink(key),'font-weight:normal; padding:4px 24px 4px 0;')
					.. '|' .. createCell(renderLang(key),'padding:4px 24px 4px 0; text-align:left;')
					.. '|' .. createCell(val['articles'],'',true,key .. ':' .. 'Special:Statistics')
					.. '|' .. createCell(val['pages'],'',true)
					.. '|' .. createCell(val['edits'],'',true)
					.. '|' .. createCell(round(val['depth']),'',true)
					.. '|' .. createCell(val['users'],'',true,key .. ':' .. 'Special:ListUsers')
					.. '|' .. createCell(val['activeusers'],'',true,key .. ':' .. 'Special:ActiveUsers')
					.. '|' .. createCell(val['admins'],'',true,key .. ':' .. 'Special:ListAdmins')
					.. '|' .. createCell(val['files'],'',true)
	
	return result .. '\n'
end

-- Функция для вывода шапки таблицы
local function createHeader()
	local cell = 'padding-bottom:2px; padding-right:24px;'
	local cellLang = 'padding-bottom:2px; text-align:left; min-width:25%;'
	
	local result = '\n{| class="sortable" style="border-collapse:collapse; font-feature-settings:\'tnum\' 1; margin:4px 0 0; width:100%;"\n'
				.. '|- style="border-bottom:1px solid #aaa; text-align:right;"\n'
				.. '!style="' .. cell .. '"| №'
				.. '|' .. createCell('Код',cell)
				.. '|' .. createCell('Язык',cellLang)
				.. '|' .. createCell('Статей',cell)
				.. '|' .. createCell('Страниц',cell)
				.. '|' .. createCell('Правок',cell)
				.. '|' .. createCell('<abbr title="Глубина">Гл.</abbr>',cell)
				.. '|' .. createCell('Участников',cell)
				.. '|' .. createCell('(<abbr title="Активных участников">акт.</abbr>)',cell)
				.. '|' .. createCell('<abbr title="Администраторов">Адм.</abbr>',cell)
				.. '|' .. createCell('Файлов',cell)
	
	return result .. '\n'
end

-- Функция для вывода подвала таблицы
local function createFooter(frame,hide)
	-- Параметр hide отвечает за оптическое выравнивание таблиц
	
	local val = frame['total']
	local cell = 'padding-right:24px; padding-top:2px;'
	local cellHide = 'padding-right:24px; padding-top:2px; visibility:hidden;'
	-- aa — закрытый раздел с самой большой глубиной
	local num = tableLength(frame) - 1
	local depth = (isEmpty(hide) and round(val['depth']) or round(frame['aa']['depth']))
	local result = '\n|- style="border-top:1px solid; font-weight:bold; text-align:right; vertical-align:top;'
				.. (isEmpty(hide) and ' border-top-color:#aaa;' or ' visibility:hidden; border-top-color:transparent;') .. '"'
				.. (isEmpty(hide) and '' or ' class="nomobile"') .. '\n'
				.. '!style="' .. cellHide .. '"| ' .. num
	
	-- zh-classical — самое длинное название раздела
	result = result .. '|' .. createCell('zh-classical',cellHide)
					.. '|' .. createCell('Всего',cell .. ' text-align:left;')
					.. '|' .. createCell(val['articles'],cell,true)
					.. '|' .. createCell(val['pages'],cell,true)
					.. '|' .. createCell(val['edits'],cell,true)
					.. '|' .. createCell(depth,cell,true)
					.. '|' .. createCell(val['users'],cell,true)
					.. '|' .. createCell(val['activeusers'],cell,true)
					.. '|' .. createCell(val['admins'],cell,true)
					.. '|' .. createCell(val['files'],cell,true)
	
	return result
end

-- Функция для вывода в [[Википедия:Список Википедий]]
function p.Editions(frame)
	local data = mw.loadData('Модуль:NumberOf/today')
	
	-- Таблица для сбора разделов по величине
	local s = {
		['1000000'] = {},
		['100000'] = {},
		['10000'] = {},
		['1000'] = {},
		['0'] = {}
	}
	
	-- Значения для проверки
	local checks = {}
	local n = 0
	for k, v in pairs(s) do
		table.insert(checks,n + 1,k)
	end
	table.sort(checks)
	
	-- Сортировка разделов по позиции и величине
	for key, val in pairs(data) do
		local curr = data[key]
		if key ~= 'total' then
			local text = createRow(key,curr)
			for i = #checks, 1, -1 do
				local n = checks[i]
				
				if curr['articles'] / n > 1 or (i == 1 and n == '0') then
					table.insert(s[n],{curr['pos'],text})
					break
				end
			end
		end
	end

	-- Вывод таблицы
	local result = ''
	for i = #checks, 1, -1 do
		local n = checks[i]
		if n == '0' then 
			result = result .. '=== Менее 1000 статей ==='
		else
			result = result .. '=== Более ' .. n .. ' статей ==='
		end
		
		-- Автоматический скролл для недостаточно широких мониторов
		result = result .. '\n<div style="overflow-x:auto;">\n' .. createHeader()

		-- Вывод рядов таблицы
		local function compare(a,b)
			return a[1] < b[1]
		end
		table.sort(s[n],compare)
		for k, v in pairs(s[n]) do
			result = result .. v[2]
		end
		
		-- Вывод подвала таблицы
		if n ~= '0' then
			result = result .. createFooter(data,true)
		else
			result = result .. createFooter(data)
		end
		result = result .. '\n|}\n</div>\n'
	end
	
	return result
end

return p