Difference between revisions of "Module:Album ratings"
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 root = mw.html.create() | local root = mw.html.create() | ||
local tableRoot = root:tag('table') | local tableRoot = root:tag('table') | ||
| − | |||
-- Table base | -- Table base | ||
| Line 74: | Line 137: | ||
end | end | ||
| − | -- | + | -- 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()) | ||
| − | + | ||
| + | -- 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], | ||
| − | + | getScore(scoreArgs, nScoreArgs) | |
| − | |||
| − | |||
| − | |||
)) | )) | ||
| − | + | if not duplicateScores and hasDuplicateScores(scoreArgs, nScoreArgs) then | |
| − | + | duplicateScores = true | |
| − | + | 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 | + | 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
| 40px | This Lua module is used on approximately 88,000 pages and changes may be widely noticed. Test changes in the module's /sandbox or /testcases subpages. Consider discussing changes on the talk page before implementing them.
Transclusion count updated automatically (see documentation). |
| 40x40px | This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
This module implements {{Album ratings}}. Please see the template page for documentation.
See also
- Category:Articles with album ratings that need to be turned into prose
- Category:Pages using album ratings with duplicate score parameters (0)
-- 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