Modul:Wikidata/Medals

ANAS Wiki saytından
imported>Toghrul R tərəfindən edilmiş 09:12, 31 avqust 2025 tarixli redaktə
(fərq) ← Əvvəlki versiya | Son versiya (fərq) | Sonrakı versiya → (fərq)
Naviqasiyaya keç Axtarışa keç

Bu modulun sənədləşdirmə səhifəsi Modul:Wikidata/Medals/doc səhifəsində yaradıla bilər

local p = {}
local mw = require('mw')
local awardsOrder = mw.ext.data.get("Wikidata/awards order.tab") 
local D = mw.loadData('Module:Wikidata/Medals/data')
local absorption      = D.absorption
local prioritizeP2910 = D.prioritizeP2910
local topPriority     = D.topPriority

local entityCache = {}
local function safeGetEntity(id)
	if not id then return nil end
	if entityCache[id] then return entityCache[id] end
	local e = mw.wikibase.getEntity(id)
	entityCache[id] = e
	return e
end

local function getId(val)
	return type(val) == "table" and val.id or val
end

local function getStatementId(stmt)
	if not stmt or not stmt.mainsnak or stmt.mainsnak.snaktype ~= 'value' or not stmt.mainsnak.datavalue then
		return nil
	end
	return getId(stmt.mainsnak.datavalue.value)
end

local function getLabel(entity)
	return entity:getLabel('az') or entity:getLabel() or entity.id
end

local function wrapWithClaimDiv(html, propertyId, itemId)
	return '<div class="wikidata-claim" data-wikidata-property-id="' .. propertyId .. '" data-wikidata-claim-id="' .. itemId .. '">' .. html .. '</div>' 
end

local function isPrioritized(id)
	for _, q in ipairs(prioritizeP2910) do
		if q == id then return true end
	end
	return false
end

local function getMainValue(claims, property)
	if not claims or not claims[property] then return nil end
	for _, stmt in ipairs(claims[property]) do
		if stmt.mainsnak and stmt.mainsnak.snaktype == 'value' and stmt.mainsnak.datavalue then
			return stmt.mainsnak.datavalue.value
		end
	end
	return nil
end

local function isDateInRange(date, startTime, endTime)
	if not date then return false end
	if startTime and date < startTime then return false end
	if endTime and date > endTime then return false end
	return true
end

local function getImage(entity, awardDate, lightMode)
	if not entity or not entity.claims then return nil end
	local claims = entity.claims

	local function parseTime(claim)
		if claim and claim.datavalue and claim.datavalue.value and claim.datavalue.value.time then
			return claim.datavalue.value.time
		end
		return nil
	end

	local function matchImage(prop)
		local propClaims = claims[prop]
		if not propClaims then return nil end

		for _, claim in ipairs(propClaims) do
			if claim.mainsnak and claim.mainsnak.snaktype == 'value' and claim.mainsnak.datavalue then
				local image = claim.mainsnak.datavalue.value
				local qualifiers = claim.qualifiers or {}
				local startTime = parseTime(qualifiers['P580'] and qualifiers['P580'][1])
				local endTime = parseTime(qualifiers['P582'] and qualifiers['P582'][1])

				if not lightMode and isDateInRange(awardDate, startTime, endTime) then
					return image
				end
			end
		end

		local first = propClaims[1]
		if first and first.mainsnak and first.mainsnak.snaktype == 'value' and first.mainsnak.datavalue then
			return first.mainsnak.datavalue.value
		end

		return nil
	end

	local id = entity.id
	local image, size, border = nil, 'x15px', false

	if isPrioritized(id) then
		image = matchImage('P2910')
		if image then size = 'x37px' else
			image = matchImage('P2425')
			if image then border = true end
		end
	else
		image = matchImage('P2425')
		if image then border = true else
			image = matchImage('P2910')
			if image then size = 'x37px' end
		end
	end

	return image, size, border
end


local function getCategoryWikitext(entity, lightMode)
	if not entity or not entity.claims then return "" end
	local claims = entity.claims

	local function extractCategoryLink(entityClaims)
		if not entityClaims or not entityClaims['P2517'] then return nil end
		for _, catClaim in ipairs(entityClaims['P2517']) do
			if catClaim.mainsnak and catClaim.mainsnak.snaktype == 'value' then
				local catId = catClaim.mainsnak.datavalue.value.id
				local catLink = mw.wikibase.getSitelink(catId)
				if catLink then return '[[' .. catLink .. ']]' end
			end
		end
		return nil
	end

	if lightMode then
		return extractCategoryLink(claims) or ""
	end

	local category = extractCategoryLink(claims)
	if category then return category end

	local parentClaim = claims['P361'] and claims['P361'][1]
	if parentClaim and parentClaim.mainsnak and parentClaim.mainsnak.snaktype == 'value' then
		local parentId = parentClaim.mainsnak.datavalue.value.id
		local parentEntity = mw.wikibase.getEntity(parentId)
		if parentEntity then
			return extractCategoryLink(parentEntity.claims) or ""
		end
	end

	return ""
