Edge Rewrite
// HTMLRewriter · presentation

This page was redesigned at the edge.

Cloudflare fetched the original article and streamed it through HTMLRewriter to apply an entirely new visual system without rebuilding the source page.

Jump to content

Module:Sports attendance

From Wikipedia, the free encyclopedia

-- Module to build tables for attendance in Sports
-- See documentation for details

require('strict')

local p = {}

-- Main function
function p.main(frame)
	-- Declare locals
    local getArgs = require('Module:Arguments').getArgs
	local Args = getArgs(frame, {parentFirst = true})
	local team_list = {['league'] = {name = 'League total', attendance = {}}}
	local sorted_teams = {}
	local t = {}
	local lang = mw.language.getContentLanguage()

	local templatestyles = frame:extensionTag{
		name = 'templatestyles', args = { src = 'Module:Sports attendance/styles.css' }
	}
    
    -- Load modules
	local yesno = require('Module:Yesno')
	local mm = require('Module:Math')
	    
    -- Form list of teams, stored under key of string following 'team_'
    for arg, value in pairs(Args) do
    	local tname = string.match(arg, '^team_(.+)')
       	if yesno(tname, true) then
			-- Initialise team in team_list
			team_list[tname] = {}
			table.insert(sorted_teams, tname)
			
        	-- Set team's name, with link stripped
        	local stripped_brackets = mw.ustring.gsub(value, '[%[%]]', '')
        	team_list[tname]['name'] = mw.ustring.gsub(stripped_brackets, '.-|', '') -- strip original page name
			team_list[tname]['sort_name'] = Args['data_sort_value_name_'..tname] or team_list[tname].name
           
        	-- Transform team's match attendances into numbers
        	local attendance = mw.text.split(Args['attendance_' .. tname] or '', '%s*[;,]%s*')
        	for i, att in ipairs(attendance) do
				if i == 1 then team_list[tname]['attendance'] = {} end -- Initialise team's attendance array
				
            	local att_num = tonumber(att)
            	team_list[tname]['attendance'][i] = att_num
            	table.insert(team_list['league']['attendance'], att_num)
        	end
           
        	-- Compute team's attendance stats for ranking
        	team_list[tname]['average'] = mm._average(unpack(attendance))
			team_list[tname]['median'] = mm._median(unpack(attendance))
			team_list[tname]['sum'] = mm._sum(unpack(attendance))
			team_list[tname]['max'] = mm._max(unpack(attendance))
			team_list[tname]['min'] = mm._min(unpack(attendance))
			team_list[tname]['range'] = (team_list[tname]['max'] or 0) - (team_list[tname]['min'] or 0)
        end
    end
    
    -- Compute league overall stats
    team_list['league']['average'] = mm._average(unpack(team_list['league'].attendance))
	team_list['league']['median'] = mm._median(unpack(team_list['league'].attendance))
	team_list['league']['sum'] = mm._sum(unpack(team_list['league'].attendance))
	team_list['league']['max'] = mm._max(unpack(team_list['league'].attendance))
	team_list['league']['min'] = mm._min(unpack(team_list['league'].attendance))
    
    -- Rank teams by average attendance
	table.sort(sorted_teams, function(a, b)
		-- If both teams do not have any attendance, sort alphabetically by sort_name
        if (not yesno(#team_list[a].attendance, true) and not yesno(#team_list[b].attendance, true)) then		return team_list[a].sort_name < team_list[b].sort_name
		end

		-- The team with no attendance is placed lower
        if not yesno(#team_list[a].attendance, true) then return false end
        if not yesno(#team_list[b].attendance, true) then return true end

		-- Sort by average if not identical
		if team_list[a].average ~= team_list[b].average then
			return team_list[a].average > team_list[b].average
		end

		-- Sort by median if not identical
		if team_list[a].median ~= team_list[b].median then
			return team_list[a].median > team_list[b].median
		end

		-- Sort by sum if not identical, to favour teams that have played more matches
		if team_list[a].sum ~= team_list[b].sum then
			return team_list[a].sum > team_list[b].sum
		end
			
		-- Sort by smaller range if not identical, to favour teams with more consistent attendance
		if team_list[a].range ~= team_list[b].range then
			return team_list[a].range < team_list[b].range
		end
        
        -- Otherwise, sort alphabetically by sort_name
        return team_list[a].sort_name < team_list[b].sort_name
    end)
	-- Add 'League total' to end of sorted_teams
	table.insert(sorted_teams, 'league')
    
    -- Create table header
    table.insert(t, '{| class="wikitable sortable" style="text-align:right;"\n')
    table.insert(t, '!width=25|<abbr title="Position">Pos</abbr>\n')
    table.insert(t, '!width=185|Team\n')
    table.insert(t, '!width=25|<abbr title="Home matches played">Pld</abbr>\n')
    table.insert(t, '!width=65|<abbr title="Total season attendance">Total</abbr>\n')
    table.insert(t, '!width=55|<abbr title="Highest season attendance">High</abbr>\n')
    table.insert(t, '!width=55|<abbr title="Lowest season attendance">Low</abbr>\n')
    table.insert(t, '!width=55|<abbr title="Median season attendance">Median</abbr>\n')
    table.insert(t, '!width=55|<abbr title="Average season attendance">Average</abbr>\n')
    table.insert(t, '!width=55|<abbr title="Change in average attendance in comparison with the previous season">Change</abbr>\n')
    
    -- Create data rows
    for pos, tname in ipairs(sorted_teams) do
        local any = yesno(#team_list[tname].attendance, true) -- Check if any attendance data is available for the team
        local total = tname == 'league'
        if total then
            -- Total row formatting
            table.insert(t, '|-class="sortbottom" style="background-color:#d8edf3; font-weight:bold;"\n')
        else
            -- Team row formatting
            table.insert(t, '|-\n')
        end
        table.insert(t, '| style="text-align:center;" |'..(any and not total and pos or '')..'\n')
        table.insert(t, '| style="text-align:left;" |'..(Args['team_'..tname] or team_list[tname].name)..'\n') -- Team name or table footer row name
        table.insert(t, '| style="text-align:center;" |'..(any and #team_list[tname].attendance or '')..'\n')
        table.insert(t, '| '..(any and lang:formatNum(team_list[tname].sum) or '')..'\n')
        table.insert(t, '| '..(any and lang:formatNum(team_list[tname].max) or '')..'\n')
        table.insert(t, '| '..(any and lang:formatNum(team_list[tname].min) or '')..'\n')
        table.insert(t, '| '..(any and lang:formatNum(team_list[tname].median) or '')..'\n')
		table.insert(t, '| style="font-weight:bold" | '..(any and lang:formatNum(mm._round(team_list[tname].average, 0)) or '')..'\n')
		-- No newline at end of {{change}} for note to be tacked on
		if yesno(Args['previous_'..tname], true) then
			if yesno(#team_list[tname].attendance, true) then -- Checking attendance list instead of average since 0 attendance with matches is possible
	        	table.insert(t, '| '..(any and frame:expandTemplate{title='change', args={Args['previous_'..tname], team_list[tname].average, disp='out', dec=1}}))
			else
				table.insert(t, '| style="text-align:center" | ')
			end
        else
        	table.insert(t, '| style="text-align:center" | n/a')
        end
        if yesno(Args['note_'..tname], true) then
            table.insert(t, frame:expandTemplate{title='efn', args={group='lower-alpha', Args['note_'..tname]}})
		end
		table.insert(t, '\n') -- end change cell
    end

	-- Close table
	table.insert(t, '|}')
    
    -- Create footer
	local note_list = {}
    if yesno(Args['updated'], true) then
        table.insert(note_list, 'Updated to match(es) played on '..Args['updated']..'.')
    end
	
    if yesno(Args['source'], true) then
        table.insert(note_list, 'Source: '..Args['source'])
	else
		table.insert(note_list, 'Source: '..frame:expandTemplate{title='Citation needed', args={date=lang:formatDate('F Y')}}..'\n')
    end
	local t_footer = '<div class="sports-attendance-notes">'..table.concat(note_list, ' ')..'</div>'..frame:expandTemplate{title='notelist', args={group='lower-alpha'}}

	return templatestyles..'\n'..table.concat(t)..t_footer
end

return p