int Add(QueryMatchID matchId,
                IMRObject objectRef,
                Exclusivity exclusivity,
                int bestMatchDataId,
                bool isRequired,
                CachedTraitCollection traitCache,
                ProxyConditions condition,
                ProxyTraitRequirements requirements,
                ConditionRatingsData rating,
                HashSet <int> matchSet,
                Dictionary <int, float> flatRatings,
                QueryResult result)
        {
            var index = GetInsertionIndex();

            QueryMatchIds[index]           = matchId;
            ObjectReferences[index]        = objectRef;
            Exclusivities[index]           = exclusivity;
            Required[index]                = isRequired;
            BestMatchDataIds[index]        = bestMatchDataId;
            CachedTraits[index]            = traitCache;
            Conditions[index]              = condition;
            TraitRequirements[index]       = requirements;
            RelationMemberships[index]     = null;
            ConditionRatings[index]        = rating;
            ReducedConditionRatings[index] = flatRatings;
            ConditionMatchSets[index]      = matchSet;
            QueryResults[index]            = result;

            m_Count++;
            ValidIndices.Add(index);
            return(index);
        }
        internal bool TryFillTraitRequirementsUpdate(int dataId, ProxyTraitRequirements requirements, QueryResult result)
        {
            foreach (var requirement in requirements)
            {
                GetTraitProvider(out MARSTraitDataProvider <Pose> poseTraitProvider);
                // We check Poses first because that is our most common use case
                if (requirement.Type == typeof(Pose))
                {
                    if (requirement.Required)
                    {
                        if (poseTraitProvider.dictionary.TryGetValue(requirement.TraitName, out var traitValues))
                        {
                            if (traitValues.TryGetValue(dataId, out var nonOffsetPose))
                            {
                                result.SetTrait(requirement.TraitName, this.ApplyOffsetToPose(nonOffsetPose));
                            }
                            else
                            {
                                return(false);
                            }
                        }
                        else
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        if (!poseTraitProvider.dictionary.TryGetValue(requirement.TraitName, out var traitValues))
                        {
                            continue;
                        }

                        if (traitValues.TryGetValue(dataId, out var nonOffset))
                        {
                            result.SetTrait(requirement.TraitName, this.ApplyOffsetToPose(nonOffset));
                        }
                    }

                    continue;
                }

                // find the type-specific requirement update action to use.
                // if a KeyNotFound exception happens here,
                // we didn't register a type handler for this when we initialized the system
                if (MarsDataType.TryGetFromType(requirement.Type, out var marsType))
                {
                    if (!TypeToRequirementUpdate[marsType](requirement, dataId, result))
                    {
                        return(false);
                    }
                }
                else
                {
                    return(false);
                }
            }

            return(true);
        }
        /// <summary>
        /// See if the value for a given data ID still meets a set of Conditions
        /// </summary>
        /// <param name="dataID">The id of the data value to check</param>
        /// <param name="conditions">The conditions to evaluate against</param>
        /// <param name="result">The Query result to fill out with updated values</param>
        /// <returns>True if the query data still matches, false otherwise</returns>
        public bool TryUpdateQueryMatchData(int dataID, ProxyConditions conditions, ProxyTraitRequirements requirements, QueryResult result)
        {
            if (requirements != null)
            {
                if (!TryFillTraitRequirementsUpdate(dataID, requirements, result))
                {
                    return(false);
                }
            }

            GetTraitProvider(out MARSTraitDataProvider <Pose> poseTraitProvider);
            GetTraitProvider(out MARSTraitDataProvider <bool> tagTraitProvider);
            if (conditions.TryGetType(out ICondition <Pose>[] poseConditions))
            {
                foreach (var condition in poseConditions)
                {
                    if (!poseTraitProvider.TryGetTraitValue(dataID, condition.traitName, out var traitValue))
                    {
                        return(false);
                    }

                    if (condition.PassesCondition(ref traitValue))
                    {
                        result.SetTrait(condition.traitName, this.ApplyOffsetToPose(traitValue));
                    }
                    else
                    {
                        return(false);
                    }
                }
            }

            if (conditions.TryGetType(out ISemanticTagCondition[] semanticTagConditions))
            {
                foreach (var condition in semanticTagConditions)
                {
                    if (!tagTraitProvider.TryGetTraitValue(dataID, condition.traitName, out var traitValue))
                    {
                        if (condition.matchRule == SemanticTagMatchRule.Match)
                        {
                            return(false);
                        }

                        continue; // an excluding match update made by lack of tag
                    }

                    if (condition.PassesCondition(ref traitValue) && condition.matchRule == SemanticTagMatchRule.Match)
                    {
                        result.SetTrait(condition.traitName, traitValue);
                    }
                    else
                    {
                        return(false);
                    }
                }
            }

            // Update all condition types that we don't special-case in generated code
            return(UpdateQueryMatchInternal(dataID, conditions, requirements, result));
        }
        internal void FillQueryResultRequirements(int dataId, ProxyTraitRequirements requirements, QueryResult result)
        {
            foreach (var requirement in requirements)
            {
                // We check Poses first because that is our most common use case & we have to offset the output
                if (requirement.Type == typeof(Pose))
                {
                    GetTraitProvider(out MARSTraitDataProvider <Pose> poseTraitProvider);
                    if (requirement.Required)
                    {
                        if (poseTraitProvider.dictionary.TryGetValue(requirement.TraitName, out var traitValues))
                        {
                            if (traitValues.TryGetValue(dataId, out var nonOffsetPose))
                            {
                                result.SetTrait(requirement.TraitName, this.ApplyOffsetToPose(nonOffsetPose));
                            }
                        }
                    }
                    else
                    {
                        if (!poseTraitProvider.dictionary.TryGetValue(requirement.TraitName, out var traitValues))
                        {
                            continue;
                        }

                        if (traitValues.TryGetValue(dataId, out var nonOffset))
                        {
                            result.SetTrait(requirement.TraitName, this.ApplyOffsetToPose(nonOffset));
                        }
                    }

                    continue;
                }

                TypeToRequirementFill[(MarsDataType)requirement.Type](requirement, dataId, result);
            }
        }
        public bool UpdateQueryMatchInternal(int dataID,
                                             Conditions conditions, ProxyTraitRequirements requirements, QueryResult result)
        {
            if (conditions.TryGetType(out ICondition <System.Int32>[] intConditions))
            {
                foreach (var condition in intConditions)
                {
                    if (!IntTraitProvider.TryGetTraitValue(dataID, condition.traitName, out var traitValue))
                    {
                        return(false);
                    }
                    if (condition.PassesCondition(ref traitValue))
                    {
                        result.SetTrait(condition.traitName, traitValue);
                    }
                    else
                    {
                        return(false);
                    }
                }
            }

            if (conditions.TryGetType(out ICondition <System.Single>[] floatConditions))
            {
                foreach (var condition in floatConditions)
                {
                    if (!FloatTraitProvider.TryGetTraitValue(dataID, condition.traitName, out var traitValue))
                    {
                        return(false);
                    }
                    if (condition.PassesCondition(ref traitValue))
                    {
                        result.SetTrait(condition.traitName, traitValue);
                    }
                    else
                    {
                        return(false);
                    }
                }
            }

            if (conditions.TryGetType(out ICondition <System.String>[] stringConditions))
            {
                foreach (var condition in stringConditions)
                {
                    if (!StringTraitProvider.TryGetTraitValue(dataID, condition.traitName, out var traitValue))
                    {
                        return(false);
                    }
                    if (condition.PassesCondition(ref traitValue))
                    {
                        result.SetTrait(condition.traitName, traitValue);
                    }
                    else
                    {
                        return(false);
                    }
                }
            }

            if (conditions.TryGetType(out ICondition <UnityEngine.Vector2>[] vector2Conditions))
            {
                foreach (var condition in vector2Conditions)
                {
                    if (!Vector2TraitProvider.TryGetTraitValue(dataID, condition.traitName, out var traitValue))
                    {
                        return(false);
                    }
                    if (condition.PassesCondition(ref traitValue))
                    {
                        result.SetTrait(condition.traitName, traitValue);
                    }
                    else
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
 /// <summary>
 /// Tries to fill out a QueryResult with updated data for a query that has been matched.
 /// This also checks if the data no longer meets the given conditions.
 /// </summary>
 /// <param name="dataID">ID for the data used by the query match</param>
 /// <param name="conditions">Criteria that the data must continue to meet</param>
 /// <param name="result">Object that will contain the updated data that still matches the conditions</param>
 /// <returns>True if the data still matches the conditions, false otherwise</returns>
 public static bool TryUpdateQueryMatchData(this IUsesDatabaseQuerying obj, int dataID, ProxyConditions conditions, ProxyTraitRequirements requirements, QueryResult result)
 {
     return(IUsesDatabaseQueryingMethods.TryUpdateQueryMatchData(dataID, conditions, requirements, result));
 }