มอดูล:Sports table

-- Module to build tables for standings in Sports
-- See documentation for details
require('strict')
local p = {}
-- Main function
function p.main(frame)
	-- Declare locals
	local getArgs = require('มอดูล:Arguments').getArgs
	local Args = getArgs(frame, {parentFirst = true})
	local ii_start, ii_end, N_rows_res = 0
	local text_field_result
	local notes_exist = false
	local t = {}
	local t_footer = {}
	local t_return = {}
	local team_list = {}
	local jj, jjj
	local table_anchor = mw.ustring.gsub(Args'section' and 'sports-table-' .. Args'section' or , ' ', '_')
	
	-- Exit early if we are using section transclusion for a different section
	local tsection = frame:getParent().args'transcludesection' or frame:getParent().args'section' or 
	local bsection = frame.args'section' or 
	if( tsection ~=  and bsection ~=  ) then
		if( tsection ~= bsection ) then
			return 
		end
	end
	local templatestyles = frame:extensionTag{
		name = 'templatestyles', args = { src = 'มอดูล:Sports table/styles.css' }
	}
	
	-- Edit links if requested
	local baselink = frame:getParent():getTitle()
	if baselink == 'มอดูล:Excerpt' then baselink =  end
	if mw.title.getCurrentTitle().fullText == baselink then	baselink =  end
	local template_name = (baselink ~=  and (':' .. baselink .. (table_anchor ~=  and '#' .. table_anchor or )))
		or 
	-- Get the custom start point for the table (most will start by default at 1)
	local top_pos = tonumber(Args'highest_pos') or 1
	-- Get the custom end point for the table (unrestricted if bottom_pos is อันดับ'
	if position_col == false then pos_label = nil end
	
	-- Show status or not
	local show_status = yesno(Args'show_status' or 'yes') and true or false
	-- Get VTE button text (but only for non-empty text)
	local VTE_text = 
	if (template_name ~= ) then
		VTE_text = require('มอดูล:Navbar')._navbar({
			template_name,
			mini=1,
			brackets=1
		})
		
		-- remove the next part if https://en.wikipedia.org/w/index.php?oldid=832717047#Sortable_link_disables_navbar_links?
		-- is ever fixed
		if yesno(Args'sortable_table' or 'no') then
			VTE_text = mw.ustring.gsub(VTE_text, '*>', ' ')
		end
	end
	
	-- Add source to title if specified and possible
	local title_source = false
	if Args'title' and Args'title_source' then
		Args'title' = Args'title' .. Args'title_source'
		title_source = true
	elseif Args'table_header' and Args'table_header_source' then
		Args'table_header' = Args'table_header' .. Args'table_header_source'
		title_source = true
	end
	-- Add a table anchor
	if table_anchor ~=  then
		table.insert(t, '\n')
	end
	-- Write column headers
	t_return = p_style.header(t,Args,p_sub,pos_label,group_col,VTE_text,full_table,results_header_txt)
	if match_table then
		-- Add empty column header
		t_return.count = t_return.count+1
		table.insert(t_return.tab_text,'! scope="row" class="unsortable" style="background-color:white;border-top:white;border-bottom:white;line-width:3pt;"| \n')
		
		-- Add rest of header
		t_return = p_matches.header(t_return,Args,p_sub,N_teams,team_list,tonumber(Args'legs') or 1)
	end
	t = t_return.tab_text
	local N_cols = t_return.count
	
	-- Determine what entries go into table
	-- Find out which team to show (if any)
	local ii_show = team_listArgs'showteam' or nil -- nil if non-existant
	-- Start and end positions to show
	local n_to_show = tonumber(Args'show_limit') or N_teams
	-- Check for "legal value", if not legal (or non declared), then show all
	local check_n = ((n_to_show>=(N_teams-top_pos+1)) or (n_to_show=(N_teams+1-n_show_side) then
			-- Bottom team
			ii_start = N_teams+1-n_to_show
			ii_end = N_teams
		else
			-- Normal case
			ii_start = ii_show-n_show_side
			ii_end = ii_show+n_show_side
		end
	end
	
	-- For results column
	local new_res_ii = ii_start
	-- Pre-check for existence of column
	if not hide_results then
		for ii = ii_start, ii_end do
			if Argsrespre..'result'..ii and Argsrespre..'text_' .. Argsrespre..'result'..ii then results_defined = true end
		end
	end
	-- Remove results header if it is unused
	if full_table and not results_defined then
		-- First get it as one string, then use string replace to replace that header by empty string
		local t_str = tostring(table.concat(t))
		t_str = mw.ustring.gsub( t_str, results_header_txt,  )
		N_cols = N_cols-1 -- There is actually one column less
		t = {}
		table.insert(t, t_str)
	end
	
	-- Write rows
	local team_name, team_code_ii, team_code_jj, pos_num, group_txt, note_local
	local note_string, note_local, note_local_num, note_id
	local note_id_list = {}
	local hth_id_list = {}
	for ii = ii_start, ii_end do
		-- First get code
		team_code_ii = team_listii
		-- Now read values
		pos_num = Args'pos_'..team_code_ii			or ii
		group_txt = Args'group_'..team_code_ii		or ' '
		team_name = Args'name_'..team_code_ii		 	or team_code_ii
		note_local = Args'note_'..team_code_ii 		or nil
		
		-- Does it need a promotion/qualification/relegation tag
		local result_local = Argsrespre..'result'..ii or nil
		local bg_col = nil
		-- Get local background colour
		if result_local then
			bg_col = result_colArgsrespre..'col_'..result_local or Argsrespre..'col_'..result_local or 'inherit'
if bg_col == 'inherit' then bg_col = bg_col .. '; color: inherit' end
			bg_col = 'background-color:'..bg_col..';' 	-- Full style tag
		end
		if not bg_col then bg_col = 'background-color:transparent; color: inherit;' end -- Becomes default if undefined
		
		-- Bold this line or not
		local ii_fw = ii == ii_show and 'font-weight: bold;' or 'font-weight: normal;'
		if yesno(Args'show_totals' or 'no') and team_code_ii == total_row_name then
			ii_fw = 'font-weight: bold;'
		end
		
		-- Check whether there is a note or not, if so get text ready for it
		if note_local and full_table then
			-- Set global check for notes to true
			notes_exist = true
			-- There are now 3 options for notes
			-- 1) It is a full note
			-- 2) It is a referal to another note (i.e. it's just a team code; e.g. note_AAA=Text, note_BBB=AAA) in which the note for BBB should link to the same footnote as AAA, with
			-- 2a) The other linked note exist in the part of the table shown
			-- 2b) The part of the note does not exist in the part of the table shown
			if not Args'note_'..note_local then
				-- Option 1
				-- Now define the identifier for this
				note_id = '"table_note_'..team_code_ii..rand_val..'"' -- Add random end for unique ID if more tables are present on article (which might otherwise share an ID)
				note_id_listteam_code_ii = note_id
				
				-- Call refn template
				note_string = frame:expandTemplate{ title = 'efn', args = { group='lower-alpha',  name=note_id, note_local} }
			else 
				-- Option 2
				-- It is option 2a in either one if either the main note is inside the sub-table
				--                                  or another ref to that note is inside the sub-table
				-- Basically when it either has been defined, or the main link will be in the table
				note_local_num = team_listnote_local
				if note_id_listnote_local or ((note_local_num >= ii_start) and (note_local_num '..string.lower(status_string)..' – ' 
				else
					status_string = ' ('..status_string..')' 
				end
			end
		end
		
		-- Now build the rows
		if yesno(Args'show_totals' or 'no') and team_code_ii == total_row_name then
			table.insert(t,'
		else
			table.insert(t,'
		end
		if position_col then
			table.insert(t,'| style="text-align: center;'..ii_fw..bg_col..'"| '..pos_num..'\n')	-- Position number
		end
		if full_table and group_col then
			table.insert(t,'| style="'..ii_fw..bg_col..'" |'..group_txt..'\n') 							-- Group number/name
		end
		-- Build the team string order based on status position
		local team_string
		if t_status.position == 'before' then
			team_string = status_string..team_name..note_string
		else
			team_string = team_name..note_string..status_string
		end
		table.insert(t,'! scope="row" style="text-align: left; white-space:nowrap;'..ii_fw..bg_col..'"| '..team_string..'\n')-- Team (with possible note)
		-- Call to subfunction
		t_return = p_style.row(frame,t,Args,p_sub,notes_exist,hth_id_list,full_table,rand_val,team_list,team_code_ii,ii_start,ii_end,ii_fw,bg_col,N_teams,ii,ii_show)
		t = t_return.t
		notes_exist = t_return.notes_exist
		hth_id_list = t_return.hth_id_list
		
		-- Now check what needs to be added inside the results column
		if full_table then
			local res_jjj
			if ii == new_res_ii then
				-- First check how many rows you need for this
				N_rows_res = 1
				jjj = ii+1
				result_local = Argsrespre..'result'..ii or 
				local cont_loop = true
				while (jjj=ii) and (ii_show 1) then
						for k, note_res_loc in ipairs(note_res_local_table) do
							multiref = multiref * (Args'note_res_' .. note_res_loc and 1 or 0)
						end
					else
						multiref = 0
					end
					-- Split failed, so make a single entry table with hth_local inside
					if multiref = ii_start) and (note_local_num '
	
	if footer_break and (not (string.lower(update)=='complete')) and not hide_footer then table.insert(t_footer,stack_string) end
	
	if source ~=  and not hide_footer then
		table.insert(t_footer,'แหล่งข้อมูล: '..source)
	end
	if class_rules and full_table and show_class_rules and not hide_footer then
		if (#t_footer > 0) then table.insert(t_footer,) end
		table.insert(t_footer,'กฏการจัดอันดับ: '..class_rules)
	end
	
	-- Now for the named status
	local status_exist = false
	local status_string = 
	local curr_letter
	for jjj = 1,mw.ustring.len(t_status.letters) do
		curr_letter = mw.ustring.upper(mw.ustring.sub(t_status.letters,jjj,jjj))
		if t_status.calledcurr_letter then
			if (footer_break and status_exist) then
				status_string = status_string..stack_string
			end
			if t_status.position == 'before' then
				status_string = status_string....string.lower(curr_letter)..' – '..t_status.codecurr_letter..'; '
			else
				status_string = status_string..'('..curr_letter..') '..t_status.codecurr_letter..'; '
			end
			status_exist = true
		end
	end
	-- Now if it contains entries the '; ' needs to be removed
	if status_exist and not hide_footer then
		if (#t_footer > 0) then table.insert(t_footer,) end
		status_string = mw.ustring.sub(status_string,1,mw.ustring.len(status_string)-2)
		table.insert(t_footer,status_string)
	end
	
	-- Add notes (if applicable)
	if notes_exist then
		if (#t_footer > 0) then table.insert(t_footer,) end
		table.insert(t_footer,'หมายเหตุ:')
		-- As reflist size text
		t_footer = ..table.concat(t_footer)..
		t_footer = t_footer..frame:expandTemplate{ title = 'notelist', args = { group='lower-alpha'} }
	else
		-- As reflist size text
		t_footer = ..table.concat(t_footer)..
	end
	
	-- Add footer to main text table
	table.insert(t,t_footer)
	
	-- Rewrite anchor links
	for k=1,#t do
		if tk:match('%%#^%%*%|') then
			tk = mw.ustring.gsub(tk, '(%%)(#^%%*%|)', '%1' .. baselink .. '%2')
		end
	end
	
	-- Generate tracking
	if not Args'notracking' then
		local getTracking = require('มอดูล:Sports table/argcheck').check
		local warning_categories, tracking_categories = getTracking(Args, frame:getParent().args)
		if #warning_categories > 0 then
			if frame:preprocess( "" ) == "" then
				for k=1,#warning_categories do
					warning_categoriesk = mw.ustring.gsub(warning_categoriesk, '^%%(.*)%%$', 'Warning: %1 = %2')
				end
			end
		end
		for k=1,#warning_categories do
				table.insert(t, warning_categoriesk)
		end
		for k=1,#tracking_categories do
				table.insert(t, tracking_categoriesk)
		end
		
		if(Args'showteam' == nil) then
			local getWarnings = require('มอดูล:Sports table/totalscheck').check
			local total_warnings = getWarnings(Args, team_list, ii_start, ii_end)
			if #total_warnings > 0 then
				if frame:preprocess( "" ) == "" then
					for k=1,#total_warnings do
						table.insert(t, 'ปัญหาที่อาจเกิดขึ้น: ' .. total_warningsk .. )
					end
				end
			end
		end
	else
		table.insert(t, 'หมวดหมู่:หน้าที่ใช้ตารางกีฬาโดยไม่ติดตาม')
	end
	
	if Args'float' then
		return frame:expandTemplate{ title = 'stack begin', args = {clear = 'true', margin = '1', float = Args'float'} }
			.. templatestyles .. '\n' .. table.concat(t) .. frame:expandTemplate{ title = 'stack end'}
	end
	return templatestyles .. '\n' .. table.concat(t)
end

return p