Module:Sandbox/B2project/NHL Standings

-- This module copies content from Template:MLB_standings; see the history of that page -- for attribution. 6/15/16

local me = { }

local nhlData

-- if mw.loadData not supported, use require instead if mw.loadData then nhlData = mw.loadData('Module:Sandbox/B2project/NHL Standings/data') else nhlData = 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', current = 'current', winsloss = 'winsloss', WLT = 'WLT', }

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])), row = tonumber(mw.text.trim(args[currentIdx+5])), gf = tonumber(mw.text.trim(args[currentIdx+6])), ga = tonumber(mw.text.trim(args[currentIdx+7])), winpoints = 2, tiepoints = 1, otlpoints = 1, points = '', gamesplayed = '', }       returnData.cIndicesRead = 8 teamInfo.gamesplayed = teamInfo.wins + teamInfo.losses + teamInfo.ties + teamInfo.otlosses teamInfo.points = (teamInfo.winpoints*teamInfo.wins)+(teamInfo.tiepoints*teamInfo.ties)+(teamInfo.otlpoints*teamInfo.otlosses)

return teamInfo end, -- function readTeamInfo.default current = 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 ) 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])), otlosses = tonumber(mw.text.trim(args[currentIdx+3])), row = tonumber(mw.text.trim(args[currentIdx+4])), gf = tonumber(mw.text.trim(args[currentIdx+5])), ga = tonumber(mw.text.trim(args[currentIdx+6])), winpoints = 2, otlpoints = 1, points = '', gamesplayed = '', }       returnData.cIndicesRead = 7 teamInfo.gamesplayed = teamInfo.wins + teamInfo.losses + teamInfo.otlosses teamInfo.points = (teamInfo.winpoints*teamInfo.wins)+(teamInfo.otlpoints*teamInfo.otlosses)

return teamInfo end, -- function readTeamInfo.default winsloss = 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 ) 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])), gf = tonumber(mw.text.trim(args[currentIdx+3])), ga = tonumber(mw.text.trim(args[currentIdx+4])), winpoints = 2, points = '', gamesplayed = '', }       returnData.cIndicesRead = 5 teamInfo.gamesplayed = teamInfo.wins + teamInfo.losses teamInfo.points = (teamInfo.winpoints*teamInfo.wins)

return teamInfo end, -- function readTeamInfo.default WLT = 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 ) 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])), gf = tonumber(mw.text.trim(args[currentIdx+4])), ga = tonumber(mw.text.trim(args[currentIdx+5])), winpoints = 2, tiepoints = 1, points = '', gamesplayed = '', }       returnData.cIndicesRead = 6 teamInfo.gamesplayed = teamInfo.wins + teamInfo.losses + teamInfo.ties teamInfo.points = (teamInfo.winpoints*teamInfo.wins) + (teamInfo.tiepoints*teamInfo.ties)

return teamInfo end, -- function readTeamInfo.default

} -- readTeamInfo object

