Starward项目中祈愿系统抽数统计机制的技术解析

Starward项目中祈愿系统抽数统计机制的技术解析

【免费下载链接】Starward Game Launcher for miHoYo - 米家游戏启动器 【免费下载链接】Starward 项目地址: https://gitcode.com/gh_mirrors/st/Starward

引言:米家游戏玩家的祈愿数据分析痛点

作为米哈游游戏玩家,你是否曾经为以下问题困扰:

  • 记不清自己在某个卡池已经抽了多少发
  • 不确定距离保底还有多少次抽卡
  • 想要统计各个稀有度物品的出货概率
  • 希望分析自己的抽卡历史数据来优化后续抽卡策略

Starward项目的祈愿系统抽数统计机制正是为了解决这些痛点而生。本文将深入解析这一机制的技术实现细节,帮助开发者理解其设计理念和实现方式。

系统架构概览

Starward的祈愿系统采用分层架构设计,主要分为三个层次:

mermaid

核心数据模型解析

GachaLogItem:基础抽卡记录实体

public class GachaLogItem
{
    public long Uid { get; set; }          // 用户ID
    public long Id { get; set; }           // 记录唯一ID
    public int GachaType { get; set; }     // 祈愿类型
    public string Name { get; set; }       // 物品名称
    public string ItemType { get; set; }   // 物品类型
    public int RankType { get; set; }      // 稀有度(3/4/5星)
    public DateTime Time { get; set; }     // 抽卡时间
    public int ItemId { get; set; }        // 物品ID
    public int Count { get; set; }         // 数量
    public string Lang { get; set; }       // 语言
}

GachaLogItemEx:扩展统计模型

public partial class GachaLogItemEx : GachaLogItem
{
    public int Index { get; set; }         // 在保底池中的顺序
    public int Pity { get; set; }          // 当前保底计数
    public double Progress { get; set; }   // 保底进度百分比
    public int ItemCount { get; set; }     // 相同物品数量统计
    public bool IsUp { get; set; }         // 是否为UP物品
    public bool HasUpItem { get; set; }    // 卡池是否有UP物品
}

抽数统计核心算法

保底计数计算机制

// 在GetGachaLogItemEx方法中的保底计算逻辑
foreach (IGachaType type in QueryGachaTypes)
{
    var l = GetGachaLogItemsByQueryType(list, type);
    int index = 0;
    int pity = 0;
    foreach (var item in l)
    {
        item.Index = ++index;    // 顺序编号
        item.Pity = ++pity;      // 保底计数递增
        if (item.RankType == 5)  // 如果抽到5星
        {
            pity = 0;            // 重置保底计数
        }
    }
}

统计数据分析算法

public virtual (List<GachaTypeStats> GachaStats, List<GachaLogItemEx> ItemStats) GetGachaTypeStats(long uid)
{
    var statsList = new List<GachaTypeStats>();
    var allItems = GetGachaLogItemEx(uid);
    
    foreach (IGachaType type in QueryGachaTypes)
    {
        var list = GetGachaLogItemsByQueryType(allItems, type);
        if (list.Count == 0) continue;
        
        var stats = new GachaTypeStats
        {
            GachaType = type.Value,
            Count = list.Count,
            Count_5_Up = list.Count(x => x.RankType == 5 && x.IsUp),
            Count_5 = list.Count(x => x.RankType == 5),
            Count_4 = list.Count(x => x.RankType == 4),
            Count_3 = list.Count(x => x.RankType == 3),
            // ... 其他统计字段
        };
        
        // 概率计算
        stats.Ratio_5 = (double)stats.Count_5 / stats.Count;
        stats.Ratio_4 = (double)stats.Count_4 / stats.Count;
        stats.Ratio_3 = (double)stats.Count_3 / stats.Count;
        
        // 平均抽数计算
        stats.Average_5 = (double)(stats.Count - stats.Pity_5) / stats.Count_5;
        if (stats.Count_5_Up > 0)
        {
            stats.Average_5_Up = (double)(stats.Count - stats.Pity_5) / stats.Count_5_Up;
        }
    }
    return (statsList, groupStats);
}

数据结构设计详解

GachaTypeStats 统计数据结构

