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(); }
/// <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); }
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); }