Module:Video game reviews

-- -- Module layout for reviewer section in the work -- -- 1 get args -- 2 extract all reviewer args -- 3 sort args for reviewer then system -- 4 output args value where reviewer + system correlate --

-- -- This module will implement -- local p = {}

local reviewer = {{'1UP.com', '1UP'}, {'ActionTrip', 'Atrip'}, {'Adventure Gamers', 'AdvGamers'}, {'Allgame', 'Allgame'}, {'Amstrad Action', 'AAction'}, {'Amtix!', 'Amtix'}, {'Computer and Video Games', 'CVG'}, {'Crash', 'CRASH'}, {'Destructoid', 'Destruct'}, {'Dragon (magazine)', 'Dragon'}, {'Edge', 'Edge'}, {'Electronic Gaming Monthly', 'EGM'}, {'Eurogamer', 'EuroG'}, {'Famitsu', 'Fam'}, {'G4', 'G4'}, {'GameCritics', 'GCritics'}, {'GameFan', 'GameFan'}, {'Game Informer', 'GI'}, {'GamePro', 'GamePro'}, {'Game Revolution', 'GameRev'}, {'GamesMaster', 'GMaster'}, {'GamesRadar', 'GRadar'}, {'GameSpot', 'GSpot'}, {'GameSpy', 'GSpy'}, {'GamesTM', 'GTM'}, {'GameTrailers', 'GT'}, {'GameWire', 'GW'}, {'GameZone', 'GameZone'}, {'Giant Bomb', 'GB'}, {'Hyper Magazine', 'Hyper'}, {'IGN', 'IGN'}, {'Joystiq', 'Joystiq'}, {'Maximum PC', 'MaxPC'}, {'NGC Magazine', 'N64'}, {'NGC Magazine', 'NGC'}, {'NGamer', 'NG'}, {'NintendoLife', 'NLife'}, {'Nintendo Power', 'NP'}, {'Nintendo World Report', 'NWR'}, {'Official Nintendo Magazine', 'ONM'}, {'Official PlayStation Magazine (US)', 'OPM'}, {'Official PlayStation Magazine (UK)', 'OPMUK'}, {'Official PlayStation Magazine (Australia)', 'OPMAU'}, {'Official Xbox Magazine', 'OXM'}, {'Official Xbox Magazine UK', 'OXMUK'}, {'PALGN', 'PALGN'}, {'PC Format', 'PCF'}, {'PC Gamer UK', 'PCGUK'}, {'PC Gamer US', 'PCGUS'}, {'PC PowerPlay', 'PCPP'}, {'PC Zone', 'PCZone'}, {'Play Magazine', 'Play'}, {'Polygon', 'Poly'}, {'PlayStation Magazine', 'PSM'}, {'PlayStation 3 Magazine', 'PSM3'}, {'RPGamer', 'RPG'}, {'Sinclair User', 'SUser'}, {'TeamXbox', 'TX'}, {'VideoGamer.com', 'VG'}, {'X-Play', 'XPlay'}, {'Your Sinclair', 'YSinclair'}}

local aggregator = {{'GameRankings','GR'}, {'Game Ratio','GRO'}, {'GameStats','GMS'}, {'GameTab','GTab'}, {'Metacritic','MC'}}

-- 2 arrays with the title and code of each predefined "system type" field to be used. local system = {{'Atari 2600','A2600'}, {'ColecoVision','CV'}, {'DS','DS'}, {'Game Boy','GB'}, {'GBA','GBA'}, {'GBC','GBC'}, {'General', 'GEN'}, {'iOS','iOS'}, {'N-Gage','N-G'}, {'N64','N64'}, {'NES','NES'}, {'GC','NGC'}, {'Shield','NSHI'}, {'PC','PC'}, {'PS','PS'}, {'PS2','PS2'}, {'PS3','PS3'}, {'PS4','PS4'}, {'PSP','PSP'}, {'Dreamcast','SDC'}, {'SGG','SGG'}, {'SNES','SNES'}, {'Mega Drive','SMD'}, {'Master System','SMS'}, {'Saturn','SSAT'}, {'TurboGrafx-16','TG16'}, {'PlayStation Vita','VITA'}, {'Xbox','XBOX'}, {'Xbox 360','X360'}, {'Xbox One','XONE'}, {'Wii','WII'}}

