Path of Exile Wiki

Wiki поддерживается сообществом, поэтому подумайте над тем, чтобы внести свой вклад.

ПОДРОБНЕЕ

Path of Exile Wiki
(Отмена правки 231293, сделанной Ruba159753 (обсуждение))
Нет описания правки
Строка 23: Строка 23:
 
notable = 'Значимые пассивные умения',
 
notable = 'Значимые пассивные умения',
 
basic = 'Базовые пассивные умения',
 
basic = 'Базовые пассивные умения',
ascendancy_notable = 'Базовые пассивные умения Восхождения',
+
ascendancy_notable = 'Значимые пассивные умения Восхождения',
ascendancy_basic = 'Значимые пассивные умения Восхождения',
+
ascendancy_basic = 'Базовые пассивные умения Восхождения',
 
},
 
},
 
 
Строка 31: Строка 31:
 
notable = 'Значимое пассивное умение',
 
notable = 'Значимое пассивное умение',
 
basic = 'Базовое пассивное умение',
 
basic = 'Базовое пассивное умение',
ascendancy_notable = 'Базовое пассивное умение Восхождения',
+
ascendancy_notable = 'Значимое пассивное умение Восхождения',
ascendancy_basic = 'Значимое пассивное умение Восхождения',
+
ascendancy_basic = 'Базовое пассивное умение Восхождения',
 
},
 
},
 
 

Версия от 18:03, 26 сентября 2018

Template info icon Документация модуля[просмотр] [править] [история] [очистить]

--
-- Module for bestiary templates
--

local m_util = require('Module:Util')
local m_cargo = require('Module:Cargo')
local getArgs = require('Module:Arguments').getArgs
local f_infocard = require('Module:Infocard')._main

local p = {}

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

local i18n = {
    icon_name = 'File:%s passive skill icon.png',
    
    cats = {
        data = 'Данные пассивных умений',
        
        keystone = 'Ключевые пассивные умения',
        notable = 'Значимые пассивные умения',
        basic = 'Базовые пассивные умения',
        ascendancy_notable = 'Значимые пассивные умения Восхождения',
        ascendancy_basic = 'Базовые пассивные умения Восхождения',
    },
    
    passive_box = {
        keystone = 'Ключевое пассивное умение',
        notable = 'Значимое пассивное умение',
        basic = 'Базовое пассивное умение',
        ascendancy_notable = 'Значимое пассивное умение Восхождения',
        ascendancy_basic = 'Базовое пассивное умение Восхождения',
    },
    
    passive_box_table = {
        id = 'Id',
        int_id = 'Integer Id',
        flavour_text = 'Flavour Text',
        reminder_text = 'Reminder Text',
        skill_points = 'Skill Points Granted',
        ascendancy_class = 'Класс Восхождения',
        connections = 'Connections',
    },
    
    passive_table = {
        ascendancy_class = 'Класс<br>Восхождения',
        name = 'Name',
        stats = 'Stats',
    },
    
    errors = {
        no_passives_found = 'No passive skills with the given name found',
    },
}

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

local tables = {}