end

local function getAwardYear(statements, id)
	for _, statement in ipairs(statements or {}) do
		local snak = statement.mainsnak
		if snak and snak.snaktype == 'value' and snak.datavalue and snak.datavalue.value then
			local value = snak.datavalue.value
			local statementId = type(value) == 'table' and value.id or value
			if statementId == id and statement.qualifiers then
				local dateClaims = statement.qualifiers['P585']
				if dateClaims then
					for _, q in ipairs(dateClaims) do
						if q and q.snaktype == 'value' then
							local dv = q.datavalue
							if dv and dv.value and dv.value.time then
								local year = string.match(dv.value.time, "%d%d%d%d")
								if year then
									return year
								end
							end
						end
					end
				end
			end
		end
	end
	return nil
end

local function buildAwardHTML(id, statement, lightMode)
	local entity = safeGetEntity(id)
	if not entity then return nil end

	if lightMode then
		local label = getLabel(entity)
		local image, size, border = getImage(entity, nil, true)
		if not image then return nil end
		local link = mw.wikibase.getSitelink(id) or ('d:' .. id)
		local html = '[[Fayl:' .. image
		if border then html = html .. '|border' end
		html = html .. '|' .. size .. '|link=' .. link .. '|' .. label .. ']]'

		local categoryWikitext = mw.title.getCurrentTitle().namespace == 0 and getCategoryWikitext(entity, true) or ""
		html = html .. categoryWikitext

		return {
			id = id,
			html = html,
			height = size,
			parents = {},
			border = border
		}
	end

	local awardDate = nil
	if statement and statement.qualifiers and statement.qualifiers['P585'] then
		for _, q in ipairs(statement.qualifiers['P585']) do
			if q.snaktype == 'value' and q.datavalue and q.datavalue.value and q.datavalue.value.time then
				awardDate = q.datavalue.value.time
				break
			end
		end
	end

	local image, size, border = getImage(entity, awardDate, lightMode)
	if not image then
		local categoryWikitext = mw.title.getCurrentTitle().namespace == 0 and getCategoryWikitext(entity, lightMode) or ""
		if categoryWikitext ~= "" then
			local fallbackHtml = wrapWithClaimDiv(categoryWikitext, 'P166', id)
			return {
				id = id,
				html = fallbackHtml,
				height = nil,
				parents = {},
				border = false
			}
		end
		return nil
	end

	local label = getLabel(entity)

	local originalId = getStatementId(statement)
	local awardYear = getAwardYear({ statement }, originalId)
	if awardYear then
		label = label .. ' — ' .. awardYear
	end

	local link = mw.wikibase.getSitelink(id)
	if not link then
		if not lightMode then
			local parent = getMainValue(entity.claims, 'P361')
			local parentId = parent and parent.id
			link = parentId and mw.wikibase.getSitelink(parentId) or "d:" .. id
		else
			link = "d:" .. id
		end
	end

	local html = '[[Fayl:' .. image
	if border then html = html .. '|border' end
	html = html .. '|' .. size .. '|link=' .. link .. '|' .. label .. ']]'

	local claims = entity.claims
	local parents = {}
	local function addParents(prop)
		for _, claim in ipairs(claims[prop] or {}) do
			if claim.mainsnak and claim.mainsnak.snaktype == 'value' and claim.mainsnak.datavalue then
				table.insert(parents, claim.mainsnak.datavalue.value.id)
			end
		end
	end
	addParents('P279')
	addParents('P361')

	local categoryWikitext = mw.title.getCurrentTitle().namespace == 0 and getCategoryWikitext(entity) or ""

	return {
		id = id,
		html = html .. categoryWikitext,
		height = size,
		parents = parents,
		border = border
	}
end

