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);
        }
Beispiel #2
0
        public async Task <QuizQuestion> GetNextQuizQuestionFromTemplateAsync(BiblePathsCoreDbContext context, string bibleId)
        {
            QuizQuestion   ReturnQuestion = new QuizQuestion();
            PredefinedQuiz Template       = new PredefinedQuiz();

            try
            {
                Template = await context.PredefinedQuizzes.Include(T => T.PredefinedQuizQuestions).Where(T => T.Id == PredefinedQuiz).FirstAsync();
            }
            catch
            {
                // This is the couldn't find template scenario,
                ReturnQuestion.QuestionSelected = false;
                return(ReturnQuestion);
            }
            // Ok we've got our Template now which Book/Chapter do we want.
            int QuestionNumber         = QuestionsAsked + 1;
            int TemplateQuestionNumber = QuestionNumber;

            // We need to calculate a Template Number
            if (QuestionNumber > Template.NumQuestions)
            {
                TemplateQuestionNumber = QuestionNumber % Template.NumQuestions;
                if (TemplateQuestionNumber == 0)
                {
                    TemplateQuestionNumber = Template.NumQuestions;
                }
            }
            // It is actually OK to not find a Question Object, we just treat that as the random book scenario.
            PredefinedQuizQuestion TemplateQuestion = new PredefinedQuizQuestion();

            try
            {
                TemplateQuestion = Template.PredefinedQuizQuestions.Where(Q => Q.QuestionNumber == TemplateQuestionNumber).First();
            }
            catch
            {
                // This is the more common pick a random Book Scenario.
                if (Template.BookNumber >= Bible.MinBookListID)
                {
                    // This is the BookList Scenario
                    return(await GetNextQuizQuestionFromBookListAsync(context, bibleId, Template.BookNumber));
                }
                else
                {
                    // this is the Book scenario.
                    return(await GetNextQuizQuestionFromBookAsync(context, bibleId, Template.BookNumber));
                }
            }
            if (TemplateQuestion.BookNumber == 0)
            {
                // This is the pick a random Book Scenario, we're unlikely to hit this, more often the question object won't exist at all.
                if (Template.BookNumber >= Bible.MinBookListID)
                {
                    // This is the BookList Scenario
                    return(await GetNextQuizQuestionFromBookListAsync(context, bibleId, Template.BookNumber));
                }
                else
                {
                    // this is the Book scenario.
                    return(await GetNextQuizQuestionFromBookAsync(context, bibleId, Template.BookNumber));
                }
            }
            else
            {
                // This would be the selected Book Scenario, but do we have a selected Chapter?
                if (TemplateQuestion.Chapter == 0)
                {
                    // this is the selected book but random Chapter scenario
                    return(await GetNextQuizQuestionFromBookAsync(context, bibleId, TemplateQuestion.BookNumber));
                }
                else
                {
                    // this is the selected Book and Chapter scenario
                    return(await GetNextQuizQuestionFromBookAndChapterAsync(context, bibleId, TemplateQuestion.BookNumber, TemplateQuestion.Chapter));
                }
            }
        }