tables.passive_skills = {
    table = 'passive_skills',
    order = {'id', 'int_id', 'name', 'main_page', 'flavour_text', 'reminder_text', 'buff_id', 'skill_points', 'icon', 'ascendancy_class', 'is_keystone', 'is_notable', 'is_multiple_choice_option', 'is_multiple_choice', 'is_icon_only', 'is_jewel_socket', 'is_ascendancy_starting_node', 'stat_text', 'stat_text_raw', 'connections',},
    fields = {
        id = {
            field = 'id',
            type = 'String(unique)',
            required = true,
        },
        int_id = {
            field = 'int_id',
            type = 'Integer(unique)',
            required = true,
        },
        name = {
            field = 'name',
            type = 'String',
        },
        main_page = {
            field = 'main_page',
            type = 'Page',
        },
        flavour_text = {
            field = 'flavour_text',
            type = 'Text',
        },
        reminder_text = {
            field = 'id',
            type = 'Text',
        },
        buff_id = {
            field = 'id',
            type = 'String',
        },
        -- TODO: Other buff stuff 
        skill_points = {
            field = 'skill_points',
            type = 'Integer',
            default = 0,
        },
        icon = {
            field = 'icon',
            type = 'Page',
            func = function(tpl_args, frame, value)
                if value then
                    return string.format(i18n.icon_name, value)
                end
            end
        },
        ascendancy_class = {
            field = 'ascendancy_class',
            type = 'String',
        },
        is_keystone = {
            field = 'is_keystone',
            type = 'Boolean',
            default = false,
        },
        is_notable = {
            field = 'is_notable',
            type = 'Boolean',
            default = false,
        },
        is_multiple_choice_option = {
            field = 'is_multiple_choice_option',
            type = 'Boolean',
            default = false,
        },
        is_multiple_choice = {
            field = 'is_multiple_choice',
            type = 'Boolean',
            default = false,
        },
        is_icon_only = {
            field = 'is_icon_only',
            type = 'Boolean',
            default = false,
        },
        is_jewel_socket = {
            field = 'is_jewel_socket',
            type = 'Boolean',
            default = false,
        },
        is_ascendancy_starting_node = {
            field = 'is_ascendancy_starting_node',
            type = 'Boolean',
            default = false,
        },
        stat_text = {
            field = 'stat_text',
            type = 'Text',
        },
        stat_text_raw = {
            field = 'stat_text',
            type = 'Text',
            func = function (tpl_args, frame)
                if tpl_args.stat_text then
                    tpl_args.stat_text_raw = string.gsub(
                        -- [[x]] -> x
                        string.gsub(
                            tpl_args.stat_text, '%[%[([^%]|]+)%]%]', '%1'
                        ), 
                        -- [[x|y]] -> y
                        '%[%[[^|]+|([^%]|]+)%]%]', '%1'
                    )
                end
                return tpl_args.stat_text_raw
            end
        },
        -- from the graph file:
        connections = {
            field = 'connections',
            type = 'List (,) of String',
        },
    }
}

tables.passive_skill_stats = {
    table = 'passive_skill_stats',
    fields = {
        id = {
            field = 'id',
            type = 'String',
        },
        value = {
            field = 'value',
            type = 'Integer',
        },
    }
}

local display = {}
display.map_to_property = {'icon', 'is_keystone', 'is_notable', 'ascendancy_class'}
display.tbl = {
    {
        key = 'id',
        header = i18n.passive_box_table.id,
        display = nil,
    },
    {
        key = 'int_id',
        header = i18n.passive_box_table.int_id,
        display = nil,
    },
    {
        css = 'tc -flavour',
        key = 'flavour_text',
        header = i18n.passive_box_table.flavour_text,
        display = nil,
    },
    {
        key = 'reminder_text',
        header = i18n.passive_box_table.reminder_text,
        display = nil,
    },
    {
        key = 'skill_points',
        header = i18n.passive_box_table.skill_points,
        display = nil,
    },
    {
        key = 'ascendancy_class',
        header = i18n.passive_box_table.ascendancy_class,
        display = function (tpl_args, frame, value)
            return string.format('[[%s]]', value)
        end,
    },
    {
        key = 'connections',
        header = i18n.passive_box_table.connections,
        display = function (tpl_args, frame, value)
            local results = m_util.cargo.map_results_to_id{
                field='passive_skills.id',
                results=m_util.cargo.array_query{
                    tables={'passive_skills'},
                    fields={'passive_skills.name', 'passive_skills._pageName'},
                    id_array=value,
                    id_field='passive_skills.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['passive_skills._pageName'], row['passive_skills.name'] or row['passive_skills._pageName'])
                else
                    text = key
                end
                ul
                    :tag('li')
                        :wikitext(text)
                        :done()
            end
            
            return tostring(ul)
        end,
    },
}

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

local h = {}

function h.format_passive_icon(passive, passive_type)
    if passive['passive_skills.icon'] == nil then
        return ''
    end
    
    local cls = string.format('passive-icon-type__%s', passive_type)
    
    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]]', passive['passive_skills.icon'], passive['passive_skills.name'] or passive['passive_skills.icon']))
    
    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

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

h.type_order = {'basic', 'notable', 'keystone', 'ascendancy_basic', 'ascendancy_notable'}
function h.get_type(passive)
    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.sort_by_type(results)
    local new = {}
    for _, key in ipairs(h.type_order) do
        new[key] = {}
    end
    
    for _, passive in ipairs(results) do
        table.insert(new[h.get_type(passive)], passive)
    end
    
    return new
end
-- ----------------------------------------------------------------------------
-- Page functions
-- ----------------------------------------------------------------------------

local p = {}

