Module:Modifier link

From Path of Exile 2 Wiki
Jump to navigation Jump to search
Module documentation[view] [edit] [history] [purge]


Implements {{modifier link}}.

-------------------------------------------------------------------------------
-- 
--                            Module:Modifier link
-- 
-- This module implements Template:Modifier link
-------------------------------------------------------------------------------

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

local m_game = mw.loadData('Module:Game')

-- Should we use the sandbox version of our submodules?
local use_sandbox = m_util.misc.maybe_sandbox('Modifier link')

-- The cfg table contains all localisable strings and configuration, to make it
-- easier to port this module to another wiki.
local cfg = use_sandbox and mw.loadData('Module:Modifier link/config/sandbox') or mw.loadData('Module:Modifier link/config')

local i18n = cfg.i18n

-- ----------------------------------------------------------------------------
-- Helper functions
-- ----------------------------------------------------------------------------
local h = {}

function h.disambiguate_mod_name(results)
    --[[
        Disambiguates results from a mods query.
    ]]
    local str = {}
    for i,v in pairs(results) do
        str[#str+1] = string.format(
            '%s - %s ([[%s|page]])',
            v['mods.id'] or v['mods._pageName'] or '',
            string.gsub(
                v['mods.stat_text_raw'] or 'N/A',
                '<br>',
                ', '
            ) or '',
            v['mods._pageName'] or ''
        )
    end
    return table.concat(str, '<br>')
end

h.display = {}

