public void Contains_ShouldReturnValidResult_ForRange()
        {
            // Arrange.
            var start       = new DateTime(2001, 1, 1, 1, 0, 0, 0, DateTimeKind.Local);
            var tomorrow    = start.AddDays(1);
            var nextWeek    = start.AddDays(7);
            var nextYear    = start.AddYears(1);
            var nextCentury = start.AddYears(100);
            var targetOne   = new DateTimeRange(start, nextYear);
            var targetTwo   = new DateTimeRange(start, tomorrow);
            var targetThree = new DateTimeRange(nextWeek, nextYear);
            var targetFour  = new DateTimeRange(tomorrow, nextWeek);
            var targetFive  = new DateTimeRange(nextWeek, nextCentury);

            // Act.
            var resultOne   = targetOne.Contains(targetOne);
            var resultTwo   = targetOne.Contains(targetTwo);
            var resultThree = targetOne.Contains(targetThree);
            var resultFour  = targetOne.Contains(targetFour);
            var resultFive  = targetOne.Contains(targetFive);

            // Assert.
            resultOne.Should().BeTrue();
            resultTwo.Should().BeTrue();
            resultThree.Should().BeTrue();
            resultFour.Should().BeTrue();
            resultFive.Should().BeFalse();
        }
        public void FunctionalLifeSpanTest_ShouldProduceDesiredResults_ForOneYearRange()
        {
            // Arrange.
            var start    = new DateTime(2001, 1, 1, 1, 0, 0, 0, DateTimeKind.Local);
            var end      = start.AddYears(1);
            var midpoint = start.AddMonths(6);
            var outlier  = end.AddYears(3);

            // Act.
            var target = new DateTimeRange(start, end);

            // Assert.
            target.Start.Should().Be(start);
            target.End.Should().Be(end);
            target.Contains(start).Should().BeTrue();
            target.Contains(end).Should().BeTrue();
            target.Contains(midpoint).Should().BeTrue();
            target.Contains(outlier).Should().BeFalse();
            target.LengthInYears.Should().Be(1);
            target.LengthInMonths.Should().Be(12);
            target.LengthInWeeks.Should().Be(52);
            target.LengthInDays.Should().Be(365);
            target.LengthInHours.Should().Be(8760);
            target.LengthInMinutes.Should().Be(525600);
            target.LengthInSeconds.Should().Be(31536000);
            target.LengthInMilliseconds.Should().Be(31536000000);
        }
Пример #3
0
        public void TestContains()
        {
            TimeSpan      step  = new TimeSpan(30, 0, 0, 0);
            DateTimeRange range = new DateTimeRange(new DateTime(2009, 1, 1), new DateTime(2010, 4, 20), step);

            Assert.IsTrue(range.Contains(range.Start + step));
            Assert.IsFalse(range.Contains(range.End.AddDays(1)));
        }
        public void Contains_Test()
        {
            // Arrange
            DateTimeRange dateTimeRange = new DateTimeRange(DateTime.Now, DateTime.Now.AddDays(2));
            DateTime      dateTime      = DateTime.Now.AddDays(1);

            // Act
            var result = dateTimeRange.Contains(dateTime: dateTime, excludeStart: true, excludeEnd: true);

            // Assert
            Assert.That(result);
        }
Пример #5
0
        private ImmutableList <Break> LoadBreaksToSmooth(
            DateTimeRange dateTimeRange,
            string salesAreaName)
        {
            return(_threadSafeCollections.BreaksForAllSalesAreasForSmoothPeriod
                   .Where(BreakIsInSalesAreaAndDateRange)
                   .ToImmutableList());

            // Local function
            bool BreakIsInSalesAreaAndDateRange(Break aBreak) =>
            aBreak.SalesArea.Equals(salesAreaName, StringComparison.InvariantCultureIgnoreCase) &&
            dateTimeRange.Contains(aBreak.ScheduledDate);
        }
        public void FunctionalLifeSpanTest_ShouldProduceDesiredResults_ForComplexRange()
        {
            // Arrange.
            var start = new DateTime(1997, 11, 6, 14, 7, 46, 482, DateTimeKind.Local);
            var end   = new DateTime(2024, 2, 29, 17, 41, 10, 193, DateTimeKind.Local);

            // Act.
            var target = new DateTimeRange(start, end);

            // Assert.
            target.Start.Should().Be(start);
            target.End.Should().Be(end);
            target.Contains(start).Should().BeTrue();
            target.Contains(end).Should().BeTrue();
            target.Contains(target.Midpoint).Should().BeTrue();
            target.LengthInYears.Should().Be(26);
            target.LengthInMonths.Should().Be(315);
            target.LengthInWeeks.Should().Be(1373);
            target.LengthInDays.Should().Be(9611);
            target.LengthInHours.Should().Be(230667);
            target.LengthInMinutes.Should().Be(13840053);
            target.LengthInSeconds.Should().Be(830403203);
            target.LengthInMilliseconds.Should().Be(830403203711);
        }
