Module:Suivi des biographies : Différence entre versions

De Lagny-sur-Marne Wiki
Aller à : navigation, rechercher
(Évite d'analyser plusieurs fois le même élément, car parfois ça se répète un peu (ex. Angelo Chiappe qui dépasse les 500 fonctions couteuses autorisées))
 
(34 révisions intermédiaires par 3 utilisateurs non affichées)
Ligne 18 : Ligne 18 :
 
   (ou référencé par un 'identique à').
 
   (ou référencé par un 'identique à').
 
   Fait au maximum 'prof' itérations.
 
   Fait au maximum 'prof' itérations.
   Retourne 'nil' si rien n'est trouvé.
+
   Retourne 'nil' ou une table vide si rien n'est trouvé
 
]]--
 
]]--
function p.cherche_parents(el, prof)
+
function p.cherche_parents(el, prof, checked)
 
if (prof <= 0) then
 
if (prof <= 0) then
 
return nil  -- fin de récursion
 
return nil  -- fin de récursion
 
end
 
end
 
 
 +
-- évite de vérifier deux fois le même élément
 +
if type(checked) ~= 'table' then
 +
checked = {}
 +
end
 +
if checked[el] then
 +
return nil
 +
else
 +
checked[el] = true
 +
end
 +
 
-- si l'élément courant est dans la table on le retourne (récursion)
 
-- si l'élément courant est dans la table on le retourne (récursion)
 
if (data.association[el] ~= nil) then
 
if (data.association[el] ~= nil) then
 
return el
 
return el
 +
end
 +
 +
-- si l'élément n'est pas une entity valide on quitte
 +
if not el:match( '^Q%d+$' ) then
 +
return nil
 
end
 
end
 
 
Ligne 63 : Ligne 78 :
 
   trouvés à partir de la propriété 'property' pour l'entité 'entity' (ou l'article
 
   trouvés à partir de la propriété 'property' pour l'entité 'entity' (ou l'article
 
   courant si 'entity' vaut 'nil')
 
   courant si 'entity' vaut 'nil')
  si une propriété présente n'est pas référencée ???
 
 
]]--
 
]]--
 
function p.propriete_parente(property, entity)
 
function p.propriete_parente(property, entity)
Ligne 80 : Ligne 94 :
 
-- on parcours tous les résultats à la recherche de ceux qui sont dans la
 
-- on parcours tous les résultats à la recherche de ceux qui sont dans la
 
-- liste 'association' ou ayant un élément fils de l'un d'entre eux
 
-- liste 'association' ou ayant un élément fils de l'un d'entre eux
 +
local checked = {}
 
for k, v in pairs(res) do
 
for k, v in pairs(res) do
 
-- si l'élément est présent on l'insert directement
 
-- si l'élément est présent on l'insert directement
 +
checked[k] = true
 
if (data.association[v] ~= nil) then
 
if (data.association[v] ~= nil) then
 
table.insert(out, v)
 
table.insert(out, v)
Ligne 87 : Ligne 103 :
 
-- on cherche "récursivement" chez les parents
 
-- on cherche "récursivement" chez les parents
 
-- la valeur numérique est la profondeur max de recherche
 
-- la valeur numérique est la profondeur max de recherche
local d = p.cherche_parents(v, 4)
+
local d = p.cherche_parents(v, 10, checked)
 
if (d ~= nil) then
 
if (d ~= nil) then
 
table.insert(out, d)
 
table.insert(out, d)
Ligne 176 : Ligne 192 :
 
   Ne reçoit actuellement aucun paramètre
 
   Ne reçoit actuellement aucun paramètre
 
]]--
 
]]--
function p.nature(frame)
 
local args = { ["property"] = "P31", link = "-", displayformat = "raw" }
 
if (entity ~= nil) then
 
args["entity"] = entity
 
end
 
local res = wd.stringTable(args)
 
 
-- pas de résultat, cette propriété WD est absente je présume
 
