Jump to content

Module:Music ratings/sandbox

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Mr. Stradivarius (talk | contribs) at 04:17, 29 October 2016 (fix variable name). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
-- This module implements [[Template:Album ratings]].

local mTableTools = require('Module:TableTools')
local yesno = require('Module:Yesno')
local p = {}

local function makeCell(html, s)
	html
		:tag('td')
			:css('text-align', 'center')
			:css('vertical-align', 'middle')
			:wikitext(s)
end

local function makeRow(review, score)
	local row = mw.html.create('tr')
	makeCell(row, review)
	makeCell(row, score)
	return row
end

local function makeHeaderRow(header, background, scope)
	local row = mw.html.create('tr')
	row
		:tag('th')
			:attr('scope', scope ~= false and 'col' or nil)
			:attr('colspan', 2)
			:css('text-align', 'center')
			:css('background', background ~= false and '#d1dbdf' or nil)
			:css('font-size', '120%')
			:wikitext(header)
	return row
end

local function makeRatingHeaderRow()
	local row = mw.html.create('tr')
	row
		:tag('th')
			:attr('scope', 'col')
			:wikitext('Source')
			:done()
		:tag('th')
			:attr('scope', 'col')
			:wikitext('Rating')
	return row
end

local function getScore(scoreArgs, length)
	for i = 1, length do
		local arg = scoreArgs[i]
		if arg then
			return arg
		end
	end
	return nil
end

local function hasDuplicateScores(scoreArgs, length)
	local count = 0
	for i = 1, length do
		local arg = scoreArgs[i]
		if arg then
			count = count + 1
		end
	end
	return count > 1
end

local function ucfirst(s)
	local first = s:sub(1, 1)
	local others = s:sub(2, -1)
	return first:upper() .. others
end

local function getArgPermutations(args, prefix, num, suffix)
	local prefixUpper = ucfirst(prefix)
	local suffixUpper = ucfirst(suffix)
	return {
		args[prefix .. num .. suffix],
		args[prefixUpper .. num .. suffix],
		args[prefix .. num .. suffixUpper],
		args[prefixUpper .. num .. suffixUpper],
	}, 4
end

local function makeWikilink(page, display)
	if not page and not display then
		error('no arguments provided to makeWikilink', 2)
	elseif display and not page then
		return display
	elseif page and not display or page == display then
		return string.format('[[%s]]', page)
	else
		return string.format('[[%s|%s]]', page, display)
	end
end

local function union(arr1, arr2)
	-- Returns the union of two sets. The sets must be arrays containing values
	-- of the same type, and that type must be sortable.
	local vals, ret = {}, {}
	for i, val in ipairs(arr1) do
		vals[val] = true
	end
	for i, val in ipairs(arr2) do
		vals[val] = true
	end
	for val in pairs(vals) do
		ret[#ret + 1] = val
	end
	table.sort(ret)
	return ret
end

function p._main(args)
	local root = mw.html.create()
	local tableRoot = root:tag('table')

	-- Table base
	tableRoot
		:addClass('wikitable infobox')
		:css('float', args.align or 'right')
		:css('width', args.width or '24.2em')
		:css('font-size', '80%')
		:css('text-align', 'center')
		:css('margin', '0.5em 0 0.5em 1em')
		:css('padding', 0)
		:css('border-spacing', 0)
		:tag('tr')
			:tag('th')
				:attr('scope', 'col')
				:attr('colspan', 2)
				:css('font-size', '120%')
				:wikitext(args.title or 'Professional ratings')

	-- Subtitle
	if args.subtitle then
		tableRoot:node(makeHeaderRow(args.subtitle, false, false))
	end

	-- Aggregate rows
	local aggregateNums = union(
		mTableTools.affixNums(args, 'aggregate', 'page'),
		mTableTools.affixNums(args, 'aggregate', 'display')
	)
	if args.MC or args.ADM or #aggregateNums > 0 then
		tableRoot:node(makeHeaderRow('Aggregate scores', true, true))
		tableRoot:node(makeRatingHeaderRow())

		-- Assemble all of the aggregate scores
		local aggregates = {}
		if args.MC then
			table.insert(aggregates, {
				page = 'Metacritic',
				score = args.MC,
			})
		end
		if args.ADM then
			table.insert(aggregates, {
				page = 'AnyDecentMusic?',
				score = args.MC,
			})
		end
		for i, num in ipairs(aggregateNums) do
			local page = args['aggregate' .. num .. 'page']
			local display = args['aggregate' .. num .. 'display']
			local score = args['aggregate' .. num .. 'score']
			table.insert(aggregates, {
				page = page,
				display = display,
				score = score,
			})
		end

		-- Sort the aggregates
		table.sort(aggregates, function (t1, t2)
			return (t1.display or t1.page) < (t2.display or t2.page)
		end)

		-- Add the aggregates to the HTML
		for i, t in ipairs(aggregates) do
			tableRoot:node(makeRow(
				makeWikilink(t.page, t.display),
				t.score
			))
		end
	end

	-- Review rows
	local reviewNums = mTableTools.affixNums(args, 'rev')
	local duplicateScores = false
	tableRoot:node(makeHeaderRow('Review scores', true, true))
	tableRoot:node(makeRatingHeaderRow())
	for i, num in ipairs(reviewNums) do
		local scoreArgs, nScoreArgs = getArgPermutations(args, 'rev', num, 'score')
		tableRoot:node(makeRow(
			args['rev' .. num],
			getScore(scoreArgs, nScoreArgs)
		))
		if not duplicateScores and hasDuplicateScores(scoreArgs, nScoreArgs) then
			duplicateScores = true
		end
	end

	-- Tracking category
	if mw.title.getCurrentTitle().namespace == 0 and yesno(args.noprose) then
		root:wikitext('[[Category:Articles with album ratings that need to be turned into prose]]')
	end
	if duplicateScores then
		root:wikitext('[[Category:Pages using album ratings with duplicate score parameters]]')
	end

	return tostring(root)
end

function p.main(frame)
	local args = require('Module:Arguments').getArgs(frame, {
		wrappers = 'Template:Album ratings'
	})
	return p._main(args)
end

return p