Module:Mastery group: Difference between revisions

From Path of Exile Wiki
Jump to navigation Jump to search
(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.)
(Attach)
Line 341: Line 341:
         table_map=tables.mastery_groups,
         table_map=tables.mastery_groups,
     }
     }
    -- Attach to tables
    mw.getCurrentFrame():expandTemplate{title = 'Template:Mastery group/cargo/mastery groups/attach'}
      
      
     --
     --

Revision as of 16:29, 27 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,
    }

    -- Attach to tables
    mw.getCurrentFrame():expandTemplate{title = 'Template:Mastery group/cargo/mastery groups/attach'}
    
    --
    -- 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