예제 #1
0
		public bool CanUltimatelyTakeFrom(ProductionNode node)
		{
			Queue<ProductionNode> Q = new Queue<ProductionNode>();
			HashSet<ProductionNode> V = new HashSet<ProductionNode>();

			V.Add(this);
			Q.Enqueue(this);

			while (Q.Any())
			{
				ProductionNode t = Q.Dequeue();
				if (t == node)
				{
					return true;
				}
				foreach (NodeLink e in t.InputLinks)
				{
					ProductionNode u = e.Supplier;
					if (!V.Contains(u))
					{
						V.Add(u);
						Q.Enqueue(u);
					}
				}
			}
			return false;
		}
예제 #2
0
		public static NodeLink Create(ProductionNode supplier, ProductionNode consumer, Item item, float maxAmount = float.PositiveInfinity)
		{
			NodeLink link = new NodeLink(supplier, consumer, item, maxAmount);
			supplier.OutputLinks.Add(link);
			consumer.InputLinks.Add(link);
			supplier.Graph.InvalidateCaches();
			return link;
		}
예제 #3
0
 //Returns true if a new link was created
 public void CreateAllLinksForNode(ProductionNode node)
 {
     foreach (Item item in node.Inputs)
     {
         foreach (ProductionNode existingNode in Nodes.Where(n => n.Outputs.Contains(item)))
         {
             if (existingNode != node)
             {
                 NodeLink.Create(existingNode, node, item);
             }
         }
     }
 }
예제 #4
0
        public static NodeLink Create(ProductionNode supplier, ProductionNode consumer, Item item, float maxAmount = float.PositiveInfinity)
        {
            if (supplier.OutputLinks.Any(l => l.Item == item && l.Consumer == consumer))
            {
                return(null);
            }
            NodeLink link = new NodeLink(supplier, consumer, item, maxAmount);

            supplier.OutputLinks.Add(link);
            consumer.InputLinks.Add(link);
            supplier.Graph.InvalidateCaches();
            return(link);
        }
예제 #5
0
        // Ensure that the solution has a rate matching desired for this node. Typically there will
        // one of these on the ultimate output node, though multiple are supported, on any node. If
        // there is a conflict, a 'best effort' solution will be returned, where some nodes actual
        // rates will not match the desired asked for here.
        public void AddTarget(ProductionNode node, float desiredRate)
        {
            var nodeVar  = variableFor(node, RateType.ACTUAL);
            var errorVar = variableFor(node, RateType.ERROR);

            // The sum of the rate for this node, plus an error variable, must be equal to
            // desiredRate. In normal scenarios, the error variable will be zero.
            var constraint = MakeConstraint(desiredRate, desiredRate);

            constraint.SetCoefficient(nodeVar, 1);
            constraint.SetCoefficient(errorVar, 1);

            minimizeError(node, errorVar);
        }
예제 #6
0
        // Ensure that the sum on the end of all the links is in relation to the rate of the recipe.
        // The given rate is always for a single execution of the recipe, so the ratio is always (X1
        // + X2 + ... + XN)*Rate:1
        //
        // For example, if a copper wire recipe (1 plate makes 2 wires) is connected to two different
        // consumers, then the sum of the wire rate flowing over those two links must be equal to 2
        // time the rate of the recipe.
        private void addRatio(ProductionNode node, Item item, IEnumerable <NodeLink> links, double rate, EndpointType type)
        {
            // Ensure that the sum of all inputs for this type of item is in relation to the rate of the recipe
            // So for the steel input to a solar panel, the sum of every input variable to this node must equal 5 * rate.
            var constraint   = MakeConstraint(0, 0);
            var rateVariable = variableFor(node);

            constraint.SetCoefficient(rateVariable, rate);
            foreach (var link in links)
            {
                var variable = variableFor(link, type);
                constraint.SetCoefficient(variable, -1);
            }
        }
