module:Progression rainbow/sandbox

--[[

This implements {{progression rainbow}}

]]

require('strict')

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 percent(param, total)

-- These suck for i18n because the % is forced to the right without spacing,

-- both in a required context (CSS) and unrequired (to-be-displayed text).

-- I.e., there should be a separate version of this

return tostring(round(100 * param / total)) .. '%'

end

local function percent_remaining(sum, total)

local remaining = total - sum

if remaining > 0 then

return percent(remaining, total)

else

return nil

end

end

local function category_count(category, project)

return mw.site.stats.pagesInCategory(

string.format('%s %s articles', category, project),

'pages'

)

end

-- This is only done once in this module, here for demonstration.

-- Gist: Make it cleaner to initialize 'trivial' variables.

local function arg_or_default(args, from_arg, default)

if args[from_arg] and args[from_arg] ~= '' then

return args[from_arg]

else

return default

end

end

function p._main(args)

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'}

}

local project = arg_or_default(args, "project", nil)

local sum_classes = 0

if project then

for _, class in ipairs(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

for i, class in ipairs(classes) do

-- 'or class.count' to keep us safe from nil arg

class.count = tonumber(args[i]) or class.count

sum_classes = sum_classes + class.count

end

end

local total

if project then

-- It makes more sense to do this sum here rather than in the project

-- loop above because total is initialized here in the non-project case

total = sum_classes + category_count(

project_classes[2].category,

project

)

else

total = tonumber(args[9]) or 100

end

local height = arg_or_default(args, 'height', nil)

local root = mw.html.create('ul')

root:addClass('progression-rainbow')

if height then

root:css('height', height)

end

local current_frame = mw.getCurrentFrame()

for _, class in ipairs(classes) do

if class.count ~= 0 then

local percentage = percent(class.count, total)

root:newline() -- sprinkled through to make the HTML easier to read

root:tag('li')

:css('background', current_frame:expandTemplate{

title = 'class/colour', args = { class.class }

})

:css('width', percentage)

:attr('title', string.format('%s %s', percentage, class.category))

:tag('span')

:addClass('sr-only')

:wikitext(string.format('%s %s', percentage, class.category))

:done()

:done()

end

end

root:newline()

local remaining = percent_remaining(sum_classes, total)

if remaining then

root:tag('li')

:addClass('remaining')

:css('width', remaining)

:attr('title', string.format('%s remaining', remaining))

:tag('span')

:addClass('sr-only')

:wikitext(string.format('%s remaining', remaining))

:done()

:done()

:newline()

end

root:allDone()

return current_frame:extensionTag{

name = 'templatestyles', args = { src = 'Module:Progression rainbow/styles.css'}

} .. current_frame:extensionTag{

name = 'templatestyles', args = { src = 'Screen reader-only/styles.css'}

} .. '\n' .. tostring(root)

end

function p.main(frame)

return p._main(require('Module:Arguments').getArgs(frame))

end

return p