public void Test_SettingFilter_Temperature()
        {
            var state = new AutomotiveSkillState();

            state.Entities.Add("SETTING", new List <string> {
                "temperature"
            });
            state.Entities.Add("AMOUNT", new List <string> {
                "21"
            });
            state.Entities.Add("UNIT", new List <string> {
                "degrees"
            });

            settingFilter.PostProcessSettingName(state);

            Assert.AreEqual("Temperature", state.Changes[0].SettingName);
            Assert.AreEqual(21, state.Changes[0].Amount.Amount);
        }
예제 #2
0
        /// <summary>
        /// Top level processing, is the user trying to check or change a setting?.
        /// </summary>
        /// <param name="sc">Step Context.</param>
        /// <param name="cancellationToken">Cancellation Token.</param>
        /// <returns>Dialog Turn Result.</returns>
        public async Task <DialogTurnResult> ProcessSetting(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await Accessor.GetAsync(sc.Context, () => new AutomotiveSkillState());

            var luisResult = state.VehicleSettingsLuisResult;
            var topIntent  = luisResult?.TopIntent().intent;

            switch (topIntent.Value)
            {
            case settingsLuis.Intent.VEHICLE_SETTINGS_CHANGE:
            case settingsLuis.Intent.VEHICLE_SETTINGS_DECLARATIVE:

                // Perform post-processing on the entities, if it's declarative we indicate for special processing (opposite of the condition they've expressed)
                settingFilter.PostProcessSettingName(state, topIntent.Value == settingsLuis.Intent.VEHICLE_SETTINGS_DECLARATIVE ? true : false);

                // Perform content logic and remove entities that don't make sense
                settingFilter.ApplyContentLogic(state);

                var settingNames = state.GetUniqueSettingNames();
                if (!settingNames.Any())
                {
                    // missing setting name
                    await sc.Context.SendActivityAsync(ResponseManager.GetResponse(VehicleSettingsResponses.VehicleSettingsMissingSettingName));

                    return(await sc.EndDialogAsync());
                }
                else if (settingNames.Count() > 1)
                {
                    // If we have more than one setting name matching prompt the user to choose
                    var options = new PromptOptions()
                    {
                        Choices = new List <Choice>(),
                    };

                    for (var i = 0; i < settingNames.Count; ++i)
                    {
                        var item     = settingNames[i];
                        var synonyms = new List <string>
                        {
                            item,
                            (i + 1).ToString()
                        };
                        synonyms.AddRange(settingList.GetAlternativeNamesForSetting(item));
                        var choice = new Choice()
                        {
                            Value    = item,
                            Synonyms = synonyms,
                        };
                        options.Choices.Add(choice);
                    }

                    var cardModel = new AutomotiveCardModel()
                    {
                        ImageUrl = GetSettingCardImageUri(FallbackSettingImageFileName)
                    };

                    var card = new Card(GetDivergedCardName(sc.Context, "AutomotiveCard"), cardModel);

                    options.Prompt = ResponseManager.GetCardResponse(VehicleSettingsResponses.VehicleSettingsSettingNameSelection, card, tokens: null);

                    // Default Text property is clumsy for speech
                    options.Prompt.Speak = SpeechUtility.ListToSpeechReadyString(options);

                    // Workaround. In teams, prompt will be changed to HeroCard and adaptive card could not be shown. So send them separatly
                    if (Channel.GetChannelId(sc.Context) == Channels.Msteams)
                    {
                        await sc.Context.SendActivityAsync(options.Prompt);

                        options.Prompt = null;
                    }

                    return(await sc.PromptAsync(Actions.SettingNameSelectionPrompt, options));
                }
                else
                {
                    // Only one setting detected so move on to next stage
                    return(await sc.NextAsync());
                }

            case settingsLuis.Intent.VEHICLE_SETTINGS_CHECK:
                await sc.Context.SendActivityAsync(sc.Context.Activity.CreateReply("The skill doesn't support checking vehicle settings quite yet!"));

                return(await sc.EndDialogAsync(true, cancellationToken));

            default:
                await sc.Context.SendActivityAsync(ResponseManager.GetResponse(VehicleSettingsResponses.VehicleSettingsOutOfDomain));

                return(await sc.EndDialogAsync(true, cancellationToken));
            }
        }
