/// ------------------------------------------------------------------------------------
 /// <summary>
 /// Returns an enumerator that iterates through the collection of questions.
 /// </summary>
 /// <returns>
 /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to
 /// iterate through the collection.
 /// </returns>
 /// ------------------------------------------------------------------------------------
 public static void GenerateAlternateForms(QuestionSections sections, Dictionary <string, string[]> alternatives)
 {
     string[] altForms;
     foreach (Section section in sections.Items)
     {
         foreach (Category category in section.Categories)
         {
             if (category.Questions == null)
             {
                 continue;
             }
             foreach (Question q in category.Questions)
             {
                 if (alternatives != null && alternatives.TryGetValue(q.Text, out altForms))
                 {
                     q.AlternateForms = altForms;
                 }
                 else
                 {
                     QuestionProviderAlternateFormBuilder bldr = new QuestionProviderAlternateFormBuilder(q.Text);
                     if (bldr.Alternatives.Count > 1)
                     {
                         q.AlternateForms = new string[bldr.Alternatives.Count];
                         for (int index = 0; index < bldr.Alternatives.Count; index++)
                         {
                             q.AlternateForms[index] = bldr.Alternatives[index];
                         }
                     }
                 }
             }
         }
     }
 }
        public static QuestionSections Generate(IEnumerable <string> sourceLines, Dictionary <string, string[]> alternatives)
        {
            m_canonicalBookNumbers = new HashSet <int>();

            // Initialize the ID textbox.
            Category        currCat = null;
            string          currRef = null;
            int             startRef = 0, endRef = 0;
            Section         currSection = null;
            bool            currSectionRefSet = false;
            Question        currQuestion = null;
            List <Section>  sections = new List <Section>();
            List <Question> currentQuestions = new List <Question>();
            int             cAnswers = 0, cComments = 0, cCategories = 0;
            int             kSectHeadMarkerLen = s_kSectionHead.Length;
            int             kRefMarkerLen      = s_kRefMarker.Length;
            int             kQMarkerLen        = s_kQuestionMarker.Length;
            int             kAMarkerLen        = s_kAnswerMarker.Length;
            int             kCommentMarkerLen  = s_kCommentMarker.Length;

            Debug.Assert(s_kDetailsMarker.Length == s_kOverviewMarker.Length);
            int   kCategoryMarkerLen = s_kDetailsMarker.Length;
            Regex regexVerseNum      = new Regex(@"\((?<startVerse>\d+)(-(?<endVerse>\d+))?\)$", RegexOptions.Compiled);

            foreach (string sLine in SourceFields(sourceLines))
            {
                if (sLine.StartsWith(s_kQuestionMarker))
                {
                    if (currQuestion != null && cAnswers == 0 && cComments == 0)
                    {
                        // Question continued in a subsequent field. Just append the text to the existing question.
                        currQuestion.Text += " " + sLine.Substring(kQMarkerLen).Trim();
                    }
                    else
                    {
                        currQuestion = new Question();
                        currentQuestions.Add(currQuestion);
                        currQuestion.Text = sLine.Substring(kQMarkerLen).Trim();
                        if (currRef != currSection.ScriptureReference)
                        {
                            currQuestion.ScriptureReference = currRef;
                            currQuestion.StartRef           = startRef;
                            currQuestion.EndRef             = endRef;
                        }
                        cAnswers  = 0;
                        cComments = 0;
                    }
                }
                else if (sLine.StartsWith(s_kAnswerMarker))
                {
                    string currAnswer = sLine.Substring(kAMarkerLen).Trim();
                    if (!currCat.IsOverview)
                    {
                        Match match = regexVerseNum.Match(currAnswer);
                        if (match.Success)
                        {
                            int    startVerse = Int32.Parse(match.Result("${startVerse}"));
                            string sEndVerse = match.Result("${endVerse}");
                            int    endVerse = string.IsNullOrEmpty(sEndVerse) ? startVerse : Int32.Parse(sEndVerse);
                            BCVRef bcvStart, bcvEnd;
                            if (currQuestion.StartRef > 0)
                            {
                                bcvStart = new BCVRef(currQuestion.StartRef);
                                bcvEnd   = new BCVRef(currQuestion.EndRef);
                                if (startVerse < bcvStart.Verse)
                                {
                                    bcvStart.Verse = startVerse;
                                }
                                if (endVerse > bcvEnd.Verse)
                                {
                                    bcvEnd.Verse = endVerse;
                                }
                            }
                            else
                            {
                                bcvStart       = new BCVRef(currSection.StartRef);
                                bcvEnd         = new BCVRef(currSection.EndRef);
                                bcvStart.Verse = startVerse;
                                bcvEnd.Verse   = endVerse;
                            }
                            currQuestion.StartRef           = bcvStart.BBCCCVVV;
                            currQuestion.EndRef             = bcvEnd.BBCCCVVV;
                            currQuestion.ScriptureReference = BCVRef.MakeReferenceString(
                                currSection.ScriptureReference.Substring(0, 3), bcvStart, bcvEnd, ".", "-");
                        }
                    }
                    string[] source = currQuestion.Answers;
                    currQuestion.Answers = new string[cAnswers + 1];
                    if (source != null)
                    {
                        Array.Copy(source, currQuestion.Answers, cAnswers);
                    }

                    currQuestion.Answers[cAnswers++] = currAnswer;
                }
                else if (sLine.StartsWith(s_kCommentMarker))
                {
                    if (currQuestion != null)
                    {
                        string[] source = currQuestion.Notes;
                        currQuestion.Notes = new string[cComments + 1];
                        if (source != null)
                        {
                            Array.Copy(source, currQuestion.Notes, cComments);
                        }

                        currQuestion.Notes[cComments++] = sLine.Substring(kCommentMarkerLen).Trim();
                    }
                }
                else
                {
                    if (sLine.StartsWith(s_kRefMarker))
                    {
                        currRef = sLine.Substring(kRefMarkerLen).Trim();
                        Parse(currRef, out startRef, out endRef);
                        if (!currSectionRefSet)
                        {
                            currSection.ScriptureReference = currRef;
                            currSection.StartRef           = startRef;
                            currSection.EndRef             = endRef;
                            currSectionRefSet = true;
                        }
                    }
                    else if (sLine.StartsWith(s_kSectionHead))
                    {
                        if (currentQuestions.Count > 0)
                        {
                            currCat.Questions = currentQuestions.ToArray();
                            currentQuestions.Clear();
                        }
                        currSection = new Section();
                        sections.Add(currSection);
                        cCategories               = 1;
                        currSection.Categories    = new Category[cCategories];
                        currSection.Categories[0] = currCat = new Category();
                        currSection.Heading       = sLine.Substring(kSectHeadMarkerLen).Trim();
                        currSectionRefSet         = false;
                    }
                    else
                    {
                        bool isOverviewMarker = sLine.StartsWith(s_kOverviewMarker);
                        if (isOverviewMarker || sLine.StartsWith(s_kDetailsMarker))
                        {
                            if (currentQuestions.Count > 0)
                            {
                                currCat.Questions = currentQuestions.ToArray();
                                currentQuestions.Clear();
                            }
                            if (currCat.Type != null || currCat.Questions != null)
                            {
                                currCat = new Category();
                                Category[] source = currSection.Categories;
                                currSection.Categories = new Category[cCategories + 1];
                                if (source != null)
                                {
                                    Array.Copy(source, currSection.Categories, cCategories);
                                }

                                currSection.Categories[cCategories++] = currCat;
                            }
                            currCat.Type       = sLine.Substring(kCategoryMarkerLen).Trim();
                            currCat.IsOverview = isOverviewMarker;
                        }
                    }

                    if (currQuestion != null)
                    {
                        currQuestion = null;
                        cAnswers     = 0;
                        cComments    = 0;
                    }
                }
            }
            if (currCat != null && currentQuestions.Count > 0)
            {
                currCat.Questions = currentQuestions.ToArray();
            }

            QuestionSections questionSections = new QuestionSections();

            questionSections.Items = sections.ToArray();
            GenerateAlternateForms(questionSections, alternatives);
            return(questionSections);
        }
		public void AddedPhrases_InsertAfterAdditionAfterInsertionBefore()
		{
			List<PhraseCustomization> customizations = new List<PhraseCustomization>();
			PhraseCustomization pc = new PhraseCustomization();
			pc.Reference = "ACT 1.6";
			pc.OriginalPhrase = "Base question";
			pc.ModifiedPhrase = "AAA";
			pc.Type = PhraseCustomization.CustomizationType.InsertionBefore;
			customizations.Add(pc);
			pc = new PhraseCustomization();
			pc.Reference = "ACT 1.6";
			pc.OriginalPhrase = "AAA";
			pc.ModifiedPhrase = "CCC";
			pc.Type = PhraseCustomization.CustomizationType.AdditionAfter;
			customizations.Add(pc);
			pc = new PhraseCustomization();
			pc.Reference = "ACT 1.6";
			pc.OriginalPhrase = "CCC";
			pc.ModifiedPhrase = "BBB";
			pc.Type = PhraseCustomization.CustomizationType.InsertionBefore;
			customizations.Add(pc);

			QuestionSections qs = new QuestionSections();
			qs.Items = new Section[1];
			qs.Items[0] = CreateSection("ACT 1.1-6", "Acts 1:1-6 Introduction to the book.", 44001001,
				44001006, 0, 1);
			Question q = qs.Items[0].Categories[1].Questions[0];
			q.ScriptureReference = "ACT 1.6";
			q.StartRef = 44001006;
			q.EndRef = 44001006;
			q.Text = "Base question";

			QuestionProvider qp = new QuestionProvider(qs, customizations);

			List<TranslatablePhrase> phrases = qp.ToList();
			Assert.AreEqual(6, phrases.Count);

			TranslatablePhrase phrase = phrases[2];
			Assert.AreEqual("AAA", phrase.PhraseInUse);
			Assert.GreaterOrEqual(phrase.SequenceNumber, 0);
			Assert.Less(phrase.SequenceNumber, phrases[3].SequenceNumber);
			Assert.IsNull(phrase.InsertedPhraseBefore);
			Assert.AreEqual(phrases[4].QuestionInfo, phrase.AddedPhraseAfter);

			phrase = phrases[3];
			Assert.AreEqual("BBB", phrase.PhraseInUse);
			Assert.Less(phrase.SequenceNumber, phrases[4].SequenceNumber);
			Assert.IsNull(phrase.InsertedPhraseBefore);
			Assert.IsNull(phrase.AddedPhraseAfter);

			phrase = phrases[4];
			Assert.AreEqual("CCC", phrase.PhraseInUse);
			Assert.Less(phrase.SequenceNumber, phrases[5].SequenceNumber);
			Assert.AreEqual(phrases[3].QuestionInfo, phrase.InsertedPhraseBefore);
			Assert.IsNull(phrase.AddedPhraseAfter);

			phrase = phrases[5];
			Assert.AreEqual("Base question", phrase.PhraseInUse);
			Assert.AreEqual(phrases[2].QuestionInfo, phrase.InsertedPhraseBefore);
			Assert.IsNull(phrase.AddedPhraseAfter);
		}
