Path of Exile Wiki

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

ПОДРОБНЕЕ

Path of Exile Wiki
(Новая страница: «------------------------------------------------------------------------------- -- -- Module:Item util -- -- This meta module conta...»)
 
Нет описания правки
 
(не показано 6 промежуточных версий этого же участника)
Строка 5: Строка 5:
 
-- This meta module contains utility functions for modules that deal with items
 
-- This meta module contains utility functions for modules that deal with items
 
-------------------------------------------------------------------------------
 
-------------------------------------------------------------------------------
  +
  +
local m_util = require('Module:Util')
  +
local m_cargo -- Lazy load require('Module:Cargo')
  +
  +
-- Should we use the sandbox version of our submodules?
  +
local use_sandbox = m_util.misc.maybe_sandbox('Item util')
   
 
-- The cfg table contains all localisable strings and configuration, to make it
 
-- The cfg table contains all localisable strings and configuration, to make it
 
-- easier to port this module to another wiki.
 
-- easier to port this module to another wiki.
local cfg = mw.loadData('Module:Item util/config')
+
local cfg = use_sandbox and mw.loadData('Module:Item util/config/sandbox') or mw.loadData('Module:Item util/config')
   
 
local i18n = cfg.i18n
 
local i18n = cfg.i18n
Строка 25: Строка 31:
 
end
 
end
 
return cfg.item_namespaces
 
return cfg.item_namespaces
  +
end
  +
  +
function m.query_item(args, qargs)
  +
qargs = qargs or {}
  +
m_cargo = m_cargo or require('Module:Cargo')
  +
if not m_util.table.has_any_key(args, cfg.search_terms) then
  +
error(i18n.errors.missing_search_term)
  +
end
  +
local tables = {'items'}
  +
local fields = {
  +
'items._pageName=_pageName',
  +
'items.drop_enabled=drop_enabled',
  +
'items.class_id=class_id',
  +
}
  +
local query = {
  +
groupBy = 'items._pageID',
  +
orderBy = 'items.drop_enabled DESC',
  +
}
  +
local search_param
  +
local results
  +
if args.metadata_id then
  +
query.where = string.format(
  +
'items.metadata_id = "%s"',
  +
args.metadata_id
  +
)
  +
search_param = 'metadata_id'
  +
elseif args.page then
  +
-- Join with _pageData in order to check for page redirect
  +
