-- This module implements .
local yesno = require('Module:Yesno')
--------------------------------------------------------------------------------- Helper functions-------------------------------------------------------------------------------
local function abbr(shortForm, longForm) return tostring(mw.html.create('abbr') :attr('title', longForm) :wikitext(shortForm) )end
--------------------------------------------------------------------------------- Team class-------------------------------------------------------------------------------
local Team = Team.__index = Team
Team.stringFields =
Team.numberFields =
function Team.new(options) options = options or local self = setmetatable(Team) for i, field in ipairs(Team.stringFields) do self[field] = options[field] end for i, field in ipairs(Team.numberFields) do self[field] = tonumber(options[field]) end return selfend
function Team:getPosition return tostring(self.pos) or '--'end
function Team:getShortName return self.shortend
function Team:getName return self.nameend
function Team:getLink local name = self:getName local link = self.link if link and name then return string.format('%s', link, name) elseif link then return string.format('%s', link) else return name endend
function Team:makeDisplayName local ret = self:getLink if not ret then return nil end local clinches = -- The numerical syntax here is a hangover from the wikitext template -- which used #expr hacks to calculate the number of clinches if self.clinch_playoff
2 then table.insert(clinches, 'c') end if self.clinch_division
1 then table.insert(clinches, 'z') end if clinches[1] then ret = string.format("%s - %s", ret, table.concat(clinches)) end return retend
function Team:getHomeWins return self.home_win or 0end
function Team:getHomeLosses return self.home_loss or 0end
function Team:getRoadWins return self.road_win or 0end
function Team:getRoadLosses return self.road_loss or 0end
function Team:getGamesPlayed return self:getHomeWins + self:getRoadWins + self:getHomeLosses + self:getRoadLossesend
function Team:getWins return self:getHomeWins + self:getRoadWinsend
function Team:getLosses return self:getHomeLosses + self:getRoadLossesend
function Team:_divideByGamesPlayed(val) local gp = self:getGamesPlayed if gp > 0 then -- avoid divide-by-zero error return val / gp else return 0 endend
function Team:getWinPercentage local percent = self:_divideByGamesPlayed(self:getWins) if percent > 1 then percent = 1 elseif percent < 0 then percent = 0 end local ret = string.format('%.3f', percent) if ret:sub(1, 1)
function Team:getGamesBack(teamInFirst) local tifDiff = teamInFirst:getWins - teamInFirst:getLosses local selfDiff = self:getWins - self:getLosses return string.format('%.1f', (tifDiff - selfDiff) / 2)end
function Team:getHomeRecord return self:getHomeWins .. ' - ' .. self:getHomeLossesend
function Team:getRoadRecord return self:getRoadWins .. ' - ' .. self:getRoadLossesend
function Team:getGoalsScored return self.gf or 0end
function Team:getGoalsAllowed return self.ga or 0end
function Team:getDifferential local diff = self:getGoalsScored - self:getGoalsAllowed if diff > 0 then return '+' .. tostring(diff) else return '−' .. tostring(-diff) endend
function Team:getGameScoredAverage local avg = self:_divideByGamesPlayed(self:getGoalsScored) return string.format('%.2f', avg)end
function Team:getGameAllowedAverage local avg = self:_divideByGamesPlayed(self:getGoalsAllowed) return string.format('%.2f', avg)end
--------------------------------------------------------------------------------- DivisionStanding class-------------------------------------------------------------------------------
local DivisionStanding = DivisionStanding.__index = DivisionStanding
function DivisionStanding.new(args) local self = setmetatable(DivisionStanding)
-- Set template-wide arguments self.division = args.division self.conference = args.conference self.team = args.team self.hideLegend = yesno(args.hideLegend, false)
-- Separate args starting with "team" by team number. local teamArgs = for k, v in pairs(args) do if type(k)
-- Make the team objects self.teams = for num, t in pairs(teamArgs) do self.teams[num] = Team.new(t) end
-- Find the first-place team if it has been specified self.teamInFirst = tonumber(args.teamInFirst) if self.teamInFirst then self.teamInFirst = self.teams[self.teamInFirst] end
-- Compress the teams array, which at the moment may contain nils self.teams = (function (t) local nums, ret =, for num in pairs(t) do nums[#nums + 1] = num end table.sort(nums) for i, num in ipairs(nums) do ret[i] = t[num] end return ret end)(self.teams)
-- Assume the first-place team is the first team in the teams array if it -- was not specified earlier if not self.teamInFirst then self.teamInFirst = self.teams[1] end
return selfend
function DivisionStanding:__tostring local root = mw.html.create local tableRoot = root:tag('table') tableRoot :addClass('wikitable sortable') :css('width', '65%')
-- Caption if self.division then tableRoot:tag('caption') :wikitext(self.division) :wikitext(' Division') elseif self.conference then tableRoot:tag('caption') :wikitext(self.conference) :wikitext(' Conference') end
-- Headers local headerRow = tableRoot:tag('tr') local function addHeader(display, width, sort) headerRow:tag('th') :css('width', tostring(width) .. '%') :attr('data-sort-type', sort) :wikitext(display) end addHeader(abbr('P', 'Position'), 4, 'number') addHeader('Team', 38, 'text') addHeader('GP', 4, 'number') addHeader('W', 4, 'number') addHeader('L', 4, 'number') addHeader('PCT', 5, 'number') addHeader('GB', 5, 'number') addHeader('Home', 6, 'number') addHeader('Road', 6, 'number') addHeader('GF', 4, 'number') addHeader('GA', 4, 'number') addHeader(abbr('Diff', 'Differential'), 4, 'number') addHeader('GF/GP', 6, 'number') addHeader('GA/GP', 6, 'number')
-- Empty header row. This is purely to hold the up-down arrow icons added -- with the "sortable" class, which helps to keep the table width down. local emptyHeaderRow = tableRoot:tag('tr') emptyHeaderRow:tag('th'):tag('br',) for i = 1, 13 do emptyHeaderRow:tag('th') end
-- Rows local function addTeamCell(teamRow, val, align) teamRow:tag('td') :css('text-align', align) :wikitext(val) end for i, team in ipairs(self.teams) do if team:getLink then local teamRow = tableRoot:tag('tr') teamRow :css('text-align', 'center') :css('background-color', self.team and self.team
-- Legend if not self.hideLegend then local function makeLegend(key, val) return string.format("%s: %s", key, val) end root:newline root:tag('small') :wikitext(table.concat('; ')) :tag('br',):done :wikitext(table.concat('; ')) :tag('br',):done :wikitext(table.concat('; ')) end
return tostring(root)end
--------------------------------------------------------------------------------- Exports-------------------------------------------------------------------------------
local p =
function p._main(args) return tostring(DivisionStanding.new(args))end
function p.main(frame) local args = require('Module:Arguments').getArgs(frame,) return p._main(args)end
return p