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); }
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); }
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()); }