private void InsertHeSaidText(IReferenceLanguageInfo referenceLanguageInfo, int i, Action <int, int, string> handleHeSaidInserted, int level = 0) { if (CorrelatedBlocks[i].CharacterIs(m_vernacularBook.BookId, CharacterVerseData.StandardCharacter.Narrator) || CorrelatedBlocks[i].CharacterId == CharacterVerseData.kUnknownCharacter) { if (CorrelatedBlocks[i].GetReferenceTextAtDepth(level) == "") { if (CorrelatedBlocks[i].CharacterId == CharacterVerseData.kUnknownCharacter) { CorrelatedBlocks[i].CharacterId = CharacterVerseData.GetStandardCharacterId(m_vernacularBook.BookId, CharacterVerseData.StandardCharacter.Narrator); } var text = referenceLanguageInfo.HeSaidText; if (i < CorrelatedBlocks.Count - 1 && !CorrelatedBlocks[i + 1].IsParagraphStart) { text += referenceLanguageInfo.WordSeparator; } SetReferenceText(i, text, level); handleHeSaidInserted(i, level, text); } if (referenceLanguageInfo.HasSecondaryReferenceText) { InsertHeSaidText(referenceLanguageInfo.BackingReferenceLanguage, i, handleHeSaidInserted, level + 1); } } }
public void AppendJoinedBlockElements(List <Block> referenceBlocks, IReferenceLanguageInfo languageInfo) { var nestedRefBlocks = new List <Block>(); foreach (Block r in referenceBlocks) { if (r.MatchesReferenceText) { nestedRefBlocks.Add(r.ReferenceBlocks.Single()); } foreach (BlockElement element in r.BlockElements) { var scriptText = element as ScriptText; if (scriptText != null) { var prevScriptText = BlockElements.LastOrDefault() as ScriptText; if (prevScriptText != null) { prevScriptText.Content = prevScriptText.Content.TrimEnd() + languageInfo.WordSeparator + scriptText.Content; continue; } } BlockElements.Add(element.Clone()); } } if (nestedRefBlocks.Any()) { var backingRefBlock = new Block(StyleTag, ChapterNumber, InitialStartVerseNumber, InitialEndVerseNumber); backingRefBlock.SetCharacterAndDeliveryInfo(this); backingRefBlock.AppendJoinedBlockElements(nestedRefBlocks, languageInfo.BackingReferenceLanguage); SetMatchedReferenceBlock(backingRefBlock); } }
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 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 void InsertHeSaidText(IReferenceLanguageInfo referenceLanguageInfo, int i, Action <int, int, string> handleHeSaidInserted, int level = 0) { var block = CorrelatedBlocks[i]; if (block.CharacterIs(BookId, CharacterVerseData.StandardCharacter.Narrator) || block.CharacterIsUnclear) { var existingEmptyVerseRefText = block.GetEmptyVerseReferenceTextAtDepth(level); if (existingEmptyVerseRefText != null) { var narrator = CharacterVerseData.GetStandardCharacterId(BookId, CharacterVerseData.StandardCharacter.Narrator); if (block.CharacterIsUnclear) { block.SetNonDramaticCharacterId(narrator); } // Deal with following blocks in quote block chain (and mark this one None). if (block.MultiBlockQuote == MultiBlockQuote.Start) { for (int iCont = i + 1; iCont < CorrelatedBlocks.Count; iCont++) { var contBlock = CorrelatedBlocks[iCont]; if (contBlock.MultiBlockQuote != MultiBlockQuote.Continuation) { break; } contBlock.MultiBlockQuote = MultiBlockQuote.None; // It's probably impossible in practice, but if this block has a character other than narrator already set, // let's leave it as is. And, of course, if it's already explicitly set to narrator, then there's nothing to // do. if (contBlock.CharacterIsUnclear) { // By far the common case will be that this block will be associated with a reference // block that has a real character ID. If so, we'll use that ID, even if it's not // narrator because it's better not to have weird UI changes (that might be scrolled off // the screen) that the user won't be able to account for. But in the unusual case where // the vernacular block was unknown/ambiguous and it didn't align to a real ref block (so // we just made up an empty one on the fly), it's probably best to go ahead and assume // that any such continuation blocks are to be assigned to the narrator. In that case, // we need to fire the handler to alert the client. var dataChange = false; var newCharacterId = contBlock.ReferenceBlocks.SingleOrDefault()?.CharacterId; if (CharacterVerseData.IsCharacterUnclear(newCharacterId)) { newCharacterId = narrator; dataChange = true; } contBlock.SetNonDramaticCharacterId(newCharacterId); if (dataChange) { handleHeSaidInserted(iCont, level, null); } } } block.MultiBlockQuote = MultiBlockQuote.None; } var text = existingEmptyVerseRefText + referenceLanguageInfo.HeSaidText; if (i < CorrelatedBlocks.Count - 1 && !CorrelatedBlocks[i + 1].IsParagraphStart) { text += referenceLanguageInfo.WordSeparator; } SetReferenceText(i, text, level); handleHeSaidInserted(i, level, text); } if (referenceLanguageInfo.HasSecondaryReferenceText) { InsertHeSaidText(referenceLanguageInfo.BackingReferenceLanguage, i, handleHeSaidInserted, level + 1); } } }