private PromptOptions GetRoutesPrompt(string prompt, List <Card> cards)
        {
            var options = new PromptOptions()
            {
                Choices = new List <Choice>(),
            };

            for (var i = 0; i < cards.Count; ++i)
            {
                // Simple distinction
                var promptReplacements = new StringDictionary
                {
                    { "Id", (i + 1).ToString() },
                };
                var suggestedActionValue = ResponseManager.GetResponse(RouteResponses.RouteSuggestedActionName, promptReplacements).Text;

                var choice = new Choice()
                {
                    Value = suggestedActionValue,
                };
                options.Choices.Add(choice);

                (cards[i].Data as RouteDirectionsModel).SubmitText = suggestedActionValue;
            }

            options.Prompt = cards == null?ResponseManager.GetResponse(prompt) : ResponseManager.GetCardResponse(prompt, cards);

            options.Prompt.Speak = SpeechUtility.ListToSpeechReadyString(options.Prompt);

            return(options);
        }
        public void GetSpeechReadyStringFromActivityWithFourAttachments()
        {
            _activity.Attachments = new List <Attachment>
            {
                new Attachment(contentType: AdaptiveCard.ContentType, content: new AdaptiveCard(adaptiveSchemaVersion)
                {
                    Speak = listItemSpeakProperty, Type = AdaptiveCard.TypeName
                }),
                new Attachment(contentType: AdaptiveCard.ContentType, content: new AdaptiveCard(adaptiveSchemaVersion)
                {
                    Speak = listItemSpeakProperty, Type = AdaptiveCard.TypeName
                }),
                new Attachment(contentType: AdaptiveCard.ContentType, content: new AdaptiveCard(adaptiveSchemaVersion)
                {
                    Speak = listItemSpeakProperty, Type = AdaptiveCard.TypeName
                }),
                new Attachment(contentType: AdaptiveCard.ContentType, content: new AdaptiveCard(adaptiveSchemaVersion)
                {
                    Speak = listItemSpeakProperty, Type = AdaptiveCard.TypeName
                }),
            };

            var response = SpeechUtility.ListToSpeechReadyString(_activity);

            var item1 = string.Format(CommonStrings.FirstItem, listItemSpeakProperty);
            var item2 = string.Format(CommonStrings.SecondItem, listItemSpeakProperty);
            var item3 = string.Format(CommonStrings.ThirdItem, listItemSpeakProperty);
            var item4 = string.Format(CommonStrings.LastItem, listItemSpeakProperty);

            Assert.AreEqual(response, string.Format($"{parentSpeakProperty} {item1}, {item2}, {item3} {CommonStrings.And} {item4}"));
        }
        public void GetSpeechReadyStringFromOnePromptOption()
        {
            _promptOptions.Choices = new List <Choice>()
            {
                new Choice(listItemSpeakProperty),
            };

            var response = SpeechUtility.ListToSpeechReadyString(_promptOptions);

            Assert.AreEqual(response, string.Format($"{parentSpeakProperty} {listItemSpeakProperty}"));
        }
