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(); private FriendService _friendService { get; set; } = GContext.container.Resolve(); private IUserService _userService { get; } = GContext.container.Resolve(); // 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> Scores { get; set; } // public EventPartnerGatherCache Cache { get; set; } = new(); private static void LogError(object t) { Debug.LogError($"PartnerInfoManager-> {t} "); } private static void Log(object t) { Debug.Log($"PartnerInfoManager-> {t} "); } private static void ELog(object t) { #if UNITY_EDITOR Debug.Log($"PartnerInfoManager-> {t} "); #endif } private static void LogWarning(object t) { Debug.LogWarning($"PartnerInfoManager-> {t} "); } 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().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 bots) { EventBuildInfo = detail; EventBuildInfo.Partners ??= new List(); 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(); if (EventBuildInfo.RequestPartners == null) EventBuildInfo.RequestPartners = new List(); if (EventBuildInfo.InvitePartners == null) EventBuildInfo.InvitePartners = new List(); 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>(), // ListInvitedBy = new List(), RefusedPartnerIds = new List() }; } else { ELog($"LoadCache eventId={EventId} cacheLength={cacheString?.Length ?? 0}"); try { Cache = JsonConvert.DeserializeObject(cacheString); } catch (Exception ex) { LogError($"LoadCacheFailed eventId={EventId} error={ex.Message}"); throw; } ELog($"LoadCacheDone eventId={EventId}"); } } // 有可能是机器人,需要获得 private void ResolveBuildInfoData(int index, PlayerInfo playerInfo, Dictionary 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 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(); 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 GetExcludeList() { var excludeSet = new HashSet(); // 添加自己 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(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> 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>(); 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(); 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().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(); // manager.SyncFromPartnerInfo(this); } } }