コード例 #1
0
        private async Task <DialogTurnResult> CheckEntities(WaterfallStepContext sc, CancellationToken cancellationToken)
        {
            var userState = await UserStateAccessor.GetAsync(sc.Context, () => new HospitalityUserSkillState(HotelService));

            var convState = await StateAccessor.GetAsync(sc.Context, () => new HospitalitySkillState());

            var entities = convState.LuisResult.Entities;

            convState.UpdatedReservation = userState.UserReservation.Copy();

            // check for valid datetime entity
            if (entities.datetime != null && (entities.datetime[0].Type == "date" ||
                                              entities.datetime[0].Type == "datetime" || entities.datetime[0].Type == "daterange") &&
                await DateValidation(sc.Context, entities.datetime[0].Expressions))
            {
                return(await sc.NextAsync());
            }

            // check for valid number composite entity
            if (entities.NumNights?[0].HotelNights != null && entities.NumNights?[0].number[0] != null &&
                await NumValidation(sc.Context, entities.NumNights[0].number[0]))
            {
                return(await sc.NextAsync());
            }

            // need clarification on input
            else if (entities.datetime == null && entities.number != null)
            {
                convState.NumberEntity = entities.number[0];

                var tokens = new StringDictionary
                {
                    { "Number", convState.NumberEntity.ToString() }
                };

                return(await sc.PromptAsync(DialogIds.CheckNumNights, new PromptOptions()
                {
                    Prompt = ResponseManager.GetResponse(ExtendStayResponses.ConfirmAddNights, tokens)
                }));
            }

            // trying to request late check out time
            else if (entities.datetime != null && (entities.datetime[0].Type == "time" || entities.datetime[0].Type == "timerange"))
            {
                return(await sc.ReplaceDialogAsync(nameof(LateCheckOutDialog)));
            }

            return(await sc.NextAsync());
        }
コード例 #2
0
        protected async Task <DialogTurnResult> InputState(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState());

            if (!(bool)sc.Result || state.TicketState == TicketState.None)
            {
                var options = new PromptOptions()
                {
                    Prompt  = ResponseManager.GetResponse(SharedResponses.InputState),
                    Choices = new List <Choice>()
                    {
                        new Choice()
                        {
                            Value = TicketState.New.ToLocalizedString()
                        },
                        new Choice()
                        {
                            Value = TicketState.InProgress.ToLocalizedString()
                        },
                        new Choice()
                        {
                            Value = TicketState.OnHold.ToLocalizedString()
                        },
                        new Choice()
                        {
                            Value = TicketState.Resolved.ToLocalizedString()
                        },
                        new Choice()
                        {
                            Value = TicketState.Closed.ToLocalizedString()
                        },
                        new Choice()
                        {
                            Value = TicketState.Canceled.ToLocalizedString()
                        }
                    }
                };

                return(await sc.PromptAsync(nameof(ChoicePrompt), options));
            }
            else
            {
                // use Index to skip localization
                return(await sc.NextAsync(new FoundChoice()
                {
                    Index = (int)state.TicketState - 1
                }));
            }
        }
コード例 #3
0
        private async Task <bool> DateValidation(ITurnContext turnContext, IReadOnlyList <string> dates)
        {
            var convState = await StateAccessor.GetAsync(turnContext, () => new HospitalitySkillState());

            var userState = await UserStateAccessor.GetAsync(turnContext, () => new HospitalityUserSkillState(HotelService));

            DateTime dateObject  = new DateTime();
            bool     dateIsEarly = false;

            string[] formats = { "XXXX-MM-dd", "yyyy-MM-dd" };
            foreach (var date in dates)
            {
                // try parse exact date format so it won't accept time inputs
                if (DateTime.TryParseExact(date, formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateObject))
                {
                    if (dateObject > DateTime.Now && dateObject > DateTime.Parse(userState.UserReservation.CheckOutDate))
                    {
                        // get first future date that is formatted correctly
                        convState.UpdatedReservation.CheckOutDate = dateObject.ToString(ReservationData.DateFormat);
                        return(await Task.FromResult(true));
                    }
                    else
                    {
                        dateIsEarly = true;
                    }
                }
            }

            // found correctly formatted date, but date is not after current check-out date
            if (dateIsEarly)
            {
                // same date as current check-out date
                if (dateObject.ToString(ReservationData.DateFormat) == userState.UserReservation.CheckOutDate)
                {
                    await turnContext.SendActivityAsync(ResponseManager.GetResponse(ExtendStayResponses.SameDayRequested));
                }
                else
                {
                    var tokens = new StringDictionary
                    {
                        { "Date", userState.UserReservation.CheckOutDate }
                    };

                    await turnContext.SendActivityAsync(ResponseManager.GetResponse(ExtendStayResponses.NotFutureDateError, tokens));
                }
            }

            return(await Task.FromResult(false));
        }
