توضیحات این پودمان می‌تواند در پودمان:AlborzSports/توضیحات قرار گیرد.

--------------------------------------------------------------------------------
-- Module:AlborzSports
-- Wiki Alborz Sports Information System
-- Core Engine
-- Version 2.2
--------------------------------------------------------------------------------

local p = {}

--------------------------------------------------------------------------------
-- LOAD DATA
--------------------------------------------------------------------------------

local data = mw.loadData("Module:AlborzSports/Data")

--------------------------------------------------------------------------------
-- LOAD DEPENDENCIES
--------------------------------------------------------------------------------

local infobox = require("Module:Infobox")

--------------------------------------------------------------------------------
-- CONFIG
--------------------------------------------------------------------------------

local DEFAULT_IMAGE_WIDTH =
	data.meta.imageWidth or "250px"

--------------------------------------------------------------------------------
-- UTILITY FUNCTIONS
--------------------------------------------------------------------------------

local function clean(value)

	if value == nil then
		return nil
	end

	if type(value) == "string" then

		value = mw.text.trim(value)

		if value == "" then
			return nil
		end

	end

	return value
end


--------------------------------------------------------------------------------
-- CHECK VALUE
--------------------------------------------------------------------------------

local function hasValue(value)

	if value == nil then
		return false
	end

	if type(value) == "string" then
		return mw.text.trim(value) ~= ""
	end

	if type(value) == "table" then
		return next(value) ~= nil
	end

	return true
end


--------------------------------------------------------------------------------
-- GET ARGUMENTS
--------------------------------------------------------------------------------

local function getArgs(frame)

	local args = {}

	local source = frame

	local parent = frame:getParent()


	if parent and next(parent.args) then

		source = parent

	end


	for k, v in pairs(source.args) do

		local key = mw.text.trim(k)

		local value = clean(v)

		if value then

			args[key] = value

		end

	end


	return args
end


--------------------------------------------------------------------------------
-- NORMALIZE INPUT
--------------------------------------------------------------------------------

local function normalize(args)

	local result = {}

	for key, value in pairs(args) do

		local field =
			data.lookup[key] or key

		result[field] = value

	end

	return result
end


--------------------------------------------------------------------------------
-- ENTITY DETECTION
--------------------------------------------------------------------------------

local function getEntity(args)

	local entity = args.entity_type

	if not entity then

		entity =
			data.defaults.entity_type

	end


	if data.entities[entity] then

		return entity

	end


	return "player"
end


--------------------------------------------------------------------------------
-- TITLE
--------------------------------------------------------------------------------

local function getTitle(entity, args)

	if args.name then

		return args.name

	end


	if data.entities[entity] then

		return data.entities[entity].title

	end


	return data.meta.title
end


--------------------------------------------------------------------------------
-- IMAGE HANDLING
--------------------------------------------------------------------------------

local function buildImage(args)

	if not args.image then

		return nil

	end


	local width =
		args.image_width or DEFAULT_IMAGE_WIDTH


	local caption =
		args.caption or ""


	local image = {

		type = "image",

		image = args.image,

		size = width,

		caption = caption

	}


	return image
end


--------------------------------------------------------------------------------
-- FIELD BUILDER
--------------------------------------------------------------------------------

local function buildFields(layouts, args)

	local fields = {}


	for _, layout in ipairs(layouts) do

		local label =
			layout[1]

		local key =
			layout[2]


		local value =
			args[key]


		value =
			clean(value)


		if value then

			table.insert(fields, {

				label = label,

				value = value

			})

		end

	end


	return fields
end


--------------------------------------------------------------------------------
-- GROUP BUILDER
--------------------------------------------------------------------------------

local function buildGroups(entity, args)

	local groups = {}


	local entityData =
		data.entities[entity]


	if not entityData then

		return groups

	end


	for _, layoutName in ipairs(entityData.layouts) do

		local layout =
			data.layouts[layoutName]


		if layout then

			local fields =
				buildFields(layout, args)


			if #fields > 0 then

				table.insert(groups, {

					name =
						data.layoutTitles[layoutName]
						or layoutName,

					layoutName =
						layoutName,

					fields =
						fields

				})

			end

		end

	end


	return groups
end


--------------------------------------------------------------------------------
-- INFOBOX BUILDER
--------------------------------------------------------------------------------

local function buildInfobox(entity, args)

	local box = {}


	box.title =
		getTitle(entity, args)


	local image =
		buildImage(args)


	if image then

		box.image =
			image

	end


	box.groups =
		buildGroups(entity, args)


	return box
end


--------------------------------------------------------------------------------
-- MEDALS
--------------------------------------------------------------------------------
-- Supports both:
--
-- |medaltemplates=
-- |medals=
--
-- medaltemplates has priority when both are supplied.
--------------------------------------------------------------------------------

