Dokumentaci tohoto modulu lze vytvořit na stránce Nápověda:Modul:Wikidata

p = {}

-- #############
-- # Utilities #
-- #############

-- Checks whether the values in two tables are identical,
-- ignoring their order
-- @param t1 table: The first table to compare
-- @param t2 table: The second table to compare
-- @return boolean: True if the values are identical, false otherwise
local function tableValuesEqual(t1, t2)
	if #t1 ~= #t2 then return false end
	local t1Counts = {}
	for _, v in pairs(t1) do
		t1Counts[v] = (t1Counts[v] or 0) + 1
	end
	local t2Counts = {}
	for _, v in pairs(t2) do
		t2Counts[v] = (t2Counts[v] or 0) + 1
	end
	for k, v in pairs(t1Counts) do
		if v ~= t2Counts[k] then return false end
	end
	return true
end

-- Maps a function over a table
-- @param t table: The input table
-- @param f function: The function to be applied to the elements
-- @return table: The table with the mapped values
local function map(t, f)
    local r = {}
    for k, v in pairs(t) do
        r[k] = f(v)
    end
    return r
end

-- Drops n elements from a table and returns the rest
-- @param t table: The table to drop the values from
-- @param n number: The number of values to drop
-- @return table: The table with the dropped values and a reset index
local function drop(t, n)
	local r = {}
	for i=n+1, #t do
		r[i-n] = t[i]
	end
	return r
end

-- Retrieves the numbered arguments from the invokation frame in an array-like form
-- @param frame: The frame from #invoke
-- @return table: The numbered arguments table
local function getNumberedArgs(frame)
	local a = {}
	local i = 1
	while frame.args[i] ~= nil do
		a[i] = frame.args[i]
		i = i + 1
	end
	return a
end

-- ##################
-- # Mapping tables #
-- ##################

local flexionCategories = {
	s = "Q110786",
	p = "Q146786",
	
	nom = "Q131105",
	gen = "Q146233",
	dat = "Q145599",
	acc = "Q146078",
	voc = "Q185077",
	loc = "Q202142",
	ins = "Q192997",
	
	poz = "Q3482678",
	komp = "Q14169499",
	sup = "Q1817208",
}

local properties = {
	style = "P6191",
	ipa = "P898",
	hyphenation = "P5279",
}

-- #########################
-- # Lexemes API Functions #
-- #########################

-- Attempts to retrieve target entity IDs for a given source entity and property ID
-- @param sourceEntity any: The source Wikidata entity
-- @param propertyId string: The ID of the property for which the target values should be retrieved
-- @return [string]: List of QIDs of the target entities
function p.getTargetValuesForProperty(sourceEntity, propertyId)
	local targetValues = {}
	
	if sourceEntity.claims[propertyId] == nil then return {} end
	
	for _, claim in pairs(sourceEntity.claims[propertyId]) do
		local datavalue = claim.mainsnak.datavalue
		if datavalue.type == "wikibase-entityid" and datavalue.value.id ~= nil then
			table.insert(targetValues, datavalue.value.id)
		elseif datavalue.type == "monolingualtext" and datavalue.value.text ~= nil then
			table.insert(targetValues, datavalue.value.text)
		else
			table.insert(targetValues, datavalue.value)
		end
	end
	return targetValues
end

-- Attempts to retrieve the representations for forms along with their language
-- styles for the specified lexeme, grammatical features and language
-- @param lexemeId string: The ID of the considered lexeme, including the L prefix
-- @param repFeatures [string]: The QIDs of the grammatical features
-- @param language string: The Wikidata code for the language
-- @return [(string, [string])]: The retrieved list of matching representations and the Q-items for their language styles
function p.getFormRepresentations(lexemeId, repFeatures, language)
	local representations = {}
	
	local lexeme = mw.wikibase.getEntity(lexemeId)
	local forms = lexeme:getForms()
	for _, form in pairs(forms) do
		local representation, _ = form:getRepresentation(language)
		local grammaticalFeatures = form:getGrammaticalFeatures()
		if representation ~= nil and tableValuesEqual(repFeatures, grammaticalFeatures) then
			local repData = {representation, p.getTargetValuesForProperty(form, properties.style)}
			table.insert(representations, repData)
		end
	end
	return representations
end

function p.form(frame)
	local args = getNumberedArgs(frame)
	local lexemeId = args[1]
	local language = args[2]
	local formFeatures = drop(args, 2)
	formFeatures = map(formFeatures, function (ff) return flexionCategories[ff] end)
	
	local representations = p.getFormRepresentations(
		lexemeId, formFeatures, language
	)
	if #representations > 0 then
		return representations[1][1]
	end
	return ""
end

return p