League of Legends Wiki

Want to contribute to this wiki?
Sign up for an account, and get started!
You can even turn off ads in your preferences.

Come join the LoL Wiki community Discord server!

READ MORE

League of Legends Wiki
Advertisement

This lua module is used to access a LoL champion's name, role, ratings, positions, stats, release date and patch, last changed patch, store prices, and the order abilities displayed on ability pages.

The data is stored at Module:ChampionData/data. If you wish to edit this data, please follow the existing format, documented at the top of that page.


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

local statsdata = {
    ["hp_base"]      = "hp",
    ["hp_lvl"]       = "hpperlevel",
    ["mp_base"]      = "mp",
    ["mp_lvl"]       = "mpperlevel",
    ["ms"]           = "movespeed",
    ["arm_base"]     = "armor",
    ["arm_lvl"]      = "armorperlevel",
    ["mr_base"]      = "spellblock",
    ["mr_lvl"]       = "spellblockperlevel",
    ["range"]        = "attackrange",
    ["hp5_base"]     = "hpregen",
    ["hp5_lvl"]      = "hpregenperlevel",
    ["mp5_base"]     = "mpregen",
    ["mp5_lvl"]      = "mpregenperlevel",
    ["dam_base"]     = "attackdamage",
    ["dam_lvl"]      = "attackdamageperlevel",
    ["as_lvl"]       = "attackspeedperlevel",
    ["as_lvl1"]      = "attackspeed"
}

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:ChampionData/getter')
    local champname = args['champname'] or args[1]
    local datatype  = args['datatype']  or args[2]
    local output    = args['output']    or args[3] or nil
    
    champname = lib.validateName(champname) --corrects for acceptable misspellings (e.g. Nunu -> Nunu & Willump)
    
    local result = get[datatype](champname)
    
    if output ~= nil and type(result) == "table" then
        if output == "csv" then
            return lib.tbl_concat{result}
        elseif output == "custom" then 
            return frame:preprocess(lib.tbl_concat{result, prepend = args['prepend'], append = args['append'], separator = args['separator'], index = args["index"]})
        elseif output == "template" then 
            return frame:preprocess(lib.tbl_concat{result, prepend = "{{" .. args['t_name'] .. "|", append = "}}", separator = args['separator']})
        end
    elseif result == nil then
        return ""
    else
        return result
    end
end

function p.getRoster()
    local lolData  = mw.loadData('Module:ChampionData/data')
    local tftData  = require('Module:TFTUnitData')
    local lorData  = require('Module:Sandbox/Onfealive/LoRData')
    local lolTable = {}
    local lorTable = {}
    local s        = ""
    
    for champname in pairs(lolData) do
        if  
            lolData[champname]["date"] == ("Upcoming" or "N/A" or "Cancelled" or "")
            or 
            champname == "Mega Gnar" or champname == "Rhaast" or champname == "Shadow Assassin" or champname == "Kled & Skaarl"
            then
            --ignore champion
        else
            table.insert(lolTable, champname)
        end
            
    end
    table.sort(lolTable)
    
    lorTable = lorData.getRosters{}
    
    for _, champion in pairs(lolTable) do
        
        --custom searches
        local search = champion
        
        if lolData[champion]["title"]    then search = search .. "," .. lolData[champion]["title"]    end
        if lolData[champion]["fullname"] then search = search .. "," .. lolData[champion]["fullname"] end
        if lolData[champion]["nickname"] then search = search .. "," .. lolData[champion]["nickname"] end
        
        --game titles
        local games = "LOL" 
        
        if tftData.checkRoster{champion} then 
            if games ~= "" then games = games .. "," end
            games = games .. "TFT," .. tftData.getTooltipSets{champion}
        end
        
        for i, champname in pairs(lorTable) do
            if champname == champion then
                if games ~= "" then games = games .. "," end
                games = games .. "LOR"
                break;
            end
        end
        
        --champion roles
        local role = p.mainrole{champion} .. "," .. p.get{champion, "role", "csv"}
        local rangetype = lolData[champion]["rangetype"]
        s = s .. '<li><span class="grid-icon champion-icon" data-champion="' .. champion .. '" data-search="' .. search .. '" data-game="' .. games .. '" data-role="' .. role .. '" data-type="' .. rangetype .. '">[[File:' .. FN.championsquare{champion} .. '|48px|alt=' .. champion .. '|link=' .. champion .. ']]</span></li>'
    end
    
    return s
end

