Noita中文 Wiki
Advertisement
Template-info.png 模板文档

该脚本使用的数据来源于模块:DataQuery/data。 一般来讲该模块只应使用于模板中。

使用[]

{{#invoke:DataQuery|main
|q?tables=Spells
|q?tier={{{tier|}}}
|q?type={{{type|}}}
|intro={{{!}} class="mw-collapsible" style="width:100%;"
{{!}}+
{{!}} <div style="display:flex;column-gap:0.5rem;row-gap:0.5rem;justify-content:center;flex-wrap:wrap">
|outro=</div>
{{!}}}
|template=SpellQuery/row2
|default=''There are no spells of the specified query.''
}}

参数[]

Parameter Description
q?tables 查询数据表,目前可用的为"Spells"
combineResultAsRow 行转列,主要用于Infobox
default 当查询结果为空时,返回的数据
intro 拼接到结果之前的wiki文本
outro 拼接到结果之后的wiki文本
template 渲染每一行数据的模板
q?tier (法术专用)法术等级, 过滤方式为AND
q?groupKey (法术专用)用于筛选一类法术, 过滤方式为AND
q?name (法术)查询名称,可使用半角逗号分隔以查询多个,可使用值为英文名、官方中文名;排他参数。
q?type (法术)查询类型,可使用半角逗号分隔以查询多个;投射物(Projectile), 静态投射物(Static projectile), 被动(Passive), 实用(Utility), 投射修正(Projectile modifier), 材料(Material), 多重释放(Multicast);指定该参数时仍将应用其他过滤条件;

示例[]

{{#invoke:DataQuery|main
|q?tables=Spells
|q?type=其他
|intro={{{!}} class="mw-collapsible" style="width:100%;"
{{!}}+
{{!}} <div style="display:flex;column-gap:0.5rem;row-gap:0.5rem;justify-content:center;flex-wrap:wrap">
|outro=</div>
{{!}}}
|template=SpellQuery/row2
|default=''There are no spells of the specified query.''
}}



local p = {

}

function p.main(frame)
    local args = frame
    if frame == mw.getCurrentFrame() then
        args = require('Module:ProcessArgs').merge(true)
    else
        frame = mw.getCurrentFrame()
    end
    -- error(mw.dumpObject(args))

    local query = {}
    for k, v in pairs(args) do
        if string.sub(k, 0, 2) == 'q?' then
            query[string.sub(k, 3)] = v
        end
    end

    local result = p.queryData(query.tables, query)
    if result[1] == nil then
        -- metatable似乎被删除了,因此#result的结果是0
        --if not next(result) then
        return frame:preprocess(args.default or '')
    end
    if args.combineResultAsRow ~= nil then
        result = combineResultAsRow(result)
    end
    local tbl = {}
    for _, row in ipairs(result) do
        tbl[#tbl + 1] = frame:expandTemplate { title = args.template, args = row }
    end
    local intro = frame:preprocess(args.intro or '')
    local outro = frame:preprocess(args.outro or '')
    return intro .. table.concat(tbl, args.delimiter or '') .. outro
end

--- 移除前后空格
local function strip(s)
    if s == nil then
        return ''
    end
    return s:gsub("^%s+", ""):gsub("%s+$", "")
end
local function isNotEmpty(s)
    return s ~= nil and s ~= ''
end

---split
---根据指定的分隔符分隔, 返回table, 内容会经过小写转换及删除前后空格
---@param s string
---@param delim string
local function split(s, delim)
    if string.find(s, delim) == nil then
        return {
            strip(s):lower()
        }
    end
    local result = {}
    for ct in string.gmatch(s, '([^' .. delim .. ']+)') do
        ct = strip(ct):lower()
        result[#result + 1] = ct
    end
    return result
end

--- 将所有结果合为一个, 后边加数字区分, 比如 { name, img, name2, img2 }
--- 不适合太大的结果集
function combineResultAsRow(result)
    if #result == 1 then
        return result
    end
    local r = {}
    for i, row in ipairs(result) do
        local suffix = ''
        if i > 1 then
            suffix = tostring(i)
        end
        for k, v in pairs(row) do
            r[k .. suffix] = v
        end
    end
    return { r }
end

-- 返回是否需要过滤结果集,用于提升性能
local function hasAnyFilter(query)
    if isNotEmpty(query.tier) then
        return true
    end
    if isNotEmpty(query.groupKey) then
        query.groupKey = query.groupKey:lower()
        return true
    end
    return false
end

--- 返回给定的行是否是符合条件的数据
local function isAvailableRow(t, v, query)
    if isNotEmpty(query.tier) then
        anyFind = false
        for _, ct in pairs(query.tier) do
            if string.find(v['spellTierPrepared'], '#' .. ct .. '#') ~= nil then
                anyFind = true
                break
            end
        end
        if not anyFind then
            return false
        end
    end
    if isNotEmpty(query.groupKey) then
        if string.find(v['sortKey'], query.groupKey) == nil then
            return false
        end
    end
    --if isNotEmpty(query.type) then
    --    if v['type'] ~= query.type then
    --        return false
    --    end
    --end
    return true
end

local function filter(t, query)
    if not hasAnyFilter(query) then
        return t
    end
    local result = {}
    if (t == nil) then
        return result
    end
    for _, v in pairs(t) do
        if isAvailableRow(t, v, query) then
            result[#result + 1] = v
        end
    end
    return result
end

--- 查询并过滤数据, 结果集未排序, 需要外部排序
function p.queryData(tables, query)
    local raw_data = mw.loadData("Module:DataQuery/data")
    local all_data_table = raw_data[tables]
    if isNotEmpty(query.tier) then
        query.tier = split(query.tier, ',')
    end
    if isNotEmpty(query.name) then
        local result = {}
        local table_by_name = raw_data[tables .. '_Name']
        for _, ct in pairs(split(query.name, ',')) do
            result[#result + 1] = table_by_name[ct]
        end
        return result
    end
    if isNotEmpty(query.type) then
        local type = query.type
        query.type = nil
        if string.find(type, ',') == nil then
            return filter(raw_data[tables .. '_Type'][strip(type):lower()], query)
        end
        local result = {}
        for _, ct in pairs(split(type, ',')) do
            local tree_table = raw_data[tables .. '_Type'][ct]
            if tree_table == nil then
                error("can't find type: '" .. ct .. "'")
            end
            for _, v in pairs(filter(tree_table, query)) do
                result[#result + 1] = v
            end
        end
        return result
    end

    return filter(all_data_table, query)
end

return p
Advertisement