public BookBlockIndices GetIndicesOfFirstBlockAtReference(VerseRef verseRef)
        {
            var        bookId    = verseRef.Book;
            int        bookIndex = -1;
            BookScript book      = null;

            for (int i = 0; i < m_books.Count; i++)
            {
                book = m_books[i];
                if (book.BookId == bookId)
                {
                    bookIndex = i;
                    break;
                }
            }

            if (bookIndex == -1 || book == null)
            {
                return(null);
            }

            var blockIndex = book.Blocks.IndexOf(
                a => a.ChapterNumber == verseRef.ChapterNum && a.InitialStartVerseNumber <= verseRef.VerseNum && a.LastVerse >= verseRef.VerseNum);

            return(blockIndex == -1 ? null : new BookBlockIndices(bookIndex, blockIndex));
        }
 internal void SetIndices(BookBlockIndices indices)
 {
     m_currentBookIndex  = indices.BookIndex;
     m_currentBook       = m_books[m_currentBookIndex];
     m_currentBlockIndex = indices.BlockIndex;
     m_currentBlock      = m_currentBook.GetScriptBlocks()[m_currentBlockIndex];
 }
Beispiel #3
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);
        }
Beispiel #4
0
        public BlockMatchup GetBlocksForVerseMatchedToReferenceText(BookScript vernacularBook, int iBlock, ScrVers vernacularVersification, uint predeterminedBlockCount = 0)
        {
            if (iBlock < 0 || iBlock >= vernacularBook.GetScriptBlocks().Count)
            {
                throw new ArgumentOutOfRangeException("iBlock");
            }

            if (!CanDisplayReferenceTextForBook(vernacularBook))
            {
                return(null);
            }

            int bookNum = BCVRef.BookToNumber(vernacularBook.BookId);
            var verseSplitLocationsBasedOnRef = GetVerseSplitLocations(vernacularBook.BookId);

            var matchup = new BlockMatchup(vernacularBook, iBlock, portion =>
            {
                MakesSplits(portion, bookNum, vernacularVersification, verseSplitLocationsBasedOnRef, "vernacular", LanguageName);
            },
                                           nextVerse => IsOkayToSplitAtVerse(nextVerse, vernacularVersification, verseSplitLocationsBasedOnRef),
                                           this, predeterminedBlockCount);

            if (!matchup.AllScriptureBlocksMatch)
            {
                MatchVernBlocksToReferenceTextBlocks(matchup.CorrelatedBlocks, vernacularBook.BookId, vernacularVersification);
            }
            return(matchup);
        }
 private BookScript NextBook()
 {
     if (IsLastBook(m_currentBook))
     {
         return(null);
     }
     return(m_currentBook = m_books[++m_currentBookIndex]);
 }
 private BookScript PreviousBook()
 {
     if (IsFirstBook(m_currentBook))
     {
         return(null);
     }
     return(m_currentBook = m_books[--m_currentBookIndex]);
 }
Beispiel #7
0
        public BookScript Clone(bool join)
        {
            BookScript newBook = (BookScript)MemberwiseClone();

            newBook.Blocks = new List <Block>(GetScriptBlocks(join).Select(b => b.Clone()));
            newBook.m_unappliedSplitBlocks = new List <List <Block> >(m_unappliedSplitBlocks.Select(l => l.Select(b => b.Clone()).ToList()));
            return(newBook);
        }
 public bool IsFirstBook(BookScript book)
 {
     if (!m_books.Any())
     {
         return(false);
     }
     return(book == m_books.First());
 }
