示例#1
0
        public static Activity CreateSettingChangeRequestEvent(SettingChange settingChange)
        {
            var settingEvent = Activity.CreateEventActivity();

            settingEvent.Name  = SettingChangeRequestEvent;
            settingEvent.Value = settingChange;
            return((Activity)settingEvent);
        }
示例#2
0
        private async Task SendActionToDevice(WaterfallStepContext sc, SettingChange setting, StringDictionary settingDetail)
        {
            // remove whitespace to create Event Name and prefix with Automotive Skill
            string reducedName = $"AutomotiveSkill.{Regex.Replace(setting.SettingName, @"\s+", string.Empty)}";

            var actionEvent = sc.Context.Activity.CreateReply();

            actionEvent.Type  = ActivityTypes.Event;
            actionEvent.Name  = reducedName;
            actionEvent.Value = settingDetail;

            await sc.Context.SendActivityAsync(actionEvent);
        }
示例#3
0
        /// <summary>
        /// Take the entities provided by LUIS (Setting and Value) to try and identify the vehicle setting we need to process.
        /// </summary>
        /// <param name="state">State object.</param>
        /// <param name="declarative">Indicates if special process for declarative utterances should be performed.</param>
        public void PostProcessSettingName(AutomotiveSkillState state, bool declarative = false)
        {
            if (state == null)
            {
                throw new ArgumentNullException(nameof(state));
            }

            IList <SettingMatch> setting_matches             = new List <SettingMatch>();
            var           has_matching_value_for_any_setting = false;
            ISet <string> setting_names_to_remove            = new HashSet <string>();

            // The Setting entity will contain any identified vehicle setting that was present in the utterance, e.g. front right airflow
            // The Value entity will contain any identified value relating to a vehicle setting that was present in the utterance, e.g. warm
            IList <AvailableSetting> selected_settings = new List <AvailableSetting>();

            if (state.Entities.ContainsKey("SETTING"))
            {
                // If we have a Setting then try to find a match between the setting name provided and the available settings
                selected_settings = this.settingMatcher.MatchSettingNamesExactly(state.Entities["SETTING"].First());

                // If we have not found an exact setting match but we have a value then combine Setting and Value together to identify a match
                if (!selected_settings.Any() && state.Entities.ContainsKey("VALUE"))
                {
                    /* First try SETTING + VALUE entities combined to catch cases like "warm my seat",
                     * where the value can help disambiguate which setting the user meant.*/

                    List <string> entityValuesToMatch = new List <string>();
                    entityValuesToMatch.AddRange(state.Entities["SETTING"]);
                    entityValuesToMatch.AddRange(state.Entities["VALUE"]);

                    selected_settings = this.settingMatcher.MatchSettingNames(
                        entityValuesToMatch, SettingNameScoreThreshold,
                        SettingNameAntonymDisambPercentageOfMax, false);
                }

                // If we still haven't found a match then try to match with just the setting but not exactly this time
                if (!selected_settings.Any())
                {
                    List <string> entityValuesToMatch = new List <string>();
                    entityValuesToMatch.AddRange(state.Entities["SETTING"]);

                    selected_settings = this.settingMatcher.MatchSettingNames(
                        entityValuesToMatch, SettingNameScoreThreshold,
                        SettingNameAntonymDisambPercentageOfMax, false);
                }
            }

            // Do we have a selected setting name?
            if (selected_settings.Any())
            {
                List <string> entityValuesToMatch = new List <string>();

                List <string> entity_types_for_value_disamb = new List <string>();
                if (state.Entities.ContainsKey("VALUE"))
                {
                    entityValuesToMatch.AddRange(state.Entities["VALUE"]);
                }
                else if (state.Entities.ContainsKey("SETTING"))
                {
                    // Sometimes the setting name itself is also a value, e.g., "defog"
                    entityValuesToMatch.AddRange(state.Entities["SETTING"]);
                }

                foreach (var setting_info in selected_settings)
                {
                    IList <SelectableSettingValue> selected_values = new List <SelectableSettingValue>();

                    if (entityValuesToMatch.Any())
                    {
                        IList <SelectableSettingValue> selectable_values = new List <SelectableSettingValue>();
                        foreach (var value in setting_info.Values)
                        {
                            SelectableSettingValue selectable = new SelectableSettingValue
                            {
                                CanonicalSettingName = setting_info.CanonicalName,
                                Value = value
                            };
                            selectable_values.Add(selectable);
                        }

                        /* From the available setting values for the given setting name identify which one applies for this setting name
                         * e.g. Set (when users says set temperature to 21 degrees
                         * e.g. Increase (when user says increase temperature)
                         * e.g. Decrease (when user says decrease temperature)
                         * e.g. Off, Alert, Alert and Brake when user wants to control Park Assist
                         */

                        selected_values = this.settingMatcher.DisambiguateSettingValues(
                            entityValuesToMatch, selectable_values,
                            SettingValueAntonymDisambThreshold, SettingValueAntonymDisambPercentageOfMax);

                        // If we don't even have a VALUE entity, we can't match multiple values.
                        // If the SETTING entity is really also a value, then it must match only one value.
                        if (!state.Entities.ContainsKey("VALUE") && selected_values.Count() > 1)
                        {
                            selected_values.Clear();
                        }

                        // For all selected values we return the canonical name for both the name and value
                        foreach (var selected_value in selected_values)
                        {
                            SettingMatch match = new SettingMatch
                            {
                                SettingName = setting_info.CanonicalName,
                                Value       = selected_value.Value.CanonicalName
                            };
                            setting_matches.Add(match);
                            has_matching_value_for_any_setting = true;
                        }
                    }

                    if (!selected_values.Any())
                    {
                        SettingMatch match = new SettingMatch
                        {
                            SettingName = setting_info.CanonicalName
                        };
                        setting_matches.Add(match);
                    }

                    AddAll(setting_names_to_remove, setting_info.IncludedSettings);
                }
            }
            else if (state.Entities.ContainsKey("VALUE") && !state.Entities.ContainsKey("SETTING"))
            {
                /*  If we have no SETTING entity, match the VALUE entities against all the values of all the settings.
                 *  This handles queries like "make it warmer" or "defog", where the value implies the setting.*/
                List <string> entityValuesToMatch = new List <string>();
                entityValuesToMatch.AddRange(state.Entities["VALUE"]);

                setting_matches = this.settingMatcher.MatchSettingValues(
                    entityValuesToMatch, SettingValueScoreThreshold,
                    SettingValueAntonymDisambPercentageOfMax);

                has_matching_value_for_any_setting = true;

                foreach (var match in setting_matches)
                {
                    var setting_info = this.settingList.FindSetting(match.SettingName);
                    if (setting_info != null)
                    {
                        AddAll(setting_names_to_remove, setting_info.IncludedSettings);
                    }
                }
            }

            // If at least one setting has a matching value, remove all settings with no matching value.
            // This effectively disambiguates the settings by their available values.
            // Also remove 'included' settings.
            IList <SettingMatch> new_setting_matches = new List <SettingMatch>();

            foreach (var match in setting_matches)
            {
                if ((!has_matching_value_for_any_setting || !string.IsNullOrEmpty(match.Value)) &&
                    !setting_names_to_remove.Contains(match.SettingName))
                {
                    new_setting_matches.Add(match);
                }
            }

            setting_matches = new_setting_matches;

            var(opt_amount, isRelative) = OptionalAmount(state, false);

            foreach (var setting_match in setting_matches)
            {
                SettingChange setting_change = new SettingChange
                {
                    SettingName = setting_match.SettingName
                };

                var value_info = this.settingList.FindSettingValue(setting_match.SettingName, setting_match.Value);
                if (declarative)
                {
                    // If the user makes a declarative statement, it means that they're unhappy with the status quo.
                    // So, we use the antonym of the value to get the opposite of the thing they're unhappy with,
                    // which should hopefully make them happy.
                    // If there is no antonym listed, then we want to return an empty value because we were unable to find
                    // the correct value.
                    if (value_info != null)
                    {
                        setting_change.Value = value_info.Antonym;
                    }
                }
                else
                {
                    setting_change.Value = setting_match.Value;
                }

                if (opt_amount != null && value_info != null && value_info.ChangesSignOfAmount)
                {
                    (opt_amount, isRelative) = OptionalAmount(state, true);
                }

                setting_change.Amount           = opt_amount;
                setting_change.IsRelativeAmount = isRelative;

                state.Changes.Add(setting_change);
            }

            if (!setting_matches.Any() && opt_amount != null)
            {
                SettingChange setting_change = new SettingChange
                {
                    Amount           = opt_amount,
                    IsRelativeAmount = isRelative
                };
                state.Changes.Add(setting_change);
            }
        }
