« Module:Outils » : différence entre les versions

De Lagny-sur-Marne Wiki
Aller à la navigation Aller à la recherche
0x010D (discussion | contributions)
extractArgs : correction bug
0x010D (discussion | contributions)
ajout conversion de nombre
Ligne 137 : Ligne 137 :
     end
     end
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).
--]]
function Outils.traite_tranche(_c1, _c2, _c3, langue)
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 = p.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 (langue == "fr") then
vvv = p.infcent[val]
elseif (langue == "be") then
vvv = p.infcent_be[val] or p.infcent[val]
elseif (langue == "ch") then
vvv = p.infcent_ch[val] or p.infcent_be[val] or p.infcent[val]
else
vvv = p.infcent_ch2[val] or p.infcent_be[val] or p.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 Outils.nombre2texte(frame)
-- local args = frame:getParent().args
local args = frame.args
-- le nombre à convertir
local valeur = args[1]
if (valeur == nil) then
return Outils.erreur("Il faut un paramètre non nommé numérique.")
end
-- s'il y a une virgule, on l'ignore
local bla = mw.ustring.find(valeur, "[.,]")
if (bla ~= nil) then
-- extraction de la partie avant la virgule
valeur = mw.ustring.match(mw.text.trim(valeur), "^[-]?[0-9]*")
end
nvaleur = tonumber(valeur)
if (type(nvaleur) ~= "number") then
return Outils.erreur("Le paramètre doit être un nombre.")
end
-- limites
if (nvaleur < -999999999999 or nvaleur > 999999999999) then
return Outils.erreur("Nombre trop grand ou trop petit.")
end
-- note : ici il faudrait s'assurer que le nombre est un entier !
-- on extrait le moins si présent
signe = false
if (nvaleur < 0) then
nvaleur = -nvaleur
signe = true
end
-- option : choix de la langue
local langue = args["langue"]
if (langue == nil) then
langue = "fr"
else
langue = mw.text.trim(langue)
end
-- validation des valeurs permises
if (langue ~= "fr" and langue ~= "be" and langue ~= "ch" and langue ~= "ch2") then
return Outils.erreur("Paramètre langue non reconnu (fr, be, ch ou ch2).")
end
-- type de résultat : seule valeur autorisée : 'ordinal'
local style = args["type"]
if (style ~= nil and style ~= "ordinal") then
style = nil
end
-- type d'orthographe
local ortho = args["orthographe"]
if (ortho ~= nil and ortho ~= "réformée") then
ortho = nil
end
-- cas (très) simple : 0
if (nvaleur == 0) then
if (style == "ordinal") then
return "zéroième"
else
return "zéro"
end
end
-- on traite les autres cas simples : le nombre est pré-codé
local val
if (langue == "fr") then
val = p.infcent[nvaleur]
elseif (langue == "be") then
val = p.infcent_be[nvaleur] or p.infcent[nvaleur]
elseif (langue == "ch") then
val = p.infcent_ch[nvaleur] or p.infcent_be[nvaleur] or p.infcent[nvaleur]
else
val = p.infcent_ch2[nvaleur] or p.infcent_be[nvaleur] or p.infcent[nvaleur]
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 tvaleur = mw.text.split(valeur, "")
local nb = #tvaleur -- 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 = tvaleur[nb-2]
local p2 = tvaleur[nb-1]
local p3 = tvaleur[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(Outils.traite_tranche(p1, p2, p3, langue) or "zéro")
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éro " and tbl[pos] ~= "zéro") 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] == "un " or tbl[pos] == "un") then
el = p.sup[pos] .. " "
else
-- on ajoute X + rang
el = tbl[pos] .. " " .. p.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 (style ~= nil) then
-- ordinal : on cherche la fin du nombre pour ajouter le "ième" qui convient
if (res == "zéro") then
res = "zéroième" -- eurk!
elseif (res == "un") then
res = "premier"
else
-- on récupère le dernier mot
local fin = mw.ustring.match(res, "%a*$")
-- on récupère le reste (début)
local debut = mw.ustring.gsub(res, "%a*$", "")
-- on génère la fin en ordinal
local nfin = p.iemes[fin]
if (nfin == nil) then
nfin = Outils.erreur("erreur interne d'ordinal.")
end
res = debut .. nfin
end
end
-- si orthographe réformée on remplace les espaces par des tirets
if (ortho == "réformée") then
res = mw.ustring.gsub(res, "[ ]", "-")
else
-- sinon on remplace les espaces par des insécables
res = mw.ustring.gsub(res, "[ ]", "&#160;")
end
if (style == nil) then
-- traitement de signe éventuel (sauf ordinaux)
if (signe) then
res = "moins&#160;" .. res
end
end
-- on retourne
return res
end


return Outils
return Outils

Version du 16 septembre 2013 à 12:46

local mw = mw or require 'mw' -- pour debugage sous ecllipse

local Outils = { }


-- trim nettoie un paramètre non nommé (supprime les espaces et retours ligne au début et à la fin) -- retourne nil si le texte est vide ou n'est pas du texte. Les nombres ne sont PAS considérés comme du texte. function Outils.trim( texte )

   if type( texte ) == 'string' and texte ~=  then
       return mw.text.trim( texte )
   end

end

-- erreur génère une erreur function Outils.erreur( texte )

   return '' .. (texte or "aucune erreur indiquée") .. ""

end

-- validTextArg renvoit le premier paramètre chaine non vide -- Paramètre : -- 1 - tableau contenant tous paramètres -- 2, ... - les noms des paramètres qui doivent êtres testés. function Outils.validTextArg( args, name, ... )

   local texte = Outils.trim( args[name] )
   if texte then
       return texte
   end
   if select( '#', ... ) > 0 then
       return Outils.validTextArg( args, ... )
   end

end

-- notEmpty renvoie le premier paramètre non vide ou nul. -- Paramètre : -- 1, ... - les variables qui doivent êtres testés. function Outils.notEmpty( var, ... )

   local tvar = type( var )
   
   if tvar == 'string' and var ~=  then
       return mw.text.trim( var )
   elseif tvar == 'table' then
       local nextFunc = pairs( var )   -- n'utilise pas next car non défini par mw.loadData
       if nextFunc( var ) ~= nil then
           return var
       end 
   elseif var == true or ( tvar == 'number' and var ~= 0 ) or tvar == 'function' then
       return var
   end
   
   if select( '#', ... ) > 0 then
       return Outils.notEmpty(  ... )
   end

end

-- extractArgs permet de récupérer les arguements du modèle, -- ou la table transmise à la fonction par une autre fonction d'un module -- Paramètres : -- 1 - un objet frame ou une table contenant les paramètre -- 2, ... - une liste de nom de paramètre pour déterminé si les paramètres sont transmis par #invoke: -- le premier paramètre sera systématiquement testé. function Outils.extractArgs ( frame, ... )

   if type( frame ) == 'table' then
       if type( frame.getParent ) == 'function' then
           if Outils.validTextArg( frame.args, 1, ...) then
               return frame.args
           else
               local args = frame:getParent().args;
               for k,v in pairs( frame.args ) do
                   args[k] = v;
               end
               return args
           end
       else
           return frame 
       end
   else
       return { frame, ... }
   end

end

-- abr génère une abréviation (discrète par défaut) -- paramètres : -- 1 = abréviation, -- 2 = texte, -- 3 = langue, -- nbsp = '-' pour une espace insécable avant l'abréviation, '+' pour l'avoir après. -- visible = true pour une abréviation non discrète function Outils.abr( frame )

   local args = Outils.extractArgs( frame )
   if args[2] == nil then 
       return args[1] or                  -- retoune l'abréviation ou au minimum une chaine vide s'il n'y a pas de texte
   end
   local wikiText = { '<abbr' }
   if not args.visible then
       table.insert( wikiText, ' class="abbr"' )
   end
   table.insert( wikiText, ' title="' )
   table.insert( wikiText, args[2] )
   if args[3] then 
       table.insert( wikiText, '" lang="' )
       table.insert( wikiText, args[3] )
   end
   table.insert( wikiText, '">' )
   table.insert( wikiText, args[1] )
   table.insert( wikiText, '' )
   if args.nbsp == '-' then
      table.insert( wikiText, 1, ' ' )
   elseif args.nbsp == '+' then
      table.insert( wikiText, ' ' )
   end
   return table.concat( wikiText )

end

-- 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 Outils.ordinal( nombre, feminin )

   local num = tonumber( nombre )
   if num == nil then
       return Outils.trim( tostring( nombre ) ) or 
   elseif num == 1 then
       if feminin then
           return Outils.abr{ '1re', 'première' }
       else
           return Outils.abr{ '1er', 'premier' }
       end
   else
       local nom = mw.loadData( 'Module:Outil/Data' ).ordinal
       if nom[num] then
           return Outils.abr{ num .. 'e', nom[num] }
       else
           return num .. 'e'
       end
   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).

