Module:Datastaven
Uiterlijk
![]() | Deze module maakt gebruik van TemplateStyles: |
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
- Module:Datastaven/Groepen - Een verzameling met voorgedefinieerde groepen die gebruikt kunnen worden met deze module.
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(' ') 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