6,946 Pages

Documentation for this module may be created at Module:LoRData/doc

-- <pre>
local p         = {}
local lib       = require('Module:Feature')
local userError = require('Dev:User error')

local regions   = {
    ["BW"]              = "Bilgewater",
    ["DE"]              = "Demacia",
    ["FR"]              = "Freljord",
    ["IO"]              = "Ionia",
    ["NX"]              = "Noxus",
    ["PZ"]              = "Piltover & Zaun",
    ["SI"]              = "Shadow Isles",
    ["SH"]              = "Shurima",
    ["MT"]              = "Targon",
    ["Bilgewater"]      = "BW",
    ["Demacia"]         = "DE",
    ["Freljord"]        = "FR",
    ["Ionia"]           = "IO",
    ["Noxus"]           = "NX",
    ["Piltover & Zaun"] = "PZ",
    ["Shadow Isles"]    = "SI",
    ["Shurima"]         = "SH",
    ["Targon"]          = "MT"
}

-- Outdated: With "The Great Beyond"
function p.cardData()
	local json        = require('Module:JSON')
    local titleobject = mw.title.new('User:Ninjamask/Sandbox/LoR.json')
    local o           = json.decode(titleobject:getContent())
    local s           = ""
    local cardData    = {}
    local lang        = mw.language.new( "en" )

    
    for _, data in pairs(o) do
        table.insert(cardData, data)
    end
    table.sort(cardData, function(a, b) return a.cardCode < b.cardCode end)
    
    -- ============================
    -- = Generate lua data output =
    -- ============================
    
    s = s .. '-- <pre>\n'
    s = s .. '-- Legends of Runeterra data \n'
    s = s .. '\n'
    s = s .. 'return {\n'
    
    for i, card in pairs(cardData) do
        -- StatTable data 
        local sLoop = ""
        sLoop = sLoop .. '    ["' .. card.cardCode .. '"] = {\n'
        sLoop = sLoop .. '        ["name"]        = "'     .. card.name                  .. '",\n'
        sLoop = sLoop .. '        ["type"]        = "'     .. card.type                  .. '",\n'
        sLoop = sLoop .. '        ["rarity"]      = "'     .. lang:ucfirst(lang:lc(card.rarity))                .. '",\n'
        
        if card.subtype ~= "" then
            sLoop = sLoop .. '        ["subtype"]     = "' .. lang:ucfirst(lang:lc(card.subtype))               .. '",\n'
        end
        
        if card.supertype ~= "" then
            sLoop = sLoop .. '        ["supertype"]   = "' .. card.supertype             .. '",\n'
        end
        
        -- if card.spellSpeed ~= "" then
        --     sLoop = sLoop .. '        ["spellSpeed"]     = "' .. card.spellSpeed            .. '",\n'
        -- end
        
        local sKeywords = '{"'
        sKeywords = sKeywords .. table.concat(card.keywords, '", "') .. '"}'
        if sKeywords ~= '{""}' then
            sLoop = sLoop .. '        ["keywords"]    = '  .. lib.tbl_debug(card.keywords)     ..  ',\n'
        end
        
        sLoop = sLoop .. '        ["collectible"] = '      .. tostring(card.collectible) ..  ',\n'
        sLoop = sLoop .. '        ["cost"]        = '      .. card.cost                  ..  ',\n'
        sLoop = sLoop .. '        ["power"]       = '      .. card.attack                ..  ',\n'
        sLoop = sLoop .. '        ["health"]      = '      .. card.health                ..  ',\n'
        if card.descriptionRaw ~= "" then
            sLoop = sLoop .. '        ["desc"]        = "' .. string.gsub(string.gsub(string.gsub(card.descriptionRaw, '\"', '\\"'), "\n", "\\n"), "\r\\n", "\\n") .. '",\n'
        end
        if card.levelupDescriptionRaw ~= "" then
            sLoop = sLoop .. '        ["lvldesc"]     = "' .. string.gsub(string.gsub(string.gsub(card.levelupDescriptionRaw, '\"', '\\"'), "\n", "\\n"), "\r\\n", "\\n") .. '",\n'
        end
        sLoop = sLoop .. '        ["flavor"]      = "'     .. string.gsub(string.gsub(string.gsub(card.flavorText, '\"', '\\"'), "\n", "\\n"), "\r\\n", "\\n") .. '",\n'
        sLoop = sLoop .. '        ["artist"]      = "'     .. card.artistName            .. '"\n'
        sLoop = sLoop .. '    },\n'
        
        s = s .. sLoop
    end
    
    s = s .. '}\n'
    s = s .. '-- </' .. 'pre>\n' -- pre needs to be splitted with, because of Lua weirdness
    s = s .. '-- [[Category:Lua]]'
    
    return '<pre>' .. mw.text.nowiki(s) .. '</pre>'