if (res == nil) then
 
return res
 
end
 
-- on parcours les résultats pour voir si celle qu'on veut est là
 
        local retour = "nature "
 
for k, v in pairs(res) do
 
                retour = retour .. v
 
if (v == "Q20643955") then
 
return true  -- trouvé
 
end
 
end
 
return retour
 
end
 
 
 
function p.categorise(frame)
 
function p.categorise(frame)
 
-- si on n'est pas dans l'espace encyclopédique on ne fait rien
 
-- si on n'est pas dans l'espace encyclopédique on ne fait rien
Ligne 242 : Ligne 236 :
 
else
 
else
 
-- catégorie par défaut
 
-- catégorie par défaut
return "[[Catégorie:Portail:Biographie/Articles liés/Général]]"
+
return mwd[1]
 
end
 
end
 
return "" -- on ne devrait pas arriver ici
 
return "" -- on ne devrait pas arriver ici
Ligne 264 : Ligne 258 :
 
local awd = p.a_wikidata(nil)
 
local awd = p.a_wikidata(nil)
 
if (not awd) then
 
if (not awd) then
-- on catégorise et on quitte
 
 
return data.cat_badwd
 
return data.cat_badwd
 
end
 
end
+
-- on regarde si la page a une nature de l'élément définie
 +
local nature = wd.formatStatements{property = 'P31', displayformat = 'raw'}
 +
if (not nature) then
 +
                -- on retourne un texte vide, donc l'action est inexistante
 +
return ""
 +
end
 +
 
 +
-- pour cumuler les éléments à retourner
 +
local out = data.cat_biographie
 +
 
 
-- on regarde si c'est un humain
 
-- on regarde si c'est un humain
 
local hwd = p.presence_propriete("P31", "Q5", nil)
 
local hwd = p.presence_propriete("P31", "Q5", nil)
 
if (not hwd) then
 
if (not hwd) then
-- on catégorise et on quitte
+
-- traitement spécifique pour les personnages humains de la Bible
return data.cat_badcall
+
local awd2 = p.presence_propriete("P31", "Q20643955", nil)
 +
                  -- traitement spécifique pour les humains possiblement fictifs
 +
                  local awd3 = p.presence_propriete("P31", "Q21070568", nil)
 +
if (awd2 or awd3) then
 +
        -- catégorisation dans Croyance et religion
 +
return out .. data.cat_religion
 +
else
 +
                        -- on retourne un texte vide, donc l'action est inexistante
 +
return ""
 +
end
 
end
 