예제 #3
0
        /// <summary>
        /// Top level processing, is the user trying to check or change a setting?.
        /// </summary>
        /// <param name="sc">Step Context.</param>
        /// <param name="cancellationToken">Cancellation Token.</param>
        /// <returns>Dialog Turn Result.</returns>
        public async Task <DialogTurnResult> ProcessSetting(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await Accessor.GetAsync(sc.Context, () => new AutomotiveSkillState());

            var luisResult = state.VehicleSettingsLuisResult;
            var topIntent  = luisResult?.TopIntent().intent;

            switch (topIntent.Value)
            {
            case Luis.VehicleSettings.Intent.VEHICLE_SETTINGS_CHANGE:
            case Luis.VehicleSettings.Intent.VEHICLE_SETTINGS_DECLARATIVE:

                // Perform post-processing on the entities, if it's declarative we indicate for special processing (opposite of the condition they've expressed)
                settingFilter.PostProcessSettingName(state, topIntent.Value == Luis.VehicleSettings.Intent.VEHICLE_SETTINGS_DECLARATIVE ? true : false);

                // Perform content logic and remove entities that don't make sense
                settingFilter.ApplyContentLogic(state);

                var settingNames = state.GetUniqueSettingNames();
                if (!settingNames.Any())
                {
                    // missing setting name
                    await sc.Context.SendActivityAsync(ResponseManager.GetResponse(VehicleSettingsResponses.VehicleSettingsMissingSettingName));

                    return(await sc.EndDialogAsync());
                }
                else if (settingNames.Count() > 1)
                {
                    // If we have more than one setting name matching prompt the user to choose
                    var options = new PromptOptions()
                    {
                        Choices = new List <Choice>(),
                    };

                    for (var i = 0; i < settingNames.Count; ++i)
                    {
                        var           item     = settingNames[i];
                        List <string> synonyms = new List <string>();
                        synonyms.Add(item);
                        synonyms.Add((i + 1).ToString());
                        synonyms.AddRange(settingList.GetAlternativeNamesForSetting(item));
                        var choice = new Choice()
                        {
                            Value    = item,
                            Synonyms = synonyms,
                        };
                        options.Choices.Add(choice);
                    }

                    options.Prompt = ResponseManager.GetResponse(VehicleSettingsResponses.VehicleSettingsSettingNameSelection);

                    var card = new ThumbnailCard
                    {
                        Images = new List <CardImage> {
                            new CardImage(GetSettingCardImageUri(FallbackSettingImageFileName))
                        },
                        Text    = options.Prompt.Text,
                        Buttons = options.Choices.Select(choice =>
                                                         new CardAction(ActionTypes.ImBack, choice.Value, value: choice.Value)).ToList(),
                    };

                    options.Prompt.Attachments.Add(card.ToAttachment());

                    // Default Text property is clumsy for speech
                    options.Prompt.Speak = $"{options.Prompt.Text} {GetSpeakableOptions(options.Choices)}";

                    return(await sc.PromptAsync(Actions.SettingNameSelectionPrompt, options));
                }
                else
                {
                    // Only one setting detected so move on to next stage
                    return(await sc.NextAsync());
                }

            case Luis.VehicleSettings.Intent.VEHICLE_SETTINGS_CHECK:
                await sc.Context.SendActivityAsync(sc.Context.Activity.CreateReply("The skill doesn't support checking vehicle settings quite yet!"));

                return(await sc.EndDialogAsync(true, cancellationToken));

            default:
                await sc.Context.SendActivityAsync(ResponseManager.GetResponse(VehicleSettingsResponses.VehicleSettingsOutOfDomain));

                return(await sc.EndDialogAsync(true, cancellationToken));
            }
        }
