模块:MaterialReaction
跳到导航
跳到搜索
模块文档
[刷新缓存]
一般来讲,本模块只应用于模板中,是用于加载材料反应的模块,如果你是想简单的加载材料反应模板,请查看{{MaterialReactions}}
local p = {}
local IDtoTable = {}--材料ID转数据表
for _,v in pairs(mw.loadData("Module:DataQuery/Materials")["Materials"])do --初始化id对应表
IDtoTable[v.herd] = v
end
--- 移除前后空格,换行
local function strip(s)
if s == nil then
return ''
end
return s:gsub("^%s+", ""):gsub("%s+$", ""):gsub("%c","")
end
---split
---根据指定的分隔符分隔, 返回table, 内容会删除前后空格
---@param s string
---@param delim string
local function split(s, delim)
if string.find(s, delim) == nil then
return {
strip(s)
}
end
local result = {}
for ct in string.gmatch(s, '([^' .. delim .. ']+)') do
ct = strip(ct)
result[#result + 1] = ct
end
return result
end
local function TagGetName(str)--删除tag的前后空格和[]以及非tag部分
str = strip(str)
local pos1 = 1
local count = 0
while(string.byte(str,pos1,pos1) ~= 91)do--91为[
pos1 = pos1 + 1
end
local pos2 = pos1+1
while(string.byte(str,pos2,pos2) ~= 93)do--93为]
pos2 = pos2 + 1
end
return string.sub(str,pos1+1,pos2-1)
end
local function TagGetNameAndLastText(str)--第一个返回值为[tag],第二个为后续内容
str = strip(str)
local pos1 = 1
local count = 0
while(string.byte(str,pos1,pos1) ~= 91)do--91为[
pos1 = pos1 + 1
end
local pos2 = pos1+1
while(string.byte(str,pos2,pos2) ~= 93)do--93为]
pos2 = pos2 + 1
end
local str1 = string.sub(str,pos1,pos2)
local str2 = string.sub(str,pos2+1)
return str1,str2
end
function p.group(frame)--按组加载函数
local args = frame
if frame == mw.getCurrentFrame() then
args = require('Module:ProcessArgs').merge(true)
else
frame = mw.getCurrentFrame()
end
local query = {}
for k, v in pairs(args) do--k为字符串
if string.sub(k, 0, 2) == 'q?' then--如果开头两个字符为q?
query[string.sub(k, 3)] = v--那么将截取之后的字符串作为一个key值,赋值为v(参数)
end
end
local resultCache = {}
if query.group ~= nil then
local raw_data = mw.loadData("Module:DataQuery/Materials").Materials_Link[strip(query.group):lower()]
for _,v in pairs(raw_data)do
table.insert(resultCache,frame:expandTemplate{title = "MaterialReactions/load", args = {id = v.herd}})
end
return table.concat(resultCache)
else
return {}
end
end
function p.allMatTable(frame)--生成所有材料的反应表格,非常好玩()
local args = frame
if frame == mw.getCurrentFrame() then
args = require('Module:ProcessArgs').merge(true)
else
frame = mw.getCurrentFrame()
end
local resultCache = {}
local raw_data = mw.loadData("Module:DataQuery/Materials")
for _,v in pairs(raw_data)do
table.insert(resultCache,frame:expandTemplate{title = "MaterialReactions/load", args = {id = v.herd}})
end
return table.concat(resultCache)
end
function p.main(frame)--已完成
local args = frame
if frame == mw.getCurrentFrame() then
args = require('Module:ProcessArgs').merge(true)
else
frame = mw.getCurrentFrame()
end
local query = {}
for k, v in pairs(args) do--k为字符串
if string.sub(k, 0, 2) == 'q?' then--如果开头两个字符为q?
query[string.sub(k, 3)] = v--那么将截取之后的字符串作为一个key值,赋值为v(参数)
end
end
local result = p.queryData(query)
if result[1] == nil then
return frame:preprocess(args.default or '')
end
local tbl = {}
for _, row in ipairs(result) do
table.insert(tbl, 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 EqTag(tagList,tag)--判断tag是否相等
for _,v in pairs(tagList)do --注意,这里传进来的已经加过[]这两个了
if v == tag then
return true
end
end
return false
end
local function FormatName(str, id, tagList, frame)--str为输入的参数,其中可能是tag,也有可能是材料id
local inputArgs = {nil, nil}--输入到模板的参数
if string.byte(str,1,1) == 91 then --91为[ 此处判断是否为tag
--是tag
local str1,str2 = TagGetNameAndLastText(str)
local isTagMaterial = EqTag(tagList,str1)--判断是不是这个材料参与的
if isTagMaterial and str2 == "" then--如果是,且没有后缀
inputArgs[1] = "[["..IDtoTable[id].link.."##|"..IDtoTable[id].name.."]]"
inputArgs[2] = IDtoTable[id].herd.."<br>"..str1
elseif isTagMaterial and str2 ~= "" and IDtoTable[IDtoTable[id].herd..str2] ~= nil then --如果是,且后缀拼接的材料存在
local tempName = IDtoTable[id].herd..str2
inputArgs[1] = "[["..IDtoTable[tempName].link.."##|"..IDtoTable[tempName].name.."]]"
inputArgs[2] = IDtoTable[tempName].herd.."<br>"..str
else
return "[[:Category:带有"..TagGetName(str).."标签的材料|"..str1.."]]"..str2 --注意,这个是特殊情况,不用展开模板
end
else
--不是tag
inputArgs[1] = "[["..IDtoTable[str].link.."##|"..IDtoTable[str].name.."]]"
inputArgs[2] = IDtoTable[str].herd
end
return frame:expandTemplate{title = "MaterialReactions/hover", args = inputArgs}
end
local function FormatTag(str, frame)--str为输入的参数,其中可能是tag,也有可能是材料id
if string.byte(str,1,1) == 91 then --91为[ 此处判断是否为tag
--是tag
local str1,str2 = TagGetNameAndLastText(str)
return "[[:Category:带有"..TagGetName(str).."标签的材料|"..str1.."]]"..str2
end
--不是tag
local inputArgs = {nil, nil}--输入到模板的参数
inputArgs[1] = "[["..IDtoTable[str].link.."##|"..IDtoTable[str].name.."]]"
inputArgs[2] = IDtoTable[str].herd
return frame:expandTemplate{title = "MaterialReactions/hover", args = inputArgs}
end
function p.queryData(query)--query为参数表
local frame = mw.getCurrentFrame()
local raw_data = mw.loadData("Module:MaterialReaction/PreData")--注意,这个表是只读的,要深拷贝
local result = {}
if query.id ~= nil then
local id = strip(query.id)
query.id = nil
local tagsList = split(IDtoTable[id].tags,",")
local tempData = {}
if IDtoTable[id].onfire == "1" then--始终燃烧材料始终带有fire标签
table.insert(tagsList, "fire");
end
if IDtoTable[id].liquidSand == "0" and IDtoTable[id].cellType == "liquid" and id ~= "mimic_liquid" then--液体材料特判
table.insert(tagsList,"any_liquid")
end
for i=1,#tagsList do --转换字符串为指定格式
tagsList[i] = "["..tagsList[i].."]"
if raw_data[tagsList[i]] ~= nil then
table.insert(tempData, raw_data[tagsList[i]])
end
end
if raw_data[id] ~= nil then
table.insert(tempData, raw_data[id])
end
for h=1,#tempData do
local thisData = tempData[h]
for i,_ in pairs(thisData[1]) do --四个数组等长的,所以只需要知道一个数组的长度即可遍历
local inputCache = {nil, nil, nil}--缓存区
local outputCache = {nil, nil, nil}
for j,_ in pairs(thisData[1][i]) do--遍历输入材料并解析
inputCache[j] = FormatName(thisData[1][i][j],id,tagsList,frame)
end
for j,_ in pairs(thisData[2][i]) do
outputCache[j] = FormatName(thisData[2][i][j],id,tagsList,frame)
end
table.insert(result,{output = table.concat(outputCache," + "),input = table.concat(inputCache," + "),rate=thisData[3][i],fast=thisData[4][i]})--直接合理初始化表
end
end
elseif query.tag ~= nil then
local tag = strip(query.tag)
query.tag = nil
tag = "["..tag.."]"
local thisData = raw_data[tag]
if thisData ~= nil then
for i,_ in pairs(thisData[1]) do --四个数组等长的,所以只需要知道一个数组的长度即可遍历
local inputCache = {nil, nil, nil}--缓存区
local outputCache = {nil, nil, nil}
for j,_ in pairs(thisData[1][i]) do--遍历输入材料并解析
inputCache[j] = FormatTag(thisData[1][i][j],frame)
end
for j,_ in pairs(thisData[2][i]) do
outputCache[j] = FormatTag(thisData[2][i][j],frame)
end
table.insert(result,{output = table.concat(outputCache," + "),input = table.concat(inputCache," + "),rate=thisData[3][i],fast=thisData[4][i]})--直接合理初始化表
end
end
end
return result
end
function p.all(frame)--已完成
local args = frame
if frame == mw.getCurrentFrame() then
args = require('Module:ProcessArgs').merge(true)
else
frame = mw.getCurrentFrame()
end
local result = {}
local raw_data = require("Module:MaterialReaction/data")
for _, v1 in pairs(raw_data.children) do --遍历元素
--获得材料输入和输出
local tempInputT = { nil, nil, nil } --nil用于占位,提供一个合适的数组大小,避免hash操作带来的性能损失
local tempOutputT = { nil, nil, nil } --nil用于占位,提供一个合适的数组大小,避免hash操作带来的性能损失
local i = 1 --用于遍历元素的属性
local cmpStr = "input_cell" .. tostring(i)
while (v1.attr[cmpStr] ~= nil) do --解析输入材料
tempInputT[i] = FormatTag(v1.attr[cmpStr],frame)
i = i + 1
cmpStr = "input_cell" .. tostring(i)
end
i = 1
local cmpStr = "output_cell" .. tostring(i)
while (v1.attr[cmpStr] ~= nil) do --解析输出材料
tempOutputT[i] = FormatTag(v1.attr[cmpStr],frame)
i = i + 1
cmpStr = "output_cell" .. tostring(i)
end
local Reactionfast = "否"
if v1.attr.fast_reaction ~= nil then --解析反应是否快速
if v1.attr.fast_reaction == "1" then
Reactionfast = "是"
end
end
table.insert(result,{output = table.concat(tempOutputT," + "),input = table.concat(tempInputT," + "),rate=v1.attr.probability,fast=Reactionfast})
end
if result[1] == nil then
return frame:preprocess(args.default or '')
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
return p