Пример #7
0
        Check_if_a_DateTimeRange_contains_a_specific_DateTime(
            DateTime dateRangeStart, DateTime dateRangeEnd,
            DateTime sample,
            bool expected
            )
        {
            // Arrange
            DateTimeRange labrat = (dateRangeStart, dateRangeEnd);

            // Act
            bool result = labrat.Contains(sample);

            // Assert
            _ = result.Should().Be(expected, becauseArgs: null);
        }
Пример #8
0
        public void ContainsTest()
        {
            var time0 = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            var time1 = new DateTime(2015, 12, 31, 0, 0, 0, DateTimeKind.Utc);
            var range = new DateTimeRange(time0, time1);

            Assert.IsFalse(range.Contains(DateTime.MinValue));
            Assert.IsFalse(range.Contains(new DateTime(1999, 12, 31, 0, 0, 0, DateTimeKind.Utc)));
            Assert.IsTrue(range.Contains(time0));
            Assert.IsTrue(range.Contains(new DateTime(2000, 6, 30, 0, 0, 0, DateTimeKind.Utc)));
            Assert.IsTrue(range.Contains(time1));
            Assert.IsFalse(range.Contains(new DateTime(2016, 1, 1, 0, 0, 0, DateTimeKind.Utc)));
            Assert.IsFalse(range.Contains(DateTime.MaxValue));
        }
Пример #9
0
        public void ShouldReturnFalseWhenCurrentRangeDoNotContainsDate()
        {
            // For
            DateTimeRange currentRange = new DateTimeRange
            {
                Start = new DateTime(2020, 04, 01),
                End   = new DateTime(2020, 04, 30)
            };

            DateTimeRange newRange = currentRange;

            // Given
            DateTime date  = new DateTime(2020, 03, 01);
            bool     value = newRange.Contains(date);

            // Assert
            Assert.IsFalse(value);
        }
Пример #10
0
        public void ShouldReturnFalseWhenCurrentRangeDoNotContainsRange(int month)
        {
            // For
            DateTimeRange currentRange = new DateTimeRange
            {
                Start = new DateTime(2020, 04, 01),
                End   = new DateTime(2020, 04, 30)
            };

            DateTimeRange newRange = currentRange;

            // Given
            DateTimeRange range = new DateTimeRange
            {
                Start = new DateTime(2020, month, 01),
                End   = new DateTime(2020, month, 30)
            };

            bool value = newRange.Contains(range);

            // Assert
            Assert.IsFalse(value);
        }
Пример #11
0
        public void ShouldReturnTrueWhenCurrentRangeContainsRange(int firstDay, int secondDay)
        {
            // For
            DateTimeRange currentRange = new DateTimeRange
            {
                Start = new DateTime(2020, 04, 01),
                End   = new DateTime(2020, 04, 30)
            };

            DateTimeRange newRange = currentRange;

            // Given
            DateTimeRange range = new DateTimeRange
            {
                Start = new DateTime(2020, 04, firstDay),
                End   = new DateTime(2020, 04, secondDay)
            };

            bool value = newRange.Contains(range);

            // Assert
            Assert.IsTrue(value);
        }