예제 #7
0
        public void LinkUpAllInputs()
        {
            HashSet <ProductionNode> nodesToVisit = new HashSet <ProductionNode>(Nodes);

            while (nodesToVisit.Any())
            {
                ProductionNode currentNode = nodesToVisit.First();
                nodesToVisit.Remove(nodesToVisit.First());

                nodesToVisit.UnionWith(CreateOrLinkAllPossibleRecipeNodes(currentNode));
                nodesToVisit.UnionWith(CreateOrLinkAllPossibleSupplyNodes(currentNode));
                CreateAllPossibleInputLinks();
            }
        }
예제 #8
0
        public void AddNode(ProductionNode node)
        {
            var x = variableFor(node);

            this.nodes.Add(node);

            // The rate of all nodes should be minimized.
            //
            // TODO: There is a tension between minimizing supply and minimizing time to produce that
            // I suspect is not explicitly handled well here. That will likely result in "unexpected"
            // results depending on which the user is wanting. Need to figure out concrete examples
            // of where this would happen. With sufficiently large error co-efficients it's probably
            // fine for most real world recipes?
            objective.SetCoefficient(x, 1.0);
        }
예제 #9
0
파일: NodeElement.cs 프로젝트: gix/foreman
        public NodeElement(ProductionNode displayedNode, ProductionGraphViewModel parent)
        {
            Parent = parent;
            HorizontalAlignment = HorizontalAlignment.Center;
            VerticalAlignment   = VerticalAlignment.Center;
            DisplayedNode       = displayedNode;
            Initialize(displayedNode);

            BackgroundColor = DisplayedNode switch {
                ConsumerNode consumer => consumer.ConsumedItem.IsMissingItem ? MissingColor : SupplyColor,
                SupplyNode supplier => supplier.SuppliedItem.IsMissingItem ? MissingColor : ConsumerColor,
                RecipeNode recipe => recipe.BaseRecipe.IsMissingRecipe ? MissingColor : RecipeColor,
                PassthroughNode passthrough => passthrough.PassedItem.IsMissingItem
                    ? MissingColor
                    : PassthroughColor,
                             _ => throw new ArgumentException("No branch for node: " + DisplayedNode)
            };
        }
예제 #10
0
		public NodeElement(ProductionNode node, ProductionGraphViewer parent) : base(parent)
		{
			Width = 100;
			Height = 90;

			DisplayedNode = node;

			if (DisplayedNode.GetType() == typeof(ConsumerNode))
			{
				backgroundColour = supplyColour;
			}
			else if (DisplayedNode.GetType() == typeof(SupplyNode))
			{
				backgroundColour = consumerColour;
			}
			else
			{
				backgroundColour = recipeColour;
			}
			backgroundBrush = new SolidBrush(backgroundColour);

			foreach (Item item in node.Inputs)
			{
				ItemTab newTab = new ItemTab(item, LinkType.Input, Parent);
				SubElements.Add(newTab);
				inputTabs.Add(newTab);
			}
			foreach (Item item in node.Outputs)
			{
				ItemTab newTab = new ItemTab(item, LinkType.Output, Parent);
				SubElements.Add(newTab);
				outputTabs.Add(newTab);
			}

			if (DisplayedNode is RecipeNode || DisplayedNode is SupplyNode)
			{
				assemblerBox = new AssemblerBox(Parent);
				SubElements.Add(assemblerBox); 
				assemblerBox.Height = assemblerBox.Width = 50;
			}

			centreFormat.Alignment = centreFormat.LineAlignment = StringAlignment.Center;
		}
예제 #11
0
        public NodeElement(ProductionNode node, ProductionGraphViewer parent) : base(parent)
        {
            Width  = 100;
            Height = 90;

            DisplayedNode = node;

            if (DisplayedNode.GetType() == typeof(ConsumerNode))
            {
                backgroundColour = supplyColour;
            }
            else if (DisplayedNode.GetType() == typeof(SupplyNode))
            {
                backgroundColour = consumerColour;
            }
            else
            {
                backgroundColour = recipeColour;
            }
            backgroundBrush = new SolidBrush(backgroundColour);

            foreach (Item item in node.Inputs)
            {
                ItemTab newTab = new ItemTab(item, LinkType.Input, Parent);
                SubElements.Add(newTab);
                inputTabs.Add(newTab);
            }
            foreach (Item item in node.Outputs)
            {
                ItemTab newTab = new ItemTab(item, LinkType.Output, Parent);
                SubElements.Add(newTab);
                outputTabs.Add(newTab);
            }

            if (DisplayedNode is RecipeNode || DisplayedNode is SupplyNode)
            {
                assemblerBox = new AssemblerBox(Parent);
                SubElements.Add(assemblerBox);
                assemblerBox.Height = assemblerBox.Width = 50;
            }

            centreFormat.Alignment = centreFormat.LineAlignment = StringAlignment.Center;
        }
