fix(marker): højst 2 slå-ture pr. mark (CP-hjørner gav uendelig genudsendelse); ryd færdige sæt ved Stop

Review-fund (MEDIUM): ADFieldJobs.finished voksede for marker der blev sendt ud igen uden at gå videre.
This commit is contained in:
2026-09-25 21:59:43 +02:00
parent 6ffd78896a
commit 4208b6e6c3
2 changed files with 20 additions and 6 deletions
+15 -6
View File
@@ -10,6 +10,8 @@ ADFieldJobs.TICK_MS = 1000
ADFieldJobs.ARRIVE_DISTANCE = 30 ADFieldJobs.ARRIVE_DISTANCE = 30
ADFieldJobs.IDLE_CONFIRM_MS = 5000 ADFieldJobs.IDLE_CONFIRM_MS = 5000
ADFieldJobs.START_TIMEOUT_MS = 60000 ADFieldJobs.START_TIMEOUT_MS = 60000
-- Courseplay kan efterlade hjørner på skæve marker: efter så mange færdige slå-ture går marken videre.
ADFieldJobs.MAX_MOW_PASSES = 2
ADFieldJobs.state = {fields = {}, fleet = {}, assignments = {}} ADFieldJobs.state = {fields = {}, fleet = {}, assignments = {}}
ADFieldJobs.timer = 0 ADFieldJobs.timer = 0
ADFieldJobs.now = 0 ADFieldJobs.now = 0
@@ -33,7 +35,7 @@ function ADFieldJobs.decide(field, info, assignments, now)
end end
if active == 0 and finished > 0 then if active == 0 and finished > 0 then
local stillStanding = field.stage == "mowing" and info ~= nil and (info.readyRatio or 0) >= ADFieldModel.CUT_RATIO local stillStanding = field.stage == "mowing" and info ~= nil and (info.readyRatio or 0) >= ADFieldModel.CUT_RATIO
if not stillStanding then return {action = "advance"} end if not stillStanding or finished >= ADFieldJobs.MAX_MOW_PASSES then return {action = "advance"} end
end end
if info == nil or info.markerId == nil then return {action = "wait"} end if info == nil or info.markerId == nil then return {action = "wait"} end
local role = ADFieldModel.wantsRig(field, active, now) local role = ADFieldModel.wantsRig(field, active, now)
@@ -205,6 +207,16 @@ end
-- ---- udsendelse og opfølgning ---- -- ---- udsendelse og opfølgning ----
-- Færdige sæt for en mark glemmes, når marken går videre eller stoppes. Listen er begrænset: en mark
-- der sendes ud igen uden at gå videre (hjørner), går videre efter MAX_MOW_PASSES færdige ture.
local function forgetFinished(fieldId)
local remaining = {}
for _, done in ipairs(ADFieldJobs.finished or {}) do
if done.fieldId ~= fieldId then table.insert(remaining, done) end
end
ADFieldJobs.finished = remaining
end
local function release(assignment, phase) local function release(assignment, phase)
assignment.phase = phase or "released" assignment.phase = phase or "released"
ADFieldJobs.state.assignments[assignment.vehicleId] = nil ADFieldJobs.state.assignments[assignment.vehicleId] = nil
@@ -338,6 +350,7 @@ function ADFieldJobs.stopField(adEnv, id)
pcall(function() if assignment.vehicle.stopCurrentAIJob ~= nil and ADCpBridge.isWorking(assignment.vehicle) then assignment.vehicle:stopCurrentAIJob(AIMessageSuccessStoppedByUser.new()) end end) pcall(function() if assignment.vehicle.stopCurrentAIJob ~= nil and ADCpBridge.isWorking(assignment.vehicle) then assignment.vehicle:stopCurrentAIJob(AIMessageSuccessStoppedByUser.new()) end end)
release(assignment) release(assignment)
end end
forgetFinished(id)
setField(ADFieldModel.stop(ADFieldJobs.getField(id))) setField(ADFieldModel.stop(ADFieldJobs.getField(id)))
ADFieldJobs.save() ADFieldJobs.save()
log(id, "stoppet fra menuen") log(id, "stoppet fra menuen")
@@ -364,11 +377,7 @@ local function stepField(adEnv, info)
elseif decision.action == "advance" then elseif decision.action == "advance" then
local nextField = ADFieldModel.advance(field) local nextField = ADFieldModel.advance(field)
setField(nextField) setField(nextField)
local remaining = {} forgetFinished(info.id)
for _, done in ipairs(ADFieldJobs.finished or {}) do
if done.fieldId ~= info.id then table.insert(remaining, done) end
end
ADFieldJobs.finished = remaining
log(info.id, "%s -> %s", field.stage, nextField.stage) log(info.id, "%s -> %s", field.stage, nextField.stage)
ADFieldJobs.save() ADFieldJobs.save()
elseif decision.action == "dispatch" then elseif decision.action == "dispatch" then
+5
View File
@@ -33,5 +33,10 @@ local collecting = M.advance(mowing)
check("J5 genoptag opsamling", J.decide(collecting, info, {}, 0).role, "collector") check("J5 genoptag opsamling", J.decide(collecting, info, {}, 0).role, "collector")
check("J5 to vogne maks", J.decide(collecting, info, {{phase = "working"}, {phase = "driving"}}, 0).action, "none") check("J5 to vogne maks", J.decide(collecting, info, {{phase = "working"}, {phase = "driving"}}, 0).action, "none")
-- J6: Courseplay efterlader et hjørne -> efter 2 færdige slå-ture går marken videre alligevel
local standing = {id = 109, markerId = 5, mowable = true, readyRatio = 0.8}
check("J6 én tur -> slå igen", J.decide(mowing, standing, {{phase = "finished"}}, 0).action, "dispatch")
check("J6 to ture -> videre", J.decide(mowing, standing, {{phase = "finished"}, {phase = "finished"}}, 0).action, "advance")
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)