Modulo:Sandbox/ppong

Versione del 16 giu 2015 alle 21:33 di Rotpunkt (discussione | contributi) (fix coding style, istanza di Monitoraggio => monitoraggio)
require("Modulo:No globals")

-- Tabella di configurazione
--------------------------------------------------------------------------------

local config = {
	-- Inserire solo le occorrenze più insolite: il modulo già rende maiuscolo il nome del progetto
	progetti = { 
		["Acquariofilia"] = "Forme di vita/Pesci/Acquariofilia",
		["anime"] = "Anime e manga",
		["animanga"] = "Anime e manga",
		["Anno"] = "Cronologia/Anno",
		["areeprotette"] = "Aree protette",
		["Armi da fuoco"] = "Guerra/Armi da fuoco",
		["Atletica leggera"] = "Sport/Atletica leggera",
		["Atletica"] = "Sport/Atletica leggera",

		["biologia"] = "Bio",
		["biochimica"] = "Bio",
		["Burma"] = "Birmania",

		["Calcio"] = "Sport/Calcio",
		["cartoni animati"] = "Cartoons",
		["Comuni"] = "Geografia/Antropica/Comuni",

		["Decade"] = "Cronologia/Decade",
		["Dialetti"] = "Dialetti d'Italia",
		["Wikilex"] = "Diritto",
		["minori"] = "Diritti dei minori",
		["disturbipsichici"] = "Disturbi psichici",
		["Documenta ecclesiae"] = "Documenta Ecclesiae",

		["aziende"] = "Economia",
		["Elicotteri"] = "Aviazione/Elicotteri",
		["Emilia"] = "Emilia e Romagna",
		["Romagna"] = "Emilia e Romagna",
		["emilia romagna"] = "Emilia e Romagna",
		["Emilia Romagna"] = "Emilia e Romagna",
		["Emilia-Romagna"] = "Emilia e Romagna",
		["ER"] = "Emilia e Romagna",
		["emilia-romagna"] = "Emilia e Romagna",

		["Fiction tv"] = "Fiction TV",
		["Film Horror"] = "Film horror",
		["horror"] = "Film horror",
		["formedivita"] = "Forme di vita",
		["Formula uno"] = "F1",
		["Formula 1"] = "F1",

		["Guerra elettronica"] = "Guerra/Guerra elettronica",
		["guerrestellari"] = "Guerre stellari",
		["GuerreStellari"] = "Guerre stellari",

		["Controlli automatici"] = "Ingegneria/Controlli automatici",

		["Musica classica"] = "Musica/Classica",
		["classica"] = "Musica/Classica",
		["metal"] = "Musica/Heavy metal",
		["Heavy Metal"] = "Musica/Heavy metal",
		["Heavy metal"] = "Musica/Heavy metal",
		["Hip Hop"] = "Musica/Hip hop",
		["hip hop"] = "Musica/Hip hop",
		["hiphop"] = "Musica/Hip hop",
		["Jazz"] = "Musica/Jazz",
		["Punk"] = "Musica/Punk",
		["Rock"] = "Musica/Rock",

		["Nobel"] = "Premi Nobel",
		["Premi nobel"] = "Premi Nobel",

		["Pallacanestro"] = "Sport/Pallacanestro",
		["Basket"] = "Sport/Pallacanestro",
		["Pk"] = "Fumetti/PK",
		["PK"] = "Fumetti/PK",
		["pokèmon"] = "Pokémon",
		["Pokemon"] = "Pokémon",
		["portorico"] = "Porto Rico",

		["Reggio calabria"] = "Reggio Calabria",
		["Rugby"] = "Sport/Rugby",

		["San marino"] = "San Marino",
		["Scienze della terra"] = "Scienze della Terra",
		["stati africa"] = "Stati",
		["stati america"] = "Stati",
		["stati asia"] = "Stati",
		["stati europa"] = "Stati",
		["stati oceania"] = "Stati",

		["tao"] = "Taoismo",
		["tv"] = "Televisione",
		["TV"] = "Televisione",

		["Venezia"] = "Venezia e Laguna",
		["venezia e laguna"] = "Venezia e Laguna",
		["Vibo valentia"] = "Vibo Valentia",
		["vibo"] = "Vibo Valentia",
		["videogames"] = "Videogiochi",

		["Disney"] = "Walt Disney",

		["q"] = "Qualità",
		["Qualita"] = "Qualità"
	},
	-- questa tabella serve per gestire i voti
	var = {
		A = "A",
		["A+"] = "A",
		VETRINA = "A",
		B = "B",
		C = "C",
		D = "D",
		E = "E",
		X = "E",
		STUB = "E",
		NC = "NC"
	},
	colore_voti = {
		A = "#6699ff",
		B = "#53e04c",
		C = "#fff31e",
		D = "#ff831E",
		E = "#ff1e29",
		NC = "white"
	},
	livelli = {
		A = "livello completo",
		B = "livello buono",
		C = "livello sufficiente",
		D = "livello minimo",
		E = "livello bozza",
		NC = "nessun livello",
		["livello completo"] = "A",
		["livello buono"] = "B",
		["livello sufficiente"] = "C",
		["livello minimo"] = "D",
		["livello bozza"] = "E",
		["nessun livello"] = "NC",
		["non compilate"] = "NC"
	},
	descrizione_stato = {
		livello = {
			["livello completo"] = "La voce ha ottenuto il massimo livello di valutazione in base a quanto raccomandato nel '''[[Progetto:Qualità/Monitoraggio voci|monitoraggio della qualità]]'''.",
			["livello buono"] = "La voce ha raggiunto un buon livello di valutazione in base a quanto raccomandato nel '''[[Progetto:Qualità/Monitoraggio voci|monitoraggio della qualità]]'''.",
			["livello sufficiente"] = "La voce è stata considerata di livello sufficiente in base a quanto raccomandato nel '''[[Progetto:Qualità/Monitoraggio voci|monitoraggio della qualità]]'''.",
			["livello minimo"] = "La voce è stata considerata di livello minimo in base a quanto raccomandato nel '''[[Progetto:Qualità/Monitoraggio voci|monitoraggio della qualità]]'''.",
			["livello bozza"] = "La voce è da considerarsi una bozza in base a quanto indicato dal '''[[Progetto:Qualità/Monitoraggio voci|monitoraggio della qualità]]''' e da [[Aiuto:abbozzo]].", -- da chiarire meglio come funziona
			["nessun livello"] = "Alla voce non può ancora essere assegnato un livello per il '''[[Progetto:Qualità/Monitoraggio voci|monitoraggio della qualità]]'''.", -- da chiarire meglio come funziona
			["non compilate"] = "La voce non è stata ancora monitorata, <span class=\"plainlinks\">[http://it.wikipedia.org/w/title=" .. mw.title.getCurrentTitle().fullText .. "&action=edit&section=0 fallo ora]!</span>"
		},
		accuratezza = {
			A = "Voce adeguatamente '''accurata'''. Tutti gli aspetti principali del tema sono affrontati con la dovuta profondità. Il tema è stabile e non dovrebbe necessitare di aggiornamenti futuri.",
			B = "Lievi problemi relativi all''''accuratezza''' dei contenuti. Informazioni esaustive nella gran parte dei casi, ma alcuni aspetti non sono del tutto approfonditi o altri non sono direttamente attinenti. Il tema non è stabile e potrebbe in breve necessitare di aggiornamenti.",
			C = "Seri problemi relativi all''''accuratezza''' dei contenuti. Importanti aspetti del tema non sono trattati o solo superficialmente. Altri aspetti non sono direttamente attinenti. Alcune informazioni importanti risultano controverse. Potrebbero essere presenti uno o più avvisi.",
			D = "Gravi problemi relativi all''''accuratezza''' o alla neutralità dei contenuti. Molti aspetti del tema non sono trattati o solo superficialmente. È assai probabile che siano presenti uno o più avvisi o che vadano inseriti.",
			E = "Gravissimi problemi relativi all''''accuratezza''' dei contenuti, segnalati da avvisi. Informazioni limitate o da controllare.",
			NC = "Nessuna informazione sull'<b>accuratezza</b> dei contenuti."
		},
		scrittura = {
			A = "Voce '''scritta''' in buon italiano e con buono [[aiuto:manuale di stile|stile]]. Sintassi e lessico adeguati, linguaggio chiaro e scorrevole, con uso attento di termini specifici. Strutturazione in paragrafi soddisfacente.",
			B = "Lievi problemi di '''scrittura'''. Qualche inciampo nello [[aiuto:manuale di stile|stile]]. Linguaggio non sempre scorrevole. Strutturazione in paragrafi adeguata, ma ancora migliorabile sotto alcuni aspetti.",
			C = "Seri problemi di '''scrittura'''. Linguaggio comprensibile, ma con [[aiuto:manuale di stile|stile]] poco scorrevole. Strutturazione in paragrafi carente.",
			D = "Gravi problemi di '''scrittura'''. Stile scadente. Strutturazione in paragrafi assente o molto carente.",
			E = "Gravissimi problemi di '''scrittura'''. Lo [[aiuto:manuale di stile|stile]] va completamente rivisto ed è auspicabile una integrale riscrittura.",
			NC = "Nessuna informazione sulla '''scrittura'''."
		},
		fonti = {
			A = "I contenuti della voce sono interamente verificabili tramite '''fonti''' autorevoli e [[Wikipedia:Fonti attendibili|attendibili]]. Il tema è stabile e non dovrebbe necessitare di aggiornamenti futuri.",
			B = "Lievi problemi relativi alla verificabilità della voce. Un aspetto del tema non è adeguatamente supportato da '''fonti''' [[Wikipedia:Fonti attendibili|attendibili]]. Alcune fonti andrebbero sostituite con altre più autorevoli. Il tema non è stabile e potrebbe in breve necessitare di aggiornamenti.",
			C = "Seri problemi relativi alla verificabilità della voce. Carenza di '''fonti''' [[Wikipedia:Fonti attendibili|attendibili]]. Alcuni aspetti del tema sono completamente privi di fonti a supporto. Presenza o necessità del template {{[[template:cn|cn]]}}. La delicatezza del tema richiede una speciale attenzione alle fonti.",
			D = "Gravi problemi relativi alla verificabilità della voce. Molti aspetti del tema sono completamente privi di '''fonti''' [[Wikipedia:Fonti attendibili|attendibili]] a supporto. Presenza o necessità del template {{[[template:F|F]]}}.",
			E = "Gravissimi problemi relativi alla verificabilità della voce. '''Fonti''' assenti o [[Wikipedia:Fonti attendibili|del tutto inadeguate]]. Presenza o necessità del template {{[[template:F|F]]}}.",
			NC = "Nessuna informazione sulla [[Wikipedia:Fonti attendibili|attendibilità]] delle '''fonti'''."
		},
		immagini = {
			A = "La voce è corredata da un adeguato numero di '''[[aiuto:immagini|immagini]]''' e altri supporti grafici, in tema con il contenuto della voce, oppure non ne necessita alcuno.",
			B = "Lievi problemi relativi alla dotazione di '''[[aiuto:immagini|immagini]]''' e altri supporti grafici nella voce. Mancano alcuni file o altri sono inadeguati.",
			C = "Seri problemi relativi alla dotazione di '''[[aiuto:immagini|immagini]]''' e altri supporti grafici nella voce. Mancano alcuni file importanti per la comprensione del tema.",
			D = "Gravi problemi relativi alla dotazione di '''[[aiuto:immagini|immagini]]''' e altri supporti grafici nella voce. Mancano molti file importanti per la comprensione del tema, alcuni essenziali.",
			E = "Gravissimi problemi relativi alla dotazione di '''[[aiuto:immagini|immagini]]''' e altri supporti grafici nella voce. La voce necessiterebbe di file importanti per la comprensione del tema, ma ne è assolutamente priva.",
			NC = "Nessuna informazione sulla presenza di '''[[aiuto:immagini|immagini]]''' o altri supporti grafici."
		}
	}
}