Example #4
0
        /// <summary>
        /// Gets ChoicePrompt options with a formatted display name if there are identical locations.
        /// Handle the special yes no case when cards has only one.
        /// </summary>
        /// <param name="prompt">Prompt string.</param>
        /// <param name="containerCard">Container card.</param>
        /// <param name="container">Container.</param>
        /// <param name="cards">List of Cards. Data must be PointOfInterestModel.</param>
        /// <returns>PromptOptions.</returns>
        protected PromptOptions GetPointOfInterestPrompt(string prompt, Card containerCard, string container, List <Card> cards)
        {
            var pointOfInterestList = cards.Select(card => card.Data as PointOfInterestModel).ToList();

            var options = new PromptOptions()
            {
                Choices = new List <Choice>(),
            };

            for (var i = 0; i < pointOfInterestList.Count; ++i)
            {
                var address = pointOfInterestList[i].Address;

                var synonyms = new List <string>()
                {
                    address,
                };

                var choice = new Choice()
                {
                    // Use speak first for SpeechUtility.ListToSpeechReadyString
                    Value    = pointOfInterestList[i].Speak,
                    Synonyms = synonyms,
                };
                options.Choices.Add(choice);

                pointOfInterestList[i].SubmitText = pointOfInterestList[i].RawSpeak;
            }

            if (cards.Count == 1)
            {
                pointOfInterestList[0].SubmitText = GetConfirmPromptTrue();
            }

            options.Prompt = new Activity();

            var data = new
            {
                Count   = options.Choices.Count,
                Options = SpeechUtility.ListToSpeechReadyString(options),
            };

            options.Prompt = TemplateManager.GenerateActivity(prompt, containerCard, data, container, cards);

            // Restore Value to SubmitText
            for (var i = 0; i < pointOfInterestList.Count; ++i)
            {
                options.Choices[i].Value = pointOfInterestList[i].RawSpeak;
            }

            return(options);
        }
        public void GetSpeechReadyStringFromActivityWithOneAttachment()
        {
            _activity.Attachments = new List <Attachment>
            {
                new Attachment(contentType: AdaptiveCard.ContentType, content: new AdaptiveCard(adaptiveSchemaVersion)
                {
                    Speak = listItemSpeakProperty, Type = AdaptiveCard.TypeName
                }),
            };

            var response = SpeechUtility.ListToSpeechReadyString(_activity);

            Assert.AreEqual(response, string.Format($"{parentSpeakProperty} {listItemSpeakProperty}"));
        }
        /// <summary>
        /// Gets ChoicePrompt options with a formatted display name if there are identical locations.
        /// </summary>
        /// <param name="prompt">Prompt string.</param>
        /// <param name="pointOfInterestList">List of PointOfInterestModels.</param>
        /// <param name="cards">List of Cards.</param>
        /// <returns>PromptOptions.</returns>
        protected PromptOptions GetPointOfInterestPrompt(string prompt, List <PointOfInterestModel> pointOfInterestList, List <Card> cards = null)
        {
            var options = new PromptOptions()
            {
                Choices = new List <Choice>(),
            };

            for (var i = 0; i < pointOfInterestList.Count; ++i)
            {
                var item    = pointOfInterestList[i].Name;
                var address = pointOfInterestList[i].Address;

                var synonyms = new List <string>()
                {
                    item,
                    address,
                    (i + 1).ToString(),
                };

                var suggestedActionValue = item;

                // Use response resource to get formatted name if multiple have the same name
                if (pointOfInterestList.Where(x => x.Name == pointOfInterestList[i].Name).Skip(1).Any())
                {
                    var promptTemplate     = POISharedResponses.PointOfInterestSuggestedActionName;
                    var promptReplacements = new StringDictionary
                    {
                        { "Name", item },
                        { "Address", address },
                    };
                    suggestedActionValue = ResponseManager.GetResponse(promptTemplate, promptReplacements).Text;
                }

                var choice = new Choice()
                {
                    Value    = suggestedActionValue,
                    Synonyms = synonyms,
                };
                options.Choices.Add(choice);

                pointOfInterestList[i].SubmitText = suggestedActionValue;
            }

            options.Prompt = cards == null?ResponseManager.GetResponse(prompt) : ResponseManager.GetCardResponse(prompt, cards);

            options.Prompt.Speak = DecorateSpeak(SpeechUtility.ListToSpeechReadyString(options.Prompt, ReadPreference.Enumeration, 5));

            return(options);
        }
        public void GetSpeechReadyStringFromTwoPromptOptionsChronological()
        {
            _promptOptions.Choices = new List <Choice>()
            {
                new Choice(listItemSpeakProperty),
                new Choice(listItemSpeakProperty),
            };

            var response = SpeechUtility.ListToSpeechReadyString(_promptOptions, ReadPreference.Chronological);

            var item1 = string.Format(CommonStrings.LatestItem, listItemSpeakProperty);
            var item2 = string.Format(CommonStrings.LastItem, listItemSpeakProperty);

            Assert.AreEqual(response, string.Format($"{parentSpeakProperty} {item1} {CommonStrings.And} {item2}"));
        }
