Jump to content

Module:Television ratings graph/sandbox

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Alex 21 (talk | contribs) at 11:42, 24 January 2017. The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
-- This module implements {{Television ratings graph}}.

--------------------------------------------------------------------------------
-- TVRG class
-- The main class.
--------------------------------------------------------------------------------

local TVRG = {}

-- Convert HEX codes to RGB values
function TVRG.hex2rgb(hex)
    hex = hex:gsub('#', '')
    if #hex == 3 then
    	-- #000 format
    	return tonumber("0x"..hex:sub(1,1)..hex:sub(1,1))/256, tonumber("0x"..hex:sub(2,2)..hex:sub(2,2))/256,
    		   tonumber("0x"..hex:sub(3,3)..hex:sub(3,3))/256
	else
    	-- #000000 format
    	return tonumber("0x"..hex:sub(1,2))/256, tonumber("0x"..hex:sub(3,4))/256, tonumber("0x"..hex:sub(5,6))/256
    end
end

-- Allow usages of {{N/A}} cells
function TVRG.NACell(frame,text)
	local cell = mw.html.create('td')
	local attrMatch = '([%a-]*)="([^"]*)"'
	
	infoParam = frame:expandTemplate{title='N/A',args={text}}
	
	-- Gather styles of {{N/A}} and assign to node variable
	while true do
		local a,b = string.match(infoParam,attrMatch)
		if a == nil or b == nil then break end
		cell:attr(a,b)
		infoParam = string.gsub(infoParam,attrMatch,'',1)
	end

	infoParam = string.gsub(infoParam,'%s*|%s*','',1)
	cell:wikitext(infoParam)
	
	return cell
end