tables[#tables+1] = '_pageData'
  +
query.join = 'items._pageName = _pageData._pageNameOrRedirect'
  +
query.where = string.format(
  +
'_pageData._pageName = "%s"',
  +
m_cargo.addslashes(args.page)
  +
)
  +
search_param = 'page'
  +
else
  +
tables[#tables+1] = 'maps'
  +
tables[#tables+1] = 'map_series'
  +
query.join = 'items._pageID = maps._pageID, maps.series = map_series.name'
  +
query.where = string.format(
  +
'items._pageNamespace IN (%s)',
  +
m.get_item_namespaces{format = 'list'}
  +
)
  +
query.orderBy = 'map_series.ordinal DESC, ' .. query.orderBy
  +
if args.item_name_exact then
  +
query.where = query.where .. string.format(
  +
' AND items.name = "%s"',
  +
m_cargo.addslashes(args.item_name_exact)
  +
)
  +
search_param = 'item_name_exact'
  +
else
  +
--[[
  +
Cargo's implementation of HOLDS breaks when there is a properly
  +
escaped quotation mark at the end of a string literal.
  +
  +
Example of a WHERE clause that results in an error:
  +
items.name_list HOLDS "\"O\' Eternal\""
  +
  +
Instead, we avoid using HOLDS by explicitly joining the child table
  +
and then comparing using a native operator.
  +
--]]
  +
tables[#tables+1] = 'items__name_list'
  +
query.join = query.join .. ', items._ID = items__name_list._rowID'
  +
query.where = query.where .. string.format(
  +
' AND items__name_list._value = "%s"',
  +
m_cargo.addslashes(args.item_name)
  +
)
  +
search_param = 'item_name'
  +
end
  +
end
  +
-- Append additional tables and fields
  +
if type(qargs.tables) == 'table' and #qargs.tables > 0 then
  +
tables = m_util.table.merge(tables, qargs.tables)
  +
end
  +
if type(qargs.fields) == 'table' and #qargs.fields > 0 then
  +
fields = m_util.table.merge(fields, qargs.fields)
  +
end
  +
-- Append to join, where and orderBy clauses
  +
if qargs.join then
  +
query.join = table.concat({query.join, qargs.join}, ', ')
  +
end
  +
if qargs.where then
  +
query.where = table.concat({query.where, qargs.where}, ' AND ')
  +
end
  +
if qargs.orderBy then
  +
query.orderBy = table.concat({qargs.orderBy, query.orderBy}, ', ')
  +
end
  +
results = m_cargo.query(tables, fields, query)
  +
local err
  +
if #results == 0 then
  +
-- No results found
  +
err = m_util.misc.raise_error_or_return{
  +
raise_required = true,
  +
args = args,
  +
msg = string.format(
  +
i18n.errors.no_results_found,
  +
search_param,
  +
args[search_param]
  +
)
  +
}
  +
elseif #results > 1 then
  +
-- More than one result found
  +
--
  +
-- If results are all maps, use the one from the most recent map
  +
-- series, regardless of whether it's drop enabled. Otherwise,
  +
-- if only one of the results is drop enabled then use that one.
  +
local map_count = 0
  +
local drop_enabled_count = 0
  +
for i, v in ipairs(results) do
  +
if v.class_id == 'Map' then
  +
map_count = map_count + 1
  +
end
  +
if m_util.cast.boolean(v.drop_enabled) then
  +
drop_enabled_count = drop_enabled_count + 1
  +
end
  +
end
  +
if (map_count == 0 or map_count ~= #results) and drop_enabled_count ~= 1 then
  +
err = m_util.misc.raise_error_or_return{
  +
raise_required = true,
  +
args = args,
  +
msg = string.format(
  +
i18n.errors.many_results_found,
  +
search_param,
  +
args[search_param]
  +
)
  +
}
  +
end
  +
end
  +
if args.debug then
  +
mw.logObject(results)
  +
end
  +
if err ~= nil then
  +
if not m_util.cast.boolean(args.nocat) then
  +
err = err .. m_util.misc.add_category({args.error_category or i18n.categories.failed_query})
  +
end
  +
return {error = err}
  +
end
  +
return results[1] -- orderBy ensures that the first result is the one we want
 
end
 
end
   

Текущая версия от 16:19, 24 января 2022

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

Этот мета-модуль предоставляет служебные функции для модулей, которые имеют дело с предметами.

Использование

Этот модуль должен быть загружен с помощью require().

-------------------------------------------------------------------------------
-- 
--                              Module:Item util
-- 
-- This meta module contains utility functions for modules that deal with items
-------------------------------------------------------------------------------

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

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

-- 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:Item util/config/sandbox') or mw.loadData('Module:Item util/config')

local i18n = cfg.i18n

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

local m = {}

function m.get_item_namespaces(args)
    -- Returns item namespaces from config as a table or as a comma-separated string
    args.format = args.format or 'table'
    if args.format == 'list' then
        return cfg.item_namespaces_list
    end
    return cfg.item_namespaces
end

function m.query_item(args, qargs)
    qargs = qargs or {}
    m_cargo = m_cargo or require('Module:Cargo')
    if not m_util.table.has_any_key(args, cfg.search_terms) then
        error(i18n.errors.missing_search_term)
    end
    local tables = {'items'}
    local fields = {
        'items._pageName=_pageName',
        'items.drop_enabled=drop_enabled',
        'items.class_id=class_id',
    }
    local query = {
        groupBy = 'items._pageID',
        orderBy = 'items.drop_enabled DESC',
    }
    local search_param
    local results
    if args.metadata_id then
        query.where = string.format(
            'items.metadata_id = "%s"',
            args.metadata_id
        )
        search_param = 'metadata_id'
    elseif args.page then
        -- Join with _pageData in order to check for page redirect
        tables[#tables+1] = '_pageData'
        query.join = 'items._pageName = _pageData._pageNameOrRedirect'
        query.where = string.format(
            '_pageData._pageName = "%s"',
            m_cargo.addslashes(args.page)
        )
        search_param = 'page'
    else
        tables[#tables+1] = 'maps'
        tables[#tables+1] = 'map_series'
        query.join = 'items._pageID = maps._pageID, maps.series = map_series.name'
        query.where = string.format(
            'items._pageNamespace IN (%s)',
            m.get_item_namespaces{format = 'list'}
        )
        query.orderBy = 'map_series.ordinal DESC, ' .. query.orderBy
        if args.item_name_exact then
            query.where = query.where .. string.format(
                ' AND items.name = "%s"',
                m_cargo.addslashes(args.item_name_exact)
            )
            search_param = 'item_name_exact'
        else
            --[[
            Cargo's implementation of HOLDS breaks when there is a properly 
            escaped quotation mark at the end of a string literal.

            Example of a WHERE clause that results in an error:
                items.name_list HOLDS "\"O\' Eternal\""

            Instead, we avoid using HOLDS by explicitly joining the child table 
            and then comparing using a native operator.
            --]]
            tables[#tables+1] = 'items__name_list'
            query.join = query.join .. ', items._ID = items__name_list._rowID'
            query.where = query.where .. string.format(
                ' AND items__name_list._value = "%s"',
                m_cargo.addslashes(args.item_name)
            )
            search_param = 'item_name'
        end
    end
    -- Append additional tables and fields
    if type(qargs.tables) == 'table' and #qargs.tables > 0 then
        tables = m_util.table.merge(tables, qargs.tables)
    end
    if type(qargs.fields) == 'table' and #qargs.fields > 0 then
        fields = m_util.table.merge(fields, qargs.fields)
    end
    -- Append to join, where and orderBy clauses
    if qargs.join then
        query.join = table.concat({query.join, qargs.join}, ', ')
    end
    if qargs.where then
        query.where = table.concat({query.where, qargs.where}, ' AND ')
    end
    if qargs.orderBy then
        query.orderBy = table.concat({qargs.orderBy, query.orderBy}, ', ')
    end
    results = m_cargo.query(tables, fields, query)
    local err
    if #results == 0 then
        -- No results found
        err = m_util.misc.raise_error_or_return{
            raise_required = true,
            args = args,
            msg = string.format(
                i18n.errors.no_results_found,
                search_param,
                args[search_param]
            )
        }
    elseif #results > 1 then
        -- More than one result found
        -- 
        -- If results are all maps, use the one from the most recent map
        -- series, regardless of whether it's drop enabled. Otherwise, 
        -- if only one of the results is drop enabled then use that one.
        local map_count = 0
        local drop_enabled_count = 0
        for i, v in ipairs(results) do
            if v.class_id == 'Map' then
                map_count = map_count + 1
            end
            if m_util.cast.boolean(v.drop_enabled) then
                drop_enabled_count = drop_enabled_count + 1
            end
        end
        if (map_count == 0 or map_count ~= #results) and drop_enabled_count ~= 1 then
            err = m_util.misc.raise_error_or_return{
                raise_required = true,
                args = args,
                msg = string.format(
                    i18n.errors.many_results_found,
                    search_param,
                    args[search_param]
                )
            }
        end
    end
    if args.debug then
        mw.logObject(results)
    end
    if err ~= nil then
        if not m_util.cast.boolean(args.nocat) then
            err = err .. m_util.misc.add_category({args.error_category or i18n.categories.failed_query})
        end
        return {error = err}
    end
    return results[1] -- orderBy ensures that the first result is the one we want
end

return m