پرش به محتوا

پودمان:AlborzSports: تفاوت میان نسخه‌ها

از ویکی البرز
جزبدون خلاصۀ ویرایش
جزبدون خلاصۀ ویرایش
 
(۳ نسخهٔ میانیِ ایجادشده توسط همین کاربر نشان داده نشد)
خط ۳: خط ۳:
-- Wiki Alborz Sports Information System
-- Wiki Alborz Sports Information System
-- Core Engine
-- Core Engine
-- Version 2.1
-- Version 2.2.2 (Fixed Entity Detection Priority)
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local p = {}
local p = {}
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- LOAD DATA
-- LOAD DATA
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
 
local data = mw.loadData("Module:AlborzSports/Data")
local data =
mw.loadData("Module:AlborzSports/Data")
 
--------------------------------------------------------------------------------
-- LOAD DEPENDENCIES
--------------------------------------------------------------------------------
 
local infobox =
require("Module:Infobox")
 
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- CONFIG
-- CONFIG
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
 
local DEFAULT_IMAGE_WIDTH = data.meta.imageWidth or "280px"
local DEFAULT_IMAGE_WIDTH =
data.meta.imageWidth or "280px"
 
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- UTILITY FUNCTIONS
-- UTILITY FUNCTIONS
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function clean(value)
local function clean(value)
if value == nil then
if value == nil then
return nil
return nil
end
end
if type(value) == "string" then
if type(value) == "string" then
 
value = mw.text.trim(value)
value =
mw.text.trim(value)
 
if value == "" then
if value == "" then
return nil
return nil
end
end
end
end
return value
return value
end
end
--------------------------------------------------------------------------------
-- HAS 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
-- GET ARGUMENTS
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function getArgs(frame)
local function getArgs(frame)
local args = {}
local args = {}
 
local source = frame
local source =
local parent = frame:getParent()
frame
 
local parent =
frame:getParent()
 
 
if parent and next(parent.args) then
if parent and next(parent.args) then
 
source = parent
source =
parent
 
end
end
 
for key, value in pairs(source.args) do
 
local cleanKey = mw.text.trim(tostring(key))
for k, v in pairs(source.args) do
local cleanValue = clean(value)
 
if cleanKey ~= "" and cleanValue then
local key =
args[cleanKey] = cleanValue
mw.text.trim(k)
 
local value =
clean(v)
 
 
if value then
 
args[key] =
value
 
end
end
end
end
return args
return args
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- NORMALIZE INPUT
-- NORMALIZE INPUT
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function normalize(args)
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
--------------------------------------------------------------------------------
-- LOCAL ENTITY ALIASES (تکمیل‌کننده Data برای پشتیبانی کامل فارسی)
--------------------------------------------------------------------------------
local localEntityAliases = {
-- People
player = "player",
athlete = "player",
["بازیکن"] = "player",
["ورزشکار"] = "player",
coach = "coach",
["مربی"] = "coach",
referee = "referee",
["داور"] = "referee",
manager = "manager",
["مدیر ورزشی"] = "manager",
["مدیر"] = "manager",


local result = {}
-- Clubs
club = "club",
sports_club = "club",
sport_club = "club",
["باشگاه"] = "club",
["باشگاه ورزشی"] = "club",


-- Academy
academy = "academy",
["آکادمی"] = "academy",
["آکادمی ورزشی"] = "academy",


for key, value in pairs(args) do
-- Facilities
stadium = "stadium",
["ورزشگاه"] = "stadium",
gym = "gym",
gymnasium = "gym",
["سالن"] = "gym",
["سالن ورزشی"] = "gym",
pool = "pool",
swimming_pool = "pool",
["استخر"] = "pool",
zurkhaneh = "zurkhaneh",
["زورخانه"] = "zurkhaneh",
sports_school = "sports_school",
["مدرسه ورزشی"] = "sports_school",
sports_complex = "sports_complex",
["مجموعه ورزشی"] = "sports_complex",
facility = "facility",
["مجموعه"] = "facility",


local field =
-- Organization / Board
data.lookup[key]
board = "board",
or key
sports_board = "board",
["هیئت"] = "board",
["هیئت ورزشی"] = "board",


-- Competition
competition = "competition",
["مسابقه"] = "competition",
["مسابقات"] = "competition"
}
--------------------------------------------------------------------------------
-- ENTITY DETECTION
--------------------------------------------------------------------------------
local function getEntity(args)
local entity = clean(args.entity_type)