local generateTableHeader = { default = function(tableHeaderInfo) return '{| class="wikitable sortable" width="" style="text-align:center;"\ ! width=32 | Pos \ ! width=190 | Team ' .. tableHeaderInfo.navbarText .. '\ ! width=32 | GP \ ! width=32 | W \ ! width=32 | L \ ! width=32 | T \ ! width=32 | OTL \ ! width=32 | ROW \ ! width=32 | GF \ ! width=32 | GA \ ! width=32 | GD \ ! width=32 | Pts \ ' end, -- function generateTableHeader.default
 * + ' .. tableHeaderInfo.division .. '' ..tableHeaderInfo.source.. '\

current = function(tableHeaderInfo) return '{| class="wikitable sortable" width="" style="text-align:center;"\ ! width=32 | Pos \ ! width=190 | Team ' .. tableHeaderInfo.navbarText .. '\ ! width=32 | GP \ ! width=32 | W \ ! width=32 | L \ ! width=32 | OTL \ ! width=32 | <abbr title="Regulation + Overtime wins">ROW \ ! width=32 | <abbr title="Goals for">GF \ ! width=32 | <abbr title="Goals for">GA \ ! width=32 | <abbr title="Goal difference">GD \ ! width=32 | <abbr title="Points">Pts \ ' end,
 * + ' .. tableHeaderInfo.division .. '\

winsloss = function(tableHeaderInfo) return '{| class="wikitable sortable" width="" style="text-align:center;"\ ! width=32 | <abbr title="Position">Pos \ ! width=190 | Team ' .. tableHeaderInfo.navbarText .. '\ ! width=32 | <abbr title="Games played">GP \ ! width=32 | <abbr title="Won">W \ ! width=32 | <abbr title="Lost">L \ ! width=32 | <abbr title="Goals for">GF \ ! width=32 | <abbr title="Goals for">GA \ ! width=32 | <abbr title="Goal difference">GD \ ! width=32 | <abbr title="Points">Pts \ ' end, -- function generateTableHeader.winloss
 * + ' .. tableHeaderInfo.division .. '\

WLT = function(tableHeaderInfo) return '{| class="wikitable sortable" width="" style="text-align:center;"\ ! width=32 | <abbr title="Position">Pos \ ! width=190 | Team ' .. tableHeaderInfo.navbarText .. '\ ! width=32 | <abbr title="Games played">GP \ ! width=32 | <abbr title="Won">W \ ! width=32 | <abbr title="Lost">L \ ! width=32 | <abbr title="Ties">T \ ! width=32 | <abbr title="Goals for">GF \ ! width=32 | <abbr title="Goals for">GA \ ! width=32 | <abbr title="Goal difference">GD \ ! width=32 | <abbr title="Points">Pts \ ' end, -- function generateTableHeader.WLT } -- generateTableHeader object
 * + ' .. tableHeaderInfo.division .. '\

local generateTeamRow = { default = function(teamRowInfo, teamInfo) return '|-' .. teamRowInfo.rowStyle .. '\
 * ' .. teamRowInfo.position ..'\
 * style="text-align:left;" | ' .. teamRowInfo.statusText .. '' .. teamInfo.name .. '\
 * ' .. teamInfo.gamesplayed .. '\
 * ' .. teamInfo.wins .. '\
 * ' .. teamInfo.losses .. '\
 * ' .. teamInfo.ties ..'\
 * ' .. teamInfo.otlosses ..'\
 * ' .. teamInfo.row ..'\
 * ' .. teamInfo.gf .. '\
 * ' .. teamInfo.ga .. '\
 * ' .. teamRowInfo.goaldiff ..'\
 * style="font-weight:bold;" | ' .. teamInfo.points ..'\n'

end, -- function generateTeamRow.default

current = function(teamRowInfo, teamInfo) return '|-' .. teamRowInfo.rowStyle .. '\
 * ' .. teamRowInfo.position ..'\
 * style="text-align:left;" | ' .. teamRowInfo.statusText .. '' .. teamInfo.name .. '\
 * ' .. teamInfo.gamesplayed .. '\
 * ' .. teamInfo.wins .. '\
 * ' .. teamInfo.losses .. '\
 * ' .. teamInfo.otlosses ..'\
 * ' .. teamInfo.row ..'\
 * ' .. teamInfo.gf .. '\
 * ' .. teamInfo.ga .. '\
 * ' .. teamRowInfo.goaldiff ..'\
 * style="font-weight:bold;" | ' .. teamInfo.points ..'\n'

end,

winsloss = function(teamRowInfo, teamInfo) return '|-' .. teamRowInfo.rowStyle .. '\
 * ' .. teamRowInfo.position ..'\
 * style="text-align:left;" | ' .. teamRowInfo.statusText .. '' .. teamInfo.name .. '\
 * ' .. teamInfo.gamesplayed .. '\
 * ' .. teamInfo.wins .. '\
 * ' .. teamInfo.losses .. '\
 * ' .. teamInfo.gf .. '\
 * ' .. teamInfo.ga .. '\
 * ' .. teamRowInfo.goaldiff ..'\
 * style="font-weight:bold;" | ' .. teamInfo.points ..'\n'

end, -- function generateTeamRow.default

WLT = function(teamRowInfo, teamInfo) return '|-' .. teamRowInfo.rowStyle .. '\
 * ' .. teamRowInfo.position ..'\
 * style="text-align:left;" | ' .. teamRowInfo.statusText .. '' .. teamInfo.name .. '\
 * ' .. teamInfo.gamesplayed .. '\
 * ' .. teamInfo.wins .. '\
 * ' .. teamInfo.losses .. '\
 * ' .. teamInfo.ties .. '\
 * ' .. teamInfo.gf .. '\
 * ' .. teamInfo.ga .. '\
 * ' .. teamRowInfo.goaldiff ..'\
 * style="font-weight:bold;" | ' .. teamInfo.points ..'\n'

end, -- function generateTeamRow.default

}  -- generateTeamRow object

