public void ValidBCVRefs() { BCVRef bcvRef = new BCVRef(1, 2, 3, 0); Assert.IsTrue(bcvRef.Valid); Assert.AreEqual(1002003, bcvRef); Assert.AreEqual(1, bcvRef.Book); Assert.AreEqual(2, bcvRef.Chapter); Assert.AreEqual(3, bcvRef.Verse); bcvRef = new BCVRef(4005006); Assert.IsTrue(bcvRef.Valid); Assert.AreEqual(4005006, bcvRef); Assert.AreEqual(4, bcvRef.Book); Assert.AreEqual(5, bcvRef.Chapter); Assert.AreEqual(6, bcvRef.Verse); bcvRef = new BCVRef(); Assert.IsFalse(bcvRef.Valid); Assert.AreEqual(0, bcvRef); Assert.AreEqual(0, bcvRef.Book); Assert.AreEqual(0, bcvRef.Chapter); Assert.AreEqual(0, bcvRef.Verse); }
public void UpdateProjectFromBundleData_ExistingProjectHasUserDecisions_UserDecisionsApplied() { var originalBundle = GetGlyssenBundleToBeUsedForProject(); originalBundle.WritingSystemDefinition.QuotationMarks[0] = new QuotationMark("open", "close", "cont", 1, QuotationMarkingSystemType.Normal); var project = new Project(originalBundle); WaitForProjectInitializationToFinish(project, ProjectState.FullyInitialized); var firstBook = project.Books[0]; var block = firstBook.GetScriptBlocks().Last(); var verseRef = new BCVRef(BCVRef.BookToNumber(firstBook.BookId), block.ChapterNumber, block.InitialStartVerseNumber); block.SetCharacterAndDelivery(new List <CharacterVerse>( new [] { new CharacterVerse(verseRef, "Wilma", "agitated beyond belief", null, true) })); block.UserConfirmed = true; var newBundle = GetGlyssenBundleToBeUsedForProject(); var updatedProject = project.UpdateProjectFromBundleData(newBundle); WaitForProjectInitializationToFinish(updatedProject, ProjectState.FullyInitialized); Assert.AreEqual(verseRef.Verse, updatedProject.Books[0].GetScriptBlocks().First(b => b.CharacterId == "Wilma").InitialStartVerseNumber); }
public static List <BookScript> ParseProject(IEnumerable <UsxDocument> books, IStylesheet stylesheet, BackgroundWorker projectWorker) { var numBlocksPerBook = new ConcurrentDictionary <string, int>(); var blocksInBook = new ConcurrentDictionary <string, XmlNodeList>(); Parallel.ForEach(books, bookScript => { var nodeList = bookScript.GetChaptersAndParas(); blocksInBook.AddOrUpdate(bookScript.BookId, nodeList, (s, list) => nodeList); numBlocksPerBook.AddOrUpdate(bookScript.BookId, nodeList.Count, (s, i) => nodeList.Count); }); int allProjectBlocks = numBlocksPerBook.Values.Sum(); int completedProjectBlocks = 0; var bookScripts = new List <BookScript>(blocksInBook.Count); Parallel.ForEach(blocksInBook, book => { var bookId = book.Key; Logger.WriteEvent("Creating bookScript ({0})", bookId); var parser = new UsxParser(bookId, stylesheet, book.Value); var bookScript = new BookScript(bookId, parser.Parse()); SingleVoiceReason singleVoiceReason; bookScript.SingleVoice = BookMetadata.DefaultToSingleVoice(bookId, out singleVoiceReason); bookScript.PageHeader = parser.PageHeader; bookScript.MainTitle = parser.MainTitle; Logger.WriteEvent("Created bookScript ({0}, {1})", bookId, bookScript.BookId); lock (bookScripts) bookScripts.Add(bookScript); Logger.WriteEvent("Added bookScript ({0}, {1})", bookId, bookScript.BookId); completedProjectBlocks += numBlocksPerBook[bookId]; projectWorker.ReportProgress(MathUtilities.Percent(completedProjectBlocks, allProjectBlocks, 99)); }); // This code is an attempt to figure out how we are getting null reference exceptions on the Sort call (See PG-275 & PG-287) // The above call to lock bookScripts probably fixes the problem!!! :-) We hope... foreach (var bookScript in bookScripts) { if (bookScript == null || bookScript.BookId == null) { var nonNullBookScripts = bookScripts.Where(b => b != null).Select(b => b.BookId); var nonNullBookScriptsStr = string.Join(";", nonNullBookScripts); var initialMessage = bookScript == null ? "BookScript is null." : "BookScript has null BookId."; throw new ApplicationException(string.Format("{0} Number of BookScripts: {1}. BookScripts which are NOT null: {2}", initialMessage, bookScripts.Count, nonNullBookScriptsStr)); } } try { bookScripts.Sort((a, b) => BCVRef.BookToNumber(a.BookId).CompareTo(BCVRef.BookToNumber(b.BookId))); } catch (NullReferenceException n) { // This code is an attempt to figure out how we are getting null reference exceptions on the Sort call (See PG-275 & PG-287) StringBuilder sb = new StringBuilder(); foreach (var bookScript in bookScripts) { sb.Append(Environment.NewLine).Append(bookScript.BookId).Append("(").Append(BCVRef.BookToNumber(bookScript.BookId)).Append(")"); } throw new NullReferenceException("Null reference exception while sorting books." + sb, n); } projectWorker.ReportProgress(100); return(bookScripts); }
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 ParseRefRange_BogusReferenceRange_SingleNumber() { BCVRef bcvRefStart = new BCVRef(41, 2, 3); BCVRef bcvRefEnd = new BCVRef(41, 2, 3); Assert.IsTrue(BCVRef.ParseRefRange("7", ref bcvRefStart, ref bcvRefEnd)); Assert.AreEqual(new BCVRef(41, 2, 7), bcvRefStart); Assert.AreEqual(new BCVRef(41, 2, 7), bcvRefEnd); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Get the start and end reference of the specified position <paramref name="ivPos"/> /// in the paragraph. Section reference could be used, if available, to fill in missing /// information, but (at least for now) we will not search back into previous sections. /// </summary> /// <param name="ivPos">Character offset in the paragraph.</param> /// <param name="refStart">[out] Start reference</param> /// <param name="refEnd">[out] End reference</param> /// <remarks><p><paramref name="refStart"/> and <paramref name="refEnd"/> are only /// different if we have bridged verse numbers.</p> /// <p>May return incomplete or invalid reference if, for example, the section /// object does not have a valid start reference.</p> /// <p>If ivPos LT zero, we will not search this para, but look only in previous /// paragraphs</p></remarks> /// ------------------------------------------------------------------------------------ public void GetBCVRefAtPosition(int ivPos, out BCVRef refStart, out BCVRef refEnd) { GetBCVRefAtPosition(-1, ivPos, false, out refStart, out refEnd); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Checks for missing chapters. /// </summary> /// ------------------------------------------------------------------------------------ private void CheckChapterNumbers() { int bookId = BCVRef.BookToNumber(m_sBookId); int lastChapInBook = m_versification.LastChapter(bookId); int nextExpectedChapter = 1; int prevChapNumber = 0; bool[] chaptersFound = new bool[lastChapInBook + 1]; foreach (ChapterToken chapToken in m_chapTokens) { if (m_nChapterToCheck != 0 && chapToken.ChapterNumber != m_nChapterToCheck) { continue; } string msg = null; int errorArg = chapToken.ChapterNumber; ITextToken token = chapToken.Token; if (!chapToken.Valid) { // Chapter number is invalid AddError(token, 0, token.Text.Length, Localize("Invalid chapter number"), errorArg); } if (chapToken.ChapterNumber >= 1) { if (chapToken.ChapterNumber > lastChapInBook) { // Chapter number is out of range msg = Localize("Chapter number out of range"); } else if (chapToken.ChapterNumber == prevChapNumber) { // Chapter number is repeated msg = Localize("Duplicate chapter number"); } else if (chapToken.ChapterNumber < nextExpectedChapter) { // Chapter number is out of order msg = Localize("Chapter out of order; expected chapter {0}"); errorArg = nextExpectedChapter; } if (msg != null) { AddError(token, 0, token.Text.Length, msg, errorArg); } else { chaptersFound[chapToken.ChapterNumber] = true; CheckVerseNumbers(chapToken, bookId); } } prevChapNumber = chapToken.ChapterNumber; nextExpectedChapter = Math.Max(chapToken.ChapterNumber + 1, nextExpectedChapter); } CheckForMissingChapters(chaptersFound); }
private BCVRef GetBcvRefForRow(List <object> row) { return(new BCVRef(BCVRef.BookToNumber((string)row[GetColumnIndex(ExportColumn.BookId)]), (int)row[GetColumnIndex(ExportColumn.Chapter)], ScrReference.VerseToIntStart((string)row[GetColumnIndex(ExportColumn.Verse)]))); }
public static QuoteSystem Guess <T>(ICharacterVerseInfo cvInfo, List <T> bookList, ScrVers versification, out bool certain, BackgroundWorker worker = null) where T : IScrBook { certain = false; var bookCount = bookList.Count; if (bookCount == 0) { ReportProgressComplete(worker); return(QuoteSystem.Default); } var scores = QuoteSystem.UniquelyGuessableSystems.ToDictionary(s => s, s => 0); var quotationDashCounts = QuoteSystem.UniquelyGuessableSystems.Where(s => !String.IsNullOrEmpty(s.QuotationDashMarker)) .ToDictionary(s => s, s => 0); var viableSystems = scores.Keys.ToList(); int totalVersesAnalyzed = 0; int totalDialoqueQuoteVersesAnalyzed = 0; int maxNonDialogueSamplesPerBook = BCVRef.LastBook * kMinSample / bookCount; int booksProcessed = 0; int bestScore = 0; bool foundEndQuote = false; bool foundSecondLevelQuoteCloser = false; // ReSharper disable once InconsistentNaming int kVerseValue = Math.Min(kStartQuoteValue + kEndQuoteValue, kQuotationDashValue); List <string> followingVerses = new List <string>(kMaxFollowingVersesToSearchForEndQuote); var stopwatch = new Stopwatch(); stopwatch.Start(); // Start with the New Testament because that's where most of the dialogue quotes are, and it makes guessing A LOT faster! foreach (var book in bookList.SkipWhile(b => BCVRef.BookToNumber(b.BookId) < 40).Union(bookList.TakeWhile(b => BCVRef.BookToNumber(b.BookId) < 40))) { if (worker != null) { worker.ReportProgress(MathUtilities.Percent(++booksProcessed, bookCount)); } int versesAnalyzedForCurrentBook = 0; int prevQuoteChapter = -1; int prevQuoteVerse = -1; foreach (var quote in cvInfo.GetAllQuoteInfo(book.BookId).Where(q => q.IsExpected)) { if (versesAnalyzedForCurrentBook > maxNonDialogueSamplesPerBook && !quote.IsDialogue) { continue; } if (quote.Chapter == prevQuoteChapter && (quote.Verse == prevQuoteVerse || quote.Verse == prevQuoteVerse + 1)) { prevQuoteVerse = quote.Verse; continue; } var text = book.GetVerseText(quote.Chapter, quote.Verse); followingVerses.Clear(); int maxFollowingVersesToSearch = kMaxFollowingVersesToSearchForEndQuote; #if SHOWTESTINFO if (quote.IsDialogue) { Debug.WriteLine("Evaluating {0} {1}:{2} - contents (DIALOGUE=TRUE): {3}", book.BookId, quote.Chapter, quote.Verse, text); } else { Debug.WriteLine("Evaluating {0} {1}:{2} - contents: {3}", book.BookId, quote.Chapter, quote.Verse, text); } #endif foreach (var quoteSystem in viableSystems) { int ichStartQuote = text.IndexOf(quoteSystem.FirstLevel.Open, StringComparison.Ordinal); int i2 = -1; if (quote.IsDialogue && !string.IsNullOrEmpty(quoteSystem.QuotationDashMarker)) { int i = text.IndexOf(quoteSystem.QuotationDashMarker, StringComparison.Ordinal); if (i >= 0 && (ichStartQuote < 0 || i < ichStartQuote)) { // Found a dialogue quote marker earlier in the text. IncrementScore(scores, quoteSystem, kQuotationDashValue, ref bestScore); quotationDashCounts[quoteSystem]++; continue; } } if (ichStartQuote >= 0 && ichStartQuote < text.Length - 2) { IncrementScore(scores, quoteSystem, kStartQuoteValue, ref bestScore); if (quoteSystem.NormalLevels.Count > 1) { i2 = text.IndexOf(quoteSystem.NormalLevels[1].Open, ichStartQuote + 1, StringComparison.Ordinal); if (i2 > ichStartQuote) { #if SHOWTESTINFO Debug.WriteLine("Found 2nd-level opener (" + quoteSystem.NormalLevels[1].Open + ") for system " + quoteSystem); #endif IncrementScore(scores, quoteSystem, kStartLevel2QuoteValue, ref bestScore); if (i2 < text.Length - 2 && text.IndexOf(quoteSystem.NormalLevels[1].Close, i2 + 1, StringComparison.Ordinal) > i2) { #if SHOWTESTINFO Debug.WriteLine("Found 2nd-level closer (" + quoteSystem.NormalLevels[1].Close + ") for system " + quoteSystem); #endif foundSecondLevelQuoteCloser = true; IncrementScore(scores, quoteSystem, kEndLevel2QuoteValue, ref bestScore); } } } if (text.IndexOf(quoteSystem.FirstLevel.Close, ichStartQuote + 1, StringComparison.Ordinal) > ichStartQuote) { foundEndQuote = true; IncrementScore(scores, quoteSystem, kEndQuoteValue, ref bestScore); } else { for (int i = 1; i <= maxFollowingVersesToSearch; i++) { if (!cvInfo.GetCharacters(book.BookId, quote.Chapter, quote.Verse + i, versification: versification).Any()) { break; } string followingText; if (followingVerses.Count >= i) { followingText = followingVerses[i - 1]; } else { followingText = book.GetVerseText(quote.Chapter, quote.Verse + i); followingVerses.Add(followingText); } if (i2 >= 0 && followingText.IndexOf(quoteSystem.NormalLevels[1].Close, StringComparison.Ordinal) >= 0) { #if SHOWTESTINFO Debug.WriteLine("Found 2nd-level closer (" + quoteSystem.NormalLevels[1].Close + ") in subsequent verse for system " + quoteSystem); #endif foundSecondLevelQuoteCloser = true; IncrementScore(scores, quoteSystem, kEndLevel2QuoteValue, ref bestScore); } if (followingText.IndexOf(quoteSystem.FirstLevel.Close, StringComparison.Ordinal) > 0) { foundEndQuote = true; IncrementScore(scores, quoteSystem, kEndQuoteValue, ref bestScore); break; } } } maxFollowingVersesToSearch = followingVerses.Count; } } totalVersesAnalyzed++; if (quote.IsDialogue) { totalDialoqueQuoteVersesAnalyzed++; } versesAnalyzedForCurrentBook++; if (totalVersesAnalyzed >= kMinSample && foundEndQuote && (totalDialoqueQuoteVersesAnalyzed >= kMinQuotationDashSample || viableSystems.TrueForAll(s => String.IsNullOrEmpty(s.QuotationDashMarker))) && (foundSecondLevelQuoteCloser || (totalVersesAnalyzed - totalDialoqueQuoteVersesAnalyzed) >= kMinSampleToAttemptToGetSecondLevel || viableSystems.TrueForAll(s => s.NormalLevels.Count == 1))) { var minViabilityScore = Math.Max(totalVersesAnalyzed * kVerseValue * kMinPercent, bestScore * kMaxCompetitorPercent); var competitors = viableSystems.Where(system => scores[system] > minViabilityScore).ToList(); if (competitors.Any()) { #if SHOWTESTINFO Debug.WriteLine("STATISTICS:"); foreach (var system in competitors) { Debug.WriteLine(system.Name + "(" + system + ")\tScore: " + scores[system]); if (!String.IsNullOrEmpty(system.QuotationDashMarker)) { Debug.WriteLine("\tPercentage matches of total Dialogue quotes analyzed: " + (100.0 * quotationDashCounts[system]) / totalDialoqueQuoteVersesAnalyzed); } } #endif if (competitors.Count == 1) { certain = true; ReportProgressComplete(worker); return(competitors[0]); } viableSystems = viableSystems.Where(competitors.Contains).ToList(); if (competitors.TrueForAll(c => c.FirstLevel.Open == competitors[0].FirstLevel.Open && c.FirstLevel.Close == competitors[0].FirstLevel.Close)) { var contendersWithQDash = competitors.Where(c => !String.IsNullOrEmpty(c.QuotationDashMarker)).ToList(); var failureThresholdForQDCount = kQuotationDashFailPercent * totalDialoqueQuoteVersesAnalyzed; if (contendersWithQDash.TrueForAll(c => quotationDashCounts[c] < failureThresholdForQDCount)) { #if SHOWTESTINFO Debug.Write("No systems with QD over minimum threshold (" + failureThresholdForQDCount + "). Competitors reduced from " + competitors.Count); #endif competitors = competitors.Where(c => String.IsNullOrEmpty(c.QuotationDashMarker)).ToList(); #if SHOWTESTINFO Debug.WriteLine(" to " + competitors.Count); #endif // We're probably (unless we reset this to false below) down to either a single contender (in // which case we can be pretty certain) or two contenders, in which case we can safely use the // one with multiple levels filled in (since there will be no harm done even if the data only // has 1st-level quotes). certain = true; } else { #if SHOWTESTINFO Debug.WriteLine("Only considering contenders with QD. Of " + competitors.Count + " competitors, there are " + contendersWithQDash.Count + " contenders with QD count over minimum threshold (" + failureThresholdForQDCount + ")."); #endif var minQDCount = kMinQuotationDashPercent * totalDialoqueQuoteVersesAnalyzed; competitors = contendersWithQDash.Where(c => scores[c] == bestScore && quotationDashCounts[c] >= minQDCount).ToList(); #if SHOWTESTINFO switch (competitors.Count) { case 0: Debug.WriteLine("Of those, none had the best score (" + bestScore + ") and had a QD count above the minimum (" + minQDCount + ")"); break; case 1: Debug.WriteLine("Of those, one had the best score (" + bestScore + ") and had a QD count above the minimum (" + minQDCount + ")"); break; default: Debug.WriteLine("Of those, " + competitors.Count + " were tied for the best score (" + bestScore + ") and had a QD count above the minimum (" + minQDCount + ")"); break; } #endif } if (competitors.Any()) { // If there are multiple systems with 2nd and 3rd levels specified, discard those options since // we didn't find anything in the data to help us choose among the options. if (competitors.Count(qs => qs.NormalLevels.Count > 1) > 1) { var bestSystems = competitors.Where(c => scores[c] == bestScore).ToList(); if (bestSystems.Count == 1) { #if SHOWTESTINFO Debug.Write("Multiple systems with 2nd and 3rd levels specified. Taking system with best score: " + bestSystems[0]); #endif competitors = bestSystems; } else { #if SHOWTESTINFO Debug.Write("Multiple systems with 2nd and 3rd levels specified. Competitors reduced from " + competitors.Count); #endif competitors = competitors.Where(qs => qs.NormalLevels.Count == 1).ToList(); #if SHOWTESTINFO Debug.WriteLine(" to " + competitors.Count); #endif certain = false; } } if (competitors.Any()) { ReportProgressComplete(worker); if (competitors.Count == 1) { return(competitors[0]); } #if SHOWTESTINFO Debug.WriteLine("SURVIVORS:"); foreach (var system in competitors) { Debug.WriteLine(system.Name + "(" + system + ")\tScore: " + scores[system]); } #endif return(competitors.FirstOrDefault(qs => qs.NormalLevels.Count > 1) ?? competitors.First()); } } } // Still have multiple systems in contention with different first-level start & end markers; // we haven't seen enough evidence to pick a clear winner. } #if SHOWTESTINFO else { Debug.WriteLine("NO COMPETITORS. Total verses analyzed = " + totalVersesAnalyzed + ". Best Score = " + bestScore + ". Minimum viability score = " + minViabilityScore); } #endif } if (stopwatch.ElapsedMilliseconds > kMaxTimeLimit) { #if SHOWTESTINFO Debug.WriteLine("Time-out guessing quote system."); #endif ReportProgressComplete(worker); return(BestGuess(viableSystems, scores, bestScore, foundEndQuote)); } prevQuoteChapter = quote.Chapter; prevQuoteVerse = quote.Verse; } } ReportProgressComplete(worker); return(BestGuess(viableSystems, scores, bestScore, foundEndQuote)); }
public void ParseRefString_ValidExtraSpace() { BCVRef reference = new BCVRef("GEN 1 : 1"); Assert.IsTrue(reference.Valid); Assert.AreEqual(01001001, reference.BBCCCVVV); }
public void ParseRefString_OnlyChapter() { BCVRef reference = new BCVRef("EXO 1"); Assert.IsTrue(reference.Valid); Assert.AreEqual(02001001, reference.BBCCCVVV); }
public void ParseRefRange_NormalReferenceRange_SubVerseLetter() { BCVRef bcvRefStart = new BCVRef(); BCVRef bcvRefEnd = new BCVRef(); Assert.IsTrue(BCVRef.ParseRefRange("LUK 9.37-43a", ref bcvRefStart, ref bcvRefEnd, true)); Assert.AreEqual(new BCVRef(42, 9, 37), bcvRefStart); Assert.AreEqual(new BCVRef(42, 9, 43), bcvRefEnd); }
public void UpdateBcvRef() { // Test updating book BCVRef bcvRef = new BCVRef(1001001); bcvRef.Book = 2; int encodedBCV = bcvRef; Assert.AreEqual(2001001, encodedBCV); // Test updating chapter bcvRef = new BCVRef(1001001); bcvRef.Chapter = 2; encodedBCV = bcvRef; Assert.AreEqual(1002001, encodedBCV); // Test updating verse bcvRef = new BCVRef(1001001); bcvRef.Verse = 2; encodedBCV = bcvRef; Assert.AreEqual(1001002, encodedBCV); }
public void ParseRefRange_BogusReferenceRange_Backwards() { BCVRef bcvRefStart = new BCVRef(); BCVRef bcvRefEnd = new BCVRef(); Assert.IsFalse(BCVRef.ParseRefRange("MRK 2:5-MRK 1:2", ref bcvRefStart, ref bcvRefEnd)); }
public void ParseRefRange_BogusReferenceRange_MultipleBooks() { BCVRef bcvRefStart = new BCVRef(); BCVRef bcvRefEnd = new BCVRef(); Assert.IsFalse(BCVRef.ParseRefRange("MAT 1:5-REV 12:2", ref bcvRefStart, ref bcvRefEnd, false)); }
public void ParseRefRange_NormalReferenceRange_MultipleBooks() { BCVRef bcvRefStart = new BCVRef(); BCVRef bcvRefEnd = new BCVRef(); Assert.IsTrue(BCVRef.ParseRefRange("MAT 1:5-REV 12:2", ref bcvRefStart, ref bcvRefEnd, true)); Assert.AreEqual(new BCVRef(40, 1, 5), bcvRefStart); Assert.AreEqual(new BCVRef(66, 12, 2), bcvRefEnd); }
public void ParseRefRange_BogusReferenceRange_MoreThanTwoRefs() { BCVRef bcvRefStart = new BCVRef(41, 2, 3); BCVRef bcvRefEnd = new BCVRef(41, 2, 3); Assert.IsFalse(BCVRef.ParseRefRange("GEN 4:5 - MAT 6:8 - REV 1:9", ref bcvRefStart, ref bcvRefEnd)); Assert.AreEqual(new BCVRef(41, 2, 3), bcvRefStart, "Since ParseRefRange failed, the reference should be unchanged"); Assert.AreEqual(new BCVRef(41, 2, 3), bcvRefEnd, "Since ParseRefRange failed, the reference should be unchanged"); }
public void ParseRefString_OnlyBook() { BCVRef reference = new BCVRef("LEV"); Assert.IsTrue(reference.Valid); Assert.AreEqual(03001001, reference.BBCCCVVV); }
// internal for testing internal List <List <object> > GetExportData(string bookId = null, int voiceActorId = -1) { var result = new List <List <object> >(); int blockNumber = 1; IEnumerable <BookScript> booksToInclude = bookId == null ? m_booksToExport : m_booksToExport.Where(b => b.BookId == bookId); foreach (var book in booksToInclude) { string singleVoiceNarratorOverride = null; if (book.SingleVoice) { singleVoiceNarratorOverride = CharacterVerseData.GetStandardCharacterId(book.BookId, CharacterVerseData.StandardCharacter.Narrator); } List <Block> pendingMismatchedReferenceBlocks = null; foreach (var block in book.GetScriptBlocks()) { if (block.IsChapterAnnouncement && block.ChapterNumber == 1) { if (Project.SkipChapterAnnouncementForFirstChapter) { continue; } if (Project.SkipChapterAnnouncementForSingleChapterBooks && Project.Versification.LastChapter(BCVRef.BookToNumber(book.BookId)) == 1) { continue; } } VoiceActor.VoiceActor voiceActor = null; bool includeInOutput = true; if (IncludeVoiceActors) { voiceActor = Project.GetVoiceActorForCharacter(singleVoiceNarratorOverride ?? block.CharacterIdInScript) ?? GetDummyActor(); includeInOutput = voiceActorId == -1 || voiceActor.Id == voiceActorId; } if (includeInOutput) { if (pendingMismatchedReferenceBlocks != null && block.ReferenceBlocks.Any()) { foreach (var refBlock in pendingMismatchedReferenceBlocks) { result.Add(GetExportDataForReferenceBlock(refBlock, book.BookId)); } pendingMismatchedReferenceBlocks = null; } result.Add(GetExportDataForBlock(block, blockNumber++, book.BookId, voiceActor, singleVoiceNarratorOverride, IncludeVoiceActors, Project.ReferenceText.HasSecondaryReferenceText)); if (!block.MatchesReferenceText && block.ReferenceBlocks.Any()) { pendingMismatchedReferenceBlocks = block.ReferenceBlocks; } } } if (pendingMismatchedReferenceBlocks != null) { foreach (var refBlock in pendingMismatchedReferenceBlocks) { result.Add(GetExportDataForReferenceBlock(refBlock, book.BookId)); } } } if (bookId == null && voiceActorId == -1) { AddAnnotations(result); } return(result); }
public void ParseRefString_ChapterOptionalForSingleChapterBooks() { BCVRef reference = new BCVRef("OBA 2"); Assert.IsTrue(reference.Valid); Assert.AreEqual(31001002, reference.BBCCCVVV); BCVRef start = new BCVRef(); BCVRef end = new BCVRef(); BCVRef.ParseRefRange("PHM 23-25", ref start, ref end); Assert.IsTrue(start.Valid); Assert.IsTrue(end.Valid); Assert.AreEqual(57001023, start.BBCCCVVV); Assert.AreEqual(57001025, end.BBCCCVVV); reference = new BCVRef("2JN 8"); Assert.IsTrue(reference.Valid); Assert.AreEqual(63001008, reference.BBCCCVVV); BCVRef.ParseRefRange("3JN 12-15", ref start, ref end, false); Assert.IsTrue(start.Valid); Assert.IsTrue(end.Valid); Assert.AreEqual(64001012, start.BBCCCVVV); Assert.AreEqual(64001015, end.BBCCCVVV); BCVRef.ParseRefRange("JUD 10-24", ref start, ref end, false); Assert.IsTrue(start.Valid); Assert.IsTrue(end.Valid); Assert.AreEqual(65001010, start.BBCCCVVV); Assert.AreEqual(65001024, end.BBCCCVVV); // Test to make sure non-single chapter book doesn't get away with any funny business! reference = new BCVRef("EXO 3-4"); Assert.IsTrue(reference.Valid); // May not seem right or logical, but BCVRef doesn't hard-code a particular chapter-verse separator character. Assert.AreEqual(02003004, reference.BBCCCVVV); }
private void SetCharacter(Block block, Character selectedCharacter) { if (selectedCharacter == null) { block.CharacterId = CharacterVerseData.kAmbiguousCharacter; block.CharacterIdInScript = null; } else if (selectedCharacter.IsNarrator) { block.SetStandardCharacter(CurrentBookId, CharacterVerseData.StandardCharacter.Narrator); } else { block.SetCharacterIdAndCharacterIdInScript(selectedCharacter.CharacterId, BCVRef.BookToNumber(CurrentBookId), m_project.Versification); } block.UserConfirmed = !block.CharacterIsUnclear; }
public void ParseRefString_Bridge() { BCVRef reference = new BCVRef("NUM 5:1-5"); Assert.IsFalse(reference.Valid); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Find the start and end reference, by searching backwards in the given ITsString /// from the given position. /// </summary> /// <param name="tss">the given ITsString</param> /// <param name="ichPos">Index of character in paragraph whose reference we want</param> /// <param name="fAssocPrev">Consider this position to be associated with any preceding /// text in the paragraph (in the case where ichPos is at a chapter boundary).</param> /// <param name="refStart">[out] Start reference for the paragraph.</param> /// <param name="refEnd">[out] End reference for the paragraph.</param> /// <returns>A value of <see cref="ChapterVerseFound"/> that tells if a chapter and/or /// verse number was found in this paragraph.</returns> /// <remarks>If ichPos LT zero, we will not search this para, and simply return. /// Be careful not to use this method to search the contents of paragraph using /// character offsets from the BT! /// </remarks> /// ------------------------------------------------------------------------------------ static public ChapterVerseFound GetBCVRefAtPosWithinTss(ITsString tss, int ichPos, bool fAssocPrev, out BCVRef refStart, out BCVRef refEnd) { refStart = new BCVRef(); refEnd = new BCVRef(); ChapterVerseFound retVal = ChapterVerseFound.None; if (tss.Length <= 0) { return(retVal); } TsRunInfo tsi; ITsTextProps ttpRun; bool fGotVerse = false; int ich = ichPos; if (ich > tss.Length) { ich = tss.Length; } while (ich >= 0) { // Get props of current run. ttpRun = tss.FetchRunInfoAt(ich, out tsi); // If we're at (the front edge of) a C/V number boundary and the // caller said to associate the position with the previous material, then // ignore this run unless we're at the beginning of the para. // The run is actually the *following* run, which we don't care about. if (!fAssocPrev || ichPos <= 0 || ichPos != tsi.ichMin) { // See if it is our verse number style. if (!fGotVerse && StStyle.IsStyle(ttpRun, ScrStyleNames.VerseNumber)) { // The whole run is the verse number. Extract it. string sVerseNum = tss.get_RunText(tsi.irun); // string sVerseNum = tss.Text.Substring(tsi.ichMin, // tsi.ichLim - tsi.ichMin); int startVerse, endVerse; ScrReference.VerseToInt(sVerseNum, out startVerse, out endVerse); refStart.Verse = startVerse; refEnd.Verse = endVerse; fGotVerse = true; retVal = ChapterVerseFound.Verse; } // See if it is our chapter number style. else if (StStyle.IsStyle(ttpRun, ScrStyleNames.ChapterNumber)) { try { // Assume the whole run is the chapter number. Extract it. string sChapterNum = tss.get_RunText(tsi.irun); int nChapter = ScrReference.ChapterToInt(sChapterNum); refStart.Chapter = refEnd.Chapter = nChapter; if (fGotVerse) { // Found a chapter number to go with the verse number we // already found, so build the full reference using this // chapter with the previously found verse (already set). retVal |= ChapterVerseFound.Chapter; } else { // Found a chapter number but no verse number, so assume the // edited text is in verse 1 of the chapter. refStart.Verse = refEnd.Verse = 1; fGotVerse = true; retVal = ChapterVerseFound.Chapter | ChapterVerseFound.Verse; } break; } catch (ArgumentException) { // ignore runs with invalid Chapter numbers } } } // move index (going backwards) to the character just before the Min of the run // we just looked at ich = tsi.ichMin - 1; } return(retVal); }
public void ParseRefString_Intro() { BCVRef reference = new BCVRef("JOS 1:0"); Assert.IsTrue(reference.Valid); Assert.AreEqual(06001000, reference.BBCCCVVV); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Get the start and end reference of the specified position <paramref name="ivPos"/> /// in the paragraph. Section reference could be used, if available, to fill in missing /// information, but (at least for now) we will not search back into previous sections. /// </summary> /// <param name="wsBT">HVO of the writing system of the BT to search, or -1 to search /// the vernacular.</param> /// <param name="ivPos">Character offset in the paragraph.</param> /// <param name="fAssocPrev">Consider this position to be associated with any preceding /// text in the paragraph (in the case where ichPos is at a chapter boundary).</param> /// <param name="refStart">[out] Start reference</param> /// <param name="refEnd">[out] End reference</param> /// <remarks><p><paramref name="refStart"/> and <paramref name="refEnd"/> are only /// different if we have bridged verse numbers.</p> /// <p>May return incomplete or invalid reference if, for example, the section /// object does not have a valid start reference.</p> /// <p>If ivPos LT zero, we will not search this para, but look only in previous /// paragraphs</p></remarks> /// ------------------------------------------------------------------------------------ public void GetBCVRefAtPosition(int wsBT, int ivPos, bool fAssocPrev, out BCVRef refStart, out BCVRef refEnd) { refStart = new BCVRef(); refEnd = new BCVRef(); // Might be trying to get the BCVRef in a footnote int ownerOwnFlid = m_cache.GetOwningFlidOfObject(OwnerHVO); if (ownerOwnFlid == (int)ScrBook.ScrBookTags.kflidFootnotes) { ScrFootnote footnote = new ScrFootnote(m_cache, OwnerHVO); refStart = footnote.StartRef; refEnd = footnote.StartRef; return; } BCVRef refStartT = new BCVRef(); BCVRef refEndT = new BCVRef(); ChapterVerseFound found = ChapterVerseFound.None; bool fGotVerse = false; ScrTxtPara para = this; // curent paragraph being examined for reference int chvoParas = 0; // count of paragraphs in the section int ihvoPara = 0; // index of the paragraph within the section BCVRef sectRefStart; BCVRef sectRefEnd; GetSectionStartAndEndRefs(out sectRefStart, out sectRefEnd); while (true) { if (para == this) { found = para.GetBCVRefAtPosWithinPara(wsBT, ivPos, fAssocPrev, out refStartT, out refEndT); } else { found = para.GetBCVRefAtEndOfPara(out refStartT, out refEndT); } // if we found a verse, remember it if (!fGotVerse && ((found & ChapterVerseFound.Verse) != 0)) { refStart.Verse = refStartT.Verse; refEnd.Verse = refEndT.Verse; fGotVerse = true; } // if we found a chapter, process it if ((found & ChapterVerseFound.Chapter) != 0) { if (sectRefStart != null && !sectRefStart.IsEmpty) { refStart.Book = refEnd.Book = sectRefStart.Book; //may not exist } refStart.Chapter = refEnd.Chapter = refStartT.Chapter; // GetBCVwithinPara always returns a verse if it finds a chapter number // so we have already built the full reference Debug.Assert(fGotVerse); return; } // We got to the beginning of the paragraph being edited and still haven't // found a decent reference for our edited text, so keep looking back to // get it from a previous paragraph. // First time thru, figure out which paragraph we are in if (chvoParas == 0) { // REVIEW (EberhardB): does this work if not all paragraphs are // loaded in the cache? chvoParas = m_cache.GetVectorSize(OwnerHVO, (int)StText.StTextTags.kflidParagraphs); // Go forward through vector of paragraphs to find the one being parsed for (ihvoPara = 0; ihvoPara < chvoParas; ihvoPara++) { int hvoPara = m_cache.GetVectorItem(OwnerHVO, (int)StText.StTextTags.kflidParagraphs, ihvoPara); if (hvoPara == Hvo) { break; // found our current para } } } // Move to the previous paragraph ihvoPara--; if (ihvoPara < 0) { // We are at the beginning of the section. We can't look back any further. // ENHANCE TomB: If we search all the way through to the beginning of the // section and never get a valid reference, this section begins in the // middle of a verse or chapter (unlikely in the case of a verse, but // quite likely in the case of a chapter). OR (most likely) this edit // happened at the very beginning of the section, and when we start // parsing, the first thing we'll get is a decent reference. // REVIEW: we're using the section reference, but since they don't get // updated, a change (like removing a chapter) in a previous section // could mess up this section. if (fGotVerse) { // Use the verse we got previously (already set), along with the // first chapter for the section and the book, if available. if (sectRefStart != 0) { refStart.Chapter = refEnd.Chapter = sectRefStart.Chapter; refStart.Book = refEnd.Book = sectRefStart.Book; } } else { // REVIEW: // For now, we're just using the first verse for the section, but this // could be wrong if the section begins in the middle of a verse bridge // or misleading if the section just doesn't yet have verse numbers // marked. if (sectRefStart != 0) { refStart = new BCVRef(sectRefStart); refEnd = new BCVRef(sectRefStart); } // If we are looking for a negative position in the first para of a section // the needed result is not precisely defined yet, // but this is where you could set it // if (para == this && ivPos < 0) // refStart.Verse = refEnd.Verse = ????; } return; } // Set up for the previous paragraph in this section, and we'll try again int hvoNewPara = m_cache.GetVectorItem(OwnerHVO, (int)StText.StTextTags.kflidParagraphs, ihvoPara); // use a special constructor since we already know the section refs para = new ScrTxtPara(m_cache, hvoNewPara, false, false); } }
public void ParseRefString_IntroInvalid() { BCVRef reference = new BCVRef("JOS 2:0"); Assert.IsFalse(reference.Valid, "Verse cannot be 0 except in chapter 1."); }
/// ----------------------------------------------------------------------------------- /// <summary> /// Initializes a new instance of the <see cref="ScrVerse"/> class for an empty paragraph. /// </summary> /// ----------------------------------------------------------------------------------- public ScrVerse(BCVRef start, BCVRef end, ITsString text, ParaNodeMap map, IScrTxtPara para, IStText paraOwner, bool isStanzaBreak) : this(start, end, text, map, para, paraOwner, 0, 0, false, false, true, isStanzaBreak) { }
public void ParseRefString_InvalidBook() { BCVRef reference = new BCVRef("BLA 1:1"); Assert.IsFalse(reference.Valid); }
public void DataIntegrity_RequiredFieldsHaveValidFormatAndThereAreNoDuplicateLines() { Regex regex = new Regex(kRegexBCV + "(?<character>[^\t]+)\t(?<delivery>[^\t]*)\t(?<alias>[^\t]*)\t(?<type>" + typeof(QuoteType).GetRegexEnumValuesString() + ")\t(?<defaultCharacter>[^\t]*)\t(?<parallelPassageRef>[^\t]*)$", RegexOptions.Compiled); Regex extraSpacesRegex = new Regex("^ |\t | \t| $", RegexOptions.Compiled); var set = new HashSet <string>(); ISet <CharacterVerse> uniqueCharacterVerses = new HashSet <CharacterVerse>(); foreach (var line in AllDataLines) { var match = regex.Match(line); Assert.IsTrue(match.Success, "Failed to match line: " + line); var bookId = match.Result("${bookId}"); var bookNum = BCVRef.BookToNumber(bookId); Assert.IsTrue(bookNum > 0, "Line: " + line); Assert.IsTrue(bookNum <= 66, "Line: " + line); var chapterAsString = match.Result("${chapter}"); var chapter = Int32.Parse(chapterAsString); Assert.IsTrue(chapter > 0, "Line: " + line); Assert.IsTrue(chapter <= ScrVers.English.GetLastChapter(bookNum), "Line: " + line); var verseAsString = match.Result("${verse}"); var verse = Int32.Parse(verseAsString); Assert.IsTrue(verse > 0 || verse == 0 && bookId == "PSA", "Line: " + line); Assert.IsTrue(verse <= ScrVers.English.GetLastVerse(bookNum, chapter), "Line: " + line); var sEndVerse = match.Result("${endVerse}"); if (!string.IsNullOrEmpty(sEndVerse)) { var endVerse = Int32.Parse(sEndVerse); Assert.IsTrue(endVerse > verse, "Line: " + line); Assert.IsTrue(endVerse <= 152, "Line: " + line); } var character = match.Result("${character}"); var alias = match.Result("${alias}"); if (!string.IsNullOrEmpty(alias)) { Assert.AreNotEqual(character, alias, "Line: " + line); } var defaultCharacter = match.Result("${defaultCharacter}"); if (!string.IsNullOrEmpty(defaultCharacter)) { Assert.AreNotEqual(character, defaultCharacter, "Line: " + line); Assert.IsFalse(defaultCharacter.Contains("/"), $"Line: {line} has a default character which is a multi-character ID."); } string typeAsString = match.Result("${type}"); if (CharacterVerseData.IsCharacterOfType(character, CharacterVerseData.StandardCharacter.Narrator)) { Assert.AreNotEqual("Dialogue", typeAsString, "Line: " + line); } var matchResult = match.Result("$&"); Assert.IsTrue(set.Add(matchResult), "Duplicate line: " + matchResult); Assert.IsTrue(QuoteType.TryParse(typeAsString, out QuoteType type)); foreach (var bcvRef in CharacterVerseData.GetAllVerses(new [] { bookId, chapterAsString, verseAsString }, () => throw new Exception("This should never happen"))) { var cv = new CharacterVerse(bcvRef, character, match.Result("${delivery}"), alias, false, type, defaultCharacter); Assert.IsTrue(uniqueCharacterVerses.Add(cv), "Line is equivalent to another line even though they are not identical: " + matchResult); } var extraSpacesMatch = extraSpacesRegex.Match(line); Assert.IsFalse(extraSpacesMatch.Success, "Line with extra space(s): " + line); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Runs the check. /// </summary> /// <param name="check">The check.</param> /// ------------------------------------------------------------------------------------ public void RunCheck(IScriptureCheck check) { if (m_bookChecksFailed == null) { m_bookChecksFailed = new Dictionary <int, Dictionary <Guid, ScrCheckRunResult> >(); } if (m_pendingCheckErrors == null) { m_pendingCheckErrors = new Dictionary <int, Dictionary <Guid, Dictionary <string, List <IScrScriptureNote> > > >(); } Dictionary <Guid, Dictionary <string, List <IScrScriptureNote> > > pendingErrorsForBook; int bookNum = m_bookBeingChecked.CanonicalNum; if (!m_pendingCheckErrors.TryGetValue(bookNum, out pendingErrorsForBook)) { pendingErrorsForBook = new Dictionary <Guid, Dictionary <string, List <IScrScriptureNote> > >(); m_pendingCheckErrors[bookNum] = pendingErrorsForBook; } Dictionary <string, List <IScrScriptureNote> > pendingErrorsForCheck = new Dictionary <string, List <IScrScriptureNote> >(); pendingErrorsForBook[check.CheckId] = pendingErrorsForCheck; IScrBookAnnotations annotations = (IScrBookAnnotations)m_scr.BookAnnotationsOS[bookNum - 1]; // Find previously created error annotions for the current book and check. foreach (IScrScriptureNote ann in annotations.NotesOS) { BCVRef beginRef = new BCVRef(ann.BeginRef); // ENHANCE, use a smarter algorithm to search for the start of the annotations for this book if (beginRef.Book == bookNum && ann.AnnotationTypeRA.Guid == check.CheckId) { BCVRef endRef = new BCVRef(ann.EndRef); IStTxtPara quotePara = (IStTxtPara)ann.QuoteOA.ParagraphsOS[0]; IStTxtPara discussionPara = (IStTxtPara)ann.DiscussionOA.ParagraphsOS[0]; string key = beginRef.AsString + endRef.AsString + quotePara.Contents.Text + discussionPara.Contents.Text; List <IScrScriptureNote> errors; if (!pendingErrorsForCheck.TryGetValue(key, out errors)) { errors = new List <IScrScriptureNote>(); pendingErrorsForCheck[key] = errors; } errors.Add(ann); } } if (!m_bookChecksFailed.ContainsKey(bookNum)) { m_bookChecksFailed[bookNum] = new Dictionary <Guid, ScrCheckRunResult>(); } // Before running the check, reset the check result for this book and check. // This is like initializing our check result to green bar in an NUnit test. // As the check is running, that status may get changed to "Inconsistencies" // (red bar) or "IgnoredInconsistencies" (yellow bar). m_bookChecksFailed[bookNum][check.CheckId] = ScrCheckRunResult.NoInconsistencies; // Create a hash table for this check to tally how many times each unique error is generated. if (m_errorCounts != null) { m_errorCounts.Clear(); m_errorCounts = null; } m_errorCounts = new ErrorInventory(); // Run the Scripture check. check.Check(TextTokens(), RecordError); // Find a check history record for the check just run. // If one cannot be found, then create a new one. IScrCheckRun checkRun = null; foreach (IScrCheckRun scrChkRun in annotations.ChkHistRecsOC) { if (scrChkRun.CheckId == check.CheckId) { checkRun = scrChkRun; break; } } if (checkRun == null) { checkRun = Cache.ServiceLocator.GetInstance <IScrCheckRunFactory>().Create(); annotations.ChkHistRecsOC.Add(checkRun); checkRun.CheckId = check.CheckId; } checkRun.RunDate = DateTime.Now; checkRun.Result = m_bookChecksFailed[bookNum][check.CheckId]; foreach (List <IScrScriptureNote> obsoleteErrors in pendingErrorsForCheck.Values) { foreach (IScrScriptureNote obsoleteError in obsoleteErrors) { annotations.NotesOS.Remove(obsoleteError); } } }
public ProjectSettingsViewModel(Project project) { Project = project; WsModel = new WritingSystemSetupModel(project.WritingSystem) { CurrentDefaultFontName = project.FontFamily, CurrentDefaultFontSize = project.FontSizeInPoints, CurrentRightToLeftScript = project.RightToLeftScript }; RecordingProjectName = project.Name; AudioStockNumber = project.AudioStockNumber; BundlePath = project.OriginalBundlePath; ParatextProjectName = project.ParatextProjectName; IsLiveParatextProject = project.IsLiveParatextProject; LanguageName = project.LanguageName; IsoCode = project.LanguageIsoCode; PublicationId = project.Id; PublicationName = project.PublicationName; Versification = project.Versification; m_chapterAnnouncementStyle = project.ChapterAnnouncementStyle; SkipChapterAnnouncementForFirstChapter = project.SkipChapterAnnouncementForFirstChapter; SkipChapterAnnouncementForSingleChapterBooks = SkipChapterAnnouncementForFirstChapter || project.SkipChapterAnnouncementForSingleChapterBooks; var block = project.IncludedBooks.SelectMany(book => book.GetScriptBlocks().Where(b => b.ContainsVerseNumber)).FirstOrDefault(); if (block != null) { SampleText = block.GetText(false); } var multiChapterBooks = project.IncludedBooks.Where(book => Versification.GetLastChapter(BCVRef.BookToNumber(book.BookId)) > 1); foreach (var book in multiChapterBooks) { var chapterBlocks = book.GetScriptBlocks().Where(b => b.IsChapterAnnouncement).Take(2).ToList(); if (chapterBlocks.Any()) { m_exampleFirstChapterLabel = chapterBlocks.First().BlockElements.OfType <ScriptText>().First().Content; if (chapterBlocks.Count > 1) { m_exampleChapterLabel = chapterBlocks[1].BlockElements.OfType <ScriptText>().First().Content; m_exampleChapterNumber = chapterBlocks[1].ChapterNumber; m_exampleMultiChapterBookId = book.BookId; var title = book.GetScriptBlocks().FirstOrDefault(b => b.StyleTag == "mt"); if (title != null) { m_exampleMultiChapterBookTitle = title.GetText(false); } } break; } } var singleChapterBook = project.IncludedBooks.FirstOrDefault(book => Versification.GetLastChapter(BCVRef.BookToNumber(book.BookId)) == 1); if (singleChapterBook != null) { var chapterBlock = singleChapterBook.GetScriptBlocks().FirstOrDefault(b => b.IsChapterAnnouncement); if (chapterBlock != null) { m_exampleSingleChapterLabel = chapterBlock.BlockElements.OfType <ScriptText>().First().Content; } m_exampleSingleChapterBookId = singleChapterBook.BookId; var title = singleChapterBook.GetScriptBlocks().FirstOrDefault(b => b.StyleTag == "mt"); if (title != null) { m_exampleSingleChapterBookTitle = title.GetText(false); } } }
private static IEnumerable <Question> GetTrailingCustomizations(int bookNum, SortedDictionary <QuestionKey, Customizations> customizations, Question lastQuestionInBook, Category category, int iQuestion) { if (customizations != null) { Debug.Assert(lastQuestionInBook != null && iQuestion > 0 && category != null, $"Book {BCVRef.NumberToBookCode(bookNum)} has no built-in questions - cannot process customizations!"); while (customizations.Any(c => c.Value.IsAdditionOrInsertion)) { var insertionForPreviousReference = customizations.FirstOrDefault(c => c.Value.IsAdditionOrInsertion && customizations.All(other => c.Value == other.Value || !other.Key.Matches(c.Key))); var key = insertionForPreviousReference.Key; if (key == null) { Debug.Assert(!customizations.Any(), $"Detected circular chain of customizations for book: {BCVRef.NumberToBookCode(bookNum)}. There were {customizations.Count} customizations that could not be processed!"); break; } var newQ = lastQuestionInBook.AddedQuestionAfter = insertionForPreviousReference.Value.PopQuestion(key); if (!insertionForPreviousReference.Value.IsAdditionOrInsertion) { customizations.Remove(key); } category.Questions.Add(newQ); foreach (Question question in GetCustomizations(newQ, category, iQuestion, customizations)) { lastQuestionInBook = question; yield return(question); iQuestion++; } } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Gets the string representation of the specified BCVRef for serialization. /// </summary> /// ------------------------------------------------------------------------------------ private string GetRef(BCVRef bcvref) { // When writing pure OXES, don't use this attribute, use oxesRef return(m_serializingForOxes || bcvref == null || bcvref.IsEmpty ? null : bcvref.ToString(BCVRef.RefStringFormat.Exchange)); }
public void ParseRefRange_BogusReferenceRange_Unintelligible() { BCVRef bcvRefStart = new BCVRef(41, 2, 3); BCVRef bcvRefEnd = new BCVRef(41, 2, 3); Assert.IsFalse(BCVRef.ParseRefRange("XYZ 3:4&6:7", ref bcvRefStart, ref bcvRefEnd)); Assert.AreEqual(new BCVRef(41, 2, 3), bcvRefStart, "Since ParseRefRange failed, the reference should be unchanged"); Assert.AreEqual(new BCVRef(41, 2, 3), bcvRefEnd, "Since ParseRefRange failed, the reference should be unchanged"); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Gets all the questions/phrases from each section, including any customized or added /// ones. Any additions are actually added to the collection of questions for the /// appropriate section & category. /// </summary> /// ------------------------------------------------------------------------------------ private IEnumerable <Question> GetQuestions() { //HashSet<string> processedCategories = new HashSet<string>(); int currBook = -1; SortedDictionary <QuestionKey, Customizations> currBookCustomizations = null; Category category = null; Question lastQuestionInBook = null; int iQuestion = -1; foreach (Section section in m_sections.Items) { if (m_customizations != null && BCVRef.GetBookFromBcv(section.StartRef) != currBook) { foreach (var question in GetTrailingCustomizations(currBook, currBookCustomizations, lastQuestionInBook, category, iQuestion)) { yield return(question); } currBook = BCVRef.GetBookFromBcv(section.StartRef); m_customizations.TryGetValue(currBook, out currBookCustomizations); } for (int iCat = 0; iCat < section.Categories.Length; iCat++) { category = section.Categories[iCat]; for (iQuestion = 0; iQuestion < category.Questions.Count;) { Question q = category.Questions[iQuestion]; if (string.IsNullOrEmpty(q.Text)) { category.Questions.RemoveAt(iQuestion); continue; } if (q.ScriptureReference == null) { q.ScriptureReference = section.ScriptureReference; q.StartRef = section.StartRef; q.EndRef = section.EndRef; } if (currBookCustomizations != null) { foreach (var question in GetCustomizations(q, category, iQuestion, currBookCustomizations)) { lastQuestionInBook = question; yield return(question); iQuestion++; } } else { yield return(q); iQuestion++; } } } } foreach (var question in GetTrailingCustomizations(currBook, currBookCustomizations, lastQuestionInBook, category, iQuestion)) { yield return(question); } m_customizations = null; // Allow this to be garbage collected (and prevent accidental future use) }
public void Invalid() { BCVRef scrRef = new BCVRef(6542, 1023, 5051); Assert.IsFalse(scrRef.Valid); Assert.AreEqual(42023051, scrRef); }
/// ------------------------------------------------------------------------------------ /// <summary> /// /// </summary> /// <param name="e"></param> /// ------------------------------------------------------------------------------------ protected override void OnKeyDown(KeyEventArgs e) { int buttonToGoTo = -1; switch (e.KeyCode) { case Keys.Up: buttonToGoTo = CurrentButton.ButtonAbove; break; case Keys.Left: buttonToGoTo = CurrentButton.ButtonLeft; break; case Keys.Right: buttonToGoTo = CurrentButton.ButtonRight; break; case Keys.Down: if ((e.Modifiers & Keys.Alt) > 0) { bool fCancel = (m_nowShowing == ListTypes.Books); if (fCancel) { m_scRef = BCVRef.Empty; } Close(fCancel); } else { buttonToGoTo = CurrentButton.ButtonBelow; } break; case Keys.Enter: if (m_nowShowing == ListTypes.Verses || m_fBooksOnly) { m_scRef.Verse = m_fBooksOnly ? 1 : CurrentButton.BCVValue; ScrPassageControl.ScReference = m_scRef; Close(false); return; } ButtonSelected(CurrentButton); break; case Keys.Escape: m_scRef = BCVRef.Empty; Close(); break; default: if ((e.Modifiers & Keys.Alt) != 0 && (e.Modifiers & Keys.Control) != 0) { base.OnKeyDown(e); return; } string charPressed = ((char)e.KeyValue).ToString(); for (int iButton = m_currButton < Controls.Count - 1 ? m_currButton + 1 : 0; iButton != m_currButton; iButton++) { if (m_buttons[iButton].Text.StartsWith(charPressed)) { buttonToGoTo = iButton; break; } if (iButton == Controls.Count - 1) { iButton = -1; // Keep looking from the start of the list } } break; } if (buttonToGoTo > -1) { CurrentButton.ShadeWhenMouseOver = false; m_buttons[buttonToGoTo].ShadeWhenMouseOver = false; ButtonEnter(m_buttons[buttonToGoTo], null); } }
public void ToString_Title() { BCVRef genesisTitleRef = new BCVRef(1000000); Assert.AreEqual("GEN 0:0", genesisTitleRef.ToString(BCVRef.RefStringFormat.General)); Assert.AreEqual("GEN Title", genesisTitleRef.ToString(BCVRef.RefStringFormat.Exchange)); }
private void AddAnnotations(List <List <object> > data) { var annotationRowIndexes = new List <int>(); int lastIndexOfPreviousVerse = 0; BCVRef previousReferenceTextVerse = null; IEnumerable <VerseAnnotation> annotationsForPreviousVerse = null; for (int i = 0; i < data.Count; i++) { var row = data[i]; if (HasReferenceText(row)) { var referenceTextVerse = GetBcvRefForRow(row); if (referenceTextVerse != previousReferenceTextVerse) { if (previousReferenceTextVerse != null && annotationsForPreviousVerse != null) { foreach (var verseAnnotation in annotationsForPreviousVerse.Where(va => va.Annotation is Pause)) { if (ExportAnnotationsInSeparateRows) { var rowIndex = lastIndexOfPreviousVerse + 1 + verseAnnotation.Offset; data.Insert(rowIndex, GetExportDataForAnnotation(verseAnnotation, BCVRef.NumberToBookCode(previousReferenceTextVerse.Book), previousReferenceTextVerse.Chapter, previousReferenceTextVerse.Verse.ToString())); i++; annotationRowIndexes.Add(rowIndex); } else { annotationRowIndexes.Add(AddAnnotationData(data, lastIndexOfPreviousVerse, verseAnnotation)); } } } if (referenceTextVerse != previousReferenceTextVerse) { var annotationsForVerse = ControlAnnotations.Singleton.GetAnnotationsForVerse(referenceTextVerse); foreach (var verseAnnotation in annotationsForVerse.Where(va => va.Annotation is Sound)) { if (ExportAnnotationsInSeparateRows) { var rowIndex = i++ + verseAnnotation.Offset; data.Insert(rowIndex, GetExportDataForAnnotation(verseAnnotation, BCVRef.NumberToBookCode(referenceTextVerse.Book), referenceTextVerse.Chapter, referenceTextVerse.Verse.ToString())); annotationRowIndexes.Add(rowIndex); } else { annotationRowIndexes.Add(AddAnnotationData(data, i, verseAnnotation)); } } annotationsForPreviousVerse = annotationsForVerse; previousReferenceTextVerse = referenceTextVerse; } } lastIndexOfPreviousVerse = i; } } m_annotatedRowIndexes = annotationRowIndexes; }
public void ToString_BogusIntro() { BCVRef genesisTitleRef = new BCVRef(1002000); Assert.AreEqual("GEN 2:0", genesisTitleRef.ToString(BCVRef.RefStringFormat.General)); Assert.AreEqual("GEN 2:0", genesisTitleRef.ToString(BCVRef.RefStringFormat.Exchange)); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Process a segment of text. If there are inline markers, then break out the /// pieces and return the next segment /// </summary> /// <param name="source">source text to process</param> /// <param name="marker">text of the marker</param> /// <param name="literalVerse">literal verse string to use</param> /// <returns>the next text segment</returns> /// ------------------------------------------------------------------------------------ private ISCTextSegment ProcessNextSegmentOfText(string source, string marker, string literalVerse) { int startPos; string startMarker = FindNextMarker(source, 0, out startPos); ImportMappingInfo markerMapping = ((ScrImportSet)m_settings).MappingForMarker(marker, m_mappingSet); // If there are no markers, return the entire string as the segment if (startMarker == null) { m_remainingLineText = string.Empty; } else if (startPos != 0 || marker != string.Empty) { // If the first marker is not at the start or if this is the very first time // through for this line, then save the text from the marker and // process the leading text (which may actually be an empty string if this // is a line beginning with a paragraph marker followed immediately by an // in-line marker). m_remainingLineText = source.Substring(startPos); source = source.Substring(0, startPos); } else { // An inline marker was found at the beginning of the line so process it now int endPos; string endMarker = FindNextMarker(source, startPos + startMarker.Length, out endPos); if (endMarker != null) { m_remainingLineText = source.Substring(endPos); int ichStartOfSegment = startPos + startMarker.Length; if (m_settings.ImportTypeEnum == TypeOfImport.Paratext5 && endPos > ichStartOfSegment) { // P5 in-line begin markers don't include the trailing space (for display // purposes), but it is required. Start markers do not end in "*", end // markers do. if (!startMarker.EndsWith("*")) { Debug.Assert(source[ichStartOfSegment] == ' ' || source[ichStartOfSegment] == '\t'); ichStartOfSegment += 1; } } source = source.Substring(ichStartOfSegment, endPos - ichStartOfSegment); } else { source = source.Substring(startPos + startMarker.Length); if (startMarker == ScrImportSet.s_markerVerse) { // Found an inline verse number (probably Paratext data). BCVRef.VerseToScrRef(source.TrimStart(), out literalVerse, out source, ref m_currentStartRef, ref m_currentEndRef); } m_remainingLineText = string.Empty; } // For inline markers, get the mapping info markerMapping = ((ScrImportSet)m_settings).MappingForMarker(startMarker, m_mappingSet); marker = startMarker; } // Build a segment to return return(new SCTextSegment(ConvertSource(source, markerMapping), marker, literalVerse, m_currentStartRef, m_currentEndRef, m_currentFile.FileName, m_lineNumber)); }
public void ToString_NormalVerse() { BCVRef exodusTitleRef = new BCVRef(2004006); Assert.AreEqual("EXO 4:6", exodusTitleRef.ToString(BCVRef.RefStringFormat.General)); Assert.AreEqual("EXO 4:6", exodusTitleRef.ToString(BCVRef.RefStringFormat.Exchange)); }
private void ApplyUserAssignments(BookScript sourceBookScript, ScrVers versification) { var comparer = new BlockElementContentsComparer(); int iTarget = 0; var bookNum = BCVRef.BookToNumber(sourceBookScript.BookId); foreach (var sourceBlock in sourceBookScript.m_blocks.Where(b => b.UserConfirmed)) { if (iTarget == m_blocks.Count) { return; } if (m_blocks[iTarget].ChapterNumber < sourceBlock.ChapterNumber) { iTarget = GetIndexOfFirstBlockForVerse(sourceBlock.ChapterNumber, sourceBlock.InitialStartVerseNumber); } else { while (m_blocks[iTarget].InitialStartVerseNumber < sourceBlock.InitialStartVerseNumber) { iTarget++; if (iTarget == m_blocks.Count) { return; } } } do { if (m_blocks[iTarget].StyleTag == sourceBlock.StyleTag && m_blocks[iTarget].IsParagraphStart == sourceBlock.IsParagraphStart && m_blocks[iTarget].BlockElements.SequenceEqual(sourceBlock.BlockElements, comparer)) { if (sourceBlock.CharacterIdOverrideForScript == null) { m_blocks[iTarget].SetCharacterIdAndCharacterIdInScript(sourceBlock.CharacterId, bookNum, versification); } else { m_blocks[iTarget].CharacterId = sourceBlock.CharacterId; m_blocks[iTarget].CharacterIdOverrideForScript = sourceBlock.CharacterIdOverrideForScript; } m_blocks[iTarget].Delivery = sourceBlock.Delivery; if (sourceBlock.MatchesReferenceText) { m_blocks[iTarget].SetMatchedReferenceBlock(sourceBlock.ReferenceBlocks.Single()); m_blocks[iTarget].CloneReferenceBlocks(); } m_blocks[iTarget].UserConfirmed = true; iTarget++; if (iTarget == m_blocks.Count) { return; } break; } } while (++iTarget < m_blocks.Count && m_blocks[iTarget].ChapterNumber == sourceBlock.ChapterNumber && m_blocks[iTarget].InitialStartVerseNumber == sourceBlock.InitialStartVerseNumber); } }
public void Parse_Intro() { BCVRef genesisTitleRef = new BCVRef("GEN Intro"); Assert.AreEqual(1, genesisTitleRef.Book); Assert.AreEqual(1, genesisTitleRef.Chapter); Assert.AreEqual(0, genesisTitleRef.Verse); }
public string GetCharacterOverrideDetailsForRefRange_MidVerseInSingleChapterOverride_ReturnsCorrectOverrideCharacter(string bookId, int chapter, int verse) { var verseRef = new VerseRef(new BCVRef(BCVRef.BookToNumber(bookId), chapter, verse), ScrVers.English); return(NarratorOverrides.GetCharacterOverrideDetailsForRefRange(verseRef, verse).Single().Character); }
public void VerseToScrRefTest_LargeVerseNumber() { BCVRef startVerse = new BCVRef(); BCVRef endVerse = new BCVRef(); string literal, remaining; bool convertSuccessful; // Test a really large number that will pass the Int16.MaxValue convertSuccessful = BCVRef.VerseToScrRef("5200000000000", out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(0, startVerse.Verse); Assert.AreEqual(0, endVerse.Verse); Assert.IsFalse(convertSuccessful); // Test a verse number just under the limit convertSuccessful = BCVRef.VerseToScrRef("32766", out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(32766, startVerse.Verse); Assert.AreEqual(32766, endVerse.Verse); Assert.IsTrue(convertSuccessful); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Find the start and end reference, by searching backwards in this paragraph from the /// given position. /// </summary> /// <param name="wsBT">HVO of the writing system of the BT to search, or -1 to search /// the vernacular.</param> /// <param name="ichPos">Index of character in paragraph whose reference we want</param> /// <param name="fAssocPrev">If true, we will search strictly backward if ichPos is at a /// chapter boundary).</param> /// <param name="refStart">[out] Start reference for the paragraph.</param> /// <param name="refEnd">[out] End reference for the paragraph.</param> /// <returns>A value of <see cref="ChapterVerseFound"/> that tells if a chapter and/or /// verse number was found in this paragraph.</returns> /// <remarks>If ichPos LT zero, we will not search this para, and simply return. /// </remarks> /// ------------------------------------------------------------------------------------ protected ChapterVerseFound GetBCVRefAtPosWithinPara(int wsBT, int ichPos, bool fAssocPrev, out BCVRef refStart, out BCVRef refEnd) { ITsString tss; if (wsBT > 0) { tss = GetBT().Translation.GetAlternativeTss(wsBT); } else { tss = Contents.UnderlyingTsString; } return(GetBCVRefAtPosWithinTss(tss, ichPos, fAssocPrev, out refStart, out refEnd)); }
public void ParseTest() { BCVRef bcvRef = new BCVRef(); // Note: Don't break into individual unit tests because this test also makes sure // that the results of a previous parse don't have unintended consequences for a // subsequent parse. // Test a normal reference bcvRef.Parse("EXO 9:32"); Assert.AreEqual(2, bcvRef.Book); Assert.AreEqual(9, bcvRef.Chapter); Assert.AreEqual(32, bcvRef.Verse); // Test a bogus book bcvRef.Parse("GYQ 8:12"); Assert.AreEqual(0, bcvRef.Book); Assert.AreEqual(9, bcvRef.Chapter); Assert.AreEqual(32, bcvRef.Verse); // Test large chapter and verse numbers bcvRef.Parse("MAT 1000:2500"); Assert.AreEqual(40, bcvRef.Book); Assert.AreEqual(1000, bcvRef.Chapter); Assert.AreEqual(2500, bcvRef.Verse); // Test no chapter or verse number bcvRef.Parse("REV"); Assert.AreEqual(66, bcvRef.Book); Assert.AreEqual(1, bcvRef.Chapter); Assert.AreEqual(1, bcvRef.Verse); // Test empty string - should not crash bcvRef.Parse(""); Assert.AreEqual(0, bcvRef.Book); Assert.AreEqual(1, bcvRef.Chapter); Assert.AreEqual(1, bcvRef.Verse); // Test no verse number bcvRef.Parse("LUK 5"); Assert.AreEqual(42, bcvRef.Book); Assert.AreEqual(5, bcvRef.Chapter); Assert.AreEqual(1, bcvRef.Verse); // Test invalid format bcvRef.Parse("ROM 5!3@4"); Assert.AreEqual(0, bcvRef.Book); Assert.AreEqual(5, bcvRef.Chapter); Assert.AreEqual(3, bcvRef.Verse); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Get the start and end reference of the specified position <paramref name="ivPos"/> /// in the paragraph. Section reference could be used, if available, to fill in missing /// information, but (at least for now) we will not search back into previous sections. /// </summary> /// <param name="ivPos">Character offset in the paragraph.</param> /// <param name="fAssocPrev">Consider this position to be associated with any preceding /// text in the paragraph (in the case where ichPos is at a chapter boundary).</param> /// <param name="refStart">[out] Start reference</param> /// <param name="refEnd">[out] End reference</param> /// <remarks><p><paramref name="refStart"/> and <paramref name="refEnd"/> are only /// different if we have bridged verse numbers.</p> /// <p>May return incomplete or invalid reference if, for example, the section /// object does not have a valid start reference.</p> /// <p>If ivPos LT zero, we will not search this para, but look only in previous /// paragraphs</p></remarks> /// ------------------------------------------------------------------------------------ public void GetBCVRefAtPosition(int ivPos, bool fAssocPrev, out BCVRef refStart, out BCVRef refEnd) { GetBCVRefAtPosition(-1, ivPos, fAssocPrev, out refStart, out refEnd); }
public void VerseToScrRefTest() { BCVRef startVerse = new BCVRef(); BCVRef endVerse = new BCVRef(); string literal, remaining = string.Empty; bool convertSuccessful; // Test invalid verse number strings convertSuccessful = BCVRef.VerseToScrRef("-12", out literal, out remaining, ref startVerse, ref endVerse); //Assert.AreEqual(12, startVerse.Verse); // start verse set to 0 instead of 12 Assert.AreEqual(12, endVerse.Verse); //Assert.IsFalse(convertSuccessful); // Does not detect invalid verse number format. convertSuccessful = BCVRef.VerseToScrRef("12-", out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(12, startVerse.Verse); Assert.AreEqual(12, endVerse.Verse); //Assert.IsFalse(convertSuccessful); // Does not detect invalid verse number format. convertSuccessful = BCVRef.VerseToScrRef("a3", out literal, out remaining, ref startVerse, ref endVerse); //Assert.AreEqual(3, startVerse.Verse); // does not set starting verse value //Assert.AreEqual(3, endVerse.Verse); // does not set end verse value Assert.IsFalse(convertSuccessful); convertSuccessful = BCVRef.VerseToScrRef("15b-a", out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(15, startVerse.Verse); Assert.AreEqual(15, endVerse.Verse); //Assert.IsFalse(convertSuccessful); // Does not detect invalid verse number format. convertSuccessful = BCVRef.VerseToScrRef("3bb", out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(3, startVerse.Verse); Assert.AreEqual(3, endVerse.Verse); //Assert.IsFalse(convertSuccessful); // Does not detect invalid verse number format. convertSuccessful = BCVRef.VerseToScrRef("0", out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(0, startVerse.Verse); Assert.AreEqual(0, endVerse.Verse); //Assert.IsFalse(convertSuccessful); // Does not detect invalid verse number format. convertSuccessful = BCVRef.VerseToScrRef(" 12", out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(12, startVerse.Verse); Assert.AreEqual(12, endVerse.Verse); //Assert.IsFalse(convertSuccessful); // Does not detect invalid verse number format. convertSuccessful = BCVRef.VerseToScrRef("12 ", out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(12, startVerse.Verse); Assert.AreEqual(12, endVerse.Verse); //Assert.IsFalse(convertSuccessful); // Does not detect invalid verse number format. convertSuccessful = BCVRef.VerseToScrRef("12-10", out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(12, startVerse.Verse); // out of order //Assert.AreEqual(12, endVerse.Verse); // end verse set to 12 instead of 10 //Assert.IsFalse(convertSuccessful); // Does not detect invalid verse number format. convertSuccessful = BCVRef.VerseToScrRef("1-176", out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(1, startVerse.Verse); Assert.AreEqual(176, endVerse.Verse); Assert.IsTrue(convertSuccessful); convertSuccessful = BCVRef.VerseToScrRef("139-1140", out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(139, startVerse.Verse); // 1140 is out of range of valid verse numbers //Assert.AreEqual(139, endVerse.Verse); // end verse set to 1140 instead of 139 //Assert.IsFalse(convertSuccessful); // Does not detect invalid verse number format. convertSuccessful = BCVRef.VerseToScrRef("177-140", out literal, out remaining, ref startVerse, ref endVerse); //Assert.AreEqual(140, startVerse.Verse); // 177 is out of range of valid verse numbers Assert.AreEqual(140, endVerse.Verse); //Assert.IsFalse(convertSuccessful); // Does not detect invalid verse number format. //Review: should this be a requirement? // convertSuccessful = BCVRef.VerseToScrRef("177", out literal, out remaining, ref startVerse, ref endVerse); // Assert.AreEqual(0, startVerse.Verse); // 177 is out of range of valid verse numbers // Assert.AreEqual(0, endVerse.Verse); //Assert.IsFalse(convertSuccessful); convertSuccessful = BCVRef.VerseToScrRef(String.Empty, out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(0, startVerse.Verse); Assert.AreEqual(0, endVerse.Verse); //Assert.IsFalse(convertSuccessful); // Does not detect invalid verse number format. convertSuccessful = BCVRef.VerseToScrRef(String.Empty, out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(0, startVerse.Verse); Assert.AreEqual(0, endVerse.Verse); //Assert.IsFalse(convertSuccessful); // Does not detect invalid verse number format. // Test valid verse number strings convertSuccessful = BCVRef.VerseToScrRef("1a", out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(1, startVerse.Verse); Assert.AreEqual(1, endVerse.Verse); Assert.IsTrue(convertSuccessful); convertSuccessful = BCVRef.VerseToScrRef("2a-3b", out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(2, startVerse.Verse); Assert.AreEqual(3, endVerse.Verse); Assert.IsTrue(convertSuccessful); convertSuccessful = BCVRef.VerseToScrRef("4-5d", out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(4, startVerse.Verse); Assert.AreEqual(5, endVerse.Verse); Assert.IsTrue(convertSuccessful); convertSuccessful = BCVRef.VerseToScrRef("6", out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(6, startVerse.Verse); Assert.AreEqual(6, endVerse.Verse); Assert.IsTrue(convertSuccessful); convertSuccessful = BCVRef.VerseToScrRef("66", out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(66, startVerse.Verse); Assert.AreEqual(66, endVerse.Verse); Assert.IsTrue(convertSuccessful); convertSuccessful = BCVRef.VerseToScrRef("176", out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(176, startVerse.Verse); Assert.AreEqual(176, endVerse.Verse); Assert.IsTrue(convertSuccessful); //We expect this test to pass //RTL verse bridge should be valid syntax convertSuccessful = BCVRef.VerseToScrRef("6" + '\u200f' + "-" + '\u200f' + "8", out literal, out remaining, ref startVerse, ref endVerse); Assert.AreEqual(6, startVerse.Verse); Assert.AreEqual(8, endVerse.Verse); Assert.IsTrue(convertSuccessful); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Load a list of sections into the beginning and ending combo boxes for export. /// TEMPORARY: If it is the first (i.e., starting) section to export, only include /// sections that begin with a chapter. See TE-7287 for story to revert this. /// </summary> /// <param name="nBook"></param> /// ------------------------------------------------------------------------------------ private void LoadSectionsForBook(int nBook) { if (nBook == m_nBookForSections) { return; } m_fLoadingBookSections = true; using (new WaitCursor(this, true)) { cboFrom.Items.Clear(); cboTo.Items.Clear(); cboFrom.SelectedIndex = -1; cboTo.SelectedIndex = -1; IScrBook book = m_scr.FindBook(nBook); Debug.Assert(book != null); string sRef; // "{0} Intro: {1}" string sRefIntro = DlgResources.ResourceString("kstidOxesExportIntro"); // "{0}: {1}" string sRefPassage = DlgResources.ResourceString("kstidOxesExportRef"); ITsString tssHeading = null; // "(No text in section heading)" ITsString tssEmpty = TsStringUtils.MakeTss(DlgResources.ResourceString("kstidOxesExportEmptyHeading"), book.Cache.DefaultVernWs); BCVRef startRef; BCVRef endRef; IScrSection sect; IScrSection prevSect = null; int iSectionFrom = 0; for (int iSection = 0; iSection < book.SectionsOS.Count; ++iSection, prevSect = sect) { sect = book.SectionsOS[iSection]; sect.GetDisplayRefs(out startRef, out endRef); if (sect.HeadingOA != null) { // Get the first non-empty heading paragraph content. for (int j = 0; j < sect.HeadingOA.ParagraphsOS.Count; ++j) { IStTxtPara para = sect.HeadingOA.ParagraphsOS[j] as IStTxtPara; if (para != null && para.Contents.Length > 0) { tssHeading = para.Contents; break; } } } if (tssHeading == null || tssHeading.Length == 0) { tssHeading = tssEmpty; } else { // Replace embedded line separator characters with spaces. ITsStrBldr tsbFix = tssHeading.GetBldr(); for (int idx = tsbFix.Text.IndexOf(StringUtils.kChHardLB); idx >= 0; idx = tsbFix.Text.IndexOf(StringUtils.kChHardLB)) { tsbFix.Replace(idx, idx + 1, " ", null); } tssHeading = tsbFix.GetString(); } sRef = BCVRef.MakeReferenceString(startRef, endRef, m_scr.ChapterVerseSepr, m_scr.Bridge); sRef = string.Format(sect.IsIntro ? sRefIntro : sRefPassage, sRef, tssHeading.Text); // Only include intro section or sections that begin with a chapter // number run in the list of starting sections. This is currently // required because of the way the ScrSection.AdjustReferences relies // upon chapter numbers. ITsString tss = TsStringUtils.MakeTss(sRef, m_scr.Cache.DefaultVernWs); if (ValidStartingSection(sect, prevSect)) { iSectionFrom = cboFrom.Items.Add(new SectionCboItem(tss, iSection, iSection)); } cboTo.Items.Add(new SectionCboItem(tss, iSection, iSectionFrom)); } cboFrom.SelectedIndex = 0; cboTo.SelectedIndex = book.SectionsOS.Count - 1; } m_fLoadingBookSections = false; }
public void BuildBcvRefByProps() { // Build a bcvRef by individual properties BCVRef bcvRef = new BCVRef(); bcvRef.Book = 13; Assert.IsFalse(bcvRef.Valid); // 0 not allowed for chapter Assert.AreEqual(13000000, bcvRef.BBCCCVVV); Assert.AreEqual(13, bcvRef.Book); Assert.AreEqual(0, bcvRef.Chapter); Assert.AreEqual(0, bcvRef.Verse); bcvRef.Chapter = 1; // a zero verse is considered valid for introduction, etc, but only for chapter 1 Assert.IsTrue(bcvRef.Valid); Assert.AreEqual(13001000, (int)bcvRef); Assert.AreEqual(13, bcvRef.Book); Assert.AreEqual(1, bcvRef.Chapter); Assert.AreEqual(0, bcvRef.Verse); bcvRef.Chapter = 14; bcvRef.Verse = 15; Assert.IsTrue(bcvRef.Valid); Assert.AreEqual(13014015, (int)bcvRef); Assert.AreEqual(13, bcvRef.Book); Assert.AreEqual(14, bcvRef.Chapter); Assert.AreEqual(15, bcvRef.Verse); bcvRef = new BCVRef(); bcvRef.Chapter = 16; Assert.IsFalse(bcvRef.Valid, "Invalid because 0 is not valid for the book number"); Assert.AreEqual(00016000, (int)bcvRef); Assert.AreEqual(0, bcvRef.Book); Assert.AreEqual(16, bcvRef.Chapter); Assert.AreEqual(0, bcvRef.Verse); bcvRef = new BCVRef(); bcvRef.Verse = 17; Assert.IsFalse(bcvRef.Valid, "Invalid because 0 is not valid for the book and chapter numbers"); Assert.AreEqual(00000017, (int)bcvRef); Assert.AreEqual(0, bcvRef.Book); Assert.AreEqual(0, bcvRef.Chapter); Assert.AreEqual(17, bcvRef.Verse); // same tests as above except that we test individual properties first // the BCVRef object operates differently in this circumstance bcvRef = new BCVRef(); bcvRef.Book = 21; Assert.AreEqual(0, bcvRef.Verse); Assert.AreEqual(0, bcvRef.Chapter); Assert.AreEqual(21, bcvRef.Book); Assert.AreEqual(21000000, (int)bcvRef); Assert.IsFalse(bcvRef.Valid, "Invalid because 0 is not valid for the chapter number"); bcvRef = new BCVRef(); bcvRef.Chapter = 22; Assert.AreEqual(0, bcvRef.Verse); Assert.AreEqual(22, bcvRef.Chapter); Assert.AreEqual(0, bcvRef.Book); Assert.AreEqual(00022000, (int)bcvRef); Assert.IsFalse(bcvRef.Valid, "Invalid because 0 is not valid for the book number"); bcvRef = new BCVRef(); bcvRef.Verse = 23; Assert.AreEqual(23, bcvRef.Verse); Assert.AreEqual(0, bcvRef.Chapter); Assert.AreEqual(0, bcvRef.Book); Assert.AreEqual(00000023, (int)bcvRef); Assert.IsFalse(bcvRef.Valid, "Invalid because 0 is not valid for the book and chapter numbers"); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Parses a verse number. /// </summary> /// <param name="runChars">The text of the token containing the verse number.</param> /// <param name="curVerseStart">The cur verse start.</param> /// <param name="curVerseEnd">The cur verse end.</param> /// <param name="vrsPart">The VRS part.</param> /// <returns></returns> /// ------------------------------------------------------------------------------------ private ParseVerseResult ParseVerseNumber(string runChars, out int curVerseStart, out int curVerseEnd, out VersePart vrsPart) { string literalVerse; string remainingText; BCVRef firstRefer = new BCVRef(); BCVRef lastRefer = new BCVRef(); string trimmedRun = runChars.TrimStart(null); bool hasPrecedingWhiteSpace = (runChars.Length != trimmedRun.Length); vrsPart = VersePart.NA; //Check for a correct format if (!m_verseNumberFormat.IsMatch(runChars.Replace(" ", string.Empty))) { // Even though the verse number is invalid, we'll still attempt to interpret it // as a verse number (or bridge) since that might avoid spurious "missing verse" // errors. if (BCVRef.VerseToScrRef(trimmedRun, out literalVerse, out remainingText, ref firstRefer, ref lastRefer) && firstRefer.Verse > 0) { curVerseStart = firstRefer.Verse; curVerseEnd = lastRefer.Verse; return(ParseVerseResult.InvalidFormat); } else { curVerseStart = 0; curVerseEnd = 0; return(ParseVerseResult.Invalid); } } // Useful method VerseToScrRef existing in BCVRef returns the parts of a verse // bridge and any non-numerical remaining text in the run. Allows accounting for // possible verse bridges. Allows accounting for verse parts, 10a 10b, account // for valid case: 7-8a 8b, if encounter "a", expectedVerse repeats in order to // expect 8b . if (!BCVRef.VerseToScrRef(trimmedRun, out literalVerse, out remainingText, ref firstRefer, ref lastRefer)) { curVerseStart = 0; curVerseEnd = 0; return(ParseVerseResult.Invalid); } curVerseStart = firstRefer.Verse; curVerseEnd = lastRefer.Verse; string remainingVerse = remainingText.Trim(); bool hasWhiteSpace = (hasPrecedingWhiteSpace || (remainingVerse.Length != remainingText.Length)); // note: if verse bridge, assumes, 'a' is on verse end // checks for a part "a" in verse if (remainingVerse == m_subVerseA) { vrsPart = VersePart.PartA; } else if (remainingVerse == m_subVerseB) { vrsPart = VersePart.PartB; } // If there was a non-numerical part or verse number > 999 that caused an error // making verseStart or verseEnd returned as 0 it will parse the trimmed // remainingVerse string to an integer and assign it as the verse number if (remainingVerse.Length != 0) { if (curVerseStart == 0 && !int.TryParse(remainingVerse, out curVerseStart)) { return(ParseVerseResult.Invalid); } if (curVerseEnd == 0 && !int.TryParse(remainingVerse, out curVerseEnd)) { return(ParseVerseResult.Invalid); } // adds error if verse part is not 'a' or 'b', for example "10c" would // be invalid verse number if " 13", still invalid format if (remainingVerse != m_subVerseA && remainingVerse != m_subVerseB) { return(ParseVerseResult.Invalid); } } if (!hasWhiteSpace) { return(ParseVerseResult.Valid); } return(curVerseStart == curVerseEnd ? ParseVerseResult.ValidWithSpaceInVerse : ParseVerseResult.ValidWithSpaceInVerseBridge); }
public void ParseRefRange_NormalVerseRange_MaxVerseNumber() { BCVRef bcvRefStart = new BCVRef(); BCVRef bcvRefEnd = new BCVRef(); Assert.IsTrue(BCVRef.ParseRefRange("PSA 119:175-176", ref bcvRefStart, ref bcvRefEnd)); Assert.AreEqual(new BCVRef(19, 119, 175), bcvRefStart); Assert.AreEqual(new BCVRef(19, 119, 176), bcvRefEnd); Assert.IsTrue(BCVRef.ParseRefRange("174-176", ref bcvRefStart, ref bcvRefEnd)); Assert.AreEqual(new BCVRef(19, 119, 174), bcvRefStart); Assert.AreEqual(new BCVRef(19, 119, 176), bcvRefEnd); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Parses the given string to get a starting and ending Scripture reference. /// </summary> /// <param name="sReference">The s reference.</param> /// <param name="startRef">The start ref.</param> /// <param name="endRef">The end ref.</param> /// ------------------------------------------------------------------------------------ internal static void ParseRefRange(string sReference, out BCVRef startRef, out BCVRef endRef) { startRef = new BCVRef(); endRef = new BCVRef(); BCVRef.ParseRefRange(sReference, ref startRef, ref endRef); }
public void ParseRefRange_NormalVerseRange_BookSpecifiedTwice() { BCVRef bcvRefStart = new BCVRef(); BCVRef bcvRefEnd = new BCVRef(); Assert.IsTrue(BCVRef.ParseRefRange("MRK 1:8-MRK 2:15", ref bcvRefStart, ref bcvRefEnd)); Assert.AreEqual(new BCVRef(41, 1, 8), bcvRefStart); Assert.AreEqual(new BCVRef(41, 2, 15), bcvRefEnd); }
private void SetBcvRefs() { m_scrStartReference = new BCVRef(); m_scrEndReference = new BCVRef(); BCVRef.ParseRefRange(Reference, ref m_scrStartReference, ref m_scrEndReference); }
public void ParseRefRange_ValidBBCCCVVVRange() { BCVRef bcvRefStart = new BCVRef(); BCVRef bcvRefEnd = new BCVRef(); Assert.IsTrue(BCVRef.ParseRefRange("40001002-41002006", ref bcvRefStart, ref bcvRefEnd, true)); Assert.AreEqual(new BCVRef(40, 1, 2), bcvRefStart); Assert.AreEqual(new BCVRef(41, 2, 6), bcvRefEnd); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Promote a simple BCV reference to a ScrReference /// </summary> /// <param name="from">The BCVRef to promote to a ScrReference.</param> /// <param name="versification">The versification.</param> /// ------------------------------------------------------------------------------------ public ScrReference(BCVRef from, ScrVers versification) : this(from.Book, from.Chapter, from.Verse, from.Segment, versification) { }
public void CompareTo_BCVRef() { ScrReference ref1 = new ScrReference("GEN 30:1", ScrVers.Original); BCVRef ref2 = new BCVRef("GEN 30:1"); Assert.AreEqual(0, ref1.CompareTo(ref2)); }