コード例 #4
0
        private async Task <bool> SettingValueSelectionValidator(PromptValidatorContext <FoundChoice> promptContext, CancellationToken cancellationToken)
        {
            var state = await StateAccessor.GetAsync(promptContext.Context, cancellationToken : cancellationToken);

            // Use the value selection LUIS model to perform validation of the users entered setting value
            var skillResult = promptContext.Context.TurnState.Get <MusicSkillLuis>(StateProperties.MusicLuisResultKey);

            if (skillResult.Entities.VolumeDirection != null && skillResult.Entities.VolumeDirection.Length > 0)
            {
                state.VolumeDirection = skillResult.Entities.VolumeDirection[0][0];
                return(true);
            }

            return(false);
        }
コード例 #5
0
        private async Task <bool> ValidateFoodOrder(PromptValidatorContext <string> promptContext, CancellationToken cancellationToken)
        {
            var convState = await StateAccessor.GetAsync(promptContext.Context, () => new HospitalitySkillState());

            var entities = convState.LuisResult.Entities;

            if (promptContext.Recognized.Succeeded && (entities.FoodRequest != null || !string.IsNullOrWhiteSpace(entities.Food?[0])))
            {
                await GetFoodEntities(promptContext.Context);

                return(await Task.FromResult(true));
            }

            return(await Task.FromResult(false));
        }
コード例 #6
0
        /// <summary>
        /// Check if geography is stored in state and route to prompt or go to API call.
        /// </summary>
        private async Task <DialogTurnResult> RouteToGeographyPromptOrForecastResponseAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            var state = await StateAccessor.GetAsync(stepContext.Context, cancellationToken : cancellationToken);

            var geography = state.Geography;

            if (string.IsNullOrEmpty(geography) && double.IsNaN(state.Latitude))
            {
                return(await stepContext.NextAsync(cancellationToken : cancellationToken));
            }
            else
            {
                return(await stepContext.ReplaceDialogAsync(DialogIds.GetForecastResponseDialog, cancellationToken : cancellationToken));
            }
        }
コード例 #7
0
        protected async Task <DialogTurnResult> AfterIfCreateTicketAsync(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            if ((bool)sc.Result)
            {
                var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState(), cancellationToken);

                state.DisplayExisting = false;

                // note that it replaces the active WaterfallDialog instead of ShowKnowledgeDialog
                return(await sc.ReplaceDialogAsync(nameof(CreateTicketDialog), cancellationToken : cancellationToken));
            }
            else
            {
                return(await sc.EndDialogAsync(cancellationToken : cancellationToken));
            }
        }
コード例 #8
0
        // Helpers
        protected async Task GetLuisResult(DialogContext dc)
        {
            if (dc.Context.Activity.Type == ActivityTypes.Message)
            {
                var state = await StateAccessor.GetAsync(dc.Context, () => new SkillState());

                // Get luis service for current locale
                var localeConfig = Services.GetCognitiveModels();
                var luisService  = localeConfig.LuisServices["BingSearchSkill"];

                // Get intent and entities for activity
                var result = await luisService.RecognizeAsync <BingSearchSkillLuis>(dc.Context, CancellationToken.None);

                state.LuisResult = result;
            }
        }
コード例 #9
0
        private async Task <DialogTurnResult> ConfirmExtentionPrompt(WaterfallStepContext sc, CancellationToken cancellationToken)
        {
            var convState = await StateAccessor.GetAsync(sc.Context, () => new HospitalitySkillState());

            var tokens = new StringDictionary
            {
                { "Date", convState.UpdatedReservation.CheckOutDate }
            };

            // confirm reservation extension with user
            return(await sc.PromptAsync(DialogIds.ConfirmExtendStay, new PromptOptions()
            {
                Prompt = ResponseManager.GetResponse(ExtendStayResponses.ConfirmExtendStay, tokens),
                RetryPrompt = ResponseManager.GetResponse(ExtendStayResponses.RetryConfirmExtendStay, tokens)
            }));
        }
