Module:Sandbox/B2project/NHL Standings

This is an old revision of this page, as edited by B2project (talk | contribs) at 15:05, 11 June 2016. The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
-- This module copies content from Template:MLB_standings; see the history of that page
-- for attribution.

local me = { }

local mlbData

-- if mw.loadData() not supported, use require() instead
if mw.loadData then
    mlbData = mw.loadData('Module:Sandbox/B2project/NHL Standings/data')
else
    mlbData = require('Module:Sandbox/B2project/NHL Standings/data')
end

local Navbar = require('Module:Navbar')

-- Temporary workaround for missing mw.text utility functions
mw.text = mw.text or {}

if (mw.text.trim == nil) then
    mw.text.trim = function(s)
        if (s == nil) then
            return ''
        end
        return mw.ustring.match(s, "^%s*(.-)%s*$")
    end
end

if (mw.text.gsplit == nil) then
    mw.text.gsplit = function( text, pattern, plain )
        local s, l = 1, mw.ustring.len( text )
        return function ()
            if s then
                local e, n = mw.ustring.find( text, pattern, s, plain )
                local ret
                if not e then
                    ret = mw.ustring.sub( text, s )
                    s = nil
                elseif n < e then
                    -- Empty separator!
                    ret = mw.ustring.sub( text, s, e )
                    if e < l then
                        s = e + 1
                    else
                        s = nil
                    end
                else
                    ret = e > s and mw.ustring.sub( text, s, e - 1 ) or ''
                    s = n + 1
                end
                return ret
            end
        end, nil, nil
    end
end