Пример #12
0
        private async Task <bool> SendSummaryNotificationAsync(Project project, SummaryNotification data)
        {
            // TODO: Add slack daily summaries
            var userIds = project.NotificationSettings.Where(n => n.Value.SendDailySummary && !String.Equals(n.Key, Project.NotificationIntegrations.Slack)).Select(n => n.Key).ToList();

            if (userIds.Count == 0)
            {
                _logger.LogInformation("Project {ProjectName} has no users to send summary to.", project.Name);
                return(false);
            }

            var results = await _userRepository.GetByIdsAsync(userIds, o => o.Cache()).AnyContext();

            var users = results.Where(u => u.IsEmailAddressVerified && u.EmailNotificationsEnabled && u.OrganizationIds.Contains(project.OrganizationId)).ToList();

            if (users.Count == 0)
            {
                _logger.LogInformation("Project {ProjectName} has no users to send summary to.", project.Name);
                return(false);
            }

            // TODO: What should we do about suspended organizations.
            var organization = await _organizationRepository.GetByIdAsync(project.OrganizationId, o => o.Cache()).AnyContext();

            if (organization == null)
            {
                _logger.LogInformation("The organization {organization} for project {ProjectName} may have been deleted. No summaries will be sent.", project.OrganizationId, project.Name);
                return(false);
            }

            _logger.LogInformation("Sending daily summary: users={UserCount} project={project}", users.Count, project.Id);
            var    sf           = new AppFilter(project, organization);
            var    systemFilter = new RepositoryQuery <PersistentEvent>().AppFilter(sf).DateRange(data.UtcStartTime, data.UtcEndTime, (PersistentEvent e) => e.Date).Index(data.UtcStartTime, data.UtcEndTime);
            string filter       = "type:error (status:open OR status:regressed)";
            var    result       = await _eventRepository.CountAsync(q => q.SystemFilter(systemFilter).FilterExpression(filter).EnforceEventStackFilter().AggregationsExpression("terms:(first @include:true) terms:(stack_id~3) cardinality:stack_id sum:count~1")).AnyContext();

            double total              = result.Aggregations.Sum("sum_count")?.Value ?? result.Total;
            double newTotal           = result.Aggregations.Terms <double>("terms_first")?.Buckets.FirstOrDefault()?.Total ?? 0;
            double uniqueTotal        = result.Aggregations.Cardinality("cardinality_stack_id")?.Value ?? 0;
            bool   hasSubmittedEvents = total > 0 || project.IsConfigured.GetValueOrDefault();
            bool   isFreePlan         = organization.PlanId == _plans.FreePlan.Id;

            string fixedFilter = "type:error status:fixed";
            var    fixedResult = await _eventRepository.CountAsync(q => q.SystemFilter(systemFilter).FilterExpression(fixedFilter).EnforceEventStackFilter().AggregationsExpression("sum:count~1")).AnyContext();

            double fixedTotal = fixedResult.Aggregations.Sum("sum_count")?.Value ?? fixedResult.Total;

            var range        = new DateTimeRange(data.UtcStartTime, data.UtcEndTime);
            var usages       = project.OverageHours.Where(u => range.Contains(u.Date)).ToList();
            int blockedTotal = usages.Sum(u => u.Blocked);
            int tooBigTotal  = usages.Sum(u => u.TooBig);

            IReadOnlyCollection <Stack> mostFrequent = null;
            var stackTerms = result.Aggregations.Terms <string>("terms_stack_id");

            if (stackTerms?.Buckets.Count > 0)
            {
                mostFrequent = await _stackRepository.GetByIdsAsync(stackTerms.Buckets.Select(b => b.Key).ToArray()).AnyContext();
            }

            IReadOnlyCollection <Stack> newest = null;

            if (newTotal > 0)
            {
                newest = (await _stackRepository.FindAsync(q => q.AppFilter(sf).FilterExpression(filter).SortExpression("-first").DateRange(data.UtcStartTime, data.UtcEndTime, "first"), o => o.PageLimit(3)).AnyContext()).Documents;
            }

            foreach (var user in users)
            {
                _logger.LogInformation("Queuing {ProjectName} daily summary email ({UtcStartTime}-{UtcEndTime}) for user {EmailAddress}.", project.Name, data.UtcStartTime, data.UtcEndTime, user.EmailAddress);
                await _mailer.SendProjectDailySummaryAsync(user, project, mostFrequent, newest, data.UtcStartTime, hasSubmittedEvents, total, uniqueTotal, newTotal, fixedTotal, blockedTotal, tooBigTotal, isFreePlan).AnyContext();
            }

            _logger.LogInformation("Done sending daily summary: users={UserCount} project={ProjectName} events={EventCount}", users.Count, project.Name, total);
            return(true);
        }
