using System.Collections.Generic; using System.Threading.Tasks; using asap.core; using cfg; using UnityEngine; using System.Linq; using System; using GameCore; using ScrollViewItemInfo = EventPartnerScrollViewItem.ScrollViewItemInfo; using EScrollViewType = EventPartnerScrollViewItem.EScrollViewType; using EventPartner; using EventPartnerGather; using game; using EventPartnerGatherRequests; using UniRx; using AutoMatchStatusResponse = EventPartnerGatherRequests.AutoMatchStatusResponse; using AutoMatchToggleResponse = EventPartnerGatherRequests.AutoMatchToggleResponse; using Robot = EventPartner.Robot; public class EventPartnerStatueArc : IEventPartnerArchitecture, IAutoMatchManagerContext, IDisposable { public IEventAggregator EventAggregator { get; set; } = new EventAggregator(); // private bool _isWhole = false; #region Models public EventPartnerStatueTableContext TableContext; public ITableContext Ctx => TableContext; private Model _model; public InvitationData InvitationData { get; set; } public PlayerInfoPool PlayerInfoPool = new PlayerInfoPool(); public RobotDataManager RobotData; public EventPartnerStatueBuff Buff = new EventPartnerStatueBuff(); #endregion public Model Model => _model; private IDisposable _botAddSub; public bool IsFirstTime { get; set; } public EventPartnerStatueArc() { _botAddSub = EventAggregator.GetEvent().Subscribe(OnBotAdd); } #region DataStorage private DateTime _lastDetailRefreshTime = DateTime.MinValue; public bool DoRefreshDetail => ZZTimeHelper.UtcNow() - _lastDetailRefreshTime > TimeSpan.FromSeconds(15); public static async void Load(cfg.FishingEvent e) { try { var arc = GContext.container.Resolve(); if (arc == null) { GContext.container.Register().AsSingleton(); arc = GContext.container.Resolve(); } arc.TableContext = new EventPartnerStatueTableContext(e.ID); arc.SetUiData(); var ppData = EventPartnerStatuePlayerPreferenceCache.Load(e.ID); var pfData = EventPartnerStatuePlayfabData.Load(); if (pfData == null || pfData.EventId != e.ID) // new event { arc._model = new Model(arc); arc.Model.SetTicketCount(arc.TableContext.GetInitGift()); arc.Model.LureInflationRate = GContext.container.Resolve().InflationRate; arc.Model.ComponentList = new List(); arc.Model.IsFinalRewardClaimed = false; arc.InvitationData = new InvitationData(arc); arc.InvitationData.Init(ppData.RecommendCache.RefusePfIds.ToHashSet(), ppData.RecommendCache); arc.PlayerInfoPool = new PlayerInfoPool(); arc.PlayerInfoPool.Init(arc); arc.RobotData = new RobotDataManager(arc); arc.Buff = new EventPartnerStatueBuff(); arc.Buff.Init(arc); arc.Requests ??= new RequestSystem(); arc.Requests.Init(e.ID); arc.RtSystem ??= new RtSystem(); // arc.RtSystem = new RtSystem(); arc.EventTrackingSystem = new EventPartnerStatueEventTrackingSystem(); arc.IsFirstTime = true; arc._isAutoMatchEnabled = false; arc._lastAutoMatchTimeUtc = DateTime.MinValue; arc.SavePlayfab(); } else // old event { arc._model ??= new Model(arc); arc.Model.SetTicketCount(pfData.TicketCount); arc.Model.LureInflationRate = pfData.LureInflationRate; arc.Model.IsFinalRewardClaimed = pfData.IsFinalRewardClaimed; arc.InvitationData ??= new InvitationData(arc); arc.InvitationData.Init(ppData.RecommendCache.RefusePfIds.ToHashSet(), ppData.RecommendCache); arc.PlayerInfoPool = new PlayerInfoPool(); arc.PlayerInfoPool.Init(arc); arc.RobotData ??= new RobotDataManager(arc); arc.RobotData.RobotList = ppData.RobotDataCache.ToDictionary(kv => kv.Key, kv => new Robot(kv.Value, arc)); arc.RobotData.RobotInvitationBuffer = ppData.RobotInvitationCache; arc.Buff ??= new EventPartnerStatueBuff(); arc.Buff.Init(arc); arc.Requests ??= new RequestSystem(); arc.Requests.Init(e.ID); arc.RtSystem ??= new RtSystem(); // arc.RtSystem = new RtSystem(); arc.IsFirstTime = ppData.IsFirstTime; arc._isAutoMatchEnabled = pfData.IsEnableAutoMatch; arc._lastAutoMatchTimeUtc = pfData.LastAutoMatchTimeUtc; arc.EventTrackingSystem = new EventPartnerStatueEventTrackingSystem(); } // GContext.container.Resolve().EventRefresh(e, arc.TableContext.GetRushId(), RushType.OneDataKey); var detail = await arc.Requests.GetDetail(); if (detail == null) { Debug.LogWarning("[EventPartnerStatue]: Get Detail failed."); return; } arc.ResolveWithDetail(detail, pfData); arc.RobotData.StartRobotLoop(); } catch (Exception ex) { Debug.LogError(ex); } } public static void EnsureTokenExchangeContextRegistered(EventPartnerStatueArc arc) { var context = GContext.container.Resolve(); if (context == null || context is not EventPartnerStatueTokenExchangeArcContext) { GContext.container.Unregister(); GContext.container.Register().AsSingleton(); context = GContext.container.Resolve(); } if (context is EventPartnerStatueTokenExchangeArcContext tokenExchangeContext) tokenExchangeContext.BindArc(arc); // EventPartnerTokenExchangeContextRegistry.Context = context; } private void SetUiData() { UITypes.EventPartnerStatuePanel.SetType(TableContext.GetMainPanelUrl()); UITypes.EventPartnerStatueBuildPanel.SetType(TableContext.GetBuildPanelUrl()); UITypes.EventPartnerStatueInfoPopupPanel.SetType(TableContext.GetInfoPanelUrl()); UITypes.EventPartnerStatuePackPanel.SetType(TableContext.GetPackPanelUrl()); // UITypes.EventPartnerStatueInvitationPanel.SetType(arc.TableContext.GetInvitePanelUrl()); } public void ResolveWithDetail(EventPartnerGatherRequests.EventPartnerGatherDetail detail, EventPartnerStatuePlayfabData pfData) { var selfPfId = GContext.container.Resolve().UserId; var maxScore = TableContext.GetMaxScore(); _model.ComponentList = new List(); for (int i = 0; i < detail.Partners.Count; i++) { var playfabId = detail.Partners[i].PlayFabId; int scoreSelf, scorePartner; if (RobotDataManager.IsRobot(playfabId)) { if (pfData == null || pfData.RobotScoreMap == null) { scoreSelf = 0; scorePartner = 0; } else (scoreSelf, scorePartner) = pfData.RobotScoreMap.TryGetValue(playfabId, out var score) ? score : (0, 0); if (!RobotData.RobotList.ContainsKey(playfabId)) { RobotData.CreateBotDataToRobotList(playfabId); RobotData.RobotList[playfabId].Schedule(scorePartner, scorePartner + scoreSelf); } } else { scoreSelf = detail.Scores[i].TryGetValue(selfPfId, out var s) ? s : 0; scorePartner = detail.Scores[i].TryGetValue(playfabId, out s) ? s : 0; } (scoreSelf, scorePartner) = MaxScoreExceedingCheck(scoreSelf, scorePartner, TableContext.GetMaxScore()); (int displaySelf, int displayPartner) = pfData != null && pfData.DisplayScoreMap.TryGetValue(playfabId, out var display) ? display : (0, 0); var scoreSelfDisplay = Mathf.Min(displaySelf, scoreSelf); var scorePartnerDisplay = Mathf.Min(displayPartner, scorePartner); _model.ComponentList.Add(new BuildComponent(i, maxScore, this, playfabId, scoreSelf, scorePartner, scoreSelfDisplay, scorePartnerDisplay)); } PlayerInfoPool.FillInDetail(detail); InvitationData.FillInDetail(_model.PartnerIdSet, detail); // _isWhole = true; _lastDetailRefreshTime = ZZTimeHelper.UtcNow(); SavePlayfab(); } private (int scoreSelfAfter, int scorePartnerAfter) MaxScoreExceedingCheck(int scoreSelf, int scorePartner, int maxScore) { int scoreSelfAfter = Mathf.Clamp(scoreSelf, 0, maxScore); int scorePartnerAfter = Mathf.Clamp(scorePartner, 0, maxScore); if (scoreSelfAfter + scorePartnerAfter > maxScore) { scorePartnerAfter = maxScore - scoreSelfAfter; } return (scoreSelfAfter, scorePartnerAfter); } // public void UpdateScoreWithDetail public EventPartnerStatuePlayfabData ToPlayfabData() { var data = new EventPartnerStatuePlayfabData(); data.EventId = TableContext.EventId; data.TicketCount = Model.TicketCount; data.BuffFreeMultiplier = Buff.FreeMultiplier == null ? -1 : Buff.FreeMultiplier.Value; data.BuffPointExpiryTime = Buff.PointBonusExpiryTime == null ? ZZTimeHelper.UtcNow() - TimeSpan.FromDays(365) : Buff.PointBonusExpiryTime.Value; data.DisplayScoreMap = Model.ComponentList.ToDictionary(x => x.PartnerId, x => (x.ScoreSelfDisplay, x.ScorePartnerDisplay)); data.RobotScoreMap = Model.ComponentList.Where(x => RobotDataManager.IsRobot(x.PartnerId)) .ToDictionary(x => x.PartnerId, x => (x.ScoreSelfActual, x.ScorePartnerActual)); data.LureInflationRate = Model.LureInflationRate; data.IsFinalRewardClaimed = Model.IsFinalRewardClaimed; data.IsEnableAutoMatch = _isAutoMatchEnabled; data.LastAutoMatchTimeUtc = _lastAutoMatchTimeUtc; return data; } public EventPartnerStatuePlayerPreferenceCache ToPlayerPreferenceCache() { var cache = new EventPartnerStatuePlayerPreferenceCache(TableContext.EventId); cache.RecommendCache = InvitationData.ToCache(); cache.RobotDataCache = RobotData.RobotList.ToDictionary(kv => kv.Key, kv => kv.Value.ToPpData()); cache.RobotInvitationCache = RobotData.RobotInvitationBuffer; cache.Buff = Buff; cache.IsFirstTime = IsFirstTime; return cache; } public void SavePlayerPreference() { ToPlayerPreferenceCache().Save(); } public void SavePlayfab() { ToPlayfabData().Save(); } #endregion #region UIData public EventPartnerStatueMainPanelData GetEventPartnerStatueMainPanelData() { var res = new EventPartnerStatueMainPanelData(); res.TicketCount = Model.TicketCount; var partnerCount = TableContext.GetMaxPartnerCount(); res.SlotViewDataList = new EventPartnerStatueSlotViewData[partnerCount]; for (int i = 0; i < partnerCount; i++) { if (i < Model.ComponentList.Count) { var component = Model.ComponentList[i]; var playerInfo = PlayerInfoPool.Get(component.PartnerId); var stage = TableContext.GetStageFromTotalScore(component.ScoreDisplayTotal); var progress = TableContext.GetPercentageWithinStage(component.ScoreDisplayTotal); var reward = TableContext.GetNextRewardFromScore(component.ScoreDisplayTotal); if (stage >= TableContext.GetScoreStageList().Count) // Show Final Reaward for this component, not actual reward. reward = null; var scoreToAdd = component.ScorePartnerActual - component.ScorePartnerDisplay; var isClaimed = component.IsRewardClaimed; res.SlotViewDataList[i] = new EventPartnerStatueSlotViewData { Index = i, IsEmpty = false, Info = playerInfo, Stage = stage, Progress = progress, Reward = reward, ScoreToAdd = scoreToAdd, IsClaimed = isClaimed }; } else { var hasInvitation = InvitationData != null && InvitationData.RequestPfIdSet != null && InvitationData.RequestPfIdSet.Count > 0 && !IsFull(); res.SlotViewDataList[i] = new EventPartnerStatueSlotViewData { IsEmpty = true, Index = i, HasInvitation = hasInvitation }; } } var (StartTime, EndTime) = TableContext.GetEventTimeLimit(); res.TimerContext = new TimerContext { StartTime = StartTime, ExpiryTime = EndTime, }; res.GrandRewardList = TableContext.GetFinalRewardList(); res.BuildStatus = Model.BuildStatus; return res; } public EventPartnerStatueBuildPanelData GetEventPartnerStatueBuildPanelData(int slotIdx) { var _userService = GContext.container.Resolve(); var res = new EventPartnerStatueBuildPanelData(); res.InfoSelf = new PlayerInfo { PlayFabId = _userService.UserId, DisplayName = _userService.DisplayName, AvatarUrl = _userService.AvatarUrl, }; res.InfoPartner = PlayerInfoPool.Get(Model.ComponentList[slotIdx].PartnerId); res.ScoreSelf = Model.ComponentList[slotIdx].ScoreSelfDisplay; res.ScorePartner = Model.ComponentList[slotIdx].ScorePartnerDisplay; res.ProgressData = new EventPartnerStatueBuildProgressData { Stage = TableContext.GetStageFromTotalScore(Model.ComponentList[slotIdx].ScoreDisplayTotal), Scores = TableContext.GetScoreStageList().ToArray(), Progress = TableContext.GetPercentageWithinStage(Model.ComponentList[slotIdx].ScoreDisplayTotal), RewardList = TableContext.GetRewardList(), }; res.TicketCount = Model.TicketCount; res.SlotIdx = slotIdx; return res; } public EventPartnerStatueBuildSceneData GetEventPartnerStatueBuildSceneData(int slotIdx) { return new EventPartnerStatueBuildSceneData() { SlotIdx = slotIdx, Stage = TableContext.GetStageFromTotalScore(Model.ComponentList[slotIdx].ScoreDisplayTotal), MaxStage = TableContext.GetScoreStageList().Count, }; } public EventPartnerStatueEntranceData GetEntranceData() { var res = new EventPartnerStatueEntranceData(); var (StartTime, EndTime) = TableContext.GetEventTimeLimit(); res.TimerContext = new TimerContext { StartTime = StartTime, ExpiryTime = EndTime, }; res.IconUrl = TableContext.GetEntranceIconUrl(); res.TicketCount = Model.TicketCount; res.HasInvitation = InvitationData != null && InvitationData.RequestPfIdSet != null && InvitationData.RequestPfIdSet.Count > 0 && !IsFull(); res.HasPartnerScore = Model != null && Model.ComponentList != null && Model.ComponentList.Any(c => c.ScorePartnerActual > c.ScorePartnerDisplay) && !Model.ComponentList.All(c => c.IsRewardClaimed); return res; } public bool IsActive { get { var (StartTime, EndTime) = TableContext.GetEventTimeLimit(); var now = ZZTimeHelper.UtcNow(); return now >= StartTime && now <= EndTime; } } #endregion #region IAutoMatchManagerContext public int EventId => TableContext?.EventId ?? -1; public bool ShouldCloseAutoMatch => IsFull(); public bool IsAutoMatchEnabled => _isAutoMatchEnabled; private bool _isAutoMatchEnabled; private DateTime _lastAutoMatchTimeUtc = DateTime.MinValue; public void SetLastAutoMatchTimeUtc(DateTime utc) { _lastAutoMatchTimeUtc = utc; SavePlayfab(); } /// 与 EventPartnerGatherManager.CanStopAutoMatch 一致:未满员且距上次开启未满 AutoMatchCD 时不可关闭。 public bool CanStopAutoMatch(out int leftTimes) { leftTimes = -1; if (IsFull()) return false; var cooldownSeconds = GContext.container.Resolve().TbEventPartnerConfig.AutoMatchCD; var elapsed = (DateTime.UtcNow - _lastAutoMatchTimeUtc).TotalSeconds; leftTimes = (int)Math.Floor(cooldownSeconds - elapsed); leftTimes = leftTimes > 0 ? leftTimes : 0; return elapsed >= cooldownSeconds; } public void SetAutoMatchEnabled(bool enabled) { _isAutoMatchEnabled = enabled; SavePlayfab(); } public async Task FetchAndProcessAutoMatchStatus(bool force = true) { var response = await Requests.GetAutoMatchStatus(); if (response?.State == EEventBuildState.Success && response?.Partners is { Count: > 0 } && !ShouldCloseAutoMatch) { var addedAny = false; var maxPartners = TableContext.GetMaxPartnerCount(); for (var i = 0; i < response.Partners.Count; ++i) { if (IsFull()) break; if (i >= maxPartners) break; var partner = response.Partners[i]; if (partner == null || RobotDataManager.IsRobot(partner.PlayFabId)) continue; if (Model.ComponentList.Any(c => c.PartnerId == partner.PlayFabId)) continue; PlayerInfoPool.Add(partner); var idx = AddPartner(partner.PlayFabId); if (idx >= 0) addedAny = true; } if (addedAny) SavePlayfab(); } return response; } public async Task ControlAutoMatch(bool enable) { return await Requests.ControlAutoMatch(enable); } public void NotifyAutoMatchStopped() { GContext.Publish(new EventForAutoMatchChangeStage { State = AutoMatchState.AutoMatchOff }); } public void NotifyAutoMatchFailed(string reason) { GContext.Publish(new EventAutoMatchFailed { Reason = reason }); } #endregion #region System public RequestSystem Requests { get; set; } public RtSystem RtSystem { get; set; } public EventPartnerStatueEventTrackingSystem EventTrackingSystem { get; set; } /// /// Roll with a cost. Returns the point and combination. /// /// The cose of this roll and the multiplier as well. /// Result point and combination public (int point, (int c1, int c2, int c3)) Roll(int cost) { var freeMultiplier = Buff.ConsumeFreeBuff(); if (freeMultiplier != -1) { cost = freeMultiplier; EventTrackingSystem.RollIsFree = 1; } else { var res = Model.AddTicket(-cost); if (!res) { Debug.Log($"[EventPartner] Failed to add ticket. Cost: {cost}, Current: {Model.TicketCount}"); return (-1, (-1, -1, -1)); } EventTrackingSystem.RollIsFree = 0; } EventTrackingSystem.RollMultiplier = cost; (var point, var combination) = TableContext.GenerateSpinResult(); EventTrackingSystem.RollIsMore = Buff.GetMoreBuff() > 0 ? 1 : 0; point = FtUtils.RoundToInt(point * (1 + Buff.GetMoreBuff())); if (combination == TableContext.GetFreeDisplayCombination()) Buff.CreateFreeBuff(cost); else if (combination == TableContext.GetMoreDisplayCombination()) Buff.CreateMoreBuff(); point *= cost; return (point, combination); } #if UNITY_EDITOR public (int point, (int c1, int c2, int c3)) RollTest(int point, (int c1, int c2, int c3) c, int cost) { var freeMultiplier = Buff.ConsumeFreeBuff(); point = FtUtils.RoundToInt(point * (1 + Buff.GetMoreBuff())); if (c == TableContext.GetFreeDisplayCombination()) Buff.CreateFreeBuff(cost); else if (c == TableContext.GetMoreDisplayCombination()) Buff.CreateMoreBuff(); point *= cost; return (point, c); } #endif public List TryGetStageReward(string partnerId) { for (int i = 0; i < Model.ComponentList.Count; i++) { if (Model.ComponentList[i].PartnerId == partnerId) return TryGetStageReward(i); } return new List(); } public List TryGetStageReward(int slotIdx) { var c = Model.ComponentList[slotIdx]; var currentStage = TableContext.GetStageFromTotalScore(c.ScoreTotal); var displayStage = TableContext.GetStageFromTotalScore(c.ScoreDisplayTotal); var ids = new List(); var res = new List(); if (displayStage >= currentStage) return res; for (int s = displayStage + 1; s <= currentStage; s++) { var dropId = TableContext.GetRewardDropIdFromStage(s); ids.Add(dropId); } Debug.Log($"[EventPartnerStatue] Add reward drop id list: {Newtonsoft.Json.JsonConvert.SerializeObject(ids)}"); if (RobotDataManager.IsRobot(c.PartnerId) && currentStage < TableContext.GetScoreStageList().Count) { RobotData.RobotList[c.PartnerId].Schedule(c.ScorePartnerActual, c.ScoreTotal); } res = GContext.container.Resolve().GetItemDataListFromListOfSingleDropId(ids); GContext.container.Resolve().LureInflation(res, Model.LureInflationRate); return res; } public void TryGrantFinalReward() { if (Model.IsFinalRewardClaimed) return; if (Model.ComponentList.Count < TableContext.GetMaxPartnerCount() || Model.ComponentList.Any(x => !x.IsDone)) return; if (Model.ComponentList.Any(x => !x.IsRewardClaimed)) // Not the time yet return; ChangeSource changeSource = new ChangeSource(TableContext.EventId, "Event_Minigame4", "Event_Minigame4_Partner", "GrandReward"); var rewardItems = GContext.container.Resolve().AddItemByDropLureInflation(Model.LureInflationRate, TableContext.GetFinalRewardDropId(), changeSource); GContext.Publish(new ShowData()); Model.IsFinalRewardClaimed = true; EventTrackingSystem.RewardPartnerId = "final"; EventTrackingSystem.RewardSlotId = 99; EventTrackingSystem.RewardStageId = 99; EventTrackingSystem.RewardHook = rewardItems.Where(r => r.id == 1001).Sum(r => r.count); EventTrackingSystem.ReportReward(); SavePlayfab(); } public bool IsFull() { return Model.ComponentList.Count >= TableContext.GetMaxPartnerCount(); } public int AddPartner(string partnerId) { var maxScore = TableContext.GetMaxScore(); var idx = Model.ComponentList.Count; if (idx >= TableContext.GetMaxPartnerCount()) { Debug.LogError("[EventPartner] Max partner count reached."); return -1; } Model.ComponentList.Add(new BuildComponent(idx, maxScore, this, partnerId)); var d = new EventPartnerStatueSlotViewData { Index = idx, IsEmpty = false, Info = PlayerInfoPool.Get(partnerId), Stage = 0, Progress = 0, Reward = TableContext.GetNextRewardFromScore(0), ScoreToAdd = 0 }; EventAggregator.Publish(d); return idx; } public (bool isMax, int idx, int multiplier) GetCurrentMultiplier(int currentIdx) { var ticketCount = Model.TicketCount; var list = TableContext.GetMultiplierList(); bool isMax = false; currentIdx %= list.Count; var multiplier = list[currentIdx]; while (multiplier > ticketCount && currentIdx > 0) { currentIdx--; multiplier = list[currentIdx]; } if (currentIdx == list.Count - 1) isMax = true; if (multiplier >= ticketCount) isMax = true; return (isMax, currentIdx, multiplier); } public (bool isMax, int idx, int multiplier) GetNextMultiplier(int currentIdx) { var ticketCount = Model.TicketCount; var list = TableContext.GetMultiplierList(); bool isMax = false; currentIdx = (currentIdx + 1) % list.Count; var multiplier = list[currentIdx]; if (multiplier > ticketCount) { currentIdx = 0; multiplier = list[0]; } if (currentIdx >= list.Count - 1) isMax = true; else if (list[currentIdx + 1] > ticketCount) isMax = true; return (isMax, currentIdx, multiplier); } public (bool isMax, int idx, int multiplier) GetInitMultiplier() { var ticketCount = Model.TicketCount; var list = TableContext.GetMultiplierList(); bool isMax = true; var currentIdx = list.Count - 1; while (currentIdx > 0 && list[currentIdx] > ticketCount) currentIdx--; return (isMax, currentIdx, list[currentIdx]); } public ScrollViewItemInfo GetScrollViewItemInfo(string partnerId, EScrollViewType type) { var partner = PlayerInfoPool.Get(partnerId); return new ScrollViewItemInfo { Type = type, PlayfabId = partnerId, DisplayName = partner.DisplayName, AvatarUrl = partner.AvatarUrl, Level = partner.Level, }; } public void OnPartnerChange(EventPartnerGatherPartnerEvt e) { var arc = GContext.container.Resolve(); PlayerInfoPool.Add(e.PartnerInfo); switch (e.EvtType) { // invite case 0: InvitationData.OnRequest(e.PartnerInfo.PlayFabId); break; // accept case 1: var slotId = AddPartner(e.PartnerInfo.PlayFabId); arc.EventTrackingSystem.InvitePartnerId = RobotDataManager.IsRobot(e.PartnerInfo.PlayFabId) ? "Robot" : e.PartnerInfo.PlayFabId; arc.EventTrackingSystem.InviteSlotId = slotId; arc.EventTrackingSystem.InviteId = 1; arc.EventTrackingSystem.ReportInvite(); break; // reject case -1: InvitationData.OnRefuse(e.PartnerInfo.PlayFabId); break; } } public void OnScore(EventPartnerGatherScoreEvt e) { var c = Model.ComponentList.FirstOrDefault(x => x.PartnerId == e.PartnerId); if (c == null) { Debug.Log($"[EventPartnerStatue] Partner in score event not found: {e.PartnerId}"); return; } c.UpdatePartnerScore(e.Score); } public string GetRedPointKey() { return "partner.statue"; } public bool HasPartnerScore() { foreach (var c in Model.ComponentList) { if (c.ScorePartnerActual > c.ScorePartnerDisplay) return true; } return false; } private void OnBotAdd(EventBotAdd e) { EventTrackingSystem.InvitePartnerId = "Robot"; EventTrackingSystem.InviteSlotId = e.SlotId; EventTrackingSystem.InviteId = 1; EventTrackingSystem.ReportInvite(); } public void Dispose() { _botAddSub?.Dispose(); } #endregion } public interface IEventPartnerArchitecture { public RequestSystem Requests { get; } public ITableContext Ctx { get; } public Model Model { get; } public InvitationData InvitationData { get; } public IEventAggregator EventAggregator { get; } public bool IsFull(); public int AddPartner(string partnerId); public void SavePlayerPreference(); public void SavePlayfab(); public string GetRedPointKey(); }