モジュールの解説[表示] [編集] [履歴] [キャッシュを破棄]

スポーツ等における順位の変遷表や勝敗表を作成するためのモジュールです。{{Fb rbr t pos}}及び{{Fb rbr position}}の代替となるものです。

使い方 編集

書式 編集

順位の変遷表
{{#invoke:Sports rbr table|table
| sortable = <!-- y or n or omit -->
| team1 = 
| pos1  = <!-- 1 / 2 / 3 / 4 / ... -->
| team2 = 
| pos2  = <!-- 1 / 2 / 3 / 4 / ... -->
<!-- ... -->
| color_1 = 1st
| text_1  = 1st place
| source = 
}}
勝敗表
{{#invoke:Sports rbr table|table
| sortable = <!-- y or n or omit -->
| team1 = 
| res1  = <!-- W / D / L ... -->
| team2 = 
| res2  = <!-- W / D / L ... -->
<!-- ... -->
| color_W = green2
| color_D = yellow2
| color_L = red2
| source = 
}}

パラメータ 編集

基本パラメータ
パラメータ 内容
|title= 表題。指定すると表の上部に表示される。
|sortable=y 並べ替え可能な表を作成する。
|labelnowrap=y これを指定すると、チーム名を改行させない(表幅が足りない場合は横スクロールする)
|color_X= |X=」(数字、アルファベット等)で指定された要素(順位や勝敗)に対する背景色を指定する。色のパラメータ値については後述。
順位に関しては範囲で要素を設定出来る。
  • |color_-3=を指定すると「3位以上」の背景色を設定出来る。
  • |color_15-=を指定すると「15位以下」の背景色を設定出来る。
|text_X= |color_X=で設定した背景に対する凡例のテキストを入力する。
|source= 結果の出典を表示する。
|notes= 表の下部に注釈を付記する。
|update=(日付) 最終更新日を入力する。(対戦開始前は「|update=future」を入力。)
|start_date=(日付) (対戦開始前の)対戦開始日を入力する。
|legendpos= 凡例の表示位置を指定する。デフォルト値は「tr」 (右上)。
br」 (右下), 「tl」(左上)、「bl」(左下)、「t」(上部)、「b」(下部)が指定可能。
|legendorder= 凡例の表示順を指定する(例:|legendorder=W/D/L)。
|toptext= 表上部に表示させるテキスト(表題とは別)。通常は|legendpos=trと併用する。
|header= チーム列ヘッダーのテキスト。 デフォルト値は「チーム ╲ 節」。
|labelalign= 列ラベルの配置。 デフォルト値は「left」。
|firstround= 表の最初(一番左)のラベルで表示される節数。以後右に1ずつ加算される。デフォルト値は「1」。
|rndN= 「第N節」のラベルに使用するテキスト(|firstround=と異なり、特定節のみの表記を書き替える時に使用)。デフォルト値は「1」。
|splitN=yes これを設定すると、Nチーム目の行の下を太線にして表が分かれているように見せる。(Nは数字に置き換えて使用)
|splitN+1=を設定しないとその下の行すべてが太線になるので注意。
順位表に用いるパラメータ
パラメータ 内容
|teamN= N番目に指定されるチーム名。
(一時的に)N番目のチームを空白とするために、|team1=-|team1=&nbsp;|team1=&ensp;|team1=TBAといった指定方法も可能。
|posN= |teamN=で指定したチームの節別順位を節ごとにスラッシュ (/) で区切って入力する。
例えば、|pos1=1/2/3/8/3/2/1と入力すれば、7節までの順位変動が「1位→2位→3位→8位→3位→2位→1位」であることを示す。
後述の|resN=と同じ行で重複使用出来ない。
|posX_rndY_note= X番目のチームのY節の結果に対して注釈を加える。
|posX_rndY_color= X番目のチームのY節の結果の背景色を上書き指定する。
勝敗表に用いるパラメータ
パラメータ 内容
|labelN= N番目の行に表示させる要素(勝敗、順位など)のラベル
|resN= |labelN=で指定した行で表示させる節別の要素をスラッシュ (/) で区切って入力する。
例えば、|res1=W/D/D/W/Lと入力すれば、5節までの勝敗が「勝ち・引き分け・引き分け・勝ち・負け」であることを示す。
前述の|posN=と同じ行で重複使用出来ない。
|resX_rndY_note= X番目の行の要素のY節の結果に対して注釈を加える。
|resX_rndY_color= X番目の行の要素のY節の結果の背景色を上書き指定する。

