Permanently protected module
From Wikipedia, the free encyclopedia


require('strict')



local p = {}

local data = require('Module:Video game reviews/data')

local yesno = require('Module:Yesno')

local vgwd = require('Module:Video game wikidata')

local getArgs



local function getActiveSystems(args)

	local activeSystems = {}

	for k, v in pairs(args) do

		if data.systemsk and yesno(v) then

			table.insert(activeSystems, k)

		end

	end

	table.sort(activeSystems, function(a, b)

		return data.systemsa].sortkey < data.systemsb].sortkey

	end)

	return activeSystems

end



local function getArgKeyTables(args)

	local reviewers, aggregators, awards = {}, {}, {}

	for k in pairs(args) do

		if string.match(k, data.i18n.pattern.reviewer) then

			table.insert(reviewers, k)

		elseif string.match(k, data.i18n.pattern.aggregator) then

			table.insert(aggregators, k)

		elseif string.match(k, data.i18n.pattern.award) then

			table.insert(awards, k)

		end

	end

	local function comparator(a, b)

		return tonumber(a:match('%d+')) < tonumber(b:match('%d+'))

	end

	table.sort(reviewers, comparator)

	table.sort(aggregators, comparator)

	table.sort(awards, comparator)

	return reviewers, aggregators, awards

end



local function getProvidedReviewersAndAggregators(args, usePlatforms)

	local providedReviewers, providedAggregators = {}, {}

	if usePlatforms then

		local seen = {}

		for k in pairs(args) do

			local splitPos = string.find(k, '_')

			if splitPos then

				local halfarg = string.sub(k, 1, splitPos - 1)

				if not seenhalfarg then

					seenhalfarg = true

					if data.reviewershalfarg then

						table.insert(providedReviewers, halfarg)

					elseif data.aggregatorshalfarg then

						table.insert(providedAggregators, halfarg)

					end

				end

			end

		end

	else

		for k in pairs(args) do

			if not string.find(k, '_') then

				if data.reviewersk then

					table.insert(providedReviewers, k)

				elseif data.aggregatorsk then

					table.insert(providedAggregators, k)

				end

			end

		end

	end

	table.sort(providedReviewers, function(a, b)

		return data.reviewersa].sortkey < data.reviewersb].sortkey

	end)

	table.sort(providedAggregators, function(a, b)

		return data.aggregatorsa].sortkey < data.aggregatorsb].sortkey

	end)

	return providedReviewers, providedAggregators

end



local function renderHeadingRowWithSystems(builder, activeSystems, headingText)

	builder:tag('tr')

		:addClass(data.i18n.class.headerrow)

		:tag('th')

			:attr('scope', 'col')

			:attr('rowspan', '2')

			:wikitext(headingText)

			:done()

		:tag('th')

			:attr('scope', 'colgroup')

			:attr('colspan', #activeSystems)

			:wikitext(data.i18n.display.score)

			:done()

	builder = builder:tag('tr')

	for _, v in ipairs(activeSystems) do

		builder:tag('th')

			:wikitext(data.systemsv].name)

			:attr('scope', 'col')

			:done()

	end

end



local function renderHeadingRow(builder, nameHeading)

	builder:tag('tr')

		:addClass(data.i18n.class.headerrow)

		:tag('th')

			:attr('scope', 'col')

			:wikitext(nameHeading)

			:done()

		:tag('th')

			:attr('scope', 'col')

			:wikitext(data.i18n.display.score)

			:done()

end



local function renderRatingsBySystem(builder, code, name, activeSystems, args, na)

	builder = builder:tag('tr')

	builder:tag('td')

		:wikitext(name)



	for _, v in ipairs(activeSystems) do

		local combinedCode = code .. '_' .. v

		local cell = builder:tag('td')

		if argscombinedCode then

			cell

				:wikitext(argscombinedCode])

				:done()

		elseif na then

			cell

				:addClass(data.i18n.class.na)

				:wikitext(data.i18n.display.na)

				:done()

		end

	end

end



local function renderRating(builder, name, rating)

	builder:tag('tr')

		:tag('td')

			:addClass(data.i18n.class.centeredpub)

			:wikitext(name)

			:done()

		:tag('td')

			:wikitext(rating)

			:done()

end