コード例 #10
0
        private async Task <bool> ValidateAddItemsAsync(PromptValidatorContext <string> promptContext, CancellationToken cancellationToken)
        {
            var convState = await StateAccessor.GetAsync(promptContext.Context, () => new HospitalitySkillState(), cancellationToken);

            var entities = convState.LuisResult?.Entities;

            if (promptContext.Recognized.Succeeded && (entities?.FoodRequest != null || !string.IsNullOrWhiteSpace(entities?.Food?[0])))
            {
                // added an item
                await GetFoodEntitiesAsync(promptContext.Context, cancellationToken);
                await ShowFoodOrderAsync(promptContext.Context, cancellationToken);
            }

            // only asks once
            return(await Task.FromResult(true));
        }
コード例 #11
0
        protected async Task <DialogTurnResult> UpdateSelectedAttribute(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState());

            var attribute = state.AttributeType;

            state.AttributeType = AttributeType.None;
            if (attribute == AttributeType.Description)
            {
                state.TicketDescription = null;
                return(await sc.BeginDialogAsync(Actions.SetDescription));
            }
            else if (attribute == AttributeType.Title)
            {
                state.TicketTitle = null;
                return(await sc.BeginDialogAsync(Actions.SetTitle));
            }
            else if (attribute == AttributeType.Search)
            {
                state.TicketTitle = null;
                return(await sc.BeginDialogAsync(Actions.SetSearch));
            }
            else if (attribute == AttributeType.Urgency)
            {
                state.UrgencyLevel = UrgencyLevel.None;
                return(await sc.BeginDialogAsync(Actions.SetUrgency));
            }
            else if (attribute == AttributeType.Id)
            {
                state.Id = null;
                return(await sc.BeginDialogAsync(Actions.SetId));
            }
            else if (attribute == AttributeType.State)
            {
                state.TicketState = TicketState.None;
                return(await sc.BeginDialogAsync(Actions.SetState));
            }
            else if (attribute == AttributeType.Number)
            {
                state.TicketNumber = null;
                return(await sc.BeginDialogAsync(Actions.SetNumber));
            }
            else
            {
                throw new Exception($"Invalid AttributeType: {attribute}");
            }
        }
コード例 #12
0
        protected async Task <DialogTurnResult> ShowConstraints(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState());

            // always prompt for search
            state.AttributeType = AttributeType.None;

            var sb = new StringBuilder();

            if (!string.IsNullOrEmpty(state.TicketNumber))
            {
                sb.AppendLine(string.Format(SharedStrings.TicketNumber, state.TicketNumber));
            }

            if (!string.IsNullOrEmpty(state.TicketTitle))
            {
                sb.AppendLine(string.Format(SharedStrings.Search, state.TicketTitle));
            }

            if (state.UrgencyLevel != UrgencyLevel.None)
            {
                sb.AppendLine(string.Format(SharedStrings.Urgency, state.UrgencyLevel.ToLocalizedString()));
            }

            if (state.TicketState != TicketState.None)
            {
                sb.AppendLine(string.Format(SharedStrings.TicketState, state.TicketState.ToLocalizedString()));
            }

            if (sb.Length == 0)
            {
                // await sc.Context.SendActivityAsync(ResponseManager.GetResponse(TicketResponses.ShowConstraintNone));
            }
            else
            {
                var token = new StringDictionary()
                {
                    { "Attributes", sb.ToString() }
                };

                await sc.Context.SendActivityAsync(ResponseManager.GetResponse(TicketResponses.ShowConstraints, token));
            }

            state.PageIndex = -1;

            return(await sc.ReplaceDialogAsync(Actions.ShowTicketLoop));
        }
コード例 #13
0
        // Helpers
        protected async Task GetLuisResult(DialogContext dc)
        {
            if (dc.Context.Activity.Type == ActivityTypes.Message)
            {
                var state = await StateAccessor.GetAsync(dc.Context, () => new SkillState());

                // Get luis service for current locale
                var locale       = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
                var localeConfig = Services.CognitiveModelSets[locale];
                var luisService  = localeConfig.LuisServices["TestBot"];

                // Get intent and entities for activity
                var result = await luisService.RecognizeAsync <TestBotLuis>(dc.Context, CancellationToken.None);

                state.LuisResult = result;
            }
        }
