Module:Adresse : Différence entre versions

De Lagny-sur-Marne Wiki
Aller à : navigation, rechercher
(Ajout d'option pour obtenir l'adresse complète à partir de Wikidata)
Ligne 1 : Ligne 1 :
 +
local formats = require "Module:Adresse/Formats"
 +
 
local p = {}
 
local p = {}
 +
local wikidata = require "Module:Interface Wikidata".fromLua
 +
local linguistic = require "Module:Linguistique"
 +
local countrymodule = require "Module:Country data"
  
local wikidata =require('Module:Wikidata')
+
local function getCountry(item) -- get country id for formatting
 
+
return wikidata.formatStatements{property = 'P17', entity = item, displayformat = 'raw', numvals = 1}  
local street = {
 
-- identifant wikipédia = regex pour le format de l'adresse
 
-- $number : le numéro de l'immeuble
 
-- $ street : le nom de la rue
 
-- questions :
 
-- utiliser des noms plutôt que des ID wikidata ?
 
-- si problème de performance, utiliser des fonctions plutôt que des regex ?
 
Q16 = '$number $street $direction',-- Canada
 
Q30 = '$number $street $direction',-- Etats-Unis
 
Q31 = '$number $street',-- Belgique
 
Q40 = '$street $number', -- Autriche
 
Q148 = '$number $street $direction', -- si l'on met les noms de rue en français
 
Q183 = '$street $number', -- Allemagne
 
Q39 = '$street $number', -- Suisse
 
Q142 = '$number $street',-- France
 
Q145 = '$number $street',-- UK
 
Q218 = '$street $number', --  Roumanie
 
default = '$number $street $direction',
 
}
 
 
 
local direction = { -- directions affichées dans les noms des rues
 
Q16 = {Q659 = 'Nord', Q679 = 'Ouest', Q684 = 'Est', Q667 = 'Sud'}, -- au Canada, on peut avoir des noms de rue en français
 
Q30 = {Q659 = 'North', Q679 = 'West', Q684 = 'East', Q667 = 'South'}, -- Etats-Unis seulement la première lettre ?
 
}
 
 
 
function p.formatAddress(streets, postcode, city, formattingarea)
 
-- streets est une table de {streetname, number, }quarge que "city" qui détermine le formatage de la rue et du code postal
 
if (not streets) and (not postcode) and (not city) then
 
return nil
 
end
 
 
 
local addresslines = {} -- lignes à mettre dans l'adresse : rue, codepostal + ville etc.
 
if streets then
 
table.insert(addresslines, streets)
 
end
 
 
if postcode or formattingarea then
 
table.insert(addresslines, (postcode or '') .. ' ' .. (formattingarea or ''))
 
end
 
 
 
return table.concat(addresslines, '<br />')
 
 
end
 
end
  
Ligne 63 : Ligne 27 :
 
local str = ''
 
local str = ''
 
for i, snak in pairs(claim.qualifiers.P560) do
 
for i, snak in pairs(claim.qualifiers.P560) do
str = str .. wikidata.formatSnak(snak,  {speciallabels = direction[area]})
+
local directionlabels = area.directions or formats.default.directions
 +
str = str .. wikidata.formatSnak(snak,  {speciallabels = directionlabels})
 
end
 
end
 
return str
 
return str
 
end
 
end
  
local function streetFromClaims(claim, formattingarea) -- réupère le nom de la rue à partir d'une affirmation P669 Wikidata
+
local function streetFromClaims(claim) -- réupère le nom de la rue à partir d'une affirmation P669 Wikidata
 
return wikidata.formatStatement(claim)
 
return wikidata.formatStatement(claim)
 
end
 
end
  
local function formatStreet(streetname, housenumber, direction, area)
+
local function formatStreet(streetname, housenumber, direction, displayformat)
local val = street[area] or street.default
+
local val = displayformat.streetline or formats.default.streetline
 
val = mw.ustring.gsub(val, '$number', housenumber or '')
 
val = mw.ustring.gsub(val, '$number', housenumber or '')
 
val = mw.ustring.gsub(val, '$street', streetname or '')
 
val = mw.ustring.gsub(val, '$street', streetname or '')
Ligne 81 : Ligne 46 :
  
 
local function wikidatastreet(claim, area) --formate des données sur la rue à partir d'une affirmation Wikidata
 
local function wikidatastreet(claim, area) --formate des données sur la rue à partir d'une affirmation Wikidata
local streetname = streetFromClaims(claim)
+
local streetname = streetFromClaims(claim, area)
local housenumber =  numberFromClaim(claim)
+
local housenumber =  numberFromClaim(claim, area)
 
local direction = directionFromClaim(claim, area)
 
local direction = directionFromClaim(claim, area)
 
