diff --git a/Verification_Engine/Compute/CompareValues.cs b/Verification_Engine/Compute/CompareValues.cs index d543b9e55..5ba323c9c 100644 --- a/Verification_Engine/Compute/CompareValues.cs +++ b/Verification_Engine/Compute/CompareValues.cs @@ -24,7 +24,6 @@ using BH.oM.Base; using BH.oM.Base.Attributes; using BH.oM.Verification; -using BH.oM.Verification.Conditions; using System; using System.ComponentModel; @@ -32,6 +31,32 @@ namespace BH.Engine.Verification { public static partial class Compute { + /***************************************************/ + /**** Interface Methods ****/ + /***************************************************/ + + [Description("Compares two values using the provided comparison requirement and tolerance.")] + [Input("value", "Value to compare against the reference value.")] + [Input("referenceValue", "Reference value to compare the value against.")] + [Input("comparisonType", "Comparison requirement, i.e. whether the value should be equal, greater, less than reference value etc.")] + [Input("tolerance", "Tolerance to apply in the comparison.")] + [Output("result", "True if comparison of the input values meets the comparison requirement, otherwise false. Null in case of inconclusive comparison.")] + public static bool? ICompareValues(this object value, object referenceValue, ValueComparisonType comparisonType, object tolerance) + { + if (value == null) + { + if (comparisonType == ValueComparisonType.EqualTo) + return referenceValue == null; + else if (comparisonType == ValueComparisonType.NotEqualTo) + return referenceValue != null; + else + return null; + } + + return BH.Engine.Base.Compute.RunExtensionMethod(value, nameof(CompareValues), new object[] { referenceValue, comparisonType, tolerance }) as bool?; + } + + /***************************************************/ /**** Public Methods ****/ /***************************************************/ diff --git a/Verification_Engine/Compute/VerifyCondition.cs b/Verification_Engine/Compute/VerifyCondition.cs index 4f521ea68..dc9fe62e9 100644 --- a/Verification_Engine/Compute/VerifyCondition.cs +++ b/Verification_Engine/Compute/VerifyCondition.cs @@ -188,25 +188,10 @@ public static ValueConditionResult VerifyCondition(this object obj, IsInDomain c // If value found, check the actual condition object value = valueFromSource.Item2; bool? pass = false; - - double tolerance; - double.TryParse(condition.Tolerance.ToString(), out tolerance); - if (double.IsNaN(tolerance) || tolerance == 0) - { - BH.Engine.Base.Compute.RecordNote("Tolerance has not been set, default value of 1e-6 is being used."); - tolerance = 1e-6; - } - double numericalValue; - if (double.TryParse(value?.ToString(), out numericalValue)) - pass = Query.IsInDomain(numericalValue, condition.Domain, tolerance); - else if (value is DateTime) - { - DateTime? dt = value as DateTime?; - pass = Query.IsInDomain(dt.Value.Ticks, condition.Domain, tolerance); - } - else - pass = null; + pass = ICompareValues(value, condition.Domain.Min, ValueComparisonType.GreaterThanOrEqualTo, condition.Tolerance); + if (pass == true) + pass = ICompareValues(value, condition.Domain.Max, ValueComparisonType.LessThanOrEqualTo, condition.Tolerance); return new ValueConditionResult(pass, value); } @@ -349,17 +334,7 @@ public static ValueConditionResult VerifyCondition(this object obj, HasValue con return new ValueConditionResult(null, null); object value = valueFromSource.Item2; - bool? pass; - if (value == null) - pass = false; - else if (value is double valueDouble) - pass = !double.IsNaN(valueDouble); - else if (value is string valueString) - pass = !string.IsNullOrEmpty(valueString); - else - pass = !(value.GetType().IsNullable() && value != null); - - return new ValueConditionResult(pass, valueFromSource.Item2); + return new ValueConditionResult(value.IHasValue(), value); } /***************************************************/ @@ -391,7 +366,7 @@ public static ValueConditionResult VerifyCondition(this object obj, ValueConditi object value = valueFromSource?.Item2; // If value found, check the actual condition - bool? pass = value.CompareValues(condition.ReferenceValue, condition.ComparisonType, condition.Tolerance); + bool? pass = value.ICompareValues(condition.ReferenceValue, condition.ComparisonType, condition.Tolerance); return new ValueConditionResult(pass, value); } @@ -438,10 +413,7 @@ public static FormulaConditionResult VerifyCondition(this object obj, FormulaCon private static bool IsInSet(this object value, List set, ComparisonConfig comparisonConfig) { - if (comparisonConfig != null) - return set.Contains(value, new HashComparer(comparisonConfig)); - else - return set.Contains(value); + return set.Any(x => ICompareValues(value, x, ValueComparisonType.EqualTo, comparisonConfig) == true); } /***************************************************/ diff --git a/Verification_Engine/Query/FormulaComponent.cs b/Verification_Engine/Query/FormulaComponent.cs new file mode 100644 index 000000000..252591e9f --- /dev/null +++ b/Verification_Engine/Query/FormulaComponent.cs @@ -0,0 +1,60 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2025, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.oM.Base.Attributes; +using System.ComponentModel; + +namespace BH.Engine.Verification +{ + public static partial class Query + { + /***************************************************/ + /**** Interface Methods ****/ + /***************************************************/ + + [Description("Unpacks the object in preparation to solve a formula.")] + [Input("obj", "Object to unpack.")] + [Output("unpacked", "Input object unpacked and ready to use in formula solution.")] + public static object IFormulaComponent(this object obj) + { + if (obj == null) + return null; + + return BH.Engine.Base.Compute.RunExtensionMethod(obj, nameof(FormulaComponent)); + } + + + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + [Description("Unpacks the object in preparation to solve a formula.")] + [Input("obj", "Object to unpack.")] + [Output("unpacked", "Input object unpacked and ready to use in formula solution.")] + public static object FormulaComponent(this object obj) + { + return obj; + } + + /***************************************************/ + } +} diff --git a/Verification_Engine/Query/HasValue.cs b/Verification_Engine/Query/HasValue.cs new file mode 100644 index 000000000..5bbba47d1 --- /dev/null +++ b/Verification_Engine/Query/HasValue.cs @@ -0,0 +1,87 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2025, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.oM.Base.Attributes; +using System.ComponentModel; + +namespace BH.Engine.Verification +{ + public static partial class Query + { + /***************************************************/ + /**** Interface Methods ****/ + /***************************************************/ + + [Description("Checks if a given object has value (e.g. if a string is not empty etc.).")] + [Input("obj", "Object to check for valid value.")] + [Output("hasValue", "True if the input object has value, otherwise false.")] + public static bool? IHasValue(this object obj) + { + if (obj == null) + return false; + + object result; + if (!BH.Engine.Base.Compute.TryRunExtensionMethod(obj, nameof(HasValue), out result)) + { + BH.Engine.Base.Compute.RecordError($"Can't check if object has value because type {obj.GetType().Name} is currently not supported."); + return null; + } + + return (bool?)result; + } + + + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + [Description("Checks if a given number has value (is not NaN).")] + [Input("obj", "Number to check for valid value.")] + [Output("hasValue", "True if the number has value, otherwise false.")] + public static bool? HasValue(this double obj) + { + return !double.IsNaN(obj); + } + + /***************************************************/ + + [Description("Checks if a given string is not null or empty.")] + [Input("obj", "String to check for valid value.")] + [Output("hasValue", "True if the string is not null or empty, otherwise false.")] + public static bool? HasValue(this string obj) + { + return !string.IsNullOrEmpty(obj); + } + + /***************************************************/ + + [Description("Checks if a given object has value (e.g. if a string is not empty etc.).")] + [Input("obj", "Object to check for valid value.")] + [Output("hasValue", "True if the input object has value, otherwise false.")] + public static bool? HasValue(this object obj) + { + return obj != null; + } + + /***************************************************/ + } +}