/// <summary> /// Unpacks this applying language rules to expand and add articles/verbs where needed /// </summary> /// <param name="overridingContext">The full lexical context</param> /// <returns>A long description</returns> public IEnumerable <ILexica> Unpack(MessagingType sensoryType, short strength, LexicalContext overridingContext = null) { if (overridingContext != null) { IGlobalConfig globalConfig = ConfigDataCache.Get <IGlobalConfig>(new ConfigDataCacheKey(typeof(IGlobalConfig), "LiveSettings", ConfigDataType.GameWorld)); //Sentence must maintain the same language, tense and personage Context.Language = overridingContext.Language ?? Context.Language ?? globalConfig.BaseLanguage; Context.Tense = overridingContext.Tense; Context.Perspective = overridingContext.Perspective; Context.Elegance = overridingContext.Elegance; Context.Severity = overridingContext.Severity; Context.Quality = overridingContext.Quality; } ILexica newLex = Mutate(sensoryType, strength); foreach (IWordRule wordRule in Context.Language.WordRules.Where(rul => rul.Matches(newLex)) .OrderByDescending(rul => rul.RuleSpecificity())) { if (wordRule.NeedsArticle && (!wordRule.WhenPositional || Context.Position != LexicalPosition.None) && !newLex.Modifiers.Any(mod => (mod.Type == LexicalType.Article && !wordRule.WhenPositional && mod.Context.Position == LexicalPosition.None) || (mod.Type == LexicalType.Preposition && wordRule.WhenPositional && mod.Context.Position != LexicalPosition.None))) { LexicalContext articleContext = Context.Clone(); //Make it determinant if the word is plural articleContext.Determinant = Context.Plural || articleContext.Determinant; IDictata article = null; if (wordRule.SpecificAddition != null) { article = wordRule.SpecificAddition; } else { article = Thesaurus.GetWord(articleContext, wordRule.WhenPositional ? LexicalType.Preposition : LexicalType.Article); } if (article != null && !newLex.Modifiers.Any(lx => article.Name.Equals(lx.Phrase, StringComparison.InvariantCultureIgnoreCase))) { ILexica newArticle = newLex.TryModify(wordRule.WhenPositional ? LexicalType.Preposition : LexicalType.Article , GrammaticalType.Descriptive, article.Name, false); if (!wordRule.WhenPositional) { newArticle.Context.Position = LexicalPosition.None; } } } else if (wordRule.SpecificAddition != null && !newLex.Modifiers.Any(lx => wordRule.SpecificAddition.Equals(lx.GetDictata()))) { newLex.TryModify(wordRule.SpecificAddition.WordType, GrammaticalType.Descriptive, wordRule.SpecificAddition.Name); } if (!string.IsNullOrWhiteSpace(wordRule.AddPrefix) && !newLex.Phrase.StartsWith(wordRule.AddPrefix)) { newLex.Phrase = string.Format("{0}{1}", wordRule.AddPrefix, newLex.Phrase.Trim()); } if (!string.IsNullOrWhiteSpace(wordRule.AddSuffix) && !newLex.Phrase.EndsWith(wordRule.AddSuffix)) { newLex.Phrase = string.Format("{1}{0}", wordRule.AddSuffix, newLex.Phrase.Trim()); } } //Placement ordering List <Tuple <ILexica, int> > modifierList = new List <Tuple <ILexica, int> > { new Tuple <ILexica, int>(newLex, 0) }; //modification rules ordered by specificity List <ILexica> currentModifiers = new List <ILexica>(newLex.Modifiers); foreach (ILexica modifier in currentModifiers) { foreach (IWordPairRule wordRule in Context.Language.WordPairRules.Where(rul => rul.Matches(newLex, modifier)) .OrderByDescending(rul => rul.RuleSpecificity())) { if (wordRule.NeedsArticle && (!wordRule.WhenPositional || Context.Position != LexicalPosition.None) && !newLex.Modifiers.Any(mod => (mod.Type == LexicalType.Article && !wordRule.WhenPositional && mod.Context.Position == LexicalPosition.None) || (mod.Type == LexicalType.Preposition && wordRule.WhenPositional && mod.Context.Position != LexicalPosition.None))) { LexicalContext articleContext = Context.Clone(); //Make it determinant if the word is plural articleContext.Determinant = Context.Plural || articleContext.Determinant; IDictata article = null; if (wordRule.SpecificAddition != null) { article = wordRule.SpecificAddition; } else { article = Thesaurus.GetWord(articleContext, wordRule.WhenPositional ? LexicalType.Preposition : LexicalType.Article); } if (article != null && !newLex.Modifiers.Any(lx => article.Name.Equals(lx.Phrase, StringComparison.InvariantCultureIgnoreCase))) { ILexica newArticle = newLex.TryModify(wordRule.WhenPositional ? LexicalType.Preposition : LexicalType.Article , GrammaticalType.Descriptive, article.Name, false); if (!wordRule.WhenPositional) { newArticle.Context.Position = LexicalPosition.None; } } } else if (wordRule.SpecificAddition != null && !newLex.Modifiers.Any(lx => wordRule.SpecificAddition.Equals(lx.GetDictata()))) { newLex.TryModify(wordRule.SpecificAddition.WordType, GrammaticalType.Descriptive, wordRule.SpecificAddition.Name); } if (!string.IsNullOrWhiteSpace(wordRule.AddPrefix) && !newLex.Phrase.StartsWith(wordRule.AddPrefix)) { newLex.Phrase = string.Format("{0}{1}", wordRule.AddPrefix, newLex.Phrase.Trim()); } if (!string.IsNullOrWhiteSpace(wordRule.AddSuffix) && !newLex.Phrase.EndsWith(wordRule.AddSuffix)) { newLex.Phrase = string.Format("{1}{0}", wordRule.AddSuffix, newLex.Phrase.Trim()); } } } foreach (ILexica modifier in newLex.Modifiers) { IWordPairRule rule = Context.Language.WordPairRules.OrderByDescending(rul => rul.RuleSpecificity()) .FirstOrDefault(rul => rul.Matches(newLex, modifier)); if (rule != null) { int i = 0; foreach (ILexica subModifier in modifier.Unpack(sensoryType, strength, overridingContext ?? Context).Distinct()) { modifierList.Add(new Tuple <ILexica, int>(subModifier, rule.ModificationOrder + i++)); } } } return(modifierList.OrderBy(tup => tup.Item2).Select(tup => tup.Item1)); }