public async Task <List <BibleVerse> > GetBibleVersesAsync(BiblePathsCoreDbContext context, bool inQuestionOnly)
        {
            List <BibleVerse> bibleVerses = new List <BibleVerse>();
            // Go grab all of the questions for this Chapter once
            // So we can count them as we iterate through each verse
            List <QuizQuestion> Questions = await context.QuizQuestions
                                            .Where(Q => (Q.BibleId == BibleId || Q.BibleId == null) &&
                                                   Q.BookNumber == BookNumber &&
                                                   Q.Chapter == Chapter &&
                                                   Q.IsDeleted == false)
                                            .ToListAsync();

            if (Chapter != Bible.CommentaryChapter)
            {
                // First retrieve all of the verses,
                if (inQuestionOnly)
                {
                    bibleVerses = await context.BibleVerses.Where(v => v.BibleId == BibleId && v.BookNumber == BookNumber && v.Chapter == Chapter && v.Verse >= StartVerse && v.Verse <= EndVerse).OrderBy(v => v.Verse).ToListAsync();
                }
                else
                {
                    bibleVerses = await context.BibleVerses.Where(v => v.BibleId == BibleId && v.BookNumber == BookNumber && v.Chapter == Chapter).OrderBy(v => v.Verse).ToListAsync();
                }
                foreach (BibleVerse verse in bibleVerses)
                {
                    verse.QuestionCount = verse.GetQuestionCountWithQuestionList(Questions);
                }
            }
            else // COMMENTARY SCENARIO:
            {
                CommentaryBook commentary = await context.CommentaryBooks.Where(c => c.BibleId == BibleId &&
                                                                                c.BookNumber == BookNumber)
                                            .FirstAsync();

                BibleVerse CommentaryVerse = new BibleVerse
                {
                    BibleId    = BibleId,
                    BookName   = BookName,
                    BookNumber = BookNumber,
                    Chapter    = Chapter,
                    Verse      = 1,
                    Text       = commentary.Text,
                };
                bibleVerses.Add(CommentaryVerse);
            }
            return(bibleVerses);
        }
