예제 #1
0
        public override async Task <DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (options is CancellationToken)
            {
                throw new ArgumentException($"{nameof(options)} cannot be a cancellation token");
            }

            // Ensure planning context
            if (dc is SequenceContext planning)
            {
                var(value, error) = condition.TryEvaluate(dc.GetState());
                var conditionResult = error == null && value != null && (bool)value;
                if (conditionResult == true && TrueScope.Actions.Any())
                {
                    // replace dialog with If True Action Scope
                    return(await dc.ReplaceDialogAsync(this.TrueScope.Id, cancellationToken : cancellationToken).ConfigureAwait(false));
                }
                else if (conditionResult == false && FalseScope.Actions.Any())
                {
                    return(await dc.ReplaceDialogAsync(this.FalseScope.Id, cancellationToken : cancellationToken).ConfigureAwait(false));
                }

                // end dialog since no triggered actions
                return(await planning.EndDialogAsync(cancellationToken : cancellationToken).ConfigureAwait(false));
            }
            else
            {
                throw new Exception("`IfCondition` should only be used in the context of an adaptive dialog.");
            }
        }
        public override async Task <DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (options is CancellationToken)
            {
                throw new ArgumentException($"{nameof(options)} cannot be a cancellation token");
            }

            if (this.Disabled != null && this.Disabled.GetValue(dc.State) == true)
            {
                return(await dc.EndDialogAsync(cancellationToken : cancellationToken).ConfigureAwait(false));
            }

            var(conditionResult, error) = this.Condition.TryGetValue(dc.State);
            if (error == null && conditionResult == true && TrueScope.Actions.Any())
            {
                // replace dialog with If True Action Scope
                return(await dc.ReplaceDialogAsync(this.TrueScope.Id, cancellationToken : cancellationToken).ConfigureAwait(false));
            }
            else if (conditionResult == false && FalseScope.Actions.Any())
            {
                return(await dc.ReplaceDialogAsync(this.FalseScope.Id, cancellationToken : cancellationToken).ConfigureAwait(false));
            }

            // end dialog since no triggered actions
            return(await dc.EndDialogAsync(cancellationToken : cancellationToken).ConfigureAwait(false));
        }
예제 #3
0
        /// <summary>
        /// Called when the dialog is started and pushed onto the dialog stack.
        /// </summary>
        /// <param name="dc">The <see cref="DialogContext"/> for the current turn of conversation.</param>
        /// <param name="options">Optional, initial information to pass to the dialog.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public override async Task <DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (options is CancellationToken)
            {
                throw new ArgumentException($"{nameof(options)} cannot be a cancellation token");
            }

            if (string.IsNullOrEmpty(Condition.ExpressionText))
            {
                throw new InvalidOperationException("Adaptive Dialogs error: Missing predicate condition. Please add a valid predicate to the Condition property of IfCondition().");
            }

            if (Disabled != null && Disabled.GetValue(dc.State))
            {
                return(await dc.EndDialogAsync(cancellationToken : cancellationToken).ConfigureAwait(false));
            }

            var(conditionResult, error) = this.Condition.TryGetValue(dc.State);
            if (error == null && conditionResult == true && TrueScope.Actions.Any())
            {
                // replace dialog with If True Action Scope
                return(await dc.ReplaceDialogAsync(this.TrueScope.Id, cancellationToken : cancellationToken).ConfigureAwait(false));
            }
            else if (conditionResult == false && FalseScope.Actions.Any())
            {
                return(await dc.ReplaceDialogAsync(this.FalseScope.Id, cancellationToken : cancellationToken).ConfigureAwait(false));
            }

            // end dialog since no triggered actions
            return(await dc.EndDialogAsync(cancellationToken : cancellationToken).ConfigureAwait(false));
        }
