--[[
This implements {{progression rainbow}}
]]
require ('Module:No globals')
local getArgs = require ('Module:Arguments').getArgs
local p = {}
-- rounding to first decimal, from http://lua-users.org/wiki/SimpleRound
local function round(num)
return math.floor(num * 10 + 0.5) / 10
end
local function class_percent(param, divisor)
return tostring(round(100 * param / divisor)) .. '%'
end
local function percent_remaining(sum, divisor)
sum = sum - divisor
if sum ~= 0 then -- find this a bit specious
return tostring(round(-100 * sum / divisor)) .. '%'
else
return nil
end
end
local function category_count(category, project)
return mw.site.stats.pagesInCategory(
category .. ' ' .. project .. ' articles',
'pages'
)
end
function p.main(frame)
local args = getArgs(frame)
return p._main(args, frame)
end
function p._main(args, frame)
-- Is there a way to avoid passing a reference to the parent frame?
-- extensionTag must be available in p._main, which on the frame object.
local classes = {
{count = 0, class = 'List', category = 'List-Class'},
{count = 0, class = 'Stub', category = 'Stub-Class'},
{count = 0, class = 'Start', category = 'Start-Class'},
{count = 0, class = 'C', category = 'C-Class'},
{count = 0, class = 'B', category = 'B-Class'},
{count = 0, class = 'GA', category = 'GA-Class'},
{count = 0, class = 'A', category = 'A-Class'},
{count = 0, class = 'FA', category = 'FA-Class'}
}
local project_classes = {
{count = 0, class = 'FL', category = 'FL-Class'},
{count = 0, class = 'Unassessed', category = 'Unassessed'}
}
-- generally, I think if there were more 'project' orthogonal attributes
-- there would be a case for object-orientation here
-- I'm not sure what that would look like
local project
-- is there a more idiomatic way to initialize project?
if args['project'] and args['project'] ~= '' then
project = args['project']
else
project = nil
end
local sum_classes = 0
if project then
for i, class in pairs(classes) do
class['count'] = category_count(class['category'], project)
if class['class'] == 'FA' then
class['count'] = class['count'] + category_count(
project_classes[1]['category'],
project
)
end
sum_classes = sum_classes + class['count']
end
else
-- I'm not sure if it's clear in this for loop that I want to get
-- parameters 1 to 8, which I could also do instead as 'for 1,8...'' ]]
for i, class in pairs(classes) do
if args[i] then
class['count'] = tonumber(args[i])
sum_classes = sum_classes + class['count']
end
end
end
local divisor
if project then
-- I think it makes more sense to do this sum here rather than in the
-- project loop above, because I initialized divisor here in the non-
-- project case
divisor = sum_classes + category_count(
project_classes[2]['category'],
project
)
else
divisor = args[9] or 100
end
local root = mw.html.create('table')
root:addClass('progression-rainbow')
:attr('role', 'presentation')
for i, class in pairs(classes) do
if class['count'] ~= 0 then
local percentage = class_percent(class['count'], divisor)
root:newline() -- sprinkled through to make the HTML easier to read
:tag('td')
:css('background', frame:expandTemplate{
title = 'class/colour', args = { class['class'] }}
)
:css('width', percentage)
:tag('span')
-- wikitext accessibly-hidden by CSS
:wikitext(percentage .. " " .. class['category'])
-- what is the more friendly way for i18n?
:done()
:done()
end
end
root:newline()
local remaining = percent_remaining(sum_classes, divisor)
if remaining then
root:tag('td')
:addClass('remaining')
:css('width', remaining)
:tag('span')
-- and same question here for i18n
:wikitext(remaining .. " remaining")
:done()
:done()
:newline()
end
-- Not sure if p._main should be stringified instead of returning an object.
return frame:extensionTag{
name = 'templatestyles',
args = { src = 'Progression rainbow/styles.css'}
} .. '\n' .. tostring(root)
-- not sure how to add \n before root is initialized, because root must be
-- an HTML element, and \n is not
end
return p