Модуль:Wikidata/Places
< Модуль:Wikidata
Версия от 15:54, 19 апреля 2016; Admin (обсуждение | вклад) (Новая страница: «local categorizeByPlaceOfBirthAndDeath = true; local WDS = require('Module:WikidataSelectors') local p = {} local project = 'ruwiki'; local function min( prev,…»)
Для документации этого модуля может быть создана страница Модуль:Wikidata/Places/doc
local categorizeByPlaceOfBirthAndDeath = true;
local WDS = require('Module:WikidataSelectors')
local p = {}
local project = 'ruwiki';
local function min( prev, next )
if ( prev == nil ) then return next;
elseif ( prev > next ) then return next;
else return prev; end
end
local function max( prev, next )
if ( prev == nil ) then return next;
elseif ( prev < next ) then return next;
else return prev; end
end
local function getTimeBoundariesFromProperty( context, propertyId )
mw.log( 'Get time boundaries for ' .. propertyId .. '...');
local dateClaims = WDS.filter( context.entity.claims, propertyId );
if ( not dateClaims or #dateClaims == 0 ) then return nil; end
mw.log( 'Get time boundaries for ' .. propertyId .. '... Got ' .. #dateClaims .. ' date claim(s)');
-- only support exact date so far, but need improvment
local left = nil;
local right = nil;
for _, claim in pairs( dateClaims ) do
if ( not claim.mainsnak ) then return nil; end
local boundaries = context.parseTimeBoundariesFromSnak( claim.mainsnak );
if ( not boundaries ) then return nil; end
left = min( left, boundaries[1] );
right = max( right, boundaries[2] );
end
if ( not left or not right ) then return nil; end
mw.log( 'Time boundaries for ' .. propertyId .. ' are ' .. left .. ' and ' .. right );
return { left, right };
end
local function getTimeBoundariesFromQualifiers( context, statement, qualifierId )
-- only support exact date so far, but need improvment
local left = nil;
local right = nil;
if ( statement.qualifiers and statement.qualifiers[qualifierId] ) then
for _, qualifier in pairs( statement.qualifiers[qualifierId] ) do
local boundaries = context.parseTimeBoundariesFromSnak( qualifier );
if ( not boundaries ) then return nil; end
left = min( left, boundaries[1] );
right = max( right, boundaries[2] );
end
end
if ( not left or not right ) then
return nil;
end
return { left, right };
end
local function getParentsInBoundariesSnakImpl( context, entity, boundaries, propertyId )
local results = {};
if ( entity.claims and entity.claims[propertyId] ) then
for _, claim in pairs( entity.claims[propertyId] ) do
local startBoundaries = getTimeBoundariesFromQualifiers( context, claim, 'P580' );
local endBoundaries = getTimeBoundariesFromQualifiers( context, claim, 'P582' );
if ( (startBoundaries == nil or ( startBoundaries[2] <= boundaries[1]))
and (endBoundaries == nil or ( endBoundaries[1] >= boundaries[2]))) then
table.insert( results, claim.mainsnak );
end
end
end
return results;
end
local function getParentsInBoundariesSnak( context, entity, boundaries )
if ( not entity ) then error('entity must be specified'); end
if ( type(entity) ~= 'table' ) then error('entity must be table'); end
if ( not boundaries ) then error('boundaries must be specified'); end
if ( type(boundaries) ~= 'table' ) then error('boundaries must be table'); end
local results = getParentsInBoundariesSnakImpl( context, entity, boundaries, 'P131' )
if ( not results ) then
results = getParentsInBoundariesSnakImpl( context, entity, boundaries, 'P17' )
end
for r, result in pairs( results ) do
local resultId = 'Q' .. result.datavalue.value['numeric-id'];
if ( resultId == entity.id ) then
return nil;
end
end
return results;
end
local unions = {
Q1140229 = true, -- political union
Q3623811 = true, -- Экономический союз
Q4120211 = true -- региональная организация
}
local countries = {
Q6256 = true, -- страна
Q7275 = true, -- государство
Q3624078 = true -- суверенное государство
}
local function isSkipTopLevel( entity )
local isCountry = false;
local isUnion = false;
if ( entity
and entity.claims
and entity.claims.P31 ) then
for c, claim in pairs( entity.claims.P31 ) do
if ( claim
and claim.mainsnak
and claim.mainsnak.datavalue
and claim.mainsnak.datavalue.value
and claim.mainsnak.datavalue.value['numeric-id'] ) then
local typeId = 'Q' .. claim.mainsnak.datavalue.value['numeric-id'];
isCountry = isCountry or countries[typeId];
isUnion = isUnion or unions[typeId];
end
end
end
return isUnion and not isCountry;
end
local function isPartOfNext(prevLabel, nextLabel)
return (mw.ustring.len(prevLabel) > mw.ustring.len(nextLabel))
and (mw.ustring.sub( prevLabel, mw.ustring.len(prevLabel) - mw.ustring.len(nextLabel) + 1 ) == nextLabel);
end
--Property:P19, Property:P20, Property:P119
function p.formatPlaceWithQualifiers( context, options, statement )
local property = mw.ustring.upper( options.property );
mw.log( 'formatPlaceWithQualifiers(..., ' .. property .. ')');
local entriesToLookupCategory = {};
local circumstances = context.getSourcingCircumstances( statement );
local result = context.formatSnak( options, statement.mainsnak, circumstances );
insertFromSnak( statement.mainsnak, entriesToLookupCategory )
local hasAdditionalQualifiers = false;
if ( statement.qualifiers ) then
--parent divisions
if ( statement.qualifiers.P131 ) then
for i, qualifier in ipairs( statement.qualifiers.P131 ) do
result = result .. ', ' .. context.formatSnak( options, qualifier );
insertFromSnak( qualifier, entriesToLookupCategory )
hasAdditionalQualifiers = true;
end
end
--country
if ( statement.qualifiers.P17 ) then
for i, qualifier in ipairs( statement.qualifiers.P17 ) do
result = result .. ', ' .. context.formatSnak( options, qualifier );
insertFromSnak( qualifier, entriesToLookupCategory )
hasAdditionalQualifiers = true;
end
end
end
if ( statement.mainsnak
and statement.mainsnak.datavalue
and statement.mainsnak.datavalue.value
and statement.mainsnak.datavalue.value['numeric-id'] ) then
local entity = mw.wikibase.getEntity( 'Q' .. statement.mainsnak.datavalue.value['numeric-id'] );
local parentSnaks = { statement.mainsnak };
local parentEntities = { entity };
local actualDateBoundariesProperty = nil;
if ( property == 'P19' ) then actualDateBoundariesProperty = 'P569'; end
if ( property == 'P20' ) then actualDateBoundariesProperty = 'P570'; end
if ( actualDateBoundariesProperty ~= nil ) then
local boundaries = getTimeBoundariesFromProperty( context, actualDateBoundariesProperty );
if ( boundaries ) then
local parent = entity;
while ( parent ~= nil ) do
-- get parent
local newParentSnaks = getParentsInBoundariesSnak( context, parent, boundaries );
if ( #newParentSnaks == 0 ) then
parent = nil;
elseif ( #newParentSnaks == 1 ) then
local parentSnak = newParentSnaks[1];
parent = mw.wikibase.getEntity( 'Q' .. parentSnak.datavalue.value['numeric-id'] );
table.insert( parentSnaks, parentSnak );
table.insert( parentEntities, parent );
else
parent = nil;
result = result .. '[[Категория:Википедия:Страницы с неоднозначными геоцепочками]]';
end
end
mw.logObject( parentSnaks );
do
local i = #parentSnaks;
while ( i > 1 ) do
local prevEntity = parentEntities[i - 1];
local nextEntity = parentEntities[i];
if ( prevEntity and nextEntity
and prevEntity.labels and nextEntity.labels
and prevEntity.labels.ru and nextEntity.labels.ru
and prevEntity.labels.ru.value and nextEntity.labels.ru.value) then
local prevLabel = prevEntity.labels.ru.value;
local nextLabel = nextEntity.labels.ru.value;
if ( prevLabel == nextLabel ) then
-- do not output same label twice (NY, NY, USA)
table.remove( parentSnaks, i );
table.remove( parentEntities, i );
elseif ( isPartOfNext( prevLabel, ' ' .. nextLabel) ) then
-- do not output same label if it's part of previos
table.remove( parentSnaks, i - 1 );
table.remove( parentEntities, i - 1 );
end
end
i = i - 1;
end
end
if ( isSkipTopLevel( parentEntities[ #parentEntities ] ) ) then
table.remove( parentSnaks, #parentEntities );
table.remove( parentEntities, #parentEntities );
end
if ( not hasAdditionalQualifiers ) then
for i=2,#parentSnaks,1 do
local parentSnak = parentSnaks[i];
result = result .. ', ' .. context.formatSnak( options, parentSnak );
insertFromSnak( parentSnak, entriesToLookupCategory )
end
end
end
end
end
result = result .. context.formatRefs( options, statement );
if ( categorizeByPlaceOfBirthAndDeath ) then
if ( property == 'P19' ) then result = result .. getCategory( 'P1464', entriesToLookupCategory ); end
if ( property == 'P20' ) then result = result .. getCategory( 'P1465', entriesToLookupCategory ); end
if ( property == 'P119' ) then result = result .. getCategory( 'P1791', entriesToLookupCategory ); end
end
return result;
end
-- append entity id from snak to result
function insertFromSnak( snak, result )
if ( not categorizeByPlaceOfBirthAndDeath ) then
return;
end
if ( snak
and snak.datavalue
and snak.datavalue.type == 'wikibase-entityid'
and snak.datavalue.value
and snak.datavalue.value['entity-type'] == 'item' ) then
table.insert( result, 'Q' .. snak.datavalue.value['numeric-id'] );
end
end
function getCategory( propertyToSearch, entriesToLookupCategoryFor )
for _, placeId in pairs( entriesToLookupCategoryFor ) do
local placeEntity = mw.wikibase.getEntity( placeId );
local claims = WDS.filter( placeEntity.claims, propertyToSearch );
if ( claims ) then
for _, claim in pairs( claims ) do
if ( claim.mainsnak
and claim.mainsnak
and claim.mainsnak.datavalue
and claim.mainsnak.datavalue.type == "wikibase-entityid" ) then
local catEntityId = 'Q' .. claim.mainsnak.datavalue.value["numeric-id"];
local catEntity = mw.wikibase.getEntity( catEntityId );
if ( catEntity and catEntity.sitelinks and catEntity.sitelinks[project] and catEntity.sitelinks[project].title ) then
return '[[' .. catEntity.sitelinks[project].title .. ']]';
end
end
end
end
end
return '';
end
return p;