result[field] =
----------------------------------------------------------------
value
-- EXPLICIT ENTITY TYPE
--
-- اگر کاربر صریحاً entity_type داده باشد،
-- بالاترین اولویت را دارد.
----------------------------------------------------------------
if entity then
entity = (data.entityAliases and data.entityAliases[entity])
or localEntityAliases[entity]
or entity


if data.entities[entity] then
return entity
end
end
end


----------------------------------------------------------------
-- INFERENCE FROM SUBTYPE (نوع)
----------------------------------------------------------------
local subtype = clean(args.subtype)
if subtype then
local lowerSubtype = mw.ustring.lower(subtype)


return result
------------------------------------------------------------
-- CLUB
------------------------------------------------------------
if mw.ustring.find(subtype, "باشگاه")
or mw.ustring.find(lowerSubtype, "club") then
return "club"
end


end
------------------------------------------------------------
-- ACADEMY
------------------------------------------------------------
if mw.ustring.find(subtype, "آکادمی")
or mw.ustring.find(lowerSubtype, "academy") then
return "academy"
end


--------------------------------------------------------------------------------
------------------------------------------------------------
-- ENTITY DETECTION
-- STADIUM
--------------------------------------------------------------------------------
------------------------------------------------------------
if mw.ustring.find(subtype, "ورزشگاه")
or mw.ustring.find(lowerSubtype, "stadium") then
return "stadium"
end


local function getEntity(args)
------------------------------------------------------------
-- GYM
------------------------------------------------------------
if mw.ustring.find(subtype, "سالن")
or mw.ustring.find(lowerSubtype, "gym") then
return "gym"
end


local entity =
------------------------------------------------------------
args.entity_type
-- SWIMMING POOL
------------------------------------------------------------
if mw.ustring.find(subtype, "استخر")
or mw.ustring.find(lowerSubtype, "pool") then
return "pool"
end


------------------------------------------------------------
-- ZURKHANEH
------------------------------------------------------------
if mw.ustring.find(subtype, "زورخانه")
or mw.ustring.find(lowerSubtype, "zurkhaneh") then
return "zurkhaneh"
end


if not entity then
------------------------------------------------------------
-- SPORTS SCHOOL
------------------------------------------------------------
if mw.ustring.find(subtype, "مدرسه")
or mw.ustring.find(lowerSubtype, "school") then
return "sports_school"
end


entity =
------------------------------------------------------------
data.defaults.entity_type
-- SPORTS COMPLEX
------------------------------------------------------------
if mw.ustring.find(subtype, "مجموعه")
or mw.ustring.find(lowerSubtype, "complex") then
return "sports_complex"
end


------------------------------------------------------------
-- SPORTS BOARD
------------------------------------------------------------
if mw.ustring.find(subtype, "هیئت")
or mw.ustring.find(lowerSubtype, "board") then
return "board"
end
end
end


----------------------------------------------------------------
-- INFERENCE FROM FIELDS
----------------------------------------------------------------
if args.established
or args.manager
or args.owner
or args.president
or args.ceo
or args.stadium
or args.capacity
or args.facilities
or args.services
or (args.address and args.city) then
------------------------------------------------------------
-- STADIUM
------------------------------------------------------------
if args.stadium or args.capacity then
return "stadium"
end


if data.entities[entity] then
------------------------------------------------------------
-- CLUB
------------------------------------------------------------
return "club"
end


return entity
----------------------------------------------------------------
-- DEFAULT ENTITY
----------------------------------------------------------------
local defaultEntity = data.defaults.entity_type or "player"


defaultEntity = (data.entityAliases and data.entityAliases[defaultEntity])
or localEntityAliases[defaultEntity]
or defaultEntity
if data.entities[defaultEntity] then
return defaultEntity
end
end


 
----------------------------------------------------------------
-- FINAL SAFE FALLBACK
----------------------------------------------------------------
return "player"
return "player"
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- TITLE
-- TITLE
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function getTitle(entity, args)
local function getTitle(entity, args)
if args.name then
if args.name then
return args.name
return args.name
end
end
 
local entityData = data.entities[entity]
 
if entityData and entityData.title then
if data.entities[entity] then
return entityData.title
 
return data.entities[entity].title
 
