Пример #1
0
        public IEnumerable <TermMatch> Match(IDialogContext context, T state, FormState form, IMessageActivity input)
        {
            IEnumerable <TermMatch> matches = null;

            Debug.Assert(form.Phase() == StepPhase.Responding);
            var stepState = (FieldStepState)form.StepState;

            if (stepState.State == FieldStepStates.SentPrompt)
            {
                matches = _field.Prompt.Recognizer.Matches(input, _field.GetValue(state));
            }
            else if (stepState.State == FieldStepStates.SentClarify)
            {
                var fieldState       = (FieldStepState)form.StepState;
                var iprompt          = _field.Prompt;
                var choiceRecognizer = ClarifyRecognizer(fieldState, iprompt.Recognizer);
                matches = MatchAnalyzer.Coalesce(MatchAnalyzer.HighestConfidence(choiceRecognizer.Matches(input)), MessageActivityHelper.GetSanitizedTextInput(input)).ToArray();
                if (matches.Count() > 1)
                {
                    matches = new TermMatch[0];
                }
            }
#if DEBUG
            if (FormDialog.DebugRecognizers)
            {
                MatchAnalyzer.PrintMatches(matches, 2);
            }
#endif
            return(matches);
        }
Пример #2
0
        public async Task <StepResult> ProcessAsync(IDialogContext context, T state, FormState form, IMessageActivity input, IEnumerable <TermMatch> matches)
        {
            var inputText = MessageActivityHelper.GetSanitizedTextInput(input);

            ValidateResult feedback = new ValidateResult();

            feedback.IsValid      = true;
            feedback.Feedback     = null;
            feedback.FeedbackCard = null;
            feedback.Choices      = null;
            FormPrompt prompt         = null;
            FormPrompt feedbackPrompt = null;
            var        iprompt        = _field.Prompt;
            var        fieldState     = (FieldStepState)form.StepState;
            object     response       = null;

            if (fieldState.State == FieldStepStates.SentPrompt)
            {
                // Response to prompt
                var firstMatch = matches.FirstOrDefault();
                if (matches.Count() == 1)
                {
                    response = firstMatch.Value;
                    if (_field.AllowsMultiple && response != null &&
                        (response.GetType() == typeof(string) || !response.GetType().IsIEnumerable()))
                    {
                        response = new List <object>()
                        {
                            response
                        };
                    }
                    feedback = await SetValueAsync(state, response, form);

                    if (!feedback.IsValid && feedback.Choices != null)
                    {
                        var choices = new Ambiguous(inputText.Substring(firstMatch.Start, firstMatch.Length), feedback.Choices);
                        fieldState.State          = FieldStepStates.SentClarify;
                        fieldState.Settled        = new List <object>();
                        fieldState.Clarifications = new List <Ambiguous>()
                        {
                            choices
                        };
                        response = SetValue(state, null);
                        prompt   = ClarifyPrompt((FieldStepState)form.StepState, iprompt.Recognizer, state);
                    }
                }
                else if (matches.Count() > 1)
                {
                    // Check multiple matches for ambiguity
                    var groups = MatchAnalyzer.GroupedMatches(matches);
                    // 1) Could be multiple match groups like for ingredients.
                    // 2) Could be overlapping matches like "onion".
                    // 3) Could be multiple matches where only one is expected.

                    if (!_field.AllowsMultiple)
                    {
                        // Create a single group of all possibilities if only want one value
                        var mergedGroup = groups.SelectMany((group) => group).ToList();
                        groups = new List <List <TermMatch> >()
                        {
                            mergedGroup
                        };
                    }
                    var ambiguous = new List <Ambiguous>();
                    var settled   = new List <object>();
                    foreach (var choices in groups)
                    {
                        if (choices.Count > 1)
                        {
                            var unclearResponses = string.Join(" ", (from choice in choices select inputText.Substring(choice.Start, choice.Length)).Distinct());
                            var values           = from match in choices select match.Value;
                            ambiguous.Add(new Ambiguous(unclearResponses, values));
                        }
                        else
                        {
                            var matchValue = choices.First().Value;
                            if (matchValue != null && matchValue.GetType() != typeof(string) && matchValue.GetType().IsIEnumerable())
                            {
                                foreach (var value in (System.Collections.IEnumerable)matchValue)
                                {
                                    settled.Add(value);
                                }
                            }
                            else
                            {
                                settled.Add(choices.First().Value);
                            }
                        }
                    }
                    if (settled.Count > 1)
                    {
                        // Remove no preference if present
                        settled.Remove(null);
                    }

                    if (ambiguous.Count > 0)
                    {
                        // Need 1 or more clarifications
                        fieldState.State          = FieldStepStates.SentClarify;
                        fieldState.Settled        = settled;
                        fieldState.Clarifications = ambiguous;
                        response = SetValue(state, null);
                        prompt   = ClarifyPrompt((FieldStepState)form.StepState, iprompt.Recognizer, state);
                    }
                    else
                    {
                        if (_field.AllowsMultiple)
                        {
                            response = settled;
                            feedback = await SetValueAsync(state, response, form);
                        }
                        else
                        {
                            Debug.Assert(settled.Count == 1);
                            response = settled.First();
                            feedback = await SetValueAsync(state, response, form);
                        }
                    }
                }
                var unmatched      = MatchAnalyzer.Unmatched(inputText, matches);
                var unmatchedWords = string.Join(" ", unmatched);
                var nonNoise       = Language.NonNoiseWords(Language.WordBreak(unmatchedWords)).ToArray();
                fieldState.Unmatched = null;
                if (_field.Prompt.Annotation.Feedback == FeedbackOptions.Always)
                {
                    fieldState.Unmatched = string.Join(" ", nonNoise);
                }
                else if (_field.Prompt.Annotation.Feedback == FeedbackOptions.Auto &&
                         nonNoise.Any() &&
                         unmatched.Any())
                {
                    fieldState.Unmatched = string.Join(" ", nonNoise);
                }
            }
            else if (fieldState.State == FieldStepStates.SentClarify)
            {
                if (matches.Count() == 1)
                {
                    // Clarified ambiguity
                    var clarify = NeedsClarification(fieldState);
                    fieldState.Settled.Add(matches.First().Value);
                    fieldState.Clarifications.Remove(clarify);
                    if (prompt == null)
                    {
                        // No clarification left, so set the field
                        if (_field.AllowsMultiple)
                        {
                            response = fieldState.Settled;
                            feedback = await SetValueAsync(state, response, form);
                        }
                        else
                        {
                            Debug.Assert(fieldState.Settled.Count == 1);
                            response = fieldState.Settled.First();
                            feedback = await SetValueAsync(state, response, form);
                        }
                        form.SetPhase(StepPhase.Completed);
                    }
                }
            }
            if (form.Phase() == StepPhase.Completed)
            {
                form.StepState = null;
                if (fieldState.Unmatched != null)
                {
                    if (feedback.FeedbackCard != null)
                    {
                        feedbackPrompt = feedback.FeedbackCard;
                    }
                    else if (feedback.Feedback != null)
                    {
                        feedbackPrompt = new FormPrompt {
                            Prompt = feedback.Feedback
                        };
                    }
                    else
                    {
                        if (fieldState.Unmatched != string.Empty)
                        {
                            feedbackPrompt = new Prompter <T>(_field.Template(TemplateUsage.Feedback), _field.Form, null).Prompt(state, _field, fieldState.Unmatched);
                        }
                        else
                        {
                            feedbackPrompt = new Prompter <T>(_field.Template(TemplateUsage.Feedback), _field.Form, null).Prompt(state, _field);
                        }
                    }
                }
            }
            var next = _field.Next(response, state);

            return(new StepResult(feedback.IsValid, next, feedbackPrompt ?? (feedback.FeedbackCard ?? new FormPrompt {
                Prompt = feedback.Feedback
            }), prompt));
        }