示例#4
0
        /// <summary>
        /// Validate a change.
        /// </summary>
        /// <param name="setting">A setting for validation.</param>
        /// <returns>Validation Status enumeration.</returns>
        private ValidationStatus ValidateChange(SettingChange setting)
        {
            if (setting == null)
            {
                throw new ArgumentNullException(nameof(setting));
            }

            ValidationStatus validity = ValidationStatus.Valid;

            if (string.IsNullOrEmpty(setting.SettingName))
            {
                return(ValidationStatus.InvalidMissingSetting);
            }

            if (string.IsNullOrEmpty(setting.Value) && setting.Amount == null)
            {
                return(ValidationStatus.InvalidMissingValue);
            }

            var settingInfo = settingList.FindSetting(setting.SettingName);

            if (settingInfo == null)
            {
                return(ValidationStatus.InvalidSettingName);
            }

            AvailableSettingValue settingValueInfo = null;

            foreach (var valueInfo in settingInfo.Values)
            {
                if (Util.NullSafeEquals(setting.Value, valueInfo.CanonicalName) ||
                    (string.IsNullOrEmpty(setting.Value) && "SET".Equals(valueInfo.CanonicalName.ToUpperInvariant())))
                {
                    settingValueInfo = valueInfo;
                    setting.Value    = valueInfo.CanonicalName;
                    break;
                }
            }

            if (settingValueInfo == null)
            {
                return(ValidationStatus.InvalidSettingValueCombination);
            }

            if (setting.Amount == null)
            {
                if (settingValueInfo.RequiresAmount)
                {
                    validity = ValidationStatus.InvalidMissingAmount;
                }

                return(validity);
            }

            if (!settingInfo.AllowsAmount || Util.IsNullOrEmpty(settingInfo.Amounts))
            {
                return(ValidationStatus.InvalidExtraAmount);
            }

            AvailableSettingAmount settingAmountInfo = null;

            foreach (var amountInfo in settingInfo.Amounts)
            {
                if (Util.NullSafeEquals(setting.Amount.Unit, amountInfo.Unit))
                {
                    settingAmountInfo = amountInfo;
                    break;
                }
            }

            if (settingAmountInfo == null)
            {
                if ("%".Equals(setting.Amount.Unit))
                {
                    settingAmountInfo = new AvailableSettingAmount()
                    {
                        Unit = "%",
                        Min  = 0,
                        Max  = 100,
                    };
                }
                else
                {
                    return(ValidationStatus.InvalidAmountUnit);
                }
            }

            if (!setting.IsRelativeAmount)
            {
                if (setting.Amount.Amount < settingAmountInfo.Min || setting.Amount.Amount > settingAmountInfo.Max)
                {
                    return(ValidationStatus.InvalidAmountOutOfRange);
                }
            }
            else if (settingAmountInfo.Min != null && settingAmountInfo.Max != null)
            {
                var maxRelative = settingAmountInfo.Max - settingAmountInfo.Min;
                var minRelative = -maxRelative;
                if (setting.Amount.Amount < minRelative || setting.Amount.Amount > maxRelative)
                {
                    return(ValidationStatus.InvalidAmountOutOfRange);
                }
            }

            return(validity);
        }