private void ItemExtracted(Pod pod, ItemDescription item) { // Skip callback, if inactive if (!_instance.SettingConfig.MonitorWellSortedness) { return; } // Return if not in use yet if (_podsContainingItems == null) { return; } // --> Update pod utility int itemDemand = _instance.StockInfo.GetCurrentDemand(item); bool updateUtilityMax = false; // Update demand by new content of pod (pod lost one of these items) if (itemDemand >= pod.CountContained(item)) { // The demand for this item is still high, but we can now supply one item less (because the content is low in comparison to the demand) _podUtility[pod]--; // Check whether utility max has to be updated if (pod == _podUtilityMaxPod) { updateUtilityMax = true; } } // Update to new demand (demand for the given item sunk by one) foreach (var itemPod in _podsContainingItems[item]) { // If the demand for the item is less then the pod content, we need to update to the new demand by decreasing the utility by one if (itemDemand < itemPod.CountContained(item)) { _podUtility[itemPod]--; // Check whether utility max has to be updated if (itemPod == _podUtilityMaxPod) { updateUtilityMax = true; } } } // Refresh new max if (updateUtilityMax) { VolatileKeyValuePair <Pod, double> bestUtility = _podUtility.ArgMax(pu => pu.Value); _podUtilityMaxPod = bestUtility.Key; PodUtilityMax = bestUtility.Value; } // --> Remove pod from list of pods containing / offering the item, if it was the last one if (!pod.IsAvailable(item)) { _podsAvailableItems[item].Remove(pod); } if (!pod.IsContained(item)) { _podsContainingItems[item].Remove(pod); } // --> Update pod speed _podSpeed[pod] -= _instance.FrequencyTracker.GetStaticFrequency(item); if (pod == _podSpeedMaxPod) { // Refresh max value VolatileKeyValuePair <Pod, double> bestSpeed = _podSpeed.ArgMax(ps => ps.Value); _podSpeedMaxPod = bestSpeed.Key; PodSpeedMax = bestSpeed.Value; } }
/// <summary> /// Initializes this tracker. /// </summary> private void EnsureInit() { if (_podsContainingItems == null) { // --> Init storage location info _storageLocationProminence = new VolatileIDDictionary <Waypoint, double>(_instance.Waypoints .Where(w => w.PodStorageLocation) // Determine pod prominence score .Select(w => new VolatileKeyValuePair <Waypoint, double>(w, _instance.OutputStations.Min(s => { return(Distances.CalculateShortestTimePathPodSafe(w, s.Waypoint, _instance)); }))) .ToList()); StorageLocationsOrdered = _storageLocationProminence // Order storage locations by their prominence .OrderBy(kvp => kvp.Value) // Break ties randomly .ThenBy(kvp => _instance.Randomizer.NextDouble()) // Select the actual locations and build a list .Select(kvp => kvp.Key).ToList(); // Store prominence index _storageLocationIndeces = new VolatileIDDictionary <Waypoint, int>(StorageLocationsOrdered.Select(w => new VolatileKeyValuePair <Waypoint, int>(w, 0)).ToList()); for (int i = 0; i < StorageLocationsOrdered.Count; i++) { _storageLocationIndeces[StorageLocationsOrdered[i]] = i; } // Determine prominence ranks _storageLocationRanks = new VolatileIDDictionary <Waypoint, int>(StorageLocationsOrdered.Select(w => new VolatileKeyValuePair <Waypoint, int>(w, 0)).ToList()); int currentRank = 1; double currentProminenceValue = _storageLocationProminence[StorageLocationsOrdered.First()]; foreach (var storageLocation in StorageLocationsOrdered) { // Update rank, if required if (_storageLocationProminence[storageLocation] > currentProminenceValue) { currentRank++; currentProminenceValue = _storageLocationProminence[storageLocation]; } // Set rank of storage location _storageLocationRanks[storageLocation] = currentRank; } _storageLocationsPerRank = _storageLocationRanks.GroupBy(kvp => kvp.Value).ToDictionary(k => k.Key, v => v.Select(kvp => kvp.Key).OrderBy(kvp => _instance.Randomizer.NextDouble()).ToList()); StorageLocationRankMax = _storageLocationRanks.Values.Max(); // Store prominence ranks for statistics tracking foreach (var w in StorageLocationsOrdered) { w.InfoTagProminence = 1.0 - ((_storageLocationRanks[w] - 1.0) / (StorageLocationRankMax - 1.0)); } // --> Init pod score values _podsContainingItems = new VolatileIDDictionary <ItemDescription, HashSet <Pod> >( _instance.ItemDescriptions.Select(i => new VolatileKeyValuePair <ItemDescription, HashSet <Pod> >(i, _instance.Pods.Where(p => p.IsContained(i)).ToHashSet())).ToList()); _podsAvailableItems = new VolatileIDDictionary <ItemDescription, HashSet <Pod> >( _instance.ItemDescriptions.Select(i => new VolatileKeyValuePair <ItemDescription, HashSet <Pod> >(i, _instance.Pods.Where(p => p.IsAvailable(i)).ToHashSet())).ToList()); // Determine initial pod utility _podUtility = new VolatileIDDictionary <Pod, double>( _instance.Pods.Select(p => new VolatileKeyValuePair <Pod, double>(p, p.ItemDescriptionsContained.Sum(i => Math.Min(p.CountContained(i), _instance.StockInfo.GetCurrentDemand(i))))) .ToList()); VolatileKeyValuePair <Pod, double> bestUtility = _podUtility.ArgMax(pu => pu.Value); _podUtilityMaxPod = bestUtility.Key; PodUtilityMax = bestUtility.Value; // Determine initial pod speed _podSpeed = new VolatileIDDictionary <Pod, double>( _instance.Pods.Select(p => new VolatileKeyValuePair <Pod, double>(p, p.ItemDescriptionsContained.Sum(i => p.CountContained(i) * _instance.FrequencyTracker.GetStaticFrequency(i)))) .ToList()); VolatileKeyValuePair <Pod, double> bestSpeed = _podSpeed.ArgMax(ps => ps.Value); _podSpeedMaxPod = bestSpeed.Key; PodSpeedMax = bestSpeed.Value; } }