Example #1
0
        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);
        }
Example #4
0
        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;
        }
Example #5
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);
        }
Example #6
0
        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);
                }
            }
        }
Example #7
0
        /// <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);
        }
Example #8
0
 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);
 }
Example #9
0
 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++;
     }
 }
Example #10
0
        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);
        }
Example #11
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;
                    }
                }
            }
        }
Example #12
0
        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));
 }