private async Task SearchRecipe(SearchArguments a, Message message) { using (var db = new Database()) { Stat stat = a.RS3Stats.GetStatForName(a.Skill.ToString()); int levelDiff = RSUtil.ExpBetweenLevels(stat, a.Level); var dbLookup = new Stopwatch(); var queryBuild = new Stopwatch(); var upload = new Stopwatch(); var convertText = new Stopwatch(); queryBuild.Start(); var tempQuery = db.recipes .Where(r => r.Skill == (int)a.Skill) .Where(r => r.Level <= stat.Level) .Select(r => new Entity { Id = r.Id, Name = r.Name, Level = r.Level, Exp = r.Exp, ExpH = r.Exp * r.Units, Number = (int)Math.Ceiling(levelDiff / r.Exp), Cost = (db.outputs.Where(o => o.RecipeId == r.Id).Sum(o => o.Quantity * o.item.Price) - (db.inputs.Where(i => i.RecipeId == r.Id).Sum(i => i.Quantity * i.item.Price) + r.Extra)) * Math.Ceiling(levelDiff / r.Exp), Time = Math.Ceiling(levelDiff / r.Exp) / r.Units }); var firstOrder = a.Orders.First(); IOrderedQueryable <Entity> query = null; // Doing first sort switch (firstOrder) { case SearchArguments.Order.Expensive: query = tempQuery.OrderBy(r => r.Cost); break; case SearchArguments.Order.Fast: query = tempQuery.OrderBy(r => r.Time); break; case SearchArguments.Order.Cheap: query = tempQuery.OrderByDescending(r => r.Cost); break; case SearchArguments.Order.Slow: query = tempQuery.OrderByDescending(r => r.Time); break; case SearchArguments.Order.Name: query = tempQuery.OrderBy(r => r.Name); break; case SearchArguments.Order.Level: query = tempQuery.OrderBy(r => r.Level); break; } // Consecutive sort for (var i = 1; i < a.Orders.Count; i++) { switch (firstOrder) { case SearchArguments.Order.Expensive: query = query.ThenByDescending(r => r.Cost); break; case SearchArguments.Order.Fast: query = query.ThenBy(r => r.Time); break; case SearchArguments.Order.Cheap: query = query.ThenBy(r => r.Cost); break; case SearchArguments.Order.Slow: query = query.ThenByDescending(r => r.Time); break; case SearchArguments.Order.Name: query = query.ThenBy(r => r.Name); break; case SearchArguments.Order.Level: query = query.ThenBy(r => r.Level); break; } } // Stopping query builder timer queryBuild.Stop(); var pages = Math.Ceiling((decimal)await query.LongCountAsync() / a.Limit); // Starting db lookup dbLookup.Start(); var recipes = await query.Skip((a.Page - 1) *a.Limit) .Take(a.Limit) .ToListAsync(); // END OF DB LOOKUP dbLookup.Stop(); if (!recipes.Any()) { await message.Channel.SendMessage("No recipes found."); return; } // Formatting Table table = new Table(); table.SetTitle($"{a.Skill} Recipes ({a.Page}/{pages})"); table.SetHeadings("Id", "Name", "Level", "Xp", "Xp/H", "Number", "Cost", "Time"); recipes.ForEach(r => table.AddRow( r.Id , r.Name , new Table.Column(r.Level, Table.Column.Alignment.Right) , new Table.Column(r.Exp.ToString("#,##0.##"), Table.Column.Alignment.Right) , new Table.Column(r.ExpH.ToString("#,##0.##"), Table.Column.Alignment.Right) , new Table.Column(r.Number.ToString("#,##0"), Table.Column.Alignment.Right) , new Table.Column(r.Cost.ToString("#,##0"), Table.Column.Alignment.Right) , new Table.Column(r.Time.ToFormattedTime(), Table.Column.Alignment.Right))); string @out = $"{table}"; // Outputing image if (a.Image) { var img = convertText.TimeTask(() => ImageUtil.ToImage(@out)); var link = await upload.TimeTaskAsync(async() => await ImageUtil.PostToImgur(img)); await message.Channel.SendMessage(link + "\n" + $"**Build Query**: {dbLookup.ElapsedMilliseconds}ms | " + $"**Query DB**: {queryBuild.Elapsed.Milliseconds}ms | " + $"**Convert Text**: {convertText.ElapsedMilliseconds}ms | " + $"**Upload Image**: {upload.ElapsedMilliseconds}ms"); } else { await message.Channel.SendMessage($"**Build Query**: {dbLookup.ElapsedMilliseconds}ms | " + $"**Query DB**: {queryBuild.Elapsed.Milliseconds}ms" + $"```{@out}```"); } } }