protected Task <bool> EndCurrentActionAsync(SequenceContext sequenceContext, CancellationToken cancellationToken = default)
        {
            if (sequenceContext.Actions.Any())
            {
                sequenceContext.Actions.RemoveAt(0);
            }

            return(Task.FromResult(false));
        }
        /// <summary>
        /// Read event queues from memory.
        /// </summary>
        /// <param name="context">Context for memory.</param>
        /// <returns>Event queues.</returns>
        public static EntityEvents Read(SequenceContext context)
        {
            var dcState = context.GetState();

            if (!dcState.TryGetValue <EntityEvents>(Events, out var queues))
            {
                queues = new EntityEvents();
            }

            return(queues);
        }
        protected async Task <DialogTurnResult> OnEndOfActionsAsync(SequenceContext sequenceContext, CancellationToken cancellationToken = default)
        {
            // End dialog and return result
            if (sequenceContext.ActiveDialog != null)
            {
                if (ShouldEnd(sequenceContext))
                {
                    sequenceContext.State.TryGetValue <object>(DefaultResultProperty, out var result);
                    return(await sequenceContext.EndDialogAsync(result, cancellationToken).ConfigureAwait(false));
                }

                return(EndOfTurn);
            }

            return(new DialogTurnResult(DialogTurnStatus.Cancelled));
        }
        protected async Task <RecognizerResult> OnRecognize(SequenceContext sequenceContext, CancellationToken cancellationToken = default)
        {
            var context = sequenceContext.Context;

            if (Recognizer != null)
            {
                var result = await Recognizer.RecognizeAsync(sequenceContext, cancellationToken).ConfigureAwait(false);

                if (result.Intents.Any())
                {
                    // just deal with topIntent
                    IntentScore topScore  = null;
                    var         topIntent = string.Empty;
                    foreach (var intent in result.Intents)
                    {
                        if (topScore == null || topScore.Score < intent.Value.Score)
                        {
                            topIntent = intent.Key;
                            topScore  = intent.Value;
                        }
                    }

                    result.Intents.Clear();
                    result.Intents.Add(topIntent, topScore);
                }
                else
                {
                    result.Intents.Add("None", new IntentScore {
                        Score = 0.0
                    });
                }

                return(result);
            }

            // none intent if there is no recognizer
            return(new RecognizerResult
            {
                Text = context.Activity.Text ?? string.Empty,
                Intents = new Dictionary <string, IntentScore> {
                    { "None", new IntentScore {
                          Score = 0.0
                      } }
                },
            });
        }
        public override DialogContext CreateChildContext(DialogContext dc)
        {
            var activeDialogState = dc.ActiveDialog.State as Dictionary <string, object>;
            var state             = activeDialogState[AdaptiveKey] as AdaptiveDialogState;

            if (state == null)
            {
                state = new AdaptiveDialogState();
                activeDialogState[AdaptiveKey] = state;
            }

            if (state.Actions != null && state.Actions.Any())
            {
                var ctx = new SequenceContext(this.Dialogs, dc, state.Actions.First(), state.Actions, changeTurnKey, this.Dialogs);
                ctx.Parent = dc;
                return(ctx);
            }

            return(null);
        }
        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);
        }
        private SequenceContext ToSequenceContext(DialogContext dc)
        {
            var activeDialogState = dc.ActiveDialog.State as Dictionary <string, object>;
            var state             = activeDialogState[AdaptiveKey] as AdaptiveDialogState;

            if (state == null)
            {
                state = new AdaptiveDialogState();
                activeDialogState[AdaptiveKey] = state;
            }

            if (state.Actions == null)
            {
                state.Actions = new List <ActionState>();
            }

            var sequenceContext = new SequenceContext(dc.Dialogs, dc, new DialogState {
                DialogStack = dc.Stack
            }, state.Actions, changeTurnKey, this.Dialogs);

            sequenceContext.Parent = dc.Parent;
            return(sequenceContext);
        }
        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);
        }
        protected async Task <RecognizerResult> OnRecognize(SequenceContext sequenceContext, CancellationToken cancellationToken = default)
        {
            var context    = sequenceContext.Context;
            var noneIntent = new RecognizerResult
            {
                Text    = context.Activity.Text ?? string.Empty,
                Intents = new Dictionary <string, IntentScore> {
                    { "None", new IntentScore {
                          Score = 0.0
                      } }
                },
                Entities = JObject.Parse("{}")
            };
            var text = context.Activity.Text;

            if (context.Activity.Value != null)
            {
                var value = JObject.FromObject(context.Activity.Value);

                // Check for submission of an adaptive card
                if (string.IsNullOrEmpty(text) && value.Property("intent") != null)
                {
                    // Map submitted values to a recognizer result
                    var recognized = new RecognizerResult {
                        Text = string.Empty
                    };

                    foreach (var property in value.Properties())
                    {
                        if (property.Name.ToLower() == "intent")
                        {
                            recognized.Intents[property.Value.ToString()] = new IntentScore {
                                Score = 1.0
                            };
                        }
                        else
                        {
                            if (recognized.Entities.Property(property.Name) == null)
                            {
                                recognized.Entities[property.Name] = new JArray(property.Value);
                            }
                            else
                            {
                                ((JArray)recognized.Entities[property.Name]).Add(property.Value);
                            }
                        }
                    }

                    return(recognized);
                }
            }

            if (Recognizer != null)
            {
                var result = await Recognizer.RecognizeAsync(context, cancellationToken).ConfigureAwait(false);

                // only allow one intent
                var topIntent = result.GetTopScoringIntent();
                result.Intents.Clear();
                result.Intents.Add(topIntent.intent, new IntentScore {
                    Score = topIntent.score
                });
                return(result);
            }

            return(noneIntent);
        }
 /// <summary>
 /// Write state into memory.
 /// </summary>
 /// <param name="context">Memory context.</param>
 public void Write(SequenceContext context)
 => context.GetState().SetValue(Events, this);