コード例 #14
0
        protected async Task <DialogTurnResult> AfterIfCreateTicket(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            if ((bool)sc.Result)
            {
                var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState());

                state.DisplayExisting = false;

                return(await sc.ReplaceDialogAsync(nameof(CreateTicketDialog)));
            }
            else
            {
                await sc.Context.SendActivityAsync(ResponseManager.GetResponse(SharedResponses.ActionEnded));

                return(await sc.CancelAllDialogsAsync());
            }
        }
コード例 #15
0
        protected async Task <DialogTurnResult> CreateTicketAsync(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState(), cancellationToken);

            var management = ServiceManager.CreateManagement(Settings, sc.Result as TokenResponse, state.ServiceCache);
            var result     = await management.CreateTicket(state.TicketTitle, state.TicketDescription, state.UrgencyLevel);

            if (!result.Success)
            {
                return(await SendServiceErrorAndCancelAsync(sc, result, cancellationToken));
            }

            var card = GetTicketCard(sc.Context, state, result.Tickets[0]);

            await sc.Context.SendActivityAsync(TemplateManager.GenerateActivity(TicketResponses.TicketCreated, card, null), cancellationToken);

            return(await sc.EndDialogAsync(await CreateActionResultAsync(sc.Context, true, cancellationToken), cancellationToken));
        }
コード例 #16
0
        private async Task <bool> NumValidation(ITurnContext turnContext, double extraNights)
        {
            var userState = await UserStateAccessor.GetAsync(turnContext, () => new HospitalityUserSkillState());

            var convState = await StateAccessor.GetAsync(turnContext, () => new HospitalitySkillState());

            if (extraNights >= 1)
            {
                // add entity number to the current check out date
                DateTime currentDate = DateTime.Parse(userState.UserReservation.CheckOutDate);
                convState.UpdatedReservation.CheckOutDate = currentDate.AddDays(extraNights).ToString("MMMM d, yyyy");
                return(await Task.FromResult(true));
            }

            await turnContext.SendActivityAsync(ResponseManager.GetResponse(ExtendStayResponses.NumberEntityError));

            return(await Task.FromResult(false));
        }
コード例 #17
0
        protected async Task <DialogTurnResult> CloseTicket(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState());

            var management = ServiceManager.CreateManagement(Settings, sc.Result as TokenResponse);
            var result     = await management.CloseTicket(id : state.Id, reason : state.CloseReason);

            if (!result.Success)
            {
                return(await SendServiceErrorAndCancel(sc, result));
            }

            var card = GetTicketCard(sc.Context, result.Tickets[0]);

            await sc.Context.SendActivityAsync(ResponseManager.GetCardResponse(TicketResponses.TicketClosed, card, null));

            return(await sc.NextAsync());
        }
コード例 #18
0
        protected async Task <DialogTurnResult> InputTicketNumber(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState());

            if (string.IsNullOrEmpty(state.TicketNumber))
            {
                var options = new PromptOptions()
                {
                    Prompt = ResponseManager.GetResponse(SharedResponses.InputTicketNumber)
                };

                return(await sc.PromptAsync(nameof(TicketNumberPrompt), options));
            }
            else
            {
                return(await sc.NextAsync(state.TicketNumber));
            }
        }
コード例 #19
0
        private async Task <bool> NumValidationAsync(ITurnContext turnContext, double extraNights, CancellationToken cancellationToken)
        {
            var userState = await UserStateAccessor.GetAsync(turnContext, () => new HospitalityUserSkillState(HotelService), cancellationToken);

            var convState = await StateAccessor.GetAsync(turnContext, () => new HospitalitySkillState(), cancellationToken);

            if (extraNights >= 1)
            {
                // add entity number to the current check out date
                DateTime currentDate = DateTime.Parse(userState.UserReservation.CheckOutDate);
                convState.UpdatedReservation.CheckOutDate = currentDate.AddDays(extraNights).ToString(ReservationData.DateFormat);
                return(await Task.FromResult(true));
            }

            await turnContext.SendActivityAsync(TemplateManager.GenerateActivity(ExtendStayResponses.NumberEntityError), cancellationToken);

            return(await Task.FromResult(false));
        }
