示例#1
0
        /// <summary>
        /// This is called to decide about potentially pending orders.
        /// This method is being timed for statistical purposes and is also ONLY called when <code>SituationInvestigated</code> is <code>false</code>.
        /// Hence, set the field accordingly to react on events not tracked by this outer skeleton.
        /// </summary>
        protected override void DecideAboutPendingOrders()
        {
            foreach (var order in _pendingOrders.Where(o => o.Positions.All(p => Instance.StockInfo.GetActualStock(p.Key) >= p.Value)).ToArray())
            {
                OutputStation chosenStation = null;
                switch (_config.OrderingRule)
                {
                case WorkloadOrderingRule.LowestOrderCount:
                    chosenStation = Instance.OutputStations
                                    .Where(s => s.Active && s.FitsForReservation(order)) // There has to be sufficient capacity left at the station
                                    .OrderBy(s => s.CapacityInUse + s.CapacityReserved)  // Choose the one with the least orders
                                    .ThenBy(s => Instance.Randomizer.NextDouble())       // Use a random tie-breaker
                                    .FirstOrDefault();
                    break;

                case WorkloadOrderingRule.HighestOrderCount:
                    chosenStation = Instance.OutputStations
                                    .Where(s => s.Active && s.FitsForReservation(order))          // There has to be sufficient capacity left at the station
                                    .OrderByDescending(s => s.CapacityInUse + s.CapacityReserved) // Choose the one with the most orders
                                    .ThenBy(s => Instance.Randomizer.NextDouble())                // Use a random tie-breaker
                                    .FirstOrDefault();
                    break;

                default: throw new ArgumentException("Unknown ordering rule: " + _config.OrderingRule);
                }
                // If we found a station, assign the bundle to it
                if (chosenStation != null)
                {
                    AllocateOrder(order, chosenStation);
                }
            }
        }
示例#2
0
        /// <summary>
        /// Called whenever a new Order has been assigned to an OutputStation.
        /// </summary>
        /// <param name="order">The Order which is assigned to the station.</param>
        /// <param name="station">The station the order is assigned to.</param>
        public void NewOrderAssignedToStation(Order order, OutputStation station)
        {
            // Connect request info with assigned station
            foreach (var request in order.Requests)
            {
                request.Assign(station);
                // If request is not yet assigned, update the info
                if (_availableExtractRequests.Contains(request))
                {
                    // Move request to available request list of station
                    _availableExtractRequestsPerStation[station].Add(request);
                    _availableExtractRequestsPerStationQueue[station].Remove(request);
                    // Update demand
                    _queuedDemand[request.Item]--;
                    _assignedDemand[request.Item]++;
                }
                // Manage queue info
                _stationQueuedPerExtractRequest.Remove(request);
            }

            /*
             * station.StatCurrentlyOpenRequests = _availableExtractRequestsPerStation[station].Count;
             * station.StatCurrentlyOpenQueuedRequests = _availableExtractRequestsPerStationQueue[station].Count;
             */
        }
示例#3
0
 /// <summary>
 /// Validates that the given combination is a valid assignment to the fast-lane slot of a station.
 /// </summary>
 /// <param name="s">The station.</param>
 /// <param name="o">The order.</param>
 /// <returns><code>true</code> if the assignment is valid, <code>false</code> otherwise.</returns>
 private bool ValidFastLaneAssignment(OutputStation s, Order o)
 {
     return(_nearestInboundPod[s] == null || _nearestInboundPod[s].GetDistance(s) > Instance.SettingConfig.Tolerance ? false :
            o.Requests.Any(r => r.State != Management.RequestState.Finished && r.Pod != null && r.Pod != _nearestInboundPod[s]) ? false :
            o.Requests.Where(r => r.State != Management.RequestState.Finished && r.Pod == null).GroupBy(r => r.Item)
            .All(i => _nearestInboundPod[s].CountAvailable(i.Key) >= i.Count()) ? true : false);
 }
