Module:MLB standings

-- 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:MLB standings/data') else mlbData = require('Module:MLB 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 = 'winLossOnlyNoNavbar', }

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 ) then return nil end teamInfo = { name      = mw.text.trim(args[currentIdx]), homeWins  = tonumber(mw.text.trim(args[currentIdx+1])), homeLosses = tonumber(mw.text.trim(args[currentIdx+2])), roadWins  = tonumber(mw.text.trim(args[currentIdx+3])), roadLosses = tonumber(mw.text.trim(args[currentIdx+4])), }       returnData.cIndicesRead = 5 teamInfo.wins = teamInfo.homeWins + teamInfo.roadWins teamInfo.losses = teamInfo.homeLosses + teamInfo.roadLosses 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 generateTableHeader = { default = function(tableHeaderInfo) return '{| class="wikitable" width="515em" style="text-align:center;"\ ! width="50%" |' .. tableHeaderInfo.navbarText .. '' .. tableHeaderInfo.division .. '\ ! width="7%" | W\ ! width="7%" | L\ ! width="9%" | Pct.\ ! width="7%" | GB\ ! width="10%" | Home\ ! width="10%" | Road\ '   end,  -- function generateTableHeader.default

winLossOnlyNoNavbar = function(tableHeaderInfo) return '{| class="wikitable" width="380em" style="text-align:center;"\ ! width="66%" | ' .. tableHeaderInfo.division .. '\ ! width="10%" | W\ ! width="10%" | L\ ! width="14%" | Pct.\ '   end,  -- function generateTableHeader.winLossOnlyNoNavBar

wildCard2012 = function(tableHeaderInfo) return '{| class="wikitable" width="375em" style="text-align:center;"\ ! width="60%" | Wild Card teams (Top 2 qualify for 1-game playoff) \ ! width="8%" | W\ ! width="8%" | L\ ! width="12%" | Pct.\ ! width="12%" | GB\ '   end,  -- function generateTableHeader.wildCard2012 } -- generateTableHeader object

local generateTeamRow = { default = function(teamRowInfo, teamInfo) return '|-' .. teamRowInfo.rowStyle .. '\
 * ' .. teamRowInfo.seedText .. '' .. teamInfo.name .. '\
 * ' .. teamInfo.wins .. ' || ' .. teamInfo.losses .. '\
 * ' .. teamRowInfo.winningPercentage .. '\
 * ' .. teamRowInfo.gamesBehind .. '\
 * ' .. teamInfo.homeWins .. '–' .. teamInfo.homeLosses ..'\
 * ' .. teamInfo.roadWins .. '–' .. teamInfo.roadLosses .. '\n'

end, -- function generateTeamRow.default

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

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

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

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 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 == 'winLossOnlyNoNavbar') then outputFormat = 'winLossOnlyNoNavbar' fDisplayNavbar = false fDisplayGamesBehind = false end if (outputArg == 'wildCard2012') then outputFormat = 'wildCard2012' fDisplayNavbar = false end end

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

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 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 table.insert(listOfTeams, teamInfo) currentArgIdx = currentArgIdx + returnData.cIndicesRead end

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

local outputBuffer = { }

local tableHeaderInfo = { division = division, }

if (fDisplayNavbar) then local divisionForNavbox = division if (mlbData.abbreviationForDivision[division] ~= nil) then divisionForNavbox = mlbData.abbreviationForDivision[division] end local standingsPage = year .. ' ' .. divisionForNavbox .. ' standings' 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.name .. ' season', winningPercentage = string.format(               '%.3f', teamInfo.wins / ( teamInfo.wins + teamInfo.losses )            ), gamesBehind = '', seedText = '', rowStyle = '', }

if (fDisplayGamesBehind) then local halfGamesBehind = leadingHalfGames - (teamInfo.wins - teamInfo.losses) local prefix = nil -- if games behind is negative, take the absolute value and prefix a + -- character if (halfGamesBehind < 0) then halfGamesBehind = -halfGamesBehind prefix = '+' end if (halfGamesBehind == 0) then teamRowInfo.gamesBehind = '—' else -- if halfGamesBehind is not 0 teamRowInfo.gamesBehind = math.floor(halfGamesBehind / 2) if (halfGamesBehind % 2 == 1) then if (halfGamesBehind == 1) then teamRowInfo.gamesBehind = '½' else teamRowInfo.gamesBehind = teamRowInfo.gamesBehind .. '½'                   end end if ( prefix ~= nil ) then teamRowInfo.gamesBehind = prefix .. teamRowInfo.gamesBehind end end -- if halfGamesBehind is not 0 end -- if (fDisplayGamesBehind)

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

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