if (mw.text.split == nil) then
    mw.text.split = function ( text, pattern, plain )
        local ret = {}
        for m in mw.text.gsplit( text, pattern, plain ) do
            ret[#ret+1] = m
        end
        return ret
    end
end

local defaultOutputForInput = {
    default = 'default',
    overallWinLoss = 'winLossOnly',
}

local readTeamInfo = {
    default = function(args, currentIdx, returnData)
        if (args[currentIdx]   == nil or
            args[currentIdx+1] == nil or
            args[currentIdx+2] == nil or
            args[currentIdx+3] == nil or
            args[currentIdx+4] == nil or
            args[currentIdx+5] == nil or
            args[currentIdx+6] == nil or
            args[currentIdx+7] == nil ) then
            return nil
        end
        teamInfo = {
            name       = mw.text.trim(args[currentIdx]),
            wins   = tonumber(mw.text.trim(args[currentIdx+1])),
            losses = tonumber(mw.text.trim(args[currentIdx+2])),
            ties   = tonumber(mw.text.trim(args[currentIdx+3])),
            OTlosses = tonumber(mw.text.trim(args[currentIdx+4])),
            tiebr = tonumber(mw.text.trim(args[currentIdx+5])),
            goalsfor = tonumber(mw.text.trim(args[currentIdx+6])),
            goalsag = tonumber(mw.text.trim(args[currentIdx+7])),
        }
        returnData.cIndicesRead = 5
        teamInfo.wins = teamInfo.wins
        teamInfo.losses = teamInfo.losses
        teamInfo.ties = teamInfo.ties
        teamInfo.OTlosses = teamInfo.OTlosses
        teamInfo.tiebr = teamInfo.tiebr
        teamInfo.goalsfor = teamInfo.goalsfor
        teamInfo.goalsag = teamInfo.goalsag
        return teamInfo
    end,  -- function readTeamInfo.default()

    overallWinLoss = function(args, currentIdx, returnData)
        if (args[currentIdx]   == nil or
            args[currentIdx+1] == nil or
            args[currentIdx+2] == nil ) then
            return nil
        end
        teamInfo = {
            name   = mw.text.trim(args[currentIdx]),
            wins   = tonumber(mw.text.trim(args[currentIdx+1])),
            losses = tonumber(mw.text.trim(args[currentIdx+2])),
        }
        returnData.cIndicesRead = 3
        return teamInfo
    end,  -- function readTeamInfo.default()

}  -- readTeamInfo object

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 = ''
	local sort_table_val = Args['sortable_table'] 	or 'no'
	if yesno(sort_table_val) then sort_text = 'sortable' end
	table.insert(t,'{|class="wikitable '..sort_text..'" style="text-align:center;"\n')            			-- Open table
	
	-- Custom header options
	-- Table header
	local table_header = Args['table_header']
	if table_header then
		table.insert(t,'|+'..table_header..'\n')
	end
	--Column headers
	local pld_head_text = Args['pld_header'] or '<abbr title="Played">Pld</abbr>'
	local OTloss_head_text = Args['OTloss_header'] or '<abbr title="Lost in overtime">OTL</abbr>'
	local tiebr_head_text = Args['tiebr_header'] or '<abbr title="Tiebreaker">TBR</abbr>'
	local group_head_text = Args['group_header'] or '<abbr title="Group">Grp</abbr>'
	-- 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 use_ratio_val = Args['use_goal_ratio'] 	or 'no'
	local do_ratio = false
	-- True if exist, false otherwise
	if yesno(use_ratio_val) then do_ratio = true end
	
	-- Whether to use tiebreak
	local use_tiebr_val = Args['use_tiebreak'] or 'yes'
	local do_tiebr = false
	if yesno(use_tiebr_val) then do_tiebr = true end
 
 	-- Ties and OTL
	local use_tieOTL_val = Args['use_ties'] or 'no'
	local do_ties = false
	if yesno(use_tieOTL_val) then do_ties = true end
 
	-- Initialize
	local tt = {}
	tt.count = 0 		-- Up by one after every call
	tt.tab_text = t		-- Actual text
	-- Actual headers
	tt = p_sub.colhead(tt,32,pos_label)											-- Position col
	-- Add group header
	if full_table and group_col then
		tt = p_sub.colhead(tt,32,group_head_text)								-- Group/division col
	end
	tt = p_sub.colhead(tt,team_width,'Team'..VTE_text)							-- Team col
	tt = p_sub.colhead(tt,32,pld_head_text)										-- Matches played col
	if full_table then
		tt = p_sub.colhead(tt,32,'<abbr title="Won">W</abbr>')					-- Win col
		tt = p_sub.colhead(tt,32,'<abbr title="Lost">L</abbr>')					-- Loss col
		if do_ties then
			tt = p_sub.colhead(tt,32,'<abbr title="Ties">T</abbr>')				-- Ties
		end
		tt = p_sub.colhead(tt,32,OTloss_head_text)
		if do_tiebr then
		tt = 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 not do_ratio then
			tt = p_sub.colhead(tt,32,'<abbr title="'..fa_word_sing..' difference">'..fa_letter..'D</abbr>')	-- Difference col
		else
			tt = p_sub.colhead(tt,36,'<abbr title="'..fa_word_sing..' ratio">'..fa_letter..'R</abbr>')	-- Ratio col
		end
	end
	tt = p_sub.colhead(tt,32,'<abbr title="Points">Pts</abbr>')					-- Points col
	if full_table then
		tt.count = tt.count+1
		table.insert(tt.tab_text,results_header_txt)
	end
 
	return tt
end

local generateTeamRow = {
    default = function(teamRowInfo, teamInfo)
        return
'|-' .. teamRowInfo.rowStyle .. '\
|| ' .. teamRowInfo.seedText .. '[[' .. teamRowInfo.teamSeasonPage .. '|' .. teamInfo.name .. ']]\
|| ' .. (teamInfo.wins+teamInfo.losses+teamInfo.ties+teamInfo.OTlosses) ..'\
|| ' .. teamInfo.wins .. ' || ' .. teamInfo.losses .. '\n'

    end,  -- function generateTeamRow.default()

    winLossOnly = function(teamRowInfo, teamInfo)
        return
'|-' .. teamRowInfo.rowStyle .. '\
|| ' .. teamRowInfo.seedText .. '[[' .. teamRowInfo.teamSeasonPage .. '|' .. teamInfo.name .. ']]\
|| ' .. teamInfo.wins .. ' || ' .. teamInfo.losses .. '\
|| ' .. teamRowInfo.winningPercentage .. '\n'
    end,  -- function generateTeamRow.winLossOnly

    wildCard2012 = function(teamRowInfo, teamInfo)
        return
'|-' .. teamRowInfo.rowStyle .. '\
|| ' .. teamRowInfo.seedText .. '[[' .. teamRowInfo.teamSeasonPage .. '|' .. teamInfo.name .. ']]\
|| ' .. teamInfo.wins .. ' || ' .. teamInfo.losses .. '\
|| ' .. teamRowInfo.winningPercentage .. '\
|| ' .. teamRowInfo.gamesBehind .. '\n'
    end,  -- function generateTeamRow.wildCard2012
}   -- generateTeamRow object

local function parseSeeds(seedsArg, seeds)
    local seedList = mw.text.split(seedsArg, '%s*,%s*')
    if (#seedList == 0) then
        return
    end

    for idx, seed in ipairs(seedList) do
        local seedData = mw.text.split(seed, '%s*:%s*')
        if (#seedData >= 2) then
            local seedNumber = tonumber(mw.text.trim(seedData[1]))
            local team = mw.text.trim(seedData[2])
            seeds[seedNumber] = team
            seeds[team] = seedNumber
        end
    end
end  -- function parseSeeds()

local function parseHighlightArg(highlightArg, teamsToHighlight)
    local teamList = mw.text.split(highlightArg, '%s*,%s*')
    if (#teamList == 0) then
        return
    end

    for idx, team in ipairs(teamList) do
        teamsToHighlight[mw.text.trim(team)] = true
    end

end  -- function parseHighlightArg

local function parseTeamLinks(teamLinksArg, linkForTeam)
    local teamList = mw.text.split(teamLinksArg, '%s*,%s*')
    if (#teamList == 0) then
        return
    end

    for idx, teamLinkInfo in ipairs(teamList) do
        local teamData = mw.text.split(teamLinkInfo, '%s*:%s*')
        if (#teamData >= 2) then
            local team = mw.text.trim(teamData[1])
            local teamLink = mw.text.trim(teamData[2])
            linkForTeam[team] = teamLink
        end
    end
end  -- function parseTeamLinks

function me.generateStandingsTable(frame)
    local inputFormat = 'default'
    if (frame.args.input ~= nil) then
        local inputArg = mw.text.trim(frame.args.input)
        if (inputArg == 'overallWinLoss') then
            inputFormat = 'overallWinLoss'
        end
    end

    local templateName = nil
    if (frame.args.template_name ~= nil) then
        templateName = frame.args.template_name
    end

    local outputFormat = defaultOutputForInput[inputFormat]
    local fDisplayNavbar = true
    local fDisplayGamesBehind = true
    if (frame.args.output ~= nil) then
        local outputArg = mw.text.trim(frame.args.output)
        if (outputArg == 'winLossOnly') then
            outputFormat = 'winLossOnly'
            fDisplayGamesBehind = false
        end
        if (outputArg == 'wildCard2012') then
            outputFormat = 'wildCard2012'
        end
    end

    local year = mw.text.trim(frame.args.year or '')
    local division = mw.text.trim(frame.args.division or '')
    local divisionLink = mw.text.trim(frame.args.division_link or division)

    local seedInfo = {}
    if (frame.args.seeds ~= nil) then
        parseSeeds(frame.args.seeds, seedInfo)
    end

    local teamsToHighlight = {}
    if (frame.args.highlight ~= nil) then
        parseHighlightArg(frame.args.highlight, teamsToHighlight)
    end

    local linkForTeam = {}
    if (frame.args.team_links ~= nil) then
        parseTeamLinks(frame.args.team_links, linkForTeam)
    end

    local listOfTeams = {};
    local currentArgIdx = 1;

    while (frame.args[currentArgIdx] ~= nil) do
        local returnData = { }
        local teamInfo = readTeamInfo[inputFormat](frame.args, currentArgIdx, returnData);
        if (teamInfo == nil) then
            break
        end
        if (linkForTeam[teamInfo.name] ~= nil) then
            teamInfo.teamLink = linkForTeam[teamInfo.name]
        else
            teamInfo.teamLink = teamInfo.name
        end
        table.insert(listOfTeams, teamInfo)
        currentArgIdx = currentArgIdx + returnData.cIndicesRead
    end

    if (#listOfTeams == 0) then
        return ''
    end

    local outputBuffer = { }

    local tableHeaderInfo = {
        division = division,
        divisionLink = divisionLink,
    }

    if (fDisplayNavbar) then
        local divisionForNavbox = division
        if (mlbData.abbreviationForDivision[division] ~= nil) then
            divisionForNavbox = mlbData.abbreviationForDivision[division]
        end

        local standingsPage
        if templateName ~= nil then
            standingsPage = templateName
        else
            standingsPage = year .. ' NHL ' .. divisionForNavbox .. ' standings'
        end
        tableHeaderInfo.navbarText =
            Navbar.navbar({
                standingsPage,
                mini = 1,
                style = 'float:left;width:0;',
            })
    end

    table.insert(outputBuffer,
        generateTableHeader[outputFormat](tableHeaderInfo)
    )

    local leadingHalfGames = nil;
    if (fDisplayGamesBehind) then
        local standingsLeaderIdx = 1;
        if (outputFormat == 'wildCard2012' and #listOfTeams > 1) then
            standingsLeaderIdx = 2;
        end
        local teamInfo = listOfTeams[standingsLeaderIdx]
        leadingHalfGames = (teamInfo.wins - teamInfo.losses)
    end

    for idx, teamInfo in ipairs(listOfTeams) do
        local teamRowInfo = {
            teamSeasonPage = year .. ' ' .. teamInfo.teamLink .. ' season',
            winningPercentage = string.format(
                '%.3f', teamInfo.wins / ( teamInfo.wins + teamInfo.losses )
            ),
            gamesBehind = '',
            seedText = '',
            rowStyle = '',
        }


        if (teamsToHighlight[teamInfo.name]) then
            teamRowInfo.rowStyle =  ' style="background:#CCFFCC"'
        end

        table.insert(outputBuffer,
            generateTeamRow[outputFormat](teamRowInfo, teamInfo)
        )
    end  -- end of looping over listOfTeams

    table.insert(outputBuffer, '|}\n')

    return table.concat(outputBuffer)

end  -- function me.generateStandingsTable()

function me.generateStandingsTable_fromTemplate(frame)
    return me.generateStandingsTable(frame:getParent())
end  -- function me.generateStandingsTable_fromTemplate()

return me