该脚本使用的数据来源于模块: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