end
end
return data.meta.title
return data.meta.title
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- IMAGE HANDLING
-- IMAGE HANDLING
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function buildImage(args)
local function buildImage(args)
if not args.image then
if not args.image then
return nil
return nil
end
end
 
local width = args.image_width or DEFAULT_IMAGE_WIDTH
 
local caption = args.caption or ""
local width =
args.image_width
or DEFAULT_IMAGE_WIDTH
 
 
local caption =
args.caption
or ""
 
 
return {
return {
type = "image",
type = "image",
image = args.image,
image = args.image,
size = width,
size = width,
caption = caption
caption = caption
}
}
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- FIELD BUILDER
-- FIELD BUILDER
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function buildFields(layout, args)
local function buildFields(layout, args)
local fields = {}
local fields = {}
for _, item in ipairs(layout) do
for _, item in ipairs(layout) do
 
local label = item[1]
local label =
local key = item[2]
item[1]
local value = clean(args[key])
 
local key =
item[2]
 
 
local value =
args[key]
 
 
value =
clean(value)
 
 
if value then
if value then
 
table.insert(fields, {
table.insert(
label = label,
 
value = value
fields,
})
 
{
 
label = label,
 
value = value
 
}
 
)
 
end
end
end
end
return fields
return fields
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- GROUP BUILDER
-- GROUP BUILDER
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function buildGroups(entity, args)
local function buildGroups(entity, args)
local groups = {}
local groups = {}
 
local entityData = data.entities[entity]
 
local entityData =
data.entities[entity]
 
 
if not entityData then
if not entityData then
return groups
return groups
end
end


 
for _, layoutName in ipairs(entityData.layouts or {}) do
for _, layoutName in ipairs(entityData.layouts) do
local layout = data.layouts[layoutName]
 
local layout =
data.layouts[layoutName]
 
 
if layout then
if layout then
 
local fields = buildFields(layout, args)
local fields =
buildFields(
layout,
args
)
 
 
if #fields > 0 then
if #fields > 0 then
 
local title = data.layoutTitles[layoutName] or layoutName
table.insert(
table.insert(groups, {
 
name = title,
groups,
fields = fields
 
})
{
 
name =
data.layoutTitles[layoutName]
or layoutName,
 
layoutName =
layoutName,
 
fields =
fields
 
}
 
)
 
end
end
end
end
end
end
return groups
return groups
end
--------------------------------------------------------------------------------
-- MEDAL BUILDER
--------------------------------------------------------------------------------
local function buildMedals(args)
local medals = clean(args.medaltemplates)
if not medals then
medals = clean(args.medals)
end
if not medals then
return nil
end


local frame = mw.getCurrentFrame()
local content = frame:expandTemplate{
title = "Infobox medal templates",
args = {
medals = medals,
title = args.medaltemplates_title or "",
expand = "yes"
}
}
content = clean(content)
if not content then
return nil
end
return content
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- INFOBOX BUILDER
-- INFOBOX BUILDER
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function buildInfobox(entity, args)
local function buildInfobox(entity, args)
local box = {}
local box = {}
box.title = getTitle(entity, args)


 
local image = buildImage(args)
box.title =
getTitle(
entity,
args
)
 
 
local image =
buildImage(args)
 
 
if image then
if image then
 
box.image = image
box.image =
image
 
end
end


 
box.groups = buildGroups(entity, args)
box.groups =
box.medals = buildMedals(args)
buildGroups(
entity,
args
)
 


return box
return box
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- RENDER VALUE
-- RENDER VALUE
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function renderValue(value)
local function renderValue(value)
if type(value) == "table" then
if type(value) == "table" then
 
return table.concat(value, "، ")
return table.concat(
value,
"، "
)
 
end
end
return tostring(value)
return tostring(value)
end
--------------------------------------------------------------------------------
-- RENDER MEDALS
--------------------------------------------------------------------------------
-- The medal template is expanded separately.
--
-- IMPORTANT:
-- The returned medal table is inserted INSIDE a <td>
-- belonging to the main sport infobox.
--------------------------------------------------------------------------------
local function renderMedals(args)
local medals =
args.medaltemplates
if not hasValue(medals) then
medals =
args.medals
end
if not hasValue(medals) then
return nil
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 nil
end
return content
end
--------------------------------------------------------------------------------
-- RENDER MEDAL ROW
--------------------------------------------------------------------------------
-- Keeps the medal table inside the main infobox.
--------------------------------------------------------------------------------
local function renderMedalRow(medals)
if not medals then
return nil
end
return
'<tr class="sport-infobox-medals-row">' ..
'<td colspan="2" class="sport-infobox-medals">' ..
medals ..
'</td>' ..
'</tr>'
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- RENDER INFOBOX
-- RENDER INFOBOX
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
 