Example #8
0
        public void GetSpeechReadyStringFromActivityWithTwoAttachments()
        {
            _activity.Attachments = new List <Attachment>
            {
                new Attachment(contentType: AdaptiveCard.ContentType, content: new AdaptiveCard()
                {
                    Speak = listItemSpeakProperty, Type = AdaptiveCard.TypeName
                }),
                new Attachment(contentType: AdaptiveCard.ContentType, content: new AdaptiveCard()
                {
                    Speak = listItemSpeakProperty, Type = AdaptiveCard.TypeName
                })
            };

            var response = SpeechUtility.ListToSpeechReadyString(_activity);

            var item1 = string.Format(CommonStrings.FirstItem, listItemSpeakProperty);
            var item2 = string.Format(CommonStrings.LastItem, listItemSpeakProperty);

            Assert.AreEqual(response, string.Format($"{parentSpeakProperty}{SpeechUtility.BreakString}{item1} {CommonStrings.And} {item2}"));
        }
Example #9
0
        /// <summary>
        /// Once we have a setting we need to process the corresponding value.
        /// </summary>
        /// <param name="sc">Step Context.</param>
        /// <returns>Dialog Turn Result.</returns>
        private async Task <DialogTurnResult> ProcessVehicleSettingsChange(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await Accessor.GetAsync(sc.Context);

            if (state.Changes.Any())
            {
                var settingValues = state.GetUniqueSettingValues();
                if (!settingValues.Any())
                {
                    // This shouldn't happen because the SettingFilter would just add all possible values to let the user select from them.
                    await sc.Context.SendActivityAsync(ResponseManager.GetResponse(VehicleSettingsResponses.VehicleSettingsMissingSettingValue));

                    return(await sc.EndDialogAsync());
                }
                else
                {
                    // We have found multiple setting values, which we need to prompt the user to resolve
                    if (settingValues.Count() > 1)
                    {
                        var settingName = state.Changes.First().SettingName;
                        var setting     = this.settingList.FindSetting(settingName);

                        // If an image filename is provided we'll use it otherwise fall back to the generic car one
                        var imageName = setting.ImageFileName ?? FallbackSettingImageFileName;

                        // If we have more than one setting value matching, prompt the user to choose
                        var options = new PromptOptions()
                        {
                            Choices = new List <Choice>(),
                        };

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

                        var promptReplacements = new StringDictionary {
                            { "settingName", settingName }
                        };
                        var cardModel = new AutomotiveCardModel()
                        {
                            ImageUrl = GetSettingCardImageUri(imageName)
                        };

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

                        options.Prompt = ResponseManager.GetCardResponse(VehicleSettingsResponses.VehicleSettingsSettingValueSelection, card, promptReplacements);

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

                        // 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.SettingValueSelectionPrompt, options));
                    }
                    else
                    {
                        // We only have one setting value so proceed to next step
                        return(await sc.NextAsync());
                    }
                }
            }
            else
            {
                // No setting value was understood
                await sc.Context.SendActivityAsync(ResponseManager.GetResponse(VehicleSettingsResponses.VehicleSettingsOutOfDomain));

                return(await sc.EndDialogAsync());
            }
        }