function p.statTable(frame)
    local args; if frame.args == nil then args = lib.arguments(frame) else args = lib.arguments(frame.args) end
    
    local _stat     = args[1]
    local lolData   = mw.loadData('Module:ChampionData/data')
    local lolTable  = {}
    local tablenode = mw.html.create('table')
    
    local convert   = {
        ["Health"]          = "hp",
        ["Health regen"]    = "hp5",
        ["Mana"]            = "mp",
        ["Mana regen"]      = "mp5",
        ["Armor"]           = "arm",
        ["Magic resist"]    = "mr",
        ["Attack damage"]   = "dam",
        ["Move speed"]      = "ms",
        ["Attack speed"]    = "as"
    }
    if _stat == "Base" then
        tablenode
            :addClass('sortable wikitable sticky-header')
            :css('width', '100%')
            :css('text-align', 'right')
            :css('white-space', 'nowrap')
            :newline()
    elseif _stat == "Base 18" then
        tablenode
            :addClass('sortable wikitable sticky-header')
            :css('width', '100%')
            :css('text-align', 'center')
            :css('white-space', 'nowrap')
            :tag('caption')
                :wikitext('Champion statistics at level 18 (without skill bonuses)')
            :done()
            :newline()
    elseif _stat == "Manaless" then
        tablenode
            :addClass('sortable wikitable')
            :css('width', '90%')
            :css('text-align', 'center')
            :css('white-space', 'nowrap')
            :css('margin-left', '5%')
            :newline()
    elseif _stat == "Ratings" then
        tablenode
            :addClass('sortable article-table sticky-header')
            :css('width', '100%')
            :css('text-align', 'center')
            :css('white-space', 'nowrap')
            :newline()
    else
    tablenode
        :addClass('sortable article-table sticky-header')
        :css('width', '100%')
        :css('text-align', 'center')
        :newline()
    end
    if _stat == "Attack speed" then
        tablenode
            :tag('tr')
                :tag('th')
                    :wikitext('Champion')
                    :css('width', '180px')
                :done()
                :tag('th')
                    :wikitext('Base')
                :done()
                :tag('th')
                    :wikitext('AS Ratio')
                :done()
                :tag('th')
                    :wikitext('Bonus AS at level 1')
                :done()
                :tag('th')
                    :wikitext('Bonus growth coefficient')
                :done()
                :tag('th')
                    :wikitext('Bonus at level 18')
                :done()
                :tag('th')
                    :wikitext('Value at level 18')
                :done()
                :tag('th')
                    :wikitext('Additional AS needed to cap at level 18')
                :done()
            :done()
            :newline()
    elseif _stat == "Basic attack" then
        tablenode
            :tag('tr')
                :tag('th')
                    :wikitext('Champion')
                    :css('width', '180px')
                :done()
                :tag('th')
                    :wikitext('Attack range')
                :done()
                :tag('th')
                    :wikitext('Range type')
                :done()
                :tag('th')
                    :wikitext('Missile speed')
                :done()
                :tag('th')
                    :wikitext('Windup')
                :done()
                :tag('th')
                    :wikitext('Windup modifier')
                :done()
            :done()
            :newline()
    elseif _stat == "Hitbox" then
        tablenode
            :tag('tr')
                :tag('th')
                    :wikitext('Champion')
                    :css('width', '180px')
                :done()
                :tag('th')
                    :wikitext('Gameplay radius')
                :done()
                :tag('th')
                    :wikitext('Selection radius')
                :done()
                :tag('th')
                    :wikitext('Pathing radius')
                :done()
                :tag('th')
                    :wikitext('Acquisition radius')
                :done()
            :done()
            :newline()
    elseif _stat == "Base" then
        tablenode
            :tag('tr')
                :tag('th')
                    :wikitext('[[Champion]]s')
                :done()
                :tag('th')
                    :wikitext('[[Health|HP]]')
                    :css('width', '4em')
                :done()
                :tag('th')
                    :wikitext('HP+')
                    :css('width', '4em')
                :done()
                :tag('th')
                    :wikitext('[[Health regeneration|HP5]]')
                    :css('width', '4em')
                :done()
                :tag('th')
                    :wikitext('HP5+')
                    :css('width', '4em')
                :done()
                :tag('th')
                    :wikitext('[[Mana|MP]]')
                    :css('width', '4em')
                :done()
                :tag('th')
                    :wikitext('MP+')
                    :css('width', '4em')
                :done()
                :tag('th')
                    :wikitext('[[Mana regeneration|MP5]]')
                    :css('width', '4em')
                :done()
                :tag('th')
                    :wikitext('MP5+')
                    :css('width', '4em')
                :done()
                :tag('th')
                    :wikitext('[[Attack damage|AD]]')
                    :css('width', '4em')
                :done()
                :tag('th')
                    :wikitext('AD+')
                    :css('width', '4em')
                :done()
                :tag('th')
                    :wikitext('[[Attack speed|AS]]')
                    :css('width', '4em')
                :done()
                :tag('th')
                    :wikitext('AS+')
                    :css('width', '4em')
                :done()
                :tag('th')
                    :wikitext('[[Armor|AR]]')
                    :css('width', '4em')
                :done()
                :tag('th')
                    :wikitext('AR+')
                    :css('width', '4em')
                :done()
                :tag('th')
                    :wikitext('[[Magic resistance|MR]]')
                    :css('width', '4em')
                :done()
                :tag('th')
                    :wikitext('MR+')
                    :css('width', '4em')
                :done()
                :tag('th')
                    :wikitext('[[Movement speed|MS]]')
                    :css('width', '4em')
                :done()
                :tag('th')
                    :wikitext('[[Range]]')
                    :css('width', '4em')
                :done()
            :done()
            :newline()
    elseif _stat == "Base 18" then
        tablenode
            :tag('tr')
                :tag('th')
                    :wikitext('Champion')
                    :css('color', 'black')
                    :css('background-color', 'white')
                :done()
                :tag('th')
                    :attr('data-sort-type', 'number')
                    :wikitext('HP')
                    :css('color', 'black')
                    :css('background-color', 'lightgreen')
                :done()
                :tag('th')
                    :attr('data-sort-type', 'number')
                    :wikitext('HP5')
                    :css('color', 'black')
                    :css('background-color', 'lightgreen')
                :done()
                :tag('th')
                    :attr('data-sort-type', 'number')
                    :wikitext('MP')
                    :css('color', 'black')
                    :css('background-color', 'lightblue')
                :done()
                :tag('th')
                    :attr('data-sort-type', 'number')
                    :wikitext('MP5')
                    :css('color', 'black')
                    :css('background-color', 'lightblue')
                :done()
                :tag('th')
                    :attr('data-sort-type', 'number')
                    :wikitext('AD')
                    :css('color', 'black')
                    :css('background-color', '#ffaaaa')
                :done()
                :tag('th')
                    :attr('data-sort-type', 'number')
                    :wikitext('AS')
                    :css('color', 'black')
                    :css('background-color', '#ffaaaa')
                :done()
                :tag('th')
                    :attr('data-sort-type', 'number')
                    :wikitext('AR')
                    :css('color', 'black')
                    :css('background-color', '#ffffaa')
                :done()
                :tag('th')
                    :attr('data-sort-type', 'number')
                    :wikitext('MR')
                    :css('color', 'black')
                    :css('background-color', '#ffffaa')
                :done()
                :tag('th')
                    :attr('data-sort-type', 'number')
                    :wikitext('Range')
                :done()
                :tag('th')
                    :attr('data-sort-type', 'number')
                    :wikitext('MS')
                :done()
            :done()
            :newline()
    elseif _stat == "Manaless" then
        tablenode
            :tag('tr')
                :tag('th')
                    :wikitext('Champion')
                :done()
                :tag('th')
                    :wikitext('Secondary Resource')
                :done()
            :done()
            :newline()
    elseif _stat == "Ratings" then
        tablenode
            :tag('tr')
                :tag('th')
                    :wikitext('Champion')
                :done()
                :tag('th')
                    :wikitext('Primary')
                :done()
                :tag('th')
                    :wikitext('Secondary')
                :done()
                :tag('th')
                    :wikitext('[[File:Damage rating.png|15px|link=]]')
                :done()
                :tag('th')
                    :wikitext('[[File:Toughness rating.png|15px|link=]]')
                :done()
                :tag('th')
                    :wikitext('[[File:Control rating.png|15px|link=]]')
                :done()
                :tag('th')
                    :wikitext('[[File:Mobility rating.png|15px|link=]]')
                :done()
                :tag('th')
                    :wikitext('[[File:Utility rating.png|15px|link=]]')
                :done()
                :tag('th')
                    :wikitext('Style')
                :done()
                :tag('th')
                    :wikitext(frame:expandTemplate{title='sti', args={'Adaptive Damage',icononly='true'}})
                :done()
                :tag('th')
                    :wikitext('Difficulty')
                :done()
            :done()
            :newline()
    else
        tablenode
            :tag('tr')
                :tag('th')
                    :wikitext('Champion')
                    :css('width', '180px')
                :done()
                :tag('th')
                    :wikitext('Base')
                :done()
                :tag('th')
                    :wikitext('Growth coefficient')
                :done()
                :tag('th')
                    :wikitext('Value at 18')
                :done()
            :done()
            :newline()
    end
    
    for champname in pairs(lolData) do
        if  
            lolData[champname]["date"] == ("Upcoming" or "N/A" or "Cancelled" or "")
            or 
            champname == ("Rhaast" or "Shadow Assassin")
            then
            --ignore champion
        else
            table.insert(lolTable, champname)
        end
    end
    table.sort(lolTable)
    
    for _, champion in pairs(lolTable) do
        local t         = lolData[champion]["stats"]
        local tablerow  = mw.html.create('tr')
        
        if _stat == "Attack speed" then
            local as_base   = t["as_base"]
            local as_ratio  = t["as_ratio"]
            local bonus_lvl = t["as_lvl"]
            local bonus_18  = 0 + bonus_lvl * (18 - 1) * (0.7025 + 0.0175 * (18 - 1))
            local variation = string.format("%.f", as_base / as_ratio * 100 - 100, 3)
                
            if variation == "-0" then
                variation = "0"
            end
            
            local disp_name = champion
            if champion == "Mega Gnar" then disp_name = "Gnar (Mega)" end
            
            if champion == "Jhin" then
                tablerow
                    :tag('td')
                        :attr('data-sort-value', disp_name)
                        :css('text-align', 'left')
                        :wikitext("[[File:" .. FN.championcircle{champion} .. "|20px|alt=" .. champion .. "|link=" .. champion .. "]] [[" .. champion .. "]] <span title='Jhin&#39;s growth increases his base attack speed. He does not gain &#39;bonus attack speed&#39;.'><sup>note</sup></span>")
                    :done()
                    :tag('td')
                        :wikitext(string.format("%0.3f", as_base, 3))
                    :done()
                    :tag('td')
                        :wikitext(string.format("%0.3f", as_ratio, 3))
                    :done()
                    :tag('td')
                        :wikitext("N/A")
                    :done()
                    :tag('td')
                        :wikitext(bonus_lvl .. "%")
                    :done()
                    :tag('td')
                        :wikitext(bonus_18 .. "%")
                    :done()
                    :tag('td')
                        :wikitext(string.format("%0.3f", as_base + as_base * (bonus_18 / 100), 3))
                    :done()
                    :tag('td')
                        :attr('data-sort-value', "9999%")
                        :wikitext(string.format("%0.0f", (2.5 / as_ratio - 1) * 100 - bonus_18, 3) .. "%")
                    :done()
                :done()
            else
                tablerow
                    :tag('td')
                        :attr('data-sort-value', disp_name)
                        :css('text-align', 'left')
                        :wikitext('[[File:' .. FN.championcircle{champion} .. '|20px|alt=' .. champion .. '|link=' .. champion .. ']] [[' .. champion .. ']]')
                    :done()
                    :tag('td')
                        :wikitext(string.format("%0.3f", as_base, 3))
                    :done()
                    :tag('td')
                        :wikitext(string.format("%0.3f", as_ratio, 3))
                    :done()
                    :tag('td')
                        :wikitext(variation .. "%")
                    :done()
                    :tag('td')
                        :wikitext(bonus_lvl .. "%")
                    :done()
                    :tag('td')
                        :wikitext(bonus_18 .. "%")
                    :done()
                    :tag('td')
                        :wikitext(string.format("%0.3f", as_base + as_ratio * (bonus_18 / 100), 3))
                    :done()
                    :tag('td')
                        :wikitext(string.format("%0.0f", (2.5 / as_ratio - 1) * 100 - bonus_18 - (as_base / as_ratio - 1) * 100, 3) .. "%")
                    :done()
                :done()
            end
        elseif _stat == "Basic attack" then
            local windup
            if (t["attack_cast_time"] and t["attack_total_time"]) then
                windup = t["attack_cast_time"] / t["attack_total_time"]
            else
                windup = 0.3 + (t["attack_delay_offset"] or 0)
            end
            
            local windup_mod
            if t["windup_modifier"] == nil then
                windup_mod = "N/A"
            else
                windup_mod = math.floor(t["windup_modifier"] * 1000 + 0.5) / 1000
            end
            
            tablerow
                :tag('td')
                    :attr('data-sort-value', champion)
                    :css('text-align', 'left')
                    :wikitext('[[File:' .. FN.championcircle{champion} .. '|20px|alt=' .. champion .. '|link=' .. champion .. ']] [[' .. champion .. ']]')
                :done()
                :tag('td')
                    :wikitext(t["range"])
                :done()
                :tag('td')
                    :wikitext(lolData[champion]["rangetype"])
                :done()
                :tag('td')
                    :wikitext(t["missile_speed"] or "N/A")
                :done()
                :tag('td')
                    :wikitext((math.floor(math.floor(windup*100*1000+0.5)/1000*100+0.5)/100) .. "%")
                :done()
                :tag('td')
                    :wikitext(windup_mod)
                :done()
            :done()
        elseif _stat == "Hitbox" then
            tablerow
                :tag('td')
                    :attr('data-sort-value', champion)
                    :css('text-align', 'left')
                    :wikitext('[[File:' .. FN.championcircle{champion} .. '|20px|alt=' .. champion .. '|link=' .. champion .. ']] [[' .. champion .. ']]')
                :done()
                :tag('td')
                    :wikitext(math.floor(t["gameplay_radius"] or 65 + 0.5))
                :done()
                :tag('td')
                    :wikitext(math.floor(t["selection_radius"] or 0 + 0.5))
                :done()
                :tag('td')
                    :wikitext(math.floor(t["pathing_radius"] or 0 + 0.5))
                :done()
                :tag('td')
                    :wikitext(math.floor(t["acquisition_radius"] or 750 + 0.5))
                :done()
            :done()
        elseif _stat == "Base" then
            local FD        = require('Module:Fd')
            
            local hp_base = FD.get{["args"]={tostring(t["hp_base"])}}
            local hp_lvl  = FD.get{["args"]={tostring(t["hp_lvl"])}}
            local hp5_base = FD.get{["args"]={tostring(t["hp5_base"])}}
            local hp5_lvl  = FD.get{["args"]={tostring(t["hp5_lvl"])}}
            local mp_base = FD.get{["args"]={tostring(t["mp_base"])}}
            local mp_lvl  = FD.get{["args"]={tostring(t["mp_lvl"])}}
            local mp5_base = FD.get{["args"]={tostring(t["mp5_base"])}}
            local mp5_lvl  = FD.get{["args"]={tostring(t["mp5_lvl"])}}
            local dam_base = FD.get{["args"]={tostring(t["dam_base"])}}
            local dam_lvl  = FD.get{["args"]={tostring(t["dam_lvl"])}}
            local as_base = FD.get{["args"]={tostring(t["as_base"])}}
            local as_lvl  = FD.get{["args"]={tostring(t["as_lvl"])}}
            local arm_base = FD.get{["args"]={tostring(t["arm_base"])}}
            local arm_lvl  = FD.get{["args"]={tostring(t["arm_lvl"])}}
            local mr_base = FD.get{["args"]={tostring(t["mr_base"])}}
            local mr_lvl  = FD.get{["args"]={tostring(t["mr_lvl"])}}
            local ms  = FD.get{["args"]={tostring(t["ms"])}}
            local range = FD.get{["args"]={tostring(t["range"])}}
            
            tablerow
                :tag('td')
                    :attr('data-sort-value', champion)
                    :css('text-align', 'left')
                    :wikitext('[[File:' .. FN.championcircle{champion} .. '|20px|alt=' .. champion .. '|link=' .. champion .. ']] [[' .. champion .. ']]')
                :done()
                :tag('td')
                    :wikitext(hp_base)
                :done()
                :tag('td')
                    :wikitext('+' .. hp_lvl)
                :done()
                :tag('td')
                    :wikitext(hp5_base)
                :done()
                :tag('td')
                    :wikitext('+' .. hp5_lvl)
                :done()
                :tag('td')
                    :wikitext(mp_base)
                :done()
                :tag('td')
                    :wikitext('+' .. mp_lvl)
                :done()
                :tag('td')
                    :wikitext(mp5_base)
                :done()
                :tag('td')
                    :wikitext('+' .. mp5_lvl)
                :done()
                :tag('td')
                    :wikitext(dam_base)
                :done()
                :tag('td')
                    :wikitext('+' .. dam_lvl)
                :done()
                :tag('td')
                    :wikitext(as_base)
                :done()
                :tag('td')
                    :wikitext('+' .. as_lvl .. '%')
                :done()
                :tag('td')
                    :wikitext(arm_base)
                :done()
                :tag('td')
                    :wikitext('+' .. arm_lvl)
                :done()
                :tag('td')
                    :wikitext(mr_base)
                :done()
                :tag('td')
                    :wikitext('+' .. mr_lvl)
                :done()
                :tag('td')
                    :wikitext(ms)
                :done()
                :tag('td')
                    :wikitext(range)
                :done()
            :done()
        elseif _stat == "Base 18" then
            local FD        = require('Module:Fd')
            
            local hp_base = tonumber(t["hp_base"])
            local hp_lvl  = tonumber(t["hp_lvl"])
            local hp_18 = FD.get{["args"]={tostring(hp_base + hp_lvl * (18 - 1) * (0.7025 + 0.0175 * (18 - 1)))}}
            local hp5_base = tonumber(t["hp5_base"])
            local hp5_lvl  = tonumber(t["hp5_lvl"])
			local hp5_18 = FD.get{["args"]={tostring(hp5_base + hp5_lvl * (18 - 1) * (0.7025 + 0.0175 * (18 - 1)))}}
            local mp_base = tonumber(t["mp_base"])
            local mp_lvl  = tonumber(t["mp_lvl"])
			local mp_18 = FD.get{["args"]={tostring(mp_base + mp_lvl * (18 - 1) * (0.7025 + 0.0175 * (18 - 1)))}}
            local mp5_base = tonumber(t["mp5_base"])
            local mp5_lvl  = tonumber(t["mp5_lvl"])
			local mp5_18 = FD.get{["args"]={tostring(mp5_base + mp5_lvl * (18 - 1) * (0.7025 + 0.0175 * (18 - 1)))}}
            local dam_base = tonumber(t["dam_base"])
            local dam_lvl  = tonumber(t["dam_lvl"])
			local dam_18 = FD.get{["args"]={tostring(dam_base + dam_lvl * (18 - 1) * (0.7025 + 0.0175 * (18 - 1)))}}
            local as_base = tonumber(t["as_base"])
            local as_ratio  = tonumber(t["as_ratio"])
            local as_lvl  = tonumber(t["as_lvl"])
            local bonus_as_18  = 0 + as_lvl * (18 - 1) * (0.7025 + 0.0175 * (18 - 1))
            local as_18 = string.format("%0.3f", as_base + as_ratio * (bonus_as_18 / 100), 3)
            if champion == "Jhin" then as_18 = string.format("%0.3f", as_base + as_base * (bonus_as_18 / 100), 3) end
            as_18 = FD.get{["args"]={as_18}}
            
            local arm_base = tonumber(t["arm_base"])
            local arm_lvl  = tonumber(t["arm_lvl"])
			local arm_18 = FD.get{["args"]={tostring(arm_base + arm_lvl * (18 - 1) * (0.7025 + 0.0175 * (18 - 1)))}}
            local mr_base = tonumber(t["mr_base"])
            local mr_lvl  = tonumber(t["mr_lvl"])
			local mr_18 = FD.get{["args"]={tostring(mr_base + mr_lvl * (18 - 1) * (0.7025 + 0.0175 * (18 - 1)))}}
            local range = FD.get{["args"]={tostring(t["range"])}}
            local ms  = FD.get{["args"]={tostring(t["ms"])}}
            
            
            
            local resource = lolData[champion]["resource"]
            if resource == "Rage"
            or resource == "Heat"
            or resource == "Grit"
            or resource == "Fury"
            or resource == "Shield"
            or resource == "Bloodthirst"
            or resource == "Courage"
            or resource == "Health"
            or resource == "Flow"
            or resource == "Ferocity"
            or resource == "Energy"
            or resource == "None" then
                mp_18 = '-'
                mp5_18 = '-'
            end
                
            tablerow
                :tag('td')
                    :attr('data-sort-value', champion)
                    :css('text-align', 'left')
                    :wikitext('[[File:' .. FN.championcircle{champion} .. '|20px|alt=' .. champion .. '|link=' .. champion .. ']] [[' .. champion .. ']]')
                :done()
                :tag('td')
                    :wikitext(hp_18)
                    :css('color', 'lightgreen')
                :done()
                :tag('td')
                    :wikitext(hp5_18)
                    :css('color', 'lightgreen')
                :done()
                :tag('td')
                    :wikitext(mp_18)
                    :css('color', 'lightblue')
                :done()
                :tag('td')
                    :wikitext(mp5_18)
                    :css('color', 'lightblue')
                :done()
                :tag('td')
                    :wikitext(dam_18)
                    :css('color', '#ffaaaa')
                :done()
                :tag('td')
                    :wikitext(as_18)
                    :css('color', '#ffaaaa')
                :done()
                :tag('td')
                    :wikitext(arm_18)
                    :css('color', '#ffffaa')
                :done()
                :tag('td')
                    :wikitext(mr_18)
                    :css('color', '#ffffaa')
                :done()
                :tag('td')
                    :wikitext(range)
                    :css('color', '#ffffff')
                :done()
                :tag('td')
                    :wikitext(ms)
                    :css('color', '#ffffff')
                :done()
            :done()
        elseif _stat == "Manaless" then