示例#4
0
 /// <summary>
 /// Gets the number of robots currently assigned to the given station. Does only work for the balanced bot manager. For others it will only return 0.
 /// </summary>
 /// <param name="station">The station to get the number for.</param>
 /// <returns>The number of bots currently assigned to the station or always 0 if the bot manager does not support these assignments.</returns>
 internal int StatGetInfoBalancedBotsPerStation(OutputStation station)
 {
     return
         (Controller.BotManager is BalancedBotManager ? (Controller.BotManager as BalancedBotManager).GetAssignedBotCount(station) :
          Controller.BotManager is ConstantRatioBotManager ? (Controller.BotManager as ConstantRatioBotManager).GetAssignedBotCount(station) :
          0);
 }
示例#5
0
        /// <summary>
        /// return the Distance between the bot and the station
        /// </summary>
        /// TODO Change the way to calculate Distance by different Tiers
        private double GetDistance(Bot bot, Object station)
        {
            double distance;

            if (station is InputStation)
            {
                InputStation inStation = station as InputStation;
                //Manhatten Distance
                distance = Math.Abs(inStation.GetInfoCenterX() - bot.GetInfoCenterX()) + Math.Abs(inStation.GetInfoCenterY() - bot.GetInfoCenterY());
                if (inStation.GetInfoCurrentTier().GetInfoZ() != bot.GetInfoCurrentTier().GetInfoZ())
                {
                    distance += bot.GetInfoCurrentTier().GetInfoWidth();
                    distance += Math.Abs(inStation.GetInfoCurrentTier().GetInfoZ() - bot.GetInfoCurrentTier().GetInfoZ());
                }
            }
            else if (station is OutputStation)
            {
                OutputStation outStation = station as OutputStation;
                //Manhatten Distance
                distance = Math.Abs(outStation.GetInfoCenterX() - bot.GetInfoCenterX()) + Math.Abs(outStation.GetInfoCenterY() - bot.GetInfoCenterY());
                if (outStation.GetInfoCurrentTier().GetInfoZ() != bot.GetInfoCurrentTier().GetInfoZ())
                {
                    distance += bot.GetInfoCurrentTier().GetInfoWidth();
                    distance += Math.Abs(outStation.GetInfoCurrentTier().GetInfoZ() - bot.GetInfoCurrentTier().GetInfoZ());
                }
            }
            else
            {
                distance = Int32.MaxValue;
            }
            return(distance);
        }
示例#6
0
        /// <summary>
        /// Notifies the instance that an order was completed in order to keep the statistics up-to-date.
        /// </summary>
        /// <param name="oStation">The corresponding station.</param>
        /// <param name="order">The order that was completed.</param>
        internal void NotifyOrderCompleted(Order order, OutputStation oStation)
        {
            // Store the number of handled items
            StatOverallOrdersHandled++;
            // Check whether the order was completed too late
            if (Controller.CurrentTime - order.DueTime > 0)
            {
                StatOverallOrdersLate++;
            }
            // Mark every item in the history with a timestamp
            //_statOrderHandlingTimestamps.Add(
            //new OrderHandledDatapoint(StatTime, oStation.ID, Controller.CurrentTime - order.TimeStamp, Controller.CurrentTime - order.TimeStampSubmit, Controller.CurrentTime - order.DueTime, Controller.CurrentTime - order.TimeStampSubmit, StatTime, StatTime, StatTime));
            // Flush data points in case there are too many already
            if (_statOrderHandlingTimestamps.Count > STAT_MAX_DATA_POINTS)
            {
                StatFlushOrdersHandled();
            }
            // Log turnover time
            _statOrderTurnoverTimes.Add(Controller.CurrentTime - order.TimeStamp);
            // Log throughput time
            _statOrderThroughputTimes.Add(Controller.CurrentTime - order.TimeStampSubmit);
            // Log lateness
            _statOrderLatenessTimes.Add(Controller.CurrentTime - order.DueTime);
            // log Time Queuing
            _statOrderTimeQueueing.Add(Controller.CurrentTime - order.TimeStampSubmit);
            _statOrderTotalTimeQueueing.Add(StatTime);
            _statOrderTaskTimeRest.Add(StatTime);

            // Raise the event
            OrderCompleted?.Invoke(order, oStation);
        }
