Модуль:Wikidata/Places2: различия между версиями

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
[отпатрулированная версия][отпатрулированная версия]
Содержимое удалено Содержимое добавлено
Новая страница: «local categorizeByPlace = true; local WDS = require( 'Module:WikidataSelectors' ); local Flags = require( 'Module:Wikidata/Flags' ); local p = {…»
 
м Wikisaurus переименовал страницу Модуль:Wikidata2/Places в Модуль:Wikidata/Places2 без оставления перенаправления: раз модуль Wikidata2 более не нужен
(не показано 89 промежуточных версий 1 участника)
Строка 40: Строка 40:
local boundaries = context.parseTimeBoundariesFromSnak( claim.mainsnak );
local boundaries = context.parseTimeBoundariesFromSnak( claim.mainsnak );
if ( not boundaries ) then return nil; end
if ( not boundaries ) then return nil; end
left = min( left, boundaries[1] );
left = min( left, boundaries[ 1 ] );
right = max( right, boundaries[2] );
right = max( right, boundaries[ 2 ] );
end
end


Строка 164: Строка 164:
and claim.mainsnak.datavalue.value.id ) then
and claim.mainsnak.datavalue.value.id ) then
local typeId = claim.mainsnak.datavalue.value.id;
local typeId = claim.mainsnak.datavalue.value.id;
isCountry = isCountry or countries[typeId];
isCountry = isCountry or countries[ typeId ];
isUnion = isUnion or unions[typeId];
isUnion = isUnion or unions[ typeId ];
end
end
end
end
Строка 172: Строка 172:
end
end


local function isPartOfNext(prevLabel, nextLabel)
local function isPartOfNext( prevLabel, nextLabel )
return (mw.ustring.len(prevLabel) > mw.ustring.len(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);
and ( mw.ustring.sub( prevLabel, mw.ustring.len( prevLabel ) - mw.ustring.len( nextLabel ) + 1 ) == nextLabel );
end
end


Строка 230: Строка 230:
local wbStatus, qualifierEntity = pcall( mw.wikibase.getEntity, qualifierEntityId )
local wbStatus, qualifierEntity = pcall( mw.wikibase.getEntity, qualifierEntityId )
if wbStatus ~= true then
if wbStatus ~= true then
return '[[:d:' .. qualifierEntityId .. '|' .. qualifierEntityId .. ']]<span style="color:#b32424; border-bottom: 1px dotted #b32424; cursor: help; white-space: nowrap" title="Ошибка получения элемента из Викиданных.">×</span>' .. categoryLinksToEntitiesWithWikibaseError;
return '[[:d:' .. qualifierEntityId .. '|' .. qualifierEntityId .. ']]'
.. '<span style="color:#b32424; border-bottom:1px dotted #b32424; cursor:help; white-space:nowrap"'
.. ' title="Ошибка получения элемента из Викиданных.">×</span>'
.. categoryLinksToEntitiesWithWikibaseError;
end
end
parentOptions['text'] = getLabel( context, qualifierEntity, boundaries );
parentOptions[ 'text' ] = getLabel( context, qualifierEntity, boundaries );
local link = context.formatSnak( parentOptions, qualifier );
local link = context.formatSnak( parentOptions, qualifier );


Строка 250: Строка 253:
and statement.mainsnak.datavalue.value
and statement.mainsnak.datavalue.value
and statement.mainsnak.datavalue.value.id ) then
and statement.mainsnak.datavalue.value.id ) then
local wbStatus, entity = pcall( mw.wikibase.getEntity, statement.mainsnak.datavalue.value.id );
local entityId = statement.mainsnak.datavalue.value.id;
local wbStatus, entity = pcall( mw.wikibase.getEntity, entityId );
local parentSnaks = { statement.mainsnak };
local parentSnaks = { statement.mainsnak };
local parentEntities = { entity };
local parentEntities = { entity };