--]] function Outils.traite_tranche(_c1, _c2, _c3, langue) 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 = p.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 (langue == "fr") then vvv = p.infcent[val] elseif (langue == "be") then vvv = p.infcent_be[val] or p.infcent[val] elseif (langue == "ch") then vvv = p.infcent_ch[val] or p.infcent_be[val] or p.infcent[val] else vvv = p.infcent_ch2[val] or p.infcent_be[val] or p.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 Outils.nombre2texte(frame) -- local args = frame:getParent().args local args = frame.args

-- le nombre à convertir local valeur = args[1] if (valeur == nil) then return Outils.erreur("Il faut un paramètre non nommé numérique.") end

-- s'il y a une virgule, on l'ignore local bla = mw.ustring.find(valeur, "[.,]") if (bla ~= nil) then -- extraction de la partie avant la virgule valeur = mw.ustring.match(mw.text.trim(valeur), "^[-]?[0-9]*") end

nvaleur = tonumber(valeur) if (type(nvaleur) ~= "number") then return Outils.erreur("Le paramètre doit être un nombre.") end -- limites if (nvaleur < -999999999999 or nvaleur > 999999999999) then return Outils.erreur("Nombre trop grand ou trop petit.") end -- note : ici il faudrait s'assurer que le nombre est un entier !