end

function p.getRosters(frame)
    local args; if frame.args == nil then args = lib.arguments(frame) else args = lib.arguments(frame.args) end
    
    local lorData   = mw.loadData('Module:LoRData/data')
    local lang      = mw.language.new( "en" )
    local tablenode = mw.html.create('table')
    local s_set  = tonumber(args["set"]) or nil
    local s_region  = args["region"] or nil
        
    -- START
    local cardtable = {}
    for cardcode in pairs(lorData) do
        table.insert(cardtable, cardcode)
    end
    table.sort(cardtable)
    
    local championtable = {}
    
    for i, cardcode in pairs(cardtable) do
        repeat
            local t = lorData[cardcode]
            
            if t.rarity ~= 'Champion' then
                break
            end
            
            table.insert(championtable, t.name)
            
            break
        until true
    end
    -- END
    return championtable
end

function p.cardlist(frame)
    local args; if frame.args == nil then args = lib.arguments(frame) else args = lib.arguments(frame.args) end
    
    local lorData       = mw.loadData('Module:LoRData/data')
    local lang          = mw.language.new( "en" )
    local s_set         = tonumber(args["set"]) or nil
    local s_region      = args["region"] or nil
    local s_type        = args["type"] or nil
    local s_keyword     = args["keyword"] or nil
    local s_collectible = args['collectible']
    local s_alternate   = not not args['alternate'] or nil
    local s_category    = args["category"] or nil
    local s_mode        = args["mode"] or nil
    local s_removed     = not not args["removed"] or false
    local s_expansion   = args["expansion"] or nil
    local s_artwork     = args["artwork"]
    local s_entire      = not not args["entire"] or nil
    
    local s_cost        = tonumber(string.sub(args["cost"] or "", 1, 1))
    local s_costCompare = string.sub(args["cost"] or "", 2, 2)
    if s_costCompare ~= "" then
	    if s_costCompare ~= '+' and s_costCompare ~= '-' then
	    	return userError("The cost comparison way " .. s_costCompare .. " doesn't exist.", "LuaError")
	    end
	else
		s_costCompare = nil
	end
	
	local s_except       = args["except"] or nil
	local s_regionExcept = args["regionExcept"] or nil
    
    local s = {}
    local s_len = 0
    
    if s_collectible ~= nil then
        if s_collectible == 'any' then
            s_collectible = nil
        else
            local s_collectible_string = tostring(s_collectible)
            if s_collectible_string == "false" then
                s_collectible = false
            elseif s_collectible_string == "true" then
                s_collectible = true
            else
                return userError('Collectible "' .. s_collectible_string .. '" is not in the data.', "LuaError")
            end
        end
    end
    
    s_len = s_len + 1
    s[s_len] = (
    	'<table class="sortable article-table nopadding sticky-header" style="width:100%;text-align:center"><tr>' ..
    	'<th></th>'..
    	'<th>Name</th>'..
    	'<th>Type</th>'..
    	'<th>Subtype</th>'..
    	'<th>Region</th>'..
    	'<th style="width:20px"><span title="Cost">[[File:LoR mana icon.png|40px|link=|]]</span></th>'..
    	'<th style="width:20px"><span title="Power">[[File:LoR Power.png|40px|link=|]]</span></th>'..
    	'<th style="width:20px"><span title="Health">[[File:LoR Health.png|40px|link=|]]</span></th>'..
    	'<th>Rarity</th>'..
    	'</tr>'
    )

    local cardtable = {}
    local cardtable_len = 0
    local sortcardtable = {}

    for cardcode in pairs(lorData) do
    	local sortedCode = cardcode
    	
    	local isAssociated, wordTIndex = string.find(sortedCode, "[^A-Z]T");
    	if isAssociated then
          local associatedText = string.sub(sortedCode, wordTIndex + 1, #sortedCode)
          sortedCode = string.sub(sortedCode, 1, wordTIndex) .. string.format("%03x", associatedText)
        end
        
        cardtable_len = cardtable_len + 1
        cardtable[cardtable_len] = sortedCode
        sortcardtable[sortedCode] = cardcode
    end

    table.sort(cardtable)
    
    local hasResult = false
    local find = string.find
    local format = string.format
    local concat = table.concat
	
    local raritySortOrder = {
		["None"]			= "0",
		["Common"]			= "1",
		["Rare"]			= "2",
		["Epic"]			= "3",
		["Champion"]		= "4",
	}

    for i = 1, cardtable_len do
    	local cardcode = sortcardtable[cardtable[i]]
    	local region   = p.getRegionFromCardcode{cardcode} or ""

        while (s_except ~= cardcode and s_regionExcept ~= region) do
            local t        = lorData[cardcode]
            
            local set      = p.getSetFromCardcode{cardcode}
            
            local art_cardcode = cardcode
            
            if s_removed ~= nil and (s_removed ~= not not t.removed) then
                break
            end
            
            if s_region ~= nil and s_region ~= region then
                break
            end
            
            if s_set ~= nil and s_set ~= set then
                break
            end
            
            if s_mode ~= t.mode then
                break
            end
            
            if s_type ~= nil then
                if s_type == 'Follower' then
                    if t.type ~= 'Unit' or t.supertype == 'Champion' then
                        break
                    end
                elseif s_type == 'Champion' then
                    if t.type ~= 'Unit' or t.supertype ~= 'Champion' then
                        break
                    end
                elseif s_type == 'Champion Spell' then
                    if t.type ~= 'Spell' or t.supertype ~= 'Champion' then
                        break
                    end
                elseif s_type ~= t.type then
                    break
                end
            end
            
            -- Using keywordRefs instead of keywords attribute
            if s_keyword ~= nil then
                local k_found = false
                
                if not t.keywordRefs then
                    break
                end

                for _, keyword in pairs(t.keywordRefs) do
                    if s_keyword == keyword then
                        k_found = true
                        break
                    end
                end

                if k_found == false then
                    break
                end
            end
            
            if s_collectible ~= nil and s_collectible ~= t.collectible then
                break
            end
            
            if s_alternate ~= nil and s_alternate ~= t.alternate then
                break
            elseif s_alternate == true and t.alternate == true then
                art_cardcode = art_cardcode .. '-alt'
            end
            
            if s_category ~= nil then
                local c_found = false
                
                if not t.categoryRefs then
                    break
                end

                for _, category in pairs(t.categoryRefs) do
                	-- Omitted cards can only be listed with category='Omitted'
                    if category == 'Omitted' and s_entire == nil then
                    	c_found = false
                    	break
                    end
                    
                    if s_category == category then
                        c_found = true
                    end
                end

                if c_found == false then
                    break
                end
            elseif (t.categoryRefs) then
            	local c_found = true
            	
            	for _, category in pairs(t.categoryRefs) do
                    -- Omitted cards can only be listed with category='Omitted'
                    if category == 'Omitted' and s_entire == nil then
                    	c_found = false
                    	break
                    end
                end
                
                if c_found == false then
                    break
                end
            end
            
            if s_expansion ~= nil and s_expansion ~= t.expansion then
            	break
            end
            
            if s_artwork ~= nil then
            	local a_found = false

            	for _, artwork in pairs(t.artworks or {}) do
            		if find(artwork, s_artwork, 1, true) then
            			a_found = true
            			break
            		end
            	end

            	if a_found == false then
                	break
                end
            end
            
            if s_cost ~= nil then
            	if s_costCompare ~= nil then
            		if s_costCompare == '+' then
            			if s_cost > t.cost then
	            			break
	            		end
            		else
            			if s_cost < t.cost then
	            			break
	            		end
            		end
            	else
            		if s_cost ~= t.cost then
            			break
            		end
            	end
            end
            
            hasResult = true

            s_len = s_len + 1
            s[s_len] = "<tr>"

            -- Image
            s_len = s_len + 1
            s[s_len] = format('<td data-sort-value="%s"><span class="lor-tooltip" data-param="%s">' ..
            	'[[File:%s.png|75px|link=%s (Legends of Runeterra)]]<br>%s' ..
            	'</span></td>',art_cardcode,art_cardcode,art_cardcode,cardcode,cardcode)

        	-- Cardname
        	s_len = s_len + 1
            s[s_len] = '<td style="text-align:left">' .. '[[' .. cardcode .. ' (Legends of Runeterra)|' .. t.name .. ']]' .. '</td>'

        	-- Type
        	s_len = s_len + 1
            s[s_len] = '<td style="text-align:left">' .. t.type .. '</td>'

        	-- Subtype
        	local subtypetext = {}
            local subtypetext_len = 0

            if (t.subtype ~= nil) then
                for _, subtype in pairs(t.subtype) do
                	subtypetext_len = subtypetext_len + 1
                	subtypetext[subtypetext_len] = subtype
		        end
		    end

        	s_len = s_len + 1
            s[s_len] = '<td style="text-align:left">' .. concat(subtypetext,", ") .. '</td>'

        	-- Region
        	s_len = s_len + 1
            s[s_len] = format(
            	'<td style="text-align:left" data-sort-value="%s">' .. 
        		(region == "" and "" or '[[File:%s LoR Region.png|20px|link=%s (Legends of Runeterra)]]&nbsp;[[%s (Legends of Runeterra)|%s]]') .. 
        		"</td>", region, region, region, region, region
        	)

        	-- Cost
        	s_len = s_len + 1
            s[s_len] = '<td>' .. t.cost .. "</td>"

        	-- Power
        	s_len = s_len + 1
        	if t.type == 'Unit' then
            	s[s_len] = '<td>' .. t.power .. "</td>"
            else
            	s[s_len] = '<td data-sort-value="-1"></td>'
            end

        	-- Health
        	s_len = s_len + 1
        	if t.type == 'Unit' then
            	s[s_len] = '<td>' .. t.health .. "</td>"
            else
            	s[s_len] = '<td data-sort-value="-1"></td>'
            end

        	-- Rarity
        	s_len = s_len + 1
            s[s_len] = (
            	'<td style="text-align:left" data-sort-value"' .. raritySortOrder[t.rarity] .. '">' .. 
        		(t.rarity == "None" and "" or '[[File:LoR ' .. t.rarity .. ' icon.png|20px|link=]]&nbsp;' .. t.rarity) .. "</td>" ..
        		"</tr>"
        	)

            break
        end
    end

    if hasResult == false then
    	s_len = s_len + 1
    	s[s_len] = '<tr><td colspan="9">No corresponding cards found.</td></tr>'
    end
	
	s_len = s_len + 1
    s[s_len] = "</table>"

    return concat(s)
end

function p.findCardsByName(frame)
    local args; if frame.args == nil then args = lib.arguments(frame) else args = lib.arguments(frame.args) end
        
    local lorData     = mw.loadData('Module:LoRData/data')
    local search      = args['search'] or args[1]
    local entire      = args['entire'] or false
    local alt         = args['alt'] or nil
    local artwork     = args['artwork'] or nil
    local firstOnly   = args['firstOnly'] or nil

    local resulttable = {}
    local resulttable_len = 0

    local modetable = {}
    local modetable_len = 0
    
    for cardcode in pairs(lorData) do
        local rCardcode = cardcode

        if alt == 'true' then
            rCardcode = rCardcode .. '-alt'
        end

        if artwork == 'true' then
            rCardcode = rCardcode .. '-full'
        end
        -- Exclusive cards is only taken when there is an "entire" param set
        if entire == false and lorData[cardcode].mode ~= nil then
            if search == lorData[cardcode].name then
            	modetable_len = modetable_len + 1
                modetable[modetable_len] = rCardcode
            end
        elseif search == lorData[cardcode].name then
        	resulttable_len = resulttable_len + 1
            resulttable[resulttable_len] = rCardcode
        end
    end
	
	if firstOnly and resulttable_len ~= 0 then
		resulttable_len = 1
	end

    -- If it is an exclusive card for other modes, it will be taken
    if resulttable_len == 0 and modetable_len ~= 0 then
        resulttable = modetable
        resulttable_len = modetable_len
    end
    
    -- Sorting
    if resulttable_len ~= 0 then
    	local firstCard = lorData[lib.split(resulttable[1], "-", true)[1]]
    	if (firstCard.supertype and firstCard.supertype == 'Champion') then
    		table.sort(resulttable, function(a, b)
    			local aCode = lib.split(a, "-", true)[1]
    			local bCode = lib.split(b, "-", true)[1]
				if lorData[aCode].power ~= lorData[bCode].power then
					return lorData[aCode].power < lorData[bCode].power
				else
					return lorData[aCode].cost < lorData[bCode].cost
				end
    		end)
    	else
			table.sort(resulttable)
		end
	end
    
    if resulttable_len == 0 then
        return ""
    elseif resulttable_len == 1 then
        return resulttable[1]
    else
        return table.concat(resulttable, ",")
    end
end

function p.get(frame)
    local args; if frame.args == nil then args = lib.arguments(frame) else args = lib.arguments(frame.args) end
 
    local get        = require ('Module:LoRData/getter')
    
    args['cardcode'] = args['cardcode'] or args[1]
    args['datatype'] = args['datatype'] or args[2]
    args['output']   = args['output']   or args[3] or nil
 
    local result = get[args['datatype']](args['cardcode'])
    
    if args['output'] ~= nil and type(result) == "table" then
        if args['output'] == "csv" then
            return lib.tbl_concat{result, separator = ","}
        elseif args['output'] == "tip" then
            table.sort(result)
            return frame:preprocess("{" .. "{TipLoR|style=margin-right:1em;|" .. lib.tbl_concat{result, separator = "}} {" .. "{TipLoR|style=margin-right:1em;|"} .. "}}")
        elseif args['output'] == "custom" then 
            return frame:preprocess(lib.tbl_concat{result, prepend = args['prepend'], append = args['append'], separator = args['separator']})
        elseif args['output'] == "template" then
            return frame:preprocess(lib.tbl_concat{result, prepend = "{{" .. args['t_name'] .. "|", append = "}}", separator = args['separator']})
        end
    elseif (args['datatype'] == "desc" or args['datatype'] == "lvldesc" or args['datatype'] == "flavor") and result ~= nil then
        return frame:preprocess(result)
    elseif result == nil then
        return ""
    else
        return result
    end
end

function p.getRegion(frame)
    local args; if frame.args == nil then args = lib.arguments(frame) else args = lib.arguments(frame.args) end
    
    return regions[args['region'] or args[1]]
end

function p.getRegionFromCardcode(frame)
    local args; if frame.args == nil then args = lib.arguments(frame) else args = lib.arguments(frame.args) end
    
    args['cardcode'] = args['cardcode'] or args[1]
    
    return regions[string.sub(args['cardcode'], 3, 4)]
end

function p.getSetFromCardcode(frame)
    local args; if frame.args == nil then args = lib.arguments(frame) else args = lib.arguments(frame.args) end
    
    args['cardcode'] = args['cardcode'] or args[1]
    
    return tonumber(string.sub(args['cardcode'], 0, 2))
end

function p.link(frame)
    local args; if frame.args == nil then args = lib.arguments(frame) else args = lib.arguments(frame.args) end
    
    local cardCode  = args['code']
    local indicator = args['indicator'] or 'true'
    
    if cardCode == nil then
        if args['name'] then
            cardCode = p.findCardsByName{search=args['name'], entire=args['entire'], alt=args['alt'], artwork=args['artwork']}
            
            if cardCode == "" then
            	return userError('Card with name "' .. args['name'] .. '" is not in the data', "LuaError")
            end
        end
    else
        if args['alt'] == 'true' then
            cardCode = cardCode .. '-alt'
        end
        if args['skin'] ~= nil then
        	cardCode = cardCode .. ' ' .. string.gsub(args['skin'], " ", "")
        end
        if args['artwork'] == 'true' or args['skin'] ~= nil then -- skins force you to append -full as well
            cardCode = cardCode .. '-full'
        end
    end
    
    args['name'] = args['name'] or p.get{args['code'], "name"}
    args['text'] = args['text'] or args['name']
    args['link'] = args['link'] or ((args['code'] or args['name']) .. ' (Legends of Runeterra)')
    
    local cardLink = formatnil('[[%s|%s]]', args['link'], args['text'])
    if args['nolink'] then
        cardLink = args['text']
    end
    
    local link = nil
    
    if indicator == 'true' then
    	local firstCardCode = string.sub(cardCode, 1, (string.find(cardCode,',',1,true) or 0) - 1)
    	firstCardCode = string.sub(firstCardCode, 1, (string.find(firstCardCode,'-',1,true) or 0) - 1)
    	firstCardCode = string.sub(firstCardCode, 1, (string.find(firstCardCode,' ',1,true) or 0) - 1)
    	
    	args['cost'] = p.get{firstCardCode, "cost"}
    	args['supertype'] = p.get{firstCardCode, "supertype"}
    	args['type'] = p.get{firstCardCode, "type"}
    	
    	local indicatorImage = 'File:LoR Non-Champion Non-Spell Indicator.png'
    	local indicatorWidth = 20
    	local indicatorLeft = 0
    	local indicatorSpace = '&nbsp;'
    	
    	if args['type'] == 'Unit' and args['supertype'] == 'Champion' then
    		indicatorImage = 'File:LoR Champion Indicator.png'
    		indicatorWidth = 30
    		indicatorLeft = 1.5
    		indicatorSpace = ''
    	elseif args['type'] == 'Spell' then
			local keywords = p.get{firstCardCode, "keywords"}
			local k_found = false

			if keywords then
				for _, keyword in pairs(keywords) do
					if keyword == 'Slow' then
						k_found = true
                        break
                    end
                end
			end

			if k_found then
				indicatorImage = 'File:LoR Spell Slow Indicator.png'
				indicatorWidth = 24
				indicatorLeft = 2
			else
				indicatorImage = 'File:LoR Spell Non-Slow Indicator.png'
				indicatorWidth = 23
				indicatorLeft = 1
			end
    	end
    	
    	local indicatorLink = formatnil('[[%s|%s|link=%s]]', indicatorImage, indicatorWidth .. 'px', args['link'])
    	
    	if args['skin'] ~= nil and args['artwork'] ~= 'true' then -- special data for skin tooltip
    		link = '<span class="skin-icon" data-game="lor" data-champion="'.. args['name'] .. '" data-skin="' .. args['skin'] .. '" data-variant="' .. args['code'] .. '"'
		else
    		link = '<span class="lor-tooltip" data-param="'.. cardCode .. '"'
    	end
    	link = link .. 'style="white-space:nowrap;font-family:Rubik">'
		link = link .. '<span style="position:relative;text-indent:0;">' .. indicatorLink
		link = link .. '<span style="position:absolute;left:' .. indicatorLeft .. 'px;top:50%;user-select:none;line-height:1.5;color:white;font-weight:normal;text-align:center;width:20px;height:20px;font-size:14px;-ms-transform:translateY(-50%);transform:translateY(-50%);">' .. args['cost'] .. '</span>'
		link = link .. '</span>' .. indicatorSpace .. cardLink
		link = link .. '</span>'
	else -- no indicator
		if args['skin'] ~= nil and args['artwork'] ~= 'true' then -- show skin tooltip instead of lor tooltip
			link = mw.html.create('span')
		        :addClass('skin-icon')
		        :attr('data-game', "lor")
		        :attr('data-champion', args['name'])
		        :attr('data-skin', args['skin'])
		        :attr('data-variant', args['code'])
		        :wikitext(cardLink)
		        :done()
		else -- no indicator, regular tooltip
	    	link = mw.html.create('span')
		        :addClass('lor-tooltip')
		        :attr('data-param', cardCode)
		        :wikitext(cardLink)
		        :done()
		end
    end
    
    return link
end

function p.splashartistpage(frame)
    local args; if frame.args == nil then args = lib.arguments(frame) else args = lib.arguments(frame.args) end
    
    local lorData = mw.loadData('Module:LoRData/data')
    local s = ""
    
    args['artist'] = args['artist'] or args[1] or mw.title.getCurrentTitle().text
    
    local cardtable = {}
    for cardcode in pairs(lorData) do
        if p.getSetFromCardcode{cardcode} ~= 0 and lorData[cardcode].artist == args['artist'] then
            table.insert(cardtable, {['name'] = lorData[cardcode].name, ['code'] = cardcode})
        end
    end
    
    table.sort(cardtable, function(a, b) return a['name'] < b['name'] end)
    
    s = ";{{tip|Legends of Runeterra}}\n{{Column|3|\n"
    for _, card in pairs(cardtable) do
        s = s .. "* {{LoR|" .. card['name'] .. "|code=" .. card['code'].. "|artwork=true}}\n"
    end
    s = s .. "}}"
    
    return frame:preprocess(s)
end

function p.fileCategories()
    local wholefilename = mw.title.getCurrentTitle().text
    local fullfilename  = wholefilename:match("(.+)%..+$")
    local filenameParts = lib.split(fullfilename, "-", true)
    local card_skin     = lib.split(table.remove(filenameParts, 1), " ", true)
    local cardcode		= card_skin[1]
    local skin			= card_skin[2]
    local HD            = false
    local alternate     = false
    local artwork       = false
    local display       = false
    local prerelease    = false
    
    for k, v in pairs(filenameParts) do
	  if (v == 'hd') then
	  	HD = true
	  end
	  if (v == 'alt') then
	  	alternate = true
	  end
	  if (v == 'full') then
	  	artwork = true
	  end
	  if (v == 'display') then
	  	display = true
	  end
	  if (v == 'pre') then
	  	prerelease = true
	  end
	end
    
    if skin ~= nil then -- it's a skin, defer to the skins module
    	local skinmodule = require('Module:LoRCosmetics')
    	return skinmodule.fileCategories{
    		cardcode = cardcode, 
    		skin = skin, 
    		modifiers = {
	    		['HD'] = HD, 
	    		['alternate'] = alternate, 
	    		['artwork'] = artwork, 
	    		['display'] = display, 
	    		['prerelease'] = prerelease
    		}
    	}
    end
    
    -- regular card categories begin here
    local lorData       = mw.loadData('Module:LoRData/data')
    
    local s             = ""
    local introduction  = ""
    
    local cardset = p.getSetFromCardcode{cardcode}
    if cardset ~= 0 and cardset ~= 99 then
        s = s .. "[[" .. "Category:LoR Set " .. cardset .. "]]"
    end
    
    local cardregion = p.getRegionFromCardcode{cardcode}
    if cardregion then
        s = s .. "[[" .. "Category:LoR " .. tostring(cardregion) .. "]]"
    end
    
    local cardtype = lorData[cardcode].type
    if cardtype == "Unit" then
        s = s .. "[[" .. "Category:LoR Units]]"
        if lorData[cardcode].supertype then
            s = s .. "[[" .. "Category:LoR Champions]]"
        else
            s = s .. "[[" .. "Category:LoR Followers]]"
        end
    elseif cardtype == "Trap" then
        s = s .. "[[" .. "Category:LoR Traps]]"
    elseif cardtype == "Spell" or cardtype == "Ability" then
        s = s .. "[[" .. "Category:LoR Spells]]"
        if cardtype == "Ability" then
            s = s .. "[[" .. "Category:LoR Abilities]]"
        end
    end
    
    local cardsubtype = lorData[cardcode].subtype
    if cardsubtype then
    	for _, subtype in pairs(cardsubtype) do
			s = s .. "[[" .. "Category:LoR " .. subtype .. "]]"
        end
    end
    
    if artwork then
        s = s .. "[[" .. "Category:LoR Card artwork]]"
    end
    
    if HD then
    	s = s .. "[[" .. "Category:High definition LoR Card artwork]]"
    end
    
    local cardMode = lorData[cardcode].mode
    local cardLocation = ''
    if cardMode then
	    cardLocation = '[[List of cards (Legends of Runeterra)/' .. cardMode .. '|' .. cardMode .. ']] mode' 
	else
		cardLocation = '[[List of cards (Legends of Runeterra)/Set ' .. cardset .. '|Set ' .. cardset .. ']]'
	end
	
	local cardContents = {}
	
	if HD then
    	table.insert(cardContents, 'HD')
    end
    if prerelease then
    	table.insert(cardContents, 'prerelease')
    end
    if alternate then
    	table.insert(cardContents, 'alternate')
    end
    if display then
    	table.insert(cardContents, 'League Displays')
    end
    if artwork then
    	table.insert(cardContents, 'card artwork')
    else
    	table.insert(cardContents, 'card image')
    end
	
	local cardContent = table.concat(cardContents, " ")
    
    introduction = mw.html.create('table')
    	:attr('align', 'center' )
    	:css('margin-top', '1em')
    	:css('width', '90%')
    	:css('border', '2px solid #FFFFFF')
    	:css('font-size', '95%')
    	:css('text-align', 'justify')
    	:css('border-collapse', 'collapse')
    	:css('border-collapse', 'collapse')
    	:tag('tr')
    		:tag('td')
	    		:attr('colspan', '2')
	    		:css('background-color', '#061E36')
	    		:css('text-align', 'center')
	    		:css('font-family', 'BeaufortLoL')
	    		:css('font-size', '120%')
	    		:css('font-weight', '700')
	    		:css('padding', '0.2em 0.5em')
	    		:css('border-bottom', '2px solid #C9AA71;')
	    		:wikitext('This is the ' .. cardContent .. ' for [[' .. cardcode .. ' (Legends of Runeterra)|' .. lorData[cardcode].name .. ']].')
	    		:wikitext('<br />')
	    		:wikitext('You can also view a list of all other cards from ' .. cardLocation .. '.')
	    		:done()
	    	:done()
    	:done()
    
    return tostring(introduction) .. s
end

function p.disambig(frame)
    local args; if frame.args == nil then args = lib.arguments(frame) else args = lib.arguments(frame.args) end
    
    local lorData = mw.loadData('Module:LoRData/data')
    local s       = ""
    
    args["search"] = string.lower(args["search"] or args[1])
    
    local resultable = {}
    for cardcode in pairs(lorData) do
        local t      = lorData[cardcode]
        
        if string.find(string.lower(t.name), args["search"]) and p.getSetFromCardcode{cardcode} ~= 0 then
            table.insert(resultable, {t.name, cardcode})
        end
    end
    table.sort(resultable, function(a, b) return a[1] < b[1] end)
    
    for i, result in pairs(resultable) do
        local t      = lorData[cardcode]
        
        s = s .. "** " .. tostring(p.link{["name"] = result[1], ["code"] = result[2]})
        
        if i < #resultable then
            s = s .. "\n"
        end
    end
    
    return s
end

--// Helper functions //
function formatnil(text, ...)
    if select("#", ...) == 0 then return text end
    for i=1, select("#", ...) do
        if select(i, ...) == nil then return nil end
    end
    return string.format(text, ...)
end

function p.meta()
    local lorData = mw.loadData('Module:LoRData/data')
    local s       = ""
        
    local cardtable = {}
    for cardcode in pairs(lorData) do
        table.insert(cardtable, cardcode)
    end
    table.sort(cardtable)
    
    for i, cardcode in pairs(cardtable) do
        local t      = lorData[cardcode]
        local region = p.getRegionFromCardcode{cardcode}
        local set    = p.getSetFromCardcode{cardcode}
        
        if set ~= 0 then
            -- mw.log("File:" .. cardcode .. ".png")
            -- mw.log(cardcode .. " (Legends of Runeterra)")
            mw.log("[[" .. t.name .. "]]")
            s = s .. "* [[" .. t.name .. "]]\n"
        end
    end
    return s
end

return p
-- </pre>
-- [[Category:Lua]]
Community content is available under CC-BY-SA unless otherwise noted.