fix(pulje): review — puljeredskab sættes altid af (også påfyldte sæt), kun rolleløse traktorer henter, traktor uden vejnet springes over og får skylden ved stoppedAway, påfyldning efter koblingen, faste maskiner respekteres
This commit is contained in:
@@ -461,7 +461,13 @@ function ADFieldWork.dispatch(adEnv, field, info, decision)
|
|||||||
end
|
end
|
||||||
if rigs == nil then
|
if rigs == nil then
|
||||||
-- ingen færdig kombination: en ledig solo-traktor henter et puljeredskab (kun hovedopgaver, ikke tømmevogne)
|
-- ingen færdig kombination: en ledig solo-traktor henter et puljeredskab (kun hovedopgaver, ikke tømmevogne)
|
||||||
if not decision.helper and (decision.count or 1) == 1 and ADPool ~= nil
|
-- marken har egne faste maskiner til rollen: den venter på dem (som uden puljen)
|
||||||
|
local ownIds, hasOwnForRole = {}, false
|
||||||
|
for _, id in ipairs(field.plan ~= nil and field.plan.rigIds or {}) do ownIds[id] = true end
|
||||||
|
for _, candidate in ipairs(candidates) do
|
||||||
|
if ownIds[candidate.id] and (candidate.role == role or (candidate.roles ~= nil and candidate.roles[role])) then hasOwnForRole = true end
|
||||||
|
end
|
||||||
|
if ADPool ~= nil and ADPool.mayUsePool(decision, hasOwnForRole)
|
||||||
and (why == "noRig" or why == "allBusy" or why == "cannotDo") then
|
and (why == "noRig" or why == "allBusy" or why == "cannotDo") then
|
||||||
local pooled, poolWhy, poolArgs = ADFieldWork.dispatchPool(adEnv, field, info, role, roleAccept)
|
local pooled, poolWhy, poolArgs = ADFieldWork.dispatchPool(adEnv, field, info, role, roleAccept)
|
||||||
if pooled then return end
|
if pooled then return end
|
||||||
@@ -913,7 +919,7 @@ local function finishAssignment(adEnv, assignment)
|
|||||||
-- manuel transport: ALDRIG ud på vejen med AutoDrive (skærebordet sidder på) — spilleren henter den
|
-- manuel transport: ALDRIG ud på vejen med AutoDrive (skærebordet sidder på) — spilleren henter den
|
||||||
-- puljeredskab bag traktoren: sæt det af på sin parkering, traktoren hjem (afhænger kun af hvad der hænger
|
-- puljeredskab bag traktoren: sæt det af på sin parkering, traktoren hjem (afhænger kun af hvad der hænger
|
||||||
-- bag, så det virker også efter genindlæsning); ellers som før
|
-- bag, så det virker også efter genindlæsning); ellers som før
|
||||||
local pooled = not assignment.adHandlesEnd and not assignment.manual and ADHitch ~= nil
|
local pooled = ADPool ~= nil and ADPool.shouldReturnHome(assignment) and ADHitch ~= nil
|
||||||
and ADHitch.returnHome(adEnv, vehicle, function(_, ok, detail)
|
and ADHitch.returnHome(adEnv, vehicle, function(_, ok, detail)
|
||||||
if not ok then log(assignment.fieldId, "'%s' kom ikke hjem fra puljen: %s", ADRuns.vehicleLabel(vehicle), tostring(detail)) end
|
if not ok then log(assignment.fieldId, "'%s' kom ikke hjem fra puljen: %s", ADRuns.vehicleLabel(vehicle), tostring(detail)) end
|
||||||
end)
|
end)
|
||||||
@@ -1166,8 +1172,9 @@ function ADFieldWork.follow(adEnv, assignment)
|
|||||||
if not hitch.done then return end
|
if not hitch.done then return end
|
||||||
ADPool.release(assignment)
|
ADPool.release(assignment)
|
||||||
if not hitch.ok then
|
if not hitch.ok then
|
||||||
-- koblingen fejlede: redskabet i karantæne, traktoren hjem, marken prøver igen
|
-- koblingen fejlede: den skyldige i karantæne (kom traktoren ikke frem, er det traktoren), hjem, prøv igen
|
||||||
ADPool.quarantine(assignment.pool.implementId, now())
|
local blamed = ADPool.failureBlames(hitch.detail) == "tractor" and assignment.vehicleId or assignment.pool.implementId
|
||||||
|
ADPool.quarantine(blamed, now())
|
||||||
ADFieldWork.release(assignment)
|
ADFieldWork.release(assignment)
|
||||||
note(assignment.fieldId, {retryAt = now() + ADFieldWork.NO_RIG_RETRY_MS,
|
note(assignment.fieldId, {retryAt = now() + ADFieldWork.NO_RIG_RETRY_MS,
|
||||||
reason = {text = string.format("kunne ikke koble '%s' på (%s) — prøver et andet om lidt",
|
reason = {text = string.format("kunne ikke koble '%s' på (%s) — prøver et andet om lidt",
|
||||||
@@ -1185,10 +1192,25 @@ function ADFieldWork.follow(adEnv, assignment)
|
|||||||
ADHitch.returnHome(adEnv, vehicle)
|
ADHitch.returnHome(adEnv, vehicle)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
-- som almindelig udsendelse: tom såmaskine/sprøjte fyldes op på vejen, uden påfyldning køres den hjem igen
|
||||||
|
local refill = refillPlan(adEnv, assignment.fieldId, vehicle, assignment.role, info.x, info.z)
|
||||||
|
local nextDrive = ADPool.nextDrive(refill)
|
||||||
|
if nextDrive == "empty" then
|
||||||
|
ADFieldWork.release(assignment)
|
||||||
|
ADHitch.returnHome(adEnv, vehicle)
|
||||||
|
fail(assignment.fieldId, string.format("'%s' er tom for %s og der er ingen påfyldning med AutoDrive-markør — fyld den op",
|
||||||
|
tostring(assignment.pool.implementName), fillTypeName(refill.fillType)))
|
||||||
|
return
|
||||||
|
end
|
||||||
assignment.width, assignment.phase, assignment.since = width, "driving", now()
|
assignment.width, assignment.phase, assignment.since = width, "driving", now()
|
||||||
assignment.startX, assignment.startZ = vehiclePosition(vehicle)
|
assignment.startX, assignment.startZ = vehiclePosition(vehicle)
|
||||||
|
if nextDrive == "load" then
|
||||||
|
startAd(adEnv, vehicle, adEnv.AutoDrive.MODE_LOAD, info.markerId, refill.refillId, refill.fillType)
|
||||||
|
assignment.drive = {mode = adEnv.AutoDrive.MODE_LOAD, first = info.markerId, second = refill.refillId, fillType = refill.fillType}
|
||||||
|
else
|
||||||
startAd(adEnv, vehicle, adEnv.AutoDrive.MODE_DRIVETO, info.markerId, nil)
|
startAd(adEnv, vehicle, adEnv.AutoDrive.MODE_DRIVETO, info.markerId, nil)
|
||||||
assignment.drive = {mode = adEnv.AutoDrive.MODE_DRIVETO, first = info.markerId}
|
assignment.drive = {mode = adEnv.AutoDrive.MODE_DRIVETO, first = info.markerId}
|
||||||
|
end
|
||||||
note(assignment.fieldId, {reason = false})
|
note(assignment.fieldId, {reason = false})
|
||||||
log(assignment.fieldId, "%s '%s' har '%s' på — kører til %s (%.1f m)", assignment.role, ADRuns.vehicleLabel(vehicle),
|
log(assignment.fieldId, "%s '%s' har '%s' på — kører til %s (%.1f m)", assignment.role, ADRuns.vehicleLabel(vehicle),
|
||||||
tostring(assignment.pool.implementName), tostring(info.markerName), width or 0)
|
tostring(assignment.pool.implementName), tostring(info.markerName), width or 0)
|
||||||
|
|||||||
@@ -65,13 +65,43 @@ local function nearest(items, x, z, keep)
|
|||||||
return best
|
return best
|
||||||
end
|
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.
|
||||||
|
function ADPool.shouldReturnHome(assignment)
|
||||||
|
return not assignment.manual
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Kun maskiner uden egen arbejdsrolle (almindelige traktorer) henter puljeredskaber — ikke mejetærskere,
|
||||||
|
-- selvkørende sprøjter o.l., selv om de har koblingspunkter.
|
||||||
|
function ADPool.canPull(role)
|
||||||
|
return role == nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Hvem fik koblingen til at fejle? Kom traktoren ikke frem, er det traktoren (ingen AD-rute), ellers redskabet.
|
||||||
|
function ADPool.failureBlames(reason)
|
||||||
|
if reason == "stoppedAway" then return "tractor" end
|
||||||
|
return "implement"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Efter koblingen: refill = markarbejdets påfyldningsplan (nil = intet at fylde).
|
||||||
|
function ADPool.nextDrive(refill)
|
||||||
|
if refill == nil or not refill.empty then return "drive" end
|
||||||
|
if refill.refillId ~= nil then return "load" end
|
||||||
|
return "empty"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Puljen bruges kun til hovedopgaver med ét sæt, og ikke når marken har egne faste maskiner til rollen.
|
||||||
|
function ADPool.mayUsePool(decision, hasOwnForRole)
|
||||||
|
return not decision.helper and (decision.count or 1) == 1 and not hasOwnForRole
|
||||||
|
end
|
||||||
|
|
||||||
-- Redskab med rollen nærmest marken, derefter nærmeste ledige traktor med nok hk til redskabet.
|
-- Redskab med rollen nærmest marken, derefter nærmeste ledige traktor med nok hk til redskabet.
|
||||||
-- blocked = {[id] = true} (reserverede og redskaber i karantæne). accept (valgfri): implement -> bool.
|
-- blocked = {[id] = true} (reserverede og redskaber i karantæne). accept (valgfri): implement -> bool.
|
||||||
function ADPool.pairFor(role, fieldX, fieldZ, implements, tractors, blocked, accept)
|
function ADPool.pairFor(role, fieldX, fieldZ, implements, tractors, blocked, accept)
|
||||||
blocked = blocked or {}
|
blocked = blocked or {}
|
||||||
local free = {}
|
local free = {}
|
||||||
for _, tractor in ipairs(tractors or {}) do
|
for _, tractor in ipairs(tractors or {}) do
|
||||||
if not blocked[tractor.id] then table.insert(free, tractor) end
|
if not blocked[tractor.id] and not tractor.offNetwork then table.insert(free, tractor) end
|
||||||
end
|
end
|
||||||
local candidates = {}
|
local candidates = {}
|
||||||
for _, implement in ipairs(implements or {}) do
|
for _, implement in ipairs(implements or {}) do
|
||||||
@@ -214,10 +244,14 @@ function ADPool.collect(adEnv, isBusy)
|
|||||||
local controlled = vehicle.getIsControlled ~= nil and vehicle:getIsControlled()
|
local controlled = vehicle.getIsControlled ~= nil and vehicle:getIsControlled()
|
||||||
if id ~= nil and park ~= nil and vehicle.spec_attacherJoints ~= nil and #ADHitch.rearImplementsOf(vehicle) == 0
|
if id ~= nil and park ~= nil and vehicle.spec_attacherJoints ~= nil and #ADHitch.rearImplementsOf(vehicle) == 0
|
||||||
and ADRunsController.getRunForVehicle(vehicle) == nil and not controlled and not isBusy(vehicle)
|
and ADRunsController.getRunForVehicle(vehicle) == nil and not controlled and not isBusy(vehicle)
|
||||||
and not ADPool.isReturning(vehicle) and ADFieldFleet.isEnabled(state.fleetMode, state.fleet, id) then
|
and not ADPool.isReturning(vehicle) and ADFieldFleet.isEnabled(state.fleetMode, state.fleet, id)
|
||||||
|
and ADPool.canPull(ADFieldFleet.roleFromSpecs(ADCpBridge.getSpecs(vehicle))) then
|
||||||
local x, z = positionOf(vehicle)
|
local x, z = positionOf(vehicle)
|
||||||
|
-- uden for AD-vejnettet: den kan ikke køre ud efter redskabet (ville sende redskaber i karantæne)
|
||||||
|
local networkDistance = ADFieldWork.distanceToNetwork(adEnv, x, z)
|
||||||
table.insert(tractors, {id = id, vehicle = vehicle, name = ADRuns.vehicleLabel(vehicle), x = x, z = z,
|
table.insert(tractors, {id = id, vehicle = vehicle, name = ADRuns.vehicleLabel(vehicle), x = x, z = z,
|
||||||
hp = tractorHpOf(vehicle), parkId = park.id})
|
hp = tractorHpOf(vehicle), parkId = park.id,
|
||||||
|
offNetwork = networkDistance ~= nil and networkDistance > ADFieldWork.MAX_OFF_NETWORK})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return implements, tractors
|
return implements, tractors
|
||||||
|
|||||||
@@ -79,5 +79,28 @@ P.setReturning(tractorObject, true)
|
|||||||
check("hjemtur: markeret", P.isReturning(tractorObject), true)
|
check("hjemtur: markeret", P.isReturning(tractorObject), true)
|
||||||
P.setReturning(tractorObject, false)
|
P.setReturning(tractorObject, false)
|
||||||
check("hjemtur: hjemme", P.isReturning(tractorObject), false)
|
check("hjemtur: hjemme", P.isReturning(tractorObject), false)
|
||||||
|
-- review-rettelser
|
||||||
|
-- C1: hjemtur også når AD selv ville parkere (påfyldte sæt); aldrig ved manuel transport
|
||||||
|
check("C1: hjem trods adHandlesEnd", P.shouldReturnHome({adHandlesEnd = true}), true)
|
||||||
|
check("C1: ikke ved manuel", P.shouldReturnHome({manual = true}), false)
|
||||||
|
-- I1: kun maskiner uden egen arbejdsrolle kan trække et puljeredskab
|
||||||
|
check("I1: traktor uden rolle", P.canPull(nil), true)
|
||||||
|
check("I1: mejetærsker", P.canPull("harvester"), false)
|
||||||
|
check("I1: selvkørende sprøjte", P.canPull("fertilizer"), false)
|
||||||
|
-- I2: traktor uden AD-vejnet springes over; fejl uden fremdrift skyldes traktoren
|
||||||
|
local offNet = P.pairFor("plow", 0, 0, {implements[2]}, {{id = "far", x = 100, z = 0, offNetwork = true}, {id = "ok", x = 400, z = 0, hp = 300}}, {})
|
||||||
|
check("I2: traktor uden for vejnettet springes over", offNet.tractor.id, "ok")
|
||||||
|
check("I2: stoppedAway -> traktoren", P.failureBlames("stoppedAway"), "tractor")
|
||||||
|
check("I2: noAttachable -> redskabet", P.failureBlames("noAttachable"), "implement")
|
||||||
|
-- I3: efter koblingen — tom uden påfyldning = fejl, tom med påfyldning = fyld op, ellers kør
|
||||||
|
check("I3: ingen påfyldningsbehov", P.nextDrive(nil), "drive")
|
||||||
|
check("I3: fyldt", P.nextDrive({empty = false}), "drive")
|
||||||
|
check("I3: tom med påfyldning", P.nextDrive({empty = true, refillId = 7}), "load")
|
||||||
|
check("I3: tom uden påfyldning", P.nextDrive({empty = true}), "empty")
|
||||||
|
-- I4: puljen kun til hovedopgaver med ét sæt, og ikke når marken har egne faste maskiner til rollen
|
||||||
|
check("I4: almindelig", P.mayUsePool({count = 1}, false), true)
|
||||||
|
check("I4: tømmevogn", P.mayUsePool({count = 1, helper = true}, false), false)
|
||||||
|
check("I4: multi-tool", P.mayUsePool({count = 2}, false), false)
|
||||||
|
check("I4: marken har faste", P.mayUsePool({count = 1}, true), false)
|
||||||
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
||||||
os.exit(failures == 0 and 0 or 1)
|
os.exit(failures == 0 and 0 or 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user