Module:CricketLeagueGroupStageSummary/sandbox
Appearance
![]() | This is the module sandbox page for Module:CricketLeagueGroupStageSummary (diff). See also the companion subpage for test cases (run). |
Example
{{#invoke: CricketLeagueGroupStageSummary|IPL <!-- home | away | result | margin | DL --> | MI | KKR | A | 41R | N | KKR | MI | A | 2W | N | MI | CSK | T | | Y | CSK | MI | H | SO | N | KKR | CSK | N | | N | CSK | KKR | | | }}
Visitor team → | CSK | KKR | MI |
---|---|---|---|
Home team ↓ | |||
Chennai Super Kings | Match 6 | Chennai Super Over | |
Kolkata Knight Riders | Match abandoned | Mumbai 2 wickets | |
Mumbai Indians | Match tied | Kolkata 41 runs |
Home team won | Visitor team won |
- Note: Results listed are according to the home (horizontal) and visitor (vertical) teams.
- Note: Click on a result to see a summary of the match.
local _module = {}
-- The error buffer. It contains all the errors accumulated when the table was generated. addError() adds an error to the buffer
local errors
local errorIndex = 1
local addError = function(msg, matchID)
errors = errors or {}
if matchID then
errors[errorIndex] = string.format('* <span class="error" style="font-weight: normal">Error (match %s): %s</span>\n', matchID, msg)
else
errors[errorIndex] = string.format('* <span class="error" style="font-weight: normal">Error: %s</span>\n', msg)
end
errorIndex = errorIndex + 1
end
local cricmatch = {}
cricmatch.__index = function(t, key)
local ret = rawget(t, key)
if ret then
return ret
end
ret = cricmatch[key]
if type(ret) == 'function' then
return function(...)
return ret(t, ...)
end
else
return ret
end
end
cricmatch.getMargin = function(m)
if not m.margin then
addError("The result 'H' or 'A' requires a margin.", id)
elseif m.margin == 'F' then return "Forfeited"
elseif m.superover then return "Super Over"
else
-- The text appended to the margin string if the match's 'dl' parameter is true
local dlString = m.dl and ' <span style="font-size: 85%">(D/L)</span>' or ""
local n, t = tonumber(string.sub(m.margin, 1, -2)), string.upper(string.sub(m.margin, -1, -1))
if not n then
addError("Margin must be a valid number suffixed with R or W.", id)
elseif t == 'R' then
return string.format("%d runs%s", n, dlString)
elseif t == 'W' then
return string.format("%d wickets%s", n, dlString)
elseif t == 'I' then
if isLimitedOvers then
addError("A margin suffixed with 'I' cannot be used in limited-overs formats.", m.id)
else
return string.format("Inns & %d runs%s", n, dlString)
end
else
addError("Margin must be 'F', or a valid number suffixed with 'R', 'W' or 'I'.", m.id)
end
end
return nil -- Return nil in case of an error
end
cricmatch.getResult = function(m, row)
-- Result not provided
if not m.result then
addError("Missing parameter: 'result'.")
addErrorCell(row, m.id)
return
end
-- Match has not been played yet
if m.result == 'X' then
addTableCell(row, notPlayedColour, string.format('[[#match%s|Match %s]]', m.id, m.id))
.css('padding', '3px 5px')
.css('line-height', '300%')
elseif m.result == 'D' then
-- Drawn match
if isLimitedOvers then
-- No draws in limited-overs matches
addError("The result 'D' cannot be used in limited-overs formats.", m.id)
addErrorCell(row, m.id)
else
addTableCell(row, drawColour, string.format('[[#match%s|Match drawn]]', m.id))
.css('padding', '3px 5px')
.css('line-height', '300%')
end
elseif m.result == 'N' then
-- Abandoned match
addTableCell(row, noResultColour, string.format('[[#match%s|Match<br />abandoned]]', m.id))
.css('padding', '3px 5px')
elseif m.result == 'T' then
-- Tied match
addTableCell(row, tieColour, string.format('[[#match%s|Match tied]]', m.id))
.css('padding', '3px 5px')
elseif m.result == 'H' then
-- Home team wins
local margin = m.getMargin()
if margin then
addTableCell(row, homeWinColour, string.format('%s<br />[[#match%s|%s]]', m.home.shortName, m.id, margin))
.css('padding', '3px 5px')
else addErrorCell(row, m.id) end
elseif m.result == 'A' then
-- Away team wins
local margin = m.getMargin()
if margin then
addTableCell(row, awayWinColour, string.format('%s<br />[[#match%s|%s]]', m.home.shortName, m.id, margin))
.css('padding', '3px 5px')
else addErrorCell(row, m.id) end
else -- Invalid result
addError("Invalid result: '" .. m.result .. "'. Expected: H, A, X, N, D or T.", m.id)
addErrorCell(row, m.id)
end
end
function createMatch(data)
local match = {}
setmetatable(match, cricmatch)
match.id = data.match
match.home = data.home
match.away = data.away
match.result = data.result
match.margin = data.margin
match.dl = data.dl
match.superover = data.superover
return match
end
---------- Background colours for table cells ----------
local noMatchColour = "#C0C0C0" -- No match defined
local homeWinColour = "#CCCCFF" -- Home team wins
local awayWinColour = "#FFCCCC" -- Away team wins
local noResultColour = "#FFDEAD" -- Match abandoned
local drawColour = "#F0E68C" -- Match drawn
local tieColour = "#DDFFDD" -- Match tied
local notPlayedColour = "inherit" -- Not played yet
local errorColour = "#FF7777" -- Error
---------- Html Builder ----------
local htmlBuilder = require('Module:HtmlBuilder')
function addTableRow(tbl)
return tbl.tag('tr')
end
function addTableCell(row, bg, text)
return row.tag('td').css('background-color', bg).wikitext(text)
end
function addNoMatch(row)
addTableCell(row, noMatchColour, '')
return row
end
function addErrorCell(row, id)
addTableCell(row, errorColour, string.format('[[#match%s|Match %s]]', id, id))
.css('padding', '3px 5px')
.css('line-height', '300%')
return row
end
function buildLegend(container, isLimitedOvers)
local key = container.tag('table')
.addClass('wikitable')
.css('float', 'right')
.css('text-align', 'center')
.css('font-size', '90%')
if isLimitedOvers then
key.css('width', '30%')
local row
row = addTableRow(key)
addTableCell(row, homeWinColour, 'Home team won').css('width', '50%')
addTableCell(row, awayWinColour, 'Visitor team won').css('width', '50%')
row = addTableRow(key)
addTableCell(row, noResultColour, 'Match abandoned')
addTableCell(row, tieColour, 'Match tied')
else
local row
row = addTableRow(key)
addTableCell(row, homeWinColour, 'Home team won').css('width', '33%')
addTableCell(row, awayWinColour, 'Visitor team won').css('width', '34%')
addTableCell(row, noResultColour, 'Match drawn')
.css('width', '33%')
.attr('rowspan', '2')
row = addTableRow(key)
addTableCell(row, tieColour, 'Match abandoned')
addTableCell(row, drawColour, 'Match tied')
end
local list = container.tag('ul')
.css('font-size', '90%')
.tag('li')
.wikitext("'''Note''': Results listed are according to the home (horizontal) and visitor (vertical) teams.")
.done()
.tag('li')
.wikitext("'''Note''': Click on a result to see a summary of the match.")
.done()
return container
end
_module.create = function(frame, title, teams, isLimitedOvers, tableStyle, useWebSlice)
---------- Functions ----------
local strMatch = string.match
local strFind = string.find
local yesno = require("Module:Yesno")
-- The table containing all the matches, looked up by home and away teams.
local matches = {}
-- Matches which have been defined have a 'true' value for their match number key in this table.
local matchIDs = {}
-- This is used to lookup team objects by name
local teamLookup = {}
-- The total number of teams
local teamCount = #teams
-- Sort the teams and create the lookup table
local teamSorter = function(t1, t2)
return t1.fullName < t2.fullName
end
table.sort(teams, teamSorter)
for i = 1, teamCount do
local teamObj = teams[i]
teamLookup[teamObj.code] = teamObj
teamLookup[teamObj.shortName] = teamObj
teamLookup[teamObj.fullName] = teamObj
end
-- Parse the rows
for i, row in ipairs(frame.args) do
local matchData = {}
-- Key/value pairs for each row are separated by semicolons, and a colon separates the key from the value.
local semicolon = 0
repeat
local start = semicolon + 1
semicolon = strFind(row, ';', start, true) or 0
local colon = strFind(row, ':', start, true)
if colon and (colon < semicolon or semicolon == 0) then
matchData[strMatch(string.sub(row, start, colon - 1), '^%s*(.-)%s*$')] = strMatch(string.sub(row, colon + 1, semicolon - 1), '^%s*(.-)%s*$')
end
until semicolon == 0
local hasError = false
local id = matchData.match
if not id then
addError(strFormat("Parameter #%d does not have a match number.", i))
hasError = true
end
-- Get the home and away teams for the match.
local home, away, t
t = matchData.home
if t then
home = teamLookup[t]
if not home then
addError("The team '" .. t .. "' does not exist.", id)
hasError = true
end
else addError("Missing parameter: 'home'."); hasError = true end
t = matchData.away
if t then
away = teamLookup[t]
if not away then
addError("The team '" .. t .. "' does not exist.", id)
hasError = true
end
else addError("Missing parameter: 'away'."); hasError = true end
if home == away then -- Home and away teams cannot be the same.
addError("Invalid match (home and away teams are equal).", id)
hasError = true
elseif matchIDs[id] then -- A match with the given match number is already defined
addError("A match with this match number has already been defined.", id); hasError = true
end
if not hasError then -- If there is no error, store the match in the matches table.
matchIDs[id] = true
if not matches[home] then matches[home] = {} end
matches[home][away] = createMatch(matchData)
end
end
-- Construct the header
local container = htmlBuilder.create('div')
.css('float', 'left')
local tbl = container.tag('table')
.attr('class', 'wikitable')
.cssText(tableStyle or "text-align: center; white-space: nowrap; width: 100%")
local header = addTableRow(tbl)
.tag('th')
.attr('scope', 'row')
.wikitext('Visitor team →')
.done()
for i = 1, teamCount do
local team = teams[i]
header.tag('th')
.attr('rowspan', '2')
.attr('scope', 'col')
.css('padding', 'inherit 10px')
.wikitext(string.format('[[%s|%s]]', team.pageName, team.code))
.newline()
end
tbl.tag('tr')
.tag('th')
.attr('scope', 'col')
.wikitext('Home team ↓')
-- Output the main body of the table
for i = 1, teamCount do
-- Each row starts with a home team header
local home = teams[i]
local noHomeMatches = not matches[home]
local row = addTableRow(tbl)
local teamcell = row.tag('th')
.attr('scope', 'row')
.css('text-align', 'left')
.css('padding', '3px 5px')
.css('white-space', 'normal')
.wikitext(string.format('[[%s|%s]]', home.pageName, home.fullName))
if noHomeMatches then
teamcell.css('line-height', '275%')
for j = 1, teamCount do
addNoMatch(row)
end
else
for j = 1, teamCount do
local away = teams[j]
local match = matches[home][away]
if match then
match.getResult(row)
else
addNoMatch(row)
end
end
end
end
-- Legend and notes
buildLegend(container, isLimitedOvers)
local output = tostring(container) .. '<div style="clear: both"></div>'
if useWebSlice then
output = frame:expandTemplate({ title = "WebSlice-begin", args = { id = "427", title = name } })
.. output
.. frame:expandTemplate({ title = 'WebSlice-end', args = {} })
end
-- If there are errors, output them and insert a tracking category
if errorIndex ~= 1 then
output = string.format('<div class="plainlist">\n%s</div>[[Category:Pages with errors reported by Module:CricketLeagueGroupStageSummary]]\n', table.concat(errors)) .. output
end
return output
end
_module.test = function(frame, title, teams, isLimitedOvers, tableStyle, useWebSlice)
return self.create(frame, title, teams, isLimitedOvers, tableStyle, useWebSlice)
end
return _module