end
 
 
-- pour cumuler les éléments à retourner (maintenant on sait que c'est une biographie)
 
local out = data.cat_biographie
 
 
 
 +
-- On est sur une biographie, on affine la catégorisation
 
-- là il faut aller plus loin et récupérer les métiers pour catégoriser
 
-- là il faut aller plus loin et récupérer les métiers pour catégoriser
 
local mwd = p.propriete_parente("P106", nil)
 
local mwd = p.propriete_parente("P106", nil)
Ligne 284 : Ligne 294 :
 
-- on catégorise
 
-- on catégorise
 
                   -- traitement spécifique pour les personnages humains de la Bible
 
                   -- traitement spécifique pour les personnages humains de la Bible
                    local hwd2 = p.presence_propriete("P31", "Q20643955", nil)
+
                  local hwd2 = p.presence_propriete("P31", "Q20643955", nil)
            if (hwd2) then
+
          if (hwd2) then
          -- catégorisation dans Religion
+
        -- catégorisation dans Religion
                          return out .. data.cat_bible
+
                        out = out .. data.cat_religion
            else
+
          else
                          return out .. data.cat_defaut
+
                        return out .. data.cat_defaut
                    end
+
                  end
  
 
else
 
else
Ligne 301 : Ligne 311 :
 
-- si 0 catégorie insérée on met celle par défaut
 
-- si 0 catégorie insérée on met celle par défaut
 
if (nb == 0) then
 
if (nb == 0) then
                    -- traitement spécifique pour les personnages humains de la Bible
+
-- traitement spécifique pour les personnages humains de la Bible
                    local hwd3 = p.presence_propriete("P31", "Q20643955", nil)
+
                        local hwd4 = p.presence_propriete("P31", "Q20643955", nil)
            if (hwd3) then
+
                  if (hwd4) then
          -- catégorisation dans Religion
+
  -- catégorisation dans Religion
                          return out .. data.cat_bible
+
return out .. data.cat_religion
            else
+
else
out = out .. data.cat_defaut
+
out = out .. data.cat_defaut
                    end
+
end
 
end
 
end
end
 
        -- ajout du cas particulier des personnages humains de la Bible
 
        local hwd4 = p.presence_propriete("P31", "Q20643955", nil)
 
        if (hwd4) then
 
  -- catégorisation dans Religion
 
          out = out .. data.cat_bible
 
 
end
 
end
  

Version actuelle datée du 17 avril 2017 à 09:51

La documentation pour ce module peut être créée à Module:Suivi des biographies/doc

--[[
Module servant au modèle:Suivi des biographies.

Ce module catégorise les biographies.
--]]

local p = {}

-- module wikidata
local wd = require 'Module:Wikidata'

-- les données associées
local data = require "Module:Suivi des biographies/données"

--[[
  fonction parcourant les "parents" de l'élément indiqué et retournant
  le premier élément présent dans la table 'association' durant ce processus
  (ou référencé par un 'identique à').
  Fait au maximum 'prof' itérations.
  Retourne 'nil' ou une table vide si rien n'est trouvé
]]--
function p.cherche_parents(el, prof, checked)
	if (prof <= 0) then
		return nil  -- fin de récursion
	end
	
	-- évite de vérifier deux fois le même élément
	if type(checked) ~= 'table' then
		checked = {}
	end
	if checked[el] then
		return nil
	else
		checked[el] = true
	end
		
	-- si l'élément courant est dans la table on le retourne (récursion)
	if (data.association[el] ~= nil) then
		return el
	end
	
	-- si l'élément n'est pas une entity valide on quitte
	if not el:match( '^Q%d+$' ) then
		return nil
	end
	
	-- on récupère les P460 (réputé identique à) au cas où
	local args = { ["property"] = "P460", ["entity"] = el, link = "-", displayformat = "raw" }
	local id = wd.stringTable(args)
	if (id ~= nil) then
		-- correspond ?
		for k, v in pairs(id) do
			if (data.association[v] ~= nil) then
				return v  -- trouvé, on quitte
			end
		end
	end
	-- si on arrive ici c'est qu'il n'a pas d'équivalence. On parcours
	-- les "sous-classe de" (P279) récursivement
	args = { ["property"] = "P279", ["entity"] = el, link = "-", displayformat = "raw" }
	id = wd.stringTable(args)
	if (id ~= nil) then
		-- pour chaque "sur-classe" on se ré-appelle
		local ret
		for k, v in pairs(id) do
			ret = p.cherche_parents(v, prof-1)
			if (ret ~= nil) then
				return ret
			end
		end
	end
	-- ici on n'a rien trouvé → nil
	return nil
end

--[[
  fonction retournant une liste des éléments de la table 'p.association'
  trouvés à partir de la propriété 'property' pour l'entité 'entity' (ou l'article
  courant si 'entity' vaut 'nil')
]]--
function p.propriete_parente(property, entity)
	local args = { ["property"] = property, link = "-", displayformat = "raw" }
	local out = {} -- table des résultats
	if (entity ~= nil) then
		args["entity"] = entity
	end
	local res = wd.stringTable(args)
	
	-- si aucun résultat on retourne nil
	if (type(res) ~= "table") then
		return nil
	end
	
	-- on parcours tous les résultats à la recherche de ceux qui sont dans la
	-- liste 'association' ou ayant un élément fils de l'un d'entre eux
	local checked = {}
	for k, v in pairs(res) do
		-- si l'élément est présent on l'insert directement
		checked[k] = true
		if (data.association[v] ~= nil) then
			table.insert(out, v)
		else
			-- on cherche "récursivement" chez les parents
			-- la valeur numérique est la profondeur max de recherche
			local d = p.cherche_parents(v, 10, checked)
			if (d ~= nil) then
				table.insert(out, d)
			end
		end
	end
	
	return out	