--        Rage,Heat,Grit,Fury,Mana,Shield,Bloodthirst,Courage,Health,Flow,Ferocity,Energy,None -- as of 1/25/2020
            local resource = lolData[champion]["resource"]
            if resource ~= "Mana" then
                local resource_msg
                if resource == nil then resource = "None" end
                if resource == "Flow" 
                or resource == "None" then
                    resource_msg = "''[[Manaless]] champion (uses '''no secondary resource''')''"
                elseif resource == "Bloodthirst" then
                    resource_msg = "''[[Manaless]] champion (uses '''[[Manaless#Health|health]]''', '''[[Manaless#Fury|" .. mw.ustring.lower(resource) .. "]]''')''"
                elseif resource == "Grit" then
                    resource_msg = "''[[Manaless]] champion (uses '''[[Manaless#Fury|" .. mw.ustring.lower(resource) .. "]]''')''"
                elseif resource == "Energy" then
                    resource_msg = "''[[Manaless]] champion (uses '''[[" .. mw.ustring.lower(resource) .. "]]''')''"
                elseif resource == "Shield"then
                    resource_msg = "''[[Manaless]] champion (uses '''[[Manaless#Flow|" .. mw.ustring.lower(resource) .. "]]''')''"
                else
                    resource_msg = "''[[Manaless]] champion (uses '''[[Manaless#" .. resource .. "|" .. mw.ustring.lower(resource) .. "]]''')''"
                end
                tablerow
                    :tag('td')
                        :attr('data-sort-value', champion)
                        :css('text-align', 'left')
                        :wikitext('[[File:' .. FN.championcircle{champion} .. '|20px|alt=' .. champion .. '|link=' .. champion .. ']] [[' .. champion .. ']]')
                    :done()
                    :tag('td')
                        :wikitext(resource_msg)
                    :done()
            else
                tablerow = nil
            end
        elseif _stat == "Ratings" then
            local role = lolData[champion]['role']
            local primary = role[1]
            local secondary = role[2]
            local damage = lolData[champion]['damage']
            local toughness = lolData[champion]['toughness']
            local control = lolData[champion]['control']
            local mobility = lolData[champion]['mobility']
            local utility = lolData[champion]['utility']
            local style = lolData[champion]['style']
            local adaptivetype = mw.ustring.lower(lolData[champion]['adaptivetype'])
            local difficulty = lolData[champion]['difficulty']
            
            local primary_msg = ''
            if primary ~= nil then
               primary_msg = frame:expandTemplate{title="tip", args={primary}}
            else 
                primary = ''
            end
            local secondary_msg = ''
            if secondary ~= nil then
                secondary_msg = frame:expandTemplate{title="tip", args={secondary}}
            else
                secondary = ''
            end
            local damage_msg = damage
            local toughness_msg = toughness
            local control_msg = control
            local mobility_msg = mobility
            local utility_msg = utility
            local style_msg = frame:expandTemplate{title="Champion style", args={style, size="100px"}}
            local adaptivetype_msg;
            if adaptivetype == "magic" then
                adaptivetype_msg = "Magic"
            elseif adaptivetype == "physical" then
                adaptivetype_msg = "Physical"
            else
                -- adaptivetype_msg = frame:expandTemplate{title="pending for test"} .. " " .. frame:expandTemplate{title="edit", args={"Module:ChampionData/data"}}
                adaptivetype_msg = "Physical" -- default physical
            end
            local difficulty_msg = difficulty

            
            tablerow
                :tag('td')
                    :attr('data-sort-value', champion)
                    :css('text-align', 'left')
                    :css('padding', '1px')
                    :wikitext('[[File:' .. FN.championcircle{champion} .. '|20px|alt=' .. champion .. '|link=' .. champion .. ']] [[' .. champion .. ']]')
                :done()
                :tag('td')
                    :wikitext(primary_msg)
                    :attr('data-sort-value', primary)
                    :css('text-align', 'left')
                    :css('padding', '1px')
                :done()
                :tag('td')
                    :wikitext(secondary_msg)
                    :attr('data-sort-value', secondary)
                    :css('text-align', 'left')
                    :css('padding', '1px')
                :done()
                :tag('td')
                    :wikitext(damage_msg)
                    :attr('bgcolor', '#420300')
                    :css('padding', '1px')
                :done()
                :tag('td')
                    :wikitext(toughness_msg)
                    :attr('bgcolor', '#102E00')
                    :css('padding', '1px')
                :done()
                :tag('td')
                    :wikitext(control_msg)
                    :attr('bgcolor', '#30004C')
                    :css('padding', '1px')
                :done()
                :tag('td')
                    :wikitext(mobility_msg)
                    :attr('bgcolor', '#000A4C')
                    :css('padding', '1px')
                :done()
                :tag('td')
                    :wikitext(utility_msg)
                    :attr('bgcolor', '#5d4407')
                    :css('padding', '1px')
                :done()
                :tag('td')
                    :wikitext(style_msg)
                    :attr('data-sort-value', style)
                    :css('padding', '1px')
                :done()
                :tag('td')
                    :wikitext(adaptivetype_msg)
                    :attr('data-sort-value', adaptivetype)
                    :css('padding', '1px')
                :done()
                :tag('td')
                    :wikitext(difficulty_msg)
                    :css('padding', '1px')
                :done()
        else
            local _base = tonumber(t[convert[_stat] .. "_base"])
            local _lvl  = tonumber(t[convert[_stat] .. "_lvl"])
            
            tablerow
                :tag('td')
                    :attr('data-sort-value', champion)
                    :css('text-align', 'left')
                    :wikitext('[[File:' .. FN.championcircle{champion} .. '|20px|alt=' .. champion .. '|link=' .. champion .. ']] [[' .. champion .. ']]')
                :done()
                :tag('td')
                    :wikitext(_base)
                :done()
                :tag('td')
                    :wikitext(_lvl)
                :done()
                :tag('td')
                    :wikitext((_base or 0) + (_lvl or 0) * (18 - 1) * (0.7025 + 0.0175 * (18 - 1)))
                :done()
            :done()
        end
        
        -- Add row to table
        if tablerow ~= nil then
            tablenode
                :node(tablerow)
                :newline()
        end
    end
    
    tablenode:allDone()
    
    return tostring(tablenode)
