模块:Xb2QueryHelper

来自乐园数据管理室

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

local p = {}

p.language = "cn"

local cache = {}

function p.query(sql)
  local cacheKey = p.language .. ":" .. sql
  if cache[cacheKey] then
    return cache[cacheKey]
  end
  local result = mw.xbdb.query(sql, p.language)
  cache[cacheKey] = result
  return result
end

function p.queryOne(sql)
  local result = p.query(sql)
  if #result == 1 then
    result = result[1]
  elseif #result == 0 then
    mw.log("SQL返回结果为空: " .. sql)
    return nil
  else
    error("结果行数大于1,请检查WHERE条件\n" .. sql)
  end
  return result
end

function p.getEnhance(id)
  if type(id) ~= "number" then
    error("id must be number")
  end

  local result =
    p.queryOne(
    [[
    SELECT
      "BTL_Enhance"."Param1",
      "BTL_Enhance"."Param2",
      "BTL_EnhanceEff"."Param",
      "btl_enhance_cap"."name" AS "Caption",
      "btl_buff_ms"."name" AS "BuffName" 
    FROM
      "BTL_Enhance"
      INNER JOIN "BTL_EnhanceEff" ON "BTL_Enhance"."EnhanceEffect" = "BTL_EnhanceEff".row_id
      LEFT JOIN "btl_enhance_cap" ON "BTL_Enhance"."Caption" = "btl_enhance_cap".row_id
      LEFT JOIN "btl_buff_ms" ON "BTL_EnhanceEff"."Name" = "btl_buff_ms".row_id
    WHERE
      "BTL_Enhance".row_id = ]] ..
      id
  )

  local CaptionText =
    p.replaceCaptionParam(
    result.Caption or "",
    {
      Param = result.Param,
      Param1 = result.Param1,
      Param2 = result.Param2
    }
  )

  result.RenderedCaption = CaptionText

  return result
end

function p.replaceCaptionParam(caption, params)
  local str = caption

  local paramStrArray = {}
  local paramStr = ""
  local inStr = false

  for i = 1, mw.ustring.len(str) do
    local c = mw.ustring.sub(str, i, i)

    if c == "]" then
      inStr = false

      if not mw.ustring.find(paramStr, "ML:Enhance") then
        error("找不到 ML:Enhance:" .. paramStr)
      end

      if mw.ustring.find(paramStr, "Param1") then
        paramStrArray.Param1 = paramStr
      elseif mw.ustring.find(paramStr, "Param2") then
        paramStrArray.Param2 = paramStr
      else
        paramStrArray.Param = paramStr
      end
    end

    if inStr then
      paramStr = paramStr .. c
    end

    if c == "[" then
      inStr = true
      paramStr = ""
    end
  end

  for k, v in pairs(paramStrArray) do
    str = mw.ustring.gsub(str, "%[" .. v .. "%]", params[k])
  end

  return str
end

function p.getBuff(id)
  return p.queryOne(
    [[
    SELECT
      "btl_buff_ms"."name" AS "Name",
      "btl_buff_cap"."name" AS "Caption",
      "BaseNum",
      "BaseTime",
      "BaseRecast",
      "BaseProb",
      "Interval" 
    FROM
      "BTL_Buff"
      LEFT JOIN "btl_buff_cap" ON "BTL_Buff"."Caption" = "btl_buff_cap".row_id
      LEFT JOIN "btl_buff_ms" ON "BTL_Buff"."Name" = "btl_buff_ms".row_id
    WHERE
      "BTL_Buff".row_id = ]] ..
      id
  )
end

function p.getArtsDr(id)
  return p.queryOne(
    [[
    SELECT
      btl_arts_dr_ms."name" AS "NameText",
      btl_arts_dr_cap."name" AS "CaptionText",
      "BTL_Arts_Dr".* 
    FROM
      "BTL_Arts_Dr"
      LEFT JOIN btl_arts_dr_ms ON "BTL_Arts_Dr"."Name" = btl_arts_dr_ms.row_id
      LEFT JOIN btl_arts_dr_cap ON "BTL_Arts_Dr"."Caption" = btl_arts_dr_cap.row_id
    WHERE
      "BTL_Arts_Dr".row_id = ]] ..
      id
  )