예제 #12
0
        public List <ProductionNode> GetTopologicalSort()
        {
            int[,] matrix = AdjacencyMatrix;
            List <ProductionNode> L = new List <ProductionNode>();              //Final sorted list
            List <ProductionNode> S = GetInputlessNodes().ToList();

            while (S.Any())
            {
                ProductionNode node = S.First();
                S.Remove(node);
                L.Add(node);

                int n = Nodes.IndexOf(node);

                for (int m = 0; m < Nodes.Count(); m++)
                {
                    if (matrix[n, m] == 1)
                    {
                        matrix[n, m] = 0;
                        int edgeCount = 0;
                        for (int i = 0; i < matrix.GetLength(1); i++)
                        {
                            edgeCount += matrix[i, m];
                        }
                        if (edgeCount == 0)
                        {
                            S.Insert(0, Nodes[m]);
                        }
                    }
                }
            }

            for (int i = 0; i < matrix.GetLength(0); i++)
            {
                for (int j = 0; j < matrix.GetLength(1); j++)
                {
                    // Edges mean there's a cycle somewhere and the sort can't be completed
                }
            }

            return(L);
        }
예제 #13
0
        public IEnumerable <IEnumerable <ProductionNode> > GetConnectedComponents()
        {
            HashSet <ProductionNode> unvisitedNodes = new HashSet <ProductionNode>(Nodes);

            List <HashSet <ProductionNode> > connectedComponents = new List <HashSet <ProductionNode> >();

            while (unvisitedNodes.Any())
            {
                connectedComponents.Add(new HashSet <ProductionNode>());
                HashSet <ProductionNode> toVisitNext = new HashSet <ProductionNode>();
                toVisitNext.Add(unvisitedNodes.First());

                while (toVisitNext.Any())
                {
                    ProductionNode currentNode = toVisitNext.First();

                    foreach (NodeLink link in currentNode.InputLinks)
                    {
                        if (unvisitedNodes.Contains(link.Supplier))
                        {
                            toVisitNext.Add(link.Supplier);
                        }
                    }
                    foreach (NodeLink link in currentNode.OutputLinks)
                    {
                        if (unvisitedNodes.Contains(link.Consumer))
                        {
                            toVisitNext.Add(link.Consumer);
                        }
                    }

                    connectedComponents.Last().Add(currentNode);
                    toVisitNext.Remove(currentNode);
                    unvisitedNodes.Remove(currentNode);
                }
            }

            return(connectedComponents);
        }
예제 #14
0
        // Constrain input to a node for a particular item so that the node does not consume more
        // than is being produced by the supplier.
        //
        // Consuming less than is being produced is fine. This represents a backup.
        public void AddInputLink(ProductionNode node, Item item, IEnumerable <NodeLink> links, double inputRate)
        {
            Debug.Assert(links.All(x => x.Consumer == node));

            // Each item input/output to a recipe has one varible per link. These variables should be
            // related to one another using one of the other Ratio methods.
            foreach (var link in links)
            {
                var supplierVariable = variableFor(link, EndpointType.SUPPLY);
                var consumerVariable = variableFor(link, EndpointType.CONSUME);
                var errorVariable    = variableFor(link, EndpointType.ERROR);

                {
                    // The consuming end of the link must be no greater than the supplying end.
                    var constraint = MakeConstraint(0, double.PositiveInfinity);
                    constraint.SetCoefficient(supplierVariable, 1);
                    constraint.SetCoefficient(consumerVariable, -1);
                }

                // Minimize over-supply. Necessary for unbalanced diamond recipe chains (such as
                // Yuoki smelting - this doesn't occur in Vanilla) where the deficit is made up by an
                // infinite supplier, in order to not just grab everything from that supplier and let
                // produced materials backup. Also, this is needed so that resources don't "pool" in
                // pass-through nodes.
                //
                // TODO: A more correct solution for pass-through would be to forbid over-supply on them.
                {
                    var constraint = MakeConstraint(0, 0);
                    constraint.SetCoefficient(errorVariable, 1);
                    constraint.SetCoefficient(supplierVariable, -1);
                    constraint.SetCoefficient(consumerVariable, 1);

                    // The cost of over-supply needs to be greater than benefit of minimizing rate,
                    // other-wise pure consumption nodes won't consume anything.
                    objective.SetCoefficient(errorVariable, 100);
                }
            }
        }
