Aller au contenu

Module:Country data/Bac à sable

Une page de Wikipédia, l'encyclopédie libre.
Ceci est une version archivée de cette page, en date du 11 mars 2023 à 12:02 et modifiée en dernier par Golmote (discuter | contributions) (Copie des fonctions de Module:CountryData (hors gestion du cache), ajout fonction de conversion du format template en format module). Elle peut contenir des erreurs, des inexactitudes ou des contenus vandalisés non présents dans la version actuelle.

 Documentation[voir] [modifier] [historique] [purger]

Ce module contient des informations utilisées par le système country.

--[[
This module is intended to replace the functionality of {{drapeau2}} and related
templates.  It provides several methods, including
]]

local p = {};

local gdata = mw.loadData ("Module:Country data/liste" )
local dates = require "Module:date complexe"
local linguistic = require "Module:Linguistique"

local function _getCompetition(c,aaaa)
	local gdomain = mw.loadData ( "Module:Drapeau/Domaine" ) -- chargé seulement sur les articles où ça sert, ça prend un peu de place
	
	local symbs = {
		['cm'] = "à la Coupe du monde",
		['coupedumonde'] = "à la Coupe du monde",
		['ce'] = "au championnat d'Europe",
		['euro'] = "au championnat d'Europe",
		['chm'] = "au championnat du monde",
		['can'] = "à la Coupe des Confédérations",
		['coupedesconfederations'] = "à la Coupe des Confédérations",
		['en'] = "en",
		['jo'] = "aux Jeux olympiques",
		['jp'] = "aux Jeux paralympiques",
	}

	local str = symbs[string.lower(c or '')] or ""
	
	--edition
	if(aaaa ~= nil and aaaa ~= "") then
		if(c=="jo"  or c=="jp" ) then
			local o=gdomain.jo["_"..aaaa];
			if(o ~= nil) then
				str = str .." "..o
			end
		else
		   str = str .." "..aaaa
		end
	end

	return str
end

local function printFlag(flagfile, alt, displayformat)
	
	displayformat = displayformat or {}
	local size = displayformat.size or '20x15'
	local border = 'border|' 
	
	if displayformat.border == '-' then
		border = ''
	end
	
	if not alt then
		alt = ''
	end
	return '<span class="flagicon">' ..
			'[[Fichier:' .. flagfile .. '|' .. size ..'px|' .. border  .. alt ..'|class=noviewer]]' ..
			'</span>';
end

local function bestfordate(data, period) -- data contient une table dont les clés sont des dates au format ['2010'] = ou ['2010-05-04'] = 
	if type(data) == 'string' then
		return data
	end

	-- très artisanal, à améliorer
	if (not period) or (period == 'default') then
		return data.default
	end
	
	local val = data.default
	local bestdate = '-1000-01-01'
	for i, j in pairs(data) do
		if j ~= 'default' and dates.before(period, i) and dates.before(i, bestdate) then
			val = j
			bestdate = i
		end -- bestdate est la date la plus récente antérieure ou égale à period, val est la donnée à cette date
	end
	return val
end


local function valueAtDate(data, period, topic) -- topic: type de drapeau, genre de l'adjectif, etc.
	if type(data) == 'string' or type(data) == 'nil' then
		return data
	end
	if type(data) ~= 'table' then
		return error('mauvais datatabpe ' .. type(data))
	end
	topic = topic or "default"
	if data[topic] then
		return bestfordate(data[topic], period)
	elseif data.default then
		return bestfordate(data.default, period)
	else
		return bestfordate(data, period)
	end
	return error()
end

local function getData(datatable, typedata, topic, period) -- récupère la chaîne de caractère la plus appropriée dans la datatable
	-- datatable: la table de sous module par exemple [[Module:Country data/grenade]]
	-- typedata: "flag" / "name" / "adjective"
	-- period: data in ISO format
	-- topic: for instance "navy" for naval ensign
	local val = datatable[typedata]

	if not val then -- error handling ?
		return nil
	end

	local val = valueAtDate(val, period, topic)

	if type(val) ~= 'string' then -- error handling ?
		return error(val)
	end
	return val
end

local function getAdjective(data, gender, number)
	if not gender then
		gender = 'm'
	end
	if not number then
		number = 's'
	end
	if (gender ~= 'm' and gender ~= 'f') then
		return error('gender devrait être m ou f mais est ' .. gender)
	end
	if (number ~= 's' and number ~= 'p') then
		return error('number devrait être s ou p mais est ' .. number)
	end
	return getData(data, 'adjective', (gender .. number))
end

local function getDemonym (data, gender, number)
	if data.demonym == nil then
		return linguistic.ucfirst( getAdjective(data, gender, number) )
	end
	gender = gender or 'm'
	number = number or 's'
	if (gender ~= 'm' and gender ~= 'f') then
		return error('gender devrait être m ou f mais est ' .. gender)
	end
	if (number ~= 's' and number ~= 'p') then
		return error('number devrait être s ou p mais est ' .. number)
	end
	return getData(data, 'demonym', (gender .. number))
end

