Files
ft/Client/Assets/Scripts/EventPartnerGather/PartnerInfoManager.cs
2026-06-29 21:18:33 +08:00

478 lines
18 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using asap.core;
using cfg;
using DataCenter;
using game;
using GameCore;
using Newtonsoft.Json;
using TMPro;
using UniRx;
using UnityEngine;
using EventPartnerGatherDetail = EventPartnerGatherRequests.EventPartnerGatherDetail;
using EventBuildBotInfo = EventPartnerData.EventBuildBotInfo;
using ScrollViewItemInfo = EventPartnerScrollViewItem.ScrollViewItemInfo;
namespace EventPartnerGather
{
// 存储Cache
public class PartnerInfoManager : IDisposable
{
// [Inject]
private static Tables _tables { get; set; } = GContext.container.Resolve<Tables>();
private FriendService _friendService { get; set; } = GContext.container.Resolve<FriendService>();
private IUserService _userService { get; } = GContext.container.Resolve<IUserService>();
// private bool _lock = false;
// private bool _whole = false;
// 缓存
private string _playerPreferenceKey;
//
private CompositeDisposable disposables;
// EventId
public int EventId { get; set; }
//
public static readonly int BuilderCapacity = _tables.TbEventPartnerConfig.InvitationCount[1];
public readonly BuildPartner[] BuildPartners = new BuildPartner[BuilderCapacity];
//
public bool IsFullyMatched => BuildPartners.All(b => b != null && b.IsValid());
public int ActiveFriendCountThreshold => _tables.TbEventPartnerConfig.FriendRecommendParam1[0];
// 当前用户的build数据
public bool HasRequestPartners => EventBuildInfo is { RequestPartners: {Count: > 0} } && !IsFullyMatched;
public bool HasMoreScore => BuildPartners.Any(b => b != null && b.IsValid() && b.GetExtraScore() > 0);
//
public EventPartnerGatherDetail EventBuildInfo { get; set; }
// 积分
private Dictionary<int, Dictionary<string, int>> Scores { get; set; }
//
public EventPartnerGatherCache Cache { get; set; } = new();
private static void LogError(object t)
{
Debug.LogError($"<color=red>PartnerInfoManager-> {t} </color>");
}
private static void Log(object t)
{
Debug.Log($"<color=cyan>PartnerInfoManager-> {t} </color>");
}
private static void ELog(object t)
{
#if UNITY_EDITOR
Debug.Log($"<color=cyan>PartnerInfoManager-> {t} </color>");
#endif
}
private static void LogWarning(object t)
{
Debug.LogWarning($"<color=yellow>PartnerInfoManager-> {t} </color>");
}
public void Init()
{
ELog($"Init eventId={EventId}");
// 获取一下缓存数据
GetPlayerCache();
if (disposables != null)
{
disposables.Dispose();
disposables = null;
}
for (int i = 0;i < BuildPartners.Length;++i)
{
BuildPartners[i] = null;
}
// BuildPartner
disposables = new CompositeDisposable();
//
GContext.OnEvent<EventSavePartnerInfoCache>().Subscribe(OnEventSaveData).AddTo(disposables);
}
public void Dispose()
{
disposables?.Dispose();
disposables = null;
}
// 注册时间
public void OnEventSaveData(EventSavePartnerInfoCache evt)
{
ELog($"OnEventSaveData eventId={EventId}");
//
SavePlayerPreferenceData();
// Cache.Save
//ToPlayfabData().Save();
}
public void LoadBuildInfo(EventPartnerGatherDetail detail, Dictionary<int, EventBuildBotInfo> bots)
{
EventBuildInfo = detail;
EventBuildInfo.Partners ??= new List<PlayerInfo>();
var partners = detail.Partners;
// // FIX Load 删除的时候保证起作用
// for (var i = 0; i < BuilderCapacity; ++i)
// {
// BuildPartners[i] = new BuildPartner();
// }
// BuildPartners[index]
if (partners != null)
{
for (int slotId = 0; slotId < partners.Count; slotId++)
{
ResolveBuildInfoData(slotId, partners[slotId], bots);
}
}
// 为空的话初始话
// EventBuildInfo.RefusedPartnerIds ??= new List<string>();
if (EventBuildInfo.RequestPartners == null)
EventBuildInfo.RequestPartners = new List<PlayerInfo>();
if (EventBuildInfo.InvitePartners == null)
EventBuildInfo.InvitePartners = new List<PlayerInfo>();
var refusedPartnerIds = Cache.RefusedPartnerIds;
if (refusedPartnerIds is { Count: > 0 })
{
EventBuildInfo.RequestPartners.RemoveAll(item => refusedPartnerIds.Contains(item.PlayFabId));
EventBuildInfo.InvitePartners.RemoveAll(item => refusedPartnerIds.Contains(item.PlayFabId));
}
}
private void GetPlayerCache()
{
_playerPreferenceKey = "EventPartnerGatherRecommendCache" + _userService?.UserId + EventId;
var cacheString = PlayerPrefs.GetString(_playerPreferenceKey, "");
if (cacheString == "")
{
Cache = new EventPartnerGatherCache
{
ActionQ = new Dictionary<int, Queue<EventPartnerData.EventBuildBotAddScoreAction>>(),
// ListInvitedBy = new List<ScrollViewItemInfo>(),
RefusedPartnerIds = new List<string>()
};
}
else
{
ELog($"LoadCache eventId={EventId} cacheLength={cacheString?.Length ?? 0}");
try
{
Cache = JsonConvert.DeserializeObject<EventPartnerGatherCache>(cacheString);
}
catch (Exception ex)
{
LogError($"LoadCacheFailed eventId={EventId} error={ex.Message}");
throw;
}
ELog($"LoadCacheDone eventId={EventId}");
}
}
// 有可能是机器人,需要获得
private void ResolveBuildInfoData(int index, PlayerInfo playerInfo, Dictionary<int, EventBuildBotInfo> bots)
{
if (index >= BuildPartners.Length)
{
return;
}
var buildPartner = BuildPartners[index] ?? new BuildPartner();
// Get display info
buildPartner.Cache = Cache;
ResolveDisplayInfo(index, playerInfo, buildPartner, bots);
BuildPartners[index] = buildPartner;
}
private void ResolveDisplayInfo(int idx, PlayerInfo playerInfo, BuildPartner buildPartner, Dictionary<int, EventBuildBotInfo> bots)
{
buildPartner.SlotId = idx;
var partnerId = playerInfo.PlayFabId;
buildPartner.PartnerId = partnerId;
if (partnerId.EndsWith(EventPartnerBot.RobotIdentifier))
{
EventPartnerGatherBot.GetBotDisplayInfo(partnerId, out buildPartner.AvatarUrl, out buildPartner.DisplayName);
var botRes = false;
EventBuildBotInfo botInfo = null;
if (bots != null)
{
botRes = bots.TryGetValue(idx, out botInfo);
}
// var botInfo =
if (botRes && botInfo != null)
{
buildPartner.BotTargetScore = botInfo.TargetScore;
buildPartner.WakeStartTime = botInfo.WakeStartTime;
buildPartner.WakingSeconds = botInfo.WakingSeconds;
buildPartner.BotGrade = botInfo.Grade;
}
else
{
botInfo = new EventBuildBotInfo
{
Id = buildPartner.PartnerId,
TargetScore = 0,
WakeStartTime = ZZTimeHelper.UtcNow(),
WakingSeconds = UnityEngine.Random.Range(_tables.TbEventPartnerConfig.RobotDailyActiveTimeWindow[0],
_tables.TbEventPartnerConfig.RobotDailyActiveTimeWindow[1]),
Grade = FtUtils.GetRandomIdxFromWeightList(_tables.TbEventPartnerRobot.DataList.Select(r => r.Weight))
};
LogWarning($"BotInfoMissing eventId={EventId} slotId={idx} followup=ScheduleBot");
var manager = GContext.container.Resolve<EventPartnerGatherManager>();
manager.SaveBotInfo(idx, botInfo);
buildPartner.BotTargetScore = botInfo.TargetScore;
buildPartner.WakeStartTime = botInfo.WakeStartTime;
buildPartner.WakingSeconds = botInfo.WakingSeconds;
buildPartner.BotGrade = botInfo.Grade;
// buildPartner.BotTargetScore = 0;
// buildPartner.WakeStartTime = ZZTimeHelper.UtcNow();
// buildPartner.WakingSeconds = UnityEngine.Random.Range( _tables.TbEventPartnerConfig.RobotDailyActiveTimeWindow[0],
// _tables.TbEventPartnerConfig.RobotDailyActiveTimeWindow[1]);
// buildPartner.BotGrade = FtUtils.GetRandomIdxFromWeightList( _tables.TbEventPartnerRobot.DataList.Select(r => r.Weight));
}
}
else
{
// buildPartner.PartnerId = partner;
// // var partnerInfo = _userService.GetPlayInfo(buildPartner.PartnerId);
buildPartner.AvatarUrl = playerInfo.AvatarUrl;
buildPartner.DisplayName = playerInfo.DisplayName;
}
}
public List<string> GetExcludeList()
{
var excludeSet = new HashSet<string>();
// 添加自己
excludeSet.Add(_userService?.UserId);
if (EventBuildInfo.RequestPartners != null)
foreach (var requestPartner in EventBuildInfo.RequestPartners)
excludeSet.Add(requestPartner.PlayFabId);
// Exclude friends
foreach (var friend in _friendService.FriendList)
excludeSet.Add(friend.playFabId);
// Exclude refused ones
if (Cache.RefusedPartnerIds is not null)
foreach (var id in Cache.RefusedPartnerIds)
excludeSet.Add(id);
// Exclude ones that player already invited
if (EventBuildInfo.InvitePartners is not null)
foreach (var p in EventBuildInfo.InvitePartners)
excludeSet.Add(p.PlayFabId);
return new List<string>(excludeSet);
}
public int GetRecommendCount()
{
var friendCount = _friendService.FriendList.Count;
if (friendCount < ActiveFriendCountThreshold)
{
return _tables.TbEventPartnerConfig.FriendRecommendParam2[0];
}
return _tables.TbEventPartnerConfig.FriendRecommendParam2[1];
}
//
public void AddRefusePartner(string partnerId)
{
Cache.RefusedPartnerIds.Add(partnerId);
// OnNoLongerUsedPartner(partnerId);
}
public void SavePlayerPreferenceData()
{
// LogError("SavePlayerPreferenceData-> ");
var cache = JsonConvert.SerializeObject(Cache);
Log($"SaveCache eventId={EventId} cacheLength={cache?.Length ?? 0}");
PlayerPrefs.SetString(_playerPreferenceKey, cache);
}
public BuildPartner GetPartnerById(string partnerId)
{
return BuildPartners.FirstOrDefault(buildPartner => buildPartner.PartnerId.Equals(partnerId));
}
public bool UpdatePartnerScore(string partnerId, int eScore)
{
var builder = GetPartnerById(partnerId);
if (builder != null)
{
builder.ScorePartnerActual = eScore;
return true;
}
return false;
}
public void LoadScore(List<Dictionary<string, int>> respScores,
List<(int myScore, int FriendScore)> buildPartnerScore)
{
if (respScores != null)
Scores = respScores.Select((x, i) => (x, i)).ToDictionary(kv => kv.i, kv => kv.x);
else
Scores = new Dictionary<int, Dictionary<string, int>>();
for (int i = 0; i < BuildPartners.Length; ++i)
{
var buildPartner = BuildPartners?[i];
var (myScore, partnerScore) = buildPartnerScore[i];
if (buildPartner is { IsPartnerRobot: true })
{
buildPartner.ScoreSelfActual = myScore;
buildPartner.ScorePartnerActual = partnerScore;
}
}
foreach (var (idx, value) in Scores)
{
if (idx >= BuildPartners?.Length)
{
continue;
}
var buildPartner = BuildPartners?[idx];
if (buildPartner != null)
{
var ret = value.TryGetValue(buildPartner.PartnerId, out var partnerScore);
if (ret)
{
buildPartner.ScorePartnerActual = partnerScore;
}
ret = value.TryGetValue(_userService.UserId, out var selfScore);
if (ret)
{
buildPartner.ScoreSelfActual = selfScore;
}
}
}
}
public void AddRequestPartner(PlayerInfo partnerInfo)
{
EventBuildInfo.RequestPartners.Add(partnerInfo);
}
public bool AddBuildPartner(BuildPartner buildPartner)
{
var index = buildPartner.SlotId;
if (index >= BuilderCapacity)
{
LogWarning($"AddBuildPartnerFailed eventId={EventId} reason=SlotOutOfRange slotId={index} capacity={BuilderCapacity}");
return false;
}
if (BuildPartners[index] != null && BuildPartners[index].IsValid())
{
LogWarning($"AddBuildPartnerFailed eventId={EventId} reason=SlotOccupied slotId={index}");
return false;
}
var manager = GContext.container.Resolve<EventPartnerGatherManager>();
var maxScore = manager.NodeCumulativeSteps[^1];
buildPartner.MaxScore = maxScore;
buildPartner.Cache = Cache;
BuildPartners[index] = buildPartner;
manager.ResetBuildPartner(buildPartner.SlotId);
manager.SavePartnerInfo(buildPartner.SlotId);
GContext.container.Resolve<IUserService>().SetPlayInfo(buildPartner.PartnerId, buildPartner.DisplayName, buildPartner.AvatarUrl);
return true;
}
public void RemoveInvitePartner(string partnerInfoPlayFabId)
{
if (string.IsNullOrEmpty(partnerInfoPlayFabId))
return;
EventBuildInfo.InvitePartners.RemoveAll(item => item.PlayFabId.Equals(partnerInfoPlayFabId));
}
// 添加之后的删除与整理,不在出现在邀请和和推荐
public void OnNoLongerUsedPartner(string playFabId)
{
if(EventBuildInfo.RequestPartners is {Count: > 0})
{
EventBuildInfo.RequestPartners.RemoveAll(p => p.PlayFabId == playFabId);
}
// SavePlayerPreferenceData();
}
public bool AddInvitationInfo(ScrollViewItemInfo invitationInfo)
{
var buildInfo = EventBuildInfo;
var partnerId = invitationInfo.PlayfabId;
if (buildInfo.InvitePartners.Select(p => p.PlayFabId).Contains(partnerId))
return false;
invitationInfo.Type = EventPartnerScrollViewItem.EScrollViewType.MyInvitation;
buildInfo.InvitePartners.Add(PlayerInfo.FromScrollViewItem(invitationInfo));
return true;
}
public void SyncGatherData(EventPartnerGatherManager manager)
{
var gatherData = manager.GatherData;
ELog($"SyncGatherData eventId={EventId} hasData={gatherData != null}");
var buildScore = gatherData.BuilderPartnerScore;
for (var i = 0; i < buildScore.Count; ++i)
{
var (myScore, partnerScore) = buildScore[i];
if (i > BuildPartners.Length - 1)
continue;
BuildPartners[i] ??= new BuildPartner();
var builder = BuildPartners[i];
if (builder != null)
{
builder.ScoreSelfDisplay = myScore;
builder.ScorePartnerDisplay = partnerScore;
builder.MaxScore = manager.NodeCumulativeSteps[^1];
builder.Cache = Cache;
}
}
}
public void SyncToGatherData()
{
// Log($"SyncGatherData-> {gatherData}");
// var manager = GContext.container.Resolve<EventPartnerGatherManager>();
// manager.SyncFromPartnerInfo(this);
}
}
}