예제 #15
0
파일: NodeLink.cs 프로젝트: gix/foreman
        public static NodeLink?Create(ProductionNode supplier, ProductionNode consumer, Item item,
                                      float maxAmount = float.PositiveInfinity)
        {
            if (!supplier.Supplies(item) || !consumer.Consumes(item))
            {
                throw new InvalidOperationException($"Cannot connect {supplier} to {consumer} using item {item}");
            }

            if (consumer.InputLinks.Any(l => l.Item == item && l.Supplier == supplier))
            {
                return(null);
            }
            if (supplier.OutputLinks.Any(l => l.Item == item && l.Consumer == consumer))
            {
                return(null);
            }

            var link = new NodeLink(supplier, consumer, item, maxAmount);

            supplier.OutputLinks.Add(link);
            consumer.InputLinks.Add(link);
            supplier.Graph.InvalidateCaches();
            return(link);
        }
예제 #16
0
        public void CreateRecipeNodeToSatisfyItemDemand(ProductionNode node, Item item, Recipe recipe)
        {
            RecipeNode newNode = RecipeNode.Create(recipe, this);

            NodeLink.Create(newNode, node, item, node.GetUnsatisfiedDemand(item));
        }
예제 #17
0
        public void CreateSupplyNodeToSatisfyItemDemand(ProductionNode node, Item item)
        {
            SupplyNode newNode = SupplyNode.Create(item, node.Graph);

            NodeLink.Create(newNode, node, item, node.GetUnsatisfiedDemand(item));
        }
예제 #18
0
		public void CreateSupplyNodeToSatisfyItemDemand(ProductionNode node, Item item)
		{
			SupplyNode newNode = SupplyNode.Create(item, node.Graph);
			NodeLink.Create(newNode, node, item, node.GetUnsatisfiedDemand(item));
		}
예제 #19
0
		public void AutoSatisfyNodeDemand(ProductionNode node, Item item)
		{
			if (node.InputLinks.Any(l => l.Item == item))	//Increase throughput of existing node link
			{
				NodeLink link = node.InputLinks.First(l => l.Item == item);
				//link.Amount += node.GetExcessDemand(item);
			}
			else if (Nodes.Any(n => n.Outputs.Contains(item)))	//Add link from existing node
			{
				ProductionNode existingNode = Nodes.Find(n => n.Outputs.Contains(item));
				NodeLink.Create(existingNode, node, item);
			}
			else if (item.Recipes.Any(r => !CyclicRecipes.Contains(r)))	//Create new recipe node and link from it
			{
				RecipeNode newNode = RecipeNode.Create(item.Recipes.First(r => !CyclicRecipes.Contains(r)), this);
				NodeLink.Create(newNode, node, item);
			}
			else	//Create new supply node and link from it
			{
				SupplyNode newNode = SupplyNode.Create(item, this);
				NodeLink.Create(newNode, node, item, node.GetUnsatisfiedDemand(item));
			}

			ReplaceCycles();
		}
예제 #20
0
 public bool TakesFrom(ProductionNode node)
 {
     return(node.OutputLinks.Any(l => l.Consumer == this));
 }
예제 #21
0
 public double ActualRate(ProductionNode node)
 {
     return(Nodes[node]);
 }
예제 #22
0
 private Variable variableFor(ProductionNode node, RateType type = RateType.ACTUAL)
 {
     return(variableFor(Tuple.Create(node, type), makeName("node", type, node.DisplayName)));
 }