示例#7
0
        /// <summary>
        /// This is called to decide about potentially pending orders.
        /// This method is being timed for statistical purposes and is also ONLY called when <code>SituationInvestigated</code> is <code>false</code>.
        /// Hence, set the field accordingly to react on events not tracked by this outer skeleton.
        /// </summary>
        protected override void DecideAboutPendingOrders()
        {
            foreach (var order in _pendingOrders.Where(o => o.Positions.All(p => Instance.StockInfo.GetActualStock(p.Key) >= p.Value)).ToArray())
            {
                OutputStation chosenStation = Instance.OutputStations
                                              // There has to be sufficient capacity left at the station
                                              .Where(s => s.Active && s.FitsForReservation(order))
                                              // Choose the one with the most lines in common
                                              .OrderByDescending(s => s.AssignedOrders.Sum(other =>
                                                                                           other.Positions.Select(p => p.Key).Intersect(order.Positions.Select(p => p.Key)).Count()))
                                              // Use a tie breaker (especially for situations where stations are empty)
                                              .ThenBy(s =>
                {
                    switch (_config.TieBreaker)
                    {
                    case RelatedOrderBatchingTieBreaker.Random: return(Instance.Randomizer.NextDouble());

                    case RelatedOrderBatchingTieBreaker.LeastBusy: return(s.AssignedOrders.Count());

                    case RelatedOrderBatchingTieBreaker.MostBusy: return(-s.AssignedOrders.Count());

                    default: throw new ArgumentException("Unknown tie-breaker: " + _config.TieBreaker);
                    }
                })
                                              // The first one is the best
                                              .FirstOrDefault();
                // If we found a station, assign the bundle to it
                if (chosenStation != null)
                {
                    AllocateOrder(order, chosenStation);
                }
            }
        }
示例#8
0
 /// <summary>
 /// Notifies the instance that an order was allocated.
 /// </summary>
 internal void NotifyOrderAllocated(OutputStation oStation, Order order)
 {
     // Store the time the order was submitted to the system
     order.TimeStampSubmit = Controller.CurrentTime;
     // Raise the event
     OrderAllocated?.Invoke(oStation, order);
 }
示例#9
0
 /// <summary>
 /// Notifies the instance that a line was handled in order to keep the statistics up-to-date.
 /// </summary>
 /// <param name="oStation">The corresponding station.</param>
 /// <param name="item">The item that was picked.</param>
 /// <param name="lineCount">The number of items that have been picked for the line.</param>
 internal void NotifyLineHandled(OutputStation oStation, ItemDescription item, int lineCount)
 {
     // Store the number of handled lines
     StatOverallLinesHandled++;
     // Raise the event
     LinePicked?.Invoke(oStation, item, lineCount);
 }
示例#10
0
 /// <summary>
 /// This is called to decide about potentially pending orders.
 /// This method is being timed for statistical purposes and is also ONLY called when <code>SituationInvestigated</code> is <code>false</code>.
 /// Hence, set the field accordingly to react on events not tracked by this outer skeleton.
 /// </summary>
 protected override void DecideAboutPendingOrders()
 {
     foreach (var order in _pendingOrders.Where(o => o.Positions.All(p => Instance.StockInfo.GetActualStock(p.Key) >= p.Value)).ToArray())
     {
         OutputStation chosenStation = null;
         // Try to reuse the last station for this order
         if (_config.Recycle && _lastChosenStation != null && _lastChosenStation.Active && _lastChosenStation.FitsForReservation(order))
         {
             // Last chosen station can be used for this order too
             chosenStation = _lastChosenStation;
         }
         else
         {
             // Choose a random station
             chosenStation = Instance.OutputStations
                             .Where(s => s.Active && s.FitsForReservation(order)) // There has to be sufficient capacity left at the station
                             .OrderBy(s => Instance.Randomizer.NextDouble())      // Choose a random one
                             .FirstOrDefault();
             _lastChosenStation = chosenStation;
         }
         // If we found a station, assign the bundle to it
         if (chosenStation != null)
         {
             AllocateOrder(order, chosenStation);
         }
     }
 }
