private async Task <bool> QueueFirstMatchAsync(SequenceContext sequenceContext, DialogEvent dialogEvent, bool preBubble, CancellationToken cancellationToken) { var selection = await Selector.Select(sequenceContext, cancellationToken).ConfigureAwait(false); if (selection.Any()) { var evt = Triggers[selection.First()]; await sequenceContext.DebuggerStepAsync(evt, dialogEvent, cancellationToken).ConfigureAwait(false); Trace.TraceInformation($"Executing Dialog: {Id} Rule[{selection}]: {evt.GetType().Name}: {evt.GetExpression(new ExpressionEngine())}"); var changes = await evt.ExecuteAsync(sequenceContext).ConfigureAwait(false); if (changes != null && changes.Count > 0) { sequenceContext.QueueChanges(changes[0]); return(true); } } return(false); }
protected async Task <bool> ProcessEventAsync(SequenceContext sequenceContext, DialogEvent dialogEvent, bool preBubble, CancellationToken cancellationToken = default) { // Save into turn sequenceContext.GetState().SetValue(TurnPath.DIALOGEVENT, dialogEvent); EnsureDependenciesInstalled(); // Look for triggered evt var handled = await QueueFirstMatchAsync(sequenceContext, dialogEvent, preBubble, cancellationToken).ConfigureAwait(false); if (handled) { return(true); } // Default processing if (preBubble) { switch (dialogEvent.Name) { case AdaptiveEvents.BeginDialog: if (sequenceContext.GetState().GetBoolValue(TurnPath.ACTIVITYPROCESSED) == false) { // Emit leading ActivityReceived event var activityReceivedEvent = new DialogEvent() { Name = AdaptiveEvents.ActivityReceived, Value = sequenceContext.Context.Activity, Bubble = false }; handled = await ProcessEventAsync(sequenceContext, dialogEvent : activityReceivedEvent, preBubble : true, cancellationToken : cancellationToken).ConfigureAwait(false); } break; case AdaptiveEvents.ActivityReceived: if (sequenceContext.Context.Activity.Type == ActivityTypes.Message) { // Recognize utterance (ignore handled) var recognizeUtteranceEvent = new DialogEvent { Name = AdaptiveEvents.RecognizeUtterance, Value = sequenceContext.Context.Activity, Bubble = false }; await ProcessEventAsync(sequenceContext, dialogEvent : recognizeUtteranceEvent, preBubble : true, cancellationToken : cancellationToken).ConfigureAwait(false); // Emit leading RecognizedIntent event var recognized = sequenceContext.GetState().GetValue <RecognizerResult>(TurnPath.RECOGNIZED); var recognizedIntentEvent = new DialogEvent { Name = AdaptiveEvents.RecognizedIntent, Value = recognized, Bubble = false }; handled = await ProcessEventAsync(sequenceContext, dialogEvent : recognizedIntentEvent, preBubble : true, cancellationToken : cancellationToken).ConfigureAwait(false); } // Has an interruption occured? // - Setting this value to true causes any running inputs to re-prompt when they're // continued. The developer can clear this flag if they want the input to instead // process the users uterrance when its continued. if (handled) { sequenceContext.GetState().SetValue(TurnPath.INTERRUPTED, true); } break; case AdaptiveEvents.RecognizeUtterance: if (sequenceContext.Context.Activity.Type == ActivityTypes.Message) { // Recognize utterance var recognized = await OnRecognize(sequenceContext, cancellationToken).ConfigureAwait(false); sequenceContext.GetState().SetValue(TurnPath.RECOGNIZED, recognized); var(name, score) = recognized.GetTopScoringIntent(); sequenceContext.GetState().SetValue(TurnPath.TOPINTENT, name); sequenceContext.GetState().SetValue(TurnPath.TOPSCORE, score); if (Recognizer != null) { await sequenceContext.DebuggerStepAsync(Recognizer, AdaptiveEvents.RecognizeUtterance, cancellationToken).ConfigureAwait(false); } handled = true; } break; } } else { switch (dialogEvent.Name) { case AdaptiveEvents.BeginDialog: if (sequenceContext.GetState().GetBoolValue(TurnPath.ACTIVITYPROCESSED) == false) { var activityReceivedEvent = new DialogEvent { Name = AdaptiveEvents.ActivityReceived, Value = sequenceContext.Context.Activity, Bubble = false }; handled = await ProcessEventAsync(sequenceContext, dialogEvent : activityReceivedEvent, preBubble : false, cancellationToken : cancellationToken).ConfigureAwait(false); } break; case AdaptiveEvents.ActivityReceived: var activity = sequenceContext.Context.Activity; if (activity.Type == ActivityTypes.Message) { // Empty sequence? if (!sequenceContext.Actions.Any()) { // Emit trailing unknownIntent event var unknownIntentEvent = new DialogEvent { Name = AdaptiveEvents.UnknownIntent, Bubble = false }; handled = await ProcessEventAsync(sequenceContext, dialogEvent : unknownIntentEvent, preBubble : false, cancellationToken : cancellationToken).ConfigureAwait(false); } else { handled = false; } } // Has an interruption occured? // - Setting this value to true causes any running inputs to re-prompt when they're // continued. The developer can clear this flag if they want the input to instead // process the users uterrance when its continued. if (handled) { sequenceContext.GetState().SetValue(TurnPath.INTERRUPTED, true); } break; } } return(handled); }