なお、チーム名等のパラメータにはモジュール:Sports tableに準拠したパラメータを使用することが出来ます。この場合、チーム名には当該モジュール内でのみ通用する、アルファベット3文字程度の略称を設定する必要があります。

モジュール:Sports tableに準拠したパラメータ
パラメータ 内容
|name_TTT= 「TTT」に定義されるチームの名前
|teamN=TTT 「TTT」に定義されるチームの表示順
|pos_TTT= 「TTT」に定義されるチームの節別順位を節ごとにスラッシュ (/) で区切って入力する。|posN=と入力方法は同じ。
|res_TTT= 「TTT」に定義されるチームの節別の要素(勝敗など)をスラッシュ (/) で区切って入力する。|resN=と入力方法は同じ。

編集

背景色には以下の種類が用意されています。モジュール:Sports tableに準拠したこれらの色のいずれかを使用することが推奨されます。

名前 16進数指定
green1 BBF3BB
green2 CCF9CC
green3 DDFCDD
green4 EEFFEE
blue1 BBF3FF
blue2 CCF9FF
blue3 DDFCFF
blue4 EEFFFF
名前 16進数指定
yellow1 FFFFBB
yellow2 FFFFCC
yellow3 FFFFDD
yellow4 FFFFEE
red1 FFBBBB
red2 FFCCCC
red3 FFDDDD
red4 FFEEEE
名前 16進数指定
black1 BBBBBB
black2 CCCCCC
black3 DDDDDD
black4 EEEEEE
1st FFD700
2nd C0C0C0
3rd CC9966

使用例 編集