Beispiel #9
0
        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>();

            Parallel.ForEach(blocksInBook, book =>
            {
                var bookId = book.Key;
                Logger.WriteEvent("Creating bookScript ({0})", bookId);
                var bookScript = new BookScript(bookId, new UsxParser(bookId, stylesheet, book.Value).Parse());
                Logger.WriteEvent("Created bookScript ({0}, {1})", bookId, bookScript.BookId);
                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)
            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 BlockNavigator(IReadOnlyList <BookScript> books)
 {
     m_books       = books;
     m_currentBook = m_books.FirstOrDefault(b => b.HasScriptBlocks);
     if (m_currentBook == null)
     {
         throw new ArgumentException("The list of books must contain at least one block.");
     }
     m_currentBlock = m_currentBook[0];
 }
        private Block PeekNthNextBlockWithinBook(int n, int bookIndex, int blockIndex)
        {
            BookScript book = m_books[bookIndex];

            if (book.GetScriptBlocks().Count < blockIndex + n + 1)
            {
                return(null);
            }
            return(book[blockIndex + n]);
        }
        public bool IsFirstBlock(Block block)
        {
            BookScript book = GetBookScriptContainingBlock(block);

            if (book == null)
            {
                return(false);
            }
            return(IsFirstBlockInBook(book, block) && IsFirstBook(book));
        }
Beispiel #13
0
 public void ApplyUserDecisions(BookScript sourceBookScript, ScrVers versification = null)
 {
     foreach (var sourceUnappliedSplit in sourceBookScript.UnappliedSplits)
     {
         List <Block> targetUnappliedSplit = sourceUnappliedSplit.Select(splitPart => splitPart.Clone()).ToList();
         m_unappliedSplitBlocks.Add(targetUnappliedSplit);
     }
     ApplyUserSplits(sourceBookScript);
     ApplyUserAssignments(sourceBookScript, versification);
     CleanUpMultiBlockQuotes(versification);
 }
        private BookScript CreateBookScript()
        {
            Logger.WriteEvent("Creating bookScript ({0})", m_bookId);
            var bookScript = new BookScript(m_bookId, Parse(), null)
            {
                PageHeader = PageHeader,
                MainTitle  = MainTitle
            };

            Logger.WriteEvent("Created bookScript ({0}, {1})", m_bookId, bookScript.BookId);
            return(bookScript);
        }
Beispiel #15
0
        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 (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].SetCharacterAndCharacterIdInScript(sourceBlock.CharacterId, bookNum, versification);
                        }
                        else
                        {
                            m_blocks[iTarget].CharacterId = sourceBlock.CharacterId;
                            m_blocks[iTarget].CharacterIdOverrideForScript = sourceBlock.CharacterIdOverrideForScript;
                        }
                        m_blocks[iTarget].Delivery      = sourceBlock.Delivery;
                        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);
            }
        }
        private int GetBookIndex(BookScript bookToFind)
        {
            int i = 0;

            foreach (BookScript book in m_books)
            {
                if (book == bookToFind)
                {
                    return(i);
                }
                i++;
            }
            throw new ArgumentException("Book is not part of book list");
        }
Beispiel #17
0
        public BlockMatchup(BookScript vernacularBook, int iBlock, Action <PortionScript> splitBlocks,
                            Func <VerseRef, bool> isOkayToBreakAtVerse, IReferenceLanguageInfo heSaidProvider)
        {
            m_vernacularBook = vernacularBook;
            int bookNum = BCVRef.BookToNumber(m_vernacularBook.BookId);

            m_referenceLanguageInfo = heSaidProvider;
            var blocks = m_vernacularBook.GetScriptBlocks();
            var originalAnchorBlock           = blocks[iBlock];
            var blocksForVersesCoveredByBlock =
                vernacularBook.GetBlocksForVerse(originalAnchorBlock.ChapterNumber, originalAnchorBlock.InitialStartVerseNumber).ToList();

            m_iStartBlock = iBlock - blocksForVersesCoveredByBlock.IndexOf(originalAnchorBlock);
            while (!blocksForVersesCoveredByBlock.First().StartsAtVerseStart&& blocksForVersesCoveredByBlock.First().InitialStartVerseNumber < originalAnchorBlock.InitialStartVerseNumber)
            {
                var prepend = vernacularBook.GetBlocksForVerse(originalAnchorBlock.ChapterNumber, blocksForVersesCoveredByBlock.First().InitialStartVerseNumber).ToList();
                prepend.RemoveAt(prepend.Count - 1);
                m_iStartBlock -= prepend.Count;
                blocksForVersesCoveredByBlock.InsertRange(0, prepend);
            }
            int iLastBlock = m_iStartBlock + blocksForVersesCoveredByBlock.Count - 1;
            int i          = iLastBlock;

            AdvanceToCleanVerseBreak(blocks, verseNum =>
            {
                return(isOkayToBreakAtVerse(new VerseRef(bookNum, originalAnchorBlock.ChapterNumber, verseNum)));
            }, ref i);
            if (i > iLastBlock)
            {
                blocksForVersesCoveredByBlock.AddRange(blocks.Skip(iLastBlock + 1).Take(i - iLastBlock));
            }
            while (CharacterVerseData.IsCharacterOfType(blocksForVersesCoveredByBlock.Last().CharacterId, CharacterVerseData.StandardCharacter.ExtraBiblical))
            {
                blocksForVersesCoveredByBlock.RemoveAt(blocksForVersesCoveredByBlock.Count - 1);
            }

            m_portion             = new PortionScript(vernacularBook.BookId, blocksForVersesCoveredByBlock.Select(b => b.Clone()));
            CorrelatedAnchorBlock = m_portion.GetScriptBlocks()[iBlock - m_iStartBlock];
            if (splitBlocks != null)
            {
                int origCount = m_portion.GetScriptBlocks().Count;
                splitBlocks(m_portion);
                m_numberOfBlocksAddedBySplitting = m_portion.GetScriptBlocks().Count - origCount;
            }
        }
        public Block PeekPreviousBlock()
        {
            if (IsFirstBlock(m_currentBlock))
            {
                return(null);
            }
            if (IsFirstBlockInBook(m_currentBook, m_currentBlock))
            {
                BookScript previousBook = PeekPreviousBook();
                if (!previousBook.HasScriptBlocks)
                {
                    return(null);
                }
                return(previousBook[previousBook.GetScriptBlocks().Count - 1]);
            }

            return(m_currentBook[m_currentBlockIndex - 1]);
        }
        public Block PeekNextBlock()
        {
            if (IsLastBlock())
            {
                return(null);
            }
            if (IsLastBlockInBook(m_currentBook, m_currentBlock))
            {
                BookScript nextBook = PeekNextBook();
                if (!nextBook.HasScriptBlocks)
                {
                    return(null);
                }
                return(nextBook[0]);
            }

            return(m_currentBook[m_currentBlockIndex + 1]);
        }
