public object LeppieExpandedWildcards()
        {
            var allTags           = WebApiApplication.TagServer.Value.AllTags;
            var leppieWildcards   = WebApiApplication.LeppieWildcards.Value;
            var nGrams            = WebApiApplication.NGrams.Value;
            var timer             = Stopwatch.StartNew();
            var expandedWildcards = WildcardProcessor.ExpandTagsNGrams(allTags, leppieWildcards, nGrams)
                                    .OrderBy(t => t)
                                    .ToList();

            timer.Stop();

            return(new
            {
                ElapsedMilliseconds = timer.Elapsed.TotalMilliseconds.ToString("N2"),
                CountBeforeExpansion = leppieWildcards.Count,
                ExpandedCount = expandedWildcards.Count,
                ExpandedWildcards = expandedWildcards
            });
        }
        public object Expand()
        {
            var queryStringPairs   = HttpContext.Current.Request.QueryString.ToPairs();
            var wildcards          = QueryStringProcessor.GetString(queryStringPairs, "wildcards", "");
            var useLeppieWildcards = QueryStringProcessor.GetBool(queryStringPairs, "useLeppieWildcards", false);

            var timer = Stopwatch.StartNew();

            var wildcardExpansionTimer = Stopwatch.StartNew();
            var initialWildcards       = useLeppieWildcards ? WebApiApplication.LeppieWildcards.Value : wildcards.Split(',').ToList();
            var allTags      = WebApiApplication.TagServer.Value.AllTags;
            var nGrams       = WebApiApplication.NGrams.Value;
            var expandedTags = WildcardProcessor.ExpandTagsNGrams(allTags, initialWildcards, nGrams);

            wildcardExpansionTimer.Stop();

            //var bitMapTimer = Stopwatch.StartNew();
            //var bitMapIndex = WebApiApplication.TagServer.Value.CreateBitMapIndexForExcludedTags(expandedTags, QueryType.Score);
            //bitMapTimer.Stop();

            timer.Stop();

            return(new
            {
                TotalElapsedMilliseconds = timer.Elapsed.TotalMilliseconds.ToString("N2") + " ms",
                WildcardExpansionMilliseconds = wildcardExpansionTimer.Elapsed.TotalMilliseconds.ToString("N2") + " ms",
                //BitMapCreationMilliseconds = bitMapTimer.Elapsed.TotalMilliseconds.ToString("N2") + " ms",
                //QuestionsIncludingExpandedTags = ((ulong)WebApiApplication.TagServer.Value.Questions.Count - bitMapIndex.GetCardinality()).ToString("N0"),
                InitialWildcards = useLeppieWildcards ? "USING Leppie's Wildcards, list to big to print!!!" : String.Join(" - ", initialWildcards),
                ExpandedTagsCount = expandedTags.Count.ToString("N0"),
                ExpandedWildcardCount = initialWildcards.Where(w => w.Contains('*'))
                                        .ToDictionary(w => w, w => WildcardProcessor.ExpandTagsNGrams(allTags, new List <string>(new[] { w }), nGrams).Count)
                                        .OrderByDescending(g => g.Value)
                                        .ThenBy(g => g.Key)
                                        .ToDictionary(g => g.Key, g => g.Value),
                ExpandedWildcard = initialWildcards.Where(w => w.Contains('*'))
                                   .ToDictionary(w => w, w => WildcardProcessor.ExpandTagsNGrams(allTags, new List <string>(new[] { w }), nGrams))
                                   .OrderBy(g => g.Key)
                                   .ToDictionary(g => g.Key, g => g.Value),
            });
        }
        public object Query(string tag)
        {
            // This timer must include everything!! (i.e processing the wildcards and doing the query!!)
            var timer = Stopwatch.StartNew();

            var queryInfo = GetQueryInfo(HttpContext.Current.Request.QueryString.ToPairs(), tag);
            var tagServer = WebApiApplication.TagServer.Value;

            var     leppieWildcards    = WebApiApplication.LeppieWildcards.Value;
            HashSet leppieExpandedTags = null;
            var     tagExpansionTimer  = new Stopwatch();

            if (queryInfo.UseLeppieExclusions)
            {
                var allTags = tagServer.AllTags;
                var nGrams  = WebApiApplication.NGrams.Value;
                tagExpansionTimer  = Stopwatch.StartNew();
                leppieExpandedTags = WildcardProcessor.ExpandTagsNGrams(allTags, leppieWildcards, nGrams);
                tagExpansionTimer.Stop();
            }

            Stopwatch exclusionBitMapTimer         = new Stopwatch();
            EwahCompressedBitArray exclusionBitMap = null;

            if (queryInfo.UseBitMapIndexes && queryInfo.UseLeppieExclusions)
            {
                exclusionBitMapTimer.Start();
                exclusionBitMap = tagServer.CreateBitMapIndexForExcludedTags(leppieExpandedTags, queryInfo.Type);
                exclusionBitMapTimer.Stop();
            }

            QueryResult result;
            var         queryTimer = Stopwatch.StartNew();

            if (queryInfo.UseBitMapIndexes)
            {
                result = tagServer.ComparisionQueryBitMapIndex(queryInfo, exclusionBitMap);
            }
            else if (queryInfo.UseLinq)
            {
                result = tagServer.ComparisonQuery(queryInfo, tagsToExclude: leppieExpandedTags);
            }
            else
            {
                result = tagServer.ComparisonQueryNoLINQ(queryInfo, tagsToExclude: leppieExpandedTags);
            }
            queryTimer.Stop();

            // Stop the overall timer, as we don't want to include the time taken to create DEBUG info in it
            timer.Stop();

            var jsonResults = new Dictionary <string, object>();

            jsonResults.Add("Statistics", GetStatistics(queryInfo, result, timer.Elapsed));
            if (queryInfo.DebugMode)
            {
                var debugInfo = GetDebugInfo(queryInfo, result,
                                             leppieWildcards, leppieExpandedTags,
                                             totalTime: timer.Elapsed,
                                             queryTime: queryTimer.Elapsed,
                                             tagsExpansionTime: tagExpansionTimer.Elapsed,
                                             exclusionBitMapTime: exclusionBitMapTimer.Elapsed);
                jsonResults.Add("DEBUGGING", debugInfo);
            }
            jsonResults.Add("Results", result.Questions);
            return(jsonResults);
        }