internal static Tuple <int, string, List <object> > GetExportDataForBlock(Block block, int blockNumber, string bookId, VoiceActor.VoiceActor voiceActor = null, string singleVoiceNarratorOverride = null, bool useCharacterIdInScript = true) { // NOTE: if the order here changes, there may be changes needed in GenerateExcelFile List <object> list = new List <object>(); list.Add(blockNumber); if (voiceActor != null) { list.Add(voiceActor.Name); } list.Add(block.StyleTag); list.Add(bookId); list.Add(block.ChapterNumber); list.Add(block.InitialStartVerseNumber); string characterId; if (singleVoiceNarratorOverride != null) { characterId = singleVoiceNarratorOverride; } else { characterId = useCharacterIdInScript ? block.CharacterIdInScript : block.CharacterId; } list.Add(CharacterVerseData.IsCharacterStandard(characterId) ? CharacterVerseData.GetStandardCharacterIdAsEnglish(characterId) : characterId); list.Add(block.Delivery); list.Add(block.GetText(true)); list.Add(block.GetText(false).Length); return(new Tuple <int, string, List <object> >(voiceActor == null ? -1 : voiceActor.Id, bookId, list)); }
private List <object> GetExportDataForReferenceBlock(Block refBlock, string bookId) { var row = new List <object>(); row.Add(null); if (IncludeVoiceActors) { row.Add(null); } row.Add(refBlock.StyleTag); row.Add(bookId); row.Add(refBlock.ChapterNumber); row.Add(refBlock.InitialVerseNumberOrBridge); row.Add((CharacterVerseData.IsCharacterStandard(refBlock.CharacterId) ? CharacterVerseData.GetStandardCharacterIdAsEnglish(refBlock.CharacterId) : refBlock.CharacterId)); if (LocalizationManager.UILanguageId != "en") { row.Add(null); } row.Add(refBlock.Delivery); row.Add(null); row.Add(refBlock.GetText(true, true)); if (Project.ReferenceText.HasSecondaryReferenceText) { row.Add(refBlock.PrimaryReferenceText); } row.Add(0); return(row); }
private void UpdateDisplay() { var blockRef = m_viewModel.GetBlockVerseRef(); int versesInBlock = m_viewModel.CurrentBlock.LastVerse - blockRef.VerseNum; var displayedRefMinusBlockStartRef = m_scriptureReference.VerseControl.VerseRef.BBBCCCVVV - blockRef.BBBCCCVVV; if (displayedRefMinusBlockStartRef < 0 || displayedRefMinusBlockStartRef > versesInBlock) { m_scriptureReference.VerseControl.VerseRef = m_viewModel.GetBlockVerseRef(); } m_labelXofY.Visible = m_viewModel.IsCurrentBlockRelevant; Debug.Assert(m_viewModel.RelevantBlockCount >= m_viewModel.CurrentBlockDisplayIndex); m_labelXofY.Text = string.Format(m_xOfYFmt, m_viewModel.CurrentBlockDisplayIndex, m_viewModel.RelevantBlockCount); m_chkSingleVoice.Text = string.Format(m_singleVoiceCheckboxFmt, m_viewModel.CurrentBookId); m_viewModel.GetBlockVerseRef().SendScrReference(); HideCharacterFilter(); m_btnAssign.Enabled = false; LoadCharacterListBox(m_viewModel.GetCharactersForCurrentReference()); UpdateShortcutDisplay(); m_chkSingleVoice.Checked = m_viewModel.IsCurrentBookSingleVoice; m_menuBtnSplitBlock.Enabled = !CharacterVerseData.IsCharacterStandard(m_viewModel.CurrentBlock.CharacterId, false); }
public void DataIntegrity_AllCharacterIdsAndDefaultCharactersHaveCharacterDetail() { CharacterDetailData.TabDelimitedCharacterDetailData = Resources.CharacterDetail; //resets cache var charactersHavingDetail = CharacterDetailData.Singleton.GetAll().Select(d => d.CharacterId).ToList(); ISet <string> missingCharacters = new SortedSet <string>(); ISet <string> missingDefaultCharacters = new SortedSet <string>(); foreach (CharacterVerse cv in ControlCharacterVerseData.Singleton.GetAllQuoteInfo()) { if (!charactersHavingDetail.Contains(cv.Character)) { if (CharacterVerseData.IsCharacterStandard(cv.Character) || cv.Character == CharacterVerseData.kNeedsReview) { continue; } // For interruptions, we actually never pay any attention to the character ID. They are always narrator. // But in some verses we have both a normal narrator Quotation and an interruption, so to avoid a problem // in other data integrity checks, we just use the dummy character id "interruption-XXX" (where XXX is the // 3-letter book code. if (cv.QuoteType == QuoteType.Interruption || cv.Character.StartsWith("interruption-")) { continue; } var characters = cv.Character.Split('/'); if (characters.Length > 1) { foreach (var character in characters.Where(character => !charactersHavingDetail.Contains(character))) { missingCharacters.Add(character); } } else { missingCharacters.Add(cv.Character); } } if (!(string.IsNullOrEmpty(cv.DefaultCharacter) || charactersHavingDetail.Contains(cv.DefaultCharacter))) { if (CharacterVerseData.IsCharacterStandard(cv.DefaultCharacter) || cv.DefaultCharacter == CharacterVerseData.kNeedsReview) { continue; } missingDefaultCharacters.Add(cv.DefaultCharacter); } } Assert.False(missingCharacters.Any() || missingDefaultCharacters.Any(), (missingCharacters.Any() ? "Characters in Character-Verse data but not in Character-Detail:" + Environment.NewLine + missingCharacters.OnePerLineWithIndent() : "") + (missingDefaultCharacters.Any() ? Environment.NewLine + "Default characters in Character-Verse data but not in Character-Detail:" + Environment.NewLine + missingDefaultCharacters.OnePerLineWithIndent() : "")); }
public static int MigrateDeprecatedCharacterIds(Project project) { var cvInfo = new CombinedCharacterVerseData(project); var characterDetailDictionary = project.AllCharacterDetailDictionary; int numberOfChangesMade = 0; // For testing foreach (BookScript book in project.Books) { int bookNum = BCVRef.BookToNumber(book.BookId); foreach (Block block in book.GetScriptBlocks().Where(block => block.CharacterId != null && block.CharacterId != CharacterVerseData.kUnknownCharacter && !CharacterVerseData.IsCharacterStandard(block.CharacterId))) { if (block.CharacterId == CharacterVerseData.kAmbiguousCharacter) { if (block.UserConfirmed) { block.UserConfirmed = false; numberOfChangesMade++; } } else { var unknownCharacter = !characterDetailDictionary.ContainsKey(block.CharacterIdInScript); if (unknownCharacter && project.ProjectCharacterVerseData.GetCharacters(bookNum, block.ChapterNumber, block.InitialStartVerseNumber, block.InitialEndVerseNumber, block.LastVerseNum). Any(c => c.Character == block.CharacterId && c.Delivery == (block.Delivery ?? ""))) { // PG-471: This is a known character who spoke in an unexpected location and was therefore added to the project CV file, // but was subsequently removed or renamed from the master character detail list. project.ProjectCharacterVerseData.Remove(bookNum, block.ChapterNumber, block.InitialStartVerseNumber, block.InitialEndVerseNumber, block.CharacterId, block.Delivery ?? ""); block.CharacterId = CharacterVerseData.kUnknownCharacter; block.CharacterIdInScript = null; numberOfChangesMade++; } else { var characters = cvInfo.GetCharacters(bookNum, block.ChapterNumber, block.InitialStartVerseNumber, block.InitialEndVerseNumber, block.LastVerseNum).ToList(); if (unknownCharacter || !characters.Any(c => c.Character == block.CharacterId && c.Delivery == (block.Delivery ?? ""))) { if (characters.Count(c => c.Character == block.CharacterId) == 1) { block.Delivery = characters.First(c => c.Character == block.CharacterId).Delivery; } else { block.SetCharacterAndDelivery(characters); } numberOfChangesMade++; } } } } } return(numberOfChangesMade); }
public void DataIntegrity_AllCharacterIdsAndDefaultCharactersHaveCharacterDetail(bool readHypotheticalAsNarrator) { ControlCharacterVerseData.ReadHypotheticalAsNarrator = readHypotheticalAsNarrator; CharacterDetailData.TabDelimitedCharacterDetailData = Resources.CharacterDetail; //resets cache try { var charactersHavingDetail = CharacterDetailData.Singleton.GetAll().Select(d => d.CharacterId).ToList(); ISet <string> missingCharacters = new SortedSet <string>(); ISet <string> missingDefaultCharacters = new SortedSet <string>(); foreach (CharacterVerse cv in ControlCharacterVerseData.Singleton.GetAllQuoteInfo()) { if (!charactersHavingDetail.Contains(cv.Character)) { if (CharacterVerseData.IsCharacterStandard(cv.Character)) { continue; } var characters = cv.Character.Split('/'); if (characters.Length > 1) { foreach (var character in characters.Where(character => !charactersHavingDetail.Contains(character))) { missingCharacters.Add(character); } } else { missingCharacters.Add(cv.Character); } } if (!(string.IsNullOrEmpty(cv.DefaultCharacter) || charactersHavingDetail.Contains(cv.DefaultCharacter))) { if (CharacterVerseData.IsCharacterStandard(cv.DefaultCharacter)) { continue; } missingDefaultCharacters.Add(cv.DefaultCharacter); } } Assert.False(missingCharacters.Any() || missingDefaultCharacters.Any(), "Characters in Character-Verse data but not in Character-Detail:" + Environment.NewLine + missingCharacters.OnePerLineWithIndent() + Environment.NewLine + "Default characters in Character-Verse data but not in Character-Detail:" + Environment.NewLine + missingDefaultCharacters.OnePerLineWithIndent()); } finally { ControlCharacterVerseData.ReadHypotheticalAsNarrator = false; } }
internal static List <object> GetExportDataForBlock(Block block, int blockNumber, string bookId, VoiceActor.VoiceActor voiceActor, string singleVoiceNarratorOverride, bool useCharacterIdInScript, bool includeSecondaryDirectorsGuide) { // NOTE: if the order here changes, there may be changes needed in GenerateExcelFile List <object> list = new List <object>(); list.Add(blockNumber); if (voiceActor != null) { list.Add(voiceActor.Name); } list.Add(block.StyleTag); list.Add(bookId); list.Add(block.ChapterNumber); list.Add(block.InitialVerseNumberOrBridge); string characterId; if (singleVoiceNarratorOverride != null) { characterId = singleVoiceNarratorOverride; } else { characterId = useCharacterIdInScript ? block.CharacterIdInScript : block.CharacterId; } list.Add(CharacterVerseData.IsCharacterStandard(characterId) ? CharacterVerseData.GetStandardCharacterIdAsEnglish(characterId) : characterId); // add a column for the localized character id if (LocalizationManager.UILanguageId != "en") { list.Add(CharacterVerseData.GetCharacterNameForUi(characterId)); } list.Add(block.Delivery); list.Add(block.GetText(true)); list.Add(block.PrimaryReferenceText); if (includeSecondaryDirectorsGuide) { var primaryRefBlock = (block.MatchesReferenceText) ? block.ReferenceBlocks.Single() : null; if (primaryRefBlock != null && primaryRefBlock.MatchesReferenceText) { list.Add(primaryRefBlock.PrimaryReferenceText); } else { list.Add(null); } } list.Add(block.GetText(false).Length); return(list); }
internal bool AddToReservedGroupIfAppropriate(string characterId) { if (CharacterVerseData.IsCharacterOfType(characterId, CharacterVerseData.StandardCharacter.Narrator)) { AddToBestNarratorGroup(characterId); return(true); } if (CharacterVerseData.IsCharacterStandard(characterId, false)) { if (ExtraBiblicalGroup != null) { ExtraBiblicalGroup.CharacterIds.Add(characterId); return(true); } } return(false); }
public string CharacterSelect(int splitId, IEnumerable <AssignCharacterViewModel.Character> characters = null) { if ((characters == null) && !string.IsNullOrEmpty(s_characterSelect)) { return(string.Format(s_characterSelect, splitId)); } const string optionTemplate = "<option value=\"{0}\">{1}</option>"; var sb = new StringBuilder("<select class=\"select-character\" data-splitid=\"{0}\"><option value=\"\"></option>"); if (characters != null) { foreach (var character in characters) { if (CharacterVerseData.IsCharacterStandard(character.CharacterId)) { } if (character.IsNarrator) { sb.AppendFormat(optionTemplate, CharacterVerseData.GetStandardCharacterId(BookCode, CharacterVerseData.StandardCharacter.Narrator), character.LocalizedDisplay); } else { var stdCharacterType = CharacterVerseData.GetStandardCharacterType(character.CharacterId); if (stdCharacterType == CharacterVerseData.StandardCharacter.NonStandard) { sb.AppendFormat(optionTemplate, character.CharacterId, character.LocalizedDisplay); } else { sb.AppendFormat(optionTemplate, CharacterVerseData.GetStandardCharacterId(BookCode, stdCharacterType), character.LocalizedDisplay); } } } } sb.Append("</select>"); s_characterSelect = sb.ToString(); return(string.Format(s_characterSelect, splitId)); }
public virtual Color GetForeColorByCharacterId(string characterId) { if (string.IsNullOrWhiteSpace(characterId)) { return(SpeechNonCharacter); } if (characterId == "Jesus") { return(SpeechJesus); } if (!CharacterVerseData.IsCharacterStandard(characterId)) { return(SpeechCharacter); } return(SpeechNonCharacter); }
public void DataIntegrity_AllNonNarratorCharacterDetailsHaveCharacterIdOrDefaultCharacter() { var characterIds = new List <string>(ControlCharacterVerseData.Singleton.GetAllQuoteInfo().Select(d => d.Character) .SelectMany(characters => characters.Split('/'))); var defaultCharacters = ControlCharacterVerseData.Singleton.GetAllQuoteInfo().Select(d => d.DefaultCharacter).ToList(); ISet <string> missingCharacters = new SortedSet <string>(); foreach (string character in CharacterDetailData.Singleton.GetAll().Select(d => d.CharacterId)) { if (!CharacterVerseData.IsCharacterStandard(character) && (!(characterIds.Contains(character) || defaultCharacters.Contains(character)))) { missingCharacters.Add(character); } } Assert.False(missingCharacters.Any(), "Characters in Character-Detail data but not in Character-Verse data:" + Environment.NewLine + missingCharacters.OnePerLineWithIndent()); }
public bool IsModified(Character newCharacter, Delivery newDelivery) { Block currentBlock = CurrentBlock; if (CharacterVerseData.IsCharacterStandard(currentBlock.CharacterId, false)) { return(false); // Can't change these. } if (newCharacter == null) { return(!(currentBlock.CharacterIsUnclear() || currentBlock.CharacterId == null)); } if (newCharacter.IsNarrator) { if (!currentBlock.CharacterIs(CurrentBookId, CharacterVerseData.StandardCharacter.Narrator)) { return(true); } } else if (newCharacter.CharacterId != currentBlock.CharacterId) { return(true); } if (newDelivery == null) { return(true); } if (newDelivery.IsNormal) { return(!string.IsNullOrEmpty(currentBlock.Delivery)); } return(newDelivery.Text != currentBlock.Delivery); }
// internal for testing internal static int MigrateDeprecatedCharacterIds(Project project) { var cvInfo = new CombinedCharacterVerseData(project); var characterDetailDictionary = CharacterDetailData.Singleton.GetDictionary(); int numberOfChangesMade = 0; // For testing foreach (BookScript book in project.Books) { int bookNum = BCVRef.BookToNumber(book.BookId); foreach (Block block in book.GetScriptBlocks().Where(block => block.CharacterId != null && block.CharacterId != CharacterVerseData.kUnexpectedCharacter && !CharacterVerseData.IsCharacterStandard(block.CharacterId))) { if (block.CharacterId == CharacterVerseData.kAmbiguousCharacter) { if (block.UserConfirmed) { block.UserConfirmed = false; numberOfChangesMade++; } } else { var knownFactoryCharacter = characterDetailDictionary.ContainsKey(block.CharacterIdInScript); var unknownCharacter = !knownFactoryCharacter && !project.IsProjectSpecificCharacter(block.CharacterIdInScript); if (unknownCharacter && project.ProjectCharacterVerseData.GetCharacters(bookNum, block.ChapterNumber, block.AllVerses) .Any(c => c.Character == block.CharacterId && c.Delivery == (block.Delivery ?? ""))) { // PG-471: This is a formerly known character who spoke in an unexpected location and was therefore added to the project CV file, // but was subsequently removed or renamed from the master character detail list. project.ProjectCharacterVerseData.RemoveAllEntriesForBlock(bookNum, block); block.UserConfirmed = false; block.CharacterId = CharacterVerseData.kUnexpectedCharacter; block.CharacterIdInScript = null; numberOfChangesMade++; } else { var characters = cvInfo.GetCharacters(bookNum, block.ChapterNumber, block.AllVerses, includeAlternatesAndRareQuotes: true, includeNarratorOverrides: true); if (unknownCharacter || !characters.Any(c => c.Character == block.CharacterId && c.Delivery == (block.Delivery ?? ""))) { if (characters.Count(c => c.Character == block.CharacterId) == 1) { // Note: For normal projects, if we get here, we will almost certainly be changing the delivery. // However, this is not the case when processing the reference text project using Glyssen after // generating it from the Director's Guide because we get here repeatedly for blocks assigned to // multiple-character IDs because we intentionally do not set the CharacterIdOverrideForScript, // preferring rather to leave it up to the program to assign the then-current default to the // vernacular block at the time the matchup is applied. var onlyKnownDelivery = characters.First(c => c.Character == block.CharacterId).Delivery; if ((block.Delivery ?? "") != onlyKnownDelivery) { block.Delivery = characters.First(c => c.Character == block.CharacterId).Delivery; numberOfChangesMade++; } } else { var match = characters.SingleOrDefault(c => c.ResolvedDefaultCharacter == block.CharacterId && c.Delivery == (block.Delivery ?? "")); if (match != null) { block.CharacterId = match.Character; block.CharacterIdInScript = match.ResolvedDefaultCharacter; } else { block.SetCharacterAndDelivery(characters); } numberOfChangesMade++; } } else if (knownFactoryCharacter) { var projectCvEntryRemoved = false; foreach (var verseNum in block.AllVerses.SelectMany(v => v.AllVerseNumbers)) { if (ControlCharacterVerseData.Singleton.GetCharacters(bookNum, block.ChapterNumber, verseNum) .Any(cv => cv.Character == block.CharacterId && cv.Delivery == (block.Delivery ?? ""))) { projectCvEntryRemoved |= project.ProjectCharacterVerseData.RemoveEntryForBlock(bookNum, block, verseNum); } } if (project.RemoveProjectCharacterDetail(block.CharacterId) || projectCvEntryRemoved) { numberOfChangesMade++; } } } } } } return(numberOfChangesMade); }
internal List <CharacterGroup> GenerateCharacterGroups() { List <CharacterGroup> characterGroups = CreateGroupsForActors(m_project.VoiceActorList.Actors).ToList(); if (characterGroups.Count == 0) { return(characterGroups); // REVIEW: Maybe we should throw an exception instead. } m_project.SetDefaultCharacterGroupGenerationPreferences(); List <VoiceActor.VoiceActor> nonCameoActors = m_project.VoiceActorList.Actors.Where(a => !a.IsCameo).ToList(); if (nonCameoActors.Count == 0) { return(characterGroups); // All cameo actors! This should never happen. } var sortedDict = from entry in m_keyStrokesByCharacterId orderby entry.Value descending select entry; IReadOnlyDictionary <string, CharacterDetail> characterDetails = m_project.AllCharacterDetailDictionary; var includedCharacterDetails = characterDetails.Values.Where(c => sortedDict.Select(e => e.Key).Contains(c.CharacterId)).ToList(); // In the first loop, we're looking for actors that could only possibly play one character role. // Since we're not doing strict age matching, this is most likely only to find any candidates in // the case of children (and then only if the project includes a limited selection of books) var characterDetailsUniquelyMatchedToActors = new Dictionary <CharacterDetail, List <VoiceActor.VoiceActor> >(); foreach (var actor in nonCameoActors) { // After we find the second match, we can quit looking because we're only interested in unique matches. var matches = includedCharacterDetails.Where(c => !CharacterVerseData.IsCharacterStandard(c.CharacterId) && actor.Matches(c)).Take(2).ToList(); if (matches.Any()) { if (matches.Count == 1) { var characterDetail = matches.First(); if (characterDetailsUniquelyMatchedToActors.ContainsKey(characterDetail)) { characterDetailsUniquelyMatchedToActors[characterDetail].Add(actor); } else { characterDetailsUniquelyMatchedToActors[characterDetail] = new List <VoiceActor.VoiceActor> { actor } }; } } } // This loop uses the results of the previous one to add the characters to a group, and to close that // group to further additions. If there's more than one candidate actor, we pick one arbitrarily, // since afterwards we'll be clearing actor names anyway. // Since all groups now have an actor assigned up-front, at the // end of the generation process, we'll need to clear all actor assignments except for the ones that // are pre-determined here. List <int> actorsWithRealAssignments = new List <int>(); foreach (var characterDetailToActors in characterDetailsUniquelyMatchedToActors) { var matchingActors = characterDetailToActors.Value; var matchingGroups = characterGroups.Where(g => matchingActors.Any(a => a.Id == g.VoiceActorId)).ToList(); matchingGroups.First().CharacterIds.Add(characterDetailToActors.Key.CharacterId); if (matchingGroups.Count == 1) { actorsWithRealAssignments.Add(matchingGroups[0].VoiceActorId); } foreach (var characterGroup in matchingGroups) { characterGroup.Closed = true; } } // TODO: Make sure we didn't close all the groups (unless we assigned all the character IDs foreach (var character in includedCharacterDetails) { var matchingActors = characterGroups.Where(g => !g.Closed).Select(g => g.VoiceActor).Where(a => a.Matches(character)).ToList(); if (matchingActors.Count == 1) { var matchingActor = matchingActors.First(); CharacterGroup groupForActor = characterGroups.Single(g => g.VoiceActorId == matchingActor.Id); groupForActor.CharacterIds.Add(character.CharacterId); actorsWithRealAssignments.Add(matchingActor.Id); } } int maxMaleNarrators = m_project.CharacterGroupGenerationPreferences.NumberOfMaleNarrators; int maxFemaleNarrators = m_project.CharacterGroupGenerationPreferences.NumberOfFemaleNarrators; TrialGroupConfiguration bestConfiguration = null; do { var trialConfigurationsForNarratorsAndExtras = TrialGroupConfiguration.GeneratePossibilities(characterGroups, ref maxMaleNarrators, ref maxFemaleNarrators, includedCharacterDetails, m_project); if (trialConfigurationsForNarratorsAndExtras.Any()) { foreach (var configuration in trialConfigurationsForNarratorsAndExtras) { foreach (var entry in sortedDict) { string characterId = entry.Key; if (configuration.Groups.Any(g => g.CharacterIds.Contains(characterId))) { continue; } CharacterDetail characterDetail; if (!characterDetails.TryGetValue(characterId, out characterDetail)) { if (characterId == CharacterVerseData.AmbiguousCharacter || characterId == CharacterVerseData.UnknownCharacter) { continue; // This should never happen in production code! } //Debug.WriteLine("No character details for unexpected character ID (see PG-): " + characterId); //continue; throw new KeyNotFoundException("No character details for unexpected character ID (see PG-471): " + characterId); } if (!configuration.AddToReservedGroupIfAppropriate(characterId)) { AddCharacterToBestGroup(characterDetail, configuration); } } } bestConfiguration = TrialGroupConfiguration.Best(trialConfigurationsForNarratorsAndExtras, bestConfiguration); if (bestConfiguration.MinimumProximity >= Proximity.kDefaultMinimumProximity) { return(GetFinalizedGroups(bestConfiguration.Groups, actorsWithRealAssignments)); } } if (maxMaleNarrators == 0) { maxFemaleNarrators--; } else if (maxFemaleNarrators == 0) { maxMaleNarrators--; } else if (bestConfiguration != null && (bestConfiguration.GroupWithWorstProximity.ContainsCharacterWithGender(CharacterGender.Female) || bestConfiguration.GroupWithWorstProximity.ContainsCharacterWithGender(CharacterGender.PreferFemale))) { maxFemaleNarrators--; } else if (bestConfiguration != null && (bestConfiguration.GroupWithWorstProximity.ContainsCharacterWithGender(CharacterGender.Male) || bestConfiguration.GroupWithWorstProximity.ContainsCharacterWithGender(CharacterGender.PreferMale))) { maxMaleNarrators--; } else if (maxMaleNarrators > maxFemaleNarrators) { maxMaleNarrators--; } else { maxFemaleNarrators--; } } while (maxMaleNarrators + maxFemaleNarrators > 0); Debug.Assert(bestConfiguration != null); return(GetFinalizedGroups(bestConfiguration.Groups, actorsWithRealAssignments)); }
internal static List <TrialGroupConfiguration> GeneratePossibilities(List <CharacterGroup> characterGroups, ref int numberOfMaleNarratorGroups, ref int numberOfFemaleNarratorGroups, List <CharacterDetail> includedCharacterDetails, Project project) { var list = new List <TrialGroupConfiguration>(2); var availableAdultGroups = GetGroupsAvailableForNarratorOrExtraBiblical(characterGroups); var availableMaleGroups = availableAdultGroups.Where(g => g.VoiceActor.Gender == ActorGender.Male).ToList(); var availableFemaleGroups = availableAdultGroups.Where(g => g.VoiceActor.Gender == ActorGender.Female).ToList(); numberOfMaleNarratorGroups = Math.Min(numberOfMaleNarratorGroups, availableMaleGroups.Count); numberOfFemaleNarratorGroups = Math.Min(numberOfFemaleNarratorGroups, availableFemaleGroups.Count); if (numberOfMaleNarratorGroups + numberOfFemaleNarratorGroups == 0) { numberOfMaleNarratorGroups = 1; } int numberOfExtraBiblicalGroups = Math.Min(1, includedCharacterDetails.Count(c => CharacterVerseData.IsCharacterStandard(c.CharacterId, false))); if (availableMaleGroups.Count >= Math.Max(Math.Min(1, numberOfExtraBiblicalGroups), numberOfMaleNarratorGroups)) { list.Add(new TrialGroupConfiguration(characterGroups, numberOfMaleNarratorGroups, numberOfFemaleNarratorGroups, Math.Min(1, numberOfExtraBiblicalGroups), 0, project, includedCharacterDetails)); } if (numberOfExtraBiblicalGroups > 0 && availableFemaleGroups.Count >= Math.Max(1, numberOfFemaleNarratorGroups)) { list.Add(new TrialGroupConfiguration(characterGroups, numberOfMaleNarratorGroups, numberOfFemaleNarratorGroups, 0, numberOfExtraBiblicalGroups, project, includedCharacterDetails)); } if (!list.Any()) { list.Add(new TrialGroupConfiguration(characterGroups, numberOfMaleNarratorGroups, numberOfFemaleNarratorGroups, numberOfExtraBiblicalGroups, 0, project, includedCharacterDetails)); numberOfMaleNarratorGroups = list[0].NarratorGroups.Count(g => g.VoiceActor.Gender == ActorGender.Male); numberOfFemaleNarratorGroups = list[0].NarratorGroups.Count(g => g.VoiceActor.Gender == ActorGender.Female); Debug.Assert(numberOfMaleNarratorGroups + numberOfFemaleNarratorGroups == 1); } return(list); }
/// <summary> /// Gets whether the specified block represents Scripture text. (Only Scripture blocks can have their /// character/delivery changed. Book titles, chapters, and section heads have characters assigned /// programmatically and cannot be changed.) /// </summary> public bool GetIsBlockScripture(Block block) { return(!CharacterVerseData.IsCharacterStandard(block.CharacterId, false)); }
private bool IsRelevant(Block block) { if (block.MultiBlockQuote == MultiBlockQuote.Continuation || block.MultiBlockQuote == MultiBlockQuote.ChangeOfDelivery) { return(false); } if ((Mode & BlocksToDisplay.ExcludeUserConfirmed) > 0 && block.UserConfirmed) { return(false); } if ((Mode & BlocksToDisplay.NeedAssignments) > 0) { return(block.UserConfirmed || block.CharacterIsUnclear()); } if ((Mode & BlocksToDisplay.AllExpectedQuotes) > 0) { if (!GetIsBlockScripture(block)) { return(false); } return(ControlCharacterVerseData.Singleton.GetCharacters(CurrentBookId, block.ChapterNumber, block.InitialStartVerseNumber, block.LastVerse, versification: Versification).Any(c => c.IsExpected)); } if ((Mode & BlocksToDisplay.MissingExpectedQuote) > 0) { if (block.IsQuote || CharacterVerseData.IsCharacterStandard(block.CharacterId, false)) { return(false); } IEnumerable <BCVRef> versesWithPotentialMissingQuote = ControlCharacterVerseData.Singleton.GetCharacters(CurrentBookId, block.ChapterNumber, block.InitialStartVerseNumber, block.LastVerse, versification: Versification).Where(c => c.IsExpected).Select(c => c.BcvRef); if (!versesWithPotentialMissingQuote.Any()) { return(false); } foreach (BCVRef verse in versesWithPotentialMissingQuote) { if (m_navigator.PeekBackwardWithinBookWhile(b => b.ChapterNumber == verse.Chapter && b.LastVerse == verse.Verse).All(b => !b.IsQuote) && m_navigator.PeekForwardWithinBookWhile(b => b.ChapterNumber == verse.Chapter && b.InitialStartVerseNumber == verse.Verse).All(b => !b.IsQuote)) { return(true); } } return(false); } if ((Mode & BlocksToDisplay.MoreQuotesThanExpectedSpeakers) > 0) { if (!block.IsQuote) { return(false); } var expectedSpeakers = ControlCharacterVerseData.Singleton.GetCharacters(CurrentBookId, block.ChapterNumber, block.InitialStartVerseNumber, block.InitialEndVerseNumber, versification: Versification).Distinct(new CharacterEqualityComparer()).Count(); var actualquotes = 1; // this is the quote represented by the given block. if (actualquotes > expectedSpeakers) { return(true); } // Check surrounding blocks to count quote blocks for same verse. actualquotes += m_navigator.PeekBackwardWithinBookWhile(b => b.ChapterNumber == block.ChapterNumber && b.InitialStartVerseNumber == block.InitialStartVerseNumber) .Count(b => b.IsQuote && (b.MultiBlockQuote == MultiBlockQuote.Start || b.MultiBlockQuote == MultiBlockQuote.None)); if (actualquotes > expectedSpeakers) { return(true); } actualquotes += m_navigator.PeekForwardWithinBookWhile(b => b.ChapterNumber == block.ChapterNumber && b.InitialStartVerseNumber == block.InitialStartVerseNumber) .Count(b => b.IsQuote && (b.MultiBlockQuote == MultiBlockQuote.Start || b.MultiBlockQuote == MultiBlockQuote.None)); return(actualquotes > expectedSpeakers); } if ((Mode & BlocksToDisplay.AllScripture) > 0) { return(GetIsBlockScripture(block)); } if ((Mode & BlocksToDisplay.AllQuotes) > 0) { return(block.IsQuote); } return(false); }
public CastSizePlanningViewModel(Project project) { m_project = project; var prefs = m_project.CharacterGroupGenerationPreferences; m_narratorsOption = prefs.NarratorsOption; if (m_narratorsOption == NarratorsOption.Custom) { m_customMaleNarratorCount = prefs.NumberOfMaleNarrators; m_customFemaleNarratorCount = prefs.NumberOfFemaleNarrators; if (m_customMaleNarratorCount + m_customFemaleNarratorCount > MaximumNarratorsValue) { var remainingFemaleNarrators = MaximumNarratorsValue - MaleNarrators; m_customFemaleNarratorCount = Math.Max(remainingFemaleNarrators, 0); if (remainingFemaleNarrators < 0) { m_customMaleNarratorCount += remainingFemaleNarrators; } } } else { m_customMaleNarratorCount = 0; m_customFemaleNarratorCount = 0; } // if not yet specified, use "Narration by Author" if (m_narratorsOption == NarratorsOption.NotSet) { m_narratorsOption = NarratorsOption.NarrationByAuthor; } var smallCast = new CastSizeRowValues(2, 2, 0); int extraCharacterCount = 0; foreach (var bookId in m_project.IncludedBooks.Where(b => !b.SingleVoice).Select(b => b.BookId)) { extraCharacterCount = 1; // OT numbers are based on actual generation from Kuna San Blas project // NT numbers are based on actual generation from Acholi project switch (bookId) { case "GEN": smallCast.Male = Math.Max(smallCast.Male, 9); smallCast.Female = 3; break; case "EXO": smallCast.Male = Math.Max(smallCast.Male, 6); smallCast.Female = 3; break; case "LEV": smallCast.Male = Math.Max(smallCast.Male, 3); break; case "NUM": smallCast.Male = Math.Max(smallCast.Male, 8); break; case "DEU": smallCast.Male = Math.Max(smallCast.Male, 2); break; case "JOS": smallCast.Male = Math.Max(smallCast.Male, 7); break; case "JDG": smallCast.Male = Math.Max(smallCast.Male, 8); break; case "RUT": smallCast.Male = Math.Max(smallCast.Male, 3); smallCast.Female = 4; break; case "1SA": smallCast.Male = Math.Max(smallCast.Male, 11); break; case "2SA": smallCast.Male = Math.Max(smallCast.Male, 12); break; case "1KI": smallCast.Male = Math.Max(smallCast.Male, 10); break; case "2KI": smallCast.Male = Math.Max(smallCast.Male, 9); break; case "1CH": smallCast.Male = Math.Max(smallCast.Male, 5); break; case "2CH": smallCast.Male = Math.Max(smallCast.Male, 9); break; case "EZR": smallCast.Male = Math.Max(smallCast.Male, 5); break; case "NEH": smallCast.Male = Math.Max(smallCast.Male, 7); break; case "EST": smallCast.Male = Math.Max(smallCast.Male, 6); break; case "JOB": smallCast.Male = Math.Max(smallCast.Male, 7); break; case "PSA": smallCast.Male = Math.Max(smallCast.Male, 3); break; case "PRO": smallCast.Male = Math.Max(smallCast.Male, 0); break; case "ECC": smallCast.Male = Math.Max(smallCast.Male, 1); break; case "SNG": smallCast.Male = Math.Max(smallCast.Male, 2); break; case "ISA": smallCast.Male = Math.Max(smallCast.Male, 6); break; case "JER": smallCast.Male = Math.Max(smallCast.Male, 9); break; case "LAM": smallCast.Male = Math.Max(smallCast.Male, 1); break; case "EZK": smallCast.Male = Math.Max(smallCast.Male, 4); break; case "DAN": smallCast.Male = Math.Max(smallCast.Male, 5); break; case "HOS": smallCast.Male = Math.Max(smallCast.Male, 2); break; case "JOL": smallCast.Male = Math.Max(smallCast.Male, 2); break; case "AMO": smallCast.Male = Math.Max(smallCast.Male, 4); break; case "OBA": smallCast.Male = Math.Max(smallCast.Male, 1); break; case "JON": smallCast.Male = Math.Max(smallCast.Male, 4); break; case "MIC": smallCast.Male = Math.Max(smallCast.Male, 3); break; case "NAM": smallCast.Male = Math.Max(smallCast.Male, 1); break; case "HAB": smallCast.Male = Math.Max(smallCast.Male, 1); break; case "ZEP": smallCast.Male = Math.Max(smallCast.Male, 1); break; case "HAG": smallCast.Male = Math.Max(smallCast.Male, 2); break; case "ZEC": smallCast.Male = Math.Max(smallCast.Male, 5); break; case "MAL": smallCast.Male = Math.Max(smallCast.Male, 1); break; //// New Testament case "MAT": smallCast.Male = Math.Max(smallCast.Male, 10); break; case "MRK": smallCast.Male = Math.Max(smallCast.Male, 12); break; case "LUK": smallCast.Male = Math.Max(smallCast.Male, 13); break; case "JHN": smallCast.Male = Math.Max(smallCast.Male, 10); break; case "ACT": smallCast.Male = Math.Max(smallCast.Male, 13); break; case "ROM": smallCast.Male = Math.Max(smallCast.Male, 2); break; case "1CO": smallCast.Male = Math.Max(smallCast.Male, 5); break; case "2CO": smallCast.Male = Math.Max(smallCast.Male, 3); break; case "GAL": smallCast.Male = Math.Max(smallCast.Male, 3); break; case "EPH": smallCast.Male = Math.Max(smallCast.Male, 0); break; case "PHP": smallCast.Male = Math.Max(smallCast.Male, 0); break; case "COL": smallCast.Male = Math.Max(smallCast.Male, 1); break; case "1TH": smallCast.Male = Math.Max(smallCast.Male, 0); break; case "2TH": smallCast.Male = Math.Max(smallCast.Male, 0); break; case "1TI": smallCast.Male = Math.Max(smallCast.Male, 0); break; case "2TI": smallCast.Male = Math.Max(smallCast.Male, 0); break; case "TIT": smallCast.Male = Math.Max(smallCast.Male, 1); break; case "PHM": smallCast.Male = Math.Max(smallCast.Male, 0); break; case "HEB": switch (m_project.DramatizationPreferences.ScriptureQuotationsShouldBeSpokenBy) { case DramatizationOption.DedicatedCharacter: smallCast.Male = Math.Max(smallCast.Male, 2); break; case DramatizationOption.DefaultCharacter: smallCast.Male = Math.Max(smallCast.Male, 4); // Not sure if 4 is correct break; case DramatizationOption.Narrator: smallCast.Male = Math.Max(smallCast.Male, 1); break; } break; case "JAS": smallCast.Male = Math.Max(smallCast.Male, 2); break; case "1PE": smallCast.Male = Math.Max(smallCast.Male, 0); break; case "2PE": smallCast.Male = Math.Max(smallCast.Male, 2); break; case "1JN": smallCast.Male = Math.Max(smallCast.Male, 0); break; case "2JN": smallCast.Male = Math.Max(smallCast.Male, 0); break; case "3JN": smallCast.Male = Math.Max(smallCast.Male, 0); break; case "JUD": smallCast.Male = Math.Max(smallCast.Male, 3); break; case "REV": smallCast.Male = Math.Max(smallCast.Male, 15); break; } } IReadOnlyDictionary <string, CharacterDetail> characterDetails = Project.AllCharacterDetailDictionary; int maleCharacterCount = 0; int femaleCharacterCount = 0; int childCharacterCount = 0; foreach (var character in Project.AllCharacterIds.Where(c => !CharacterVerseData.IsCharacterStandard(c))) { CharacterDetail characterInfo; try { characterInfo = characterDetails[character]; } catch (KeyNotFoundException e) { throw new KeyNotFoundException(String.Format("Unable to find details for character {0}", character), e); } if (characterInfo.Age == CharacterAge.Child) { childCharacterCount++; } else { if (characterInfo.Gender == CharacterGender.Female || characterInfo.Gender == CharacterGender.PreferFemale) { femaleCharacterCount++; } else { maleCharacterCount++; } } } smallCast.Male = Math.Min(maleCharacterCount, smallCast.Male); smallCast.Male += extraCharacterCount; smallCast.Female = Math.Min(femaleCharacterCount, smallCast.Female); smallCast.Child = Math.Min(1, childCharacterCount); if (smallCast.Female == 0) { if ((m_project.DramatizationPreferences.BookIntroductionsDramatization == ExtraBiblicalMaterialSpeakerOption.FemaleActor) || (m_project.DramatizationPreferences.SectionHeadDramatization == ExtraBiblicalMaterialSpeakerOption.FemaleActor) || (m_project.DramatizationPreferences.BookTitleAndChapterDramatization == ExtraBiblicalMaterialSpeakerOption.FemaleActor)) { smallCast.Female = 1; } } var largeCast = new CastSizeRowValues(smallCast.Male * 2, Math.Min(8, femaleCharacterCount), Math.Min(4, childCharacterCount)); if (largeCast.Male > 10) { largeCast.Male = Math.Min(39, largeCast.Male); } largeCast.Male = Math.Min(maleCharacterCount + extraCharacterCount, largeCast.Male); m_baseRowValues[CastSizeOption.Small] = smallCast; m_baseRowValues[CastSizeOption.Recommended] = new CastSizeRowValues( (int)Math.Ceiling((double)(smallCast.Male + largeCast.Male) / 2), (int)Math.Ceiling((double)(smallCast.Female + largeCast.Female) / 2), (int)Math.Ceiling((double)(smallCast.Child + largeCast.Child) / 2)); m_baseRowValues[CastSizeOption.Large] = largeCast; if (prefs.NumberOfMaleActors == 0 && prefs.NumberOfFemaleActors == 0 && prefs.NumberOfChildActors == 0) { m_updatedCustomActorCounts = GetCastSizeRowValues(CastSizeOption.Recommended); } m_updatedCustomActorCounts = new CastSizeRowValues(prefs.NumberOfMaleActors, prefs.NumberOfFemaleActors, prefs.NumberOfChildActors); }