private async Task <DialogTurnResult> FinalStepAsync(
            WaterfallStepContext stepContext,
            CancellationToken cancellationToken)
        {
            // Retrieve their selection list, the choice they made, and whether they chose to finish.
            var list   = stepContext.Values[CountriesSelected] as List <string>;
            var choice = (FoundChoice)stepContext.Result;
            var done   = choice.Value == DoneOption;

            if (!done)
            {
                // If they chose a company, add it to the list.
                list.Add(choice.Value);
            }

            if (done)
            {
                // If they're done, exit and return their list.
                ConsoleWriter.WriteLineInfo("Filter for: " + string.Join(", ", list));
                FilterForWordDetails filterForWordDetails = new FilterForWordDetails();
                filterForWordDetails.columnName = list.ToArray();


                ConsoleWriter.WriteLineInfo("ColumnName: " + filterForWordDetails.columnName[0]);
                await BOT_Api.SendFilterForWord(stepContext, usedColumn, list.ToArray());

                return(await stepContext.EndDialogAsync(list, cancellationToken));
            }
            else
            {
                // Otherwise, repeat this dialog, passing in the list from this iteration.
                return(await stepContext.ReplaceDialogAsync(nameof(FilterForWordDialog), list, cancellationToken));
            }
        }
Exemplo n.º 2
0
        //This function is called every time the user enters an input. The intent is determined in the switch case block. From there we call the needed Dialogs
        private async Task <DialogTurnResult> ActStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            var luisResult = await _luisRecognizer.RecognizeAsync <VisualizationInteraction>(stepContext.Context, cancellationToken);


            switch (luisResult.TopIntent().intent)
            {
            //The user wants to change the charttype
            case VisualizationInteraction.Intent.ChangeChartType:

                string[] chartTypeResults = luisResult.ToChartTypeEntity;

                var changeChartTypeDetails = new ChangeChartTypeDetails()
                {
                    AmbiguousChartTypes = chartTypeResults,
                    ToChartType         = chartTypeResults?[0],
                };

                //Check if changechartTypeDetails is null (in the Dialog) and ask for information if it is null
                return(await stepContext.BeginDialogAsync(nameof(ChangeChartTypeDialog), changeChartTypeDetails, cancellationToken));

            // user wants to filter for country, product or segment (nominal Rows)
            case VisualizationInteraction.Intent.Filter:

                (string[] columnnameLuis, string[] filterAttributeLuis, string[] countryLuis, string[] segmentLuis, string[] productLuis) = luisResult.FilterForWordEntities;

                string usedColumn;

                if (countryLuis != null)
                {
                    usedColumn = "Country";
                }
                else if (segmentLuis != null)
                {
                    usedColumn = "Segment";
                }
                else if (productLuis != null)
                {
                    usedColumn = "Product";
                }
                else
                {
                    usedColumn = "Country";
                }

                ConsoleWriter.WriteLineInfo("Column: " + usedColumn);

                var filterForWordDetails = new FilterForWordDetails
                {
                    columnName      = columnnameLuis,
                    filterAttribute = filterAttributeLuis,
                    country         = countryLuis,
                    segment         = segmentLuis,
                    product         = productLuis,
                    usedColumn      = usedColumn
                };
                return(await stepContext.BeginDialogAsync(nameof(FilterForWordDialog), filterForWordDetails, cancellationToken));


            //user wants to filter for number (cardinal rows)
            case VisualizationInteraction.Intent.FilterForNumber:

                (string[] columnNameLuis, string comparisonOperatorLuis, string filterNumberLuis) = luisResult.FilterForNumberEntities;

                var filterForNumberDetails = new FilterForNumberDetails
                {
                    columnName         = columnNameLuis,
                    comparisonOperator = comparisonOperatorLuis,
                    filterNumber       = filterNumberLuis
                };

                return(await stepContext.BeginDialogAsync(nameof(FilterForNumberDialog), filterForNumberDetails, cancellationToken));

            //user input is a complete query to be visualized -> send query to nl4dv
            case VisualizationInteraction.Intent.Nl4dv:
                //Gets the whole message from the User to the bot out of the luis result
                string nl4dvQuery = luisResult.Text;

                (string queryText, string[] chartType, string[] axis1, string[] axis2) = luisResult.Nl4dvEntities;

                var nl4dvQueryDetails = new Nl4dvQueryDetails
                {
                    queryText = queryText,
                    chartType = chartType,
                    axis1     = axis1,
                    axis2     = axis2
                };

                ConsoleWriter.WriteLineInfo("nl4dvQuery: " + nl4dvQuery);

                return(await stepContext.BeginDialogAsync(nameof(Nl4dvDialog), nl4dvQueryDetails, cancellationToken));


                //Here we would have to call the NL4DV function in the event handler (in the Python project)
                //BOT_Api.SendNL4DV(nl4dvQuery);
                break;

            // user wants to change e.g. legend or y-axis
            case VisualizationInteraction.Intent.ChangeVisualizationPart:

                (string visualizationPartLuis, string[] toValueLuis) = luisResult.ChangeVisualizationPartEntities;


                var changeVisualizationPartDetails = new ChangeVisualizationPartDetails
                {
                    visualizationPart = visualizationPartLuis,
                    toValue           = toValueLuis
                };

                return(await stepContext.BeginDialogAsync(nameof(ChangeVisualizationPartDialog), changeVisualizationPartDetails, cancellationToken));

            // user wants to change the aggregate of an axis
            case VisualizationInteraction.Intent.ChangeAggregate:

                (string toVisPartLuis, string toAggregateLuis) = luisResult.ChangeAggregateEntities;


                var changeAggregateDetails = new ChangeAggregateDetails
                {
                    visualizationPart = toVisPartLuis,
                    toAggregate       = toAggregateLuis
                };

                return(await stepContext.BeginDialogAsync(nameof(ChangeAggregateDialog), changeAggregateDetails, cancellationToken));

            case VisualizationInteraction.Intent.ClearFilter:
                await BOT_Api.SendClearFilter(stepContext);

                break;

            case VisualizationInteraction.Intent.Help:
                var helpMessageText = "Here is a quick guide for you: say \"show me sales by country\" to create a new visualization || \"change yaxis to profit\" to change the label of y-axis to profit || \"change aggregate of yaxis to sum\" changes the data aggregation of yaxis to sum (you can say sum, count, average) || \"change charttype to piechart\" changes the visualization to a piechart || \"filter for sales >= 200\" filters the dataset for all rows containing sales >= 200 || \"clear filter\" to clear all added filters";
                var helpMessage     = MessageFactory.Text(helpMessageText, helpMessageText, InputHints.IgnoringInput);
                await stepContext.Context.SendActivityAsync(helpMessage, cancellationToken);

                break;


            //intent not recognized
            default:
                // Catch all for unhandled intents
                var didntUnderstandMessageText = $"Sorry, I didn't get that. Please try asking in a different way (intent was {luisResult.TopIntent().intent})";
                var didntUnderstandMessage     = MessageFactory.Text(didntUnderstandMessageText, didntUnderstandMessageText, InputHints.IgnoringInput);
                await stepContext.Context.SendActivityAsync(didntUnderstandMessage, cancellationToken);

                break;
            }

            return(await stepContext.NextAsync(null, cancellationToken));
        }
        //Check if input is empty or additionally it is asked to filter for countries, then add country option list
        private async Task <DialogTurnResult> SelectionStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            // Continue using the same selection list, if any, from the previous iteration of this dialog.
            var list = stepContext.Options as List <string> ?? new List <string>();

            bool filterForCountry = false;

            if (stepContext.Options.GetType().ToString().Equals("Microsoft.BotBuilderSamples.FilterForWordDetails"))
            {
                FilterForWordDetails filterForWordDetails = (FilterForWordDetails)stepContext.Options;
                usedColumn = filterForWordDetails.usedColumn;
                // Check if filter for Word Dialog input is empty
                if (filterForWordDetails.columnName == null)
                {
                    string messageNull   = "I could not recognize what column you want to apply that filter to. Please say something like \"Filter for Germany and Canada\"";
                    var    cancelMessage = MessageFactory.Text(messageNull, CancelMsgText, InputHints.IgnoringInput);
                    await stepContext.Context.SendActivityAsync(cancelMessage, cancellationToken);

                    return(await stepContext.CancelAllDialogsAsync(cancellationToken));
                }

                //Filter for country
                for (int i = 0; i < filterForWordDetails.columnName.Length; i++)
                {
                    string s = UppercaseFirst(filterForWordDetails.columnName[i]);
                    list.Add(s);

                    //becomes true when you enter "filter for country"
                    if (string.Equals(s, "Country") || string.Equals(s, "Countries"))
                    {
                        filterForCountry = true;
                    }
                }

                if ((filterForWordDetails.country == null) && (filterForWordDetails.segment == null) && (filterForWordDetails.product == null) && !filterForCountry)
                {
                    string messageNull = "I could not recognize what column you want to apply that filter to. Please say something like \"Filter for Germany and Canada\"";

                    var cancelMessage = MessageFactory.Text(messageNull, CancelMsgText, InputHints.IgnoringInput);
                    await stepContext.Context.SendActivityAsync(cancelMessage, cancellationToken);

                    return(await stepContext.CancelAllDialogsAsync(cancellationToken));
                }


                //Breaks if we did not recognize any countries
                if (!filterForCountry)
                {
                    filterForWordDetails.columnName = list.ToArray();
                    ConsoleWriter.WriteLineInfo("Filter for: " + string.Join(", ", list));
                    ConsoleWriter.WriteLineInfo("ColumnName: " + filterForWordDetails.columnName[0]);
                    await BOT_Api.SendFilterForWord(stepContext, usedColumn, list.ToArray());

                    return(await stepContext.EndDialogAsync(filterForWordDetails.columnName));
                }
            }


            //if user entered "FILTER FOR COUNTRY" OR "COUNTRIES":

            stepContext.Values[CountriesSelected] = list;
            //Create a prompt message
            string message;

            if (list[0] == "Country")
            {
                message = $"Please choose a country to filter to finish.";
                list.Remove("Country");
            }
            else if (list[0] == "Countries")
            {
                message = $"Please choose a country to filter to finish.";
                list.Remove("Countries");
            }
            else
            {
                message = $"You have selected **{String.Join(", ", list)}**. You can filter for an additional country, " +
                          $"or choose `{DoneOption}` to finish.";
            }

            // Create the list of options to choose from.
            var options = _countryOptions.ToList();

            if (list.Count > 0)
            {
                options.Add(DoneOption);
                options = options.Except(list).ToList();
            }

            var promptOptions = new PromptOptions
            {
                Prompt      = MessageFactory.Text(message),
                RetryPrompt = MessageFactory.Text("Please choose an option from the list."),
                Choices     = ChoiceFactory.ToChoices(options),
            };

            // Prompt the user for a choice.
            return(await stepContext.PromptAsync(nameof(ChoicePrompt), promptOptions, cancellationToken));
        }