예제 #23
0
            public HashSet <TarjanNode> Links = new HashSet <TarjanNode>();           //Links to other nodes

            public TarjanNode(ProductionNode sourceNode)
            {
                this.SourceNode = sourceNode;
            }
예제 #24
0
        // Constrain a ratio on the input side of a node
        public void AddInputRatio(ProductionNode node, Item item, IEnumerable <NodeLink> links, double rate)
        {
            Debug.Assert(links.All(x => x.Consumer == node));

            addRatio(node, item, links, rate, EndpointType.CONSUME);
        }
예제 #25
0
        // Constrain a ratio on the output side of a node
        public void AddOutputRatio(ProductionNode node, Item item, IEnumerable <NodeLink> links, double rate)
        {
            Debug.Assert(links.All(x => x.Supplier == node));

            addRatio(node, item, links, rate * node.ProductivityMultiplier(), EndpointType.SUPPLY);
        }
예제 #26
0
 public NodeElement GetElementForNode(ProductionNode node)
 {
     return(Elements.OfType <NodeElement>().FirstOrDefault(e => e.DisplayedNode == node));
 }
예제 #27
0
        public void LoadFromJson(JObject json)
        {
            Graph.Nodes.Clear();
            Elements.Clear();

            //Has to go first, as all other data depends on which mods are loaded
            List <String> EnabledMods = json["EnabledMods"].Select(t => (String)t).ToList();

            foreach (Mod mod in DataCache.Mods)
            {
                mod.Enabled = EnabledMods.Contains(mod.Name);
            }
            List <String> enabledMods = DataCache.Mods.Where(m => m.Enabled).Select(m => m.Name).ToList();


            using (ProgressForm form = new ProgressForm(enabledMods))
            {
                form.ShowDialog();
            }

            Graph.SelectedAmountType = (AmountType)(int)json["AmountType"];
            Graph.SelectedUnit       = (RateUnit)(int)json["Unit"];

            List <JToken> nodes = json["Nodes"].ToList <JToken>();

            foreach (var node in nodes)
            {
                ProductionNode newNode = null;

                switch ((String)node["NodeType"])
                {
                case "Consumer":
                {
                    String itemName = (String)node["ItemName"];
                    if (DataCache.Items.ContainsKey(itemName))
                    {
                        Item item = DataCache.Items[itemName];
                        newNode = ConsumerNode.Create(item, Graph);
                    }
                    else
                    {
                        Item missingItem = new Item(itemName);
                        missingItem.IsMissingItem = true;
                        newNode = ConsumerNode.Create(missingItem, Graph);
                    }
                    break;
                }

                case "Supply":
                {
                    String itemName = (String)node["ItemName"];
                    if (DataCache.Items.ContainsKey(itemName))
                    {
                        Item item = DataCache.Items[itemName];
                        newNode = SupplyNode.Create(item, Graph);
                    }
                    else
                    {
                        Item missingItem = new Item(itemName);
                        missingItem.IsMissingItem = true;
                        DataCache.Items.Add(itemName, missingItem);
                        newNode = SupplyNode.Create(missingItem, Graph);
                    }
                    break;
                }

                case "PassThrough":
                {
                    String itemName = (String)node["ItemName"];
                    if (DataCache.Items.ContainsKey(itemName))
                    {
                        Item item = DataCache.Items[itemName];
                        newNode = PassthroughNode.Create(item, Graph);
                    }
                    else
                    {
                        Item missingItem = new Item(itemName);
                        missingItem.IsMissingItem = true;
                        DataCache.Items.Add(itemName, missingItem);
                        newNode = PassthroughNode.Create(missingItem, Graph);
                    }
                    break;
                }

                case "Recipe":
                {
                    String recipeName = (String)node["RecipeName"];
                    if (DataCache.Recipes.ContainsKey(recipeName))
                    {
                        Recipe recipe = DataCache.Recipes[recipeName];
                        newNode = RecipeNode.Create(recipe, Graph);
                    }
                    else
                    {
                        Recipe missingRecipe = new Recipe(recipeName, 0f, new Dictionary <Item, float>(), new Dictionary <Item, float>());
                        missingRecipe.IsMissingRecipe = true;
                        DataCache.Recipes.Add(recipeName, missingRecipe);
                        newNode = RecipeNode.Create(missingRecipe, Graph);
                    }

                    if (node["Assembler"] != null)
                    {
                        var assemblerKey = (String)node["Assembler"];
                        if (DataCache.Assemblers.ContainsKey(assemblerKey))
                        {
                            (newNode as RecipeNode).Assembler = DataCache.Assemblers[assemblerKey];
                        }
                    }

                    (newNode as RecipeNode).NodeModules = ModuleSelector.Load(node);
                    break;
                }

                default:
                {
                    Trace.Fail("Unknown node type: " + node["NodeType"]);
                    break;
                }
                }

                if (newNode != null)
                {
                    newNode.rateType = (RateType)(int)node["RateType"];
                    if (newNode.rateType == RateType.Manual)
                    {
                        if (node["DesiredRate"] != null)
                        {
                            newNode.desiredRate = (float)node["DesiredRate"];
                        }
                        else
                        {
                            // Legacy data format stored desired rate in actual
                            newNode.desiredRate = (float)node["ActualRate"];
                        }
                    }
                    if (node["SpeedBonus"] != null)
                    {
                        newNode.SpeedBonus = Math.Round((float)node["SpeedBonus"], 4);
                    }
                    if (node["ProductivityBonus"] != null)
                    {
                        newNode.ProductivityBonus = Math.Round((float)node["ProductivityBonus"], 4);
                    }
                }
            }

            List <JToken> nodeLinks = json["NodeLinks"].ToList <JToken>();

            foreach (var nodelink in nodeLinks)
            {
                ProductionNode supplier = Graph.Nodes[(int)nodelink["Supplier"]];
                ProductionNode consumer = Graph.Nodes[(int)nodelink["Consumer"]];

                String itemName = (String)nodelink["Item"];
                if (!DataCache.Items.ContainsKey(itemName))
                {
                    Item missingItem = new Item(itemName);
                    missingItem.IsMissingItem = true;
                    DataCache.Items.Add(itemName, missingItem);
                }
                Item item = DataCache.Items[itemName];
                NodeLink.Create(supplier, consumer, item);
            }

            IEnumerable <String> EnabledAssemblers = json["EnabledAssemblers"].Select(t => (String)t);

            foreach (Assembler assembler in DataCache.Assemblers.Values)
            {
                assembler.Enabled = EnabledAssemblers.Contains(assembler.Name);
            }

            IEnumerable <String> EnabledMiners = json["EnabledMiners"].Select(t => (String)t);

            foreach (Miner miner in DataCache.Miners.Values)
            {
                miner.Enabled = EnabledMiners.Contains(miner.Name);
            }

            IEnumerable <String> EnabledModules = json["EnabledModules"].Select(t => (String)t);

            foreach (Module module in DataCache.Modules.Values)
            {
                module.Enabled = EnabledModules.Contains(module.Name);
            }

            JToken enabledRecipesToken;

            if (json.TryGetValue("EnabledRecipes", out enabledRecipesToken))
            {
                IEnumerable <String> EnabledRecipes = enabledRecipesToken.Select(t => (String)t);
                foreach (Recipe recipe in DataCache.Recipes.Values)
                {
                    recipe.Enabled = EnabledRecipes.Contains(recipe.Name);
                }
            }

            Graph.UpdateNodeValues();
            AddRemoveElements();

            List <String> ElementLocations = json["ElementLocations"].Select(l => (String)l).ToList();

            for (int i = 0; i < ElementLocations.Count; i++)
            {
                int[]        splitPoint = ElementLocations[i].Split(',').Select(s => Convert.ToInt32(s)).ToArray();
                GraphElement element    = GetElementForNode(Graph.Nodes[i]);
                element.Location = new Point(splitPoint[0], splitPoint[1]);
            }

            LimitViewToBounds();
        }
