private void MovesForHandoverCrane(World world, PlannedCraneMoves plan) { var sortedTargets = world.Locations.Where(x => x.Type == StackTypes.SortedBuffer && !IsMovePlanned(x, plan)).ToList(); // PRIO 1: Move blocks from shuffle buffer to sorted buffer var shuffleBufferLots = Enumerable.Range(1, world.HandoverCrane.CraneCapacity) .SelectMany(lotsize => world.Locations.Where(x => x.Type == StackTypes.ShuffleBuffer && x.Height >= lotsize && !IsMovePlanned(x, plan) && IsDecreasingSequenceOfSameMill(x, lotsize)) .Select(x => (Location: x, Lot: x.Stack.TopToBottom.Take(lotsize).ToList()))).ToList(); var move = ShuffleToSorted(sortedTargets, world.HandoverCrane, shuffleBufferLots); if (move != null) { move.ReleaseTime = world.Now; plan.Moves.Add(move); } else { // PRIO 2: Rearrange and consolidate sorted buffer var sortingLots = Enumerable.Range(1, world.HandoverCrane.CraneCapacity) .SelectMany(lotsize => world.Locations.Where(x => x.Type == StackTypes.SortedBuffer && x.Height >= lotsize && !IsMovePlanned(x, plan) && IsDecreasingSequenceOfSameMill(x, lotsize)) .Select(x => (Location: x, Lot: x.Stack.TopToBottom.Take(lotsize).ToList()))).ToList(); var sortMove = SortedToSorted(sortedTargets, world.HandoverCrane, sortingLots); if (sortMove != null) { sortMove.ReleaseTime = world.Now; plan.Moves.Add(sortMove); } } }
private void PlanMovesHeuristic() { plan = new PlannedCraneMoves(); // in the rolling mill we got to cranes we can plan independendly. if (!world.CraneMoves.Moves.Any(mov => mov.RequiredCraneId == world.HandoverCrane.Id)) { PlanHandoverCrane(); } if (!world.CraneMoves.Moves.Any(mov => mov.RequiredCraneId == world.ShuffleCrane.Id)) { PlanShuffleCrane(); } }
protected override async Task OnCraneMessageReceived(byte[] payload) { await Task.Delay(200); PlannedCraneMoves moves = null; try { moves = Serializer.Deserialize <PlannedCraneMoves>(payload.AsSpan()); } catch (Exception ex) { Logger.WriteLine(ex.ToString()); } if (moves == null) { return; } await sim.SetPlannedMovesAsync(moves); }
public virtual PlannedCraneMoves CalculateMoves(World world) { var plan = new PlannedCraneMoves() { SequenceNr = planNr++, Moves = new List <CraneMove>(world.CraneMoves.Moves) }; if (plan.Moves.All(x => x.RequiredCraneId != world.ShuffleCrane.Id)) { MovesForShuffleCrane(world, plan); } if (plan.Moves.All(x => x.RequiredCraneId != world.HandoverCrane.Id)) { MovesForHandoverCrane(world, plan); } return(plan); }
private void MovesForShuffleCrane(World world, PlannedCraneMoves plan) { var craneCap = world.ShuffleCrane.CraneCapacity; var craneCap1 = Math.Max(1, craneCap - 1); // priority locations are those that contain blocks that are soon to be processed //var prios = world.Locations.Where(x => x.Type == StackTypes.ArrivalStack || x.Type == StackTypes.ShuffleBuffer) // .Select(x => new { Location = x, Prio = x.Stack.BottomToTop.Any(y => y.Sequence <= craneCap) ? 0 : 1 }) // .ToDictionary(x => x.Location, x => x.Prio); //var minPrio = prios.Values.Min(); var shuffleTargets = world.Locations.Where(x => x.Type == StackTypes.ShuffleBuffer && !IsMovePlanned(x, plan)).ToList(); // PRIO 1: Admit blocks from the arrival stack and move them to the shuffle buffer // Note that when lots arrive pre-sorted, these could potentially be transported from arrival to sorted right away var admit = false; if (world.Locations.Any(x => x.Type == StackTypes.ArrivalStack && x.Height > 0 && !IsMovePlanned(x, plan))) { var arrivalLots = Enumerable.Range(1, craneCap) .SelectMany(lotsize => world.Locations.Where(x => x.Type == StackTypes.ArrivalStack && x.Height >= lotsize && !IsMovePlanned(x, plan) && IsDecreasingSequenceOfSameMill(x, lotsize) ).Select(x => (Location: x, Lot: x.Stack.TopToBottom.Take(lotsize).ToList()))).ToList(); var admissionMove = ArrivalToShuffle(shuffleTargets, world.ShuffleCrane, arrivalLots); if (admissionMove != null) { admissionMove.ReleaseTime = world.Now; plan.Moves.Add(admissionMove); admit = true; } } if (!admit) { var sortedTargets = world.Locations.Where(x => x.Type == StackTypes.SortedBuffer && !IsMovePlanned(x, plan)).ToList(); // PRIO 2: Move bigger lots from the shuffle area to the sorted area using the shuffle crane // The handover crane will be used to transport smaller lots var shuffleBufferLots = Enumerable .Range(craneCap1, Math.Min(2, world.ShuffleCrane.CraneCapacity)) .SelectMany(lotsize => world.Locations.Where(x => x.Type == StackTypes.ShuffleBuffer && x.Height >= lotsize && !IsMovePlanned(x, plan) && IsDecreasingSequenceOfSameMill(x, lotsize)) .Select(x => (Location: x, Lot: x.Stack.TopToBottom.Take(lotsize).ToList()))).ToList(); var sortMove = ShuffleToSorted(sortedTargets, world.ShuffleCrane, shuffleBufferLots); if (sortMove != null) { sortMove.ReleaseTime = world.Now; plan.Moves.Add(sortMove); } else { // PRIO 3: Consolidate the shuffle buffer var shuffleLots = Enumerable.Range(1, craneCap) .SelectMany(lotsize => world.Locations.Where(x => x.Type == StackTypes.ShuffleBuffer && x.Height >= lotsize && !IsMovePlanned(x, plan) && IsDecreasingSequenceOfSameMill(x, lotsize)) .Select(x => (Location: x, Lot: x.Stack.TopToBottom.Take(lotsize).ToList())) ).ToList(); var shuffleMove = ShuffleToShuffle(shuffleTargets, world.ShuffleCrane, shuffleLots); if (shuffleMove != null) { shuffleMove.ReleaseTime = world.Now; plan.Moves.Add(shuffleMove); } } } }