local function addMedals(result, args)

	local medals =
		args.medaltemplates


	if not hasValue(medals) then

		medals =
			args.medals

	end


	if not hasValue(medals) then

		return

	end


	local frame =
		mw.getCurrentFrame()


	local content =
		frame:expandTemplate{

			title =
				"Infobox medal templates",

			args = {

				medals =
					medals,

				title =
					args.medaltemplates_title
					or "",

				expand =
					"yes"

			}

		}


	if not hasValue(content) then

		return

	end


	table.insert(
		result,

		'<tr>' ..
		'<td colspan="2" class="sport-infobox-medals">' ..
		content ..
		'</td>' ..
		'</tr>'

	)

end


--------------------------------------------------------------------------------
-- RENDER TEXT
--------------------------------------------------------------------------------

local function renderValue(value)

	if type(value) == "table" then

		return table.concat(value, "، ")

	end


	return tostring(value)
end


--------------------------------------------------------------------------------
-- RENDER INFOBOX
--------------------------------------------------------------------------------

local function renderInfobox(box, args)

	local result = {}


	table.insert(
		result,

		'<table class="sport-infobox">'

	)


	------------------------------------------------------------
	-- TITLE
	------------------------------------------------------------

	if box.title then

		table.insert(

			result,

			'<tr class="sport-infobox-title">' ..

			'<th colspan="2">' ..

			box.title ..

			'</th></tr>'

		)

	end


	------------------------------------------------------------
	-- IMAGE
	------------------------------------------------------------

	if box.image then

		local image =
			box.image

		local file =
			image.image

		local size =
			image.size or DEFAULT_IMAGE_WIDTH

		local caption =
			image.caption or ""


		table.insert(

			result,

			'<tr>' ..

			'<td colspan="2" class="sport-infobox-image">' ..

			'[[File:' ..

			file ..

			'|' ..

			size ..

			']]'

		)


		if caption ~= "" then

			table.insert(

				result,

				'<div class="sport-infobox-caption">' ..

				caption ..

				'</div>'

			)

		end


		table.insert(

			result,

			'</td></tr>'

		)

	end


	------------------------------------------------------------
	-- GROUPS
	------------------------------------------------------------

	for _, group in ipairs(box.groups) do


		table.insert(

			result,

			'<tr class="sport-infobox-header">' ..

			'<th colspan="2">' ..

			group.name ..

			'</th></tr>'

		)


		for _, field in ipairs(group.fields) do


			table.insert(

				result,

				'<tr>' ..

				'<th class="sport-infobox-label">' ..

				field.label ..

				'</th>' ..

				'<td class="sport-infobox-value">' ..

				renderValue(field.value) ..

				'</td>' ..

				'</tr>'

			)

		end


		--------------------------------------------------------
		-- MEDALS
		--------------------------------------------------------
		-- Insert medals immediately after the Honors group.
		--------------------------------------------------------

		if group.layoutName == "honors" then

			addMedals(
				result,
				args
			)

		end

	end


	------------------------------------------------------------
	-- CLOSE
	------------------------------------------------------------

	table.insert(

		result,

		'</table>'

	)


	return table.concat(
		result,
		"\n"
	)
end


--------------------------------------------------------------------------------
-- PUBLIC FUNCTION
--------------------------------------------------------------------------------

function p.main(frame)

	local args =
		getArgs(frame)


	args =
		normalize(args)


	local entity =
		getEntity(args)


	local box =
		buildInfobox(
			entity,
			args
		)


	return renderInfobox(
		box,
		args
	)
end


--------------------------------------------------------------------------------
-- TEMPLATE ENTRY
--------------------------------------------------------------------------------

function p.infobox(frame)

	return p.main(frame)

end


--------------------------------------------------------------------------------
-- DEBUG FUNCTION
--------------------------------------------------------------------------------

function p.test(frame)

	local args =
		getArgs(frame)


	args =
		normalize(args)


	local entity =
		getEntity(args)


	local entityData =
		data.entities[entity]


	if not entityData then

		return "Entity not found"

	end


	local result = {}


	table.insert(
		result,

		"Entity: " ..
		entity

	)


	table.insert(
		result,

		"Title: " ..
		entityData.title

	)


	table.insert(
		result,

		"Layouts: " ..

		table.concat(

			entityData.layouts,

			", "

		)

	)


	return table.concat(
		result,
		"\n"
	)
end


--------------------------------------------------------------------------------
-- GET ENTITY LIST
--------------------------------------------------------------------------------

function p.entities()

	local result = {}


	for key, value in pairs(data.entities) do

		table.insert(

			result,

			key ..
			" : " ..
			value.title

		)

	end


	return table.concat(
		result,
		"\n"
	)
end


--------------------------------------------------------------------------------
-- GET VERSION
--------------------------------------------------------------------------------

function p.version()

	return

		data.version.name ..

		" v" ..

		data.version.major ..

		"." ..

		data.version.minor
end


--------------------------------------------------------------------------------
-- EXPORT
--------------------------------------------------------------------------------

return p