/// <summary> /// Finds the best delivery task for the specified pod. /// Sets <code>bestDeliveryRequest</code> to null if none found, otherwise <code>bestDeliveryRequest</code> and <code>bestTimeForDeliveryRequest</code> are initialized. /// </summary> /// <param name="bot">The bot to consider.</param> /// <param name="pod">Pod to take.</param> /// <param name="podLocation">Current location of the pod.</param> /// <param name="bestExtractTask">The best extract task set by this method.</param> /// <param name="bestTimeForExtract">The time of the best extract set by this method.</param> void GetBestTaskForPod(Bot bot, Pod pod, Waypoint podLocation, out ExtractRequest bestExtractTask, out double bestTimeForExtract) { bestExtractTask = null; bestTimeForExtract = 0.0; bestExtractTask = null; if (pod == null || podLocation == null) { return; } bestTimeForExtract = double.PositiveInfinity; // Check all tasks foreach (var delivery in Instance.ResourceManager.AvailableAndAssignedExtractRequests) { // If it has the item if (pod.IsContained(delivery.Item)) { // See how long it would take to get to the output-station // Choose the worst of delivering or waiting Waypoint sw = delivery.Station.Waypoint; double time = Math.Max(Estimators.EstimateTravelTimeEuclid(bot, podLocation, sw), Estimators.EstimateOutputStationWaitTime(bot, sw)); // If it's the best, then use it if (time < bestTimeForExtract) { bestExtractTask = delivery; bestTimeForExtract = time; } } } }
/// <summary> /// Based on the current situation, the bot needs to get an item, but doesn't have it. /// This function reserves the item the pod should pick up. Returns the pod that should be used, null if it's carying a pod and the current pod won't work (too full). /// </summary> /// <param name="bot">The bot to consider.</param> /// <param name="bestRequest">The best request to use for the best pickup task.</param> /// <param name="bestStation">The station to use for the best pickup task.</param> /// <param name="bestPod">The pod to use for the best pickup task.</param> public void ReserveBestItemToPickUp(Bot bot, out InsertRequest bestRequest, out Pod bestPod, out InputStation bestStation) { bestPod = null; bestStation = null; bestRequest = null; // If have a pod currently if (bot.Pod != null) { Pod pod = bot.Pod; // Current pod works, so find closest input station and best task double closestInputStationTime = double.PositiveInfinity; // Check all tasks foreach (var storeTask in Instance.ResourceManager.AvailableStoreRequests) { // See how long it would take to get to this input station // Choose the worst of delivering or waiting Waypoint sw = storeTask.Station.Waypoint; double time = Math.Max(Estimators.EstimateTravelTimeEuclid(bot, bot.CurrentWaypoint, sw), Estimators.EstimateInputStationWaitTime(bot, sw)); // If it's the best and it fits the current pod, then use it if (time < closestInputStationTime && pod.CapacityInUse + storeTask.Bundle.BundleWeight <= pod.Capacity) { bestRequest = storeTask; closestInputStationTime = time; } } // If no pickup suits the pod, get rid of it if (bestRequest == null) { return; } // Allocate task! bestStation = bestRequest.Station; bestPod = pod; } // Don't have a pod double bestPickupTime = double.PositiveInfinity; bestRequest = null; bestPod = null; foreach (var pod in Instance.ResourceManager.UnusedPods) { // Find time to pick up the bundle double pickupTime = Estimators.EstimateTravelTimeEuclid(bot, pod.Waypoint); // Check all tasks foreach (var storeTask in Instance.ResourceManager.AvailableStoreRequests) { // If it has room if (pod.CapacityInUse + storeTask.Bundle.BundleWeight <= pod.Capacity) { // See how long it would take to get to this input station // Choose the worst of delivering or waiting Waypoint sw = storeTask.Station.Waypoint; double deliverTime = Math.Max(Estimators.EstimateTravelTimeEuclid(bot, pod.Waypoint, sw), Estimators.EstimateInputStationWaitTime(bot, sw)); //if it's the best, then use it if (pickupTime + deliverTime < bestPickupTime) { bestRequest = storeTask; bestPickupTime = pickupTime + deliverTime; bestPod = pod; } } } } // No pickup request available if (bestRequest == null) { return; } // Pickup available - set it bestStation = bestRequest.Station; }
/// <summary> /// Determines the best delivery task for the given bot, and allocates the required resources. /// </summary> /// <param name="bot">The bot to consider.</param> /// <param name="bestPod">The pod to use for the best delivery task.</param> /// <param name="bestItemDescription">The type of the item to use for the best delivery task.</param> /// <param name="bestRequest">The request to use for the best delivery task.</param> /// <param name="bestStation">The station to use for the best delivery task.</param> /// <param name="bestStorageLocationOldPod">The storage location for the current pod to use for the best delivery task.</param> public void GetBestDeliveryTask(Bot bot, out ExtractRequest bestRequest, out Pod bestPod, out ItemDescription bestItemDescription, out OutputStation bestStation, out Waypoint bestStorageLocationOldPod) { // Find an item to retrieve double bestTaskTime = double.PositiveInfinity; bestPod = null; bestStorageLocationOldPod = null; // Try with the current pod ExtractRequest bestExtractTask; double bestExtractTime; GetBestTaskForPod(bot, bot.Pod, bot.CurrentWaypoint, out bestExtractTask, out bestExtractTime); bestRequest = bestExtractTask; if (bestRequest != null) { bestTaskTime = bestExtractTime; bestPod = bot.Pod; } // Time to pick up the pod double baseTime = bot.PodTransferTime; // Time to set down the current pod if it has one if (bot.Pod != null) { baseTime += bot.PodTransferTime; } foreach (var pod in Instance.ResourceManager.UnusedPods) { double time = baseTime; Waypoint bestStorageLocationForThisPod = null; // If need to set down current pod if (bot.Pod != null) { // Grab this once to pull it out of the loop Waypoint targetPodWaypoint = pod.Waypoint; double minStorageTime = double.PositiveInfinity; foreach (var storageLocation in Instance.ResourceManager.UnusedPodStorageLocations) { // Need time to set down current pod and also pick up new pod double storeTime = 2 * bot.PodTransferTime; // Find time to get to storage location storeTime += Estimators.EstimateTravelTimeEuclid(bot, storageLocation); // Find time to get from storage location to new pod storeTime += Estimators.EstimateTravelTimeEuclid(bot, storageLocation, targetPodWaypoint); if (storeTime < minStorageTime) { minStorageTime = storeTime; bestStorageLocationForThisPod = storageLocation; } } // Use the best waypoint time += minStorageTime; } else { // No pod, just go pick it up time += Estimators.EstimateTravelTimeEuclid(bot, pod.Waypoint); } // Get place to take the pod GetBestTaskForPod(bot, pod, pod.Waypoint, out bestExtractTask, out bestExtractTime); if (bestExtractTask != null) { // If the time is still better, then count it if (time + bestExtractTime < bestTaskTime) { bestRequest = bestExtractTask; bestTaskTime = time + bestExtractTime; bestPod = pod; bestStorageLocationOldPod = bestStorageLocationForThisPod; } } } // If found no task, take the oldest if (bestRequest == null) { bestRequest = Instance.ResourceManager.AvailableAndAssignedExtractRequests.First(); } bestItemDescription = bestRequest.Item; bestStation = bestRequest.Station; }