Welcome to the Umamusume Wiki! If you want to contribute, please read the guidelines.

Module:Game/Supports/Data

From Umamusume Wiki
Jump to navigation Jump to search

Documentation for this module may be created at Module:Game/Supports/Data/doc

--[[
    !! THIS PAGE IS MANAGED BY GITLAB !!
    ANY EDITS TO PAGE CONTENT WILL BE OVERWRITTEN
    TO MAKE CHANGES, PLEASE SUBMIT A MERGE REQUEST AT https://gitlab.com/umamusume-wiki/lua-modules
]]

local Data = {}
local Game = require("Module:Game")
local Utils = require("Module:Utils")
local BannerUtils = require("Module:Game/Banners/Utils")
local Unique = require("Module:Game/Supports/Data/Unique")
local Leveled = require("Module:Game/Supports/Data/Leveled")

---@class SupportData
---@field id string
---@field characterId string
---@field groupCharacterIds string[]|nil
---@field nameJP string
---@field displayNameJP string
---@field episodeJP string[]
---@field nameEN string|nil
---@field displayNameEN string|nil
---@field episodeEN string[]|nil
---@field availableEN boolean
---@field releaseDateJP string|nil
---@field releaseDateEN string|nil
---@field rarity string
---@field attribute string
---@field hintSkillIds string[]
---@field effects SupportDataEffects
---@field iconPage string
---@field cardPage string
---@field fullPage string

---@class SupportDataEffects
---@field unique SupportDataEffectUnique|nil
---@field leveled SupportDataEffectLeveled[]
---@field calculated SupportDataEffectCalculated[]

---Get support data by its ID
---@param supportId string
---@return SupportData|nil
function Data.getSupport(supportId)
    local support_card_datas = Game.queryMaster {
        from = "support_card_data",
        where = string.format("id = %s", supportId),
        limit = 1
    }
    if support_card_datas == nil or #support_card_datas == 0 then return nil end
    return Data._mapDatas(support_card_datas)[Utils.normalString(supportId)]
end

---Get a batch of supports by list of IDs
---@param supportIds string[]
---@return SupportData[]
function Data.getBatch(supportIds)
    local supportIdsInsert = table.concat(supportIds, ",")
    local support_card_datas = Game.queryMaster {
        from = "support_card_data",
        where = string.format("id IN (%s)", supportIdsInsert)
    }
    local mapped = Data._mapDatas(support_card_datas)
    local datas = {}
    for _, supportId in ipairs(supportIds) do
        table.insert(datas, mapped[Utils.normalString(supportId)])
    end
    return datas
end

---@param support_datas table[]
---@return SupportData[]
function Data._mapDatas(support_datas)
    local supportIds = {}
    for _, support_data in ipairs(support_datas) do
        table.insert(supportIds, support_data.id)
    end
    local supportIdsInsert = table.concat(supportIds, ',')

    local namesJP = Game.getJPText(76, supportIds)
    local displayNamesJP = Game.getJPText(75, supportIds)
    local episodesJP = Game.getJPText(88, supportIds)

    local namesEN = Game.getENText(76, supportIds)
    local displayNamesEN = Game.getENText(75, supportIds)
    local episodesEN = Game.getENText(88, supportIds)

    local support_datas_en = Game.queryMasterEN {
        from = "support_card_data",
        where = string.format("id IN (%s)", supportIdsInsert),
        data = { "id" }
    }
    local availabilityEN = {}
    for _, support_data in ipairs(support_datas_en) do
        if support_data[1] ~= nil then -- single results will mess up the iteration
            availabilityEN[support_data[1]] = true
        end
    end

    -- Get release dates for support cards from gacha data
    local releaseDatesJP = BannerUtils.getReleaseDates(supportIds, "support", "JP")
    local releaseDatesEN = BannerUtils.getReleaseDates(supportIds, "support", "EN")

    local rarityMap = {
        ['1'] = "R",
        ['2'] = "SR",
        ['3'] = "SSR",
    }

    local groupCharacterMap = {}
    local support_card_groups = Game.queryMaster {
        from = "support_card_group",
        where = string.format("support_card_id IN (%s)", supportIdsInsert),
    }
    for _, support_card_group in ipairs(support_card_groups) do
        local key = support_card_group.support_card_id
        if groupCharacterMap[key] == nil then groupCharacterMap[key] = {} end
        table.insert(groupCharacterMap[key], support_card_group.chara_id)
    end

    local hintMap = {}
    local single_mode_hint_gains = Game.queryMaster {
        from = "single_mode_hint_gain",
        where = string.format("support_card_id IN (%s) AND hint_gain_type=0", supportIdsInsert),
        order_by = "hint_group ASC"
    }
    for _, single_mode_hint_gain in ipairs(single_mode_hint_gains) do
        local key = single_mode_hint_gain.support_card_id
        if hintMap[key] == nil then hintMap[key] = {} end
        table.insert(hintMap[key], single_mode_hint_gain.hint_value_1)
    end

    local uniqueMap = Unique.getUniqueEffects(support_datas)
    local leveledMap = Leveled.getSupportLevels(support_datas)
    local calculatedMap = Leveled.getCalculatedLevels(uniqueMap, leveledMap)

    local datas = {}
    for _, support_data in ipairs(support_datas) do
        local episodeRawJP = episodesJP[support_data.id] or ''
        local episodeJP = Utils.splitLines(episodeRawJP)

        local episodeRawEN = episodesEN[support_data.id]
        local episodeEN = episodeRawEN and Utils.splitLines(episodeRawEN) or nil
        
        local releaseDateJP = releaseDatesJP[support_data.id]  -- stores Unix timestamp
        local releaseDateEN = releaseDatesEN[support_data.id]  -- stores Unix timestamp

        local attribute = Data._mapAttribute(support_data.command_id, support_data.support_card_type)
        local unique = uniqueMap[support_data.id]
        local leveled = leveledMap[support_data.id]
        local calculated = calculatedMap[support_data.id]

        local data = { ---@type SupportData
            id = support_data.id,
            characterId = support_data.chara_id,
            groupCharacterIds = groupCharacterMap[support_data.id],
            nameJP = namesJP[support_data.id],
            displayNameJP = displayNamesJP[support_data.id],
            episodeJP = episodeJP,
            nameEN = namesEN[support_data.id],
            displayNameEN = displayNamesEN[support_data.id],
            episodeEN = episodeEN,
            availableEN = availabilityEN[support_data.id] == true,
            releaseDateJP = releaseDateJP,
            releaseDateEN = releaseDateEN,
            rarity = rarityMap[support_data.rarity] or support_data.rarity,
            attribute = attribute,
            hintSkillIds = hintMap[support_data.id] or {},
            effects = {
                unique = unique,
                leveled = leveled,
                calculated = calculated
            },
            iconPage = string.format("Support Card %s Icon.png", support_data.id),
            cardPage = string.format("Support Card %s Card.png", support_data.id),
            fullPage = string.format("Support Card %s.png", support_data.id),
        }
        datas[support_data.id] = data
    end
    return datas
end

---@param commandId string
---@param supportCardType string
---@return string
function Data._mapAttribute(commandId, supportCardType)
    if supportCardType == '2' then return "Pal" end
    if supportCardType == '3' then return "Group" end
    if commandId == '101' then return "Speed" end
    if commandId == '102' then return "Power" end
    if commandId == '103' then return "Guts" end
    if commandId == '105' then return "Stamina" end
    if commandId == '106' then return "Wit" end
    return string.format("Unknown (%s, %s)", commandId, supportCardType)
end

return Data