fix(markarbejde): utoppede kartofler (forberedelige stadier) tæller som høstklare; klargøring på en mark med uhøstet afgrøde spoles tilbage til klar (F16) (v1.34.2.0)

This commit is contained in:
2026-09-27 09:09:08 +02:00
parent 307676004e
commit 5274925f2a
5 changed files with 46 additions and 2 deletions
+15
View File
@@ -31,6 +31,10 @@ ADFieldJobs.ACTIVE_PHASES = {driving = true, starting = true, waitingCourse = tr
-- Andel græs i mellemhøjde (høstbart, men halv ydelse) der får en afbrudt slåning til at vente. -- Andel græs i mellemhøjde (høstbart, men halv ydelse) der får en afbrudt slåning til at vente.
ADFieldJobs.REGROW_RATIO = 0.1 ADFieldJobs.REGROW_RATIO = 0.1
-- Trin efter høsten der ødelægger/ignorerer en stående afgrøde.
ADFieldJobs.PREP_STAGES = {strawCollecting = true, baling = true, baleCollecting = true, mulching = true, liming = true,
plowing = true, cultivating = true, sowing = true, rolling = true}
-- ---- ren beslutning ---- -- ---- ren beslutning ----
-- Er afgrøden taget (trin med afgrøde)? Slåning: under 50 % står. Høst: marken er bar eller under 50 %. -- Er afgrøden taget (trin med afgrøde)? Slåning: under 50 % står. Høst: marken er bar eller under 50 %.
@@ -65,6 +69,12 @@ function ADFieldJobs.decide(field, info, assignments, now, env)
return {action = "start"} return {action = "start"}
end end
end end
-- klargøring på en mark hvor afgrøden står uhøstet: tilbage til klar (in-game 27/9 F16: kartofler
-- blev regnet som høstet, og marken stod til kultivering med afgrøden i jorden)
if ADFieldJobs.PREP_STAGES[field.stage] and info ~= nil and info.kind == "harvest" and info.phase == "ready"
and (info.readyRatio or 0) >= ADFieldModel.READY_RATIO then
return {action = "rewind"}
end
if not ADFieldModel.isWorking(field) then if not ADFieldModel.isWorking(field) then
local care = ADFieldModel.careNeed(field, info) local care = ADFieldModel.careNeed(field, info)
if care == nil then return {action = "none"} end if care == nil then return {action = "none"} end
@@ -256,6 +266,11 @@ local function stepField(adEnv, info, env)
ADFieldJobs.setField(started) ADFieldJobs.setField(started)
ADFieldJobs.log(info.id, "starter (%s: %s)", tostring(info.kind), started.stage) ADFieldJobs.log(info.id, "starter (%s: %s)", tostring(info.kind), started.stage)
ADFieldJobs.save() ADFieldJobs.save()
elseif decision.action == "rewind" then
ADFieldJobs.setField(ADFieldModel.with(field, {stage = "ready", retryAt = 0, reason = false}))
ADFieldWork.windDownHelpers(adEnv, info.id, field.stage)
ADFieldJobs.log(info.id, "%s -> ready: afgrøden står stadig uhøstet (%.0f %% klar)", field.stage, (info.readyRatio or 0) * 100)
ADFieldJobs.save()
elseif decision.action == "care" then elseif decision.action == "care" then
ADFieldJobs.setField(ADFieldModel.startCare(field, decision.stage)) ADFieldJobs.setField(ADFieldModel.startCare(field, decision.stage))
ADFieldJobs.log(info.id, "pleje: %s", decision.stage) ADFieldJobs.log(info.id, "pleje: %s", decision.stage)
+16 -1
View File
@@ -50,6 +50,7 @@ end
function ADFields.growthPhase(state, fruit) function ADFields.growthPhase(state, fruit)
if state == nil or fruit == nil then return nil end if state == nil or fruit == nil then return nil end
if state == 0 then return "none" end if state == 0 then return "none" end
if ADFields.isPreparable(state, fruit) then return "ready" end
if fruit.cutState ~= nil and fruit.cutState ~= 0 and state == fruit.cutState then return "cut" end if fruit.cutState ~= nil and fruit.cutState ~= 0 and state == fruit.cutState then return "cut" end
if fruit.witheredState ~= nil and state == fruit.witheredState then return "withered" end if fruit.witheredState ~= nil and state == fruit.witheredState then return "withered" end
local minReady = fruit.minHarvestingGrowthState or fruit.minHarvestGrowthState local minReady = fruit.minHarvestingGrowthState or fruit.minHarvestGrowthState
@@ -71,6 +72,15 @@ function ADFields.primeState(fruit)
return minReady return minReady
end end
-- Kan stadiet "forberedes" (toppes)? Dakota-kartofler: "harvestReady" er kun forberedelig — først det
-- toppede stadie er høstklart, men skærebord med topper (Ropa rrXL9) tager begge i ét drag.
function ADFields.isPreparable(state, fruit)
if fruit == nil or type(state) ~= "number" or state <= 0 then return false end
local minPrep, maxPrep = fruit.minPreparingGrowthState, fruit.maxPreparingGrowthState
if type(minPrep) ~= "number" or minPrep <= 0 then return false end
return state >= minPrep and state <= (type(maxPrep) == "number" and maxPrep >= minPrep and maxPrep or minPrep)
end
-- Tæller punktets klar-pixels? Kun når stadiet (4. værdi fra getFruitArea) er fuldt udvokset. -- Tæller punktets klar-pixels? Kun når stadiet (4. værdi fra getFruitArea) er fuldt udvokset.
function ADFields.isPrime(growthState, prime) function ADFields.isPrime(growthState, prime)
if prime == nil or type(growthState) ~= "number" or growthState <= 0 then return true end if prime == nil or type(growthState) ~= "number" or growthState <= 0 then return true end
@@ -369,8 +379,9 @@ function ADFields.scanPerFruit(scan)
-- slåafgrøder: genvækst i mellemhøjde tæller ikke som klar (in-game 27/9: halvt slået F90 blev -- slåafgrøder: genvækst i mellemhøjde tæller ikke som klar (in-game 27/9: halvt slået F90 blev
-- klippet igen i mellemhøjde) -- klippet igen i mellemhøjde)
local prime = nil local prime = nil
local fruitDesc = fruitIndex ~= nil and g_fruitTypeManager:getFruitTypeByIndex(fruitIndex) or nil
if fruitIndex ~= nil and ADFields.getMowable()[fruitIndex] ~= nil then if fruitIndex ~= nil and ADFields.getMowable()[fruitIndex] ~= nil then
prime = ADFields.primeState(g_fruitTypeManager:getFruitTypeByIndex(fruitIndex)) prime = ADFields.primeState(fruitDesc)
end end
for _, point in ipairs(scan.points) do for _, point in ipairs(scan.points) do
push(scan, function() push(scan, function()
@@ -382,6 +393,10 @@ function ADFields.scanPerFruit(scan)
if not ADFields.isPrime(pointState, prime) then scan.immatureSum = scan.immatureSum + anyPixels end if not ADFields.isPrime(pointState, prime) then scan.immatureSum = scan.immatureSum + anyPixels end
end end
local okR, _, readyPixels = pcall(FSDensityMapUtil.getFruitArea, fruitIndex, x - 2, z - 2, x + 2, z, x, z + 2, false, false) local okR, _, readyPixels = pcall(FSDensityMapUtil.getFruitArea, fruitIndex, x - 2, z - 2, x + 2, z, x, z + 2, false, false)
-- utoppede kartofler tæller som klar (in-game 27/9 F16: klar-andel 0 -> sprang høsten over)
if okA and anyPixels and ADFields.isPreparable(pointState, fruitDesc) then
okR, readyPixels = true, math.max(readyPixels or 0, anyPixels)
end
if okR and readyPixels and ADFields.isPrime(okA and pointState or nil, prime) then if okR and readyPixels and ADFields.isPrime(okA and pointState or nil, prime) then
scan.readySum = scan.readySum + readyPixels scan.readySum = scan.readySum + readyPixels
end end
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?> <?xml version="1.0" encoding="utf-8" standalone="no"?>
<modDesc descVersion="107"> <modDesc descVersion="107">
<author>masterdraco</author> <author>masterdraco</author>
<version>1.34.1.0</version> <version>1.34.2.0</version>
<title> <title>
<en>AD Smart Pickup</en> <en>AD Smart Pickup</en>
</title> </title>
+6
View File
@@ -105,5 +105,11 @@ check("J13 genvækst -> vent", dRegrow.action, "wait"); check("J13 grund", dRegr
check("J13 genvækst men tur færdig -> slå hjørnet", J.decide(mowing, regrowing, {{phase = "finished"}}, 0).action, "dispatch") check("J13 genvækst men tur færdig -> slå hjørnet", J.decide(mowing, regrowing, {{phase = "finished"}}, 0).action, "dispatch")
check("J13 halvt slået uden genvækst -> slå resten", J.decide(mowing, {id = 90, markerId = 9, mowable = true, readyRatio = 0.6, immatureRatio = 0}, {}, 0).action, "dispatch") check("J13 halvt slået uden genvækst -> slå resten", J.decide(mowing, {id = 90, markerId = 9, mowable = true, readyRatio = 0.6, immatureRatio = 0}, {}, 0).action, "dispatch")
-- J14: kultivering på en mark med uhøstede kartofler (in-game 27/9 F16) -> tilbage til klar; rest efter høst -> ikke
local cultivatingField = M.with(auto, {stage = "cultivating", kind = "harvest"})
check("J14 uhøstet -> spol tilbage", J.decide(cultivatingField, {id = 16, markerId = 9, kind = "harvest", phase = "ready", readyRatio = 1}, {}, 0).action, "rewind")
check("J14 høstrest 30 % -> kultiver", J.decide(cultivatingField, {id = 16, markerId = 9, kind = "harvest", phase = "ready", readyRatio = 0.3}, {}, 0).action ~= "rewind", true)
check("J14 stub -> kultiver", J.decide(cultivatingField, {id = 16, markerId = 9, kind = "bare", phase = "cut", readyRatio = 0}, {}, 0).action ~= "rewind", true)
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)
+8
View File
@@ -70,5 +70,13 @@ check("F8 fuld højde tæller", F.isPrime(5, 4), true)
check("F8 ukendt stadie tæller", F.isPrime(nil, 4), true) check("F8 ukendt stadie tæller", F.isPrime(nil, 4), true)
check("F8 ingen krav", F.isPrime(3, nil), true) check("F8 ingen krav", F.isPrime(3, nil), true)
-- F9: kartofler (Dakota): 6 = klar men kun forberedelig, 10 = toppet (høstklar)
local potato = {minHarvestingGrowthState = 10, maxHarvestingGrowthState = 10, minPreparingGrowthState = 6, maxPreparingGrowthState = 6, witheredState = 7, cutState = 8}
check("F9 utoppet er forberedelig", F.isPreparable(6, potato), true)
check("F9 voksende ikke", F.isPreparable(5, potato), false)
check("F9 fase klar", F.growthPhase(6, potato), "ready")
check("F9 toppet klar", F.growthPhase(10, potato), "ready")
check("F9 ingen forberedelse", F.isPreparable(6, {minPreparingGrowthState = -1}), 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)