Module:Sports table/WDL OT

From blackwiki
< Module:Sports table
Revision as of 19:03, 12 March 2020 by blackwiki>Gonnym (abbreviations should match the text. Changed abbreviations to match the text, but it can also go the other way. "TBR" is not an abbreviation for tiebreaker. This should be handled similar to other one letter words.)
Jump to navigation Jump to search

Documentation for this module may be created at Module:Sports table/WDL OT/doc

-- Style for football tables
local pp = {}
 
function pp.header(t,Args,p_sub,pos_label,group_col,VTE_text,full_table,results_header_txt)
	-- Load relevant modules
	local yesno = require('Module:Yesno')
	
	-- Create table header
	-- Pre stuff
	local team_width = Args['teamwidth'] or '190'
	local sort_text = yesno(Args['sortable_table'] or 'no') and ' sortable' or ''
	local show_played = not yesno(Args['hide_played'] or 'no')
	table.insert(t,'{| class="wikitable'..sort_text..'" style="text-align:center;"\n')            			-- Open table
	-- Table title
	if Args['title'] or Args['table_header'] then
		table.insert(t,'|+ ' .. (Args['title'] or Args['table_header']) .. '\n')
	end
	-- Custom header options
	local played_head_text = Args['pld_header'] or '<abbr title="Played">Pld</abbr>'
	local group_head_text = Args['group_header'] or '<abbr title="Group">Grp</abbr>'
	local win_head_text = Args['win_header'] or '<abbr title="Won">W</abbr>'
	local OTwin_head_text = Args['OTwin_header'] or '<abbr title="Won in overtime">WIO</abbr>'
	local OTloss_head_text = Args['OTloss_header'] or '<abbr title="Lost in overtime">LIO</abbr>'
	local PKwin_head_text = Args['PKwin_header'] or '<abbr title="Won on penalty kicks">WOPK</abbr>'
	local PKloss_head_text = Args['PKloss_header'] or '<abbr title="Lost on penalty kicks">LOPK</abbr>'
	local loss_head_text = Args['loss_header'] or '<abbr title="Lost">L</abbr>'
	local bonus_head_text = Args['bonus_header'] or '<abbr title="Bonus points">BP</abbr>'
	local tiebr_head_text = Args['tiebr_header'] or '<abbr title="Tiebreaker">T</abbr>'
	
	-- What to rank the teams by
	local ranking_style = Args['ranking_style'] or 'pts'
	local show_points, show_perc = false
	ranking_style = string.lower(ranking_style)
	if ranking_style=='w' or ranking_style=='win' or ranking_style=='wins' or ranking_style=='none' then
		-- Based on wins
	elseif ranking_style=='perc' or ranking_style=='percentage' or ranking_style=='%' then				-- NOTE: This is for points %, unlike Module:Sports table/WDL which caculates win %
		-- Based on percentage
		show_perc = true
	else
		-- Based on points
		show_points = true
	end

	-- Use points instead of goals for/against
	local for_against_style = Args['for_against_style'] 	or 'goals'
	local fa_letter, fa_word_sing, fa_word_plur
	-- First convert to lower case if it is a string
	for_against_style = string.lower(for_against_style)
	if for_against_style=='g' or for_against_style=='goal' or for_against_style=='goals' then
		fa_letter = 'G'
		fa_word_sing = 'Goal'
		fa_word_plur = 'Goals'
	elseif for_against_style=='p' or for_against_style=='point' or for_against_style=='points' then
		fa_letter = 'P'
		fa_word_sing = 'Point'
		fa_word_plur = 'Points'
	else
		fa_letter = 'G'
		fa_word_sing = 'Goal'
		fa_word_plur = 'Goals'
	end
	-- Whether to use goal ratio (goal average) instead
	local do_ratio = yesno(Args['use_goal_ratio'] or 'no')
	local do_average = yesno(Args['use_goal_average'] or 'no')
	
	-- Whether to use goal percentage instead
	local do_percentage = yesno(Args['use_goal_percentage'] or Args['use_point_percentage'] or 'no')
	
	-- True if exist, false otherwise
	local show_bonus_points = yesno(Args['show_bonus_points'] or 'no')
	local show_tiebr = yesno(Args['show_tiebr'] or 'no')
	
	-- Whether to show the OT win and OT loss and draw columns
	local show_OTwin = yesno(Args['showOTwin'] or 'yes')
	local show_OTloss = yesno(Args['showOTloss'] or 'yes')
	local show_PKwin = yesno(Args['showPKwin'] or 'no')
	local show_PKloss = yesno(Args['showPKloss'] or 'no')
	local show_draw = yesno(Args['show_draw'] or 'yes')
	local OTloss_after = yesno(Args['OTloss_after_loss'] or 'no')
	local PKloss_after = yesno(Args['PKloss_after_loss'] or 'no')
	
	-- Use games behind header
	local show_GB = yesno(Args['show_GB'] or 'no')
 
	-- Initialize
	local tt = {}
	tt.count = 0 		-- Up by one after every call
	tt.tab_text = t		-- Actual text
	-- Actual headers
	if pos_label ~= nil then
		tt = p_sub.colhead(tt,32,pos_label)										-- Position col
	end
	-- Add group header
	if full_table and group_col then
		tt = p_sub.colhead(tt,28,group_head_text)								-- Group col
	end
	tt = p_sub.colhead(tt,team_width,'Team'..VTE_text)							-- Team col
	if show_played then
		tt = p_sub.colhead(tt,32,played_head_text)								-- Matches played col
	end
	if full_table then
		tt = p_sub.colhead(tt,32,win_head_text)					-- Win col
		if show_OTwin then tt = p_sub.colhead(tt,32,OTwin_head_text) end
		if show_PKwin then tt = p_sub.colhead(tt,32,PKwin_head_text) end
		if show_draw then
			tt = p_sub.colhead(tt,32,'<abbr title="Drawn">D</abbr>')					-- Draw col
		end
		if show_OTloss and not OTloss_after then t = p_sub.colhead(tt,32,OTloss_head_text) end
		if show_PKloss and not PKloss_after then t = p_sub.colhead(tt,32,PKloss_head_text) end
		tt = p_sub.colhead(tt,32,loss_head_text)					-- Loss col
		if show_OTloss and OTloss_after then t = p_sub.colhead(tt,32,OTloss_head_text) end
		if show_PKloss and PKloss_after then t = p_sub.colhead(tt,32,PKloss_head_text) end
		if show_tiebr then t = p_sub.colhead(tt,32,tiebr_head_text) end
		tt = p_sub.colhead(tt,32,'<abbr title="'..fa_word_plur..' for">'..fa_letter..'F</abbr>')		-- For col
		tt = p_sub.colhead(tt,32,'<abbr title="'..fa_word_plur..' against">'..fa_letter..'A</abbr>')	-- Against col
		if do_ratio or do_average then
			local ratio_word = do_ratio and ' ratio' or ' average'
			local ratio_letter = do_ratio and 'R' or 'Av'
			tt = p_sub.colhead(tt,36,'<abbr title="'..fa_word_sing..ratio_word..'">'..fa_letter..ratio_letter..'</abbr>')	-- Ratio col
		elseif do_percentage then
			tt = p_sub.colhead(tt,28,'<abbr title="'..fa_word_sing..' percentage">%</abbr>')			-- Percentage col
		else
			tt = p_sub.colhead(tt,32,'<abbr title="'..fa_word_sing..' difference">'..fa_letter..'D</abbr>')	-- Difference col
		end
	end
	if show_bonus_points then
		tt = p_sub.colhead(tt,28,bonus_head_text)			-- Bonus points col
	end
	if show_points then
		tt = p_sub.colhead(tt,32,'<abbr title="Points">Pts</abbr>')					-- Points col
	elseif show_perc then
		tt = p_sub.colhead(tt,36,'<abbr title="Point percentage">PCT</abbr>')			-- Point percentage col
	end
	if full_table then
		tt.count = tt.count+1
		table.insert(tt.tab_text,results_header_txt)
	end
 
	return tt