-- Require necessary modules. local HtmlBuilder = require('Module:HtmlBuilder') local categoryHandler = require('Module:Category handler').main

-- Set aliases for often-used functions to reduce table lookups. local args local frame local keys local halfkeysrev local halfkeysagg local platforms local custome_agg local custome_rev local awardnums = {}

-- -- Splits a string on a delimiter n number of times. -- function Split(str, delim, maxNb) if string.find(str, delim) == nil then return { str } end if maxNb == nil or maxNb < 1 then maxNb = 0 -- No limit end local result = {} local pat = "(.-)" .. delim .. ""   local nb = 0 local lastPos for part, pos in string.gfind(str, pat) do       nb = nb + 1 result[nb] = part lastPos = pos if nb == maxNb then break end end if nb ~= maxNb then result[nb + 1] = string.sub(str, lastPos) end return result end

-- -- Sorts keys by string. -- function pairsByKeys (t, f)   local a = {} for n in pairs(t) do       if type(n) == 'string' then table.insert(a, n)       end end table.sort(a, f)   local i = 0 -- iterator variable local iter = function -- iterator function i = i + 1 if a[i] == nil then return nil else return a[i] end end return iter end

-- -- Return all the keys of an array -- function array_keys(input) local key local keys = {}

for key in pairs(input) do       table.insert(keys, key) end

return keys end

-- -- Returns the count of how many platforms are active. -- function platforms local count = 0 for i = 1, #system do       if args[tostring(system[i][2])] ~= nil then if string.lower(tostring(args[tostring(system[i][2])])) == 'true' then count=count+1 end end end return count end

-- -- Returns the count of how many custom aggregators are active. -- function custome_agg local cagg = 0 for i = 1, 10 do       if args['agg' .. tostring(i)] ~= nil then cagg = cagg + 1 end end return cagg end

-- -- Returns the count of how many custom reviewers are active. -- function custome_rev local crev = 0 for i = 1, 10 do       if args['rev' .. tostring(i)] ~= nil then crev = crev + 1 end end return crev end -- -- Title row -- function renderTitleRow(tbl) local titleCell = tbl.tag('tr').tag('th').css('font-size', '120%')

if args.state == 'plain' then titleCell .tag('span') .css('padding-left', '5.7em') .wikitext(' ') end

if args.title then titleCell .wikitext(args.title) .done else titleCell .addClass('Reception') .wikitext('Reception') .done end

if args.subtitle then tbl .tag('tr') .tag('th') .css('font-size', '120%') .wikitext(args.subtitle) .done end end

