모듈:LoL
이 모듈에 대한 설명문서는 모듈:LoL/설명문서에서 만들 수 있습니다
local p = {}
-- Faction/Region mapping from Korean to English
local factionMap = {
["녹서스"] = "Noxus",
["데마시아"] = "Demacia",
["아이오니아"] = "Ionia",
["이오니아"] = "Ionia",
["킨코우 결사단"] = "Kinkou_Order",
["킨코우"] = "Kinkou_Order",
["킨쿠 결사단"] = "Ionia",
["킨쿠"] = "Ionia",
["빌지워터"] = "Bilgewater",
["그림자 군도"] = "Shadow_Isles",
["슈리마"] = "Shurima",
["타곤"] = "Mount_Targon",
["타곤 산"] = "Mount_Targon",
["타곤산"] = "Mount_Targon",
["라코어"] = "Mount_Targon",
["공허"] = "Void",
["자운"] = "Zaun",
["필트오버"] = "Piltover",
["밴들 시티"] = "Bandle_City",
["밴들시티"] = "Bandle_City",
["축복의 빛 군도"] = "Blessed_Isles",
["카마보르"] = "Camavor",
["이쉬탈"] = "Ixtal",
["룬테라"] = "Runeterra",
["빛의 감시자"] = "Sentinels_of_Light",
["크라운가드 가문"] = "Crownguard_House",
["크라운가드"] = "Crownguard_House",
["빛방패 가문"] = "Lightshield_House",
["빛의 방패"] = "Lightshield_House",
["빛의 방패 가문"] = "Lightshield_House",
["페로스 가문"] = "Ferros_Clan",
["키라만 가문"] = "Kiramman_House",
["프렐요드"] = "Freljord",
["겨울 발톱"] = "Freljord",
["아바로사"] = "Freljord",
}
-- Skill/Ability mapping from Korean to English
local skillMap = {
["만트라"] = "Mantra",
["무형의 검"] = "Formless_Blade",
["액체 칼날"] = "Formless_Blade",
["환희의 장막"] = "Jubilant_Veil",
["급류"] = "Slipstream",
["요동치는 인도"] = "Apotheosis",
["운명의 장난"] = "New_Destiny",
}
-- Champion mapping from Korean to English (parsed from wiki templates)
local champMap = {
['Card infobox'] = '{{{1}}}',
['MOONGTANGYEE'] = '뭉탱이',
['가렌'] = 'Garen',
['갈리오'] = 'Galio',
['갱플랭크'] = 'Gangplank',
['그라가스'] = 'Gragas',
['그레이브즈'] = 'Graves',
['길에서 보지 쳐팔고 다니는 하코 저주짤'] = '좆코뒤짐 와',
['나르'] = 'Gnar',
['나미'] = 'Nami',
['나서스'] = 'Nasus',
['노틸러스'] = 'Nautilus',
['녹턴'] = 'Nocturne',
['누누'] = 'Nunu',
['뉴튼 룩'] = 'portrait_Newton1',
['니달리'] = 'Nidalee',
['닉 밴드'] = 'portrait_Nick1',
['다리우스'] = 'Darius',
['다이애나'] = 'Diana',
['드레이븐'] = 'Draven',
['라이즈'] = 'Ryze',
['랄스턴 판슬리'] = 'portrait_Ralston1',
['랄스톤 판슬리'] = 'portrait_Ralston1',
['람머스'] = 'Rammus',
['램 스티드'] = 'portrait_Ram1',
['럭스'] = 'Lux',
['럼블'] = 'Rumble',
['레넥톤'] = 'Renekton',
['레오나'] = 'Leona',
['레이라 카슐드'] = 'portrait_Reira1',
['레이라 캐슐드'] = 'portrait_Reira1',
['레이라 케슐드'] = 'portrait_Reira1',
['렉사이'] = 'RekSai',
['렝가'] = 'Rengar',
['루시안'] = 'Lucian',
['룰루'] = 'Lulu',
['르블랑'] = 'Leblanc',
['리 신'] = 'LeeSin',
['리븐'] = 'Riven',
['리산드라'] = 'Lissandra',
['리쳐 에보니'] = 'portrait_Richor1',
['마스터 이'] = 'MasterYi',
['마오카이'] = 'Maokai',
['말자하'] = 'Malzahar',
['말파이트'] = 'Malphite',
['모건 래켐'] = 'portrait_CptMorgan1',
['모데카이저'] = 'Mordekaiser',
['모르가나'] = 'Morgana',
['문도 박사'] = 'DrMundo',
['미스 포츈'] = 'MissFortune',
['바드'] = 'Bard',
['바루스'] = 'Varus',
['바이'] = 'Vi',
['밥 나샤하고'] = 'portrait_Bob1',
['베이가'] = 'Veigar',
['베인'] = 'Vayne',
['벨코즈'] = 'Velkoz',
['볼리베어'] = 'Volibear',
['브라움'] = 'Braum',
['브랜드'] = 'Brand',
['브리스크스'] = 'portrait_LB1',
['브리스키스'] = 'portrait_LB1',
['블라디미르'] = 'Vladimir',
['블리츠크랭크'] = 'Blitzcrank',
['빅토르'] = 'Viktor',
['뽀삐'] = 'Poppy',
['사용자 상자:레스터 시티(GTA)'] = 'Leicester City FC',
['사이온'] = 'Sion',
['샤코'] = 'Shaco',
['세주아니'] = 'Sejuani',
['섹드립'] = '좆코를 강간하자',
['소나'] = 'Sona',
['소라카'] = 'Soraka',
['쉔'] = 'Shen',
['쉬바나'] = 'Shyvana',
['스웨인'] = 'Swain',
['스카너'] = 'Skarner',
['시비르'] = 'Sivir',
['신 짜오'] = 'XinZhao',
['신드라'] = 'Syndra',
['신지드'] = 'Singed',
['쓰레쉬'] = 'Thresh',
['아리'] = 'Ahri',
['아리아 브레커'] = 'portrait_Aria1',
['아무무'] = 'Amumu',
['아우라스 램'] = 'portrait_Auras1',
['아우러스 램'] = 'portrait_Ram1',
['아우렐리온 솔'] = 'AurelionSol',
['아지르'] = 'Azir',
['아칼리'] = 'Akali',
['아트록스'] = 'Aatrox',
['알리스타'] = 'Alistar',
['애니'] = 'Annie',
['애니비아'] = 'Anivia',
['애쉬'] = 'Ashe',
['야스오'] = 'Yasuo',
['에코'] = 'Ekko',
['엘리스'] = 'Elise',
['오공'] = 'MonkeyKing',
['오리아나'] = 'Orianna',
['올라프'] = 'Olaf',
['요릭'] = 'Yorick',
['우디르'] = 'Udyr',
['우르곳'] = 'Urgot',
['워윅'] = 'Warwick',
['유저박스:1000편집(GTA)'] = 'Silver_award',
['유저박스:Loud(GTA)'] = 'TheJewelStoreJob-GTAV-LoudApproachEscape',
['유저박스:채널 X(GTA)'] = 'ChannelXTee-GTAO-Advert',
['응 해봐'] = '광대드플',
['이렐리아'] = 'Irelia',
['이블린'] = 'Evelynn',
['이즈리얼'] = 'Ezreal',
['일라오이'] = 'Illaoi',
['자르반 4세'] = 'JarvanIV',
['자이라'] = 'Zyra',
['자전거의 종류'] = 'cycle',
['자크'] = 'Zac',
['잔나'] = 'Janna',
['잭스'] = 'Jax',
['제드'] = 'Zed',
['제라스'] = 'Xerath',
['제이스'] = 'Jayce',
['직스'] = 'Ziggs',
['진'] = 'Jhin',
['질리언'] = 'Zilean',
['징크스'] = 'Jinx',
['초가스'] = 'Chogath',
['카르마'] = 'Karma',
['카사딘'] = 'Kassadin',
['카서스'] = 'Karthus',
['카시오페아'] = 'Cassiopeia',
['카직스'] = 'Khazix',
['카타리나'] = 'Katarina',
['칼리스타'] = 'Kalista',
['케넨'] = 'Kennen',
['케이틀린'] = 'Caitlyn',
['케일'] = 'Kayle',
['코그모'] = 'KogMaw',
['코르키'] = 'Corki',
['퀸'] = 'Quinn',
['퀸톤 그로트'] = 'portrait_Quinton1',
['퀸튼 그로트'] = 'portrait_Quinton1',
['킨드레드'] = 'Kindred',
['타릭'] = 'Taric',
['탈론'] = 'Talon',
['탐 켄치'] = 'TahmKench',
['토비아스 드럼'] = 'portrait_Tobias1',
['톰 타룸카'] = 'portrait_Tom1',
['툼 타룸카'] = 'portrait_Tom1',
['트런들'] = 'Trundle',
['트리스타나'] = 'Tristana',
['트린다미어'] = 'Tryndamere',
['트위스티드 페이트'] = 'TwistedFate',
['트위치'] = 'Twitch',
['티모'] = 'Teemo',
['판테온'] = 'Pantheon',
['프레스트'] = 'portrait_Jace1',
['피들스틱'] = 'FiddleSticks',
['피오라'] = 'Fiora',
['피즈'] = 'Fizz',
['하이머딩거'] = 'Heimerdinger',
['헤카림'] = 'Hecarim',
['헨릴 드레빙'] = 'Portrait Henril1',
}
-- Manual fallback/update champion map for missing ones
local fallbackMap = {
["닐라"] = "Nilah",
["비에고"] = "Viego",
["그웬"] = "Gwen",
["세나"] = "Senna",
["피들스틱"] = "FiddleSticks",
["일라오이"] = "Illaoi",
["볼리베어"] = "Volibear",
["잔나"] = "Janna",
["모르가나"] = "Morgana",
["모데카이저"] = "Mordekaiser",
}
local function cleanName(name)
if not name then return "" end
name = mw.text.trim(name)
-- Remove namespace if present (e.g. "틀:" or "Template:")
name = string.gsub(name, "^[^:]+:", "")
-- Remove parentheses suffix like (LEAGUEOFLEGENDS)
name = string.gsub(name, "%s*%([^)]*%)$", "")
return name
end
-- Helper for ui and cbi rendering
local function renderIconLink(name, display, link, file, defaultSuffix)
if name == "" then
return ""
end
if display == "" then
display = name
end
local cleanNameVal = cleanName(name)
-- Determine target page link
if link == "" then
link = cleanNameVal .. "(LEAGUEOFLEGENDS)"
end
-- Determine file name
if file == "" then
local engName = champMap[cleanNameVal] or fallbackMap[cleanNameVal] or cleanNameVal
engName = string.gsub(engName, "%s", "_")
file = engName .. defaultSuffix
end
-- Check if file exists in MediaWiki
local fileTitle = mw.title.new("File:" .. file)
local imgHtml = ""
if fileTitle and fileTitle.exists then
imgHtml = "[[File:" .. file .. "|20px|link=" .. link .. "|alt=]] "
else
-- Fallback to checking without suffix if it fails
local baseFile = string.gsub(file, "Square%.png$", ".png")
local baseTitle = mw.title.new("File:" .. baseFile)
if baseTitle and baseTitle.exists then
imgHtml = "[[File:" .. baseFile .. "|20px|link=" .. link .. "|alt=]] "
end
end
return '<span class="unit-icon" style="white-space:nowrap;">' .. imgHtml .. '[[' .. link .. '|' .. display .. ']]</span>'
end
-- Unit Icon
function p.ui(frame)
local args = frame:getParent().args
if not args[1] then
args = frame.args
end
local name = args[1] or ""
local display = args[2] or ""
local link = args["link"] or args["링크"] or ""
local file = args["file"] or args["image"] or args["파일"] or args["이미지"] or ""
return renderIconLink(name, display, link, file, "Square.png")
end
-- Champion Biography Icon
function p.cbi(frame)
local args = frame:getParent().args
if not args[1] then
args = frame.args
end
local name = args[1] or ""
local display = args[2] or ""
local link = args["link"] or args["링크"] or ""
local file = args["file"] or args["image"] or args["파일"] or args["이미지"] or ""
return renderIconLink(name, display, link, file, "Square.png")
end
-- Faction/Region Icon
function p.fi(frame)
local args = frame:getParent().args
if not args[1] then
args = frame.args
end
local name = args[1] or ""
local display = args[2] or ""
if name == "" then
return ""
end
if display == "" then
display = name
end
local cleanFaction = cleanName(name)
local engFaction = factionMap[cleanFaction] or cleanFaction
local fileBase = string.gsub(engFaction, "%s", "_")
-- Check multiple crest/icon patterns
local patterns = {
"%s_Crest_icon.png",
"%s_Crest_icon.svg",
"%s_Crest.png",
"%s_icon.png",
"%sSquare.png",
"%s_Crest_icon.PNG",
"%s_Crest.PNG",
"%s_icon.PNG",
}
local foundFile = ""
for _, pattern in ipairs(patterns) do
local file = string.format(pattern, fileBase)
local fileTitle = mw.title.new("File:" .. file)
if fileTitle and fileTitle.exists then
foundFile = file
break
end
end
-- Form default link
local link = cleanFaction .. "(LEAGUEOFLEGENDS)"
local imgHtml = ""
if foundFile ~= "" then
imgHtml = "[[File:" .. foundFile .. "|20px|link=" .. link .. "|alt=]] "
end
return '<span class="faction-icon" style="white-space:nowrap;">' .. imgHtml .. '[[' .. link .. '|' .. display .. ']]</span>'
end
-- Ability Icon
function p.ai(frame)
local args = frame:getParent().args
if not args[1] then
args = frame.args
end
local skillName = args[1] or ""
local champName = args[2] or ""
local display = args[3] or ""
if skillName == "" then
return ""
end
if display == "" then
display = skillName
end
local cleanChamp = cleanName(champName)
local cleanSkill = cleanName(skillName)
local engChamp = champMap[cleanChamp] or fallbackMap[cleanChamp] or cleanChamp
local engSkill = skillMap[cleanSkill] or cleanSkill
local champBase = string.gsub(engChamp, "%s", "_")
local skillBase = string.gsub(engSkill, "%s", "_")
-- Check patterns for ability icons:
-- 1. [ChampName]_[SkillName].png
-- 2. [SkillName].png
local file1 = champBase .. "_" .. skillBase .. ".png"
local file2 = skillBase .. ".png"
local foundFile = ""
if mw.title.new("File:" .. file1).exists then
foundFile = file1
elseif mw.title.new("File:" .. file2).exists then
foundFile = file2
end
local link = cleanChamp .. "(LEAGUEOFLEGENDS)#" .. cleanSkill
local imgHtml = ""
if foundFile ~= "" then
imgHtml = "[[File:" .. foundFile .. "|20px|link=" .. link .. "|alt=]] "
end
return '<span class="ability-icon" style="white-space:nowrap;">' .. imgHtml .. '[[' .. link .. '|' .. display .. ']]</span>'
end
-- Passive progression (evaluates math in values like "1.2*12 ~ 2.4*12")
function p.pp(frame)
local args = frame:getParent().args
if not args[1] then
args = frame.args
end
local val = args[1] or ""
local function eval(expr)
expr = mw.text.trim(expr)
local success, result = pcall(function()
return frame:preprocess("{{#expr: " .. expr .. "}}")
end)
if success and result and not string.find(result, "Expression error") then
local num = tonumber(result)
if num then
if num == math.floor(num) then
return string.format("%d", num)
else
local formatted = string.format("%.2f", num)
formatted = string.gsub(formatted, "0+$", "")
formatted = string.gsub(formatted, "%.$", "")
return formatted
end
end
return result
end
return expr
end
local parts = {}
local sep = " ~ "
if string.find(val, "~") then
sep = " ~ "
for part in string.gmatch(val, "[^~]+") do
table.insert(parts, eval(part))
end
elseif string.find(val, "–") then
sep = " – "
for part in string.gmatch(val, "[^–]+") do
table.insert(parts, eval(part))
end
else
return eval(val)
end
return table.concat(parts, sep)
end
-- Adaptive Force conversion
function p.adaptive(frame)
local args = frame:getParent().args
if not args[1] then
args = frame.args
end
local val = args[1] or "0"
local sep = nil
if string.find(val, "~") then
sep = "~"
elseif string.find(val, "–") then
sep = "–"
end
if sep then
local parts_ad = {}
local parts_ap = {}
for part in string.gmatch(val, "[^" .. sep .. "]+") do
part = mw.text.trim(part)
table.insert(parts_ad, "0.6*(" .. part .. ")")
table.insert(parts_ap, part)
end
local expr_ad = table.concat(parts_ad, sep)
local expr_ap = table.concat(parts_ap, sep)
return "(" .. p.pp(frame:newChild{args={expr_ad}}) .. " '''추가''' 공격력 또는 " .. p.pp(frame:newChild{args={expr_ap}}) .. " 주문력)"
else
local num = tonumber(val) or 0
local ad = num * 0.6
local ap = num
local ad_str = string.format("%.2f", ad):gsub("0+$", ""):gsub("%.$", "")
local ap_str = string.format("%.2f", ap):gsub("0+$", ""):gsub("%.$", "")
return "(" .. ad_str .. " '''추가''' 공격력 또는 " .. ap_str .. " 주문력)"
end
end
return p