function p.formatProperty(context, options)
	local entityId = type(options.entity) == "table" and options.entity.id or options.entity or mw.wikibase.getEntityIdForCurrentPage()
	if not entityId then return '' end

	local claims = mw.wikibase.getBestStatements(entityId, 'P166')
	if not claims or #claims == 0 then return "" end
	
	local lightMode = #claims > 50

	local rawCount = {}
	for _, claim in ipairs(claims) do
		if claim.mainsnak and claim.mainsnak.snaktype == 'value' and claim.mainsnak.datavalue and claim.mainsnak.datavalue.value then
		local qid = getStatementId(claim)
		rawCount[qid] = (rawCount[qid] or 0) + 1
			rawCount[qid] = (rawCount[qid] or 0) + 1
		end
	end
	local resolvedCount, replaced = {}, {}
	for qid, count in pairs(rawCount) do
		local replacement = absorption[qid]
		if replacement then
			if rawCount[replacement] then
				replaced[qid] = true
			else
				resolvedCount[replacement] = (resolvedCount[replacement] or 0) + count
			end
		elseif not replaced[qid] then
			resolvedCount[qid] = (resolvedCount[qid] or 0) + count
		end
	end

	local built = {}
	local count = 0
	for _, statement in ipairs(claims) do
		if statement.mainsnak and statement.mainsnak.snaktype == 'value' and statement.mainsnak.datavalue and statement.mainsnak.datavalue.value then
			local qid = getStatementId(statement)
			local resolvedId = absorption[qid] or qid
			if not replaced[qid] then
				local html = buildAwardHTML(resolvedId, statement, lightMode)
				if html then
					table.insert(built, html)
					if not lightMode then
						count = count + 1
						if count >= 50 then break end
					end
				end
			end
		end
	end

	local idSet = {}
	for _, a in ipairs(built) do idSet[a.id] = true end
	for _, a in ipairs(built) do
		for _, parent in ipairs(a.parents or {}) do
			if idSet[parent] then idSet[parent] = nil end
		end
	end

	local filtered = {}
	for _, a in ipairs(built) do
		if idSet[a.id] then table.insert(filtered, a) end
	end

	local function orderByAwardsList(dataList)
		local grouped, ordered = {}, {}
		for _, a in ipairs(dataList) do
			grouped[a.id] = grouped[a.id] or {}
			table.insert(grouped[a.id], a)
		end
	
		for _, row in ipairs(awardsOrder.data or {}) do
			local qid = row[1]
			if grouped[qid] then
				for _, item in ipairs(grouped[qid]) do
					table.insert(ordered, item)
				end
				grouped[qid] = nil
			end
		end
	
		for _, group in pairs(grouped) do
			for _, item in ipairs(group) do
				table.insert(ordered, item)
			end
		end
	
		return ordered
	end

	local top, ribbons, pics, categoriesOnly = {}, {}, {}, {}
	for _, a in ipairs(filtered) do
		if not a.height and a.html:match('%[%[Kateqoriya:') then
			table.insert(categoriesOnly, a)
		elseif topPriority[a.id] then
			table.insert(top, a)
		elseif a.border then
			table.insert(ribbons, a)
		else
			table.insert(pics, a)
		end
	end

	top = orderByAwardsList(top)
	ribbons = orderByAwardsList(ribbons)
	pics = orderByAwardsList(pics)

	local finalOut = {}
	for _, a in ipairs(top) do table.insert(finalOut, a.html) end
	if #top > 0 then table.insert(finalOut, "<br>") end

	local function outputGrouped(group)
		local grouped = {}
		for _, a in ipairs(group) do
			if a.height then
				grouped[a.height] = grouped[a.height] or {}
				table.insert(grouped[a.height], a.html)
			end
		end
		for _, row in ipairs(awardsOrder.data or {}) do
			local id = row[1]
			for height, list in pairs(grouped) do
				if #list > 0 and string.find(list[1], id, 1, true) then
					for _, h in ipairs(list) do table.insert(finalOut, h) end
					table.insert(finalOut, "<br>")
					grouped[height] = nil
				end
			end
		end
		for _, list in pairs(grouped) do
			for _, h in ipairs(list) do table.insert(finalOut, h) end
			table.insert(finalOut, "<br>")
		end
	end

	outputGrouped(ribbons)
	outputGrouped(pics)
	
	local hasImage = false
	for _, a in ipairs(top) do if a.height then hasImage = true break end end
	if not hasImage then for _, a in ipairs(ribbons) do if a.height then hasImage = true break end end end
	if not hasImage then for _, a in ipairs(pics) do if a.height then hasImage = true break end end end
	
	if hasImage then
		for _, a in ipairs(categoriesOnly) do
			table.insert(finalOut, a.html)
		end
	end

	if finalOut[#finalOut] == "<br>" then table.remove(finalOut) end
	return table.concat(finalOut, options.separator or ' ')
end

function p.formatValue(context, options, statement)
	local entityId = statement.id or getStatementId(statement)
	if not entityId then return '' end

	local entity = mw.wikibase.getEntity(entityId)
	if not entity then return '' end

	local label = getLabel(entity)

	local awardYear = nil
	if statement.qualifiers and statement.qualifiers['P585'] then
		for _, q in ipairs(statement.qualifiers['P585']) do
			if q.snaktype == 'value' and q.datavalue and q.datavalue.value and q.datavalue.value.time then
				local timeVal = q.datavalue.value.time
				awardYear = string.match(timeVal, "%d%d%d%d")
				break
			end
		end
	end
	if awardYear then
		label = label .. ' — ' .. awardYear
	end

	local image, size, border = getImage(entity, nil, true)

	local link = mw.wikibase.getSitelink(entityId) or ('d:' .. entityId)
	local out = ''

	if image then
		out = '[[Fayl:' .. image
		if border then out = out .. '|border' end
		out = out .. '|' .. size .. '|link=' .. link .. '|' .. label .. ']]'
	else
		out = '[[' .. link .. '|' .. label .. ']]'
	end

	return out
end

return p