Example #10
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));
            }
        }
        private async Task <PromptOptions> GenerateOptionsForName(WaterfallStepContext sc, List <PersonModel> unionList, ITurnContext context, bool isSinglePage = true)
        {
            var state = await Accessor.GetAsync(sc.Context);

            var pageIndex            = state.FindContactInfor.ShowContactsIndex;
            var pageSize             = 3;
            var skip                 = pageSize * pageIndex;
            var currentRecipientName = state.FindContactInfor.CurrentContactName;

            // Go back to the last page when reaching the end.
            if (skip >= unionList.Count && pageIndex > 0)
            {
                state.FindContactInfor.ShowContactsIndex--;
                pageIndex = state.FindContactInfor.ShowContactsIndex;
                skip      = pageSize * pageIndex;
                await sc.Context.SendActivityAsync(ResponseManager.GetResponse(FindContactResponses.AlreadyLastPage));
            }

            var options = new PromptOptions
            {
                Choices = new List <Choice>(),
                Prompt  = ResponseManager.GetResponse(FindContactResponses.ConfirmMultipleContactNameSinglePage, new StringDictionary()
                {
                    { "UserName", currentRecipientName }
                })
            };

            if (!isSinglePage)
            {
                options.Prompt = ResponseManager.GetResponse(FindContactResponses.ConfirmMultipleContactNameMultiPage, new StringDictionary()
                {
                    { "UserName", currentRecipientName }
                });
            }

            for (var i = 0; i < unionList.Count; i++)
            {
                var user = unionList[i];

                var choice = new Choice()
                {
                    Value    = $"**{user.DisplayName}**",
                    Synonyms = new List <string> {
                        (options.Choices.Count + 1).ToString(), user.DisplayName, user.DisplayName.ToLower()
                    },
                };
                var userName = user.UserPrincipalName?.Split("@").FirstOrDefault() ?? user.UserPrincipalName;
                if (!string.IsNullOrEmpty(userName))
                {
                    choice.Synonyms.Add(userName);
                    choice.Synonyms.Add(userName.ToLower());
                }

                if (skip <= 0)
                {
                    if (options.Choices.Count >= pageSize)
                    {
                        options.Prompt.Speak = SpeechUtility.ListToSpeechReadyString(options, ReadPreference.Chronological, ConfigData.GetInstance().MaxReadSize);
                        options.Prompt.Text  = GetSelectPromptString(options, true);
                        options.RetryPrompt  = ResponseManager.GetResponse(FindContactResponses.DidntUnderstandMessage);
                        return(options);
                    }

                    options.Choices.Add(choice);
                }
                else
                {
                    skip--;
                }
            }

            options.Prompt.Speak = SpeechUtility.ListToSpeechReadyString(options, ReadPreference.Chronological, ConfigData.GetInstance().MaxReadSize);
            options.Prompt.Text  = GetSelectPromptString(options, true);
            options.RetryPrompt  = ResponseManager.GetResponse(FindContactResponses.DidntUnderstandMessage);
            return(options);
        }
