Modul:WikidataChart

Modul mit Komfortfunktionen um Daten aus Wikidata grafisch in Diagrammform aufzubereiten.

Zur Verwendung siehe {{WikidataChart}}.


local p = {}

function p.plot(frame)
	local property = frame.args[1] or error("Wikidata property to chart required")
	local xQualifier = frame.args[2] or error("Wikidata qualifier for x axis required")
	local yIds = mw.text.split(frame.args["pageIds"] or "", ",", true)
	local xStart = frame.args["xStart"]
	local xEnd = frame.args["xEnd"]
	local precision = tonumber(frame.args["precision"])
	
	--[[ 
	order-based parameters are not fully trimmed, and can carry newlines. trim them.
	this can happen when the template in wiki uses multiline style:
	{{#invoke:WikidataChart|plotWrapper
	| P1087
	| P585
	...
	}}
	]]
	property = mw.text.trim(property)
	xQualifier = mw.text.trim(xQualifier)

	
	-- Daten sammeln
	local series = { captions = {}, points = {} }
	for seriesIdx, id in ipairs(yIds) do
		if id == "" then id = nil end
		local entity = mw.wikibase.getEntity(id)
		
		local labels = entity.labels or {}
		series.captions[seriesIdx] = (labels.de or labels.en or {}).value or id

		local property = entity.claims[property]
		for _, item in ipairs(property) do
			if item.qualifiers and item.qualifiers[xQualifier] and item.qualifiers[xQualifier][1] then
				local qualifier = item.qualifiers[xQualifier][1]
				if qualifier.snaktype ~= "value" or qualifier.datatype ~= "time" then
					error("'xQualifier' parameter must be a time")
				end
				local x = applyPrecision(mw.text.trim(qualifier.datavalue.value.time, "+"), precision)
				
				if (not xStart or x >= xStart) and (not xEnd or string.sub(x, 1, #xEnd) <= xEnd) and qualifier.datavalue.value.precision >= (precision or 0) then
					local mainsnak = item.mainsnak
					if mainsnak.snaktype ~= "value" or mainsnak.datatype ~= "quantity" then
						error("'property' parameter must be numeric")
					end
					local y = tonumber(mainsnak.datavalue.value.amount)
	
					if not series.points[x] then series.points[x] = {} end
					series.points[x][seriesIdx] = y
				end
			end
		end
	end

	-- x-Werte sortieren
	local xValues = {}
	for k in pairs(series.points) do table.insert(xValues, k) end
	table.sort(xValues)

	-- default werte, können überschrieben werden
	local chartArgs =
	{
		type = "line",
		xType = "date",
		x = table.concat(xValues, ","),
		yType = "number",
		--auskommentiert, da momentan nicht supported von der chart extension
		--xAxisTitle = mw.wikibase.label(xQualifier),
		--yAxisTitle = mw.wikibase.label(property)
	}
	-- Legenden/Reihentitel setzen
	for seriesIdx, caption in ipairs(series.captions) do
		chartArgs["y" .. seriesIdx] = ""
		chartArgs["y" .. seriesIdx .. "Title"] = caption
	end
	-- Werte setzen
	local seriesCount = #series.captions
	for _, x in ipairs(xValues) do
		yValues = series.points[x]
		for seriesIdx = 1, seriesCount do
			chartArgs["y" .. seriesIdx] = chartArgs["y" .. seriesIdx] .. "," .. (yValues[seriesIdx] or "")
		end
	end
	-- Separatoren am Anfang entfernen
	for seriesIdx, _ in ipairs(series.captions) do
		chartArgs["y" .. seriesIdx] = mw.ustring.sub(chartArgs["y" .. seriesIdx], 2)
	end
	-- Diagrammparameter übergeben (alle Paramater die mit chart_ anfangen, werden direkt ohne Präfix an das Graph-Modul übergeben)
	for k, v in pairs(frame.args) do
		local chartParam = string.match(k, "^chart_(.+)")
		if chartParam then
			--für abwärtskompatibilität, kann später entfernt werden
			if chartParam == "width" then
				chartArgs["Breite"] = v .. "px"
			else
				chartArgs[chartParam] = v 
			end			
		end
	end
	
	--workaround, um Datumsformat besser darzustellen solange das von der extension nicht sauber unterstützt wird
	if chartArgs["xType"]=="date" then
		xValuesCutted = {}
		for _, k in pairs(xValues) do
			table.insert(xValuesCutted,string.sub( k, 1, 10))
		end
		chartArgs["x"] = table.concat(xValuesCutted, ",")
	end	
	
	-- Plot erzeugen
	local resultplot
	resultplot = mw.getCurrentFrame():expandTemplate {
		title = 'Vorlage:ChartDirekt',
		args = chartArgs
		}
		
	return resultplot
end

function p.plotWrapper(frame)
	return p.plot(frame:getParent())
end

function applyPrecision(date, precision)
	if not precision then precision = math.huge end

	local _, _, year, month, day, hour, minute, second, timezone = string.find(date, "^(.?%d+)-(%d+)-(%d+)T(%d+):(%d+):(%d+)(.+)$")
	if precision < 14 then second = "00" end
	if precision < 13 then minute = "00" end
	if precision < 12 then hour = "00" end
	if precision < 11 or day == "00" then day = "01" end
	if precision < 10 or month == "00" then month = "01" end
	return year .. "-" .. month .. "-" .. day .. "T" .. hour .. ":" .. minute .. ":" .. second .. timezone
end

return p

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.