end

function p.getArtsDrListByDriver(id)
  return p.query(
    [[
    SELECT
      btl_arts_dr_ms."name" AS "NameText",
      btl_arts_dr_cap."name" AS "CaptionText",
      condcapms."name" AS "CondCapText",
      talentcapms."name" AS "TalentCapText",
      "BTL_Arts_Dr".* 
    FROM
      "BTL_Arts_Dr"
      LEFT JOIN btl_arts_dr_ms ON "BTL_Arts_Dr"."Name" = btl_arts_dr_ms.row_id
      LEFT JOIN btl_arts_dr_cap ON "BTL_Arts_Dr"."Caption" = btl_arts_dr_cap.row_id
			LEFT JOIN btl_arts_dr_cap AS condcapms ON "BTL_Arts_Dr"."CondCap" = condcapms.row_id
      LEFT JOIN btl_arts_dr_cap AS talentcapms ON "BTL_Arts_Dr"."TalentCap" = talentcapms.row_id
    WHERE
      "BTL_Arts_Dr"."Driver" = ]] ..
      id
  )
end

function p.getArtsDrListByDriverAndWpnType(driverId, WpnType)
  return p.query(
    [[
    SELECT
      btl_arts_dr_ms."name" AS "NameText",
      btl_arts_dr_cap."name" AS "CaptionText",
      condcapms."name" AS "CondCapText",
      talentcapms."name" AS "TalentCapText",
      "BTL_Arts_Dr".* 
    FROM
      "BTL_Arts_Dr"
      LEFT JOIN btl_arts_dr_ms ON "BTL_Arts_Dr"."Name" = btl_arts_dr_ms.row_id
      LEFT JOIN btl_arts_dr_cap ON "BTL_Arts_Dr"."Caption" = btl_arts_dr_cap.row_id
			LEFT JOIN btl_arts_dr_cap AS condcapms ON "BTL_Arts_Dr"."CondCap" = condcapms.row_id
      LEFT JOIN btl_arts_dr_cap AS talentcapms ON "BTL_Arts_Dr"."TalentCap" = talentcapms.row_id
    WHERE
      "BTL_Arts_Dr"."Driver" = ]] ..
      driverId .. [[ AND "BTL_Arts_Dr"."WpnType" = ]] .. WpnType
  )
end

function p.getDr(id)
  id = tonumber(id)
  if type(id) ~= "number" then
    error("id must be number")
  end
  if id <= 0 then
    return nil
  end
  local result =
    p.queryOne(
    [[
    SELECT
      chr_dr_ms."name" AS "NameText",
      category1."name" AS "FavoriteCategory1Text",
      itm1ms."name" AS "FavoriteItem1Text",
      category2."name" AS "FavoriteCategory2Text",
      itm2ms."name" AS "FavoriteItem2Text",
      "CHR_Dr".* 
    FROM
      "CHR_Dr"
      LEFT JOIN chr_dr_ms ON "CHR_Dr"."Name" = chr_dr_ms.row_id
      LEFT JOIN menu_favorite_category AS category1 ON "CHR_Dr"."FavoriteCategory1" - 11 = category1.row_id
      LEFT JOIN menu_favorite_category AS category2 ON "CHR_Dr"."FavoriteCategory2" - 11 = category2.row_id
      LEFT JOIN "ITM_FavoriteList" AS item1 ON "CHR_Dr"."FavoriteItem1" = item1.row_id
      LEFT JOIN itm_favorite AS itm1ms ON item1."Name" = itm1ms.row_id
      LEFT JOIN "ITM_FavoriteList" AS item2 ON "CHR_Dr"."FavoriteItem2" = item2.row_id
      LEFT JOIN itm_favorite AS itm2ms ON item2."Name" = itm2ms.row_id 
    WHERE
      "CHR_Dr".row_id = ]] ..
      id
  )

  local WpnType = result.WpnType
  WpnType = mw.ustring.sub(WpnType, 2)
  WpnType = mw.ustring.sub(WpnType, 1, -2)

  local WpnTypeArray = {}
  for str in mw.ustring.gmatch(WpnType, "([^,]+)") do
    table.insert(WpnTypeArray, str)
  end

  local condition = {}
  for i, v in ipairs(WpnTypeArray) do
    if tonumber(v) > 0 then
      table.insert(condition, i)
    end
  end
  condition = table.concat(condition, ", ")

  result.WpnType =
    p.query(
    [[
    SELECT
      "ITM_PcWpnType".row_id,
      itm_pcwpntype_ms."name" AS "Name",
      menu_role_name_ms."name" AS "Role",
      "ITM_PcWpnType"."JustRange",
      "ITM_PcWpnType"."JustRange2"
    FROM
      "ITM_PcWpnType"
      LEFT JOIN itm_pcwpntype_ms ON itm_pcwpntype_ms.row_id = "ITM_PcWpnType"."Name"
      LEFT JOIN menu_role_name_ms ON menu_role_name_ms.row_id = "ITM_PcWpnType"."Role"    
    WHERE
      "ITM_PcWpnType".row_id IN (]] ..
      condition .. [[)
    ]]
  )

  return result
