/// <summary> /// Returns the created Metric Tree with all data values and metadata included /// </summary> /// <param name="metricInstanceSetRequest">The request originally passed to the metric service, containing the domain-specific context.</param> /// <param name="metricMetadataNode">Should already Filtered by MetricNodeId</param> /// <param name="metricDataContainer">Should already be filtered by the domain entity key</param> /// <returns>An instance of a class derived from <see cref="MetricBase"/>, and all its descendents.</returns> public MetricBase CreateTree(MetricInstanceSetRequestBase metricInstanceSetRequest, MetricMetadataNode metricMetadataNode, MetricDataContainer metricDataContainer) { // Get the custom metric initialization activity data var initializationActivityData = GetMetricInitializationActivityData(metricInstanceSetRequest); return CreateMetric(metricInstanceSetRequest, metricMetadataNode, metricDataContainer, null, initializationActivityData); }
protected override void EstablishContext() { //Prepare supplied data collections suppliedStudentInformationData = GetSuppliedStudentInformation(); suppliedRootMetricNode = GetSuppliedRootNode(); suppliedRootMetricHierarchy = GetSuppliedRootMetricHierarchy(); suppliedRootIEnumerableOfKeyValuePair = GetSuppliedRootKeyValuePairs(); //Set up the mocks studentInformationRepository = mocks.StrictMock<IRepository<StudentInformation>>(); rootMetricNodeResolver = mocks.StrictMock<IRootMetricNodeResolver>(); domainMetricService = mocks.StrictMock<IDomainMetricService<StudentSchoolMetricInstanceSetRequest>>(); metricTreeToIEnumerableOfKeyValuePairProvider = mocks.StrictMock<IMetricTreeToIEnumerableOfKeyValuePairProvider>(); //Set expectations Expect.Call(studentInformationRepository.GetAll()).Return(suppliedStudentInformationData); Expect.Call(rootMetricNodeResolver.GetRootMetricNode()).Return(suppliedRootMetricNode); Expect.Call(domainMetricService.Get(null)) .Constraints( new ActionConstraint<StudentSchoolMetricInstanceSetRequest>(x => { Assert.That(x.SchoolId == suppliedSchoolId); Assert.That(x.StudentUSI == suppliedStudentUSI); Assert.That(x.MetricVariantId == suppliedRootMetricNode.MetricVariantId); }) ).Return(suppliedRootMetricHierarchy); Expect.Call(metricTreeToIEnumerableOfKeyValuePairProvider.FlattenMetricTree((ContainerMetric) suppliedRootMetricHierarchy.RootNode)).Return(suppliedRootIEnumerableOfKeyValuePair); }
protected virtual ChartData.Series[] GetChartSeries(IEnumerable <StudentMetricAssessmentHistorical> data, MetricMetadataNode metricMetadataNode, string labelType) { decimal?previousValue = null; var result = new List <ChartData.Point>(); foreach (var entry in data) { decimal?value = null; string valueAsText = null; if (!String.IsNullOrEmpty(entry.Value)) { value = Convert.ToDecimal(entry.Value); valueAsText = metricMetadataNode.Format != null ? string.Format(metricMetadataNode.Format, value) : entry.Value; } var trend = GetTrend(previousValue, value); var point = MapDataToPoint(entry, valueAsText, trend, GetValueScaling(labelType)); previousValue = value; result.Add(point); } return(new[] { new ChartData.Series { Name = metricMetadataNode.DisplayName, Points = result } }); }
private static Goal CalculateGoal(MetricMetadataNode metricNode, MetricGoal goalData, MetricInstance metricInstance) { //If we have a disabled metric we should not blow up and return a default Goal. if(!metricNode.Enabled) return new Goal { Interpretation = TrendInterpretation.None, Value = null }; if (metricNode.TrendInterpretation == null) throw new InvalidOperationException(string.Format("Trend Interpretation is needed to be able to calculate Goal. Metric Id({0})", metricNode.MetricId)); //Lets try to get goal from data. var goalFromData = GetGoalFromGoalData(metricNode, goalData); if (goalFromData != null) return goalFromData; //If we are still here lets get the Goal value from the MetricState. var goalFromMetricState = GetGoalFromMetricState(metricNode, goalData, metricInstance); if (goalFromMetricState != null) return goalFromMetricState; //If we are still here something went wrong. throw new InvalidOperationException("Something went wrong and I could not calculate a goal for metric Id:" + metricNode.MetricId); }
protected override void EstablishContext() { metadataNode = getSuppliedMetaDataNode(); suppliedGranularMetricFlagged = new GranularMetric<int> { MetricId = 20 }; suppliedGranularMetricNotFlagged = new GranularMetric<int> { MetricId = 40 }; suppliedMetricDataFlagged = new CurrentYearMetricData { MetricInstances = (new List<MetricInstance>() { new MetricInstance { MetricId = 20, Flag = true } }).AsQueryable() }; suppliedMetricDataNotFlagged = new CurrentYearMetricData { MetricInstances = (new List<MetricInstance>() { new MetricInstance { MetricId = 40, Flag = false } }).AsQueryable() }; }
public bool GetMetricFlag(MetricBase metricBase, MetricMetadataNode metadataNode, MetricData metricData) { var metricInstance = metricData.MetricInstancesByMetricId.GetValueOrDefault(metricBase.MetricId); if (metricInstance == null) return false; return metricInstance.Flag.GetValueOrDefault(); }
public Goal GetMetricGoal(MetricMetadataNode metricMetadataNode, MetricData metricData) { if (metricData.MetricGoalsByMetricId == null) return null; var goalData = metricData.MetricGoalsByMetricId.GetValueOrDefault(metricMetadataNode.MetricId); var metricInstance = metricData.MetricInstancesByMetricId.GetValueOrDefault(metricMetadataNode.MetricId); return CalculateGoal(metricMetadataNode, goalData, metricInstance); }
public MetricData GetMetricData(MetricMetadataNode metricMetadataNode) { foreach (var md in metricData) { if (md.CanSupplyMetricData(metricMetadataNode)) return md; } throw new NotSupportedException("Can't resolve metric data for metric metadata node '" + metricMetadataNode.MetricNodeId + "'."); }
protected override void EstablishContext() { //Prepare supplied data collections suppliedGranularMetric = GetSuppliedGM(); suppliedMetricMetadataNode = GetSuppliedMetricMetadataNode(); //Set up the mocks domainSpecificMetricNodeResolver = mocks.StrictMock<IDomainSpecificMetricNodeResolver>(); //Set expectations var tree = new TestMetricMetadataTree(); Expect.Call(domainSpecificMetricNodeResolver.GetAdvancedCourseEnrollmentMetricNode()).Return(new MetricMetadataNode(tree) { MetricId = 1 }); Expect.Call(domainSpecificMetricNodeResolver.GetAdvancedCoursePotentialMetricNode()).Return(new MetricMetadataNode(tree) { MetricId = 2 }); }
protected override void EstablishContext() { //initialize Granular Metrics granularMetricInt = getSuppliedGranularMetric_int(); granularMetricDecimal = getSuppliedGranularMetric_decimal(); granularMetricDouble = getSuppliedGranularMetric_double(); granularMetricString = getSuppliedGranularMetric_string(); //initialize metadata nodes metadataNodeInt = getSuppliedMetricMetadataNode_int(); metadataNodeDecimal = getSuppliedMetricMetadataNode_decimal(); metadataNodeDouble = getSuppliedMetricMetadataNode_double(); metadataNodeString = getSuppliedMetricMetadataNode_string(); }
public State GetState(MetricMetadataNode metricNode, MetricInstance metricInstance) { var defaultState = new State(MetricStateType.None, string.Empty); //If the instance is null then we cant calculate a state so we default to none. if (metricInstance == null) return defaultState; //Lets see if the State has been supplied to us. if (metricInstance.MetricStateTypeId.HasValue) { var suppliedState = (MetricStateType) metricInstance.MetricStateTypeId.Value; //We can have more than one state rule per state type so lets see what weve got. var metricStateRules = metricNode.States.Where(x => x.StateType == suppliedState); //We only need one rule to proceed. Models.MetricState singleRuleThatApplies = null; if (metricStateRules.Count() == 1) singleRuleThatApplies = metricStateRules.Single(); if (metricStateRules.Count() > 1) singleRuleThatApplies = GetStateThatAppliesFromMultipleStates(metricNode, metricInstance, metricStateRules); //If we didnt find any then lets check if our metric is enabled. if (!metricStateRules.Any() || singleRuleThatApplies == null) { //If there is no state then we should see if the metric is enabled, if so this is a problem in the metadata... if (metricNode.Enabled) throw new InvalidOperationException("Metric Id:" + metricNode.MetricId + " needs a Metric State value in its table to be able to calculate a State."); //If we are still here it means that we have a disabled metric and we should not blow up. return defaultState; } return new State(suppliedState, singleRuleThatApplies.StateText); } //If we are still here then we don't have a supplied state and now we need to go and calculate the state. return CalculateState(metricNode, metricInstance.Value, metricInstance.ValueTypeName); }
protected override void EstablishContext() { suppliedMetricInstanceSetRequest = new SomeMetricInstanceSetRequest { MetricVariantId = suppliedMetricVariantId }; //mock data services return metricMetadataTreeService = mocks.StrictMock<IMetricMetadataTreeService>(); Expect.Call(metricMetadataTreeService.Get(null)).IgnoreArguments().Return(GetSuppliedMetricMetadataTree()); metricDataService = mocks.StrictMock<IMetricDataService<SomeMetricInstanceSetRequest>>(); Expect.Call(metricDataService.Get(suppliedMetricInstanceSetRequest)).Return(GetSuppliedMetricData()); metricInstanceTreeFactory = mocks.StrictMock<IMetricInstanceTreeFactory>(); Expect.Call(metricInstanceTreeFactory.CreateTree(suppliedMetricInstanceSetRequest, null, null)) .IgnoreArguments() .Return(GetSuppliedMetricInstanceTree()); var suppliedMetricNode = new MetricMetadataNode(new TestMetricMetadataTree()) { MetricNodeId = suppliedMetricNodeId }; metricNodeResolver = mocks.StrictMock<IMetricNodeResolver>(); Expect.Call(metricNodeResolver.ResolveFromMetricVariantId(suppliedMetricVariantId)).Return(suppliedMetricNode); }
protected virtual MetricRenderingContext FindRenderingParent(MetricMetadataNode root, int? metricIdToFind, MetricVariantType metricVariantType) { if (root == null || !metricIdToFind.HasValue) return new MetricRenderingContext(); //We are at the overview collection level. foreach (var renderingParent in root.Children) { var tempMetric = renderingParent.FindInDescendantsOrSelfByMetricId(metricIdToFind.Value).SingleOrDefault(x => x.MetricVariantType == metricVariantType); if (tempMetric == null) tempMetric = renderingParent.FindInDescendantsOrSelfByMetricId(metricIdToFind.Value).SingleOrDefault(); if (tempMetric != null)//We found it return new MetricRenderingContext { ContextMetricVariantId = renderingParent.MetricVariantId, MetricVariantId = tempMetric.MetricVariantId }; } return null; }
//Method used to tag the parents to the hierarchy protected void setParents(MetricMetadataNode metric, MetricMetadataNode parentMetric) { metric.Parent = parentMetric; foreach (var childMetric in metric.Children) setParents(childMetric, metric); }
private MetricBase CreateMetric(MetricInstanceSetRequestBase metricInstanceSetRequest, MetricMetadataNode metricMetadataNode, MetricDataContainer metricDataContainer, MetricBase parentMetric, Dictionary<string, object> initializationActivityData) { MetricBase metric; var metricData = metricDataContainer.GetMetricData(metricMetadataNode); switch (metricMetadataNode.MetricType) { case MetricType.ContainerMetric: metric = containerMetricFactory.CreateMetric(metricInstanceSetRequest, metricMetadataNode, metricData, parentMetric); break; case MetricType.AggregateMetric: metric = aggregateMetricFactory.CreateMetric(metricInstanceSetRequest, metricMetadataNode, metricData, parentMetric); break; case MetricType.GranularMetric: metric = granularMetricFactory.CreateMetric(metricInstanceSetRequest, metricMetadataNode, metricData, parentMetric); break; default: throw new NotSupportedException(string.Format("Unsupported metric type '{0}'.", metricMetadataNode.MetricType)); } // Process children var metricWithChildren = metric as ContainerMetric; // If this is a node type that has children if (metricWithChildren != null) ProcessForChildren(metricInstanceSetRequest, metricMetadataNode, metricDataContainer, metricWithChildren, initializationActivityData); // Execute initialization activities InvokeInitializationActivities(metric, metricInstanceSetRequest, metricMetadataNode, metricData, initializationActivityData); return metric; }
public override bool CanSupplyMetricData(MetricMetadataNode metricMetadataNode) { return metricNodeId == metricMetadataNode.MetricNodeId; }
protected virtual void InvokeInitializationActivities(MetricBase metric, MetricInstanceSetRequestBase metricInstanceSetRequest, MetricMetadataNode metadataNode, MetricData metricData, Dictionary<string, object> initializationActivityData) { foreach (var initializationActivity in metricInitializationActivities) initializationActivity.InitializeMetric(metric, metricInstanceSetRequest, metadataNode, metricData, initializationActivityData); }
public virtual MetricMetadataNode GetRootMetricNodeForLocalEducationAgency() { if (_rootMetricNodeForLocalEducationAgency != null) return _rootMetricNodeForLocalEducationAgency; const int rootNodeIdForLocalEducationAgency = (int)MetricHierarchyRoot.LocalEducationAgency; const int metricVariantIdForLocalEducationAgencyOverview = (int)LocalEducationAgencyMetricEnum.Overview; var nodeForLocalEducationAgencyOverview = MetricMetadata.AllNodesByMetricVariantId.ValuesByKey(metricVariantIdForLocalEducationAgencyOverview).SingleOrDefault(x => x.RootNodeId == rootNodeIdForLocalEducationAgency); _rootMetricNodeForLocalEducationAgency = nodeForLocalEducationAgencyOverview; return _rootMetricNodeForLocalEducationAgency; }
/// <summary> /// Throws an exception describing the unhandled request for a metric route. /// </summary> /// <param name="metricInstanceSetRequest">The metric instance set request providing the domain-specific context for the metric.</param> /// <param name="metadataNode">The metadata for the metric.</param> /// <returns>The URL for the application-specific location for the metric.</returns> public IEnumerable<Link> GetRoute(MetricInstanceSetRequestBase metricInstanceSetRequest, MetricMetadataNode metadataNode) { throw new NotSupportedException( string.Format("Metric route generation for request type '{0}' was unhandled.", metricInstanceSetRequest.GetType().Name)); }
private static Goal GetGoalFromMetricState(MetricMetadataNode metricNode, MetricGoal goalData, MetricInstance metricInstance) { var model = new Goal { Interpretation = (TrendInterpretation)metricNode.TrendInterpretation.GetValueOrDefault() }; //We can have more than one good state so lets see what we've got. var metricStateGoodRules = metricNode.States.Where(x => x.StateType == MetricStateType.Good).ToList(); //We only one rule to proceed. Models.MetricState singleRuleThatApplies = null; if (metricStateGoodRules.Count() == 1) singleRuleThatApplies = metricStateGoodRules.Single(); if (metricStateGoodRules.Count() > 1) { //To get a metric state from a case like this we need an instance if no instance then we cant proceed. if (metricInstance == null) { model.Value = null; return model; } singleRuleThatApplies = GetStateThatAppliesFromMultipleStates(metricNode, metricInstance, metricStateGoodRules); } //If we didn't find any then lets check if our metric is enabled. if (!metricStateGoodRules.Any() || singleRuleThatApplies == null) { //If there's no state, see if the metric is enabled, if it's not enabled, ignore the problem. if (!metricNode.Enabled) { //If we are here it means that we have a disabled metric and we should not blow up. return new Goal { Interpretation = TrendInterpretation.None, Value = null }; } //If the metric is configured not to use metric states, then it's fine for there not to be a goal. if (metricNode.States.Any(x => x.StateType == MetricStateType.Na || x.StateType == MetricStateType.None)) { return new Goal { Interpretation = TrendInterpretation.None, Value = null }; } //Otherwise, this is a problem with the metadata. throw new InvalidOperationException("Metric Id:" + metricNode.MetricId + " needs a Metric State value in its table to be able to calculate a goal."); } if (singleRuleThatApplies.MinValue != null && singleRuleThatApplies.MinValue.Value != 0) { model.Value = singleRuleThatApplies.MinValue.Value; return model; } if (singleRuleThatApplies.MaxValue != null) { model.Value = singleRuleThatApplies.MaxValue.Value; return model; } //This metric has a state rule but we cant calculate the value of the goal so its null. //This metric does not have goal. if (singleRuleThatApplies.MinValue == null && singleRuleThatApplies.MaxValue == null) { model.Value = null; return model; } return null; }
private static Goal GetGoalFromGoalData(MetricMetadataNode metricNode, MetricGoal goalData) { var model = new Goal { Interpretation = (TrendInterpretation)metricNode.TrendInterpretation.GetValueOrDefault() }; //Lets see if we have a goal. if (goalData != null) { model.Value = goalData.Value; return model; } return null; }
private State CalculateState(MetricMetadataNode node, string value, string valueType) { if (string.IsNullOrEmpty(value)) return new State(MetricStateType.None, String.Empty); if (string.IsNullOrEmpty(valueType)) throw new ArgumentNullException("valueType", string.Format("Can't calculate State for metric Id({0}) because value and value type are null", node.MetricId)); //Activate the value. var t = GetType(valueType); object valueInstance = Convert.ChangeType(value, t); var compValue = (IComparable)valueInstance; foreach (var stateRule in node.States) { bool? metMinValueConditionResult = null; bool? metMaxValueConditionResult = null; //Test to see what condition applies. Func<bool> metMinValueCondition = () => { if (metMinValueConditionResult != null) return metMinValueConditionResult.Value; metMinValueConditionResult = IsMinimumConditionMet(stateRule, compValue, t); return metMinValueConditionResult.Value; }; Func<bool> metMaxValueCondition = () => { if (metMaxValueConditionResult != null) return metMaxValueConditionResult.Value; metMaxValueConditionResult = IsMaximumConditionMet(stateRule, compValue, t); return metMaxValueConditionResult.Value; }; if (stateRule.MaxValue == null) if (metMinValueCondition()) metMaxValueConditionResult = true; if (stateRule.MinValue == null && metMaxValueCondition()) metMinValueConditionResult = true; if (metMinValueCondition() && metMaxValueCondition()) return new State(stateRule.StateType, stateRule.StateText); } //After going through the foreach if there is nothing then there is no threshold rule defined. //throw new NullReferenceException("There is no threshold rule that applies for this metricId=" + studentMetric.MetricId); return new State(MetricStateType.None, String.Empty); }
protected override void EstablishContext() { //Prepare supplied data collections suppliedDomainEntityType = "School"; suppliedMetricMetadataNode = GetSuppliedMetricMetadataNode(); suppliedGranularMetricValue = .55m; suppliedGoalInterpretation = TrendInterpretation.Standard; suppliedGoalValue = .50m; suppliedGranularMetric = GetSuppliedGranularMetric(); //This is for the original values in the state object for the granular metric. originalStateDisplayStateText = "This should be overriden."; originalStateStateText = "Should maintain value."; originalStateStateType = MetricStateType.None; }
private static Models.MetricState GetStateThatAppliesFromMultipleStates(MetricMetadataNode metricNode, MetricInstance metricInstance, IEnumerable<Models.MetricState> metricStateGoodRules) { //Logic to pick the right one when we have many. if (metricInstance == null) throw new ArgumentNullException("metricInstance", string.Format("Can not calculate a Goal for metric Id:({0}) A Metric Instance is needed in the DB.", metricNode.MetricId)); //We need to have the value to proceed. if (string.IsNullOrEmpty(metricInstance.Value)) throw new ArgumentOutOfRangeException("metricInstance", "The value has to be supplied in order to be able to calculate the state. metric Id:(" + metricNode.MetricId + ")"); if (string.IsNullOrEmpty(metricInstance.ValueTypeName)) // In case of bad or missing metadata throw new ArgumentOutOfRangeException("metricInstance", "The value type has to be supplied in order to be able to calculate the state. metric Id:(" + metricNode.MetricId + ")"); if (!metricInstance.ValueTypeName.StartsWith("System.")) return null; //new Goal { Interpretation = TrendInterpretation.None, Value = null}; //Activate the value. Type t = Type.GetType(metricInstance.ValueTypeName); object value = Convert.ChangeType(metricInstance.Value, t); var compValue = (IComparable)value; foreach (var stateRule in metricStateGoodRules) { //Test to see what condition applies! bool metMinValueCondition = IsMinimumConditionMet(stateRule, compValue, t); bool metMaxValueCondition = IsMaximumConditionMet(stateRule, compValue, t); if (stateRule.MaxValue == null) if (metMinValueCondition) metMaxValueCondition = true; if (stateRule.MinValue == null && metMaxValueCondition) metMinValueCondition = true; if (metMinValueCondition && metMaxValueCondition) return stateRule; } return null; }
protected virtual void ProcessForChildren(MetricInstanceSetRequestBase metricInstanceSetRequest, MetricMetadataNode metricMetadataNode, MetricDataContainer metricDataContainer, ContainerMetric parentMetric, Dictionary<string, object> initializationActivityData) { // Initialize the list if it's not already initialized if (parentMetric.Children == null) parentMetric.Children = new List<MetricBase>(); // Iterate through the children in the metadata foreach (var node in metricMetadataNode.Children) { // Call recursively to create the tree var newChildMetric = CreateMetric(metricInstanceSetRequest, node, metricDataContainer, parentMetric, initializationActivityData); parentMetric.Children.Add(newChildMetric); } }
private void EnsureMetricNodeIdInitialized(MetricMetadataNode metadataNode) { if (metadataNode.MetricNodeId == 0) metadataNode.MetricNodeId = int.MinValue + offset++; }
protected override void ExecuteTest() { var service = new MetricNodeResolver(dashboardContextProvider, metricMetadataTreeService, rootMetricNodeResolver); actualModel = service.ResolveFromMetricVariantId(suppliedLocalEducationAgencyMetricVariantId); }
private void SetParent(MetricMetadataNode parent) { foreach (var child in parent.Children) { SetParent(child); child.Parent = parent; } }
private MetricMetadataNode GetSchoolRootOverviewNode() { var tree = new TestMetricMetadataTree(); var root = new MetricMetadataNode(tree) { MetricId = 0, MetricVariantId = 1000, MetricVariantType = MetricVariantType.CurrentYear, Name = "Root", Children = new List<MetricMetadataNode> { new MetricMetadataNode(tree) { MetricId = 1, MetricVariantId = 1001, MetricVariantType = MetricVariantType.CurrentYear, Name = "LEA Overview", ChildDomainEntityMetricId = 2, Children = new List<MetricMetadataNode> { new MetricMetadataNode(tree) { MetricId=11, MetricVariantId = 1011, MetricVariantType = MetricVariantType.CurrentYear, ChildDomainEntityMetricId = 21, Name = "LEA's Attendance and Discipline", Children = new List<MetricMetadataNode> { new MetricMetadataNode(tree) { MetricId=111, MetricVariantId = 1111, MetricVariantType = MetricVariantType.CurrentYear, ChildDomainEntityMetricId = 211, Name = "Attendance" }, new MetricMetadataNode(tree) { MetricId=111, MetricVariantId = 2111, MetricVariantType = MetricVariantType.PriorYear, ChildDomainEntityMetricId = 211, Name = "Attendance" }, new MetricMetadataNode(tree) { MetricId=112, MetricVariantId = 1112, MetricVariantType = MetricVariantType.CurrentYear, Name = "Discipline" } } } } } } }; tree.Children = new List<MetricMetadataNode> { root }; return root.Children.ElementAt(0); }
public override bool CanSupplyMetricData(MetricMetadataNode metricMetadataNode) { return metricMetadataNode.MetricVariantType == MetricVariantType.PriorYear; }
private MetricMetadataNode GetSchoolRootOverviewNode() { var tree = new TestMetricMetadataTree(); var root = new MetricMetadataNode(tree) { MetricId = 0, MetricVariantId = 1000, MetricVariantType = MetricVariantType.CurrentYear, Name = "Root", Children = new List<MetricMetadataNode> { new MetricMetadataNode(tree) { MetricId = 2, MetricVariantId = 1002, MetricVariantType = MetricVariantType.CurrentYear, Name = "School Overview", MetricNodeId = 7, Parent = null, Children = new List<MetricMetadataNode> { new MetricMetadataNode(tree) { MetricId=21, MetricVariantId = 1021, MetricVariantType = MetricVariantType.CurrentYear, MetricNodeId = 71, Name = "School's Attendance and Discipline", Children = new List<MetricMetadataNode> { new MetricMetadataNode(tree) { MetricId=211, MetricVariantId = 1211, MetricVariantType = MetricVariantType.CurrentYear, MetricNodeId = 711, Name = "Attendance" }, new MetricMetadataNode(tree) { MetricId=212, MetricVariantId = 1212, MetricVariantType = MetricVariantType.CurrentYear, Name = "Discipline" } } }, new MetricMetadataNode(tree) { MetricId=22, MetricVariantId = 1022, MetricVariantType = MetricVariantType.CurrentYear, MetricNodeId = 72, Name = "School's Other Metric" }, } } } }; tree.Children = new List<MetricMetadataNode> { root }; return root.Children.ElementAt(0); }