예제 #28
0
 private Variable VariableFor(ProductionNode node, RateType type = RateType.ACTUAL)
 {
     return(VariableFor(
                Tuple.Create(node, type),
                key => MakeName(GetNodePrefix(key.Item1), type, key.Item1.DisplayName)));
 }
예제 #29
0
		public void CreateRecipeNodeToSatisfyItemDemand(ProductionNode node, Item item, Recipe recipe)
		{
			RecipeNode newNode = RecipeNode.Create(recipe, this);
			NodeLink.Create(newNode, node, item, node.GetUnsatisfiedDemand(item));
		}
예제 #30
0
		public bool TakesFrom(ProductionNode node)
		{
			return node.OutputLinks.Any(l => l.Consumer == this);
		}
예제 #31
0
			public HashSet<TarjanNode> Links = new HashSet<TarjanNode>(); //Links to other nodes

			public TarjanNode(ProductionNode sourceNode)
			{
				this.SourceNode = sourceNode;
			}
예제 #32
0
		public bool GivesTo(ProductionNode node)
		{
			return node.InputLinks.Any(l => l.Supplier == this);
		}
예제 #33
0
파일: NodeLink.cs 프로젝트: gix/foreman
 public static bool CanLink(ProductionNode supplier, ProductionNode consumer, Item item)
 {
     return(supplier.Supplies(item) && consumer.Consumes(item));
 }
