/// <summary> /// Handles the custom message. The message will have the query information /// </summary> /// <param name="activity">The activity.</param> /// <returns></returns> private static async Task <string> HandleCustomMessage(Activity activity) { //Get natural language processed by LUIS var luisResponse = await LUISMetalQueryClient.ParseUserInput(activity.Text); var responseMessage = string.Empty; switch (luisResponse.intents[0].intent) { case "Metal Sales": var showHelp = luisResponse.entities.Any(x => x.type == "help" || x.type == "greeting"); if (showHelp) { responseMessage = $"Hi I am **Metal Bot**, I can assist you with sales of Metal. {Environment.NewLine}You can ask me something like 'What is the average sale for 2010?' or 'What was the highest sale in USA,Widwest'. {Environment.NewLine}**Give me a try!** {Environment.NewLine}![logo](https://pbs.twimg.com/profile_images/803953567686131712/8qIowSgm_400x400.jpg)"; return(responseMessage); } // what is the lowest for gold in 20/10/2017 var metals = luisResponse.entities.Where(x => x.type == "metal").Select(x => x.entity).ToList(); var numbers = luisResponse.entities.Where(x => x.type == "builtin.number").Select(x => x.resolution.value).ToList(); var dates = luisResponse.entities.Where(x => x.type == "builtin.datetime.date").Select(x => x.resolution.date).ToList(); var parsedDates = dates.Select(x => x.Contains('-') ? DateTime.Parse(x) : new DateTime(int.Parse(x), 1, 1)).ToList(); var isPriceOriented = luisResponse.entities.Any(x => x.type == "cost"); var requestsLowest = luisResponse.entities.Any(x => x.type == "lowest"); var requestsHighest = luisResponse.entities.Any(x => x.type == "highest"); DateTime maxDate; DateTime minDate; using (var dataContext = new botEntities()) { maxDate = dataContext.prices.Max(x => x.date); minDate = dataContext.prices.Min(x => x.date); } if (parsedDates.Any() && parsedDates.All(x => !(minDate <= x && maxDate >= x))) { responseMessage = $"Sorry I only have data from {minDate:MMMM yyyy} to {maxDate:MMMM yyyy}"; return(responseMessage); } PriceFilterType priceFilter; if (requestsLowest) //Intentionally done first, in case both exist i.e worst expensive { priceFilter = PriceFilterType.Least; } else if (requestsHighest) { priceFilter = PriceFilterType.Most; } else { priceFilter = PriceFilterType.None; } //Question 'What is the cost of gold in January 2015' has 2015 as part of date and number numbers.RemoveAll(x => x.Length == 4 && dates.Any(d => d.Contains(x))); var hasMonths = false; if (dates.Any()) { hasMonths = dates.Any(x => x.Contains('-')); } var number = 1; //TODO: What if user gives more than one number if (numbers.Any()) { number = int.Parse(numbers.First()); } var queryDescriptor = new QueryDescriptor( isPriceOriented, metals, parsedDates, hasMonths ? TimelineConstraintLimit.Month : TimelineConstraintLimit.Year, priceFilter, !dates.Any(), number ); var result = QueryProcessor.Process(queryDescriptor); var failedToEvaluate = EvaluateResultStatus(out responseMessage, result.QueryResultType); if (failedToEvaluate) { return(responseMessage); } responseMessage = FormatResult(result.Prices.ToList(), number); break; case "None": responseMessage = "Sorry, I don't understand, perhaps try something like \"What was sales in 2010\""; break; } return(responseMessage); }
/// <summary> /// Processes the query. /// </summary> public static QueryResults Process(QueryDescriptor query) { var queryResult = new QueryResults(); #pragma warning disable 618 var predicate = PredicateBuilder.False <price>(); #pragma warning restore 618 if (!query.IsCostFocused && !query.HasPriceFilter) { queryResult.SetResultState(QueryResultType.NonCostFocused); return(queryResult); } if (!query.HasMetalNames && !query.HasPriceFilter) { queryResult.SetResultState(QueryResultType.NoMetalSpecified); return(queryResult); } //botEntities is a EntityDataContext var dataContext = new botEntities(); //What is the price of gold //What is the current price of gold //What is the price of gold now //What is the price of gold today // Current price //What is the price of gold in 2015 //What is the price of gold in January 2015 if (!query.HasPriceFilter) { foreach (string keyword in query.MetalNames) { string temp = keyword; predicate = predicate.Or(p => p.metal.name.Equals(temp)); } if (!query.HasTimeConstraints || query.UseCurrentTimeLine) { query.SetTimelineToCurrent(); } foreach (var time in query.TimelineConstraints) { predicate = query.TimeLineConstraintLimit == TimelineConstraintLimit.Month ? predicate.And(p => (p.date.Year == time.Year && p.date.Month == time.Month)) : predicate.And(p => (p.date.Year == time.Year)); } queryResult.Prices = dataContext.prices.AsExpandable().Where(predicate); queryResult.SetResultState(QueryResultType.Ok); return(queryResult); } //When was gold most expensive //When was gold cheapest // Open specific metal filter //When was gold most expensive in 2015 // Restricted specific metal filter //What metal was the most expensive in 2015 //Which metal was the cheapest in 2015 if (query.HasPriceFilter && query.MetalNames.Count <= 1) { var keyword = query.MetalNames.FirstOrDefault(); if (keyword != null) { predicate = predicate.Or(p => p.metal.name.Equals(keyword)); } foreach (var time in query.TimelineConstraints) { predicate = query.TimeLineConstraintLimit == TimelineConstraintLimit.Month ? predicate.And(p => (p.date.Year == time.Year && p.date.Month == time.Month)) : predicate.And(p => (p.date.Year == time.Year)); } if (query.PriceFilterType == PriceFilterType.Least) { queryResult.Prices = dataContext.prices.AsExpandable() .Where(predicate) .OrderBy(t => t.price1) .Take(query.NumberConstraint); } else { queryResult.Prices = dataContext.prices.AsExpandable() .Where(predicate) .OrderByDescending(t => t.price1) .Take(query.NumberConstraint); } queryResult.SetResultState(QueryResultType.Ok); return(queryResult); } queryResult.SetResultState(QueryResultType.Inconclusive); return(queryResult); }