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

--Beginning construction of a Module for automatically pulling card data.
--Based on the data in Module:Cards/data - If the information is wrong, update it there.

local p = {}

local CardData = mw.loadData( 'Module:Cards/data' )
local Shared = require( 'Module:Shared' )
local Keywords = require( 'Module:Keywords' )

--The before & after text for a highlighted text section
local highlightPre = "<span style='color:lawngreen;font-weight:bold'>"
local highlightPost = "</span>"
local classOrder = {"Ironclad", "Silent", "Defect", "Watcher", "Neutral", "Curse", "Status"}

function colorToClass(colorName)
    if(colorName == 'Red') then
        return 'Ironclad'
    elseif(colorName == 'Green') then
        return 'Silent'
    elseif(colorName == 'Blue') then
        return 'Defect'
    elseif(colorName == 'Purple') then
            return 'Watcher'
    elseif(colorName == 'Colorless') then
        return 'Neutral'
    end
    
    return colorName
end

function rarityToNumber(rarity)
    if(rarity == nil) then return -1 end
    
    if(rarity == "Basic") then
        return 0
    elseif(rarity == "Common") then
        return 1
    elseif(rarity == "Uncommon") then
        return 2
    elseif(rarity == "Rare") then
        return 3
    elseif(rarity == "Special") then
        return 4
    else
        return -2
    end
end

function p.getCard(cardName)
    --If no name is sent, just return nil
    if(cardName == nil or cardName == "") then return nil end
    
    --Remove + from the end of upgraded cards
    if(string.sub(cardName, -1, -1) == "+") then
        cardName = string.sub(cardName, 1, -2)
    end
    
    --Loop through all cards, return if the key or the name match
    for i, card in pairs(CardData["Cards"]) do
        if card.Name == cardName then return card 
        elseif card.ID == cardName then return card end
    end
    
    --If not found, return nil
    return nil
end