예제 #4
0
        /// <summary>
        /// Top level processing, is the user trying to check or change a setting?.
        /// </summary>
        /// <param name="sc">Step Context.</param>
        /// <param name="cancellationToken">Cancellation Token.</param>
        /// <returns>Dialog Turn Result.</returns>
        public async Task <DialogTurnResult> ProcessSetting(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await Accessor.GetAsync(sc.Context);

            // Ensure we don't have state from a previous instantiation
            state.Changes.Clear();
            state.Entities.Clear();

            var luisResult = state.VehicleSettingsLuisResult;
            var topIntent  = luisResult?.TopIntent().intent;

            switch (topIntent.Value)
            {
            case Luis.VehicleSettings.Intent.VEHICLE_SETTINGS_CHANGE:
            case Luis.VehicleSettings.Intent.VEHICLE_SETTINGS_DECLARATIVE:

                // Process the LUIS result and add entities to the State accessors for ease of access
                if (luisResult.Entities.AMOUNT != null)
                {
                    state.Entities.Add(nameof(luisResult.Entities.AMOUNT), luisResult.Entities.AMOUNT);
                }

                if (luisResult.Entities.INDEX != null)
                {
                    state.Entities.Add(nameof(luisResult.Entities.INDEX), luisResult.Entities.INDEX);
                }

                if (luisResult.Entities.SETTING != null)
                {
                    state.Entities.Add(nameof(luisResult.Entities.SETTING), luisResult.Entities.SETTING);
                }

                if (luisResult.Entities.TYPE != null)
                {
                    state.Entities.Add(nameof(luisResult.Entities.TYPE), luisResult.Entities.TYPE);
                }

                if (luisResult.Entities.UNIT != null)
                {
                    state.Entities.Add(nameof(luisResult.Entities.UNIT), luisResult.Entities.UNIT);
                }

                if (luisResult.Entities.VALUE != null)
                {
                    state.Entities.Add(nameof(luisResult.Entities.VALUE), luisResult.Entities.VALUE);
                }

                // Perform post-processing on the entities, if it's declarative we indicate for special processing (opposite of the condition they've expressed)
                settingFilter.PostProcessSettingName(state, topIntent.Value == Luis.VehicleSettings.Intent.VEHICLE_SETTINGS_DECLARATIVE ? true : false);

                // Perform content logic and remove entities that don't make sense
                settingFilter.ApplyContentLogic(state);

                var settingNames = state.GetUniqueSettingNames();
                if (!settingNames.Any())
                {
                    // missing setting name
                    await sc.Context.SendActivityAsync(sc.Context.Activity.CreateReply(VehicleSettingsResponses.VehicleSettingsMissingSettingName));

                    return(await sc.EndDialogAsync());
                }
                else if (settingNames.Count() > 1)
                {
                    // If we have more than one setting name matching prompt the user to choose
                    var options = new PromptOptions()
                    {
                        Choices = new List <Choice>(),
                    };

                    for (var i = 0; i < settingNames.Count; ++i)
                    {
                        var item   = settingNames[i];
                        var choice = new Choice()
                        {
                            Value    = item,
                            Synonyms = new List <string> {
                                (i + 1).ToString(), item
                            },
                        };
                        options.Choices.Add(choice);
                    }

                    var card = new HeroCard
                    {
                        Images = new List <CardImage> {
                            new CardImage(GetSettingCardImageUri("settingcog.jpg"))
                        },
                        Text    = "Please choose from one of the available settings shown below",
                        Buttons = options.Choices.Select(choice =>
                                                         new CardAction(ActionTypes.ImBack, choice.Value, value: choice.Value)).ToList(),
                    };

                    options.Prompt = (Activity)MessageFactory.Attachment(card.ToAttachment());

                    return(await sc.PromptAsync(Actions.SettingNameSelectionPrompt, options));
                }
                else
                {
                    // Only one setting detected so move on to next stage
                    return(await sc.NextAsync());
                }

            case Luis.VehicleSettings.Intent.VEHICLE_SETTINGS_CHECK:
                await sc.Context.SendActivityAsync(sc.Context.Activity.CreateReply("The skill doesn't support checking vehicle settings quite yet!"));

                return(await sc.EndDialogAsync(true, cancellationToken));

            default:
                await sc.Context.SendActivityAsync(sc.Context.Activity.CreateReply(VehicleSettingsResponses.VehicleSettingsOutOfDomain));

                return(await sc.EndDialogAsync(true, cancellationToken));
            }
        }
        /// <summary>
        /// Top level processing, is the user trying to check or change a setting?.
        /// </summary>
        /// <param name="sc">Step Context.</param>
        /// <param name="cancellationToken">Cancellation Token.</param>
        /// <returns>Dialog Turn Result.</returns>
        public async Task <DialogTurnResult> ProcessSettingAsync(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await Accessor.GetAsync(sc.Context, () => new AutomotiveSkillState(), cancellationToken);

            var  skillResult   = sc.Context.TurnState.Get <SettingsLuis>(StateProperties.SettingsLuisResultKey);
            bool isDeclarative = skillResult?.TopIntent().intent == SettingsLuis.Intent.VEHICLE_SETTINGS_DECLARATIVE;

            // Perform post-processing on the entities, if it's declarative we indicate for special processing (opposite of the condition they've expressed)
            settingFilter.PostProcessSettingName(state, isDeclarative);

            // Perform content logic and remove entities that don't make sense
            settingFilter.ApplyContentLogic(state);

            var settingNames = state.GetUniqueSettingNames();

            if (!settingNames.Any())
            {
                // missing setting name
                await sc.Context.SendActivityAsync(TemplateManager.GenerateActivityForLocale(VehicleSettingsResponses.VehicleSettingsMissingSettingName), cancellationToken);

                return(await sc.EndDialogAsync(cancellationToken : cancellationToken));
            }
            else if (settingNames.Count() > 1)
            {
                // If we have more than one setting name matching prompt the user to choose
                var options = new PromptOptions()
                {
                    Choices = new List <Choice>(),
                };

                for (var i = 0; i < settingNames.Count; ++i)
                {
                    var item     = settingNames[i];
                    var synonyms = new List <string>
                    {
                        item,
                        (i + 1).ToString()
                    };
                    synonyms.AddRange(settingList.GetAlternativeNamesForSetting(item));
                    var choice = new Choice()
                    {
                        Value    = item,
                        Synonyms = synonyms,
                    };
                    options.Choices.Add(choice);
                }

                var cardModel = new AutomotiveCardModel()
                {
                    ImageUrl = GetSettingCardImageUri(FallbackSettingImageFileName)
                };

                var card = TemplateManager.GenerateActivityForLocale(GetDivergedCardName(sc.Context, "AutomotiveCard"), cardModel);
                options.Prompt             = TemplateManager.GenerateActivityForLocale(VehicleSettingsResponses.VehicleSettingsSettingNameSelection);
                options.Prompt.Attachments = card.Attachments;

                // Default Text property is clumsy for speech
                options.Prompt.Speak = SpeechUtility.ListToSpeechReadyString(options);

                // Workaround. In teams, prompt will be changed to HeroCard and adaptive card could not be shown. So send them separatly
                if (Channel.GetChannelId(sc.Context) == Channels.Msteams)
                {
                    await sc.Context.SendActivityAsync(options.Prompt, cancellationToken);

                    options.Prompt = null;
                }

                return(await sc.PromptAsync(Actions.SettingNameSelectionPrompt, options, cancellationToken));
            }
            else
            {
                // Only one setting detected so move on to next stage
                return(await sc.NextAsync(cancellationToken : cancellationToken));
            }
        }