end

--[[
  fonction retournant true si la valeur 'value' est présente dans la liste des
  propriétés 'property' pour l'entité 'entity' (ou l'article courant si 'entity'
  vaut 'nil')
  retourne false sinon
]]--
function p.presence_propriete(property, value, entity)
	local args = { ["property"] = property, link = "-", displayformat = "raw" }
	if (entity ~= nil) then
		args["entity"] = entity
	end
	local res = wd.stringTable(args)
	
	-- pas de résultat, cette propriété WD est absente je présume
	if (res == nil) then
		return false
	end
	-- on parcours les résultats pour voir si celle qu'on veut est là
	for k, v in pairs(res) do
		if (v == value) then
			return true  -- trouvé
		end
	end
	return false -- pas trouvé
end

-- dédoublonne le contenu
function p.dedoublonne(tbl)
	if (type(tbl) ~= "table") then
		return tbl
	end
	local out = {}
	local tmp = {}
	for k, v in ipairs(tbl) do
		if (tmp[v] == nil) then
			table.insert(out, v)
			tmp[v] = true
		end
	end
	return out
end

-- conversion affichage d'une liste de 'association'
function p.affiche_elements(tbl)
	local ret = ""
	for k, v in ipairs(tbl) do
		ret = ret .. data.association[v]["texte"] .. " (" .. v .. ") "
	end
	return ret
end