end

function p.groupedStatTable(frame)
    local args; if frame.args == nil then args = lib.arguments(frame) else 
        if frame:getParent().args ~= nil then args = lib.arguments(lib.mergeFrames(frame, frame:getParent())) else args = lib.arguments(frame.args) end
    end
    
    local _stat             = args['datatype'] or args[1]
    local _statDisplayName  = args['label'] or args[2]
    local _filter           = args[3]
    local lolData   = mw.loadData('Module:ChampionData/data')
    local get       = require('Module:ChampionData/getter')
    local IL        = require('Module:ImageLink')
    
    local threshold3col = tonumber(args['3col']) or 12
    local threshold2col = tonumber(args['2col']) or 8
    
    local statTable = {}
    -- standard entries with note
    for champion in pairs(lolData) do
        -- filter
        if _stat == 'range' and get['rangetype'](champion) ~= _filter then -- do nothing
        elseif args[champion .. '_o'] then -- do nothing 
        else
            local v = get[_stat](champion)
            if v == nil then
            else
                if statTable[v] == nil then statTable[v] = {} end
                local displaystring = tostring(IL.champion{
                    ["champion"] = champion,
                    -- ["circle"] = "true",
                })
                if args[champion .. '_m'] then
                    displaystring = displaystring .. ' ' .. args[champion .. '_m']
                end
                if args[champion .. '_n'] then
                    displaystring = displaystring .. ' <span title="'.. args[champion .. '_n'] .. '"><sup>note</sup></span>'
                end
                statTable[v][champion] = displaystring
            end
        end
    end
    -- custom/manual entries
    local function customparams_iter(t)
        local i = 0
        local n = 0
        for i, _ in pairs(t) do
            n = n + 1
        end
        return function ()
            i = i + 1
            if i <= n and (t['c' .. i .. 'c'] or t['c' .. i .. 'm']) and t['c' .. i .. 'v'] then
                return t['c' .. i .. 'c'] or '', t['c' .. i .. 'm'] or '', t['c' .. i ..'n'] or '', t['c' .. i .. 'v']
            else
                return nil
            end
        end
    end
    for champion, modifier, note, value in customparams_iter(args) do
        local v = tonumber(value)
        local displaystring = ''
        if champion ~= '' then
            displaystring = displaystring .. tostring(IL.champion{
                ["champion"] = champion,
                -- ["circle"] = "true",
            })
        end
        if modifier ~= '' then
            displaystring = displaystring .. ' ' .. modifier
        end
        if note ~= '' then
            displaystring = displaystring .. '  <span title="'.. note .. '"><sup>note</sup></span>'
        end
        if statTable[v] == nil then statTable[v] = {} end
        if champion ~= '' then 
            statTable[v][champion] = displaystring
        else
            statTable[v][modifier] = displaystring
        end
    end
    
    -- table header row
    local tablenode = mw.html.create('table')
    tablenode
        :addClass('wikitable')
        :css('width', '100%')
        :newline()
    tablenode
        :tag('tr')
            :tag('th')
                :wikitext(_statDisplayName or _stat)
            :done()
            :tag('th')
                :wikitext('Champion')
            :done()
            -- :tag('th')
            --     :wikitext('Notes')
            -- :done()
        :done()
        :newline()
    
    -- sorting and table rows
    local optionTable = {}
    for option in pairs(statTable) do
        table.insert(optionTable, option)
    end
    table.sort(optionTable, function(a,b) return a > b end)
    for _, option in ipairs(optionTable) do
        local tablerow = mw.html.create('tr')
        local champcell = tablerow
            :tag('td')
                :css('text-align', 'center')
        if option == tonumber('inf') then
            champcell:wikitext('∞')
        else
            champcell:wikitext(option)
        end
        champcell = champcell
            :done()
            :newline()
            :tag('td')
                :tag('div')
                    :addClass('columntemplate')
                    :css('margin','0.4em 0 0.4em 0')
        local championTable = {}
        for champion in pairs(statTable[option]) do
            table.insert(championTable, champion)
        end
        table.sort(championTable)
        if table.getn(championTable) >= threshold3col then
            champcell
                :css('column-count', 3)
                :css('-webkit-column-count', 3)
                :css('-moz-column-count', 3)
        elseif table.getn(championTable) >= threshold2col then
            champcell
                :css('column-count', 2)
                :css('-webkit-column-count', 2)
                :css('-moz-column-count', 2)
        end
        champcell = champcell
                    :tag('ul')
        for _, champion in ipairs(championTable) do
            champcell
                :tag('li')
                    :wikitext(statTable[option][champion])
                    :newline()
        end
        tablenode
            :node(tablerow)
            :newline()
    end
    
    return tostring(tablenode)
