using System; using System.Collections; using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; using KwaiAds.Scripts.Api; using KwaiAds.Scripts.Api.Reward; using UnityEngine; using static WZ.KwaiAdsConfigParser; namespace WZ { public class KwaiFloorRvManager : D_MonoSingleton { private int _rvParallelRequests = 3; private List _rvFloorConfigs = new List(); public Dictionary _rvFloorAdControllers = new Dictionary(); private List _sortedFloors = new List(); private int _currentFloorIndex = 0; private bool _isRequestingFloors = false; private List _currentRequestBatch = new List(); private FloorConfig _successfulFloor = null; public float _rvStartLoadTime = 0; private int _waterfallRequestCount = 0; // waterfall请求次数 private Dictionary _unitIdRequestCounts = new Dictionary(); // 每个unite_id的请求次数 private string _currentRequestId; // 当前waterfall请求的ID public void InitializeWithFloors() { // 对楼层按价格从高到低排序 _sortedFloors = _rvFloorConfigs.OrderByDescending(f => f.price).ToList(); LoggerUtils.Debug("[kwai] floor reward Sorted floors: " + string.Join(", ", _sortedFloors.Select(f => $"{f.id}:{f.price}"))); } public void LoadKwaiBiddingConfig() { _rvParallelRequests = KwaiAdsConfigParser.GetRvParallelRequests(); _rvFloorConfigs = KwaiAdsConfigParser.GetRvFloorConfigs(); //KwaiAdsManager.Instance._appId = KwaiAdsConfigParser.GetKwaiAppId(); //KwaiAdsManager.Instance._token = KwaiAdsConfigParser.GetKwaiAppToken(); LoggerUtils.Debug($"[kwai] floor reward bidding config loaded. FloorOpen: {KwaiAdsConfigParser.GetKwaiRvFloorOpen()}, ParallelRequests: {_rvParallelRequests}, Floors: {_rvFloorConfigs.Count}"); } public void LoadRewardedWithFloors() { if (_rvFloorConfigs == null || _rvFloorConfigs.Count == 0) { LoggerUtils.Debug("[kwai] floor reward No floor configs available, using standard load"); KwaiAdsManager.Instance.LoadRewardedStandard(); return; } _rvStartLoadTime = Time.realtimeSinceStartup; // 重置状态 _currentFloorIndex = 0; _successfulFloor = null; _isRequestingFloors = true; _currentRequestId = GenerateRequestId(); KwaiAdsManager.Instance._rewardAdRevenue = -1; // 增加waterfall请求计数 _waterfallRequestCount++; // 清理之前的广告控制器 foreach (var controller in _rvFloorAdControllers.Values) { controller.Destroy(); } _rvFloorAdControllers.Clear(); // 开始请求楼层广告 RequestNextFloorBatch(); AdsActionEvents.TrackKwaiWaterfallRequest(AdsType.Rewarded, _currentRequestId, _waterfallRequestCount, _rvParallelRequests); } private void RequestNextFloorBatch() { if (!_isRequestingFloors || _successfulFloor != null) return; // 获取下一批要请求的楼层 _currentRequestBatch = new List(); int count = 0; while (_currentFloorIndex < _sortedFloors.Count && count < _rvParallelRequests) { _currentRequestBatch.Add(_sortedFloors[_currentFloorIndex]); _currentFloorIndex++; count++; } if (_currentRequestBatch.Count == 0) { // 检查是否还有正在处理的请求 bool hasPendingRequests = false; foreach (var kvp in _rvFloorAdControllers) { if (kvp.Value != null && !kvp.Value.IsReady()) { hasPendingRequests = true; break; } } if (!hasPendingRequests) { // 所有楼层都请求完毕,并且没有正在处理的请求,确实没有填充 LoggerUtils.Debug("[kwai] floor reward All floors requested, no fill"); _isRequestingFloors = false; } } LoggerUtils.Debug($"[kwai] floor reward Requesting floor batch: {string.Join(", ", _currentRequestBatch.Select(f => $"{f.id}({f.price})"))}"); // 并行请求当前批次的楼层 foreach (var floor in _currentRequestBatch) { RequestFloorAd(floor); } } private void RequestFloorAd(FloorConfig floor) { // 更新unite_id请求计数 if (!_unitIdRequestCounts.ContainsKey(floor.unite_id)) { _unitIdRequestCounts[floor.unite_id] = 0; } _unitIdRequestCounts[floor.unite_id]++; // 获取当前楼层在排序列表中的位置 int floorIndex = GetFloorIndex(floor.id); LoggerUtils.Debug($"[kwai] floor reward Requesting floor {floor.id} (index: {floorIndex}), unite_id {floor.unite_id} has been requested {GetUniteIdRequestCount(floor.unite_id)} times, request id: {_currentRequestId}"); IRewardAdController controller = KwaiAds.Scripts.Api.KwaiAdsSdk.SDK.getRewardAdController(); _rvFloorAdControllers[floor.id] = controller; KwaiRewardAdRequest kwaiRewardAdRequest = new KwaiRewardAdRequest(floor.unite_id); kwaiRewardAdRequest.ExtParams[Constants.Request.BID_FLOOR_PRICE] = floor.price.ToString(); controller.Load(kwaiRewardAdRequest, new FloorRewardAdListener(this, floor), new FloorRewardAdLoadListener(this, floor)); AdsActionEvents.TrackKwaiAdunitRequest(AdsType.Rewarded, _currentRequestId, floor.unite_id, floor.price, GetWaterfallRequestCount(), GetUniteIdRequestCount(floor.unite_id), floorIndex); } // 处理楼层广告加载成功 public void OnFloorAdLoaded(FloorConfig floor, IRewardAdController controller, double revenue) { if (!_isRequestingFloors || _successfulFloor != null) return; // 获取当前楼层在排序列表中的位置 int floorIndex = GetFloorIndex(floor.id); LoggerUtils.Debug($"[kwai] floor reward Floor ad loaded: {floor.id} (index: {floorIndex}) with floor price: {floor.price}, unite_id {floor.unite_id} has been requested {GetUniteIdRequestCount(floor.unite_id)} times, revenue:{revenue}"); // 暂停其他并行请求 _successfulFloor = floor; _isRequestingFloors = false; KwaiAdsManager.Instance._rewardAdRevenue = revenue; // 取消其他楼层的请求 foreach (var kvp in _rvFloorAdControllers) { if (kvp.Key != floor.id) { kvp.Value.Destroy(); } } AdsActionEvents.TrackKwiWaterfallFill(AdsType.Rewarded, _currentRequestId, floor.unite_id, floor.price, GetWaterfallRequestCount(), GetUniteIdRequestCount(floor.unite_id), floorIndex, revenue); } // 处理楼层广告加载失败 public void OnFloorAdFailed(FloorConfig floor, string error) { LoggerUtils.Debug($"[kwai] floor reward ad failed: {floor.id} with error: {error} _isRequestingFloors:{!_isRequestingFloors} _successfulFloor: {_successfulFloor != null}"); if (!_isRequestingFloors || _successfulFloor != null) return; // 移除失败floor if (_currentRequestBatch.Contains(floor)) _currentRequestBatch.Remove(floor); // 检查当前批次是否全部失败 bool allFailedInBatch = true; if (_currentRequestBatch.Count > 0) allFailedInBatch = false; // 如果当前批次全部失败,请求下一批 if (allFailedInBatch) { RequestNextFloorBatch(); } } public bool IsRewardedAvailable() { return _successfulFloor != null && _rvFloorAdControllers.ContainsKey(_successfulFloor.id) && _rvFloorAdControllers[_successfulFloor.id] != null && _rvFloorAdControllers[_successfulFloor.id].IsReady(); } public void ShowRewarded(Action _action) { if (_successfulFloor != null && _rvFloorAdControllers.ContainsKey(_successfulFloor.id) && _rvFloorAdControllers[_successfulFloor.id] != null) { _rvFloorAdControllers[_successfulFloor.id].Show(); } else { _action?.Invoke(); } } /// /// 获取当前waterfall请求次数 /// public int GetWaterfallRequestCount() { return _waterfallRequestCount; } /// /// 获取当前waterfall请求次数 /// public int GetUniteIdRequestCount(string unitId) { return _unitIdRequestCounts.TryGetValue(unitId, out var time) ? time : 0; } /// /// 根据floor.id获取其在排序后的楼层列表中的索引位置 /// public int GetFloorIndex(string floorId) { for (int i = 0; i < _sortedFloors.Count; i++) { if (_sortedFloors[i].id == floorId) { return i; } } return -1; // 未找到 } /// /// 获取当前Request ID /// public string GetCurrentRequestId() { return _currentRequestId; } /// /// 生成唯一的Request ID /// private string GenerateRequestId() { return Guid.NewGuid().ToString("N"); } } }