Módulo:Avaliação: diferenças entre revisões

Origem: Wikipédia, a enciclopédia livre.
Conteúdo apagado Conteúdo adicionado
Lavapés (Resende) contém "[Resende (Rio de Janeiro)|Resende]]", causando "Erro em Lua em Módulo:Avaliação na linha 264: attempt to index local 'pageTitle' (a nil value)." na Discussão:Lavapés (Resende)
Alguns redirecionamentos têm mais conteúdo além da primeira linha (exemplo), mas o título da página de destino não deverá conter quebras de linha, então é melhor restringir a regex
Linha 259: Linha 259:
if pageTitle.isRedirect then
if pageTitle.isRedirect then
-- Redefine the title to the target page after extracting it from wikicode
-- Redefine the title to the target page after extracting it from wikicode
local text = mw.ustring.match( pageTitle:getContent(), '%[%[(.-)%|', 10 )
local text = mw.ustring.match( pageTitle:getContent(), '^[^\n]-%[%[([^\n]-)%|', 10 )
if not text then
if not text then
text = mw.ustring.match( pageTitle:getContent(), '%[%[(.-)%]%]', 10 )
text = mw.ustring.match( pageTitle:getContent(), '^[^\n]-%[%[([^\n]-)%]%]', 10 )
end
end
pageTitle = mw.title.new( text )
pageTitle = mw.title.new( text )

Revisão das 10h41min de 23 de junho de 2014

Documentação do módulo[ver] [editar] [histórico] [purgar]


Descrição

Este módulo implementa a Predefinição:Marca de projeto.

Ver também

-- Ver também:
-- [[Wikipédia:Avaliação automática]]
-- [[User:Danilo.bot/marcas.py]]
-- [[b:User:Helder.wiki/Tools/AssessmentHelper.js]]

local getArgs = require('Module:Arguments').getArgs
local quality = {}

quality[2] = {
	minBytesRef =  {2000, 'menos de 2000 bytes'},
	minBytesNoRefSection = {8000, 'menos de 8000 bytes e não tem seção de referências'},
	noTemplates = {{'mínimo', 'contexto', 'reciclagem', 'reciclar-sobre'}, 'encontrada predefinição:%s'},
	parMaxBytes = {2500, 'parágrafo muito grande (%d bytes): \'%s...\''},
	links = {10, 'menos de 10 ligações internas'},
	minParagraphs = {5, 'menos de 5 parágrafos'}
}

quality[3] = {
	noTemplates = {{'esboço', 'wikificação', 'revisão', 'revisão-sobre'}, 'encontrada predefinição:%s'},
	needRefSection = {true, 'não tem seção de referências'},
	minBytes = {12000, 'menos de 12000 bytes'},
	links = {30, 'menos de 30 ligações internas'},
	sections = {2, 'menos de 2 seções'},
	refs = {5, 'menos de 5 referências'},
	images = {1, 'não tem imagem'},
	allSecRef = {true, 'não encontrada referência na seção \'%s\''}
}

quality[4] = {
	noTemplates = {{'artigo com problemas', 'artigo longo', 'artigo sobre direito com problemas', 'bsre', 'coi', 'caracteres não-padrão',
		'conflito interwiki', 'contextualizar2', 'conteúdo parcial', 'controverso', 'corrigir', 'ctx2', 'curiosidades', 'direitos-autorais',
		'disputa-bpv', 'divisão', 'em tradução', 'expandir', 'expandir2', 'fusão', 'fusão com', 'fusão de', 'fusão vot', 'global',
		'global/brasil', 'global/lusofonia', 'global/portugal', 'hanzi', 'idioma estrangeiro', 'matrad', 'mtag', 'multitag', 'má introdução',
		'má tradução', 'não informado', 'não informado n', 'não-enc', 'não-enciclopédico', 'não-enciclopédico2', 'parcial', 'parcialcontroverso',
		'publicidade', 'rec', 'reciclagem', 'reciclar-sobre', 'ren-pag', 'renomear página', 'revisão', 'revisão de tradução', 'revisão-sobre',
		's-fontes-bpv', 'sem cat', 'sem-fontes-bpv', 'sem-fontes-sobre', 'semimagem-arquitetura', 'semimagem-sobre', 'separar', 'suspeito2',
		'tradução de', 'vda2', 'wikificação'}, 'encontrado predefinição:%s'},
	minBytes = {20000, 'menos de 20000 bytes'},
	links = {50, 'menos de 50 ligações internas'},
	sections = {4, 'menos de 4 seções'},
	refs = {10, 'menos de 10 referências'},
	images = {2, 'só tem uma imagem'}
}

