public async void RandomCollectionReview(int noteCount)
        {
            // Setup DB & LazyLoader
            CardDbAsync db = new CardDbAsync();

            // Setup collection
            CollectionConfig    config    = CollectionConfig.Default;
            CollectionGenerator generator =
                new CollectionGenerator(
                    new CardGenerator(new TimeGenerator(3 * 30, true), config, noteCount * 2), noteCount,
                    3);

            IEnumerable <Note> notes = await generator.GenerateAsync(db).ConfigureAwait(true);

            // Collection review testing

            ReviewCollectionImpl reviewCollection = new ReviewCollectionImpl(db, config, true);

            bool @continue = await reviewCollection.Initialized.ConfigureAwait(true);

            while (@continue)
            {
                Card currentCard = reviewCollection.Current;

                currentCard.Should().NotBeNull();
                currentCard.Data.Should().NotBeNull();

                @continue = await reviewCollection.AnswerAsync(Grade.Good).ConfigureAwait(true);
            }
        }
        public async void AnswerCard(int cardCount, int gradeValue)
        {
            Grade grade = gradeValue;

            // Create context
            CardDbAsync        db     = new CardDbAsync();
            CollectionConfig   config = CollectionConfig.Default;
            IEnumerable <Note> notes  =
                await
                new CollectionGenerator(
                    new CardGenerator(new TimeGenerator(), config, cardCount), cardCount, 1)
                .GenerateAsync(db).ConfigureAwait(true);

            // Ensure context
            notes.Count().Should().Be(cardCount);
            notes.Sum(n => n.Cards.Count).Should().Be(cardCount);
            notes.Max(n => n.Cards.Count).Should().Be(1);
            notes.Min(n => n.Cards.Count).Should().Be(1);

            // Compute expected results
            int itCount    = 0;
            int itExpected = ComputeTotalReviewCount(notes, config, grade);

            // Create review collection and answer all
            ReviewCollectionImpl reviewCollection = new ReviewCollectionImpl(db, config, true);
            bool @continue = await reviewCollection.Initialized.ConfigureAwait(true);

            @continue.Should().Be(true);

            while (@continue)
            {
                itCount++;

                Card card = reviewCollection.Current;
                card.Should().NotBeNull();

                @continue = await reviewCollection.AnswerAsync(grade).ConfigureAwait(true);
            }

            itCount.Should().Be(itExpected);

            reviewCollection = new ReviewCollectionImpl(db, config, true);
            @continue        = await reviewCollection.Initialized.ConfigureAwait(true);

            @continue.Should().Be(false);
            reviewCollection.Current.Should().BeNull();
        }
        public async void ReviewCount()
        {
            // Create context
            CardDbAsync      db     = new CardDbAsync();
            CollectionConfig config = CollectionConfig.Default;

            int newCardCount = config.NewCardPerDay * 2;
            int dueCardCount = config.DueCardPerDay * 2;
            int cardCount    = newCardCount + dueCardCount;

            IEnumerable <Note> notes =
                await
                new CollectionGenerator(
                    new CardGenerator(
                        new TimeGenerator(), config, cardCount, newCardCount, 0, dueCardCount, 0),
                    cardCount, 1).GenerateAsync(db).ConfigureAwait(true);

            // Ensure context
            notes.Count().Should().Be(cardCount);
            notes.Sum(n => n.Cards.Count).Should().Be(cardCount);
            notes.Max(n => n.Cards.Count).Should().Be(1);
            notes.Min(n => n.Cards.Count).Should().Be(1);
            notes.Any(n => n.Cards.Any(c => c.Lapses > 0)).Should().Be(false);
            notes.Sum(n => n.Cards.Count(c => c.PracticeState == PracticeState.New))
            .Should()
            .Be(newCardCount);
            notes.Sum(n => n.Cards.Count(c => c.PracticeState == PracticeState.Due))
            .Should()
            .Be(dueCardCount);

            // Compute expected results
            int itCount      = 0;
            int itDueCount   = 0;
            int itNewCount   = 0;
            int itLearnCount = 0;

            HashSet <int> learnIds = new HashSet <int>();

            int itExpected = ComputeTotalReviewCount(notes, config, Grade.Good);

            int newCardGoal1 = config.NewCardPerDay / 2;
            int dueCardGoal1 = config.DueCardPerDay / 2;


            // 1
            // Create review collection and answer first batch
            ReviewCollectionImpl reviewCollection = new ReviewCollectionImpl(db, config, true);
            bool @continue = await reviewCollection.Initialized.ConfigureAwait(true);

            @continue.Should().Be(true);

            while (@continue)
            {
                // Sanity card check
                Card card = reviewCollection.Current;
                card.Should().NotBeNull();

                // Check learn cards
                if (card.IsLearning())
                {
                    learnIds.Contains(card.Id).Should().Be(false);
                    learnIds.Add(card.Id);
                }

                // Update counters
                itCount++;

                if (card.IsNew())
                {
                    itNewCount++;
                }
                else if (card.IsDue())
                {
                    itDueCount++;
                }
                else
                {
                    itLearnCount++;
                }

                // Answer
                @continue = await reviewCollection.AnswerAsync(Grade.Good).ConfigureAwait(true);

                int dueLeft = reviewCollection.CountByState(CardPracticeStateFilterFlag.Due);
                int newLeft = reviewCollection.CountByState(CardPracticeStateFilterFlag.New);

                @continue = @continue && dueLeft > dueCardGoal1;
                @continue = @continue && newLeft > newCardGoal1;

                // Assert
                newLeft.Should().Be(config.NewCardPerDay - itNewCount);
                dueLeft.Should().Be(config.DueCardPerDay - itDueCount);
            }

            itCount.Should().BeLessThan(itExpected);

            // 2
            // Create review collection and answer first batch
            reviewCollection = new ReviewCollectionImpl(db, config, true);
            @continue        = await reviewCollection.Initialized.ConfigureAwait(true);

            @continue.Should().Be(true);

            while (@continue)
            {
                // Sanity card check
                Card card = reviewCollection.Current;
                card.Should().NotBeNull();

                // Check learn cards
                if (card.IsLearning())
                {
                    learnIds.Contains(card.Id).Should().Be(false);
                    learnIds.Add(card.Id);
                }

                // Update counters
                itCount++;

                bool learn = false;

                if (card.IsNew())
                {
                    itNewCount++;
                }

                else if (card.IsDue())
                {
                    itDueCount++;
                }

                else
                {
                    itLearnCount++;
                    learn = true;
                }

                // Answer
                @continue = await reviewCollection.AnswerAsync(Grade.Good).ConfigureAwait(true);

                int dueLeft = reviewCollection.CountByState(CardPracticeStateFilterFlag.Due);
                int newLeft = reviewCollection.CountByState(CardPracticeStateFilterFlag.New);


                if (learn)
                {
                    card.IsLearning().Should().Be(false);
                }

                // Assert
                newLeft.Should().Be(config.NewCardPerDay - itNewCount);
                dueLeft.Should().Be(config.DueCardPerDay - itDueCount);
            }

            itNewCount.Should().Be(config.NewCardPerDay);
            itDueCount.Should().Be(config.DueCardPerDay);
            itLearnCount.Should().Be(config.NewCardPerDay);
            itCount.Should().Be(itExpected);
        }