Example #12
0
        private async Task <PromptOptions> GenerateOptionsForEmail(WaterfallStepContext sc, PersonModel confirmedPerson, ITurnContext context, bool isSinglePage = true)
        {
            var state = await EmailStateAccessor.GetAsync(context);

            var pageIndex = state.ShowRecipientIndex;
            var pageSize  = ConfigData.GetInstance().MaxDisplaySize;
            var skip      = pageSize * pageIndex;
            var emailList = confirmedPerson.Emails;

            // Go back to the last page when reaching the end.
            if (skip >= emailList.Count && pageIndex > 0)
            {
                state.ShowRecipientIndex--;
                state.ReadRecipientIndex = 0;
                pageIndex = state.ShowRecipientIndex;
                skip      = pageSize * pageIndex;
                await sc.Context.SendActivityAsync(ResponseManager.GetResponse(FindContactResponses.AlreadyLastPage));
            }

            var options = new PromptOptions
            {
                Choices = new List <Choice>(),
                Prompt  = ResponseManager.GetResponse(FindContactResponses.ConfirmMultiplContactEmailSinglePage, new StringDictionary()
                {
                    { "UserName", confirmedPerson.DisplayName }
                })
            };

            if (!isSinglePage)
            {
                options.Prompt = ResponseManager.GetResponse(FindContactResponses.ConfirmMultiplContactEmailMultiPage, new StringDictionary()
                {
                    { "UserName", confirmedPerson.DisplayName }
                });
            }

            for (var i = 0; i < emailList.Count; i++)
            {
                var user        = confirmedPerson;
                var mailAddress = emailList[i] ?? user.UserPrincipalName;

                var choice = new Choice()
                {
                    Value    = $"{user.DisplayName}: {mailAddress}",
                    Synonyms = new List <string> {
                        (options.Choices.Count + 1).ToString(), user.DisplayName, user.DisplayName.ToLower(), mailAddress
                    },
                };
                var userName = user.UserPrincipalName?.Split("@").FirstOrDefault() ?? user.UserPrincipalName;
                if (!string.IsNullOrEmpty(userName))
                {
                    choice.Synonyms.Add(userName);
                    choice.Synonyms.Add(userName.ToLower());
                }

                if (skip <= 0)
                {
                    if (options.Choices.Count >= pageSize)
                    {
                        options.Prompt.Speak = SpeechUtility.ListToSpeechReadyString(options, ReadPreference.Chronological, ConfigData.GetInstance().MaxReadSize);
                        options.Prompt.Text += "\r\n" + GetSelectPromptEmailString(options, true);
                        options.RetryPrompt  = ResponseManager.GetResponse(EmailSharedResponses.NoChoiceOptionsRetry);
                        return(options);
                    }

                    options.Choices.Add(choice);
                }
                else
                {
                    skip--;
                }
            }

            options.Prompt.Speak = SpeechUtility.ListToSpeechReadyString(options, ReadPreference.Chronological, ConfigData.GetInstance().MaxReadSize);
            options.Prompt.Text += "\r\n" + GetSelectPromptEmailString(options, true);
            options.RetryPrompt  = ResponseManager.GetResponse(EmailSharedResponses.NoChoiceOptionsRetry);
            return(options);
        }
        private async Task <PromptOptions> GenerateOptionsForEmailAsync(WaterfallStepContext sc, List <CustomizedPerson> unconfirmedPerson, ITurnContext context, bool isSinglePage = true, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await Accessor.GetAsync(context, cancellationToken : cancellationToken);

            var pageIndex  = state.MeetingInfo.ContactInfor.ShowContactsIndex;
            var pageSize   = 3;
            var skip       = pageSize * pageIndex;
            var emailCount = 0;

            foreach (var person in unconfirmedPerson)
            {
                emailCount += person.Emails.ToList().Count;
            }

            // Go back to the last page when reaching the end.
            if (skip >= emailCount && pageIndex > 0)
            {
                state.MeetingInfo.ContactInfor.ShowContactsIndex--;
                pageIndex = state.MeetingInfo.ContactInfor.ShowContactsIndex;
                skip      = pageSize * pageIndex;
                var activity = TemplateManager.GenerateActivityForLocale(FindContactResponses.AlreadyLastPage);
                await sc.Context.SendActivityAsync(activity, cancellationToken);
            }

            var options = new PromptOptions
            {
                Choices = new List <Choice>(),
                Prompt  = TemplateManager.GenerateActivityForLocale(
                    unconfirmedPerson.Count == 1 ? FindContactResponses.ConfirmMultipleContactEmailSinglePage : FindContactResponses.ConfirmMultipleContactNameSinglePage,
                    new
                {
                    ContactName = state.MeetingInfo.ContactInfor.CurrentContactName
                }) as Activity
            };

            if (!isSinglePage)
            {
                options.Prompt = TemplateManager.GenerateActivityForLocale(
                    unconfirmedPerson.Count == 1 ? FindContactResponses.ConfirmMultipleContactEmailMultiPage : FindContactResponses.ConfirmMultipleContactNameMultiPage,
                    new
                {
                    ContactName = state.MeetingInfo.ContactInfor.CurrentContactName
                }) as Activity;
            }

            foreach (var person in unconfirmedPerson)
            {
                var emailList = person.Emails.ToList();
                for (var i = 0; i < emailList.Count; i++)
                {
                    var user        = person;
                    var mailAddress = emailList[i].Address ?? user.UserPrincipalName;

                    var choice = new Choice()
                    {
                        Value    = $"{user.DisplayName}: {mailAddress}",
                        Synonyms = new List <string> {
                            (options.Choices.Count + 1).ToString(), user.DisplayName, user.DisplayName.ToLower(), mailAddress
                        },
                    };
                    var userName = user.UserPrincipalName?.Split("@").FirstOrDefault() ?? user.UserPrincipalName;
                    if (!string.IsNullOrEmpty(userName))
                    {
                        choice.Synonyms.Add(userName);
                        choice.Synonyms.Add(userName.ToLower());
                    }

                    if (skip <= 0)
                    {
                        if (options.Choices.Count >= pageSize)
                        {
                            options.Prompt.Speak = SpeechUtility.ListToSpeechReadyString(options, ReadPreference.Chronological, ConfigData.GetInstance().MaxReadSize);
                            options.Prompt.Text += "\r\n" + GetSelectPromptEmailString(options, true, unconfirmedPerson.Count != 1);
                            options.RetryPrompt  = TemplateManager.GenerateActivityForLocale(CalendarSharedResponses.DidntUnderstandMessage) as Activity;
                            return(options);
                        }

                        options.Choices.Add(choice);
                    }
                    else
                    {
                        skip--;
                    }
                }
            }

            options.Prompt.Speak = SpeechUtility.ListToSpeechReadyString(options, ReadPreference.Chronological, ConfigData.GetInstance().MaxReadSize);
            options.Prompt.Text += "\r\n" + GetSelectPromptEmailString(options, true, unconfirmedPerson.Count != 1);
            options.RetryPrompt  = TemplateManager.GenerateActivityForLocale(CalendarSharedResponses.DidntUnderstandMessage) as Activity;
            return(options);
        }
        /// <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));
            }
        }
