feat: Wait-punkter for rest-læs + læs der passer foretrækkes (v1.7.0.0)

Rest-læs ved fuldt mål: AutoDrive ventede ved aflæsningspunktet 'til tømt' og
spærrede køen. Nu omdirigeres den aktuelle UnloadAtDestinationTask (destinationID +
drivePathModule:setPathTo) til nærmeste ledige markør med 'Wait' i navnet / mappen
Wait (fælles pulje, reservationer pr. køretøj); tilbage når målet har plads til
hele resten. Ventende ser rotateTargets=RT_NONE så 'rotér aflæsning' ikke kører
videre fra Wait-punktet. Ingen ledige punkter = som i dag + én advarsel.

Rangering: varer hvor et fuldt læs (AutoDrive.getAllFillLevels-kapacitet) passer i
målet går forud; passer intet, mest trængende. Nyt modul adUnloadWait.lua;
ADSmartPickup.getTargetFreeCapacity delt hjælper.
This commit is contained in:
2026-09-22 21:12:55 +02:00
parent 2ff0b641b0
commit 39fccefa40
7 changed files with 469 additions and 22 deletions
+42 -1
View File
@@ -114,9 +114,46 @@ function ADSupplyPlanner.scoreNeed(level, capacity, freeSpace, minutesToEmpty)
return freeSpace / capacity
end
-- nil når læs-størrelsen er ukendt, ellers om et fuldt læs kan komme af i målet.
function ADSupplyPlanner.fullLoadFits(freeSpace, loadCapacity)
if loadCapacity == nil or loadCapacity <= 0 then
return nil
end
return freeSpace >= loadCapacity
end
-- Wait-punkter: markører med ordet "Wait" i navnet (uanset store/små) eller i mappen "Wait".
-- Her venter en traktor med rest-læs, til der igen er plads i målet.
function ADSupplyPlanner.isWaitMarker(marker)
if marker.group == "Wait" then
return true
end
local name = string.lower(tostring(marker.name or ""))
return string.find(name, "%f[%a]wait%f[%A]") ~= nil
end
-- candidates: {{marker, x, z}}; claims: {[marker.id] = køretøj}. Nærmeste punkt der er
-- ledigt eller allerede reserveret af dette køretøj. nil hvis alle er optaget.
function ADSupplyPlanner.pickNearestFreeWaitPoint(candidates, claims, x, z, vehicle)
local best, bestDistance = nil, nil
for _, candidate in ipairs(candidates) do
local owner = claims[candidate.marker.id]
if owner == nil or owner == vehicle then
local dx, dz = candidate.x - x, candidate.z - z
local distance = dx * dx + dz * dz
if bestDistance == nil or distance < bestDistance then
best, bestDistance = candidate, distance
end
end
end
return best
end
-- needs: {{fillType, level, capacity[, litersPerMinute]}, ...}. Returnerer NY liste,
-- mest trængende først; ingredienser uden plads i målet er sorteret fra.
function ADSupplyPlanner.rankNeeds(needs)
-- loadCapacity (valgfri): vognens kapacitet — varer hvor et FULDT læs kan komme af
-- går forud (så vognen ikke ender med rest-læs); passer intet, gælder ren trang.
function ADSupplyPlanner.rankNeeds(needs, loadCapacity)
local ranked = {}
for _, need in ipairs(needs) do
local freeSpace = need.capacity - need.level
@@ -129,11 +166,15 @@ function ADSupplyPlanner.rankNeeds(needs)
freeSpace = freeSpace,
litersPerMinute = need.litersPerMinute,
minutesToEmpty = minutesToEmpty,
fits = ADSupplyPlanner.fullLoadFits(freeSpace, loadCapacity),
score = ADSupplyPlanner.scoreNeed(need.level, need.capacity, freeSpace, minutesToEmpty),
})
end
end
table.sort(ranked, function(a, b)
if a.fits ~= b.fits then
return a.fits == true
end
if a.score ~= b.score then
return a.score > b.score
end