forked from microsoft/BotBuilder-Samples
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[C#] Add demo-RollerSkill sample (microsoft#112)
* Add C# version of demo-RollerSkill sample * Update sample to BotBuilder v3.5.9 * [CSharp-RollerSkill] Update to BotBuilder v3.8.0
- Loading branch information
Showing
21 changed files
with
1,302 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
namespace RollerSkillBot | ||
{ | ||
using System.Web.Http; | ||
using Newtonsoft.Json; | ||
using Newtonsoft.Json.Serialization; | ||
|
||
public static class WebApiConfig | ||
{ | ||
public static void Register(HttpConfiguration config) | ||
{ | ||
// Json settings | ||
config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; | ||
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); | ||
config.Formatters.JsonFormatter.SerializerSettings.Formatting = Formatting.Indented; | ||
JsonConvert.DefaultSettings = () => new JsonSerializerSettings() | ||
{ | ||
ContractResolver = new CamelCasePropertyNamesContractResolver(), | ||
Formatting = Newtonsoft.Json.Formatting.Indented, | ||
NullValueHandling = NullValueHandling.Ignore, | ||
}; | ||
|
||
// Web API configuration and services | ||
|
||
// Web API routes | ||
config.MapHttpAttributeRoutes(); | ||
|
||
config.Routes.MapHttpRoute( | ||
name: "DefaultApi", | ||
routeTemplate: "api/{controller}/{id}", | ||
defaults: new { id = RouteParameter.Optional }); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
namespace RollerSkillBot | ||
{ | ||
using System.Net; | ||
using System.Net.Http; | ||
using System.Threading.Tasks; | ||
using System.Web.Http; | ||
using Microsoft.Bot.Builder.Dialogs; | ||
using Microsoft.Bot.Connector; | ||
using RollerSkillBot.Dialogs; | ||
|
||
[BotAuthentication] | ||
public class MessagesController : ApiController | ||
{ | ||
/// <summary> | ||
/// POST: api/Messages | ||
/// Receive a message from a user and reply to it | ||
/// </summary> | ||
public async Task<HttpResponseMessage> Post([FromBody]Activity activity) | ||
{ | ||
await Conversation.SendAsync(activity, () => new RootDispatchDialog()); | ||
|
||
var response = Request.CreateResponse(HttpStatusCode.OK); | ||
|
||
return response; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
namespace RollerSkillBot.Dialogs | ||
{ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Threading.Tasks; | ||
using Microsoft.Bot.Builder.Dialogs; | ||
using RollerSkillBot.Properties; | ||
|
||
[Serializable] | ||
public class CreateGameDialog : IDialog<GameData> | ||
{ | ||
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); | ||
} | ||
|
||
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); | ||
} | ||
} | ||
|
||
private async Task DiceNumberReceivedAsync(IDialogContext context, IAwaitable<long> result) | ||
{ | ||
GameData game; | ||
if (context.UserData.TryGetValue<GameData>(Utils.GameDataKey, out game)) | ||
{ | ||
game.Count = await result; | ||
context.UserData.SetValue<GameData>(Utils.GameDataKey, game); | ||
} | ||
|
||
context.Done(game); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
namespace RollerSkillBot.Dialogs | ||
{ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Threading.Tasks; | ||
using Microsoft.Bot.Builder.Dialogs; | ||
using Microsoft.Bot.Connector; | ||
using RollerSkillBot.Properties; | ||
|
||
[Serializable] | ||
public class HelpDialog : IDialog<object> | ||
{ | ||
private const string RollDiceOptionValue = "roll some dice"; | ||
|
||
private const string PlayCrapsOptionValue = "play craps"; | ||
|
||
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); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
namespace RollerSkillBot.Dialogs | ||
{ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Threading.Tasks; | ||
using Microsoft.Bot.Builder.Dialogs; | ||
using Microsoft.Bot.Connector; | ||
using RollerSkillBot.Properties; | ||
|
||
[Serializable] | ||
public class PlayGameDialog : IDialog<object> | ||
{ | ||
private const string RollAgainOptionValue = "roll again"; | ||
|
||
private const string NewGameOptionValue = "new game"; | ||
|
||
private GameData gameData; | ||
|
||
public PlayGameDialog(GameData gameData) | ||
{ | ||
this.gameData = gameData; | ||
} | ||
|
||
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); | ||
} | ||
} | ||
} |
Oops, something went wrong.