예제 #4
0
        private async Task <DialogTurnResult> InterruptAsync(DialogContext innerDc, CancellationToken cancellationToken)
        {
            if (innerDc.Context.Activity.Type == ActivityTypes.Message)
            {
                var text        = innerDc.Context.Activity.Text.ToLower();
                var _DialogInfo = await _dialogInfoStateProperty.GetAsync(innerDc.Context);

                switch (text)
                {
                case "lang":


                    await innerDc.ReplaceDialogAsync(nameof(LanguageDialog), "ChangeLanguage",
                                                     cancellationToken : cancellationToken);

                    return(new DialogTurnResult(DialogTurnStatus.Waiting));

                case "restart":
                case "again":
                case "new":
                case "reload":
                    innerDc.Context.Activity.Text = "begin";
                    await innerDc.ReplaceDialogAsync(nameof(LocationDialog), "begin", cancellationToken);

                    return(new DialogTurnResult(DialogTurnStatus.Waiting));

                case "quit":
                case "exit":
                    await innerDc.Context.SendActivityAsync($"Cancelling", cancellationToken : cancellationToken);

                    return(await innerDc.CancelAllDialogsAsync());

                case "sub":
                case "subscriptions":
                    await innerDc.ReplaceDialogAsync(nameof(SubscriptionDialog),
                                                     cancellationToken : cancellationToken);

                    return(new DialogTurnResult(DialogTurnStatus.Waiting));

                case "email":
                    await innerDc.ReplaceDialogAsync(nameof(EmailDialog),
                                                     cancellationToken : cancellationToken);

                    return(new DialogTurnResult(DialogTurnStatus.Waiting));

                case "help":
                    await innerDc.ReplaceDialogAsync(nameof(HelpDialog),
                                                     cancellationToken : cancellationToken);

                    return(new DialogTurnResult(DialogTurnStatus.Waiting));
                }
            }

            return(null);
        }
예제 #5
0
        // Runs when this dialog ends. Handles result of prompt to switch skills or resume waiting dialog.
        protected override async Task <DialogTurnResult> EndComponentAsync(DialogContext outerDc, object result, CancellationToken cancellationToken)
        {
            var skillId = await _skillIdAccessor.GetAsync(outerDc.Context, () => null).ConfigureAwait(false);

            var lastActivity = await _lastActivityAccessor.GetAsync(outerDc.Context, () => null).ConfigureAwait(false);

            outerDc.Context.Activity.Text = lastActivity.Text;

            // Ends this dialog.
            await outerDc.EndDialogAsync().ConfigureAwait(false);

            if ((bool)result)
            {
                // If user decided to switch, replace current skill dialog with new skill dialog.
                var skillDialogArgs = new SkillDialogArgs {
                    SkillId = skillId
                };

                // Start the skill dialog.
                return(await outerDc.ReplaceDialogAsync(skillId, skillDialogArgs).ConfigureAwait(false));
            }
            else
            {
                // Otherwise, continue the waiting skill dialog with the user's previous utterance.
                return(await outerDc.ContinueDialogAsync().ConfigureAwait(false));
            }
        }
예제 #6
0
        public override async Task <DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (options is CancellationToken)
            {
                throw new ArgumentException($"{nameof(options)} cannot be a cancellation token");
            }

            var dcState = dc.GetState();

            if (this.Disabled != null && this.Disabled.GetValue(dcState) == true)
            {
                return(await dc.EndDialogAsync(cancellationToken : cancellationToken).ConfigureAwait(false));
            }

            var dialog = this.ResolveDialog(dc);

            // use bindingOptions to bind to the bound options
            var boundOptions = BindOptions(dc, options);

            // set the activity processed state (default is true)
            dcState.SetValue(TurnPath.ACTIVITYPROCESSED, this.ActivityProcessed.GetValue(dcState));

            // replace dialog with bound options passed in as the options
            return(await dc.ReplaceDialogAsync(dialog.Id, options : boundOptions, cancellationToken : cancellationToken).ConfigureAwait(false));
        }
        private async Task <DialogTurnResult> InterruptAsync(DialogContext innerDc, CancellationToken cancellationToken)
        {
            if (innerDc.Context.Activity.Type == ActivityTypes.Message)
            {
                var text = innerDc.Context.Activity.Text.ToLowerInvariant();

                switch (text)
                {
                case "help":
                case "?":
                    var helpMessage = MessageFactory.Text(HelpMsgText, HelpMsgText, InputHints.ExpectingInput);
                    await innerDc.Context.SendActivityAsync(helpMessage, cancellationToken);

                    return(new DialogTurnResult(DialogTurnStatus.Waiting));

                case "cancel":
                case "quit":
                    var cancelMessage = MessageFactory.Text(CancelMsgText, CancelMsgText, InputHints.IgnoringInput);
                    await innerDc.Context.SendActivityAsync(cancelMessage, cancellationToken);

                    await innerDc.CancelAllDialogsAsync(cancellationToken);

                    return(await innerDc.ReplaceDialogAsync(nameof(MainDialog), null, cancellationToken : cancellationToken));

                    //return await innerDc.CancelAllDialogsAsync(cancellationToken);
                }
            }

            return(null);
        }