-- Create the graph and table
function TVRG.new(frame,args)
	args = args or {}
	
	-- Variables
	local timeline = ''
	local longestseason = -1
	local average = args.average and 1 or 0
	local season_title = args.season_title or 'Season'
	local root = mw.html.create('div')
		:attr('align', 'center')
	
	-- Create the timeline
	if args.nograph == nil then
		-- Bar width
		local barwidth
		if #args < 20 then barwidth = 8
		elseif #args > 75 then barwidth = 6
		else barwidth = 7 end
		
		-- Basis parameters
		timeline = timeline .. "ImageSize  = width:" .. (args.width or 1000) .. " height:" .. (args.height or 300) .. "\n"
		timeline = timeline .. "PlotArea   = left:50 bottom:70 top:20 right:50\n"
		timeline = timeline .. "AlignBars  = justify\n"
		
		timeline = timeline .. "Colors     =\n"
		timeline = timeline .. " id:a value:gray(0.7)\n"
		
		-- Determine number of seasons
		local num_seasons = -1
		for k,v in pairs(args) do
			local thisseason = tonumber(string.sub(k,6))
			if string.sub(k,1,5) == 'color' and thisseason > num_seasons then
				num_seasons = thisseason
			end
		end
		
		-- Colour and legend variables
		local season = 1
		for season = 1,num_seasons do 
			local r,g,b = TVRG.hex2rgb(args['color' .. season] or '#006600')
			timeline = timeline .. " id:season" .. season .. " value:rgb("..r..","..g..","..b..") legend:" ..
				string.gsub(string.gsub((args["legend" .. season] or season_title .. " " .. season), ' ', '_'), "''(.-)''", '%1') .. "\n"
			season = season + 1
		end
	
		-- Determine maximum viewer figure
		local maxviewers = -1
		for k,v in pairs(args) do
			local num = tonumber(v)
			if tonumber(k) ~= nil and num ~= nil and num > maxviewers then
				maxviewers = num
			end
		end
	
		-- Further parameters, with rounded-up viewer figures as maximum period
		timeline = timeline .. "DateFormat = x.y\n"
		timeline = timeline .. "Period     = from:0 till:" .. math.ceil(maxviewers) .. "\n"
		timeline = timeline .. "TimeAxis   = orientation:vertical\n"
		timeline = timeline .. "ScaleMajor = gridcolor:a increment:1 start:0\n"
		timeline = timeline .. "Legend     = orientation:horizontal\n"
		
		-- Interval parameter set to prevent overlapping bars
		local bar = 1
		if args.intervals then
			timeline = timeline .. "BarData    =\n"
			for k,v in pairs(args) do
				if tonumber(k) ~= nil and (tonumber(v) ~= nil or v == '') then
					timeline = timeline .. "  bar:"..bar.."  text:"..((bar == 1 or bar % args.intervals == 0) and bar or '&nbsp;').."\n"
					bar = bar + 1
				end
			end
		end
	
		-- Plot data
		timeline = timeline .. "PlotData   =\n"
		timeline = timeline .. "  width:" .. barwidth .. "\n"
		
		-- Add bars to timeline, one per viewer figure
		local bar = 1
		local season = 1
		local thisseason = 0
		
		for k,v in pairs(args) do
			if tonumber(k) ~= nil then
				if v == '-' then
					-- Hyphen means new season, so change colour
					timeline = timeline .. "  color:season" .. season .. "\n"
					season = season + 1
					-- Determine highest number of episodes in a season
					if thisseason > longestseason then
						longestseason = thisseason
					end
					thisseason = 0
				elseif average == 0 or (average == 1 and (args[k+1] == '-' or args[k+1] == nil) == false) then
					-- Include bar for viewer figure, do not include if averages are included and the next parameter is a new season marker
					timeline = timeline .. "  bar:" .. bar .. " from:start till:" .. (v ~= '' and v or 'start') .. "\n"
					thisseason = thisseason + 1
					bar = bar + 1
				end
			end
		end
		-- Determine highest number of episodes in a season after final season's bars
		if thisseason > longestseason then
			longestseason = thisseason
		end
		
		-- Add timeline to div
		root:node(frame:extensionTag('timeline', timeline))
	end
	
	-- Create ratings table
	if args.notable == nil then
		local rtable = mw.html.create('table')
		   	:addClass('wikitable')
			:css('text-align', 'center')
		
		-- If there's a title, add it with the viewers caption, else just display the viewers caption by itself
		if args.title ~= nil and args.title ~= '' then
			rtable:tag('caption'):wikitext("''" .. args.title .. "''" .. frame:expandTemplate{ title = 'hsp' } .. ": Viewers per episode (millions)")
		else
			rtable:tag('caption'):wikitext("Viewers per episode (millions)")
		end
		
		-- Headers rows for episodes 1 to highest number of episodes
		local row = rtable:tag('tr')
		row:tag('th'):wikitext(season_title)
			:attr('colspan','2')
		
		for i = 1,longestseason do
			row:tag('th')
			   :attr('scope','col')
			   :wikitext(frame:expandTemplate{ title='abbr', args={ 'Ep.', 'Episode' } } .. ' ' .. i)
		end
		
		-- Average column
		if average == 1 then
			row:tag('th')
			   :attr('scope','col')
			   :wikitext("''Average''")
		end
		
		local season = 1
		local thisseason = 0
		
		-- Create table rows and cells
		for k,v in pairs(args) do
			if tonumber(k) ~= nil then
				-- New season marker, or final episode rating
				if v == '-'  or (average == 1 and args[k+1] == nil) then
					if season > 1 then
						-- Spanning empty cells with {{N/A}}
						if thisseason < longestseason then
							row:node(TVRG.NACell(frame,"N/A"):attr('colspan',longestseason-thisseason))
						end
						
						if average == 1 then
							-- If averages included, then set the averages cell with value or TBD
							if v ~= '' then
								row:tag('td'):wikitext(args[k+1] ~= nil and args[k-1] or v)
							else
								row:node(TVRG.NACell(frame,"TBD"))
							end
							thisseason = thisseason + 1
						end
					end
					
					-- New season marker
					if v == '-' then
						-- New row with default or preset caption
						row = rtable:tag('tr')
						row:tag('th')
							:css('background-color', args['color' .. season])
							:css('width','10px')
						
						row:tag('th')
						   :attr('scope','row')
						   :wikitext(args["legend" .. season] and args["legend" .. season] or season)
						
						thisseason = 0
						season = season + 1
					end
				elseif average == 0 or (average == 1 and args[k+1] ~= '-' and args[k+1] ~= nil) then
					-- Viewer figures, either as a number or TBD
					if v ~= '' then
						row:tag('td'):wikitext(v)
					else
						row:node(TVRG.NACell(frame,"TBD"))
					end
					thisseason = thisseason + 1
				end
			end
		end
		
		-- Finish by checking if final row needs {{N/A}} cells
		if thisseason < longestseason then
			row:node(TVRG.NACell(frame,"N/A"):attr('colspan',longestseason-thisseason))
		end
		
		-- Add table to div root and return
		root:node(rtable)
	end
	
	return tostring(root)
end

--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------

local p = {}

function p.main(frame)
	local args = require('Module:Arguments').getArgs(frame, {
		removeBlanks = false,
		wrappers = 'Template:Television ratings graph'
	})
	return TVRG.new(frame,args)
end

return p