Модуль:Passive skill table

Материал из Path of Exile Wiki
Перейти к: навигация, поиск
Документация модуля[создать]
--
-- Module for passive skill table
--

local m_util = require('Module:Util')
local m_cargo = require('Module:Cargo')
local getArgs = require('Module:Arguments').getArgs
local f_passive_skill_link = require('Module:passive_skill_link').passive_skill_link

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

local i18n = {
    icon_name = 'File:%s passive skill icon.png',

    cats = {
        data = 'Данные пассивных умений',

        keystone = 'Ключевые пассивные умения',
        notable = 'Значимые пассивные умения',
        basic = 'Базовые пассивные умения',
        ascendancy_notable = 'Значимые пассивные умения Восхождения',
        ascendancy_basic = 'Базовые пассивные умения Восхождения',
    },

    passive_table = {
        ascendancy_class = 'Класс<br>Восхождения',
        name = 'Название',
        id = 'Id',
        int_id = 'Integer id',
        stats = 'Свойства',
        skill_points = 'Skill points',
        connections = 'Соединения',
        flavour_text = 'Сопроводительный текст',
        reminder_text = 'Reminder text',
        is_notable = 'Значимое',
        is_keystone = 'Ключевое',
    },

    errors = {
        invalid_args = 'Passive skill table: необходимо указать q_where',
        no_passives_found = 'Пассивных умений с таким названием не найдено',
        cats = 'Страницы со сломанными таблицами пассивных умений',
    },
}


-- ----------------------------------------------------------------------------
-- Constants & Data
-- ----------------------------------------------------------------------------

-- local c = {}

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

local h = {}

function h.make_order(results, field, args)
    --[[
    Merge duplicates and then create a ordered list.
    ]]
    local values = {}
    local order = {}
    for _, row in ipairs(results) do
        local val = row[field]
        if args.fmt then
            val = args.fmt(row[field])
        end
        -- Can't show results here that don't have a value:
        if val then
            if values[val] == nil then
                values[val] = {row}
                table.insert(order, val)
            else
                table.insert(values[val], row)
            end
        end
    end

    return values, order
end

function h.data_page_links(values, order)
    local out = {}
    for i, key in ipairs(order) do
        local links = {}
        for j, row in ipairs(values[key]) do
            links[#links+1] = string.format(
                '[[%s|&#91;%s&#93;]]',
                row['passive_skills._pageName'],
                j + (i-1) * #values[key]
            )
        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.get_type(passive)
    --[[
    Determine what type of passive skill this passive is.
    ]]
    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.na_or_val(tr, value, func, args)
    --[[

    Parameters
    ----------
    tr :

    value :

    func : function

    args : list of
        Valid keys are:
        * colour

    ]]
    local args = args or {}
    if value == nil or value == '' then
        tr:wikitext(m_util.html.td.na())
    else
        local raw_value = value
        if func ~= nil then
            value = func(value)
        end

        local td = tr:tag('td')
        td:attr('data-sort-value', raw_value)
        td:wikitext(value)
        if args.colour then
            td:attr('class', 'tc -' .. args.colour)
        end
    end
end

-- Format style for field:
h.fmt = {}
function h.fmt.link(field)
    local fields = m_util.string.split(field, ',')
    for i, v in ipairs(fields) do
        fields[i] = string.format('[[%s]]', v)
    end
    return table.concat(fields, ', ')
end
function h.fmt.passive_skill_link(field)
    local fields = m_util.string.split(field, ',')
    for i, v in ipairs(fields) do
        fields[i] = f_passive_skill_link{id=v}
    end
    return table.concat(fields, ', ')
end
function h.fmt.boolean(field)
    local fields = m_util.string.split(field, ',')
    for i, v in ipairs(fields) do
        if m_util.cast.boolean(v) then
            fields[i] = '<div class="table-yes" data-sort-value=1><span>&#x2713;</span></div>'
        else
            fields[i] = '<div class="table-no" data-sort-value=0><span>&#x2717;</span></div>'
        end
    end
    return table.concat(fields, ', ')
