Module:Mastery group: Difference between revisions

From Path of Exile Wiki
Jump to navigation Jump to search
No edit summary
(Removed some unused code. To maintain better code encapsulation, do not export helper functions. Use invoker factory from Module:Util. Passing the rarely used frame object around the entire codebase through function parameters is a code smell. Testing shows that it doesn't significantly impact execution time to simply call mw.getCurrentFrame() as needed.)
Line 1: Line 1:
--
-------------------------------------------------------------------------------
-- Module for Mastery Groups
--  
--
--                            Module:Mastery group
--
-- This module implements Template:Mastery group
-------------------------------------------------------------------------------


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 82: Line 83:
             field = 'icon',
             field = 'icon',
             type = 'Page',
             type = 'Page',
             func = function(tpl_args, frame, value)
             func = function(tpl_args, value)
                 if value then
                 if value then
                     return string.format(i18n.icon_name, value)
                     return string.format(i18n.icon_name, value)
Line 102: Line 103:
         key = 'mastery_effects',
         key = 'mastery_effects',
         header = nil,
         header = nil,
         display = function (tpl_args, frame, value)
         display = function (tpl_args, value)
             local results = m_cargo.map_results_to_id{
             local results = m_cargo.map_results_to_id{
                 field='mastery_effects.id',
                 field='mastery_effects.id',
Line 234: Line 235:
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 240: Line 241:
     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 254: Line 255:
end
end


-- function h.stat_box(tpl_args, frame)
-- function h.stat_box(tpl_args)
--    --[[
--    --[[
--    Display the stat box.
--    Display the stat box.
Line 315: Line 316:
--    return tostring(container)
--    return tostring(container)
-- end
-- end


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


local p = {}
local function _mastery_group(tpl_args)
 
-- This way the helper functions can be used in other modules
p.h = h
 
-- Declare cargo tables:
p.table_mastery_groups = m_cargo.declare_factory{data=tables.mastery_groups}
 
function p.mastery_group(frame)
     --[[
     --[[
     Stores data and displays a infobox about the passive skill.
     Stores data and displays a infobox about the passive skill.
Line 343: Line 335:
      
      
     ]]
     ]]
    -- Get args
    local tpl_args = getArgs(frame, {
        parentFirst = true
    })
    frame = m_util.misc.get_frame(frame)


     -- parse and store mastery group into cargo table
     -- parse and store mastery group 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_groups,
         table_map=tables.mastery_groups,
     }
     }
Line 383: Line 368:
             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 407: Line 392:
     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 419: Line 404:
end
end


function p.mastery_group_box(frame)
local function _mastery_group_box(tpl_args)
     --[[
     --[[
     Queries a mastery group and displays it.
     Queries a mastery group and displays it.
Line 428: Line 413:
      
      
     ]]
     ]]
   
    -- Get args
    local tpl_args = getArgs(frame, {
        parentFirst = true
    })
    frame = m_util.misc.get_frame(frame)
      
      
     tpl_args.name = tpl_args.name or tpl_args[1]
     tpl_args.name = tpl_args.name or tpl_args[1]
Line 480: Line 459:
         for _, v in ipairs(results) do
         for _, v in ipairs(results) do
             m_cargo.store(
             m_cargo.store(
                frame,
                 {
                 {
                     _table='main_pages',  
                     _table='main_pages',  
Line 496: Line 474:
end
end


-- function p.passive_skill_link(frame)
-- ----------------------------------------------------------------------------
--     --[[
-- Exported functions
--     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_mastery_icon(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
local p = {}


-- function p.passive_skill_table2(frame)
-- Declare cargo tables:
--    -- Get args
p.table_mastery_groups = m_cargo.declare_factory{data=tables.mastery_groups}
--    tpl_args = getArgs(frame, {
--        parentFirst = true
--    })
--    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_mastery_icon(passive))
--                            :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
-- Template:Mastery group
--     tpl_args = getArgs(frame, {
--  
--        parentFirst = true
p.mastery_group = m_util.misc.invoker_factory(_mastery_group, {
--    })
     wrappers = 'Template:Mastery group',
--    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_mastery_icon(row)))
--                            :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

Revision as of 19:53, 13 June 2022

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


Lua logo

This module depends on the following other modules:

This module is for specifying one passive mastery. Implements {{mastery group}}.

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

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

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

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

local i18n = {
    icon_name = 'File:%s mastery icon.png',
    cats = {
        effect = 'Mastery Group',
        data = 'Mastery Groups',
        
        keystone = 'Keystone passive skills',
        notable = 'Notable passive skills',
        basic = 'Basic passive skills',
        ascendancy_notable = 'Ascendancy notable passive skills',
        ascendancy_basic = 'Ascendancy basic passive skills',
    },
    
    passive_box = {
        keystone = 'Keystone',
        notable = 'Notable Passive Skill',
        basic = 'Passive Skill',
        ascendancy_notable = 'Ascendancy Notable Passive Skill',
        ascendancy_basic = 'Ascendancy Passive Skill',
    },
    
    intro = {
        text = "Bonuses from the '''%s''' can be allocated for one passive point after allocating a [[Passive_skill#Notable_passives|notable passive skill]] within an applicable cluster. ",
    },
    
    mastery_group_box_table = {
        header = '%s Mastery',
        id = 'Id',
        mastery_effects = 'Mastery Effects',
    },
    
    passive_table = {
        ascendancy_class = 'Ascendancy<br>Class',
        name = 'Name',
        stats = 'Stats',
    },
    
    errors = {
        no_passives_found = 'No mastery groups with the given name were found',
    },
}

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

local tables = {}

tables.mastery_groups = {
    table = 'mastery_groups',
    order = {'id', 'name', 'main_page', 'icon', 'mastery_effects',},
    fields = {
        id = {
            field = 'id',
            type = 'String',
            required = true,
        },
        name = {
            field = 'name',
            type = 'String',
        },
        main_page = {
            field = 'main_page',
            type = 'Page',
        },
        icon = {
            field = 'icon',
            type = 'Page',
            func = function(tpl_args, value)
                if value then
                    return string.format(i18n.icon_name, value)
                end
            end
        },
        mastery_effects = {
            field = 'mastery_effects',
            type = 'List (,) of String',
        },
    }
}


local display = {}
display.map_to_property = {'icon', 'mastery_effects'}
display.tbl = {
    {
        key = 'mastery_effects',
        header = nil,
        display = function (tpl_args, value)
            local results = m_cargo.map_results_to_id{
                field='mastery_effects.id',
                results=m_cargo.array_query{
                    tables={'mastery_effects'},
                    fields={'mastery_effects.id', 'mastery_effects._pageName', 'mastery_effects.stat_text'},
                    id_array=value,
                    id_field='mastery_effects.id',
                    ignore_missing=true,
                }
            }
            
            local ul = mw.html.create('ul')
            for _, key in ipairs(value) do
                local row = results[key]
                if row then
                    row = row[1]
                end
                local text
                if row then
                    text = string.format('[[%s|%s]]', row['mastery_effects._pageName'], row['mastery_effects.stat_text'] or row['mastery_effects.id'] or row['mastery_effects._pageName'])
                else
                    text = key
                end
                ul
                    :tag('li')
                        :wikitext(text)
                        :done()
            end
            
            return tostring(ul)
        end,
    },
}

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

local h = {}

function h.format_mastery_icon(mastery_group)
    if mastery_group['mastery_groups.icon'] == nil then
        return ''
    end
    
    local cls = 'passive-icon-type__mastery'
    local main_page = mastery_group['mastery_groups.main_page'] or mastery_group['main_pages._pageName'] or mastery_group['mastery_groups.name'] or mastery_group['mastery_groups.icon']
    local 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]]', 
            mastery_group['mastery_groups.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

-------------------------------------
-- Parameters:
--   results: the set of mastery_groups matching the query
-------------------------------------
function h.make_effects_order(results)
    local mastery_effects_list = {}
    local me_order = {}
    for _, row in ipairs(results) do 
        local mastery_effects = row['mastery_groups.mastery_effects']
        -- Can't show results here that don't have a stat line
        if mastery_effects then
            if mastery_effects_list[mastery_effects] == nil then
                mastery_effects_list[mastery_effects] = {row}
                table.insert(me_order, mastery_effects)
            else
                table.insert(mastery_effects_list[mastery_effects], row)
            end
        end
    end
    
    return mastery_effects_list, me_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

function h.effect_page_links(effects_order, effects_list)
    local out = {}
    for i, key in ipairs(effects_order) do
        local links = {}
        for j, row in ipairs(effects_list[key]) do
            links[#links+1] = string.format('[[%s|&#91;%s&#93;]]', row['mastery_groups._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

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['name']
    )
    
    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 
--     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_group(tpl_args)
    --[[
    Stores data and displays a infobox about the passive skill.
    
    Examples
    --------
    = p.mastery_group{
        id = 'Armour',
        name = 'Armour Mastery'
        mastery_effects = 'Armour1,Armour2,Armour3,Armour4,Armour5,Armour6',
        icon = 'PassiveMasteryArmourActive'
    }
    
    ]]

    -- parse and store mastery group into cargo table
    m_util.args.from_cargo_map{
        tpl_args=tpl_args,
        table_map=tables.mastery_groups,
    }
    
    --
    -- Infobox
    --
    local mastery = {}
    for _, key in ipairs(display.map_to_property) do
        local v = tpl_args[key]
        if type(v) == 'boolean' then
            if v then
                v = 1
            else
                v = 0
            end
        end
        mastery[string.format('%s.%s', tables.mastery_groups.table, tables.mastery_groups.fields[key].field)] = v
    end
    
    local infocard_args = {}
    infocard_args.header = tpl_args.name
    
    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_groups.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] = h.format_mastery_icon(mastery)
    infocard_args.class = 'mastery_infocard'
    --infocard_args[3] = tpl_args.stat_text

    local out = {
        f_infocard(infocard_args),
        h.intro_text(tpl_args),
        --h.stat_box(tpl_args),
    }
    
    --mw.logObject(out)
    
    local cats = {
        i18n.cats.data,
    }
    return table.concat(out) .. m_util.misc.add_category(cats)
end

local function _mastery_group_box(tpl_args)
    --[[
    Queries a mastery group and displays it.
    
    Examples
    --------
    = p.mastery_group_box{name='Accuracy'}
    
    ]]
    
    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('mastery_groups.id="%s" AND mastery_groups.mastery_effects > ""', 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(
        {'mastery_groups'},
        {
            'mastery_groups.icon',
            'mastery_groups.mastery_effects',
            'mastery_groups.id'
        }, 
        {
            where=tpl_args.q_where,
            orderBy='mastery_groups.id',
            limit=5000,
        }
    )
    if #results == 0 then
        error(i18n.errors.no_passives_found)
    end
    
    local out = {}
    local cats = {}
    if #results > 0 then
        cats[#cats+1] = i18n.cats[type_key]
        local effects_list, effects_order = h.make_effects_order(results)
        
        local mastery_group = results[1]
        
        local infocard_args = {}
        infocard_args.header = mastery_group['mastery_groups.id']
        
        infocard_args[1] = h.format_mastery_icon(passive)
        infocard_args[2] = h.effect_page_links(effects_order, effects_list)
        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(results) do
            m_cargo.store(
                {
                    _table='main_pages', 
                    id=v['mastery_groups.id'],
                }
            )
        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

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

local p = {}

-- Declare cargo tables:
p.table_mastery_groups = m_cargo.declare_factory{data=tables.mastery_groups}

--
-- Template:Mastery group
-- 
p.mastery_group = m_util.misc.invoker_factory(_mastery_group, {
    wrappers = 'Template:Mastery group',
})

return p