예제 #8
0
        /// <summary>
        /// This override is used to test the "abort" command to interrupt skills from the parent and
        /// also to test the "tangent" command to start a tangent and resume a skill.
        /// </summary>
        /// <param name="innerDc">The inner <see cref="DialogContext"/> for the current turn of conversation.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        protected override async Task <DialogTurnResult> OnContinueDialogAsync(DialogContext innerDc, CancellationToken cancellationToken = default)
        {
            // This is an example on how to cancel a SkillDialog that is currently in progress from the parent bot.
            var activeSkill = await _activeSkillProperty.GetAsync(innerDc.Context, () => null, cancellationToken);

            var activity = innerDc.Context.Activity;

            if (activeSkill != null && activity.Type == ActivityTypes.Message && activity.Text.Equals("abort", StringComparison.CurrentCultureIgnoreCase))
            {
                // Cancel all dialogs when the user says abort.
                // The SkillDialog automatically sends an EndOfConversation message to the skill to let the
                // skill know that it needs to end its current dialogs, too.
                await innerDc.CancelAllDialogsAsync(cancellationToken);

                return(await innerDc.ReplaceDialogAsync(InitialDialogId, "Canceled! \n\n What skill would you like to call?", cancellationToken));
            }

            // Sample to test a tangent when in the middle of a skill conversation.
            if (activeSkill != null && activity.Type == ActivityTypes.Message && activity.Text.Equals("tangent", StringComparison.CurrentCultureIgnoreCase))
            {
                // Start tangent.
                return(await innerDc.BeginDialogAsync(nameof(TangentDialog), cancellationToken : cancellationToken));
            }

            return(await base.OnContinueDialogAsync(innerDc, cancellationToken));
        }
        // Runs when this dialog ends. Handles result of prompt to switch skills or resume waiting dialog.
        protected override async Task <DialogTurnResult> EndComponentAsync(DialogContext outerDc, object result, CancellationToken cancellationToken)
        {
            var skillId = await _skillIdAccessor.GetAsync(outerDc.Context, () => null).ConfigureAwait(false);

            var lastActivity = await _lastActivityAccessor.GetAsync(outerDc.Context, () => null).ConfigureAwait(false);

            outerDc.Context.Activity.Text = lastActivity.Text;

            if ((bool)result)
            {
                // If user decided to switch, replace current skill dialog with new skill dialog.
                var skillDialogOptions = new BeginSkillDialogOptions {
                    Activity = outerDc.Context.Activity
                };

                // End the SwitchSkillDialog without triggering the ResumeDialog function of current SkillDialog
                outerDc.Stack.RemoveAt(0);

                // Start the skill dialog.
                return(await outerDc.ReplaceDialogAsync(skillId, skillDialogOptions).ConfigureAwait(false));
            }
            else
            {
                // Ends this dialog.
                return(await outerDc.EndDialogAsync().ConfigureAwait(false));
            }
        }
        private async Task <DialogTurnResult> InterruptAsync(DialogContext innerDc, CancellationToken cancellationToken)
        {
            if (innerDc.Context.Activity.Type == ActivityTypes.Message)
            {
                var text = innerDc.Context.Activity.Text.ToLowerInvariant();

                switch (text)
                {
                case "help":
                case "?":
                    await innerDc.Context.SendActivityAsync($"Show Help...", cancellationToken : cancellationToken);

                    // When you have Q&A Dialog, you can redirect conversation to that Dialog
                    return(await innerDc.ReplaceDialogAsync(nameof(RootDialog), cancellationToken : cancellationToken));

                case "cancel":
                case "quit":
                    await innerDc.Context.SendActivityAsync($"Cancelling", cancellationToken : cancellationToken);

                    return(await innerDc.CancelAllDialogsAsync(cancellationToken : cancellationToken));
                }
            }

            return(null);
        }
