Beispiel #1
0
        /// <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);
        }