字段名类型描述计算公式
Countint总抽数-
Count_5int5星物品数量Count(x => x.RankType == 5)
Count_5_UpintUP的5星数量Count(x => x.RankType == 5 && x.IsUp)
Count_4int4星物品数量Count(x => x.RankType == 4)
Count_3int3星物品数量Count(x => x.RankType == 3)
Ratio_5double5星出货率Count_5 / Count
Ratio_4double4星出货率Count_4 / Count
Ratio_3double3星出货率Count_3 / Count
Average_5double平均5星抽数(Count - Pity_5) / Count_5
Average_5_Updouble平均UP5星抽数(Count - Pity_5) / Count_5_Up
Pity_5int当前5星保底计数最后5星后的抽数
Pity_4int当前4星保底计数最后4星后的抽数

游戏特定保底规则处理

// 武器池和光锥池的特殊保底规则
public double Progress => (double)Pity / ((GachaType is GenshinGachaType.WeaponEventWish 
    or StarRailGachaType.LightConeEventWarp 
    or ZZZGachaType.WEngineChannel) ? 80 : 90) * 100;

数据存储与查询优化

SQLite数据库表结构

-- 抽卡记录表结构
CREATE TABLE GachaLog (
    Uid INTEGER,      -- 用户ID
    Id INTEGER,       -- 记录ID
    GachaType INTEGER,-- 祈愿类型
    Name TEXT,        -- 物品名称
    ItemType TEXT,    -- 物品类型
    RankType INTEGER, -- 稀有度
    Time DATETIME,    -- 抽卡时间
    ItemId INTEGER,   -- 物品ID
    Count INTEGER,    -- 数量
    Lang TEXT         -- 语言
);

-- 祈愿URL缓存表
CREATE TABLE GachaLogUrl (
    GameBiz TEXT,     -- 游戏业务标识
    Uid INTEGER,      -- 用户ID
    Url TEXT,         -- 祈愿URL
    Time DATETIME     -- 缓存时间
);

查询性能优化策略

  1. 索引优化:在Uid、GachaType、Time字段上建立索引
  2. 分批处理:支持分页获取抽卡记录,避免一次性加载大量数据
  3. 内存缓存:对统计结果进行缓存,减少重复计算
  4. 异步操作:所有数据库操作都采用异步方式,避免UI阻塞

多游戏支持架构

Starward支持米哈游多款游戏的祈愿系统,通过抽象接口实现统一处理:

// 祈愿类型接口
public interface IGachaType
{
    int Value { get; }
    string ToLocalization();
}

// 游戏特定实现
public class GenshinGachaType : IGachaType { /* 原神实现 */ }
public class StarRailGachaType : IGachaType { /* 星穹铁道实现 */ }
public class ZZZGachaType : IGachaType { /* 绝区零实现 */ }

实战应用示例

抽卡记录分析流程

mermaid

统计信息展示示例

假设用户有以下抽卡数据:

  • 角色祈愿池:300抽,5个5星,其中3个UP
  • 武器祈愿池:150抽,2个5星,其中1个UP

系统将自动计算并显示:

  • 角色池5星出货率:1.67%
  • 角色池平均5星抽数:60抽
  • 角色池UP5星平均抽数:100抽
  • 当前保底计数:45抽(距离保底还有45抽)

技术亮点与创新

  1. 统一的跨游戏架构:一套代码支持多款米哈游游戏
  2. 实时保底计算:动态计算当前保底状态和进度
  3. 智能数据去重:避免重复导入相同抽卡记录
  4. 多维度统计分析:提供全面的抽卡数据洞察
  5. 离线数据支持:所有数据本地存储,支持离线分析

总结

Starward项目的祈愿系统抽数统计机制通过精心的架构设计和算法实现,为米哈游游戏玩家提供了强大的抽卡数据分析能力。其核心技术包括:

  • 基于ORM的数据持久化层
  • 多游戏统一的抽象接口设计
  • 实时保底计数和概率统计算法
  • 高性能的数据查询和缓存机制
  • 丰富的统计维度和可视化展示

这一机制不仅解决了玩家的实际需求,也为开发者提供了可扩展、可维护的技术架构范例。通过深入理解这一机制,开发者可以更好地进行二次开发或类似系统的构建。

【免费下载链接】Starward Game Launcher for miHoYo - 米家游戏启动器 【免费下载链接】Starward 项目地址: https://gitcode.com/gh_mirrors/st/Starward

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值