static void FillRelationChildResults <T>(MARSTraitDataProvider <T> traitProvider,
                                                 Dictionary <IMRObject, QueryResult> childResults, Dictionary <IMRObject, int> dataAssignments,
                                                 IRelation <T>[] typeRelations)
        {
            foreach (var relation in typeRelations)
            {
                var child1 = relation.child1;
                if (childResults.TryGetValue(child1, out var child1Result))
                {
                    var trait1Name = relation.child1TraitName;
                    traitProvider.TryGetTraitValue(dataAssignments[child1], trait1Name, out var value1);
                    child1Result.SetTrait(trait1Name, value1);
                }

                var child2 = relation.child2;
                if (childResults.TryGetValue(child2, out var child2Result))
                {
                    var trait2Name = relation.child2TraitName;
                    traitProvider.TryGetTraitValue(dataAssignments[child2], trait2Name, out var value2);
                    child2Result.SetTrait(trait2Name, value2);
                }
            }
        }
        static bool ConditionsPass <T>(MARSTraitDataProvider <T> traitProvider, ICondition <T>[] conditions, int dataId)
        {
            foreach (var condition in conditions)
            {
                var passed = traitProvider.TryGetTraitValue(dataId, condition.traitName, out var value) &&
                             condition.PassesCondition(ref value);

                if (!passed)
                {
                    return(false);
                }
            }

            return(true);
        }
        // this function is used by generated code
        static bool CheckIfDataStillMatches <T>(Dictionary <IMRObject, int> dataAssignments,
                                                IRelation <T>[] relations, MARSTraitDataProvider <T> traitProvider,
                                                Dictionary <IMRObject, SetChildArgs> children, HashSet <IMRObject> nonRequiredChildrenLost)
        {
            foreach (var relation in relations)
            {
                var child1 = relation.child1;
                var child2 = relation.child2;

                // If a child is not in dataAssignments then it is a non-required child that was lost in a previous update,
                // and there's no need to check this relation.
                if (!dataAssignments.TryGetValue(child1, out var dataID1) || !dataAssignments.TryGetValue(child2, out var dataID2))
                {
                    continue;
                }

                var child1Required = children[child1].required;
                var child2Required = children[child2].required;
                var trait1Name     = relation.child1TraitName;
                var trait2Name     = relation.child2TraitName;
                var trait1Exists   = traitProvider.TryGetTraitValue(dataID1, trait1Name, out var trait1Value);
                var trait2Exists   = traitProvider.TryGetTraitValue(dataID2, trait2Name, out var trait2Value);

                if (!trait1Exists)
                {
                    if (child1Required)
                    {
                        return(false);
                    }

                    nonRequiredChildrenLost.Add(child1);
                }

                if (!trait2Exists)
                {
                    if (child2Required)
                    {
                        return(false);
                    }

                    nonRequiredChildrenLost.Add(child2);
                }

                if (trait1Exists && trait2Exists && !relation.PassesRelation(ref trait1Value, ref trait2Value))
                {
                    if (child1Required && child2Required)
                    {
                        return(false);
                    }

                    if (!child1Required)
                    {
                        nonRequiredChildrenLost.Add(child1);
                    }

                    if (!child2Required)
                    {
                        nonRequiredChildrenLost.Add(child2);
                    }
                }
            }
            return(true);
        }