-- on extrait le moins si présent signe = false if (nvaleur < 0) then nvaleur = -nvaleur signe = true end

-- option : choix de la langue local langue = args["langue"] if (langue == nil) then langue = "fr" else langue = mw.text.trim(langue) end -- validation des valeurs permises if (langue ~= "fr" and langue ~= "be" and langue ~= "ch" and langue ~= "ch2") then return Outils.erreur("Paramètre langue non reconnu (fr, be, ch ou ch2).") end

-- type de résultat : seule valeur autorisée : 'ordinal' local style = args["type"] if (style ~= nil and style ~= "ordinal") then style = nil end

-- type d'orthographe local ortho = args["orthographe"] if (ortho ~= nil and ortho ~= "réformée") then ortho = nil end

-- cas (très) simple : 0 if (nvaleur == 0) then if (style == "ordinal") then return "zéroième" else return "zéro" end end

-- on traite les autres cas simples : le nombre est pré-codé local val if (langue == "fr") then val = p.infcent[nvaleur] elseif (langue == "be") then val = p.infcent_be[nvaleur] or p.infcent[nvaleur] elseif (langue == "ch") then val = p.infcent_ch[nvaleur] or p.infcent_be[nvaleur] or p.infcent[nvaleur] else val = p.infcent_ch2[nvaleur] or p.infcent_be[nvaleur] or p.infcent[nvaleur] 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 tvaleur = mw.text.split(valeur, "") local nb = #tvaleur -- 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 = tvaleur[nb-2] local p2 = tvaleur[nb-1] local p3 = tvaleur[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(Outils.traite_tranche(p1, p2, p3, langue) or "zéro") 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éro " and tbl[pos] ~= "zéro") 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] == "un " or tbl[pos] == "un") then el = p.sup[pos] .. " " else -- on ajoute X + rang el = tbl[pos] .. " " .. p.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 (style ~= nil) then -- ordinal : on cherche la fin du nombre pour ajouter le "ième" qui convient if (res == "zéro") then res = "zéroième" -- eurk! elseif (res == "un") then res = "premier" else -- on récupère le dernier mot local fin = mw.ustring.match(res, "%a*$") -- on récupère le reste (début) local debut = mw.ustring.gsub(res, "%a*$", "")

-- on génère la fin en ordinal local nfin = p.iemes[fin] if (nfin == nil) then nfin = Outils.erreur("erreur interne d'ordinal.") end res = debut .. nfin end end

-- si orthographe réformée on remplace les espaces par des tirets if (ortho == "réformée") then res = mw.ustring.gsub(res, "[ ]", "-") else -- sinon on remplace les espaces par des insécables res = mw.ustring.gsub(res, "[ ]", " ") end if (style == nil) then -- traitement de signe éventuel (sauf ordinaux) if (signe) then res = "moins " .. res end end

-- on retourne return res end


return Outils