예제 #1
0
 public RefineryDriver(StaticState configuredStaticState)
 {
     state            = new SystemState(configuredStaticState);
     blockCollector   = new BlockCollector(configuredStaticState.InventoryBlockNames);
     inventoryScanner = new InventoryScanner(configuredStaticState.IngotTypes.AllIngotItemTypes, configuredStaticState.OreTypes.All);
     refineryWorklist = new RefineryWorklist(configuredStaticState.OreTypes, configuredStaticState.IngotTypes, configuredStaticState.RefineryFactory, configuredStaticState.Blueprints);
     ingotWorklist    = new IngotWorklist(state.Ingots);
     displayRenderer  = new DisplayRenderer();
 }
예제 #2
0
        /// <summary>
        /// Provide the specified refinery with enough work to keep it busy until the next iteration.
        /// </summary>
        /// <remarks>
        /// Ore already being processed is not considered when estimating how many ingots will be produced.
        /// This is because we already have at least one interval of lag in adjusting to new requests anyway
        /// and the amount of ore in flight should be insignificant in comparison (approx. one
        /// 'IntervalOverlapSeconds'); it's not worth the hassle to calculate it.
        /// </remarks>
        private bool FillCurrentRefinery(IngotWorklist ingotWorklist, IRefineryIterator worklist)
        {
            var assignedWork = false;

            // How much work does this refinery need to keep it busy until the next iteration, with a safety margin?
            Debug.Assert(worklist.PreferredWorkSeconds > 0, "PreferredWorkSeconds <= 0");

            // Get candidate blueprints in priority order.
            var candidates = worklist.GetCandidateBlueprints().OrderByDescending(ingotWorklist.ScoreBlueprint).ToArray();

            for (var i = 0; i < candidates.Length; i++)
            {
                var blueprint = candidates[i];

                var workProvidedSeconds = TryFillRefinery(worklist.Current, blueprint, worklist.PreferredWorkSeconds);
                if (workProvidedSeconds <= 0)
                {
                    Debug.Write(Debug.Level.All, new Message("Unable to allocate any {0}, moving to next candidate.", blueprint.Input.ItemType.SubtypeId));
                    continue;
                }
                assignedWork = true;
                var isRefinerySatisfied = worklist.AssignedWork(ref workProvidedSeconds);
                if (workProvidedSeconds > 0)
                {
                    Debug.Write(Debug.Level.Debug, new Message("Provided {0} seconds of work using {1}.", workProvidedSeconds, blueprint.Name));
                    // Some of the new work will be processed before next iteration. Update our estimates.
                    ingotWorklist.UpdateStockpileEstimates(worklist.Current, blueprint, workProvidedSeconds);
                }
                // If the refinery's work target is satisfied, it should not run dry before we run again.
                if (isRefinerySatisfied)
                {
                    break;
                }
            }

            // No more ore available for this refinery.
            worklist.Next();
            return(assignedWork);
        }
예제 #3
0
        public bool AllocateSingle(IngotWorklist ingotWorklist)
        {
            IngotStockpile preferred;

            while (ingotWorklist.TryGetPreferred(out preferred))
            {
                var type = preferred.Ingot.ItemType;
                IRefineryIterator refineries;
                if (refineryWorklist.TrySelectIngot(type, out refineries))
                {
                    do
                    {
                        if (FillCurrentRefinery(ingotWorklist, refineries))
                        {
                            return(true);               // Yield as soon as we've allocated work.
                        }
                    } while (refineries.CanAllocate()); // Otherwise keep looking for a refinery which can do something.
                }
                ingotWorklist.Skip();
            }
            return(false);
        }