Exemplo n.º 2
0
        public static async Task <BibleVerse> GetVerseAsync(BiblePathsCoreDbContext context, string BibleId, int BookNumber, int Chapter, int Verse)
        {
            BibleVerse bibleVerse = new BibleVerse();

            try
            {
                bibleVerse = await context.BibleVerses.Where(v => v.BibleId == BibleId &&
                                                             v.BookNumber == BookNumber &&
                                                             v.Chapter == Chapter &&
                                                             v.Verse == Verse)
                             .SingleAsync();
            }
            catch
            {
                return(null);
            }
            return(bibleVerse);
        }
        public async Task <QuizQuestion> BuildQuestionForVerseAsync(BiblePathsCoreDbContext context, BibleVerse verse, int MaxPoints, string BibleId)
        {
            int           BlankWordProbability = 3; // read as 1 in every 3 valid words may get blanked rnd is 0 based
            int           MinPoints            = 3;
            int           Iteration            = 0;
            int           MaxIterations        = 3;
            string        BlankWordSring       = "_____";
            string        FitBPrepend          = "fill in the blanks: ";
            int           BlankedWordCount     = 0;
            List <string> BlankedWords         = new List <string>();
            string        QuestionString       = String.Empty;

            BibleId = await QuizQuestion.GetValidBibleIdAsync(context, BibleId);

            Random rnd = new Random();

            // We'll make at most MaxIteratons at this, increasing BlankWordProbability each time.
            while (Iteration < MaxIterations && BlankedWordCount < MinPoints)
            {
                QuestionString = verse.Text;
                BlankedWords.Clear();
                BlankedWordCount = 0;

                // Read the verse "word" by "word" i.e. stop at each Space till we hit the end.
                int i = 0;
                while (i < QuestionString.Length && BlankedWordCount < MaxPoints)
                {
                    int WordStart = i;
                    int WordEnd   = QuestionString.IndexOf(" ", i);
                    if (WordEnd == -1)
                    {
                        WordEnd = QuestionString.Length - 1;
                    }

                    // Now we should have a rough "word" to work with,
                    // but let's progressively shrink our Word Selction until it's starts/ends with a letter.
                    if (WordStart < WordEnd && WordEnd < QuestionString.Length)
                    {
                        // find the first letter
                        while (WordStart < WordEnd && !char.IsLetter(QuestionString, WordStart))
                        {
                            WordStart++;
                        }
                        // find the last letter
                        while (WordEnd > WordStart && !char.IsLetter(QuestionString, WordEnd))
                        {
                            WordEnd--;
                        }

                        // Now we should have a true "word" at least as far as we are concerned.
                        string Word = QuestionString.Substring(WordStart, (WordEnd + 1) - WordStart);

                        if (await IsWordGoodForBlankAsync(context, Word, BibleId))
                        {
                            // Ok now we don't want to simply replace every valid word so let's get random
                            int dice = rnd.Next(BlankWordProbability);
                            if (dice == 0) // 0 will always turn up on the 3rd iteration.
                            {
                                // Blank out our word in the QuestionString
                                StringBuilder VerseWithBlanksSB = new StringBuilder();
                                VerseWithBlanksSB.Append(QuestionString.Substring(0, WordStart));
                                VerseWithBlanksSB.Append(BlankWordSring);
                                VerseWithBlanksSB.Append(QuestionString.Substring(WordEnd + 1));
                                QuestionString = VerseWithBlanksSB.ToString();
                                // Add our word to the blanked words list
                                BlankedWords.Add(Word);
                                BlankedWordCount++;
                                // Set our index to the latest instance of BlankWordString
                                i = QuestionString.LastIndexOf(BlankWordSring) + BlankWordSring.Length;
                            }
                            else
                            {
                                i = WordEnd + 1;
                            }
                        }
                        else
                        {
                            i = WordEnd + 1;
                        }
                    }
                    else
                    {
                        // Why would we ever be here?
                        i = WordEnd + 1;
                    }
                }
                Iteration++;
                BlankWordProbability--; // Reducing this increases the probability of any word being selected.
            }

            QuizQuestion NewQuestion = new QuizQuestion();
            QuizAnswer   FitBAnswer  = new QuizAnswer();

            NewQuestion.BibleId    = BibleId;
            NewQuestion.Points     = BlankedWordCount;
            NewQuestion.Question   = FitBPrepend + QuestionString;
            NewQuestion.BookNumber = verse.BookNumber;
            NewQuestion.Chapter    = verse.Chapter;
            NewQuestion.StartVerse = verse.Verse;
            NewQuestion.EndVerse   = verse.Verse;
            NewQuestion.Source     = "BiblePaths.Net Question Generator - Iteration: " + Iteration.ToString();
            // Build the Answer
            FitBAnswer.Answer = string.Join(", ", BlankedWords);
            NewQuestion.QuizAnswers.Add(FitBAnswer);

            if (NewQuestion.QuizAnswers.Count > 0)
            {
                NewQuestion.IsAnswered = true;
            }
            else
            {
                NewQuestion.IsAnswered = false;
            }

            return(NewQuestion);
        }