示例#11
0
        /// <summary>
        /// This is called to decide about potentially pending orders.
        /// This method is being timed for statistical purposes and is also ONLY called when <code>SituationInvestigated</code> is <code>false</code>.
        /// Hence, set the field accordingly to react on events not tracked by this outer skeleton.
        /// </summary>
        protected override void DecideAboutPendingOrders()
        {
            foreach (var order in _pendingOrders.Where(o => o.Positions.All(p => Instance.StockInfo.GetActualStock(p.Key) >= p.Value)).ToArray())
            {
                // Check all pods for the maximum number of picks that can be done with them
                List <Pod> bestPods     = new List <Pod>();
                int        bestPodPicks = -1;
                foreach (var pod in Instance.Pods.Where(p => !p.InUse))
                {
                    // Calculate picks that can potentially be done with the pod
                    int picks = order.Positions.Sum(pos => Math.Min(pod.CountAvailable(pos.Key), pos.Value));
                    // Check whether we found even more possible picks with this pod
                    if (bestPodPicks < picks)
                    {
                        bestPods.Clear();
                        bestPods.Add(pod);
                        bestPodPicks = picks;
                    }
                    else
                    {
                        // Check whether the current pod belongs into the winner group
                        if (bestPodPicks == picks)
                        {
                            bestPods.Add(pod);
                        }
                    }
                }
                // Choose station nearest to one of the best pods
                OutputStation chosenStation    = null;
                double        shortestDistance = double.PositiveInfinity;
                foreach (var station in Instance.OutputStations.Where(s => s.Active && s.FitsForReservation(order)))
                {
                    foreach (var pod in bestPods)
                    {
                        double distance;
                        switch (_config.DistanceRule)
                        {
                        case NearBestPodOrderBatchingDistanceRule.Euclid: distance = Distances.CalculateEuclid(pod, station, Instance.WrongTierPenaltyDistance); break;

                        case NearBestPodOrderBatchingDistanceRule.Manhattan: distance = Distances.CalculateManhattan(pod, station, Instance.WrongTierPenaltyDistance); break;

                        case NearBestPodOrderBatchingDistanceRule.ShortestPath: distance = Distances.CalculateShortestPathPodSafe(pod.Waypoint, station.Waypoint, Instance); break;

                        default: throw new ArgumentException("Unknown distance rule: " + _config.DistanceRule);
                        }
                        if (distance < shortestDistance)
                        {
                            shortestDistance = distance;
                            chosenStation    = station;
                        }
                    }
                }
                // If we found a station, assign the bundle to it
                if (chosenStation != null)
                {
                    AllocateOrder(order, chosenStation);
                }
            }
        }
示例#12
0
 /// <summary>
 /// Removes the request information belonging to the order.
 /// </summary>
 /// <param name="order">The order that was just completed.</param>
 /// <param name="station">The station at which the order was completed.</param>
 private void OrderCompleted(Order order, OutputStation station)
 {
     foreach (var r in order.Requests)
     {
         _stationQueuedPerExtractRequest.Remove(r);
     }
     _availableExtractRequestsPerOrder.Remove(order);
 }
示例#13
0
 private void PodHandled(Pod pod, InputStation iStation, OutputStation oStation)
 {
     // If the recycled pod was just handled at an input-station, do not assign any more bundles to it (we do not want to bring it back immediately after replenishing it)
     if (pod == _lastChosenPod && iStation != null)
     {
         _lastChosenPod = null;
     }
 }