function h.display.abbr(args)
    local name = m_util.html.poe_color(
        'mod',
        string.format(
            '[[%s|%s]]',
            args.results_unique[1]['mods._pageName'],
            args.results_unique[1]['mods.name'] 
                or args.results_unique[1]['mods.stat_text_raw'] and string.gsub(
                    args.results_unique[1]['mods.stat_text_raw'],
                    '<br>',
                    ', '
                )
                or args.results_unique[1]['mods.id']
        )
    )
    local tooltip_table = {
        m_util.html.poe_color(
            'mod',
            args.results_unique[1]['mods.name'] or args.results_unique[1]['mods.id']
        ),
        m_util.html.poe_color(
            'help',
            m_game.constants.mod.generation_types[
                tonumber(
                    args.results_unique[1]['mods.generation_type']
                )
            ].short_upper
        ),
        -- m_util.html.poe_color(
            -- 'help',
           -- table.concat(
                -- m_util.string.split(args.results_unique[1]['mods.tags'] or '', ','),
                -- ', '
            -- )
        -- ),
        m_util.html.poe_color(
            'normal',
            args.results_unique[1]['mods.stat_text_raw']
        ),
    }
    local tt_tbl_fltrd = {}
    for _,v in ipairs(tooltip_table) do
        if v ~= nil and v ~= '' then
            tt_tbl_fltrd[#tt_tbl_fltrd+1] = v
        end
    end
    local tooltip = table.concat(tt_tbl_fltrd, '<br>')
    return m_util.html.tooltip(name, tooltip)
end

function h.display.id(args)
    local name = m_util.html.poe_color(
        'mod',
        string.format(
            '[[%s|%s]]',
            args.results_unique[1]['mods._pageName'],
            args.results_unique[1]['mods.id']
        )
    )
    local tooltip_table = {
        m_util.html.poe_color(
            'mod',
            args.results_unique[1]['mods.name'] or args.results_unique[1]['mods.id']
        ),
        m_util.html.poe_color(
            'help',
            m_game.constants.mod.generation_types[
                tonumber(
                    args.results_unique[1]['mods.generation_type']
                )
            ].short_upper
        ),
        m_util.html.poe_color(
            'normal',
            args.results_unique[1]['mods.stat_text_raw']
        ),
    }
    local tt_tbl_fltrd = {}
    for _,v in ipairs(tooltip_table) do
        if v ~= nil and v ~= '' then
            tt_tbl_fltrd[#tt_tbl_fltrd+1] = v
        end
    end
    local tooltip = table.concat(tt_tbl_fltrd, '<br>')
    return m_util.html.tooltip(name, tooltip)
end

function h.display.verbose(args)
    return string.format(
        '%s - %s (%s)',
        m_util.html.poe_color(
            'mod',
            string.format(
                '[[%s|%s]]',
                args.results_unique[1]['mods._pageName'],
                args.results_unique[1]['mods.name'] or args.results_unique[1]['mods.id']
            )
        ),
        m_util.html.poe_color(
            'mod',
            string.gsub(
                args.results_unique[1]['mods.stat_text'],
                '<br>',
                ', '
            )
        ),
        m_game.constants.mod.generation_types[
            tonumber(
                args.results_unique[1]['mods.generation_type']
            )
        ].short_upper
    )
end

function h.display.stat_text(args)
    return m_util.html.poe_color(
        'mod',
        args.results_unique[1]['mods.stat_text']
    )
end

function h.display.stat_max(args)
    local statid = {}
    for _, v in ipairs(args.results[args.results_unique[1]['mods._pageName']]) do
        statid[#statid+1] = v['mod_stats.id']
        if args.statid == v['mod_stats.id'] then
            return v['mod_stats.max']
        end
    end

    if args.statid == nil then
        return m_util.html.error(
            {
                msg = string.format(
                    i18n.errors.undefined_statid,
                    table.concat(statid, ', ')
                )
            }
        )
    end
end

function h.display.stat_min(args)
    local statid = {}
    for _, v in ipairs(args.results[args.results_unique[1]['mods._pageName']]) do
        statid[#statid+1] = v['mod_stats.id']
        if args.statid == v['mod_stats.id'] then
            return v['mod_stats.min']
        end
    end

    if args.statid == nil then
        return m_util.html.error(
            {
                msg = string.format(
                    i18n.errors.undefined_statid,
                    table.concat(statid, ', ')
                )
            }
        )
    end
end

-- ----------------------------------------------------------------------------
-- Main function
-- ----------------------------------------------------------------------------

local function _main(args)
    --[[
    Finds and links to a modifier in formatted form.

    To do list
    ----------
    * Standardize hoverbox so it can be used in multiple places easily
    and make it easy to add rows of data.

    Examples
    --------
    = p.modifier_link{"Tyrannical"}
    = p.modifier_link{"Flaring"}
    = p.modifier_link{"Dictator's"}
    = p.modifier_link{"StrDexMaster%"}
    = p.modifier_link{"LocalIncreasedPhysicalDamagePercentAndAccuracyRating8", display='max', statid='local_physical_damage_+%'}

    ]]
    
    args.modid = args.modid or args.id or args[1] or ''
    args.display = args.display or 'abbr'

    -- Map display argument to function name
    local display = {
        abbr = 'abbr',
        id = 'id',
        verbose = 'verbose',
        stat_text = 'stat_text',
        max = 'stat_max',
        min = 'stat_min',
    }

    if not display[args.display] then
        return m_util.html.error({
            msg = string.format(i18n.errors.invalid_display_option, args.display) .. m_util.misc.add_category({i18n.categories.general_errors})
        })
    end

    -- Query cargo rows:
    args.results = m_cargo.map_results_to_id{
        results=m_cargo.query(
            {'mods', 'mod_stats'},
            {
                'mods.name',
                'mods.stat_text',
                'mods.stat_text_raw',
                'mods.generation_type',
                'mods.tags',
                'mods._pageName',
                'mod_stats.max',
                'mod_stats.min',
                'mods.id',
                'mod_stats.id'
            },
            {
                join = 'mods._pageName=mod_stats._pageName',
                where = string.format(
                    [[
                        (
                            mods.name LIKE "%s" or
                            mods.id LIKE "%s" or
                            mods.stat_text LIKE "%s" or
                            mods.stat_text_raw LIKE "%s"
                        )
                        AND mod_stats.id LIKE "%%%s%%"
                    ]],
                    args.modid,
                    args.modid,
                    args.modid,
                    args.modid,
                    args.statid or '%'
                ),
            }
        ),
        field='mods._pageName',
        keep_id_field=true,
        append_id_field=true,
    }

    -- Get a sorted list that only has unique page names:
    args.results_unique = {{}}
    for i, v in ipairs(args.results) do
        args.results_unique[i] = args.results[v][1]
    end

    -- Helpful error handling:
    local err_tbl = {
        {
            bool = #args.results == 0,
            disp = {
                i18n.errors.no_results,
            }
        },
        {
            bool = #args.results_unique > 1,
            disp = {
                i18n.errors.multiple_results,
                h.disambiguate_mod_name(args.results_unique),
            },
        },
        {
            bool = args.modid ~= args.results_unique[1]['mods.id'],
            disp = {
                string.gsub(
                    i18n.errors.incorrect_modid,
                    '%%s',
                    args.modid,
                    1
                ),
                h.disambiguate_mod_name(args.results_unique),
            },
        },
    }
    for _, v in ipairs(err_tbl) do
        if v.bool then
            return m_util.html.error({
                msg = string.format(v.disp[1], v.disp[2]) .. m_util.misc.add_category({i18n.categories.general_errors})
            })
        end
    end

    return h.display[display[args.display]](args)
end

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

local p = {}

p.main = m_util.misc.invoker_factory(_main, {
    wrappers = cfg.wrappers,
})

p.modifier_link = p.main

return p