local function renderInfobox(box)
local function renderInfobox(box, args)
 
local result = {}
local result = {}


table.insert(result, '<table class="sport-infobox">')


------------------------------------------------------------
-- Title
-- MEDALS
------------------------------------------------------------
 
local medals =
renderMedals(args)
 
 
local medalsRendered =
false
 
 
------------------------------------------------------------
-- OPEN MAIN TABLE
------------------------------------------------------------
 
table.insert(
 
result,
 
'<table class="sport-infobox">'
 
)
 
 
------------------------------------------------------------
-- TITLE
------------------------------------------------------------
 
if box.title then
if box.title then
 
table.insert(result,
table.insert(
 
result,
 
'<tr class="sport-infobox-title">' ..
'<tr class="sport-infobox-title">' ..
 
'<th colspan="2">' .. box.title .. '</th></tr>'
'<th colspan="2">' ..
 
box.title ..
 
'</th>' ..
 
'</tr>'
 
)
)
end
end


 
-- Image
------------------------------------------------------------
-- IMAGE
------------------------------------------------------------
 
if box.image then
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 ""


local image =
table.insert(result,
box.image
'<tr><td colspan="2" class="sport-infobox-image">' ..
 
'[[File:' .. file .. '|' .. size .. ']]'
 
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
if caption ~= "" then
 
table.insert(result,
table.insert(
'<div class="sport-infobox-caption">' .. caption .. '</div>'
 
result,
 
'<div class="sport-infobox-caption">' ..
 
caption ..
 
'</div>'
 
)
)
end
end
 
table.insert(result, '</td></tr>')
 
table.insert(
 
result,
 
'</td>' ..
 
'</tr>'
 
)
 
end
end


 
-- Groups
------------------------------------------------------------
-- GROUPS
------------------------------------------------------------
 
for _, group in ipairs(box.groups) do
for _, group in ipairs(box.groups) do
 
table.insert(result,
 
--------------------------------------------------------
-- GROUP HEADER
--------------------------------------------------------
 
table.insert(
 
result,
 
'<tr class="sport-infobox-header">' ..
'<tr class="sport-infobox-header">' ..
 
'<th colspan="2">' .. group.name .. '</th></tr>'
'<th colspan="2">' ..
 
group.name ..
 
'</th>' ..
 
'</tr>'
 
)
)
--------------------------------------------------------
-- GROUP FIELDS
--------------------------------------------------------
for _, field in ipairs(group.fields) do
for _, field in ipairs(group.fields) do
 
table.insert(result,
table.insert(
 
result,
 
'<tr>' ..
'<tr>' ..
 
'<th class="sport-infobox-label">' .. field.label .. '</th>' ..
'<th class="sport-infobox-label">' ..
'<td class="sport-infobox-value">' .. renderValue(field.value) .. '</td>' ..
 
field.label ..
 
'</th>' ..
 
'<td class="sport-infobox-value">' ..
 
renderValue(field.value) ..
 
'</td>' ..
 
'</tr>'
'</tr>'
)
)
end
--------------------------------------------------------
-- MEDALS
--------------------------------------------------------
-- Insert the medal table INSIDE the main infobox.
--------------------------------------------------------
if group.layoutName == "honors"
and medals
and not medalsRendered then
local medalRow =
renderMedalRow(medals)
if medalRow then
table.insert(
result,
medalRow
)
medalsRendered =
true
end
end
end
end
end


 
-- Medals
------------------------------------------------------------
if box.medals then
-- MEDALS FALLBACK
table.insert(result,
------------------------------------------------------------
'<tr><td colspan="2" class="sport-infobox-medals">' ..
-- If no honors group was generated, add the medal section
box.medals .. '</td></tr>'
-- directly before closing the main infobox.
------------------------------------------------------------
 
if medals
and not medalsRendered then
 
 
--------------------------------------------------------
-- HEADER
--------------------------------------------------------
 
table.insert(
 
result,
 
'<tr class="sport-infobox-header">' ..
 
'<th colspan="2">افتخارات</th>' ..
 
'</tr>'
 
)
)
--------------------------------------------------------
-- MEDAL TABLE
--------------------------------------------------------
local medalRow =
renderMedalRow(medals)
if medalRow then
table.insert(
result,
medalRow
)
end
medalsRendered =
true
end
end


 
table.insert(result, '</table>')
------------------------------------------------------------
return table.concat(result, "\n")
-- CLOSE MAIN TABLE
------------------------------------------------------------
 
table.insert(
 
result,
 
'</table>'
 
)
 
 
return table.concat(
 
result,
 
"\n"
 
)
 
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- PUBLIC FUNCTION
-- PUBLIC FUNCTION
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function p.main(frame)
function p.main(frame)
 
local args = getArgs(frame)
local args =
args = normalize(args)
getArgs(frame)
local entity = getEntity(args)
 
local box = buildInfobox(entity, args)
 
return renderInfobox(box)
args =
normalize(args)
 
 
local entity =
getEntity(args)
 
 
local box =
buildInfobox(
entity,
args
)
 
 
return renderInfobox(
box,
args
)
 
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- TEMPLATE ENTRY
-- TEMPLATE ENTRY
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function p.infobox(frame)
function p.infobox(frame)
return p.main(frame)
return p.main(frame)
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- DEBUG FUNCTION
-- DEBUG FUNCTION
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function p.test(frame)
function p.test(frame)
 
local args = getArgs(frame)
local args =
args = normalize(args)
getArgs(frame)
local entity = getEntity(args)
 
local entityData = data.entities[entity]
 
args =
normalize(args)
 
 
local entity =
getEntity(args)
 
 
local entityData =
data.entities[entity]
 


if not entityData then
if not entityData then
 
return "Entity not found: " .. tostring(entity)
return "Entity not found"
 
end
end


local result = {}
local result = {}
table.insert(result, "Entity: " .. entity)
table.insert(result, "Title: " .. tostring(entityData.title))
table.insert(result, "Layouts: " .. table.concat(entityData.layouts or {}, ", "))
table.insert(result, "Subtype: " .. tostring(args.subtype or "NOT FOUND"))
table.insert(result, "Coach: " .. tostring(args.coach or "NOT FOUND"))
table.insert(result, "Medals: " .. tostring(args.medaltemplates or args.medals or "NOT FOUND"))


 
return table.concat(result, "\n")
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
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- GET ENTITY LIST
-- GET ENTITY LIST
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function p.entities()
function p.entities()
local result = {}
local result = {}
for key, value in pairs(data.entities) do
for key, value in pairs(data.entities) do
 
table.insert(result, key .. " : " .. tostring(value.title))
table.insert(
 
result,
 
key ..
" : " ..
value.title
 
)
 
end
end
 
table.sort(result)
 
return table.concat(result, "\n")
return table.concat(
 
result,
 
"\n"
 
)
 
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- GET VERSION
-- GET VERSION
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function p.version()
function p.version()
 
return data.version.name .. " v" .. data.version.major .. "." .. data.version.minor
return
 
data.version.name ..
 
" v" ..
 
data.version.major ..
 
"." ..
 
data.version.minor
 
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- EXPORT
-- EXPORT
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
return p
return p

نسخهٔ کنونی تا ‏۱۰ اوت ۲۰۲۶، ساعت ۱۸:۲۹

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

--------------------------------------------------------------------------------
-- Module:AlborzSports
-- Wiki Alborz Sports Information System
-- Core Engine
-- Version 2.2.2 (Fixed Entity Detection Priority)
--------------------------------------------------------------------------------
local p = {}
--------------------------------------------------------------------------------
-- LOAD DATA
--------------------------------------------------------------------------------
local data = mw.loadData("Module:AlborzSports/Data")
--------------------------------------------------------------------------------
-- CONFIG
--------------------------------------------------------------------------------
local DEFAULT_IMAGE_WIDTH = data.meta.imageWidth or "280px"
--------------------------------------------------------------------------------
-- 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
--------------------------------------------------------------------------------
-- 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 key, value in pairs(source.args) do
		local cleanKey = mw.text.trim(tostring(key))
		local cleanValue = clean(value)
		if cleanKey ~= "" and cleanValue then
			args[cleanKey] = cleanValue
		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
--------------------------------------------------------------------------------
-- LOCAL ENTITY ALIASES (تکمیل‌کننده Data برای پشتیبانی کامل فارسی)
--------------------------------------------------------------------------------
local localEntityAliases = {
	-- People
	player = "player",
	athlete = "player",
	["بازیکن"] = "player",
	["ورزشکار"] = "player",
	coach = "coach",
	["مربی"] = "coach",
	referee = "referee",
	["داور"] = "referee",
	manager = "manager",
	["مدیر ورزشی"] = "manager",
	["مدیر"] = "manager",

	-- Clubs
	club = "club",
	sports_club = "club",
	sport_club = "club",
	["باشگاه"] = "club",
	["باشگاه ورزشی"] = "club",

	-- Academy
	academy = "academy",
	["آکادمی"] = "academy",
	["آکادمی ورزشی"] = "academy",

	-- Facilities
	stadium = "stadium",
	["ورزشگاه"] = "stadium",
	gym = "gym",
	gymnasium = "gym",
	["سالن"] = "gym",
	["سالن ورزشی"] = "gym",
	pool = "pool",
	swimming_pool = "pool",
	["استخر"] = "pool",
	zurkhaneh = "zurkhaneh",
	["زورخانه"] = "zurkhaneh",
	sports_school = "sports_school",
	["مدرسه ورزشی"] = "sports_school",
	sports_complex = "sports_complex",
	["مجموعه ورزشی"] = "sports_complex",
	facility = "facility",
	["مجموعه"] = "facility",

	-- Organization / Board
	board = "board",
	sports_board = "board",
	["هیئت"] = "board",
	["هیئت ورزشی"] = "board",

	-- Competition
	competition = "competition",
	["مسابقه"] = "competition",
	["مسابقات"] = "competition"
}
--------------------------------------------------------------------------------
-- ENTITY DETECTION
--------------------------------------------------------------------------------
local function getEntity(args)
	local entity = clean(args.entity_type)

	----------------------------------------------------------------
	-- EXPLICIT ENTITY TYPE
	--
	-- اگر کاربر صریحاً entity_type داده باشد،
	-- بالاترین اولویت را دارد.
	----------------------------------------------------------------
	if entity then
		entity = (data.entityAliases and data.entityAliases[entity])
			or localEntityAliases[entity]
			or entity

		if data.entities[entity] then
			return entity
		end
	end

	----------------------------------------------------------------
	-- INFERENCE FROM SUBTYPE (نوع)
	----------------------------------------------------------------
	local subtype = clean(args.subtype)

	if subtype then
		local lowerSubtype = mw.ustring.lower(subtype)

		------------------------------------------------------------
		-- CLUB
		------------------------------------------------------------
		if mw.ustring.find(subtype, "باشگاه")
			or mw.ustring.find(lowerSubtype, "club") then
			return "club"
		end

		------------------------------------------------------------
		-- ACADEMY
		------------------------------------------------------------
		if mw.ustring.find(subtype, "آکادمی")
			or mw.ustring.find(lowerSubtype, "academy") then
			return "academy"
		end

		------------------------------------------------------------
		-- STADIUM
		------------------------------------------------------------
		if mw.ustring.find(subtype, "ورزشگاه")
			or mw.ustring.find(lowerSubtype, "stadium") then
			return "stadium"
		end

		------------------------------------------------------------
		-- GYM
		------------------------------------------------------------
		if mw.ustring.find(subtype, "سالن")
			or mw.ustring.find(lowerSubtype, "gym") then
			return "gym"
		end

		------------------------------------------------------------
		-- SWIMMING POOL
		------------------------------------------------------------
		if mw.ustring.find(subtype, "استخر")
			or mw.ustring.find(lowerSubtype, "pool") then
			return "pool"
		end

		------------------------------------------------------------
		-- ZURKHANEH
		------------------------------------------------------------
		if mw.ustring.find(subtype, "زورخانه")
			or mw.ustring.find(lowerSubtype, "zurkhaneh") then
			return "zurkhaneh"
		end

		------------------------------------------------------------
		-- SPORTS SCHOOL
		------------------------------------------------------------
		if mw.ustring.find(subtype, "مدرسه")
			or mw.ustring.find(lowerSubtype, "school") then
			return "sports_school"
		end

		------------------------------------------------------------
		-- SPORTS COMPLEX
		------------------------------------------------------------
		if mw.ustring.find(subtype, "مجموعه")
			or mw.ustring.find(lowerSubtype, "complex") then
			return "sports_complex"
		end

		------------------------------------------------------------
		-- SPORTS BOARD
		------------------------------------------------------------
		if mw.ustring.find(subtype, "هیئت")
			or mw.ustring.find(lowerSubtype, "board") then
			return "board"
		end
	end

	----------------------------------------------------------------
	-- INFERENCE FROM FIELDS
	----------------------------------------------------------------
	if args.established
		or args.manager
		or args.owner
		or args.president
		or args.ceo
		or args.stadium
		or args.capacity
		or args.facilities
		or args.services
		or (args.address and args.city) then

		------------------------------------------------------------
		-- STADIUM
		------------------------------------------------------------
		if args.stadium or args.capacity then
			return "stadium"
		end

		------------------------------------------------------------
		-- CLUB
		------------------------------------------------------------
		return "club"
	end

	----------------------------------------------------------------
	-- DEFAULT ENTITY
	----------------------------------------------------------------
	local defaultEntity = data.defaults.entity_type or "player"

	defaultEntity = (data.entityAliases and data.entityAliases[defaultEntity])
		or localEntityAliases[defaultEntity]
		or defaultEntity

	if data.entities[defaultEntity] then
		return defaultEntity
	end

	----------------------------------------------------------------
	-- FINAL SAFE FALLBACK
	----------------------------------------------------------------
	return "player"
end
--------------------------------------------------------------------------------
-- TITLE
--------------------------------------------------------------------------------
local function getTitle(entity, args)
	if args.name then
		return args.name
	end
	local entityData = data.entities[entity]
	if entityData and entityData.title then
		return entityData.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 ""
	return {
		type = "image",
		image = args.image,
		size = width,
		caption = caption
	}
end
--------------------------------------------------------------------------------
-- FIELD BUILDER
--------------------------------------------------------------------------------
local function buildFields(layout, args)
	local fields = {}
	for _, item in ipairs(layout) do
		local label = item[1]
		local key = item[2]
		local value = clean(args[key])
		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 or {}) do
		local layout = data.layouts[layoutName]
		if layout then
			local fields = buildFields(layout, args)
			if #fields > 0 then
				local title = data.layoutTitles[layoutName] or layoutName
				table.insert(groups, {
					name = title,
					fields = fields
				})
			end
		end
	end
	return groups
