Module:Wikidata/Places

localcategorizeByPlace=true;localWDS=require('Module:WikidataSelectors');localFlags=require('Module:Wikidata/Flags');localp={config={hideSameLabels=false,hidePartOfLabels=false,hideUnitsForCapitals=true,reverseOrder=false,catAmbiguousGeoChains='[[Kateqoriya:Vikipediya:Coğrafi zənciri olan səhifələr]]',catWikibaseError='[[Kateqoriya:Vikipediya:Vikiverilənlər istifadə edən skript xətalı səhifələr]]'}};localfunctionmin(prev,next)ifprev==nilthenreturnnext;elseifprev>nextthenreturnnext;elsereturnprev;endendlocalfunctionmax(prev,next)ifprev==nilthenreturnnext;elseifprev<nextthenreturnnext;elsereturnprev;endendlocalfunctiongetTimeBoundariesFromProperty(context,propertyId)localdateClaims=WDS.filter(context.entity.claims,propertyId);ifnotdateClaimsor#dateClaims==0thenreturnnil;end-- only support exact date so far, but need improvmentlocalleft=nil;localright=nil;for_,claiminpairs(dateClaims)doifnotclaim.mainsnakthenreturnnil;endlocalboundaries=context.parseTimeBoundariesFromSnak(claim.mainsnak);ifnotboundariesthenreturnnil;endleft=min(left,boundaries[1]);right=max(right,boundaries[2]);endifnotleftornotrightthenreturnnil;endreturn{left,right};endlocalfunctiongetTimeBoundariesFromProperties(context,propertyIds)for_,propertyIdinipairs(propertyIds)dolocalresult=getTimeBoundariesFromProperty(context,propertyId);ifresultthenreturnresult;endendreturnnil;endlocalfunctiongetTimeBoundariesFromQualifiers(context,statement,qualifierId)-- only support exact date so far, but need improvmentlocalleft=nil;localright=nil;ifstatement.qualifiersandstatement.qualifiers[qualifierId]thenfor_,qualifierinpairs(statement.qualifiers[qualifierId])dolocalboundaries=context.parseTimeBoundariesFromSnak(qualifier);ifnotboundariesthenreturnnil;endleft=min(left,boundaries[1]);right=max(right,boundaries[2]);endendifnotleftornotrightthenreturnnil;endreturn{left,right};endlocalfunctiongetParentsInBoundariesSnakImpl(context,entityId,boundaries,propertyIds,selectors)localresults={};ifnotpropertyIdsor#propertyIds==0thenreturnresults;endfor_,propertyIdinipairs(propertyIds)doif(notstring.match(propertyId,'^P%d+$'))thenerror('Incorrect propertyId: '+propertyId);endlocalselector;if(selectors~=nil)thenselector=selectors[propertyId]orpropertyId;elseselector=propertyId;endlocalentityClaims={};entityClaims[propertyId]=mw.wikibase.getAllStatements(entityId,propertyId);localfilteredClaims=WDS.filter(entityClaims,selector..'[rank:preferred, rank:normal]');iffilteredClaimsthenfor_,claiminpairs(filteredClaims)doifnotboundariesornotpropertyIdsor#propertyIds==0thentable.insert(results,claim.mainsnak);elselocalstartBoundaries=getTimeBoundariesFromQualifiers(context,claim,'P580');localendBoundaries=getTimeBoundariesFromQualifiers(context,claim,'P582');if(startBoundaries==nilorstartBoundaries[2]<=boundaries[1])and(endBoundaries==nilorendBoundaries[1]>=boundaries[2])thentable.insert(results,claim.mainsnak);endendendendif#results>0thenbreak;endendreturnresults;endlocalfunctiongetParentsInBoundariesSnak(context,entityId,boundaries)ifnotentityIdthenerror('entityId must be specified');endiftype(entityId)~='string'thenerror('entityId must be string');endifnotboundariesthenerror('boundaries must be specified');endiftype(boundaries)~='table'thenerror('boundaries must be table');endlocalresults=getParentsInBoundariesSnakImpl(context,entityId,boundaries,{'P131'})-- located inifnotresultsor#results==0thenresults=getParentsInBoundariesSnakImpl(context,entityId,boundaries,{'P17'})-- countryendforr,resultinpairs(results)doifresult.snaktype~='value'thenreturnnil;endlocalresultId=result.datavalue.value.id;ifresultId==entityIdthenreturnnil;endendreturnresults;endlocalunions={Q1140229=true,-- political unionQ3623811=true,-- Экономический союзQ4120211=true-- региональная организация}localcountries={Q6256=true,-- странаQ7275=true,-- государствоQ3024240=true,-- историческое государствоQ3624078=true-- суверенное государство}localfunctionisSkipTopLevel(entity)localisCountry=false;localisUnion=false;ifentityandentity.claimsandentity.claims.P31thenforc,claiminpairs(entity.claims.P31)doifclaimandclaim.mainsnakandclaim.mainsnak.datavalueandclaim.mainsnak.datavalue.valueandclaim.mainsnak.datavalue.value.idthenlocaltypeId=claim.mainsnak.datavalue.value.id;isCountry=isCountryorcountries[typeId];isUnion=isUnionorunions[typeId];endendendreturnisUnionandnotisCountry;endlocalfunctionisPartOfNext(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:P119functionp.formatPlaceWithQualifiers(context,options,statement)localproperty=mw.ustring.upper(options.property);localactualDateBoundariesProperties=nil;ifproperty=='P19'thenactualDateBoundariesProperties={'P569','P570'};endifproperty=='P20'thenactualDateBoundariesProperties={'P570','P569'};endifproperty=='P119'thenactualDateBoundariesProperties={'P570','P569'};endifproperty=='P159'thenactualDateBoundariesProperties={'P576'};endlocalboundaries=nil;ifactualDateBoundariesProperties~=nilthenboundaries=getTimeBoundariesFromProperties(context,actualDateBoundariesProperties);if(boundaries==nil)and(property=='P159')thenboundaries={os.time()*1000,os.time()*1000};endendlocalentriesToLookupCategory={};localcircumstances=context.getSourcingCircumstances(statement);localresult='';localbaseResult=context.formatSnak(options,statement.mainsnak,circumstances);ifnotbaseResultthenreturnnil;endinsertFromSnak(statement.mainsnak,entriesToLookupCategory)localhasAdditionalQualifiers=false;ifstatement.qualifiersthen--parent divisionsifstatement.qualifiers.P131thenfori,qualifierinipairs(statement.qualifiers.P131)dolocalparentOptions=context.cloneOptions(options);localqualifierEntityId=qualifier.datavalue.value.id;parentOptions['text']=getLabel(context,qualifierEntityId,boundaries);locallink=context.formatSnak(parentOptions,qualifier);ifp.config.reverseOrderthenresult=link..', '..result;elseresult=result..', '..link;endinsertFromSnak(qualifier,entriesToLookupCategory)hasAdditionalQualifiers=true;endend--countryifstatement.qualifiers.P17thenfori,qualifierinipairs(statement.qualifiers.P17)dolocalparentOptions=context.cloneOptions(options);localqualifierEntityId=qualifier.datavalue.value.id;parentOptions['text']=getLabel(context,qualifierEntityId,boundaries);locallink=context.formatSnak(parentOptions,qualifier);ifp.config.reverseOrderthenresult=link..', '..result;elseresult=result..', '..link;endinsertFromSnak(qualifier,entriesToLookupCategory)hasAdditionalQualifiers=true;endendendifstatement.mainsnakandstatement.mainsnak.datavalueandstatement.mainsnak.datavalue.valueandstatement.mainsnak.datavalue.value.idthenlocalentityId=statement.mainsnak.datavalue.value.id;localparentSnaks={statement.mainsnak};localparentEntityIds={entityId};ifactualDateBoundariesProperties~=nilthenlocalfilterCapitalOf={[entityId]=getParentsInBoundariesSnakImpl(context,entityId,boundaries,{'P1376'})};ifboundariesthenlocalentityOptions=context.cloneOptions(options);entityOptions['text']=getLabel(context,entityId,boundaries);baseResult=context.formatSnak(entityOptions,statement.mainsnak,circumstances);localparentId=entityId;whileparentId~=nildo-- get parentlocalnewParentSnaks=getParentsInBoundariesSnak(context,parentId,boundaries);ifnotnewParentSnaksor#newParentSnaks==0thenparentId=nil;elseif#newParentSnaks==1thenlocalparentSnak=newParentSnaks[1];parentId=parentSnak.datavalue.value.id;table.insert(parentSnaks,parentSnak);table.insert(parentEntityIds,parentId);filterCapitalOf[parentId]=getParentsInBoundariesSnakImpl(context,parentId,boundaries,{'P1376'});elseparentId=nil;ifp.configandp.config.catAmbiguousGeoChainsthenresult=result..p.config.catAmbiguousGeoChains;endendendifnothasAdditionalQualifiersthenfori=2,#parentSnaks,1dolocalparentSnak=parentSnaks[i];insertFromSnak(parentSnak,entriesToLookupCategory)endenddolocali=#parentSnaks;whilei>1dolocalprevEntityId=parentEntityIds[i-1];-- TODO: use English labels, if there is no current language labelslocalprevLabel=getLabel(context,prevEntityId,boundaries)or'';localnextEntityId=parentEntityIds[i];localnextLabel=getLabel(context,nextEntityId,boundaries)or'';ifp.configandp.config.hideSameLabels==trueandprevLabel==nextLabelthen-- do not output same label twice (NY, NY, USA)table.remove(parentSnaks,i);table.remove(parentEntityIds,i);elseifp.configandp.config.hidePartOfLabels==trueandisPartOfNext(prevLabel,' '..nextLabel)then-- do not output same label if it's part of previostable.remove(parentSnaks,i-1);table.remove(parentEntityIds,i-1);elseifp.configandp.config.hideUnitsForCapitals==truethen-- do not ouput items whose capital is the first itemlocalcapitalId=nil;for_capitalId,capitalSnaksinpairs(filterCapitalOf)doif#capitalSnaks>0thenfor__,capitalSnakinpairs(capitalSnaks)doifparentSnaks[i].datavalue.value.id==capitalSnak.datavalue.value.idthencapitalId=_capitalId;break;endendendendifcapitalId~=nilthenifi==#parentSnakstheni=i-1;endwhilei>1andparentEntityIds[i]~=capitalIddotable.remove(parentSnaks,i);table.remove(parentEntityIds,i);i=i-1;endendendi=i-1;endendifisSkipTopLevel(parentEntityIds[#parentEntityIds])thentable.remove(parentSnaks,#parentEntityIds);table.remove(parentEntityIds,#parentEntityIds);endifnothasAdditionalQualifiersthenfori=2,#parentSnaks,1dolocalparentSnak=parentSnaks[i];localparentOptions=context.cloneOptions(options);parentOptions['text']=getLabel(context,parentEntityIds[i],boundaries);ifp.config.reverseOrderthenresult=context.formatSnak(parentOptions,parentSnak)..', '..result;elseresult=result..', '..context.formatSnak(parentOptions,parentSnak);endendendendendendifoptions['thisLocationOnly']thenresult=baseResult..context.formatRefs(options,statement);elseifp.config.reverseOrderthenresult=result..baseResult..context.formatRefs(options,statement);elseresult=baseResult..result..context.formatRefs(options,statement);endifcategorizeByPlacethenifproperty=='P19'thenresult=result..getCategory('P1464',entriesToLookupCategory);endifproperty=='P20'thenresult=result..getCategory('P1465',entriesToLookupCategory);endifproperty=='P119'thenresult=result..getCategory('P1791',entriesToLookupCategory);endendreturnresult;end-- append entity id from snak to resultfunctioninsertFromSnak(snak,result)ifnotcategorizeByPlacethenreturn;endifsnakandsnak.datavalueandsnak.datavalue.type=='wikibase-entityid'andsnak.datavalue.valueandsnak.datavalue.value['entity-type']=='item'thentable.insert(result,snak.datavalue.value.id);endendfunctiongetCategory(propertyId,entriesToLookupCategoryFor)for_,placeIdinpairs(entriesToLookupCategoryFor)dolocalclaims=mw.wikibase.getBestStatements(placeId,propertyId);ifclaimsthenfor_,claiminpairs(claims)doifclaim.mainsnakandclaim.mainsnakandclaim.mainsnak.datavalueandclaim.mainsnak.datavalue.type=='wikibase-entityid'thenlocalcatEntityId=claim.mainsnak.datavalue.value.id;localcatSitelink=mw.wikibase.getSitelink(catEntityId);if(catSitelink)thenreturn'[['..catSitelink..']]';endendendendendreturn'';endlocalhistoricNamesProperties={'P1813','P1448','P1705'};locallangCode=mw.language.getContentLanguage():getCode();localhistoricNamesPropertySelectors={P1813='P1813[language:'..langCode..']',P1448='P1448[language:'..langCode..']',P1705='P1705[language:'..langCode..']'};-- get current of historic name of placefunctiongetLabel(context,entityId,boundaries)ifnotentityIdthenreturnnil;endif(type(entityId)~='string')thenerror('incorrect type of entityId argument');end;locallabel=nil;-- name from propertieslocalresults=getParentsInBoundariesSnakImpl(context,entityId,boundaries,historicNamesProperties,historicNamesPropertySelectors);forr,resultinpairs(results)doifresult.datavalueandresult.datavalue.valueandresult.datavalue.value.textthenlabel=result.datavalue.value.text;break;endend-- name from labeliflabel==nilthenlabel=mw.wikibase.getLabel(entityId);endreturnlabel;endp.getLabel=getLabel;localfunctioncalculateEndDateTimestamp(context,options,statement)ifnotcontextthenerror('context not specified')end;ifnotoptionsthenerror('options not specified')end;ifnotoptions.entitythenerror('options.entity missing')end;ifnotstatementthenerror('statement not specified')end;ifstatement.qualifiersandstatement.qualifiers.P582thenfori,qualifierinipairs(statement.qualifiers.P582)dolocalparsedTime=context.parseTimeFromSnak(qualifier);ifparsedTimethenreturnparsedTime;endendend-- check death day... do we have it at all?forh,propertyIdinpairs({"P570","P577","P576"})dolocaldateClaims=context.selectClaims(options,propertyId);ifdateClaimsthenfori,statementinipairs(dateClaims)dolocalparsedTime=context.parseTimeFromSnak(statement.mainsnak);ifparsedTimethenreturnparsedTime;endendendend-- TODO: check other "end" properties-- no death dayreturnos.time()*1000;endlocalfunctiondeleteTwinAncestors(countryEntityId,propertyId)localbadTwinif(countryEntityId=='Q174193')thenbadTwin='Q145'elseif(countryEntityId=='Q838261')thenbadTwin='Q37024'elsereturntrue;endfor_,claiminpairs(mw.wikibase.getBestStatements(mw.wikibase.getEntityIdForCurrentPage(),propertyId))doif(claimandclaim.mainsnakandclaim.mainsnak.datavalueandclaim.mainsnak.datavalue.valueandclaim.mainsnak.datavalue.value.id)thenlocalactualId=claim.mainsnak.datavalue.value.id;if(actualId==badTwin)thenreturnfalse;endendendreturntrue;endfunctionp.formatCountryClaimWithFlag(context,options,statement)ifnotcontextthenerror('context not specified')end;ifnotoptionsthenerror('options not specified')end;ifnotoptions.entitythenerror('options.entity is missing')end;ifnotstatementthenerror('statement not specified')end;ifnotstatement.mainsnakornotstatement.mainsnak.datavalueornotstatement.mainsnak.datavalue.valueornotstatement.mainsnak.datavalue.value.idthenlocalresult=context.formatStatementDefault(context,options,statement);ifnotresultthenreturn'';endreturn'<span class="country-name">'..result..'</span>';endlocalcountryEntityId=statement.mainsnak.datavalue.value.id;localendDateTimestamp=calculateEndDateTimestamp(context,options,statement);localboundaries=getTimeBoundariesFromProperties(context,{'P570','P577','P571'});ifdeleteTwinAncestors(countryEntityId,string.upper(options.property))thenlocalcountryOptions=context.cloneOptions(options);ifnotcountryOptions['text']orcountryOptions['text']==''thencountryOptions['text']=getLabel(context,countryEntityId,boundaries);endlocalflag=Flags.getFlag(context,countryEntityId,endDateTimestamp);ifflagthenreturnflag..'&nbsp;<span class="country-name">'..context.formatStatementDefault(context,countryOptions,statement)..'</span>';endreturn'<span class="country-name">'..context.formatStatementDefault(context,countryOptions,statement)..'</span>';elsereturnnil;endendreturnp;