Модуль:Video game reviews/песочница

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
Документация

Реализация {{оценки игры/песочница}} на Lua.

Строковые значения используемых полей, заголовков и прочего поставляются из Модуль:Video game reviews/data.

Функции

[править код]

Вызываемые через {{#invoke:}}

Статические методы

[править код]

Вызываемые из других модулей через require():

  • Module:No globals - модуль вызывает ошибку при чтении любых нулевых глобальных переменных или записи в глобальные переменные за исключением arg. Детально смотри Модуль:No globals
  • Module:Video game reviews/data - данные поставляемые для модуля Video game reviews. Документация по использованию.
  • Module:Yesno - модуль предоставляет единый интерфейс для обработки булевых или булевоподобных входных данных детально смотри Модуль:Yesno

Методы

[править код]

Вызываемые от объекта

См. также

[править код]
require('strict')

local p = {}

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

local function getActiveSystems(args)
	local activeSystems = {}
	for k,v in pairs(args) do
		if data.systems[k] and yesno(v) then
			table.insert(activeSystems, k)
		end
	end
	table.sort(activeSystems, function(a, b)
		return data.systems[a].sortkey < data.systems[b].sortkey
	end)
	return activeSystems
end

local function getArgKeyTables(args)
	local reviewers, reviewersRu, aggregators, awards = {}, {}, {}, {}
	local hasObsolete = false
	for k in pairs(args) do
		if string.match(k, '^revRu%d+$') then
			table.insert(reviewersRu, k)
		elseif string.match(k, '^rev%d+$') then
			table.insert(reviewers, k)
		elseif string.match(k, '^agg%d+$') then
			table.insert(aggregators, k)
		elseif string.match(k, '^award%d+$') then
			table.insert(awards, k)
		elseif data.obsolete[k] then
			hasObsolete = true
		end
	end
	local function comparator(a, b)
		return tonumber(a:match('%d+')) < tonumber(b:match('%d+'))
	end
	table.sort(reviewers, comparator)
	table.sort(reviewersRu, comparator)
	table.sort(aggregators, comparator)
	table.sort(awards, comparator)
	return reviewers, reviewersRu, aggregators, awards, hasObsolete
end

local function getProvidedReviewersAndAggregators(args, usePlatforms)
	local providedReviewers, providedReviewersRu, 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 seen[halfarg] then
					seen[halfarg] = true
					if data.reviewers[halfarg] then
						table.insert(providedReviewers, halfarg)
					elseif data.reviewersRu[halfarg] then
						table.insert(providedReviewersRu, halfarg)
					elseif data.aggregators[halfarg] then
						table.insert(providedAggregators, halfarg)
					end
				end
			end
		end
	else
		for k in pairs(args) do
			if not string.find(k, '_') then
				if data.reviewers[k] then
					table.insert(providedReviewers, k)
				elseif data.reviewersRu[k] then
					table.insert(providedReviewersRu, k)
				elseif data.aggregators[k] then
					table.insert(providedAggregators, k)
				end
			end
		end
	end
	table.sort(providedReviewers, function(a, b)
		return data.reviewers[a].sortkey < data.reviewers[b].sortkey
	end)
	table.sort(providedReviewersRu, function(a, b)
		return data.reviewersRu[a].sortkey < data.reviewersRu[b].sortkey
	end)
	table.sort(providedAggregators, function(a, b)
		return data.aggregators[a].sortkey < data.aggregators[b].sortkey
	end)
	return providedReviewers, providedReviewersRu, providedAggregators
end

local function renderTitleRow(tbl, title, colspan)
	local titleCell = tbl:tag('tr'):tag('th'):css('font-size', '130%'):attr('colspan', colspan)

	if title then
		titleCell
			:wikitext(title)
	else
		titleCell
			:addClass('Reception')
			:wikitext(data.i18n.reception)
	end
end

local function renderMainHeading(builder, colspan, headingText, borderTop)
	builder:tag('tr'):tag('th')
		:attr('colspan', colspan)
		:css('background', '#d1dbdf')
		:css('font-size', '120%')
		:css('border-top', borderTop)
		:wikitext(headingText)
end

local function renderHeadingRowWithSystems(builder, mainHeading, activeSystems)
	renderMainHeading(builder, #activeSystems + 1, mainHeading)
	builder:tag('tr')
		:tag('th')
			:attr('rowspan', '2')
			:css('background', '#e8f4ff')
			:css('text-align', 'center')
			:css('vertical-align', 'middle')
			:wikitext(data.i18n.publication)
		:done()
		:tag('th')
			:attr('colspan', #activeSystems)
			:css('background', '#e8f4ff')
			:css('vertical-align', 'middle')
			:wikitext(data.i18n.score)
	builder = builder:tag('tr')
	for _,v in ipairs(activeSystems) do
		builder:tag('th'):wikitext(data.systems[v].name)
	end
end

local function renderHeadingRow(builder, mainHeading, nameHeading)
	renderMainHeading(builder, 2, mainHeading)
	builder
		:tag('tr')
			:tag('th')
				:css('background', '#00f4f8')
				:css('text-align', 'center')
				:css('vertical-align', 'middle')
				:wikitext(nameHeading)
			:done()
			:tag('th')
				:css('background', '#02f4f8')
				:css('vertical-align', 'middle')
				:wikitext(data.i18n.score)
end

local function renderRatingsBySystem(builder, code, name, activeSystems, args, na)
	builder = builder:tag('tr')
	builder:tag('td')
		:css('vertical-align','middle')
		:wikitext(name)

	for _,v in ipairs(activeSystems) do
		local combinedCode = code .. '_' .. v
		local cell = builder:tag('td')
		if args[combinedCode] then
			cell
				:css('vertical-align', 'middle')
				:css('font-size', '110%')
				:wikitext(args[combinedCode])
		elseif na then
			cell
				:css('color', 'lightgray')
				:css('vertical-align','middle')
				:css('text-align', 'center')
				:css('font-size', '110%')
				:addClass('table-na')
				:wikitext(data.i18n.na)
		end
	end
end

local function renderRating(builder, name, rating)
	builder:tag('tr')
		:tag('td')
			:css('text-align', 'center')
			:css('vertical-align', 'middle')
			:wikitext(name)
		:done()
		:tag('td')
			:css('text-align', 'center')
			:css('font-size', '110%')
			:wikitext(rating)
end

local function renderReviews(builder, providedReviewers, providedReviewersRu, providedAggregators, activeSystems, customAggregatorKeys, customReviewerKeys, customReviewerRuKeys, args)
	local hasReviewers = #providedReviewers ~= 0 or #customReviewerKeys ~= 0
	local hasReviewersRu = #providedReviewersRu ~= 0 or #customReviewerRuKeys ~= 0
	local hasAggregators = #providedAggregators ~= 0 or #customAggregatorKeys ~= 0
	builder:css('font-size', '100%')
	if #activeSystems ~= 0 then
--		builder:wikitext(data.i18n.multiplatformCategory)
		builder:css('font-size', '80%')
		local na = yesno(args.na)
		local showplatforms = #activeSystems ~= 1 or yesno(args.showplatforms)
		if hasAggregators then
			--if hasReviewers then
			--	renderMainHeading(builder, #activeSystems+1, data.i18n.aggregateScores)
			--end
			if showplatforms then
				renderHeadingRowWithSystems(builder, data.i18n.aggregateScores, activeSystems)
			else
				renderHeadingRow(builder, data.i18n.aggregateScores, data.i18n.aggregator)
			end

			for _,v in ipairs(providedAggregators) do
				renderRatingsBySystem(builder, v, data.aggregators[v].name, activeSystems, args, na)
			end
			for _,v in ipairs(customAggregatorKeys) do
				renderRatingsBySystem(builder, v, args[v], activeSystems, args, na)
			end
		end
		if hasReviewers then
			if showplatforms then
				renderHeadingRowWithSystems(builder, data.i18n.reviewScores, activeSystems)
			else
				renderHeadingRow(builder, data.i18n.reviewScores, data.i18n.publication)
			end

			for _,v in ipairs(providedReviewers) do
				renderRatingsBySystem(builder, v, data.reviewers[v].name, activeSystems, args, na)
			end
			for _,v in ipairs(customReviewerKeys) do
				renderRatingsBySystem(builder, v, args[v], activeSystems, args, na)
			end
		end
		if hasReviewersRu then
			if showplatforms then
				renderHeadingRowWithSystems(builder, data.i18n.reviewScoresRu, activeSystems)
			else
				renderHeadingRow(builder, data.i18n.reviewScoresRu, data.i18n.publication)
			end

			for _,v in ipairs(providedReviewersRu) do
				renderRatingsBySystem(builder, v, data.reviewersRu[v].name, activeSystems, args, na)
			end
			for _,v in ipairs(customReviewerRuKeys) do
				renderRatingsBySystem(builder, v, args[v], activeSystems, args, na)
			end
		end
	else
--		builder:wikitext(data.i18n.singleplatformCategory)
		builder:css('font-size', '80%')
		if hasAggregators then
			renderHeadingRow(builder, data.i18n.aggregateScores, data.i18n.aggregator)
			for _,v in ipairs(providedAggregators) do
				renderRating(builder, data.aggregators[v].name, args[v])
			end
			for _,v in ipairs(customAggregatorKeys) do
				renderRating(builder, args[v], args[v .. 'Score'])
			end
		end
		if hasReviewers then
			renderHeadingRow(builder, data.i18n.reviewScores, data.i18n.publication)
			for _,v in ipairs(providedReviewers) do
				renderRating(builder, data.reviewers[v].name, args[v])
			end
			for _,v in ipairs(customReviewerKeys) do
				renderRating(builder, args[v], args[v .. 'Score'])
			end
		end
		if hasReviewersRu then
			renderHeadingRow(builder, data.i18n.reviewScoresRu, data.i18n.publication)
			for _,v in ipairs(providedReviewersRu) do
				renderRating(builder, data.reviewersRu[v].name, args[v])
			end
			for _,v in ipairs(customReviewerRuKeys) do
				renderRating(builder, args[v], args[v .. 'Score'])
			end
		end
	end
end

local function renderAwards(builder, args, awardKeys, borderTop, activeSystems)
	if #activeSystems == 0 then
		renderMainHeading(builder, 2, data.i18n.awards, borderTop)
	else
		renderMainHeading(builder, #activeSystems + 1, data.i18n.awards, borderTop)
	end

	if #activeSystems == 0 then
		builder:tag('tr')
			:tag('th')
				:wikitext(data.i18n.awardpublication)
				:done()
			:tag('th')
				:wikitext(data.i18n.award)
	

		for _,v in ipairs(awardKeys) do
			if (args[v .. 'Pub'] ~= nil) then
				builder:tag('tr')
					:tag('td')
					:css('font-weight','bold')
						:wikitext(args[v .. 'Pub'])
					:done()
					:tag('td')
						:wikitext(args[v])
			else 
				builder:tag('tr')
					:tag('td')
					:attr('colspan',2)
						:wikitext(args[v])
					:done()
			end
		end
	else
		builder:tag('tr')
			:tag('th')
				:wikitext(data.i18n.awardpublication)
				:done()
			:tag('th')
			:attr('colspan', #activeSystems)
				:wikitext(data.i18n.award)
	

		for _,v in ipairs(awardKeys) do
			if (args[v .. 'Pub'] ~= nil) then
				builder:tag('tr')
					:tag('td')
					:css('font-weight','bold')
						:wikitext(args[v .. 'Pub'])
					:done()
					:tag('td')
						:attr('colspan', #activeSystems)
						:wikitext(args[v])
			else 
				builder:tag('tr')
					:tag('td')
					:attr('colspan', #activeSystems + 1)
						:wikitext(args[v])
					:done()
			end
		end
	end
end

local function renderMainTable(providedReviewers, providedReviewersRu, providedAggregators, awardKeys, activeSystems, customAggregatorKeys, customReviewerKeys, customReviewerRuKeys, hasObsolete, args)
	local tbl = mw.html.create('table')
		:addClass('wikitable collapsible')
		:attr('cellpadding', 3)
		:attr('cellspacing', 0)
		:css('background', 'transparent')
		:css('padding', '0em')
		:css('margin', '5px')
		:css('text-align', 'center')
		:css('font-size', '80%')
		:css('float', args.align or 'right')
		:css('clear', args.align or 'right')
		:css('width', '23em')

	if #activeSystems == 0 then
		-- Width: 20% Seems better since it scales with the article size.
		tbl
			:css('width', args.width or '23em')
		renderTitleRow(tbl, args.title, 2)
	else
		renderTitleRow(tbl, args.title, #activeSystems + 1)
	end

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

	renderReviews(tbl, providedReviewers, providedReviewersRu, providedAggregators, activeSystems, customAggregatorKeys, customReviewerKeys, customReviewerRuKeys, args)
	if #awardKeys ~= 0 then
		renderAwards(tbl, args, awardKeys, (#customAggregatorKeys ~= 0 or #customReviewerKeys ~= 0 or #providedAggregators ~= 0 or #providedReviewers ~= 0) and 'none' or nil, activeSystems)
	end
	
	if hasObsolete then
		tbl:tag('tr'):tag('td')
			:css("color","red")
			:attr('colspan',2)
			:wikitext(data.i18n.obsoleteText)

		if mw.title.getCurrentTitle().namespace == 0 then  
			tbl:wikitext(data.i18n.obsoleteCategory)
		end
	end
	return tbl
end

function p._reviewbox(args)
	local activeSystems = getActiveSystems(args)
	local customReviewerKeys, customReviewerRuKeys, customAggregatorKeys, awardKeys, hasObsolete = getArgKeyTables(args)

	local providedReviewers, providedReviewersRu, providedAggregators = getProvidedReviewersAndAggregators(args, #activeSystems ~= 0)
	if #customAggregatorKeys ~= 0 or #customReviewerKeys ~= 0 or #customReviewerRuKeys ~= 0 or #providedAggregators ~= 0 or #providedReviewers ~= 0 or #providedReviewersRu ~= 0 or #awardKeys ~= 0 then
		return renderMainTable(providedReviewers, providedReviewersRu, providedAggregators, awardKeys, activeSystems, customAggregatorKeys, customReviewerKeys, customReviewerRuKeys, hasObsolete, args)
--	elseif mw.title.getCurrentTitle().namespace == 0 then
--		return data.i18n.emptyCategory
	end
end

function p.reviewbox(frame)
	if not getArgs then
		getArgs = require('Module:Arguments').getArgs
	end
	return p._reviewbox(getArgs(frame, {wrappers = data.i18n.wrapper, trim = false, translate = data.argi18n}))
end

return p