Модуль:Wikidata/Places/Custom
< Модуль:Wikidata | Places
Дакументацыю да гэтага модуля можна стварыць у Модуль:Wikidata/Places/Custom/Дакументацыя
local WDS = require( 'Module:WikidataSelectors' );
local WD = require( 'Module:Wikidata' );
local Flags = require( 'Module:Wikidata/Flags' );
local p = {};
local project = 'bewiki';
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 splitISO8601(str)
if 'table' == type(str) then
if str.args and str.args[1] then
str = '' .. str.args[1]
else
return 'unknown argument type: ' .. type( str ) .. ': ' .. table.tostring( str )
end
end
local Y, M, D = (function(str)
local pattern = "(%-?%d+)%-(%d+)%-(%d+)T"
local Y, M, D = mw.ustring.match( str, pattern )
return tonumber(Y), tonumber(M), tonumber(D)
end) (str);
local h, m, s = (function(str)
local pattern = "T(%d+):(%d+):(%d+)%Z";
local H, M, S = mw.ustring.match( str, pattern);
return tonumber(H), tonumber(M), tonumber(S);
end) (str);
local oh,om = ( function(str)
if str:sub(-1)=="Z" then return 0,0 end; -- ends with Z, Zulu time
-- matches ±hh:mm, ±hhmm or ±hh; else returns nils
local pattern = "([-+])(%d%d):?(%d?%d?)$";
local sign, oh, om = mw.ustring.match( str, pattern);
sign, oh, om = sign or "+", oh or "00", om or "00";
return tonumber(sign .. oh), tonumber(sign .. om);
end )(str)
return {year=Y, month=M, day=D, hour=(h+oh), min=(m+om), sec=s};
end
local function parseTimeBoundaries( time, precision )
local s = splitISO8601( time );
if (not s) then return nil; end
if ( precision >= 0 and precision <= 8 ) then
local powers = { 1000000000 , 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10 }
local power = powers[ precision + 1 ];
local left = s.year - ( s.year % power );
return { tonumber(os.time( {year=left, month=1, day=1, hour=0, min=0, sec=0} )) * 1000,
tonumber(os.time( {year=left + power - 1, month=12, day=31, hour=29, min=59, sec=58} )) * 1000 + 1999 };
end
if ( precision == 9 ) then
return { tonumber(os.time( {year=s.year, month=1, day=1, hour=0, min=0, sec=0} )) * 1000,
tonumber(os.time( {year=s.year, month=12, day=31, hour=23, min=59, sec=58} )) * 1000 + 1999 };
end
if ( precision == 10 ) then
local lastDays = {31, 28.25, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
local lastDay = lastDays[s.month];
return { tonumber(os.time( {year=s.year, month=s.month, day=1, hour=0, min=0, sec=0} )) * 1000,
tonumber(os.time( {year=s.year, month=s.month, day=lastDay, hour=23, min=59, sec=58} )) * 1000 + 1999 };
end
if ( precision == 11 ) then
return { tonumber(os.time( {year=s.year, month=s.month, day=s.day, hour=0, min=0, sec=0} )) * 1000,
tonumber(os.time( {year=s.year, month=s.month, day=s.day, hour=23, min=59, sec=58} )) * 1000 + 1999 };
end
if ( precision == 12 ) then
return { tonumber(os.time( {year=s.year, month=s.month, day=s.day, hour=s.hour, min=0, sec=0} )) * 1000,
tonumber(os.time( {year=s.year, month=s.month, day=s.day, hour=s.hour, min=59, sec=58} )) * 1000 + 19991999 };
end
if ( precision == 13 ) then
return { tonumber(os.time( {year=s.year, month=s.month, day=s.day, hour=s.hour, min=s.min, sec=0} )) * 1000,
tonumber(os.time( {year=s.year, month=s.month, day=s.day, hour=s.hour, min=s.min, sec=58} )) * 1000 + 1999 };
end
if ( precision == 14 ) then
local t = tonumber(os.time( {year=s.year, month=s.month, day=s.day, hour=s.hour, min=s.min, sec=0} ) );
return { t * 1000, t * 1000 + 999 };
end
error('Unsupported precision: ' .. precision );
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 getTimeBoundariesFromProperties( context, propertyIds )
for _, propertyId in ipairs( propertyIds ) do
local result = getTimeBoundariesFromProperty( context, propertyId );
if result then
return result;
end
end
return nil;
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, propertyIds )
local results = {};
if not propertyIds or #propertyIds == 0 then
return results;
end
if entity.claims then
for _, propertyId in ipairs( propertyIds ) do
local filteredClaims = WDS.filter( entity.claims, propertyId .. '[rank:preferred, rank:normal]' );
if filteredClaims then
for _, claim in pairs( filteredClaims ) do
if not boundaries or not propertyIds or #propertyIds == 0 then
table.insert( results, claim.mainsnak );
else
local endBoundaries = getTimeBoundariesFromQualifiers( context, claim, 'P582' );
if ( endBoundaries == nil ) then
table.insert( results, claim.mainsnak );
end
end
end
end
if #results > 0 then
break;
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'} ) -- located in
if not results or #results == 0 then
results = getParentsInBoundariesSnakImpl( context, entity, boundaries, {'P17'} ) -- country
end
for r, result in pairs( results ) do
if result.snaktype ~= 'value' then
return nil;
end
local resultId = 'Q' .. result.datavalue.value['numeric-id'];
if ( resultId == entity.id ) then
return nil;
end
end
return results;
end
function p.getStatus( frame )
local args = frame.args;
local entity = mw.wikibase.getEntityObject( );
if ( not entity ) then
return 'Населены пункт'
end
local filteredClaims = WDS.filter( entity.claims, 'P31[Q7216840,Q20019082,Q15078955,Q27587491]' );
if ( filteredClaims and #filteredClaims > 0 ) then
return 'Пасёлак гарадскога тыпу'
else
filteredClaims = WDS.filter( entity.claims, 'P31[Q106389302,Q7216840,Q12131640,Q5123999,Q515,Q7930989,Q12131624]' );
if ( filteredClaims and #filteredClaims > 0 ) then
return 'Горад'
else
filteredClaims = WDS.filter( entity.claims, 'P31[Q2514025]' );
if ( filteredClaims and #filteredClaims > 0 ) then
return 'Пасёлак'
else
filteredClaims = WDS.filter( entity.claims, 'P31[Q5084, Q21672098]' );
if ( filteredClaims and #filteredClaims > 0 ) then
return 'Вёска'
else
filteredClaims = WDS.filter( entity.claims, 'P31[Q532]' );
if ( filteredClaims and #filteredClaims > 0 ) then
return 'Сяло'
else
filteredClaims = WDS.filter( entity.claims, 'P31[Q748331]' );
if ( filteredClaims and #filteredClaims > 0 ) then
return 'Станіца'
else
filteredClaims = WDS.filter( entity.claims, 'P31[Q771444]' );
if ( filteredClaims and #filteredClaims > 0 ) then
return 'Аул'
else
filteredClaims = WDS.filter( entity.claims, 'P31[Q27517161]' );
if ( filteredClaims and #filteredClaims > 0 ) then
return 'Курортны пасёлак'
else
return 'Населены пункт'
end
end
end
end
end
end
end
end
end
function p.getRegion( frame )
local args = frame.args;
if not args.regionEntity then
error( 'regionEntity is absent' )
end
local statement = mw.wikibase.getEntityObject( );
local context = {
entity = statement}
context.parseTimeBoundariesFromSnak = function( snak )
if ( snak and snak.datavalue and snak.datavalue.value and snak.datavalue.value.time and snak.datavalue.value.precision ) then
return parseTimeBoundaries( snak.datavalue.value.time, snak.datavalue.value.precision );
end
return nil;
end
local result = '';
local entity = statement;
if ( not entity) then
return ''
else
local filteredClaims = WDS.filter( entity.claims, 'P31[' .. args.regionEntity .. ']' );
if ( not filteredClaims or #filteredClaims == 0 ) then
local parent = entity;
while ( parent ~= nil ) do
-- get parent
local newParentSnaks = getParentsInBoundariesSnak( context, parent, {nil, nil} );
if ( not newParentSnaks or #newParentSnaks == 0 ) then
parent = nil;
else
--if ( #newParentSnaks > 1 ) then
-- result = result .. '[[Катэгорыя:Вікіпедыя:Старонкі з неадназначнымі геаланцужкамі]]';
--end
local parentSnak = newParentSnaks[1];
mw.log( 'snak found (' .. parentSnak.datavalue.value['numeric-id'] .. ')');
parent = mw.wikibase.getEntity( 'Q' .. parentSnak.datavalue.value['numeric-id'] );
local regionSnaks = WDS.filter(parent.claims, 'P31[' .. args.regionEntity .. ']')
if ( not regionSnaks or #regionSnaks == 0 ) then
mw.log( 'snak has not needed type. Continue search');
else
mw.log( 'snak has needed type');
local label = mw.wikibase.label( 'Q' .. parentSnak.datavalue.value['numeric-id'] );
if (mw.wikibase.sitelink( 'Q' .. parentSnak.datavalue.value['numeric-id'] )) then
if args.label == '1' then
result = label;
elseif args.plainlink == '1' then
result = mw.wikibase.sitelink( 'Q' .. parentSnak.datavalue.value['numeric-id'] );
else
result = WD.simpleFormatEntityId(parent.id);
end;
else
local title = mw.title.new( label );
if args.label == '1' then
result = label;
else
result = WD.simpleFormatEntityId(parent.id)
end
end
--if ( #newParentSnaks > 1 ) then
-- result = result .. '[[Катэгорыя:Вікіпедыя:Старонкі з неадназначнымі геаланцужкамі]]';
--end
return result;
end
end
end
else
mw.log( 'snak has needed type');
result = mw.wikibase.sitelink( mw.wikibase.getEntityIdForCurrentPage()) .. '|' .. mw.wikibase.label( mw.wikibase.getEntityIdForCurrentPage() );
return result;
end
end
return result;
end
-- атрыманне ланцужка басейнаў для гідраграфічнага аб’екта
function p.getBasin( frame )
local args = frame.args
local entity = mw.wikibase.getEntity();
local parent = entity;
local result = ''
while ( parent ~= nil and parent.claims ) do
if parent.claims.P403 then
parent = mw.wikibase.getEntity( 'Q' .. parent.claims.P403[1].mainsnak.datavalue.value['numeric-id'] );
local label = WD.simpleFormatEntityId(parent.id)
mw.log(label)
if (result == '') then
result = result .. label
else
result = result .. ' → ' .. label
end
else
parent = nil
end
end
return result;
end
return p;