908 lines
60 KiB
Lua
908 lines
60 KiB
Lua
-- Kør: luajit tests/test_adRunsController.lua (fra repo-roden)
|
|
-- Controlleren oversætter et run til AutoDrive-tilstand pr. traktor. Mock'er AD + de
|
|
-- få ADSmartPickup-opslag den bruger.
|
|
|
|
local STRAW, TMR, WATER, MILK = 31, 116, 8, 30
|
|
local FILL_TYPE_NAMES = {[STRAW] = "STRAW", [TMR] = "FORAGE", [WATER] = "WATER", [MILK] = "MILK"}
|
|
local FILL_TYPE_INDEX = {}
|
|
for index, name in pairs(FILL_TYPE_NAMES) do FILL_TYPE_INDEX[name] = index end
|
|
g_fillTypeManager = {
|
|
getFillTypeNameByIndex = function(_, index) return FILL_TYPE_NAMES[index] end,
|
|
getFillTypeIndexByName = function(_, name) return FILL_TYPE_INDEX[name] end,
|
|
getFillTypes = function()
|
|
return {
|
|
{index = STRAW, name = "STRAW", title = "Halm"},
|
|
{index = TMR, name = "FORAGE", title = "TMR"},
|
|
{index = WATER, name = "WATER", title = "Vand"},
|
|
{index = MILK, name = "MILK", title = "Mælk"},
|
|
}
|
|
end,
|
|
}
|
|
local logLines = {}
|
|
Logging = {
|
|
info = function(fmt, ...) table.insert(logLines, string.format(fmt, ...)) end,
|
|
warning = function(fmt, ...) table.insert(logLines, "WARN " .. string.format(fmt, ...)) end,
|
|
}
|
|
Utils = {prependedFunction = function(original, extra) return function(...) extra(...); return original(...) end end}
|
|
ItemSystem = {save = function() end}
|
|
g_currentMission = {getFarmId = function() return 1 end, missionInfo = {}}
|
|
|
|
-- ---- AutoDrive-mock ----
|
|
local RT_NONE, RT_ONLYPICKUP = 1, 2
|
|
local MODE_PICKUPANDDELIVER = 2
|
|
local vehicles, markers, wayPoints = {}, {}, {}
|
|
FS25_AutoDrive = {
|
|
AutoDrive = {
|
|
RT_NONE = RT_NONE, RT_ONLYPICKUP = RT_ONLYPICKUP, MODE_PICKUPANDDELIVER = MODE_PICKUPANDDELIVER,
|
|
settings = {
|
|
useFolders = {values = {false, true}, current = 1, isVehicleSpecific = false},
|
|
rotateTargets = {values = {1, 2, 3, 4}, current = 1, isVehicleSpecific = true},
|
|
ALUnload = {values = {0, 1, 2, 3, 4}, current = 1, isVehicleSpecific = true},
|
|
},
|
|
getAllVehicles = function() return vehicles end,
|
|
getAllUnits = function(vehicle) return vehicle.trailers end,
|
|
getAllFillLevels = function(trailers) return trailers.level or 0, trailers.capacity or 0, false, 0 end,
|
|
getSupportedFillTypesOfAllUnitsAlphabetically = function(vehicle) return vehicle.carriable or {} end,
|
|
},
|
|
ADGraphManager = {
|
|
getMapMarkers = function() return markers end,
|
|
getMapMarkerByWayPointId = function(_, id) for _, m in ipairs(markers) do if m.id == id then return m end end end,
|
|
getWayPointById = function(_, id) return wayPoints[id] end,
|
|
getDistanceFromNetwork = function(_, vehicle) return vehicle.networkDistance or 0 end,
|
|
},
|
|
}
|
|
|
|
local function addMarker(id, name, group, x, z)
|
|
wayPoints[id] = {x = x, z = z, incoming = {}}
|
|
table.insert(markers, {id = id, markerIndex = #markers + 1, name = name, group = group})
|
|
end
|
|
|
|
-- ADSmartPickup-opslag: hvilke waypoints har hvilken slags station, og hvad målet tager
|
|
local unloadAt, loadAt = {}, {}
|
|
ADSmartPickup = {
|
|
getFarmId = function(vehicle) return vehicle.farmId end,
|
|
getUnloadStationAtWayPointId = function(_, id) return unloadAt[id] end,
|
|
getLoadStationAtWayPointId = function(_, id) return loadAt[id] end,
|
|
getStationLevelAndCapacity = function(station, fillType)
|
|
if station.accepts[fillType] == nil then return nil end
|
|
return (station.levels or {})[fillType] or 0, station.accepts[fillType]
|
|
end,
|
|
-- forenklet rangering: mest fri plads (relativt) først; fulde sidst
|
|
getTargetNeedsRanked = function(station, fillTypes)
|
|
local ranked = {}
|
|
for _, fillType in ipairs(fillTypes) do
|
|
local capacity = station.accepts[fillType]
|
|
if capacity ~= nil then
|
|
local level = (station.levels or {})[fillType] or 0
|
|
table.insert(ranked, {fillType = fillType, level = level, capacity = capacity, freeSpace = capacity - level, score = (capacity - level) / capacity})
|
|
end
|
|
end
|
|
table.sort(ranked, function(a, b) return a.score > b.score end)
|
|
return ranked
|
|
end,
|
|
}
|
|
ADSupplyPlanner = {isWaitMarker = function(marker) return string.find(string.lower(marker.group or ""), "%f[%a]wait%f[%A]") ~= nil end}
|
|
|
|
local function makeVehicle(uniqueId, name, carriable, capacity, x, z)
|
|
local stateModule = {selectedFillTypes = {}, fillType = 0, active = false, loopCounter = 5, loopsDone = 3, dirtyCount = 0}
|
|
stateModule.setMode = function(self, mode) self.mode = mode end
|
|
stateModule.setFirstMarkerByWayPointId = function(self, id) self.firstMarkerId = id end
|
|
stateModule.setSecondMarkerByWayPointId = function(self, id) self.secondMarkerId = id end
|
|
stateModule.setFillType = function(self, fillType) self.fillType = fillType end
|
|
stateModule.raiseDirtyFlag = function(self) self.dirtyCount = self.dirtyCount + 1 end
|
|
stateModule.setLoopsDone = function(self, n) self.loopsDone = n end
|
|
stateModule.isActive = function(self) return self.active end
|
|
-- Bruges af C13: getTargetFillTypes skal følge AD's LIVE mål (mock'er AD's eget getSecondMarker).
|
|
stateModule.getSecondMarker = function(self) return self.secondMarkerId ~= nil and {id = self.secondMarkerId} or nil end
|
|
local vehicle = {
|
|
uniqueId = uniqueId, farmId = 1, rootNode = uniqueId,
|
|
carriable = carriable, trailers = {level = 0, capacity = capacity},
|
|
getName = function() return name end,
|
|
getOwnerFarmId = function() return 1 end,
|
|
startAutoDrive = function(self) self.ad.stateModule.active = true; self.started = (self.started or 0) + 1 end,
|
|
getClosestWayPoint = function() return nil, 0 end,
|
|
stopAutoDrive = function(self) self.ad.stateModule.active = false; self.stopped = (self.stopped or 0) + 1 end,
|
|
ad = {stateModule = stateModule, settings = {rotateTargets = {values = {1, 2, 3, 4}, current = 1, new = 1, isVehicleSpecific = true}, ALUnload = {values = {0, 1, 2, 3, 4}, current = 1, new = 1, isVehicleSpecific = true}}},
|
|
}
|
|
nodePositions = nodePositions or {}
|
|
nodePositions[uniqueId] = {x = x or 0, z = z or 0}
|
|
table.insert(vehicles, vehicle)
|
|
return vehicle
|
|
end
|
|
function getWorldTranslation(node) local p = nodePositions[node]; return p.x, 0, p.z end
|
|
|
|
dofile("FS25_ADSmartPickup/adRuns.lua")
|
|
dofile("FS25_ADSmartPickup/adRunsStorage.lua")
|
|
dofile("FS25_ADSmartPickup/adWaitPool.lua")
|
|
dofile("FS25_ADSmartPickup/adRunsController.lua")
|
|
local adEnv = FS25_AutoDrive
|
|
|
|
local failures = 0
|
|
local function check(name, actual, expected)
|
|
if actual == expected then
|
|
print("OK " .. name)
|
|
else
|
|
failures = failures + 1
|
|
print(string.format("FAIL %s: forventede %s, fik %s", name, tostring(expected), tostring(actual)))
|
|
end
|
|
end
|
|
|
|
local function buildWorld()
|
|
vehicles, markers, wayPoints, unloadAt, loadAt, logLines = {}, {}, {}, {}, {}, {}
|
|
ADRunsController.store = ADRuns.newStore()
|
|
addMarker(94, "Cow 1 Food", "Cow Food", 5000, 0); unloadAt[94] = {accepts = {[STRAW] = 300000, [TMR] = 300000, [WATER] = 50000}}
|
|
addMarker(44, "10 Silo Storage", "Siloer", 0, 0); loadAt[44] = {}
|
|
addMarker(75, "TMR Load", "Fabrication", 900, 0); loadAt[75] = {}
|
|
addMarker(100, "Cow Wait", "Cow Wait", 5100, 0)
|
|
addMarker(101, "Cow Wait", "Cow Wait", 5200, 0)
|
|
addMarker(200, "F91 Wait", "F91", 8000, 0)
|
|
addMarker(300, "Pig Wait", "Pig Wait", 9000, 0)
|
|
end
|
|
|
|
-- C1: køretøjs-id og farmens AD-køretøjer
|
|
buildWorld()
|
|
local fastracA = makeVehicle("vehicleA", "Fastrac A", {STRAW, TMR}, 1000000, 100, 0)
|
|
local fastracB = makeVehicle("vehicleB", "Fastrac B", {STRAW}, 700000, 4000, 0)
|
|
local noAd = {uniqueId = "vehicleC", getOwnerFarmId = function() return 1 end}
|
|
table.insert(vehicles, noAd)
|
|
local otherFarm = makeVehicle("vehicleD", "Nabo", {STRAW}, 1000, 0, 0); otherFarm.getOwnerFarmId = function() return 2 end
|
|
check("C1 uniqueId", ADRunsController.getVehicleId(fastracA), "vehicleA")
|
|
check("C1 fallback savegame-id", ADRunsController.getVehicleId({currentSavegameId = 7}), "7")
|
|
check("C1 intet id -> nil", ADRunsController.getVehicleId({}), nil)
|
|
check("C1 farmens AD-køretøjer", #ADRunsController.getFarmVehicles(adEnv), 2)
|
|
check("C1 opslag på id", ADRunsController.findVehicleById(adEnv, "vehicleB"), fastracB)
|
|
check("C1 ukendt id -> nil", ADRunsController.findVehicleById(adEnv, "nope"), nil)
|
|
|
|
-- C2: opret run, tildel; opslag run for køretøj; flyt mellem runs
|
|
local cow = ADRunsController.createRun("Cow Feed")
|
|
check("C2 run oprettet", ADRuns.getRun(ADRunsController.store, cow.id).name, "Cow Feed")
|
|
check("C2 ingen tidligere", ADRunsController.assignVehicle(cow.id, fastracA), nil)
|
|
check("C2 run for køretøj", ADRunsController.getRunForVehicle(fastracA).id, cow.id)
|
|
check("C2 ikke tildelt -> nil", ADRunsController.getRunForVehicle(fastracB), nil)
|
|
local pig = ADRunsController.createRun("Pig Feed")
|
|
check("C2 flyttet fra Cow", ADRunsController.assignVehicle(pig.id, fastracA), cow.id)
|
|
check("C2 nu i Pig", ADRunsController.getRunForVehicle(fastracA).id, pig.id)
|
|
ADRunsController.unassignVehicle(fastracA)
|
|
check("C2 fjernet", ADRunsController.getRunForVehicle(fastracA), nil)
|
|
ADRunsController.deleteRun(pig.id)
|
|
check("C2 slettet", ADRuns.getRun(ADRunsController.store, pig.id), nil)
|
|
|
|
-- C3: Auto-vareliste = vognens varer ∩ målets varer; manual = navne -> indeks (ukendte droppes)
|
|
ADRunsController.updateRun(cow.id, {targetWayPointId = 94})
|
|
local cowRun = ADRuns.getRun(ADRunsController.store, cow.id)
|
|
check("C3 auto: halm+TMR (vand kan vognen ikke bære)", table.concat(ADRunsController.getRunIngredients(adEnv, cowRun, fastracA), ","), STRAW .. "," .. TMR)
|
|
check("C3 auto: kun halm for halm-vogn", table.concat(ADRunsController.getRunIngredients(adEnv, cowRun, fastracB), ","), tostring(STRAW))
|
|
ADRunsController.updateRun(cow.id, {ingredientMode = "manual", ingredients = {"FORAGE", "UNKNOWN_THING"}})
|
|
cowRun = ADRuns.getRun(ADRunsController.store, cow.id)
|
|
check("C3 manual: FORAGE -> indeks, ukendt droppes", table.concat(ADRunsController.getRunIngredients(adEnv, cowRun, fastracA), ","), tostring(TMR))
|
|
ADRunsController.updateRun(cow.id, {ingredientMode = "auto"})
|
|
local noTarget = ADRunsController.createRun("Uden mål")
|
|
check("C3 uden mål -> tom liste", #ADRunsController.getRunIngredients(adEnv, ADRuns.getRun(ADRunsController.store, noTarget.id), fastracA), 0)
|
|
|
|
-- C4: validering
|
|
cowRun = ADRuns.getRun(ADRunsController.store, cow.id)
|
|
check("C4 ok", ADRunsController.validateVehicle(adEnv, cowRun, fastracA).ok, true)
|
|
check("C4 kapacitet", ADRunsController.validateVehicle(adEnv, cowRun, fastracA).capacity, 1000000)
|
|
local noTrailer = makeVehicle("vehicleE", "Uden vogn", {}, 0)
|
|
check("C4 ingen vogn", ADRunsController.validateVehicle(adEnv, cowRun, noTrailer).reason, "noTrailer")
|
|
local milkTruck = makeVehicle("vehicleF", "Mælkebil", {MILK}, 20000)
|
|
check("C4 kan ikke bære", ADRunsController.validateVehicle(adEnv, cowRun, milkTruck).reason, "cannotCarry")
|
|
fastracB.networkDistance = 31
|
|
check("C4 for langt fra vejnettet", ADRunsController.validateVehicle(adEnv, cowRun, fastracB).reason, "farFromNetwork")
|
|
fastracB.networkDistance = 0
|
|
check("C4 intet mål", ADRunsController.validateVehicle(adEnv, ADRuns.getRun(ADRunsController.store, noTarget.id), fastracA).reason, "noTarget")
|
|
ADRunsController.updateRun(noTarget.id, {targetWayPointId = 4242})
|
|
check("C4 mål-markør findes ikke", ADRunsController.validateVehicle(adEnv, ADRuns.getRun(ADRunsController.store, noTarget.id), fastracA).reason, "noTarget")
|
|
|
|
-- C5: Start skriver AD-tilstand og starter; ✖-traktorer springes over
|
|
ADRunsController.updateRun(cow.id, {loops = 4, waitPoolGroup = "Cow Wait"})
|
|
ADRunsController.assignVehicle(cow.id, fastracA)
|
|
ADRunsController.assignVehicle(cow.id, noTrailer)
|
|
local results = ADRunsController.startRun(adEnv, cow.id)
|
|
check("C5 to resultater", #results, 2)
|
|
check("C5 A startet", fastracA.started, 1)
|
|
check("C5 A ok", results[1].ok, true)
|
|
check("C5 uden vogn sprunget over", noTrailer.started, nil)
|
|
check("C5 uden vogn grund", results[2].reason, "noTrailer")
|
|
local state = fastracA.ad.stateModule
|
|
check("C5 mode P&D", state.mode, MODE_PICKUPANDDELIVER)
|
|
check("C5 mål = run'ets mål", state.secondMarkerId, 94)
|
|
check("C5 start-pickup = nærmeste læssestation", state.firstMarkerId, 44)
|
|
check("C5 varer = auto-listen", table.concat(state.selectedFillTypes, ","), STRAW .. "," .. TMR)
|
|
check("C5 fillType = første", state.fillType, STRAW)
|
|
check("C5 loops", state.loopCounter, 4)
|
|
check("C5 loopsDone nulstillet", state.loopsDone, 0)
|
|
check("C5 rotateTargets = kun pålæsning (current)", fastracA.ad.settings.rotateTargets.current, 2)
|
|
check("C5 rotateTargets = kun pålæsning (new)", fastracA.ad.settings.rotateTargets.new, 2)
|
|
check("C5 useFolders globalt til", adEnv.AutoDrive.settings.useFolders.current, 2)
|
|
check("C5 dirty flag", state.dirtyCount > 0, true)
|
|
check("C5 status", ADRunsController.getRunStatus(adEnv, ADRuns.getRun(ADRunsController.store, cow.id)).running, 1)
|
|
check("C5 total", ADRunsController.getRunStatus(adEnv, ADRuns.getRun(ADRunsController.store, cow.id)).total, 2)
|
|
check("C5 ukendt run -> tom", #ADRunsController.startRun(adEnv, 999), 0)
|
|
|
|
-- C6: Stop
|
|
check("C6 stoppede", ADRunsController.stopRun(adEnv, cow.id), 1)
|
|
check("C6 A stoppet", fastracA.stopped, 1)
|
|
check("C6 status 0", ADRunsController.getRunStatus(adEnv, ADRuns.getRun(ADRunsController.store, cow.id)).running, 0)
|
|
check("C6 medlemskab bevaret", ADRunsController.getRunForVehicle(fastracA).id, cow.id)
|
|
|
|
-- C7: Start på traktor der allerede kører AD (fx startet manuelt) -> stoppes og startes på run'et
|
|
fastracA.ad.stateModule.active = true
|
|
fastracA.stopped = 0
|
|
ADRunsController.startRun(adEnv, cow.id)
|
|
check("C7 kørende traktor stoppes først", fastracA.stopped, 1)
|
|
check("C7 og startes på run'et", fastracA.started, 2)
|
|
check("C7 run markeret som kørende", ADRunsController.getRunStatus(adEnv, ADRuns.getRun(ADRunsController.store, cow.id)).isRunning, true)
|
|
ADRunsController.stopRun(adEnv, cow.id)
|
|
check("C7 stop rydder markeringen", ADRunsController.getRunStatus(adEnv, ADRuns.getRun(ADRunsController.store, cow.id)).isRunning, false)
|
|
-- en traktor der kører AD uden at run'et er startet af os, gør IKKE run'et "kørende"
|
|
fastracA.ad.stateModule.active = true
|
|
check("C7 manuel AD tæller ikke som kørende run", ADRunsController.getRunStatus(adEnv, ADRuns.getRun(ADRunsController.store, cow.id)).isRunning, false)
|
|
-- efter genindlæsning: runningRuns er tom, men flowet er ikke stoppet og traktoren kører -> kørende (Stop-knap)
|
|
-- (in-game 29/9: Flows-listen viste [Start] ved flows der kørte)
|
|
ADRuns.getRun(ADRunsController.store, cow.id).stopped = false
|
|
ADRunsController.runningRuns[cow.id] = nil
|
|
check("C7b efter genindlæsning: kørende", ADRunsController.getRunStatus(adEnv, ADRuns.getRun(ADRunsController.store, cow.id)).isRunning, true)
|
|
check("C7b efter genindlæsning: kan stoppes", ADRunsController.getRunStatus(adEnv, ADRuns.getRun(ADRunsController.store, cow.id)).canStop, true)
|
|
ADRuns.getRun(ADRunsController.store, cow.id).stopped = true
|
|
check("C7 men aktive tæller stadig", ADRunsController.getRunStatus(adEnv, ADRuns.getRun(ADRunsController.store, cow.id)).running, 1)
|
|
fastracA.ad.stateModule.active = false
|
|
-- sprungne traktorer logges med årsag
|
|
logLines = {}
|
|
ADRunsController.startRun(adEnv, cow.id)
|
|
local skippedLogged = false
|
|
for _, line in ipairs(logLines) do if line:find("sprunget over", 1, true) and line:find("noTrailer", 1, true) then skippedLogged = true end end
|
|
check("C7 sprunget over logges med årsag", skippedLogged, true)
|
|
-- kapacitet under 100 l (kun trækkerens egne tanke) = ingen vogn
|
|
local tinyCapacity = makeVehicle("vehicleTiny", "T255", {STRAW, TMR}, 1, 100, 0)
|
|
check("C7 1 l kapacitet -> noTrailer", ADRunsController.validateVehicle(adEnv, ADRuns.getRun(ADRunsController.store, cow.id), tinyCapacity).reason, "noTrailer")
|
|
-- UAL-køretøj: AutoDrive melder kapacitet i PALLER (læssede + 1), så en tom pallebil har "1" — det er ikke "ingen vogn"
|
|
adEnv.AutoDrive.hasAL = function(_, unit) return unit.ual == true end
|
|
local palletTruck = makeVehicle("vehicleDragon", "Dragon", {}, 1, 100, 0)
|
|
palletTruck.trailers[1] = {ual = true}
|
|
local truckValidation = ADRunsController.validateVehicle(adEnv, ADRuns.getRun(ADRunsController.store, cow.id), palletTruck)
|
|
check("C7 pallebil: ikke noTrailer", truckValidation.reason ~= "noTrailer", true)
|
|
check("C7 pallebil: kapacitet i paller markeret", truckValidation.isAutoload, true)
|
|
check("C7 pallebil: liter-kapacitet ukendt", truckValidation.capacity, nil)
|
|
-- in-game 27/9: en tipvogn med UniversalAutoload slået til tæller hos AutoDrive kun som palle-/ballevogn,
|
|
-- så en forsynings-flow med løsvarer afviste den som "kan ikke bære" uden at sige hvorfor
|
|
check("C7 AutoLoad slået til på vogn i forsyning -> autoloadOn", truckValidation.reason, "autoloadOn")
|
|
adEnv.AutoDrive.hasAL = nil
|
|
|
|
-- C8: mål-markører (kun stalde og fabrikker — siloer tager alt og er ikke mål; stalde først,
|
|
-- så fabrikker, så navn) og Wait-puljer til dropdowns
|
|
unloadAt[94].owningPlaceable = {getHusbandryFillLevel = function() return 0 end}
|
|
addMarker(96, "8 Silo Storage", "Siloer", 100, 0); unloadAt[96] = {accepts = {[STRAW] = 1}, owningPlaceable = {spec_silo = {}}}
|
|
addMarker(97, "TMR Unload", "Fabrication", 900, 0); unloadAt[97] = {accepts = {[STRAW] = 1}, owningPlaceable = {spec_productionPoint = {}}}
|
|
addMarker(98, "Bull Food", "Cow Food", 5100, 0); unloadAt[98] = {accepts = {[STRAW] = 1}, owningPlaceable = {getHusbandryFillLevel = function() return 0 end}}
|
|
local targets = ADRunsController.getTargetMarkers(adEnv, 1)
|
|
check("C8 kun stalde og fabrikker (ikke siloen)", #targets, 3)
|
|
check("C8 stalde først, alfabetisk", targets[1].name .. "," .. targets[2].name, "Bull Food,Cow 1 Food")
|
|
check("C8 fabrik sidst", targets[3].name, "TMR Unload")
|
|
local pools = ADRunsController.getWaitPools(adEnv)
|
|
check("C8 to puljer (F91 er ikke en Wait-mappe)", #pools, 2)
|
|
check("C8 sorteret", pools[1].group, "Cow Wait")
|
|
check("C8 antal", pools[1].count, 2)
|
|
|
|
-- C9: gem/indlæs; ukendte køretøjs-id'er logges ved indlæsning men beholdes i run'et
|
|
local savedRecords
|
|
ADRunsStorage.save = function(store) savedRecords = ADRuns.toRecords(store); return true end
|
|
ADRunsStorage.load = function() return ADRuns.fromRecords(savedRecords) end
|
|
ADRunsController.assignVehicle(cow.id, {uniqueId = "vehicleGONE", ad = {}, getOwnerFarmId = function() return 1 end, getName = function() return "Væk" end})
|
|
check("C9 gemt", ADRunsController.save(), true)
|
|
ADRunsController.store = ADRuns.newStore()
|
|
ADRunsController.load(adEnv)
|
|
check("C9 indlæst", ADRuns.getRun(ADRunsController.store, cow.id).name, "Cow Feed")
|
|
check("C9 ukendt køretøj logget", logLines[#logLines]:find("vehicleGONE", 1, true) ~= nil, true)
|
|
check("C9 run beholder kendte", ADRunsController.getRunForVehicle(fastracA).id, cow.id)
|
|
local hooked = false
|
|
ItemSystem.save = function() hooked = true end
|
|
ADRunsController.installSaveHook()
|
|
ItemSystem.save()
|
|
check("C9 save-hook kaldes før ItemSystem.save", hooked, true)
|
|
|
|
-- C11: vogn uden egen ad.settings-tabel (ingen rotateTargets pr. køretøj) -> den
|
|
-- køretøjs-specifikke indstilling skrives IKKE til den globale settings-tabel
|
|
adEnv.AutoDrive.settings.rotateTargets.current = 1
|
|
adEnv.AutoDrive.settings.useFolders.current = 1
|
|
local settingsRun = ADRunsController.createRun("Settings Test")
|
|
ADRunsController.updateRun(settingsRun.id, {targetWayPointId = 94, loops = 1})
|
|
local noSettings = makeVehicle("vehicleH", "Uden AD-settings", {STRAW}, 500000, 200, 0)
|
|
noSettings.ad.settings = {}
|
|
ADRunsController.assignVehicle(settingsRun.id, noSettings)
|
|
ADRunsController.startRun(adEnv, settingsRun.id)
|
|
check("C11 global rotateTargets urørt", adEnv.AutoDrive.settings.rotateTargets.current, 1)
|
|
check("C11 useFolders global stadig skrevet", adEnv.AutoDrive.settings.useFolders.current, 2)
|
|
check("C11 køretøjet startet", noSettings.started, 1)
|
|
|
|
-- C12: startAutoDrive() kaster for én traktor -> pcall'et applyAndStart fanger fejlen,
|
|
-- resultatet markeres ok=false/reason="error", og de ØVRIGE traktorer i run'et startes stadig
|
|
-- (fejlen må ikke undslippe startRun-loopet).
|
|
buildWorld()
|
|
local brokenRun = ADRunsController.createRun("Broken Start")
|
|
ADRunsController.updateRun(brokenRun.id, {targetWayPointId = 94, loops = 2})
|
|
local broken = makeVehicle("vehicleBroken", "Fejl-traktor", {STRAW, TMR}, 500000, 100, 0)
|
|
broken.startAutoDrive = function() error("boom") end
|
|
local normal = makeVehicle("vehicleNormal", "Normal-traktor", {STRAW, TMR}, 500000, 200, 0)
|
|
ADRunsController.assignVehicle(brokenRun.id, broken)
|
|
ADRunsController.assignVehicle(brokenRun.id, normal)
|
|
local c12Results = ADRunsController.startRun(adEnv, brokenRun.id)
|
|
check("C12 to resultater", #c12Results, 2)
|
|
check("C12 fejl-traktor ok=false", c12Results[1].ok, false)
|
|
check("C12 fejl-traktor reason=error", c12Results[1].reason, "error")
|
|
check("C12 fejl-traktor ikke startet", broken.started, nil)
|
|
check("C12 normal-traktor ok=true", c12Results[2].ok, true)
|
|
check("C12 normal-traktor startet", normal.started, 1)
|
|
|
|
-- C13: Auto-listen følger traktorens LIVE AD-mål (stateModule:getSecondMarker()) mens den kører,
|
|
-- IKKE run'ets gemte targetWayPointId — ellers afviger listen fra det choosePickup/findSupplyPickup
|
|
-- faktisk bruger, hvis brugeren redigerer run'ets Mål mens traktoren kører.
|
|
addMarker(95, "Alt Cow Food", "Cow Food", 5300, 0)
|
|
unloadAt[95] = {accepts = {[STRAW] = 1000}}
|
|
local liveRun = ADRunsController.createRun("Live Target")
|
|
ADRunsController.updateRun(liveRun.id, {targetWayPointId = 94})
|
|
local liveRunData = ADRuns.getRun(ADRunsController.store, liveRun.id)
|
|
local liveVehicle = makeVehicle("vehicleLive", "Live-traktor", {STRAW, TMR}, 500000, 300, 0)
|
|
check("C13 inaktiv: auto-liste fra run'ets mål (94)", table.concat(ADRunsController.getRunIngredients(adEnv, liveRunData, liveVehicle), ","), STRAW .. "," .. TMR)
|
|
liveVehicle.ad.stateModule.active = true
|
|
liveVehicle.ad.stateModule.secondMarkerId = 95
|
|
check("C13 aktiv: auto-liste fra AD's live mål (95)", table.concat(ADRunsController.getRunIngredients(adEnv, liveRunData, liveVehicle), ","), tostring(STRAW))
|
|
liveVehicle.ad.stateModule.active = false
|
|
liveVehicle.ad.stateModule.secondMarkerId = nil
|
|
|
|
-- C10: målets accepterede varer (til afkrydsning i GUI'et) + køretøjs-label
|
|
buildWorld()
|
|
local labelA = makeVehicle("vehicleA", "Fastrac A", {STRAW, TMR}, 1000000)
|
|
local labelB = makeVehicle("vehicleB", "Fastrac B", {STRAW}, 700000)
|
|
local accRun = ADRunsController.createRun("Cow Feed")
|
|
check("C10 uden mål -> tom", #ADRunsController.getTargetAcceptedFillTypes(adEnv, ADRuns.getRun(ADRunsController.store, accRun.id)), 0)
|
|
ADRunsController.updateRun(accRun.id, {targetWayPointId = 94})
|
|
local accepted = ADRunsController.getTargetAcceptedFillTypes(adEnv, ADRuns.getRun(ADRunsController.store, accRun.id))
|
|
check("C10 tre varer (halm, TMR, vand)", #accepted, 3)
|
|
check("C10 sorteret på titel", accepted[1].title .. "," .. accepted[2].title .. "," .. accepted[3].title, "Halm,TMR,Vand")
|
|
check("C10 navn med", accepted[1].name, "STRAW")
|
|
check("C10 label", ADRunsController.getVehicleLabel(adEnv, labelB), "Fastrac B (#2)")
|
|
|
|
-- C14: Start går gennem AD's mode:start(USER_PLAYER) (som HUD'en), ikke kun startAutoDrive
|
|
buildWorld()
|
|
local modeVehicle = makeVehicle("vehicleM", "Mode-traktor", {STRAW, TMR}, 1000000, 100, 0)
|
|
local modeStarts = {}
|
|
modeVehicle.ad.stateModule.getCurrentMode = function() return {start = function(_, user) table.insert(modeStarts, user); modeVehicle:startAutoDrive() end} end
|
|
modeVehicle.ad.stateModule.setActualFarmId = function(self, farmId) self.actualFarmId = farmId end
|
|
adEnv.AutoDrive.USER_PLAYER = 1
|
|
local modeRun = ADRunsController.createRun("Mode")
|
|
ADRunsController.updateRun(modeRun.id, {targetWayPointId = 94})
|
|
ADRunsController.assignVehicle(modeRun.id, modeVehicle)
|
|
ADRunsController.startRun(adEnv, modeRun.id)
|
|
check("C14 mode:start kaldt med USER_PLAYER", modeStarts[1], 1)
|
|
check("C14 traktor aktiv", modeVehicle.started, 1)
|
|
check("C14 farm-id sat", modeVehicle.ad.stateModule.actualFarmId, 1)
|
|
check("C14 loopsDone nulstillet", modeVehicle.ad.stateModule.loopsDone, 0)
|
|
|
|
-- C15: aktivitet til overblikket — stoppet / venter / med læs / tom på vej efter vare
|
|
ADUnloadWait = {getWaitFor = function(v) return v.waitInfo end, getRestLoad = function(_, v) return v.loadType, v.loadLiters or 0 end}
|
|
ADSmartPickup.getActivePickup = function(v) return v.pickupInfo end
|
|
buildWorld()
|
|
local actVehicle = makeVehicle("vehicleAct", "Akt", {STRAW, TMR}, 1000000, 100, 0)
|
|
check("C15 stoppet", ADRunsController.getVehicleActivity(adEnv, actVehicle).kind, "stopped")
|
|
actVehicle.ad.stateModule.active = true
|
|
actVehicle.ad.stateModule.secondMarkerId = 94
|
|
actVehicle.loadType, actVehicle.loadLiters = STRAW, 8000
|
|
local loaded = ADRunsController.getVehicleActivity(adEnv, actVehicle)
|
|
check("C15 med læs", loaded.kind .. "/" .. loaded.fillType .. "/" .. loaded.liters, "loaded/" .. STRAW .. "/8000")
|
|
actVehicle.loadLiters = 0
|
|
actVehicle.pickupInfo = {markerName = "Silo 3", fillType = TMR}
|
|
local empty = ADRunsController.getVehicleActivity(adEnv, actVehicle)
|
|
check("C15 tom på vej efter TMR", empty.kind .. "/" .. tostring(empty.place) .. "/" .. tostring(empty.fillType), "empty/Silo 3/" .. TMR)
|
|
actVehicle.waitInfo = {markerName = "Cow Wait", fillType = STRAW, rest = 5000}
|
|
check("C15 venter", ADRunsController.getVehicleActivity(adEnv, actVehicle).kind, "waiting")
|
|
ADUnloadWait = nil
|
|
|
|
-- C16: flere mål pr. run — Auto-varer = union; chooseTarget = den stald der mangler mest; validering
|
|
buildWorld()
|
|
addMarker(99, "Cow 2 Food", "Cow Food", 5200, 0); unloadAt[99] = {accepts = {[STRAW] = 300000, [TMR] = 300000}, levels = {[STRAW] = 0, [TMR] = 0}}
|
|
unloadAt[94].levels = {[STRAW] = 250000, [TMR] = 250000, [WATER] = 50000}
|
|
local multiVehicle = makeVehicle("vehicleMulti", "Multi", {STRAW, TMR, WATER}, 1000000, 100, 0)
|
|
local multi = ADRunsController.createRun("Kvæg")
|
|
ADRunsController.updateRun(multi.id, {targetWayPointIds = {94, 99}})
|
|
local multiRun = ADRuns.getRun(ADRunsController.store, multi.id)
|
|
check("C16 auto-varer = union (vand kun i stald 1)", table.concat(ADRunsController.getRunIngredients(adEnv, multiRun, multiVehicle), ","), WATER .. "," .. STRAW .. "," .. TMR)
|
|
check("C16 accepterede varer = union", #ADRunsController.getTargetAcceptedFillTypes(adEnv, multiRun), 3)
|
|
check("C16 vælger stald 2 (tom)", ADRunsController.chooseTarget(adEnv, multiRun, multiVehicle), 99)
|
|
unloadAt[99].levels = {[STRAW] = 290000, [TMR] = 290000}
|
|
check("C16 vælger stald 1 når stald 2 er fuld", ADRunsController.chooseTarget(adEnv, multiRun, multiVehicle), 94)
|
|
check("C16 validering ok med flere mål", ADRunsController.validateVehicle(adEnv, multiRun, multiVehicle).ok, true)
|
|
-- C16b: en anden vogn er allerede på vej til stald 2 — så vælges stald 1 selvom stald 2 er mindre fyldt
|
|
-- (drive-on-bunker: kun én kan tippe ad gangen; in-game 26/9 kørte 3 biogas-vogne til samme drop)
|
|
unloadAt[99].levels = {[STRAW] = 100000, [TMR] = 100000}
|
|
unloadAt[94].levels = {[STRAW] = 200000, [TMR] = 200000, [WATER] = 50000}
|
|
ADSmartPickup.countEnRoute = function(id, exclude) return id == 99 and 1 or 0 end
|
|
check("C16b ledigt mål foran mindre fyldt mål med vogn på vej", ADRunsController.chooseTarget(adEnv, multiRun, multiVehicle), 94)
|
|
ADSmartPickup.countEnRoute = function() return 1 end
|
|
check("C16b lige mange på vej -> mindst fyldte", ADRunsController.chooseTarget(adEnv, multiRun, multiVehicle), 99)
|
|
ADSmartPickup.countEnRoute = nil
|
|
-- C16c: fyldte traktorer startet i samme run fordeles på målene (in-game 27/9: tre fyldte biogas-traktorer
|
|
-- kørte alle til Drop 1, fordi læs der allerede lå på vognen aldrig blev registreret "på vej")
|
|
do
|
|
unloadAt[99].levels = {[STRAW] = 100000, [TMR] = 100000}
|
|
unloadAt[94].levels = {[STRAW] = 200000, [TMR] = 200000, [WATER] = 50000}
|
|
local onWay = {}
|
|
ADSmartPickup.countEnRoute = function(id, exclude)
|
|
local n = 0
|
|
for v, target in pairs(onWay) do if v ~= exclude and target == id then n = n + 1 end end
|
|
return n
|
|
end
|
|
ADSmartPickup.registerCargo = function(_, v, targetId) onWay[v] = targetId; return true end
|
|
local loadedA = makeVehicle("vehicleLoadedA", "Fyldt A", {STRAW, TMR}, 1000000, 100, 0)
|
|
local loadedB = makeVehicle("vehicleLoadedB", "Fyldt B", {STRAW, TMR}, 1000000, 110, 0)
|
|
local both = ADRunsController.createRun("To fyldte")
|
|
ADRunsController.updateRun(both.id, {targetWayPointIds = {94, 99}})
|
|
ADRunsController.assignVehicle(both.id, loadedA)
|
|
ADRunsController.assignVehicle(both.id, loadedB)
|
|
ADRunsController.startRun(adEnv, both.id)
|
|
local a, b = loadedA.ad.stateModule.secondMarkerId, loadedB.ad.stateModule.secondMarkerId
|
|
check("C16c første fyldte -> mindst fyldte mål", a, 99)
|
|
check("C16c anden fyldte -> det andet mål", b, 94)
|
|
ADSmartPickup.countEnRoute, ADSmartPickup.registerCargo = nil, nil
|
|
end
|
|
ADRunsController.updateRun(multi.id, {targetWayPointIds = {4242}})
|
|
check("C16 kun ukendte mål -> noTarget", ADRunsController.validateVehicle(adEnv, ADRuns.getRun(ADRunsController.store, multi.id), multiVehicle).reason, "noTarget")
|
|
|
|
-- C17: kørende traktor der fjernes fra run stoppes; slettes run, stoppes dets traktorer; Stop logger
|
|
buildWorld()
|
|
local runVehicle = makeVehicle("vehicleR", "Kørende", {STRAW, TMR}, 1000000, 100, 0)
|
|
local stopRun = ADRunsController.createRun("Stop-test")
|
|
ADRunsController.updateRun(stopRun.id, {targetWayPointId = 94})
|
|
ADRunsController.assignVehicle(stopRun.id, runVehicle)
|
|
ADRunsController.startRun(adEnv, stopRun.id)
|
|
check("C17 kører", runVehicle.started, 1)
|
|
ADRunsController.unassignVehicle(runVehicle)
|
|
check("C17 fjernet fra run -> stoppet", runVehicle.stopped, 1)
|
|
ADRunsController.assignVehicle(stopRun.id, runVehicle)
|
|
ADRunsController.startRun(adEnv, stopRun.id)
|
|
ADRunsController.deleteRun(stopRun.id, adEnv)
|
|
check("C17 run slettet -> stoppet", runVehicle.stopped, 2)
|
|
check("C17 stop logget", logLines[#logLines]:find("stoppet", 1, true) ~= nil, true)
|
|
|
|
-- C18: forkert last ved Start (halm på vognen, run mod sukkerfabrik) -> første stop = silo der tager halm
|
|
ADUnloadWait = {getRestLoad = function(_, v) return v.loadType, v.loadLiters or 0 end, getWaitFor = function() return nil end,
|
|
hasRouteBothWays = function() return true end}
|
|
ADLoadSwap = {findDumpMarker = function(_, v, fillType, rest, homeId, isReachable) return {id = 44, name = "10 Silo Storage", markerIndex = 2} end}
|
|
buildWorld()
|
|
addMarker(77, "sugar offload", "Fabrication", 950, 0); unloadAt[77] = {accepts = {[TMR] = 360000}} -- "fabrik" der ikke tager halm (TMR står for roer her)
|
|
local sugarVehicle = makeVehicle("vehicleSugar", "Roe-traktor", {STRAW, TMR}, 20000, 100, 0)
|
|
sugarVehicle.loadType, sugarVehicle.loadLiters = STRAW, 8000
|
|
local sugar = ADRunsController.createRun("Sugar")
|
|
ADRunsController.updateRun(sugar.id, {targetWayPointId = 77})
|
|
ADRunsController.assignVehicle(sugar.id, sugarVehicle)
|
|
ADRunsController.startRun(adEnv, sugar.id)
|
|
check("C18 første stop = siloen (aflæs forkert last)", sugarVehicle.ad.stateModule.secondMarkerId, 44)
|
|
check("C18 logget", logLines[#logLines]:find("læsser", 1, true) ~= nil or logLines[#logLines - 1]:find("læsser", 1, true) ~= nil, true)
|
|
-- rigtig last (TMR=roer) -> direkte til fabrikken
|
|
sugarVehicle.loadType = TMR
|
|
sugarVehicle.ad.stateModule.active = false
|
|
ADRunsController.startRun(adEnv, sugar.id)
|
|
check("C18 rigtig last -> målet", sugarVehicle.ad.stateModule.secondMarkerId, 77)
|
|
-- C18b: målet TAGER varen, men den er ikke en af run'ets valgte varer (gødning i en ensilage-DOB)
|
|
-- -> aflæs i en silo der tager den, ikke i målet
|
|
unloadAt[77].accepts = {[TMR] = 360000, [STRAW] = 360000}
|
|
ADRunsController.updateRun(sugar.id, {ingredientMode = "manual", ingredients = {"FORAGE"}})
|
|
sugarVehicle.loadType = STRAW
|
|
sugarVehicle.ad.stateModule.active = false
|
|
ADRunsController.startRun(adEnv, sugar.id)
|
|
check("C18b forkert vare for run'et -> silo, ikke målet", sugarVehicle.ad.stateModule.secondMarkerId, 44)
|
|
-- auto-varer: alt målet tager hører til -> målet
|
|
ADRunsController.updateRun(sugar.id, {ingredientMode = "auto", ingredients = {}})
|
|
sugarVehicle.ad.stateModule.active = false
|
|
ADRunsController.startRun(adEnv, sugar.id)
|
|
check("C18b auto: målet tager varen -> målet", sugarVehicle.ad.stateModule.secondMarkerId, 77)
|
|
ADUnloadWait = nil; ADLoadSwap = nil
|
|
|
|
-- C19: Wait-markører er aldrig mål — heller ikke når de står inden for 40 m af staldens trigger
|
|
buildWorld()
|
|
-- staldens station med bygning; Wait-markøren ligger i triggerens rækkevidde og "mangler mere" end 94
|
|
local barnPlaceable = {getHusbandryFillLevel = function() return 0 end}
|
|
unloadAt[94].owningPlaceable = barnPlaceable
|
|
addMarker(400, "Cow Wait", "Cow Wait", 5005, 0); unloadAt[400] = {accepts = {[STRAW] = 300000, [TMR] = 300000}, levels = {}, owningPlaceable = barnPlaceable}
|
|
local targetNames = {}
|
|
for _, marker in ipairs(ADRunsController.getTargetMarkers(adEnv, 1)) do table.insert(targetNames, marker.name) end
|
|
check("C19 Wait-markør ikke i mål-listen", table.concat(targetNames, ","):find("Cow Wait", 1, true), nil)
|
|
local waitTargetRun = ADRunsController.createRun("Wait som mål")
|
|
ADRunsController.updateRun(waitTargetRun.id, {targetWayPointIds = {94, 400}})
|
|
local waitVehicle = makeVehicle("vehicleW", "W", {STRAW, TMR}, 20000, 5000, 0)
|
|
check("C19 chooseTarget springer Wait over", ADRunsController.chooseTarget(adEnv, ADRuns.getRun(ADRunsController.store, waitTargetRun.id), waitVehicle), 94)
|
|
|
|
-- C-out: udkørsels-runs — oprettelse, kilder, produkter, validering, start, status
|
|
local BASKET = 7
|
|
FILL_TYPE_NAMES[BASKET] = "STRAW_BASKET"; FILL_TYPE_INDEX["STRAW_BASKET"] = BASKET
|
|
local sourcesAt, productsAt = {}, {}
|
|
ADSources = {
|
|
identify = function(_, id) return sourcesAt[id] end,
|
|
getProducts = function(_, source) return productsAt[source.wayPointId] or {} end,
|
|
getSellMarkers = function() return {} end,
|
|
stationAccepts = function() return false end,
|
|
getSourcePlaceables = function() return {} end,
|
|
}
|
|
local outboundStatus = {reasons = {"SUGAR 78 % af top (kræver 90), lager 41 %"}, warning = nil}
|
|
local holdFor = {}
|
|
ADOutbound = {
|
|
isOutboundVehicle = function(v) local r = ADRunsController.getRunForVehicle(v) return r ~= nil and r.kind == "outbound" end,
|
|
getRunStatus = function() return outboundStatus end,
|
|
getHoldFor = function(v) return holdFor[v] end,
|
|
getTripFor = function() return nil end,
|
|
releaseInactive = function() end,
|
|
}
|
|
ADUnloadWait = {getRestLoad = function() return nil, 0 end, getWaitFor = function() return nil end}
|
|
buildWorld()
|
|
addMarker(1, "Suger Load", "Pickup points", 100, 0); loadAt[1] = {}
|
|
addMarker(3, "Objektlager", "Pickup points", 300, 0)
|
|
addMarker(10, "selling station", "selling", 500, 0)
|
|
sourcesAt[1] = {kind = "factory", wayPointId = 1, station = loadAt[1], name = "Sugar mill"}
|
|
sourcesAt[3] = {kind = "objectStorage", wayPointId = 3, name = "Objektlager"}
|
|
productsAt[1] = {{fillType = TMR, name = "FORAGE", title = "TMR", available = 150000, level = 150000, capacity = 180000, isPallet = false}}
|
|
productsAt[3] = {{fillType = BASKET, name = "STRAW_BASKET", title = "Halmkurve", available = 8000, level = 8, capacity = 4000, isPallet = true}}
|
|
local bulkTractor = makeVehicle("vehicleBulk", "MT635", {STRAW, TMR}, 20000, 100, 0)
|
|
local ualTractor = makeVehicle("vehicleUal", "Fendt", {}, 8000, 300, 0)
|
|
ualTractor.trailers[1] = {ual = true}
|
|
adEnv.AutoDrive.hasAL = function(_, trailer) return trailer.ual == true end
|
|
|
|
local out = ADRunsController.createRun("Sugar out", "outbound")
|
|
check("Cout1 kind", ADRuns.getRun(ADRunsController.store, out.id).kind, "outbound")
|
|
check("Cout1 supply-run har kind supply", ADRunsController.createRun("Cows").kind, "supply")
|
|
check("Cout1 kilde-markører", #ADRunsController.getSourceMarkers(adEnv, 1), 2)
|
|
check("Cout1 første kilde-markør", ADRunsController.getSourceMarkers(adEnv, 1)[1].marker.name, "Objektlager")
|
|
|
|
-- Cout2: validering
|
|
local outRun = ADRuns.getRun(ADRunsController.store, out.id)
|
|
-- diagnose: hvad moden ser på enhederne, når ingen autoload findes (logges én gang pr. traktor,
|
|
-- første gang varerne slås op — dvs. allerede ved noProducts-tjekket nedenfor)
|
|
logLines = {}
|
|
bulkTractor.trailers[1] = {spec_universalAutoload = {isAutoloadAvailable = false, autoloadDisabled = true}, getName = function() return "Vogn" end}
|
|
check("Cout2 ingen kilder -> noSource", ADRunsController.validateVehicle(adEnv, outRun, bulkTractor).reason, "noSource")
|
|
ADRunsController.store = ADRuns.toggleSource(ADRunsController.store, out.id, 1)
|
|
ADRunsController.store = ADRuns.toggleSource(ADRunsController.store, out.id, 3)
|
|
outRun = ADRuns.getRun(ADRunsController.store, out.id)
|
|
check("Cout2 ingen vare valgt -> noProducts", ADRunsController.validateVehicle(adEnv, outRun, bulkTractor).reason, "noProducts")
|
|
ADRunsController.store = ADRuns.setProductPolicy(ADRunsController.store, out.id, "STRAW_BASKET", "sell")
|
|
outRun = ADRuns.getRun(ADRunsController.store, out.id)
|
|
check("Cout2 kun paller uden UAL -> needsAutoload", ADRunsController.validateVehicle(adEnv, outRun, bulkTractor).reason, "needsAutoload")
|
|
local diag = nil
|
|
for _, line in ipairs(logLines) do if line:find("ingen autoload", 1, true) then diag = line end end
|
|
check("Cout2 diagnose logges", diag ~= nil, true)
|
|
check("Cout2 diagnose viser UAL-flag", diag ~= nil and diag:find("isAutoloadAvailable=false", 1, true) ~= nil, true)
|
|
logLines = {}
|
|
ADRunsController.validateVehicle(adEnv, outRun, bulkTractor)
|
|
check("Cout2 diagnose kun én gang", #logLines, 0)
|
|
bulkTractor.trailers[1] = nil
|
|
check("Cout2 UAL-vogn ok", ADRunsController.validateVehicle(adEnv, outRun, ualTractor).ok, true)
|
|
ADRunsController.store = ADRuns.setProductPolicy(ADRunsController.store, out.id, "FORAGE", "store")
|
|
outRun = ADRuns.getRun(ADRunsController.store, out.id)
|
|
check("Cout2 bulk-vogn ok med TMR", ADRunsController.validateVehicle(adEnv, outRun, bulkTractor).ok, true)
|
|
local strawOnly = makeVehicle("vehicleStraw", "Halm", {STRAW}, 20000, 100, 0)
|
|
check("Cout2 kan ikke bære -> cannotCarry", ADRunsController.validateVehicle(adEnv, outRun, strawOnly).reason, "cannotCarry")
|
|
|
|
-- Cout3: start sætter mode, 1./2. markør = første kilde, varevalg = det vognen kan bære af run'ets varer
|
|
ADRunsController.assignVehicle(out.id, bulkTractor)
|
|
ADRunsController.assignVehicle(out.id, ualTractor)
|
|
local results = ADRunsController.startRun(adEnv, out.id)
|
|
check("Cout3 to startet", #results, 2)
|
|
check("Cout3 mode P&D", bulkTractor.ad.stateModule.mode, MODE_PICKUPANDDELIVER)
|
|
check("Cout3 1. markør = første kilde", bulkTractor.ad.stateModule.firstMarkerId, 1)
|
|
check("Cout3 2. markør = første kilde (pladsholder)", bulkTractor.ad.stateModule.secondMarkerId, 1)
|
|
check("Cout3 bulk-vogn: kun TMR", table.concat(bulkTractor.ad.stateModule.selectedFillTypes, ","), tostring(TMR))
|
|
check("Cout3 UAL-vogn: kurve", table.concat(ualTractor.ad.stateModule.selectedFillTypes, ","), tostring(BASKET))
|
|
check("Cout3 rotation kun pålæsning", bulkTractor.ad.settings.rotateTargets.current, 2)
|
|
check("Cout3 startet", bulkTractor.started, 1)
|
|
-- AD's "AL unload" er slået FRA som standard (values[1] = 0): autoload-vognen ville aldrig læsse af
|
|
-- ved salgsstedet. Ved Start sættes den til "center" hvis den er fra; et brugervalg (left/right/behind) røres ikke.
|
|
check("Cout3 ALUnload sat til center for autoload-bil", ualTractor.ad.settings.ALUnload.current, 2)
|
|
check("Cout3 ALUnload rører ikke tipvogn", bulkTractor.ad.settings.ALUnload.current, 1)
|
|
ualTractor.ad.settings.ALUnload.current = 4
|
|
ualTractor.ad.stateModule.active = false
|
|
ADRunsController.startRun(adEnv, out.id)
|
|
check("Cout3 ALUnload brugervalg bevares", ualTractor.ad.settings.ALUnload.current, 4)
|
|
|
|
-- Cout4: produkter til fanen (politik slået op, sorteret på titel) og status
|
|
local list = ADRunsController.getRunProducts(adEnv, outRun)
|
|
check("Cout4 to produkter", #list, 2)
|
|
check("Cout4 første = Halmkurve", list[1].title, "Halmkurve")
|
|
check("Cout4 politik", list[1].policy, "sell")
|
|
check("Cout4 TMR lager", list[2].policy, "store")
|
|
check("Cout4 available", list[2].available, 150000)
|
|
local st = ADRunsController.getOutboundStatus(adEnv, outRun)
|
|
check("Cout4 status-begrundelse", st.reasons[1], "SUGAR 78 % af top (kræver 90), lager 41 %")
|
|
holdFor[bulkTractor] = {markerName = "Wait 3", reasons = {"SUGAR 78 % af top (kræver 90), lager 41 %"}}
|
|
local activity = ADRunsController.getVehicleActivity(adEnv, bulkTractor)
|
|
check("Cout4 aktivitet = holder", activity.kind, "holding")
|
|
check("Cout4 aktivitet sted", activity.place, "Wait 3")
|
|
check("Cout4 udkørsel har ingen mål", #ADRunsController.getRunTargets(outRun), 0)
|
|
-- Cout5 (I2): Start kræver et Wait-punkt i puljen; Cout6 (I3): last på vognen ved Start får eget mål
|
|
ADSupplyPlanner.isWaitMarker = function(marker) return string.find(string.lower(marker.group or ""), "%f[%a]wait%f[%A]") ~= nil end
|
|
local noWait = ADRunsController.createRun("No wait", "outbound")
|
|
ADRunsController.store = ADRuns.toggleSource(ADRunsController.store, noWait.id, 1)
|
|
ADRunsController.store = ADRuns.setProductPolicy(ADRunsController.store, noWait.id, "FORAGE", "store")
|
|
ADRunsController.store = ADRuns.updateRun(ADRunsController.store, noWait.id, {waitPoolGroup = "Pig Wait"})
|
|
ADRunsController.store = ADRuns.updateRun(ADRunsController.store, noWait.id, {waitPoolGroup = "Findes ikke"})
|
|
local noWaitRun = ADRuns.getRun(ADRunsController.store, noWait.id)
|
|
check("Cout5 ingen Wait-punkt i puljen -> noWaitPoint", ADRunsController.validateVehicle(adEnv, noWaitRun, bulkTractor).reason, "noWaitPoint")
|
|
ADRunsController.store = ADRuns.updateRun(ADRunsController.store, noWait.id, {waitPoolGroup = "Cow Wait"})
|
|
noWaitRun = ADRuns.getRun(ADRunsController.store, noWait.id)
|
|
check("Cout5 Wait-punkt findes -> ok", ADRunsController.validateVehicle(adEnv, noWaitRun, bulkTractor).ok, true)
|
|
ADUnloadWait.getRestLoad = function(_, v) return v.loadType, v.loadLiters or 0 end
|
|
ADOutbound.planCargoTarget = function(adEnv, run, vehicle, fillType) return fillType == TMR and 10 or nil end
|
|
bulkTractor.loadType, bulkTractor.loadLiters = TMR, 8000
|
|
ADRunsController.assignVehicle(noWait.id, bulkTractor)
|
|
bulkTractor.ad.stateModule.active = false
|
|
ADRunsController.startRun(adEnv, noWait.id)
|
|
check("Cout6 last på vognen -> 2. markør = lastens mål", bulkTractor.ad.stateModule.secondMarkerId, 10)
|
|
bulkTractor.loadType = STRAW
|
|
check("Cout6 last uden mål -> cargoNoTarget", ADRunsController.validateVehicle(adEnv, noWaitRun, bulkTractor).reason, "cargoNoTarget")
|
|
bulkTractor.loadType = nil
|
|
ADUnloadWait = nil; ADOutbound = nil; ADSources = nil
|
|
|
|
-- C-flow: bygninger -> markører (resolveMarkers), migration af gamle markør-runs, noMarker, flow-rækker
|
|
local buildings = {
|
|
{id = "barn1", name = "Kostald 1", kind = "husbandry", loadMarker = {id = 10, name = "cow 1 milk", distance = 5}, loadMarkers = {{id = 10, name = "cow 1 milk", distance = 5}, {id = 11, name = "cow 1 slurry", distance = 3}}, unloadMarker = {id = 94, name = "Cow 1 Food", distance = 8}, canBeSource = true, canBeTarget = true, canSell = false},
|
|
{id = "shed", name = "Palleskur", kind = "objectStorage", loadMarker = nil, unloadMarker = nil, canBeSource = true, canBeTarget = false, canSell = false},
|
|
{id = "mill", name = "Sukkerfabrik", kind = "factory", loadMarker = {id = 12694, name = "Suger Load", distance = 3}, unloadMarker = {id = 77, name = "sugar offload", distance = 4}, canBeSource = true, canBeTarget = true, canSell = false},
|
|
}
|
|
ADBuildings = {
|
|
list = function() return buildings end,
|
|
find = function(_, _, id) for _, b in ipairs(buildings) do if b.id == id then return b end end end,
|
|
byMarker = function(_, _, wayPointId, role)
|
|
for _, b in ipairs(buildings) do
|
|
if role == "unload" then
|
|
if b.unloadMarker ~= nil and b.unloadMarker.id == wayPointId then return b end
|
|
else
|
|
for _, m in ipairs(b.loadMarkers or {b.loadMarker}) do if m ~= nil and m.id == wayPointId then return b end end
|
|
end
|
|
end
|
|
end,
|
|
}
|
|
ADSources = {identify = function(_, id) return (id == 10 or id == 12694 or id == 555) and {kind = "x", wayPointId = id, name = "k"} or nil end, getProducts = function() return {} end, getSellMarkers = function() return {} end, stationAccepts = function() return false end, getSourcePlaceables = function() return {} end}
|
|
ADOutbound = {isOutboundVehicle = function() return false end, getRunStatus = function() return {reasons = {"SUGAR 78 % af top"}} end, getHoldFor = function() return nil end, getTripFor = function() return nil end, releaseInactive = function() end}
|
|
buildWorld()
|
|
addMarker(10, "cow 1 milk", "Milk", 100, 0); loadAt[10] = {}
|
|
addMarker(555, "raa markoer", "Pickup", 200, 0); loadAt[555] = {}
|
|
addMarker(77, "sugar offload", "production", 950, 0); unloadAt[77] = {accepts = {[TMR] = 360000}}
|
|
-- CF1: udkørsel: bygninger + rå markør -> sourceWayPointIds; manglende markør rapporteres
|
|
local flowOut = ADRunsController.createRun("Milk", "outbound")
|
|
ADRunsController.updateRun(flowOut.id, {sourceBuildingIds = {"barn1", "shed"}, sourceWayPointIds = {555}})
|
|
local resolved = ADRunsController.resolveMarkers(adEnv, ADRuns.getRun(ADRunsController.store, flowOut.id))
|
|
check("CF1 kildemarkører = ALLE bygningens læssemarkører + rå", table.concat(ADRuns.getRun(ADRunsController.store, flowOut.id).sourceWayPointIds, ","), "10,11,555")
|
|
check("CF1 manglende markør", resolved.missing[1], "Palleskur")
|
|
-- en markør der HØRER til en bygning som ikke længere er valgt, fjernes (den er ikke rå)
|
|
ADRunsController.updateRun(flowOut.id, {sourceWayPointIds = {12694, 555}})
|
|
ADRunsController.resolveMarkers(adEnv, ADRuns.getRun(ADRunsController.store, flowOut.id))
|
|
check("CF1 fravalgt bygnings markør fjernes", table.concat(ADRuns.getRun(ADRunsController.store, flowOut.id).sourceWayPointIds, ","), "10,11,555")
|
|
-- CF1b: gamle rå markører ryddes: ikke-kilde (identify = nil) og markør der hører til en valgt bygning
|
|
ADSources.identify = function(_, id)
|
|
if id == 10 or id == 12694 or id == 555 then return {kind = "x", wayPointId = id, name = "k"} end
|
|
if id == 556 then return {kind = "husbandry", wayPointId = id, name = "Kostald 1", placeable = "barn1-placeable"} end
|
|
return nil
|
|
end
|
|
buildings[1].placeable = "barn1-placeable"
|
|
ADRunsController.updateRun(flowOut.id, {sourceBuildingIds = {"barn1"}, sourceWayPointIds = {10, 11, 555, 556, 999}})
|
|
logLines = {}
|
|
ADRunsController.resolveMarkers(adEnv, ADRuns.getRun(ADRunsController.store, flowOut.id))
|
|
check("CF1b rå ikke-kilde og dublet-bygning fjernet", table.concat(ADRuns.getRun(ADRunsController.store, flowOut.id).sourceWayPointIds, ","), "10,11,555")
|
|
local pruneLogged = false
|
|
for _, line in ipairs(logLines) do if line:find("gamle markører fjernet", 1, true) then pruneLogged = true end end
|
|
check("CF1b logget", pruneLogged, true)
|
|
|
|
-- CF1c: et gammelt kilde-id der ikke længere er en AD-MARKØR (AutoDrive har omnummereret waypoints)
|
|
-- fjernes, selv om punktet ligger ved en kilde — ellers kører traktoren til et tilfældigt vejpunkt
|
|
local identifyBefore = ADSources.identify
|
|
ADSources.identify = function(adEnv_, id, farmId)
|
|
if id == 10873 then return {kind = "husbandry", wayPointId = id, name = "Anden stald", placeable = "anden-stald"} end
|
|
return identifyBefore(adEnv_, id, farmId)
|
|
end
|
|
ADRunsController.updateRun(flowOut.id, {sourceBuildingIds = {"barn1"}, sourceWayPointIds = {10, 11, 555, 10873}})
|
|
ADRunsController.resolveMarkers(adEnv, ADRuns.getRun(ADRunsController.store, flowOut.id))
|
|
check("CF1c vejpunkt uden markør fjernet", table.concat(ADRuns.getRun(ADRunsController.store, flowOut.id).sourceWayPointIds, ","), "10,11,555")
|
|
ADSources.identify = identifyBefore
|
|
|
|
-- CF2: forsyning: mål-bygninger -> targetWayPointIds + targetWayPointId
|
|
local flowIn = ADRunsController.createRun("Foder", "supply")
|
|
ADRunsController.updateRun(flowIn.id, {targetBuildingIds = {"barn1", "mill"}})
|
|
ADRunsController.resolveMarkers(adEnv, ADRuns.getRun(ADRunsController.store, flowIn.id))
|
|
check("CF2 målmarkører", table.concat(ADRunsController.getRunTargets(ADRuns.getRun(ADRunsController.store, flowIn.id)), ","), "94,77")
|
|
check("CF2 primært mål", ADRuns.getRun(ADRunsController.store, flowIn.id).targetWayPointId, 94)
|
|
-- CF2b: gamle rå mål der ikke er en markør (slettet i AD) eller hører til en valgt bygning, ryddes
|
|
addMarker(78, "Anden stald food", "Cow Food", 3000, 0); unloadAt[78] = {accepts = {[TMR] = 1000}, owningPlaceable = "anden-stald"}
|
|
unloadAt[11062] = {accepts = {[TMR] = 1000}, owningPlaceable = "anden-stald"} -- waypoint uden markør
|
|
ADRunsController.updateRun(flowIn.id, {targetWayPointIds = {94, 77, 11062, 78}})
|
|
ADRunsController.resolveMarkers(adEnv, ADRuns.getRun(ADRunsController.store, flowIn.id))
|
|
check("CF2b ikke-markør fjernet, rå markør med station beholdt", table.concat(ADRunsController.getRunTargets(ADRuns.getRun(ADRunsController.store, flowIn.id)), ","), "94,77,78")
|
|
ADRunsController.updateRun(flowIn.id, {targetWayPointIds = {94, 77}})
|
|
-- CF3: migration: gamle markør-runs får bygninger
|
|
local oldOut = ADRunsController.createRun("Gammel ud", "outbound")
|
|
ADRunsController.updateRun(oldOut.id, {sourceWayPointIds = {12694, 555}})
|
|
local oldIn = ADRunsController.createRun("Gammel ind", "supply")
|
|
ADRunsController.updateRun(oldIn.id, {targetWayPointIds = {94}})
|
|
ADRunsController.migrateBuildings(adEnv)
|
|
check("CF3 ud: markør -> bygning", ADRuns.getRun(ADRunsController.store, oldOut.id).sourceBuildingIds[1], "mill")
|
|
check("CF3 ud: rå markør uden bygning beholdes", table.concat(ADRuns.getRun(ADRunsController.store, oldOut.id).sourceWayPointIds, ","), "12694,555")
|
|
check("CF3 ind: markør -> bygning", ADRuns.getRun(ADRunsController.store, oldIn.id).targetBuildingIds[1], "barn1")
|
|
ADRunsController.migrateBuildings(adEnv)
|
|
check("CF3 migration er idempotent", #ADRuns.getRun(ADRunsController.store, oldOut.id).sourceBuildingIds, 1)
|
|
-- CF4: validering: valgt bygning uden markør -> noMarker
|
|
local cfVehicle = makeVehicle("vehicleCF", "CF", {STRAW, TMR}, 20000, 100, 0)
|
|
ADRunsController.updateRun(flowOut.id, {sourceBuildingIds = {"shed"}, sourceWayPointIds = {}})
|
|
local cfValidation = ADRunsController.validateVehicle(adEnv, ADRuns.getRun(ADRunsController.store, flowOut.id), cfVehicle)
|
|
check("CF4 noMarker", cfValidation.reason, "noMarker")
|
|
check("CF4 hvilken bygning", cfValidation.missingBuilding, "Palleskur")
|
|
-- CF4b: ÉN bygning uden markør blandt flere med markør -> start alligevel, advar om den ene
|
|
ADRunsController.updateRun(flowOut.id, {sourceBuildingIds = {"barn1", "shed"}, sourceWayPointIds = {}})
|
|
logLines = {}
|
|
local cfValidation2 = ADRunsController.validateVehicle(adEnv, ADRuns.getRun(ADRunsController.store, flowOut.id), cfVehicle)
|
|
check("CF4b ikke afvist pga. markør", cfValidation2.reason ~= "noMarker", true)
|
|
local warned = false
|
|
for _, line in ipairs(logLines) do if line:find("Palleskur", 1, true) and line:find("springes over", 1, true) then warned = true end end
|
|
check("CF4b advarsel nævner bygningen", warned, true)
|
|
-- CF5: flow-række til tavlen
|
|
ADRunsController.updateRun(flowOut.id, {sourceBuildingIds = {"barn1"}, products = {{fillType = "SUGAR", policy = "sell"}, {fillType = "FORAGE", policy = "store"}}, collectRound = true})
|
|
ADRunsController.assignVehicle(flowOut.id, cfVehicle)
|
|
local row = ADRunsController.getFlowRow(adEnv, ADRuns.getRun(ADRunsController.store, flowOut.id))
|
|
check("CF5 vare-navne", table.concat(row.productNames, ","), "SUGAR,FORAGE")
|
|
check("CF5 fra", row.fromNames[1], "Kostald 1")
|
|
check("CF5 politikker", table.concat(row.policies, ","), "sell,store")
|
|
check("CF5 traktor", row.vehicleNames[1], "CF")
|
|
check("CF5 begrundelse", row.reason, "SUGAR 78 % af top")
|
|
check("CF5 runde", row.collectRound, true)
|
|
ADRunsController.updateRun(flowOut.id, {sourceBuildingIds = {"barn1", "shed"}})
|
|
check("CF5 manglende bygning markeres", ADRunsController.getFlowRow(adEnv, ADRuns.getRun(ADRunsController.store, flowOut.id)).missing[1], "Palleskur")
|
|
local rowIn = ADRunsController.getFlowRow(adEnv, ADRuns.getRun(ADRunsController.store, flowIn.id))
|
|
check("CF5 forsyning fra = alle siloer", rowIn.fromAllSilos, true)
|
|
check("CF5 forsyning til", table.concat(rowIn.toNames, ","), "Kostald 1,Sukkerfabrik")
|
|
check("CF5 forsyning auto-varer", rowIn.productAuto, true)
|
|
-- SB: "Lager til" — valgte bygninger -> deres aflæsningsmarkører (i valgt rækkefølge; ukendte udelades)
|
|
do
|
|
local sbRun = ADRunsController.createRun("Gylle", "outbound")
|
|
ADRunsController.updateRun(sbRun.id, {storeBuildingIds = {"mill", "findes-ikke", "barn1"}})
|
|
check("SB markører", table.concat(ADRunsController.getStoreMarkers(adEnv, ADRuns.getRun(ADRunsController.store, sbRun.id)), ","), "77,94")
|
|
ADRunsController.updateRun(sbRun.id, {storeBuildingIds = {}})
|
|
check("SB tom = ingen tvang", #ADRunsController.getStoreMarkers(adEnv, ADRuns.getRun(ADRunsController.store, sbRun.id)), 0)
|
|
end
|
|
-- CS: "Lager til" viser kun bygninger der kan tage flowets lagervarer (æg-paller: kun palleskure der tager æg)
|
|
do
|
|
local EGG, SILAGE = 501, 502
|
|
local shed = {id = "shed1", kind = "objectStorage", placeable = {takesEggs = true}}
|
|
local shedNo = {id = "shed2", kind = "objectStorage", placeable = {takesEggs = false}}
|
|
local silo = {id = "silo9", kind = "silo", placeable = {}, unloadMarker = {id = 901}}
|
|
unloadAt[901] = {accepts = {[SILAGE] = 100000}, getIsFillTypeSupported = function(_, ft) return ft == SILAGE end}
|
|
local accBefore, storeBefore = ADSources.objectStorageAccepts, ADLoadSwap and ADLoadSwap.isStoreTarget
|
|
ADSources.objectStorageAccepts = function(placeable, ft) return ft == EGG and placeable.takesEggs end
|
|
ADLoadSwap = ADLoadSwap or {}
|
|
ADLoadSwap.isStoreTarget = function(station, ft) return station.getIsFillTypeSupported(station, ft) end
|
|
local eggs = {{fillType = EGG, isPallet = true}}
|
|
check("CS palleskur der tager æg", ADRunsController.canStoreAt(adEnv, shed, eggs), true)
|
|
check("CS palleskur der ikke tager æg", ADRunsController.canStoreAt(adEnv, shedNo, eggs), false)
|
|
check("CS silo kan ikke tage æg-paller", ADRunsController.canStoreAt(adEnv, silo, eggs), false)
|
|
check("CS silo tager ensilage", ADRunsController.canStoreAt(adEnv, silo, {{fillType = SILAGE, isPallet = false}}), true)
|
|
ADSources.objectStorageAccepts = accBefore
|
|
ADLoadSwap.isStoreTarget = storeBefore
|
|
end
|
|
ADBuildings = nil; ADSources = nil; ADOutbound = nil
|
|
|
|
-- RC-navne: køretøjer får AD-førernavn efter forløbet; ude af forløb -> modelnavnet igen
|
|
do
|
|
local named = makeVehicle("vehicleNamed", "Virtus 135", {MILK or 1}, 20000, 0, 0)
|
|
named.ad.stateModule.driverName = "Virtus 135"
|
|
named.ad.stateModule.setName = function(self, n) self.driverName = n end
|
|
named.ad.stateModule.getName = function(self) return self.driverName end
|
|
local run = ADRunsController.createRun("Mælk ind", "outbound")
|
|
ADRunsController.assignVehicle(run.id, named)
|
|
ADRunsController.applyVehicleNames(adEnv)
|
|
check("RC-navne sat efter forløb", named.ad.stateModule.driverName, "Mælk ind")
|
|
check("RC-navne label bruger førernavn", ADRuns.vehicleLabel(named), "Mælk ind")
|
|
ADRunsController.store = ADRuns.unassignVehicle(ADRunsController.store, "vehicleNamed")
|
|
ADRunsController.applyVehicleNames(adEnv)
|
|
check("RC-navne ude af forløb -> modelnavn", named.ad.stateModule.driverName, "Virtus 135")
|
|
check("RC-navne label uden AD-navn", ADRuns.vehicleLabel({getName = function() return "Fendt" end}), "Fendt")
|
|
end
|
|
|
|
-- PM: afhentningsmarkører fra udkørsels-forløb (lagerture undgår dem som aflæsningssted)
|
|
do
|
|
local sale = ADRunsController.createRun("Salg-test", "outbound")
|
|
ADRunsController.updateRun(sale.id, {sourceWayPointIds = {4711, 4712}})
|
|
local supply = ADRunsController.createRun("Forsyning-test", "supply")
|
|
ADRunsController.updateRun(supply.id, {sourceWayPointIds = {9999}})
|
|
local pickups = ADRunsController.getPickupMarkers()
|
|
check("PM udkørsels-kilde med", pickups[4711], true)
|
|
check("PM forsyning tæller ikke", pickups[9999], nil)
|
|
end
|
|
|
|
-- SA: Start/Stop alle flows — kørende flows røres ikke ved Start alle; Stop alle stopper alt aktivt
|
|
do
|
|
buildWorld()
|
|
local idle = makeVehicle("vehicleAllA", "Alle A", {STRAW, TMR}, 1000000, 100, 0)
|
|
local busy = makeVehicle("vehicleAllB", "Alle B", {STRAW, TMR}, 1000000, 100, 0)
|
|
local runA = ADRunsController.createRun("Alle-A")
|
|
ADRunsController.updateRun(runA.id, {targetWayPointId = 94})
|
|
ADRunsController.assignVehicle(runA.id, idle)
|
|
local runB = ADRunsController.createRun("Alle-B")
|
|
ADRunsController.updateRun(runB.id, {targetWayPointId = 94})
|
|
ADRunsController.assignVehicle(runB.id, busy)
|
|
ADRunsController.createRun("Alle-tom") -- ingen traktorer: tæller ikke med
|
|
ADRunsController.startRun(adEnv, runB.id)
|
|
local busyStarts = busy.started
|
|
local summary = ADRunsController.startAllRuns(adEnv)
|
|
check("SA idle startet", idle.started, 1)
|
|
check("SA kørende flow ikke genstartet", busy.started, busyStarts)
|
|
check("SA mindst ét flow startet", summary.runsStarted >= 1, true)
|
|
check("SA kørende flow talt", summary.alreadyRunning >= 1, true)
|
|
check("SA traktorer startet tæller idle", summary.vehiclesStarted >= 1, true)
|
|
check("SA resultater med", type(summary.results), "table")
|
|
check("SA noget aktivt", ADRunsController.hasActiveRuns(adEnv), true)
|
|
local stopped = ADRunsController.stopAllRuns(adEnv)
|
|
check("SA stop alle stopper begge", stopped >= 2, true)
|
|
check("SA idle stoppet", idle.ad.stateModule.active, false)
|
|
check("SA busy stoppet", busy.ad.stateModule.active, false)
|
|
check("SA intet aktivt bagefter", ADRunsController.hasActiveRuns(adEnv), false)
|
|
check("SA isRunning ryddet", ADRunsController.getRunStatus(adEnv, ADRuns.getRun(ADRunsController.store, runA.id)).isRunning, false)
|
|
end
|
|
|
|
|
|
-- C20: Start alle i kø — én traktor ad gangen med STAGGER_MS mellemrum (in-game 27/9: ellers kører de
|
|
-- sammen på parkeringspladsen); pause ophæves
|
|
do
|
|
buildWorld()
|
|
local q1 = makeVehicle("vehicleQ1", "Q1", {STRAW, TMR}, 1000000, 100, 0)
|
|
local q2 = makeVehicle("vehicleQ2", "Q2", {STRAW, TMR}, 1000000, 110, 0)
|
|
local q3 = makeVehicle("vehicleQ3", "Q3", {}, 0, 120, 0) -- ingen vogn -> springes over, ikke i kø
|
|
local qrun = ADRunsController.createRun("Kø")
|
|
ADRunsController.updateRun(qrun.id, {targetWayPointIds = {94}})
|
|
ADRunsController.assignVehicle(qrun.id, q1)
|
|
ADRunsController.assignVehicle(qrun.id, q2)
|
|
ADRunsController.assignVehicle(qrun.id, q3)
|
|
local summary = ADRunsController.queueStartAll(adEnv)
|
|
check("C20 to i kø", summary.queued, 2)
|
|
check("C20 en sprunget over", #summary.skipped, 1)
|
|
check("C20 intet startet før første tick", (q1.started or 0) + (q2.started or 0), 0)
|
|
ADRunsController.processStartQueue(adEnv, 0)
|
|
check("C20 første startes straks", (q1.started or 0) + (q2.started or 0), 1)
|
|
ADRunsController.processStartQueue(adEnv, ADRunsController.STAGGER_MS - 1)
|
|
check("C20 næste venter mellemrummet", (q1.started or 0) + (q2.started or 0), 1)
|
|
ADRunsController.processStartQueue(adEnv, 1)
|
|
check("C20 næste efter mellemrummet", (q1.started or 0) + (q2.started or 0), 2)
|
|
check("C20 kø tom", #ADRunsController.startQueue, 0)
|
|
check("C20 run markeret kørende", ADRunsController.runningRuns[qrun.id], true)
|
|
end
|
|
|
|
|
|
-- C21: Stop alt og parkér — stopper flow-traktorerne, sender dem til AD-parkering, sætter pause
|
|
do
|
|
buildWorld()
|
|
local p1 = makeVehicle("vehicleP1", "P1", {STRAW, TMR}, 1000000, 100, 0)
|
|
local p2 = makeVehicle("vehicleP2", "P2", {STRAW, TMR}, 1000000, 110, 0)
|
|
local prun = ADRunsController.createRun("Park")
|
|
ADRunsController.updateRun(prun.id, {targetWayPointIds = {94}})
|
|
ADRunsController.assignVehicle(prun.id, p1)
|
|
ADRunsController.assignVehicle(prun.id, p2)
|
|
ADRunsController.startRun(adEnv, prun.id)
|
|
local parked, paused = {}, nil
|
|
local oldWork, oldJobs, oldSilos = ADFieldWork, ADFieldJobs, ADFieldSilos
|
|
ADFieldWork = {
|
|
parkMarkerId = function(_, v) return v == p1 and 700 or nil end,
|
|
startAd = function(_, v, mode, first) parked[v] = first end,
|
|
stopAllAssignments = function() return {} end,
|
|
}
|
|
ADFieldJobs = {setPaused = function(value) paused = value end}
|
|
ADFieldSilos = {stopAll = function() end}
|
|
ADRunsController.queueStartAll(adEnv)
|
|
local summary = ADRunsController.stopAllAndPark(adEnv)
|
|
check("C21 begge stoppet", (p1.stopped or 0) >= 1 and (p2.stopped or 0) >= 1, true)
|
|
check("C21 P1 kører til parkering", parked[p1], 700)
|
|
check("C21 P2 uden parkering bliver stående", parked[p2], nil)
|
|
check("C21 tæller parkerede", summary.parked, 1)
|
|
check("C21 nævner dem uden parkering", summary.noPark[1], "P2")
|
|
check("C21 pause sat", paused, true)
|
|
check("C21 startkø tømt", #ADRunsController.startQueue, 0)
|
|
check("C21 run ikke længere kørende", ADRunsController.runningRuns[prun.id], nil)
|
|
ADFieldWork, ADFieldJobs, ADFieldSilos = oldWork, oldJobs, oldSilos
|
|
end
|
|
|
|
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
|
os.exit(failures == 0 and 0 or 1)
|