예제 #11
0
        public override async Task <DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (options is CancellationToken)
            {
                throw new ArgumentException($"{nameof(options)} cannot be a cancellation token");
            }

            var dcState = dc.GetState();

            if (this.Disabled != null && this.Disabled.GetValue(dcState) == true)
            {
                return(await dc.EndDialogAsync(cancellationToken : cancellationToken).ConfigureAwait(false));
            }

            // Ensure planning context
            if (dc is SequenceContext planning)
            {
                lock (this.Condition)
                {
                    if (this.caseExpressions == null)
                    {
                        this.caseExpressions = new Dictionary <string, Expression>();

                        foreach (var cse in this.Cases)
                        {
                            // Values for cases are always coerced to string
                            var caseCondition = Expression.EqualsExpression(this.Condition.ToExpression(), cse.CreateValueExpression());

                            // Map of expression to actions
                            this.caseExpressions[cse.Value] = caseCondition;
                        }
                    }
                }

                ActionScope actionScope = this.DefaultScope;

                foreach (var caseScope in this.Cases)
                {
                    var(value, error) = this.caseExpressions[caseScope.Value].TryEvaluate(dcState);

                    if (error != null)
                    {
                        throw new Exception($"Expression evaluation resulted in an error. Expression: {caseExpressions[caseScope.Value].ToString()}. Error: {error}");
                    }

                    // Compare both expression results. The current switch case triggers if the comparison is true.
                    if (((bool)value) == true)
                    {
                        actionScope = caseScope;
                        break;
                    }
                }

                return(await dc.ReplaceDialogAsync(actionScope.Id, null, cancellationToken : cancellationToken).ConfigureAwait(false));
            }
            else
            {
                throw new Exception("`IfCondition` should only be used in the context of an adaptive dialog.");
            }
        }
예제 #12
0
        private async Task ExecuteActions(DialogContext dc, IEnumerable <CommandAction> actions)
        {
            var activities  = new List <IActivity>();
            var actionStack = new Stack <CommandAction>(actions.Reverse());

            // Process each action in turn, populating the activities list.
            CommandAction action;

            while (actionStack.TryPop(out action))
            {
                var nextDialogAction = action.Execute(dc, activities, _gameFlags);
                if (nextDialogAction.NextDialogType != DialogType.None)
                {
                    // If the result of the action indicates that we need to start a new dialog
                    // (e.g. conversation with an actor, or a switch to a new room), first send all
                    // activities collected up to this point to the client.
                    if (activities.Any())
                    {
                        await dc.Context.SendActivitiesAsync(activities.ToArray());
                    }

                    if (nextDialogAction.NextDialogType == DialogType.Conversation)
                    {
                        // If the player starts a conversation, save any remaining actions to the state.
                        // These will be executed when the conversation is done and this dialog
                        // continues.
                        if (actionStack.Any())
                        {
                            // Conver to List because Stacks don't serialize in the correct order.
                            // See https://github.com/JamesNK/Newtonsoft.Json/issues/971.
                            dc.ActiveDialog.State.Add(DialogStatePendingActions, actionStack.ToList());
                        }

                        // Start the conversation.
                        await dc.BeginDialogAsync(nextDialogAction.NextDialogId);
                    }
                    else
                    {
                        // Switch to the new room.
                        await dc.ReplaceDialogAsync(nextDialogAction.NextDialogId);
                    }

                    // Stop processing any further actions now that we've switched to a new dialog.
                    return;
                }
            }

            // Add an Idle activity to let the GUI know that we're waiting for user interaction.
            activities.Add(CreateEventActivity(dc, "Idle"));

            await dc.Context.SendActivitiesAsync(activities.ToArray());
        }
예제 #13
0
        public override async Task <DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (options is CancellationToken)
            {
                throw new ArgumentException($"{nameof(options)} cannot be a cancellation token");
            }

            var dialog = this.ResolveDialog(dc);

            // use bindingOptions to bind to the bound options
            var boundOptions = BindOptions(dc, options);

            // replace dialog with bound options passed in as the options
            return(await dc.ReplaceDialogAsync(dialog.Id, options : boundOptions, cancellationToken : cancellationToken).ConfigureAwait(false));
        }