end
function h.fmt.link_passive(field)
    --[[
    Create a link to the passive skill data page from the ID.
    ]]
    local fields = m_util.string.split(field, ',')
    for i, v in ipairs(fields) do
        fields[i] = string.format(
            '[[Passive Skill:%s|%s]]',
            string.gsub(v, '_', '~'),
            v
        )
    end
    return table.concat(fields, ', ')
end

-- Display
h.tbl = {}
h.tbl.display = {}

h.tbl.display.factory = {}
function h.tbl.display.factory.merged_values(args)
    local args = args or {}
    return function (tpl_args, frame, tr, rows, rowinfo)
        local values, order = h.make_order(rows, args.field, args)
        local value = h.data_page_links(values, order)
        h.na_or_val(tr, value, func, args)
    end
end

-- ----------------------------------------------------------------------------
-- Data mappings
-- ----------------------------------------------------------------------------

data = {}
data.passive_skill_table = {
    tables = {
        passive_skill_stats = {
            join='passive_skills._pageID=passive_skill_stats._pageID',
        },
        main_pages = {
            join='passive_skills.id=main_pages.id'
        }
    },
    -- Display data
    {
        args = nil,
        header = i18n.passive_table.name,
        fields = {
            -- Optional:
            'passive_skills.is_keystone',
            'passive_skills.is_notable',
            'passive_skills.ascendancy_class',
            'passive_skills.main_page',
            'main_pages._pageName',
            -- 'passive_skills.html',

            -- Required:
            'passive_skills._pageName',
            'passive_skills.name',
            'passive_skills.icon',
        },
        display = function (tpl_args, frame, tr, data)
            local passive = data[1]

            local psl_args = {
                skip_query = true,
                page = passive['passive_skills.main_page']
                    or passive['main_pages._pageName']
                    or passive['passive_skills.name']
                    or passive['passive_skills._pageName'],
                name = passive['passive_skills.name'],
                icon = passive['passive_skills.icon'],
                is_keystone = passive['passive_skills.is_keystone'],
                is_notable = passive['passive_skills.is_notable'],
                ascendancy_class = passive['passive_skills.ascendancy_class'],
            }
            if tpl_args.no_html == nil then
                psl_args.html = passive['passive_skills.html']
            end
            if tpl_args.large then
                psl_args.large = tpl_args.large
            end

            tr
                :tag('td')
                    :attr(
                        'data-sort-value',
                        passive['passive_skills.name'] .. h.get_type(passive)
                    )
                    :attr('style', 'text-align:center;')
                    :wikitext(f_passive_skill_link(psl_args))
                    :done()

        end,
        order = 1000,
        sort_type = 'text',
        options = {
            [1] = {optional=true},
            [2] = {optional=true},
            [3] = {optional=true},
            [4] = {optional=true},
            [5] = {optional=true},
        },
    },
    {
        args = {'ascendancy'},
        header = i18n.passive_table.ascendancy_class,
        fields = {'passive_skills.ascendancy_class'},
        display = function (tpl_args, frame, tr, data)
            local passive = data[1]
            h.na_or_val(tr, passive['passive_skills.ascendancy_class'],
                function ()
                    return 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']
                    )
                end
            )
        end,
        order = 0,
        sort_type = 'text',
    },
    {
        args = 'id',
        header = i18n.passive_table.id,
        fields = {'passive_skills.id'},
        display = h.tbl.display.factory.merged_values{field='passive_skills.id'},
        order = 1001,
        sort_type = 'text',
    },
    {
        args = 'int_id',
        header = i18n.passive_table.int_id,
        fields = {'passive_skills.int_id'},
        display = h.tbl.display.factory.merged_values{field='passive_skills.int_id'},
        order = 1002,
        sort_type = 'text',
    },
    {
        args = {'stat', 'stats', 'stat_text'},
        header = i18n.passive_table.stats,
        fields = {'passive_skills.stat_text'},
        display = h.tbl.display.factory.merged_values{field='passive_skills.stat_text', colour='mod'},
        order = 2000,
        sort_type = 'text',
    },
    {
        args = 'skill_points',
        header = i18n.passive_table.skill_points,
        fields = {'passive_skills.skill_points'},
        display = h.tbl.display.factory.merged_values{field='passive_skills.skill_points'},
        order = 2001,
        sort_type = 'text',
    },
    {
        args = 'connections',
        header = i18n.passive_table.connections,
        fields = {'passive_skills.connections'},
        display = h.tbl.display.factory.merged_values{
            field='passive_skills.connections',
            fmt=h.fmt.passive_skill_link,
        },
        order = 3000,
        sort_type = 'text',
    },
    {
        args = 'flavour_text',
        header = i18n.passive_table.flavour_text,
        fields = {'passive_skills.flavour_text'},
        display = h.tbl.display.factory.merged_values{
            field='passive_skills.flavour_text',
            colour='flavour',
        },
        order = 3001,
        sort_type = 'text',
    },
    {
        args = 'reminder_text',
        header = i18n.passive_table.reminder_text,
        fields = {'passive_skills.reminder_text'},
        display = h.tbl.display.factory.merged_values{
            field='passive_skills.reminder_text',
            colour='help',
        },
        order = 3002,
        sort_type = 'text',
    },
    {
        args = 'is_notable',
        header = i18n.passive_table.is_notable,
        fields = {'passive_skills.is_notable'},
        display = h.tbl.display.factory.merged_values{
            field='passive_skills.is_notable',
            fmt=h.fmt.boolean
        },
        order = 4000,
        sort_type = 'number',
    },
    {
        args = 'is_keystone',
        header = i18n.passive_table.is_keystone,
        fields = {'passive_skills.is_keystone'},
        display = h.tbl.display.factory.merged_values{
            field='passive_skills.is_keystone',
            fmt=h.fmt.boolean
        },
        order = 4001,
        sort_type = 'number',
    },
}