local function renderAggregators(builder, providedAggregators, activeSystems, customAggregatorKeys, args)

	

	local aggregatorCount = #providedAggregators + #customAggregatorKeys

	if aggregatorCount == 0 then return end

	

	builder = builder:tag('table')

		:addClass(data.i18n.class.aggregators)

		:addClass(data.i18n.class.wikitable)

		:addClass(args.state and 'mw-collapsible-content' or nil)

		:tag('caption')

			:wikitext(data.i18n.displayaggregatorCount == 1 and 'aggregateScore' or 'aggregateScores'])

			:done()



	if #activeSystems ~= 0 then

		local na = yesno(args.na)

		local showplatforms = #activeSystems ~= 1 or yesno(args.showplatforms)

		if showplatforms then

			renderHeadingRowWithSystems(builder, activeSystems, data.i18n.display.aggregator)

		else

			renderHeadingRow(builder, data.i18n.display.aggregator)

		end



		for _, v in ipairs(providedAggregators) do

			renderRatingsBySystem(builder, v, data.aggregatorsv].name, activeSystems, args, na)

		end

		for _, v in ipairs(customAggregatorKeys) do

			renderRatingsBySystem(builder, v, argsv], activeSystems, args, na)

		end

	else

		renderHeadingRow(builder, data.i18n.display.aggregator)

		for _, v in ipairs(providedAggregators) do

			renderRating(builder, data.aggregatorsv].name, argsv])

		end

		for _, v in ipairs(customAggregatorKeys) do

			renderRating(builder, argsv], argsv .. 'Score'])

		end

	end

end



local function renderReviews(builder, providedReviewers, activeSystems,

	customReviewerKeys, args, reviewerCount, priorReviewCount)

	

	if reviewerCount == 0 then return end

	

	builder = builder:tag('table')

		:addClass(data.i18n.class.reviews)

		:addClass(data.i18n.class.wikitable)

		:addClass(args.state and 'mw-collapsible-content' or nil)

		:tag('caption')

			:wikitext(data.i18n.displayreviewerCount == 1 and 'reviewScore' or 'reviewScores'])

			:addClass(priorReviewCount > 0 and data.i18n.class.stacked or nil)

			:done()

	

	if #activeSystems ~= 0 then

		local na = yesno(args.na)

		local showplatforms = #activeSystems ~= 1 or yesno(args.showplatforms)

		if showplatforms then

			renderHeadingRowWithSystems(builder, activeSystems, data.i18n.display.publication)

		else

			renderHeadingRow(builder, data.i18n.display.publication)

		end



		for _, v in ipairs(providedReviewers) do

			renderRatingsBySystem(builder, v, data.reviewersv].name, activeSystems, args, na)

		end

		for _, v in ipairs(customReviewerKeys) do

			renderRatingsBySystem(builder, v, argsv], activeSystems, args, na)

		end

	else

		renderHeadingRow(builder, data.i18n.display.publication)

		for _, v in ipairs(providedReviewers) do

			renderRating(builder, data.reviewersv].name, argsv])

		end

		for _, v in ipairs(customReviewerKeys) do

			renderRating(builder, argsv], argsv .. 'Score'])

		end

	end

end



local function renderAwards(builder, args, awardKeys, priorReviewCount)

	if #awardKeys == 0 then return end

	

	builder = builder:tag('table')

		:addClass(data.i18n.class.awards)

		:addClass(data.i18n.class.wikitable)

		:addClass("notheme")

		:addClass(args.state and 'mw-collapsible-content' or nil)

		:tag('caption')

			:wikitext(data.i18n.display#awardKeys == 1 and 'award' or 'awards'])

			:addClass(priorReviewCount > 0 and data.i18n.class.stacked or nil)

			:done()

		:tag('tr')

			:tag('th')

				:attr('scope', 'col')

				:wikitext(data.i18n.display.publication)

				:done()

			:tag('th')

				:attr('scope', 'col')

				:wikitext(data.i18n.display.award)

				:done()



	for _, v in ipairs(awardKeys) do

		builder:tag('tr')

			:tag('td')

				:wikitext(argsv .. 'Pub'])

				:done()

			:tag('td')

				:wikitext(argsv])

				:done()

	end

	builder:done()

	builder:done()

end



local function renderEditOnWikidata(builder, wikidata, state)

	if not wikidata then return end

	

	builder:tag('div')

		:addClass(data.i18n.class.wikidata)

		:addClass('skin-nightmode-reset-color')

		:addClass(state and 'mw-collapsible-content' or nil)

		:wikitext(vgwd.getUpdateLink())

		:done()

end



local function categorizePlatformCount(builder, platformCount)

	if platformCount ~= 0 then

		builder:wikitext(data.i18n.category.multiplatform)

	else

		builder:wikitext(data.i18n.category.singleplatform)

	end

end



local function renderTitles(builder, title, subtitle)

	builder:tag('div')

		:addClass(data.i18n.class.title)

		:wikitext(title or data.i18n.display.reception)

		:done()



	if subtitle then

		builder:tag('div')

			:addClass(data.i18n.class.subtitle)

			 -- The only reason to use the subtitle is collapsible content

			 -- So always add the related class.

			:addClass('mw-collapsible-content')

			:wikitext(subtitle)

			:done()

	end

