Module:Ranking movements explained

-- This module implements local p =

local templatestyles = 'Module:Ranking movements/styles.css'

local colors = local labels =

local legend =

local function format_cell_text(s) if s then if s:match('^[Nn][Rr]') or s:match('^—') then legend['—'] = true end if s:match('^[Rr][Vv]') then legend['RV'] = true end if s:match('%d[%-%s]*[Tt]') or s:match('[Tт]') then legend['т'] = true end if s:match('[%(%)]') then legend[''] = true end s = mw.ustring.gsub(s, '^NR', '—') end return send

local function get_rank(s) -- This is intended to remove any extra stuff after the ranking local result = mw.ustring.match(s or , '^%d*') or -- Is it numbers? if result

then result = mw.ustring.match(s or , '^[%a/—]*') or -- Is it letters? end return resultend

local function get_color(lastweek, thisweek) -- No coloring if first week or this week is blank if (lastweek

'first week') or (thisweek

) or (lastweek

) or (lastweek

'N/A') or (thisweek

'N/A') then return nil end -- No coloring if the rank has not changes if (lastweek

thisweek) then return nil end -- If last week was NR then rank has increased if (lastweek

'NR' or lastweek

'—') then legend['+'] = true return colors['+'] end -- If last week was RV if (lastweek

'RV') then -- If this week is NR then rank has decreased, otherwise increased if (thisweek

'NR' or thisweek

'—') then legend['-'] = true return colors['-'] else legend['+'] = true return colors['+'] end end -- In all other cases, just compare the numbers lastweek = tonumber(lastweek) or 999999 thisweek = tonumber(thisweek) or 999999 if (lastweek > thisweek) then legend['+'] = true return colors['+'] end if (thisweek > lastweek) then legend['-'] = true return colors['-'] end return nilend

local tracking, preview =,

local function checkargs(args) for k, v in pairs(args) do if v ~= then if k and type(k)

'string' then if k:match('^poll[1-6]firstweek$') or k:match('^poll[1-6]lastweek$') or k:match('^poll[1-6]title$') or k:match('^poll[1-6]_final$') or k

'title' or k

'nocat' or k:match('^wk1?%d$') or k:match('^wk2[01]') then -- valid elseif k:match('^poll[1-6]_1?%d$') or k:match('^poll[1-6]_2[01]$') then -- valid local i = mw.ustring.gsub(k, '^poll([1-6])_%d+$', '%1') local j = mw.ustring.gsub(k, '^poll[1-6]_(%d+)$', '%1') local maxweeks = tonumber(args['poll' .. i .. 'lastweek']) or 20 if tonumber(j) > maxweeks then table.insert(tracking, '') end else -- invalid local vlen = mw.ustring.len(k) k = mw.ustring.sub(k, 1, (vlen < 25) and vlen or 25) k = mw.ustring.gsub(k, '[^%w\-_ ]', '?') table.insert(tracking, '') table.insert(preview, '"' .. k .. '"') end end end endend

function p.main(frame) local args = require('Module:Arguments').getArgs(frame) local maxpolls = 6 -- Compute the maximum number of columns local minweeks = 20 local maxweeks = 0 for k = 1,maxpolls do local n = tonumber(args['poll' .. k .. 'lastweek']) or (args['poll' .. k .. 'title'] and 20 or 0) maxweeks = (n > maxweeks) and n or maxweeks local n = tonumber(args['poll' .. k .. 'firstweek']) or (args['poll' .. k .. 'title'] and 0 or 20) minweeks = (n < minweeks) and n or minweeks end

-- Start table local root = mw.html.create('table') :addClass('wikitable ranking-movements')

-- Table caption title local caption = root:tag('caption'):wikitext(args['title'] or labels['title'])

-- Week header row local row = root:tag('tr') row:tag('th') -- Blank space in corner row:tag('th'):attr('colspan', maxweeks - minweeks + 1):wikitext(labels['week'])

-- Poll header row row = root:tag('tr') row:tag('th') :wikitext(labels['poll']) for k = minweeks,maxweeks do local text = args['wk' .. k] or k if (k

0) then text = args['wk' .. k] or labels['pre'] elseif (k

maxweeks) then text = args['wk' .. k] or labels['final'] end row:tag('th') :wikitext(text) end -- Poll data rows for i = 1,maxpolls do local ptitle = args['poll' .. i .. 'title'] or local pfirstweek = tonumber(args['poll' .. i .. 'firstweek']) or 0 local plastweek = tonumber(args['poll' .. i .. 'lastweek']) or 20 if ptitle ~= then row = root:tag('tr') row:tag('th') :wikitext(ptitle) -- Before the first poll if pfirstweek > minweeks then row:tag('td') :attr('colspan', pfirstweek - minweeks) :css('background', colors['not released']) :wikitext(labels['not released']) end -- Results local lastweek = 'first week' for k = pfirstweek,plastweek do local rank = args['poll' .. i .. '_' .. k] if rank then rank = mw.ustring.gsub(rank, '^&[MNmn][Dd][Aa][Ss][Hh];', '—') rank = mw.ustring.gsub(rank, '^[–%-]', '—') end local thisweek = get_rank(rank) row:tag('td') :css('background', get_color(lastweek, thisweek)) :wikitext(format_cell_text(rank)) lastweek = thisweek end -- After the last poll if plastweek < maxweeks then rank = args['poll' .. i .. '_final'] local colspan = (maxweeks - plastweek) - (rank and 1 or 0) row:tag('td') :attr('colspan', (colspan > 1) and colspan or nil) :css('background', colors['not released']) :wikitext(labels['not released']) if rank and colspan > 0 then rank = mw.ustring.gsub(rank, '^&[MNmn][Dd][Aa][Ss][Hh];', '—') rank = mw.ustring.gsub(rank, '^[–%-]', '—') local thisweek = get_rank(rank) row:tag('td') :css('background', get_color(lastweek, thisweek)) :wikitext(format_cell_text(rank)) end end end end -- Add legend local line1, line2 = , if legend['+'] or legend['-'] then for k,v in ipairs do line1 = line1 .. '

██' line1 = line1 .. ' ' .. labels[v] end end for k,v in ipairs do if legend[v] then line2 = line2 .. ' ' .. v .. ' = ' .. labels[v] end end if line1 ~= or line2 ~= then caption:wikitext('
\'\'\ .. labels['legend'] .. ':\'\'\ .. line1) if line1 ~= and line2 ~= then caption:wikitext('
') end caption:wikitext(line2 .. '
') end checkargs(args)

local trackstr = (#tracking > 0) and table.concat(tracking, ) or if #preview > 0 then trackstr = require('Module:If preview')._warning .. trackstr end

return frame:extensionTag .. tostring(root) .. trackstrend

return p