Module:Population
Apparence
La documentation de ce module est générée par le modèle {{Documentation module}}.
Les éditeurs peuvent travailler dans le bac à sable (modifier).
Voir les statistiques d'appel depuis le wikicode sur l'outil wstat et les appels depuis d'autres modules.
local p = {}
--
-- Les modules et sous-modules dont on aura besoin
--
local wd = require "Module:Wikidata"
-- le module démographie
p.demographie = require("Module:Démographie")
-- le module chartes
p.chartes = require("Module:Chartes")
-- on charge les sous-modules
p.constantes = require("Module:Population de France/Constantes")
p.sources = require("Module:Population de France/Sources") -- à simplifier pour avoir juste une liste de textes
p.notes = require("Module:Population de France/Notes")
p.donnees = require("Module:Population de France/Données")
p.outils = require("Module:Population de France/Outils")
p.intro = require("Module:Population de France/Introductions")
local function getData(qid) -- récupère le fichier où sont stockés les données pour une page ou un élément Wikidata
local filename = wd.formatStatements{entity = qid, property = 'P4179', numval = 1}
if not (qid and filename) then
return p.outils.err_nodata("tableau", donnees, filename or "pas de fichier")
end
return filename, mw.ext.data.get(filename)
end
local function getIdAndName(id, name)
if (not id) then -- si pas d'id Wikidata, prendre celui de la page active
id = mw.wikibase.getEntityIdForTitle(name or mw.title.getCurrentTitle().subpageText)
end
if (not name) then
name = wd.getLabel(name) or mw.title.getCurrentTitle().subpageText
end
return id, name
end
local function analyseData(data) -- définit la signification des différents champs de données du fichier
local fields = data.schema.fields
local popfield, datefield, methodfield, criterionfield, sourcefield, sourceurlfield
for num, j in ipairs(fields) do
if string.find(fields[num].name, "P585") then
datefield = num
elseif string.find(fields[num].name, "P1082") then
popfield = num
elseif string.find(fields[num].name, "P1082") then
popfield = num
elseif string.find(fields[num].name, "P459") then
methodfield = num
elseif string.find(fields[num].name, "P1013") then
criterionfield = num
elseif string.find(fields[num].name, "S248") then
sourcefield = num
elseif string.find(fields[num].name, "S248") then
sourceurlfield = num
end
end
-- exits if no field for population or date
if (popfield * datefield == 0) then
return error("data could not be parsed correctly") -- FIXME
end
return {population = popfield, date = datefield, method = methodfield, criterion = criterionfield, source = sourcefield, sourcefield = sourceurlfield}
end
local function getYear(data)
local d = data[datefield]
d = tonumber(d) -- enlève le "+" de départ éventuel
d = tostring(d)
return mw.ustring.sub(d, 1, 4)
end
local function keepValFR(val, fieldnames)
-- recencement, on garde
local method = val[fieldnames.method]
local d = val[fieldnames.date]
if (method == "Q39825") then
return true
end
-- interpolation or exptrapolation du recencement quinquennal, on rejette
if (method == "Q744069") or (method == "Q187631") then
return false
end
-- enquête pour les communes de plus de 10 000 habs
-- on garde 2006, 2011 et 2016
if (method == "Q98415788") then
local year = getYear(d)
if (d == "2006") or (d == "2011") or (d == "2016") then
return true
end
end
return true -- autres méthodes, erreurs ?
end
local function keepVal(data, fieldnames, country)
if true or country == "Q142" then -- France
return keepValFR(data, fieldnames)
end
return true -- on garde par défaut
end
local tableFormat = {
-- on prépare les paramètres à fournir au module Démographie
["largeur_tableau"] = "48em",
["taille_police"] = "95%",
["marge_interlignes"] = "10px",
["hauteur_lignes"] = "110%",
["population_fond"] = "#F9F9F9",
["style_notes"] = "centré",
}
function p.tableau_m(param)
-- le nom de la cible (param. nom ou titre page)
local id, name = getIdAndName(param["wikidata"], param["nom"])
-- récupération et vérification des données
local datafile, data = getData(id, name)
local fieldnames = analyseData(data)
local country = wd.formatStatements{entity = id, property = "P17", numval = 1, displayformat = "raw"}
-- couleur (on passe par Chartes avec un "truc" pour commune nouvelle)
local dest = tableFormat
if (data["division"] == "commune nouvelle") then
dest["annees_fond"] = p.chartes.charte_m("geographie", "secondaire", "commune", true)
else
dest["annees_fond"] = p.chartes.charte_m("geographie", "secondaire", data["division"], true)
end
-- le titre du tableau
dest["titre"] = (param["titre"] or p.constantes.titre_tableau)
.. " <small>[ [[:c:Data:" .. datafile .. "|modifier]] ]</small>"
-- notes FIXME
local tmp = p.notes.notes(data, vnom)
if ((tmp ~= nil) and (mw.text.trim(tmp) ~= "")) then
dest["notes"] = tmp
end
-- sources FIXME
tmp = p.sources.sources(data)
if ((tmp ~= nil) and (mw.text.trim(tmp) ~= "")) then
dest["sources"] = tmp
end
-- récupération des chiffres
for i, j in ipairs(data.data) do
if ( keepVal(j, fieldnames, country) or i == #data.data) then -- on garde les données correspondant au critères + la plus récente
local annee = tonumber(j[fieldnames["date"]])-- A ADAPTER POUR LE CAS OU LA DATE COMPORTE LE MOIS OU LE JOUR
dest[annee] = j[fieldnames["population"]]
end
end
-- on effectue l'appel terminal et on retourne (et on ajoute la catégorie)
return p.demographie.demographie_m(dest) .. p.constantes.cat_usage
end
-- fonction "wrapper" pour la précédente, pour appel depuis un modèle
function p.tableau(frame)
local param = {}
-- deux paramètres : nom et titre
param["nom"] = p.outils.nettoie(frame.args["nom"] or frame:getParent().args["nom"] or nil)
param["titre"] = p.outils.nettoie(frame.args["titre"] or frame:getParent().args["titre"] or nil)
-- on appelle la vraie fonction
return p.tableau_m(param)
end
--[[
Fonction créant une introduction de population de commune
--]]
function p.introduction_m(param)
local resu
local nom = param["nom"] or mw.title.getCurrentTitle().subpageText
local donnees = getData(nom)
-- on charge les données associées à la commune
local data, wlm = p.donnees.charge_donnees(nom)
if (type(wlm) == "number") then
return p.outils.err_nodata("introduction", donnees, wlm)
end
if (data["division"] == "fraction cantonale") then
return p.outils.err_nodata("introduction", donnees, 6) -- pas d'intro pour ça
end
resu = p.intro.introduction(data)
return resu
end
-- fonction "wrapper" pour la fonction précédente, pour appel depuis un modèle
function p.introduction(frame)
local pframe = frame:getParent()
local param = {}
-- récupération de l'unique paramètre (nom)
param["nom"] = p.outils.nettoie(frame.args["nom"] or pframe.args["nom"] or nil)
return p.introduction_m(param)
end
-- fonction de tri utilisée par la fonction suivante
-- tri sur la valeur du 1er élément des éléments
function p.sort_par_annee(el1, el2)
if (el1[1] < el2[1]) then
return true
end
return false
end
--[[
Fonction créant un graphique de population de commune
--]]
function p.graphique_m(param)
local resu
local qid, name = getIdAndName(param["id"], param["nom"])
if not (name and qid) then
return error("quelle page ?") -- FIXME
end
local data = getData(qid, name)
if not (data) then
return p.outils.err_nodata("graphique", data, filename or "pas de fichier")
end
-- seuil (nombre de données) à afficher
param["seuil"] = tonumber(param["seuil"])
if ((param["seuil"] == nil) or (param["seuil"] <= 0)) then
param["seuil"] = 5 -- valeur par défaut
end
local graphLayout = {
-- "Histogramme population manuel" étant un modèle, on fabrique la structure d'appel
-- ici il faudrait modifier "couleur-barres" qui devrait dépendre de la charte…
["largeur"] = 710,
["hauteur"] = 340,
["couleur-fond"] = "rgb(1,1,1)"
}
prm = { }
local cb
if (data["division"] == "commune nouvelle") then
cb = p.chartes.charte_m("geographie", "primaire", "commune", true)
else
cb = p.chartes.charte_m("geographie", "primaire", data["division"], true)
end
cb = p.outils.color2rgb(cb)
if (cb == nil) then
prm["couleur-barres"] = "rgb(0.7,0.9,0.7)" -- couleur "par défaut"
else
prm["couleur-barres"] = "rgb(" .. cb .. ")"
end
prm["nom"] = param["nom"]
prm["titre"] = param["titre"] or p.constantes.titre_graphique
prm["max"] = data["popmax"]
-- parcours des données
local tmp = {}
for annee, pop in pairs(data) do
if (type(annee) == "number") then
-- est-ce qu'on garde l'année ?
if (p.outils.test_annee(annee, data) and (type(pop["pop"]) == "number") and (pop["pop"] > 0)) then
table.insert(tmp, { annee, pop["pop"] })
end
end
end
-- tri des éléments
table.sort(tmp, p.sort_par_annee)
-- on insert année / valeur dans l'ordre (histogramme pop… a besoin des données dans l'ordre)
local nb = 1
local nbp = 0
for k, v in pairs(tmp) do
if (v[2] > 0) then
prm[nb] = v[1]
prm[nb+1] = v[2]
nb = nb + 2
nbp = nbp + 1 -- nombre de barres (réel)
end
end
-- si pas assez de données on ne traite pas
if (nbp < param["seuil"]) then
return "" -- on retourne "rien"
end
prm["nombre"] = nbp
prm["sources"] = p.sources.sources_graphique(data)
-- précaution
if (nbp == 0) then
p.outils.err_nodata("graphique", donnees, 7, true)
end
-- on "appelle" le modèle
return mw.getCurrentFrame():expandTemplate{ title = 'Histogramme population manuel', args = prm }
end
-- fonction "wrapper" pour la fonction précédente, pour appel depuis un modèle
function p.graphique(frame)
local pframe = frame:getParent()
local param = {}
-- récupération des paramètre (nom et titre)
param["nom"] = p.outils.nettoie(frame.args["nom"] or pframe.args["nom"] or nil)
param["titre"] = p.outils.nettoie(frame.args["titre"] or pframe.args["titre"] or nil)
param["seuil"] = p.outils.nettoie(frame.args["seuil"] or pframe.args["seuil"] or nil)
return p.graphique_m(param)
end
--[[
Retourne la dernière population (ou la dernière date) pour la commune "nom" (ou courante)
Si prm[1] est vide retourne la population, sans formatage
Si prm[1] vaut "date", retourne la date
Si prm[1] vaut "nombre", idem premier cas mais avec formatage du nombre
Si prm[1] vaut "table", retourne une table avec l'année en 1er élément et le nombre en 2e élément
--]]
function p.derniere_population_m(prm)
local nom = prm["nom"] or mw.title.getCurrentTitle().subpageText
local data = getData(nil, nom)
if data then
return mw.language.getContentLanguage():formatNum(tmp[2])
end
end
-- fonction "wrapper" pour la fonction précédente, pour appel depuis un modèle
function p.derniere_population(frame)
local pframe = frame:getParent()
local param = {}
-- récupération des paramètre (nom et titre)
param["nom"] = p.outils.nettoie(frame.args[2] or pframe.args[2] or nil)
param["type"] = frame.args[1] or pframe.args[1] or nil
return p.derniere_population_m(param)
end
--[[
Retourne une phrase décrivant la variation de population de la commune
courante (ou "nom") ou un pictograme si "type" = "picto"
--]]
function p.variation_texte_m(prm)
local nom = prm["nom"] or mw.title.getCurrentTitle().subpageText
local donnees = "Module:Données/" .. nom .. "/évolution population"
-- on charge les données associées à la commune
local data, wlm = p.donnees.charge_donnees(nom)
if (type(wlm) == "number") then
return p.outils.err_nodata("variation_texte", donnees, wlm, true)
end
local txt, sens = p.donnees.variation_texte(data)
if (txt == nil) then
return p.outils.err_nodata("variation_texte", donnees, 7, true)
end
if (prm["type"] ~= "picto") then
return txt
end
-- on crée le pictogramme
if (sens > 0) then
return "[[Fichier:Increase2.svg|11px|link=|class=noviewer|" .. txt .. "]]"
elseif (sens < 0) then
return "[[Fichier:Decrease2.svg|11px|link=|class=noviewer|" .. txt .. "]]"
else -- égal
return "[[fichier:steady.svg|10px|link=|class=noviewer|" .. txt .. "]]"
end
end
-- fonction "wrapper" pour la fonction précédente, pour appel depuis un modèle
function p.variation_texte(frame)
local pframe = frame:getParent()
local param = {}
-- récupération des paramètre (nom et titre)
param["nom"] = p.outils.nettoie(frame.args["nom"] or pframe.args["nom"] or nil)
param["type"] = frame.args["type"] or pframe.args["type"] or nil
return p.variation_texte_m(param)
end
--[[
Retourne la densité de la commune. Si "précision" indiquée utilise celle-ci,
sinon précision 1 par défaut
--]]
function p.densite_m(params)
local name, id = getIdAndName( params["nom"], params["id"])
if not id then
return nil -- or error ?
end
-- population et densité par Wikdata. Ou prendre la pop des données tabulaires par cohérence ?
local pop = wd.formatStatements{entity = id, property = 'P1082', numval = 1, displayformat = "raw"}
local area = wd.formatStatements{entity = id, property = 'P2046', numval = 1, targetunit = "sqkm", displayformat = "raw", showunit = "-"}
-- TODO: test supplémentaire pour vérifier que la date et la population portent sur la même date ?
if not (pop and area) then -- FIXME
return p.outils.err_nodata("densite", donnees, 7, true)
end
pop, area = tonumber(pop), tonumber(area)
local prc = 1
if (type(params["précision"]) == "number") then
prc = params["précision"]
end
if (params["format"] ~= nil) then
return mw.language.getContentLanguage():formatNum(p.outils.round(pop / area, prc))
else
return p.outils.round(pop / area, prc)
end
end
-- fonction "wrapper" pour la fonction précédente, pour appel depuis un modèle
function p.densite(frame)
local pframe = frame:getParent()
local param = {}
-- récupération des paramètre (nom et titre)
param["nom"] = p.outils.nettoie(frame.args["nom"] or pframe.args["nom"] or nil)
param["précision"] = tonumber(frame.args["précision"] or pframe.args["précision"] or nil)
param["format"] = frame.args["format"] or pframe.args["format"] or nil
return p.densite_m(param)
end
--[[
Retourne la superficie de la commune.
--]]
function p.superficie_m(prm)
local nom = prm["nom"] or mw.title.getCurrentTitle().subpageText
local donnees = "Module:Données/" .. nom .. "/évolution population"
-- on charge les données associées à la commune
local data, wlm = p.donnees.charge_donnees(nom)
if (type(wlm) == "number") then
return p.outils.err_nodata("superficie", donnees, wlm, true)
end
return (data["superficie"])
end
-- fonction "wrapper" pour la fonction précédente, pour appel depuis un modèle
function p.superficie(frame)
local pframe = frame:getParent()
local param = {}
-- récupération des paramètre (nom et titre)
param["nom"] = p.outils.nettoie(frame.args["nom"] or pframe.args["nom"] or nil)
return p.superficie_m(param)
end
return p