Skip to content
This repository was archived by the owner on Jun 30, 2022. It is now read-only.

Commit dd32c7a

Browse files
authored
[POI] add ShouldInterrupt for SelectPointOfInterestPrompt, SelectActionPrompt (#2268)
* Based on how RouterDialog handles DialogTurnStatus.Empty * Add test RouteToPointOfInterestAndInterruptTest * fix selectAction (Teams supports 1.1?)
1 parent 921c20f commit dd32c7a

File tree

4 files changed

+100
-3
lines changed

4 files changed

+100
-3
lines changed

skills/csharp/pointofinterestskill/Content/PointOfInterestOverview.1.0.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,12 @@
6161
],
6262
"selectAction": {
6363
"type": "Action.Submit",
64-
"data": "{SubmitText}"
64+
"data": {
65+
"msteams": {
66+
"type": "imBack",
67+
"value": "{SubmitText}"
68+
}
69+
}
6570
}
6671
}
6772
],

skills/csharp/pointofinterestskill/Dialogs/PointOfInterestDialogBase.cs

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ public PointOfInterestDialogBase(
8181

8282
AddDialog(new TextPrompt(Actions.CurrentLocationPrompt));
8383
AddDialog(new ConfirmPrompt(Actions.ConfirmPrompt) { Style = ListStyle.Auto, });
84-
AddDialog(new ChoicePrompt(Actions.SelectPointOfInterestPrompt) { Style = ListStyle.None });
85-
AddDialog(new ChoicePrompt(Actions.SelectActionPrompt) { Style = ListStyle.None });
84+
AddDialog(new ChoicePrompt(Actions.SelectPointOfInterestPrompt, InterruptablePromptValidator) { Style = ListStyle.None });
85+
AddDialog(new ChoicePrompt(Actions.SelectActionPrompt, InterruptablePromptValidator) { Style = ListStyle.None });
8686
AddDialog(new ChoicePrompt(Actions.SelectRoutePrompt) { ChoiceOptions = new ChoiceFactoryOptions { InlineSeparator = string.Empty, InlineOr = string.Empty, InlineOrMore = string.Empty, IncludeNumbers = true } });
8787
}
8888

@@ -113,8 +113,29 @@ public static Activity CreateOpenDefaultAppReply(Activity activity, PointOfInter
113113
return replyEvent;
114114
}
115115

116+
public override async Task<DialogTurnResult> ContinueDialogAsync(DialogContext outerDc, CancellationToken cancellationToken = default(CancellationToken))
117+
{
118+
var result = await base.ContinueDialogAsync(outerDc, cancellationToken);
119+
var state = await Accessor.GetAsync(outerDc.Context);
120+
if (state.ShouldInterrupt)
121+
{
122+
// Assume already call CancelAllDialogsAsync
123+
// TODO Empty indicates RouteAsync in RouterDialog
124+
state.ShouldInterrupt = false;
125+
return new DialogTurnResult(DialogTurnStatus.Empty);
126+
}
127+
else
128+
{
129+
return result;
130+
}
131+
}
132+
116133
protected override async Task<DialogTurnResult> OnBeginDialogAsync(DialogContext dc, object options, CancellationToken cancellationToken = default(CancellationToken))
117134
{
135+
// Clear interrupt state
136+
var state = await Accessor.GetAsync(dc.Context);
137+
state.ShouldInterrupt = false;
138+
118139
return await base.OnBeginDialogAsync(dc, options, cancellationToken);
119140
}
120141

