モジュール:Television ratings graph

-- This module implements .
local contrast_ratio = require('Module:Color contrast')._ratio
--------------------------------------------------------------------------------
-- 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  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  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
	
	-- Number of actual viewer numbers
	local numberargs = 0
	for k,v in pairs(args) do 
		if not string.match(k,'^%d+') and not string.match(v,'^%d\.+') then numberargs = numberargs + 1 end
	end
	-- 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
	-- Determine number of episodes
	local num_episodes
		-- Subtract averages if included (they should be equal to the number of seasons)
		if average == 1 then
			num_episodes = numberargs-num_seasons
		else
			num_episodes = numberargs
		end
	-- Bar width
	local barwidth
	if num_episodes = 20 and num_episodes = 50 and num_episodes = 80 then barwidth = 5
	end
	-- Graph width
	local graphwidth
	if args.bar_width == nil then
		if num_episodes = 20 and num_episodes = 50 and num_episodes = 80 then graphwidth = num_episodes*10+98
		end
	else
		if num_episodes = 20 and num_episodes = 50 and num_episodes = 80 then graphwidth = num_episodes*(10+args.bar_width-barwidth)+98
		end
	end
	-- Basis parameters
	timeline = timeline .. "ImageSize  = width:" .. (args.width or graphwidth) .. " 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:gray value:gray(0.7)\n"
	
	-- Colour and legend variables
	local season = 1
	for season = 1,num_seasons do 
		local r,g,b = TVRG.hex2rgb(args'color' .. season or '#006600')
		
		local GraphLegend = season_title .. " " .. season
		if args"legend" .. season then
			local legendKey = string.sub(args"legend" .. season, 0, 1)
			if type(tonumber(legendKey)) == "number" then
				GraphLegend = season_title .. " " .. args"legend" .. season
			else
				GraphLegend = args"legend" .. season
			end
		end
		
		timeline = timeline .. " id:season" .. season .. " value:rgb("..r..","..g..","..b..") " ..
			(args.hidelegend == nil and "legend:" .. string.gsub(string.gsub(GraphLegend, ' ', '_'), "(.-)", '%1') or ) .. "\n"
		season = season + 1
	end
	-- Determine maximum viewer figure
	local maxviewers = -1
	local multiple = 'millions'
	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
	if maxviewers  longestseason then
					longestseason = thisseason
				end
				thisseason = 0
			elseif average == 0 or (average == 1 and argsk+1 ~= '-' and argsk+1 ~= nil) then
				-- Include white/black bar to act as border
				local black_cr = contrast_ratio{args'color' .. season, 'black', 'error' = 0}
				local white_cr = contrast_ratio{'white', args'color' .. season, 'error' = 0}
				local bgrnd_cr = (black_cr > white_cr and 'black' or 'gray')
	
				timeline = timeline .. "  mark:(line," .. bgrnd_cr .. ")\n"
				timeline = timeline .. "  color:" .. bgrnd_cr .. "\n"
				timeline = timeline .. "  bar:" .. bar .. " width:" .. ((args.bar_width or barwidth)+2) .. " from:start till:" .. (v ~=  and v or 'start') .. "\n"
				
				-- Include bar for viewer figure, do not include if averages are included and the next parameter is a new season marker
				timeline = timeline .. "  color:season" .. season .. "\n"
				timeline = timeline .. "  bar:" .. bar .. " from:start till:" .. (v ~=  and v or 'start') .. "\n"
				
				-- Increment tracking variables
				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
	
	-- Axis labels
	local countryDisplayUS, countryDisplayUK, countryDisplayOther
	if args.country ~= nil and args.country ~=  then
		if args.country == "U.S." or args.country == "US" or args.country == "United States" then countryDisplayUS = 'U.S.'
		elseif args.country == "U.K." or args.country == "UK" or args.country == "United Kingdom" then countryDisplayUK = 'U.K.'
		else countryDisplayOther = args.country
		end
	end
	timeline = timeline .. "TextData =\n"
	timeline = timeline .. "  pos:(" .. ((args.width or graphwidth)/2-18) .. ",45) textcolor:black fontsize:S text:Episode\n"
	timeline = timeline .. "  pos:(10," .. ((args.height or 300)-10) .. ") textcolor:black fontsize:S text:" .. ((countryDisplayUS or countryDisplayUK or countryDisplayOther) or "") .. ((countryDisplayUS or countryDisplayUK or countryDisplayOther) and " v" or "V") .. "iewers (" .. multiple .. ")\n"
	
	-- 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
			root:wikitext("" .. args.title .. "" .. frame:expandTemplate{ title = 'hsp' } ..
				  ": " .. ((countryDisplayUS or countryDisplayUK or countryDisplayOther) or "") .. ((countryDisplayUS or countryDisplayUK or countryDisplayOther) and "" or "") .. "エピソード別視聴者数 (" .. multiple .. ")")
		else
			root:wikitext("エピソード別視聴者数 (" .. multiple .. ")")
		end
	-- Add timeline to div
	if args.no_graph == nil then
		root:node(frame:extensionTag('timeline', timeline))
	end
	
	-- Create ratings table
	if args.no_table == nil then
		local rtable = mw.html.create('table')
		   	:addClass('wikitable')
			:css('text-align', 'center')
		
			-- Create headers rows
			local row = rtable:tag('tr')
			row:tag('th'):wikitext(season_title)
				:attr('colspan','2')
				:attr('rowspan','2')
				:css('padding-left', '.8em')
				:css('padding-right', '.8em')
				
			row:tag('th')
				:attr('colspan',longestseason)
				:wikitext("エピソード番号")
				:css('padding-left', '.8em')
				:css('padding-right', '.8em')
				
			-- Average column
			if average == 1 then
				row:tag('th')
				   :attr('scope','col')
				   :attr('rowspan','2')
				   :wikitext("平均")
				   :css('padding-left', '.8em')
				   :css('padding-right', '.8em')
			end
			local row = rtable:tag('tr')
			
			for i = 1,longestseason do
				row:tag('th')
				   :attr('scope','col')
				   :wikitext(i)
			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 argsk+1 == nil) then
					if season > 1 then
						-- Spanning empty cells with 
						if thisseason ニールセン・メディア・リサーチによる視聴率計測" .. (args.refs or tostring(span)))
	elseif countryDisplayUK then
		root:wikitext("Broadcasters' Audience Research Boardによる視聴率計測" .. (args.refs or tostring(span)))
	else
		root:wikitext("出典: " .. (args.refs or tostring(span)))
	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