public override string Help(T state, object defaultValue) { var prompt = new Prompter <T>(_field.Template(TemplateUsage.DateTimeHelp), _field.Form, null); var args = HelpArgs(state, defaultValue); return(prompt.Prompt(state, _field, args.ToArray()).Prompt); }
public FormPrompt Start(DialogContext context, T state, FormState form) { form.SetPhase(StepPhase.Completed); var prompt = new Prompter <T>(_promptDefinition, _form, null); return(prompt.Prompt(state, null)); }
public FormPrompt NotUnderstood(DialogContext context, T state, FormState form, IMessageActivity input) { var template = _field.Template(TemplateUsage.NotUnderstood); var prompter = new Prompter <T>(template, _field.Form, null); return(prompter.Prompt(state, _field, MessageActivityHelper.GetSanitizedTextInput(input))); }
public FormPrompt Help(T state, FormState form, string commandHelp) { var recognizer = _field.Prompt.Recognizer; var prompt = new Prompter <T>(_field.Template(TemplateUsage.HelpNavigation), _field.Form, recognizer, _fields); var help = prompt.Prompt(state, _field, "* " + recognizer.Help(state, null), commandHelp); return(new FormPrompt { Prompt = "* " + help.Prompt, Buttons = help.Buttons }); }
public FormPrompt Help(T state, FormState form, string commandHelp) { var template = _field.Template(TemplateUsage.HelpConfirm); var prompt = new Prompter <T>(template, _field.Form, _field.Prompt.Recognizer); var help = prompt.Prompt(state, _field, "* " + prompt.Recognizer.Help(state, null), commandHelp); return(new FormPrompt { Prompt = "* " + help.Prompt, Buttons = help.Buttons }); }
public override string Help(T state, object defaultValue) { var prompt = new Prompter <T>( _field.Template(this.multipleAttachments ? TemplateUsage.AttachmentCollectionHelp : TemplateUsage.AttachmentFieldHelp), _field.Form, null); // create instance just to call virtual method var awaitableAttachment = Activator.CreateInstance(this.GetAttachmentTypeFromField(), default(Attachment)) as AwaitableAttachment; return(prompt.Prompt(state, _field, awaitableAttachment.ProvideHelp(_field)).Prompt); }
public override string Help(T state, object defaultValue) { var prompt = new Prompter <T>(_field.Template(TemplateUsage.DoubleHelp), _field.Form, null); var args = HelpArgs(state, defaultValue); if (_showLimits) { args.Add(_min); args.Add(_max); } return(prompt.Prompt(state, _field, args.ToArray()).Prompt); }
protected void DefineRecognizer() { if (_recognizer == null) { if (_type == null || _type.IsEnum) { _recognizer = new RecognizeEnumeration <T>(this); } else if (_type == typeof(bool)) { _recognizer = new RecognizeBool <T>(this); } else if (_type == typeof(string)) { _recognizer = new RecognizeString <T>(this); } else if (_type.IsIntegral()) { _recognizer = new RecognizeNumber <T>(this); } else if (_type.IsDouble()) { _recognizer = new RecognizeDouble <T>(this); } else if (_type == typeof(DateTime)) { _recognizer = new RecognizeDateTime <T>(this); } else if (_type.IsAttachmentType() || _type.IsAttachmentCollection()) { _recognizer = new RecognizeAttachment <T>(this, _type.IsAttachmentCollection()); } else if (_type.IsIEnumerable()) { var elt = _type.GetGenericElementType(); if (elt.IsEnum) { _recognizer = new RecognizeEnumeration <T>(this); } } _buildPrompts = true; } if (_buildPrompts) { var template = Template(TemplateUsage.Help); _help = new Prompter <T>(template, _form, _recognizer); var prompt = _promptDefinition; _prompt = new Prompter <T>(_promptDefinition, _form, _recognizer); _buildPrompts = false; } }
private FormPrompt ClarifyPrompt(FieldStepState stepState, IRecognize <T> recognizer, T state) { var clarify = NeedsClarification(stepState); FormPrompt prompt = null; if (clarify != null) { var field = ClarifyField(clarify, recognizer); var prompter = new Prompter <T>(field.Template(TemplateUsage.Clarify), field.Form, new RecognizeEnumeration <T>(field)); prompt = prompter.Prompt(state, field, clarify.Response); } return(prompt); }
public NavigationField(string name, string startField, IForm <T> form, T state, FormState formState, Fields <T> fields) : base(name, FieldRole.Value) { Form = form; var field = form.Fields.Field(startField); SetFieldDescription(_form.Configuration.Navigation); SetOptional(); foreach (var value in formState.Next.Names) { var svalue = (string)value; var sfield = form.Fields.Field(svalue); var fieldPrompt = sfield.Template(TemplateUsage.NavigationFormat); var prompter = new Prompter <T>(fieldPrompt, form, sfield.Prompt.Recognizer); AddDescription(value, prompter.Prompt(state, sfield).Prompt, null, sfield.FieldDescription.Message ?? sfield.FieldDescription.Description); AddTerms(value, form.Fields.Field(svalue).FieldTerms.ToArray()); } var template = field.Template(TemplateUsage.Navigation); SetPrompt(new PromptAttribute(template)); SetRecognizer(new RecognizeEnumeration <T>(this)); _prompt = new Prompter <T>(template, form, _recognizer, fields); }
public async Task <StepResult> ProcessAsync(DialogContext 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 != "") { 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)); }
private string ExpandTemplate(string template, string currentChoice, string noValue, T state, IField <T> field, object[] args, ref IList <DescribeAttribute> buttons) { bool foundUnspecified = false; int last = 0; int numeric; var response = new StringBuilder(); foreach (Match match in _args.Matches(template)) { var expr = match.Groups[1].Value.Trim(); var substitute = string.Empty; if (expr.StartsWith("&")) { var name = expr.Substring(1); if (name == string.Empty && field != null) { name = field.Name; } var pathField = _fields.Field(name); substitute = Language.Normalize(pathField == null ? field.Name : pathField.FieldDescription.Description, _annotation.FieldCase); } else if (expr == "||") { var builder = new StringBuilder(); var values = _recognizer.ValueDescriptions(); var useButtons = !field.AllowsMultiple && (_annotation.ChoiceStyle == ChoiceStyleOptions.Auto || _annotation.ChoiceStyle == ChoiceStyleOptions.Buttons || _annotation.ChoiceStyle == ChoiceStyleOptions.Carousel); if (values.Any() && _annotation.AllowDefault != BoolDefault.False && field.Optional) { values = values.Concat(new DescribeAttribute[] { new DescribeAttribute(Language.Normalize(noValue, _annotation.ChoiceCase)) }); } string current = null; if (_annotation.AllowDefault != BoolDefault.False) { if (!field.Optional) { if (!field.IsUnknown(state)) { current = ExpandTemplate(currentChoice, null, noValue, state, field, args, ref buttons); } } else { current = ExpandTemplate(currentChoice, null, noValue, state, field, args, ref buttons); } } if (values.Any()) { if (useButtons) { foreach (var value in values) { buttons.Add(value); } } else { // Buttons do not support multiple selection so we fall back to text if (((_annotation.ChoiceStyle == ChoiceStyleOptions.Auto || _annotation.ChoiceStyle == ChoiceStyleOptions.AutoText) && values.Count() < 4) || (_annotation.ChoiceStyle == ChoiceStyleOptions.Inline)) { // Inline choices if (_annotation.ChoiceParens == BoolDefault.True) { builder.Append('('); } var choices = new List <string>(); var i = 1; foreach (var value in values) { choices.Add(string.Format(_annotation.ChoiceFormat, i, Language.Normalize(value.Description, _annotation.ChoiceCase))); ++i; } builder.Append(Language.BuildList(choices, _annotation.ChoiceSeparator, _annotation.ChoiceLastSeparator)); if (_annotation.ChoiceParens == BoolDefault.True) { builder.Append(')'); } if (current != null) { builder.Append(" "); builder.Append(current); } } else { // Separate line choices if (current != null) { builder.Append(current); builder.Append(" "); } var i = 1; foreach (var value in values) { builder.AppendLine(); builder.Append(" "); if (!_annotation.AllowNumbers) { builder.Append("* "); } builder.AppendFormat(_annotation.ChoiceFormat, i, Language.Normalize(value.Description, _annotation.ChoiceCase)); ++i; } } } } else if (current != null) { builder.Append(" "); builder.Append(current); } substitute = builder.ToString(); } else if (expr.StartsWith("*")) { // Status display of active results var filled = expr.ToLower().Trim().EndsWith("filled"); var builder = new StringBuilder(); if (match.Index > 0) { builder.AppendLine(); } foreach (var entry in (from step in _fields where (!filled || !step.IsUnknown(state)) && step.Role == FieldRole.Value && step.Active(state) select step)) { var format = new Prompter <T>(Template(entry, TemplateUsage.StatusFormat), _form, null); builder.Append("* ").AppendLine(format.Prompt(state, entry).Prompt); } substitute = builder.ToString(); } else if (expr.StartsWith("[") && expr.EndsWith("]")) { // Generate a list from multiple fields var paths = expr.Substring(1, expr.Length - 2).Split(' '); var values = new List <Tuple <IField <T>, object, string> >(); foreach (var spec in paths) { if (!spec.StartsWith("{") || !spec.EndsWith("}")) { throw new ArgumentException("Only {<field>} references are allowed in lists."); } var formatArgs = spec.Substring(1, spec.Length - 2).Trim().Split(':'); var name = formatArgs[0]; if (name == string.Empty && field != null) { name = field.Name; } var format = (formatArgs.Length > 1 ? "0:" + formatArgs[1] : "0"); var eltDesc = _fields.Field(name); if (!eltDesc.IsUnknown(state)) { var value = eltDesc.GetValue(state); if (value.GetType() != typeof(string) && value.GetType().IsIEnumerable()) { var eltValues = (value as System.Collections.IEnumerable); foreach (var elt in eltValues) { values.Add(Tuple.Create(eltDesc, elt, format)); } } else { values.Add(Tuple.Create(eltDesc, eltDesc.GetValue(state), format)); } } } if (values.Count() > 0) { var elements = (from elt in values select Language.Normalize(ValueDescription(elt.Item1, elt.Item2, elt.Item3), _annotation.ValueCase)).ToArray(); substitute = Language.BuildList(elements, _annotation.Separator, _annotation.LastSeparator); } } else if (expr.StartsWith("?")) { // Conditional template var subValue = ExpandTemplate(expr.Substring(1), currentChoice, null, state, field, args, ref buttons); if (subValue == null) { substitute = string.Empty; } else { substitute = subValue; } } else if (TryParseFormat(expr, out numeric)) { // Process ad hoc arg if (numeric < args.Length && args[numeric] != null) { substitute = string.Format("{" + expr + "}", args); } else { foundUnspecified = true; break; } } else { var formatArgs = expr.Split(':'); var name = formatArgs[0]; if (name == string.Empty && field != null) { name = field.Name; } var pathDesc = _fields.Field(name); if (pathDesc.IsUnknown(state)) { if (noValue == null) { foundUnspecified = true; break; } substitute = noValue; } else { var value = pathDesc.GetValue(state); if (value.GetType() != typeof(string) && value.GetType().IsIEnumerable()) { if (value.GetType().IsAttachmentCollection()) { var locTemplate = this._form.Configuration.Template(TemplateUsage.AttachmentCollectionDescription); substitute = string.Format(locTemplate.Pattern(), (value as IEnumerable <AwaitableAttachment>).Count()); } else { var values = (value as System.Collections.IEnumerable); substitute = Language.BuildList(from elt in values.Cast <object>() select Language.Normalize(ValueDescription(pathDesc, elt, "0"), _annotation.ValueCase), _annotation.Separator, _annotation.LastSeparator); } } else if (value.GetType().IsAttachmentType()) { var attachment = (value as AwaitableAttachment).Attachment; var locTemplate = this._form.Configuration.Template(TemplateUsage.AttachmentFieldDescription); substitute = string.Format(locTemplate.Pattern(), attachment.Name, attachment.ContentType); } else { var format = (formatArgs.Length > 1 ? "0:" + formatArgs[1] : "0"); substitute = ValueDescription(pathDesc, value, format); } } } response.Append(template.Substring(last, match.Index - last)).Append(substitute); last = match.Index + match.Length; } return(foundUnspecified ? null : response.Append(template.Substring(last, template.Length - last)).ToString()); }