Exemplo n.º 4
0
        public async Task <List <PathNode> > GetTeamStepsAsync(BiblePathsCoreDbContext context, string BibleId)
        {
            List <PathNode> ReturnSteps = new List <PathNode>();
            // The goal is to return a set of random Steps + Current Step, all related to Keyword
            // Get our current step and all details
            PathNode CurrentStep = await context.PathNodes.FindAsync(CurrentStepId);

            _ = await CurrentStep.AddGenericStepPropertiesAsync(context, BibleId);

            _ = await CurrentStep.AddPathStepPropertiesAsync(context);

            CurrentStep.Verses = await CurrentStep.GetBibleVersesAsync(context, BibleId, true, false);

            ReturnSteps.Add(CurrentStep);

            int VerseCount = (CurrentStep.EndVerse - CurrentStep.StartVerse) + 1;

            // Build A hashtable of our current verses so we can exclude them.
            Hashtable CurrentVerses = new Hashtable();

            foreach (BibleVerse currentVerse in CurrentStep.Verses)
            {
                CurrentVerses.Add(currentVerse.Id, null);
            }
            // Performance change: Instead of searching Text we'll reference the BibleWordIndex Table
            // Find all verses with associated with KeyWord, not in our Current Step verses
            //List<BibleVerse> FoundVerses = await context.BibleVerses.Where(V => V.BibleId == BibleId
            //                                                                && V.Text.Contains(KeyWord))
            //                                                            .ToListAsync();

            List <BibleWordIndex> FoundVerses = await GetVerseIndicesByWordAsync(context, BibleId, KeyWord);

            var rand = new Random();

            // now select 6 from this set randomly using a HashTable to ensure Uniqueness
            // We select 6 and throw one or more out to reduce impact from duplicates in randomization.
            Hashtable UniqueVerses = new Hashtable();

            for (int i = 0; i < 6; i++)
            {
                int VerseIndex = rand.Next(FoundVerses.Count - 1);
                if (!UniqueVerses.ContainsKey(FoundVerses[VerseIndex].VerseId))
                {
                    // We don't want any of our CurrentVerses either.
                    if (!CurrentVerses.ContainsKey(FoundVerses[VerseIndex].VerseId))
                    {
                        UniqueVerses.Add(FoundVerses[VerseIndex].VerseId, null);
                    }
                }
            }
            // We need 4 random Unique "Ids" as well we'll use these to sort the bodgedSteps
            // We use a range around CurrentStep to make it difficult to guess based on Id.
            Hashtable UniqueIds = new Hashtable();
            int       LowRange  = CurrentStep.Id - 10;

            if (LowRange < 0)
            {
                LowRange = 0;
            }
            int HighRange = CurrentStep.Id + 10;
            int KnownGood = HighRange + 1;

            // now we've got a selected set of unique verses let's build appropriate sized Steps out of them.
            foreach (int VerseId in UniqueVerses.Keys)
            {
                // Now we go grab or actual verse object.
                BibleVerse FoundVerse = await context.BibleVerses.FindAsync(VerseId);

                if (FoundVerse == null)
                {
                    continue;
                }
                // Pick a Random ID
                int RandomID = rand.Next(LowRange, HighRange);
                if (!UniqueIds.ContainsKey(RandomID) && RandomID != CurrentStep.Id)
                {
                    UniqueIds.Add(RandomID, null);
                }
                else
                {
                    RandomID = KnownGood;
                    UniqueIds.Add(KnownGood, null);
                    KnownGood++;
                }

                // Build our Bodged Step
                PathNode bodgedStep = new PathNode();
                bodgedStep.Id         = RandomID;
                bodgedStep.BookNumber = FoundVerse.BookNumber;
                bodgedStep.Chapter    = FoundVerse.Chapter;
                int ChapterLen = await bodgedStep.GetChapterLengthAsync(context, BibleId);

                if (VerseCount > 1)
                {
                    int Increment = (int)VerseCount / 2;
                    bodgedStep.StartVerse = (FoundVerse.Verse - Increment + 1 > 0) ? (FoundVerse.Verse - Increment + 1) : FoundVerse.Verse;
                    bodgedStep.EndVerse   = (FoundVerse.Verse + Increment <= ChapterLen) ? (FoundVerse.Verse + Increment) : FoundVerse.Verse;
                }
                else
                {
                    bodgedStep.StartVerse = FoundVerse.Verse;
                    bodgedStep.EndVerse   = FoundVerse.Verse;
                }
                _ = await bodgedStep.AddGenericStepPropertiesAsync(context, BibleId);

                bodgedStep.Verses = await bodgedStep.GetBibleVersesAsync(context, BibleId, true, false);

                if (ReturnSteps.Count < 4)
                {
                    ReturnSteps.Add(bodgedStep);
                }
                else
                {
                    return(ReturnSteps.OrderBy(S => S.Id).ToList());
                }
            }
            return(ReturnSteps.OrderBy(S => S.Id).ToList());
        }