diff --git a/FS25_ADSmartPickup/adCpBridge.lua b/FS25_ADSmartPickup/adCpBridge.lua index 4d12418..08623a2 100644 --- a/FS25_ADSmartPickup/adCpBridge.lua +++ b/FS25_ADSmartPickup/adCpBridge.lua @@ -5,7 +5,7 @@ ADCpBridge = {} -ADCpBridge.SPECS = {"spec_mower", "spec_tedder", "spec_windrower", "spec_forageWagon", "spec_combine", +ADCpBridge.SPECS = {"spec_mower", "spec_tedder", "spec_windrower", "spec_forageWagon", "spec_combine", "spec_baler", "spec_sowingMachine", "spec_cultivator", "spec_plow", "spec_roller", "spec_weeder", "spec_mulcher"} -- Sprøjtens/sprederens fyld -> rolle (tom sprøjte har ingen rolle; den kan ikke sendes ud). @@ -86,6 +86,10 @@ function ADCpBridge.getSpecs(vehicle) local ok, can = pcall(vehicle.getCanStartCpCombineUnloader, vehicle) specs.canUnload = ok and can == true or nil end + if vehicle.getCanStartCpBaleFinder ~= nil then + local ok, can = pcall(vehicle.getCanStartCpBaleFinder, vehicle) + specs.canBaleCollect = ok and can == true or nil + end return specs end @@ -189,6 +193,58 @@ function ADCpBridge.getRefillLevel(vehicle, fillType) return total end +-- Halmskår bag mejetærskeren (Courseplays køretøjsindstilling strawSwath: 1 = fra/hakkes, 2 = til). +function ADCpBridge.setStrawSwath(vehicle, on) + return (pcall(function() vehicle:getCpSettings().strawSwath:setValue(on and 2 or 1) end)) +end + +-- Ballesamler: Courseplays BALE_FINDER_CP (ballevogn eller Universal Autoload) samler markens baller. +function ADCpBridge.startBaleFinder(vehicle, fieldX, fieldZ, onDone) + if AIJobType == nil or AIJobType.BALE_FINDER_CP == nil then + return nil, "Courseplay (BALE_FINDER_CP) findes ikke" + end + local farmId = vehicle:getOwnerFarmId() + local job = g_currentMission.aiJobTypeManager:createJob(AIJobType.BALE_FINDER_CP) + if job == nil then return nil, "kunne ikke oprette ballesamler-job" end + pcall(function() job:applyCurrentState(vehicle, g_currentMission, farmId, false, false) end) + local params = job.cpJobParameters + if params ~= nil and params.fieldPosition ~= nil then pcall(function() params.fieldPosition:setPosition(fieldX, fieldZ) end) end + if params ~= nil and params.startPosition ~= nil then + local vx, _, vz = getWorldTranslation(vehicle.rootNode) + pcall(function() params.startPosition:setPosition(vx, vz) end) + end + pcall(function() job:setValues() end) + local handle = {cancelled = false, fired = false, finished = false} + local function finish(success, reason) + if handle.finished then return end + handle.finished = true + if not handle.cancelled then onDone(success, reason) end + end + local function startJob() + if handle.cancelled then return end + local valid, err = job:validate(farmId) + if not valid then return finish(false, "Courseplay: " .. tostring(err)) end + g_currentMission.aiSystem:startJob(job, farmId) + finish(true) + end + handle.onBoundary = function(_, success, message) + if handle.fired then return end + handle.fired = true + if not success then return finish(false, "Courseplay fandt ikke markgrænsen: " .. tostring(message)) end + startJob() + end + if job.registerFieldBoundaryDetectionCallback ~= nil then + job:registerFieldBoundaryDetectionCallback(handle, handle.onBoundary) + end + local isValid, isRunning, message = job:detectFieldBoundary() + if isValid and not isRunning then + startJob() + elseif not isRunning then + return nil, "Courseplay: " .. tostring(message) + end + return handle +end + -- Stop køretøjets AI-job (Courseplay/hjælper). function ADCpBridge.stop(vehicle) pcall(function() diff --git a/FS25_ADSmartPickup/adFieldFleet.lua b/FS25_ADSmartPickup/adFieldFleet.lua index 90ef464..2f4e360 100644 --- a/FS25_ADSmartPickup/adFieldFleet.lua +++ b/FS25_ADSmartPickup/adFieldFleet.lua @@ -8,6 +8,7 @@ ADFieldFleet = {} -- plov, ikke aflæsningsvogn). sprayRole kommer fra sprøjtens/sprederens fyld (gødning/kalk/ukrudt). ADFieldFleet.ROLE_SPECS = { {role = "harvester", spec = "spec_combine"}, + {role = "baler", spec = "spec_baler"}, {role = "collector", spec = "spec_forageWagon"}, {role = "rake", spec = "spec_windrower"}, {role = "tedder", spec = "spec_tedder"}, @@ -19,6 +20,7 @@ ADFieldFleet.ROLE_SPECS = { {role = "mulcher", spec = "spec_mulcher"}, {role = "cultivator", spec = "spec_cultivator"}, {role = "plow", spec = "spec_plow"}, + {role = "baleCollector", spec = "canBaleCollect"}, {role = "unloader", spec = "canUnload"}, } diff --git a/FS25_ADSmartPickup/adFieldModel.lua b/FS25_ADSmartPickup/adFieldModel.lua index 2db8be7..f40666d 100644 --- a/FS25_ADSmartPickup/adFieldModel.lua +++ b/FS25_ADSmartPickup/adFieldModel.lua @@ -28,7 +28,7 @@ ADFieldModel.ROLES = { mowing = "mower", tedding = "tedder", raking = "rake", collecting = "collector", harvesting = "harvester", mulching = "mulcher", liming = "limer", plowing = "plow", cultivating = "cultivator", sowing = "seeder", rolling = "roller", weeding = "weeder", - fertilizing = "fertilizer", + fertilizing = "fertilizer", strawCollecting = "collector", baling = "baler", baleCollecting = "baleCollector", } ADFieldModel.HELPERS = {harvesting = "unloader"} ADFieldModel.CARE_STAGES = {fertilizing = true, weeding = true, careLiming = true} @@ -42,8 +42,11 @@ KNOWN_STAGES.careLiming = true local DEFAULT_PLAN = { mode = "manual", product = "auto", rake = false, rigs = 1, unloaders = 1, mulch = false, lime = true, soil = "auto", sow = false, sowFruit = "", roll = false, - fertilize = true, weed = true, targetFruit = "", prepAfterMow = false, + fertilize = true, weed = true, targetFruit = "", prepAfterMow = false, straw = "chop", } +local STRAW_VALUES = {chop = true, collect = true, bale = true} +-- halm-trin efter høst (mejetærskeren lægger skår når halmen skal bruges) +local STRAW_STAGES = {collect = {"strawCollecting"}, bale = {"baling", "baleCollecting"}} local SOIL_VALUES = {auto = true, cultivate = true, plow = true, none = true} local PRODUCTS = {auto = true, silage = true, hay = true, harvest = true} @@ -116,6 +119,7 @@ function ADFieldModel.workStages(plan, kind, needs) local product = ADFieldModel.product(plan, kind) if product == "harvest" then local stages = {"harvesting"} + for _, stage in ipairs(STRAW_STAGES[plan.straw or "chop"] or {}) do table.insert(stages, stage) end for _, stage in ipairs(ADFieldModel.prepStages(plan, needs)) do table.insert(stages, stage) end return stages end @@ -168,9 +172,10 @@ function ADFieldModel.shouldStartBare(field, kind, plantableNow) return plantableNow == true end --- Krævet bredde for et sæt: kun læssevognen uden riv skal dække slåmaskinens baner. +-- Krævet bredde for et sæt: kun læssevognen uden riv skal dække slåmaskinens baner (halmskår ligger i +-- høsterens spor — der er breddekravet ligegyldigt). function ADFieldModel.requiredWidth(field, role) - if role == "collector" and not field.plan.rake then + if role == "collector" and not field.plan.rake and field.stage ~= "strawCollecting" then return field.mowWidth end return nil @@ -178,6 +183,8 @@ end -- Hvilket tidligere kursus sættet skal køre: læssevognen følger skårene; de andre laver deres eget. function ADFieldModel.courseSource(field, role) + -- halm: læssevogn og presser kører høsterens kursus (skåret ligger i mejetærskerens spor) + if field.stage == "strawCollecting" or role == "baler" then return "harvester" end if role ~= "collector" then return nil end return field.plan.rake and "rake" or "mower" end @@ -247,6 +254,7 @@ local function freshCycle(copy) copy.mowWidth = nil copy.mowVehicleId = nil copy.rakeVehicleId = nil + copy.harvestVehicleId = nil copy.windrowOffset = nil copy.careRuns = {} end @@ -276,7 +284,7 @@ function ADFieldModel.advance(field, needs) local stages = ADFieldModel.workStages(field.plan, field.kind, needs) copy.stage = "done" local passed = false - local order = {"mowing", "tedding", "raking", "collecting", "harvesting", "mulching", "liming", "plowing", "cultivating", "sowing", "rolling"} + local order = {"mowing", "tedding", "raking", "collecting", "harvesting", "strawCollecting", "baling", "baleCollecting", "mulching", "liming", "plowing", "cultivating", "sowing", "rolling"} local rank = {} for index, stage in ipairs(order) do rank[stage] = index end for _, stage in ipairs(stages) do @@ -303,7 +311,7 @@ end -- Vejrfølsomme trin: afgrøde og skår skal være tørre (høst, slåning, vending, rivning, hø-opsamling). -- Jordbehandling, såning, pleje og ensilage-opsamling kan køre i regn. -local WEATHER_STAGES = {harvesting = true, mowing = true, tedding = true, raking = true} +local WEATHER_STAGES = {harvesting = true, mowing = true, tedding = true, raking = true, strawCollecting = true, baling = true} function ADFieldModel.isWeatherSensitive(stage, plan, kind) if WEATHER_STAGES[stage] then return true end return stage == "collecting" and ADFieldModel.product(plan, kind or "mowable") == "hay" @@ -423,11 +431,12 @@ function ADFieldModel.toRecord(field) rigs = plan.rigs, unloaders = plan.unloaders, mulch = flag(plan.mulch), lime = flag(plan.lime), soil = plan.soil, sow = flag(plan.sow), sowFruit = plan.sowFruit or "", roll = flag(plan.roll), fertilize = flag(plan.fertilize), weed = flag(plan.weed), - targetFruit = plan.targetFruit or "", prepAfterMow = flag(plan.prepAfterMow), + targetFruit = plan.targetFruit or "", prepAfterMow = flag(plan.prepAfterMow), straw = plan.straw or "chop", kind = field.kind or "", lastFruit = field.lastFruit or "", care = table.concat(care, " "), mowWidth = field.mowWidth or 0, mowVehicle = field.mowVehicleId or "", rakeVehicle = field.rakeVehicleId or "", + harvestVehicle = field.harvestVehicleId or "", windrowOffset = field.windrowOffset ~= nil and string.format("%.2f", field.windrowOffset) or "", } end @@ -462,12 +471,14 @@ function ADFieldModel.fromRecord(record) plan.weed = readFlag(record.weed, true) plan.targetFruit = record.targetFruit or "" plan.prepAfterMow = readFlag(record.prepAfterMow, false) + plan.straw = STRAW_VALUES[record.straw] and record.straw or "chop" field.kind = readText(record.kind) field.lastFruit = readText(record.lastFruit) for stage, runs in string.gmatch(record.care or "", "(%w+)=(%d+)") do field.careRuns[stage] = tonumber(runs) end field.mowWidth = (record.mowWidth or 0) > 0 and record.mowWidth or nil field.mowVehicleId = readText(record.mowVehicle) field.rakeVehicleId = readText(record.rakeVehicle) + field.harvestVehicleId = readText(record.harvestVehicle) field.windrowOffset = tonumber(record.windrowOffset) return field end diff --git a/FS25_ADSmartPickup/adFieldStorage.lua b/FS25_ADSmartPickup/adFieldStorage.lua index 4b4c744..9d7f2cd 100644 --- a/FS25_ADSmartPickup/adFieldStorage.lua +++ b/FS25_ADSmartPickup/adFieldStorage.lua @@ -11,8 +11,8 @@ ADFieldStorage.FIELD_TYPES = { id = "Int", stage = "String", mode = "String", product = "String", rake = "Int", store = "String", rigs = "Int", unloaders = "Int", mulch = "Int", lime = "Int", soil = "String", sow = "Int", sowFruit = "String", roll = "Int", fertilize = "Int", weed = "Int", - kind = "String", lastFruit = "String", care = "String", targetFruit = "String", prepAfterMow = "Int", - mowWidth = "Float", mowVehicle = "String", rakeVehicle = "String", windrowOffset = "String", + kind = "String", lastFruit = "String", care = "String", targetFruit = "String", prepAfterMow = "Int", straw = "String", + mowWidth = "Float", mowVehicle = "String", rakeVehicle = "String", harvestVehicle = "String", windrowOffset = "String", } function ADFieldStorage.getPath() diff --git a/FS25_ADSmartPickup/adFieldWork.lua b/FS25_ADSmartPickup/adFieldWork.lua index 2ce76a1..df734f9 100644 --- a/FS25_ADSmartPickup/adFieldWork.lua +++ b/FS25_ADSmartPickup/adFieldWork.lua @@ -166,6 +166,9 @@ end -- Hvilken vare markens trin fører til lager: skår (ensilage), tørskår (hø) eller høstet afgrøde. function ADFieldWork.storeFillType(field, info) if field.stage == "harvesting" then return info.harvestFillType end + if field.stage == "strawCollecting" or field.stage == "baling" or field.stage == "baleCollecting" then + return g_fillTypeManager:getFillTypeIndexByName("STRAW") + end local product = ADFieldModel.product(field.plan, field.kind or info.kind) return product == "hay" and info.hay or info.windrow end @@ -202,11 +205,11 @@ local function coursesOf(fieldId) return ADFieldJobs.courses[fieldId] end --- Kurset et trin skal genbruge ("mower"/"rake"): gemt kopi, ellers maskinens nuværende kursus. +-- Kurset et trin skal genbruge ("mower"/"rake"/"harvester"): gemt kopi, ellers maskinens nuværende kursus. local function sourceCourse(adEnv, field, source) local saved = coursesOf(field.id)[source] if saved ~= nil then return saved end - local vehicleId = source == "rake" and field.rakeVehicleId or field.mowVehicleId + local vehicleId = source == "rake" and field.rakeVehicleId or source == "harvester" and field.harvestVehicleId or field.mowVehicleId if vehicleId == nil then return nil end for _, vehicle in ipairs(ADRunsController.getFarmVehicles(adEnv)) do if ADRunsController.getVehicleId(vehicle) == vehicleId then return ADCpBridge.getCourse(vehicle) end @@ -435,6 +438,51 @@ local function beginUnloader(adEnv, field, info, assignment) assignment.handle = handle end +-- Ballesamler: Courseplays ballefinder; fuld vogn tømmes af AutoDrive i nærmeste ballelager (palleskur der +-- tager halmballer), som læssevognen. Uden lager stopper den når den er fuld. +local function beginBaleCollector(adEnv, field, info, assignment) + local vehicle = assignment.vehicle + local farmId = vehicle:getOwnerFarmId() + local straw = g_fillTypeManager:getFillTypeIndexByName("STRAW") + local isReachable = function(markerId) return ADUnloadWait.hasRouteTo(adEnv, vehicle, markerId) end + local store = ADSources.findPalletStore(adEnv, vehicle, straw, nil, isReachable, farmId) + if store ~= nil then + pcall(function() + local module = stateModule(vehicle) + module:setMode(adEnv.AutoDrive.MODE_PICKUPANDDELIVER) + module:setFirstMarkerByWayPointId(info.markerId) + module:setSecondMarkerByWayPointId(store.wayPointId) + module:setStartHelper(true) + module.usedHelper = helperCp(adEnv) + enableParkAtJobFinished(vehicle) + module:raiseDirtyFlag() + end) + assignment.adHandlesEnd = true + log(field.id, "ballesamler '%s' kører fulde læs til %s", ADRuns.vehicleLabel(vehicle), tostring(store.name)) + else + log(field.id, "intet ballelager med plads og vej fundet — ballesamleren stopper når den er fuld") + end + local point = info.points[1] or {x = info.x, z = info.z} + assignment.phase = "starting" + assignment.since = now() + local handle, err = ADCpBridge.startBaleFinder(vehicle, point.x, point.z, function(ok, reason) + if ok then + assignment.phase = "working" + assignment.since = now() + log(field.id, "Courseplay startet (ballesamler)") + else + ADFieldWork.release(assignment) + fail(field.id, "ballesamler: " .. tostring(reason)) + end + end) + if handle == nil then + ADFieldWork.release(assignment) + fail(field.id, "ballesamler: " .. tostring(err)) + return + end + assignment.handle = handle +end + -- Multi-tool: følgere venter på lederens kursus for trinnet og kopierer det med deres bane. local function courseOptions(adEnv, field, assignment) local source = ADFieldModel.courseSource(field, assignment.role) @@ -459,6 +507,12 @@ end local function beginWork(adEnv, field, info, assignment) local vehicle = assignment.vehicle if assignment.role == "unloader" then return beginUnloader(adEnv, field, info, assignment) end + if assignment.role == "baleCollector" then return beginBaleCollector(adEnv, field, info, assignment) end + -- høsteren: halmskår efter planen (hakkes = fra; samles op/presses = skår) + if assignment.role == "harvester" then + local keepStraw = field.plan.straw == "collect" or field.plan.straw == "bale" + ADCpBridge.setStrawSwath(vehicle, keepStraw) + end local opts, source = courseOptions(adEnv, field, assignment) if opts == nil then -- følger uden lederens kursus endnu @@ -504,6 +558,9 @@ local function beginWork(adEnv, field, info, assignment) elseif assignment.role == "rake" then note(field.id, {rakeVehicleId = assignment.vehicleId}) rememberCourse(field, "rake", vehicle) + elseif assignment.role == "harvester" then + note(field.id, {harvestVehicleId = assignment.vehicleId}) + rememberCourse(field, "harvester", vehicle) end if assignment.leader and (assignment.groupSize or 1) > 1 then rememberCourse(field, field.stage, vehicle) diff --git a/FS25_ADSmartPickup/gui/SmartPickupFieldTab.lua b/FS25_ADSmartPickup/gui/SmartPickupFieldTab.lua index 0731ba0..0d83ef9 100644 --- a/FS25_ADSmartPickup/gui/SmartPickupFieldTab.lua +++ b/FS25_ADSmartPickup/gui/SmartPickupFieldTab.lua @@ -9,7 +9,7 @@ SmartPickupFrame.FIELD_ROW_KINDS = { fieldProduct = true, fieldMode = true, fieldRake = true, fieldStore = true, fleetVehicle = true, fieldRigs = true, fieldUnloaders = true, fieldMulch = true, fieldLime = true, fieldSoil = true, fieldSow = true, fieldSowFruit = true, fieldRoll = true, fieldFertilize = true, fieldWeed = true, - fieldTarget = true, fleetMode = true, + fieldTarget = true, fleetMode = true, fieldStraw = true, } SmartPickupFrame.ROLE_KEYS = { mower = "spu_field_role_mower", tedder = "spu_field_role_tedder", rake = "spu_field_role_rake", @@ -17,6 +17,7 @@ SmartPickupFrame.ROLE_KEYS = { mulcher = "spu_field_role_mulcher", limer = "spu_field_role_limer", plow = "spu_field_role_plow", cultivator = "spu_field_role_cultivator", seeder = "spu_field_role_seeder", roller = "spu_field_role_roller", weeder = "spu_field_role_weeder", fertilizer = "spu_field_role_fertilizer", + baler = "spu_field_role_baler", baleCollector = "spu_field_role_baleCollector", } SmartPickupFrame.SOIL_VALUES = {"auto", "cultivate", "plow", "none"} -- simple Ja/Nej-valg på planen: rækketype -> plan-felt @@ -25,7 +26,8 @@ SmartPickupFrame.PLAN_TOGGLES = { fieldFertilize = "fertilize", fieldWeed = "weed", } -- valg med flere muligheder: rækketype -> plan-felt -SmartPickupFrame.PLAN_CHOICES = {fieldRigs = "rigs", fieldUnloaders = "unloaders", fieldSoil = "soil", fieldSowFruit = "sowFruit"} +SmartPickupFrame.PLAN_CHOICES = {fieldRigs = "rigs", fieldUnloaders = "unloaders", fieldSoil = "soil", fieldSowFruit = "sowFruit", fieldStraw = "straw"} +SmartPickupFrame.STRAW_VALUES = {"chop", "collect", "bale"} -- ---- tekster ---- @@ -200,14 +202,25 @@ function SmartPickupFrame:fillFieldDetail(adEnv, info) end local rigTexts, rigValues = numberTexts(1, ADFieldModel.MAX_RIGS) self:addChoiceRow("fieldRigs", i18n:getText("spu_field_rigs"), rigTexts, rigValues, plan.rigs or 1) - if info.kind == "mowable" then + -- græs-valgene (ensilage/hø, riv) også når målet er en slåafgrøde (fx græs på en kornmark) + local targetMowable = false + if hasTarget and ADFields ~= nil and g_fruitTypeManager ~= nil then + local targetFruit = g_fruitTypeManager:getFruitTypeByName(plan.targetFruit) + targetMowable = targetFruit ~= nil and ADFields.getMowable()[targetFruit.index] ~= nil + end + if info.kind == "mowable" or targetMowable then local isHay = ADFieldModel.product(plan, "mowable") == "hay" self:addToggleRow("fieldProduct", i18n:getText("spu_field_plan"), {i18n:getText("spu_field_plan_silage"), i18n:getText("spu_field_plan_hay")}, isHay) self:addToggleRow("fieldRake", i18n:getText("spu_field_rake"), yesNo, plan.rake == true) - else + end + -- klargøring: høst-/bare marker, og græsmarker der skal skifte til en anden mål-afgrøde + if info.kind ~= "mowable" or (hasTarget and info.fruitName ~= plan.targetFruit) then if info.kind == "harvest" then local unloaderTexts, unloaderValues = numberTexts(1, ADFieldModel.MAX_UNLOADERS) self:addChoiceRow("fieldUnloaders", i18n:getText("spu_field_unloaders"), unloaderTexts, unloaderValues, plan.unloaders or 1) + local strawTexts = {} + for _, value in ipairs(SmartPickupFrame.STRAW_VALUES) do table.insert(strawTexts, i18n:getText("spu_field_straw_" .. value)) end + self:addChoiceRow("fieldStraw", i18n:getText("spu_field_straw"), strawTexts, SmartPickupFrame.STRAW_VALUES, plan.straw or "chop") end self:addTextRow(i18n:getText(info.kind == "harvest" and "spu_field_section_after" or "spu_field_section_prep")) self:addToggleRow("fieldMulch", i18n:getText("spu_field_mulch"), yesNo, plan.mulch == true) diff --git a/FS25_ADSmartPickup/l10n/l10n_da.xml b/FS25_ADSmartPickup/l10n/l10n_da.xml index 9d83182..e7f44e5 100644 --- a/FS25_ADSmartPickup/l10n/l10n_da.xml +++ b/FS25_ADSmartPickup/l10n/l10n_da.xml @@ -160,6 +160,15 @@ + + + + + + + + + diff --git a/FS25_ADSmartPickup/l10n/l10n_en.xml b/FS25_ADSmartPickup/l10n/l10n_en.xml index e953080..71b0a6e 100644 --- a/FS25_ADSmartPickup/l10n/l10n_en.xml +++ b/FS25_ADSmartPickup/l10n/l10n_en.xml @@ -160,6 +160,15 @@ + + + + + + + + + diff --git a/tests/test_adFieldFleet.lua b/tests/test_adFieldFleet.lua index dddda8a..c5b82be 100644 --- a/tests/test_adFieldFleet.lua +++ b/tests/test_adFieldFleet.lua @@ -88,5 +88,11 @@ check("FL11 flueben: uden flueben ude", F.isEnabled("ticked", {}, "v1"), false) check("FL11 flueben: med flueben", F.isEnabled("ticked", {v1 = true}, "v1"), true) check("FL11 ukendt tilstand = alle", F.isEnabled(nil, {}, "v1"), true) +-- FL12: ballepresser og ballesamler (ballevogn/Universal Autoload som Courseplays ballesamler kan bruge) +check("FL12 ballepresser", F.roleFromSpecs({spec_baler = true}), "baler") +check("FL12 ballesamler", F.roleFromSpecs({canBaleCollect = true}), "baleCollector") +check("FL12 ballesamler før aflæsningsvogn", F.roleFromSpecs({canBaleCollect = true, canUnload = true}), "baleCollector") +check("FL12 høster før presser", F.roleFromSpecs({spec_combine = true, spec_baler = true}), "harvester") + print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL")) os.exit(failures == 0 and 0 or 1) diff --git a/tests/test_adFieldModel.lua b/tests/test_adFieldModel.lua index 02a5527..f458975 100644 --- a/tests/test_adFieldModel.lua +++ b/tests/test_adFieldModel.lua @@ -270,5 +270,24 @@ check("M21 arbejdende mark beholder trin", M.setTarget(started, "CANOLA").stage, local cleared = M.setTarget(chosen, "") check("M21 mål fjernet", cleared.plan.targetFruit, ""); check("M21 tilbage til manuel", cleared.plan.mode, "manual") +-- M22: halm efter høst — hakkes (standard), samles op, eller presses til baller og samles +local strawBase = {soil = "none", sow = false, lime = false} +check("M22 hakkes: kun høst", table.concat(M.workStages(strawBase, "harvest", {}), ","), "harvesting") +check("M22 samles op", table.concat(M.workStages(M.with(M.newField(1), {plan = {soil = "none", lime = false, straw = "collect"}}).plan, "harvest", {}), ","), "harvesting,strawCollecting") +check("M22 baller", table.concat(M.workStages(M.with(M.newField(1), {plan = {soil = "none", lime = false, straw = "bale"}}).plan, "harvest", {}), ","), "harvesting,baling,baleCollecting") +local baleChain = M.start(M.with(M.newField(2), {plan = {straw = "bale", soil = "cultivate", lime = false}}), "harvest", {}) +check("M22 høst -> presses", M.advance(baleChain, {}).stage, "baling") +check("M22 presses -> baller samles", M.advance(M.advance(baleChain, {}), {}).stage, "baleCollecting") +check("M22 -> kultivér", M.advance(M.advance(M.advance(baleChain, {}), {}), {}).stage, "cultivating") +check("M22 roller", M.roleFor("baling") .. "," .. M.roleFor("baleCollecting") .. "," .. M.roleFor("strawCollecting"), "baler,baleCollector,collector") +check("M22 halm-læssevogn følger høsterens kursus", M.courseSource(M.with(M.newField(3), {stage = "strawCollecting"}), "collector"), "harvester") +check("M22 presser følger høsterens kursus", M.courseSource(M.with(M.newField(3), {stage = "baling"}), "baler"), "harvester") +check("M22 græs-læssevogn følger stadig slåkurset", M.courseSource(M.with(M.newField(3), {stage = "collecting"}), "collector"), "mower") +check("M22 halm-læssevogn uden breddekrav", M.requiredWidth(M.with(M.newField(3), {stage = "strawCollecting", mowWidth = 40}), "collector"), nil) +check("M22 presning vejrfølsom", M.isWeatherSensitive("baling", {}, "harvest"), true) +check("M22 ballesamling ikke vejrfølsom", M.isWeatherSensitive("baleCollecting", {}, "harvest"), false) +check("M22 gemmes", M.fromRecord(M.toRecord(M.with(M.newField(4), {plan = {straw = "bale"}}))).plan.straw, "bale") +check("M22 ukendt -> hakkes", M.fromRecord({id = 5, straw = "x"}).plan.straw, "chop") + print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL")) os.exit(failures == 0 and 0 or 1)