function p.convertText(text, isUpgraded)
    --Converts text for upgraded cards
    --Format is [normal|upgraded]. 
    --Text that appears on upgrade is |text]
    --Text that disappears on upgrade is [text|
    if(text == nil) then return nil end
    if(isUpgraded == nil) then isUpgraded = false end
    if(isUpgraded) then
        text, count = string.gsub(text, "%[([^|]+)|([^%]|]+)%]", highlightPre.."%2"..highlightPost)
        text = string.gsub(text, "%[([^|]+)|", "")
        text = string.gsub(text, "|([^%]]+)]", highlightPre.."%1"..highlightPost)
        --Moving \n outside span closing to fix a slight issue
        text = string.gsub(text, "\n"..highlightPost, highlightPost.."\n")
    else
        text = string.gsub(text, "%[([^|]+)|([^%]|]+)%]", "%1")
        text = string.gsub(text, "%[([^|]+)|", "%1")
        text = string.gsub(text, "|([^%]]+)]", "")
    end
    
    text = Keywords.FillIcons(text)
    text = Keywords.FillKeywords(text)
    return text
end

function hasTrait(theCard, theTrait)
    if(theCard == nil or theTrait == nil) then return false
    elseif(theCard.Traits == nil) then return false 
    else return Shared.contains(theCard.Traits, theTrait) end
end

function getValue(theCard, valName, asString)
    if(asString == nil) then asString = false end
    
    if (valName == nil or valName == "") then
        return "ERROR: No value chosen"
    end
    
    local result = nil
    valName = string.upper(valName)
    if(valName == "NAME") then
        result = theCard.Name
    elseif(valName == "NAMELINK") then
        if(theCard.Link ~= nil) then
            result = '[['..theCard.Link..'|'..theCard.Name..']]'
        else
            result = '[['..theCard.Name..']]'
        end
    elseif(valName == "CANUPGRADE") then
        return theCard.NoUpgrade == nil or not theCard.NoUpgrade
    elseif(valName == "COLOR") then
        result = theCard.Color
    elseif(valName == "COST") then
        result = theCard.Cost
        if(asString) then
            if(theCard.Cost == -1) then
                result = 'X'
            elseif(theCard.Cost == -2) then
                result = 'Unplayable'
            end
        end
    elseif(valName == "COST+" or valName == "COSTPLUS") then
        if theCard.CostPlus ~= nil then
            result = theCard.CostPlus
            if(asString) then
                if(theCard.CostPlus == -1) then result = 'X' 
                elseif(theCard.CostPlus == -2) then result = 'Unplayable' end
                result = highlightPre..result..highlightPost
            end
        else
            if(getValue(theCard, "CanUpgrade")) then        
                result = getValue(theCard, "Cost", asString)
            end
        end
    elseif(valName == "CLASS") then
        if(theCard.Color ~= nil) then
            result = colorToClass(theCard.Color)
        end
    elseif(valName == "IMAGE") then
        result = theCard.Image
    elseif(valName == "IMAGE+" or valName == "IMAGEPLUS") then
        result = theCard.ImagePlus
    elseif(valName == "LINK") then
        if(theCard.Link ~= nil) then
            result =  theCard.Link
        else
            result = theCard.Name
        end
    elseif(valName == "RARITY") then
        result = theCard.Rarity
    elseif(valName == "TEXT") then
        if(theCard.Text ~= nil) then
            result = p.convertText(theCard.Text, false)
        end
    elseif(valName == "TEXT+" or valName == "TEXTPLUS") then
        if(not theCard.NoUpgrade and theCard.Text ~= nil) then
            result = p.convertText(theCard.Text, true)
        end
    elseif(valName == "TYPE") then    
        result = theCard.Type
        if(asString and result ~= nil) then
            result = '[['..result..']]'
        end
    else
        result = "ERROR: No such value found"
    end
    
    if(asString and result == nil) then result = '' end
    return result
end

function p.getValue(frame)
    local CardName = frame.args ~= nil and frame.args[1] or nil
    local ValName = frame.args ~= nil and frame.args[2] or nil
    
    if (CardName == nil or CardName == "") then return "ERROR: No card name chosen" end
    
    local TheCard = p.getCard(CardName)
    
    if(TheCard == nil) then return nil end
    
    return getValue(TheCard, ValName, true)
end

function p._getCardLink(CardName, imgsize, OverrideText)
    if imgsize == nil or imgsize == "" then imgsize = 'x240' end
    if(CardName == nil or CardName == "") then return "ERROR: No card name chosen" end
    
    local TheCard = p.getCard(CardName)
	local name = getValue(TheCard, 'Name')
	local link = getValue(TheCard, 'Link')
	
    if(TheCard == nil) then return nil end
    
    local cardLink = ''
    if(OverrideText == nil or OverrideText == '') then
        cardLink = getValue(TheCard, 'NameLink')
    else
        cardLink = '[['..link..'|'..OverrideText..']]'
    end

	if(link == 'Strike (Ironclad)' or link == 'Defend (Ironclad)' or link == 'Strike (Silent)' or link == 'Defend (Silent)' or link == 'Strike (Defect)' or link == 'Defend (Defect)' or link == 'Strike (Watcher)' or link == 'Defend (Watcher)') then
		name = link
    end

    local result = '<span class="card-tooltip" data-name="'..name..'">'..cardLink
    result = result..'</span>'
    
    return result
end

function p._getCardTooltip(CardName)	
    if imgsize == nil or imgsize == "" then imgsize = 'x240' end
    if(CardName == nil or CardName == "") then return "ERROR: No card name chosen" end

	local cardNameStore = CardName
	
	if(cardNameStore == 'Strike (Ironclad)' or cardNameStore == 'Strike (Silent)' or cardNameStore == 'Strike (Defect)' or cardNameStore == 'Strike (Watcher)') then
		CardName = 'Strike'
	end
	
	if(cardNameStore == 'Defend (Ironclad)' or cardNameStore == 'Defend (Silent)' or cardNameStore == 'Defend (Defect)' or cardNameStore == 'Defend (Watcher)') then
		CardName = 'Defend'
	end
    
    local TheCard = p.getCard(CardName)
    if(TheCard == nil) then return nil end

    local color = getValue(TheCard, 'Color')
	local canUpgrade = getValue(TheCard, "CanUpgrade")
	
	local borderColor = ''
	local bgColor = ''
	
	if(color == "Red") then
		borderColor = 'IndianRed'
		bgColor = '#342d19'
	elseif(color == "Green") then
		borderColor = 'MediumSeaGreen'
		bgColor = 'DarkGreen'
	elseif(color == "Blue") then
		borderColor = 'CornflowerBlue'
		bgColor = 'DarkBlue'
	elseif(color == "Purple") then
		borderColor = 'MediumPurple'
		bgColor = 'DarkViolet'
	elseif(color == "Curse") then
		borderColor = 'DarkSlateBlue'
		bgColor = 'Black'
	else
		borderColor = 'Silver'
		bgColor = 'DimGray'
	end
	 
    local image = getValue(TheCard, 'Image')

	if(cardNameStore == 'Strike (Ironclad)') then
		image = 'Strike_R.png'
	elseif(cardNameStore == 'Strike (Silent)') then
		image = 'Strike_G.png'
	elseif(cardNameStore == 'Strike (Defect)') then
		image = 'Strike_B.png'
	elseif(cardNameStore == 'Strike (Watcher)') then
		image = 'Strike_P.png'
	elseif(cardNameStore == 'Defend (Ironclad)') then
		image = 'Defend_R.png'
	elseif(cardNameStore == 'Defend (Silent)') then
		image = 'Defend_G.png'
	elseif(cardNameStore == 'Defend (Defect)') then
		image = 'Defend_B.png'
	elseif(cardNameStore == 'Defend (Watcher)') then
		image = 'Defend_P.png'
	end
    
    local result = '{| style="border: 2px solid; border-color:#5959c0; background-color: #2C2A4E; border-radius: 10px; padding: 10px 10px 10px 10px;"'
	result = result..'\n|[[File:'..image..'|center|240px]]'	
	if (canUpgrade) then
		local plusImage = string.gsub(image, ".png", "Plus.png")
		result = result..'\n|[[File:'..plusImage..'|center|240px]]'
	end
    result = result..'\n|-'
	result = result..'|}'
    
    return result
end

function p.getCardLink(frame)
    local CardName = frame.args ~= nil and frame.args[1] or frame
    local imgsize = frame.args ~= nil and frame.args.imgsize or nil
    local OverrideText = frame.args ~= nil and frame.args.text or nil
    
    return p._getCardLink(CardName, imgsize, OverrideText)
end

function p.getCardTooltip(frame)
    local CardName = frame.args[1] or frame.args["card"] or nil
 
    return p._getCardTooltip(CardName)
end

function p.getCardExistsError(frame)
    local CardName = frame.args ~= nil and frame.args[1] or frame
    
    local TheCard = p.getCard(CardName)
    
    if(TheCard == nil) then
        return "ERROR: No card named "..CardName.." found"
    else
        return nil
    end
end

function p.getCardCategories(frame)
    local CardName = frame.args ~= nil and frame.args[1] or frame
    local result = ""
    
    local theCard = p.getCard(CardName)
    
    if(theCard ~= nil) then
        local color = getValue(theCard, "Color")
        if(color ~= nil) then
            result = result..'[[Category:'..colorToClass(color)..' Cards]]'
        end
        
        local cardType = getValue(theCard, 'Type')
        if(cardType ~= nil) then
            result = result..'[[Category:'..cardType..' Cards]]'
        end
        
        local rarity = getValue(theCard, "Rarity")
        if(rarity ~= nil) then
            result = result..'[[Category:'..rarity..' Cards]]'
        end
        
        if(theCard.Traits ~= nil) then
            for i, traits in Shared.skpairs(theCard.Traits) do
                if(traits == "AddDexterity") then
                    result = result..'[[Category:Dexterity]]'
                elseif(traits == "Ethereal") then
                    result = result..'[[Category:Ethereal Cards]][[Category:Exhaust]]'
                elseif(traits == "SelfExhaust" or traits == "ExhaustOther" or traits == "Exhaust") then
                    result = result..'[[Category:Exhaust]]'
                elseif(traits == "Innate") then
                    result = result..'[[Category:Innate Cards]]'
                elseif(traits == "AddPoison" or traits == "UsePoison") then
                    result = result..'[[Category:Poison]]'
                elseif(traits == "Shiv") then
                    result = result..'[[Category:Shiv]]'
                elseif(traits == "AddStrength" or traits == "RemoveStrength" or traits == "UseStrength") then
                    result = result..'[[Category:Strength]]'
                elseif(traits == "Unplayable") then
                    result = result..'[[Category:Unplayable Cards]]'
                end
            end
        end
    end
    
    return result
end

--Gets a list of all cards in the database
--Sorted by color and then alphabetically
function p.getFullCardList(frame)
    local result = ''
    local data = {}
    
    for i, card in pairs(CardData["Cards"]) do
        if(card.Color ~= nil) then
            if(data[card.Color] == nil) then data[card.Color] = {} end
            table.insert(data[card.Color], getValue(card, 'NameLink'))
        end
    end

    for color, nameList in Shared.skpairs(data) do
        if(result ~= '') then result = result..'\n' end
        result = result..'* '..Shared.tableCount(nameList)..' '..colorToClass(color)..' Cards:'
        for i, name in pairs(nameList) do
            result = result..'\n** '..name
        end
    end

    return result
end

function p.getNavboxCardList(frame)
    local Color = frame.args ~= nil and frame.args[1]
    local Type = frame.args ~= nil and frame.args[2]
    local Rarity = frame.args ~= nil and frame.args[3]
    
    if(Color == nil or Type == nil) then return nil end
    
    local result = ''
    local count = 0
    local data = {}
	local cardLink = ''
	local cardName = ''
    for i, card in pairs(CardData["Cards"]) do
        if(card.Color == Color) then
          if(card.Rarity == Rarity) then
                if (card.Rarity == 'Basic') then
					cardName = getValue(card, 'Name')
					cardLink = getValue(card, 'NameLink')
					cardLink = '<span class="card-tooltip" data-name="'..cardName..'">'..cardLink..'</span>'
               	 table.insert(data, cardLink)
                elseif(card.Type == Type) then
					cardName = getValue(card, 'Name')
					cardLink = getValue(card, 'NameLink')
					cardLink = '<span class="card-tooltip" data-name="'..cardName..'">'..cardLink..'</span>'
                table.insert(data, cardLink)
                end
            end
        end
    end

    table.sort(data)
    for i, key in pairs(data) do
        if(i > 1) then result = result..' • ' end
        result = result..key
    end
    
    return result
end

function p.getNavboxCardListByRarity(frame)
    local Color = frame.args ~= nil and frame.args[1]
    local Rarity = frame.args ~= nil and frame.args[2]
    
    if(Color == nil or Rarity == nil) then return nil end
    
    local result = ''
    local count = 0
    local data = {}
    for i, card in pairs(CardData["Cards"]) do
        if(card.Color == Color) then
            if(card.Rarity == Rarity) then
                table.insert(data, getValue(card, 'NameLink'))
            end
        end
    end

    table.sort(data)
    for i, key in pairs(data) do
        if(i > 1) then result = result..' • ' end
        result = result..key
    end
    
    return result
end

function p.getCardList(frame)
    local Color = frame.args ~= nil and frame.args[1]
    local Type = frame.args ~= nil and frame.args[2]
    local ListText = frame.args ~= nil and frame.args[3]
    
    if(Color == nil or Type == nil) then return nil end
    if(ListText == nil) then ListText = "List of "..colorToClass(Color).." "..Type.." Cards:" end
    
    local result = '* '..ListText
    local count = 0
    local data = {}
    for i, card in pairs(CardData["Cards"]) do
        if(card.Color == Color) then
            if(card.Type == Type) then
                table.insert(data, getValue(card, 'NameLink'))
            end
        end
    end

    table.sort(data)
    for i, key in pairs(data) do
        result = result..'\n** '..key
    end
    
    return result
end

function p.getTraitList(frame)
    local Trait = frame.args ~= nil and frame.args[1] or frame
    if(Trait == nil) then return "ERROR: Must choose a trait" end
    
    local result = ''
    local data = {}
    for i, card in pairs(CardData["Cards"]) do
        if(hasTrait(card, Trait)) then
            local color = getValue(card, "Color")
            local cardType = getValue(card, "Type")
            local listName = nil
            if(cardType == "Status" or cardType == "Curse") then 
                listName = cardType
            else
                listName = colorToClass(color)
            end
            
            if(listName ~= nil) then
                if(data[listName] == nil) then data[listName] = {} end
                table.insert(data[listName], getValue(card, "Name"))
            end
        end
    end

    for i, class in pairs(classOrder) do
        local nameList = data[class]
        if(nameList ~= nil) then
            table.sort(nameList)
            if(result ~= '') then result = result..'\n' end
            result = result..'* '..Shared.tableCount(nameList)..' '..class..' Cards:'
            for i, name in pairs(nameList) do
                result = result..'\n** '..p._getCardLink(name)
            end
        end
    end

    return result
end
    

function getCardTable(CardList, showCostCol)
    if(showCostCol == nil) then showCostCol = true end
    
    table.sort(CardList, function(x, y) return x.Name < y.Name end)
    local result = ''
    result = '{| class="article-table sortable"'
    result = result..'\n! data-sort-type="text" | Name'
    result = result..'\n! class="unsortable" | Picture'
    result = result..'\n! data-sort-type="number" | Rarity'
    result = result..'\n! data-sort-type="text" | Type'
    if(showCostCol) then
        result = result..'\n! data-sort-type="number" | Energy'
    end
    result = result..'\n! class="unsortable" | Description\n<hr>\nUpgraded Description'
    
    for i, card in pairs(CardList) do
        result = result..'\n|-'
        result = result..'\n|'..getValue(card, "NameLink", true)
        result = result..'\n|'
        local img = getValue(card, "Image")
        if(img ~= nil) then
            result = result..'[[File:'..img..'|x229px|link='..getValue(card, "Link")..']]'
        end
        result = result..'\n|'
        local rarity = getValue(card, "Rarity")
        if(rarity ~= nil) then
            result = result..' data-sort-value="'..rarityToNumber(rarity)..'" | '..rarity
        else
            result = result..' data-sort-value="-2" | Unknown'
        end
        result = result..'\n| '..getValue(card, "Type")
        local canUpgrade = getValue(card, "CanUpgrade")
        if(showCostCol) then
            result = result..'\n| '
            local cost1 = getValue(card, "Cost")
            local cost2 = getValue(card, "CostPlus")
            if(cost1 ~= nil) then
                result = result..' data-sort-value="'..cost1..'" | '..getValue(card, "Cost", true)
                if(canUpgrade and cost2 ~= cost1) then
                    result = result..' ('..cost2..')'
                end
            else
                result = result..' data-sort-value="-3" | Unknown'
            end
        end
        local text1 = getValue(card, "Text")
        
        local text2 = getValue(card, "TextPlus")
        result = result..'\n| '..string.gsub(text1, '\n', '\n\n')
        if(canUpgrade and text2 ~= text1) then
            result = result..'\n<hr>\n'..string.gsub(text2, '\n', '\n\n')
        end
    end

    result = result..'\n|}'
    
    return result
end

function p.getCardTable(frame)
    local Color = frame.args ~= nil and frame.args[1] or frame
    if(Color == nil) then return nil end
    local showCostCol = (Color ~= "Status" and Color ~= "Curse")
        
    local cards = {}
    for i, card in pairs(CardData["Cards"]) do
        if(Color == "Neutral" or Color == "Status" or Color == "Curse") then
            local color = getValue(card, "Color")
            local cardType = getValue(card, "Type")
            if(cardType == "Status") then
                if(Color == "Status") then table.insert(cards, card) end
            elseif(cardType == "Curse") then
                if(Color == "Curse") then table.insert(cards, card) end
            elseif(color == "Colorless") then
                if(Color == "Neutral") then table.insert(cards, card) end
            end
        elseif(getValue(card, "Color") == Color) then
            table.insert(cards, card)
        end
    end

    return getCardTable(cards, showCostCol)
end

return p
Community content is available under CC-BY-SA unless otherwise noted.