Naar inhoud springen

Module:Datastaven

Uit Wikipedia, de vrije encyclopedie
Dit is een oude versie van deze pagina, bewerkt door Strepulah (overleg | bijdragen) op 15 jan 2021 om 12:10. (Test link)
Deze versie kan sterk verschillen van de huidige versie van deze pagina.
Moduledocumentatie​[bekijk] [bewerk] [ververs] [geschiedenis]

Deze module kan gebruikt worden voor het in een staafdiagram weergeven van klasseringen / aantallen / rangen / posities / standen / eindstanden of iets in die trant. Of iets anders.

Deze module wordt toegepast in Sjabloon:Datastaven. Zie voor een overzicht van parameters de documentatie aldaar.

Gebruik

Standaard:

{{#invoke:Datastaven|main}}

Speciaal voor eindstanden kan ook gebruik worden gemaakt van:

{{#invoke:Datastaven|main|type=eindstanden}}

Kleuren

De kleuren van de staven kunnen zowel ingesteld worden op de groepen als op individuele staven. Als er geen kleur is opgegeven wordt er een uit het standaardkleurenpalet gehaald:

(Bewerk)

(Bewerk)

Zie ook

require('Module:No globals')

local p = {}
local getArgs = require('Module:Arguments').getArgs
local unpackItem = require('Module:Item').unpack
local _delink = require('Module:Delink')._delink
local yesno = require('Module:Yesno')
local templatestyles = 'Module:Datastaven/styles.css'
local data = {}
local chartHeight = 180 -- In px
local extraHeight = 20 -- Extra height per extra tier, in px
local barWidth = 3 -- In em
local truncateX = false
local invertY = false
local ySuffix = ''
local colors = {
	'#002a62', '#2c699a', '#db0c23', '#e36271',
	'#e99fa8', '#618b25', '#6bd425', '#eee8aa',
	'#eca72c', '#fff943', '#ffe4e1', '#dda0dd',
	'#0b6b61', '#3ec9a6', '#edf669', '#aabc1e',
	'#95291d', '#ee2b08', '#999999', '#ffffff'
}
-- Translations for parameter names
local w = {
	rankings = 'eindstanden',
	chartHeight = 'grafiekhoogte',
	barWidth = 'staafbreedte',
	groups = 'groepen',
	truncateX = 'x afkappen',
	invertY = 'y omkeren',
	x = 'x',
	y = 'y',
	yMax = 'y-max',
	ySuffix = 'y-suffix',
	group = 'groep',
	subgroup = 'subgroep',
	code = 'code',
	label = 'label',
	color = 'kleur',
	tier = 'niveau',
}

local function isItem(arg)
	return string.find(mw.text.trim(arg), '|', 1, true) == 1
end

local function pick(param, bar)
	-- Picks a parameter from bar or else from it's group or else from data.
	return bar[w[param]] or bar[w.group] and data.groups[bar[w.group]][w[param]] or data[param]
end

local function minn(table)
	-- Returns the lowest positive numerical index of the given table, or zero
	-- if the table has no numerical indices.
	local minn, k = nil, nil
	repeat
		k = next(table, k)
		if type(k) == 'number' then
			if k == 1 then return 1 end
			if minn == nil or k < minn then minn = k end
		end
	until not k
	return minn or 0
end

local function countTiers(tiers)
	-- Gives the number of tiers, empty inbetweens included.
	return table.maxn(tiers) - minn(tiers) + 1
end

local function rankTiers(tiers)
	-- Ranks the tiers bottom up for convenience, since heights will be calculated
	-- from the bottom up. Example:
	--   [2] = true,           [2] = 4,
	--   [3] = true,    -->    [3] = 3,
	--   [5] = true,           [5] = 1,
	local highestTierNumber = table.maxn(tiers)
	
	for n, _ in pairs(tiers) do
		tiers[n] = highestTierNumber - n + 1
	end
	
	return tiers
end

local function extractGroups(args)
	if args[w.groups] == nil or not isItem(args[w.groups]) then return {} end
	
	local groups = {}
	
	for _, arg in pairs(unpackItem(args[w.groups])) do
		if isItem(arg) then
			local group = unpackItem(arg)
			
			if group[w.code] and group[w.label] then
				group[w.tier] = tonumber(group[w.tier])
				group[w.yMax] = tonumber(group[w.yMax]) or 0
				groups[group[w.code]] = group
				group[w.code] = nil
			else
				error("Voor elke groep zijn een 'code' en 'label' verplicht.")
			end
		end
	end
	
	return groups
end

local function extractData(args)
	data = {
		chartHeight = args[w.chartHeight] or chartHeight,
		barWidth = args[w.barWidth] or barWidth,
		truncateX = yesno(args[w.truncateX], truncateX),
		invertY = yesno(args[w.invertY], invertY),
		yMax = args[w.yMax] or 0,
		ySuffix = args[w.ySuffix] or ySuffix,
		bars = {},
		groups = {},
		tiers = {},
	}
	local presetGroups = extractGroups(args)
	
	-- Extract from data items.
	for _, arg in ipairs(args) do
		if isItem(arg) then
			local bar = unpackItem(arg)
			bar[w.y] = tonumber(bar[w.y])
			bar[w.tier] = tonumber(bar[w.tier])
			table.insert(data.bars, bar)
			
			if bar[w.y] then
				data.yMax = math.max(data.yMax, bar[w.y])
			end
			
			if bar[w.group] then
				if data.groups[bar[w.group]] == nil then
					data.groups[bar[w.group]] = presetGroups[bar[w.group]]
												or { label = bar[w.group] }
				end
			end
			
			local tier = tonumber(pick('tier', bar))
			if tier then data.tiers[tier] = true end
		end
	end
	
	data.tiers = rankTiers(data.tiers)
	data.tiersCount = countTiers(data.tiers)
	data.chartHeight = data.chartHeight + extraHeight * (data.tiersCount - 1)
	
	return data
end

local function calculateBarHeight(bar)
	local y = bar[w.y]
	local yMax = pick('yMax', bar)
	local tierRank = data.tiers[pick('tier', bar)] or 1
	local h
	
	if invertY then
		h = y and (1 - ((y - 1) / yMax)) * 100		 -- Height % (within it's tier)
		if y > yMax then h = 0 end
	else
		h = y and y / yMax * 100
	end
	
	h = (h + tierRank * 100 - 100) / data.tiersCount -- Add heights of lower tiers
	h = math.floor(h * 1000) / 1000					 -- Truncate number
	return h
end

local function pickColor(bar)
	local color = pick('color', bar)
	if color then return color end
	
	-- Else, pick a color from the colors table.
	color = table.remove(colors) or '#fff'
	
	-- Add color to group.
	if bar[w.group] then
		data.groups[bar[w.group]][w.color] = color
	end
	
	return color
end

local function delink(text)
	-- Removes (wiki)links from a text.
	if not type(text) == 'string' then return text end
	return _delink({ text, urls = 'no', comments = 'no', whitespace = 'no' })
end

local function drawTooltip(bar)
	local text = mw.html.create()
	
	if bar[w.x] and bar[w.x] ~= '' then text:tag('b'):wikitext(bar[w.x]) end
	if bar[w.x] and bar[w.y] then text:wikitext('&ensp;') end
	if bar[w.y] then text:wikitext(bar[w.y] .. data.ySuffix) end
	
	if bar[w.group] then
		if tostring(text) ~= '' then text:tag('br') end
		text:wikitext(delink(data.groups[bar[w.group]].label))
		if bar[w.subgroup] then text:wikitext(' ' .. bar[w.subgroup]) end
	end
	
	return mw.html.create()
		:newline()
		:tag('div')
		:addClass('es-tip')
		:node(text)
		:done()
end

local function drawBars()
	local bars = mw.html.create()
	
	for _, bar in ipairs(data.bars) do
		local x = bar[w.x]
		local y = bar[w.y]
		local h = y and calculateBarHeight(bar) .. '%'
		local c = pickColor(bar)
		
		if x and truncateX then x = string.sub(x, -2) end -- Show only the last two digits of the year
		
		bars
			:newline()
			:tag('li')
			:addClass('es-bar')
			:attr('data-x', x)
			:attr('data-y', y)
			:css('height', h)
			:css('background-color', c)
			:node(drawTooltip(bar))
			:newline()
	end
	
	return bars
end

local function drawLegend()
	local legend = mw.html.create('div')
		:addClass('es-legend')
		:tag('ul')
	
	for _, group in pairs(data.groups) do
		legend
			:newline()
			:tag('li')
			:tag('span')
			:css('background-color', group[w.color] or '#fff')
			:done()
			:wikitext(group[w.label])
	end
	
	return legend:done()
end

local function drawChart(args)
	data = extractData(args)
	-- return mw.dumpObject(data)
	
	if #data.bars == 0 then
		return "''Geen data om weer te geven.''"
	end
	
	local chart = mw.html.create()
		:tag('div')
		:addClass('es-chart')
		:css('overflow-y', 'auto')
		:tag('ul')
		:addClass('es-grid')
		:css('width', data.barWidth * #data.bars .. 'em')
		:css('height', data.chartHeight .. 'px')
		:css('background', 'repeating-linear-gradient(#ccc, white 1px, white ' .. 100 / data.tiersCount .. '%)')
		:node(drawBars())
		:allDone()
		:node(drawLegend())
	
	return tostring(chart)
end

function p.main(frame)
	-- local args = getArgs(frame)
	return 'Link [[Zesde klasse]]'
	-- if args[1] == w.rankings then
	-- 	invertY = true
	-- 	barWidth = 1.5
	-- 	truncateX = true
	-- 	ySuffix = 'e'
	-- end
	
	-- return frame:extensionTag{ name = 'templatestyles', args = { src = templatestyles } } .. drawChart(args)
end

return p