void AddBannner(BannerDataHolder banner, Timeslot currentTimeslot, int i)
		{
			BannerTimeslotInfoWithDesiredHits info = new BannerTimeslotInfoWithDesiredHits(banner, currentTimeslot);
			info.Considerations.Increment();
			long actualHits = info.ActualHits.Value;
			long targetHits = (long)Math.Ceiling(getTargetHits(info) * Server.ServiceMultiplier);
			long remainingHits = (actualHits < targetHits) ? (targetHits - actualHits) : 0;
			if (remainingHits == 0)
			{
				if (Common.Settings.SpreadBannerHits)
				{
					info.NotifyAllHitsServed();
					#region REMOVED DUE TO BANNER SERVER BUG
					//IndicesOfBannersThatHaveReachedTheirLimits.Add(i);
					#endregion
				}
			}
			else
			{
				Banners.Add(banner);
				BannerTimeslotInfos.Add(info);
				TotalRemainingImpressionsForTheCurrentTimeSlot += remainingHits;
				ActualHitsList.Add(actualHits);
				RequiredHitsList.Add(targetHits);
			}
		}
		public TargetHitsBannerQuerySetInfo(List<BannerDataHolder> banners, Timeslot currentTimeslot, Func<BannerTimeslotInfoWithDesiredHits, long> getTargetHits)
			: base(banners)
		{
			this.getTargetHits = getTargetHits;
			this.BannerTimeslotInfos = new List<BannerTimeslotInfoWithDesiredHits>(allBannersMatchingQuery.Count);
			for (int i = 0; i < allBannersMatchingQuery.Count; i++)
			{
				BannerDataHolder banner = allBannersMatchingQuery[i];
				if (banner.AlwaysShow == false)
				{
					AddBannner(banner, currentTimeslot, i);
				}
			}
		}
		private long GetTotalRequiredImpressions(Banner.Positions position, DateTime date)
		{
			return Caching.Instances.Main.Get("RequiredImpressionsForBannerImpressionStats" + date.ToString("yyyymmdd") + position.ToString(), () =>
			{
				long desiredHits = 0;
				using (new Common.General.Context<Clock>(() => Common.Time.Clock, (c) => Common.Time.Clock = c, new FixedClock(date)))
				{
					Query q = new Query();
					q.QueryCondition = new And(Banner.IsLiveQ, new Q(Banner.Columns.Position, position));
					BannerSet bs = new BannerSet(q);

					foreach (Banner b in bs)
					{
						for (Timeslot timeslot = new Timeslot(date); timeslot.StartTime < date.AddDays(1); timeslot = timeslot.GetNextTimeslot())
						{
							BannerTimeslotInfoWithDesiredHits bannerTimeslotInfo = new BannerTimeslotInfoWithDesiredHits(b, timeslot);
							desiredHits += bannerTimeslotInfo.DesiredHits;
						}
					}
				}
				return desiredHits;
				}
			);
		}
		public BannerTimeslotInfoWithDesiredHits(IBannerDesiredHitsRequiredInformation bannerDataHolder, Timeslot timeslot)
			: base(bannerDataHolder.K, timeslot)
		{
			this.bdh = bannerDataHolder;
		}
		public BannerTimeslotInfo(int bannerK, Timeslot timeslot)
		{
			this.bannerK = bannerK;
			this.timeslot = timeslot;
			this.cacheKey = "BannerTimeslotInfo(" + timeslot.GetCacheKey() + "," + this.bannerK + ")";
		}
		protected void Page_Load(object sender, EventArgs e)
		{
			Query q = Bobs.BannerServer.Server.GetQueryForBannersActiveBetweenTwoTimes(DateTime.Today, DateTime.Now);
			q.OrderBy = new OrderBy(new OrderBy(Banner.Columns.Position), new OrderBy(Banner.Columns.K));
			BannerSet bannerSet = new BannerSet(q);
			List<Banner> banners = bannerSet.ToList();

			Timeslot timeslotMinus0 = Timeslots.GetCurrentTimeslot();
			Timeslot timeslotMinus1 = timeslotMinus0.GetPreviousTimeslot();

			if (!IsPostBack){
				this.TimeslotStart.Items.Add(timeslotMinus0.StartTime.ToString());
				this.TimeslotEnd.Items.Add(timeslotMinus0.StartTime.ToString());
				DateTime date = timeslotMinus0.StartTime.Date.AddDays(-7);
				while (date < timeslotMinus0.StartTime)
				{
					this.TimeslotStart.Items.Insert(1, date.ToString());
					this.TimeslotEnd.Items.Insert(1, date.ToString());
					date = date.AddHours(8);
				}
				this.TimeslotStart.SelectedIndex = (int) global::Caching.Instances.MainCounterStore.GetCounter("BannerHitViewer.TimeslotStart.SelectedValue for Usr " + Usr.Current.K, () => 0u);
				this.TimeslotEnd.SelectedIndex = (int)global::Caching.Instances.MainCounterStore.GetCounter("BannerHitViewer.TimeslotEnd.SelectedValue for Usr " + Usr.Current.K, () => 1u);
			}

			global::Caching.Instances.MainCounterStore.SetCounter("BannerHitViewer.TimeslotStart.SelectedValue for Usr " + Usr.Current.K, (uint) this.TimeslotStart.SelectedIndex);
			global::Caching.Instances.MainCounterStore.SetCounter("BannerHitViewer.TimeslotEnd.SelectedValue for Usr " + Usr.Current.K, (uint) this.TimeslotEnd.SelectedIndex);


			List<BannerInfo> bannerData = new List<BannerInfo>();
			List<BannerTotalStat> bannerTotalStat = BannerStat.GetBannerStatTotals(banners.ConvertAll(b=>b.K).ToArray());
			

			for (int i=0;i<banners.Count;i++)
			{
				Banner banner = banners[i];
				BannerTimeslotInfoWithDesiredHits bannerTimeslotInfo = new BannerTimeslotInfoWithDesiredHits(banner, timeslotMinus0);
				BannerTimeslotInfoWithDesiredHits previousBannerTimeslotInfo = new BannerTimeslotInfoWithDesiredHits(banner, timeslotMinus1);
				long actualHitsPreviousTimeslot = previousBannerTimeslotInfo.ActualHits.Value;
				long hitsRequiredPreviousTimeslot = previousBannerTimeslotInfo.RequiredHits;
				long hitsDesiredPreviousTimeslot = previousBannerTimeslotInfo.DesiredHits;
				long actualHitsCurrentTimeslot = bannerTimeslotInfo.ActualHits.Value;
				long hitsRequiredCurrentTimeslot = bannerTimeslotInfo.RequiredHits;
				long hitsDesiredCurrentTimeslot = bannerTimeslotInfo.DesiredHits;

				float elapsedLifespan = (float) (Time.Now - banner.FirstDay).TotalDays;
				float lifespan = (float) (banner.LastDay - banner.FirstDay).TotalDays + 1;

				BannerInfo bannerInfo = new BannerInfo()
					{
						K = banner.K,
						Name = banner.Name,
						Position = banner.Position,
						Url = banner.Url(),
						IsMusicTargetted = banner.IsMusicTargetted,
						IsPlaceTargetted = banner.IsPlaceTargetted,
						HitsRequired = banner.TotalRequiredImpressions,
						HitsSoFar = banner.TotalHits,
						UniqueHitsSoFar = bannerTotalStat[i].UniqueVisitors,
						HitsSoFarDb = bannerTotalStat[i].Hits,
						ClicksSoFar = (int)banner.TotalClicks,
						ClicksSoFarDb = bannerTotalStat[i].Clicks,
						ElapsedLifespan = elapsedLifespan,
						Lifespan = lifespan,
						IsTotalHitRateBad = elapsedLifespan / lifespan > 0.5 && ((float)banner.TotalHits / (float)banner.TotalRequiredImpressions) < (0.9 * elapsedLifespan / lifespan),
						ActualHitsCurrentTimeslot = actualHitsCurrentTimeslot,
						HitsRequiredCurrentTimeslot = hitsRequiredCurrentTimeslot,
						HitsDesiredCurrentTimeslot = hitsDesiredCurrentTimeslot,
						ActualHitsPreviousTimeslot = actualHitsPreviousTimeslot,
						HitsRequiredPreviousTimeslot = hitsRequiredPreviousTimeslot,
						HitsDesiredPreviousTimeslot = hitsDesiredPreviousTimeslot,
						IsPreviousTimeslotBad = actualHitsPreviousTimeslot < 0.9 * hitsDesiredPreviousTimeslot,
						IsCurrentTimeslotBad = actualHitsCurrentTimeslot < 0.9 * (Timeslot.ElapsedTimeSinceStartOfCurrentTimeInterval(Time.Now, Timeslot.Duration).TotalMinutes / Timeslot.Duration.TotalMinutes) * hitsDesiredCurrentTimeslot,
						TimesConsidered = bannerTimeslotInfo.Considerations.Value,
						TimesConsideredPrev = previousBannerTimeslotInfo.Considerations.Value,
						Rate = bannerTimeslotInfo.ProportionToBeServed,
						RatePrev = previousBannerTimeslotInfo.ProportionToBeServed,
						RemainingSecondsWhenPreviousBannerCompleted = bannerTimeslotInfo.NumberOfSecondsLeftWhenAllHitsWereServed.Value,
						CreditsPerClick =  ((double)banner.PriceCredits * ((double)banner.TotalHits / (double)banner.TotalRequiredImpressions)) / (double)banner.TotalClicks
					};
				bannerData.Add(bannerInfo);
			}

			this.BannerInfoRepeater.DataSource = bannerData;
			this.BannerInfoRepeater.DataBind();

			

			List<TimeslotInfo> timeslotInfos = new List<TimeslotInfo>();
			Timeslot first;
			try
			{
				first = new Timeslot(DateTime.Parse(TimeslotStart.SelectedValue));
			}
			catch
			{
				first = timeslotMinus0;
			}
			Timeslot last;
			try
			{
				last = new Timeslot(DateTime.Parse(TimeslotStart.SelectedValue));
			}
			catch
			{
				last = timeslotMinus1;
			}
			
			if (first.StartTime < last.StartTime)
			{
				Timeslot temp = first;
				first = last;
				last = temp;
			}

			List<Timeslot> timeslots = new List<Timeslot>();
			while(first.StartTime >= last.StartTime)
			{
				timeslots.Add(first);
				first = first.GetPreviousTimeslot();
			}
			foreach (Timeslot ts in timeslots)
			{
				long actualHits = 0;
				long requiredHits = 0;

				if (ts.StartTime != timeslotMinus0.StartTime)
				{
					actualHits = global::Caching.Instances.Main.Get(ts.GetCacheKey() + "actualHitsForBannerHitViewer", () =>
						{
							long hits = 0;
							banners.ForEach(b =>
							{
								BannerTimeslotInfo info = new BannerTimeslotInfo(b.K, ts);
								hits += info.ActualHits.Value; 
							});
							return hits;
						}
					);
					requiredHits = global::Caching.Instances.Main.Get(ts.GetCacheKey() + "requiredHitsForBannerHitViewer", () =>
						{
							long hits = 0;
							banners.ForEach(b => {
								BannerTimeslotInfoWithDesiredHits info = new BannerTimeslotInfoWithDesiredHits(b, ts);
								hits += info.DesiredHits; 
							});
							return hits;
						}
					);
				}
				else
				{

					banners.ForEach(b => {
						BannerTimeslotInfo info = new BannerTimeslotInfo(b.K, ts); 
						actualHits += info.ActualHits.Value; 
					});
					banners.ForEach(b => {
						BannerTimeslotInfoWithDesiredHits info = new BannerTimeslotInfoWithDesiredHits(b, ts); 
						requiredHits += info.DesiredHits;
					});
				}
				

				
				
				TimeslotInfo ti = new TimeslotInfo()
								  {
									  TimeslotStart = ts.StartTime,
									  NotShown = ts.TotalNotShown().Value,
									  Actual = actualHits,
									  Required = requiredHits,
									  Timeouts = ts.BannerTimeouts().Value,
									  CallsToBannerServer = ts.CallsToBannerServer().Value

								  };

				
				timeslotInfos.Add(ti);
			}


			this.TimeslotInfoRepeater.DataSource = timeslotInfos;
			this.TimeslotInfoRepeater.DataBind();
			
			
		}