<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://mywikibiz.com/index.php?action=history&amp;feed=atom&amp;title=Module%3AProgression_rainbow</id>
	<title>Module:Progression rainbow - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://mywikibiz.com/index.php?action=history&amp;feed=atom&amp;title=Module%3AProgression_rainbow"/>
	<link rel="alternate" type="text/html" href="https://mywikibiz.com/index.php?title=Module:Progression_rainbow&amp;action=history"/>
	<updated>2026-06-14T00:54:21Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.3</generator>
	<entry>
		<id>https://mywikibiz.com/index.php?title=Module:Progression_rainbow&amp;diff=479041&amp;oldid=prev</id>
		<title>Zoran: Pywikibot 6.4.0</title>
		<link rel="alternate" type="text/html" href="https://mywikibiz.com/index.php?title=Module:Progression_rainbow&amp;diff=479041&amp;oldid=prev"/>
		<updated>2021-07-16T05:25:33Z</updated>

		<summary type="html">&lt;p&gt;Pywikibot 6.4.0&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;--[[&lt;br /&gt;
This implements {{progression rainbow}}&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
require('Module:No globals')&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
-- rounding to first decimal, from http://lua-users.org/wiki/SimpleRound&lt;br /&gt;
local function round(num)&lt;br /&gt;
	return math.floor(num * 10 + 0.5) / 10&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function class_percent(param, total)&lt;br /&gt;
	-- These suck for i18n because the % is forced to the right without spacing,&lt;br /&gt;
	-- both in a required context (CSS) and unrequired (to-be-displayed text).&lt;br /&gt;
	-- I.e., there should be a separate version of this or a function parameter&lt;br /&gt;
	-- which takes a boolean. :(&lt;br /&gt;
	return tostring(round(100 * param / total)) .. '%'&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function percent_remaining(sum, total)&lt;br /&gt;
	local remaining = total - sum&lt;br /&gt;
	if remaining &amp;gt; 0 then&lt;br /&gt;
		return tostring(round(100 * remaining / total)) .. '%'&lt;br /&gt;
	else&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function category_count(category, project)&lt;br /&gt;
	return mw.site.stats.pagesInCategory(&lt;br /&gt;
		string.format('%s %s articles', category, project),&lt;br /&gt;
		'pages'&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- This is only done once in this module, here for demonstration.&lt;br /&gt;
-- Gist: Make it cleaner to initialize 'trivial' variables.&lt;br /&gt;
local function arg_or_default(args, from_arg, default)&lt;br /&gt;
	if args[from_arg] and args[from_arg] ~= '' then&lt;br /&gt;
		return args[from_arg]&lt;br /&gt;
	else&lt;br /&gt;
		return default&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
	return p._main(require('Module:Arguments').getArgs(frame))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main(args)&lt;br /&gt;
&lt;br /&gt;
	local classes = {&lt;br /&gt;
		{count = 0, class = 'List', category = 'List-Class'},&lt;br /&gt;
		{count = 0, class = 'Stub', category = 'Stub-Class'},&lt;br /&gt;
		{count = 0, class = 'Start', category = 'Start-Class'},&lt;br /&gt;
		{count = 0, class = 'C', category = 'C-Class'},&lt;br /&gt;
		{count = 0, class = 'B', category = 'B-Class'},&lt;br /&gt;
		{count = 0, class = 'GA', category = 'GA-Class'},&lt;br /&gt;
		{count = 0, class = 'A', category = 'A-Class'},&lt;br /&gt;
		{count = 0, class = 'FA', category = 'FA-Class'}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	local project_classes = {&lt;br /&gt;
		{count = 0, class = 'FL', category = 'FL-Class'},&lt;br /&gt;
		{count = 0, class = 'Unassessed', category = 'Unassessed'}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	local project = arg_or_default(args, &amp;quot;project&amp;quot;, nil)&lt;br /&gt;
	&lt;br /&gt;
	local sum_classes = 0&lt;br /&gt;
	if project then&lt;br /&gt;
		for _, class in ipairs(classes) do&lt;br /&gt;
			class.count = category_count(class.category, project)&lt;br /&gt;
			if class.class == 'FA' then&lt;br /&gt;
				class.count = class.count + category_count(&lt;br /&gt;
					project_classes[1].category,&lt;br /&gt;
					project&lt;br /&gt;
				)&lt;br /&gt;
			end&lt;br /&gt;
			sum_classes = sum_classes + class.count&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		for i, class in ipairs(classes) do&lt;br /&gt;
			-- 'or class.count' to keep us safe from a non-numeric value in args.&lt;br /&gt;
			class.count = tonumber(args[i]) or class.count&lt;br /&gt;
			sum_classes = sum_classes + class.count&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local total&lt;br /&gt;
	if project then&lt;br /&gt;
		-- It makes more sense to do this sum here rather than in the project&lt;br /&gt;
		-- loop above because total is initialized here in the non-project case&lt;br /&gt;
		total = sum_classes + category_count(&lt;br /&gt;
			project_classes[2].category,&lt;br /&gt;
			project&lt;br /&gt;
		)&lt;br /&gt;
	else&lt;br /&gt;
		total = tonumber(args[9]) or 100&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local root = mw.html.create('ul')&lt;br /&gt;
	root:addClass('progression-rainbow')&lt;br /&gt;
&lt;br /&gt;
	-- Don't care which frame it is if all I want to do is expand templates&lt;br /&gt;
	-- and extension tags&lt;br /&gt;
	local current_frame = mw.getCurrentFrame()&lt;br /&gt;
	for _, class in ipairs(classes) do&lt;br /&gt;
		if class.count ~= 0 then&lt;br /&gt;
			local percentage = class_percent(class.count, total)&lt;br /&gt;
				root:newline() -- sprinkled through to make the HTML easier to read&lt;br /&gt;
				root:tag('li')&lt;br /&gt;
				:css('background', current_frame:expandTemplate{&lt;br /&gt;
					title = 'class/colour', args = { class.class }&lt;br /&gt;
				})&lt;br /&gt;
				:css('width', percentage)&lt;br /&gt;
				:tag('span')&lt;br /&gt;
				:addClass('sr-only')&lt;br /&gt;
				:wikitext(string.format('%s %s', percentage, class.category))&lt;br /&gt;
				:done()&lt;br /&gt;
				:done()&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	root:newline()&lt;br /&gt;
	&lt;br /&gt;
	local remaining = percent_remaining(sum_classes, total)&lt;br /&gt;
	if remaining then&lt;br /&gt;
		root:tag('li')&lt;br /&gt;
		:addClass('remaining')&lt;br /&gt;
		:css('width', remaining)&lt;br /&gt;
		:tag('span')&lt;br /&gt;
		:addClass('sr-only')&lt;br /&gt;
		:wikitext(string.format('%s remaining', remaining))&lt;br /&gt;
		:done()&lt;br /&gt;
		:done()&lt;br /&gt;
		:newline()&lt;br /&gt;
	end&lt;br /&gt;
	root:allDone()&lt;br /&gt;
	return current_frame:extensionTag{&lt;br /&gt;
		name = 'templatestyles', args = { src = 'Module:Progression rainbow/styles.css'}&lt;br /&gt;
	} .. current_frame:extensionTag{&lt;br /&gt;
		name = 'templatestyles', args = { src = 'Screen reader-only/styles.css'}&lt;br /&gt;
	} .. '\n' .. tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Zoran</name></author>
	</entry>
</feed>