Пример #13
0
 public IEnumerable <Break> Search(DateTimeRange scheduledDatesRange, IEnumerable <string> salesAreaNames)
 {
     return(GetAllByType <Break>(_folder, _type, currentItem =>
                                 scheduledDatesRange.Contains(currentItem.ScheduledDate) && salesAreaNames.Contains(currentItem.SalesArea)));
 }
Пример #14
0
        private async Task <bool> SendSummaryNotificationAsync(Project project, SummaryNotification data)
        {
            // TODO: Add slack daily summaries
            var userIds = project.NotificationSettings.Where(n => n.Value.SendDailySummary && !String.Equals(n.Key, Project.NotificationIntegrations.Slack)).Select(n => n.Key).ToList();

            if (userIds.Count == 0)
            {
                _logger.Info().Project(project.Id).Message("Project \"{0}\" has no users to send summary to.", project.Name).Write();
                return(false);
            }

            var results = await _userRepository.GetByIdsAsync(userIds, o => o.Cache()).AnyContext();

            var users = results.Where(u => u.IsEmailAddressVerified && u.EmailNotificationsEnabled && u.OrganizationIds.Contains(project.OrganizationId)).ToList();

            if (users.Count == 0)
            {
                _logger.Info().Project(project.Id).Message("Project \"{0}\" has no users to send summary to.", project.Name);
                return(false);
            }

            // TODO: What should we do about suspended organizations.
            var organization = await _organizationRepository.GetByIdAsync(project.OrganizationId, o => o.Cache()).AnyContext();

            if (organization == null)
            {
                _logger.Info().Project(project.Id).Message("The organization \"{0}\" for project \"{1}\" may have been deleted. No summaries will be sent.", project.OrganizationId, project.Name);
                return(false);
            }

            _logger.Info("Sending daily summary: users={0} project={1}", users.Count, project.Id);
            var    sf           = new ExceptionlessSystemFilter(project, organization);
            var    systemFilter = new RepositoryQuery <PersistentEvent>().SystemFilter(sf).DateRange(data.UtcStartTime, data.UtcEndTime, (PersistentEvent e) => e.Date).Index(data.UtcStartTime, data.UtcEndTime);
            string filter       = $"{EventIndexType.Alias.Type}:{Event.KnownTypes.Error} {EventIndexType.Alias.IsHidden}:false {EventIndexType.Alias.IsFixed}:false";
            var    result       = await _eventRepository.CountBySearchAsync(systemFilter, filter, "terms:(first @include:true) terms:(stack_id~3) cardinality:stack_id sum:count~1").AnyContext();

            double total              = result.Aggregations.Sum("sum_count").Value ?? result.Total;
            double newTotal           = result.Aggregations.Terms <double>("terms_first")?.Buckets.FirstOrDefault()?.Total ?? 0;
            double uniqueTotal        = result.Aggregations.Cardinality("cardinality_stack_id")?.Value ?? 0;
            bool   hasSubmittedEvents = total > 0 || project.IsConfigured.GetValueOrDefault();
            bool   isFreePlan         = organization.PlanId == BillingManager.FreePlan.Id;

            string fixedFilter = $"{EventIndexType.Alias.Type}:{Event.KnownTypes.Error} {EventIndexType.Alias.IsHidden}:false {EventIndexType.Alias.IsFixed}:true";
            var    fixedResult = await _eventRepository.CountBySearchAsync(systemFilter, fixedFilter, "sum:count~1").AnyContext();

            double fixedTotal = fixedResult.Aggregations.Sum("sum_count").Value ?? fixedResult.Total;

            var range        = new DateTimeRange(data.UtcStartTime, data.UtcEndTime);
            var usages       = project.OverageHours.Where(u => range.Contains(u.Date)).ToList();
            int blockedTotal = usages.Sum(u => u.Blocked);
            int tooBigTotal  = usages.Sum(u => u.TooBig);

            IReadOnlyCollection <Stack> mostFrequent = null;
            var stackTerms = result.Aggregations.Terms <string>("terms_stack_id");

            if (stackTerms?.Buckets.Count > 0)
            {
                mostFrequent = await _stackRepository.GetByIdsAsync(stackTerms.Buckets.Select(b => b.Key).ToArray()).AnyContext();
            }

            IReadOnlyCollection <Stack> newest = null;

            if (newTotal > 0)
            {
                newest = (await _stackRepository.GetByFilterAsync(sf, filter, "-first", "first", data.UtcStartTime, data.UtcEndTime, o => o.PageLimit(3)).AnyContext()).Documents;
            }

            foreach (var user in users)
            {
                _logger.Info().Project(project.Id).Message("Queuing \"{0}\" daily summary email ({1}-{2}) for user {3}.", project.Name, data.UtcStartTime, data.UtcEndTime, user.EmailAddress);
                await _mailer.SendProjectDailySummaryAsync(user, project, mostFrequent, newest, data.UtcStartTime, hasSubmittedEvents, total, uniqueTotal, newTotal, fixedTotal, blockedTotal, tooBigTotal, isFreePlan).AnyContext();
            }

            _logger.Info().Project(project.Id).Message("Done sending daily summary: users={0} project={1} events={2}", users.Count, project.Name, total);
            return(true);
        }