-- Funzione di utilità
--------------------------------------------------------------------------------

local getArgs = require("Modulo:Arguments").getArgs

local iconaArgomento = require("Modulo:Sandbox/ppong/Icona").iconaArgomento

local italiano = mw.language.new("it")

-- ovvero come complicarsi la vita inutilmente
local function riordinaTabella(t)
	local n = 0
	for _, _ in pairs(t) do
		n = n + 1
	end
	local i = 0
	for ii = 1, n do
		while true do
			i = i + 1
			if t[i] then
				break
			end
		end
		t[ii] = t[i]
	end
end

-- Classe Monitoraggio
--------------------------------------------------------------------------------

local Monitoraggio = {}

function Monitoraggio:new(o)
	o = {} or o
	setmetatable(o, self)
	self.__index = self
	return o
end

function Monitoraggio:newError(err, cat) -- funzione di utilità per gli errori
	if not self.errori then
		self.errori = {}
	end
	self.errori[#self.errori + 1] = err
--	if cat then
--		if not self.categorie_errore then -- per gestire varie categorie di errore
--			self.categorie_errore = {}
--		end
--		self.categorie_errore[cat] = cat
--	end
end

function Monitoraggio:organizzaArgomenti(args)
	-- minuscolizza tutti i parametri
	for k, v in pairs(args) do
		if type(k) == "string" then
			local kk = mw.ustring.lower(k)
			if kk ~= k and args[kk] then
				self:newError("parametro <tt>" .. kk .. "</tt> inserito più volte con un diverso uso della maiuscola")
				args[k] = nil
			elseif kk ~= k then
				args[kk] = v
				args[k] = nil
			end
		end
	end
	self.voti = {}
	for _, s in ipairs({"accuratezza", "scrittura", "fonti", "immagini"}) do
		local voto = args[s] or "NC"
		voto = string.upper(voto)
		if config.var[voto] then
			self.voti[s] = config.var[voto]
		else
			self:newError("valore \"" .. voto .. "\" non riconosciuto per il campo <tt>" .. s .. "</tt>")
			self.voti[s] = "NC"
		end
		args[s] = nil
	end
	for _, s in ipairs{"note", "utente", "data"} do
		self[s] = args[s]
		args[s] = nil
	end
	if args.progetto and args.progetto1 then
		self:newError("<tt>progetto</tt> e <tt>progetto1</tt> entrambi specificati, sono due donominazioni alternative per il primo progetto, i seguenti vanno numerati a partire da 2")
		args.progetto = nil
	elseif args.progetto then
		args.progetto1 = args.progetto
		args.progetto = nil
	end
	self.progetti = {}
	self.link_progetti = {}
	for k, v in pairs(args) do
		if string.find(k, "^progetto%d+$") then
			local i = tonumber(k:match("^progetto(%d+)$"))
			self.progetti[i] = v
			-- attinge alla tabella di configurazione per ottenere il nome completo del progetto
			local uv = italiano:ucfirst(v)
			local lv
			if config.progetti[v] then
				lv = config.progetti[v]
			elseif config.progetti[uv] then
				lv = config.progetti[uv]
			else
				lv = uv
			end
			self.link_progetti[i] = lv
			args[k] = nil
		else
			self:newError("parametro <tt>" .. k .. "</tt> non riconosciuto")
			args[k] = nil
		end
	end
	riordinaTabella(self.progetti)
	riordinaTabella(self.link_progetti)
	if #self.progetti == 0 then
		self:newError("nessun progetto specificato")
	elseif #self.progetti > 4 then
		self:newError("più di quattro progetti specificati")
		for i = 5, #self.progetti do
			self.progetti[i] = nil
			self.link_progetti[i] = nil
		end
	end
end

-- la funzione attuale non è proprio così banale
function Monitoraggio:assegnaLivello() 
	local out = "non compilate"
	for _, v in pairs(self.voti) do
		if v ~= "NC" then
			-- cerca un valore alla volta in tutti i parametri, partendo dal basso, quindi assegna in generale
			for _, vv in ipairs({"NC", "E", "D", "C", "B", "A"}) do
				-- un livello corrispondente al più basso valore tra i voti che sono stati dati alla voce
				for k, vvv in pairs(self.voti) do
					if vv == vvv then
						out = config.livelli[vv]
						break
					end
				end
				if out ~= "non compilate" then
					break
				end
			end
			break
		end
	end
	self.livello = out
end

function Monitoraggio:creaCategorie()
	local out = self.categorie or {}
	out[#out + 1] = "[[Categoria:Voci monitorate - " .. self.livello .. "]]"
	for _, prg in ipairs(self.link_progetti) do
		local indirizzo = "Voci monitorate Progetto " .. prg .. " - " .. self.livello
		if mw.title.makeTitle(Categoria, indirizzo):esist() then
			out[#out + 1] = "[[Categoria:" .. indirizzo .. "]]"
		end
		end
	for k, v in pairs(self.voti) do
		out[#out + 1] = "[[Categoria:Voci monitorate - " .. k .. " " .. v .. "]]"
		for _, prg in ipairs(self.link_progetti) do
			local indirizzo = "Progetto:" .. prg .. "/Tabella monitoraggio automatico - " .. self.livello
			if mw.title.makeTitle(Categoria, indirizzo):esist() then
				out[#out + 1] = "[[Categoria:" .. indirizzo .. "]]"
			end
		end
	end
	if not self.data then
		self:newError("data non specificata")
	else
		local indirizzo = "Voci monitorate - " .. self.data
		if mw.title.makeTitle(Categoria, indirizzo):esist() then
			out[#out + 1] = "[[Categoria:" .. indirizzo .. "]]"
		else
			self:newError("data non riconosciuta, inserire: <code>data = " .. italiano:formatDate("F Y") .. "</code>")
		end
	end
	self.categorie = out
end

function Monitoraggio:impostaRigaProgetti()
	local out = { icone = {}, testo = {} }
	for i, prg in ipairs(self.progetti) do
		local l_prg = self.link_progetti[i]
		out.icone[i] = "[[File:" .. iconaArgomento({prg, "Crystal Clear app ksirtet.png"}) .. "|35x50px]]"
		if i == 1 then
			out.testo = {"[[Progetto:" .. l_prg .. "/Monitoraggio voci|Monitoraggio " .. prg .. "]]"}
		else
			out.testo[i] = "[[Progetto:" .. l_prg .. "/Monitoraggio voci|" .. prg .. "]]"
		end
	end
	return out
end

function Monitoraggio:impostaRigaLivello()
	local out = {}
	local liv = self.livello
	if config.livelli[liv] == "NC" then
		out.icona = "[[File:Symbol stub class.svg|25px]]"
	else
		out.icona = "<span style =\"font-weight: bold; font-size: 145%; border: 1px solid lightsteelblue; background:" ..
					config.colore_voti[config.livelli[liv]] .. "; color:blue; \">&nbsp;'''<tt>[[:Categoria:Voci monitorate - " .. liv .. "|" ..
					string.gsub(liv, "livello ", "") .. "]]'''</tt>&nbsp;</span>"
	end
	out.testo = config.descrizione_stato.livello[liv]
	-- da modificare o migliorare?
	if liv == "nessun livello" then
		local nonvotati = {}
		for k, v in pairs(self.voti) do
			if v == config.livelli[liv] then
				nonvotati[#nonvotati + 1] = k
			end
		end
		out.testo = out.testo .. " <small>Non è stato fornita una valutazione per " .. table.concat(nonvotati, ", ") .. "</small>"
	end
	if self.data then
		out.data = "Voce monitorata nel mese di " .. self.data
	end
	return out
end

function Monitoraggio:impostaRigheVoti()
	local out = {}
	for i, s in ipairs({"accuratezza", "scrittura", "fonti", "immagini"}) do
		local voto = self.voti[s]
		if voto ~= "NC" then -- le righe non valutate non compaiono, perché dovrebbero?
			local outi = {}
			outi.icona = "<span style =\"font-weight: bold; font-size: 155%; border: 1px solid lightsteelblue; background:" ..
						 config.colore_voti[voto] .. ";\">&thinsp;'''<tt>" .. voto .. "</tt>'''&thinsp;</span>"
			outi.testo = config.descrizione_stato[s][voto]
			out[i] = outi
		end
	end
	return out
end

function Monitoraggio:creaContenitore()
	local prg = self:impostaRigaProgetti()
	local liv = self:impostaRigaLivello()
	local out = mw.html.create("div")
		:addClass("mw-collapsible") -- per rendere i voti particolari a scomparsa
		:cssText("border: 1px solid silver; margin: 0 10% 0.2em 10%; background-color: white; padding: 3px;")
	-- il box è diviso in tre tabelle
	local out_prg = out:tag("div")
		:cssText("background-color: #B5D9D3;")
		:tag("table")
			:cssText("border: none; margin-right:" .. (#prg.icone * 35) .. "px;") -- border-collapse: collapse;
			:tag("tr")
	for i, icona in ipairs(prg.icone) do
		out_prg:tag("td")
			:cssText("width: 35px; text-align: center;")
			:wikitext(prg.icone[i])
	end
	out_prg:tag("th")
		:cssText("width: 100%; text-align: center;")
		:wikitext(table.concat(prg.testo, ", "))

	out:tag("table")
		:cssText("width: 100%; border: none;") -- border-collapse: collapse;
		:tag("tr")
			:tag("td")
				:wikitext(liv.icona)
				:done()
			:tag("td")
				:cssText("font-size: 107%;") -- lo toglierei
				:wikitext(liv.testo)
				:done()
			:tag("td")
				:cssText("color: grey; text-align: right; padding-right: 6px; font-size: 95%;")
				:wikitext(liv.data)

	local out_voti = out:tag("table")
		:addClass("mw-collapsible-content")
		:cssText("border-collapse: collapse; width: 100%;")
	for _, t in ipairs(self:impostaRigheVoti()) do
		out_voti:tag("tr")
			:cssText("border: 1px solid #B5D9D3;")
			:tag("td")
				:wikitext(t.icona)
				:done()
			:tag("td")
				:wikitext(t.testo)
	end
	if self.note then
		out:tag("div")
			:cssText("margin: 0.3em 0 0.1em 1em")
			:wikitext("Note: ''" .. self.note .. "''")
	end
	return out
end

function Monitoraggio:__tostring()
--	for _, s in self.categorie_errore do
--		self.categorie[#self.categorie + 1] = s
--	end
	local out = tostring(self:creaContenitore())
	local err = self.errori
	local cat = self.categorie
	if err then
		out = out .. "<div class=\"error\">" .. table.concat(err, "<br />") .. "</div>"
	end
	if cat then
		if err then
			cat[#cat + 1] = "[[Categoria:Errori di compilazione del template Monitoraggio]]"
		end
		out = out .. table.concat(cat, "\n")
	end
	return out
end

-- Funzione di invoke
--------------------------------------------------------------------------------

local p = {}

function p.main(frame)
	local args = getArgs(frame)
	local monitoraggio = Monitoraggio:new()
	monitoraggio:organizzaArgomenti(args)
	monitoraggio:assegnaLivello()
	if mw.title.getCurrentTitle().namespace == 1 then
		monitoraggio:creaCategorie()
	end
	return tostring(monitoraggio)
end

return p