示例#1
0
        public static ProgressHierarchy GetHierarchy(List <ProgressRecordEx> records)
        {
            var parent = new ProgressRecord(0, "Activity", "Description");

            parent.GetType().GetField("id", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(parent, -1);
            parent.ParentActivityId = -2;

            var hierarchy = new ProgressHierarchy(parent);

            GetChildren(hierarchy, records);

            return(hierarchy);
        }
示例#2
0
        static void AddLostChildren(ProgressHierarchy hierarchy, List <ProgressRecordEx> list, int i)
        {
            //We will build a collection of progress records we need to append to the root, then apply them

            var theChain = new List <ProgressRecord> {
                list[i]
            };
            var startIndex = i;

            var chainLength = theChain.Count;

            //Loop backwards through the list of progress records, trying to find the last parent we would've belonged to,
            //then their last parent, and so on until we reach the record with no parent
            while (theChain.Last().ParentActivityId != -1)
            {
                for (int j = startIndex; j >= 0; j--)
                {
                    if (list[j].ActivityId == theChain.Last().ParentActivityId)
                    {
                        theChain.Add(list[j]);
                        startIndex = j - 1;
                        break;
                    }
                }

                var newLength = theChain.Count;

                if (newLength != chainLength)
                {
                    chainLength = newLength;
                }
                else
                {
                    throw new Exception($"Cannot find parent with activity ID {theChain.Last().ParentActivityId}");
                }
            }

            //Now apply the records against the root record, constructing a parent > child relationship between them
            theChain.Reverse <ProgressRecord>().Aggregate(hierarchy, (h, r) =>
            {
                var newChild = new ProgressHierarchy(r);
                h.Children.Add(newChild);
                return(newChild);
            });
        }
示例#3
0
        static int GetChildren(ProgressHierarchy hierarchy, List <ProgressRecordEx> list, int i = 0)
        {
            /*
             * Given a list of ParentID/ID pairs in the form
             * -1 1
             * -1 1
             *  1 2
             *  1 2
             *  2 3
             *
             * We wish to create an association between each level and the children found under them, i.e.
             * -1 1
             * -1 1
             *    1 2
             *    1 2
             *      2 3
             *
             * This information will be later used to create a unique tree for each branch of the relationship, i.e.
             *
             * -1 1    (Grandfather1 [Standalone])
             *
             * -1 1    (Grandfather2)
             *
             * -1 1    (Grandfather2 -> Father1)
             *    1 2
             *
             * -1 1    (Grandfather2 -> Father2 -> Child)
             *    1 2
             *      2 3
             */

            //Our parent will need to know how many records we've processed and needs to skip over
            var returnIndex = i;
            var initial     = i;

            ProgressGrouperLogger.LogStart(hierarchy.Record);

            for (; i < list.Count; i++)
            {
                ProgressGrouperLogger.Log($"{i}: Begin loop for item {list[i].Activity} ({list[i].CurrentOperation},{list[i].StatusDescription}) (ID: {list[i].ActivityId}, PID: {list[i].ParentActivityId})");
                ProgressGrouperLogger.Log($"{i}: Parent is {hierarchy.Record.Activity} ({hierarchy.Record.CurrentOperation},{hierarchy.Record.StatusDescription}) (ID: {hierarchy.Record.ActivityId}, {hierarchy.Record.ParentActivityId})");
                //We're on the same level or the next item is below us; no more children to be found for me
                if (hierarchy.Record.ParentActivityId >= list[i].ParentActivityId)
                {
                    ProgressGrouperLogger.Log($"{i}: item {list[i].Activity} ({list[i].CurrentOperation},{list[i].StatusDescription}) is on the same level or is below {hierarchy.Record.Activity}. Returning {returnIndex}");
                    ProgressGrouperLogger.LogEnd(hierarchy.Record);

                    //If the current record isn't the child of the current parent, it could be the child of our grandparent (effectively, our uncle).
                    //So tell our parent we didn't process any records, it's back where it started
                    if (i == initial)
                    {
                        return(initial - 1);
                    }

                    //We processed 1 or more records, and this is the index we got up to.
                    return(returnIndex);
                }

                //If this item is the child of the record this method is analyzing
                if (hierarchy.Record.ActivityId == list[i].ParentActivityId)
                {
                    ProgressGrouperLogger.Log($"{i}: item {list[i].Activity} ({list[i].CurrentOperation},{list[i].StatusDescription}) is the child of {hierarchy.Record.Activity}");

                    //Mark the record as a child
                    var nextChild = new ProgressHierarchy(list[i]);
                    hierarchy.Children.Add(nextChild);

                    //Get the children of THAT record
                    var result = GetChildren(nextChild, list, i + 1);

                    //If we skipped over more than 1 record while evaluating our children, we'll need to update our position
                    if (result > i)
                    {
                        i = result;
                    }

                    //And tell our parent about it too
                    returnIndex = i;
                }
                else
                {
                    ProgressGrouperLogger.Log($"{i}: Record's activity ID {list[i].ParentActivityId} does not match current parent activity ID {hierarchy.Record.ActivityId}. Parent record has already been completed. Creating parent from record history");

                    if (hierarchy.Record.ParentActivityId != -2)
                    {
                        //We need to keep going back to the root loop. Each time we go back, the current loop will +1 us as it begins its
                        //next loop after its own call to GetChildren returns, so we just need to undo that.
                        return(returnIndex - 1);
                    }

                    AddLostChildren(hierarchy, list, i);
                }
            }

            ProgressGrouperLogger.LogEnd(hierarchy.Record);

            return(returnIndex);
        }
示例#4
0
        public static IEnumerable <IEnumerable <ProgressRecord> > GetProgressSnapshots(ProgressHierarchy hierarchy, List <ProgressRecord> soFar)
        {
            if (hierarchy.Children.Any())
            {
                foreach (var item in hierarchy.Children)
                {
                    //Add a child to its parent
                    soFar.Add(item.Record);

                    //Retrieve the rest of the hierarchy for this child
                    var result = GetProgressSnapshots(item, soFar);

                    //Return the entire evaluated hierarchy. result will only contain a single IEnumerable<ProgressRecord>,
                    //which we'll transform into a List<List<ProgressRecord>> when we're done.
                    foreach (var r in result)
                    {
                        yield return(r);
                    }

                    //Remove the child from its parent, so we can replace it with the next child if we loop again
                    soFar.Remove(item.Record);
                }
            }
            else
            {
                //It's the end of the line. Return any ProgressRecords we collected up to this point as an
                //IEnumerable(of size 1)<IEnumerable<ProgressRecord>>
                if (soFar.Any())
                {
                    yield return(soFar.Select(f => f));
                }
            }
        }