Example #15
0
        protected async Task GetRouteDirectionsViewCards(DialogContext sc, RouteDirections routeDirections)
        {
            var routes = routeDirections.Routes;
            var state  = await Accessor.GetAsync(sc.Context);

            var cardData = new List <RouteDirectionsModel>();
            var routeId  = 0;

            if (routes != null)
            {
                state.FoundRoutes = routes.ToList();

                var destination = state.Destination;

                foreach (var route in routes)
                {
                    var travelTimeSpan  = TimeSpan.FromSeconds(route.Summary.TravelTimeInSeconds);
                    var trafficTimeSpan = TimeSpan.FromSeconds(route.Summary.TrafficDelayInSeconds);

                    destination.Provider.Add(routeDirections.Provider);

                    // Set card data with formatted time strings and distance converted to miles
                    var routeDirectionsModel = new RouteDirectionsModel()
                    {
                        Name                    = destination.Name,
                        Street                  = destination.Street,
                        City                    = destination.City,
                        AvailableDetails        = destination.AvailableDetails,
                        Hours                   = destination.Hours,
                        PointOfInterestImageUrl = destination.PointOfInterestImageUrl,
                        TravelTime              = GetShortTravelTimespanString(travelTimeSpan),
                        DelayStatus             = GetFormattedTrafficDelayString(trafficTimeSpan),
                        Distance                = $"{(route.Summary.LengthInMeters / 1609.344).ToString("N1")} {PointOfInterestSharedStrings.MILES_ABBREVIATION}",
                        ETA                 = route.Summary.ArrivalTime.ToShortTimeString(),
                        TravelTimeSpeak     = GetFormattedTravelTimeSpanString(travelTimeSpan),
                        TravelDelaySpeak    = GetFormattedTrafficDelayString(trafficTimeSpan),
                        ProviderDisplayText = string.Format($"{PointOfInterestSharedStrings.POWERED_BY} **{{0}}**", destination.Provider.Aggregate((j, k) => j + " & " + k).ToString()),
                        Speak               = GetFormattedTravelTimeSpanString(travelTimeSpan)
                    };

                    cardData.Add(routeDirectionsModel);
                    routeId++;
                }

                if (cardData.Count() > 1)
                {
                    var cards = new List <Card>();
                    foreach (var data in cardData)
                    {
                        cards.Add(new Card("PointOfInterestDetailsWithRoute", data));
                    }

                    var replyMessage = ResponseManager.GetCardResponse(POISharedResponses.MultipleRoutesFound, cards);
                    replyMessage.Speak = SpeechUtility.ListToSpeechReadyString(replyMessage);
                    await sc.Context.SendActivityAsync(replyMessage);
                }
                else
                {
                    var card         = new Card("PointOfInterestDetailsWithRoute", cardData.SingleOrDefault());
                    var replyMessage = ResponseManager.GetCardResponse(POISharedResponses.SingleRouteFound, card, tokens: null);
                    replyMessage.Speak = SpeechUtility.ListToSpeechReadyString(replyMessage);
                    await sc.Context.SendActivityAsync(replyMessage);
                }
            }
            else
            {
                var replyMessage = ResponseManager.GetResponse(POISharedResponses.NoLocationsFound);
                await sc.Context.SendActivityAsync(replyMessage);
            }
        }
