/// <summary> /// Determines if the specified dictionary entry passes the filter. /// </summary> /// <param name="entry">The entry to test.</param> /// <param name="exclusive">Specifies whether the search is exclusive.</param> /// <returns></returns> public bool Test(RantDictionaryEntry entry, bool exclusive = false) { return(exclusive ? _items.Any() == entry.GetClasses().Any() && entry.GetClasses().All(c => _items.Any(item => item.Any(rule => rule.ShouldMatch && rule.Class == c))) : !_items.Any() || _items.All(set => set.Any(rule => entry.ContainsClass(rule.Class) == rule.ShouldMatch))); }
private static RantPackage LoadOldPackage(EasyReader reader) { int numPatterns = reader.ReadInt32(); int numTables = reader.ReadInt32(); if (numPatterns < 0 || numTables < 0) { throw new InvalidDataException("File is corrupt."); } var pkg = new RantPackage(); // Patterns for (int i = 0; i < numPatterns; i++) { var name = reader.ReadString(); var code = reader.ReadString(); pkg.AddPattern(new RantPattern(name, RantPatternOrigin.String, code)); } // Tables for (int i = 0; i < numTables; i++) { var name = reader.ReadString(); var subs = reader.ReadStringArray(); int numEntries = reader.ReadInt32(); var hiddenClasses = reader.ReadStringArray(); var entries = new RantDictionaryEntry[numEntries]; for (int j = 0; j < numEntries; j++) { int weight = reader.ReadInt32(); bool flags = reader.ReadBoolean(); // unused int numTerms = reader.ReadInt32(); var terms = new RantDictionaryTerm[numTerms]; for (int k = 0; k < numTerms; k++) { var value = reader.ReadString(); var pron = reader.ReadString(); terms[k] = new RantDictionaryTerm(value, pron); } var classes = reader.ReadStringArray(); entries[j] = new RantDictionaryEntry(terms, classes, weight); } pkg.AddTable(new RantDictionaryTable(name, subs, entries, hiddenClasses)); } return(pkg); }
public static bool DivergesFrom(this RantDictionaryEntry a, RantDictionaryEntry b) { if (a == null || b == null) { return(false); } bool aNoneRequired = !a.GetRequiredClasses().Any(); bool bNoneRequired = !b.GetRequiredClasses().Any(); if (aNoneRequired && bNoneRequired) { return(true); // If both have no required classes, pass. } // One or both have required classes. // Remove B optionals from A required. var aRequired = a.GetRequiredClasses().Except(b.GetOptionalClasses()); // Remove A optionals from B required. var bRequired = b.GetRequiredClasses().Except(a.GetOptionalClasses()); // Both should be either empty, or differ by at least one class. return(aRequired.Except(bRequired).Any() || bRequired.Except(aRequired).Any()); }
public static bool RelatesWith(this RantDictionaryEntry a, RantDictionaryEntry b) { if (a == null || b == null) { return(false); } bool aNoneRequired = !a.GetRequiredClasses().Any(); bool bNoneRequired = !b.GetRequiredClasses().Any(); if (aNoneRequired && bNoneRequired) { return(true); // If both have no required classes, pass. } // One or both have required classes. // Remove B optionals from A required. var aRequired = a.GetRequiredClasses().Except(b.GetOptionalClasses()); // Remove A optionals from B required. var bRequired = b.GetRequiredClasses().Except(a.GetOptionalClasses()); // Both should share at least one class. return(aRequired.Intersect(bRequired).Any()); }
public static bool AssociatesWith(this RantDictionaryEntry a, RantDictionaryEntry b) { if (a == null || b == null) { return(false); } bool aNoneRequired = !a.GetRequiredClasses().Any(); bool bNoneRequired = !b.GetRequiredClasses().Any(); if (aNoneRequired && bNoneRequired) { return(true); // If both have no required classes, pass. } // One or both have required classes. // Remove B optionals from A required. var aRequired = a.GetRequiredClasses().Except(b.GetOptionalClasses()); // Remove A optionals from B required. var bRequired = b.GetRequiredClasses().Except(a.GetOptionalClasses()); // Both should be either empty, or have exactly the same classes. return(!aRequired.Except(bRequired).Any() && aRequired.Any() == bRequired.Any()); }
public override bool Test(RantDictionary dictionary, RantDictionaryTable table, RantDictionaryEntry entry, int termIndex, Query query) => TestAgainst(entry[termIndex].SyllableCount);
/// <summary> /// Loads a package from the specified stream and returns it as a RantPackage object. /// </summary> /// <param name="source">The stream to load the package data from.</param> /// <returns></returns> public static RantPackage Load(Stream source) { using (var reader = new EasyReader(source)) { var magic = Encoding.ASCII.GetString(reader.ReadBytes(4)); if (magic == OLD_MAGIC) { return(LoadOldPackage(reader)); } if (magic != MAGIC) { throw new InvalidDataException("File is corrupt."); } var package = new RantPackage(); var version = reader.ReadUInt32(); if (version != PACKAGE_VERSION) { throw new InvalidDataException("Invalid package version: " + version); } var compress = reader.ReadBoolean(); var size = reader.ReadInt32(); var data = reader.ReadBytes(size); if (compress) { data = EasyCompressor.Decompress(data); } var doc = BsonDocument.Read(data); var info = doc["info"]; if (info == null) { throw new InvalidDataException("Metadata is missing from package."); } package.Title = info["title"]; package.ID = info["id"]; package.Version = RantPackageVersion.Parse(info["version"]); package.Description = info["description"]; package.Authors = (string[])info["authors"]; package.Tags = (string[])info["tags"]; var deps = info["dependencies"]; if (deps != null && deps.IsArray) { for (int i = 0; i < deps.Count; i++) { var dep = deps[i]; var depId = dep["id"].Value; var depVersion = dep["version"].Value; bool depAllowNewer = (bool)dep["allow-newer"].Value; package.AddDependency(new RantPackageDependency(depId.ToString(), depVersion.ToString()) { AllowNewer = depAllowNewer }); } } var patterns = doc["patterns"]; if (patterns != null) { var names = patterns.Keys; foreach (string name in names) { package.AddPattern(new RantPattern(name, RantPatternOrigin.File, patterns[name])); } } var tables = doc["tables"]; if (tables != null) { var names = tables.Keys; foreach (string name in names) { var table = tables[name]; string tableName = table["name"]; string[] tableSubs = (string[])table["subs"]; string[] hiddenClasses = (string[])table["hidden"]; var entries = new List <RantDictionaryEntry>(); var entryList = table["entries"]; for (var i = 0; i < entryList.Count; i++) { var loadedEntry = entryList[i]; int weight = 1; if (loadedEntry.HasKey("weight")) { weight = (int)loadedEntry["weight"].Value; } string[] requiredClasses = (string[])loadedEntry["classes"]; string[] optionalClasses = (string[])loadedEntry["optional_classes"]; var terms = new List <RantDictionaryTerm>(); var termList = loadedEntry["terms"]; for (var j = 0; j < termList.Count; j++) { var t = new RantDictionaryTerm(termList[j]["value"], termList[j]["pron"]); terms.Add(t); } var entry = new RantDictionaryEntry( terms.ToArray(), requiredClasses.Concat(optionalClasses.Select(x => x + "?")), weight ); entries.Add(entry); } var rantTable = new RantDictionaryTable( tableName, tableSubs, entries, hiddenClasses ); package.AddTable(rantTable); } } return(package); } }
internal RantDictionaryEntry GetEntry(Carrier carrier, int subtypeIndex, IEnumerable <RantDictionaryEntry> pool, RNG rng, bool weighted) { if (carrier == null) { return(pool.PickEntry(rng, weighted)); } RantDictionaryEntry result = null; // Handle match carriers foreach (string match in carrier.GetComponentsOfType(CarrierComponentType.Match)) { if (_matchTable.TryGetValue(match, out result)) { return(result); } } // Handle associative carriers foreach (string assoc in carrier.GetComponentsOfType(CarrierComponentType.Associative)) { if (_assocTable.TryGetValue(assoc, out result)) { pool = pool.Where(e => e.AssociatesWith(result)); } break; } // Handle match-associative carriers foreach (string massoc in carrier.GetComponentsOfType(CarrierComponentType.MatchAssociative)) { if (_matchTable.TryGetValue(massoc, out result)) { pool = pool.Where(e => e.AssociatesWith(result)); } break; } // Handle unique carriers foreach (string unique in carrier.GetComponentsOfType(CarrierComponentType.Unique)) { HashSet <RantDictionaryEntry> usedSet; if (!_uniqueTable.TryGetValue(unique, out usedSet)) { usedSet = _uniqueTable[unique] = new HashSet <RantDictionaryEntry>(); } pool = pool.Except(usedSet); } // Handle match-unique carriers foreach (string munique in carrier.GetComponentsOfType(CarrierComponentType.Unique)) { if (_matchTable.TryGetValue(munique, out result)) { pool = pool.Where(e => e != result); } } // Handle relational carriers foreach (string relate in carrier.GetComponentsOfType(CarrierComponentType.Relational)) { if (_assocTable.TryGetValue(relate, out result)) { pool = pool.Where(e => e.RelatesWith(result)); } } // Handle match-relational carriers foreach (string relate in carrier.GetComponentsOfType(CarrierComponentType.MatchRelational)) { if (_matchTable.TryGetValue(relate, out result)) { pool = pool.Where(e => e.RelatesWith(result)); } } // Handle dissociative carriers foreach (string relate in carrier.GetComponentsOfType(CarrierComponentType.Dissociative)) { if (_assocTable.TryGetValue(relate, out result)) { pool = pool.Where(e => !e.RelatesWith(result)); } } // Handle match-dissociative carriers foreach (string relate in carrier.GetComponentsOfType(CarrierComponentType.MatchDissociative)) { if (_matchTable.TryGetValue(relate, out result)) { pool = pool.Where(e => !e.RelatesWith(result)); } } // Handle divergent carriers foreach (string diverge in carrier.GetComponentsOfType(CarrierComponentType.Divergent)) { if (_assocTable.TryGetValue(diverge, out result)) { pool = pool.Where(e => e.DivergesFrom(result)); } } // Handle match-divergent carriers foreach (string diverge in carrier.GetComponentsOfType(CarrierComponentType.MatchDivergent)) { if (_matchTable.TryGetValue(diverge, out result)) { pool = pool.Where(e => e.DivergesFrom(result)); } } result = pool.PickEntry(rng, weighted); // Handle rhyme carrier foreach (string rhyme in carrier.GetComponentsOfType(CarrierComponentType.Rhyme)) { _ <RantDictionaryTerm, HashSet <RantDictionaryEntry> > rhymeState; if (!_rhymeTable.TryGetValue(rhyme, out rhymeState)) { result = pool .Where(e => !Util.IsNullOrWhiteSpace(e[subtypeIndex].Pronunciation)) .PickEntry(rng, weighted); if (result == null) { return(null); } _rhymeTable[rhyme] = _.Create(result[subtypeIndex], new HashSet <RantDictionaryEntry>(new[] { result })); break; } result = pool.Except(rhymeState.Item2) .Where(e => !Util.IsNullOrWhiteSpace(e[subtypeIndex].Pronunciation) && Rhymer.Rhyme(rhymeState.Item1, e[subtypeIndex])) .PickEntry(rng, weighted); if (result != null) { rhymeState.Item2.Add(result); } break; // Ignore any extra rhyme carriers } if (result == null) { return(null); } foreach (string a in carrier.GetComponentsOfType(CarrierComponentType.Associative)) { if (!_assocTable.ContainsKey(a)) { _assocTable[a] = result; } } foreach (string a in carrier.GetComponentsOfType(CarrierComponentType.Dissociative)) { if (!_assocTable.ContainsKey(a)) { _assocTable[a] = result; } } foreach (string a in carrier.GetComponentsOfType(CarrierComponentType.Divergent)) { if (!_assocTable.ContainsKey(a)) { _assocTable[a] = result; } } foreach (string a in carrier.GetComponentsOfType(CarrierComponentType.Relational)) { if (!_assocTable.ContainsKey(a)) { _assocTable[a] = result; } } foreach (string unique in carrier.GetComponentsOfType(CarrierComponentType.Unique)) { _uniqueTable[unique].Add(result); } foreach (string match in carrier.GetComponentsOfType(CarrierComponentType.Match)) { _matchTable[match] = result; break; } return(result); }
public override bool Test(RantDictionary dictionary, RantDictionaryTable table, RantDictionaryEntry entry, int termIndex, Query query) => Regex.IsMatch(entry[termIndex].Value) == Outcome;
/// <summary> /// Determines if the specified dictionary entry passes the filter. /// </summary> /// <param name="dictionary">The dictionary being queried.</param> /// <param name="table">The table being queried.</param> /// <param name="entry">The entry to test.</param> /// <param name="termIndex">The index of the term requested by the query.</param> /// <param name="query">The originating query.</param> /// <returns></returns> public abstract bool Test(RantDictionary dictionary, RantDictionaryTable table, RantDictionaryEntry entry, int termIndex, Query query);
public override bool Test(RantDictionary dictionary, RantDictionaryTable table, RantDictionaryEntry entry, int termIndex, Query query) { bool match = query.Exclusive ? _items.Any() == entry.GetClasses().Any() && entry.GetClasses().All(c => _items.Any(item => item.Any(rule => rule.ShouldMatch && rule.Class == c))) : !_items.Any() || _items.All(set => set.Any(rule => entry.ContainsClass(rule.Class) == rule.ShouldMatch)); // Enumerate hidden classes that aren't manually exposed or explicitly allowed by the filter var hidden = table.HiddenClasses.Where(c => !AllowsClass(c)).Except(dictionary.IncludedHiddenClasses); return(match && !hidden.Any(entry.ContainsClass)); }