コード例 #20
0
        protected async Task <DialogTurnResult> InputAttribute(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState());

            if (!(bool)sc.Result || state.AttributeType == AttributeType.None)
            {
                var options = new PromptOptions()
                {
                    Prompt = ResponseManager.GetResponse(InputAttributeResponse)
                };

                return(await sc.PromptAsync(InputAttributePrompt, options));
            }
            else
            {
                return(await sc.NextAsync(state.AttributeType));
            }
        }
コード例 #21
0
        protected async Task <DialogTurnResult> IfContinueShow(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState());

            if (state.InterruptedIntent == ITSMLuis.Intent.TicketClose)
            {
                return(await sc.ReplaceDialogAsync(nameof(CloseTicketDialog)));
            }
            else if (state.InterruptedIntent == ITSMLuis.Intent.TicketUpdate)
            {
                return(await sc.ReplaceDialogAsync(nameof(UpdateTicketDialog)));
            }
            else if (state.InterruptedIntent != ITSMLuis.Intent.None)
            {
                throw new Exception($"Invalid InterruptedIntent {state.InterruptedIntent}");
            }

            var intent = (GeneralLuis.Intent)sc.Result;

            if (intent == GeneralLuis.Intent.Reject)
            {
                await sc.Context.SendActivityAsync(ResponseManager.GetResponse(SharedResponses.ActionEnded));

                return(await sc.CancelAllDialogsAsync());
            }
            else if (intent == GeneralLuis.Intent.Confirm)
            {
                return(await sc.ReplaceDialogAsync(Actions.ShowAttribute));
            }
            else if (intent == GeneralLuis.Intent.ShowNext)
            {
                state.PageIndex += 1;
                return(await sc.ReplaceDialogAsync(Actions.ShowTicketLoop));
            }
            else if (intent == GeneralLuis.Intent.ShowPrevious)
            {
                state.PageIndex = Math.Max(0, state.PageIndex - 1);
                return(await sc.ReplaceDialogAsync(Actions.ShowTicketLoop));
            }
            else
            {
                throw new Exception($"Invalid GeneralLuis.Intent {intent}");
            }
        }
コード例 #22
0
        private async Task <DialogTurnResult> MenuPrompt(WaterfallStepContext sc, CancellationToken cancellationToken)
        {
            var convState = await StateAccessor.GetAsync(sc.Context, () => new HospitalitySkillState());

            convState.FoodList = new List <FoodRequestClass>();
            await GetFoodEntities(sc.Context);

            var menu = convState.LuisResult.Entities.Menu;

            // didn't order, prompt if 1 menu type not identified
            if (convState.FoodList.Count == 0 && string.IsNullOrWhiteSpace(menu?[0][0]) && menu?.Length != 1)
            {
                var prompt = ResponseManager.GetResponse(RoomServiceResponses.MenuPrompt);

                var actions = new List <CardAction>()
                {
                    new CardAction(type: ActionTypes.ImBack, title: "Breakfast", value: "Breakfast menu"),
                    new CardAction(type: ActionTypes.ImBack, title: "Lunch", value: "Lunch menu"),
                    new CardAction(type: ActionTypes.ImBack, title: "Dinner", value: "Dinner menu"),
                    new CardAction(type: ActionTypes.ImBack, title: "24 Hour", value: "24 hour menu")
                };

                // create hero card instead when channel does not support suggested actions
                if (!Channel.SupportsSuggestedActions(sc.Context.Activity.ChannelId))
                {
                    var hero = new HeroCard(buttons: actions);
                    prompt.Attachments.Add(hero.ToAttachment());
                }
                else
                {
                    prompt.SuggestedActions = new SuggestedActions {
                        Actions = actions
                    };
                }

                return(await sc.PromptAsync(DialogIds.MenuPrompt, new PromptOptions()
                {
                    Prompt = prompt,
                    RetryPrompt = ResponseManager.GetResponse(RoomServiceResponses.ChooseOneMenu)
                }));
            }

            return(await sc.NextAsync());
        }
コード例 #23
0
        // This method is called by any waterfall step that throws an exception to ensure consistency
        protected async Task HandleDialogExceptions(WaterfallStepContext sc, Exception ex)
        {
            // send trace back to emulator
            var trace = new Activity(type: ActivityTypes.Trace, text: $"DialogException: {ex.Message}, StackTrace: {ex.StackTrace}");
            await sc.Context.SendActivityAsync(trace);

            // log exception
            TelemetryClient.TrackException(ex, new Dictionary <string, string> {
                { nameof(sc.ActiveDialog), sc.ActiveDialog?.Id }
            });

            // send error message to bot user
            await sc.Context.SendActivityAsync(ResponseManager.GetResponse(SharedResponses.ErrorMessage));

            // clear state
            var state = await StateAccessor.GetAsync(sc.Context);

            state.Clear();
        }
