local p =
--Provides a convenient naming shortcut up to = for columns = 1, 9 do local N = math.pow(2, columns) p['N' .. N] = function(frame) return p.main(frame.args, columns) end p['n' .. N] = p['N' .. N]--to make case insensitiveend
--saves memory and avoids errors when using a nil as a table by providing a temporary table; if using nil as false; use 'table(k)' to look up table[k]p.nilAsTab = --never assign a value to these or they will stop being emptylocal infiniteEmpty = setmetatable -- infiniteEmpty[1][2][3]...[infinity] = local callableEmpty = setmetatable(p.nilAsTab)
local rowNum, head, m, col, tab, esc =,,,, mw.html.create'table', local nodeFunc =
setmetatable(nodeFunc.helper,)function p.getNodeFunc return nodeFunc.helperend
local function newRow(bodyRow) local first = p.flex_tree.merge and mw.clone(p.flex_tree.cell) or p.flex_tree.cell tab.r = tab:tag'tr' :node(first) if bodyRow then table.insert(rowNum, bodyRow, tab.r) if p.flex_tree.merge then rowNum[bodyRow].first = first rowNum[bodyRow].first.unchanged = true end endend
local function drawHead(text, row3rd) local td = (row3rd and rowNum[row3rd]:tag'td':attr or head.row:tag'td') :attr if text ~= 'omit_label' then td:wikitext(text):css endend
local function spacer(width) tab.r:tag'td' :attr :wikitext(p.no_column_head and or ' ')end
local function dpBox(v, r) p.dpBoxBase = p.dpBoxBase or mw.html.create'td':attr if not v then p.dpBoxEmpty = p.previewnumbers and mw.clone(p.dpBoxBase) or p.dpBoxEmpty or mw.clone(p.dpBoxBase):wikitext(p.flex_tree.wt) rowNum[r]:node(p.dpBoxEmpty) else rowNum[r]:node(mw.clone(p.dpBoxBase):wikitext(v)) endend
p.scoreWasher =
local function boldWin(s1, s2) return setmetatable(p.bold and s1 ~= s2 and (math[({'min', 'max'})[p.bold]](s1, s2)
local function maxSpan(span, start, rows) return math.min(span, math.max(0, rows - start + 1))end
--in case of templates like RDseed need padding valuep.teamBoxPadding = function return '.6ex'endp.teamBoxPadTab = p.teamBoxNormal = local function teamBox(v, r, f) if p.flex_tree.merge and not v and f.phase
1 then v = hasBold end end local cell if f[1] then cell = f.sumBox and f.sumBox[1] and or cell['text-align'] = v and f[1] else cell = p.teamBoxPadTab end local text = v or f[1] and or ' ' if f.bold then text = mw.ustring.gsub(text, '(%(%[%[[^%[%]]*%]%]%))', '
%1') end tab.r = rowNum[r]:tag'td' :css(p.teamBoxCSS) :css(cell) :attr :node(mw.html.create(f.bold and 'b'):wikitext(text)) endendfunction p._main(args) function args:clean(key, params)--prevent html comments from breaking named args and reduces repeat concatenation params = params or local clean = args[key] or params.ifNil if clean then params.append = params.append or clean = mw.text.decode(clean):gsub('', ):gsub(params.pattern or '[^%w-;%.]', ) .. params.append clean = clean ~= params.append and clean or params.ifNil end args[key] = params.keepOld and args[key] or clean return clean end p.cols = tonumber(args:clean('columns',)) p.tCols = (tonumber(args:clean('final_RDs_excluded',)) or 0) + p.cols local matchPer = local skipMatch, unBold =, --(skip|manualbold)match# to boolean for k, _ in pairs(args) do local mType, mNum = string.match(k, '^(%l+)match(%d*)$') mType, mNum = [mType], tonumber(mNum) if mType then if mNum then mType[mNum] = args:clean(k)
'true' else for pattern in args:clean(k,):gfind(matchPer.pattern) do local d1, period, op, d2 = pattern:match(matchPer.vals) d1 = tonumber(d1) or 1 d2 = op
nil or type(p[v])
'yes' or args[v]
local head_br = p.branch_upwards = p.branch_upwards and 0 for k = 1, p.cols do if k > 1 then spacer(sp[3]) spacer(sp[4]) if not p.no_column_head then head.row:tag'td':attr end end spacer(sp[1]) for s = 1, p.scoreBoxes do spacer(#scoreWidth
p.cols and (p['3rdplace'] or p.cols > 3 and nil
p.tCols) or ((c
p.tCols and rowNum.third local colorFinal, bumpMid = p.color and c
0 then m.showBox = setmetatable(nodeArgs.tableSum) if nodeFunc:scanPattern(args, step) then nodeFunc.called = m.available = true else m.available = nil end end if skipMatch[m.num] then if m.phase
2 then if nodeFunc.pattern and (nodeFunc.called.bridge or nodeFunc.called.canvas) then step = step + 1 end m.num = m.num + 1 step = step + (p.omit_blanks and 0 or m.showBox) bumps = bumps + (col.show3rd and 0 or maxSpan(p.span, m.r, rows)) end elseif m.phase
false then m.showBox = nodeArgs.blank step = step + 1 end end if m.showBox[1] then if col.show3rd then col.show3rd = (m.num - col.top) * 2 if col.show3rd
1 then bumps = p.textThird and 3 or 0 elseif p.branch_upwards then r = 7 bumps = p.textThird and 2 or 0 end m.r = r + bumps if p.textThird then drawHead(p.textThird, m.r) bumps = bumps + 2 m.r = r + bumps end end end dpBox(nodeFunc.pattern and nodeFunc.nonFunc or args[step], m.r) if p.previewnumbers then rowNum[m.r].nodes[#rowNum[m.r].nodes] :tag'div' :css :wikitext(m.num) :attr end end if p.colspan then m.nonEmpty = for s = step + 2, step + nodeArgs.team.offset do local i = if args[i[1]] or args[i[2]] then table.insert(m.nonEmpty, i) end end if p.bold and m.showBox[2] and m.showBox[3] and not unBold[m.num] then m.bold = local notSummed = not p.scoreSumBox or #m.nonEmpty < 2 for s, i in ipairs(m.nonEmpty) do m.bold.clean[s] = m.bold.box[s] = notSummed and boldWin(m.bold.clean[s][1], m.bold.clean[s][2]) or callableEmpty end if p.scoreSumBox and m.nonEmpty[2] then local i = table.insert(m.nonEmpty, i) args[i[1]], args[i[2]] = p.scoreWasher.sum(m.bold.clean) m.bold.box[p.scoreBoxes] = boldWin(args[i[1]], args[i[2]]) end getmetatable(boxStyle).__index = p.scoreSumBoxes and m.bold.win = m.bold.box[#m.nonEmpty] or callableEmpty else m.bold = infiniteEmpty end end else if m.showBox[m.phase] then if col.color_repechage then col.color_repechage = 2 end if p.bold then if m.bold.win(m.phase) and (colorFinal or col.color_repechage) then color_index = 1 + (col.show3rd or 0) + (col.color_repechage or 0) elseif m.bold.box[#m.nonEmpty] then color_index = 2 + (col.show3rd or 0) + (col.color_repechage or 0) else color_index = 4 end p.teamBoxCSS = (colorFinal or col.color_repechage) and or p.teamBoxNormal p.teamBoxMedalColor = color_index < 4 else p.teamBoxCSS = (colorFinal or col.color_repechage) and or p.teamBoxNormal end local f = teamBox(args[step + nodeArgs.team[m.phase]], m.r, f) f[1] = 'center' if p.colspan then if m.nonEmpty[1] then local loneSum if #m.nonEmpty < p.scoreBoxes then loneSum = #m.nonEmpty
2 then col.show3rd = col.show3rd ~= 2 and col.show3rd or nil if p.scoreWasher.demo and p.scoreWasher.demo
m.num then skipMatch[m.num] = 'orphan' end step = step + m.showBox m.num = m.num + 1 if bump > 0 and rowNum[m.r + 2] and not (nodeFunc.pattern and nodeFunc.called.canvas) then bumps = bumps + p.span rowNum[m.r + 2]:node(bumpMid) end r = r + (col.show3rd or bump) end end m.phase = (m.phase + 1) % 3 end end if p.cols > c then--draw lines to next round p.unit = bump + 3 bump = 3 * math.pow(2, c) - 3 bumps = p.branch_upwards and 4 or (p.unit + 1) rowNum[1] :tag'td':attr if not p.branch_upwards then rowNum[1]:tag'td' :attr :css(nodeFunc.bridge.lay[c](0) and or ) end col.n = 0 col.t2 = nil for r = bumps + 1, rows, p.unit * 2 do tab.r = rowNum[r]:tag'td' local interval = ((r - bumps - 1) / (p.unit * 2)) % 4 if interval % 2
0 then --draws the ']' when a PAIR of matches needs lines tab.r :attr :css(skipMatch[col.tot + col.n / 2] and or) else --draws the lines when only top OR bottom match need lines tab.r :attr :cssText(col.t
1 and (nodeFunc.bridge.lay[c](col.n - 2) and p:saveStr('right', ';border-right:', p.reuseStr.solid) or 'vertical-align:bottom' ) or nil ) :node(col.t
1 and p:saveStr('bttmRght', 'border-width:0 ', tab.line[2], ' 0;border-style:solid') or col.t
2 and interval ~= 2 and not nodeFunc.bridge.lay[c](col.n + 2) and p.cornerDiv) end col.t = rowNum[r + (p.branch_upwards or p.unit)]:tag'td' :attr :css(interval
--local standard = --function p.main(frame, columns) local args = require'Module:Arguments'.getArgs(frame,) args.columns = args.columns or columns return p._main(args)end
function p.seed(frame) local parent = frame:getParent or frame local function arg(k, alt) return parent.args[k] or frame.args[k] or alt end local padding, width = arg(2, p.teamBoxPadding), arg(3, arg('widescore') and 40 or 30) padding = tonumber(padding) and tonumber(padding) .. 'px' or padding width = tonumber(width) and tonumber(width) .. 'px' or width return mw.html.create'div' :css :wikitext(arg(1, ' '))end
return p