feat: læs-bytte fra Wait — rest afleveres i silo når målet mangler en anden vare
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
-- AD Load Swap
|
||||
-- En traktor der venter ved et Wait-punkt med en vare målet er fuldt af, mens målet
|
||||
-- MANGLER en anden vare i traktorens liste, låser forsyningen (alle venter med halm,
|
||||
-- ingen henter TMR). Her afleveres resten i en silo der tager varen, så vognen er tom
|
||||
-- og næste tur henter det målet mangler.
|
||||
|
||||
ADLoadSwap = {}
|
||||
|
||||
ADLoadSwap.LOG_PREFIX = "ADSmartPickup: "
|
||||
-- Opslaget går over alle markører; ventende traktorer tjekker derfor kun så tit.
|
||||
ADLoadSwap.CHECK_INTERVAL_MS = 5000
|
||||
|
||||
local warnedNoSilo = setmetatable({}, {__mode = "k"})
|
||||
|
||||
-- Er en anden vare i listen så tom i målet, at et FULDT læs passer, og findes den i en silo?
|
||||
function ADLoadSwap.findMissingIngredient(adEnv, vehicle, restFillType)
|
||||
local ingredients = ADSmartPickup.getIngredientsFor(adEnv, vehicle)
|
||||
if ingredients == nil or #ingredients < 2 then
|
||||
return nil
|
||||
end
|
||||
local choice = ADSmartPickup.findSupplyPickup(adEnv, vehicle, ingredients)
|
||||
if choice == nil or choice.fillType == nil or choice.fillType == restFillType or choice.need.fits ~= true then
|
||||
return nil
|
||||
end
|
||||
return choice
|
||||
end
|
||||
|
||||
-- Kun rene lager-siloer: stalde og fabrikker har egne regler, og målet selv er fuldt.
|
||||
local function isSilo(station, homeStation)
|
||||
local placeable = station.owningPlaceable
|
||||
return placeable ~= nil and placeable.spec_silo ~= nil and placeable.getHusbandryFillLevel == nil
|
||||
and placeable.spec_productionPoint == nil and (homeStation == nil or placeable ~= homeStation.owningPlaceable)
|
||||
end
|
||||
|
||||
local function acceptsRest(station, fillType, rest, farmId)
|
||||
if station.getIsFillTypeSupported ~= nil and not station:getIsFillTypeSupported(fillType) then
|
||||
return false
|
||||
end
|
||||
local free = station.getFreeCapacity ~= nil and station:getFreeCapacity(fillType, farmId) or 0
|
||||
return free >= rest
|
||||
end
|
||||
|
||||
-- Nærmeste silo med plads til resten og vejnet til/fra; siloer der allerede har varen foretrækkes.
|
||||
function ADLoadSwap.findDumpMarker(adEnv, vehicle, fillType, rest, homeWayPointId, isReachable)
|
||||
local farmId = ADSmartPickup.getFarmId(vehicle)
|
||||
local homeStation = ADSmartPickup.getUnloadStationAtWayPointId(adEnv, homeWayPointId, farmId)
|
||||
local x, _, z = getWorldTranslation(vehicle.rootNode)
|
||||
local candidates = {}
|
||||
for _, marker in pairs(adEnv.ADGraphManager:getMapMarkers()) do
|
||||
local station = ADSmartPickup.getUnloadStationAtWayPointId(adEnv, marker.id, farmId)
|
||||
if station ~= nil and isSilo(station, homeStation) and acceptsRest(station, fillType, rest, farmId) then
|
||||
local wayPoint = adEnv.ADGraphManager:getWayPointById(marker.id)
|
||||
local dx, dz = wayPoint.x - x, wayPoint.z - z
|
||||
table.insert(candidates, {
|
||||
marker = marker,
|
||||
hasFillType = ADSmartPickup.getOwnStorageLevel(station, {fillType}) > 0,
|
||||
distance = dx * dx + dz * dz,
|
||||
})
|
||||
end
|
||||
end
|
||||
table.sort(candidates, function(a, b)
|
||||
if a.hasFillType ~= b.hasFillType then
|
||||
return a.hasFillType
|
||||
end
|
||||
return a.distance < b.distance
|
||||
end)
|
||||
for _, candidate in ipairs(candidates) do
|
||||
if isReachable(candidate.marker.id) then
|
||||
return candidate.marker
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Kaldes fra Wait-logikken hvert tick; redirect(task, id) og release(vehicle) er dens egne.
|
||||
-- true = traktoren er sendt til en silo (Wait-punktet er frigivet).
|
||||
function ADLoadSwap.tryFromWait(adEnv, task, wait, dt, redirect, release, isReachable)
|
||||
wait.swapTimerMs = (wait.swapTimerMs or 0) + (dt or 0)
|
||||
if wait.swapTimerMs < ADLoadSwap.CHECK_INTERVAL_MS then
|
||||
return false
|
||||
end
|
||||
wait.swapTimerMs = 0
|
||||
local vehicle = task.vehicle
|
||||
local missing = ADLoadSwap.findMissingIngredient(adEnv, vehicle, wait.fillType)
|
||||
if missing == nil then
|
||||
return false
|
||||
end
|
||||
local marker = ADLoadSwap.findDumpMarker(adEnv, vehicle, wait.fillType, wait.rest, wait.homeDestinationID, isReachable)
|
||||
local restName = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(wait.fillType) or tostring(wait.fillType)
|
||||
local missingName = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(missing.fillType) or tostring(missing.fillType)
|
||||
if marker == nil then
|
||||
if not warnedNoSilo[vehicle] then
|
||||
warnedNoSilo[vehicle] = true
|
||||
Logging.warning(ADLoadSwap.LOG_PREFIX .. "'%s' venter med %.0f l %s, og målet mangler %s — ingen silo med plads og vejnet til/fra tager resten, så den bliver ved Wait-punktet", tostring(vehicle:getName()), wait.rest, tostring(restName), tostring(missingName))
|
||||
end
|
||||
return false
|
||||
end
|
||||
warnedNoSilo[vehicle] = nil
|
||||
release(vehicle)
|
||||
redirect(task, marker.id)
|
||||
Logging.info(ADLoadSwap.LOG_PREFIX .. "'%s' bytter læs: %.0f l %s tilbage i %s (markør %s), målet mangler %s", tostring(vehicle:getName()), wait.rest, tostring(restName), tostring(marker.name), tostring(marker.markerIndex or marker.id), tostring(missingName))
|
||||
return true
|
||||
end
|
||||
|
||||
function ADLoadSwap.clearWarning(vehicle)
|
||||
warnedNoSilo[vehicle] = nil
|
||||
end
|
||||
@@ -96,6 +96,9 @@ local function release(vehicle)
|
||||
claims[wait.waitMarker.id] = nil
|
||||
end
|
||||
waits[vehicle] = nil
|
||||
if ADLoadSwap ~= nil then
|
||||
ADLoadSwap.clearWarning(vehicle)
|
||||
end
|
||||
end
|
||||
|
||||
-- Står køretøjet ved målet med rest-læs, som målet ikke kan tage? Så find et Wait-punkt.
|
||||
@@ -136,7 +139,7 @@ local function startWaiting(adEnv, task)
|
||||
end
|
||||
|
||||
-- Ventende køretøj: er der nu plads til hele resten, køres tilbage til målet.
|
||||
local function updateWaiting(adEnv, task, wait)
|
||||
local function updateWaiting(adEnv, task, wait, dt)
|
||||
local vehicle = task.vehicle
|
||||
if wait.task ~= task then
|
||||
release(vehicle)
|
||||
@@ -149,6 +152,12 @@ local function updateWaiting(adEnv, task, wait)
|
||||
end
|
||||
local free, capacity = ADSmartPickup.getTargetFreeCapacity(adEnv, vehicle, fillType)
|
||||
if free == nil or not ADSupplyPlanner.canUnloadRest(free, rest, capacity) then
|
||||
if ADLoadSwap ~= nil then
|
||||
local isReachable = function(markerId)
|
||||
return hasRouteBothWays(adEnv, vehicle, markerId, wait.homeDestinationID)
|
||||
end
|
||||
ADLoadSwap.tryFromWait(adEnv, task, wait, dt, redirect, release, isReachable)
|
||||
end
|
||||
return
|
||||
end
|
||||
local home = wait.homeDestinationID
|
||||
@@ -157,10 +166,10 @@ local function updateWaiting(adEnv, task, wait)
|
||||
Logging.info(ADUnloadWait.LOG_PREFIX .. "'%s' kører tilbage fra %s og læsser %.0f l af (målet har %.0f l fri)", tostring(vehicle:getName()), tostring(wait.waitMarker.name), rest, free)
|
||||
end
|
||||
|
||||
function ADUnloadWait.beforeUpdate(adEnv, task)
|
||||
function ADUnloadWait.beforeUpdate(adEnv, task, dt)
|
||||
local wait = waits[task.vehicle]
|
||||
if wait ~= nil then
|
||||
updateWaiting(adEnv, task, wait)
|
||||
updateWaiting(adEnv, task, wait, dt)
|
||||
else
|
||||
startWaiting(adEnv, task)
|
||||
end
|
||||
@@ -204,7 +213,7 @@ function ADUnloadWait.install(adEnv)
|
||||
local originalUpdate, originalFinished, originalGetSetting = task.update, task.finished, autoDrive.getSetting
|
||||
|
||||
task.update = function(self, dt)
|
||||
local ok, err = pcall(ADUnloadWait.beforeUpdate, adEnv, self)
|
||||
local ok, err = pcall(ADUnloadWait.beforeUpdate, adEnv, self, dt)
|
||||
if not ok then
|
||||
Logging.warning(ADUnloadWait.LOG_PREFIX .. "fejl i Wait-punkt-logik, AutoDrive fortsætter selv: %s", tostring(err))
|
||||
release(self.vehicle)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<sourceFile filename="adRuns.lua"/>
|
||||
<sourceFile filename="adRunsStorage.lua"/>
|
||||
<sourceFile filename="adRunsController.lua"/>
|
||||
<sourceFile filename="adLoadSwap.lua"/>
|
||||
<sourceFile filename="adUnloadWait.lua"/>
|
||||
<sourceFile filename="adSmartPickup.lua"/>
|
||||
</extraSourceFiles>
|
||||
|
||||
Reference in New Issue
Block a user