Aller au contenu

Module:Nombro2tèxto

De Vouiquipèdia, l’enciclopèdia abada.

La documentation pour ce module peut être créée à Module:Nombro2tèxto/doc

local p = { }

--[[
	ordinal renvoie une chaine correspondant à l'abréviation de l'adjectif ordinal du nombre.
	Paramètres :
		1 = nombre (string ou number) 
		2 = true pour avoir première au lieu de premier su nombre = 1
--]]
function p.ordenal( nombro, femenin )
	local num = tonumber( nombro )
	if num == nil then
		return mw.text.trim( tostring( nombro ) or '' )
	else
		local nom = p.nombro2texto_vere( nombro, nil, 'ordenâl', 'rèformâye', femenin and 'femenin' )
		local exposent
		if num == 1 then
			exposent = (femenin and 'ére' or 'ér')
		else
			exposent = 'éma'
		end
		return '<abbr class="abbr" title="' .. nom .. '">' .. num .. '<sup>' .. exposent .. '</sup></abbr>'
	end
end

--[[
  Fonction de traitement d'une "tranche" de nombres entre 0 et 999.
  Retourne la forme texturelle (5 → cinq, 46 → quarante six, 432 → quatre cent trente deux…)
  Les paramètres sont les chiffres, du plus grand au plus petit (centaine, dizaine, unité).
  La valeur nil signifie "0" (pour n'importe lequel des paramètres)
  La fonction retourne le texte ou 'nil' si la valeur est zéro (pour gérer les 0 millier…)
  Le paramètre 'langue' indique la variante de langue (fr, be, ch ou ch2).
  Data est la table des données (issue de loadData())
--]]
function p.treta_trenche(_c1, _c2, _c3, lengoua, Data)
    local c1, c2, c3
	if (_c1 == nil) then c1 = 0 else c1 = tonumber(_c1) or 0 end
	if (_c2 == nil) then c2 = 0 else c2 = tonumber(_c2) or 0 end
	if (_c3 == nil) then c3 = 0 else c3 = tonumber(_c3) or 0 end

	if (c1 == 0 and c2 == 0 and c3 == 0) then
		return nil -- sil signifie "zéro" (mais à traiter spécialement quand entouré)
	end
	local resu = ""
	
	-- on calcule la valeur restante (sans les centaines)
	local val = 10*c2 + c3
	-- présence d'une centaine ?
	if (c1 ~= 0) then
		if (c1 == 1) then
			resu = "cent " -- séparateur
		else
			-- plusieurs centaines : on ajoute l'unité
			resu = Data.infcent[c1] .. " cent"
			-- si pas d'unité 100 prend un 's'
			if (val == 0) then
				resu = resu .. "s "
			else
				resu = resu .. " "
			end
		end
	end
	-- reste = 0 ?
	if (val == 0) then
		-- on retourne directement la centaine
		return resu
	end
	-- c'est forcément un nombre pré-défini
	local vvv
	if (lengoua == "frp") then
		vvv = Data.infcent[val]
	elseif (lengoua == "fr") then
		vvv = Data.infcent_fr[val] or Data.infcent[val]
	elseif (lengoua == "ch") then
		vvv = Data.infcent_ch[val] or Data.infcent_fr[val] or Data.infcent[val]
	else
		vvv = Data.infcent_ch2[val] or Data.infcent_fr[val] or Data.infcent[val]
	end
	return resu .. vvv .. " "
	-- note : cette fonction retourne *toujours* un " " à la fin du terme
end

--[[
  Fonction principale
  Reçoit en paramètre (premier non nommé) le nombre à traiter.
  Retourne la forme textuelle de ce nombre.
--]]
function p.nombro2texto_vere(pnombro, plengoua, ptipo, portografia, pgenro, pgrantaletra, pordenal)
	-- le nombre à convertir (vient toujours du modèle)
	local valor = pnombro
	if (valor == nil) then
		return '<span class="error">Fôt un paramètro pas nomâ numerico.</span>'
	elseif type(valor) == "sting" then
		
		-- s'il y a une virgule, on l'ignore
		local bla = mw.ustring.find(valor, "[.,]")
		if (bla ~= nil) then
			-- extraction de la partie avant la virgule
			valor = mw.ustring.match(mw.text.trim(valor), "^[-]?[0-9]*")
		end
	elseif type(valor) == "number" then
		valor = math.floor(valor)
	end
	
	local nvalor = tonumber(valor)
	if (type(nvalor) ~= "number") then
		return '<span class="error">Lo paramètro dêt étre un nombro.</span>'
	end
	-- limites
	if (nvalor < -999999999999 or nvalor > 999999999999) then
		return '<span class="error">Nombro trop grant ou ben trop petiôt.</span>'
	end
	-- note : ici il faudrait s'assurer que le nombre est un entier !

	-- on extrait le moins si présent
	local segno = false
	if (nvalor < 0) then
		nvalor = -nvalor
		segno = true
	end

	-- option : choix de la langue
	local lengoua = plengoua
	if (lengoua == nil) then
		lengoua = "frp"
	else
		lengoua = mw.text.trim(lengoua)
	end
	-- validation des valeurs permises
	if (lengoua ~= "frp" and lengoua ~= "fr" and lengoua ~= "ch" and lengoua ~= "ch2") then
		return '<span class="error">Paramètro lengoua pas recognu (frp, fr, ch ou ben ch2).</span>'
	end

	-- type de résultat : seule valeur autorisée : 'ordinal'
	local stilo = ptipo
	if (stilo ~= nil and stilo ~= "ordenâl") then
		stilo = nil
	end

	-- type d'orthographe
	local orto = portografia
	if (orto ~= nil and orto ~= "rèformâye") then
		orto = nil
	end
	
	-- genre : uniquement pour l'ordinal "premier / première"
	local genro = pgenro
	if (genro ~= nil and genro ~= "femenin") then
		genro = nil
	end
	
	-- majuscule : mettre une majuscule au premier mot
	local gra = pgrantaletra
	if (gra ~= nil and gra ~= "ouè") then
		gra = nil
	end

	-- cas (très) simple : 0
	if (nvalor == 0) then
		if (stilo == "ordenâl") then
			if (gra) then
				return "Zérôiéma"
			else
				return "zérôiéma"
			end
		else
			if (gra) then
				return "Zérô"
			else
				return "zérô"
			end
		end
	end

	-- on charge les données
	local Data = mw.loadData( 'Module:Nombro2texto/Data' )

	-- on traite les autres cas simples : le nombre est pré-codé
	local val
	if (lengoua == "frp") then
		val = Data.infcent[nvalor]
	elseif (lengoua == "fr") then
		val = Data.infcent_be[nvalor] or Data.infcent[nvalor]
	elseif (lengoua == "ch") then
		val = Data.infcent_ch[nvalor] or Data.infcent_fr[nvalor] or Data.infcent[nvalor]
	else
		val = Data.infcent_ch2[nvalor] or Data.infcent_fr[nvalor] or Data.infcent[nvalor]
	end

	local res = val or ""
	if (val == nil) then
		-- pas de résultat, on fait le "calcul"

		-- on l'éclate en une table des différents caractères
		local tvalor = mw.text.split(valor, "")
		local nb = #tvalor -- nombre d'éléments

		-- on boucle sur les triplets de chiffres et on stocke le résultat dans une table
		local tbl = {}
		while (true) do
			-- on prend les 3 valeurs concernées
			local p1 = tvalor[nb-2]
			local p2 = tvalor[nb-1]
			local p3 = tvalor[nb]
			-- si les 3 sont 'nil' on a terminé
			if (p1 == nil and p2 == nil and p3 == nil) then
				break
			end
			-- on calcule la valeur du bloc concerné (rangé dans la table)
			local tmp = mw.text.trim(p.treta_trenche(p1, p2, p3, lengoua, Data) or "zérô")
			table.insert(tbl, tmp)
			-- décalage
			nb = nb - 3
		end

		-- on construit le résultat final en combinant les éléments
		-- et en ajoutant les milliers/millions/...
		local pos = 1
		while (tbl[pos] ~= nil) do
			local el = ""
			-- on l'ajoute, s'il existe
			if (tbl[pos] ~= "zérô " and tbl[pos] ~= "zérô") then
				if (pos == 1) then
					-- rang "1", on ajoute simplement la valeur
					el = tbl[pos] .. " "
				else
					-- si la valeur est "un" on ajoute seulement le rang
					if (tbl[pos] == "yon " or tbl[pos] == "yon") then
						el = Data.sup[pos] .. " "
					else
						-- on ajoute X + rang
						el = tbl[pos] .. " " .. Data.sup[pos]
						-- le pluriel, sauf pour 1000, et le séparateur
						if (pos ~= 2) then
							el = el .. "s "
						else
							el = el .. " "
						end
					end
				end
			end
			-- on insert
			res = el .. res

			-- on passe au suivant
			pos = pos + 1
		end

		-- suppression espaces
		res = mw.text.trim(res)

	end -- fin (si on n'avait pas trouvé en pré-défini)

	if (stilo ~= nil) then
		-- ordinal : on cherche la fin du nombre pour ajouter le "ième" qui convient
		if (res == "zérô") then
			res = "zérôiéma" -- eurk!
		elseif (res == "yon") then
			if (genro == nil) then
				res = "premiér"
			else
				res = "premiére"
			end
		else
			-- on récupère le dernier mot
			local fin = mw.ustring.match(res, "%a*$")
			-- on récupère le reste (début)
			local comencement = mw.ustring.gsub(res, "%a*$", "")
			
			-- on génère la fin en ordinal
			local nfin = Data.iemes[fin]
			if (nfin == nil) then
				nfin = '<span class="error">fôta de dedens d\'ordenâl.</span>'
			end
			res = comencement .. nfin
		end
	end

	-- si orthographe réformée on remplace les espaces par des tirets
	if (orto == "rèformâye") then
		res = mw.ustring.gsub(res, "[ ]", "-")
	else
		-- sinon on remplace les espaces par des insécables
		res = mw.ustring.gsub(res, "[ ]", "&#160;")
	end
	if (stilo == nil) then
		-- traitement de signe éventuel (sauf ordinaux)
		if (segno) then
			res = "muens&#160;" .. res
		end
	end

	-- si demandé on passe la première lettre en majuscule
	if (gra) then
		local lengajo = mw.getContentLanguage()
		res = lengajo:ucfirst(res)
	end

	-- on retourne
	return res
end

--[[
  Fonction principale
  Reçoit en paramètre (premier non nommé) le nombre à traiter.
  Retourne la forme textuelle de ce nombre.
--]]
function p.nombro2texto(frame)
	local pframe = frame:getParent()

	return p.nombro2texto_vere(
		 pframe.args[1] or frame.args[1], -- pas obligé. Pour permettre des exemples, avec priorité au modèle
		 frame.args["lengoua"] or pframe.args["lengoua"],
		 frame.args["tipo"] or pframe.args["tipo"],
		 frame.args["ortografia"] or pframe.args["ortografia"],
		 frame.args["genro"] or pframe.args["genro"],
		 frame.args["granta lètra"] or pframe.args["granta lètra"],
		 frame.args["ordenâl"] or pframe.args["ordenâl"]);
end

return p