예제 #14
0
        private async Task <DialogTurnResult> FinishInsuranceTypeStep(DialogContext stepContext, string insuranceType)
        {
            var context = stepContext.Context;

            if (string.Equals(insuranceType, "car", StringComparison.OrdinalIgnoreCase))
            {
                return(await stepContext.ReplaceDialogAsync(PromptStep.GatherInfo));
            }
            else
            {
                await context.SendActivityAsync($"Right now I can only help with car insurance: {insuranceType}");

                return(await stepContext.EndDialogAsync());
            }
        }
예제 #15
0
        public override async Task <DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (options is CancellationToken)
            {
                throw new ArgumentException($"{nameof(options)} cannot be a cancellation token");
            }

            var dialog = this.ResolveDialog(dc);

            // use bindingOptions to bind to the bound options
            var boundOptions = BindOptions(dc, options);

            if (this.IncludeActivity)
            {
                // reset this to false so that new dialog has opportunity to process the activity
                dc.GetState().SetValue(TurnPath.ACTIVITYPROCESSED, false);
            }

            // replace dialog with bound options passed in as the options
            return(await dc.ReplaceDialogAsync(dialog.Id, options : boundOptions, cancellationToken : cancellationToken).ConfigureAwait(false));
        }
        private async Task <DialogTurnResult> InterruptAsync(DialogContext innerDialogContext, CancellationToken cancellationToken)
        {
            if (innerDialogContext.Context.Activity.Type == ActivityTypes.Message &&
                innerDialogContext.Context.Activity?.Text != null)
            {
                var text = innerDialogContext.Context.Activity.Text.ToLowerInvariant();

                switch (text)
                {
                case "help":
                case "?":
                    if (innerDialogContext.Stack != null && innerDialogContext.Stack.Count > 0)
                    {
                        var currentDialog = innerDialogContext.Stack[innerDialogContext.Stack.Count - 1]?.Id;

                        if (!string.IsNullOrWhiteSpace(currentDialog))
                        {
                            await innerDialogContext.Context.SendActivityAsync($"Show Help for {currentDialog}", cancellationToken : cancellationToken);

                            innerDialogContext.Context.Activity.Text = null;

                            return(await innerDialogContext.ReplaceDialogAsync(currentDialog, cancellationToken));
                        }
                    }

                    break;

                case "cancel":
                case "quit":
                case "stop":
                case "menu":
                case "exit":
                    await innerDialogContext.Context.SendActivityAsync($"Cancelling...", cancellationToken : cancellationToken);

                    return(await innerDialogContext.CancelAllDialogsAsync());
                }
            }

            return(null);
        }