コード例 #24
0
        private async Task <DialogTurnResult> ExtendDatePrompt(WaterfallStepContext sc, CancellationToken cancellationToken)
        {
            var userState = await UserStateAccessor.GetAsync(sc.Context, () => new HospitalityUserSkillState());

            var convState = await StateAccessor.GetAsync(sc.Context, () => new HospitalitySkillState());

            // if new date hasnt been set yet
            if (userState.UserReservation.CheckOutDate == convState.UpdatedReservation.CheckOutDate)
            {
                // get extended reservation date
                return(await sc.PromptAsync(DialogIds.ExtendDatePrompt, new PromptOptions()
                {
                    Prompt = ResponseManager.GetResponse(ExtendStayResponses.ExtendDatePrompt),
                    RetryPrompt = ResponseManager.GetResponse(ExtendStayResponses.RetryExtendDate)
                }));
            }

            return(await sc.NextAsync());
        }
コード例 #25
0
        protected async Task <DialogTurnResult> IfContinueShowAsync(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState(), cancellationToken);

            // Skip in Action mode in ShowNavigateValidator
            if (state.InterruptedIntent == ITSMLuis.Intent.TicketClose)
            {
                return(await sc.ReplaceDialogAsync(nameof(CloseTicketDialog), cancellationToken : cancellationToken));
            }
            else if (state.InterruptedIntent == ITSMLuis.Intent.TicketUpdate)
            {
                return(await sc.ReplaceDialogAsync(nameof(UpdateTicketDialog), cancellationToken : cancellationToken));
            }
            else if (state.InterruptedIntent != ITSMLuis.Intent.None)
            {
                throw new Exception($"Invalid InterruptedIntent {state.InterruptedIntent}");
            }

            var intent = (GeneralLuis.Intent)sc.Result;

            if (intent == GeneralLuis.Intent.Reject)
            {
                return(await sc.EndDialogAsync(await CreateActionResultAsync(sc.Context, true, cancellationToken), cancellationToken));
            }
            else if (intent == GeneralLuis.Intent.Confirm)
            {
                return(await sc.ReplaceDialogAsync(Actions.ShowAttribute, cancellationToken : cancellationToken));
            }
            else if (intent == GeneralLuis.Intent.ShowNext)
            {
                state.PageIndex += 1;
                return(await sc.ReplaceDialogAsync(Actions.ShowTicketLoop, cancellationToken : cancellationToken));
            }
            else if (intent == GeneralLuis.Intent.ShowPrevious)
            {
                state.PageIndex = Math.Max(0, state.PageIndex - 1);
                return(await sc.ReplaceDialogAsync(Actions.ShowTicketLoop, cancellationToken : cancellationToken));
            }
            else
            {
                throw new Exception($"Invalid GeneralLuis.Intent {intent}");
            }
        }
コード例 #26
0
        // This method is called by any waterfall step that throws an exception to ensure consistency
        protected async Task HandleDialogExceptionsAsync(WaterfallStepContext sc, Exception ex, CancellationToken cancellationToken)
        {
            // send trace back to emulator
            var trace = new Activity(type: ActivityTypes.Trace, text: $"DialogException: {ex.Message}, StackTrace: {ex.StackTrace}");
            await sc.Context.SendActivityAsync(trace, cancellationToken);

            // log exception
            TelemetryClient.TrackException(ex, new Dictionary <string, string> {
                { nameof(sc.ActiveDialog), sc.ActiveDialog?.Id }
            });

            // send error message to bot user
            await sc.Context.SendActivityAsync(TemplateEngine.GenerateActivityForLocale("ErrorMessage"), cancellationToken);

            // clear state
            var state = await StateAccessor.GetAsync(sc.Context, cancellationToken : cancellationToken);

            state.Clear();
        }
