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.donnees = require("Module:Population de France/Données")
p.outils = require("Module:Population de France/Outils")
p.intro = require("Module:Population de France/Introductions")
-- Fonctions d'erreur, à améliorer
local function NoItem()
return error("Element Wikidata non trouvé")
end
local function NoTable()
return error("table Commons non trouvée")
end
-- Récupération des données Commmons, à partir d'un identifiant Wikidata
local function getData(qid)
if (not qid) then
return NoItem()
end
local filename = wd.formatStatements{entity = qid, property = 'P4179', numval = 1}
local file = mw.ext.data.get(filename)
if (not filename) or (not file) then
return NoTable()
end
return filename, file
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 not (popfield and datefield) 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, fields)
local d = data[fields.date]
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,fieldnames)
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 country == "Q142" then -- France
return keepValFR(data, fieldnames)
end
return true -- on garde par défaut
end
local function notes(data, vnom)
if ((data["division"] == "canton") or (data["division"] == "commune nouvelle") or (data["division"] == "commune en COM1") or
(data["division"] == "commune en COM2") or (data["division"] == "commune en COM3") or (data["division"] == "arrondissement")) then
return nil
elseif (data["division"] == "arrondissement") then
return "De 1962 à 1999 : [[Chiffres de population de la France#Aspect statistique|population sans doubles comptes]] ; " ..
"pour les dates suivantes : [[Chiffres de population de la France#La population municipale|population municipale]]."
elseif (data["division"] == "département") then
return nil
elseif (data["division"] == "région") then
return nil
elseif (data["division"] == "commune en DROM") then
return "De 1961 à 1999 : [[Chiffres de population de la France#Aspect statistique|population sans doubles comptes]] ; " ..
"pour les dates suivantes : [[Chiffres de population de la France#La population municipale|population municipale]]."
else -- le reste
-- peut-être déplacer ce texte dans /Constantes
return "De 1962 à 1999 : [[Chiffres de population de la France#Aspect statistique|population sans doubles comptes]] ; " ..
"pour les dates suivantes : [[Chiffres de population de la France#La population municipale|population municipale]]."
end
end
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"}
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é",
}
-- 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 = 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 un Wikitexte présentant les données de population
function p.introduction_m(param)
local resu
local nom = param["nom"] or mw.title.getCurrentTitle().subpageText
local datafile, donnes = getData(id, 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"])
local country = wd.formatStatements{entity = qid, property = "P17", numval = 1, displayformat = "raw"}
if not (name and qid) then
return error("quelle page ?") -- FIXME
end
local datafile, data = getData(qid, name)
if not (data) then
return p.outils.err_nodata("graphique", data, filename or "pas de fichier")
end
local fieldnames = analyseData(data)
--[[ 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 prm = { }
-- Paramètre requis par Modèle:Histogramme population manuel FIXME avec l'extension graph
local nval, maxpop = 0, 0
-- récupération des données pertinentes de la table
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 year = getYear(j, fieldnames)
local pop = j[fieldnames["population"]]
table.insert(prm, year)
table.insert(prm, pop)
nval, maxpop = nval + 1, math.max(pop, maxpop) -- pour Modèle:Histogramme
end
end
prm["nombre"] = nval
prm["max"] = maxpop
prm["largeur"] = 710
prm["hauteur"] = 340
prm["couleurs"] = "rgb(1,1,1)"
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
local tmp = {}
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 superificie en km2, sous forme de nombre
function p.superficie_m(param)
local qid = getIdAndName(param["id"], param["nom"])
return wd.formatStatements{property = "P2046", displayformat = "raw", targetunit = "sqkm", entity = qid, numval = 1, excludespecal = true}
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