Beispiel #20
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 Block NextBlock()
        {
            if (IsLastBlock())
            {
                return(null);
            }
            if (IsLastBlockInBook(m_currentBook, m_currentBlock))
            {
                BookScript nextBook = NextBook();
                if (!nextBook.HasScriptBlocks)
                {
                    return(null);
                }
                m_currentBlockIndex = 0;
                return(nextBook[m_currentBlockIndex]);
            }

            return(m_currentBlock = m_currentBook[++m_currentBlockIndex]);
        }
Beispiel #22
0
        public BookBlockIndices GetIndicesOfFirstBlockAtReference(VerseRef verseRef, bool allowMidQuoteBlock = false)
        {
            var        bookId    = verseRef.Book;
            int        bookIndex = -1;
            BookScript book      = null;

            for (int i = 0; i < m_books.Count; i++)
            {
                book = m_books[i];
                if (book.BookId == bookId)
                {
                    bookIndex = i;
                    break;
                }
            }

            if (bookIndex == -1 || book == null)
            {
                return(null);
            }

            var block = book.Blocks.FirstOrDefault(
                a => a.ChapterNumber == verseRef.ChapterNum && a.InitialStartVerseNumber <= verseRef.VerseNum && a.LastVerseNum >= verseRef.VerseNum);

            if (block == null)
            {
                return(null);
            }

            int blockIndex = book.Blocks.IndexOf(block);

            if (!allowMidQuoteBlock)
            {
                if (block.IsContinuationOfPreviousBlockQuote)
                {
                    blockIndex = book.Blocks.FindLastIndex(blockIndex, b => b.MultiBlockQuote == MultiBlockQuote.Start);
                }
            }

            return(blockIndex == -1 ? null : new BookBlockIndices(bookIndex, blockIndex));
        }