예제 #17
0
        private async Task <DialogTurnResult> InterruptAsync(DialogContext innerDc, CancellationToken cancellationToken)
        {
            if (innerDc.Context.Activity.Type == ActivityTypes.Message)
            {
                string text = (string.IsNullOrEmpty(innerDc.Context.Activity.Text)) ? innerDc.Context.Activity.Value.ToString() : innerDc.Context.Activity.Text.ToLowerInvariant();

                switch (text)
                {
                case "help":
                case "volver":
                    //await innerDc.Context.SendActivityAsync($"Show Help...", cancellationToken: cancellationToken);
                    return(await innerDc.ReplaceDialogAsync(nameof(RootDialog), cancellationToken : cancellationToken));

                case "cancel":
                case "quit":
                    await innerDc.Context.SendActivityAsync($"Cancelling", cancellationToken : cancellationToken);

                    return(await innerDc.CancelAllDialogsAsync(cancellationToken : cancellationToken));
                }
            }
            return(null);
        }
        /// <summary>
        /// Called when the dialog is started and pushed onto the dialog stack.
        /// </summary>
        /// <param name="dc">The <see cref="DialogContext"/> for the current turn of conversation.</param>
        /// <param name="options">Optional, initial information to pass to the dialog.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public override async Task <DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (options is CancellationToken)
            {
                throw new ArgumentException($"{nameof(options)} cannot be a cancellation token");
            }

            if (this.Disabled != null && this.Disabled.GetValue(dc.State) == true)
            {
                return(await dc.EndDialogAsync(cancellationToken : cancellationToken).ConfigureAwait(false));
            }

            lock (this.Condition)
            {
                if (this.caseExpressions == null)
                {
                    this.caseExpressions = new Dictionary <string, Expression>();

                    foreach (var @case in this.Cases)
                    {
                        if (long.TryParse(@case.Value, out long intVal))
                        {
                            // you don't have to put quotes around numbers, "23" => 23 OR "23"
                            this.caseExpressions[@case.Value] = Expression.OrExpression(
                                Expression.EqualsExpression(this.Condition, Expression.ConstantExpression(intVal)),
                                Expression.EqualsExpression(this.Condition, Expression.ConstantExpression(@case.Value)));
                        }
                        else if (float.TryParse(@case.Value, out float floatVal))
                        {
                            // you don't have to put quotes around numbers, "23" => 23 OR "23"
                            this.caseExpressions[@case.Value] = Expression.OrExpression(
                                Expression.EqualsExpression(this.Condition, Expression.ConstantExpression(floatVal)),
                                Expression.EqualsExpression(this.Condition, Expression.ConstantExpression(@case.Value)));
                        }
                        else if (bool.TryParse(@case.Value, out bool boolVal))
                        {
                            // you don't have to put quotes around bools, "true" => true OR "true"
                            this.caseExpressions[@case.Value] = Expression.OrExpression(
                                Expression.EqualsExpression(this.Condition, Expression.ConstantExpression(boolVal)),
                                Expression.EqualsExpression(this.Condition, Expression.ConstantExpression(@case.Value)));
                        }
                        else
                        {
                            // if someone does "=23" that will be numeric comparison or "='23'" that will be string comparison, or it can be a
                            // real expression bound to memory.
                            var(value, _) = new ValueExpression(@case.Value).TryGetValue(dc.State);
                            this.caseExpressions[@case.Value] = Expression.EqualsExpression(this.Condition, Expression.ConstantExpression(value));
                        }
                    }
                }
            }

            ActionScope actionScope = this.DefaultScope;

            foreach (var caseScope in this.Cases)
            {
                var(value, error) = this.caseExpressions[caseScope.Value].TryEvaluate(dc.State);

                // Compare both expression results. The current switch case triggers if the comparison is true.
                if (value != null && ((bool)value) == true)
                {
                    actionScope = caseScope;
                    break;
                }
            }

            return(await dc.ReplaceDialogAsync(actionScope.Id, null, cancellationToken : cancellationToken).ConfigureAwait(false));
        }
        public override async Task <DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (options is CancellationToken)
            {
                throw new ArgumentException($"{nameof(options)} cannot be a cancellation token");
            }

            var dcState = dc.GetState();

            if (this.Disabled != null && this.Disabled.GetValue(dcState) == true)
            {
                return(await dc.EndDialogAsync(cancellationToken : cancellationToken).ConfigureAwait(false));
            }

            lock (this.Condition)
            {
                if (this.caseExpressions == null)
                {
                    this.caseExpressions = new Dictionary <string, Expression>();

                    foreach (var cse in this.Cases)
                    {
                        Expression caseExpression = null;

                        // Values for cases are always coerced to constant
                        if (long.TryParse(cse.Value, out long i))
                        {
                            caseExpression = Expression.ConstantExpression(i);
                        }
                        else if (float.TryParse(cse.Value, out float f))
                        {
                            caseExpression = Expression.ConstantExpression(f);
                        }
                        else if (bool.TryParse(cse.Value, out bool b))
                        {
                            caseExpression = Expression.ConstantExpression(b);
                        }
                        else
                        {
                            caseExpression = Expression.ConstantExpression(cse.Value);
                        }

                        var caseCondition = Expression.EqualsExpression(this.Condition, caseExpression);

                        // Map of expression to actions
                        this.caseExpressions[cse.Value] = caseCondition;
                    }
                }
            }

            ActionScope actionScope = this.DefaultScope;

            foreach (var caseScope in this.Cases)
            {
                var(value, error) = this.caseExpressions[caseScope.Value].TryEvaluate(dcState);

                if (error != null)
                {
                    throw new Exception($"Expression evaluation resulted in an error. Expression: {caseExpressions[caseScope.Value].ToString()}. Error: {error}");
                }

                // Compare both expression results. The current switch case triggers if the comparison is true.
                if (((bool)value) == true)
                {
                    actionScope = caseScope;
                    break;
                }
            }

            return(await dc.ReplaceDialogAsync(actionScope.Id, null, cancellationToken : cancellationToken).ConfigureAwait(false));
        }