local function getLabel(data, topic, period, form)
	local label
	if (not form) or form == 'short' then
		label = getData(data, 'shortname', topic, period)
	end
	if not label then
		label = getData(data, 'name')
	end
	if (not label) and data.item then
		label = mw.wikibase.label(getData(data, 'item'))
	end
	return label
end

local function getLink(data, topic, period)
	local link = getData(data, 'link', topic, period)
	if (not link) and data.item then
		link =  mw.wikibase.label(getData(data, 'item'))
	end
	return link
end

local function applyregex(str, areadata)
	local cio = 'code CIO (en attente)' --require('Module:Wikidata')._formatStatements({entity= areadata.item, property= 'P984'}) or '??'

	local label = getData(areadata, 'name')
	local of = linguistic.of(label, areadata.genre)
	
	str = mw.ustring.gsub(str, '$de$label', of)
	str = mw.ustring.gsub(str, '$label', label)
	str = mw.ustring.gsub(str, '$cio', 'cio') 

	if string.find(str, '$gentile') then
		local function get(genre) return getData(areadata, 'adjective', genre) end
		local gentileMS, gentileFS, gentileMP, gentileFP = get('ms'), get('fs'), get('mp'), get('fp')
		str = mw.ustring.gsub(str, '$gentileMS', gentileMS)
		str = mw.ustring.gsub(str, '$gentileFS', gentileFS)
		str = mw.ustring.gsub(str, '$gentileMP', gentileMP)
		str = mw.ustring.gsub(str, '$gentileFP', gentileFP)
	end
	return str
end

local function getDatatable(zone)
	zone = mw.ustring.lower(zone)
	if gdata[zone] then
		return require('Module:Country data/' .. gdata[zone])
	else -- si le module existe mais n'est pas dans la liste
		return require('Module:Country data/' .. zone)
	end
end


local function flagIcon(data, flagtype, period, displayformat)
	local flagimage = getData(data, 'flag', flagtype, period)
	if flagimage then
		return printFlag(flagimage, '', displayformat)
	end
end

local function getcontents(frame,country,params)
  return frame:expandTemplate({title="Country data "..country;args=params})
end

function p.gettable(frame,country,params)
--Returns the parameters of a country data template as a Lua table
  --If not a valid data template, return empty table
  local bool, s = pcall(getcontents,frame,country,params or {})
  if bool and (string.find(s,"^%{%{ *%{%{%{1") or string.find(s,"^%{%{safesubst: *%{%{%{1"))
  then
    --Replace parameter delimiters with arbitrary control characters
    --to avoid clashes if param values contain equals/pipe signs
    s = string.gsub(s,"|([^|=]-)=","\1\1%1\2")
    s = string.gsub(s,"}}%s*$","\1")
    --Loop over string and add params to table
    local part = {}
    for par in string.gmatch(s,"\1[^\1\2]-\2[^\1\2]-\1") do
      local k = string.match(par,"\1%s*(.-)%s*\2")
      local v = string.match(par,"\2%s*(.-)%s*\1")
      if v and not (v=="" and string.find(k,"^flag alias")) then
        part[k] = v
      end
    end
    return part
  else
  	return {}
  end
end

function p.getalias(frame)
--Returns a single parameter value from a data template
  local part = p.gettable(frame,frame.args[1])
  if frame.args.variant
    then return tostring(part[frame.args[2].."-"..frame.args.variant]
                         or part[frame.args[2]] or frame.args.def)
    else return tostring(part[frame.args[2]] or frame.args.def)
  end
end

function p.gettemplate(frame)
--For testing, recreates the country data from the created Lua table
  --Get data table
  local data = p.gettable(frame,frame.args[1])
  --Concatenate fields into a template-like string
  local out = "{{ {{{1}}}"
  for k,v in pairs(data) do
    out = out.."\n| "..k.." = "..v
  end
  return out.."\n}}"
end

local function convertTemplateToModuleFormat(data)
	if not data.alias or not data['flag alias'] then
		return false, nil
	end
	local newData = {
		name = data['shortname alias'] or data.alias,
		link = {default = {default = data.alias}},
		flag = {default = {default = data['flag alias']}},
		--sizeflag = {},
		--borderflag = {},
		--alt = {},
		--sortkey = {},
	}
	if data.size then
		newData.size = {default = {default = data.size}}
	end

	local keys = {
		link = 'link',
		flag = 'flag',
		['size flag'] = 'sizeflag',
		border = 'borderflag',
		['alt attribute'] = 'alt',
		sortkey = 'sortkey',
	}
	local topics = {
		naval = 'naval',
		['air force'] = 'airforce',
		army = 'army',
		marines = 'marines',
		['coast guard'] = 'coastguard',
		military = 'military',
	}
	for k, v in pairs(data) do
		local foundKey, foundTopic, foundYear
		for key, newKey in pairs(keys) do
			for topic, newTopic in pairs(topics) do
				if k == key .. ' alias-' .. topic then
					foundYear = 'default'
				else
					foundYear = k:match('^' .. key .. ' alias%-' .. topic .. '%-(%d+)$')
				end
				if foundYear then
					foundTopic = newTopic
					break
				end
			end
			if not foundTopic then
				if k == key then
					foundYear = 'default'
				else
					foundYear = k:match('^' .. key .. ' alias%-(%d+)$')
				end
				if foundYear then
					foundTopic = 'default'
				end
			end
			if not foundTopic then
				foundYear = 'default'
				foundTopic = k:match('^' .. key .. ' alias%-(.+)')
			end
			if foundTopic then
				foundKey = newKey
				break
			end
		end
		if foundKey and foundTopic and foundYear then
			newData[foundKey] = newData[foundKey] or {}
			newData[foundKey][foundTopic] = newData[foundKey][foundTopic] or {}
			newData[foundKey][foundTopic][foundYear] = v
		end
	end
	return true, newData
