Esempio n. 1
0
        static void HorizontalPositionsByDensity()
        {
            foreach (var node in Nodes)
            {
                List <Node> level = new List <Node>();
                level.Add(node);

                int depth = 1;
                while (level.Count > 0 && level.Any(n => n.InNodes.Count > 0))
                {
                    // has any parent, increment level.
                    depth++;

                    // set level to next batch of distinct Parents, where Parents may not be itself.
                    level = level.SelectMany(n => n.InNodes).Distinct().Where(n => n != node).ToList();

                    // stop infinite recursion with loops of size greater than 2
                    if (depth > 100)
                    {
                        ResearchLog.Error("{0} has more than 100 levels of prerequisites. Is the Research Tree defined as a loop?", false, node);
                        break;
                    }
                }
                node.SetDepth(depth);
            }
        }
Esempio n. 2
0
        public static ResearchNode ResearchNode(this ResearchProjectDef research)
        {
            var node = Tree.Nodes.OfType <ResearchNode>().FirstOrDefault(n => n.Research == research);

            if (node == null)
            {
                ResearchLog.Error("Node for {0} not found. Was it intentionally hidden or locked?", true, research.LabelCap);
            }
            return(node);
        }
Esempio n. 3
0
        private static void CheckPrerequisites()
        {
            // check prerequisites

            var nodes = new Queue <ResearchNode>(Nodes.OfType <ResearchNode>());

            // remove redundant prerequisites
            while (nodes.Count > 0)
            {
                var node = nodes.Dequeue();
                if (node.Research.prerequisites.NullOrEmpty())
                {
                    continue;
                }

                var ancestors = node.Research.prerequisites?.SelectMany(r => r.Ancestors()).ToList();
                var redundant = ancestors.Intersect(node.Research.prerequisites);
                if (redundant.Any())
                {
                    ResearchLog.Warning("\tredundant prerequisites for {0}: {1}", node.Research.LabelCap,
                                        string.Join(", ", redundant.Select(r => r.LabelCap).ToArray()) + ", fixing, please save");
                    foreach (var redundantPrerequisite in redundant)
                    {
                        ProfileManager.AddCommand("".Find(node.Research).Get(new { node.Research.prerequisites }).Remove().Find(redundantPrerequisite));
                        node.Research.prerequisites.Remove(redundantPrerequisite);
                    }
                }
            }

            // fix bad techlevels
            nodes = new Queue <ResearchNode>(Nodes.OfType <ResearchNode>());
            while (nodes.Count > 0)
            {
                var node = nodes.Dequeue();
                if (!node.Research.prerequisites.NullOrEmpty())
                {
                    // warn and fix badly configured techlevels
                    if (node.Research.prerequisites.Any(r => r.techLevel > node.Research.techLevel))
                    {
                        ResearchLog.Warning("\t{0} has a lower techlevel than (one of) it's prerequisites, fixing, please save",
                                            node.Research.defName);
                        TechLevel maxTech = node.Research.prerequisites.Max(r => r.techLevel);
                        ProfileManager.AddCommand("".Find(node.Research).Set(new { node.Research.techLevel }).Find(maxTech));
                        node.Research.techLevel = maxTech;

                        // re-enqeue all descendants
                        foreach (var descendant in node.Descendants.OfType <ResearchNode>())
                        {
                            nodes.Enqueue(descendant);
                        }
                    }
                }
            }
        }
Esempio n. 4
0
        private static void EdgeLengthSweep_Local_Layer(int l, bool @in)
        {
            // The objective here is to;
            // (1) move and/or swap nodes to reduce local edge length
            // (2) not increase the number of crossings
            var x         = @in ? l - 1 : l + 1;
            var crossings = Crossings(x);

            var layer = Layer(l, true);

            foreach (var node in layer)
            {
                foreach (var edge in @in ? node.InEdges : node.OutEdges)
                {
                    // current length
                    var length    = edge.Length;
                    var neighbour = @in ? edge.In : edge.Out;
                    if (neighbour.X != x)
                    {
                        ResearchLog.Warning("{0} is not at layer {1}", neighbour, x);
                    }

                    // we only need to loop over positions that might be better for this node.
                    // min = minimum of current position, node position
                    var min = Mathf.Min(node.Y, neighbour.Y);
                    var max = Mathf.Max(node.Y, neighbour.Y);

                    // already at only possible position
                    if (min == max && min == node.Y)
                    {
                        continue;
                    }

                    for (var y = min; y <= max; y++)
                    {
                        if (y == neighbour.Y)
                        {
                            continue;
                        }

                        // is this spot occupied?
                        var otherNode = NodeAt(x, y);

                        // occupied, try swapping
                        if (otherNode != null)
                        {
                            Swap(neighbour, otherNode);
                            var candidateCrossings = Crossings(x);
                            if (candidateCrossings > crossings)
                            {
                                // abort
                                Swap(otherNode, neighbour);
                            }
                            else
                            {
                                var candidateLength = edge.Length;
                                if (length - candidateLength < Epsilon)
                                {
                                    // abort
                                    Swap(otherNode, neighbour);
                                }
                                else
                                {
                                    length = candidateLength;
                                }
                            }
                        }

                        // not occupied, try moving
                        else
                        {
                            var oldY = neighbour.Y;
                            neighbour.Y = y;
                            var candidateCrossings = Crossings(x);
                            if (candidateCrossings > crossings)
                            {
                                // abort
                                neighbour.Y = oldY;
                            }
                            else
                            {
                                var candidateLength = edge.Length;
                                if (length - candidateLength < Epsilon)
                                {
                                    // abort
                                    neighbour.Y = oldY;
                                }
                                else
                                {
                                    length = candidateLength;
                                }
                            }
                        }
                    }
                }
            }
        }