@@ -183,6 +204,12 @@ protected async Task<DialogTurnResult> ProcessCurrentLocationSelection(Waterfall
183204
try
184205
{
185206
var state = await Accessor.GetAsync(sc.Context);
207+
208+
if (state.ShouldInterrupt)
209+
{
210+
return await sc.CancelAllDialogsAsync();
211+
}
212+
186213
var cancelMessage = ResponseManager.GetResponse(POISharedResponses.CancellingMessage);
187214

188215
if (sc.Result != null)
@@ -323,6 +350,12 @@ protected async Task<DialogTurnResult> ProcessPointOfInterestSelection(Waterfall
323350
try
324351
{
325352
var state = await Accessor.GetAsync(sc.Context);
353+
354+
if (state.ShouldInterrupt)
355+
{
356+
return await sc.CancelAllDialogsAsync();
357+
}
358+
326359
var defaultReplyMessage = ResponseManager.GetResponse(POISharedResponses.GetRouteToActiveLocationLater);
327360

328361
if (sc.Result != null)
@@ -404,6 +437,11 @@ protected async Task<DialogTurnResult> ProcessPointOfInterestAction(WaterfallSte
404437
{
405438
var state = await Accessor.GetAsync(sc.Context);
406439

440+
if (state.ShouldInterrupt)
441+
{
442+
return await sc.CancelAllDialogsAsync();
443+
}
444+
407445
var choice = sc.Result as FoundChoice;
408446
int choiceIndex = choice.Index;
409447

@@ -827,6 +865,33 @@ private string GetCardImageUri(string imagePath)
827865
return $"{serverUrl}/images/{imagePath}";
828866
}
829867

868+
private async Task<bool> InterruptablePromptValidator<T>(PromptValidatorContext<T> promptContext, CancellationToken cancellationToken)
869+
{
870+
if (promptContext.Recognized.Succeeded)
871+
{
872+
return true;
873+
}
874+
else
875+
{
876+
var locale = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
877+
var localeConfig = Services.CognitiveModelSets[locale];
878+
localeConfig.LuisServices.TryGetValue("PointOfInterest", out var poiService);
879+
var poiResult = await poiService.RecognizeAsync<PointOfInterestLuis>(promptContext.Context, CancellationToken.None);
880+
var topIntent = poiResult.TopIntent();
881+
882+
if (topIntent.score > 0.5 && topIntent.intent != PointOfInterestLuis.Intent.None)
883+
{
884+
var state = await Accessor.GetAsync(promptContext.Context);
885+
state.ShouldInterrupt = true;
886+
return true;
887+
}
888+
else
889+
{
890+
return false;
891+
}
892+
}
893+
}
894+
830895
private class ImageSize
831896
{
832897
public const int RouteWidth = 440;

skills/csharp/pointofinterestskill/Models/PointOfInterestSkillState.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ public PointOfInterestSkillState()
2525

2626
public List<RouteDirections.Summary> FoundRoutes { get; set; }
2727

28+
public bool ShouldInterrupt { get; set; }
29+
2830
public string Keyword { get; set; }
2931

3032
public string Address { get; set; }

skills/csharp/tests/pointofinterestskill.tests/Flow/PointOfInterestDialogTests.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,31 @@ await GetTestFlow()
119119
.StartTestAsync();
120120
}
121121

122+
/// <summary>
123+
/// Find points of interest nearby with interruptions.
124+
/// </summary>
125+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
126+
[TestMethod]
127+
public async Task RouteToPointOfInterestAndInterruptTest()
128+
{
129+
await GetTestFlow()
130+
.Send(BaseTestUtterances.LocationEvent)
131+
.Send(FindPointOfInterestUtterances.WhatsNearby)
132+
.AssertReply(AssertContains(POISharedResponses.MultipleLocationsFound, new string[] { CardStrings.Overview }))
133+
.Send(FindPointOfInterestUtterances.WhatsNearby)
134+
.AssertReply(AssertContains(POISharedResponses.MultipleLocationsFound, new string[] { CardStrings.Overview }))
135+
.Send(BaseTestUtterances.OptionOne)
136+
.AssertReply(AssertContains(null, new string[] { CardStrings.DetailsNoCall }))
137+
.Send(FindPointOfInterestUtterances.WhatsNearby)
138+
.AssertReply(AssertContains(POISharedResponses.MultipleLocationsFound, new string[] { CardStrings.Overview }))
139+
.Send(BaseTestUtterances.OptionOne)
140+
.AssertReply(AssertContains(null, new string[] { CardStrings.DetailsNoCall }))
141+
.Send(BaseTestUtterances.StartNavigation)
142+
.AssertReply(CheckForEvent())
143+
.AssertReply(CompleteDialog())
144+
.StartTestAsync();
145+
}
146+
122147
/// <summary>
123148
/// Find points of interest nearby with multiple routes.
124149
/// </summary>

0 commit comments

Comments
 (0)