Beispiel #23
0
        private void ApplyUserSplits(BookScript sourceBookScript)
        {
            int          splitId = Block.kNotSplit;
            List <Block> split   = null;

            foreach (var block in sourceBookScript.Blocks.Where(b => b.SplitId != Block.kNotSplit))
            {
                if (block.SplitId != splitId)
                {
                    if (split != null)
                    {
                        m_unappliedSplitBlocks.Add(split);
                    }
                    split   = new List <Block>();
                    splitId = block.SplitId;
                }
                split.Add(block);
            }
            if (split != null)
            {
                m_unappliedSplitBlocks.Add(split);
            }

            var comparer = new SplitBlockComparer();

            for (int index = 0; index < m_unappliedSplitBlocks.Count; index++)
            {
                var  unappliedSplit    = m_unappliedSplitBlocks[index];
                var  firstBlockOfSplit = unappliedSplit.First();
                var  i = GetIndexOfFirstBlockThatStartsWithVerse(firstBlockOfSplit.ChapterNumber, firstBlockOfSplit.InitialStartVerseNumber);
                var  iFirstMatchingBlock = i;
                var  iUnapplied          = 0;
                bool blocksMatch;
                do
                {
                    var splitBlock  = unappliedSplit[iUnapplied];
                    var parsedBlock = m_blocks[i++];
                    blocksMatch = comparer.Equals(splitBlock, parsedBlock);
                    if (iUnapplied > 0 || blocksMatch)
                    {
                        if (!blocksMatch)
                        {
                            break;
                        }
                        if (iUnapplied == 0)
                        {
                            iFirstMatchingBlock = i;
                        }
                        iUnapplied++;
                    }
                } while (i < m_blocks.Count && iUnapplied < unappliedSplit.Count);
                if (blocksMatch)
                {
                    m_unappliedSplitBlocks.RemoveAt(index--);
                }
                else
                {
                    var combinedBlock = CombineBlocks(unappliedSplit);
                    for (int iBlock = iFirstMatchingBlock; iBlock < m_blocks.Count && m_blocks[iBlock].InitialStartVerseNumber == combinedBlock.InitialStartVerseNumber; iBlock++)
                    {
                        if (comparer.Equals(combinedBlock, m_blocks[iBlock]))
                        {
                            i = iBlock;
                            for (iUnapplied = 1; iUnapplied < unappliedSplit.Count; iUnapplied++)
                            {
                                var    elementsOfBlockPrecedingSplit         = unappliedSplit[iUnapplied - 1].BlockElements;
                                var    textElementAtEndOfBlockPrecedingSplit = elementsOfBlockPrecedingSplit.Last() as ScriptText;
                                int    offset = textElementAtEndOfBlockPrecedingSplit != null ? textElementAtEndOfBlockPrecedingSplit.Content.Length : 0;
                                string verse;
                                if (unappliedSplit[iUnapplied].BlockElements.First() is Verse)
                                {
                                    var lastVerseInPrecedingBlock = elementsOfBlockPrecedingSplit.OfType <Verse>().LastOrDefault();
                                    if (lastVerseInPrecedingBlock != null)
                                    {
                                        verse = lastVerseInPrecedingBlock.Number;
                                    }
                                    else
                                    {
                                        verse = m_blocks[i].InitialVerseNumberOrBridge;
                                    }
                                }
                                else
                                {
                                    verse = unappliedSplit[iUnapplied].InitialVerseNumberOrBridge;
                                }
                                SplitBlock(m_blocks[i++], verse, offset);
                                if (unappliedSplit[iUnapplied - 1].MatchesReferenceText)
                                {
                                    m_blocks[i - 1].SetMatchedReferenceBlock(unappliedSplit[iUnapplied - 1].ReferenceBlocks.Single().Clone());
                                }
                            }
                            if (unappliedSplit[iUnapplied - 1].MatchesReferenceText)
                            {
                                m_blocks[i].SetMatchedReferenceBlock(unappliedSplit[iUnapplied - 1].ReferenceBlocks.Single().Clone());
                            }

                            m_unappliedSplitBlocks.RemoveAt(index--);
                            break;
                        }
                    }
                }
            }
        }
        private BookScript TryLoadBook(string[] files, string bookCode)
        {
            var fileName = files.FirstOrDefault(f => Path.GetFileName(f) == bookCode + Constants.kBookScriptFileExtension);

            return(fileName != null?BookScript.Deserialize(fileName, Versification) : null);
        }
Beispiel #25
0
 public bool CanDisplayReferenceTextForBook(BookScript vernacularBook)
 {
     return(Books.Any(b => b.BookId == vernacularBook.BookId));
 }