end
--------------------------------------------------------------------------------
-- MEDAL BUILDER
--------------------------------------------------------------------------------
local function buildMedals(args)
	local medals = clean(args.medaltemplates)
	if not medals then
		medals = clean(args.medals)
	end
	if not medals then
		return nil
	end

	local frame = mw.getCurrentFrame()
	local content = frame:expandTemplate{
		title = "Infobox medal templates",
		args = {
			medals = medals,
			title = args.medaltemplates_title or "",
			expand = "yes"
		}
	}
	content = clean(content)
	if not content then
		return nil
	end
	return content
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)
	box.medals = buildMedals(args)

	return box
end
--------------------------------------------------------------------------------
-- RENDER VALUE
--------------------------------------------------------------------------------
local function renderValue(value)
	if type(value) == "table" then
		return table.concat(value, "، ")
	end
	return tostring(value)
end
--------------------------------------------------------------------------------
-- RENDER INFOBOX
--------------------------------------------------------------------------------
local function renderInfobox(box)
	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
	end

	-- Medals
	if box.medals then
		table.insert(result,
			'<tr><td colspan="2" class="sport-infobox-medals">' ..
			box.medals .. '</td></tr>'
		)
	end

	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)
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: " .. tostring(entity)
	end

	local result = {}
	table.insert(result, "Entity: " .. entity)
	table.insert(result, "Title: " .. tostring(entityData.title))
	table.insert(result, "Layouts: " .. table.concat(entityData.layouts or {}, ", "))
	table.insert(result, "Subtype: " .. tostring(args.subtype or "NOT FOUND"))
	table.insert(result, "Coach: " .. tostring(args.coach or "NOT FOUND"))
	table.insert(result, "Medals: " .. tostring(args.medaltemplates or args.medals or "NOT FOUND"))

	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 .. " : " .. tostring(value.title))
	end
	table.sort(result)
	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