Difference between revisions of "Module:Album ratings"

From blackwiki
Jump to navigation Jump to search
blackwiki>Frietjes
(just found a bunch of rev1Score = and rev1score = parameter clashes, adding tracking to find the rest (Category:Pages using album ratings with duplicate score parameters))
blackwiki>Mr. Stradivarius
(add AnyDecentMusic and generic aggregation service parameters; split out duplicate detection into separate functions)
Line 44: Line 44:
 
:wikitext('Rating')
 
:wikitext('Rating')
 
return row
 
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 -- The 4 is the length of the array; this is needed as the args may be nil
 +
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 findSortText(wikitext)
 +
-- Simplified wikitext parser that returns a value that can be used for
 +
-- sorting.
 +
wikitext = mw.text.killMarkers(wikitext)
 +
-- Replace piped links with their display values
 +
wikitext = wikitext:gsub('%[%[[^%]]*|([^%]]-)%]%]', '%1')
 +
-- Replace non-piped links with their display values
 +
wikitext = wikitext:gsub('%[%[([^%]]-)%]%]', '%1')
 +
-- Strip punctuation
 +
wikitext = wikitext:gsub('%p', '')
 +
-- Trim whitespace
 +
wikitext = wikitext:gsub('^%s*', ''):gsub('%s*$', '')
 +
return wikitext
 
end
 
end
  
 
function p._main(args)
 
function p._main(args)
local reviewNums = mTableTools.affixNums(args, 'rev')
 
 
local root = mw.html.create()
 
local root = mw.html.create()
 
local tableRoot = root:tag('table')
 
local tableRoot = root:tag('table')
local duplicatescores = 0
 
  
 
-- Table base
 
-- Table base
Line 74: Line 137:
 
end
 
end
  
-- Metacritic
+
-- Aggregate rows
if args.MC then
+
local aggregateNums = mTableTools.affixNums(args, 'aggregate')
 +
if args.MC or args.ADM or #aggregateNums > 0 then
 
tableRoot:node(makeHeaderRow('Aggregate scores', true, true))
 
tableRoot:node(makeHeaderRow('Aggregate scores', true, true))
 
tableRoot:node(makeRatingHeaderRow())
 
tableRoot:node(makeRatingHeaderRow())
tableRoot:node(makeRow('[[Metacritic]]', args.MC))
+
 
 +
-- Assemble all of the aggregate scores
 +
local aggregates = {}
 +
if args.MC then
 +
table.insert(aggregates, {
 +
name = '[[Metacritic]]',
 +
sort = 'Metacritic',
 +
score = args.MC,
 +
})
 +
end
 +
if args.ADM then
 +
table.insert(aggregates, {
 +
name = '[[AnyDecentMusic?]]',
 +
sort = 'AnyDecentMusic?',
 +
score = args.ADM,
 +
})
 +
end
 +
for i, num in ipairs(aggregateNums) do
 +
local name = args['aggregate' .. num]
 +
local sort = findSortText(name)
 +
local score = args['aggregate' .. num .. 'score']
 +
table.insert(aggregates, {
 +
name = name,
 +
sort = sort,
 +
score = score,
 +
})
 +
end
 +
 
 +
-- Sort the aggregates
 +
table.sort(aggregates, function (t1, t2)
 +
return t1.sort < t2.sort
 +
end)
 +
 
 +
-- Add the aggregates to the HTML
 +
for i, t in ipairs(aggregates) do
 +
tableRoot:node(makeRow(t.name, t.score))
 +
end
 
end
 
end
  
 
-- Review rows
 
-- Review rows
 +
local reviewNums = mTableTools.affixNums(args, 'rev')
 +
local duplicateScores = false
 
tableRoot:node(makeHeaderRow('Review scores', true, true))
 
tableRoot:node(makeHeaderRow('Review scores', true, true))
 
tableRoot:node(makeRatingHeaderRow())
 
tableRoot:node(makeRatingHeaderRow())
 
for i, num in ipairs(reviewNums) do
 
for i, num in ipairs(reviewNums) do
 +
local scoreArgs, nScoreArgs = getArgPermutations(args, 'rev', num, 'score')
 
tableRoot:node(makeRow(
 
tableRoot:node(makeRow(
 
args['rev' .. num],
 
args['rev' .. num],
args['rev' .. num .. 'Score'] or
+
getScore(scoreArgs, nScoreArgs)
args['Rev' .. num .. 'Score'] or
 
args['rev' .. num .. 'score'] or
 
args['Rev' .. num .. 'score']
 
 
))
 
))
local scorecount = 0
+
if not duplicateScores and hasDuplicateScores(scoreArgs, nScoreArgs) then
scorecount = scorecount + (args['rev' .. num .. 'Score'] and 1 or 0)
+
duplicateScores = true
scorecount = scorecount + (args['Rev' .. num .. 'Score'] and 1 or 0)
+
end
scorecount = scorecount + (args['rev' .. num .. 'score'] and 1 or 0)
 
scorecount = scorecount + (args['Rev' .. num .. 'score'] and 1 or 0)
 
if scorecount > 1 then duplicatescores = duplicatescores + 1 end
 
 
end
 
end
  
Line 104: Line 201:
 
root:wikitext('[[Category:Articles with album ratings that need to be turned into prose]]')
 
root:wikitext('[[Category:Articles with album ratings that need to be turned into prose]]')
 
end
 
end
if duplicatescores > 0 then
+
if duplicateScores then
 
root:wikitext('[[Category:Pages using album ratings with duplicate score parameters]]')
 
root:wikitext('[[Category:Pages using album ratings with duplicate score parameters]]')
 
end
 
end

Revision as of 08:40, 31 October 2016

This module implements {{Album ratings}}. Please see the template page for documentation.

See also



-- 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 -- The 4 is the length of the array; this is needed as the args may be nil
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 findSortText(wikitext)
	-- Simplified wikitext parser that returns a value that can be used for
	-- sorting.
	wikitext = mw.text.killMarkers(wikitext)
	-- Replace piped links with their display values
	wikitext = wikitext:gsub('%[%[[^%]]*|([^%]]-)%]%]', '%1')
	-- Replace non-piped links with their display values
	wikitext = wikitext:gsub('%[%[([^%]]-)%]%]', '%1')
	-- Strip punctuation
	wikitext = wikitext:gsub('%p', '')
	-- Trim whitespace
	wikitext = wikitext:gsub('^%s*', ''):gsub('%s*$', '')
	return wikitext
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 = mTableTools.affixNums(args, 'aggregate')
	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, {
				name = '[[Metacritic]]',
				sort = 'Metacritic',
				score = args.MC,
			})
		end
		if args.ADM then
			table.insert(aggregates, {
				name = '[[AnyDecentMusic?]]',
				sort = 'AnyDecentMusic?',
				score = args.ADM,
			})
		end
		for i, num in ipairs(aggregateNums) do
			local name = args['aggregate' .. num]
			local sort = findSortText(name)
			local score = args['aggregate' .. num .. 'score']
			table.insert(aggregates, {
				name = name,
				sort = sort,
				score = score,
			})
		end

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

		-- Add the aggregates to the HTML
		for i, t in ipairs(aggregates) do
			tableRoot:node(makeRow(t.name, 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