예제 #34
0
		public NodeElement GetElementForNode(ProductionNode node)
		{
			return Elements.OfType<NodeElement>().FirstOrDefault(e => e.DisplayedNode == node);
		}
예제 #35
0
 private NodeLink(ProductionNode supplier, ProductionNode consumer, Item item, float maxAmount = float.PositiveInfinity)
 {
     Supplier = supplier;
     Consumer = consumer;
     Item     = item;
 }
예제 #36
0
		private NodeLink(ProductionNode supplier, ProductionNode consumer, Item item, float maxAmount = float.PositiveInfinity)
		{
			Supplier = supplier;
			Consumer = consumer;
			Item = item;
		}
예제 #37
0
 public bool GivesTo(ProductionNode node)
 {
     return(node.InputLinks.Any(l => l.Supplier == this));
 }
예제 #38
0
        public NodeElement(ProductionNode node, ProductionGraphViewer parent) : base(parent)
        {
            Width  = 100;
            Height = 90;

            DisplayedNode = node;

            Color backgroundColour = missingColour;
            Color textColour       = darkTextColour;

            if (DisplayedNode is ConsumerNode)
            {
                backgroundColour = outputColour;

                if (((ConsumerNode)DisplayedNode).ConsumedItem.IsMissingItem)
                {
                    backgroundColour = missingColour;
                }
            }
            else if (DisplayedNode is SupplyNode)
            {
                backgroundColour = supplyColour;
                if (((SupplyNode)DisplayedNode).SuppliedItem.IsMissingItem)
                {
                    backgroundColour = missingColour;
                }
            }
            else if (DisplayedNode is RecipeNode)
            {
                backgroundColour = recipeColour;
                if (((RecipeNode)DisplayedNode).BaseRecipe.IsMissingRecipe)
                {
                    backgroundColour = missingColour;
                }
            }
            else if (DisplayedNode is PassthroughNode)
            {
                backgroundColour = passthroughColour;
                if (((PassthroughNode)DisplayedNode).PassedItem.IsMissingItem)
                {
                    backgroundColour = missingColour;
                }
            }
            else
            {
                Trace.Fail("No branch for node: " + DisplayedNode.ToString());
            }
            backgroundBrush = new SolidBrush(backgroundColour);
            textBrush       = new SolidBrush(textColour);

            foreach (Item item in node.Inputs)
            {
                ItemTab newTab = new ItemTab(item, LinkType.Input, Parent);
                SubElements.Add(newTab);
                inputTabs.Add(newTab);
            }
            foreach (Item item in node.Outputs)
            {
                ItemTab newTab = new ItemTab(item, LinkType.Output, Parent);
                SubElements.Add(newTab);
                outputTabs.Add(newTab);
            }

            if (DisplayedNode is RecipeNode || DisplayedNode is SupplyNode)
            {
                assemblerBox = new AssemblerBox(Parent);
                SubElements.Add(assemblerBox);
                assemblerBox.Height = assemblerBox.Width = 50;
            }

            centreFormat.Alignment = centreFormat.LineAlignment = StringAlignment.Center;
        }