コード例 #27
0
        private async Task <DialogTurnResult> ItemPrompt(WaterfallStepContext sc, CancellationToken cancellationToken)
        {
            var convState = await StateAccessor.GetAsync(sc.Context, () => new HospitalitySkillState());

            convState.ItemList = new List <ItemRequestClass>();
            await GetEntities(sc.Context);

            if (convState.ItemList.Count == 0)
            {
                // prompt for item
                return(await sc.PromptAsync(DialogIds.ItemPrompt, new PromptOptions()
                {
                    Prompt = ResponseManager.GetResponse(RequestItemResponses.ItemPrompt),
                    RetryPrompt = ResponseManager.GetResponse(RequestItemResponses.RetryItemPrompt)
                }));
            }

            return(await sc.NextAsync());
        }
コード例 #28
0
        protected async Task <DialogTurnResult> CloseTicketAsync(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState(), cancellationToken);

            var management = ServiceManager.CreateManagement(Settings, sc.Result as TokenResponse, state.ServiceCache);
            var result     = await management.CloseTicket(id : state.Id, reason : state.CloseReason);

            if (!result.Success)
            {
                // Check if Error is UnAuthorized and logout user
                return(await HandleAPIUnauthorizedError(sc, result, cancellationToken));
            }

            var card = GetTicketCard(sc.Context, state, result.Tickets[0]);

            await sc.Context.SendActivityAsync(TemplateManager.GenerateActivity(TicketResponses.TicketClosed, card, null), cancellationToken);

            return(await sc.NextAsync(await CreateActionResultAsync(sc.Context, true, cancellationToken), cancellationToken));
        }
コード例 #29
0
        private async Task <DialogTurnResult> ItemRequest(WaterfallStepContext sc, CancellationToken cancellationToken)
        {
            var convState = await StateAccessor.GetAsync(sc.Context, () => new HospitalitySkillState());

            // check json, if item is available
            List <ItemRequestClass> notAvailable = new List <ItemRequestClass>();

            foreach (var itemRequest in convState.ItemList.ToList())
            {
                var roomItem = _hotelService.CheckRoomItemAvailability(itemRequest.Item[0]);

                if (roomItem == null)
                {
                    // specific item is not available
                    notAvailable.Add(itemRequest);
                    convState.ItemList.Remove(itemRequest);
                }
                else
                {
                    itemRequest.Item[0] = roomItem.Item;
                }
            }

            if (notAvailable.Count > 0)
            {
                var reply = ResponseManager.GetResponse(RequestItemResponses.ItemNotAvailable).Text;
                foreach (var itemRequest in notAvailable)
                {
                    reply += Environment.NewLine + "- " + itemRequest.Item[0];
                }

                await sc.Context.SendActivityAsync(reply);

                return(await sc.PromptAsync(DialogIds.GuestServicesPrompt, new PromptOptions()
                {
                    Prompt = ResponseManager.GetResponse(RequestItemResponses.GuestServicesPrompt),
                    RetryPrompt = ResponseManager.GetResponse(RequestItemResponses.RetryGuestServicesPrompt)
                }));
            }

            return(await sc.NextAsync());
        }
コード例 #30
0
        private async Task <DialogTurnResult> EndDialogAsync(WaterfallStepContext sc, CancellationToken cancellationToken)
        {
            var convState = await StateAccessor.GetAsync(sc.Context, () => new HospitalitySkillState(), cancellationToken);

            var result = convState.IsAction ? new ActionResult(false) : null;

            if (result != null && sc.Result is bool && (bool)sc.Result)
            {
                result.ActionSuccess = true;
            }

            if (convState.ItemList.Count > 0)
            {
                List <Card> roomItems = new List <Card>();

                foreach (var itemRequest in convState.ItemList)
                {
                    var roomItem = new RoomItem
                    {
                        Item     = itemRequest.Item[0],
                        Quantity = itemRequest.number == null ? 1 : (int)itemRequest.number[0]
                    };

                    roomItems.Add(new Card(GetCardName(sc.Context, "RoomItemCard"), roomItem));
                }

                await HotelService.RequestItems(convState.ItemList);

                // if at least one item was available send this card reply
                await sc.Context.SendActivityAsync(TemplateManager.GenerateActivity(null, new Card(GetCardName(sc.Context, "RequestItemCard")), null, "items", roomItems), cancellationToken);

                await sc.Context.SendActivityAsync(TemplateManager.GenerateActivity(RequestItemResponses.ItemsRequested), cancellationToken);

                if (result != null)
                {
                    result.ActionSuccess = true;
                }
            }

            return(await sc.EndDialogAsync(result, cancellationToken));
        }