Example #4
0
 /// ------------------------------------------------------------------------------------
 /// <summary>
 /// Initializes a new instance of the <see cref="QuestionProvider"/> class.
 /// </summary>
 /// <param name="sections">Class representing the questions, organized by Scripture
 /// section and category.</param>
 /// <param name="customizations">.</param>
 /// ------------------------------------------------------------------------------------
 public QuestionProvider(QuestionSections sections, IEnumerable <PhraseCustomization> customizations)
 {
     m_sections       = sections;
     m_customizations = customizations;
 }
		public void AddedPhrases_Compound()
		{
			List<PhraseCustomization> customizations = new List<PhraseCustomization>();
			PhraseCustomization pc = new PhraseCustomization();
			pc.Reference = "ACT 1.1-5";
			pc.OriginalPhrase = "What do you think an apostle of Jesus is?";
			pc.ModifiedPhrase = "Is this question before the one about the meaning of apostle?";
			pc.Answer = "Yup";
			pc.Type = PhraseCustomization.CustomizationType.InsertionBefore;
			customizations.Add(pc);
			pc = new PhraseCustomization();
			pc.Reference = "ACT 1.6";
			pc.OriginalPhrase = "What question did the apostles ask Jesus about his kingdom?";
			pc.ModifiedPhrase = "What did He answer?";
			pc.Answer = "He told them to mind their own business.";
			pc.Type = PhraseCustomization.CustomizationType.AdditionAfter;
			customizations.Add(pc);
			pc = new PhraseCustomization();
			pc.Reference = "ACT 1.1-5";
			pc.OriginalPhrase = "Is this question before the one about the meaning of apostle?";
			pc.ModifiedPhrase = "Is this question before the one before the one about the meaning of apostle?";
			pc.Type = PhraseCustomization.CustomizationType.InsertionBefore;
			customizations.Add(pc);
			pc = new PhraseCustomization();
			pc.Reference = "ACT 1.1-5";
			pc.OriginalPhrase = "Is this question before the one about the meaning of apostle?";
			pc.ModifiedPhrase = "This is going to hurt, isn't it?";
			pc.Type = PhraseCustomization.CustomizationType.AdditionAfter;
			customizations.Add(pc);
			pc = new PhraseCustomization();
			pc.Reference = "ACT 1.6";
			pc.OriginalPhrase = "What did He answer?";
			pc.ModifiedPhrase = "I said, what did He answer?";
			pc.Type = PhraseCustomization.CustomizationType.AdditionAfter;
			customizations.Add(pc);
			pc = new PhraseCustomization();
			pc.Reference = "ACT 1.6";
			pc.OriginalPhrase = "I said, what did He answer?";
			pc.ModifiedPhrase = "Can I just go home now?";
			pc.Type = PhraseCustomization.CustomizationType.AdditionAfter;
			customizations.Add(pc);

			QuestionSections qs = new QuestionSections();
			qs.Items = new Section[2];
			int iS = 0;
			qs.Items[iS] = CreateSection("ACT 1.1-5", "Acts 1:1-5 Introduction to the book.", 44001001,
				44001005, 2, 1);
			int iC = 0;
			Question q = qs.Items[iS].Categories[iC].Questions[0];
			q.Text = "What information did Luke, the writer of this book, give in this introduction?";
			q.Answers = new[] { "Luke reminded his readers that he was about to continue the true story about Jesus" };
			q = qs.Items[iS].Categories[iC].Questions[1];
			q.Text = "What do you think an apostle of Jesus is?";
			q.Answers = new[] { "Key Term Check: To be an apostle of Jesus means to be a messenger" };

			iC = 1;
			q = qs.Items[iS].Categories[iC].Questions[0];
			q.Text = "To whom did the writer of Acts address this book?";
			q.Answers = new[] { "He addressed this book to Theophilus." };

			iS = 1;
			qs.Items[iS] = CreateSection("ACT 1.6-10", "Acts 1:6-10 The continuing saga.", 44001006, 44001010, 1, 1);
			iC = 0;
			q = qs.Items[iS].Categories[iC].Questions[0];
			q.Text = "What happened?";
			q.Answers = new[] { "Stuff" };

			iC = 1;
			q = qs.Items[iS].Categories[iC].Questions[0];
			q.ScriptureReference = "ACT 1.6";
			q.StartRef = 44001006;
			q.EndRef = 44001006;
			q.Text = "What question did the apostles ask Jesus about his kingdom?";
			q.Answers = new[] { "The apostles asked Jesus whether he was soon going to set up his kingdom in a way that everybody could see and cause the people of Israel to have power in that kingdom." };

			QuestionProvider qp = new QuestionProvider(qs, customizations);

			List<TranslatablePhrase> phrases = qp.ToList();
			Assert.AreEqual(13, phrases.Count);
			Assert.AreEqual(1, qp.AvailableBookIds.Length);
			Assert.AreEqual(44, qp.AvailableBookIds[0]);
			Assert.AreEqual(2, qp.SectionHeads.Count);
			Assert.AreEqual("Acts 1:1-5 Introduction to the book.", qp.SectionHeads["ACT 1.1-5"]);
			Assert.AreEqual("Acts 1:6-10 The continuing saga.", qp.SectionHeads["ACT 1.6-10"]);

			TranslatablePhrase phrase = phrases[0];
			Assert.AreEqual("Overview", phrase.PhraseInUse);
			Assert.AreEqual(-1, phrase.Category);
			Assert.AreEqual(string.Empty, phrase.Reference);
			Assert.AreEqual(001001001, phrase.StartRef);
			Assert.AreEqual(066022021, phrase.EndRef);
			Assert.AreEqual(0, phrase.SequenceNumber);
			Assert.IsNull(phrase.QuestionInfo);

			phrase = phrases[1];
			Assert.AreEqual("What information did Luke, the writer of this book, give in this introduction?",
				phrase.PhraseInUse);
			Assert.AreEqual(0, phrase.Category);
			Assert.AreEqual("ACT 1.1-5", phrase.Reference);
			Assert.AreEqual(44001001, phrase.StartRef);
			Assert.AreEqual(44001005, phrase.EndRef);
			Assert.Greater(phrase.SequenceNumber, 0);
			Assert.IsNull(phrase.InsertedPhraseBefore);
			Assert.IsNull(phrase.AddedPhraseAfter);
			Assert.IsNotNull(phrase.QuestionInfo);
			Assert.AreEqual(1, phrase.QuestionInfo.Answers.Count());
			Assert.AreEqual("Luke reminded his readers that he was about to continue the true story about Jesus",
				phrase.QuestionInfo.Answers.First());

			phrase = phrases[2];
			Assert.AreEqual("Is this question before the one before the one about the meaning of apostle?", phrase.PhraseInUse);
			Assert.AreEqual(0, phrase.Category);
			Assert.AreEqual("ACT 1.1-5", phrase.Reference);
			Assert.AreEqual(44001001, phrase.StartRef);
			Assert.AreEqual(44001005, phrase.EndRef);
			Assert.Less(phrases[1].SequenceNumber, phrase.SequenceNumber);
			Assert.IsNull(phrase.InsertedPhraseBefore);
			Assert.IsNull(phrase.AddedPhraseAfter);
			Assert.IsNull(phrase.QuestionInfo.Answers);

			phrase = phrases[3];
			Assert.AreEqual("Is this question before the one about the meaning of apostle?", phrase.PhraseInUse);
			Assert.AreEqual(0, phrase.Category);
			Assert.AreEqual("ACT 1.1-5", phrase.Reference);
			Assert.AreEqual(44001001, phrase.StartRef);
			Assert.AreEqual(44001005, phrase.EndRef);
			Assert.Less(phrases[2].SequenceNumber, phrase.SequenceNumber);
			Assert.AreEqual(phrases[2].QuestionInfo, phrase.InsertedPhraseBefore);
			Assert.AreEqual(phrases[4].QuestionInfo, phrase.AddedPhraseAfter);
			Assert.AreEqual("Yup", phrase.QuestionInfo.Answers.First());

			phrase = phrases[4];
			Assert.AreEqual("This is going to hurt, isn't it?", phrase.PhraseInUse);
			Assert.AreEqual(0, phrase.Category);
			Assert.AreEqual("ACT 1.1-5", phrase.Reference);
			Assert.AreEqual(44001001, phrase.StartRef);
			Assert.AreEqual(44001005, phrase.EndRef);
			Assert.Less(phrases[3].SequenceNumber, phrase.SequenceNumber);
			Assert.IsNull(phrase.InsertedPhraseBefore);
			Assert.IsNull(phrase.AddedPhraseAfter);
			Assert.IsNull(phrase.QuestionInfo.Answers);

			phrase = phrases[5];
			Assert.AreEqual("What do you think an apostle of Jesus is?", phrase.PhraseInUse);
			Assert.AreEqual(0, phrase.Category);
			Assert.AreEqual("ACT 1.1-5", phrase.Reference);
			Assert.AreEqual(44001001, phrase.StartRef);
			Assert.AreEqual(44001005, phrase.EndRef);
			Assert.Less(phrases[4].SequenceNumber, phrase.SequenceNumber);
			Assert.AreEqual("Is this question before the one about the meaning of apostle?", phrase.InsertedPhraseBefore.Text);
			Assert.IsNull(phrase.AddedPhraseAfter);
			Assert.IsNotNull(phrase.QuestionInfo);
			Assert.AreEqual(1, phrase.QuestionInfo.Answers.Count());
			Assert.AreEqual("Key Term Check: To be an apostle of Jesus means to be a messenger",
				phrase.QuestionInfo.Answers.ElementAt(0));

			phrase = phrases[6];
			Assert.AreEqual("Details", phrase.PhraseInUse);
			Assert.AreEqual(-1, phrase.Category);
			Assert.AreEqual(string.Empty, phrase.Reference);
			Assert.AreEqual(001001001, phrase.StartRef);
			Assert.AreEqual(066022021, phrase.EndRef);
			Assert.AreEqual(1, phrase.SequenceNumber);
			Assert.IsNull(phrase.InsertedPhraseBefore);
			Assert.IsNull(phrase.AddedPhraseAfter);
			Assert.IsNull(phrase.QuestionInfo);

			phrase = phrases[7];
			Assert.AreEqual("To whom did the writer of Acts address this book?", phrase.PhraseInUse);
			Assert.AreEqual(1, phrase.Category);
			Assert.AreEqual("ACT 1.1-5", phrase.Reference);
			Assert.AreEqual(44001001, phrase.StartRef);
			Assert.AreEqual(44001005, phrase.EndRef);
			Assert.AreEqual(1, phrase.SequenceNumber);
			Assert.IsNull(phrase.InsertedPhraseBefore);
			Assert.IsNull(phrase.AddedPhraseAfter);
			Assert.IsNotNull(phrase.QuestionInfo);
			Assert.AreEqual(1, phrase.QuestionInfo.Answers.Count());
			Assert.AreEqual("He addressed this book to Theophilus.",
				phrase.QuestionInfo.Answers.First());

			phrase = phrases[8];
			Assert.AreEqual("What happened?", phrase.PhraseInUse);
			Assert.AreEqual(0, phrase.Category);
			Assert.AreEqual("ACT 1.6-10", phrase.Reference);
			Assert.AreEqual(44001006, phrase.StartRef);
			Assert.AreEqual(44001010, phrase.EndRef);
			Assert.AreEqual(1, phrase.SequenceNumber);
			Assert.IsNull(phrase.InsertedPhraseBefore);
			Assert.IsNull(phrase.AddedPhraseAfter);
			Assert.IsNotNull(phrase.QuestionInfo);
			Assert.AreEqual(1, phrase.QuestionInfo.Answers.Count());
			Assert.AreEqual("Stuff", phrase.QuestionInfo.Answers.First());

			phrase = phrases[9];
			Assert.AreEqual("What question did the apostles ask Jesus about his kingdom?",
				phrase.PhraseInUse);
			Assert.AreEqual(1, phrase.Category);
			Assert.AreEqual("ACT 1.6", phrase.Reference);
			Assert.AreEqual(44001006, phrase.StartRef);
			Assert.AreEqual(44001006, phrase.EndRef);
			Assert.Greater(phrase.SequenceNumber, 0);
			Assert.IsNull(phrase.InsertedPhraseBefore);
			Assert.AreEqual(phrases[10].QuestionInfo, phrase.AddedPhraseAfter);
			Assert.IsNotNull(phrase.QuestionInfo);
			Assert.AreEqual(1, phrase.QuestionInfo.Answers.Count());
			Assert.AreEqual("The apostles asked Jesus whether he was soon going to set up his kingdom in a way that everybody could see and cause the people of Israel to have power in that kingdom.",
				phrase.QuestionInfo.Answers.First());

			phrase = phrases[10];
			Assert.AreEqual("What did He answer?", phrase.PhraseInUse);
			Assert.AreEqual(1, phrase.Category);
			Assert.AreEqual("ACT 1.6", phrase.Reference);
			Assert.AreEqual(44001006, phrase.StartRef);
			Assert.AreEqual(44001006, phrase.EndRef);
			Assert.Less(phrases[9].SequenceNumber, phrase.SequenceNumber);
			Assert.IsNull(phrase.InsertedPhraseBefore);
			Assert.AreEqual(phrases[11].QuestionInfo, phrase.AddedPhraseAfter);
			Assert.AreEqual("He told them to mind their own business.", phrase.QuestionInfo.Answers.First());

			phrase = phrases[11];
			Assert.AreEqual("I said, what did He answer?", phrase.PhraseInUse);
			Assert.AreEqual(1, phrase.Category);
			Assert.AreEqual("ACT 1.6", phrase.Reference);
			Assert.AreEqual(44001006, phrase.StartRef);
			Assert.AreEqual(44001006, phrase.EndRef);
			Assert.Less(phrases[10].SequenceNumber, phrase.SequenceNumber);
			Assert.IsNull(phrase.InsertedPhraseBefore);
			Assert.AreEqual(phrases[12].QuestionInfo, phrase.AddedPhraseAfter);
			Assert.IsNull(phrase.QuestionInfo.Answers);

			phrase = phrases[12];
			Assert.AreEqual("Can I just go home now?", phrase.PhraseInUse);
			Assert.AreEqual(1, phrase.Category);
			Assert.AreEqual("ACT 1.6", phrase.Reference);
			Assert.AreEqual(44001006, phrase.StartRef);
			Assert.AreEqual(44001006, phrase.EndRef);
			Assert.Less(phrases[11].SequenceNumber, phrase.SequenceNumber);
			Assert.IsNull(phrase.QuestionInfo.Answers);
		}
		public void AddedPhrases_AddAfterInsertionBefore()
		{
			List<PhraseCustomization> customizations = new List<PhraseCustomization>();
			PhraseCustomization pc = new PhraseCustomization();
			pc.Reference = "ACT 1.6";
			pc.OriginalPhrase = "What question did the apostles ask Jesus about his kingdom?";
			pc.ModifiedPhrase = "Is this question before the one about the meaning of apostle?";
			pc.Type = PhraseCustomization.CustomizationType.InsertionBefore;
			customizations.Add(pc);
			pc = new PhraseCustomization();
			pc.Reference = "ACT 1.6";
			pc.OriginalPhrase = "Is this question before the one about the meaning of apostle?";
			pc.ModifiedPhrase = "This is a phrase after the inserted question.";
			pc.Type = PhraseCustomization.CustomizationType.AdditionAfter;
			customizations.Add(pc);

			QuestionSections qs = new QuestionSections();
			qs.Items = new Section[1];
			qs.Items[0] = CreateSection("ACT 1.1-6", "Acts 1:1-6 Introduction to the book.", 44001001,
				44001006, 0, 1);
			Question q = qs.Items[0].Categories[1].Questions[0];
			q.ScriptureReference = "ACT 1.6";
			q.StartRef = 44001006;
			q.EndRef = 44001006;
			q.Text = "What question did the apostles ask Jesus about his kingdom?";
			q.Answers = new[] { "Stuff." };

			QuestionProvider qp = new QuestionProvider(qs, customizations);

			List<TranslatablePhrase> phrases = qp.ToList();
			Assert.AreEqual(5, phrases.Count);

			TranslatablePhrase phrase = phrases[2];
			Assert.AreEqual("Is this question before the one about the meaning of apostle?", phrase.PhraseInUse);
			Assert.AreEqual(1, phrase.Category);
			Assert.AreEqual("ACT 1.6", phrase.Reference);
			Assert.AreEqual(44001006, phrase.StartRef);
			Assert.AreEqual(44001006, phrase.EndRef);
			Assert.GreaterOrEqual(phrase.SequenceNumber, 0);
			Assert.Less(phrase.SequenceNumber, phrases[3].SequenceNumber);
			Assert.IsNull(phrase.InsertedPhraseBefore);
			Assert.AreEqual(phrases[3].QuestionInfo, phrase.AddedPhraseAfter);
			Assert.IsNull(phrase.QuestionInfo.Answers);

			phrase = phrases[3];
			Assert.AreEqual("This is a phrase after the inserted question.", phrase.PhraseInUse);
			Assert.AreEqual(1, phrase.Category);
			Assert.AreEqual("ACT 1.6", phrase.Reference);
			Assert.AreEqual(44001006, phrase.StartRef);
			Assert.AreEqual(44001006, phrase.EndRef);
			Assert.Less(phrase.SequenceNumber, phrases[4].SequenceNumber);
			Assert.IsNull(phrase.InsertedPhraseBefore);
			Assert.IsNull(phrase.AddedPhraseAfter);
			Assert.IsNull(phrase.QuestionInfo.Answers);

			phrase = phrases[4];
			Assert.AreEqual("What question did the apostles ask Jesus about his kingdom?", phrase.PhraseInUse);
			Assert.AreEqual(1, phrase.Category);
			Assert.AreEqual("ACT 1.6", phrase.Reference);
			Assert.AreEqual(44001006, phrase.StartRef);
			Assert.AreEqual(44001006, phrase.EndRef);
			Assert.AreEqual(phrases[2].QuestionInfo, phrase.InsertedPhraseBefore);
			Assert.IsNull(phrase.AddedPhraseAfter);
			Assert.IsNotNull(phrase.QuestionInfo);
			Assert.AreEqual(1, phrase.QuestionInfo.Answers.Count());
			Assert.AreEqual("Stuff.", phrase.QuestionInfo.Answers.ElementAt(0));
		}
		public void ExcludePhrases()
		{
			List<PhraseCustomization> customizations = new List<PhraseCustomization>();
			PhraseCustomization pc = new PhraseCustomization();
			pc.Reference = "ACT 1.1-5";
			pc.OriginalPhrase = "What do you think an apostle of Jesus is?";
			pc.Type = PhraseCustomization.CustomizationType.Deletion;
			customizations.Add(pc);
			pc = new PhraseCustomization();
			pc.Reference = "ACT 1.6";
			pc.OriginalPhrase = "What question did the apostles ask Jesus about his kingdom?";
			pc.Type = PhraseCustomization.CustomizationType.Deletion;
			customizations.Add(pc);

			QuestionSections qs = new QuestionSections();
			qs.Items = new Section[2];
			int iS = 0;
			qs.Items[iS] = CreateSection("ACT 1.1-5", "Acts 1:1-5 Introduction to the book.", 44001001,
				44001005, 2, 1);
			int iC = 0;
			Question q = qs.Items[iS].Categories[iC].Questions[0];
			q.Text = "What information did Luke, the writer of this book, give in this introduction?";
			q.Answers = new[] { "Luke reminded his readers that he was about to continue the true story about Jesus" };
			q = qs.Items[iS].Categories[iC].Questions[1];
			q.Text = "What do you think an apostle of Jesus is?";
			q.Answers = new[] { "Key Term Check: To be an apostle of Jesus means to be a messenger"};

			iC = 1;
			q = qs.Items[iS].Categories[iC].Questions[0];
			q.Text = "To whom did the writer of Acts address this book?";
			q.Answers = new[] { "He addressed this book to Theophilus." };

			iS = 1;
			qs.Items[iS] = CreateSection("ACT 1.6-10", "Acts 1:6-10 The continuing saga.", 44001006, 44001010, 1, 1);
			iC = 0;
			q = qs.Items[iS].Categories[iC].Questions[0];
			q.Text = "What happened?";
			q.Answers = new[] { "Stuff" };

			iC = 1;
			q = qs.Items[iS].Categories[iC].Questions[0];
			q.ScriptureReference = "ACT 1.6";
			q.StartRef = 44001006;
			q.EndRef = 44001006;
			q.Text = "What question did the apostles ask Jesus about his kingdom?";
			q.Answers = new[] { "The apostles asked Jesus whether he was soon going to set up his kingdom in a way that everybody could see and cause the people of Israel to have power in that kingdom." };

			QuestionProvider qp = new QuestionProvider(qs, customizations);

			List<TranslatablePhrase> phrases = qp.ToList();
			Assert.AreEqual(7, phrases.Count);
			Assert.AreEqual(1, qp.AvailableBookIds.Length);
			Assert.AreEqual(44, qp.AvailableBookIds[0]);
			Assert.AreEqual(2, qp.SectionHeads.Count);
			Assert.AreEqual("Acts 1:1-5 Introduction to the book.", qp.SectionHeads["ACT 1.1-5"]);
			Assert.AreEqual("Acts 1:6-10 The continuing saga.", qp.SectionHeads["ACT 1.6-10"]);

			TranslatablePhrase phrase = phrases[0];
			Assert.AreEqual("Overview", phrase.PhraseInUse);
			Assert.IsFalse(phrase.IsExcluded);

			phrase = phrases[1];
			Assert.AreEqual("What information did Luke, the writer of this book, give in this introduction?",
				phrase.PhraseInUse);
			Assert.IsFalse(phrase.IsExcluded);

			phrase = phrases[2];
			Assert.AreEqual("What do you think an apostle of Jesus is?", phrase.PhraseInUse);
			Assert.IsTrue(phrase.IsExcluded);

			phrase = phrases[3];
			Assert.AreEqual("Details", phrase.PhraseInUse);
			Assert.IsFalse(phrase.IsExcluded);

			phrase = phrases[4];
			Assert.AreEqual("To whom did the writer of Acts address this book?",
				phrase.PhraseInUse);
			Assert.IsFalse(phrase.IsExcluded);

			phrase = phrases[5];
			Assert.AreEqual("What happened?", phrase.PhraseInUse);
			Assert.IsFalse(phrase.IsExcluded);

			phrase = phrases[6];
			Assert.AreEqual("What question did the apostles ask Jesus about his kingdom?",
				phrase.PhraseInUse);
			Assert.IsTrue(phrase.IsExcluded);
		}
		public void EnumeratePhrases_Basic()
		{
			QuestionSections qs = new QuestionSections();
			qs.Items = new Section[2];
			int iS= 0;
			qs.Items[iS] = CreateSection("ACT 1.1-5", "Acts 1:1-5 Introduction to the book.", 44001001,
				44001005, 2, 1);
			int iC = 0;
			Question q = qs.Items[iS].Categories[iC].Questions[0];
			q.Text = "What information did Luke, the writer of this book, give in this introduction?";
			q.Answers = new [] { "Luke reminded his readers that he was about to continue the true story about Jesus" };
			q = qs.Items[iS].Categories[iC].Questions[1];
			q.Text = "What do you think an apostle of Jesus is?";
			q.Answers = new [] { "Key Term Check: To be an apostle of Jesus means to be a messenger", "Can also be translated as \"sent one\"" };
			q.Notes = new [] {"Note: apostles can be real sweethearts sometimes"};

			iC = 1;
			q = qs.Items[iS].Categories[iC].Questions[0];
			q.Text = "To whom did the writer of Acts address this book?";
			q.Answers = new [] { "He addressed this book to Theophilus." };

			iS= 1;
			qs.Items[iS] = CreateSection("ACT 1.6-10", "Acts 1:6-10 The continuing saga.", 44001006, 44001010, 1, 1);
			iC = 0;
			q = qs.Items[iS].Categories[iC].Questions[0];
			q.Text = "What happened?";
			q.Answers = new [] { "Stuff" };

			iC = 1;
			q = qs.Items[iS].Categories[iC].Questions[0];
			q.ScriptureReference = "ACT 1.6";
			q.StartRef = 44001006;
			q.EndRef = 44001006;
			q.Text = "What question did the apostles ask Jesus about his kingdom?";
			q.Answers = new [] { "The apostles asked Jesus whether he was soon going to set up his kingdom in a way that everybody could see and cause the people of Israel to have power in that kingdom." };

			QuestionProvider qp = new QuestionProvider(qs, null);

			Assert.AreEqual(2, qp.SectionHeads.Count);
			Assert.AreEqual("Acts 1:1-5 Introduction to the book.", qp.SectionHeads["ACT 1.1-5"]);
			Assert.AreEqual("Acts 1:6-10 The continuing saga.", qp.SectionHeads["ACT 1.6-10"]);
			Assert.AreEqual(1, qp.AvailableBookIds.Length);
			Assert.AreEqual(44, qp.AvailableBookIds[0]);
			List<TranslatablePhrase> phrases = qp.ToList();
			Assert.AreEqual(7, phrases.Count);

			TranslatablePhrase phrase = phrases[0];
			Assert.AreEqual("Overview", phrase.PhraseInUse);
			Assert.AreEqual(-1, phrase.Category);
			Assert.AreEqual(string.Empty, phrase.Reference);
			Assert.AreEqual(001001001, phrase.StartRef);
			Assert.AreEqual(066022021, phrase.EndRef);
			Assert.AreEqual(0, phrase.SequenceNumber);
			Assert.IsNull(phrase.QuestionInfo);

			phrase = phrases[1];
			Assert.AreEqual("What information did Luke, the writer of this book, give in this introduction?",
				phrase.PhraseInUse);
			Assert.AreEqual(0, phrase.Category);
			Assert.AreEqual("ACT 1.1-5", phrase.Reference);
			Assert.AreEqual(44001001, phrase.StartRef);
			Assert.AreEqual(44001005, phrase.EndRef);
			Assert.AreEqual(1, phrase.SequenceNumber);
			Assert.IsNotNull(phrase.QuestionInfo);
			Assert.AreEqual(1, phrase.QuestionInfo.Answers.Count());
			Assert.IsNull(phrase.QuestionInfo.Notes);
			Assert.AreEqual("Luke reminded his readers that he was about to continue the true story about Jesus",
				phrase.QuestionInfo.Answers.First());

			phrase = phrases[2];
			Assert.AreEqual("What do you think an apostle of Jesus is?", phrase.PhraseInUse);
			Assert.AreEqual(0, phrase.Category);
			Assert.AreEqual("ACT 1.1-5", phrase.Reference);
			Assert.AreEqual(44001001, phrase.StartRef);
			Assert.AreEqual(44001005, phrase.EndRef);
			Assert.AreEqual(phrases[1].SequenceNumber + 1, phrase.SequenceNumber);
			Assert.IsNotNull(phrase.QuestionInfo);
			Assert.AreEqual(2, phrase.QuestionInfo.Answers.Count());
			Assert.AreEqual(1, phrase.QuestionInfo.Notes.Count());
			Assert.AreEqual("Key Term Check: To be an apostle of Jesus means to be a messenger",
				phrase.QuestionInfo.Answers.ElementAt(0));
			Assert.AreEqual("Can also be translated as \"sent one\"",
				phrase.QuestionInfo.Answers.ElementAt(1));
			Assert.AreEqual("Note: apostles can be real sweethearts sometimes",
				phrase.QuestionInfo.Notes.ElementAt(0));

			phrase = phrases[3];
			Assert.AreEqual("Details", phrase.PhraseInUse);
			Assert.AreEqual(-1, phrase.Category);
			Assert.AreEqual(string.Empty, phrase.Reference);
			Assert.AreEqual(001001001, phrase.StartRef);
			Assert.AreEqual(066022021, phrase.EndRef);
			Assert.AreEqual(1, phrase.SequenceNumber);
			Assert.IsNull(phrase.QuestionInfo);

			phrase = phrases[4];
			Assert.AreEqual("To whom did the writer of Acts address this book?",
				phrase.PhraseInUse);
			Assert.AreEqual(1, phrase.Category);
			Assert.AreEqual("ACT 1.1-5", phrase.Reference);
			Assert.AreEqual(44001001, phrase.StartRef);
			Assert.AreEqual(44001005, phrase.EndRef);
			Assert.AreEqual(1, phrase.SequenceNumber);
			Assert.IsNotNull(phrase.QuestionInfo);
			Assert.AreEqual(1, phrase.QuestionInfo.Answers.Count());
			Assert.IsNull(phrase.QuestionInfo.Notes);
			Assert.AreEqual("He addressed this book to Theophilus.",
				phrase.QuestionInfo.Answers.First());

			phrase = phrases[5];
			Assert.AreEqual("What happened?", phrase.PhraseInUse);
			Assert.AreEqual(0, phrase.Category);
			Assert.AreEqual("ACT 1.6-10", phrase.Reference);
			Assert.AreEqual(44001006, phrase.StartRef);
			Assert.AreEqual(44001010, phrase.EndRef);
			Assert.AreEqual(1, phrase.SequenceNumber);
			Assert.IsNotNull(phrase.QuestionInfo);
			Assert.AreEqual(1, phrase.QuestionInfo.Answers.Count());
			Assert.IsNull(phrase.QuestionInfo.Notes);
			Assert.AreEqual("Stuff", phrase.QuestionInfo.Answers.First());

			phrase = phrases[6];
			Assert.AreEqual("What question did the apostles ask Jesus about his kingdom?",
				phrase.PhraseInUse);
			Assert.AreEqual(1, phrase.Category);
			Assert.AreEqual("ACT 1.6", phrase.Reference);
			Assert.AreEqual(44001006, phrase.StartRef);
			Assert.AreEqual(44001006, phrase.EndRef);
			Assert.AreEqual(1, phrase.SequenceNumber);
			Assert.IsNotNull(phrase.QuestionInfo);
			Assert.AreEqual(1, phrase.QuestionInfo.Answers.Count());
			Assert.IsNull(phrase.QuestionInfo.Notes);
			Assert.AreEqual("The apostles asked Jesus whether he was soon going to set up his kingdom in a way that everybody could see and cause the people of Israel to have power in that kingdom.",
				phrase.QuestionInfo.Answers.First());
		}
		public void EnumeratePhrases_UnnamedCategory()
		{
			QuestionSections qs = new QuestionSections();
			qs.Items = new Section[1];
			int iS= 0;
			Section s = new Section();
			qs.Items[iS] = s;

			s.ScriptureReference = "ROM 1.1-17";
			s.Heading = "Romans 1:1-17 Introduction to the book.";
			s.StartRef = 45001001;
			s.EndRef = 45001017;
			s.Categories = new Category[1];
			s.Categories[0] = new Category();
			s.Categories[0].Questions = new Question[1];
			Question q = s.Categories[0].Questions[0] = new Question();
			q.Text = "Who wrote this book?";
			q.Answers = new[] { "Paul." };

			QuestionProvider qp = new QuestionProvider(qs, null);

			Assert.AreEqual(1, qp.SectionHeads.Count);
			Assert.AreEqual("Romans 1:1-17 Introduction to the book.", qp.SectionHeads["ROM 1.1-17"]);
			Assert.AreEqual(1, qp.AvailableBookIds.Length);
			Assert.AreEqual(45, qp.AvailableBookIds[0]);
			List<TranslatablePhrase> phrases = qp.ToList();
			Assert.AreEqual(1, phrases.Count);

			TranslatablePhrase phrase = phrases[0];
			Assert.AreEqual("Who wrote this book?", phrase.PhraseInUse);
			Assert.AreEqual(0, phrase.Category);
			Assert.AreEqual("ROM 1.1-17", phrase.Reference);
			Assert.AreEqual(45001001, phrase.StartRef);
			Assert.AreEqual(45001017, phrase.EndRef);
			Assert.AreEqual(1, phrase.SequenceNumber);
			Assert.IsNotNull(phrase.QuestionInfo);
			Assert.AreEqual(1, phrase.QuestionInfo.Answers.Count());
			Assert.IsNull(phrase.QuestionInfo.Notes);
			Assert.AreEqual("Paul.", phrase.QuestionInfo.Answers.First());
		}
		public void AddedPhrases_AddQuestionWithoutEnglishVersion()
		{
			List<PhraseCustomization> customizations = new List<PhraseCustomization>();
			PhraseCustomization pc = new PhraseCustomization();
			pc.Reference = "ACT 1.6";
			pc.OriginalPhrase = "What question did the apostles ask Jesus about his kingdom?";
			Guid guidOfAddedQuestion = Guid.NewGuid();
			pc.ModifiedPhrase = Question.kGuidPrefix + guidOfAddedQuestion;
			pc.Type = PhraseCustomization.CustomizationType.InsertionBefore;
			customizations.Add(pc);

			QuestionSections qs = new QuestionSections();
			qs.Items = new Section[1];
			qs.Items[0] = CreateSection("ACT 1.1-6", "Acts 1:1-6 Introduction to the book.", 44001001,
				44001006, 0, 1);
			Question q = qs.Items[0].Categories[1].Questions[0];
			q.ScriptureReference = "ACT 1.6";
			q.StartRef = 44001006;
			q.EndRef = 44001006;
			q.Text = "What question did the apostles ask Jesus about his kingdom?";
			q.Answers = new[] { "Stuff." };

			QuestionProvider qp = new QuestionProvider(qs, customizations);

			List<TranslatablePhrase> phrases = qp.ToList();
			Assert.AreEqual(4, phrases.Count);

			TranslatablePhrase phrase = phrases[2];
			Assert.AreEqual(string.Empty, phrase.PhraseInUse);
			Assert.AreEqual("User-added question with no English version", phrase.PhraseToDisplayInUI);
			Assert.AreEqual(Question.kGuidPrefix + guidOfAddedQuestion, phrase.PhraseKey.Text);
			Assert.AreEqual(string.Empty, phrase.OriginalPhrase);
			Assert.AreEqual(1, phrase.Category);
			Assert.AreEqual("ACT 1.6", phrase.Reference);
			Assert.AreEqual(44001006, phrase.StartRef);
			Assert.AreEqual(44001006, phrase.EndRef);
			Assert.GreaterOrEqual(phrase.SequenceNumber, 0);
			Assert.Less(phrase.SequenceNumber, phrases[3].SequenceNumber);
			Assert.IsNull(phrase.InsertedPhraseBefore);
			Assert.IsNull(phrase.AddedPhraseAfter);
			Assert.IsNull(phrase.QuestionInfo.Answers);

			phrase = phrases[3];
			Assert.AreEqual("What question did the apostles ask Jesus about his kingdom?", phrase.PhraseInUse);
			Assert.AreEqual(1, phrase.Category);
			Assert.AreEqual("ACT 1.6", phrase.Reference);
			Assert.AreEqual(44001006, phrase.StartRef);
			Assert.AreEqual(44001006, phrase.EndRef);
			Assert.AreEqual(phrases[2].QuestionInfo, phrase.InsertedPhraseBefore);
			Assert.IsNull(phrase.AddedPhraseAfter);
			Assert.IsNotNull(phrase.QuestionInfo);
			Assert.AreEqual(1, phrase.QuestionInfo.Answers.Count());
			Assert.AreEqual("Stuff.", phrase.QuestionInfo.Answers.ElementAt(0));
		}
		public void AddedPhrases_InsertAfterPhraseWithoutEnglishVersion()
		{
			List<PhraseCustomization> customizations = new List<PhraseCustomization>();
			PhraseCustomization pc = new PhraseCustomization();
			pc.Reference = "ACT 1.6";
			pc.OriginalPhrase = "Base question";
			Guid guidOfAddedQuestion = Guid.NewGuid();
			pc.ModifiedPhrase = Question.kGuidPrefix + guidOfAddedQuestion;
			pc.Type = PhraseCustomization.CustomizationType.AdditionAfter;
			customizations.Add(pc);
			pc = new PhraseCustomization();
			pc.Reference = "ACT 1.6";
			pc.OriginalPhrase = Question.kGuidPrefix + guidOfAddedQuestion;
			pc.ModifiedPhrase = "Is this English, or what?";
			pc.Type = PhraseCustomization.CustomizationType.AdditionAfter;
			customizations.Add(pc);

			QuestionSections qs = new QuestionSections();
			qs.Items = new Section[1];
			qs.Items[0] = CreateSection("ACT 1.1-6", "Acts 1:1-6 Introduction to the book.", 44001001,
				44001006, 0, 1);
			Question q = qs.Items[0].Categories[1].Questions[0];
			q.ScriptureReference = "ACT 1.6";
			q.StartRef = 44001006;
			q.EndRef = 44001006;
			q.Text = "Base question";

			QuestionProvider qp = new QuestionProvider(qs, customizations);

			List<TranslatablePhrase> phrases = qp.ToList();
			Assert.AreEqual(5, phrases.Count);

			TranslatablePhrase phrase = phrases[2];
			Assert.AreEqual("Base question", phrase.PhraseInUse);
			Assert.Less(phrase.SequenceNumber, phrases[3].SequenceNumber);
			Assert.IsNull(phrase.InsertedPhraseBefore);
			Assert.AreEqual(phrases[3].QuestionInfo, phrase.AddedPhraseAfter);

			phrase = phrases[3];
			Assert.AreEqual("User-added question with no English version", phrase.PhraseToDisplayInUI);
			Assert.AreEqual(Question.kGuidPrefix + guidOfAddedQuestion, phrase.PhraseKey.Text);
			Assert.AreEqual(string.Empty, phrase.OriginalPhrase);
			Assert.Less(phrase.SequenceNumber, phrases[4].SequenceNumber);
			Assert.IsNull(phrase.InsertedPhraseBefore);
			Assert.AreEqual(phrases[4].QuestionInfo, phrase.AddedPhraseAfter);

			phrase = phrases[4];
			Assert.AreEqual("Is this English, or what?", phrase.PhraseInUse);
			Assert.IsNull(phrase.InsertedPhraseBefore);
			Assert.IsNull(phrase.AddedPhraseAfter);
		}
		public static QuestionSections Generate(IEnumerable<string> sourceLines, Dictionary<string, string[]> alternatives)
		{
			m_canonicalBookNumbers = new HashSet<int>();

			// Initialize the ID textbox.
			Category currCat = null;
			string currRef = null;
			int startRef = 0, endRef = 0;
			Section currSection = null;
			bool currSectionRefSet = false;
			Question currQuestion = null;
			List<Section> sections = new List<Section>();
			List<Question> currentQuestions = new List<Question>();
			int cAnswers = 0, cComments = 0, cCategories = 0;
			int kSectHeadMarkerLen = s_kSectionHead.Length;
			int kRefMarkerLen = s_kRefMarker.Length;
			int kQMarkerLen = s_kQuestionMarker.Length;
			int kAMarkerLen = s_kAnswerMarker.Length;
			int kCommentMarkerLen = s_kCommentMarker.Length;
			Debug.Assert(s_kDetailsMarker.Length == s_kOverviewMarker.Length);
			int kCategoryMarkerLen = s_kDetailsMarker.Length;
			Regex regexVerseNum = new Regex(@"\((?<startVerse>\d+)(-(?<endVerse>\d+))?\)$", RegexOptions.Compiled);
			foreach (string sLine in SourceFields(sourceLines))
			{
				if (sLine.StartsWith(s_kQuestionMarker))
				{
					if (currQuestion != null && cAnswers == 0 && cComments == 0)
					{
						// Question continued in a subsequent field. Just append the text to the existing question.
						currQuestion.Text += " " + sLine.Substring(kQMarkerLen).Trim();
					}
					else
					{
						currQuestion = new Question();
						currentQuestions.Add(currQuestion);
						currQuestion.Text = sLine.Substring(kQMarkerLen).Trim();
						if (currRef != currSection.ScriptureReference)
						{
							currQuestion.ScriptureReference = currRef;
							currQuestion.StartRef = startRef;
							currQuestion.EndRef = endRef;
						}
						cAnswers = 0;
						cComments = 0;
					}
				}
				else if (sLine.StartsWith(s_kAnswerMarker))
				{
					string currAnswer = sLine.Substring(kAMarkerLen).Trim();
					if (!currCat.IsOverview)
					{
						Match match = regexVerseNum.Match(currAnswer);
						if (match.Success)
						{
							int startVerse = Int32.Parse(match.Result("${startVerse}"));
							string sEndVerse = match.Result("${endVerse}");
							int endVerse = string.IsNullOrEmpty(sEndVerse) ? startVerse : Int32.Parse(sEndVerse);
							BCVRef bcvStart, bcvEnd;
							if (currQuestion.StartRef > 0)
							{
								bcvStart = new BCVRef(currQuestion.StartRef);
								bcvEnd = new BCVRef(currQuestion.EndRef);
								if (startVerse < bcvStart.Verse)
									bcvStart.Verse = startVerse;
								if (endVerse > bcvEnd.Verse)
									bcvEnd.Verse = endVerse;
							}
							else
							{
								bcvStart = new BCVRef(currSection.StartRef);
								bcvEnd = new BCVRef(currSection.EndRef);
								bcvStart.Verse = startVerse;
								bcvEnd.Verse = endVerse;
							}
							currQuestion.StartRef = bcvStart.BBCCCVVV;
							currQuestion.EndRef = bcvEnd.BBCCCVVV;
							currQuestion.ScriptureReference = BCVRef.MakeReferenceString(
								currSection.ScriptureReference.Substring(0, 3), bcvStart, bcvEnd, ".", "-");
						}
					}
					string[] source = currQuestion.Answers;
					currQuestion.Answers = new string[cAnswers + 1];
					if (source != null)
						Array.Copy(source, currQuestion.Answers, cAnswers);

					currQuestion.Answers[cAnswers++] = currAnswer;
				}
				else if (sLine.StartsWith(s_kCommentMarker))
				{
					if (currQuestion != null)
					{
						string[] source = currQuestion.Notes;
						currQuestion.Notes = new string[cComments + 1];
						if (source != null)
							Array.Copy(source, currQuestion.Notes, cComments);

						currQuestion.Notes[cComments++] = sLine.Substring(kCommentMarkerLen).Trim();
					}
				}
				else
				{
					if (sLine.StartsWith(s_kRefMarker))
					{
						currRef = sLine.Substring(kRefMarkerLen).Trim();
						Parse(currRef, out startRef, out endRef);
						if (!currSectionRefSet)
						{
							currSection.ScriptureReference = currRef;
							currSection.StartRef = startRef;
							currSection.EndRef = endRef;
							currSectionRefSet = true;
						}
					}
					else if (sLine.StartsWith(s_kSectionHead))
					{
						if (currentQuestions.Count > 0)
						{
							currCat.Questions = currentQuestions.ToArray();
							currentQuestions.Clear();
						}
						currSection = new Section();
						sections.Add(currSection);
						cCategories = 1;
						currSection.Categories = new Category[cCategories];
						currSection.Categories[0] = currCat = new Category();
						currSection.Heading = sLine.Substring(kSectHeadMarkerLen).Trim();
						currSectionRefSet = false;
					}
					else
					{
						bool isOverviewMarker = sLine.StartsWith(s_kOverviewMarker);
						if (isOverviewMarker || sLine.StartsWith(s_kDetailsMarker))
						{
							if (currentQuestions.Count > 0)
							{
								currCat.Questions = currentQuestions.ToArray();
								currentQuestions.Clear();
							}
							if (currCat.Type != null || currCat.Questions != null)
							{
								currCat = new Category();
								Category[] source = currSection.Categories;
								currSection.Categories = new Category[cCategories + 1];
								if (source != null)
									Array.Copy(source, currSection.Categories, cCategories);

								currSection.Categories[cCategories++] = currCat;
							}
							currCat.Type = sLine.Substring(kCategoryMarkerLen).Trim();
							currCat.IsOverview = isOverviewMarker;
						}
					}

					if (currQuestion != null)
					{
						currQuestion = null;
						cAnswers = 0;
						cComments = 0;
					}
				}
			}
			if (currCat != null && currentQuestions.Count > 0)
				currCat.Questions = currentQuestions.ToArray();

			QuestionSections questionSections = new QuestionSections();
			questionSections.Items = sections.ToArray();
			GenerateAlternateForms(questionSections, alternatives);
			return questionSections;
		}
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Returns an enumerator that iterates through the collection of questions.
		/// </summary>
		/// <returns>
		/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to
		/// iterate through the collection.
		/// </returns>
		/// ------------------------------------------------------------------------------------
		public static void GenerateAlternateForms(QuestionSections sections, Dictionary<string, string[]> alternatives)
		{
			string[] altForms;
			foreach (Section section in sections.Items)
			{
				foreach (Category category in section.Categories)
				{
					if (category.Questions == null)
						continue;
					foreach (Question q in category.Questions)
					{
						if (alternatives != null && alternatives.TryGetValue(q.Text, out altForms))
							q.AlternateForms = altForms;
						else
						{
							QuestionProviderAlternateFormBuilder bldr = new QuestionProviderAlternateFormBuilder(q.Text);
							if (bldr.Alternatives.Count > 1)
							{
								q.AlternateForms = new string[bldr.Alternatives.Count];
								for (int index = 0; index < bldr.Alternatives.Count; index++)
									q.AlternateForms[index] = bldr.Alternatives[index];
							}
						}
					}
				}
			}
		}