順位の変遷表
{{#invoke:Sports rbr table|table
|title = 使用例1
|sortable = y
|team1 = Aチーム
|pos1 = 1/2/2/2/2
|team2 = Bチーム
|pos2 = 2/1/4/4/4
|team3 = Cチーム
|pos3 = 3/4/1/6/1
|team4 = Dチーム
|pos4 = 4/3/6/1/3
|team5 = Eチーム
|pos5 = 5/6/3/8/7
|team6 = Fチーム
|pos6 = 6/5/8/3/5
|team7 = Gチーム
|pos7 = 7/8/5/5/8
|team8 = Hチーム
|pos8 = 8/7/7/7/6
|color_1 = 1st
|text_1 = 優勝/昇格
|color_2 = green1
|text_2 = 昇格
|color_3-4 = blue2
|text_3-4 = プレーオフ進出
|color_7- = red1
|text_7- = 降格
|source = Some source
}}
優勝/昇格
昇格
プレーオフ進出
降格
使用例1
チーム ╲ 節12345
Aチーム12222
Bチーム21444
Cチーム34161
Dチーム43613
Eチーム56387
Fチーム65835
Gチーム78558
Hチーム87776
出典: Some source
{{#invoke:Sports rbr table|table
|title = [[リーガ・エスパニョーラ2008-2009]] 順位表
|sortable = y
|team1 = {{Fb team Atlético Madrid}} |pos1 = 1 /7 /5 /4 /7 /7 /8 /10/6 /7 /6 / / / / / / / /
|team2 = {{Fb team Barcelona}}       |pos2 = 15/15/9 /6 /5 /4 /4 /2 /1 /1 /1 / / / / / / / /
|team3 = {{Fb team Betis}}           |pos3 = 16/16/16/17/18/20/16/14/16/15/10/ / / / / / / /
|team4 = {{Fb team Espanyol}}        |pos4 = 6 /1 /4 /8 /10/9 /10/11/10/12/16/ / / / / / / /
|team5 = {{Fb team Real Madrid}}     |pos5 = 13/8 /6 /3 /3 /5 /5 /3 /3 /4 /4 / / / / / / / /
|team6 = {{Fb team Sevilla}}         |pos6 = 10/4 /7 /5 /4 /3 /2 /5 /5 /5 /5 / / / / / / / /
|team7 = {{Fb team Valencia}}        |pos7 = 2 /2 /1 /1 /1 /1 /1 /1 /4 /3 /3 / / / / / / / /
|team8 = {{Fb team Villarreal}}      |pos8 = 9 /6 /3 /2 /2 /2 /3 /4 /2 /2 /2 / / / / / / / /
|legendpos = b
|color_1 = 1st
|text_1 = 優勝
|color_2 = 2nd
|text_2 = 準優勝
|color_3 = 3rd
|text_3 = 3位
|color_18- = red1
|text_18- = 降格
|source = [http://www.kicker.de/news/fussball/intligen/ligen/tabelle/liga/900 www.kicker.de {{de icon}}]
}}
リーガ・エスパニョーラ2008-2009 順位表
チーム ╲ 節12345678910111213141516171819
アトレティコ・マドリード175477810676
バルセロナ1515965442111
ベティス1616161718201614161510
エスパニョール61481091011101216
レアル・マドリード138633553344
セビージャ104754325555
バレンシア22111111433
ビジャレアル96322234222
出典: www.kicker.de (ドイツ語)
  = 優勝;   = 準優勝;   = 3位;   = 降格
勝敗表
{{#invoke:sports rbr table|table
|title = 使用例2
|header =|label1 = ホーム/アウェイ
|res1 = H/A/A/H/A/H/A/H/H/A/A/H/H/A/H/A/A/H/H/A/A
|label2 = 勝敗
|res2 = W/L/L/W/W/D/W/L/L/L/L/W/W/W/W/L/D/L/L/D/L
|label3 = 順位
|pos3 = 4/10/14/8/6/7/7/8/9/10/11/11/8/7/6/6/6/7/9/9/9
|color_W = green2|color_D = yellow2|color_L = red2
|color_1 = green1|color_2 = green2|color_3-4 = green3
|color_5-7 = blue1|color_18- = red1
|source = Some source
}}
使用例2
123456789101112131415161718192021
ホーム/アウェイHAAHAHAHHAAHHAHAAHHAA
勝敗WLLWWDWLLLLWWWWLDLLDL
順位41014867789101111876667999
出典: Some source

-- This module implements {{Sports rbr table}}
local p = {}

-- Internationalisation
local labels = {
	teamround = 'チーム ╲ 節',
	source = '出典:',
	notes = '注釈:',
	matches = '試合',
	updatedto = '最終更新は<date>の<matches>終了時.',
	firstplayed = '<matches>は<date> に開始予定.',
	futuredate = '?',
	complete = 'complete',
	future = 'future'
}

local modname = 'Module:Sports rbr table'
local templatestyles = 'Module:Sports rbr table/styles.css'

local args = nil

local preview, tracking = '', ''
local hasnotes = false

local colorlist = {}
local textlist = {}

local color_map = {
		green1='#BBF3BB', green2='#CCF9CC', green3='#DDFCDD', green4='#EEFFEE',
		blue1='#BBF3FF', blue2='#CCF9FF', blue3='#DDFCFF', blue4='#EEFFFF',
		yellow1='#FFFFBB', yellow2='#FFFFCC', yellow3='#FFFFDD', yellow4='#FFFFEE',
		red1='#FFBBBB', red2='#FFCCCC', red3='#FFDDDD', red4='#FFEEEE',
		black1='#BBBBBB', black2='#CCCCCC', black3='#DDDDDD', black4='#EEEEEE',
		['1st']='#FFD700', ['2nd']='#C0C0C0', ['3rd']='#CC9966'
	}

local legend_symbols = {O='W/O'}

local legend_order_default = {'A', 'H', 'N', 'B', 'W', 'D', 'L', 'Ab', 'P', 'O'}

local function isnotempty(s)
	return s and s:match( '^%s*(.-)%s*$' ) ~= ''
end

local function zeropad(n)
	if n>=0 and n < 10 then
		return '00' .. n
	end
	if n>=0 and n < 100 then
		return '0' .. n
	end
	return '' .. n
end

local function pad_key(k)
	-- Zero pad, fix ranges and dashes
	if k then
		k = k .. ' '
		k = mw.ustring.gsub(k, '–', '-')
		k = mw.ustring.gsub(k, '_([%d][^%d])', '_0%1')
		k = mw.ustring.gsub(k, '%-([%d][^%d])', '-0%1')
		k = mw.ustring.gsub(k, '_([%d][%d][^%d])', '_0%1')
		k = mw.ustring.gsub(k, '%-([%d][%d][^%d])', '-0%1')
		k = mw.ustring.gsub(k, '([^%d])%-([%d])', '%1000-%2')
		k = mw.ustring.gsub(k, '([%d])%-%s*$', '%1-999')
		k = mw.ustring.gsub(k, '^%s*(.-)%s*$', '%1')
	end

	return k
end

local function matches_date(text, m, d)
	return mw.ustring.gsub(mw.ustring.gsub(text .. '', '<matches>', m), '<date>', d)
end

local function escapetag(text)
	return mw.ustring.gsub(text, '</', '<FORWARDSLASH')
end

local function unescapetag(text)
	return mw.ustring.gsub(text, '<FORWARDSLASH', '</')
end

local function get_color(p)
	if p then
		p = mw.ustring.gsub(p, '</?[Aa][Bb][Bb][Rr][^<>]*>', '')
		p = mw.ustring.gsub(p, '<[Ss][Uu][Pp]>[^<>]*</[Ss][Uu][Pp]>', '')
		p = mw.ustring.gsub(p, '</?[Ss][^<>]*>', '')
		p = mw.ustring.gsub(p, '†%s*$', '')
		p = mw.ustring.gsub(p, '=%s*$', '')
		p = mw.ustring.gsub(p, '%[%[[^%[%]|]*|([^%[%]|]*)%]%]', '%1')
		if p:match('^%a%a*$') then
			if args['text_' .. p] == nil then
				tracking = tracking .. '[[Category:Pages using sports rbr table with an undescribed result|' 
					.. p:match('^(%a).*$') .. ']]'
			end
		end
	end
	local c = colorlist[p] or colorlist[zeropad(tonumber(p) or -1)]
	if c then
		return color_map[c] or c
	end
	p = tonumber(p or '0') or 0
	if p <= 0 then
		return nil
	end
	-- ranges in order of specificity
	local offset1, offset2 = 999, 999
	for k,v in pairs( colorlist ) do
		local r1 = tostring(k):match( '^%s*([%d]+)%-[%d]+%s*$' )
		local r2 = tostring(k):match( '^%s*[%d]+%-([%d]+)%s*$' )
		if r1 and r2 then
			r1 = tonumber(r1)
			r2 = tonumber(r2)
			if (r1 <= p) and (r2 >= p) then
				if (c == nil) or ((p - r1) <= offset1 and (r2 - p) <= offset2) then
					c = color_map[v] or v
					offset1 = p - r1
					offset2 = r2 - p
				end
			end
		end
	end
	return c
end

local function check_arg(k, st)
	k = tostring(k) or ''
	if k == 'firstround' or k == 'sortable' or k == 'updated' or k == 'update'
		or k =='source' or k =='notes' or k == 'legendpos' or k == 'date' 
		or k == 'header' or k == 'title' or k == 'start_date' or k == 'labelnowrap'
		or k == 'labelalign' or k == 'toptext' or st.addtl_args(k) then
	elseif k == 'legendorder' then
		tracking = tracking .. '[[Category:Pages using sports rbr table with legendorder]]'
	elseif tostring(k):match( '^%s*text_?(.-)%s*$' ) then
	elseif tostring(k):match( '^%s*colou?r_?(.-)%s*$' ) then
	elseif tostring(k):match( '^%s*team[%d]+%s*$' ) then
	elseif tostring(k):match( '^%s*label[%d]+%s*$' ) then
		if args['header'] then
		else
			tracking = tracking .. '[[Category:Pages using sports rbr table with unsupported parameters|ψ]]'
		end
	elseif tostring(k):match( '^%s*opp[%d]+%s*$' ) then
	elseif tostring(k):match( '^%s*pos[%d]+%s*$' ) then
	elseif tostring(k):match( '^%s*grnd[%d]+%s*$' ) then
	elseif tostring(k):match( '^%s*res[%d]+%s*$' ) then
	elseif tostring(k):match( '^%s*posc[%d]+%s*$' ) then
	elseif tostring(k):match( '^%s*grndc[%d]+%s*$' ) then
	elseif tostring(k):match( '^%s*resc[%d]+%s*$' ) then
	elseif tostring(k):match( '^%s*split[%d]+%s*$' ) then
	elseif k == 'rnd1' then
		tracking = tracking .. '[[Category:Pages using sports rbr table with rnd parameters]]'
	elseif tostring(k):match( '^%s*rnd[%d]+%s*$' ) then
	elseif tostring(k):match( '^%s*opp_' ) then
	elseif tostring(k):match( '^%s*pos_' ) then
	elseif tostring(k):match( '^%s*grnd_' ) then
	elseif tostring(k):match( '^%s*res_' ) then
	elseif tostring(k):match( '^%s*posc_' ) then
	elseif tostring(k):match( '^%s*grndc_' ) then
	elseif tostring(k):match( '^%s*resc_' ) then
	elseif tostring(k):match( '^%s*name_' ) then
	elseif tostring(k):match( '^%s*note_' ) then
	elseif tostring(k):match( '^%s*pos[%d]+_rnd[%d]+_colou?r%s*$' ) then
		tracking = tracking .. '[[Category:Pages using sports rbr table with per team and round coloring]]'
	elseif tostring(k):match( '^%s*res[%d]+_rnd[%d]+_colou?r%s*$' ) then
		tracking = tracking .. '[[Category:Pages using sports rbr table with per team and round coloring]]'
	elseif tostring(k):match( '^%s*pos[%d]+_rnd[%d]+_note%s*$' ) then
	elseif tostring(k):match( '^%s*res[%d]+_rnd[%d]+_note%s*$' ) then
	else
		local vlen = mw.ustring.len(k)
		k = mw.ustring.sub(k, 1, (vlen < 25) and vlen or 25) 
		k = mw.ustring.gsub(k, '[^%w\-_ ]', '?')
		preview = preview .. 'Unknown: "' .. k .. '"<br>'
		tracking = tracking .. '[[Category:Pages using sports rbr table with unsupported parameters|' .. k .. ']]'
	end
end

function p.table(frame)
	local getArgs = require('Module:Arguments').getArgs
	local yesno = require('Module:Yesno')
	args = getArgs(frame, {wrappers = {'Template:Sports rbr table'}})
	
	local style_def = args['style']
	local p_style = require(modname)
	if style_def ~= nil then p_style = require(modname .. '/' .. style_def) end
	
	args = p_style.defaults(args,yesno,color_map)
	
	local rounds = tonumber(args['rounds'] or '0') or 0
	local firstround = tonumber(args['firstround'] or 1) or 1
	local sortable = yesno(args['sortable'] or 'no')
	local updated = args['updated'] or args['update']
	local source = args['source']
	local notes = args['notes']
	local delimiter = args['delimiter'] or '/'
	local addlegend = nil
	local legendpos = (args['legendpos'] or 'tr'):lower()
	local header, footer, prenotes  = '', '', ''
	
	-- Lowercase two labels --
	labels['complete'] = string.lower(labels['complete'])
	labels['future'] = string.lower(labels['future'])

	-- Adjust rounds
	rounds = rounds - (firstround - 1)
	
	-- Tracking
	if updated and updated:match(' %d%d%d%d$') then
		local YY = mw.ustring.gsub(updated, '^.*(%d%d)$', '%1')
		local pn = frame:getParent():getTitle() or ''
		if pn:match('^User:') or pn:match('^User talk:') or pn:match('^Draft:') or pn:match('^Talk:') then
		else
			if pn:match('%d%d' .. YY) or pn:match('[–%-]' .. YY) then
			else
				tracking = tracking .. '[[Category:Pages using sports rbr table with dubious updated parameter]]'
			end
		end
    end
	-- Require a source
	if source == nil then
		source = frame:expandTemplate{ title = 'citation needed', args = { reason='No source parameter defined', date=args['date'] or os.date('%B %Y') } }
	elseif source and source:match('[^%[]#') then 
		if source:match('eason#') or source:match('%d%d#') then
			tracking = tracking .. '[[Category:Pages using sports rbr table with an unusual source]]'
		elseif source:match('^[Hh][Tt][Tt][Pp]') then
			tracking = tracking .. '[[Category:Pages using sports rbr table with an unusual source|Φ]]'
		end
	end
	
	-- Process team, pos, and color args
	local team_list = {}
	local maxrounds = 0
	local rowlength = {}
	for k, v in pairs( args ) do
		check_arg(k, p_style)
		-- Preprocess ranges
		if tostring(k):match( '^%s*text_?(.-)%s*$' ) then
			k = pad_key(k)
		end
		if tostring(k):match( '^%s*colou?r_?(.-)%s*$' ) then
			k = pad_key(k)
		end

		-- Create the list of teams and count rounds
		local i = tonumber(
				tostring(k):match( '^%s*team([%d]+)%s*$' ) or
				tostring(k):match( '^%s*label([%d]+)%s*$' ) or '0'
				)
		if ( i > 0 and isnotempty(v) ) then
			table.insert(team_list, i)
			local p = p_style.get_argvalues_for_maxround(args,i)
			if args['name_' .. v] then
				local t = args['team' .. i] or args['label' .. i] or ''
				p = p_style.get_argvalues_for_maxround(args,t,'_')
			end
			local pos = mw.text.split(escapetag(p), '%s*' .. delimiter .. '%s*')
			table.insert(rowlength, #pos)
			maxrounds = (#pos > maxrounds) and #pos or maxrounds
			-- maxrounds = p_style.get_maxrounds(args,team_list,i,v,rowlength,maxrounds,delimiter)
		end
		-- Create the list of colors
		local s = tostring(k):match( '^%s*colou?r_?(.-)%s*$' )
		if ( s and isnotempty(v) ) then
			colorlist[s] = v:lower()
		end
		-- Check if we are adding a legend
		s = tostring(k):match( '^%s*text_?(.-)%s*$' )
		if ( s and isnotempty(v) ) then
			textlist[s] = v
			addlegend = 1
		end
	end
	
	maxrounds = p_style.get_rounds_or_maxrounds(rounds,maxrounds,args,team_list)
	
	table.sort(rowlength)
	for k=2,#rowlength do
		if rowlength[k] ~= rowlength[k-1] then
			tracking = tracking .. '[[Category:Pages using sports rbr table with unequal row lengths|k]]'
		end
	end

	-- sort the teams
	table.sort(team_list)

	local fs = 95
	if ((maxrounds - firstround) > 37 ) then
		fs = fs - 2*(maxrounds - firstround - 37)
		fs = (fs < 80) and 80 or fs
	end

	-- Build the table
	local root = mw.html.create('table')
	root:addClass('wikitable')
	root:addClass(sortable and 'sortable' or nil)
	root:addClass('sportsrbrtable')
	root:css('font-size', fs .. '%')

	if args['title'] then
		root:tag('caption'):wikitext(args['title'])
	end

	local navbar = ''
	if args['template_name'] then
		navbar = '<br />' .. frame:expandTemplate{ title = 'navbar', args = { mini=1, style='', brackets=1, args['template_name']}}
		-- remove the next part if https://en.wikipedia.org/w/index.php?oldid=832717047#Sortable_link_disables_navbar_links?
		-- is ever fixed
		if sortable then
			navbar = mw.ustring.gsub(navbar, '<%/?abbr[^<>]*>', ' ')
		end
	end
	
	-- Heading row
	local row = p_style.header(root,args,labels,maxrounds,navbar,team_list,firstround)

	-- Team positions
	local prefixes = {'pos', 'res', 'grnd'}
	for k=1,#team_list do
		local i = team_list[k]
		local t = args['team' .. i] or args['label' .. i] or ''
		local o = args['opp' .. i] or ''
		local n = args['note' .. i] or ''
		local efnname = 'note' .. i
		local suf = i
		if args['name_' .. t] then
			o = args['opp_' .. t] or ''
			n = args['note_' .. t] or ''
			efnname = 'note' .. t
			suf = '_' .. t
			t = args['name_' .. t]
		end

		if n ~= '' then
			if args['note_' .. n] then 
				n = frame:expandTemplate{ title = 'efn', args = { name='note' .. n, ''} }
			else
				n = frame:expandTemplate{ title = 'efn', args = { name=efnname, n} }
			end
			hasnotes = true
		end
		
		local resfound = (args['grnd' .. i] and 1 or 0) + (args['pos' .. i] and 1 or 0) + (args['res' .. i] and 1 or 0)
		if args['name_' .. t] then
			resfound = (args['grnd_' .. t] and 1 or 0) + (args['pos_' .. t] and 1 or 0) + (args['res_' .. t] and 1 or 0)
		end
		if (resfound > 1) then
			tracking = tracking .. '[[Category:Pages using sports rbr table with conflicting parameters]]'
		end
		local rowsdisp = 0
		for subrow,lbl in ipairs(prefixes) do
			local p = args[lbl .. suf] or ''
			local pc = args[lbl .. 'c' .. suf] or ''
			if p ~= '' or (rowsdisp == 0 and subrow == 3) then
				rowsdisp = rowsdisp + 1
				row = root:tag('tr')
				row:tag('th')
					:addClass(args['team' .. i] and 'sportsrbrtable-team' or 'sportsrbrtable-lbl')
					:css('text-align', args['labelalign'])
					:css('white-space', args['labelnowrap'] and 'nowrap' or nil)
					:attr('scope', 'row')
					:wikitext(mw.ustring.gsub(t,'^%s*%-%s*$', '&nbsp;') .. n)
				if t:match('<%s*[Cc][Ee][Nn][Tt][Ee][Rr]%s*>') then
					tracking = tracking .. '[[Category:Pages using sports rbr table with unsupported parameters|χ]]'
				end
				local opp = mw.text.split(escapetag(o), '%s*' .. delimiter .. '%s*')
				local pos = mw.text.split(escapetag(p), '%s*' .. delimiter .. '%s*')
				local clr = mw.text.split(escapetag(pc), '%s*' .. delimiter .. '%s*')
				for r=1,maxrounds do
					local s = args['team' .. i .. '_rnd' .. r .. '_' .. 'color'] or
						args['team' .. i .. '_rnd' .. r .. '_' .. 'colour'] or
						args[lbl .. i .. '_rnd' .. r .. '_' .. 'color'] or
						args[lbl .. i .. '_rnd' .. r .. '_' .. 'colour'] or nil
					local n = args['team' .. i .. '_rnd' .. r .. '_' .. 'note'] or
						args[lbl .. i .. '_rnd' .. r .. '_' .. 'note'] or nil
					if s then s = color_map[s] or s end
					local opprt, posrt = unescapetag(opp[r] or ''), unescapetag(pos[r] or '')
					local posrc = isnotempty(clr[r]) and clr[r] or posrt

					if posrt:match('^%s*<[Uu]>[%d–]+[A-Za-z][A-Za-z0-9]*') then
						posrc = posrc:match('^%s*<[Uu]>[%d–]+([A-Za-z][A-Za-z0-9]*)')
						posrt = mw.ustring.gsub(posrt, '^%s*(<[Uu]>[%d–]+)[A-Za-z][A-Za-z0-9]*', '%1')
					elseif posrt:match('^%s*[%d–]+[A-Za-z][A-Za-z0-9]*') then
						posrc = posrc:match('^%s*[%d–]+([A-Za-z][A-Za-z0-9]*)')
						posrt = mw.ustring.gsub(posrt, '^%s*([%d–]+)[A-Za-z][A-Za-z0-9]*', '%1')
					end
			
					local ds
					if args['sortable'] and (opprt or posrt):match('^%s*[%d]+[^%d%s]') then
						ds = mw.ustring.gsub(opprt or posrt, '^%s*([%d]+)[^%d%s].*$', '%1')
					end

					if n then
						if args['note_' .. n] then
							n = frame:expandTemplate{ title = 'efn', args = { name='note' .. n, args['note_' .. n]} }
						else
							n = frame:expandTemplate{ title = 'efn', args = { name='note' .. i .. '_rnd_' .. r, n} }
						end
						hasnotes = true
					end
		
					row:tag('td')
						:attr('data-sort-value', ds)
						:css('background-color', s or get_color(p_style.rowbg(posrc, opprt)))
						:wikitext(p_style.rowtext(frame,args,legend_symbols,posrt,opprt) .. (n or ''))
				end
				if args['split' .. i] and k ~= #team_list then
					row = root:tag('tr')
						:css('background-color', '#BBBBBB')
						:css('line-height', '3pt')
					row:tag('td')
						:attr('colspan', maxrounds + 1)
				end
			end
		end
	end

	-- build the legend
	if addlegend then
		-- Sort the keys for the legend
		local legendkeys = {}
		for k,v in pairs( textlist ) do
			table.insert(legendkeys, k)
		end
		table.sort(legendkeys)

		if args['legendorder'] then
			legendkeys = mw.text.split(args['legendorder'] .. delimiter ..
				table.concat(legend_order_default, delimiter) .. delimiter ..
				table.concat(legendkeys, delimiter), '%s*' .. delimiter .. '%s*')
		else
			legendkeys = mw.text.split(
				table.concat(legend_order_default, delimiter) .. delimiter ..
				table.concat(legendkeys, delimiter), '%s*' .. delimiter .. '%s*')
		end
		local lroot
		if (legendpos == 't' or legendpos == 'b') then
			lroot = mw.html.create('')
			local firsttag = true
			for k,v in pairs( legendkeys ) do
				if v and textlist[v] then
					if firsttag == false then lroot:wikitext('; ') end
					local c = colorlist[v] or ''
					local l = lroot:tag('span')
						:css('margin', '0')
						:css('white-space', 'nowrap')
						:tag('span')
							:addClass('legend-text')
							:css('border', 'none')
							:css('padding', '1px .3em')
							:css('background-color', color_map[c] or c)
							:css('font-size', '95%')
							:css('border', '1px solid #BBB')
							:css('line-height', '1.25')
							:css('text-align', 'center')
							:wikitext(p_style.legendtext(legend_symbols,v))
							:done()
						:wikitext(' = ' .. textlist[v])
					textlist[v] = nil
					firsttag = false
				end
			end
		else
			lroot = mw.html.create('table')
			if legendpos == 'tl' or legendpos == 'bl' then
				lroot:addClass('wikitable')
				lroot:css('font-size', '88%')
			else
				lroot:addClass('infobox')
				lroot:addClass('bordered')
				-- lroot:css('width', 'auto')
			end
			for k,v in pairs( legendkeys ) do
				if v and textlist[v] then
					local c = colorlist[v] or ''
					local row = (legendpos == 'tl' or legendpos == 'bl') and lroot or lroot:tag('tr')
					local l = row:tag('th'):css('background-color', color_map[c] or c)
					if legend_symbols[v] then
						l:css('font-weight', 'normal')
							:css('padding', '1px 3px')
							:wikitext(legend_symbols[v])
					else
						l:css('width', '10px')
					end
					row:tag('td')
						:css('padding', '1px 3px')
						:wikitext(textlist[v])
					textlist[v] = nil
				end
			end
		end
		if (legendpos == 'bl' or legendpos == 'br') then
			footer = footer .. tostring(lroot)
		elseif (legendpos == 'b') then
			prenotes = prenotes .. tostring(lroot)
		elseif (legendpos == 't') then
			args['toptext'] = (args['toptext'] or '')
				.. frame:expandTemplate{ title = 'refbegin' }
				.. tostring(lroot)
				.. frame:expandTemplate{ title = 'refend' }

		else
			header = header .. tostring(lroot)
		end
	end

	-- simplify updated == complete case
	local lupdated = updated and string.lower(updated) or ''
	if lupdated == labels['complete'] or lupdated == 'complete' then
		lupdated = ''
	end

	-- add note list
	if hasnotes then
		footer = footer .. frame:expandTemplate{ title = 'notelist' }
	end
	
	-- build the footer	
	if prenotes ~= '' or notes or source or lupdated ~= '' then
		footer = footer .. frame:expandTemplate{ title = 'refbegin' }
		if lupdated ~= '' then
			local mtext = args['matches_text'] or labels['matches']
			if lupdated == labels['future'] or lupdated == 'future' then
				footer = footer .. matches_date(labels['firstplayed'] .. ' ',
					mtext, args['start_date'] or labels['futuredate'])
			else
				footer = footer .. matches_date(labels['updatedto'] .. ' ',
					mtext, updated)
			end
		end
		if source then
			footer = footer .. labels['source'] .. ' ' .. source
		end
		if prenotes ~= '' then
			if lupdated ~= '' or source then
				footer = footer .. '<br>'
			end
			footer = footer .. prenotes
		end
		if notes then
			if prenotes ~= '' or lupdated ~= '' or source then
				footer = footer .. '<br>'
			end
			footer = footer .. labels['notes'] .. ' ' .. notes
		end
		footer = footer .. frame:expandTemplate{ title = 'refend' }
	end
	-- add clear right for the legend if necessary
	footer = footer .. ((addlegend and (legendpos == 'bl' or legendpos == 'br'))
		and '<div style="clear:right"></div>' or '')
	if tracking ~= '' then
		if frame:preprocess( "{{REVISIONID}}" ) == "" then
			tracking = preview
		end
	end
	return frame:extensionTag{ name = 'templatestyles', args = { src = templatestyles} }
		.. header .. (args['toptext'] or '') .. '<div style="overflow:hidden">'
		.. '<div class="noresize overflowbugx" style="overflow:auto">'
		.. tostring(root) .. '</div></div>' .. footer .. tracking
end

function p.get_argvalues_for_maxround(args, x, del)
	del = del or ''
	return args['pos' .. del .. x] or args['res' .. del .. x] or ''
end

function p.get_rounds_or_maxrounds(rounds, maxrounds)
	return (rounds > maxrounds) and rounds or maxrounds
end

function p.addtl_args(k)
	-- just return 'true', no additional args
	return true
end

function p.defaults(args)
	-- set nothing
	return args
end

function p.header(root,args,labels,maxrounds,navbar,team_list,firstround)
	local row = root:tag('tr')
	row:tag('th')
		:attr('rowspan', args['sortable'] and 2 or nil)
		:wikitext((args['header'] or labels['teamround']) .. navbar)
	for r=1,maxrounds do
		row:tag('th')
			:addClass(args['sortable'] and 'sportsrbrtable-rnd-sort' or 'sportsrbrtable-rnd')
			:attr('scope', 'col')
			:wikitext(args['rnd' .. (r + (firstround - 1))]
				or (r + (firstround - 1)))
	end
	if args['sortable'] then
		row = root:tag('tr')
		for r=1,maxrounds do
			row:tag('th')
				:addClass('sportsrbrtable-rnd-toggle')
		end
	end
	return row
end

function p.rowtext(frame,args,legend_symbols,posrt,postrc,opprt,opprc)
	return legend_symbols[posrt] or posrt
end

function p.rowbg(posrc)
	return posrc
end

function p.legendtext(legend_symbols,v)
	return legend_symbols[v] or (v:match('^[^%d][^%d]?$') and v) or '&nbsp;'
end

return p