Example #16
0
        protected async Task <List <PointOfInterestModel> > GetPointOfInterestLocationCards(DialogContext sc, List <PointOfInterestModel> pointOfInterestList)
        {
            var state = await Accessor.GetAsync(sc.Context);

            var service        = ServiceManager.InitMapsService(Services);
            var addressService = ServiceManager.InitAddressMapsService(Services);

            if (pointOfInterestList != null && pointOfInterestList.Count > 0)
            {
                for (int i = 0; i < pointOfInterestList.Count; i++)
                {
                    if (sc.ActiveDialog.Id.Equals(Actions.CheckForCurrentLocation))
                    {
                        pointOfInterestList[i] = await addressService.GetPointOfInterestDetailsAsync(pointOfInterestList[i]);
                    }
                    else
                    {
                        pointOfInterestList[i] = await service.GetPointOfInterestDetailsAsync(pointOfInterestList[i]);
                    }

                    // Increase by one to avoid zero based options to the user which are confusing
                    pointOfInterestList[i].Index = i + 1;

                    if (string.IsNullOrEmpty(pointOfInterestList[i].PointOfInterestImageUrl))
                    {
                        pointOfInterestList[i].PointOfInterestImageUrl = GetCardImageUri(FallbackPointOfInterestImageFileName);
                    }

                    if (string.IsNullOrEmpty(pointOfInterestList[i].Name))
                    {
                        pointOfInterestList[i].Name = pointOfInterestList[i].Street;
                    }

                    pointOfInterestList[i].ProviderDisplayText = string.Format($"{PointOfInterestSharedStrings.POWERED_BY} **{{0}}**", pointOfInterestList[i].Provider.Aggregate((j, k) => j + "&" + k).ToString());

                    // If multiple points of interest share the same name, use their combined name & address as the speak property.
                    // Otherwise, just use the name.
                    if (pointOfInterestList.Where(x => x.Name == pointOfInterestList[i].Name).Skip(1).Any())
                    {
                        var promptTemplate     = POISharedResponses.PointOfInterestSuggestedActionName;
                        var promptReplacements = new StringDictionary
                        {
                            { "Name", pointOfInterestList[i].Name },
                            { "Address", pointOfInterestList[i].Street },
                        };
                        pointOfInterestList[i].Speak = ResponseManager.GetResponse(promptTemplate, promptReplacements).Text;
                    }
                    else
                    {
                        pointOfInterestList[i].Speak = pointOfInterestList[i].Name;
                    }
                }

                state.LastFoundPointOfInterests = pointOfInterestList;

                if (pointOfInterestList.Count() > 1)
                {
                    var templateId = POISharedResponses.MultipleLocationsFound;
                    var cards      = new List <Card>();

                    foreach (var pointOfInterest in pointOfInterestList)
                    {
                        cards.Add(new Card("PointOfInterestDetails", pointOfInterest));
                    }

                    var replyMessage = ResponseManager.GetCardResponse(templateId, cards);

                    replyMessage.Speak = SpeechUtility.ListToSpeechReadyString(replyMessage);

                    await sc.Context.SendActivityAsync(replyMessage);
                }
                else
                {
                    var templateId = POISharedResponses.SingleLocationFound;

                    var card         = new Card("PointOfInterestDetails", state.LastFoundPointOfInterests[0]);
                    var replyMessage = ResponseManager.GetCardResponse(templateId, card, tokens: null);
                    replyMessage.Speak = SpeechUtility.ListToSpeechReadyString(replyMessage);

                    await sc.Context.SendActivityAsync(replyMessage);
                }
            }
            else
            {
                var replyMessage = ResponseManager.GetResponse(POISharedResponses.NoLocationsFound);
                await sc.Context.SendActivityAsync(replyMessage);
            }

            return(pointOfInterestList);
        }