Beispiel #26
0
        public BlockMatchup(BookScript vernacularBook, int iBlock, Action <PortionScript> splitBlocks,
                            Func <VerseRef, bool> isOkayToBreakAtVerse, IReferenceLanguageInfo heSaidProvider, uint predeterminedBlockCount = 0)
        {
            m_vernacularBook = vernacularBook;
            int bookNum = BCVRef.BookToNumber(m_vernacularBook.BookId);

            m_referenceLanguageInfo = heSaidProvider;
            var blocks = m_vernacularBook.GetScriptBlocks();
            var originalAnchorBlock = blocks[iBlock];

            if (predeterminedBlockCount == 0)
            {
                var blocksForVersesCoveredByBlock =
                    vernacularBook.GetBlocksForVerse(originalAnchorBlock.ChapterNumber, originalAnchorBlock.InitialStartVerseNumber).ToList();
                var indexOfAnchorBlockInVerse = blocksForVersesCoveredByBlock.IndexOf(originalAnchorBlock);
                if (indexOfAnchorBlockInVerse < 0)
                {
                    Logger.WriteEvent($"Anchor block not found in verse: {m_vernacularBook.BookId} {originalAnchorBlock.ChapterNumber}:" +
                                      $"{originalAnchorBlock.InitialStartVerseNumber} Verse apparently occurs more than once in the Scripture text.");
                    // REVIEW: This logic assumes that the repeated verse is wholly contained in this onwe block.
                    blocksForVersesCoveredByBlock = new List <Block>()
                    {
                        originalAnchorBlock
                    };
                    indexOfAnchorBlockInVerse = 0;
                }
                m_iStartBlock = iBlock - indexOfAnchorBlockInVerse;
                while (m_iStartBlock > 0)
                {
                    if (blocksForVersesCoveredByBlock.First().InitialStartVerseNumber < originalAnchorBlock.InitialStartVerseNumber &&
                        !blocksForVersesCoveredByBlock.First().StartsAtVerseStart)
                    {
                        var prepend = vernacularBook.GetBlocksForVerse(originalAnchorBlock.ChapterNumber,
                                                                       blocksForVersesCoveredByBlock.First().InitialStartVerseNumber).ToList();
                        prepend.RemoveAt(prepend.Count - 1);
                        m_iStartBlock -= prepend.Count;
                        blocksForVersesCoveredByBlock.InsertRange(0, prepend);
                    }
                    if (m_iStartBlock == 0 || isOkayToBreakAtVerse(new VerseRef(bookNum, originalAnchorBlock.ChapterNumber,
                                                                                blocksForVersesCoveredByBlock.First().InitialStartVerseNumber)))
                    {
                        break;
                    }

                    m_iStartBlock--;
                    blocksForVersesCoveredByBlock.Insert(0, blocks[m_iStartBlock]);
                }
                int iLastBlock = m_iStartBlock + blocksForVersesCoveredByBlock.Count - 1;
                int i          = iLastBlock;
                AdvanceToCleanVerseBreak(blocks,
                                         verseNum => isOkayToBreakAtVerse(new VerseRef(bookNum, originalAnchorBlock.ChapterNumber, verseNum)),
                                         ref i);
                if (i > iLastBlock)
                {
                    blocksForVersesCoveredByBlock.AddRange(blocks.Skip(iLastBlock + 1).Take(i - iLastBlock));
                }
                while (CharacterVerseData.IsCharacterOfType(blocksForVersesCoveredByBlock.Last().CharacterId, CharacterVerseData.StandardCharacter.ExtraBiblical))
                {
                    blocksForVersesCoveredByBlock.RemoveAt(blocksForVersesCoveredByBlock.Count - 1);
                }
                m_portion = new PortionScript(vernacularBook.BookId, blocksForVersesCoveredByBlock.Select(b => b.Clone()));

                try
                {
                    CorrelatedAnchorBlock = m_portion.GetScriptBlocks()[iBlock - m_iStartBlock];
                }
                catch (Exception ex)
                {
                    Logger.WriteEvent(ex.Message);
                    Logger.WriteEvent($"iBlock = {iBlock}; m_iStartBlock = {m_iStartBlock}");
                    foreach (var block in m_portion.GetScriptBlocks())
                    {
                        Logger.WriteEvent($"block = {block}");
                    }
                    throw;
                }
            }
            else
            {
                m_iStartBlock         = iBlock;
                m_portion             = new PortionScript(vernacularBook.BookId, vernacularBook.GetScriptBlocks().Skip(iBlock).Take((int)predeterminedBlockCount).Select(b => b.Clone()));
                CorrelatedAnchorBlock = m_portion.GetScriptBlocks().First();
            }

            if (splitBlocks != null)
            {
                int origCount = m_portion.GetScriptBlocks().Count;
                splitBlocks(m_portion);
                m_numberOfBlocksAddedBySplitting = m_portion.GetScriptBlocks().Count - origCount;
            }
        }
 private bool IsLastBlockInBook(BookScript book, int blockIndex)
 {
     return(blockIndex == book.GetScriptBlocks().Count - 1);
 }
 public bool IsFirstBlockInBook(BookScript book, Block block)
 {
     return(block == book.GetScriptBlocks().FirstOrDefault());
 }