示例#14
0
        /// <summary>
        /// Estimates the amount of time it will take before a new item can be delivered to the output-station.
        /// </summary>
        /// <param name="w">The waypoint of the output-station.</param>
        /// <param name="bot">The bot to consider.</param>
        /// <returns>The estimated time.</returns>
        public static double EstimateOutputStationWaitTime(Bot bot, Waypoint w)
        {
            OutputStation ws = w.OutputStation;
            // Assume the wait time is 2 * length of the bot there plus the time for all items
            double waitTime = ((ws.ItemTransferTime + 5 * 2 * bot.Radius) / bot.MaxVelocity) * w.BotCountOverall * w.BotCountOverall; // TODO this time estimate cannot hold when transferring multiple items at once

            return(waitTime);
        }
示例#15
0
 /// <summary>
 /// Checks whether a filling repositioning move is necessary for the given station.
 /// </summary>
 /// <param name="station">The station to check.</param>
 /// <returns><code>true</code> if filling repositioning should be done for the station, <code>false</code> otherwise. </returns>
 private bool NeedsFillingRepositioning(OutputStation station)
 {
     return
         // We need to relocate, if the number of used cache storage locations is smaller ...
         (_chacheStorageLocations[station].Count(w => w.Pod != null) <
          // ... than the number of cache storage locations overall minus the ones to keep free per cache
          _chacheStorageLocations[station].Count - _config.CacheClearing);
 }
示例#16
0
 private void PodHandled(Pod pod, InputStation iStation, OutputStation oStation)
 {
     // If the recycled pod was just handled at an input-station, do not assign any more bundles to it
     if (pod == _lastChosenPod && iStation != null)
     {
         _lastChosenPod = null;
     }
 }
示例#17
0
 private void PodHandled(Pod pod, InputStation iStation, OutputStation oStation)
 {
     // If the recycled pod was just handled at an input-station, do not assign any more bundles to it (we do not want to bring it back immediately after replenishing it)
     if (iStation != null && _lastChosenPodByClassReverse.ContainsKey(pod))
     {
         _lastChosenPodByClass.Remove(_lastChosenPodByClassReverse[pod]);
         _lastChosenPodByClassReverse.Remove(pod);
     }
 }
示例#18
0
 /// <summary>
 /// Cleans up after a task was successfully executed.
 /// </summary>
 public override void Finish()
 {
     if (Requests.Any())
     {
         throw new InvalidOperationException("An unfinished request cannot be marked as finished!");
     }
     OutputStation.UnregisterInboundPod(ReservedPod);
     OutputStation.UnregisterExtractTask(this);
 }
示例#19
0
 /// <summary>
 /// Immediately submits the order to the station.
 /// </summary>
 /// <param name="order">The order that is going to be allocated.</param>
 /// <param name="station">The station the order is assigned to.</param>
 protected void AllocateOrder(Order order, OutputStation station)
 {
     // Update lists
     _pendingOrders.Remove(order);
     // Update intermediate capacity information
     station.RegisterOrder(order);
     // Submit the decision
     Instance.Controller.Allocator.Allocate(order, station);
 }
示例#20
0
        public void buildPickStation(int row, int column, directions d, List <Waypoint> bufferPaths, int activationOrderID)
        {
            OutputStation oStation = instance.CreateOutputStation(
                instance.RegisterOutputStationID(), tier, column + 0.5, row + 0.5, lc.StationRadius, lc.OStationCapacity, lc.ItemTransferTime, lc.ItemPickTime, activationOrderID);

            createTile_PickStation(row, column, d, oStation);
            Waypoint wp = tiles[row, column].wp;

            oStation.Queues[wp] = bufferPaths;
        }
示例#21
0
        public void createTile_PickStation(int row, int column, directions d, OutputStation oStation)
        {
            Waypoint wp = instance.CreateWaypoint(instance.RegisterWaypointID(), tier, oStation, true);

            if (tiles[row, column] != null)
            {
                throw new ArgumentException("trying to overwrite an existing waypoint!! At createTile_PickStation: tiles[row, column] != null");
            }
            tiles[row, column] = new Tile(d, wp, waypointTypes.PickStation);
        }
