打开/关闭菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

模块:FrameChart:修订间差异

来自骷髅女孩Wiki
无编辑摘要
标签已被回退
无编辑摘要
标签已被回退
第4行: 第4行:
local framechart = require( "Module:MetaFrameChart" )
local framechart = require( "Module:MetaFrameChart" )
mw.log(framechart and "Module loaded" or "Module not loaded")
mw.log(framechart and "Module loaded" or "Module not loaded")
 
if framechart then
  if framechart.drawFrameData then
    mw.error("drawFrameData is available")
  else
    mw.error("drawFrameData is not available")
  end
else
  mw.error("Failed to load Module:MetaFrameChart")
end
function p.drawFrameData( frame )
function p.drawFrameData( frame )
   -- 初始化chara和input变量用于存储角色和输入数据
   -- 初始化chara和input变量用于存储角色和输入数据

2024年12月20日 (五) 23:09的版本

此模块的文档可以在模块:FrameChart/doc创建

-- FrameChart
local p = {}
local cargo = mw.ext.cargo
local framechart = require( "Module:MetaFrameChart" )
mw.log(framechart and "Module loaded" or "Module not loaded")
if framechart then
  if framechart.drawFrameData then
    mw.error("drawFrameData is available")
  else
    mw.error("drawFrameData is not available")
  end
else
  mw.error("Failed to load Module:MetaFrameChart")
end
function p.drawFrameData( frame )
  -- 初始化chara和input变量用于存储角色和输入数据
  -- 检查frame参数中是否有chara和input字段,如有,则使用frame:preprocess方法预处理
  -- 如果chara为nil,则尝试从当前页面标题提取角色名(当前页面标题中最后一个斜杠后面的文本)
  -- 如果仍为nil,则报错;如input为nil,也报错
  local chara = nil
  if frame.args['chara'] ~= nil then
    chara = frame:preprocess(frame.args['chara'])
  end
  local input = nil
  if frame.args['input'] then
    input = frame:preprocess(frame.args['input'])
  end
  if chara == nil then
    chara = string.match(mw.title.getCurrentTitle().text, "/([^/]+)")  --[^/]+匹配1-n个非斜杠字符
  end
  if chara == nil then 
    return '<span class="error">failed to determine fighter. Please specify explicitly</span>'
  end
  if input == nil then
    return '<span class="error">input is not specified</span>'
  end

  -- 从Cargo扩展中查询数据,存储于framedata变量中
  local cargo_tables = 'MoveData'
  local fields = 'MoveData.startup, MoveData.active, MoveData.recovery'
  local cargo_args = {
    where = 'MoveData.fighter="' .. chara .. '" AND MoveData.input="' .. input .. '"'
  }
  local framedata = cargo.query(cargo_tables, fields, cargo_args);
  -- 如果查询返回了多个结果(fields),报错
  if framedata[2] ~= nil then
    return '<span class="error">cargo returned more than one move for that query somehow... This is a bug..</span>'
  end
  -- 将查询的第一个结果赋值给fd,若其为nil,则报错
  local fd = framedata[1]
  if fd == nil then
    return '<span class="error">No results</span>'
  end
  -- 开始循环,遍历包含{startup, active, recovery}的列表
  -- 对于每种帧类型,从fd中获取相应的帧数数据并存储在duration中
  -- 如果frame参数中有对应的帧类型字段,使用frame:preprocess方法处理该字段值
  -- _, frameKind表示,忽略迭代过程中的第一个返回值(即k,键),只关心第二个返回值(即v,值,循环变量命名为frameKind)
  -- inpairs保证以数组顺序(1-n)遍历数组,所以以下代码意为将frameKind依次赋值为s、a、r并进行循环体操作
  for _, frameKind in ipairs({"startup", "active", "recovery"}) do
    local duration = fd[frameKind]
    if frame.args[frameKind] ~= nil then  -- frame.args[frameKind]表示访问frame表中frameKind键对应的值
      duration = frame:preprocess(frame.args[frameKind])  -- frame:preprocess的参数中如有MW模板或变量(如{{Var}}),会自动展开
    end
    -- 如果duration为nil,则跳过这个帧类型
    if duration == nil then
    -- 如果duration可以直接转化为数字,则直接赋值给frame.args[frameKind]
    elseif tonumber(duration) ~= nil then
      frame.args[frameKind] = duration
    -- 如果不是数字,则使用对应的解析函数解析帧数字并存储于
    else
      local parsed = nil
      if frameKind == "active" then
        parsed = parseActive(duration)
      elseif frameKind == "startup" then
        parsed = parseStartup(duration)
      elseif frameKind == "recovery" then
        parsed = parseRecovery(duration)
      end
    -- 如果parsed为nil,表示解析失败,报错
      if parsed == nil then
        return string.format('<span class="error">The number of %s frames is not a simple number (%s). Please specify explicitly.</span>', frameKind, tostring(duration))
      end
    -- 如果解析成功,遍历解析后的表parsed,将每个字段值赋给frame.args[k]
      for k, v in pairs(parsed) do  -- parsed格式会是{startup = s, active = a, recovery = r}的数据格式
        frame.args[k] = v
      end
    end
  end

  -- 将此模块中p.drawFrameData的参数处理后输入给调用Module:MetaFrameChart的drawFrameData函数
  return framechart.drawFrameData(frame)
