Ejemplo n.º 1
0
 /// <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)));
 }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        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());
        }
Ejemplo n.º 4
0
        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());
        }
Ejemplo n.º 5
0
        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());
        }
Ejemplo n.º 6
0
 public override bool Test(RantDictionary dictionary, RantDictionaryTable table, RantDictionaryEntry entry, int termIndex, Query query) => TestAgainst(entry[termIndex].SyllableCount);
Ejemplo n.º 7
0
        /// <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);
            }
        }
Ejemplo n.º 8
0
        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);
        }
Ejemplo n.º 9
0
 public override bool Test(RantDictionary dictionary, RantDictionaryTable table, RantDictionaryEntry entry, int termIndex, Query query) => Regex.IsMatch(entry[termIndex].Value) == Outcome;
Ejemplo n.º 10
0
 /// <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);
Ejemplo n.º 11
0
        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));
        }