private bool BlocksMatch(int bookNum, Block vernBlock, Block refBlock, ScrVers vernacularVersification) { var vernInitStartVerse = new VerseRef(bookNum, vernBlock.ChapterNumber, vernBlock.InitialStartVerseNumber, vernacularVersification); var refInitStartVerse = new VerseRef(bookNum, refBlock.ChapterNumber, refBlock.InitialStartVerseNumber, Versification); return(vernInitStartVerse.CompareTo(refInitStartVerse) == 0 && (vernBlock.CharacterId == refBlock.CharacterId || vernBlock.CharacterIsUnclear()) && BlocksEndWithSameVerse(bookNum, vernBlock, refBlock, vernacularVersification)); }
public BlockNavigatorViewModel(IReadOnlyList <BookScript> books, ScrVers versification) { m_navigator = new BlockNavigator(books); m_includedBooks = books.Select(b => b.BookId); Versification = versification; Mode = BlocksToDisplay.AllScripture; }
public VerseRef GetBlockVerseRef(Block block = null, ScrVers targetVersification = null) { block = block ?? m_navigator.CurrentBlock; var verseRef = new VerseRef(BCVRef.BookToNumber(CurrentBookId), block.ChapterNumber, block.InitialStartVerseNumber, Versification); if (targetVersification != null) { verseRef.ChangeVersification(targetVersification); } return(verseRef); }
public void Apply(Paratext.ScrVers versification) { if (!AllScriptureBlocksMatch) { throw new InvalidOperationException("Cannot apply reference blocks unless all Scripture blocks have corresponding reference blocks."); } var bogusRefBlock = GetInvalidReferenceBlockAtAnyLevel(CorrelatedBlocks); if (bogusRefBlock != null) { throw new InvalidReferenceTextException(bogusRefBlock); } if (m_numberOfBlocksAddedBySplitting > 0) { m_vernacularBook.ReplaceBlocks(m_iStartBlock, CorrelatedBlocks.Count - m_numberOfBlocksAddedBySplitting, CorrelatedBlocks.Select(b => b.Clone())); } int bookNum = BCVRef.BookToNumber(m_vernacularBook.BookId); var origBlocks = m_vernacularBook.GetScriptBlocks(); for (int i = 0; i < CorrelatedBlocks.Count; i++) { if (!CorrelatedBlocks[i].MatchesReferenceText) // e.g., section head { continue; } var vernBlock = origBlocks[m_iStartBlock + i]; var refBlock = CorrelatedBlocks[i].ReferenceBlocks.Single(); vernBlock.SetMatchedReferenceBlock(refBlock); vernBlock.SetCharacterAndDeliveryInfo(CorrelatedBlocks[i], bookNum, versification); if (CorrelatedBlocks[i].UserConfirmed) { if (vernBlock.CharacterIsUnclear()) { throw new InvalidOperationException("Character cannot be confirmed as ambigous or unknown."); } vernBlock.UserConfirmed = true; } //if (vernBlock.CharacterId != refBlock.CharacterId) //{ // vernBlock.CharacterId = refBlock.CharacterId; // if (refBlock.CharacterIdOverrideForScript != null) // vernBlock.CharacterIdOverrideForScript = refBlock.CharacterIdOverrideForScript; //} } m_numberOfBlocksAddedBySplitting = 0; }
internal void ApplyTo(BookScript vernacularBook, ScrVers vernacularVersification) { ReloadModifiedBooks(); int bookNum = BCVRef.BookToNumber(vernacularBook.BookId); var referenceBook = Books.Single(b => b.BookId == vernacularBook.BookId); var verseSplitLocationsBasedOnRef = GetVerseSplitLocations(referenceBook, bookNum); var verseSplitLocationsBasedOnVern = GetVerseSplitLocations(vernacularBook, bookNum); MakesSplits(vernacularBook, bookNum, vernacularVersification, verseSplitLocationsBasedOnRef, "vernacular", LanguageName); if (MakesSplits(referenceBook, bookNum, Versification, verseSplitLocationsBasedOnVern, LanguageName, "vernacular")) { m_modifiedBooks.Add(referenceBook.BookId); } MatchVernBlocksToReferenceTextBlocks(vernacularBook.GetScriptBlocks(), vernacularBook.BookId, vernacularVersification); }
public void MatchAllBlocks(Paratext.ScrVers versification) { int bookNum = BCVRef.BookToNumber(m_vernacularBook.BookId); foreach (var block in CorrelatedBlocks) { if (block.MatchesReferenceText) { if (block.CharacterIsUnclear()) { var refBlock = block.ReferenceBlocks.Single(); block.SetCharacterAndDeliveryInfo(refBlock, bookNum, versification); if (block.CharacterIsUnclear()) { throw new InvalidOperationException("Character cannot be confirmed as ambigous or unknown."); } block.UserConfirmed = true; // This does not affect original block until Apply is called } } else { var refBlock = new Block(block.StyleTag, block.ChapterNumber, block.InitialStartVerseNumber, block.InitialEndVerseNumber); refBlock.SetCharacterAndDeliveryInfo(block, bookNum, versification); if (block.ReferenceBlocks.Any()) { refBlock.AppendJoinedBlockElements(block.ReferenceBlocks, m_referenceLanguageInfo); } else { refBlock.BlockElements.Add(new ScriptText("")); } block.SetMatchedReferenceBlock(refBlock); } } }
/// <summary> /// Split blocks in the given book to match verse split locations /// </summary> /// <returns>A value indicating whether any splits were made</returns> private static bool MakesSplits(PortionScript blocksToSplit, int bookNum, ScrVers versification, List <VerseSplitLocation> verseSplitLocations, string descriptionOfProjectBeingSplit, string descriptionOfProjectUsedToDetermineSplitLocations) { if (!verseSplitLocations.Any()) { return(false); } bool splitsMade = false; var iSplit = 0; VerseRef verseToSplitAfter = verseSplitLocations[iSplit]; var blocks = blocksToSplit.GetScriptBlocks(); for (int index = 0; index < blocks.Count; index++) { var block = blocks[index]; var initStartVerse = new VerseRef(bookNum, block.ChapterNumber, block.InitialStartVerseNumber, versification); VerseRef initEndVerse; if (block.InitialEndVerseNumber != 0) { initEndVerse = new VerseRef(bookNum, block.ChapterNumber, block.InitialEndVerseNumber, versification); } else { initEndVerse = initStartVerse; } while (initEndVerse > verseToSplitAfter) { if (iSplit == verseSplitLocations.Count - 1) { return(splitsMade); } verseToSplitAfter = verseSplitLocations[++iSplit]; } var lastVerse = new VerseRef(bookNum, block.ChapterNumber, block.LastVerseNum, versification); if (lastVerse < verseToSplitAfter) { continue; } if (initEndVerse.CompareTo(lastVerse) != 0 && lastVerse >= verseSplitLocations[iSplit].Before) { versification.ChangeVersification(verseToSplitAfter); if (blocksToSplit.TrySplitBlockAtEndOfVerse(block, verseToSplitAfter.VerseNum)) { splitsMade = true; } else { #if DEBUG if (!BlockContainsVerseEndInMiddleOfVerseBridge(block, verseToSplitAfter.VerseNum)) { ErrorReport.NotifyUserOfProblem( "Attempt to split {0} block to match breaks in the {1} text failed. Book: {2}; Chapter: {3}; Verse: {4}; Block: {5}", descriptionOfProjectBeingSplit, descriptionOfProjectUsedToDetermineSplitLocations, blocksToSplit.Id, block.ChapterNumber, verseToSplitAfter.VerseNum, block.GetText(true)); } #endif if (iSplit == verseSplitLocations.Count - 1) { break; } verseToSplitAfter = verseSplitLocations[++iSplit]; index--; } } } return(splitsMade); }
public VerseSplitLocation(int bookNum, Block prevBlock, Block splitStartBlock, ScrVers versification) { m_after = new VerseRef(bookNum, prevBlock.ChapterNumber, prevBlock.LastVerseNum, versification); m_before = new VerseRef(bookNum, splitStartBlock.ChapterNumber, splitStartBlock.InitialStartVerseNumber, versification); }
private static void FindAllScriptureBlocksThroughVerse(IReadOnlyList <Block> blockList, VerseRef endVerse, ref int i, ScrVers versification) { for (; ;) { var nextScriptureBlock = blockList.Skip(i + 1).FirstOrDefault(b => !CharacterVerseData.IsCharacterExtraBiblical(b.CharacterId)); if (nextScriptureBlock == null) { break; } var nextVerseRef = new VerseRef(endVerse.BookNum, nextScriptureBlock.ChapterNumber, nextScriptureBlock.InitialStartVerseNumber, versification); if (nextVerseRef > endVerse) { break; } i++; } }
private bool BlocksEndWithSameVerse(int bookNum, Block vernBlock, Block refBlock, ScrVers vernacularVersification) { var lastVernVerse = new VerseRef(bookNum, vernBlock.ChapterNumber, vernBlock.LastVerseNum, vernacularVersification); var lastRefVerse = new VerseRef(bookNum, refBlock.ChapterNumber, refBlock.LastVerseNum, Versification); return(lastVernVerse.CompareTo(lastRefVerse) == 0); }
private void MatchVernBlocksToReferenceTextBlocks(IReadOnlyList <Block> vernBlockList, string bookId, ScrVers vernacularVersification) { int bookNum = BCVRef.BookToNumber(bookId); var refBook = Books.Single(b => b.BookId == bookId); var refBlockList = refBook.GetScriptBlocks(); int iRefBlock = 0; // The following is a minor performance enhancement to help when just hooking up one verse's worth of blocks. // In it's current form, it doesn't work for tests that have partial reference texts that don't start at verse 1. // Also, it doesn't take versification mappings into consideration. //if (vernBlockList[0].ChapterNumber > 1) //{ // iRefBlock = refBook.GetIndexOfFirstBlockForVerse(vernBlockList[0].ChapterNumber, ); // if (iRefBlock < 0) // { // // Apparently there is no reference text for the verse(s) we're interested in. // return; // } //} for (int iVernBlock = 0; iVernBlock < vernBlockList.Count && iRefBlock < refBlockList.Count; iVernBlock++, iRefBlock++) { var currentVernBlock = vernBlockList[iVernBlock]; var currentRefBlock = refBlockList[iRefBlock]; var vernInitStartVerse = new VerseRef(bookNum, currentVernBlock.ChapterNumber, currentVernBlock.InitialStartVerseNumber, vernacularVersification); var refInitStartVerse = new VerseRef(bookNum, currentRefBlock.ChapterNumber, currentRefBlock.InitialStartVerseNumber, Versification); var type = CharacterVerseData.GetStandardCharacterType(currentVernBlock.CharacterId); switch (type) { case CharacterVerseData.StandardCharacter.BookOrChapter: if (currentVernBlock.IsChapterAnnouncement) { var refChapterBlock = new Block(currentVernBlock.StyleTag, currentVernBlock.ChapterNumber); refChapterBlock.BlockElements.Add(new ScriptText(GetFormattedChapterAnnouncement(bookId, currentVernBlock.ChapterNumber))); if (currentRefBlock.IsChapterAnnouncement && currentRefBlock.MatchesReferenceText) { refChapterBlock.SetMatchedReferenceBlock(currentRefBlock.ReferenceBlocks.Single().Clone()); } currentVernBlock.SetMatchedReferenceBlock(refChapterBlock); if (currentRefBlock.IsChapterAnnouncement) { continue; } } goto case CharacterVerseData.StandardCharacter.ExtraBiblical; case CharacterVerseData.StandardCharacter.ExtraBiblical: if (type == CharacterVerseData.GetStandardCharacterType(currentRefBlock.CharacterId)) { currentVernBlock.SetMatchedReferenceBlock(currentRefBlock); continue; } goto case CharacterVerseData.StandardCharacter.Intro; case CharacterVerseData.StandardCharacter.Intro: // This will be re-incremented in the for loop, so it effectively allows // the vern index to advance while keeping the ref index the same. iRefBlock--; continue; default: if (refInitStartVerse > vernInitStartVerse || currentVernBlock.MatchesReferenceText) { iRefBlock--; continue; } break; } while (CharacterVerseData.IsCharacterExtraBiblical(currentRefBlock.CharacterId) || vernInitStartVerse > refInitStartVerse) { iRefBlock++; if (iRefBlock == refBlockList.Count) { return; // couldn't find a ref block to use at all. } currentRefBlock = refBlockList[iRefBlock]; refInitStartVerse = new VerseRef(bookNum, currentRefBlock.ChapterNumber, currentRefBlock.InitialStartVerseNumber, vernacularVersification); } var indexOfVernVerseStart = iVernBlock; var indexOfRefVerseStart = iRefBlock; BlockMatchup.AdvanceToCleanVerseBreak(vernBlockList, i => true, ref iVernBlock); var lastVernVerseFound = new VerseRef(bookNum, vernBlockList[iVernBlock].ChapterNumber, vernBlockList[iVernBlock].LastVerseNum, vernacularVersification); FindAllScriptureBlocksThroughVerse(refBlockList, lastVernVerseFound, ref iRefBlock, Versification); int numberOfVernBlocksInVerseChunk = iVernBlock - indexOfVernVerseStart + 1; int numberOfRefBlocksInVerseChunk = iRefBlock - indexOfRefVerseStart + 1; for (int i = 0; i < numberOfVernBlocksInVerseChunk && i < numberOfRefBlocksInVerseChunk; i++) { var vernBlockInVerseChunk = vernBlockList[indexOfVernVerseStart + i]; var refBlockInVerseChunk = refBlockList[indexOfRefVerseStart + i]; if (BlocksMatch(bookNum, vernBlockInVerseChunk, refBlockInVerseChunk, vernacularVersification) || (numberOfVernBlocksInVerseChunk == 1 && numberOfRefBlocksInVerseChunk == 1 && BlocksEndWithSameVerse(bookNum, vernBlockInVerseChunk, refBlockInVerseChunk, vernacularVersification))) { if (i == numberOfVernBlocksInVerseChunk - 1 && i < numberOfRefBlocksInVerseChunk - 1) { vernBlockInVerseChunk.MatchesReferenceText = false; vernBlockInVerseChunk.ReferenceBlocks = new List <Block>(refBlockList.Skip(indexOfRefVerseStart + i).Take(numberOfRefBlocksInVerseChunk - i)); break; } vernBlockInVerseChunk.SetMatchedReferenceBlock(refBlockList[indexOfRefVerseStart + i]); } else { iVernBlock = indexOfVernVerseStart + i; int j = 0; if (numberOfVernBlocksInVerseChunk - i >= 2) { // Look from the bottom up for (; j + 1 < numberOfVernBlocksInVerseChunk && j + i < numberOfRefBlocksInVerseChunk; j++) { vernBlockInVerseChunk = vernBlockList[indexOfVernVerseStart + numberOfVernBlocksInVerseChunk - j - 1]; refBlockInVerseChunk = refBlockList[indexOfRefVerseStart + numberOfRefBlocksInVerseChunk - j - 1]; if (BlocksMatch(bookNum, vernBlockInVerseChunk, refBlockInVerseChunk, vernacularVersification)) { vernBlockInVerseChunk.SetMatchedReferenceBlock(refBlockInVerseChunk); } else { break; } } } vernBlockList[iVernBlock].MatchesReferenceText = false; vernBlockList[iVernBlock].ReferenceBlocks = new List <Block>(refBlockList.Skip(indexOfRefVerseStart + i).Take(numberOfRefBlocksInVerseChunk - i - j)); iRefBlock = indexOfRefVerseStart + numberOfRefBlocksInVerseChunk - 1; break; } } } }
public BlockMatchup GetBlocksForVerseMatchedToReferenceText(BookScript vernacularBook, int iBlock, ScrVers vernacularVersification) { if (iBlock < 0 || iBlock >= vernacularBook.GetScriptBlocks().Count) { throw new ArgumentOutOfRangeException("iBlock"); } if (!Books.Any(b => b.BookId == vernacularBook.BookId)) { return(null); } int bookNum = BCVRef.BookToNumber(vernacularBook.BookId); var referenceBook = Books.Single(b => b.BookId == vernacularBook.BookId); var verseSplitLocationsBasedOnRef = GetVerseSplitLocations(referenceBook, bookNum); var matchup = new BlockMatchup(vernacularBook, iBlock, portion => { MakesSplits(portion, bookNum, vernacularVersification, verseSplitLocationsBasedOnRef, "vernacular", LanguageName); }, nextVerse => { nextVerse.Versification = vernacularVersification; return(verseSplitLocationsBasedOnRef.Any(s => s.Before.CompareTo(nextVerse) == 0)); }, this); if (!matchup.AllScriptureBlocksMatch) { MatchVernBlocksToReferenceTextBlocks(matchup.CorrelatedBlocks, vernacularBook.BookId, vernacularVersification); } return(matchup); }
/// <summary> /// This method is preferred over the string bookId counterpart for performance reasons (so we don't have to look up the book number) /// </summary> public IEnumerable <CharacterVerse> GetCharacters(int bookId, int chapter, int initialStartVerse, int initialEndVerse = 0, int finalVerse = 0, ScrVers versification = null) { if (versification == null) { versification = ScrVers.English; } IEnumerable <CharacterVerse> result; if (initialEndVerse == 0 || initialStartVerse == initialEndVerse) { var verseRef = new VerseRef(bookId, chapter, initialStartVerse, versification); verseRef.ChangeVersification(ScrVers.English); result = m_lookup[verseRef.BBBCCCVVV]; } else { int start = new BCVRef(bookId, chapter, initialStartVerse).BBCCCVVV; int end = new BCVRef(bookId, chapter, initialEndVerse).BBCCCVVV; result = Enumerable.Empty <CharacterVerse>(); for (int i = start; i <= end; i++) { result = result.Union(m_lookup[i]); } } if (finalVerse == 0 || result.Count() == 1) { return(result); } var nextVerse = Math.Max(initialStartVerse, initialEndVerse) + 1; while (nextVerse <= finalVerse) { var verseRef = new VerseRef(bookId, chapter, nextVerse, versification); verseRef.ChangeVersification(ScrVers.English); IEnumerable <CharacterVerse> nextResult = m_lookup[verseRef.BBBCCCVVV]; if (!nextResult.Any()) { nextVerse++; continue; } if (!result.Any()) { result = nextResult; nextVerse++; continue; } var intersection = nextResult.Intersect(result, m_characterDeliveryEqualityComparer); if (intersection.Count() == 1) { result = intersection; break; } nextVerse++; } return(result); }
/// <summary> /// Prefer the int bookId counterpart method for performance reasons (this method has to perform a book Id lookup) /// </summary> public IEnumerable <CharacterVerse> GetCharacters(string bookId, int chapter, int initialStartVerse, int initialEndVerse = 0, int finalVerse = 0, ScrVers versification = null) { return(GetCharacters(BCVRef.BookToNumber(bookId), chapter, initialStartVerse, initialEndVerse, finalVerse, versification)); }