local function parsestatus_list(status_listArg, status_list) local statusList = mw.text.split(status_listArg, '%s*,%s*') if (#statusList == 0) then return end

for idx, status in ipairs(statusList) do       local statusData = mw.text.split(status, '%s*:%s*') if (#statusData >= 2) then local statusNumber = mw.text.trim(statusData[1]) local team = mw.text.trim(statusData[2]) status_list[statusNumber] = team status_list[team] = statusNumber end end end -- function parsestatus_list

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 == 'current') then inputFormat = 'current' end if (inputArg == 'winsloss') then inputFormat = 'winsloss' end if (inputArg == 'WLT') then inputFormat = 'WLT' 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 fDisplayTies = true if (frame.args.output ~= nil) then local outputArg = mw.text.trim(frame.args.output) if (outputArg == 'current') then outputFormat = 'current' fDisplayTies = false end if (outputArg == 'winsloss') then outputFormat = 'winsloss' end if (outputArg == 'WLT') then outputFormat = 'WLT' 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 source = mw.text.trim(frame.args.source or '')

local statusInfo = {} if (frame.args.status_list ~= nil) then parsestatus_list(frame.args.status_list, statusInfo) 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 t_footer = { }

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

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

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

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

local leadingHalfGames = nil;

for idx, teamInfo in ipairs(listOfTeams) do       local teamRowInfo = { teamSeasonPage = year .. ' ' .. teamInfo.teamLink .. ' season', statusText = '', rowStyle = '', position = idx, goaldiff = '', winpoints = 2, tiepoints = 1, otlpoints = 1, }       teamRowInfo.goaldiff = teamInfo.gf - teamInfo.ga        if teamRowInfo.goaldiff>0 then teamRowInfo.goaldiff=' +'..teamRowInfo.goaldiff..' ' elseif teamRowInfo.goaldiff<0 then teamRowInfo.goaldiff=teamRowInfo.goaldiff*-1 teamRowInfo.goaldiff=' &minus;'..teamRowInfo.goaldiff..' ' end if (statusInfo[teamInfo.name] ~= nil) then teamRowInfo.statusText = ' ' .. string.lower(statusInfo[teamInfo.name]) .. ' – '           --teamRowInfo.rowStyle = ' style="background:#CCFFCC"' end

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

table.insert(outputBuffer,           generateTeamRow[outputFormat](teamRowInfo, teamInfo)        )

end -- end of looping over listOfTeams

table.insert(outputBuffer, '|}\n') local update = mw.text.trim(frame.args.update or 'unknown') local start_date = mw.text.trim(frame.args.start_date or 'unknown') --local source = mw.text.trim(frame.args.source or '') if (source ~= nil) then source = source else source = '' end local matches_text = mw.text.trim(frame.args.matches_text or 'games') if string.lower(update)=='complete' then table.insert(t_footer,'Final standings.'..tableHeaderInfo.source..'') elseif update=='' then -- Empty table.insert(t_footer,'Source'..tableHeaderInfo.source..'') elseif update=='future' then -- Future start date table.insert(t_footer,'First '..matches_text..' will be played on '..start_date..'. ') else table.insert(t_footer,'Updated to '..matches_text..' played on '..update..'.'..tableHeaderInfo.source..'') end return table.concat(outputBuffer), table.concat(t_footer)

end -- function me.generateStandingsTable

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

return me