local a = {}  local categories = { 	ignored_parameters = , 	missing_results = , 	missing_teams = , 	orphaned_match_notes = , 	orphaned_names = , 	orphaned_notes = , 	orphaned_results = , 	possible_incorrect_winpoints = , 	possibly_ignored_parameters = , 	unknown_parameters = 'বিষয়শ্রেণী:অজানা প্যারামিটারসহ ক্রীড়া ছক ব্যবহার করা পাতা' }  local good_args = { 	['away_goals_header'] = 1, 	['bonus_header'] = 1, 	['class_rules'] = 1, 	['draw_header'] = 1, 	['drawpoints'] = 1, 	['float'] = 1, 	['for_against_style'] = 1, 	['GB_team'] = 1, 	['goalpoints'] = 1, 	['group_header'] = 1, 	['hide_footer'] = 1, 	['hide_for_against_columns'] = 1, 	['hide_played'] = 1, 	['hide_results'] = 1, 	['highest_pos'] = 1, 	['legs'] = 1, 	['loss_before_draw'] = 1, 	['loss_before_tie'] = 1, 	['losspoints'] = 1, 	['lowest_pos'] = 1, 	['matches_style'] = 1, 	['matches_text'] = 1, 	['match_col_width'] = 1, 	['note_header_res'] = 1, 	['only_pld_pts'] = 1, 	['only_totals'] = 1, 	['only_fa_totals'] = 1, 	['pct_style'] = 1, 	['pld_header'] = 1, 	['postitle'] = 1, 	['perc_first'] = 1, 	['pts_first'] = 1, 	['ranking_style'] = 1, 	['res_col_header'] = 1, 	['result_prefix'] = 1, 	['rwpoints'] = 1, 	['rw_header'] = 1, 	['section'] = 1, 	['short_style'] = 1, 	['show_GB'] = 1, 	['show_away_goals'] = 1, 	['show_bonus_points'] = 1, 	['show_class_rules'] = 1, 	['show_draw'] = 1, 	['show_groups'] = 1, 	['show_limit'] = 1, 	['show_matches'] = 1, 	['show_positions'] = 1, 	['show_rw'] = 1, 	['show_status'] = 1, 	['show_totals'] = 1, 	['solid_cell'] = 1, 	['sortable_table'] = 1, 	['source'] = 1, 	['start_date'] = 1, 	['stack_footer'] = 1, 	['status_order'] = 1, 	['status_pos'] = 1, 	['style'] = 1, 	['table_header'] = 1, 	['table_header_source'] = 1, 	['team_header'] = 1, 	['team_order'] = 1, 	['team_order_start'] = 1, 	['teamwidth'] = 1, 	['title'] = 1, 	['title_source'] = 1, 	['transcludesection'] = 1, 	['update'] = 1, 	['use_against_percentage'] = 1, 	['use_goal_average'] = 1, 	['use_goal_diff'] = 1, 	['use_goal_percentage'] = 1, 	['use_goal_ratio'] = 1, 	['use_goals_scored'] = 1, 	['use_point_percentage'] = 1, 	['use_goals_per_match'] = 1, 	['use_points_per_match'] = 1, 	['use_tie'] = 1, 	['winpoints'] = 1, }  local good_args_HA = { 	['ha_side'] = 1, 	['hdrawpoints'] = 1, 	['adrawpoints'] = 1, 	['hlosspoints'] = 1, 	['alosspoints'] = 1, 	['hwinpoints'] = 1, 	['awinpoints'] = 1 }  local good_args_PKOT = { 	['showOTloss'] = 1, 	['showOTwin'] = 1, 	['showPKloss'] = 1, 	['showSOloss'] = 1, 	['showPKwin'] = 1, 	['showSOwin'] = 1, 	['show_tiebr'] = 1, 	['PKlosspoints'] = 1, 	['SOlosspoints'] = 1, 	['OTlosspoints'] = 1, 	['PKwinpoints'] = 1, 	['SOwinpoints'] = 1, 	['OTwinpoints'] = 1, 	['PKloss_after_loss'] = 1, 	['SOloss_after_loss'] = 1, 	['OTloss_after_loss'] = 1, 	['tiebr_header'] = 1, }  local good_args_BDT = { 	['drawpoints'] = 0, 	['game_for_against_style'] = 1, 	['point_for_against_style'] = 1 }  local good_args_VB = { 	['winpoints'] = 0, 	['losspoints'] = 0, 	['drawpoints'] = 0, 	['bwinpoints'] = 1, 	['blosspoints'] = 1, 	['swinpoints'] = 1, 	['slosspoints'] = 1, 	['win3points'] = 1, 	['loss3points'] = 1, 	['win4points'] = 1, 	['loss4points'] = 1, 	['win5points'] = 1, 	['loss5points'] = 1, 	['show_sets'] = 1, 	['show_setpoints'] = 1, 	['setpoints_before_sets'] = 1, 	['best_of'] = 1 }  local ignored_args = { 	['date'] = 1, 	['ptsfirst'] = 1 }  local col_names = { 	['adjust_points'] = 1, 	['away_goals'] = 1, 	['draw'] = 1, 	['loss'] = 1, 	['gf'] = 1, 	['ga'] = 1, 	['group'] = 1, 	['pf'] = 1, 	['pa'] = 1, 	['matches'] = 1, 	['pos'] = 1, 	['rw'] = 1, 	['short'] = 1, 	['startpoints'] = 1, 	['status'] = 1, 	['win'] = 1, }  local col_names_HA = { 	['draw'] = 0, 	['loss'] = 0, 	['gf'] = 0, 	['ga'] = 0, 	['pf'] = 0, 	['pa'] = 0, 	['rw'] = 0, 	['hdraw'] = 1, 	['adraw'] = 1, 	['hloss'] = 1, 	['aloss'] = 1, 	['hwin'] = 1, 	['awin'] = 1, 	['hga'] = 1, 	['aga'] = 1, 	['hgf'] = 1, 	['agf'] = 1, 	['hpa'] = 1, 	['apa'] = 1, 	['hpf'] = 1, 	['apf'] = 1, }  local col_names_PKOT = { 	['PKloss'] = 1, 	['SOloss'] = 1, 	['OTloss'] = 1, 	['PKwin'] = 1, 	['SOwin'] = 1, 	['OTwin'] = 1, 	['tiebr'] = 1 }  local col_names_BDT = { 	['win'] = 1, 	['loss'] = 1, 	['mf'] = 1, 	['ma'] = 1, 	['gf'] = 1, 	['ga'] = 1, 	['pf'] = 1, 	['pa'] = 1 }  local col_names_VB = { 	['win'] = 0, 	['loss'] = 0, 	['draw'] = 0, 	['bwin'] = 1, 	['swin'] = 1, 	['bloss'] = 1, 	['sloss'] = 1, 	['sw'] = 1, 	['sl'] = 1, 	['spw'] = 1, 	['spl'] = 1, 	['win3s'] = 1, 	['loss3s'] = 1, 	['win4s'] = 1, 	['loss4s'] = 1, 	['win5s'] = 1, 	['loss5s'] = 1, }  local tracked_styles = { 	['football'] = 'জয়-ড্র-হার', 	['WDL'] = 'জয়-ড্র-হার', 	['WL'] = 'জয়-ড্র-হার', 	['ফুটবল'] = 'জয়-ড্র-হার', 	['জয়-ড্র-হার'] = 'জয়-ড্র-হার', 	['WDLHA'] = 'HA', 	['WDL OT'] = 'PKOT', 	['WLHA'] = 'HA', 	['WL OT'] = 'PKOT', 	['WL PK'] = 'PKOT', 	['WL OTL tiebreak'] = 'PKOT', 	['Volleyball'] = 'VB', 	['Badminton team'] = 'BDT' }  local warn = {} local track = {}  local function get_tracking_category(category, value) 	return '' .. value .. '' end  local function validate_table_values(args, category, bad_char, is_track) 	for _, v in ipairs(args) do 		v = mw.ustring.gsub(v, bad_char, '?') 		if v ==  then 			v = ' ' 		end 		if is_track then 			table.insert(track, get_tracking_category(category, v)) 		else 			table.insert(warn, get_tracking_category(category, v)) 		end 	end end  function a.check(targs, pargs) 	local teams = {} 	local missing_teams = {} 	local results = {} 	local missing_results = {} 	local orphaned_match_notes = {} 	local orphaned_results = {} 	local orphaned_names = {} 	local orphaned_notes = {} 	local ignored = {} 	local possibly_ignored = {} 	local unknown = {} 	 	local mstyle = mw.ustring.gsub(targs['style'] or , '[%s_][%s_]*', ' ') 	mstyle = tracked_styles[mstyle] 	 	if mstyle == nil then 		return warn, track 	end 	 	if mstyle == 'HA' then 		for k, v in pairs(good_args_HA) do 			good_args[k] = v ~= 0 and v or nil 		end 		for k, v in pairs(col_names_HA) do 			col_names[k] = v ~= 0 and v or nil 		end 		if targs['only_fa_totals'] then 			col_names['pf'] = 1 			col_names['gf'] = 1 			col_names['pa'] = 1 			col_names['ga'] = 1 		end 	end 	 	if mstyle == 'PKOT' then 		for k, v in pairs(good_args_PKOT) do 			good_args[k] = v ~= 0 and v or nil 		end 		for k, v in pairs(col_names_PKOT) do 			col_names[k] = v ~= 0 and v or nil 		end 	end 	 	if mstyle == 'BDT' then 		for k, v in pairs(good_args_BDT) do 			good_args[k] = v ~= 0 and v or nil 		end 		for k, v in pairs(col_names_BDT) do 			col_names[k] = v ~= 0 and v or nil 		end 	end 	 	if mstyle == 'VB' then 		for k, v in pairs(good_args_VB) do 			good_args[k] = v ~= 0 and v or nil 		end 		for k, v in pairs(col_names_VB) do 			col_names[k] = v ~= 0 and v or nil 		end 	end 	 	-- Alternative syntax for team list 	if targs['team_order'] and targs['team_order'] ~=  then 		local tlist = mw.text.split(targs['team_order'], '%s*[;,]%s*') 		for k, tname in ipairs(tlist) do 			if tname ~=  then 				targs['team' .. k] = tname 			end 		end 	end 	 	-- Limited tracking if we are only showing part of the table 	if targs['showteam'] then 		local top_pos = tonumber(targs['highest_pos']) or 1 		local bottom_pos = tonumber(targs['lowest_pos']) or 0 		local N = top_pos - 1 		while targs['team' .. N + 1] ~= nil and (bottom_pos < top_pos or N < bottom_pos) do 			N = N + 1 			teams[targs['team' .. N]] = 1 			if teams[targs['showteam']] then 				return warn, track 			end 		end 	end  	-- Step 1: Generate a team and result list 	for k,v in pairs(targs) do 		if type(k) == 'string' then 			if k:find('^team%d%d*$') then 				teams[v] = 1 				targs[k] =  				if targs['name_' .. v] then 					-- Great! 					targs['name_' .. v] = 				else 					table.insert(missing_teams, v) 				end 				if targs['note_' .. v] then 					targs['note_' .. v] =  				end 				if targs['hth_' .. v] then 					local multiref = 1 					local hth_local_table = mw.text.split(targs['hth_' .. v], '%s*,%s*') 					if (#hth_local_table > 1) then 						for _, hth_loc in ipairs(hth_local_table) do 							multiref = multiref * (targs['hth_' .. hth_loc] and 1 or 0) 						end 					else 						multiref = 0 					end 					if multiref > 0 then 						for _, hth_loc in ipairs(hth_local_table) do 							targs['hth_' .. hth_loc] = 						end 					elseif targs['hth_' .. targs['hth_' .. v]] then 						targs['hth_' .. targs['hth_' .. v]] =  					end 					targs['hth_' .. v] = 				end 			elseif k:find('^result%d%d*$') or k:find('^.*_result%d%d*$') then 				local pre = mw.ustring.gsub(k, '^(.*)result%d%d*$', '%1') 				results[v] = 1 				targs[k] =  				if targs[pre .. 'col_' .. v] or targs[pre .. 'text_' .. v] or targs[pre .. 'note_res_' .. v] then 					-- Great! 					if targs[pre .. 'col_' .. v] then 						targs[pre .. 'col_' .. v] = 					end 					if targs[pre .. 'text_' .. v] then 						targs[pre .. 'text_' .. v] =  					end 					if targs[pre .. 'note_res_' .. v] then 						local multiref = 1 						local note_res_local_table = mw.text.split(targs[pre .. 'note_res_' .. v], '%s*,%s*') 						if (#note_res_local_table > 1) then 							for _, note_res_loc in ipairs(note_res_local_table) do 								multiref = multiref * (targs[pre .. 'note_res_' .. note_res_loc] and 1 or 0) 							end 						else 							multiref = 0 						end 						if multiref > 0 then 							for _, note_res_loc in ipairs(note_res_local_table) do 								targs[pre .. 'note_res_' .. note_res_loc] = 							end 						elseif targs[pre .. 'note_res_' .. targs[pre .. 'note_res_' ..  v]] then 							targs[pre .. 'note_res_' ..  targs[pre .. 'note_res_' ..  v]] =  						end 						targs[pre .. 'note_res_' .. v] = 					end 					if targs[pre .. 'res_col_header'] then 						targs[pre .. 'res_col_header'] =  					end 				else 					table.insert(missing_results, v) 				end 			elseif k:find('^match[%d]*_.*_.*_note$') then 				local m = mw.ustring.gsub(k, '^(match[%d]*_.*_.*)_note$', '%1') 				targs[k] = 				if targs[m] then 					if targs['note_' .. v] then 						targs['note_' .. v] =  					end 					-- Great! 				else 					table.insert(orphaned_match_notes, m) 				end 			end 		end 	end  	local possible_missing_winpoints = 0 	for k,v in pairs(targs) do 		if v and v ~=  then 			local found_arg = 0 			if type(k) == 'string' then 				if k:find('^adjust_points_') then 					local p = mw.ustring.gsub(k, '^adjust_points_', ) 					if (tonumber(v) or 0) ~= 0 then 						local pdiff = (tonumber(targs['win_' .. p] or 0) or 0) + tonumber(v) 						if pdiff == 0 then 							possible_missing_winpoints = possible_missing_winpoints + 1 						else 							possible_missing_winpoints = possible_missing_winpoints - 1 						end 					end 				end 				if found_arg == 0 and (good_args[k] or k:find('^split[%d][%d]*$')) then 					-- Great! 					found_arg = 1 				end 				if found_arg == 0 and k == 'showteam' then 					-- Great! 					found_arg = 1 					if teams[v] ~= 1 then 						table.insert(missing_teams, v) 					end 				end 				if found_arg == 0 and (ignored_args[k] or k:find('^att_')) then 					found_arg = 1 					table.insert(ignored, k) 				end 				if found_arg == 0 and k:find('^[A-Za-z3-5]*_.*$') then 					local p = mw.ustring.gsub(k, '^([A-Za-z3-5]*)_.*$', '%1') 					if col_names[p] then 						-- Great! 						found_arg = 1 					end 				end 				if found_arg == 0 and k:find('^[A-Za-z]*_[A-Za-z]*_.*$') then 					local p = mw.ustring.gsub(k, '^([A-Za-z]*_[A-Za-z]*)_.*$', '%1') 					if col_names[p] then 						-- Great! 						found_arg = 1 					end 				end  				if found_arg == 0 and k:find('^match[%d]*_.*_.*$') then 					local t1 = mw.ustring.gsub(k, '^match[%d]*_(.*)_(.*)$', '%1') 					local t2 = mw.ustring.gsub(k, '^match[%d]*_(.*)_(.*)$', '%2') 					found_arg = 1 					if teams[t1] == nil or teams[t2] == nil then 						if teams[t1] == nil then 							table.insert(missing_teams, t1) 						end 						if teams[t2] == nil then 							table.insert(missing_teams, t2) 						end 					end 				end 				if found_arg == 0 and k:find('^result_.*_.*$') then 					local t1 = mw.ustring.gsub(k, '^result[%d]*_(.*)_(.*)$', '%1') 					local t2 = mw.ustring.gsub(k, '^result[%d]*_(.*)_(.*)$', '%2') 					found_arg = 1 					if teams[t1] == nil or teams[t2] == nil then 						if teams[t1] == nil then 							table.insert(missing_teams, t1) 						end 						if teams[t2] == nil then 							table.insert(missing_teams, t2) 						end 					end 				end 				if found_arg == 0 and (k:find('^name_') or k:find('^short_')) then 					found_arg = 1 					table.insert(orphaned_names, k) 				end 				if found_arg == 0 and (k:find('^note_') or k:find('^hth_')) then 					found_arg = 1 					if (k == 'hth_ABC' and v == 'H2H note') then 						table.insert(warn, get_tracking_category(categories.ignored_parameters , 'hth_ABC')) 					elseif (k == 'note_ABC' and v == 'Team note') then 						table.insert(warn, get_tracking_category(categories.ignored_parameters , 'note_ABC')) 					elseif (k == 'note_res_AAA' and v == 'Result note') then 						table.insert(warn, get_tracking_category(categories.ignored_parameters , 'note_res_AAA')) 					else 						table.insert(orphaned_notes, k) 					end 				end 				if found_arg == 0 and (k:find('^col_') or k:find('^text_')) then 					found_arg = 1 					table.insert(orphaned_results, k) 				end 			end 			if found_arg == 0 then 				if pargs[k] and pargs[k] ~= '' then 					if tonumber(k) then 						k = k .. ' = ' .. v 					end 					table.insert(possibly_ignored, k) 				else 					if tonumber(k) then 						k = k .. ' = ' .. v 					end 					table.insert(unknown, k) 				end 			end 		end 	end  	local bad_char = '[^A-Za-z0-9_%(%)%- ]' 	validate_table_values(unknown, categories.unknown_parameters, bad_char, false) 	validate_table_values(missing_teams, categories.missing_teams, bad_char, false) 	validate_table_values(missing_results, categories.missing_results, bad_char, false) 	validate_table_values(orphaned_results, categories.orphaned_results, bad_char, false) 	validate_table_values(orphaned_names, categories.orphaned_names, '[^A-Za-z0-9_ ]', false) 	validate_table_values(orphaned_notes, categories.orphaned_notes, bad_char, false) 	validate_table_values(orphaned_match_notes, categories.orphaned_match_notes, bad_char, false) 	validate_table_values(ignored, categories.ignored_parameters, bad_char, false) 	validate_table_values(possibly_ignored, categories.possibly_ignored_parameters, bad_char, true)  	if possible_missing_winpoints > 1 then 		table.insert(track, get_tracking_category(categories.possible_incorrect_winpoints, possible_missing_winpoints)) 	end 	 	return warn, track end  return a