return formatStreet(streetname, housenumber, direction, area)
 
return formatStreet(streetname, housenumber, direction, area)
 
end
 
end
  
function p.wikidataAddress(item) -- fprùate l'intégralité d'une adresse à partir des données contenues dans une élément Wikidata
+
function p.streetAddress(item, area) -- formate la ligne concernant la rue et le numéro de rue
 
+
local streets -- châine contenant le ou les rues et numéros d'immeuble
-- définit la zone dans laquelle on se trouve pour choisir le format à utilier
+
area = area or formats[getCountry(item)]
local area = wikidata.formatStatements({item = item, property = 'P17', numval = 1, displayformat = 'raw'}) -- = pays
 
 
 
local streets -- châine contenant le ou les rues et numéros d'immeuble
 
 
 
-- essaye de remplir street, en priorité avec P669, type : élément
 
-- essaye de remplir street, en priorité avec P669, type : élément
local streetclaims = wikidata.getClaims{item=item, property = 'P669', item=item}
+
local streetclaims = wikidata.getClaims{entity = item, property = 'P669'}
 
if streetclaims then
 
if streetclaims then
 
for i, j in pairs(streetclaims) do
 
for i, j in pairs(streetclaims) do
streetclaims[i] = wikidatastreet(j, area)  
+
streetclaims[i] = wikidatastreet(j, area)
 
end
 
end
 
streets = mw.text.listToText(streetclaims)
 
streets = mw.text.listToText(streetclaims)
streets = wikidata.addLinkback(streets, item, 'P669')
+
streets = wikidata.formatAndCat{value = streets, entity = item, property = 'P669'}
-- faut-il ajouter Category:Page utilisant des données de Wikidata/P969 ?
 
 
end
 
end
 
-- sinon : P969, type : string
 
-- sinon : P969, type : string
 
if not streets then  
 
if not streets then  
 
streets =  wikidata.formatAndCat{property = 'P969', entity = item}
 
streets =  wikidata.formatAndCat{property = 'P969', entity = item}
 +
end
 +
return streets
 +
end
 +
 +
function p.adminDivList(item, country) -- returns a list of admin divisions matching the criteria defined in Module:Adresse/Formats
 +
country = country or getCountry(item)
 +
local query = {entity = place, property = 'P131'}
 +
local divs = wikidata.transitiveVals(item, query, 0, 10, country)
 +
 +
 +
-- solution 1: looks for divs of a certain type
 +
local function setValue(targetclasses, depth)
 +
local test = {}
 +
for _, d in pairs(divs) do
 +
for j, divtype in pairs(targetclasses) do
 +
if wikidata.isInstance(divtype, d, 3) then
 +
-- restrain list to new value, will be expanded only if needed
 +
divs = {d}
 +
return d
 +
end
 +
end
 +
end
 +
if depth >= 0 then
 +
local num = #divs
 +
divs = wikidata.addVals(divs, query, 0, 10, country)
 +
if #divs > num then return setValue(targetclasses, depth) end
 +
end
 
end
 
end
  
