示例#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;
         // 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);
         }
     }
 }
示例#2
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()
        {
            // If not initialized, do it now
            if (_bestCandidateSelectOrder == null)
            {
                Initialize();
            }
            // Define filter functions
            Func <OutputStation, bool> validStationNormalAssignment   = _config.FastLane ? (Func <OutputStation, bool>)IsAssignableKeepFastLaneSlot : IsAssignable;
            Func <OutputStation, bool> validStationFastLaneAssignment = IsAssignable;

            // Get some meta info
            PrepareAssessment();
            // Assign fast lane orders while possible
            bool furtherOptions = true;

            while (furtherOptions && _config.FastLane)
            {
                // Prepare helpers
                OutputStation chosenStation = null;
                Order         chosenOrder   = null;
                _bestCandidateSelectFastLane.Recycle();
                // Look for next station to assign orders to
                foreach (var station in Instance.OutputStations
                         // Station has to be valid
                         .Where(s => validStationFastLaneAssignment(s)))
                {
                    // Set station
                    _currentStation = station;
                    // Check whether there is a suitable pod
                    if (_nearestInboundPod[station] != null && _nearestInboundPod[station].GetDistance(station) < Instance.SettingConfig.Tolerance)
                    {
                        // Search for best order for the station in all fulfillable orders
                        foreach (var order in _pendingOrders.Where(o =>
                                                                   // Order needs to be immediately fulfillable
                                                                   o.Positions.All(p => _nearestInboundPod[station].CountAvailable(p.Key) >= p.Value)))
                        {
                            // Set order
                            _currentOrder = order;
                            // --> Assess combination
                            if (_bestCandidateSelectFastLane.Reassess())
                            {
                                chosenStation = _currentStation;
                                chosenOrder   = _currentOrder;
                            }
                        }
                    }
                }
                // Assign best order if available
                if (chosenOrder != null)
                {
                    // Assign the order
                    AllocateOrder(chosenOrder, chosenStation);
                    // Log fast lane assignment
                    Instance.StatCustomControllerInfo.CustomLogOB1++;
                }
                else
                {
                    // No more options to assign orders to stations
                    furtherOptions = false;
                }
            }
            // Repeat normal assignment until no further options
            furtherOptions = true;
            while (furtherOptions)
            {
                // Prepare some helper values
                if (_config.OrderSelectionRule == DefaultOrderSelection.FrequencyAge)
                {
                    _oldestOrderTimestamp = _pendingOrders.Where(o => o.Positions.All(p => Instance.StockInfo.GetActualStock(p.Key) >= p.Value)).MinOrDefault(o => o.TimeStamp, -1);
                    _newestOrderTimestamp = _pendingOrders.Where(o => o.Positions.All(p => Instance.StockInfo.GetActualStock(p.Key) >= p.Value)).MaxOrDefault(o => o.TimeStamp, -1);
                    // Avoid division by zero, if necessary
                    if (_oldestOrderTimestamp == _newestOrderTimestamp)
                    {
                        _newestOrderTimestamp += 1;
                    }
                }
                // Choose order
                _bestCandidateSelectOrder.Recycle();
                Order bestOrder = null;
                foreach (var order in _pendingOrders.Where(o => o.Positions.All(p => Instance.StockInfo.GetActualStock(p.Key) >= p.Value)))
                {
                    // Update candidate
                    _currentOrder = order;
                    // Assess next order
                    if (_bestCandidateSelectOrder.Reassess())
                    {
                        bestOrder = _currentOrder;
                    }
                }
                // Check success
                if (bestOrder != null)
                {
                    // Try to reuse the last station for this order
                    OutputStation bestStation = null;
                    bool          recycling   = false;
                    if (_config.Recycle && _lastChosenStation != null && _lastChosenStation.Active && _lastChosenStation.FitsForReservation(bestOrder))
                    {
                        // Last chosen station can be used for this order too
                        bestStation = _lastChosenStation;
                        recycling   = true;
                    }
                    else
                    {
                        // Choose new station
                        _bestCandidateSelectStation.Recycle();
                        foreach (var station in Instance.OutputStations.Where(s => validStationNormalAssignment(s)))
                        {
                            // Update candidate
                            _currentStation = station;
                            // Assess next order
                            if (_bestCandidateSelectStation.Reassess())
                            {
                                bestStation = _currentStation;
                            }
                        }
                        // Store decision
                        _lastChosenStation = bestStation;
                    }

                    // Check success
                    if (bestStation != null)
                    {
                        // Add the assignment to the ready list
                        AllocateOrder(bestOrder, bestStation);
                        // Log score statistics (order)
                        if (_statScorerValuesOrder == null)
                        {
                            _statScorerValuesOrder = _bestCandidateSelectOrder.BestScores.ToArray();
                        }
                        else
                        {
                            for (int i = 0; i < _bestCandidateSelectOrder.BestScores.Length; i++)
                            {
                                _statScorerValuesOrder[i] += _bestCandidateSelectOrder.BestScores[i];
                            }
                        }
                        _statOrderSelections++;
                        Instance.StatCustomControllerInfo.CustomLogOB1 = _statScorerValuesOrder[0] / _statOrderSelections;
                        // Log score statistics (station)
                        if (!recycling)
                        {
                            if (_statScorerValuesStation == null)
                            {
                                _statScorerValuesStation = _bestCandidateSelectStation.BestScores.ToArray();
                            }
                            else
                            {
                                for (int i = 0; i < _bestCandidateSelectStation.BestScores.Length; i++)
                                {
                                    _statScorerValuesStation[i] += _bestCandidateSelectStation.BestScores[i];
                                }
                            }
                            _statStationSelections++;
                            Instance.StatCustomControllerInfo.CustomLogOB2 = _statScorerValuesStation[0] / _statStationSelections;
                        }
                    }
                    else
                    {
                        // No further options
                        furtherOptions = false;
                    }
                }
                else
                {
                    // No further options
                    furtherOptions = false;
                }
            }
        }