Модуль:Wikidata/P512

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
Документация

Содержит функции для форматирования учёных степеней, получаемых из свойства викиданных d:Property:P512. По сравнению с formatPropertyDefault() из Модуль:Wikidata включает в себя следующую логику:

  1. В викиданных отмечаются факты получения всех степеней, но в карточке нет смысла показывать кандидатскую при наличии соответствующей докторской. Например Путилов, Борис Николаевич (показывается только д. ф. н.), Зайцев, Александр Иосифович (показывается и к. ф. н. и д. и. н.)
  2. После самой учёной степени в скобках показывается год её присвоения (из квалификатора d:P585). Иногда для указания этой же информации используют d:P580, но первый вариант гораздо распространённее (ср. [1] и [2])
  3. В статью добавляется соответствующая степени категория (например Категория:Кандидаты искусствоведения)

Для правильной реализации пунктов 1 и 3 нужно загружать элемент, соответствующий каждой ученой степени персоны и обращаться к свойствам d:P156 и d:P910 соответственно. Однако, для первой версии, решено захардкодить связи между степенями первой и второй ступени, а также соответствующими категориями по соображениям производительности и для минимизации зависимостей данного модуля от других.

Названия функций данного модуля, а также их сигнатуры могут меняться без предупреждения, поэтому не рекомендуется использовать их напрямую. Штатно модуль используется из шаблона {{wikidata/p512}}, в котором осуществляется вызов {{#invoke:Wikidata|formatStatements с параметрами property-module=Wikidata/P512 и property-function=formatAcademicDegree

Тесты

All tests passed.

test_formatAcademicDegree:

Text Expected Actual
✔ demo <span class="wikidata-claim" data-wikidata-property-id="P512" data-wikidata-claim-id="Q4115189$2fb0ce43-4ffe-9e6e-6dab-0d101b0ceac0">доктор филологических наук</span>[[Категория:Доктора филологических наук]] <span class="wikidata-claim" data-wikidata-property-id="P512" data-wikidata-claim-id="Q4115189$2fb0ce43-4ffe-9e6e-6dab-0d101b0ceac0">доктор филологических наук</span>[[Категория:Доктора филологических наук]]

test_formatCorrespondingCategory:

Text Expected Actual
✔ d:Q752297[1] Категория:Доктора философии Категория:Доктора философии
✔ d:Q849697[1]
✔ d:Q913404[1] Категория:Доктора медицины Категория:Доктора медицины
✔ d:Q959320[1] Категория:Доктора права Категория:Доктора права
✔ d:Q5978719[1]
✔ d:Q17281180[1] Категория:Доктора искусствоведения Категория:Доктора искусствоведения
✔ d:Q19603972[1] Категория:Кандидаты философских наук Категория:Кандидаты философских наук

test_formatQualifier:

Text Expected Actual
✔ {} "" ""
✔ {1987} " (1987)" " (1987)"
✔ {2017, 2024} " (2017)" " (2017)"

test_getPreviousDegrees:

Text Expected Actual
✔ {} {} {}
✔ {1} {} {}
✔ {1, 16698078, 19610224} {[19610224]=true} {[19610224]=true}
✔ {17281125, 17281125} {[18071588]=true} {[18071588]=true}


local p = {}

--[[
  Функция формирует строку с викиразметкой для переданного свойства
  
  Принимает: объект контекста для вызова форматтеров и таблицу настройек
  Возвращает: вики-форматированную строку
 ]]
function p.formatAcademicDegree( context, options )
	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;
 
    local claims = context.selectClaims( options, options.property );
    if (claims == nil) then
        return ''
    end
    
    local blackList = p.getPreviousDegrees( claims )
    local formattedClaims = {}
 
    for i, claim in ipairs(claims) do
    	if (claim.mainsnak.datavalue and not blackList[claim.mainsnak.datavalue.value['numeric-id']]) then
	        local formattedStatement = context.formatStatement( options, claim )

	        if (formattedStatement) then
	            formattedStatement = '<span class="wikidata-claim"' .. 
		            ' data-wikidata-property-id="' .. 
		            string.upper( options.property ) .. 
		            '" data-wikidata-claim-id="' .. 
		            claim.id .. '">' ..
		            formattedStatement .. '</span>'

	            if (claim.qualifiers) then
	            	formattedStatement = formattedStatement .. 
	            		p.formatQualifier( context, options, claim.qualifiers.P585 )
	            end
	            formattedStatement = formattedStatement .. 
	            	p.formatCorrespondingCategory( claim )

	            table.insert( formattedClaims, formattedStatement )
	        end
	    end
    end
 
	-- создание текстовой строки со списком оформленых заявлений из таблицы  
    return mw.text.listToText( formattedClaims, options.separator, options.conjunction );	
end

--[[
  Функция помещает в скобки текст первого квалификатора из переданной таблицы
  
  Принимает: объект контекста для вызова форматтеров, таблицу настроеки 
  и таблицу квалификаторов
  Возвращает: отформатированная строка с квалификатором
 ]]
function p.formatQualifier( context, options, qualifiers )
	if (qualifiers~=nil and qualifiers[1] ~= nil) then
		return ' (' .. context.formatSnak( options, qualifiers[1] ) .. ')'
	end
	
	return ''
end

--[[
  Функция формирует список соответствующих ученых степеней нижней ступени (P155)
  Например, для "доктор искусствоведения" это будет "кандидат искусствоведения"
  
  Принимает: объект таблицу сущностей - академических степеней персоны (P512)
  Возвращает: объект таблицу идентификаторов степеней нижней ступени
 ]]
function p.getPreviousDegrees( claims )
	-- Пока нет нормальной возможности загружать элементы c кэшем
	-- снаружи Module:Wikidata, мы эти соответствия захардкодим (без Q)
	local correspondingCandidates = {
		[16698078] = 19610224, -- архитектор
		[17281188] = 19610186, -- биолог
		[17281187] = 19610187, -- ветеринар
		[17281186] = 19610193, -- военный
		[16698080] = 19610195, -- географ
		[16698082] = 19610197, -- гео-мин
		[17281180] = 18523814, -- искусствовед
		[12101789] = 18523811, -- историк
		[16698084] = 19610200, -- культуролог
		[17281165] = 19610203, -- медик
		[17281161] = 19610206, -- педагог
		[12101787] = 4212319,  -- политолог
		[17281156] = 19610208, -- психолог
		[17281153] = 19610210, -- сель-хоз
		[17281152] = 19610212, -- социолог
		[17281125] = 18071588, -- техник
		[17281115] = 19610228, -- фармацевт
		[17281097] = 18002832, -- физ-мат
		[17281087] = 19603970, -- филолог
		[17281084] = 19603972, -- философ
		[17281079] = 19610312, -- химик
		[17281072] = 17744738, -- экономист
		[18745564] = 19610320  -- юрист
	}
	
	local previousElements = {}
	for i, claim in ipairs(claims) do
		if(claim.mainsnak.datavalue) then
			local entityId = claim.mainsnak.datavalue.value['numeric-id']
			if (entityId) then
				if correspondingCandidates[entityId] then
					previousElements[correspondingCandidates[entityId]] = true
				end
			end
		end
	end
	return previousElements
end

--[[ 
  Функция формирует вики-разметку категории, соответствующей ученой степени

  Принимает: объект таблицу утверждения
  Возвращает: строку оформленного текста либо пустую строку
 ]]
function p.formatCorrespondingCategory (claim)
	if ( not claim ) then return '' end;
	if ( not claim.mainsnak ) then return '' end;
	
	local label = mw.wikibase.label("Q" .. claim.mainsnak.datavalue.value['numeric-id'])
	if not label then label = '' end
		
	local result, changes = string.gsub(label, "доктор ", "Категория:Доктора ")
	if (changes == 1) then
		return '[[' .. result .. ']]'
	end
	
	result, changes = string.gsub(label, "кандидат ", "Категория:Кандидаты ")
	if (changes == 1) then
		return '[[' .. result .. ']]'
	end
	
	return ''
end

return p