private BannerDataHolder PickBannerK(Identity id, BannerQuerySetInfo info) { int? indexOfBannerToReturn = null; double target = ThreadSafeRandom.NextDouble() * info.TotalRemainingImpressionsForTheCurrentTimeSlot; Stack<int> suitableBannersIndexes = new Stack<int>(); for (int i = 0; i < info.Banners.Count && indexOfBannerToReturn == null; i++) { long remainingHits = info.GetRemainingHits(i); if (remainingHits == 0) { continue; } target -= remainingHits; suitableBannersIndexes.Push(i); if (target <= 0) { indexOfBannerToReturn = ReturnFirstBannerThatNeedsAHit(id, suitableBannersIndexes, info); } } if (indexOfBannerToReturn.HasValue) { return info.Banners[indexOfBannerToReturn.Value]; } else { return null; } }
private void AddBanners(int numberOfBannersToGet, Identity id, BannerQuerySetInfo info, List<BannerDataHolder> chosenBanners) { for (int i = 0; i < numberOfBannersToGet - chosenBanners.Count; i++) { BannerDataHolder banner = PickBannerK(id, info); if (banner != null) { chosenBanners.Add(banner); } } }
private int? ReturnFirstBannerThatNeedsAHit(Identity id, Stack<int> suitableBanners, BannerQuerySetInfo info) { double hitProportion = Common.ThreadSafeRandom.NextDouble(); while (suitableBanners.Count > 0) { int index = suitableBanners.Peek(); BannerDataHolder banner = info.Banners[index]; if (BannerHasBeenShownToAParticularIdentityTooManyTimesToday(banner, id) || info.BannerNeedsToDropAHit(index, hitProportion)) { suitableBanners.Pop(); continue; } return suitableBanners.Peek(); } return null; }