end
 
function pp.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)
	-- Build the inner parts of individual rows
	
	-- Sub-module usage
	local mm = require('Module:Math')
	local yesno = require('Module:Yesno')
 
	-- Get custom/default options for in table
	local win_points = tonumber(Args['winpoints'])				or 3
	local OTwin_points = tonumber(Args['OTwinpoints'])			or 2
	local draw_points = tonumber(Args['drawpoints'])			or 1
	local OTloss_points = tonumber(Args['OTlosspoints'])		or 1
	local PKwin_points = tonumber(Args['PKwinpoints'])			or 1
	local PKloss_points = tonumber(Args['PKlosspoints'])		or 0
	local loss_points = tonumber(Args['losspoints'])			or 0
 
	-- Get some input
	local wins = tonumber(Args['win_'..team_code_ii])			or 0
	local OTwins = tonumber(Args['OTwin_'..team_code_ii])		or 0
	local draws = tonumber(Args['draw_'..team_code_ii]) 		or 0
	local OTlosses = tonumber(Args['OTloss_'..team_code_ii])	or 0
	local PKwins = tonumber(Args['PKwin_'..team_code_ii])		or 0
	local PKlosses = tonumber(Args['PKloss_'..team_code_ii])	or 0
	local losses = tonumber(Args['loss_'..team_code_ii])		or 0
	local tiebr = tonumber(Args['tiebr_'..team_code_ii])		or 0
	local gfor = tonumber(Args['gf_'..team_code_ii] or Args['pf_'..team_code_ii] or '0') or '?'
	local gaig = tonumber(Args['ga_'..team_code_ii] or Args['pa_'..team_code_ii] or '0') or '?'
	local s_pts = tonumber(Args['adjust_points_'..team_code_ii]) or tonumber(Args['startpoints_'..team_code_ii]) or 0
	local hth_local = Args['hth_'..team_code_ii]				or nil
	-- Then calculate some values
	local matches = wins + OTwins + draws + OTlosses + PKwins + PKlosses + losses
	local points = win_points*wins + OTwin_points*OTwins + draw_points*draws 
		+ OTloss_points*OTlosses + loss_points*losses 
		+ PKwin_points*PKwins + PKloss_points*PKlosses + s_pts
		
	if Args['goalpoints'] and tonumber(Args['gf_'..team_code_ii] or Args['pf_'..team_code_ii]) then
		points = points + (tonumber(Args['goalpoints']) or 1)*tonumber(Args['gf_'..team_code_ii] or Args['pf_'..team_code_ii])
	end
		
	if tonumber(Args['win_'..team_code_ii]) == nil or tonumber(Args['draw_'..team_code_ii]) == nil or tonumber(Args['loss_'..team_code_ii]) == nil then
		matches = tonumber(Args['matches_'..team_code_ii]) or matches
	end

	--Some sports use draw as well
	local percentage_format = Args['percentage_format']
	local point_perc
	if percentage_format == 'hundred 1 decimal' then
		point_perc = mm._precision_format(((points) / (matches*win_points)*100), 1)
	elseif percentage_format == 'hundred 2 decimals' then
		point_perc = mm._precision_format(((points) / (matches*win_points)*100), 2)
	else
		point_perc = mm._precision_format((points) / (matches*win_points), 3)
		percentage_format = 'no'
	end
	if matches == 0 then 
		-- Escape for zero matches
		point_perc = '&mdash;' 
	elseif points ~= (matches*win_points) and percentage_format == 'no' then
		-- Drop the leading zero (from the string)
		point_perc = string.sub(point_perc,2,string.len(point_perc))
	end

	-- Comparison of for against
	local gcomp
	-- Whether to use goal ratio (goal average) instead
	local skip_sign
	if yesno(Args['use_goal_ratio'] or 'no') or yesno(Args['use_goal_average'] or 'no') then
		-- Now it is the goal ratio/goal average
		if (gfor == '?') or (gaig == '?') or (gaig == 0) then
			gcomp = '&mdash;'
		else
			gcomp = mm._precision_format(gfor / gaig, 3)
		end
	elseif yesno(Args['use_goal_percentage'] or 'no') then
		-- Now it is the percentage
		if (gfor == '?') or (gaig == '?') or gaig == 0 then
			gcomp = '&mdash;'
		else
			gcomp = mm._precision_format(100 * gfor / gaig , 1)
		end
	elseif yesno(Args['use_point_percentage'] or 'no') then
		-- Now it is the point percentage
		if (gfor == '?') or (gaig == '?') or (gfor + gaig) <= 0 then
			gcomp = '&mdash;'
		else
			gcomp = mm._precision_format(100 * gfor / (gfor + gaig) , 2)
		end
	else
		-- It's goal difference
		if (gfor == '?') or (gaig == '?') then
			gcomp = '&mdash;'
		else
			gcomp = gfor - gaig
			-- Formatting with signs
			if gcomp>0 then
				gcomp='+'..gcomp
			elseif gcomp < 0 then
				gcomp='&minus;'..-gcomp
			end
		end
	end
	-- Use actual values if gfor or gaig is not numeric
	if (gfor == '?') then gfor = Args['gf_'..team_code_ii] or Args['pf_'..team_code_ii] or '' end
	if (gaig == '?') then gaig = Args['ga_'..team_code_ii] or Args['pa_'..team_code_ii] or '' end
	
	-- Show games behind
	local show_GB = yesno(Args['show_GB'] or 'no')
	local GB_text = '&mdash;'
	if show_GB then
		local GB_team_no = tonumber(Args['GB_team']) or 1
		if ii == GB_team_no then
			-- Do nothing, it's vs this team
		else
			local wins_GB = tonumber(Args['win_'..team_list[GB_team_no]])		or 0
			local losses_GB = tonumber(Args['loss_'..team_list[GB_team_no]])	or 0
			local GB_num = (wins_GB-wins+losses-losses_GB)/2
			-- Display options
			if GB_num >0 then
				-- Indicates trailing GB_team
				GB_text = GB_num
			elseif GB_num == 0 then
				-- Equal, do nothing to get dash
			else 
				-- Ahead of GB team, should be noted by plus (instead of minus that comes from formula)
				GB_text = '+'..-GB_num
			end
		end
	end
	
	-- Whether to show the OT win and OT loss and draw columns
	local show_OTwin = yesno(Args['showOTwin'] or 'yes')
	local show_OTloss = yesno(Args['showOTloss'] or 'yes')
	local show_PKwin = yesno(Args['showPKwin'] or 'no')
	local show_PKloss = yesno(Args['showPKloss'] or 'no')
	local show_draw = yesno(Args['show_draw'] or 'yes')
	local OTloss_after = yesno(Args['OTloss_after_loss'] or 'no')
	local PKloss_after = yesno(Args['PKloss_after_loss'] or 'no')
 
	-- Some local vars	
	local hth_string
	local tt_return = p_sub.hth(frame,Args,full_table,hth_id_list,hth_local,notes_exist,team_list,team_code_ii,ii_start,ii_end,rand_val)
	hth_string = tt_return.str
	hth_id_list = tt_return.list
	notes_exist = tt_return.notes_exist
	
	-- What to rank the teams by
	local ranking_style = Args['ranking_style'] or 'pts'
	local rank_points, rank_perc = false
	local win_fw, win_string
	ranking_style = string.lower(ranking_style)
	if ranking_style=='w' or ranking_style=='win' or ranking_style=='wins' then
		-- Based on wins
		win_fw = 'font-weight: bold;'
		win_string = hth_string
	elseif ranking_style=='perc' or ranking_style=='percentage' or ranking_style=='%' then
		-- Based on percentage
		rank_perc = true
		win_fw=ii_fw
		win_string = ''
	elseif ranking_style=='none' then
		win_fw=ii_fw
		win_string = ''
	else
		-- Based on points
		rank_points = true
		win_fw=ii_fw
		win_string = ''
	end

	local show_played = not yesno(Args['hide_played'] or 'no')
	local show_bonus_points = yesno(Args['show_bonus_points'] or 'no')
	local show_tiebr = yesno(Args['show_tiebr'] or 'no')
	-- Row building
	if show_played then
		table.insert(t,'| style="'..ii_fw..bg_col..'" |'..matches..'\n') 		-- Played
	end
	if full_table then
		-- Use actual values if wins, draws, and losses are not numeric
		if (OTwins == 0 and PKwins == 0 and wins == 0 and draws == 0 and OTlosses == 0 and PKlosses == 0 and losses == 0) then
			local function numorval(s)
				return s and ((s == '' and 0) or tonumber(s) or s) or 0
			end
			wins = numorval(Args['win_'..team_code_ii])
			OTwins = numorval(Args['OTwin_'..team_code_ii])
			PKwins = numorval(Args['PKwin_'..team_code_ii])
			draws = numorval(Args['draw_'..team_code_ii])
			losses = numorval(Args['loss_'..team_code_ii])
			OTlosses = numorval(Args['OTloss_'..team_code_ii])
			PKlosses = numorval(Args['PKloss_'..team_code_ii])
		end

		table.insert(t,'| style="'..win_fw..bg_col..'" |'..wins..win_string..'\n') 			-- Won
		if show_OTwin then
			table.insert(t,'| style="'..ii_fw..bg_col..'" |'..OTwins..'\n') 	-- Won in OT
		end
		if show_PKwin then
			table.insert(t,'| style="'..ii_fw..bg_col..'" |'..PKwins..'\n') 	-- Won on PKs
		end
		if show_draw then
			table.insert(t,'| style="'..ii_fw..bg_col..'" |'..draws..'\n') 		-- Drawn
		end
		if show_OTloss and not OTloss_after then
			table.insert(t,'| style="'..ii_fw..bg_col..'" |'..OTlosses..'\n') 	-- Lost in OT
		end
		if show_PKloss and not PKloss_after then
			table.insert(t,'| style="'..ii_fw..bg_col..'" |'..PKlosses..'\n') 	-- Lost on PKs
		end
		table.insert(t,'| style="'..ii_fw..bg_col..'" |'..losses..'\n') 	-- Lost
		if show_OTloss and OTloss_after then
			table.insert(t,'| style="'..ii_fw..bg_col..'" |'..OTlosses..'\n') 	-- Lost in OT
		end
		if show_PKloss and PKloss_after then
			table.insert(t,'| style="'..ii_fw..bg_col..'" |'..PKlosses..'\n') 	-- Lost on PKs
		end
		if show_tiebr then
			table.insert(t,'| style="'..ii_fw..bg_col..'" |'..tiebr..'\n') 	-- Tie breaker
		end
		table.insert(t,'| style="'..ii_fw..bg_col..'" |'..gfor..'\n') 		-- GF
		table.insert(t,'| style="'..ii_fw..bg_col..'" |'..gaig..'\n')		-- GA
		table.insert(t,'| style="'..ii_fw..bg_col..'" |'..gcomp..'\n')      -- Goal comparison
	end
	if show_bonus_points then
		if s_pts < 0 then
			table.insert(t,'| style="'..bg_col..'" | &minus;'..-s_pts..'\n')
		else
			table.insert(t,'| style="'..bg_col..'" | '..s_pts..'\n')
		end
	end
	
	if rank_points then
		-- Add &minus; for negative point totals
		if points<0 then
			table.insert(t,'| style="font-weight: bold;'..bg_col..'" | &minus;'..-points..hth_string..'\n')
		else
			table.insert(t,'| style="font-weight: bold;'..bg_col..'" | '..points..hth_string..'\n')
		end
	elseif rank_perc then
		table.insert(t,'| style="font-weight: bold;'..bg_col..'" | '..point_perc..hth_string..'\n')
	end
	if show_GB then
		table.insert(t,'| style="'..ii_fw..bg_col..'" |'..GB_text..'\n')  -- GB
	end
 
	return {t=t, notes_exist=notes_exist, hth_id_list=hth_id_list}