--[[
  fonction qui retourne true si un élément wikidata existe pour l'article
  courant (ou l'élément 'entity' si différent de 'nil') et false sinon
  Note : le paramètre 'entity' n'a pas de sens, c'est juste pour du test. En
         effet si on a une 'entity' c'est que ça existe…
]]--
function p.a_wikidata(entity)
	if (entity == nil) then
		if (mw.wikibase.getEntity() ~= nil) then
			return true
		else
			return false
		end
	else -- cette partie disparaitra
		if (mw.wikibase.getEntity(entity) ~= nil) then
			return true
		else
			return false
		end
	end
end


--[[
  Fonction externe (appelable) qui catégorise l'article courant en fonction de WD
  Ne reçoit actuellement aucun paramètre
]]--
function p.categorise(frame)
	-- si on n'est pas dans l'espace encyclopédique on ne fait rien
	local titre = mw.title.getCurrentTitle()
	if ((titre == nil) or (titre.namespace ~= 0)) then
		return ""  -- on retourne un texte vide, donc l'action est inexistante
	end
	
	-- on regarde si la page a une entrée wikidata
	local awd = p.a_wikidata(nil)
	if (not awd) then
		-- on catégorise et on quitte
		return "[[Catégorie:Wikipédia:Article sans Wikidata appelant le modèle Suivi des biographies]]"
	end
	
	-- on regarde si c'est un humain
	local hwd = p.presence_propriete("P31", "Q5", nil)
	if (not hwd) then
		-- on catégorise et on quitte
		return "[[Catégorie:Wikipédia:Article non biographique appelant le modèle Suivi des biographies]]"
	end
	
	-- là il faut aller plus loin et récupérer les métiers pour catégoriser
	local mwd = p.propriete_parente("P106", nil)
	-- si aucune réponse on le place dans "autres"
	if (mwd == nil) then
		-- on catégorise et on quitte
		return "[[Catégorie:Portail:Biographie/Articles liés/Général]]"
	end
	-- on a (au moins) une réponse : on regarde ce que contient le 1er élément (le "principal")
	--[[ note : on pourrait faire du multi-catégorie (ne pas utiliser de else/elseif alors
	              mais "cumuler" diverses catégories et retourner le tout à la fin)
	            on pourrait aussi faire des tests plus complexes du style si militaire et pas
	              homme politique alors faire ci sinon si cela faire ça…
	]]--  
	if (mwd[1] == "Q483501") then
		return "[[Catégorie:Portail:Biographie/Articles liés/Culture et arts]]"
	elseif (mwd[1] == "Q47064") then
		return "[[Catégorie:Portail:Biographie/Articles liés/Militaire]]"
	elseif (mwd[1] == "Q82955") then
		return "[[Catégorie:Portail:Biographie/Articles liés/Politique]]"
	elseif (mwd[1] == "Q2066131") then
		return "[[Catégorie:Portail:Biographie/Articles liés/Sport]]"
	else
		-- catégorie par défaut
		return mwd[1]
	end
	return "" -- on ne devrait pas arriver ici
end



--[[
  Fonction externe (appelable) qui catégorise l'article courant en fonction de WD
  Ne reçoit actuellement aucun paramètre
  version "2", avec cumul de catégories
]]--
function p.categoriseBiographie(frame)
	-- si on n'est pas dans l'espace encyclopédique on ne fait rien
	local titre = mw.title.getCurrentTitle()
	if ((titre == nil) or (titre.namespace ~= 0)) then
		return ""  -- on retourne un texte vide, donc l'action est inexistante
	end
	
	-- on regarde si la page a une entrée wikidata
	local awd = p.a_wikidata(nil)
	if (not awd) then
		return data.cat_badwd
	end
	-- on regarde si la page a une nature de l'élément définie
	local nature = wd.formatStatements{property = 'P31', displayformat = 'raw'}
	if (not nature) then
                -- on retourne un texte vide, donc l'action est inexistante
		return ""
	end

	-- pour cumuler les éléments à retourner
	local out = data.cat_biographie

	-- on regarde si c'est un humain
	local hwd = p.presence_propriete("P31", "Q5", nil)
	if (not hwd) then
		-- traitement spécifique pour les personnages humains de la Bible
		 local awd2 = p.presence_propriete("P31", "Q20643955", nil)
                   -- traitement spécifique pour les humains possiblement fictifs
                   local awd3 = p.presence_propriete("P31", "Q21070568", nil)
		 if (awd2 or awd3) then
		        -- catégorisation dans Croyance et religion
			return out .. data.cat_religion
		 else
                        -- on retourne un texte vide, donc l'action est inexistante
			return ""
		 end
	end
	
	
	-- On est sur une biographie, on affine la catégorisation
	-- là il faut aller plus loin et récupérer les métiers pour catégoriser
	local mwd = p.propriete_parente("P106", nil)
	-- si aucune réponse on le place dans "autres"
	if (mwd == nil) then
		-- on catégorise
                   -- traitement spécifique pour les personnages humains de la Bible
                   local hwd2 = p.presence_propriete("P31", "Q20643955", nil)
	           if (hwd2) then
		        -- catégorisation dans Religion
                        out = out .. data.cat_religion
	           else
                        return out .. data.cat_defaut
                   end

	else
		-- on a (au moins) une réponse : on parcours chaque entrée et on cumule les catégories associées
		nb = 0
		for k, v in ipairs(mwd) do
			out = out .. data.association[v]["catégorie"]
			nb = nb + 1
		end
		-- si 0 catégorie insérée on met celle par défaut
		if (nb == 0) then
			 -- traitement spécifique pour les personnages humains de la Bible
                         local hwd4 = p.presence_propriete("P31", "Q20643955", nil)
	                  if (hwd4) then
			  -- catégorisation dans Religion
				return out .. data.cat_religion
			 else
				out = out .. data.cat_defaut
			end
		end
	end

	-- on retourne le résultat final
	return out
end


return p