end

local function getDatatableFromTemplate(frame, country)
	local data = p.gettable(frame, country)
	if next(data) == nil then
		return false, nil
	end
	return convertTemplateToModuleFormat(data)
end

function p.standarddisplay(zone, args)
	if not zone then
		return nil
	end
	-- nettoyage des paramètres
	if not args then
		args = {}
	end
	for i, j in pairs(args) do
		args[i] = mw.text.trim(j) -- remove whitespaces
		if args[i] == '' then args[i] = nil end
	end

   -- ajout des valeurs par défaut
	local size = args.flagsize or '20x15'
	local flagtype = args.type

	local align = args.align or 'left'
	local link = args.link
	local period = args.date
	local competition = args.competition
	local edition = args.edition
	local extra = ''
	
	local success, data = pcall(getDatatable, zone)
	if not success then
		success, data = getDatatableFromTemplate(mw.getCurrentFrame(), zone)
	end
	if not success then
		if args.strict then
			return error('lieu non reconnu')
		end
		return nil
	end
	
	-- image
	local flag = flagIcon(data, flagtype, period)
	if (args.label == '-') then
		return flag, true
	end

	-- text
	local text
	local label = getLabel(data, flagtype)
	local link = getLink(data, flagtype)

	if competition then 
		competition = _getCompetition(linguistic.toascii(competition),args["édition"])
	end
	if link and competition then
		link = link .. ' ' .. competition
	end

	if link then
		text = '[[' .. link .. '|' .. label .. ']]'
	end

	-- si les données sont extraites d'un formulaire standard comme module:Drapeau/domain, appliquer des regex
	if string.match(text, '%$') then
		text = applyregex(text, data)
	end
	
	local val
	if align == 'right' then
		val = text .. '&nbsp;' .. flag
	else
		val = flag .. '&nbsp;' .. text
	end
	
	return val, true -- true indique le succès
end

-- fonction appelable avec #invoke
function p.standarddisplay2(frame)
	result, success = p.standarddisplay(frame.args['pays'],frame.args)
	return result
end


function p.nationality(zone, gender, number, topic, period)
	local success, data = pcall(getDatatable, zone)
	if not success then return
		zone
	end
	
	local str = getAdjective(data, gender, number)
	if not str then
		return zone
	end
	local link = getLink(data, topic, period) 
	if link then
		str = '[[' .. link .. '|' .. str .. ']]'
	end
	return str, true-- true indique le succès
end

function p.getNationality(args) -- pour obtenir la nationalité d'une personne sur Wikidata sous forme d'adjectifs
	if not args then
		return nil
	end
	local wikidata = require "Module:Wikidata"
	local complexdate = require "Module:Date complexe"
	
	if type(args) == 'string' then -- si un seul argument, c'est l'entité à utiliser
		args = {item = args}
	end
	if args.args then -- si vient de frame
		args = args.args
	end
	local item = args.item or args[1]
	
	-- établit la variable gender pour l'élément
	local vals = {
		['Q6581072'] = 'f',
		['Q6581097'] = 'm',
		default	  = '?'
	}
	local gender = args.gender
	if not gender then
		gender = wikidata.formatStatements{entity = item, property = 'P21', displayformat = 'raw'}
		gender = vals[gender] or vals.default
	end
	-- désactivation si date de naissance avant l'Ère contemporaine : trop d'imprécisions et d'anachronismes
	local mindate = args.mindate or '1789'
	if mindate ~= "-" then
		local birthdate = wikidata.formatStatements{entity = item, property = 'P569', displayformat = 'raw', numval = 1}
                local deathdate = wikidata.formatStatements{entity = item, property = 'P570', displayformat = 'raw', numval = 1}
		if ((not birthdate) or complexdate.before(mindate, birthdate)) and ((not deathdate) or complexdate.before(mindate, deathdate)) then
			return nil
		end
	end
	return wikidata.formatStatements{
			property = 'P27',
			showdate = true,
			entity = item,
			conjtype = args.conjtype or 'and',
			removedupes = true,
			linktopic = '-',
			displayformat = 
				function(snak)
					local g = gender -- genre de la personne, pour affichage du gentilé
					if g == '?' then -- si inconnu, au masculin
						g = 'm'
					end
					local val, success = p.nationality(wikidata.getId(snak), g)
					if not success then
						val = wikidata.formatSnak(snak)
					end
					return val
				end
	}
end

return p