/// <summary> /// Queries the vocabulary according to the specified criteria and returns a random match. /// </summary> /// <param name="rng">The random number generator to randomize the match with.</param> /// <param name="query">The search criteria to use.</param> /// <returns></returns> public string Query(RNG rng, Query query) { Dictionary wordList; return !_wordLists.TryGetValue(query.Name, out wordList) ? "MISSINGDIC" : wordList.Query(rng, query); }
private static bool DoQuery(Interpreter interpreter, SourceReader reader, State state) { var first = reader.ReadToken(); reader.SkipSpace(); var namesub = reader.Read(TokenType.Text, "list name").Split(new[] { '.' }, 2).ToArray(); var q = new Query(namesub[0].Value.Trim(), namesub.Length == 2 ? namesub[1].Value : "", "", reader.Take(TokenType.Dollar), null, null); Token<TokenType> token = null; // Class filter list. Not initialized unless class filters actually exist. List<Tuple<bool, string>> cfList = null; while (true) { if (reader.Take(TokenType.Hyphen)) { // Initialize the filter list. (cfList ?? (cfList = new List<Tuple<bool, string>>())).Clear(); do { bool notin = reader.Take(TokenType.Exclamation); if (notin && q.Exclusive) throw new ProcessusException(reader.Source, reader.PrevToken, "Cannot use the '!' modifier on exclusive class filters."); cfList.Add(Tuple.Create(!notin, reader.Read(TokenType.Text, "class identifier").Value.Trim())); } while (reader.Take(TokenType.Pipe)); q.ClassFilters.Add(cfList.ToArray()); } else if (reader.Take(TokenType.Question)) { token = reader.Read(TokenType.Regex, "regex"); q.RegexFilters.Add(Tuple.Create(true, Util.ParseRegex(token.Value))); } else if (reader.Take(TokenType.Without)) { token = reader.Read(TokenType.Regex, "regex"); q.RegexFilters.Add(Tuple.Create(false, Util.ParseRegex(token.Value))); } else if (reader.Take(TokenType.DoubleColon)) { token = reader.Read(TokenType.Text, "carrier name"); q.Carrier = token.Value.Trim(); if (!reader.Take(TokenType.RightAngle)) { throw new ProcessusException(reader.Source, token, "Expected '>' after carrier. (The carrier should be your last query argument!)"); } break; } else if (reader.Take(TokenType.RightAngle)) { break; } else if (!reader.SkipSpace()) { var t = !reader.End ? reader.ReadToken() : null; throw new ProcessusException(reader.Source, t, t == null ? "Unexpected end-of-file in query." : "Unexpected token '" + t.Value + "' in query."); } } interpreter.Print(interpreter.Engine.Vocabulary.Query(interpreter.RNG, q)); return false; }
internal string Query(RNG rng, Query query) { var index = String.IsNullOrEmpty(query.Subtype) ? 0 : GetSubtypeIndex(query.Subtype); if (index == -1) { return "BAD_SUBTYPE"; } IEnumerable<DictionaryEntry> pool = _words; pool = query.Exclusive ? pool.Where(e => e.Classes.Any() && e.Classes.All(c => query.ClassFilters.Any(set => set.Any(t => t.Item2 == c)))) : pool.Where(e => query.ClassFilters.All(set => set.Any(t => t.Item1 == (e.Classes.Contains(t.Item2))))); pool = query.RegexFilters.Aggregate(pool, (current, regex) => current.Where(e => regex.Item1 == regex.Item2.IsMatch(e.Values[index]))); if (!pool.Any()) { return "NOT_FOUND"; } int number = String.IsNullOrEmpty(query.Carrier) ? rng.Next(pool.Sum(e => e.Weight)) + 1 : rng.PeekAt(query.Carrier.Hash(), pool.Sum(e => e.Weight)); foreach (var e in pool) { if (number <= e.Weight) return e.Values[index]; number -= e.Weight; } return "NOT_FOUND"; }