예제 #20
0
        public override async Task <DialogTurnResult> ContinueDialogAsync(DialogContext dc, CancellationToken cancellationToken = default)
        {
            var lastaskedquestion = await LastAskedAccessor.GetAsync(dc.Context, cancellationToken : cancellationToken);

            switch (lastaskedquestion)
            {
            case "anythingelse":
            {
                var phraseType = Helper.GetPhraseType(dc.Context.Activity.Text);
                switch (phraseType)
                {
                case PhraseType.Positive:
                {
                    await LastAskedAccessor.DeleteAsync(dc.Context, cancellationToken : cancellationToken);

                    return(await dc.ReplaceDialogAsync(nameof(FoodOrderDialog), cancellationToken : cancellationToken));
                }

                case PhraseType.Negative:
                {
                    //var cart = await Mediator.Send(new Application.Queries.ViewCartQuery(dc.Context.Activity.GetConversationReference()));
                    //if (cart != null && cart.NumberOfItems > 0)
                    //{
                    //    await Helper.SendConfirmationPrompt("Do You want to checkout?", dc.Context, cancellationToken);
                    //    await LastAskedAccessor.SetAsync(dc.Context, "wanttocheckout", cancellationToken: cancellationToken);
                    //    return EndOfTurn;
                    //}
                    //else
                    //{
                    await dc.Context.SendActivityAsync("මට ඔබට සහය විය හැක්කේ කෙසේද ?", cancellationToken : cancellationToken);

                    return(await dc.EndDialogAsync(cancellationToken : cancellationToken));

                    //}
                }

                default:
                {
                    await LastAskedAccessor.DeleteAsync(dc.Context, cancellationToken : cancellationToken);

                    await dc.CancelAllDialogsAsync(cancellationToken);

                    return(await dc.BeginDialogAsync(nameof(MainDialog), "no_intro_msg", cancellationToken : cancellationToken));
                }
                }
            }

            case "wanttocheckout":
            {
                var phraseType = Helper.GetPhraseType(dc.Context.Activity.Text);
                switch (phraseType)
                {
                case PhraseType.Positive:
                {
                    // return await dc.ReplaceDialogAsync(nameof(ViewCartDialog), cancellationToken: cancellationToken);
                    return(EndOfTurn);
                }

                case PhraseType.Negative:
                {
                    await dc.Context.SendActivityAsync("Is there anything else I can do for you?", cancellationToken : cancellationToken);

                    return(await dc.EndDialogAsync(cancellationToken : cancellationToken));
                }

                default:
                {
                    await dc.CancelAllDialogsAsync(cancellationToken);

                    return(await dc.BeginDialogAsync(nameof(MainDialog), "no_intro_msg", cancellationToken : cancellationToken));
                }
                }
            }

            default:
            {
                await LastAskedAccessor.DeleteAsync(dc.Context, cancellationToken : cancellationToken);

                await dc.CancelAllDialogsAsync(cancellationToken);

                return(await dc.BeginDialogAsync(nameof(MainDialog), "no_intro_msg", cancellationToken : cancellationToken));
            }
            }
            return(EndOfTurn);
        }
