Module:Démographie/Bac à sable
De Wikipedia, l'encyclopédie encyclopedia
local p = {} -- le module
--[[
Module reprenant les fonctionnalités du modèle Démographie.
--]]
-- le module chartes (centralisation des styles) local data = require "Module:Chartes"
-- liste des paramètres reconnus (valeur = nom de la variable) p.parametres = {
["titre"] = "titre", ["charte"] = "charte", ["colonnes"] = "colonnes", ["notes"] = "notes", ["source"] = "source", ["sources"] = "sources", ["flottant"] = "flottant", ["largeur-tableau"] = "largeur_tableau", ["sansdoublescomptes"] = "sansdoublescomptes", ["enquêteannuelle"] = "enqueteannuelle", ["marge-interlignes"] = "marge_interlignes", ["taille-police"] = "taille_police", ["hauteur-lignes"] = "hauteur_lignes", ["hyperliens-années"] = "hyperliens_annees", ["années-fond"] = "annees_fond", ["population-fond"] = "population_fond", ["notes-fond"] = "notes_fond", ["style-notes"] = "style_notes", -- pour permettre les paramètres "depuis Lua" ["largeur_tableau"] = "largeur_tableau", ["marge_interlignes"] = "marge_interlignes", ["taille_police"] = "taille_police", ["hauteur_lignes"] = "hauteur_lignes", ["hyperliens_annees"] = "hyperliens_annees", ["hyperliens_années"] = "hyperliens_annees", ["années_fond"] = "annees_fond", ["annees_fond"] = "annees_fond", ["population_fond"] = "population_fond", ["notes_fond"] = "notes_fond", ["style_notes"] = "style_notes",
}
-- le nom de la catégorie d'erreur (pour simplifier les changements)
p.categorie_erreur = "Page avec une erreur d'utilisation du modèle Démographie"
-- le titre par défaut (pour simplifier les changements) → plus utilisé : il n'y a plus de titre par défaut p.titre_par_defaut = "Évolution démographique"
--[[
Fonction exportée reprenant le fonctionnement de {{Charte de couleur}}
Fonction devenue inutile (voir Module:Chartes), maintenue pour compatibilité éventuelle question : est-il possible de tester un appel à une fonction précise ?
--]] function p.charte_de_couleur(frame)
local pframe = frame:getParent()
-- les deux paramètres local nom = mw.ustring.lower(mw.text.trim(pframe.args[1] or "")) local code = mw.ustring.lower(mw.text.trim(pframe.args[2] or ""))
return data.charte_m("geographie", "secondaire", code, "non")
end
--[[
Insert une catégorie d'erreur
--]] p.liste_erreurs = {} p.liste_cats = {} function p.erreur(message, cle)
table.insert(p.liste_erreurs, message) table.insert(p.liste_cats, cle)
end
--[[
Fonction de récupération d'un paramètre nommé.
--]] function p.lit_parametre(nom, pasvide)
if (type(nom) ~= "string") then return nil -- pas un paramètre nommé end local temp = p.frame.args[nom] or p.pframe.args[nom] -- du modèle, puis de l'article if (temp ~= nil) then if (pasvide) then if (temp == "") then return nil else return temp end else return temp end else return nil end
end
local function get_snack_value(t, v, ...) if v and type(t) == 'table' then return get_snack_value(t[v], ...) elseif v then return nil else return t end end
--[[
Fonction de récupération des données de Wikidata.
--]] function p.valeur_wikidata(pm) local id = mw.wikibase.getEntityIdForCurrentPage() if mw.wikibase.isValidEntityId(p.pframe.args.wikidata) then id = p.pframe.args.wikidata elseif not id then return end local popProp = mw.wikibase.getAllStatements( id, 'P1082' ) if not popProp or #popProp == 0 then return end for _, statement in ipairs( popProp ) do local pop = get_snack_value(statement, 'mainsnak', 'datavalue', 'value', 'amount') local date_table = get_snack_value(statement, 'qualifiers', 'P585', 1, 'datavalue', 'value' ) if pop and date_table and date_table.precision > 8 and statement.rank ~= 'deprecated' then local an = tonumber(date_table.time:match('^%+(%d%d%d%d)')) if an then pm[an] = pop:match('%d+') end end end end
--[[
Fonction de tri de la table
--]] function p.mysort(el1, el2)
if (el1 == nil) then return true end if (el2 == nil) then return false end if (el1[1] < el2[1]) then return true else return false end
end
--[[
Supprime le premier retour à la ligne (éventuel) de forme
--]] function p.sans_nl(texte)
if (texte == nil or texte == "" or type(texte) ~= "string") then return texte end return mw.ustring.gsub(texte, "[<][bB][rR][ ]*[/]?[>]", "", 1)
end
--[[
Fonction principale reçoit une table des paramètres (pm) issus de l'appel
--]] function p.demographie_m(pm)
-- titre par défaut --[[ if (pm.titre == "off" or pm.titre == "non") then pm.titre = nil elseif (pm.titre == nil) then pm.titre = p.titre_par_defaut end --]] -- modification : maintenant le titre est réellement optionnel if (pm.titre == "") then pm.titre = nil end
-- valeur marge interlignes if (pm.marge_interlignes == nil) then pm.marge_interlignes = "5px" else -- les valeurs trop petites if (pm.marge_interlignes == "0" or pm.marge_interlignes == "0em" or pm.marge_interlignes == "0.1em" or pm.marge_interlignes == "0px" or pm.marge_interlignes == "1px" or pm.marge_interlignes == "2px" or pm.marge_interlignes == "3px" or pm.marge_interlignes == "4px") then pm.marge_interlignes = "5px" end end
-- valeur effective du flottant local vflottant = 'margin: 0 auto' -- valeur par défaut if (mw.ustring.lower(pm.flottant or "") == "gauche") then vflottant = 'float:left; margin: 0 1em 1em 0' elseif (mw.ustring.lower(pm.flottant or "") == "droite") then vflottant = 'float:right; margin: 0 0 1em 1em' end
if (pm.hauteur_lignes == nil) then pm.hauteur_lignes = "" else pm.hauteur_lignes = "line-height:" .. pm.hauteur_lignes .. ";" end pm.taille_police = (pm.taille_police or "100%") -- valeur par défaut taille police if (pm.notes_fond ~= nil) then pm.notes_fond = "background: " .. pm.notes_fond .. ";" else pm.notes_fond = "" end local parenthese = false if (pm.style_notes == "gauche") then pm.style_notes = 'border: 1px solid #aaa; text-align:left;' else pm.style_notes = 'border: 0; border-width: 0;' parenthese = true end
-- valeur par défaut lien if (pm.hyperliens_annees == nil) then pm.hyperliens_annees = false else -- validation valeur if (pm.hyperliens_annees == "on" or pm.hyperliens_annees == "oui") then pm.hyperliens_annees = true else pm.hyperliens_annees = false -- toute valeur autre que "on" = "off" end end -- valeurs par défaut des colonnes local colonnes_par_defaut if (pm.colonnes == nil) then colonnes_par_defaut = true pm.colonnes = 9 else pm.colonnes = tonumber(pm.colonnes) -- pour que ce soit un nombre end -- on valide les colonnes if (type(pm.colonnes) ~= "number" or pm.colonnes < 1) then -- colonne erronée : erreur p.erreur("La valeur du paramètre colonnes (" .. (pm.colonnes or "<pas un nombre>") .. ") n'est pas valide", "nombre de colonnes") pm.colonnes = 9 end -- largeur par défaut : 5.4em * colonnes local largeur_tableau_par_defaut if (pm.largeur_tableau == nil) then largeur_tableau_par_defaut = true pm.largeur_tableau = pm.colonnes*5.4 .. "em" end if (pm.charte == nil) then pm.charte = "défaut" else -- on valide la charte pm.charte = mw.ustring.lower(pm.charte) end -- on récupère les couleurs de la charte sauf si indiquées local coul_annees = (pm.annees_fond or data.charte_m("geographie", "secondaire", pm.charte , "oui")) local coul_valeurs = (pm.population_fond or nil) -- valeur par défaut = rien
if (coul_valeurs == nil) then coul_valeurs = "" else coul_valeurs = 'style="background:' .. coul_valeurs .. ';"' end
-- extraction des éléments de la table, rangés dans une "vraie" table pour les trier local tbl = {} for annee, valeur in pairs(pm) do -- il y a aussi les paramètres nommés dans cette table, qu'on laisse if type(annee) == "number" then table.insert(tbl, {annee,valeur}) else -- on profite de cette boucle pour vérifier les paramètres qui n'existent pas if p.parametres[annee] == nil then -- cas particulier : les paramètres sous la forme "XXXX notes" et "XXXX unité" sont acceptés if not (annee:match("^[0-9]+ notes$") or annee:match("^[0-9]+ unité$") or annee:match("^[0-9]+ affichage$")) then -- pas un paramètre connu ni XXXX notes → erreur p.erreur("Le paramètre >>" .. annee .. "<< est inconnu", "paramètre inconnu") -- on ignore simplement ce champs end end end end -- tri de la table table.sort(tbl, p.mysort)
-- cette fois on parcours la structure des infos local ret = "" local odebug = "" -- sortie de debug
-- on parcours les données (années) pour générer la table structurée local col = 1 local ligne = 1 local struct = {} table.insert(struct, {}) -- on crée la première ligne local total = 0 -- compte du nombre total local pos = 1 while (tbl[pos] ~= nil) do annee = tbl[pos][1] valeur = tbl[pos][2] pos = pos + 1 -- il y a aussi les paramètres nommés dans cette table, qu'on laisse if (type(annee) == "number" and not (annee == 1 and (valeur == nil or valeur == ""))) then -- protection : un paramètre non nommé vaudra "1" -- nettoyage de la valeur local v = mw.text.trim(valeur or "") -- on insert dans la ligne en cours table.insert(struct[ligne], { annee, v })
-- suivant total = total + 1 col = col + 1 -- fin de la ligne ? if (col > pm.colonnes) then col = 1 ligne = ligne + 1 table.insert(struct, {}) end end end -- aucune entrée ? erreur. if (total == 0) then p.erreur("Aucune année fournie au modèle", "absence d'années") -- on insert une donnée fictive tbl[1] = { 1970, 0 } end -- cas particulier : si les données arrivent pile à la dernière colonne on a alors -- une nouvelle ligne vide, pour rien. On l'enlève si c'est le cas if (struct[ligne] ~= nil and struct[ligne][1] == nil) then struct[ligne] = nil ligne = ligne - 1 end -- on traite la largeur if (colonnes_par_defaut == true and ligne == 1 and total < pm.colonnes) then pm.colonnes = total -- restriction du nombre de colonnes au nombre réel d'éléments -- il faut aussi recalculer la largeur totale : on fait le rapport entre 9 (ancien) et le nouveau nombre de colonnes if (largeur_tableau_par_defaut == true) then -- uniquement si l'utilisateur n'a pas fixé la taille pm.largeur_tableau = pm.colonnes*5.4 .. "em" end end
-- on récupère le "langage" courant pour utiliser formatnum local lang = mw.language.getContentLanguage()
-- on récupère le namespace -- local ttl = mw.title.getCurrentTitle().namespace -- on force le namespace à "non encyclopédique" pour avoir systématiquement les messages d'erreur local ttl = 1 -- 1 ou autre chose, mais pas pas 0. Il faudrait si on conserve ça virer le code qui teste cette valeur (plus propre)
-- création du div principal
ret = ret .. '
' .. temp .. ' | [[' .. struct[ligne][col][1] .. ']] | ' .. struct[ligne][col][1] .. ' | - |
---|---|---|---|
- | ' .. tmp .. ' | - |
"
-- si namespace encyclo (ttl = 0) on insert les catégories d'erreur if (ttl == 0) then local i = 1 while (p.liste_cats[i] ~= nil) do ret = ret .. "" i = i + 1 end end
-- on retourne le résultat return ret
end
--[[
Fonction appelable depuis un modèle. Se contente d'appeler demographie_m() qui fait le traitement et est également appelable depuis un autre module
--]] function p.demographie(frame)
-- pour simplifier on stocke la frame et la pframe p.frame = frame p.pframe = frame:getParent()
-- pm est la table des parametres → on lit tous les paramètres référencés local pm = {} for k, v in pairs(p.parametres) do pm[v] = p.lit_parametre(k, true) end -- les paramètres numériques maintenant (les années) if require('Module:Yesno')(p.pframe.args.wikidata, true, false) then -- obtient les données de wikidata, mais les données locales auront priorité p.valeur_wikidata(pm) mw.logObject( pm, 'pm' ) end for k, v in pairs(p.pframe.args) do if type(k) == "number" then pm[k] = mw.text.trim(v) elseif k:sub(1, 1) ~= "_" then pm[k] = v end end for k, v in pairs(p.frame.args) do if type(k) == "number" then pm[k] = mw.text.trim(v) elseif k:sub(1, 1) ~= "_" then pm[k] = v end end
-- on appelle (et on retourne) la fonction principale return p.demographie_m(pm)
end
return p -- on retourne le module