p.table_passive_skills = m_util.cargo.declare_factory{data=tables.passive_skills}
p.table_passive_skill_stats = m_util.cargo.declare_factory{data=tables.passive_skill_stats}

function p.passive_skill(frame)
    -- Get args
    tpl_args = getArgs(frame, {
        parentFirst = true
    })
    frame = m_util.misc.get_frame(frame)
    -- parse 
    m_util.args.from_cargo_map{
        tpl_args=tpl_args,
        frame=frame,
        table_map=tables.passive_skills,
    }
    
    -- parse stats
    m_util.args.stats(tpl_args, {})
    for _, stat in ipairs(tpl_args.stats) do
        stat._table = tables.passive_skill_stats.table
        m_util.cargo.store(frame, stat)
    end
    
    --
    -- Infobox
    --
    local passive = {}
    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
        passive[string.format('%s.%s', tables.passive_skills.table, tables.passive_skills.fields[key].field)] = v
    end
    
    local type_key = h.get_type(passive)
    
    local infocard_args = {}
    infocard_args.header = tpl_args.name
    infocard_args.subheader = i18n.passive_box[type_key]
    
    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.passive_skills.fields[data.key].default then
            local dsp
            if data.display then
                dsp = data.display(tpl_args, frame, 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] = tpl_args.stat_text
    infocard_args[3] = h.format_passive_icon(passive, type_key)
    
    --
    --
    --
    
    cats = {
        i18n.cats.data,
    }
    
    return f_infocard(infocard_args) .. m_util.misc.add_category(cats)
end

function p.passive_skill_box(frame)
    -- 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 not tpl_args.q_where and tpl_args.name then
        tpl_args.q_where = string.format('passive_skills.name="%s" AND passive_skills.stat_text IS NOT NULL', 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_util.cargo.query(
        {'passive_skills'},
        {
            'passive_skills._pageName', 
            'passive_skills.name', 
            'passive_skills.stat_text',
            -- TODO: only really need these once, maybe put in extra query
            'passive_skills.flavour_text',
            'passive_skills.icon',
            'passive_skills.is_keystone',
            'passive_skills.is_notable',
            'passive_skills.ascendancy_class',
        }, 
        {
            where=tpl_args.q_where,
            orderBy='passive_skills.stat_text',
            limit=5000,
        }
    )
    if #results == 0 then
        error(i18n.errors.no_passives_found)
    end
    
    results = h.sort_by_type(results)
    local out = {}
    local cats = {}
    for _, type_key in ipairs(h.type_order) do
        local type_results = results[type_key]
        if #type_results > 0 then
            cats[#cats+1] = i18n.cats[type_key]
            local stats, stat_order = h.make_stat_order(type_results)
            
            local passive = type_results[1]
            
            local infocard_args = {}
            infocard_args.header = passive['passive_skills.name']
            infocard_args.subheader = i18n.passive_box[type_key]
            
            infocard_args[1] = h.format_passive_icon(passive, type_key)
            infocard_args[2] = h.stat_page_links(stat_order, stats)
            infocard_args[3] = m_util.html.poe_color('flavour', passive['passive_skills.flavour_text'])
            
            out[#out+1] = f_infocard(infocard_args)
        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

function p.passive_skill_link(frame)
    -- 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_util.cargo.query(
        {'passive_skills'},
        {
            'passive_skills._pageName', 
            'passive_skills.stat_text',
            'passive_skills.name',
            'passive_skills.icon',
            'passive_skills.is_keystone',
            'passive_skills.is_notable',
            'passive_skills.ascendancy_class',
        }, 
        {
            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
        return string.format('| [[%s]]%s\n| %s', passive['passive_skills.name'], h.format_passive_icon(passive, h.get_type(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

function p.passive_skill_table2(frame)
    -- Get args
    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.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]]<br>%s', passive['passive_skills.name'], h.format_passive_icon(passive, type_key)))
                            :done()
                end,
                order = 1000,
                sort_type = 'text',
                options = {
                    [6] = {
                        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
    tpl_args = getArgs(frame, {
        parentFirst = true
    })
    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_util.cargo.query(
        {'passive_skills', 'passive_skill_stats'},
        {
            'passive_skills._pageName', 
            '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_util.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]]<br>%s', row['passive_skills.name'], h.format_passive_icon(row, type_key)))
                            :done()
                        :tag('td')
                            :wikitext(h.stat_page_links(stat_order, stats))
                            :done()
                end
            end
        end
    end
    
    return tostring(tbl)
end

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

return p