public void When_the_projector_runs_for_more_than_10_minutes_it_should_only_evaluate_the_last_10_minutes()
        {
            //-----------------------------------------------------------------------------------------------------------
            // Arrange
            //-----------------------------------------------------------------------------------------------------------
            DateTime nowUtc = 16.June(2017).At(15, 00).AsUtc();

            var stats = new ProjectionStats(() => nowUtc);

            //-----------------------------------------------------------------------------------------------------------
            // Act
            //-----------------------------------------------------------------------------------------------------------
            long checkpoint = 0;

            // The first ten minutes should be ignored
            for (int seconds = 0; seconds < (10 * 60); ++seconds)
            {
                checkpoint += 1000;

                stats.TrackProgress("myProjector", checkpoint);

                nowUtc = nowUtc.Add(1.Seconds());
            }

            // Then nine minutes of 2000/s.
            for (int seconds = 0; seconds < (9 * 60); ++seconds)
            {
                checkpoint += 2000;

                stats.TrackProgress("myProjector", checkpoint);

                nowUtc = nowUtc.Add(1.Seconds());
            }

            // The last minute should run on 3000/s
            for (int seconds = 0; seconds < (60); ++seconds)
            {
                checkpoint += 3000;

                stats.TrackProgress("myProjector", checkpoint);

                nowUtc = nowUtc.Add(1.Seconds());
            }

            //-----------------------------------------------------------------------------------------------------------
            // Assert
            //-----------------------------------------------------------------------------------------------------------
            TimeSpan?eta = stats.GetTimeToReach("myProjector", checkpoint + 100000);

            float precalculatedWeightedAveragePerSecond = 2222.5022F;

            long secondsToComplete = (long)(100000 / precalculatedWeightedAveragePerSecond);

            eta.Should().Be(TimeSpan.FromSeconds(secondsToComplete));
            stats.GetSpeed("myProjector").Should().BeApproximately(precalculatedWeightedAveragePerSecond, 1);
        }
        public void When_the_projector_has_not_checked_in_yet_it_should_not_provide_an_eta()
        {
            //-----------------------------------------------------------------------------------------------------------
            // Arrange
            //-----------------------------------------------------------------------------------------------------------
            var stats = new ProjectionStats(() => DateTime.UtcNow);

            //-----------------------------------------------------------------------------------------------------------
            // Act
            //-----------------------------------------------------------------------------------------------------------
            TimeSpan?eta = stats.GetTimeToReach("myProjector", 100000);

            //-----------------------------------------------------------------------------------------------------------
            // Assert
            //-----------------------------------------------------------------------------------------------------------
            eta.Should().NotHaveValue();

            stats.GetSpeed("myProjector").Should().BeNull();
        }
        public void When_the_projectors_speed_increases_it_should_favor_the_higher_speed_in_the_eta()
        {
            //-----------------------------------------------------------------------------------------------------------
            // Arrange
            //-----------------------------------------------------------------------------------------------------------
            DateTime nowUtc = 16.June(2017).At(15, 00).AsUtc();

            var stats = new ProjectionStats(() => nowUtc);

            long transactionsPerSecond = 1000;

            //-----------------------------------------------------------------------------------------------------------
            // Act
            //-----------------------------------------------------------------------------------------------------------
            long checkpoint = 0;

            for (int seconds = 0; seconds < 60; ++seconds)
            {
                checkpoint += transactionsPerSecond;

                stats.TrackProgress("myProjector", checkpoint);

                nowUtc = nowUtc.Add(1.Seconds());
                transactionsPerSecond += 100;
            }

            //-----------------------------------------------------------------------------------------------------------
            // Assert
            //-----------------------------------------------------------------------------------------------------------
            TimeSpan?eta = stats.GetTimeToReach("myProjector", checkpoint + 100000);

            long weightedAveragePerSecond = 4550;

            stats.GetSpeed("myProjector").Should().Be(weightedAveragePerSecond);


            long secondsToComplete = 100000 / weightedAveragePerSecond;

            eta.Should().Be(TimeSpan.FromSeconds(secondsToComplete));
        }
        public void When_the_projector_is_ahead_of_the_requested_checkpoint_the_eta_should_be_zero()
        {
            //-----------------------------------------------------------------------------------------------------------
            // Arrange
            //-----------------------------------------------------------------------------------------------------------
            DateTime utcNow = new DateTime(2017, 7, 4, 11, 50, 0, DateTimeKind.Utc);
            var      stats  = new ProjectionStats(() => utcNow);

            stats.TrackProgress("myProjector", 1000);

            //-----------------------------------------------------------------------------------------------------------
            // Act
            //-----------------------------------------------------------------------------------------------------------
            utcNow = new DateTime(2017, 7, 4, 11, 52, 0, DateTimeKind.Utc);
            stats.TrackProgress("myProjector", 10000);

            //-----------------------------------------------------------------------------------------------------------
            // Assert
            //-----------------------------------------------------------------------------------------------------------
            stats.GetSpeed("myProjector").Should().Be((10000 - 1000) / 120);
            stats.GetTimeToReach("myProjector", 5000).Should().Be(TimeSpan.Zero);
        }
        public void When_the_projector_runs_at_a_constant_speed_it_should_use_that_to_calculate_the_eta()
        {
            //-----------------------------------------------------------------------------------------------------------
            // Arrange
            //-----------------------------------------------------------------------------------------------------------
            DateTime nowUtc = 16.June(2017).At(15, 00).AsUtc();

            var stats = new ProjectionStats(() => nowUtc);

            long transactionsPerSecond = 1000;

            //-----------------------------------------------------------------------------------------------------------
            // Act
            //-----------------------------------------------------------------------------------------------------------
            long checkpoint = 0;

            for (int seconds = 0; seconds < 60; ++seconds)
            {
                checkpoint += transactionsPerSecond;

                stats.TrackProgress("myProjector", checkpoint);

                nowUtc = nowUtc.Add(1.Seconds());
            }

            //-----------------------------------------------------------------------------------------------------------
            // Assert
            //-----------------------------------------------------------------------------------------------------------
            TimeSpan?eta = stats.GetTimeToReach("myProjector", 100000);

            stats.GetSpeed("myProjector").Should().Be(transactionsPerSecond);

            long secondsToComplete = (100000 - checkpoint) / transactionsPerSecond;

            eta.Should().Be(TimeSpan.FromSeconds(secondsToComplete));
        }