end



local function render(providedReviewers, providedAggregators, awardKeys,

	activeSystems, customAggregatorKeys, customReviewerKeys, args, wikidata)

	local is_collapsible = args.title and args.state and

		(args.state == data.i18n.state.autocollapse or

			args.state == data.i18n.state.collapsed or

			args.state == data.i18n.state.expanded

		)

	local div = mw.html.create('div')

		:attr('role', 'complementary')

		:addClass(data.i18n.class.container)

		:addClass(data.i18n.class.dark)

		:addClass(#activeSystems == 0 and data.i18n.class.containersingle or nil)

		:addClass(args.align == data.i18n.align.left and data.i18n.class.containerleft or nil)

		:addClass(args.align == data.i18n.align.none and data.i18n.class.containernone or nil)

		:addClass(is_collapsible and 'mw-collapsible' or nil)

		:addClass(is_collapsible and args.state == data.i18n.state.collapsed and 'mw-collapsed' or nil)

		:addClass(is_collapsible and args.state == data.i18n.state.autocollapse and args.state or nil)



	renderTitles(div, args.title, args.subtitle)



	local aggregatorCount = #providedAggregators + #customAggregatorKeys

	renderAggregators(

		div,

		providedAggregators,

		activeSystems,

		customAggregatorKeys,

		args,

		aggregatorCount

	)

	local reviewerCount = #customReviewerKeys + #providedReviewers

	renderReviews(

		div,

		providedReviewers,

		activeSystems,

		customReviewerKeys,

		args,

		reviewerCount,

		aggregatorCount

	)

	renderAwards(

		div,

		args,

		awardKeys,

		reviewerCount + aggregatorCount

	)

	renderEditOnWikidata(div, wikidata, args.state)

	categorizePlatformCount(div, #activeSystems)

		

	return div

end



local function checkForWikidata(frame, args, activeSystems, providedAggregators)

	local wikidata = false

	

	if args.qid == 'none' then

		return wikidata

	end



	vgwd.setDateFormat(args.df)

	vgwd.setGame(args.qid)

	vgwd.setSystem(nil)

	vgwd.setGenerateReferences(true)

	vgwd.setShowUpdateLink(false)

	vgwd.setUpdateLinkStyle("text and pen")

	vgwd.setSystemFormat(args.systemFormat)



	-- Loop through aggregators if we have any.

	if #providedAggregators ~= 0 then

		for _, aggr in ipairs(providedAggregators) do

			-- Check if vgwd knows this aggregator.

			if vgwd.setReviewer(aggr) == nil then

				-- Loop through active systems

				if #activeSystems ~= 0 then

					for _, sys in ipairs(activeSystems) do

						local combinedCode = aggr .. '_' .. sys

						if argscombinedCode == 'wikidata' then

							vgwd.setSystem(sys)

							vgwd.setShowSystem(false)

							local vgwdScore = vgwd.printReviewScores(frame)

							if vgwdScore then

								argscombinedCode = vgwdScore

							end

							wikidata = true

						end

					end

				else

					vgwd.setShowSystem(true)

					if argsaggr == 'wikidata' then

						local vgwdScore = vgwd.printReviewScores(frame)

						if vgwdScore then

							argsaggr = vgwdScore

						end

						wikidata = true

					end

				end

			end

		end

	end



	return wikidata

end



function p._reviewbox(frame, args)

	local activeSystems = getActiveSystems(args)

	local customReviewerKeys, customAggregatorKeys, awardKeys = getArgKeyTables(args)

	local providedReviewers, providedAggregators = getProvidedReviewersAndAggregators(args, #activeSystems ~= 0)

	local wikidata = checkForWikidata(frame, args, activeSystems, providedAggregators)

	if #customAggregatorKeys ~= 0 or #customReviewerKeys ~= 0 or

		#providedAggregators ~= 0 or #providedReviewers ~= 0 or #awardKeys ~= 0 then

		return frame:extensionTag{

			name='templatestyles', args = { src = data.i18n.templatestyles }

		} ..  tostring(render(

				providedReviewers,

				providedAggregators,

				awardKeys,

				activeSystems,

				customAggregatorKeys,

				customReviewerKeys,

				args,

				wikidata

		))

	elseif mw.title.getCurrentTitle().namespace == 0 then

		return data.i18n.category.empty

	end

end



function p.reviewbox(frame)

	if not getArgs then

		getArgs = require('Module:Arguments').getArgs

	end

	return p._reviewbox(frame, getArgs(frame,

		{ wrappers = data.i18n.wrapper, trim = false, translate = data.argi18n }

	))

end



return p