end

function p.getSkillDrList(id)
  local driverIds = {
    [1] = true,
    [2] = true,
    [3] = true,
    [4] = true,
    [5] = true,
    [6] = true,
    [17] = true,
    [18] = true,
    [19] = true
  }
  if not driverIds[tonumber(id)] then
    return nil
  end

  if tonumber(id) < 10 then
    id = "0" .. tostring(tonumber(id))
  end

  local result =
    p.query(
    [[
      SELECT
        btl_skill_dr_name."name" AS "NameText",
        "BTL_Skill_Dr_Table]] ..
      id ..
        [[".*,
        "BTL_Skill_Dr"."Enhance"
      FROM
        "BTL_Skill_Dr_Table]] ..
          id ..
            [["
      LEFT JOIN "BTL_Skill_Dr" ON "BTL_Skill_Dr_Table]] ..
              id ..
                [["."SkillID" = "BTL_Skill_Dr".row_id
      LEFT JOIN  btl_skill_dr_name ON btl_skill_dr_name.row_id = "BTL_Skill_Dr"."Name"
      ORDER BY
        "Round",
        "RowNum",
        "ColumnNum"
    ]]
  )

  for _, row in ipairs(result) do
    row.Enhance = p.getEnhance(tonumber(row.Enhance))
  end
  return result
end

function p.getNpcPopByNpcId(npcId)
  if type(npcId) ~= "number" then
    error("getNpcPopByNpcId 的参数不是number")
  end

  -- 获取所有NpcPops表名
  local tables =
    p.query(
    mw.ustring.format(
      [[SELECT tablename FROM pg_catalog.pg_tables WHERE "schemaname" = '%s' AND "tablename" != 'ma90a_FLD_NpcPop' AND "tablename" like '%%_FLD_NpcPop']],
      p.language
    )
  )

  local result = {}
  for _, t in ipairs(tables) do
    local sql = mw.ustring.format([[SELECT * FROM "%s" WHERE "NpcID" = '%s']], t.tablename, npcId)
    local resultInSingleTable = p.query(sql)
    for _, npcPopRow in ipairs(resultInSingleTable) do
      -- Npc存在Group字段,则用Group覆盖自身数据
      if npcPopRow.Group > 0 then
        local groupData =
          p.queryOne(
          mw.ustring.format(
            [[SELECT "memberNum", "ScenarioFlagMin", "ScenarioFlagMax", "QuestFlag", "QuestFlagMin", "QuestFlagMax", "TimeRange", "Condition" FROM "FLD_NpcGroupId" WHERE "row_id" = '%d']],
            npcPopRow.Group
          )
        )
        for k, v in pairs(groupData) do
          npcPopRow[k] = v
        end
      end
      table.insert(result, npcPopRow)
    end
  end

  return result
end

function p.getNpcByName(npcName)
  return p.query(
    mw.ustring.format(
      [[SELECT * FROM "RSC_NpcList" WHERE "Name" IN (SELECT row_id FROM fld_npcname WHERE "name"='%s')]],
      npcName
    )
  )
end

function p.getNpcPopByNpcName(npcName)
  local npcs = p.getNpcByName(npcName)
  for _, npc in ipairs(npcs) do
    local npcId = npc.row_id
    npc.Pops = p.getNpcPopByNpcId(npcId)
  end
  return npcs
end

local function getEventTableName(id)
  if id > 60000 then
    return "EVT_listDeb01"
  end
  if (id > 40000) then
    return "EVT_listTlk01"
  end
  if (id > 30000) then
    return "EVT_listFev01"
  end
  if (id > 20000) then
    return "EVT_listQst01"
  end
  if (id > 19000) then
    return "EVT_listBl"
  end
  return "EVT_listBf"
end

local function checkTableExist(tablename)
  local talkTableCount =
    p.queryOne(
    mw.ustring.format(
      [[SELECT COUNT(*) FROM pg_catalog.pg_tables WHERE "schemaname" = '%s' AND  "tablename" = '%s']],
      p.language,
      tablename
    )
  )

  if talkTableCount.count == 0 then
    -- mw.log("eventTable: " .. tablename .. " not exist")
    return false
  end

  return true
end

function p.getDialogByEventId(eventId)
  if type(eventId) ~= "number" then
    error("event id must be number")
  end

  if eventId == 0 then
    return {}
  end

  local eventTable = getEventTableName(eventId)
  local event = p.queryOne(mw.ustring.format([[SELECT "evtName" FROM "%s" WHERE "row_id" = %s]], eventTable, eventId))
  local talkTable = event.evtName .. "_ms"

  if checkTableExist(talkTable) == false then
    return {}
  end
  local talks = p.query(mw.ustring.format([[SELECT "name" FROM "%s" WHERE "style" != 62 AND "style" != 0]], talkTable))
  local ret = {}
  for _, talk in ipairs(talks) do
    table.insert(ret, talk.name)
  end
  return ret
end

local function getQuestListTableName(id, ira)
  if ira then
    -- 黄金国
    if id > 2000 then
      return "FLD_QuestListNormalIra", "fld_quest_normal"
    end
  else
    -- 本篇
    if id > 7000 then
      return "FLD_QuestListAchievement", "fld_quest_achievement"
    end
    if id > 6000 then
      return "FLD_QuestListMercenaries", "fld_quest_mercenaries"
    end
    if id > 5000 then
      return "FLD_QuestListBlade", "fld_quest_blade"
    end
    if id > 2000 then
      return "FLD_QuestListNormal", "fld_quest_normal"
    end
    if id > 1000 then
      return "FLD_QuestListMini", "fld_quest_mini"
    end
  end
end

function p.getQuestTitleByQuestId(questId, ira)
  if type(questId) ~= "number" then
    error("quest id must be number")
  end

  if questId == 0 then
    return nil
  end

  local questTable, questTableMs = getQuestListTableName(questId, ira)
  if questTable == nil then
    return nil
  end

  -- 通过QuestTitle查询实际任务名
  local function getQuestTitle(titleId)
    if titleId <= 0 then
      return nil
    end
    local questTitle =
      p.queryOne(mw.ustring.format([[SELECT "name" FROM "%s" WHERE "row_id" = '%s']], questTableMs, titleId))
    return questTitle.name
  end

  local quest =
    p.queryOne(
    mw.ustring.format([[SELECT "QuestTitle", "PRTQuestID" FROM "%s" WHERE "row_id" = '%s']], questTable, questId)
  )

  -- 若结果是子任务,通过PRTQuestID字段查询父任务
  if quest.QuestTitle > 0 then
    return getQuestTitle(quest.QuestTitle)
  elseif quest.PRTQuestID > 0 then
    local prtQuest =
      p.queryOne(
      mw.ustring.format([[SELECT "QuestTitle" FROM "%s" WHERE "row_id" = '%d']], questTable, quest.PRTQuestID)
    )
    local phase = questId - quest.PRTQuestID
    return getQuestTitle(prtQuest.QuestTitle), phase
  end
  return nil
end

function p.getConditonList(id)
  if id <= 0 then
    return nil
  end
  return p.queryOne(mw.ustring.format([[SELECT * FROM "FLD_ConditionList" WHERE "row_id" = '%d']], id))
end

function p.getSubCondition(conditionType, id)
  if id <= 0 then
    return nil
  end
  local table = "FLD_Condition" .. conditionType
  return p.queryOne(mw.ustring.format([[SELECT * FROM "%s" WHERE "row_id" = '%d']], table, id))
end

local function getCharacterTable(id)
  if id > 2000 then
    return "RSC_NpcList", "fld_npcname"
  end
  if id > 1000 then
    return "CHR_Bl", "chr_bl_ms"
  end
  return "CHR_Dr", "chr_dr_ms"
end

function p.getCharacterName(id)
  local tablename, tablems = getCharacterTable(id)
  local character = p.queryOne(mw.ustring.format([[SELECT "Name" FROM "%s" WHERE "row_id" = '%d']], tablename, id))
  if character == nil then
    return nil
  end
  local characterMs =
    p.queryOne(mw.ustring.format([[SELECT "name" FROM "%s" WHERE "row_id" = '%d']], tablems, character.Name))
  if characterMs == nil then
    return nil
  end
  return characterMs.name
end

function p.getFieldSkillName(id)
  local tablename, tablems = "FLD_FieldSkillList", "fld_fieldskilltxt"
  local dataRow = p.queryOne(mw.ustring.format([[SELECT "Name" FROM "%s" WHERE "row_id" = '%d']], tablename, id))
  if dataRow == nil then
    return nil
  end
  local dataMs = p.queryOne(mw.ustring.format([[SELECT "name" FROM "%s" WHERE "row_id" = '%d']], tablems, dataRow.Name))
  if dataMs == nil then
    return nil
  end
  return dataMs.name
end

function p.getAchievementSetName(id)
  local tablename = "CHR_Bl"
  local data =
    p.query(
    mw.ustring.format(
      [[SELECT
      "row_id",
      "BArts1",
      "BArts2",
      "BArts3",
      "BSkill1",
      "BSkill2",
      "BSkill3",
      "FSkill1",
      "FSkill2",
      "FSkill3",
      "ArtsAchievement1",
      "ArtsAchievement2",
      "ArtsAchievement3",
      "SkillAchievement1",
      "SkillAchievement2",
      "SkillAchievement3",
      "FskillAchivement1",
      "FskillAchivement2",
      "FskillAchivement3",
      "KeyAchievement" 
    FROM
      "%s" 
    WHERE
      "ArtsAchievement1" = '%d' 
      OR "ArtsAchievement2" = '%d' 
      OR "ArtsAchievement3" = '%d' 
      OR "SkillAchievement1" = '%d' 
      OR "SkillAchievement2" = '%d' 
      OR "SkillAchievement3" = '%d' 
      OR "FskillAchivement1" = '%d' 
      OR "FskillAchivement2" = '%d' 
      OR "FskillAchivement3" = '%d' 
      OR "KeyAchievement" = '%d']],
      tablename,
      id,
      id,
      id,
      id,
      id,
      id,
      id,
      id,
      id,
      id
    )
  )

  if #data > 0 then
    data = data[1]
  else
    error("在CHR_Bl中找不到包含 achievement set: " .. id .. " 的数据")
  end

  local bladeName = p.getCharacterName(data.row_id)

  if id == data.KeyAchievement then
    return "阶段解锁", bladeName
  end

  local achievementTypeMap = {
    ArtsAchievement1 = "BArts1",
    ArtsAchievement2 = "BArts2",
    ArtsAchievement3 = "BArts3",
    SkillAchievement1 = "BSkill1",
    SkillAchievement2 = "BSkill2",
    SkillAchievement3 = "BSkill3",
    FskillAchivement1 = "FSkill1",
    FskillAchivement2 = "FSkill2",
    FskillAchivement3 = "FSkill3"
  }

  local function getSkillTable(type)
    local type = mw.ustring.sub(type, 1, -2)
    if type == "BArts" then
      return "BTL_Arts_Bl", "btl_arts_bl_ms"
    end
    if type == "BSkill" then
      return "BTL_Skill_Bl", "btl_skill_bl_name"
    end
    if type == "FSkill" then
      return "FLD_FieldSkillList", "fld_fieldskilltxt"
    end
  end

  local achievementType
  for k, v in pairs(achievementTypeMap) do
    if data[k] == id then
      achievementType = achievementTypeMap[k]
    end
  end

  local tablename, tablems = getSkillTable(achievementType)
  local skillId = data[achievementType]

  local skill = p.queryOne(mw.ustring.format([[SELECT "Name" FROM "%s" WHERE "row_id" = '%d']], tablename, skillId))
  if skill == nil then
    return nil
  end

  local skillMs = p.queryOne(mw.ustring.format([[SELECT "name" FROM "%s" WHERE "row_id" = '%d']], tablems, skill.Name))
  if skillMs == nil then
    return nil
  end

  return skillMs.name, bladeName
end

local function getItemTable(id)
  if id > 61000 then
    return "ITM_EtherCrystal"
  end
  if id > 60000 then
    return "ITM_HanaAssist", "itm_orb"
  end
  if id > 59000 then
    return "ITM_HanaNArtsSet", "itm_hana_narts_set_ms"
  end
  if id > 58000 then
    return "ITM_HanaArtsEnh", "itm_orb"
  end
  if id > 57000 then
    return "ITM_HanaAtr", "itm_hana_atr_ms"
  end
  if id > 56000 then
    return "ITM_HanaRole", "itm_hana_role_ms"
  end
  if id > 50000 then
    return "ITM_BoosterList", "itm_booster"
  end
  if id > 45000 then
    return "ITM_CrystalList", "itm_crystal"
  end
  if id > 40000 then
    return "ITM_FavoriteList", "itm_favorite"
  end
  if id > 35000 then
    return "ITM_TresureList", "itm_tresure"
  end
  if id > 30000 then
    return "ITM_CollectionList", "itm_collection"
  end
  if id > 27000 then
    return "ITM_EventList", "itm_evt"
  end
  if id > 26000 then
    return "ITM_InfoList", "itm_info"
  end
  if id > 25000 then
    return "ITM_PreciousList", "itm_precious"
  end
  if id > 20000 then
    return "ITM_SalvageList", "itm_salvage"
  end
  if id > 17000 then
    return "ITM_OrbEquip", "itm_orb"
  end
  if id > 14000 then
    return "ITM_Orb", "itm_orb"
  end
  if id > 10000 then
    return "ITM_PcWpnChip", "itm_pcwpnchip_ms"
  end
  if id > 5000 then
    return "ITM_PcWpn", "itm_pcwpn_ms"
  end
  return "ITM_PcEquip", "itm_pcequip"
end

function p.getItemName(id)
  local tablename, tablems = getItemTable(id)
  if tablename == nil or tablems == nil then
    error("item id: " .. id .. "非法")
  end

  local dataRow = p.queryOne(mw.ustring.format([[SELECT "Name" FROM "%s" WHERE "row_id" = '%d']], tablename, id))
  if dataRow == nil then
    return nil
  end
  local dataMs = p.queryOne(mw.ustring.format([[SELECT "name" FROM "%s" WHERE "row_id" = '%d']], tablems, dataRow.Name))
  if dataMs == nil then
    return nil
  end

  local itemName = dataMs.name
  itemName = mw.ustring.gsub(itemName, "\\%]", "」")
  itemName = mw.ustring.gsub(itemName, "\\%[", "「")
  return itemName
end

function p.getWeatherList()
  local data =
    p.query(
    [[
    SELECT
      "fld_mapinfo"."name" 
    FROM
      "FLD_WeatherInfo"
      INNER JOIN "fld_mapinfo" ON "FLD_WeatherInfo"."msg" = "fld_mapinfo"."row_id" 
    ORDER BY
      "FLD_WeatherInfo".row_id
  ]]
  )

  local result = {}

  for _, v in ipairs(data) do
    table.insert(result, v.name)
  end
  return result
end

return p