end

-- JSON to Lua function for data from
-- http://ddragon.leagueoflegends.com/cdn/<patchversion>/data/en_US/champion.json

function p.jsontolua()
    local titleobject  = mw.title.new("User:Ninjamask/jsontemp")
    local o            = json.decode(titleobject:getContent())
    --local o2           = mw.loadData('Module:ChampionData/data')
    local s            = ""
    local championdata = {}
 
    for jsonchampname in pairs(o['data']) do
        table.insert(championdata, {jsonchampname, o['data'][jsonchampname]['name']})
    end
    table.sort(championdata, function(a, b) return a[2] < b[2] end)
    
    -- ============================
    -- = Generate lua data output =
    -- ============================
    
    s = s .. '-- <pre>\n'
    s = s .. '-- Champion data for patch version: ' .. o['version'] .. '\n'
    s = s .. '\n'
    s = s .. 'return {\n'

    
    for i, champname in pairs(championdata) do
        local t = o['data'][champname[1]]
        
        s = s .. '  ["' .. t['name'] .. '"] = {\n'
        s = s .. '    ["id"]         = '  .. t['key']                            .. ',\n'
        s = s .. '    ["apiname"]    = "' .. t['id']                            .. '",\n'
        s = s .. '    ["title"]      = "' .. t['title']                         .. '",\n'
        
        s = s .. '    ["attack"]     = '  .. t['info']['attack']                 .. ',\n'
        s = s .. '    ["defense"]    = '  .. t['info']['defense']                .. ',\n'
        s = s .. '    ["magic"]      = '  .. t['info']['magic']                  .. ',\n'
        s = s .. '    ["difficulty"] = '  .. t['info']['difficulty']             .. ',\n'
        
        s = s .. '    ["herotype"]   = "'  .. t['tags'][1]                      .. '",\n'
        if t['tags'][2] ~= nil then
            s = s .. '    ["alttype"]    = "'  .. t['tags'][2]                  .. '",\n'
        end
        
        s = s .. '    ["resource"]   = "'  .. t['partype']                      .. '",\n'
        s = s .. '    ["stats"] = {\n'
        s = s .. '      ["hp_base"]             = ' .. t['stats']['hp']                        .. ',\n'
        s = s .. '      ["hp_lvl"]              = ' .. t['stats']['hpperlevel']                .. ',\n'
        s = s .. '      ["mp_base"]             = ' .. t['stats']['mp']                        .. ',\n'
        s = s .. '      ["mp_lvl"]              = ' .. t['stats']['mpperlevel']                .. ',\n'
        s = s .. '      ["arm_base"]            = ' .. t['stats']['armor']                     .. ',\n'
        s = s .. '      ["arm_lvl"]             = ' .. t['stats']['armorperlevel']             .. ',\n'
        s = s .. '      ["mr_base"]             = ' .. t['stats']['spellblock']                .. ',\n'
        s = s .. '      ["mr_lvl"]              = ' .. t['stats']['spellblockperlevel']        .. ',\n'
        s = s .. '      ["hp5_base"]            = ' .. t['stats']['hpregen']                   .. ',\n'
        s = s .. '      ["hp5_lvl"]             = ' .. t['stats']['hpregenperlevel']           .. ',\n'
        s = s .. '      ["mp5_base"]            = ' .. t['stats']['mpregen']                   .. ',\n'
        s = s .. '      ["mp5_lvl"]             = ' .. t['stats']['mpregenperlevel']           .. ',\n'
        s = s .. '      ["dam_base"]            = ' .. t['stats']['attackdamage']              .. ',\n'
        s = s .. '      ["dam_lvl"]             = ' .. t['stats']['attackdamageperlevel']      .. ',\n'
        s = s .. '      ["as_base"]             = ' .. t['stats']['attackspeed']               .. ',\n'
        s = s .. '      ["as_lvl"]              = ' .. t['stats']['attackspeedperlevel']       .. ',\n'
        s = s .. '      ["range"]               = ' .. t['stats']['attackrange']               .. ',\n'
        s = s .. '      ["ms"]                  = ' .. t['stats']['movespeed']                 .. ',\n'
        s = s .. '      ["acquisition_radius"]  = ' .. p.get{t['name'], "acquisition_radius"}  .. ',\n'
        s = s .. '      ["selection_radius"]    = ' .. p.get{t['name'], "selection_radius"}    .. ',\n'
        s = s .. '      ["pathing_radius"]      = ' .. p.get{t['name'], "pathing_radius"}      .. ',\n'
        s = s .. '      ["gameplay_radius"]     = ' .. p.get{t['name'], "gameplay_radius"}     .. ',\n'
        s = s .. '      ["crit_base"]           = ' .. p.get{t['name'], "crit_base"}           .. ',\n'
        s = s .. '      ["crit_mod"]            = ' .. p.get{t['name'], "crit_mod"}            .. ',\n'
        s = s .. '      ["as_ratio"]            = ' .. p.get{t['name'], "as_ratio"}            .. ',\n'
        s = s .. '      ["windup_modifier"]     = ' .. p.get{t['name'], "windup_modifier"}     .. ',\n'
        s = s .. '      ["missile_speed"]       = ' .. p.get{t['name'], "missile_speed"}       .. ',\n'
        s = s .. '      ["attack_cast_time"]    = ' .. p.get{t['name'], "attack_cast_time"}    .. ',\n'
        s = s .. '      ["attack_total_time"]   = ' .. p.get{t['name'], "attack_total_time"}   .. ',\n'
        s = s .. '      ["attack_delay_offset"] = ' .. p.get{t['name'], "attack_delay_offset"} .. ',\n'
        s = s .. '      ["windup"]              = ' .. p.get{t['name'], "windup"}              .. ',\n'
        s = s .. '      ["aram_dmg_dealt"]      = ' .. p.get{t['name'], "aram_dmg_dealt"}      .. ',\n'
        s = s .. '      ["aram_dmg_taken"]      = ' .. p.get{t['name'], "aram_dmg_taken"}      .. ',\n'
        s = s .. '      ["aram_healing"]        = ' .. p.get{t['name'], "aram_healing"}        .. ',\n'
        s = s .. '      ["aram_shielding"]      = ' .. p.get{t['name'], "aram_shielding"}      .. ',\n'
        s = s .. '      ["nb_dmg_dealt"]      = ' .. p.get{t['name'], "nb_dmg_dealt"}      .. ',\n'
        s = s .. '      ["nb_dmg_taken"]      = ' .. p.get{t['name'], "nb_dmg_taken"}      .. ',\n'
        s = s .. '      ["nb_healing"]        = ' .. p.get{t['name'], "nb_healing"}        .. ',\n'
        s = s .. '      ["nb_shielding"]      = ' .. p.get{t['name'], "nb_shielding"}      .. ',\n'
        s = s .. '      ["ofa_dmg_dealt"]       = ' .. p.get{t['name'], "ofa_dmg_dealt"}      .. ',\n'
        s = s .. '      ["ofa_dmg_taken"]       = ' .. p.get{t['name'], "ofa_dmg_taken"}      .. ',\n'
        s = s .. '      ["ofa_healing"]         = ' .. p.get{t['name'], "ofa_healing"}        .. ',\n'
        s = s .. '      ["ofa_shielding"]       = ' .. p.get{t['name'], "ofa_shielding"}      .. ',\n'
        s = s .. '      ["urf_dmg_dealt"]       = ' .. p.get{t['name'], "urf_dmg_dealt"}       .. ',\n'
        s = s .. '      ["urf_dmg_taken"]       = ' .. p.get{t['name'], "urf_dmg_taken"}       .. ',\n'
        s = s .. '      ["urf_healing"]         = ' .. p.get{t['name'], "urf_healing"}         .. ',\n'
        s = s .. '      ["urf_shielding"]       = ' .. p.get{t['name'], "urf_shielding"}       .. '\n'
        s = s .. '    }\n'
        s = s .. '  }' .. lib.ternary(i ~= #championdata, ',\n','\n')
    end

    s = s .. '}\n'
    s = s .. '-- </' .. 'pre>\n' -- pre needs to be splitted with .. cause of Lua/Mediawiki weirdness

    s = s .. '-- [[Category:StatTable data]]'
    
    return 'Copy & paste data below to [[Module:StatTable/data/' .. o['version'] ..  ']]<pre>' .. s .. '</pre>Copy & paste data above to [[Module:StatTable/data/' .. o['version'] .. ']]'
end

function p.main2(frame) -- deprecated
    local args; if frame.args == nil then args = lib.arguments(frame) else args = lib.arguments(frame.args) end
    
    local patchid      = args[1] or args['patchid'] or cmd.main{"PatchId"}
    local luadata      = loadData(patchid)
    local o            = mw.loadData('Module:StatTable/data/' .. patchid)
    local s            = ""
    local championdata = {}
    
    if type(luadata)     == nil then
        return userError("No data available for patch " .. patchid, "LuaError")
    end
    
    for championname in pairs(o) do
        table.insert(championdata, championname)
    end
    table.sort(championdata)
    
    -- ============================
    -- = Generate lua data output =
    -- ============================
    
    s = s .. '-- <pre>\n'
    s = s .. '-- Champion data for patch version: ' .. patchid .. '\n'
    s = s .. '\n'
    s = s .. 'return {\n'

    
    for i, champname in pairs(championdata) do
        local t = o[champname]
        
        -- StatTable data 
        s = s .. '  ["' .. champname .. '"] = {\n'
        s = s .. '    ["id"]         = '  .. t['id']                            .. ',\n'
        s = s .. '    ["apiname"]    = "' .. t['apiname']                       .. '",\n'
        s = s .. '    ["title"]      = "' .. t['title']                         .. '",\n'
        
        s = s .. '    ["attack"]     = '  .. t['attack']                        .. ',\n'
        s = s .. '    ["defense"]    = '  .. t['defense']                       .. ',\n'
        s = s .. '    ["magic"]      = '  .. t['magic']                         .. ',\n'
        s = s .. '    ["difficulty"] = '  .. t['difficulty']                    .. ',\n'
        
        s = s .. '    ["herotype"]   = "'  .. t['herotype']                     .. '",\n'
        if t['alttype'] ~= nil then
            s = s .. '    ["alttype"]    = "'  .. t['alttype']                  .. '",\n'
        end
        
        s = s .. '    ["resource"]   = "'  .. t['resource']                     .. '",\n'
        s = s .. '    ["stats"] = {\n'
        s = s .. '      ["hp_base"]  = '  .. t['stats']['hp_base']              .. ',\n'
        s = s .. '      ["hp_lvl"]   = '  .. t['stats']['hp_lvl']               .. ',\n'
        s = s .. '      ["mp_base"]  = '  .. t['stats']['mp_base']              .. ',\n'
        s = s .. '      ["mp_lvl"]   = '  .. t['stats']['mp_lvl']               .. ',\n'
        s = s .. '      ["arm_base"] = '  .. t['stats']['arm_base']             .. ',\n'
        s = s .. '      ["arm_lvl"]  = '  .. t['stats']['arm_lvl']              .. ',\n'
        s = s .. '      ["mr_base"]  = '  .. t['stats']['mr_base']              .. ',\n'
        s = s .. '      ["mr_lvl"]   = '  .. t['stats']['mr_lvl']               .. ',\n'
        s = s .. '      ["hp5_base"] = '  .. t['stats']['hp5_base']             .. ',\n'
        s = s .. '      ["hp5_lvl"]  = '  .. t['stats']['hp5_lvl']              .. ',\n'
        s = s .. '      ["mp5_base"] = '  .. t['stats']['mp5_base']             .. ',\n'
        s = s .. '      ["mp5_lvl"]  = '  .. t['stats']['mp5_lvl']              .. ',\n'
        s = s .. '      ["dam_base"] = '  .. t['stats']['dam_base']             .. ',\n'
        s = s .. '      ["dam_lvl"]  = '  .. t['stats']['dam_lvl']              .. ',\n'
        s = s .. '      ["as_base"]  = '  .. pst2(champname, "as_base")         .. ',\n'
        if t['stats']['as_lvl1'] ~= nil and t['stats']['as_lvl1'] ~= tonumber(pst2(champname, "as_base")) then
            s = s .. '      ["as_lvl1"]  = '     .. t['stats']['as_lvl1']       .. ',\n'
        end
        if t['stats']['attack_delay'] ~= nil then
            s = s .. '      ["attack_delay"] = ' .. t['stats']['attack_delay']  .. ',\n'
        end
        as_lvl1 = pst2(champname, "as_lvl1_bonus")
        if as_lvl1 ~= "{{{as_lvl1_bonus}}}" then
            s = s .. '      ["as_lvl1_bonus"]  = '  .. pst2(champname, "as_lvl1_bonus")         .. ',\n'
        end
        s = s .. '      ["as_lvl"]   = '  .. t['stats']['as_lvl']               .. ',\n'
        s = s .. '      ["range"]    = '  .. pst2(champname, "range")           .. ',\n'
        s = s .. '      ["ms"]       = '  .. pst2(champname, "ms")              ..  '\n'
        s = s .. '    },\n'
        
        -- Additional data from champion data templates
        fullname = pst2(champname, "fullname")
        if fullname ~= "{{{fullname}}}" then
            s = s .. '    ["fullname"]   = "' .. fullname                       .. '",\n'
        end
        
        nickname = pst2(champname, "nickname")
        if nickname ~= "{{{nickname}}}" then
            s = s .. '    ["nickname"]   = "' .. nickname                       .. '",\n'
        end
        
        s = s .. '    ["rangetype"]   = "' .. pst2(champname, "rangetype")           .. '",\n'
        s = s .. '    ["date"]        = "' .. pst2(champname, "date")                .. '",\n'
        s = s .. '    ["patch"]       = "' .. pst2(champname, "patch")               .. '",\n'
        s = s .. '    ["changes"]     = "' .. pst2(champname, "changes")             .. '",\n'
        s = s .. '    ["role"]        = {' .. strtoluadata(pst2(champname, "role"), ",") .. '},\n'
        s = s .. '    ["damage"]      = '  .. pst2(champname, "damage")              .. ',\n'
        s = s .. '    ["toughness"]   = '  .. pst2(champname, "toughness")           .. ',\n'
        s = s .. '    ["control"]     = '  .. pst2(champname, "control")             .. ',\n'
        s = s .. '    ["mobility"]    = '  .. pst2(champname, "mobility")            .. ',\n'
        s = s .. '    ["utility"]     = '  .. pst2(champname, "utility")             .. ',\n'
        s = s .. '    ["style"]       = '  .. pst2(champname, "style")               .. ',\n'
        s = s .. '    ["adaptivetype"]= "' .. pst2(champname, "adaptivetype")        .. '",\n'
        s = s .. '    ["be"]          = '  .. pst2(champname, "be")                  .. ',\n'
        s = s .. '    ["rp"]          = '  .. pst2(champname, "rp")                  .. ',\n'
        s = s .. '    ["skill_i"]     = {' .. strtoluadatai(pst2(champname, "skill_i"), ";") .. '},\n'
        s = s .. '    ["skill_q"]     = {' .. strtoluadatai(pst2(champname, "skill_q"), ";") .. '},\n'
        s = s .. '    ["skill_w"]     = {' .. strtoluadatai(pst2(champname, "skill_w"), ";") .. '},\n'
        s = s .. '    ["skill_e"]     = {' .. strtoluadatai(pst2(champname, "skill_e"), ";") .. '},\n'
        s = s .. '    ["skill_r"]     = {' .. strtoluadatai(pst2(champname, "skill_r"), ";") .. '}\n'
        s = s .. '  }' .. lib.ternary(i ~= #championdata, ',\n','\n')
    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.main(frame) -- deprecated
    local o            = mw.loadData('Module:StatTable/data/' .. patchid)
    local s            = ""
    local championdata = {}
    
    if type(luadata)     == nil then
        return userError("No data available for patch " .. patchid, "LuaError")
    end
    
    for championname in pairs(o) do
        table.insert(championdata, championname)
    end
    table.sort(championdata)
    
    -- ============================
    -- = Generate lua data output =
    -- ============================
    
    s = s .. '-- <pre>\n'
    s = s .. '-- Champion data for patch version: ' .. patchid .. '\n'
    s = s .. '\n'
    s = s .. 'return {\n'

    
    for i, champname in pairs(championdata) do
        local t = o[champname]
        
        -- StatTable data 
        s = s .. '  ["' .. champname .. '"] = {\n'
        s = s .. '    ["id"]         = '  .. t['id']                            .. ',\n'
        s = s .. '    ["apiname"]    = "' .. t['apiname']                       .. '",\n'
        s = s .. '    ["title"]      = "' .. t['title']                         .. '",\n'
        
        s = s .. '    ["attack"]     = '  .. t['attack']                        .. ',\n'
        s = s .. '    ["defense"]    = '  .. t['defense']                       .. ',\n'
        s = s .. '    ["magic"]      = '  .. t['magic']                         .. ',\n'
        s = s .. '    ["difficulty"] = '  .. t['difficulty']                    .. ',\n'
        
        s = s .. '    ["herotype"]   = "'  .. t['herotype']                     .. '",\n'
        if t['alttype'] ~= nil then
            s = s .. '    ["alttype"]    = "'  .. t['alttype']                  .. '",\n'
        end
        
        s = s .. '    ["resource"]   = "'  .. t['resource']                     .. '",\n'
        s = s .. '    ["stats"] = {\n'
        s = s .. '      ["hp_base"]  = '  .. t['stats']['hp_base']              .. ',\n'
        s = s .. '      ["hp_lvl"]   = '  .. t['stats']['hp_lvl']               .. ',\n'
        s = s .. '      ["mp_base"]  = '  .. t['stats']['mp_base']              .. ',\n'
        s = s .. '      ["mp_lvl"]   = '  .. t['stats']['mp_lvl']               .. ',\n'
        s = s .. '      ["arm_base"] = '  .. t['stats']['arm_base']             .. ',\n'
        s = s .. '      ["arm_lvl"]  = '  .. t['stats']['arm_lvl']              .. ',\n'
        s = s .. '      ["mr_base"]  = '  .. t['stats']['mr_base']              .. ',\n'
        s = s .. '      ["mr_lvl"]   = '  .. t['stats']['mr_lvl']               .. ',\n'
        s = s .. '      ["hp5_base"] = '  .. t['stats']['hp5_base']             .. ',\n'
        s = s .. '      ["hp5_lvl"]  = '  .. t['stats']['hp5_lvl']              .. ',\n'
        s = s .. '      ["mp5_base"] = '  .. t['stats']['mp5_base']             .. ',\n'
        s = s .. '      ["mp5_lvl"]  = '  .. t['stats']['mp5_lvl']              .. ',\n'
        s = s .. '      ["dam_base"] = '  .. t['stats']['dam_base']             .. ',\n'
        s = s .. '      ["dam_lvl"]  = '  .. t['stats']['dam_lvl']              .. ',\n'
        s = s .. '      ["as_base"]  = '  .. pst2(champname, "as_base")         .. ',\n'
        if t['stats']['as_lvl1'] ~= nil and t['stats']['as_lvl1'] ~= tonumber(pst2(champname, "as_base")) then
            s = s .. '      ["as_lvl1"]  = '     .. t['stats']['as_lvl1']       .. ',\n'
        end
        if t['stats']['attack_delay'] ~= nil then
            s = s .. '      ["attack_delay"] = ' .. t['stats']['attack_delay']  .. ',\n'
        end
        as_lvl1 = pst2(champname, "as_lvl1_bonus")
        if as_lvl1 ~= "{{{as_lvl1_bonus}}}" then
            s = s .. '      ["as_lvl1_bonus"]  = '  .. pst2(champname, "as_lvl1_bonus")         .. ',\n'
        end
        s = s .. '      ["as_lvl"]   = '  .. t['stats']['as_lvl']               .. ',\n'
        s = s .. '      ["range"]    = '  .. pst2(champname, "range")           .. ',\n'
        s = s .. '      ["ms"]       = '  .. pst2(champname, "ms")              ..  '\n'
        s = s .. '    },\n'
        
        -- Additional data from champion data templates
        fullname = pst2(champname, "fullname")
        if fullname ~= "{{{fullname}}}" then
            s = s .. '    ["fullname"]   = "' .. fullname                       .. '",\n'
        end
        
        nickname = pst2(champname, "nickname")
        if nickname ~= "{{{nickname}}}" then
            s = s .. '    ["nickname"]   = "' .. nickname                       .. '",\n'
        end
        
        s = s .. '    ["rangetype"]   = "' .. pst2(champname, "rangetype")           .. '",\n'
        s = s .. '    ["date"]        = "' .. pst2(champname, "date")                .. '",\n'
        s = s .. '    ["patch"]       = "' .. pst2(champname, "patch")               .. '",\n'
        s = s .. '    ["changes"]     = "' .. pst2(champname, "changes")             .. '",\n'
        s = s .. '    ["role"]        = {' .. strtoluadata(pst2(champname, "role"), ",") .. '},\n'
        s = s .. '    ["damage"]      = '  .. pst2(champname, "damage")              .. ',\n'
        s = s .. '    ["toughness"]   = '  .. pst2(champname, "toughness")           .. ',\n'
        s = s .. '    ["control"]     = '  .. pst2(champname, "control")             .. ',\n'
        s = s .. '    ["mobility"]    = '  .. pst2(champname, "mobility")            .. ',\n'
        s = s .. '    ["utility"]     = '  .. pst2(champname, "utility")             .. ',\n'
        s = s .. '    ["style"]       = '  .. pst2(champname, "style")               .. ',\n'
        s = s .. '    ["adaptivetype"]= "' .. pst2(champname, "adaptivetype")        .. '",\n'
        s = s .. '    ["be"]          = '  .. pst2(champname, "be")                  .. ',\n'
        s = s .. '    ["rp"]          = '  .. pst2(champname, "rp")                  .. ',\n'
        s = s .. '    ["skill_i"]     = {' .. strtoluadatai(pst2(champname, "skill_i"), ";") .. '},\n'
        s = s .. '    ["skill_q"]     = {' .. strtoluadatai(pst2(champname, "skill_q"), ";") .. '},\n'
        s = s .. '    ["skill_w"]     = {' .. strtoluadatai(pst2(champname, "skill_w"), ";") .. '},\n'
        s = s .. '    ["skill_e"]     = {' .. strtoluadatai(pst2(champname, "skill_e"), ";") .. '},\n'
        s = s .. '    ["skill_r"]     = {' .. strtoluadatai(pst2(champname, "skill_r"), ";") .. '}\n'
        s = s .. '  }' .. lib.ternary(i ~= #championdata, ',\n','\n')
    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.mainrole(frame)
    local args; if frame.args == nil then args = lib.arguments(frame) else args = lib.arguments(frame.args) end
    
    local parentroletable = {
        ["Catcher"]    = "Controller",
        ["Enchanter"]  = "Controller",
        ["Diver"]      = "Fighter",
        ["Juggernaut"] = "Fighter",
        ["Battlemage"] = "Mage",
        ["Burst"]      = "Mage",
        ["Artillery"]  = "Mage",
        ["Assassin"]   = "Slayer",
        ["Skirmisher"] = "Slayer",
        ["Vanguard"]   = "Tank",
        ["Warden"]     = "Tank",
        ["Marksman"]   = "",
        ["Specialist"] = "",
    }
    
    local champname = args[1] or args['champname'] 
    local lolData   = mw.loadData('Module:ChampionData/data')
    local item      = lolData[champname][positions]
    local s         = ""
    
    for i, subrole in pairs(item) do
        if i ~= 1 then
            s = s .. ","
        end
        s = s .. parentroletable[subrole]
    end
    
    return s
end

function p.positioncategory(frame)
    local args; if frame.args == nil then args = lib.arguments(frame) else args = lib.arguments(frame.args) end
    
    local category  = {
        ["Top"]     = "[[Category:Top champion]]",
        ["Jungle"]  = "[[Category:Jungle champion]]",
        ["Middle"]  = "[[Category:Middle champion]]",
        ["Bottom"]  = "[[Category:Bottom champion]]",
        ["Support"] = "[[Category:Support champion]]"
    }
    
    local champname = args[1] or args['champname'] 
    local get       = require ('Module:ChampionData/getter')
    local item      = positions(champname)
    local s         = ""
    
    for i, subpos in pairs(item) do
        if i ~= 1 then
            s = s .. ","
        end
        s = s .. category[subpos]
    end
    
    return s
end

function p.minmaxstattable() -- work in progress
    local o            = mw.loadData('Module:ChampionData/data')
    local stat         = 'hp5_lvl'
    local stattable    = {}
    
    for champion in pairs(o) do
        -- mw.log(champion, o[champion].stats.hp5_base)
        table.insert(stattable, {champion, o[champion].stats.hp5_base, o[champion].stats.hp5_lvl, o[champion].stats.hp5_base + o[champion].stats.hp5_lvl * (18-1) * (0.7025 + 0.0175 * (18 - 1))})
    end
    table.sort(stattable, function(a, b) return a[2] > b[2] end)
    -- mw.log(lib.tbl(stattable))
    
    result ={}
    size = 0
    for i, t in ipairs(stattable) do
        if i == 1 then
            table.insert(result, t)
            size = size + 1
        elseif result[i-1][2] ~= t[2] then
            table.insert(result, t)
            size = size + 1
        elseif size <= 5 then
            table.insert(result, t)
        else
            break
        end
    end
    
        -- if i == 1 then
        --     table.insert(result, t)
        --     size = size + 1
        -- elseif size < 5 then
        --     if result[i-1][2] ~= t[2] then
        --         table.insert(result, t)
        --         size = size + 1
        --     end
        -- else
        --     break
        -- end
    
    
    table.sort(result, function(a, b) return a[2] < b[2] end)
    mw.log(lib.tbl(result))
end

--
-- local funtions
-- 

function strtoluadata(str, sep)
    x = lib.split(str, sep)
    i = 1
    s = '"' .. mw.text.trim(x[i]) .. '"'
    i = i + 1
    while i <= #x do
        s = s .. ', "' .. mw.text.trim(x[i]) .. '"'
        i = i + 1
    end
    return s
end

function strtoluadatai(str, sep)
    x = lib.split(str, sep)
    i = 1
    s = '[' .. i .. '] = "' .. mw.text.trim(x[i]) .. '"'
    i = i + 1
    while i <= #x do
        s = s .. ', [' .. i .. '] = "' .. mw.text.trim(x[i]) .. '"'
        i = i + 1
    end
    return s
end

function pst2(champion, stat)
    local frame = mw.getCurrentFrame()
 
    return frame:expandTemplate{
        title = 'Data ' .. champion, args = {'pst2', stat}
    }
end

function loadData(patchid)
    if exists('Module:StatTable/data/' .. patchid) then
        return mw.loadData('Module:StatTable/data/' .. patchid)
    end
 
    return nil
end
 
function exists(page)
    local sPage = page
 
    if sPage then 
        local _, val = pcall(package.loaders[2], sPage)
 
        if type(val) == "function" or type(val) == "string" then
           return true
        end
    end
 
    return false
end

return p
-- </pre>
-- [[Category:Lua]]
Advertisement