-- ----------------------------------------------------------------------------
-- Page functions
-- ----------------------------------------------------------------------------

local p = {}

function p.passive_skill_table(frame)
    --[[
    Displays a table of passive skills.

    TODO: Why is the groupBy necessary?

    Examples
    --------
    = p.passive_skill_table{
        q_where = 'passive_skills.ascendancy_class = "Gladiator"',
        large=1,
    }
    = p.passive_skill_table{
        q_where='passive_skills.stat_text LIKE "%damage%taken%as%"',
        ascendancy=1,
        stat_text=1,
    }

    ]]
    local t = os.clock()

    -- Get args
    local tpl_args = getArgs(frame, {
        parentFirst = true
    })
    frame = m_util.misc.get_frame(frame)

    -- Check if the correct parameters have been set:
    if tpl_args.q_where == nil then
        return m_util.html.error{msg=i18n.errors.invalid_args .. m_util.misc.add_category(i18n.errors.cats)}
    end

    -- Cargo query settings:
    tpl_args.q_groupBy = tpl_args.q_groupBy or 'passive_skills._pageID'
    tpl_args.q_orderBy = tpl_args.q_orderBy or [[
        passive_skills.ascendancy_class IS NULL DESC,
        passive_skills.is_keystone,
        passive_skills.is_notable,
        passive_skills.name
    ]]

    -- Run the query and display the results:
    local out = m_cargo.table_query{
        tpl_args=tpl_args,
        frame=frame,
        main_table='passive_skills',
        row_unique_fields={'passive_skills.name'},
        data=data.passive_skill_table,
        empty_cell=m_util.html.td.na()
    }

    mw.logObject({os.clock() - t, tpl_args})

    return out
end


-- ----------------------------------------------------------------------------
-- End
-- ----------------------------------------------------------------------------

return p