if ( wbStatus == true and actualDateBoundariesProperties ~= nil ) then
if ( wbStatus == true and actualDateBoundariesProperties ~= nil ) then
local filterCapitalOf = { getParentsInBoundariesSnakImpl( context, entity, boundaries, {'P1376'} ) };
local filterCapitalOf = {
[ entityId ] = getParentsInBoundariesSnakImpl( context, entity, boundaries, {'P1376'} )
};
if ( boundaries ) then
if ( boundaries ) then
local entityOptions = context.cloneOptions( options );
local entityOptions = context.cloneOptions( options );
Строка 269: Строка 275:
parent = nil;
parent = nil;
elseif ( #newParentSnaks == 1 ) then
elseif ( #newParentSnaks == 1 ) then
local parentSnak = newParentSnaks[1];
local parentSnak = newParentSnaks[ 1 ];
wbStatus, parent = pcall( mw.wikibase.getEntity, parentSnak.datavalue.value.id );
local parentId = parentSnak.datavalue.value.id;
wbStatus, parent = pcall( mw.wikibase.getEntity, parentId );
if wbStatus == true then
if wbStatus == true then
table.insert( parentSnaks, parentSnak );
table.insert( parentSnaks, parentSnak );
table.insert( parentEntities, parent );
table.insert( parentEntities, parent );
table.insert( filterCapitalOf, getParentsInBoundariesSnakImpl( context, parent, boundaries, {'P1376'} ) );
filterCapitalOf[ parentId ] = getParentsInBoundariesSnakImpl( context, parent, boundaries, { 'P1376' } );
end
end
else
else
Строка 283: Строка 290:
end
end
end
end
local ussr=false;
local nado=false;


if ( not hasAdditionalQualifiers ) then
if ( not hasAdditionalQualifiers ) then
for i = 2, #parentSnaks, 1 do
for i = 2, #parentSnaks, 1 do
local parentSnak = parentSnaks[i];
local parentSnak = parentSnaks[ i ];
insertFromSnak( parentSnak, entriesToLookupCategory )
insertFromSnak( parentSnak, entriesToLookupCategory )
end
end
Строка 293: Строка 302:
do
do
local i = #parentSnaks;
local i = #parentSnaks;
if (i == 2) then
nado=true;
end
while ( i > 1 ) do
while ( i > 1 ) do
if (ussr) then
local prevEntity = parentEntities[i - 1];
if (isInstanceOf( parentEntities[ i ], 'Q236036' ) ) or (isInstanceOf( parentEntities[ i ], 'Q3336843' ) ) or (isInstanceOf( parentEntities[ i ], 'Q12959600' ) ) or (isInstanceOf( parentEntities[ i ], 'Q56219758' ) ) then
for _capitalId, capitalSnaks in pairs( filterCapitalOf ) do
if #capitalSnaks > 0 then
for __, capitalSnak in pairs( capitalSnaks ) do
if parentSnaks[ i ] ~= nil then
if parentSnaks[ i ].datavalue.value.id == capitalSnak.datavalue.value.id then
nado=true;
break;
end
end
end
end
end
table.remove( parentSnaks, i );
table.remove( parentEntities, i );
end
ussr=false;
end
ussr=true;
local prevEntity = parentEntities[ i - 1 ];
-- TODO: use English labels, if there is no current language labels
-- TODO: use English labels, if there is no current language labels
local prevLabel = getLabel( context, prevEntity, boundaries ) or '';
local prevLabel = getLabel( context, prevEntity, boundaries ) or '';
local nextEntity = parentEntities[i];
local nextEntity = parentEntities[ i ];
local nextLabel = getLabel( context, nextEntity, boundaries ) or '';
local nextLabel = getLabel( context, nextEntity, boundaries ) or '';
if ( p.config and p.config.hideSameLabels == true and prevLabel == nextLabel ) then
if ( p.config and p.config.hideSameLabels == true and prevLabel == nextLabel ) then
Строка 307: Строка 341:
table.remove( parentSnaks, i - 1 );
table.remove( parentSnaks, i - 1 );
table.remove( parentEntities, i - 1 );
table.remove( parentEntities, i - 1 );
elseif ( p.config and p.config.hideUnitsForCapitals == true and i ~= #parentSnaks ) then
elseif ( p.config and p.config.hideUnitsForCapitals == true ) then
-- do not ouput items whose capital is the first item
-- do not ouput items whose capital is the first item
local isCapital = false;
local capitalId = nil;
for _, capitalSnaks in pairs( filterCapitalOf ) do
for _capitalId, capitalSnaks in pairs( filterCapitalOf ) do
for __, capitalSnak in pairs( capitalSnaks ) do
if #capitalSnaks > 0 then
for __, capitalSnak in pairs( capitalSnaks ) do
if parentSnaks[i].datavalue.value.id == capitalSnak.datavalue.value.id then
if parentSnaks[ i ] ~= nil then
isCapital = true;
if parentSnaks[ i ].datavalue.value.id == capitalSnak.datavalue.value.id then
break;
capitalId = _capitalId;
break;
end
end
end
end
end
end
end
end

if isCapital then
while ( i > 1 ) do
if (capitalId ~= nil or i ~= #parentSnaks) then
table.remove( parentSnaks, 1 );
table.remove( parentEntities, 1 );
end

if (capitalId ~= nil and nado3) then
if ( i == #parentSnaks ) then
i = i - 1;
end

while ( i > 1 and parentEntities[ i ].id ~= capitalId ) do
table.remove( parentSnaks, i );
table.remove( parentSnaks, i );
table.remove( parentEntities, i );
table.remove( parentEntities, i );
i = i - 1;
i = i - 1;
end
end

nado3=false;
end
end
end
end

i = i - 1;
i = i - 1;

if (i == 2) then
table.remove( parentSnaks, i+1);
table.remove( parentEntities, i+1);
end
if (i == 1) and (nado == true) then
table.remove( parentSnaks, 1);
table.remove( parentEntities, 1);
end
end
end
end
end
Строка 336: Строка 396:


if ( not hasAdditionalQualifiers ) then
if ( not hasAdditionalQualifiers ) then
for i=2,#parentSnaks,1 do
for i = 2, #parentSnaks, 1 do
local parentSnak = parentSnaks[i];
local parentSnak = parentSnaks[ i ];

local parentOptions = context.cloneOptions( options );
local parentOptions = context.cloneOptions( options );
parentOptions['text'] = getLabel( context, parentEntities[i], boundaries );
parentOptions['text'] = getLabel( context, parentEntities[ i ], boundaries );


if p.config.reverseOrder then
if p.config.reverseOrder then
Строка 353: Строка 412:


if wbStatus ~= true and p.config and p.config.catWikibaseError then
if wbStatus ~= true and p.config and p.config.catWikibaseError then
result = result .. p.config.catWikibaseError;
result = result .. p.config.catWikibaseError;
end
end
end
end


if ( options['thisLocationOnly'] ) then
if ( options[ 'thisLocationOnly' ] ) then
result = baseResult .. context.formatRefs( options, statement );
result = baseResult .. context.formatRefs( options, statement );
elseif p.config.reverseOrder then
elseif p.config.reverseOrder then
Строка 364: Строка 423:
result = baseResult .. result .. context.formatRefs( options, statement );
result = baseResult .. result .. context.formatRefs( options, statement );
end
end

if ( categorizeByPlace ) then
if ( categorizeByPlace ) then
if ( property == 'P19' ) then result = result .. getCategory( 'P1464', entriesToLookupCategory ); end
if ( property == 'P19' ) then result = result .. getCategory( 'P1464', entriesToLookupCategory ); end
Строка 370: Строка 428:
if ( property == 'P119' ) then result = result .. getCategory( 'P1791', entriesToLookupCategory ); end
if ( property == 'P119' ) then result = result .. getCategory( 'P1791', entriesToLookupCategory ); end
end
end

return result;
return result;
end
end
Строка 383: Строка 440:
and snak.datavalue.type == 'wikibase-entityid'
and snak.datavalue.type == 'wikibase-entityid'
and snak.datavalue.value
and snak.datavalue.value
and snak.datavalue.value['entity-type'] == 'item' ) then
and snak.datavalue.value[ 'entity-type' ] == 'item' ) then
table.insert( result, snak.datavalue.value.id );
table.insert( result, snak.datavalue.value.id );
end
end
Строка 399: Строка 456:
and claim.mainsnak
and claim.mainsnak
and claim.mainsnak.datavalue
and claim.mainsnak.datavalue
and claim.mainsnak.datavalue.type == "wikibase-entityid" ) then
and claim.mainsnak.datavalue.type == 'wikibase-entityid' ) then
local catEntityId = claim.mainsnak.datavalue.value.id;
local catEntityId = claim.mainsnak.datavalue.value.id;
local wbStatus, catEntity = pcall( mw.wikibase.getEntity, catEntityId );
local wbStatus, catEntity = pcall( mw.wikibase.getEntity, catEntityId );
Строка 426: Строка 483:
local label = nil;
local label = nil;
if entity.labels then
if entity.labels then
if entity.labels[langCode] and entity.labels[langCode].value then
if entity.labels[ langCode ] and entity.labels[ langCode ].value then
label = entity.labels[langCode].value;
label = entity.labels[ langCode ].value;
elseif entity.labels.en and entity.labels.en.value then
elseif entity.labels.en and entity.labels.en.value then
label = entity.labels.en.value;
label = entity.labels.en.value;
Строка 455: Строка 512:


local function calculateEndDateTimestamp( context, options, statement )
local function calculateEndDateTimestamp( context, options, statement )
if (not context) then error('context not specified') end;
if ( not context ) then error( 'context not specified' ) end;
if (not options) then error('options not specified') end;
if ( not options ) then error( 'options not specified' ) end;
if (not options.entity) then error('options.entity missing') end;
if ( not options.entity ) then error( 'options.entity missing' ) end;
if (not statement) then error('statement not specified') end;
if ( not statement ) then error( 'statement not specified' ) end;


if ( statement.qualifiers and statement.qualifiers.P582 ) then
if ( statement.qualifiers and statement.qualifiers.P582 ) then

Версия от 13:03, 1 ноября 2018

Документация

Вариант Модуль:Wikidata/Places, выдающий укороченные геоцепочки для Шаблон:ВД-Преамбула. Пожалуйста, не используйте этот модуль для других целей, используйте основную версию.

local categorizeByPlace = true;

local WDS = require( 'Module:WikidataSelectors' );
local Flags = require( 'Module:Wikidata/Flags' );
local p = {
	config = {
		hideSameLabels = false,
		hidePartOfLabels = false,
		hideUnitsForCapitals = true,
		reverseOrder = false,
		catAmbiguousGeoChains = '[[Категория:Википедия:Страницы с неоднозначными геоцепочками]]',
		catWikibaseError = '[[Категория:Википедия:Страницы с ошибками скриптов, использующих Викиданные]]'
	}
};

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 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 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
			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 = result.datavalue.value.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.id ) then
				local typeId = claim.mainsnak.datavalue.value.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 actualDateBoundariesProperties = nil;
	if ( property == 'P19' ) then actualDateBoundariesProperties = {'P569','P570'}; end
	if ( property == 'P20' ) then actualDateBoundariesProperties = {'P570','P569'}; end
	if ( property == 'P119' ) then actualDateBoundariesProperties = {'P570','P569'}; end

	local boundaries = nil;
	if ( actualDateBoundariesProperties ~= nil ) then
		boundaries = getTimeBoundariesFromProperties( context, actualDateBoundariesProperties );
	end

	local entriesToLookupCategory = {};

	local circumstances = context.getSourcingCircumstances( statement );
	local result = '';
	local baseResult = 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
				local parentOptions = context.cloneOptions( options );
				local qualifierEntityId = qualifier.datavalue.value.id;
				local wbStatus, qualifierEntity = pcall( mw.wikibase.getEntity, qualifierEntityId )
				if wbStatus ~= true then
					return '[[:d:' .. qualifierEntityId .. '|' .. qualifierEntityId .. ']]<span style="color:#b32424; border-bottom: 1px dotted #b32424; cursor: help; white-space: nowrap" title="Ошибка получения элемента из Викиданных.">×</span>' .. categoryLinksToEntitiesWithWikibaseError;
				end
				parentOptions['text'] = getLabel( context, qualifierEntity, boundaries );
				local link = context.formatSnak( parentOptions, qualifier );

				if p.config.reverseOrder then
					result = link .. ', ' .. result;
				else
					result = result .. ', ' .. link;
				end
				insertFromSnak( qualifier, entriesToLookupCategory )
				hasAdditionalQualifiers = true;
			end
		end

		--country
		if ( statement.qualifiers.P17 ) then
			for i, qualifier in ipairs( statement.qualifiers.P17 ) do
				local parentOptions = context.cloneOptions( options );
				local qualifierEntityId = qualifier.datavalue.value.id;
				local wbStatus, qualifierEntity = pcall( mw.wikibase.getEntity, qualifierEntityId )
				if wbStatus ~= true then
					return '[[:d:' .. qualifierEntityId .. '|' .. qualifierEntityId .. ']]'
						.. '<span style="color:#b32424; border-bottom:1px dotted #b32424; cursor:help; white-space:nowrap"'
						.. ' title="Ошибка получения элемента из Викиданных.">×</span>'
						.. categoryLinksToEntitiesWithWikibaseError;
				end
				parentOptions[ 'text' ] = getLabel( context, qualifierEntity, boundaries );
				local link = context.formatSnak( parentOptions, qualifier );

				if p.config.reverseOrder then
					result = link .. ', ' .. result;
				else
					result = result .. ', ' .. link;
				end
				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.id ) then
		local entityId = statement.mainsnak.datavalue.value.id;
		local wbStatus, entity = pcall( mw.wikibase.getEntity, entityId );
		local parentSnaks = { statement.mainsnak };
		local parentEntities = { entity };

		if ( wbStatus == true and actualDateBoundariesProperties ~= nil ) then
			local filterCapitalOf = {
				[ entityId ] = getParentsInBoundariesSnakImpl( context, entity, boundaries, {'P1376'} )
			};
			if ( boundaries ) then
				local entityOptions = context.cloneOptions( options );
				entityOptions['text'] = getLabel( context, entity, boundaries );
				baseResult = context.formatSnak( entityOptions, statement.mainsnak, circumstances );

				local parent = entity;
				local wbStatus = true;
				while ( wbStatus == true and parent ~= nil ) do
					-- get parent
					local newParentSnaks = getParentsInBoundariesSnak( context, parent, boundaries );
					if ( not newParentSnaks or #newParentSnaks == 0 ) then
						parent = nil;
					elseif ( #newParentSnaks == 1 ) then
						local parentSnak = newParentSnaks[ 1 ];
						local parentId = parentSnak.datavalue.value.id;
						wbStatus, parent = pcall( mw.wikibase.getEntity, parentId );
						if wbStatus == true then
							table.insert( parentSnaks, parentSnak );
							table.insert( parentEntities, parent );
							filterCapitalOf[ parentId ] = getParentsInBoundariesSnakImpl( context, parent, boundaries, { 'P1376' } );
						end
					else
						parent = nil;
						if p.config and p.config.catAmbiguousGeoChains then
							result = result .. p.config.catAmbiguousGeoChains;
						end
					end
				end
				local ussr=false;
				local nado=false;

				if ( not hasAdditionalQualifiers ) then
					for i = 2, #parentSnaks, 1 do
						local parentSnak = parentSnaks[ i ];
						insertFromSnak( parentSnak, entriesToLookupCategory )
					end
				end

				do
					local i = #parentSnaks;
                                        if (i == 2) then
                                          nado=true;
                                        end
                    
					while ( i > 1 ) do
						if (ussr) then
							if (isInstanceOf( parentEntities[ i ], 'Q236036' ) ) or (isInstanceOf( parentEntities[ i ], 'Q3336843' ) ) or (isInstanceOf( parentEntities[ i ], 'Q12959600' ) ) or (isInstanceOf( parentEntities[ i ], 'Q56219758' ) ) then
								for _capitalId, capitalSnaks in pairs( filterCapitalOf ) do
									if #capitalSnaks > 0 then
										for __, capitalSnak in pairs( capitalSnaks ) do
											if parentSnaks[ i ] ~= nil then
												if parentSnaks[ i ].datavalue.value.id == capitalSnak.datavalue.value.id then
													nado=true;
													break;
												end
											end
										end
									end
								end
								table.remove( parentSnaks, i );
								table.remove( parentEntities, i );
							end
							ussr=false;
						end
						
						ussr=true;
						local prevEntity = parentEntities[ i - 1 ];
						-- TODO: use English labels, if there is no current language labels
						local prevLabel = getLabel( context, prevEntity, boundaries ) or '';
						local nextEntity = parentEntities[ i ];
						local nextLabel = getLabel( context, nextEntity, boundaries ) or '';
						if ( p.config and p.config.hideSameLabels == true and prevLabel == nextLabel ) then
							-- do not output same label twice (NY, NY, USA)
							table.remove( parentSnaks, i );
							table.remove( parentEntities, i );
						elseif ( p.config and p.config.hidePartOfLabels == true and 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 );
						elseif ( p.config and p.config.hideUnitsForCapitals == true ) then
							-- do not ouput items whose capital is the first item
							local capitalId = nil;
							for _capitalId, capitalSnaks in pairs( filterCapitalOf ) do
							    if #capitalSnaks > 0 then
							        for __, capitalSnak in pairs( capitalSnaks ) do
								        if parentSnaks[ i ] ~= nil then
											if parentSnaks[ i ].datavalue.value.id == capitalSnak.datavalue.value.id then
												capitalId = _capitalId;
												break;
											end
										end
									end
								end
							end

							if (capitalId ~= nil or i ~= #parentSnaks) then
								table.remove( parentSnaks, 1 );
								table.remove( parentEntities, 1 );
							end

							if (capitalId ~= nil and nado3) then
								if ( i == #parentSnaks ) then
									i = i - 1;
								end

								while ( i > 1 and parentEntities[ i ].id ~= capitalId ) do
									table.remove( parentSnaks, i );
									table.remove( parentEntities, i );
									i = i - 1;
								end

								nado3=false;
							end
						end

						i = i - 1;

						if (i == 2) then
							table.remove( parentSnaks, i+1);
							table.remove( parentEntities, i+1);
						end
						if (i == 1) and (nado == true) then
							table.remove( parentSnaks, 1);
							table.remove( parentEntities, 1);
						end
					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 ];
						local parentOptions = context.cloneOptions( options );
						parentOptions['text'] = getLabel( context, parentEntities[ i ], boundaries );

						if p.config.reverseOrder then
							result = context.formatSnak( parentOptions, parentSnak ) .. ', ' .. result;
						else
							result = result .. ', ' .. context.formatSnak( parentOptions, parentSnak );
						end
					end
				end
			end
		end

		if wbStatus ~= true and p.config and p.config.catWikibaseError then
				result = result .. p.config.catWikibaseError;
		end
	end

	if ( options[ 'thisLocationOnly' ] ) then
		result = baseResult  .. context.formatRefs( options, statement );
	elseif p.config.reverseOrder then
		result = result .. baseResult .. context.formatRefs( options, statement );
	else
		result = baseResult .. result .. context.formatRefs( options, statement );
	end
	if ( categorizeByPlace ) 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 categorizeByPlace ) 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, snak.datavalue.value.id );
	end
end

function getCategory( propertyToSearch, entriesToLookupCategoryFor )
	for _, placeId in pairs( entriesToLookupCategoryFor ) do
		local wbStatus, placeEntity = pcall( mw.wikibase.getEntity, placeId );
		if wbStatus == true and placeEntity then
			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 = claim.mainsnak.datavalue.value.id;
						local wbStatus, catEntity = pcall( mw.wikibase.getEntity, catEntityId );
						if ( wbStatus == true and catEntity and catEntity:getSitelink() ) then
							return '[[' .. catEntity:getSitelink() .. ']]';
						end
					end
				end
			end
		end
	end
	return '';
end

-- get current of historic name of place
function getLabel( context, entity, boundaries )
	if not entity then
		return nil;
	end

	local lang = mw.language.getContentLanguage();
	local langCode = lang:getCode();

	-- name from label
	-- TODO: lang:getFallbackLanguages()
	local label = nil;
	if entity.labels then
		if entity.labels[ langCode ] and entity.labels[ langCode ].value then
			label = entity.labels[ langCode ].value;
		elseif entity.labels.en and entity.labels.en.value then
			label = entity.labels.en.value;
		end
	end

	-- name from properties
	local results = getParentsInBoundariesSnakImpl( context, entity, boundaries, {
		'P1813[language:' .. langCode .. ']',
		'P1448[language:' .. langCode .. ']',
		'P1705[language:' .. langCode .. ']'
	} );

	for r, result in pairs( results ) do
		if result.datavalue
				and result.datavalue.value
				and result.datavalue.value.text then
			label = result.datavalue.value.text;
			break;
		end
	end

	return label;
end

p.getLabel = getLabel;

local function calculateEndDateTimestamp( context, options, statement )
	if ( not context ) then error( 'context not specified' ) end;
	if ( not options ) then error( 'options not specified' ) end;
	if ( not options.entity ) then error( 'options.entity missing' ) end;
	if ( not statement ) then error( 'statement not specified' ) end;

	if ( statement.qualifiers and statement.qualifiers.P582 ) then
		for i, qualifier in ipairs(statement.qualifiers.P582 ) do
			local parsedTime = context.parseTimeFromSnak( qualifier );
			if ( parsedTime ) then
				return parsedTime;
			end
		end
	end

	-- check death day... do we have it at all?
	for h, propertyId in pairs( { "P570", "P577", "P571" } ) do
		local dateClaims = context.selectClaims( options, propertyId );
		if ( dateClaims ) then
			for i, statement in ipairs( dateClaims ) do
				local parsedTime = context.parseTimeFromSnak( statement.mainsnak );
				if ( parsedTime ) then
					return parsedTime;
				end
			end
		end
	end

	-- TODO: check other "end" properties

	-- no death day
	return os.time() * 1000;
end

function p.formatCountryClaimWithFlag( context, options, statement )
	if (not context) then error('context not specified') end;
	if (not options) then error('options not specified') end;
	if (not options.entity) then error('options.entity is missing') end;
	if (not statement) then error('statement not specified') end;

	local countryEntityId = nil;
	local countryEntity = nil;
	local wbStatus = false;
	if ( statement.mainsnak and statement.mainsnak.datavalue and statement.mainsnak.datavalue.value and statement.mainsnak.datavalue.value.id ) then
		countryEntityId = statement.mainsnak.datavalue.value.id;
		wbStatus, countryEntity = pcall( mw.wikibase.getEntity, countryEntityId );
	end
	
	if wbStatus ~= true or not countryEntity then
		local result = '<span class="country-name">' .. context.formatStatementDefault( context, options, statement ) .. '</span>';
		if wbStatus ~= true and p.config and p.config.catWikibaseError then
			result = result .. p.config.catWikibaseError;
		end
		return result;
	end

	local endDateTimestamp = calculateEndDateTimestamp( context, options, statement );
	local boundaries = getTimeBoundariesFromProperties( context, {'P570', 'P577', 'P571'} );

	local countryOptions = context.cloneOptions( options );
	if not countryOptions['text'] or countryOptions['text'] == '' then
		countryOptions['text'] = getLabel( context, countryEntity, boundaries );
	end

	local flag = Flags.getFlag( context, countryEntityId, endDateTimestamp );	
	if ( flag ) then
		return flag .. '&nbsp;<span class="country-name">' .. context.formatStatementDefault( context, countryOptions, statement ) .. '</span>';
	end

	return '<span class="country-name">' .. context.formatStatementDefault( context, countryOptions, statement ) .. '</span>';
end

return p;