end


-- 解析函数,类似MetaFrameChart模块中的功能
function parseActive(duration)
  -- simple number
  if tonumber(duration) ~= nil then
    return {active = tonumber(duration)}
  end

  if string.find(duration, "%d+%s*,") ~= nil then
    -- 1,2,3,4 format -- multihit with no gaps
    local totalActive = 0

    -- first match - just a number
    local firstval, pos = string.match(duration, "^(%d+)%s*()")
    if firstval == nil then
      return nil
    end
    -- subsequent matches - coma, then number. Might have spaces between them
    totalActive = totalActive + tonumber(firstval)
    for p1, dur, p2 in string.gmatch(duration, "(),%s*(%d+)%s*()") do
      if pos ~= p1 then
        return nil
      end
      pos = p2
      totalActive = totalActive + tonumber(dur)
    end
    if pos ~= string.len(duration)+1 then
      return nil -- trailing stuff at the end
    end
    -- Done.
    local out = {active = totalActive}
    return out 
  elseif mw.ustring.find(duration, "^%d+[x×]%d+$") ~= nil then
    -- 3x4 format -- also multihit with no gaps
    local a, b = mw.ustring.match(duration, "^(%d+)[x×](%d+)$")
    local out = { active = tonumber(a) * tonumber(b) }
    return out
  elseif string.find(duration, "^%d+%(%d+%)") ~= nil then
    -- 1(2)3(4)5 format -- multihit with gaps
    local out = {}
    -- special handling for the first number
    local firstval, pos = string.match(duration, "^(%d+)()")
    out['active'] = firstval

    local ordinal = 2
    -- then we just have a groups of "(inactive)active"
    for p1, d1, d2, p2 in string.gmatch(duration, "()%((%d+)%)(%d+)()") do
      if pos ~= p1 then
        return nil -- not directly following the previous match, so basically not what we expect
      end
      out['inactive' .. tostring(ordinal)] = d1
      out['active' .. tostring(ordinal+1)] = d2
      ordinal = ordinal + 2
      pos = p2
    end
    if pos ~= string.len(duration)+1 then
      return nil -- trailing stuff at the end
    end
    -- Done.
    return out
  end
  -- unrecognized format
  return nil
end

function parseStartup(duration)
  -- simple number
  if tonumber(duration) ~= nil then
    return {startup = tonumber(duration)}
  end

  -- 1+2 -- common for supers
  if string.find(duration, "^%d+%+%d+$") ~= nil then
    local first, second = string.match(duration, "^(%d+)%+(%d+)$")
    return {startup = tonumber(first) + tonumber(second) }
  end
  return nil
end

function parseRecovery(duration)
  -- simple number
  if tonumber(duration) ~= nil then
    return {startup = tonumber(duration)}
  end

  -- "Until L+10" -- aerial moves, such as grabs.
  if string.find(duration, "^Until L%+%d+$") ~= nil then
    local recovery = string.match(duration, "^Until L%+(%d+)$")
    return { recovery=0, specialRecovery=recovery }
  end
  return nil
end

return p