/// <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)); } }
/// <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)); } }
/// <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)); } }