示例#22
0
 /// <summary>
 /// Creates a new task.
 /// </summary>
 /// <param name="instance">The instance this task belongs to.</param>
 /// <param name="bot">The robot that shall execute the task.</param>
 /// <param name="reservedPod">The pod to use for executing the task.</param>
 /// <param name="outputStation">The output station to bring the pod to.</param>
 /// <param name="requests">The requests to handle with this task.</param>
 public ExtractTask(Instance instance, Bot bot, Pod reservedPod, OutputStation outputStation, List <ExtractRequest> requests)
     : base(instance, bot)
 {
     ReservedPod   = reservedPod;
     OutputStation = outputStation;
     Requests      = requests;
     foreach (var request in requests)
     {
         request.StatInjected = false;
     }
 }
示例#23
0
 /// <summary>
 /// Prepares everything for executing the task (claiming resources and similar).
 /// </summary>
 public override void Prepare()
 {
     Instance.ResourceManager.ClaimPod(ReservedPod, Bot, BotTaskType.Extract);
     OutputStation.RegisterInboundPod(ReservedPod);
     OutputStation.RegisterExtractTask(this);
     for (int i = 0; i < Requests.Count; i++)
     {
         Instance.ResourceManager.RemoveExtractRequest(Requests[i]);
         ReservedPod.RegisterItem(Requests[i].Item, Requests[i]);
     }
 }
示例#24
0
        /// <summary>
        /// Enqueues an extraction task.
        /// </summary>
        /// <param name="bot">The bot that shall execute the task.</param>
        /// <param name="station">The station at which the task will be executed.</param>
        /// <param name="pod">The pod used for the task.</param>
        /// <param name="requests">The requests to handle when executing the task.</param>
        protected void EnqueueExtract(Bot bot, OutputStation station, Pod pod, List <ExtractRequest> requests)
        {
            ExtractTask task = new ExtractTask(Instance, bot, pod, station, requests);

            task.Prepare();
            if (_taskQueues[bot] != null)
            {
                _taskQueues[bot].Cancel();
            }
            _taskQueues[bot]       = task;
            _lastTaskEnqueued[bot] = task;
        }
示例#25
0
 /// <summary>
 /// Cleans up a cancelled task.
 /// </summary>
 public override void Cancel()
 {
     if (Bot.Pod == null)
     {
         Instance.ResourceManager.ReleasePod(ReservedPod);
     }
     OutputStation.UnregisterInboundPod(ReservedPod);
     OutputStation.UnregisterExtractTask(this);
     for (int i = 0; i < Requests.Count; i++)
     {
         Instance.ResourceManager.ReInsertExtractRequest(Requests[i]);
         ReservedPod.UnregisterItem(Requests[i].Item, Requests[i]);
     }
 }
示例#26
0
        /// <summary>
        /// Creates a new waypoint that serves as the handover point for an output station.
        /// </summary>
        /// <param name="id">The ID of the waypoint.</param>
        /// <param name="tier">The position (tier).</param>
        /// <param name="station">The station.</param>
        /// <param name="isQueueWaypoint">Indicates whether this waypoint is also a queue waypoint.</param>
        /// <returns>The newly created waypoint.</returns>
        public Waypoint CreateWaypoint(int id, Tier tier, OutputStation station, bool isQueueWaypoint)
        {
            Waypoint wp = new Waypoint(this)
            {
                ID = id, X = station.X, Y = station.Y, Radius = station.Radius, OutputStation = station, IsQueueWaypoint = isQueueWaypoint
            };

            station.Waypoint = wp;
            tier.AddWaypoint(wp);
            Waypoints.Add(wp);
            WaypointGraph.Add(wp);
            _idToWaypoint[wp.ID] = wp;
            // Set volatile ID
            SetVolatileIDForWaypoint(wp);
            // Return
            return(wp);
        }
