Module:Mastery effect/sandbox: Difference between revisions

From Path of Exile Wiki
Jump to navigation Jump to search
(troubleshooting..., changing how cargo data gets stored.)
No edit summary
 
(3 intermediate revisions by the same user not shown)
Line 1: Line 1:
--
-------------------------------------------------------------------------------
-- Module for Mastery Effects
--  
--
--                            Module:Mastery effect
--
-- This module implements Template:Mastery effect
-------------------------------------------------------------------------------


local m_util = require('Module:Util')
local m_util = require('Module:Util')
local m_cargo = require('Module:Cargo')
local m_cargo = require('Module:Cargo')
local getArgs = require('Module:Arguments').getArgs
 
local f_infocard = require('Module:Infocard')._main
local f_infocard = require('Module:Infocard')._main
local p = {}


-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
Line 81: Line 82:
             field = 'stat_text',
             field = 'stat_text',
             type = 'Text',
             type = 'Text',
             func = function (tpl_args, frame)
             func = function (tpl_args, value)
                 if tpl_args.stat_text then
                 if tpl_args.stat_text then
                     tpl_args.stat_text_raw = string.gsub(
                     tpl_args.stat_text_raw = string.gsub(
Line 215: Line 216:
-- end
-- end


function h.intro_text(tpl_args, frame)
function h.intro_text(tpl_args)
     --[[
     --[[
     Display an introductory text about the passive skill.
     Display an introductory text about the passive skill.
Line 221: Line 222:
     local out = {}
     local out = {}
     if mw.ustring.find(tpl_args['id'], '_') then
     if mw.ustring.find(tpl_args['id'], '_') then
         out[#out+1] = frame:expandTemplate{
         out[#out+1] = mw.getCurrentFrame():expandTemplate{
             title='Incorrect title',  
             title='Incorrect title',  
             args = {title=tpl_args['id']}  
             args = {title=tpl_args['id']}  
Line 235: Line 236:
end
end


function h.stat_box(tpl_args, frame)
function h.stat_box(tpl_args)
     --[[
     --[[
     Display the stat box.
     Display the stat box.
Line 244: Line 245:
          
          
     -- stat table  
     -- stat table  
     tbl = container:tag('table')
     local tbl = container:tag('table')
     tbl
     tbl
         :attr('class', 'wikitable sortable')
         :attr('class', 'wikitable sortable')
Line 296: Line 297:
     return tostring(container)
     return tostring(container)
end
end


-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
-- Page functions
-- Main functions
-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------


local p = {}
local function _mastery_effect(tpl_args)
 
-- This way the helper functions can be used in other modules
p.h = h
 
-- Declare cargo tables:
p.table_mastery_effects = m_cargo.declare_factory{data=tables.mastery_effects}
p.table_mastery_effect_stats = m_cargo.declare_factory{data=tables.mastery_effect_stats}
 
function p.mastery_effect(frame)
     --[[
     --[[
     Stores data and displays a infobox about the passive skill.
     Stores data and displays a infobox about the passive skill.
Line 327: Line 318:
      
      
     ]]
     ]]
    -- Get args
    tpl_args = getArgs(frame, {
        parentFirst = true
    })
    frame = m_util.misc.get_frame(frame)


     -- parse and store mastery effect into cargo table
     -- parse and store mastery effect into cargo table
     m_util.args.from_cargo_map{
     m_util.args.from_cargo_map{
         tpl_args=tpl_args,
         tpl_args=tpl_args,
        frame=frame,
         table_map=tables.mastery_effects,
         table_map=tables.mastery_effects,
     }
     }
Line 348: Line 332:
     end
     end
      
      
    -- Attach to tables
    mw.getCurrentFrame():expandTemplate{title = 'Template:Mastery effect/cargo/mastery effects/attach'}
    mw.getCurrentFrame():expandTemplate{title = 'Template:Mastery effect/cargo/mastery effect stats/attach'}
     --
     --
     -- Infobox
     -- Infobox
Line 368: Line 356:
             local dsp
             local dsp
             if data.display then
             if data.display then
                 dsp = data.display(tpl_args, frame, value)
                 dsp = data.display(tpl_args, value)
             else
             else
                 dsp = value
                 dsp = value
Line 390: Line 378:
     local out = {
     local out = {
         f_infocard(infocard_args),
         f_infocard(infocard_args),
         h.intro_text(tpl_args, frame),
         h.intro_text(tpl_args),
         h.stat_box(tpl_args, frame),
         h.stat_box(tpl_args),
     }
     }
      
      
Line 397: Line 385:
         i18n.cats.data,
         i18n.cats.data,
     }
     }
     return table.concat(out) .. m_util.misc.add_category(cats)
     return table.concat(out) .. m_util.misc.add_category(cats)
end
end


-- function p.passive_skill_box(frame)
-- ----------------------------------------------------------------------------
--     --[[
-- Exported functions
--     Queries a passive skill and displays it.
-- ----------------------------------------------------------------------------
   
--     Examples
--     --------
--     = p.passive_skill_box{name='Ghost Reaver'}
   
--     ]]
   
--     -- Get args
--     tpl_args = getArgs(frame, {
--         parentFirst = true
--     })
--     frame = m_util.misc.get_frame(frame)
   
--     tpl_args.name = tpl_args.name or tpl_args[1]
   
--     if not tpl_args.q_where and tpl_args.name then
--         tpl_args.q_where = string.format('passive_skills.name="%s" AND passive_skills.stat_text IS NOT NULL', tpl_args.name)
--     elseif not (tpl_args.q_where and not tpl_args.name) then
--         error('q_where or name must be specified')
--     end
   
--     local results = m_cargo.query(
--        {'passive_skills'},
--         {
--             'passive_skills._pageName',
--             'passive_skills.main_page',
--             'passive_skills.name',
--             'passive_skills.stat_text',
--             -- TODO: only really need these once, maybe put in extra query
--             'passive_skills.flavour_text',
--             'passive_skills.icon',
--             'passive_skills.is_keystone',
--            'passive_skills.is_notable',
--            'passive_skills.ascendancy_class',
--            'passive_skills.id'
--        },
--         {
--             where=tpl_args.q_where,
--             orderBy='passive_skills.stat_text',
--             limit=5000,
--         }
--     )
--     if #results == 0 then
--         error(i18n.errors.no_passives_found)
--     end
   
--     results = h.sort_by_type(results)
--     local out = {}
--     local cats = {}
--     for _, type_key in ipairs(h.type_order) do
--         local type_results = results[type_key]
--         if #type_results > 0 then
--             cats[#cats+1] = i18n.cats[type_key]
--             local stats, stat_order = h.make_stat_order(type_results)
           
--             local passive = type_results[1]
           
--             local infocard_args = {}
--             infocard_args.header = passive['passive_skills.name']
--             infocard_args.subheader = i18n.mastery_effct_box[type_key]
           
--             infocard_args[1] = h.format_passive_icon(passive, type_key)
--             infocard_args[2] = h.stat_page_links(stat_order, stats)
--             infocard_args[3] = m_util.html.poe_color('flavour', passive['passive_skills.flavour_text'])
           
--             out[#out+1] = f_infocard(infocard_args)
           
--             -- Store as main page:
--             for _, v in ipairs(type_results) do
--                 m_cargo.store(
--                     frame,
--                     {
--                         _table='main_pages',
--                         id=v['passive_skills.id'],
--                     }
--                 )
--             end
--         end
--     end
   
--     if tpl_args.cats == nil or m_util.cast.boolean(tpl_args.cats) then
--         out[#out+1] = m_util.misc.add_category(cats)
--     end
   
--     return table.concat(out)
-- end


-- function p.passive_skill_link(frame)
local p = {}
--    --[[
--    Links a passive skill
   
--    Examples
--    --------
--    = p.passive_skill_link{id='AscendancyAscendant45', format='tablerow'}
--    ]]
   
--    -- Get args
--    tpl_args = getArgs(frame, {
--        parentFirst = true
--    })
--    frame = m_util.misc.get_frame(frame)
   
--    tpl_args.name = tpl_args.name or tpl_args[1]
--    if tpl_args.name then
--        tpl_args.q_where = string.format('passive_skills.name="%s"', tpl_args.name)
--    elseif tpl_args.id then
--        tpl_args.q_where = string.format('passive_skills.id="%s"', tpl_args.id)
--    elseif tpl_args.q_where then
--    else
--        error('Either name, id or q_where must be specified')
--    end
   
--    local results = m_cargo.query(
--        {'passive_skills', 'main_pages'},
--        {
--            'passive_skills._pageName',
--            'passive_skills.stat_text',
--            'passive_skills.main_page',
--            'passive_skills.name',
--            'passive_skills.icon',
--            'passive_skills.is_keystone',
--            'passive_skills.is_notable',
--            'passive_skills.ascendancy_class',
--            'main_pages._pageName',
--        },
--        { 
--            join='passive_skills.id=main_pages.id',
--            where=string.format('(%s) AND passive_skills.stat_text IS NOT NULL', tpl_args.q_where),
--            orderBy='passive_skills.stat_text',
--            limit=2,
--        }
--    )
   
--    if #results > 1 then
--        error('Too many passives found!')
--    elseif #results < 1 then
--        error('No passives found')
--    end
--    local passive = results[1]
   
--    if tpl_args.format == 'tablerow' then
--        local main_page = passive['passive_skills.main_page'] or passive['main_pages._pageName'] or passive['passive_skills.name']
--        return string.format(
--            '| [[%s|%s]]%s\n| %s',
--            main_page,
--            passive['passive_skills.name'],
--            h.format_passive_icon(passive, h.get_type(passive)),
--            passive['passive_skills.stat_text']
--        )
--    elseif tpl_args.format == nil then
--        return
--    else
--        error(string.format('Invalid return format specified: %s', tpl_args.format))
--    end
-- end


-- -- Not sure whether we need a more sophisticated variant like item or mod tables here yet
-- Declare cargo tables:
p.table_mastery_effects = m_cargo.declare_factory{data=tables.mastery_effects}
p.table_mastery_effect_stats = m_cargo.declare_factory{data=tables.mastery_effect_stats}


-- function p.passive_skill_table2(frame)
--
--    -- Get args
-- Template:Mastery effect
--    tpl_args = getArgs(frame, {
--  
--        parentFirst = true
p.mastery_effect = m_util.misc.invoker_factory(_mastery_effect, {
--    })
     wrappers = 'Template:Mastery effect',
--    frame = m_util.misc.get_frame(frame)
})
   
--    if tpl_args.q_tables then
--        tpl_args.q_tables = tpl_args.q_tables .. ',' .. 'passive_skill_stats'
--    else
--        tpl_args.q_tables = 'passive_skill_stats'
--    end
   
--    if tpl_args.q_join then
--        tpl_args.q_join = tpl_args.q_join .. ',' .. 'passive_skills._pageID=passive_skill_stats._pageID'
--    else
--        tpl_args.q_join = 'passive_skills._pageID=passive_skill_stats._pageID'
--    end
   
--    tpl_args.q_orderBy = 'passive_skills.ascendancy_class IS NULL DESC, passive_skills.is_keystone, passive_skills.is_notable, passive_skills.name'
   
--    return m_cargo.table_query{
--        tpl_args=tpl_args,
--        frame=frame,
--        main_table='passive_skills',
--        row_unique_fields = {'passive_skills.name'},
--        data={
--            tables = {
--                passive_skill_stats = {
--                    join='passive_skills._pageID=passive_skill_stats._pageID',
--                },
--            },
--            -- display data
--            {
--                args = {'ascendancy'},
--                header = i18n.passive_table.ascendancy_class,
--                fields = {
--                    'passive_skills.ascendancy_class',
--                },
--                display = function (tpl_args, frame, tr, data)
--                    local passive = data[1]
--                    if passive['passive_skills.ascendancy_class'] then
--                        tr:tag('td')
--                            :wikitext(string.format('[[%s]]<br>[[File:%s avatar.png|link=%s]]', passive['passive_skills.ascendancy_class'], passive['passive_skills.ascendancy_class'], passive['passive_skills.ascendancy_class']))
--                    else
--                        tr:wikitext(m_util.html.td.na{})
--                    end
--                end,
--                order = 0,
--                sort_type = 'text',
--            },
--            {
--                args = nil,
--                header = i18n.passive_table.name,
--                fields = {
--                    'passive_skills._pageName',
--                    'passive_skills.main_page',
--                    'passive_skills.name',
--                    'passive_skills.icon',
--                    'passive_skills.is_keystone',
--                    'passive_skills.is_notable',
--                    'passive_skills.ascendancy_class',
--                },
--                display = function (tpl_args, frame, tr, data)
--                    local passive = data[1]
--                    local type_key = h.get_type(passive)
--                    tr
--                        :tag('td')
--                            :attr('data-sort-value', passive['passive_skills.name'] .. type_key)
--                            :wikitext(string.format('[[%s|%s]]<br>%s', passive['passive_skills.main_page'] or passive['passive_skills.name'], passive['passive_skills.name'], h.format_passive_icon(passive, type_key)))
--                             :done()
--                end,
--                 order = 1000,
--                sort_type = 'text',
--                options = {
--                    [7] = {
--                        optional=true,
--                    },
--                },
--            },
--            {
--                arg = {'default', 'stat', 'stats', 'stat_text'},
--                header = i18n.passive_table.stats,
--                fields = {
--                    'passive_skills.stat_text',
--                },
--                display = function (tpl_args, frame, tr, data)
--                    local passive = data[1]
--                    local stats, stat_order = h.make_stat_order(data)
--                    tr
--                        :tag('td')
--                            :wikitext(h.stat_page_links(stat_order, stats))
--                            :done()
--                end,
--                order = 1001,
--                sort_type = 'text',
--            }
--        },
--    }
-- end
 
-- function p.passive_skill_table(frame)
--    -- Get args
--    tpl_args = getArgs(frame, {
--        parentFirst = true
--    })
--    frame = m_util.misc.get_frame(frame)
   
--    tpl_args.ascendancy = m_util.cast.boolean(tpl_args.ascendancy)
   
--    local prepend = {
--        q_join=true,
--    }
   
--    local query = {
--        join='passive_skills._pageID=passive_skill_stats._pageID',
--        limit=5000,
--        groupBy='passive_skills._pageID',
--    }
--    for key, value in pairs(tpl_args) do
--        if string.sub(key, 0, 2) == 'q_' then
--            if prepend[key] then
--                value = ',' .. value
--            end
           
--            query[string.sub(key, 3)] = value
--        end
--    end
   
--    local results = m_cargo.query(
--        {'passive_skills', 'passive_skill_stats'},
--        {
--            'passive_skills._pageName',
--            'passive_skills.main_page',
--            'passive_skills.name',
--            'passive_skills.stat_text',
--            'passive_skills.icon',
--            'passive_skills.is_keystone',
--            'passive_skills.is_notable',
--            'passive_skills.ascendancy_class',
--        },
--        query
--    )
--     result_map = m_cargo.map_results_to_id{
--        results=results,
--        field='passive_skills.name',
--        keep_id_field=true,
--    }
--    for key, rows in pairs(result_map) do
--        result_map[key] = h.sort_by_type(rows)
--    end
   
--    -- header
--    local tbl = mw.html.create('table')
--    tbl:addClass('wikitable')
--    tbl:addClass('sortable')
   
--    local tr = tbl:tag('tr')
--    if tpl_args.ascendancy then
--        tr:tag('th')
--            :wikitext(i18n.passive_table.ascendancy_class)
--    end
   
--    tr
--        :tag('th')
--            :wikitext(i18n.passive_table.name)
--            :done()
--        :tag('th')
--            :wikitext(i18n.passive_table.stats)
--            :done()
   
--    -- rows
--    local used_names = {}
--    for _, passive_row in ipairs(results) do
--        local pn = passive_row['passive_skills.name']
--        if used_names[pn] == nil then
--            local type_results_map = result_map[passive_row['passive_skills.name']]
--            used_names[pn] = true
--            for _, type_key in ipairs(h.type_order) do
--                local type_results = type_results_map[type_key]
--                if #type_results > 0 then
--                    local row = type_results[1]
--                    tr = tbl:tag('tr')
                       
--                    if tpl_args.ascendancy then
--                        if row['passive_skills.ascendancy_class'] then
--                            tr:tag('td')
--                                :wikitext(string.format('[[%s]]<br>[[File:%s avatar.png|link=%s]]', row['passive_skills.ascendancy_class'], row['passive_skills.ascendancy_class'], row['passive_skills.ascendancy_class']))
--                        else
--                            tr:wikitext(m_util.html.td.na{})
--                        end
--                    end
                   
--                    local stats, stat_order = h.make_stat_order(type_results)
--                    tr
--                        :tag('td')
--                            :attr('data-sort-value', row['passive_skills.name'] .. type_key)
--                            :wikitext(string.format('[[%s|%s]]<br>%s', row['passive_skills.main_page'] or row['passive_skills.name'], row['passive_skills.name'], h.format_passive_icon(row, type_key)))
--                            :done()
--                        :tag('td')
--                            :wikitext(h.stat_page_links(stat_order, stats))
--                            :done()
--                end
--            end
--        end
--    end
   
--    return tostring(tbl)
-- end
 
-- ----------------------------------------------------------------------------
-- End
-- ----------------------------------------------------------------------------


return p
return p

Latest revision as of 05:00, 27 June 2022

This is the module sandbox page for Module:Mastery effect (diff).

Module documentation[view] [edit] [history] [purge]


This module is for specifying the mastery effects of one option from a passive mastery

Lua logo

This module depends on the following other modules:


-------------------------------------------------------------------------------
-- 
--                            Module:Mastery effect
-- 
-- This module implements Template:Mastery effect
-------------------------------------------------------------------------------

local m_util = require('Module:Util')
local m_cargo = require('Module:Cargo')

local f_infocard = require('Module:Infocard')._main

-- ----------------------------------------------------------------------------
-- Strings
-- ----------------------------------------------------------------------------

local i18n = {
    cats = {
        effect = 'Mastery Effect',
        data = 'Mastery Effects',
        
        keystone = 'Keystone passive skills',
        notable = 'Notable passive skills',
        basic = 'Basic passive skills',
        ascendancy_notable = 'Ascendancy notable passive skills',
        ascendancy_basic = 'Ascendancy basic passive skills',
    },
    
    mastery_effct_box = {
        title = 'Mastery Effect',
    },
    
    intro = {
        text = "'''%s''' is the internal id for the a [[Passive Mastery|Mastery Effect]]. ",
    },
    
    mastery_effct_box_table = {
        id = 'Id',
        int_id = 'Integer Id',
        flavour_text = 'Flavour Text',
        reminder_text = 'Reminder Text',
        skill_points = 'Skill Points Granted',
        ascendancy_class = 'Ascendancy Class',
        connections = 'Connections',
    },
    
    passive_table = {
        ascendancy_class = 'Ascendancy<br>Class',
        name = 'Name',
        stats = 'Stats',
    },
    
    errors = {
        no_passives_found = 'No passive skills with the given name found',
    },
}

-- ----------------------------------------------------------------------------
-- Cargo
-- ----------------------------------------------------------------------------

local tables = {}

tables.mastery_effects = {
    table = 'mastery_effects',
    order = {'id', 'main_page', 'stat_text', 'stat_text_raw',},
    fields = {
        id = {
            field = 'id',
            type = 'String',
            required = true,
        },
        main_page = {
            field = 'main_page',
            type = 'Page',
        },
        stat_text = {
            field = 'stat_text',
            type = 'Text',
        },
        stat_text_raw = {
            field = 'stat_text',
            type = 'Text',
            func = function (tpl_args, value)
                if tpl_args.stat_text then
                    tpl_args.stat_text_raw = string.gsub(
                        -- [[x]] -> x
                        string.gsub(
                            tpl_args.stat_text, '%[%[([^%]|]+)%]%]', '%1'
                        ), 
                        -- [[x|y]] -> y
                        '%[%[[^|]+|([^%]|]+)%]%]', '%1'
                    )
                end
                return tpl_args.stat_text_raw
            end
        },
    }
}

tables.mastery_effect_stats = {
    table = 'mastery_effect_stats',
    fields = {
        id = {
            field = 'id',
            type = 'String',
        },
        value = {
            field = 'value',
            type = 'Integer',
        },
    }
}

local display = {}
display.map_to_property = {'id'}
display.tbl = {
    {
        key = 'id',
        header = i18n.mastery_effct_box_table.id,
        display = nil,
    },
}

-- ----------------------------------------------------------------------------
-- Helper functions
-- ----------------------------------------------------------------------------

local h = {}

-- function h.format_passive_icon(passive, passive_type)
--     if passive['passive_skills.icon'] == nil then
--         return ''
--     end
    
--     local cls = string.format('passive-icon-type__%s', passive_type)
--     local main_page = passive['passive_skills.main_page'] or passive['main_pages._pageName'] or passive['passive_skills.name'] or passive['passive_skills.icon']
--     div = mw.html.create('div')
--     div:addClass('passive-icon-container')
--     div:addClass(cls)
--     div:tag('div')
--         :addClass('passive-icon-frame')
--         :done()
--     div:wikitext(
--         string.format(
--             '[[%s|link=%s]]', 
--             passive['passive_skills.icon'], 
--             main_page
--         )
--     )
    
--     return tostring(div)
-- end

-- function h.make_stat_order(results)
--     local stats = {}
--     local stat_order = {}
--     for _, row in ipairs(results) do 
--         local stat = row['passive_skills.stat_text']
--         -- Can't show results here that don't have a stat line
--         if stat then
--             if stats[stat] == nil then
--                 stats[stat] = {row}
--                 table.insert(stat_order, stat)
--             else
--                 table.insert(stats[stat], row)
--             end
--         end
--     end
    
--     return stats, stat_order
-- end

-- function h.stat_page_links(stat_order, stats)
--     local out = {}
--     for i, key in ipairs(stat_order) do
--         local links = {}
--         for j, row in ipairs(stats[key]) do
--             links[#links+1] = string.format('[[%s|&#91;%s&#93;]]', row['passive_skills._pageName'], j)
--         end
--         out[i] = string.format('<span class="passive-line">%s <span class="passive-hover">%s</span></span>', key, table.concat(links, ' '))
--     end
    
--     return table.concat(out, '<hr>')
-- end

-- h.type_order = {'basic', 'notable', 'keystone', 'ascendancy_basic', 'ascendancy_notable'}
-- function h.get_type(passive)
--     local key
--     if tonumber(passive['passive_skills.is_keystone']) == 1 then
--         key = 'keystone'
--     elseif tonumber(passive['passive_skills.is_notable']) == 1 then
--         key = 'notable'
--     else
--         key = 'basic'
--     end
    
--     if passive['passive_skills.ascendancy_class'] ~= nil then
--         key = 'ascendancy_' .. key
--     end
    
--     return key
-- end

-- function h.sort_by_type(results)
--     local new = {}
--     for _, key in ipairs(h.type_order) do
--         new[key] = {}
--     end
    
--     for _, passive in ipairs(results) do
--         table.insert(new[h.get_type(passive)], passive)
--     end
    
--     return new
-- end

function h.intro_text(tpl_args)
    --[[
    Display an introductory text about the passive skill.
    ]]
    local out = {}
    if mw.ustring.find(tpl_args['id'], '_') then
        out[#out+1] = mw.getCurrentFrame():expandTemplate{
            title='Incorrect title', 
            args = {title=tpl_args['id']} 
        }
    end
    
    out[#out+1] = string.format(
        i18n.intro.text, 
        tpl_args['id']
    )
    
    return table.concat(out)
end

function h.stat_box(tpl_args)
    --[[
    Display the stat box.
    ]]
    local container = mw.html.create('div')
    container
        :attr('class', 'modbox floatright')
        
    -- stat table 
    local tbl = container:tag('table')
    tbl
        :attr('class', 'wikitable sortable')
        -- :attr('style', 'style="width: 100%;"')
        :tag('tr')
            :tag('th')
                :attr('colspan', 3)
                :wikitext('Stats')
                :done()
            :done()
        :tag('tr')
            :tag('th')
                :wikitext('#')
                :done()
            :tag('th')
                :wikitext('Stat Id')
                :done()
            :tag('th')
                :wikitext('Value')
                :done()
            :done()
            :done()
        :done()
        
    local i = 0
    local value = nil
    repeat
        i = i + 1
        value = {
            id = tpl_args[string.format('stat%s_id', i)],
            value = tpl_args[string.format('stat%s_value', i)],
        }
        
        if value.id then
            tbl
                :tag('tr')
                    :tag('td')
                        :wikitext(i)
                        :done()
                    :tag('td')
                        :wikitext(value.id)
                        :done()
                    :tag('td')
                        :wikitext(value.value)
                        :done()
                    :done()
                :done()
        end
    until value.id == nil
    
    return tostring(container)
end

-- ----------------------------------------------------------------------------
-- Main functions
-- ----------------------------------------------------------------------------

local function _mastery_effect(tpl_args)
    --[[
    Stores data and displays a infobox about the passive skill.
    
    Examples
    --------
    = p.mastery_effect{
        id = 'Resistance6',
        stat1_id = 'base_resist_all_elements_%',
        stat1_value = '12',
        stat2_id = 'base_chaos_damage_resistance_%',
        stat2_value = '7',
        stat_text = '+12% to all Elemental Resistance<br>+7% to Chaos Resistance',
    }
    
    ]]

    -- parse and store mastery effect into cargo table
    m_util.args.from_cargo_map{
        tpl_args=tpl_args,
        table_map=tables.mastery_effects,
    }
    
    -- parse stats and store them into cargo table
    m_util.args.stats(tpl_args, {})
    for _, stat in ipairs(tpl_args.stats) do
        stat._table = tables.mastery_effect_stats.table
        m_cargo.store(stat)
    end
    
    -- Attach to tables
    mw.getCurrentFrame():expandTemplate{title = 'Template:Mastery effect/cargo/mastery effects/attach'}
    mw.getCurrentFrame():expandTemplate{title = 'Template:Mastery effect/cargo/mastery effect stats/attach'}

    --
    -- Infobox
    --
    local passive = {}
    for _, key in ipairs(display.map_to_property) do
        local v = tpl_args[key]
        passive[string.format('%s.%s', tables.mastery_effects.table, tables.mastery_effects.fields[key].field)] = v
    end

    local infocard_args = {}
    infocard_args.header = tpl_args.id
    infocard_args.subheader = i18n.mastery_effct_box['title']
    
    local tbl = mw.html.create('table')
    for _, data in ipairs(display.tbl) do
        local value = tpl_args[data.key]
        -- if default is nil, this will be compared against nil which is what we want, so value ~= nil isn't needed
        if value ~= tables.mastery_effects.fields[data.key].default then
            local dsp
            if data.display then
                dsp = data.display(tpl_args, value)
            else
                dsp = value
            end
            tbl
                :tag('tr')
                    :tag('th')
                        :wikitext(data.header)
                        :done()
                    :tag('td')
                        :attr('class', data.css)
                        :wikitext(dsp)
                        :done()
                    :done()
        end
    end
    
    infocard_args[1] = tostring(tbl)
    infocard_args[2] = tpl_args.stat_text

    local out = {
        f_infocard(infocard_args),
        h.intro_text(tpl_args),
        h.stat_box(tpl_args),
    }
    
    local cats = {
        i18n.cats.data,
    }

    return table.concat(out) .. m_util.misc.add_category(cats)
end

-- ----------------------------------------------------------------------------
-- Exported functions
-- ----------------------------------------------------------------------------

local p = {}

-- Declare cargo tables:
p.table_mastery_effects = m_cargo.declare_factory{data=tables.mastery_effects}
p.table_mastery_effect_stats = m_cargo.declare_factory{data=tables.mastery_effect_stats}

--
-- Template:Mastery effect
-- 
p.mastery_effect = m_util.misc.invoker_factory(_mastery_effect, {
    wrappers = 'Template:Mastery effect',
})

return p