-- -- Insert reviews -- function reviews local arg_system local tbl2 if (#halfkeysrev > 0 or #halfkeysagg > 0) and platforms >= 1 then tbl2 = HtmlBuilder.create('table') .addClass('infobox wikitable') .attr('cellpadding', 0) .attr('cellspacing', 0) .css('width', '100%') .css('border-bottom', 'none') .css('margin', '0em') .done elseif (#halfkeysrev > 0 or #halfkeysagg > 0 or custome_agg > 0 or custome_rev > 0) and platforms == 0 then tbl2 = HtmlBuilder.create('table') .addClass('infobox wikitable') .attr('cellpadding', 0) .attr('cellspacing', 0) .css('width', '100%') .css('font-size', '100%') .css('border-bottom', 'none') .css('margin', '0em') .done end if #halfkeysrev > 0 and (platforms > 1 or string.lower(tostring(args['showplatforms'])) == 'true') then tbl2.tag('tr').tag('th') .attr('colspan', #system + 1) .css('background', '#d1dbdf') .css('font-size', '120%') .wikitext('Review scores') .done

tbl2 .tag('tr') .tag('th') .attr('rowspan', '2') .css('background', '#e8f4f8') .css('text-align', 'center') .css('vertical-align', 'middle') .wikitext('Publication') .done .tag('th') .attr('colspan', #system) .css('background', '#e8f4f8') .css('vertical-align', 'middle') .wikitext('Score') .done local forloop = tbl2.tag('tr') for j = 1, #system do           if string.lower(tostring(args[tostring(system[j][2])])) == 'true' then forloop.tag('th').wikitext(tostring(system[j][1])) end end elseif #halfkeysrev > 0 and platforms == 1 and string.lower(tostring(args['showplatforms'])) ~= 'true' then tbl2.tag('tr').tag('th') .attr('colspan', '2') .css('background', '#d1dbdf') .css('font-size', '120%') .wikitext('Review scores') .done

tbl2 .tag('tr') .tag('th') .css('background', '#e8f4f8') .css('text-align', 'center') .css('vertical-align', 'middle') .wikitext('Publication') .done .tag('th') .css('background', '#e8f4f8') .css('vertical-align', 'middle') .wikitext('Score') .done end if platforms >= 1 then for i = 1, #reviewer do           for k = 1, #halfkeysrev do                if reviewer[i][2] == halfkeysrev[k] then local forloop = tbl2.tag('tr') forloop.tag('td') .css('vertical-align','middle') .wikitext(reviewer[i][1]) .done

for j = 1, #system do                       local temp = tostring(reviewer[i][2]) .. '_' .. tostring(system[j][2]) if string.lower(tostring(args[tostring(system[j][2])])) == 'true' and args[temp] ~= nil then forloop.tag('td') .css('vertical-align', 'middle') .wikitext(tostring(args[temp])) elseif string.lower(tostring(args[tostring(system[j][2])])) == 'true' and string.lower(tostring(args['na'])) == 'true' then forloop.tag('td') .css('color', 'lightgray') .css('vertical-align','middle') .css('text-align', 'center') .addClass('table-na') .wikitext('N/A') .done elseif string.lower(tostring(args[tostring(system[j][2])])) == 'true' then forloop.tag('td').done end end end end end for i = 1, 10 do           if args['rev' .. tostring(i)] ~= nil then local forloop = tbl2.tag('tr') forloop.tag('td').wikitext(tostring(args['rev' .. tostring(i)])) for j = 1, #system do local temp = 'rev'.. tostring(i) .. '_' .. tostring(system[j][2]) if string.lower(tostring(args[tostring(system[j][2])])) == 'true' and args[temp] ~= nil then forloop.tag('td') .css('vertical-align','middle') .wikitext(tostring(args[temp])) .done elseif string.lower(tostring(args[tostring(system[j][2])])) == 'true' and string.lower(tostring(args['na'])) == 'true' then forloop.tag('td') .css('color', 'lightgray') .css('vertical-align','middle') .css('text-align', 'center') .addClass('table-na') .wikitext('N/A') .done elseif string.lower(tostring(args[tostring(system[j][2])])) == 'true' then forloop.tag('td').done end end end end if (#halfkeysagg > 0 and platforms > 1) and #halfkeysrev == 0 then tbl2 .tag('tr') .tag('th') .attr('colspan', #system+1) .css('background', '#d1dbdf') .css('font-size', '120%') .wikitext('Aggregate scores') .done tbl2 .tag('tr') .tag('th') .attr('rowspan', '2') .css('background', '#e8f4f8') .css('text-align', 'center') .css('vertical-align', 'middle') .wikitext('Publication') .done .tag('th') .attr('colspan', #system+1) .css('background', '#e8f4f8') .css('vertical-align', 'middle') .wikitext('Score') .done local forloop = tbl2.tag('tr') for j = 1, #system do               if string.lower(tostring(args[tostring(system[j][2])])) == 'true' then forloop.tag('th').wikitext(tostring(system[j][1])) end end elseif (#halfkeysagg > 0 and #halfkeysrev > 0) or (#halfkeysagg > 0 and platforms == 1)then tbl2 .tag('tr') .tag('th') .attr('colspan', #system+1) .css('background', '#d1dbdf') .css('font-size', '120%') .wikitext('Aggregate scores') .done end for i = 1, #aggregator do           for k = 1, #halfkeysagg do                if aggregator[i][2] == halfkeysagg[k] then local forloop = tbl2.tag('tr') forloop.tag('td') .css('vertical-align','middle') .wikitext(aggregator[i][1]) .done

for j = 1, #system do                       local temp = tostring(aggregator[i][2]) .. '_' .. tostring(system[j][2]) if string.lower(tostring(args[tostring(system[j][2])])) == 'true' and args[temp] ~= nil then forloop.tag('td').wikitext(tostring(args[temp])) elseif string.lower(tostring(args[tostring(system[j][2])])) == 'true' and string.lower(tostring(args['na'])) == 'true' then forloop.tag('td') .css('color', 'lightgray') .css('vertical-align','middle') .css('text-align', 'center') .addClass('table-na') .wikitext('N/A') .done elseif string.lower(tostring(args[tostring(system[j][2])])) == 'true' then forloop.tag('td').done end end end end end elseif platforms == 0 then if #halfkeysagg > 0 or custome_agg > 0 then tbl2 .tag('tr') .tag('th') .attr('colspan', 2) .css('background', '#d1dbdf') .css('font-size', '120%') .wikitext('Aggregate scores') .done .tag('tr') .tag('th') .css('background', '#e8f4f8') .css('text-align', 'center') .wikitext('Aggregator') .done .tag('th') .css('background', '#e8f4f8') .wikitext('Score') .done end for i = 1, #aggregator do           for k = 1, #halfkeysagg do                if aggregator[i][2] == halfkeysagg[k] then tbl2 .tag('tr') .tag('td') .css('text-align', 'center') .css('vertical-align', 'middle') .wikitext(aggregator[i][1]) .done .tag('td') .css('text-align', 'center') .css('font-size', '110%') .wikitext(tostring(args[tostring(aggregator[i][2])])) .done end end end for i = 1, 10 do           if args['agg' .. tostring(i)] ~= nil then tbl2 .tag('tr') .tag('td') .css('text-align', 'center') .css('vertical-align', 'middle') .wikitext(tostring(args['agg' .. tostring(i)])) .done .tag('td') .css('text-align', 'center') .css('font-size', '110%') .wikitext(tostring(args['agg'.. tostring(i) .. 'Score'])) .done end end if #halfkeysrev > 0 or custome_rev > 0 then tbl2.tag('tr').tag('th') .attr('colspan', #system + 1) .css('background', '#d1dbdf') .css('font-size', '120%') .wikitext('Review scores') .done tbl2 .tag('tr') .tag('th') .css('background', '#e8f4f8') .css('text-align', 'center') .wikitext('Publication') .done .tag('th') .attr('colspan', '25') .css('background', '#e8f4f8') .wikitext('Score') .done

for i = 1, #reviewer do               for k = 1, #halfkeysrev do                    if reviewer[i][2] == halfkeysrev[k] then tbl2 .tag('tr') .tag('td') .css('text-align', 'center') .css('vertical-align', 'middle') .wikitext(reviewer[i][1]) .done .tag('td') .css('text-align', 'center') .css('font-size', '110%') .wikitext(tostring(args[tostring(reviewer[i][2])])) .done end end end for i = 1, 10 do               if args['rev' .. tostring(i)] ~= nil then tbl2 .tag('tr') .tag('td') .css('text-align', 'center') .css('vertical-align', 'middle') .wikitext(tostring(args['rev' .. tostring(i)])) .done .tag('td') .css('text-align', 'center') .css('font-size', '110%') .wikitext(tostring(args['rev'.. tostring(i) .. 'Score'])) .done end end end end return tbl2 end

-- -- Inserts a award into the table output. -- function award(tbl, awardnum) local temp = tbl.tag('tr') .tag('td') .css('font-weight','bold') .css('background-color','#f2f2f2') .wikitext(args['award' .. awardnum .. 'Pub']) .done .tag('td') .css('background-color','#f2f2f2') .wikitext(args['award' .. awardnum]) .done return temp end

-- -- Insert awards header and calls award row creation. -- function awards if args['award1'] then local Cell = HtmlBuilder.create('table') .addClass('infobox wikitable') .css('width', '100%') .css('margin', '0em') .css('border-top', 'none') .attr('cellpadding', 3) .attr('cellspacing', 0) Cell .tag('tr') .tag('th') .attr('colspan', 2) .css('background', '#d1dbdf') .css('font-size', '120%') .css('border-top', 'none') .wikitext('Awards') .done Cell .tag('tr') .tag('th').wikitext('Publication') .tag('th').wikitext('Award')

for i, awardnum in ipairs(awardnums) do           local awardRow = award(Cell, awardnum) awardRow .done end return Cell end end

-- -- Main tables --

function renderMainTable local tbl

if args['award1'] or ((#halfkeysagg > 0 or #halfkeysrev > 0 or custome_agg > 0 or custome_rev > 0) and platforms >= 0) then if platforms == 0 then -- Width: 20% Seems better since it scales with the article size. tbl = HtmlBuilder.create('table') .attr('cellpadding', 0) .attr('cellspacing', 0) .css('background', 'transparent') .css('padding', '0em') .css('margin', '0em 1em 1em 1em') .css('text-align', 'center') .css('font-size', '80%') if args.width then tbl .css('width',args.width) else tbl .css('width', '23em') end else tbl = HtmlBuilder.create('table') .attr('cellpadding', 0) .attr('cellspacing', 0) .css('background', 'transparent') .css('padding', '0em') .css('margin', '0em 1em 1em 1em') .css('text-align', 'center') .css('font-size', '80%') end if args.state then tbl .addClass(args.state) else tbl .addClass('collapsible') end

if args.title and (args.state ~= 'plain' and args.state ~= 'off') then tbl .addClass('collapsible') .addClass(args.state) end

if args.align and args.align ~= 'right' then tbl .css('float', args.align) else tbl .css('float', 'right') end

renderTitleRow(tbl)

tbl .tag('tr') .tag('td') .node(reviews) .done

tbl .tag('tr') .tag('td') .node(awards) .done else category = categoryHandler{ main = '' }       category = category or '' -- Check that we don't have a nil value for the category variable. tbl = HtmlBuilder.create tbl.wikitext(category) end return tbl end

-- -- Creates the table and calls functions that create the reviews and awards tables/columns/rows. -- function p._reviewbox(reviewBoxArgs) local t = {} local flags = {} local nitem = {} local halfargs = {} local j = 1 -- calls for the args. args = reviewBoxArgs platforms = platforms custome_rev = custome_rev custome_agg = custome_agg

-- sorts args by string. for k in pairsByKeys(args) do       table.insert(t, k)    end keys = t

-- creates a table of all unique reviewers. for i=1,#keys do       if string.find(tostring(keys[i]), '_') ~= nil and platforms >= 1 then halfargs = Split(tostring(keys[i]),'_') for k=1, #reviewer do               if reviewer[k][2] == halfargs[1] then if not flags[halfargs[1]] then flags[halfargs[1]] = true nitem[j] = halfargs[1] j = j + 1 end end end elseif string.find(tostring(keys[i]), '_') == nil and platforms == 0 then for k=1, #reviewer do               if reviewer[k][2] == keys[i] then nitem[j] = keys[i] j = j + 1 end end end end halfkeysrev = nitem

local flags = {} local nitem = {} local halfargs = {} local j = 1 -- creates a table of all unique aggregators. for i=1,#keys do       if string.find(tostring(keys[i]), '_') ~= nil and platforms >= 1 then halfargs = Split(tostring(keys[i]),'_') for k=1, #aggregator do               if aggregator[k][2] == halfargs[1] then if not flags[halfargs[1]] then flags[halfargs[1]] = true nitem[j] = halfargs[1] j = j + 1 end end end elseif string.find(tostring(keys[i]), '_') == nil and platforms == 0 then for k=1, #aggregator do               if aggregator[k][2] == keys[i] then nitem[j] = keys[i] j = j + 1 end end end end halfkeysagg = nitem

-- sorts awards by number from args. for k, v in pairs(args) do       local awardnum = ('' .. k):match('^award(%d+)$') if awardnum then table.insert(awardnums, tonumber(awardnum)) end end if awardnums then table.sort(awardnums) end

-- render the main body of the Review Box local tbl = renderMainTable

-- render the appropriate wrapper around the Review Box, depending on the border param local res = HtmlBuilder.create

res.node(tbl)

return tostring(res) end

-- -- Main: frame function. -- function p.reviewbox(frame) -- ParserFunctions considers the empty string to be false, so to preserve the previous -- behavior of, change any empty arguments to nil, so Lua will consider -- them false too. local args = {} local parent_args = frame:getParent.args; for k, v in pairs(parent_args) do       if v ~= '' then args[k] = v       end end

return p._reviewbox(args) end

return p