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"
local mathmod = require "Module:math"
local chartes = require "Module:Chartes"
local demographie = require "Module:Démographie"
-- sous-modules
p.intro = require("Module:Population de France/Introductions")
local texts = {
["no item"] = "élément Wikidata non trouvé pour le $param",
["no datatable"] = "page de table de donnée trouvée pour l'élément $param",
["invalid datatable"] = "la page de données $param n'a pas pu être correctement analysée",
["missing param"] = "paramètre manquant : $param",
["error"] = "erreur dans Module:Population",
["errorcat"] = "Page avec un problème sur les donnnées démographiques",
["decrease"] = "en diminution de $num par rapport à $date",
["increase"] = "en augmentation de $num par rapport à $date",
["stable"] = "en stagnation par rapport à $date",
["cat"] = "Article avec module Population de France",
["graph title"] = "Histogramme de l'évolution démographique",
["table title"] = "Évolution de la population",
["source file"] = "Fichier utilisé : [[commons:Data:$1]]."
}
-- Fonctions d'erreur
local function err(errtype,param)
local cat, msg
-- message à afficher sur la page
if errtype == "no item" then
msg = texts["no item"]
elseif errtype == "no datatable" then
msg = texts["no datatable"]
elseif errtype then
msg = texts[errtype] or errtype
else
msg = texts["error"]
end
-- catégorie de maintenance à ajouter à la page
-- une seule catégorie d'erreur. Plus simple et suffisant ?
cat = texts["errorcat"]
if cat then
cat = "[[Category:" .. cat .. "]]"
end
if msg then
msg = '<span style="color:red">' .. mw.ustring.gsub(msg, "$param", (param or "")) .. "</span>"
end
return (msg or "") .. (cat or "")
end
local function sources(data, country) -- TODO
-- todo
end
local function sources_graphique(data, country)
-- todo
end
-- Récupération des données Commmons, à partir d'un identifiant Wikidata
local function getTable(qid)
if (not qid) then
return nil
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 nil
end
return filename, file
end
local function keepVal(val, fields, params)
return true
end
local function filterVals(data, fields, filters)
local year, month, day
for i, datapoint in pairs(data.data) do
if frequency == 'yearly' then
local f = string.gmatch(str, '%d+') -- analyse des dates ISO utliliser [[Module:Date complexe]] ?
local y, m, d = f(), f(), f()
if y and year then
if (y - year == 0) then
table.remove(data, i)
i = i - 1 if true then return error("hello") end
break
end
end
if (not keepVal(val, fields, params)) then
table.remove(data, i)
i = i - 1
end
end
end
return data
end
-- essai de récupération du nom de l'entité géographique et de son identifiant Wikidata, en fonction des infos disponibles
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
-- Cherche le numéro de colonne du fichier Commons pour les différentes infos nécessaires
local function analyseData(data)
local fields = data.schema.fields
local fieldnums = {}
for num, j in ipairs(fields) do
if string.find(fields[num].name, "P585") then
fieldnums["date"] = num
elseif string.find(fields[num].name, "P1082") then
fieldnums["population"] = num
elseif string.find(fields[num].name, "P459") then
fieldnums["method"] = num
elseif string.find(fields[num].name, "P1013") then
fieldnums["criterion"] = num
elseif string.find(fields[num].name, "S248") then
fieldnums["source"] = num
elseif string.find(fields[num].name, "S854") then
fieldnums["sourceurl"] = num
end
end
-- exits if no field for population or date
if not (fieldnums["population"] and fieldnums["date"]) then
return error()
end
return fieldnums
end
-- extrait l'année d'une date en format pseudoISO, à améliorer
local function getYear(data, fields)
local d = data[fields.date]
d = string.gsub(d, "+", "")
return string.sub(d, 1, 4)
end
local function notes(data, vnom, country)
return nil
end
local function clean(val)
if (val == nil) then
return val
end
if (type(val) ~= "string") then
return val
end
if ( mw.text.trim(val) == "") then
return nil
end
return val
end
local function getData(id, name)
local id, name = getIdAndName(id, name)
if (not id) then
return error(), "no item", name
end
local datafile, data = getTable(id, name)
if not (datafile and data) then
return error(), "no datable", id
end
local fields = analyseData (data)
if (not fields) or (fields == nil) then
return error(), "invalid datatable", datafile
end
return name, id, datafile, data, fields
end
function p.tableau_m(param)
local dataloaded, name, id, datafile, data, fields = pcall(getData, param["id"], param["nom"])
if not dataloaded then
return err(name, id) -- retourne une erreur avec les deux paramètres retournés en cas d'erreur par la fonction getData
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é",
}
-- couleur (on passe par Chartes avec un "truc" pour commune nouvelle)
local dest = tableFormat
if (data["division"] == "commune nouvelle") then
dest["annees_fond"] = chartes.charte_m("geographie", "secondaire", "commune", true)
else
dest["annees_fond"] = chartes.charte_m("geographie", "secondaire", data["division"], true)
end
-- le titre du tableau
dest["titre"] = (param["titre"] or texts["table title"])
-- sélection des données
local wantedvals = filterVals(data, fields, params)
-- passage des paramètres au tableau
for i, datapoint in pairs(wantedvals.data) do
local year = tonumber(getYear(datapoint, fields))
dest[year] = datapoint[fields["population"]]
end
-- on effectue l'appel terminal et on retourne (et on ajoute la catégorie)
return demographie.demographie_m(dest) .. "[[Category:" .. texts["cat"] .. "]]"
end
-- fonction "wrapper" pour la précédente, pour appel depuis un modèle
function p.tableau(frame)
local pframe = frame:getParent()
local param = {}
param["nom"] = clean(frame.args["nom"] or pframe.args["nom"] or nil)
param["id"] = clean(frame.args["id"] or pframe.args["id"] or nil)
param["titre"] = clean(frame.args["titre"] or pframe.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)
if true then return
"todo : textes d'intro "
end
local resu
-- le nom de la cible (param. nom ou titre page)
local id, name = getIdAndName(param["id"], param["nom"])
if not id then return
err("no item", name)
end
local datafile, data = getTable(id, name)
local success, fields = pcall(analyseData, data)
if (not success) or (fields == nil) then
return err("invalid datatable", datafile)
end
local country = wd.formatStatements{entity = id, property = "P17", numval = 1, displayformat = "raw"}
if country == "Q142" then
return require "Module:Population/France".introduction(param, id)
end
return nil
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 = {}
param["nom"] = clean(frame.args["nom"] or pframe.args["nom"] or nil)
param["id"] = clean(frame.args["id"] or pframe.args["id"] or nil)
return p.introduction_m(param)
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 = {}
param["nom"] = clean(frame.args["nom"] or pframe.args["nom"] or nil)
param["id"] = clean(frame.args["id"] or pframe.args["nom"] or nil)
param["titre"] = clean(frame.args["titre"] or pframe.args["titre"] or nil)
param["seuil"] = clean(frame.args["seuil"] or pframe.args["seuil"] or nil)
return p.graphique_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(param)
local dataloaded, name, id, datafile, data, fields = pcall(getData, param["id"], param["nom"])
if not dataloaded then
return err(name, id) -- retourne une erreur avec les deux paramètres retournés en cas d'erreur par la fonction getData
end
local pop = data.data[#data.data][fields.population]
local year = getYear( data.data[#data.data], fields)
local prevyear, prevpop
for i, j in ipairs(data.data) do
local d = getYear( data.data[#data.data +1 -i], fields)
if (year - d) == 5 then
prevyear = d
prevpop = data.data[#data.data +1 -i][fields.population]
break
end
end
if not (prevpop and prevyear) then
return err("invalid datatable", datafile)
end
local pctdiff = mathmod._round(100 * (pop - prevpop)/prevpop, 2)
local txt
if pctdiff > 0 then
txt = texts["increase"]
elseif pctdiff < 0 then
txt = texts["decrease"]
pctdiff = - pctdiff
else
txt = texts["stagnation"]
end
txt = mw.ustring.gsub(txt, "$date", year)
txt = mw.ustring.gsub(txt, "$num", mw.language.getContentLanguage():formatNum(pctdiff) .. "%")
if (param["type"] ~= "picto") then
return txt
end
-- on crée le pictogramme
if (pctdiff > 0) then
return "[[Fichier:Increase2.svg|11px|link=|class=noviewer|" .. txt .. "]]"
elseif (pctdiff < 0) then
return "[[Fichier:Decrease2.svg|11px|link=|class=noviewer|" .. txt .. "]]"
else -- stagnation
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 = {}
param["nom"] = clean(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
function p.graphique_m(params)
local resu
local dataloaded, name, id, datafile, data, fields = pcall(getData, params["id"], params["nom"])
if not dataloaded then
return err(name, id) -- retourne une erreur avec les deux paramètres retournés en cas d'erreur par la fonction getData
end
local years, pops = {}, {}
-- filtre de données
params.frequency = params.frequency or 'yearly'-- fréquence maximale des données
local wantedvals = filterVals(data, fields, params)
for i, datapoint in pairs(wantedvals.data) do
local year = tonumber(getYear(datapoint, fields))
local pop = datapoint[fields["population"]]
table.insert(years, year)
table.insert(pops, pop)
end
-- rendu du module par [[Template:Graph:Chart]] à Lua-iser
years, pops = table.concat(years, ","), table.concat(pops, ",")
local graph = mw.getCurrentFrame():expandTemplate({
title = "Graph:Chart",
args = {
x = years,
y = pops,
width = params.width or "600",
height = params.height or "340",
colors = params.colors or "green",
linewidth = params.linewidth,
showSymbols = params.showSymbols,
symbolsShape = params.symbolsShape or "cross",
yAxisMin= params.yAxisMin or 0,
yGrid = years
}}
)
local sourcestr = mw.ustring.gsub(texts["source file"] , "$1", datafile)
sourcestr = sourcestr .. " (TODO : mise en forme des sources)"
-- rendu final : div html comprenant le graph lui même + le titre et les sources
local out =
mw.html.create("div")
:tag('div')
:css{['text-align'] = 'center'}
:wikitext(params.titre or texts["graph title"])
:done()
:tag('div')
:wikitext(graph)
:done()
:tag('div')
:wikitext(sourcestr)
:done()
:allDone()
return tostring(out)
end
-- fonction "wrapper" pour la fonction précédente, pour appel depuis un modèle
function p.graphique_test(frame)
--local pframe = frame:getParent()
return p.graphique_m(frame.args)
end
return p