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

Module:Game/Banners/Data

From Umamusume Wiki
Jump to navigation Jump to search

Documentation for this module may be created at Module:Game/Banners/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")

---@class BannerData
---@field id string
---@field name string
---@field bannerType string
---@field cardType string
---@field imagePage string
---@field pickups BannerPickupData[]
---@field selects BannerSelectPickupData[]
---@field hasRateup boolean
---@field startDateFormat string
---@field startDateTime number
---@field endDateFormat string
---@field endDateTime number

---@class BannerPickupData
---@field cardId string
---@field rarity string
---@field odds number

---@class BannerSelectPickupData
---@field cardId string
---@field recommended boolean

---Get a list of all (free gem) gacha banners on the JP server
---@return BannerData[] bannerDatas keyed by ID
function Data.getBannersJP()
    local gacha_datas = Game.queryMaster {
        from = "gacha_data",
        where = "type IN (3, 11, 12)"
    }
    return Data._mapDatas(gacha_datas, false)
end

---Get a list of all (free gem) gacha banners currently running on the JP server
---@return BannerData[] bannerDatas keyed by ID
function Data.getCurrentBannersJP()
    local time = os.time()
    local gacha_datas = Game.queryMaster {
        from = "gacha_data",
        where = string.format("type IN (3, 11, 12) AND start_date < %s AND end_date > %s", time, time),
    }
    return Data._mapDatas(gacha_datas, false)
end

---Get a list of all (free gem) gacha banners on the EN server
---@return BannerData[] bannerDatas keyed by ID
function Data.getBannersEN()
    local gacha_datas = Game.queryMasterEN {
        from = "gacha_data",
        where = "type IN (3, 11, 12)"
    }
    return Data._mapDatas(gacha_datas, true)
end

---Get a list of all (free gem) gacha banners currently running on the EN server
---@return BannerData[] bannerDatas keyed by ID
function Data.getCurrentBannersEN()
    local time = os.time()
    local gacha_datas = Game.queryMasterEN {
        from = "gacha_data",
        where = string.format("type IN (3, 11, 12) AND start_date < %s AND end_date > %s", time, time),
    }
    return Data._mapDatas(gacha_datas, true)
end

function Data._mapDatas(gacha_datas, en)
    local gachaIds = {}
    for _, gacha_data in ipairs(gacha_datas) do
        table.insert(gachaIds, gacha_data.id)
    end
    local gachaIdsInsert = table.concat(gachaIds, ',')

    local banner_datas = (en and Game.queryMasterEN or Game.queryMaster) {
        from = "banner_data",
        where = string.format("transition IN (%s)", gachaIdsInsert)
    }
    local gachaBannerMap = {}
    for _, banner_data in ipairs(banner_datas) do
        gachaBannerMap[banner_data.transition] = banner_data
    end

    -- Select all units that are either marked as rateup, or, if banner has no ratups, are max rarity
    local gacha_availables = (en and Game.queryMasterEN or Game.queryMaster) {
        from = "gacha_available",
        where = string.format("gacha_id IN (%s) AND (CASE WHEN (SELECT count(*)"
            .. " FROM gacha_available as ga WHERE ga.gacha_id=gacha_available.gacha_id"
            .. " AND ga.is_pickup=1) >= 1 THEN is_pickup=1 ELSE rarity=3 END)", gachaIdsInsert),
        order_by = "recommend_order DESC"
    }
    local gachaAvailableMap = {}
    for _, gacha_available in ipairs(gacha_availables) do
        local key = gacha_available.gacha_id
        if gachaAvailableMap[key] == nil then gachaAvailableMap[key] = {} end
        table.insert(gachaAvailableMap[key], gacha_available)
    end

    --- remove "not en and" when EN adds select_pickup table
    local select_pickups = not en and (en and Game.queryMasterEN or Game.queryMaster) {
        from = "select_pickup",
        where = string.format("gacha_id IN (%s)", gachaIdsInsert),
        order_by = "recommend_order DESC",
    }
    local selectPickupMap = {}
    for _, select_pickup in ipairs(select_pickups or {}) do
        local key = select_pickup.gacha_id
        if selectPickupMap[key] == nil then selectPickupMap[key] = {} end
        table.insert(selectPickupMap[key], select_pickup)
    end

    local gachaNames = en and Game.getENText(26, gachaIds) or Game.getJPText(26, gachaIds)

    local gachaTypesMap = {
        ['1'] = "Debug",
        ['2'] = "Ticket",
        ['3'] = "Standard",
        ['5'] = "Paid Guarantee",
        ['10'] = "Paid Group Select",
        ['11'] = "Twinkle Collection",
        ['12'] = "Select Pickup",
        ['13'] = "Live Gacha?",
        ['14'] = "Stepup",
        ['15'] = "Stamp Sheet"
    }
    local cardTypesMap = {
        ['1'] = "Trainee",
        ['2'] = "Support"
    }

    local datas = {}
    for _, gacha_data in ipairs(gacha_datas) do
        local banner_data = gachaBannerMap[gacha_data.id]
        local availables = gachaAvailableMap[gacha_data.id] or {}
        local selectPickups = selectPickupMap[gacha_data.id] or {}
        if banner_data ~= nil then
            local imagePage = string.format("Game Banner %s %s.png", banner_data.banner_image_id or banner_data
                .banner_id, en and "EN" or "JP")

            local name = gachaNames[gacha_data.id] or ''
            local bannerType = gachaTypesMap[gacha_data.type]
            local cardType = cardTypesMap[gacha_data.card_type]

            local startDate = os.date("%B %d, %Y", gacha_data.start_date) .. ''
            local endDate = os.date("%B %d, %Y", gacha_data.end_date) .. ''

            local hasRateup = false

            local pickups = {}
            for _, gacha_available in ipairs(availables) do
                if gacha_available.is_pickup == '1' then hasRateup = true end
                local pickupData = { ---@type BannerPickupData
                    cardId = gacha_available.card_id,
                    rarity = gacha_available.rarity,
                    odds = tonumber(gacha_available.odds) / 10000
                }
                table.insert(pickups, pickupData)
            end

            local selects = {}
            for _, select in ipairs(selectPickups) do
                local selectData = { ---@type BannerSelectPickupData
                    cardId = select.card_id,
                    recommended = select.recommend_type == '1'
                }
                table.insert(selects, selectData)
            end

            local data = { ---@type BannerData
                id = gacha_data.id,
                name = name,
                bannerType = bannerType,
                cardType = cardType,
                imagePage = imagePage,
                pickups = pickups,
                selects = selects,
                hasRateup = hasRateup,
                startDateFormat = startDate,
                startDateTime = tonumber(gacha_data.start_date) or 0,
                endDateFormat = endDate,
                endDateTime = tonumber(gacha_data.end_date) or 0,
            }
            datas[gacha_data.id] = data
        end
    end
    return datas
end

return Data