end
 
function pp.status(Args)
	-- Declare status options
	-- ------------------------------------------------------------
	-- NOTE: If you add to status_code, also add to status_called and status_letters!!
	-- Or functionality will be compromised
	-- ------------------------------------------------------------
	local status_code, status_called = {}, {}
	status_code = {	A='Advances to a further round', C='Champion', D='Disqualified', 
		E='Eliminated', H='Host', O='Play-off winner', P='Promoted', Q='Qualified to the phase indicated',
		R='Relegated', T='Qualified, but not yet to the particular phase indicated'}
	local status_letters = (Args['status_order'] or '') .. 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
	
	-- Status position (before or after read and default)
	local stat_pos_val = Args['status_pos'] or ''
	local status_position = 'after' 	-- Default location
	stat_pos_val = string.lower(stat_pos_val)
	if stat_pos_val=='before' then
		status_position = 'before'
	elseif stat_pos_val=='after' then
		status_position = 'after'
	end
	-- Read in custom status options
	for l in mw.text.gsplit(status_letters, '') do
		status_called[l] = false
		status_code[l] = status_code[l] or '?'
		status_letters = mw.ustring.gsub(status_letters, '(' .. l ..'.-)' .. l, '%1')

		if Args['status_text_' .. l] then
			status_code[l] = Args['status_text_' .. l]
		end
	 end
	
	return {code=status_code, called=status_called, letters=status_letters, position=status_position}
end

return pp