Module:Modifier link

From Path of Exile 2 Wiki
Revision as of 04:05, 18 October 2021 by Angelic knight (talk | contribs)
Jump to navigation Jump to search
Module documentation[view] [edit] [history] [purge]


Implements {{modifier link}}.

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

local getArgs -- Lazy load require('Module:Arguments').getArgs
local m_util = require('Module:Util')
local m_cargo = require('Module:Cargo')

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

-- The cfg table contains all localisable strings and configuration, to make it
-- easier to port this module to another wiki.
local cfg = 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 unique_mods_stat_text = nil
	if(args.results_unique[1]['mods.stat_text_raw'] ~= nil) then
		unique_mods_stat_text = string.gsub(
            args.results_unique[1]['mods.stat_text_raw'],
            '<br>',
            ', '
        )
	end
    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 unique_mods_stat_text 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']
                )
            ].full
        ),
        -- 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']
                )
            ].full
        ),
        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']
            )
        ].full
    )
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', 'spawn_weights'},
            {
                'mods.name',
                'mods.stat_text',
                'mods.stat_text_raw',
                'mods.generation_type',
                'mods.tags',
                'mods._pageName',
                'mod_stats.max',
                'mod_stats.min',
                'spawn_weights.tag',
                'spawn_weights.weight',
                'mods.id',
                'mod_stats.id'
            },
            {
                join = [[
                    mods._pageName=mod_stats._pageName,
                    mods._pageName=spawn_weights._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 '%'
                ),
                -- groupBy = 'mods._pageID, mod_stats.id, spawn_weights.tag',
            }
        ),
        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 = {}

function p.main(frame)
    local args
    if type(frame.args) == 'table' then
        -- Called via #invoke, so use getArgs().
        getArgs = require('Module:Arguments').getArgs
        args = getArgs(frame, {
            parentFirst = true
        })
    else
        -- Called from another module or from the debug console, so assume args 
        -- are passed in directly.
        args = frame
    end
    return _main(args)
end

p.modifier_link = p.main

return p