Module:WikidataChart

local defaultFormat = {
	[0] = "Y",				-- precision: billion years
	[1] = "Y",				-- precision: hundred million years
	[2] = "Y",				-- precision: ten million years
	[3] = "Y",				-- precision: million years
	[4] = "Y",				-- precision: hundred thousand years
	[5] = "Y",				-- precision: ten thousand years
	[6] = "Y",				-- precision: millennium
	[7] = "Y",				-- precision: century
	[8] = "Y",				-- precision: decade
	[9]  = "Y",				-- precision: year
	[10] = "M Y",			-- precision: month
	[11] = "j F Y",			-- precision: day
	[12] = "j F Y ga",		-- precision: hour
	[13] = "j F Y g:ia",	-- precision: minute
	[14] = "j F Y g:i:sa"	-- precision: second
}

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"])
	local xAxisFormat = defaultFormat[precision or 9]	
	
	-- Collect data
	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.en or labels.de 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

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

    -- default values, can be overwritten
	local chartArgs =
	{
		type = "line",
		xType = "date",
		x = table.concat(xValues, ","),
		yType = "number",
		
		-- these are not supported anymore with new chart extension as of now..
--		xAxisTitle = mw.wikibase.label(xQualifier),		
--		yAxisTitle = mw.wikibase.label(property)
	}
	-- Set legends / series titles
	for seriesIdx, caption in ipairs(series.captions) do
		chartArgs["y" .. seriesIdx] = ""
		chartArgs["y" .. seriesIdx .. "Title"] = caption
	end
	-- Set values
	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
	-- Remove separators at the beginning
	for seriesIdx, _ in ipairs(series.captions) do
		chartArgs["y" .. seriesIdx] = mw.ustring.sub(chartArgs["y" .. seriesIdx], 2)
	end
	-- Transfer diagram parameters (all parameters that start with chart_ are transferred directly to the Graph module without a prefix)
	for k, v in pairs(frame.args) do
		local chartParam = string.match(k, "^chart_(.+)")
		if chartParam then chartArgs[chartParam] = v end
	end

 	
	--workaround, to better show dates since the extension doesn't support them yet properly
	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
	-- if number, use precision to round (default 9=years)
	if chartArgs["xType"]=="number" then
		xValuesCutted = {}
		for _, k in pairs(xValues) do
			table.insert(xValuesCutted,mw.getContentLanguage():formatDate(xAxisFormat, k))
		end
		chartArgs["x"] = table.concat(xValuesCutted, ",")
	end
	
	-- create the plot
	local resultplot
	resultplot = mw.getCurrentFrame():expandTemplate {
		title = 'Template:ChartDirect',
		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.