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