Module:Démographie Québec
La documentation de ce module est générée par le modèle {{Documentation module}}.
Les éditeurs peuvent travailler dans le bac à sable (créer).
Voir les statistiques d'appel depuis le wikicode sur l'outil wstat et les appels depuis d'autres modules.
local p = {}
--------------------------------------------------------------------
-- Normalisation des valeurs P1082
--------------------------------------------------------------------
local function normalizePop(raw)
if type(raw) == "table" and raw.amount then
return tonumber(raw.amount)
end
return tonumber(raw)
end
--------------------------------------------------------------------
-- Extraction des données P1082 + P585 (toutes les déclarations)
--------------------------------------------------------------------
local function getPopData(entityId)
local entity = mw.wikibase.getEntity(entityId)
local statements = entity and entity.claims and entity.claims.P1082 or {}
local data = {}
for _, s in ipairs(statements) do
if s.rank == "normal" or s.rank == "preferred" then
local rawPop = s.mainsnak.datavalue and s.mainsnak.datavalue.value
local pop = normalizePop(rawPop)
local dateQualifier = s.qualifiers and s.qualifiers.P585
if pop and dateQualifier then
for _, q in ipairs(dateQualifier) do
local time = q.datavalue.value.time
local year = tonumber(time:match("(%d%d%d%d)"))
if year then
table.insert(data, { year = year, pop = pop })
end
end
end
end
end
table.sort(data, function(a, b) return a.year < b.year end)
return data
end
--------------------------------------------------------------------
-- Construction du modèle Graphique démographique
--------------------------------------------------------------------
local function buildGraph(data, couleur, anneeMin, largeur, note)
-- Filtrage année min
if anneeMin then
local filtered = {}
for _, v in ipairs(data) do
if v.year >= anneeMin then
table.insert(filtered, v)
end
end
data = filtered
end
if #data == 0 then
return "''Aucune donnée démographique disponible dans Wikidata.''"
end
if #data < 2 then
return "''Données insuffisantes pour générer un graphique.''"
end
local minYear = data[1].year
local maxYear = data[#data].year
local maxPop = 0
for _, v in ipairs(data) do
if v.pop and v.pop > maxPop then
maxPop = v.pop
end
end
local out = {}
table.insert(out, "{{Graphique démographique")
table.insert(out, "| mode = image")
table.insert(out, "| type = tout")
table.insert(out, "| largeur image = " .. largeur)
table.insert(out, "| hauteur image = 300")
table.insert(out, "| épaisseur histogramme = 10")
table.insert(out, "| max pop = " .. maxPop)
table.insert(out, "| année min = " .. minYear)
table.insert(out, "| année max = " .. maxYear)
table.insert(out, "| couleur = " .. couleur)
-- NOTE reçue en paramètre (singulier) → envoyée en "notes" (pluriel)
if note and note ~= "" then
table.insert(out, "| notes = " .. note)
else
table.insert(out, "| notes = Estimation et recensement de la population")
end
for _, v in ipairs(data) do
table.insert(out, "| " .. v.year .. "|" .. v.pop)
end
table.insert(out, "}}")
return table.concat(out, "\n")
end
--------------------------------------------------------------------
-- Fonction publique : Graphique démographique WD
--------------------------------------------------------------------
function p.graphiqueWD(frame)
local args = frame.args
-- Paramètres utilisateur
local titre = args["titre"]
local couleur = args["couleur"] or "#3366cc"
local anneeMin = tonumber(args["année min"])
local largeur = tonumber(args["largeur"]) or 600
local note = args["note"] -- ← réception du paramètre "note"
-- Identification de l’élément Wikidata
local entityId = args.id
if not entityId or entityId == "" then
entityId = mw.wikibase.getEntityIdForCurrentPage()
end
if not entityId then
return "''Impossible d’identifier l’élément Wikidata.''"
end
-- Récupération des données WD
local data = getPopData(entityId)
-- Construction du rendu final
local out = ""
-- Titre centré
if titre and titre ~= "" then
out = out .. '<div style="text-align:center;">\'\'\'' .. titre .. '\'\'\'</div>\n'
end
-- Génération du graphique AVEC note
out = out .. frame:preprocess(buildGraph(data, couleur, anneeMin, largeur, note))
return out
end
--------------------------------------------------------------------
-- TABLEAU HORIZONTAL MULTI‑COLONNES
--------------------------------------------------------------------
function p.tableauHorizontalMulti(frame)
local parent = frame:getParent()
local args = {}
-- On copie d'abord les paramètres du modèle
for k, v in pairs(parent.args) do
if v ~= "" then
args[k] = v
end
end
-- Puis on écrase avec les paramètres passés directement à #invoke
for k, v in pairs(frame.args) do
if v ~= "" then
args[k] = v
end
end
----------------------------------------------------------------
-- 2) Normalisation des notes
local newArgs = {}
for k, v in pairs(args) do
local key = tostring(k)
-- Trim des espaces invisibles
key = mw.text.trim(key)
-- Normalisation des espaces spéciaux
key = key:gsub("\194\160", " ") -- U+00A0
key = key:gsub("\226\128\175", " ") -- U+202F
key = key:gsub("\226\128\137", " ") -- U+2009
key = key:gsub("\226\128\131", " ") -- U+2003
key = key:gsub("\226\128\130", " ") -- U+2002
-- Détection d'année
local year = key:match("(%d%d%d%d)$")
if year then
-- Toutes les formes possibles
if key:match("^note" .. year .. "$") -- note2001
or key:match("^notes" .. year .. "$") -- notes2001
or key:match("^note[%s%-%_]+" .. year .. "$") -- note 2001, note-2001, note_2001
or key:match("^notes[%s%-%_]+" .. year .. "$") then
newArgs["note" .. year] = v
else
newArgs[key] = v
end
else
newArgs[key] = v
end
end
args = newArgs
----------------------------------------------------------------
-- 3) Paramètres d'affichage
----------------------------------------------------------------
local showEstimations = (args.estimations == "oui")
local source = args.source
if not source or source == "" then
source = "[[Statistique Canada]]"
end
local MAX_COLS = tonumber(args.colonnes) or 12
if MAX_COLS < 1 then MAX_COLS = 1 end
if MAX_COLS > 12 then MAX_COLS = 12 end
local title = args.titre
if not title or title == "" then
title = "Évolution démographique"
end
local year_color = args.couleur
if not year_color or year_color == "" then
year_color = "#ddffdd"
end
----------------------------------------------------------------
-- 4) Récupération Wikidata
----------------------------------------------------------------
local entityId = mw.wikibase.getEntityIdForCurrentPage()
if not entityId then
return "Données Wikidata introuvables."
end
local entity = mw.wikibase.getEntity(entityId)
if not entity or not entity.claims or not entity.claims.P1082 then
return "Aucune donnée de population disponible."
end
----------------------------------------------------------------
-- 5) Construction des lignes
----------------------------------------------------------------
local rows = {}
for _, statement in ipairs(entity.claims.P1082 or {}) do
if statement.rank == "normal" or statement.rank == "preferred" then
local mainsnak = statement.mainsnak
if mainsnak and mainsnak.datavalue then
local raw = mainsnak.datavalue.value
local popNum =
(type(raw) == "table" and tonumber(raw.amount))
or tonumber(raw)
if popNum then
local qualifiers = statement.qualifiers or {}
-- Date
local date = qualifiers.P585
and qualifiers.P585[1]
and qualifiers.P585[1].datavalue
and qualifiers.P585[1].datavalue.value.time
local year = date and mw.ustring.match(date, "%d%d%d%d")
year = tonumber(year)
if year and (year % 5 ~= 1) then
year = nil
end
-- Méthode
local method = nil
if qualifiers.P459
and qualifiers.P459[1]
and qualifiers.P459[1].datavalue
and qualifiers.P459[1].datavalue.value
and qualifiers.P459[1].datavalue.value.id then
method = qualifiers.P459[1].datavalue.value.id
end
local keep = true
if method == "Q29051383" and not showEstimations then
keep = false
end
-- Références
local references = statement.references or {}
local url = nil
for _, ref in ipairs(references) do
if ref.snaks and ref.snaks.P854 and ref.snaks.P854[1]
and ref.snaks.P854[1].datavalue then
url = ref.snaks.P854[1].datavalue.value
break
end
end
if year and keep then
----------------------------------------------------------------
-- Gestion populationYYYY + noteYYYY
----------------------------------------------------------------
local manualPopKey = "population" .. tostring(year)
local manualNoteKey = "note" .. tostring(year)
local manualPop = args[manualPopKey]
local manualNote = args[manualNoteKey]
-- Détection d’un <ref> dans la population manuelle
local extractedPop, extractedNote = nil, nil
if manualPop then
extractedPop, extractedNote = manualPop:match("^(.-)(<ref.*)$")
end
-- Note finale
local finalNote = nil
if manualNote and manualNote ~= "" then
finalNote = manualNote
elseif extractedNote and extractedNote ~= "" then
finalNote = extractedNote
end
-- Population finale (WD uniquement)
local popValue = popNum
----------------------------------------------------------------
-- Séparation URL brute / URL pour <ref group="Source">
----------------------------------------------------------------
local rawUrl = url -- affichée dans la cellule
local refUrl = nil -- utilisée dans les références
if url and year then
refUrl = string.format("[%s Recensement %d]", url, year)
end
----------------------------------------------------------------
-- Ajout final
----------------------------------------------------------------
table.insert(rows, {
year = year,
pop = popValue,
note = finalNote,
url = rawUrl, -- cellule
ref = refUrl, -- <ref group="Source">
manual = (manualPop ~= nil and manualPop ~= "")
})
end
end
end
end
end
----------------------------------------------------------------
-- 6) Filtrage, tri, affichage
----------------------------------------------------------------
if #rows == 0 then
return "Aucune donnée de recensement valide disponible."
end
table.sort(rows, function(a, b) return a.year < b.year end)
local filtered = {}
for _, r in ipairs(rows) do
if r.year >= 1956 then
table.insert(filtered, r)
end
end
rows = filtered
if #rows == 0 then
return ""
end
local langObj = mw.language.new("fr")
local out = '{| class="wikitable centre" style="text-align:center; white-space:nowrap;"\n'
local invisibleSources = ""
out = out .. '|+ style="background:#ffffff; font-weight:bold;" | ' .. title .. '\n'
local N = #rows
----------------------------------------------------------------
-- CAS 1 : tableau large (plus de 12 colonnes)
----------------------------------------------------------------
if N > 12 then
local mid = math.ceil(N / 2)
local function printBlock(startIdx, endIdx)
-- Ligne des années
out = out .. "|-\n"
for i = startIdx, endIdx do
local r = rows[i]
local yearText
if r.url then
yearText = '<span class="plainlinks">[' .. r.url .. ' \'\'\'' .. r.year .. '\'\'\' ]</span>'
else
yearText = "'''" .. r.year .. "'''"
end
if r.url then
invisibleSources = invisibleSources .. frame:extensionTag("ref", "Source : " .. r.url, { group = "sources" })
end
if i == startIdx then
out = out .. '| style="background:' .. year_color .. ';" | ' .. yearText
else
out = out .. ' || style="background:' .. year_color .. ';" | ' .. yearText
end
end
out = out .. "\n"
-- Ligne des populations + notes
out = out .. "|-\n"
for i = startIdx, endIdx do
local r = rows[i]
-- Sécurisation : pop ne doit jamais être nil
local pop
if r.manual then
pop = r.pop or ""
else
if r.pop then
pop = langObj:formatNum(r.pop)
else
pop = ""
end
end
-- Ajout de la note sous forme de <ref>
if r.note and r.note ~= "" then
pop = pop .. " " .. frame:extensionTag("ref", r.note)
end
if i == startIdx then
out = out .. '| style="background:#f3fff3;" | ' .. pop
else
out = out .. ' || style="background:#f3fff3;" | ' .. pop
end
end
out = out .. "\n"
end
printBlock(1, mid)
printBlock(mid + 1, N)
out = out .. '|-\n| colspan="' .. mid .. '" style="text-align:center; font-size:90%; background:#f3fff3;" | Source : ' .. source .. '\n'
out = out .. "|}"
return out
end
----------------------------------------------------------------
-- CAS 2 : tableau normal (MAX_COLS)
----------------------------------------------------------------
for i = 1, N, MAX_COLS do
local block = {}
for j = i, math.min(i + MAX_COLS - 1, N) do
table.insert(block, rows[j])
end
-- Ligne des années
out = out .. "|-\n"
for k, r in ipairs(block) do
local yearText
if r.url then
yearText = '<span class="plainlinks">[' .. r.url .. ' \'\'\'' .. r.year .. '\'\'\' ]</span>'
else
yearText = "'''" .. r.year .. "'''"
end
if r.url then
invisibleSources = invisibleSources .. frame:extensionTag("ref", r.ref, { group = "sources" })
end
if k == 1 then
out = out .. '| style="background:' .. year_color .. ';" | ' .. yearText
else
out = out .. ' || style="background:' .. year_color .. ';" | ' .. yearText
end
end
out = out .. "\n"
-- Ligne des populations + notes
out = out .. "|-\n"
for k, r in ipairs(block) do
local pop
if r.manual then
pop = r.pop or ""
else
if r.pop then
pop = langObj:formatNum(r.pop)
else
pop = ""
end
end
if r.note and r.note ~= "" then
pop = pop .. " " .. frame:extensionTag("ref", r.note)
end
if k == 1 then
out = out .. '| style="background:#f3fff3;" | ' .. pop
else
out = out .. ' || style="background:#f3fff3;" | ' .. pop
end
end
out = out .. "\n"
end
out = out .. '|-\n| colspan="' .. MAX_COLS .. '" style="text-align:center; font-size:90%; background:#f3fff3;" | Source : ' .. source .. '\n'
out = out .. "|}"
return frame:preprocess(out)
end
return p