Files
back_cantanBuilding/Assets/Scripts/DataCenter/OfferChainsChestManager.cs
2026-05-26 16:15:54 +08:00

487 lines
17 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using asap.core;
using cfg;
using game;
using GameCore;
using Newtonsoft.Json;
using UnityEngine;
namespace DataCenter
{
// 锁链礼包
public class TOfferChainsData
{
public class TItem
{
public int Id;
public int Item;
public int Number;
// 0 可选1 高亮 2 糊了 ,锁链隐藏 应该转换成Enum
public int Status;
// public int SKUId;
}
public bool FirstOpen; // 是否首次打开
public int EventId; // 默认存一下ID
public DateTime StartTime; // 开始时间
public DateTime EndTime;// 结束时间
public int ItemId = -1;
// 当前抽奖次数,必须抽了才会更新
public int LotteryNum;
public List<TItem> Items;
public bool Finished;
public int ChestReward;
public List<int> RewardList; // 当前获得的奖励Item
}
public class OfferChainsChestManager
{
public const string SaveKey = "OfferChainsChestData";
[Inject] public Tables _tables { get; set; }
// 计入当前Event
private FishingEvent _fishingEvent;
//
public EventOfferChainsChestMain OfferChainsChestMain { get; set; }
public List<EventOfferChainsChestRewards> OfferChainsChestRewards { get; set; }
// 当前可保存数据
public TOfferChainsData OfferChainsData { get; private set; }
public List<int> ValidIds;
public bool IsFirstOpen
{
get => OfferChainsData.FirstOpen;
set
{
if (OfferChainsData.FirstOpen)
{
OfferChainsData.FirstOpen = false;
DoSave();
}
}
}
public void UpdateEventData(FishingEvent fishingEvent)
{
Log($"Refresh - > {fishingEvent}");
_fishingEvent = fishingEvent;
UpdateLocalData();
}
private void UpdateLocalData()
{
//选择当前的 Main
var redirectId = _fishingEvent.RedirectID;
var configList = _tables.TbEventOfferChainsChestMain.DataList;
foreach (var eventChallenge in configList.Where(eventChallenge => eventChallenge.ID == redirectId))
{
OfferChainsChestMain = eventChallenge;
break;
}
OfferChainsChestRewards = _tables.TbEventOfferChainsChestRewards.DataList;
// SkuIds = OfferChainsChestMain.IapList;
}
public void Init()
{
Log("Init-> ");
if (OfferChainsData == null)
{
if (_fishingEvent == null) // 不存在Event
{
return;
}
InitOfferChainsData();
}
UpdateOfferChainsData();
}
//
private void ProcessLastOne()
{
if (OfferChainsData != null)
{
if(!IsTimeAllow())
{
Settle();
ClearOfferChainsData();
}
else if (IsCanGetFinalReward())
{
Settle(); // 补充一下最终大奖
}
}
}
private void UpdateOfferChainsData()
{
// 更新可用数据
UpdateTime();
UpdateOfferChainsItems();
UpdateLotteryItemId();
}
private void InitOfferChainsData()
{
var limitedTime = (LimitedTime)_fishingEvent.TimeDefinition;
var startTime = GlobalUtils.TryParseDateTime(limitedTime.StartTime, ZZTimeHelper.UtcNow());
var endTime = GlobalUtils.TryParseDateTime(limitedTime.EndTime, ZZTimeHelper.UtcNow());
OfferChainsData = new TOfferChainsData
{
FirstOpen = true,
EventId = _fishingEvent.ID,
StartTime = startTime,
EndTime = endTime,
Items = new List<TOfferChainsData.TItem>(),
RewardList = new List<int>(),
ChestReward = OfferChainsChestMain.ChestReward, // 最终大奖存储下,方便额外的处理
};
for (var i = 0; i < OfferChainsChestRewards.Count; ++i)
{
var item = new TOfferChainsData.TItem
{
Id = OfferChainsChestRewards[i].ID,
Item = OfferChainsChestRewards[i].Item,
Number = OfferChainsChestRewards[i].Number,
Status = 0,
// SKUId = OfferChainsChestMain.IapList[i],
};
OfferChainsData.Items.Add(item);
}
}
public bool IsTimeAllow()
{
var now = ZZTimeHelper.UtcNow();
var startTime = OfferChainsData.StartTime;
var endTime = OfferChainsData.EndTime;
#if UNITY_EDITOR
var timeOpened = (now - startTime).TotalSeconds;
var timeEnded = ( endTime -now).TotalSeconds;
Log($"StartTime: {startTime} Now: {now} EndTime:{endTime} TimeOpened:{timeOpened} TimeToEnd:{timeEnded} Other: {1800000- timeOpened} IsTimeAllow => {now <= endTime}");
#endif
return now >= startTime && now <= endTime;
}
public void CheckInit()
{
ProcessLastOne();
Init();
}
// ReSharper disable Unity.PerformanceAnalysis
private static void Log(object t)
{
Debug.Log($"<color=yellow>OfferChainsChestManager -> {t} </color>");
}
public bool CheckOpen()
{
//
if (OfferChainsData == null) return false;
//
if (!IsTimeAllow()) return false;
if (OfferChainsChestMain == null)
{
return false;
}
if (IsFinished())
{
return false;
}
return true;
}
public bool IsFinished()
{
return OfferChainsData?.Finished ?? false;
}
private void DoSave()
{
PlayFabMgr.Instance.UpdateUserDataValue(SaveKey, JsonConvert.SerializeObject(OfferChainsData));
}
public void LoadChainsChestData(string dataValue)
{
OfferChainsData = JsonConvert.DeserializeObject<TOfferChainsData>(dataValue);
}
// 进入游戏舞台
public async void OnEnterGameAct()
{
Log("OnEnterGameAct()");
IsFirstOpen = false;
await UIManager.Instance.ShowUI(new UIType(OfferChainsChestMain.UIPanel));
}
private static T WeightedRandom<T>(Dictionary<T, int> weightTable)
{
// 1. 计算总权重
var totalWeight = weightTable.Values.Sum();
// 2. 生成随机数
var randomValue = UnityEngine.Random.Range(0, totalWeight);
// 3. 线性遍历选择
var currentWeight = 0;
foreach (var (key, value) in weightTable)
{
currentWeight += value;
if (randomValue < currentWeight)
return key;
}
return default; // 理论上不会执行到这里
}
// 活动当前的抽奖索引
private int CalcLotteryItemId()
{
var lotteryNum = OfferChainsData.LotteryNum;
// var validIds = (from item in OfferChainsData.Items where item.Status == 0 select item.Id).ToList();
ValidIds = (from item in OfferChainsData?.Items where item.Status == 0 select item.Id).ToList();
if (ValidIds.Count <= 0)
{
return -1;
}
if (OfferChainsChestRewards == null)
{
return -1;
}
//
// while (true)
// {
var dict = OfferChainsChestRewards.Where(
item => ValidIds.Contains(item.ID) && item.LimitConfig <= lotteryNum)
.ToDictionary(elem => (elem.ID, elem.LimitConfig), elem => elem.Weight);
var (elemId, limitConfig) = WeightedRandom(dict);
Log($"CalcLotteryItemId -> {lotteryNum} {elemId} {limitConfig}");
// if (limitConfig >0 && lotteryNum > limitConfig )
return elemId;
// }
}
public int GetLotteryItemId()
{
if (OfferChainsData.ItemId == -1)
{
UpdateLotteryItemId();
}
return OfferChainsData.ItemId;
}
private void UpdateOfferChainsItems()
{
if (OfferChainsData != null && _fishingEvent != null && OfferChainsData.EventId == _fishingEvent.ID)
{
var items = OfferChainsData.Items;
if (OfferChainsChestRewards is { Count: > 0 })
{
for (int i = 0; i < items.Count; ++i)
{
EventOfferChainsChestRewards reward = null;
if (i < OfferChainsChestRewards.Count)
{
reward = OfferChainsChestRewards[i];
}
if (reward != null)
{
items[i].Id = reward.ID;
items[i].Item = reward.Item;
items[i].Number = reward.Number;
}
}
}
if (OfferChainsChestMain != null)
{
OfferChainsData.ChestReward = OfferChainsChestMain.ChestReward;
}
}
// for (var i = 0; i < OfferChainsChestRewards.Count; ++i)
// {
// var item = new TOfferChainsData.TItem
// {
// Id = OfferChainsChestRewards[i].ID,
// Item = OfferChainsChestRewards[i].Item,
// Number = OfferChainsChestRewards[i].Number,
// Status = 0,
// };
// OfferChainsData.Items.Add(item);
// }
}
private void UpdateTime()
{
if (OfferChainsData != null && _fishingEvent != null && OfferChainsData.EventId == _fishingEvent.ID)
{
var limitedTime = (LimitedTime)_fishingEvent.TimeDefinition;
var startTime = GlobalUtils.TryParseDateTime(limitedTime.StartTime, ZZTimeHelper.UtcNow());
var endTime = GlobalUtils.TryParseDateTime(limitedTime.EndTime, ZZTimeHelper.UtcNow().AddDays(-1));
OfferChainsData.StartTime = startTime;
OfferChainsData.EndTime = endTime;
}
}
private void UpdateLotteryItemId()
{
// ValidIds = (from item in OfferChainsData?.Items where item.Status == 0 select item.Id).ToList();
var targetId = CalcLotteryItemId();
OfferChainsData.ItemId = targetId;
DoSave();
}
public void FinishLottery(int targetId)
{
Log($"FinishLottery -> {targetId}");
var lastItem = OfferChainsData.Items.SingleOrDefault(it => it.Id == targetId);
if (lastItem is {Status: not 2})
{
lastItem.Status = 2;
// OfferChainsData.LotteryNum += 1;
// OfferChainsData.RewardList.Add(targetId);
UpdateLotteryItemId();
}
}
public bool IsCanGetFinalReward()
{
return OfferChainsData.LotteryNum >= OfferChainsData.Items.Count
&& !OfferChainsData.Finished;
}
public void ClearOfferChainsData()
{
OfferChainsData = null;
DoSave();
}
public TOfferChainsData.TItem GetTItemById(int targetId)
{
var lastItem = OfferChainsData.Items.FirstOrDefault(it => it.Id == targetId);
return lastItem;
}
public int GetDropIdById(int id)
{
var item = GetTItemById(id);
var itemData = _tables.TbItem.GetOrDefault(item.Item);
return itemData.RedirectID;
}
public void OnGetFinalReward()
{
// var item = _tables.TbItem.GetOrDefault(OfferChainsChestMain.ChestReward);
var item = _tables.TbItem.GetOrDefault(OfferChainsData.ChestReward);
var itemFinal = GContext.container.Resolve<PlayerItemData>()
.GetItemDropPackageItemList(item.RedirectID, 1);
GContext.container.Resolve<PlayerItemData>().AddItem(itemFinal);
GContext.Publish(new ShowData(itemFinal));
GContext.Publish(new ShowData());
OfferChainsData.Finished = true;
DoSave();
GContext.Publish(new OfferChainsRefreshEvent());
}
public float GetProbability(int id)
{
var theIdWeight = OfferChainsChestRewards .FirstOrDefault(item => item.ID == id)?.Weight ?? 0;
var weightTable = OfferChainsChestRewards
.Where(item => !IsItemFinished(item.ID) )
.Select(item => item.Weight ).ToList();
var totalWeight = weightTable.Sum();
return (float)Math.Round((float)theIdWeight / totalWeight * 100, 2);
}
private bool IsItemFinished(int itemID)
{
var lastItem = OfferChainsData.Items.SingleOrDefault(it => it.Id == itemID);
return lastItem?.Status == 2;
}
public TimeSpan GetTimeRemain()
{
if (OfferChainsData != null)
{
return OfferChainsData.EndTime - ZZTimeHelper.UtcNow();
}
// 活动未开始
return ZZTimeHelper.UtcNow().AddDays(-1) - ZZTimeHelper.UtcNow();
}
public void Settle()
{
if (IsCanGetFinalReward())
{
OnGetFinalReward();
}
}
public bool UIRunning { get; set; } = false;
public void OnBuySuccess()
{
Log("OnBuySuccess -> ");
OfferChainsData.RewardList.Add(OfferChainsData.ItemId);
OfferChainsData.LotteryNum += 1;
if (IsCanGetFinalReward())
{
OfferChainsData.RewardList.Add(OfferChainsData.ChestReward);
}
EventTracking();
//NEXT TURN
if (UIRunning)
{ // 播放动画逻辑交给UI
return;
}
// 补单,直接给奖励
FinishLottery(OfferChainsData.ItemId);
Settle();
}
public void EventTracking()
{
//var price = GetPayAmountById(OfferChainsData.ItemId);
var price = GetIapItemListThisTime(OfferChainsData.LotteryNum -1)?.PaymentAmount ??0F;
var itemEnt = GetTItemById(OfferChainsData.ItemId);
var rewardStr = string.Join(',', OfferChainsData.RewardList);
var number = OfferChainsData.LotteryNum;
#if AGG
using (var e = GEvent.TackEvent("offer_chainchest"))
{
e.AddContent("event_id", OfferChainsData.EventId);
e.AddContent("number",number);
e.AddContent("price", price);
e.AddContent("reward",OfferChainsData.ItemId);
e.AddContent("reward_claimed_list", rewardStr);
}
#endif
Log($"EventTracking: event_id: {OfferChainsData.EventId} number: {number} price: {price} " +
$"reward :{OfferChainsData.ItemId} reward_claimed_list :{rewardStr}" );
}
public IAPItemList GetIapItemListThisTime()
{
return GetIapItemListThisTime(OfferChainsData.LotteryNum);
}
private IAPItemList GetIapItemListThisTime(int index)
{
// var index = OfferChainsData.LotteryNum;
index = Mathf.Clamp(index, 0, OfferChainsChestMain.IapList.Count -1);
var iapId = OfferChainsChestMain.IapList[index];
var iAPItemList = _tables.TbIAPItemList.GetOrDefault(iapId);
return iAPItemList;
}
}
}