示例#27
0
        private double Score(ScoreFunctionStationOrder scoreFunction, OutputStation station, Order order)
        {
            double score;

            switch (scoreFunction)
            {
            case ScoreFunctionStationOrder.InboundPodsAvailablePicks: score = ScoreNormal(station, order); break;

            case ScoreFunctionStationOrder.InboundPodsAvailablePicksDepletePod: score = ScoreWeightedDepletePod(station, order); break;

            case ScoreFunctionStationOrder.Deadline: score = ScoreDeadline(station, order); break;

            case ScoreFunctionStationOrder.InboundPodsAvailablePicksNotDepletePod: score = ScoreWeightedOTW(station, order); break;

            default: throw new ArgumentException("Unknown score function: " + _config.ScoreFunctionStationOrder.ToString());
            }
            return(score);
        }
示例#28
0
 /// <summary>
 /// Notifies the instance that items were handled in order to keep the statistics up-to-date.
 /// </summary>
 /// <param name="pod">The corresponding pod.</param>
 /// <param name="bot">The corresponding bot.</param>
 /// <param name="oStation">The corresponding station.</param>
 /// <param name="item">The item that was picked.</param>
 internal void NotifyItemHandled(Pod pod, Bot bot, OutputStation oStation, ItemDescription item)
 {
     // Store the number of handled items
     pod.StatItemsHandled++;
     StatOverallItemsHandled++;
     // Mark every item in the history with a timestamp
     _statItemHandlingTimestamps.Add(new ItemHandledDatapoint(Controller.CurrentTime - StatTimeStart, bot.ID, pod.ID, oStation.ID));
     // Flush data points in case there are too many already
     if (_statItemHandlingTimestamps.Count > STAT_MAX_DATA_POINTS)
     {
         StatFlushItemsHandled();
     }
     // Keep track of the maximal number of handled items
     if (StatMaxItemsHandledByPod < pod.StatItemsHandled)
     {
         StatMaxItemsHandledByPod = pod.StatItemsHandled;
     }
     // Raise the event
     ItemPicked?.Invoke(pod, bot, oStation, item);
 }
示例#29
0
 /// <summary>
 /// Allocates the order.
 /// </summary>
 /// <param name="order">The order to allocate.</param>
 /// <param name="station">The station to allocate the order to.</param>
 public void Allocate(Order order, OutputStation station)
 {
     // Indicate change at instance
     Instance.Changed = true;
     // Check whether decision is possible
     if (station.CapacityInUse + 1 > station.Capacity)
     {
         throw new InvalidOperationException("Allocating the bundle to the station would exceed its capacity!");
     }
     // Hand over the order
     station.AssignOrder(order);
     // Add extraction request
     Instance.ResourceManager.NewOrderAssignedToStation(order, station);
     // Mark orders allocated
     Instance.Controller.OrderManager.SignalOrderAllocated(order, station);
     // Notify item manager
     Instance.ItemManager.NewOrderAssignedToStation(station, order);
     // Remove order from item manager
     (Instance.ItemManager as ItemManager).TakeAvailableOrder(order);
 }
示例#30
0
 /// <summary>
 /// Called whenever a new order shall be assigned to the order pool of a station.
 /// </summary>
 /// <param name="order">The order to assign to the order pool of the station.</param>
 /// <param name="station">The station to assign the order to.</param>
 public void NewOrderQueuedToStation(Order order, OutputStation station)
 {
     // Remember queue time
     order.TimeStampQueued = _instance.Controller.CurrentTime;
     // Remember station for all requests of the order
     foreach (var request in order.Requests)
     {
         _stationQueuedPerExtractRequest[request] = station;
     }
     // Update active requests
     foreach (var request in _availableExtractRequestsPerOrder[order])
     {
         // Move not yet allocated requests to available requests of station
         _availableExtractRequestsPerStationQueue[station].Add(request);
         // Update demand
         _queuedDemand[request.Item]++;
         _backlogDemand[request.Item]--;
     }
     // Update statistics
     station.StatCurrentlyOpenQueuedRequests = _availableExtractRequestsPerStationQueue[station].Count;
 }