예제 #21
0
        private async Task <bool> ExecuteActionsAsync(DialogContext dc, IEnumerable <CommandAction> actions)
        {
            var stateFlags = await _stateFlagsStateAccessor.GetAsync(dc.Context);

            var inventoryItems = await _inventoryItemsAccessor.GetAsync(dc.Context);

            // Get the room state. It always exists at this point because it's
            // set up in the BeginDialogAsync method.
            var roomStates = await _roomStateAccessor.GetAsync(dc.Context, () => new Dictionary <string, RoomState>());

            var roomState = roomStates[_roomId];

            var activities  = new List <IActivity>();
            var actionStack = new Stack <CommandAction>(actions.Reverse());

            // Process each action in turn, populating the activities list.
            while (actionStack.TryPop(out CommandAction nextAction))
            {
                switch (nextAction)
                {
                case AddToInventoryAction action:
                {
                    if (!inventoryItems.Contains(action.InventoryItemId))
                    {
                        inventoryItems.Add(action.InventoryItemId);

                        activities.Add(_activityFactory.InventoryItemAdded(dc, action.InventoryItemId));
                    }
                    break;
                }

                case ClearFlagAction action:
                {
                    if (stateFlags.Contains(action.Flag))
                    {
                        stateFlags.Remove(action.Flag);
                    }
                    break;
                }

                case GuiDelayAction action:
                {
                    activities.Add(_activityFactory.Delayed(dc, action.Milliseconds));
                    break;
                }

                case GuiChangeActorDirectionAction action:
                {
                    activities.Add(_activityFactory.ActorDirectionChanged(dc,
                                                                          action.ActorId, action.Direction));
                    break;
                }

                case GuiMoveActorAction action:
                {
                    // Save the actor's new position in the room state.
                    roomState.ActorPositions[action.ActorId] = action.Position;

                    activities.Add(_activityFactory.ActorMoved(dc, action.ActorId, action.Position));
                    break;
                }

                case GuiNarratorAction action:
                {
                    activities.Add(_activityFactory.Narrated(dc, action.Text));
                    break;
                }

                case GuiPlaceActorAction action:
                {
                    // Save the actor's new position in the room state.
                    roomState.ActorPositions[action.ActorId] = action.Position;

                    activities.Add(_activityFactory.ActorPlacedInRoom(dc, action.ActorId, action.Position));
                    break;
                }

                case GuiPlaceObjectAction action:
                {
                    // Save the object's new position in the room state.
                    roomState.ObjectPositions[action.ObjectId] = action.Position;

                    activities.Add(_activityFactory.ObjectPlacedInRoom(dc, action.ObjectId, action.Position));
                    break;
                }

                case GuiRemoveObjectAction action:
                {
                    // Remove the object from the room state.
                    roomState.ObjectPositions.Remove(action.ObjectId);

                    activities.Add(_activityFactory.ObjectRemovedFromRoom(dc, action.ObjectId));
                    break;
                }

                case RemoveFromInventoryAction action:
                {
                    if (inventoryItems.Contains(action.InventoryItemId))
                    {
                        inventoryItems.Remove(action.InventoryItemId);
                    }
                    activities.Add(_activityFactory.InventoryItemRemoved(dc, action.InventoryItemId));
                    break;
                }

                case SetFlagAction action:
                {
                    if (!stateFlags.Contains(action.Flag))
                    {
                        stateFlags.Add(action.Flag);
                    }
                    break;
                }

                case SpeakAction action:
                {
                    activities.Add(_activityFactory.Speak(dc, action.ActorId, action.Text));
                    break;
                }

                case StartConversationAction action:
                {
                    // If the result of the action indicates that we need to start a new dialog
                    // (e.g. conversation with an actor, or a switch to a new room), first send all
                    // activities collected up to this point to the client.
                    if (activities.Any())
                    {
                        await dc.Context.SendActivitiesAsync(activities.ToArray());
                    }

                    // If the player starts a conversation, save any remaining actions to the state.
                    // These will be executed when the conversation is done and this dialog
                    // continues.
                    if (actionStack.Any())
                    {
                        // Conver to List because Stacks don't serialize in the correct order.
                        // See https://github.com/JamesNK/Newtonsoft.Json/issues/971.
                        dc.ActiveDialog.State.Add(DialogStatePendingActions, actionStack.ToList());
                    }

                    // Start the conversation.
                    await dc.BeginDialogAsync(action.ConversationId);

                    // Stop processing any further actions now that we've switched to a new dialog.
                    return(false);
                }

                case SwitchRoomAction action:
                {
                    // If the result of the action indicates that we need to start a new dialog
                    // (e.g. conversation with an actor, or a switch to a new room), first send all
                    // activities collected up to this point to the client.
                    if (activities.Any())
                    {
                        await dc.Context.SendActivitiesAsync(activities.ToArray());
                    }

                    // Switch to the new room.
                    await dc.ReplaceDialogAsync(action.RoomId);

                    // Stop processing any further actions now that we've switched to a new dialog.
                    return(false);
                }

                case TextDescribeAction action:
                {
                    activities.Add(MessageFactory.Text(action.Text));
                    break;
                }
                }
            }

            await dc.Context.SendActivitiesAsync(activities.ToArray());

            // Returning true here indicates that we can continue processing the actions for this turn.
            return(true);
        }