private IForm <HotelsQuery> BuildHotelsForm() { OnCompletionAsyncDelegate <HotelsQuery> processHotelsSearch = async(context, state) => { var message = "Searching for hotels"; var speech = @"<speak version=""1.0"" xml:lang=""en-US"">Searching for hotels"; if (!string.IsNullOrEmpty(state.Destination)) { state.Destination = state.Destination.Capitalize(); message += $" in { state.Destination}..."; speech += $" in { state.Destination}..."; } else if (!string.IsNullOrEmpty(state.AirportCode)) { message += $" near {state.AirportCode.ToUpperInvariant()} airport..."; speech += $@" near<break time=""100ms""/>{SSMLHelper.SayAs("characters",state.AirportCode.ToUpperInvariant())} <break time=""200ms""/>airport"; } speech += "</speak>"; var response = context.MakeMessage(); response.Summary = message; response.Speak = speech; response.InputHint = InputHints.IgnoringInput; await context.PostAsync(response); }; return(new FormBuilder <HotelsQuery>() .Field(nameof(HotelsQuery.Destination), (state) => string.IsNullOrEmpty(state.AirportCode)) .Field(nameof(HotelsQuery.AirportCode), (state) => string.IsNullOrEmpty(state.Destination)) .OnCompletion(processHotelsSearch) .Build()); }
private async Task PresentResultsVoiceOnly(IDialogContext context, IEnumerable <Hotel> hotels) { // For voice, we'll limit results to first three otherwise it gets to be too long going through a long list using voice. // Aa well designed skill would offer the user the option to hear "Next Results" if the first ones don't interest them. // Not implemented in this sample. var hotelList = hotels.ToList(); context.ConversationData.SetValue <List <Hotel> >("Hotels", hotelList); // Array of strings for the PromptDialog.Choice buttons - though note these are not spoken, just for debugging use var descriptions = new List <string>(); // Build the spoken prompt listing the results var speakText = new StringBuilder(); speakText.Append($"Here are the first three results: "); for (int count = 1; count < 4; count++) { var hotel = hotelList[count - 1]; descriptions.Add($"{hotel.Name}"); //speakText.Append($"{count}: {hotel.Name}, {hotel.Rating} stars, from ${hotel.PriceStarting} per night. "); speakText.Append($"{count}, {hotel.Name}, from ${hotel.PriceStarting}. "); } // Send the spoken message listing the options separately from the PromptDialog // Currently, PromptDialog built-in recognizer does not work if you have too long a 'speak' // phrase (bug) before the user speaks their choice, so say most ahead of the choice dialog var resultsMessage = context.MakeMessage(); resultsMessage.Speak = speakText.ToString(); resultsMessage.InputHint = InputHints.IgnoringInput; await context.PostAsync(resultsMessage); // Define the choices, plus synonyms for each choice - include the hotel name var choices = new Dictionary <string, IReadOnlyList <string> >() { { "1", new List <string> { "one", hotelList[0].Name, hotelList[0].Name.ToLowerInvariant() } }, { "2", new List <string> { "two", hotelList[1].Name, hotelList[1].Name.ToLowerInvariant() } }, { "3", new List <string> { "three", hotelList[2].Name, hotelList[2].Name.ToLowerInvariant() } }, }; var promptOptions = new PromptOptionsWithSynonyms <string>( prompt: "notused", // prompt is not spoken choices: choices, descriptions: descriptions, speak: SSMLHelper.Speak($"Which one do you want to hear more about?")); PromptDialog.Choice(context, HotelChoiceReceivedAsync, promptOptions); }
public async Task Help(IDialogContext context, LuisResult result) { var response = context.MakeMessage(); response.Summary = "Hi! Try asking me things like 'search for hotels in Seattle', 'search for hotels near LAX airport' or 'show me the reviews of The Bot Resort'"; response.Speak = @"<speak version=""1.0"" xml:lang=""en-US"">Hi! Try asking me things like 'search for hotels in Seattle', " + @"'search for hotels near<break time=""100ms""/>" + SSMLHelper.SayAs("characters", "LAX") + @" <break time=""200ms""/>airport', or 'show me the reviews of The Bot Resort'</speak>"; response.InputHint = InputHints.ExpectingInput; await context.PostAsync(response); context.Wait(this.MessageReceived); }
private async Task DiceChoiceReceivedAsync(IDialogContext context, IAwaitable <string> result) { GameData game; if (context.UserData.TryGetValue <GameData>(Utils.GameDataKey, out game)) { int sides; if (int.TryParse(await result, out sides)) { game.Sides = sides; context.UserData.SetValue <GameData>(Utils.GameDataKey, game); } var promptText = string.Format(Resources.ChooseCount, sides); // TODO: When supported, update to pass Min and Max paramters var promptOption = new PromptOptions <long>(promptText, speak: SSMLHelper.Speak(Utils.RandomPick(Resources.ChooseCountSSML))); var prompt = new PromptDialog.PromptInt64(promptOption, min: 1, max: 100); context.Call <long>(prompt, this.DiceNumberReceivedAsync); } }
public async Task StartAsync(IDialogContext context) { context.UserData.SetValue <GameData>(Utils.GameDataKey, new GameData()); var descriptions = new List <string>() { "4 Sides", "6 Sides", "8 Sides", "10 Sides", "12 Sides", "20 Sides" }; var choices = new Dictionary <string, IReadOnlyList <string> >() { { "4", new List <string> { "four", "for", "4 sided", "4 sides" } }, { "6", new List <string> { "six", "sex", "6 sided", "6 sides" } }, { "8", new List <string> { "eight", "8 sided", "8 sides" } }, { "10", new List <string> { "ten", "10 sided", "10 sides" } }, { "12", new List <string> { "twelve", "12 sided", "12 sides" } }, { "20", new List <string> { "twenty", "20 sided", "20 sides" } } }; var promptOptions = new PromptOptionsWithSynonyms <string>( Resources.ChooseSides, choices: choices, descriptions: descriptions, speak: SSMLHelper.Speak(Utils.RandomPick(Resources.ChooseSidesSSML))); PromptDialog.Choice(context, this.DiceChoiceReceivedAsync, promptOptions); }
public async Task StartAsync(IDialogContext context) { var message = context.MakeMessage(); message.Speak = SSMLHelper.Speak(Resources.HelpSSML); message.InputHint = InputHints.AcceptingInput; message.Attachments = new List <Attachment> { new HeroCard(Resources.HelpTitle) { Buttons = new List <CardAction> { new CardAction(ActionTypes.ImBack, "Roll Dice", value: RollDiceOptionValue), new CardAction(ActionTypes.ImBack, "Play Craps", value: PlayCrapsOptionValue) } }.ToAttachment() }; await context.PostAsync(message); context.Done <object>(null); }
public async Task StartAsync(IDialogContext context) { if (this.gameData == null) { if (!context.UserData.TryGetValue <GameData>(Utils.GameDataKey, out this.gameData)) { // User started session with "roll again" so let's just send them to // the 'CreateGameDialog' context.Done <object>(null); } } int total = 0; var randomGenerator = new Random(); var rolls = new List <int>(); // Generate Rolls for (int i = 0; i < this.gameData.Count; i++) { var roll = randomGenerator.Next(1, this.gameData.Sides); total += roll; rolls.Add(roll); } // Format rolls results var result = string.Join(" . ", rolls.ToArray()); bool multiLine = rolls.Count > 5; var card = new HeroCard() { Subtitle = string.Format( this.gameData.Count > 1 ? Resources.CardSubtitlePlural : Resources.CardSubtitleSingular, this.gameData.Count, this.gameData.Sides), Buttons = new List <CardAction>() { new CardAction(ActionTypes.ImBack, "Roll Again", value: RollAgainOptionValue), new CardAction(ActionTypes.ImBack, "New Game", value: NewGameOptionValue) } }; if (multiLine) { card.Text = result; } else { card.Title = result; } var message = context.MakeMessage(); message.Attachments = new List <Attachment>() { card.ToAttachment() }; // Determine bots reaction for speech purposes string reaction = "normal"; var min = this.gameData.Count; var max = this.gameData.Count * this.gameData.Sides; var score = total / max; if (score == 1) { reaction = "Best"; } else if (score == 0) { reaction = "Worst"; } else if (score <= 0.3) { reaction = "Bad"; } else if (score >= 0.8) { reaction = "Good"; } // Check for special craps rolls if (this.gameData.Type == "Craps") { switch (total) { case 2: case 3: case 12: reaction = "CrapsLose"; break; case 7: reaction = "CrapsSeven"; break; case 11: reaction = "CrapsEleven"; break; default: reaction = "CrapsRetry"; break; } } // Build up spoken response var spoken = string.Empty; if (this.gameData.Turns == 0) { spoken += Utils.RandomPick(Resources.ResourceManager.GetString($"Start{this.gameData.Type}GameSSML")); } spoken += Utils.RandomPick(Resources.ResourceManager.GetString($"{reaction}RollReactionSSML")); message.Speak = SSMLHelper.Speak(spoken); // Increment number of turns and store game to roll again this.gameData.Turns++; context.UserData.SetValue <GameData>(Utils.GameDataKey, this.gameData); // Send card and bots reaction to user. message.InputHint = InputHints.AcceptingInput; await context.PostAsync(message); context.Done <object>(null); }
public async Task Control(IDialogContext context, IAwaitable <IMessageActivity> activity, LuisResult result) { bool isWelcomeDone, firstCommand = false; context.ConversationData.TryGetValue <bool>("WelcomeDone", out isWelcomeDone); context.ConversationData.TryGetValue <bool>("FirstCommand", out firstCommand); // Did we already do this? Has the user followed up an initial query with another one? if (!isWelcomeDone) { var response = context.MakeMessage(); // For display text, use Summary to display large font, italics - this is to emphasize this // is the Skill speaking, not Cortana // Continue the displayed text using the Text property of the response message response.Summary = $"Welcome to the NeoFalcon Navigation!"; response.Text = $"We are analyzing your message: '{(await activity).Text}'..."; // Speak is what is spoken out response.Speak = @"<speak version=""1.0"" xml:lang=""en-US"">Welcome to the Neo Falcon navigation<break time=""1000ms""/></speak>";; // InputHint influences how the microphone behaves response.InputHint = InputHints.IgnoringInput; // Post the response message await context.PostAsync(response); // Set a flag in conversation data to record that we already sent out the Welcome message context.ConversationData.SetValue <bool>("WelcomeDone", true); } //9/21 //var AccessaryQuery = new AccessaryQuery(); EntityRecommendation lightstatus; if (result.TryFindEntity(EntityStatus, out lightstatus)) { lightstatus.Type = "Place"; lightStatus = lightstatus.Entity.ToLowerInvariant(); } var descriptions = new List <string>() { "Drive", "Walk" }; var speakText = new StringBuilder(); for (int count = 1; count < 3; count++) { speakText.Append($"{count}: {descriptions[count - 1]}"); } if (!firstCommand) { var resultsMessage = context.MakeMessage(); //resultsMessage.Speak = speakText.ToString(); resultsMessage.Speak = @"<speak version=""1.0"" xml:lang=""en-US"">There are two transportation available on Neofalcon , " + @" <break time=""1000ms""/> 'first one is Drive'" + @" <break time=""300ms""/> 'second one is Walk '</speak>"; resultsMessage.InputHint = InputHints.IgnoringInput; await context.PostAsync(resultsMessage); context.ConversationData.SetValue <bool>("FirstCommand", true); } else { var resultsMessage = context.MakeMessage(); resultsMessage.Speak = @"<speak version=""1.0"" xml:lang=""en-US"">Drive, " + @" <break time=""1000ms""/> Walk </speak>"; resultsMessage.InputHint = InputHints.IgnoringInput; await context.PostAsync(resultsMessage); } var choices = new Dictionary <string, IReadOnlyList <string> >() { { "1", new List <string> { "one", "Drive", ("Drive").ToLowerInvariant() } }, { "2", new List <string> { "two", "Walk", ("Walk").ToLowerInvariant() } } }; var promptOptions = new PromptOptionsWithSynonyms <string>( prompt: "notused", // prompt is not spoken choices: choices, descriptions: descriptions, speak: SSMLHelper.Speak($"Which one do you want to transport?")); PromptDialog.Choice(context, LightChoiceReceivedAsync, promptOptions); }
public async Task CetusTimeIntent(IDialogContext context, LuisResult result) { var response = context.MakeMessage(); var worldState = CurrentWorldState; TimeSpan timeRemaining = (worldState.cetusCycle.expiry - DateTimeOffset.Now); List <String> timeParts = new List <String>(); if (timeRemaining.Hours >= 1) { timeParts.Add(string.Format(Resources.ResourceManager.GetString("TimePartHour"), timeRemaining.Hours, timeRemaining.Hours == 1 ? "" : "s")); } if (timeRemaining.Minutes >= 1) { timeParts.Add(string.Format(Resources.ResourceManager.GetString("TimePartMinute"), timeRemaining.Minutes, timeRemaining.Minutes == 1 ? "" : "s")); } if (timeRemaining.Seconds >= 1) { timeParts.Add(string.Format(Resources.ResourceManager.GetString("TimePartSecond"), timeRemaining.Seconds, timeRemaining.Seconds == 1 ? "" : "s")); } List <String> timePartResources = new List <string>() { "TimeReadableOnePart", "TimeReadableTwoParts", "TimeReadableThreeParts" }; String timePartStringName = timePartResources[timeParts.Count - 1]; String timePartString = Resources.ResourceManager.GetString(timePartStringName); String timeRemainingPretty = string.Format(timePartString, timeParts.ToArray()); var card = new HeroCard() { Title = string.Format("It's {0} on the Plains.", worldState.cetusCycle.isDay ? "daytime" : "night"), Images = new List <CardImage>() { new CardImage(worldState.cetusCycle.isDay ? "https://i.imgur.com/kllwm5a.jpg" : "https://i.imgur.com/UNgWSQe.jpg") }, Buttons = new List <CardAction>() { new CardAction(ActionTypes.ImBack, "Set Alarm", value: "SET_ALARM"), } }; var message = context.MakeMessage(); message.Attachments = new List <Attachment>() { card.ToAttachment() }; var spoken = string.Empty; spoken = string.Format(Resources.ResourceManager.GetString("PlainsTimeSSML"), worldState.cetusCycle.isDay ? "daytime" : "night", worldState.cetusCycle.isDay ? "set" : "rise", timeRemainingPretty ); message.Speak = SSMLHelper.Speak(spoken); //response.Text = spoken; //response.InputHint = InputHints.ExpectingInput; message.InputHint = InputHints.AcceptingInput; await context.PostAsync(message); context.Done <object>(null); //context.Wait(MessageReceived); }