Beispiel #1
0
 protected virtual void OnFlowChanged(MeasurementChangedEventArgs e)
 {
     FlowChanged?.Invoke(this, e);
 }
        private void FixProductionFlow()
        {
            var rawData = Configuration.Instance.RawData;

            var baseItems = new Dictionary <BaseProducibleObject, WorkspaceProducibleItem>();

            foreach (var src in ExistingSources)
            {
                baseItems.GetOrCreate(src.MyItem, () => new WorkspaceProducibleItem {
                    Item = src.MyItem
                }).Balance = float.PositiveInfinity;
            }
            foreach (var dst in WantedResults)
            {
                baseItems.GetOrCreate(dst.MyItem, () => new WorkspaceProducibleItem {
                    Item = dst.MyItem
                }).Balance -= dst.Amount;
            }

            Dictionary <BaseProducibleObject, WorkspaceProducibleItem> roundResults;
            int nrounds = 100;

            do
            {
                roundResults = new Dictionary <BaseProducibleObject, WorkspaceProducibleItem>(baseItems);

                //Step 1: balance all existing nodes
                var toRemove = new List <BaseFlowNode>();
                foreach (var node in ProductionNodes)
                {
                    var needed = (int)Math.Ceiling(node.Results.Max(x => - roundResults.GetOrDefault(x.RealItem, () => new WorkspaceProducibleItem()).Balance / x.BaseRate));
                    if (node is Recipe r)
                    {
                        r.Producers = needed;
                    }
                    if (needed == 0)
                    {
                        toRemove.Add(node);
                        continue;
                    }

                    foreach (var egress in node.Results)
                    {
                        var item = roundResults.GetOrCreate(egress.RealItem, () => new WorkspaceProducibleItem {
                            Item = egress.RealItem
                        });
                        item.Producers.Add(node);
                        item.Balance += egress.Rate;
                    }

                    foreach (var ingress in node.Sources)
                    {
                        var item = roundResults.GetOrCreate(ingress.RealItem, () => new WorkspaceProducibleItem {
                            Item = ingress.RealItem
                        });
                        item.Consumers.Add(node);
                        item.Balance -= ingress.Rate;
                    }
                }

                foreach (var n in toRemove)
                {
                    ProductionNodes.Remove(n);
                }

                //Step 2: add more nodes
                foreach (var neededItem in roundResults.Where(x => x.Value.Balance < 0))
                {
                    var possibleRecipies = rawData.Recipes.Where(x => x.Value.HasResult(neededItem.Key)).ToArray();
                    _selectedRecipies.TryGetValue(neededItem.Key, out var selectedRecipe);
                    if (!possibleRecipies.Any())
                    {
                        var satisfier = new ManualItemSource(neededItem.Key);
                        ProductionNodes.Add(satisfier);
                    }
                    else if (possibleRecipies.Length == 1 || selectedRecipe != null)
                    {
                        var recipe    = selectedRecipe ?? possibleRecipies.First().Value;
                        var satisfier = new Recipe(recipe);
                        ProductionNodes.Add(satisfier);
                    }
                    else
                    {
                        var selector = new SelectRecipe(possibleRecipies.Select(x => x.Value), neededItem.Key);
                        ProductionNodes.Add(selector);
                    }
                }
            } while (roundResults.Any(x => x.Value.Balance < 0) && nrounds-- > 0);


            Application.Current.Dispatcher.Invoke(() =>
            {
                Items.Clear();
                foreach (var item in roundResults)
                {
                    foreach (var ingress in item.Value.Consumers)
                    {
                        foreach (var egress in item.Value.Producers)
                        {
                            var edge = new ProducibleItem(egress.Results.First(x => x.RealItem.Equals(item.Key)), ingress.Sources.First(x => x.RealItem.Equals(item.Key)), item.Key);
                            Items.Add(edge);
                        }
                    }
                }
            });

            /*var rawData = Configuration.Instance.RawData;
             * var unsatisfied = new HashSet<BaseProducibleObject>(
             *  _satisfierNodes.SelectMany(x => x.Value.Sources.Select(ingress => ingress.RealItem))
             *      .Concat(WantedResults.Select(w => w.MyItem))
             *      .Except(_satisfierNodes.Keys)
             *      .Except(ExistingSources.Select(x => x.MyItem))
             * );
             * while (unsatisfied.Any())
             * {
             *  var result = unsatisfied.First();
             *  unsatisfied.Remove(result);
             *  var possibleRecipies = rawData.Recipes.Where(x => x.Value.HasResult(result)).ToArray();
             *  _selectedRecipies.TryGetValue(result, out var selectedRecipe);
             *  if (!possibleRecipies.Any())
             *  {
             *      var satisfier = new ManualItemSource(result);
             *      ProductionNodes.Add(satisfier);
             *      //Bind(satisfier);
             *      _satisfierNodes[result] = satisfier;
             *  }
             *  else if (possibleRecipies.Length == 1 || selectedRecipe != null)
             *  {
             *      var recipe = selectedRecipe ?? possibleRecipies.First().Value;
             *      var satisfier = new Recipe(recipe);
             *      ProductionNodes.Add(satisfier);
             *      foreach (var r in recipe.CurrentMode.Results)
             *      {
             *          var res = rawData.Get(r.Value.Type, r.Value.Name);
             *          _satisfierNodes[res] = satisfier;
             *          unsatisfied.Remove(res);
             *      }
             *
             *      foreach (var r in possibleRecipies.First().Value.CurrentMode.Sources)
             *      {
             *          var res = rawData.Get(r.Value.Type, r.Value.Name);
             *          if (!_satisfierNodes.ContainsKey(res))
             *          {
             *              unsatisfied.Add(res);
             *          }
             *      }
             *  }
             *  else
             *  {
             *      var selector = new SelectRecipe(possibleRecipies.Select(x => x.Value), result);
             *      ProductionNodes.Add(selector);
             *      //Bind(selector);
             *      _satisfierNodes[result] = selector;
             *  }
             * }
             *
             * Items.Clear();
             * foreach (var source in _satisfierNodes)
             * {
             *  var egress = source.Value.Results.First(x => x.RealItem.Equals(source.Key));
             *  foreach (var dest in _satisfierNodes.Values.SelectMany(x => x.Sources?.Where(ingress => ingress.RealItem.Equals(source.Key)) ?? new RecipeIO[0]))
             *  {
             *      var edge = new ProducibleItem(egress, dest, source.Key);
             *      Items.Add(edge);
             *  }
             * }*/

            FlowChanged?.Invoke(this, EventArgs.Empty);
        }