feat(pulje): bedste pasform — mindste traktor med hk nok vælges; afstand kun inden for ±15 %; over 2,5x redskabets behov kun som nødløsning (v1.56.0.0)

This commit is contained in:
2026-09-29 14:33:43 +02:00
parent 6af89c3034
commit 3e7e3d588e
3 changed files with 54 additions and 6 deletions
+39 -5
View File
@@ -70,7 +70,7 @@ end
local function nearest(items, x, z, keep)
local best, bestDistance = nil, math.huge
for _, item in ipairs(items) do
if keep(item) then
if keep == nil or keep(item) then
local distance = distanceSq(item.x, item.z, x, z)
if distance < bestDistance then best, bestDistance = item, distance end
end
@@ -80,6 +80,38 @@ end
-- Når opgaven slutter, sættes puljeredskabet af — også når AutoDrive ellers selv ville parkere (påfyldte
-- sæt): AD parkerer ved redskabets plads med redskabet på. Aldrig ved manuel transport.
-- Bedste pasform: den mindste traktor med hk nok; afstand afgør kun mellem traktorer inden for FIT_BAND af den
-- mindste. Over OVERSIZE_FACTOR x behovet kun når intet andet passer; ukendt traktor-hk efter de kendte.
-- Redskab uden hk-data: nærmeste (intet at matche på). tractors = allerede filtrerede kandidater.
ADPool.FIT_BAND = 1.15
ADPool.OVERSIZE_FACTOR = 2.5
function ADPool.bestFit(tractors, implement, role)
local fitting = {}
for _, tractor in ipairs(tractors or {}) do
if suits(tractor, implement, role) then table.insert(fitting, tractor) end
end
local needed = implement.neededHp
if needed == nil or needed <= 0 then return nearest(fitting, implement.x, implement.z) end
local sized, oversized, unknown = {}, {}, {}
for _, tractor in ipairs(fitting) do
if tractor.hp == nil or tractor.hp <= 0 then table.insert(unknown, tractor)
elseif tractor.hp > needed * ADPool.OVERSIZE_FACTOR then table.insert(oversized, tractor)
else table.insert(sized, tractor) end
end
local pool = #sized > 0 and sized or (#unknown > 0 and unknown or oversized)
if pool ~= unknown then
local smallest = math.huge
for _, tractor in ipairs(pool) do smallest = math.min(smallest, tractor.hp) end
local band = {}
for _, tractor in ipairs(pool) do
if tractor.hp <= smallest * ADPool.FIT_BAND then table.insert(band, tractor) end
end
pool = band
end
return nearest(pool, implement.x, implement.z)
end
function ADPool.shouldReturnHome(assignment)
return not assignment.manual
end
@@ -160,7 +192,7 @@ function ADPool.pairFor(role, fieldX, fieldZ, implements, tractors, blocked, acc
end)
local weakest = nil
for _, implement in ipairs(candidates) do
local tractor = nearest(free, implement.x, implement.z, function(t) return suits(t, implement, role) end)
local tractor = ADPool.bestFit(free, implement, role)
if tractor ~= nil then return {implement = implement, tractor = tractor} end
if weakest == nil or (implement.neededHp or 0) < (weakest.neededHp or 0) then weakest = implement end
end
@@ -174,9 +206,11 @@ function ADPool.pairAll(role, implements, tractors, blocked)
local used, result = {}, {}
for _, implement in ipairs(implements or {}) do
if hasRole(implement, role) and not blocked[implement.id] then
local tractor = nearest(tractors or {}, implement.x, implement.z, function(t)
return not used[t.id] and not blocked[t.id] and not t.offNetwork and suits(t, implement, role)
end)
local open = {}
for _, t in ipairs(tractors or {}) do
if not used[t.id] and not blocked[t.id] and not t.offNetwork then table.insert(open, t) end
end
local tractor = ADPool.bestFit(open, implement, role)
if tractor ~= nil then
used[tractor.id] = true
table.insert(result, {implement = implement, tractor = tractor})
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<modDesc descVersion="107">
<author>masterdraco</author>
<version>1.55.1.0</version>
<version>1.56.0.0</version>
<title>
<en>AD Smart Pickup</en>
</title>