quality[5] = {
	template = {'artigo bom', 'artigo bom'}
}

quality[6] = {
	template = {'artigo destacado', 'artigo destacado'}
}

local refTemplates = {'referências', 'ref-section', 'refsection', 'rodapé referências', 'reflist'}
local refNoTemplates = {'==%s-[Rr]eferências%s-=='}
local imageTemplates = {'imagem dupla'}
local fileNsAliases = {'ficheiro', 'imagem', 'image', 'file', 'arquivo'}
local otherImages = {'{{.-[Ii]magem *=.-%.%a%a%a%a?'}
local exceptions = {'Referências', 'Ver também', 'Notas', 'Notas e referências','Discografia','Galeria de imagens',
	'Referências gerais', 'Leitura adicional', 'Subdivisões', 'Leitura recomendada', 'Ligações externas', 'Bibliografia'}

local getClassForText = function(text)
	local bytes = #text
	local hasRefSection = false
	local images = 0
	local tList = {}
	local paragraphs = 0
	local lang = mw.language.getContentLanguage()

	local hasitem = function(tbl, item)
		for i = 1, #tbl do
			if tbl[i] == item then
				return true
			end
		end

		return false
	end

	local count = function(txt, pattern)
		local c = 0

		for i in mw.ustring.gmatch(txt, pattern) do
			c = c + 1
		end

		return c
	end

	if bytes < quality[2].minBytesRef[1] then
		return {1, quality[2].minBytesRef[2]}         -- Q1: Artigo é muito pequeno; Article is too small
	end

	-- Verificando as predefinições; Checking the templates
	for t in mw.ustring.gmatch(text, '{{ *([^|}\n]+)[ \n]*[|}]') do
		t = lang:lcfirst(t)

		if t == quality[6].template[1] then
			return {6, quality[6].template[2]}    -- Q6: Artigo destacado; Featured article
		elseif t == quality[5].template[1] then
			return {5, quality[5].template[1]}    -- Q5: Artigo bom; Good article
		elseif not hasRefSection and hasitem(refTemplates, t) then
			hasRefSection = true
		elseif hasitem(imageTemplates, t) then
			--FIXME: Imagem dupla deve contar como uma única imagem?
			images = images + 1
		elseif hasitem(quality[2].noTemplates[1], t) then
			noTemplate = {1, mw.ustring.format(quality[2].noTemplates[2], t)}  -- Q1: Predefinição proibida para Q2; Template proibited for Q2
		elseif hasitem(quality[3].noTemplates[1], t) then
			noTemplate = {2, mw.ustring.format(quality[3].noTemplates[2], t)}  -- Q2: Predefinição proibida para Q3; Template proibited for Q3
		elseif hasitem(quality[4].noTemplates[1], t) then
			noTemplate = {3, mw.ustring.format(quality[4].noTemplates[2], t)}  -- Q3: Predefinição proibida para Q4; Template proibited for Q4
		end
		if not hasitem(tList, t) then
			table.insert(tList, t)
		end
	end
	-- Verificando referências fora de predefinição; Checking referências outside templates
	if not hasRefSection then
		local n = 0

		for i = 1, #refNoTemplates do
			text, n = mw.ustring.gsub(text, refNoTemplates[i], '')

			if n > 0 then
				hasRefSection = true
			end
		end
	end

	if not hasRefSection and bytes < quality[2].minBytesNoRefSection[1] then
		return {1, quality[2].minBytesNoRefSection[2]}       -- Q1: Artigo pequeno sem referências; Small article without references
	end

	-- Removendo e contando notas de rodapé; Removing and counting citations
	-- FIXME: "refs" deveria ser 1 (não 2) quando text='A<ref>B</ref>C<ref>B</ref>D'
	local textNoRef, refs1, refs2, refs
	textNoRef, refs1 = mw.ustring.gsub(text, '<[Rr][Ee][Ff]>.-</[Rr][Ee][Ff]>', '')
	textNoRef, refs2 = mw.ustring.gsub(textNoRef, '<[Rr][Ee][Ff] [^>]-[^/]>.-</[Rr][Ee][Ff]>', '')
	-- FIXME: Guardar a quantidade de nomes (únicos) de refs reutilizados?
	textNoRef = mw.ustring.gsub(textNoRef, '<[Rr][Ee][Ff].-/>', '')
	refs = refs1 + refs2
	-- Paragrafos; Paragraphs
	local paragraph = '\n([^*{\n|[]' .. mw.ustring.rep('[^\n]', 99) .. '+)\n'
	for p in mw.ustring.gmatch( textNoRef, paragraph ) do
		if #p > quality[2].parMaxBytes[1] then
			return {1, mw.ustring.format(quality[2].parMaxBytes[2], #p, mw.ustring.sub(p,1, 25))}  -- Q1: parágrafo muito grande; Too big paragraph
		else
			paragraphs = paragraphs + (mw.ustring.find(p, '%. ') and 1 or 0.5)
		end
	end

	local wikilinks = count(textNoRef, '%[%[[^:\n][^:\n]-%]%]')
	textNoRef = nil

	if wikilinks < quality[2].links[1] then
		return {1, quality[2].links[2]}           -- Q1: Poucas ligações internas; Few internal links
	end

	if paragraphs < quality[2].minParagraphs[1] then
		return {1, quality[2].minParagraphs[2]}   -- Q1: Poucos parágrafos; Few paragraphs
	end

	if noTemplate and noTemplate[1] == 1 then
		return noTemplate
	end

	-- Check if some requirement for Q3 is not satisfied
	if quality[3].needRefSection[1] and not hasRefSection then
		return {2, quality[3].needRefSection[2]}     -- Q2: Não tem seção de referências; There is no references section
	end

	if bytes < quality[3].minBytes[1] then
		return {2, quality[3].minBytes[2]}            -- Q2: Muito pequeno para Q3; Too small for Q3
	end

	if wikilinks < quality[3].links[1] then
		return {2, quality[3].links[2]}           -- Q2: Poucas ligações internas; Few internal links
	end

	local sections = count(text, '\n==[^=}{\n][^=}{\n]-==')
	sections = sections + count(text, '\n===[^=}{\n][^=}{\n]-===') / 5

	if sections < quality[3].sections[1] then
		return {2, quality[3].sections[2]}        -- Q2: Poucas seções; Few sections
	end

	if refs < quality[3].refs[1] then
		return {2, quality[3].refs[2]}            -- Q2: Poucas referências; Few references
	end

	for l in mw.ustring.gmatch(text, '%[%[ *(%a+) *:[^%]\n]-%]%]') do
		if hasitem(fileNsAliases, lang:lc(l)) then
			images = images + 1
		end
	end

	for i = 1, #otherImages do
		images = images + count(text, otherImages[i])
	end

	if images < quality[3].images[1] then
		return {2, quality[3].images[2]}          -- Q2: Sem imagens; No images
	end

	-- Só retorna Q2 depois de todos testes para Q1
	if noTemplate and noTemplate[1] == 2 then
		return noTemplate
	end

	-- Check if some requirement for Q4 is not satisfied
	if bytes < quality[4].minBytes[1] then
		return {3, quality[4].minBytes[2]}            -- Q3: Muito pequeno para Q4; Too small for Q4
	end

	if wikilinks < quality[4].links[1] then
		return {3, quality[4].links[2]}           -- Q3: Poucas ligações internas; Few internal links
	end

	if sections < quality[4].sections[1] then
		return {3, quality[4].sections[2]}        -- Q3: Poucas seções; Few sections
	end
	--FIXME: "refs" tem um valor impreciso, como exemplificado acima
	if refs < quality[4].refs[1] then
		return {3, quality[4].refs[2]}            -- Q3: Poucas referências; Few references
	end

	if images < quality[4].images[1] then
		return {3, quality[4].images[2]}          -- Q3: Poucas imagens; Few images
	end

	-- Só retorna Q3 depois de todos testes para Q1 e Q2
	if noTemplate and noTemplate[1] == 3 then
		return noTemplate
	end

	local a, b, s = mw.ustring.find(text, '\n==+ *([^={}\n]-) *==+')
	local a2, b2, s2 = 0, 0, ''

	while quality[3].allSecRef[1] and b do
		local r = mw.ustring.find(text, '<[Rr][Ee][Ff]', b)
		local p = mw.ustring.find(text, '\n[^*\n]' .. mw.ustring.rep('[^\n]', 99) .. '+', b)
		a2, b2, s2 = mw.ustring.find(text, '\n==+ *([^={}\n]-) *==+', b)

		if ( ( a2 and p and r and p < a2 and r > a2 ) or (p and not r) ) and not hasitem(exceptions, s) then
			return {3, mw.ustring.format(quality[3].allSecRef[2], s)}  -- Q3: Existem seções sem referências; There are sections with no citations
		end

		a, b, s = a2, b2, s2

	end

	-- Nada encontrado; Nothing found
	return {4, 'indique para EAD quando o artigo satisfizer os critérios de artigo bom'}
end

local getClassForPage = function ( page )
	local pageTitle = mw.title.new( page )

	if pageTitle.isRedirect then
		-- Redefine the title to the target page after extracting it from wikicode
		local text = mw.ustring.match( pageTitle:getContent(), '^[^\n]-%[%[([^\n]-)%|', 10 )
		if not text then
			text = mw.ustring.match( pageTitle:getContent(), '^[^\n]-%[%[([^\n]-)%]%]', 10 )
		end
		pageTitle = mw.title.new( text )
	end

	return getClassForText( pageTitle:getContent() or '' )
end

-- [[Predefinição:Marca de projeto/projeto]]
local _getBannerRow = function ( args )
	-- local banner = root:tag( 'table' )
	--	:css( 'background', '#F8EABA' )
	local importance = tonumber( args['i'] )
	if importance and ( importance < 1 or 4 < importance ) then
		importance = nil
	end
	local quality = tonumber( args['q'] )
	if quality and ( quality < 1 or 6 < quality ) then
		quality = nil
	end
	local row = mw.html.create( 'tr' )
		:tag( 'td' )
			:addClass( 'tmbox-image' )
			:css( 'border-top', '1px solid #fc8' )
			:css( 'border-bottom', '1px solid #fc8' )
			:css( 'padding', '2px 0px 2px 0.9em' )
			:css( 'text-align', 'center' )
			:wikitext( args['imagem'] )
			:done()
		:tag( 'td' )
			:css( 'border-top', '1px solid #fc8' )
			:css( 'border-bottom', '1px solid #fc8' )
			:css( 'text-align', 'center' )
			:wikitext(
				'[[Imagem:Escala-laranja-' ..
				( importance and ( importance .. 'de4' ) or 'PA' ) ..
				'.svg]]'
			)
			:done()
	local textCell = row:tag( 'td' )
		:addClass( 'tmbox-text' )
		:css( 'border-top', '1px solid #fc8' )
		:css( 'border-bottom', '1px solid #fc8' )
		:css( 'padding', '1em 2px 1em 0.9em' )
		:css( 'width', '100%' )
	if args['texto'] then
		textCell
			:tag( 'p' )
			:wikitext( args['texto'] )
	end
	page = args['página'] or mw.title.getCurrentTitle().subjectPageTitle.prefixedText
	local nsNum = mw.title.new( page ).namespace
	local pageTypes = {
		[102] = 'anexo',
		[100] = 'portal'
	}
	local pageType = pageTypes[nsNum] or 'artigo'
	textCell
		:wikitext(
			'Para o \'\'\'' .. args['link'] .. '\'\'\' este ' .. pageType ..
			' possui \'\'\'[[Predefinição:Escala de importância|importância]] ' ..
			( importance or 'ainda não avaliada' ) ..
			'\'\'\'. Se você se interessa pelo assunto, visite o projeto para conhecer as tarefas e [[Wikipédia Discussão:Projetos/' ..
			( args['discussão'] or mw.language.getContentLanguage():ucfirst( args['sobre'] or '' ) ) ..
			'|discussões]] em curso.'
		)
	local cats = ''
	if mw.title.getCurrentTitle().basePageTitle == 'Marca de projeto' then
		cats = cats .. '[[categoria:!Marcas de wikiprojetos' ..
			( args['sobre'] and ( '|' .. args['sobre'] ) or '' ) .. ']]\n'
	else
		if mw.site.contentNamespaces[nsNum] and args['sobre'] then
			cats = cats .. '[[categoria:!Artigos '
			if not quality then
				cats = cats .. 'de qualidade desconhecida'
			else
				if quality <= 4 then
					cats = cats .. 'de qualidade ' .. quality
				elseif quality == 5 then
					cats = cats .. 'bons'
				elseif quality == 6 then
					cats = cats .. 'destacados'
				end
			end
			cats = cats .. ' sobre ' .. args['sobre'] .. ']]\n'
		end
	end
	cats = cats .. '[[categoria:!Artigos de importância ' ..
		( importance or 'desconhecida' ) .. ' sobre ' .. args['sobre'] .. ']]\n'
	if args['r'] then
		if mw.language.getContentLanguage():formatDate( 'Ymd', '-6 months' ) > ( args['r'] or '99999999' ) then
			cats = cats .. '[[Categoria:!Artigos sobre ' .. args['sobre'] ..
				' por reavaliar|' .. page .. ']]'
		end
	end
	return tostring( row ) .. cats
end

-- [[Predefinição:Marca de projeto]]
local _getBanners = function ( args )
	page = args['página'] or mw.title.getCurrentTitle().subjectPageTitle.prefixedText
	local qualityByUser = args[1] or args['qualidade']
	local qualityByModule = getClassForPage( page )
	local reason = args['motivo'] or 'motivo não informado'
	local lang = mw.language.getContentLanguage()

	if qualityByUser then
		-- Convert to numbers
		if qualityByUser == 'AB' then
			qualityByUser = { 5, reason }
		elseif qualityByUser == 'AD' then
			qualityByUser = { 6, reason }
		else
			qualityByUser = tonumber( qualityByUser )
			if qualityByUser and 1 <= qualityByUser and qualityByUser <= 6 then
				qualityByUser = { qualityByUser, reason }
			else
				qualityByUser = nil
			end
		end
	end

	local quality = qualityByUser or qualityByModule
	local proj = {}
	local importanceForProj = {}
	local pos = 2

	while args[pos] do
		table.insert( proj, args[pos] )
		table.insert( importanceForProj, args[pos+1] or '?' )
		pos = pos + 2
	end

	local dateOfLastestReview = args['rev']
	local root = mw.html.create('')
	local banner = root:tag( 'table' )
		:addClass( 'plainlinks tmbox tmbox-content' )
		:css( 'margin', '4px 10%' )
		:css( 'border-collapse', 'collapse' )
		:css( 'background', '#f8eaba' )
		:css( 'border', '2px solid #f28500' )
		:css( 'width', '80%' )

	if #proj > 2 then
		banner:addClass( 'collapsible collapsed' )
	end

	local firstRow = banner:tag( 'tr' )

	firstRow:tag( 'td' )
		:attr( 'colspan', 2 )
		:addClass( 'tmbox-text' )
		:css( 'border', 'none' )
		:css( 'padding', '0.25em 0.9em' )
		:css( 'text-align', 'right' )
		:css( 'background', 'transparent' )
		:wikitext( '[[Imagem:Escala-azul-' .. quality[1] .. 'de6.svg]]' )

	local qualityCell = firstRow:tag( #proj > 0 and 'th' or 'td' )

	qualityCell:addClass( 'tmbox-text' )
		:css( 'border', 'none' )
		:css( 'padding', '0.25em 0.9em' )
		:css( 'text-align', 'left' )
		:css( 'font-weight', 'normal' )

	local nsNum = mw.title.new( page ).namespace
	local pageTypes = {
		[102] = 'anexo',
		[100] = 'portal'
	}
	local pageType = pageTypes[nsNum] or 'artigo'

	if qualityByUser then
		if quality[1] <= 4 then
			qualityCell
				:wikitext( 'Este ' .. pageType .. ' foi avaliado com ' )
				:tag( 'b' )
					:attr( 'title', quality[2] )
					:wikitext( '[[Wikipédia:Qualidade|qualidade]] ' .. quality[1] )

			if dateOfLastestReview and mw.ustring.len( dateOfLastestReview ) == 8 then
				qualityCell:wikitext( ' em ' .. lang:formatDate( 'd "de" F "de" Y', dateOfLastestReview ) )
			end
		elseif quality[1] == 5 then
			qualityCell
				:wikitext( 'Este ' .. pageType .. ' foi ' )
				:tag( 'b' )
					:wikitext( 'eleito um ' .. pageType .. ' bom' )
		elseif quality[1] == 6 then
			qualityCell
				:wikitext( 'Este ' .. pageType .. ' foi ' )
				:tag( 'b' )
					:wikitext( 'eleito um ' .. pageType .. ' destacado' )
		end
	else
		qualityCell
			:wikitext( 'Este ' .. pageType .. ' foi avaliado [[Wikipédia:Avaliação automática|automaticamente]] com ' )
			:tag( 'b' )
				:attr( 'title', quality[2] )
				:wikitext( '[[Wikipédia:Qualidade|qualidade]] ' .. quality[1] )
	end

	if #proj < 1 then
		qualityCell:wikitext( '.' )
	elseif #proj == 1 then
		qualityCell:wikitext( ' e faz parte do âmbito de um WikiProjeto: ' ..  proj[1] .. '.' )
	else
		qualityCell:wikitext(
			' e faz parte do âmbito de ' .. #proj .. ' WikiProjetos: ' ..
			mw.text.listToText( proj ) .. '.'
		)
	end
	for i = 1, #proj do
		local projBanner = 'Marca de projeto/' .. lang:ucfirst( proj[i] )
		if mw.title.new( 'Template:' .. projBanner ).exists then
			banner:wikitext(
				mw.getCurrentFrame():expandTemplate{
					title = projBanner,
					-- The template uses this for categorization
					args = { quality[1], importanceForProj[i], dateOfLastestReview or '' }
				}
			)
		end
	end

	if #proj > 0 then
		banner:tag( 'tr' )
			:tag( 'td' )
				:attr( 'colspan', 3 )
				:css( 'text-align', 'center' )
				:css( 'font-size', '90%' )
				:wikitext( 'Se não tiver suas questões respondidas nesta página de discussão procure o(s) wikiprojeto(s) acima.' )
	end

	local talkPageTimestamp = mw.getCurrentFrame():callParserFunction{
		name = 'REVISIONTIMESTAMP',
		args = mw.title.new( page ).talkPageTitle.prefixedText
	}

	local cats = ''

	if talkPageTimestamp ~= '' and tonumber( talkPageTimestamp ) < ( tonumber( args['rev'] ) or 20110000000000 ) then
		cats = cats .. '[[Categoria:!Artigos com avaliação revisada]]\n'
	else
		if mw.site.contentNamespaces[nsNum] then
			if not qualityByUser then
				cats = cats .. '[[Categoria:!Artigos com qualidade estimada automaticamente]]\n'
			elseif qualityByUser[1] ~= qualityByModule[1] then
				cats = cats .. '[[Categoria:!Artigos com avaliações conflitantes-' .. qualityByModule[1] .. ']]\n'
			end
		end
	end

	return tostring( root ) .. cats
end

return {
	_getClassForText = getClassForText,
	_getClassForPage = getClassForPage,
	projeto = function( frame )
		local args = getArgs( frame )
		return _getBannerRow( args )
	end,
	marcas = function( frame )
		local args = getArgs( frame )
		return _getBanners( args )
	end,
	qualidade = function( frame )
		local args = getArgs( frame )
		local page = args['página'] or args[1]
		local template = args['predefinição'] or args[2] or 'Qualidade $1 ($2)'

		if page == nil then
			page = mw.title.getCurrentTitle().subjectPageTitle.prefixedText
		end

		local quality = getClassForPage( page )
		local text = mw.ustring.gsub(mw.ustring.gsub(template,'$1', tostring(quality[1])),'$2', quality[2])
		return text
	end
}