Пример #15
0
        /// <summary>
        /// Creates a list of timelines from the provided time bands; only using
        /// valid sponsorships that meet sales area and time stamp
        /// </summary>
        private List <SmoothSponsorshipTimeline> CreateTimelinesFromTimeBands(
            IEnumerable <SponsoredItem> sponsoredItems)
        {
            var smoothTimelines = new List <SmoothSponsorshipTimeline>();

            foreach (var currentDate in _dateTimeRange)
            {
                foreach (var sponsoredItem in sponsoredItems)
                {
                    foreach (var sponsorship in sponsoredItem.SponsorshipItems)
                    {
                        DateTimeRange dateRange = (sponsorship.StartDate, sponsorship.EndDate);
                        foreach (var dayPart in sponsorship.DayParts)
                        {
                            AddSmoothTimelineByDate(
                                sponsoredItem,
                                currentDate,
                                dateRange,
                                dayPart);
                        }
                    }
                }
            }

            return(smoothTimelines);

            bool TimeBandIsOnValidDayOfWeek(string[] daysOfWeek, DateTime date) =>
            DayOfWeekHelper.DateFallsOnDayOfWeek(daysOfWeek, date);

            void AddSmoothTimelineByDate(
                SponsoredItem sponsoredItem,
                DateTime currentDate,
                DateTimeRange dateRange,
                SponsoredDayPart dayPart)
            {
                if (!(TimeBandIsOnValidDayOfWeek(dayPart.DaysOfWeek, currentDate) &&
                      dateRange.Contains(currentDate.Date)))
                {
                    return;
                }

                var start = DateHelper.ConvertBroadcastToStandard(currentDate.Date, dayPart.StartTime);
                var end   = DateHelper.ConvertBroadcastToStandard(currentDate.Date, dayPart.EndTime);

                List <(string advertiserIdentifier, int restrictionValue)> advertiserExclusivities =
                    GetAdvertiserReferenceAndRestrictionValue(
                        sponsoredItem.AdvertiserExclusivities,
                        sponsoredItem.RestrictionValue ?? 0);

                List <(string clashExternalReference, int restrictionValue)> clashExclusivities =
                    GetClashReferenceAndRestrictionValue(
                        sponsoredItem.ClashExclusivities,
                        sponsoredItem.RestrictionValue ?? 0);

                smoothTimelines.Add(new SmoothSponsorshipTimeline()
                {
                    DateTimeRange           = (start, end),
                    AdvertiserIdentifiers   = advertiserExclusivities,
                    ClashExternalReferences = clashExclusivities,
                    SponsoredProducts       = sponsoredItem.Products,
                    Applicability           = sponsoredItem.Applicability ?? SponsorshipApplicability.AllCompetitors,
                    CalculationType         = sponsoredItem.CalculationType
                });
            }