--[[ code postal, peu utile pour l'instant
+
-- solution2: looks for divs that are part of a closed list (way more efficient for big items)
local postcode = wikidata.getClaims{property= 'P281', item=item}
+
local function findInList(list, depth)
if postcode and #postcode > 1 then -- s'il y a plusieurs codes postaux, il y a sans doute plusieurs adresses différentes, c'est difficile de savoir lequel correspond à laquelle
+
for i, j in pairs(divs) do
postcode = nil
+
for k, l in pairs(list) do
elseif postcode then
+
if j == l then
postcode = wikidata.formatStatement(postcode[1])
+
divs = {l}
 +
return l
 +
end
 +
end
 +
end
 +
if depth >= 0 then
 +
local num = #divs
 +
divs = wikidata.addVals(divs, query, 0, 10, country)
 +
if #divs > num then return findInList(list, depth) end
 +
end
 +
end
 +
 +
displayformat = formats[country] or formats.default
 +
local maxdepth = 3
 +
if not divs then
 +
return nil
 
end
 
end
]]--
+
local validDivs = {}
-- faaut-il essayer d'ajouter la ville par P131 ? Souvent on en veut pas (par exemple en infobox)
+
local val = p.formatAddress(streets, postcode)
+
if displayformat.div1 then
if val then return
+
local val = setValue(displayformat.div1, maxdepth)
val .. '[[Category:Page utilisant une adresse fournie par Wikidata]]'
+
if val and val ~= validDivs[#validDivs] then
 +
table.insert(validDivs, val)
 +
end
 +
end
 +
 
 +
if displayformat.div2 then
 +
local val = setValue(displayformat.div2, maxdepth)
 +
if val and val ~= validDivs[#validDivs] then
 +
table.insert(validDivs, val)
 +
end
 +
elseif displayformat.div2vals then
 +
local val =  findInList(displayformat.div2vals, 1)
 +
if val and val ~= validDivs[#validDivs] then
 +
table.insert(validDivs, val)
 +
end
 +
end
 +
 +
if displayformat.div3 then
 +
local val = setValue(displayformat.div3, maxdepth)
 +
if val and val ~= validDivs[#validDivs] then
 +
table.insert(validDivs, val)
 +
end
 +
elseif displayformat.div3vals then
 +
local val =  findInList(displayformat.div3vals, 0)
 +
if val and val ~= validDivs[#validDivs] then
 +
table.insert(validDivs, val)
 +
end
 +
end
 +
 +
return validDivs
 +
end
 +
 
 +
function p.cityLine(item, country, divlist) -- line with list of admin divisions + optional postcode
 +
country = country or getCountry(item)
 +
 +
local postcode = wikidata.formatStatements{entity = item, property = 'P281'} or ''
 +
local divstr = ''
 +
 +
divlist = divlist or p.adminDivList(item, country)
 +
if not divlist then-- add a maintenance category ?
 +
end
 +
for i, j in pairs(divlist) do
 +
divlist[i] = wikidata.formatEntity(j)
 +
end
 +
local divstr = linguistic.conj(divlist, 'comma')
 +
 
 +
local str = formats[country].cityline or formats.default.cityline
 +
str = str:gsub("$postcode", postcode or '')
 +
str = str:gsub("$admindivs", divstr or '')
 +
return str
 +
end
 +
 
 +
function p.fullAddress(item, country, divs)
 +
 
 +
-- country id used for formatting
 +
country = country or getCountry(item)
 +
local displayformat = formats[country] or formats.default
 +
 
 +
-- line 1 street
 +
local streetline = p.streetAddress(item, country)
 +
 +
-- line 2: administrative divisions, postcodes
 +
local cityline = p.cityLine(item, country, divs)
 +
 
 +
if mw.text.trim(cityline) == '' then
 +
cityline = nil
 +
end
 +
 +
-- line 3: country
 +
local countryline = countrymodule.standarddisplay(country) or wikidata.formatStatements{entity = entity, property = 'P17'}
 +
 +
return linguistic.conj({streetline, cityline, countryline}, '<br />')
 +
end
 +
 
 +
function p.wikidataAddress(item, country) -- fonction de transition
 +
local area = formats[country] or formats.default
 +
local val = p.streetAddress(item, area)
 +
if val then
 +
return val .. '[[Category:Page utilisant une adresse fournie par Wikidata]]'
 
end
 
end
 
end
 
end
 
return p
 
return p

Version du 2 septembre 2015 à 11:54

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

local formats = require "Module:Adresse/Formats"

local p = {}
local wikidata = require "Module:Interface Wikidata".fromLua
local linguistic = require "Module:Linguistique"
local countrymodule = require "Module:Country data"

local function getCountry(item) -- get country id for formatting
	return wikidata.formatStatements{property = 'P17', entity = item, displayformat = 'raw', numvals = 1} 
end

local function numberFromClaim(claim) -- récupère le numéro de l'immeuble à partir d'un qualificatif P670 d'une affirmation Wikidata
	if not claim.qualifiers or not claim.qualifiers.P670 then
		return nil
	end
	local vals = {}
	for i, j in pairs(claim.qualifiers.P670) do
		table.insert(vals, wikidata.formatSnak(j))
	end
	return table.concat(vals, '-')
end

local function directionFromClaim(claim, area) -- par exemple rue Sherbrooke Ouest
	if not claim.qualifiers or not claim.qualifiers.P560 then
		return nil
	end
	local str = ''
	for i, snak in pairs(claim.qualifiers.P560) do
		local directionlabels = area.directions or formats.default.directions
		str = str .. wikidata.formatSnak(snak,  {speciallabels = directionlabels})
	end
	return str
end

local function streetFromClaims(claim) -- réupère le nom de la rue à partir d'une affirmation P669 Wikidata
	return wikidata.formatStatement(claim)
end

local function formatStreet(streetname, housenumber, direction, displayformat)
	local val = displayformat.streetline or formats.default.streetline
	val = mw.ustring.gsub(val, '$number', housenumber or '')
	val = mw.ustring.gsub(val, '$street', streetname or '')
	val = mw.ustring.gsub(val, '$direction', direction or '')
	return val
end

local function wikidatastreet(claim, area) --formate des données sur la rue à partir d'une affirmation Wikidata
	local streetname = streetFromClaims(claim, area)
	local housenumber =  numberFromClaim(claim, area)
	local direction = directionFromClaim(claim, area)
	return formatStreet(streetname, housenumber, direction, area)
end

function p.streetAddress(item, area) -- formate la ligne concernant la rue et le numéro de rue
	local streets -- châine contenant le ou les rues et numéros d'immeuble
	area = area or formats[getCountry(item)]
	
	-- essaye de remplir street, en priorité avec P669, type : élément
	local streetclaims = wikidata.getClaims{entity = item, property = 'P669'}
	if streetclaims then
		for i, j in pairs(streetclaims) do
			streetclaims[i] = wikidatastreet(j, area)
		end
		streets = mw.text.listToText(streetclaims)
		streets = wikidata.formatAndCat{value = streets, entity = item, property = 'P669'}
	end
	-- sinon : P969, type : string
	if not streets then 
		streets =  wikidata.formatAndCat{property = 'P969', entity = item}
	end
	return streets
end

function p.adminDivList(item, country) -- returns a list of admin divisions matching the criteria defined in Module:Adresse/Formats
	country = country or getCountry(item)
	local query = {entity = place, property = 'P131'}
	local divs = wikidata.transitiveVals(item, query, 0, 10, country)
	
	
	-- solution 1: looks for divs of a certain type
	local function setValue(targetclasses, depth) 
		local test = {}
		for _, d in pairs(divs) do
			for j, divtype in pairs(targetclasses) do
				if wikidata.isInstance(divtype, d, 3) then
					 -- restrain list to new value, will be expanded only if needed
					divs = {d}
					return d
				end
			end
		end
		if depth >= 0 then
			local num = #divs
			divs = wikidata.addVals(divs, query, 0, 10, country)
			if #divs > num then return setValue(targetclasses, depth) end
		end
	end

	-- solution2: looks for divs that are part of a closed list (way more efficient for big items)
	local function findInList(list, depth) 
		for i, j in pairs(divs) do
			for k, l in pairs(list) do
				if j == l then
					divs = {l}
					return l
				end
			end
		end
		if depth >= 0 then
			local num = #divs
			divs = wikidata.addVals(divs, query, 0, 10, country)
			if #divs > num then return findInList(list, depth) end
		end
	end
					
	displayformat = formats[country] or formats.default
	local maxdepth = 3
	if not divs then
		return nil
	end
	local validDivs = {}
	
	if displayformat.div1 then
		local val = setValue(displayformat.div1, maxdepth)
		if val and val ~= validDivs[#validDivs] then
			table.insert(validDivs, val)
		end
	end

	if displayformat.div2 then
		local val = setValue(displayformat.div2, maxdepth)
		if val and val ~= validDivs[#validDivs] then
			table.insert(validDivs, val)
		end
	elseif displayformat.div2vals then
		local val =  findInList(displayformat.div2vals, 1)
		if val and val ~= validDivs[#validDivs] then
			table.insert(validDivs, val)
		end
	end
	
	if displayformat.div3 then
		local val = setValue(displayformat.div3, maxdepth)
		if val and val ~= validDivs[#validDivs] then
			table.insert(validDivs, val)
		end
	elseif displayformat.div3vals then
		local val =  findInList(displayformat.div3vals, 0)
		if val and val ~= validDivs[#validDivs] then
			table.insert(validDivs, val)
		end
	end
	
	return validDivs
end

function p.cityLine(item, country, divlist) -- line with list of admin divisions + optional postcode
	country = country or getCountry(item)
	
	local postcode = wikidata.formatStatements{entity = item, property = 'P281'} or ''
	local divstr = ''
	
	divlist = divlist or p.adminDivList(item, country)
	if not divlist then-- add a maintenance category ?
	end
	for i, j in pairs(divlist) do
		divlist[i] = wikidata.formatEntity(j)
	end
	local divstr = linguistic.conj(divlist, 'comma')

	local str = formats[country].cityline or formats.default.cityline
	str = str:gsub("$postcode", postcode or '')
	str = str:gsub("$admindivs", divstr or '')
	return str
end

function p.fullAddress(item, country, divs)

	 -- country id used for formatting
	country = country or getCountry(item)
	local displayformat = formats[country] or formats.default

	-- line 1 street
	local streetline = p.streetAddress(item, country)
	
	-- line 2: administrative divisions, postcodes
	local cityline = p.cityLine(item, country, divs)

	if mw.text.trim(cityline) == '' then
		cityline = nil
	end
	
	-- line 3: country
	local countryline = countrymodule.standarddisplay(country) or wikidata.formatStatements{entity = entity, property = 'P17'}
	
	return linguistic.conj({streetline, cityline, countryline}, '<br />')
end

function p.wikidataAddress(item, country) -- fonction de transition
	local area = formats[country] or formats.default
	local val = p.streetAddress(item, area)
	if val then
		return val .. '[[Category:Page utilisant une adresse fournie par Wikidata]]'
	end
end
return p