fix(marksilo): review — flerværdi-valg som MultiTextOption, lagerreservation på tværs af runder, vagt kun før start, rutetjek + straks-fejl pauses, rotation fra på lånte vogne, kræver parkering, flow-siloer udelades, slettede vogne og små rester håndteres
This commit is contained in:
@@ -61,6 +61,11 @@ function ADFieldSiloPlanner.plan(input)
|
||||
for _, loan in ipairs(input.loans or {}) do
|
||||
local k = key(loan.siloId, loan.fillType)
|
||||
onWay[k] = (onWay[k] or 0) + (loan.liters or 0)
|
||||
-- læs på vej til et lager optager pladsen, til de er aflæsset (også i senere runder)
|
||||
if loan.storeId ~= nil then
|
||||
local reserveKey = loan.storeId .. ":" .. tostring(loan.fillType)
|
||||
reserved[reserveKey] = (reserved[reserveKey] or 0) + (loan.liters or 0)
|
||||
end
|
||||
end
|
||||
local status, tasks = {}, {}
|
||||
for _, silo in ipairs(input.silos or {}) do
|
||||
|
||||
@@ -9,6 +9,8 @@ ADFieldSilos.PLAN_INTERVAL_MS = 60000
|
||||
ADFieldSilos.CHECK_INTERVAL_MS = 2000
|
||||
ADFieldSilos.STUCK_MS = 120000
|
||||
ADFieldSilos.PAUSE_MS = 600000
|
||||
ADFieldSilos.FAIL_MS = 30000 -- AD slukket inden for 30 s uden fremdrift = turen kunne ikke køres
|
||||
ADFieldSilos.CARGO_MIN_LITERS = 100 -- rest under dette tæller ikke som last
|
||||
ADFieldSilos.MOVING_SPEED = 0.00028 -- m/ms, samme grænse som AutoDrive
|
||||
ADFieldSilos.FILE_NAME = "ADSmartPickup_fieldsilos.xml"
|
||||
ADFieldSilos.ROOT = "ADSmartPickupFieldSilos"
|
||||
@@ -22,13 +24,18 @@ local planTimerMs, checkTimerMs, nowMs = ADFieldSilos.PLAN_INTERVAL_MS, 0, 0
|
||||
|
||||
-- ---- ren frigivelsesregel ----
|
||||
|
||||
-- vehicleState = {adActive, controlled, fill, moving}
|
||||
-- vehicleState = {adActive, controlled, fill, moving}. Fremdrift = kører, eller fyldningen ændrer sig (læsser
|
||||
-- eller aflæsser). Vagten gælder kun før turen er kommet i gang — kø ved siloen/lageret er normalt.
|
||||
function ADFieldSilos.releaseReason(loan, vehicleState, now)
|
||||
if vehicleState.controlled then return "player" end
|
||||
if not vehicleState.adActive then return "done" end
|
||||
if vehicleState.moving then return nil end
|
||||
if (vehicleState.fill or 0) > (loan.lastFill or 0) then return nil end
|
||||
if now - (loan.lastProgressMs or loan.startedMs or 0) > ADFieldSilos.STUCK_MS then return "stuck" end
|
||||
local progressing = vehicleState.moving or (vehicleState.fill or 0) ~= (loan.lastFill or 0)
|
||||
local hasProgressed = loan.hasProgressed or progressing
|
||||
local age = now - (loan.startedMs or 0)
|
||||
if not vehicleState.adActive then
|
||||
return (not hasProgressed and age < ADFieldSilos.FAIL_MS) and "failed" or "done"
|
||||
end
|
||||
if hasProgressed then return nil end
|
||||
if age > ADFieldSilos.STUCK_MS then return "stuck" end
|
||||
return nil
|
||||
end
|
||||
|
||||
@@ -91,6 +98,18 @@ local function firstMarker(building, role)
|
||||
return markers[1] ~= nil and markers[1].id or nil
|
||||
end
|
||||
|
||||
-- Bygninger der er kilde, mål eller lager i et flow: dem tømmer marksilo-flowet ikke (de hører til den drift).
|
||||
local function runBuildingIds()
|
||||
local ids = {}
|
||||
local store = ADRunsController ~= nil and ADRunsController.store or nil
|
||||
for _, run in ipairs(store ~= nil and store.runs or {}) do
|
||||
for _, list in ipairs({run.sourceBuildingIds or {}, run.targetBuildingIds or {}, run.storeBuildingIds or {}}) do
|
||||
for _, id in ipairs(list) do ids[id] = true end
|
||||
end
|
||||
end
|
||||
return ids
|
||||
end
|
||||
|
||||
-- Gårdlagre fra opsætningen + marksiloer (alle markers marksiloer, uden dubletter og uden gårdlagre).
|
||||
function ADFieldSilos.collectBuildings(adEnv)
|
||||
local fid = farmId()
|
||||
@@ -103,7 +122,7 @@ function ADFieldSilos.collectBuildings(adEnv)
|
||||
x = x, z = z, free = siloFree(building.placeable)})
|
||||
end
|
||||
end
|
||||
local silos, seen = {}, {}
|
||||
local silos, seen = {}, runBuildingIds()
|
||||
for _, info in ipairs(ADFields.list()) do
|
||||
for _, building in ipairs(ADFields.fieldSilos(adEnv, fid, info)) do
|
||||
if not seen[building.id] and not ADFieldSiloConfig.hasStore(ADFieldSilos.config, building.id) then
|
||||
@@ -126,7 +145,7 @@ local function trailerInfo(adEnv, vehicle)
|
||||
for fillType in pairs(object.getFillUnitSupportedFillTypes ~= nil and object:getFillUnitSupportedFillTypes(index) or {}) do
|
||||
carries[fillType] = true
|
||||
end
|
||||
if (object:getFillUnitFillLevel(index) or 0) > 0 then cargo = object:getFillUnitFillType(index) end
|
||||
if (object:getFillUnitFillLevel(index) or 0) >= ADFieldSilos.CARGO_MIN_LITERS then cargo = object:getFillUnitFillType(index) end
|
||||
end
|
||||
end
|
||||
return capacity, carries, cargo
|
||||
@@ -140,7 +159,9 @@ end
|
||||
function ADFieldSilos.collectVehicles(adEnv)
|
||||
local vehicles, byId = {}, {}
|
||||
for _, rig in ipairs(ADFieldWork.getRigs(adEnv)) do
|
||||
if rig.role == "unloader" and rig.enabled and not rig.busy and not rig.controlled then
|
||||
-- uden AD-parkeringspunkt bliver vognen holdende på lagerets markør og spærrer for de næste
|
||||
local canPark = ADFieldWork.parkMarkerId == nil or ADFieldWork.parkMarkerId(adEnv, rig.vehicle) ~= nil
|
||||
if rig.role == "unloader" and rig.enabled and not rig.busy and not rig.controlled and canPark then
|
||||
local capacity, carries, cargo = trailerInfo(adEnv, rig.vehicle)
|
||||
table.insert(vehicles, {id = rig.id, x = rig.x, z = rig.z, capacity = capacity, carries = carries, cargo = cargo})
|
||||
byId[rig.id] = rig.vehicle
|
||||
@@ -166,10 +187,14 @@ local function dispatchOne(adEnv, order, vehicle, silosById, storesById)
|
||||
module.loopCounter = 1
|
||||
if module.setLoopsDone ~= nil then module:setLoopsDone(0) end
|
||||
ADFieldWork.enableParkAtJobFinished(vehicle)
|
||||
-- rotation fra: ellers kan modens egne pickup-hooks sende vognen til en anden silo i mappen
|
||||
if ADRunsController ~= nil and ADRunsController.setSetting ~= nil then
|
||||
ADRunsController.setSetting(adEnv, vehicle, "rotateTargets", adEnv.AutoDrive.RT_NONE)
|
||||
end
|
||||
module:raiseDirtyFlag()
|
||||
ADFieldWork.startAd(adEnv, vehicle, adEnv.AutoDrive.MODE_PICKUPANDDELIVER, order.siloMarkerId, order.storeMarkerId, order.fillType)
|
||||
local silo, store = silosById[order.siloId], storesById[order.storeId]
|
||||
loans[vehicle] = {siloId = order.siloId, siloName = silo ~= nil and silo.name or order.siloId, fillType = order.fillType,
|
||||
loans[vehicle] = {siloId = order.siloId, storeId = order.storeId, siloName = silo ~= nil and silo.name or order.siloId, fillType = order.fillType,
|
||||
liters = order.liters, startedMs = nowMs, lastProgressMs = nowMs, lastFill = fillLevel(adEnv, vehicle)}
|
||||
Logging.info(ADFieldSilos.LOG_PREFIX .. "'%s' henter %d l %s i %s -> %s", tostring(ADRuns.vehicleLabel(vehicle)),
|
||||
math.floor(order.liters), fillTypeName(order.fillType), tostring(silo ~= nil and silo.name or order.siloId),
|
||||
@@ -180,12 +205,13 @@ local function release(adEnv, vehicle, reason)
|
||||
local loan = loans[vehicle]
|
||||
loans[vehicle] = nil
|
||||
if loan == nil then return end
|
||||
if reason == "stuck" then
|
||||
if reason == "stuck" or reason == "failed" then
|
||||
local k = ADFieldSiloPlanner.key(loan.siloId, loan.fillType)
|
||||
paused[k] = nowMs + ADFieldSilos.PAUSE_MS
|
||||
pcall(vehicle.stopAutoDrive, vehicle)
|
||||
Logging.warning(ADFieldSilos.LOG_PREFIX .. "'%s' kom ikke i gang ved %s (%s) på 2 min — stoppet; siloen springes over i 10 min",
|
||||
tostring(ADRuns.vehicleLabel(vehicle)), tostring(loan.siloName), fillTypeName(loan.fillType))
|
||||
local why = reason == "stuck" and "kom ikke i gang på 2 min — stoppet" or "AutoDrive stoppede turen med det samme (rute/læssested?)"
|
||||
Logging.warning(ADFieldSilos.LOG_PREFIX .. "'%s' ved %s (%s): %s; siloen springes over i 10 min",
|
||||
tostring(ADRuns.vehicleLabel(vehicle)), tostring(loan.siloName), fillTypeName(loan.fillType), why)
|
||||
elseif reason == "stopped" then
|
||||
pcall(vehicle.stopAutoDrive, vehicle)
|
||||
end
|
||||
@@ -202,6 +228,10 @@ local function checkLoans(adEnv)
|
||||
local list = {}
|
||||
for vehicle in pairs(loans) do table.insert(list, vehicle) end
|
||||
for _, vehicle in ipairs(list) do
|
||||
if vehicle.isDeleted then
|
||||
loans[vehicle] = nil -- solgt/slettet mens den var lånt
|
||||
else
|
||||
local ok, err = pcall(function()
|
||||
local loan = loans[vehicle]
|
||||
local stateModule = vehicle.ad ~= nil and vehicle.ad.stateModule or nil
|
||||
local fill = fillLevel(adEnv, vehicle)
|
||||
@@ -210,10 +240,16 @@ local function checkLoans(adEnv)
|
||||
controlled = vehicle.getIsControlled ~= nil and vehicle:getIsControlled() or false,
|
||||
fill = fill, moving = (vehicle.lastSpeedReal or 0) >= ADFieldSilos.MOVING_SPEED,
|
||||
}
|
||||
if vehicleState.moving or fill > (loan.lastFill or 0) then loan.lastProgressMs = nowMs end
|
||||
loan.lastFill = math.max(loan.lastFill or 0, fill)
|
||||
local reason = ADFieldSilos.releaseReason(loan, vehicleState, nowMs)
|
||||
if vehicleState.moving or fill ~= (loan.lastFill or 0) then loan.hasProgressed = true end
|
||||
loan.lastFill = fill
|
||||
if reason ~= nil then release(adEnv, vehicle, reason) end
|
||||
end)
|
||||
if not ok then
|
||||
loans[vehicle] = nil
|
||||
Logging.warning(ADFieldSilos.LOG_PREFIX .. "lån opgivet (fejl): %s", tostring(err))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -227,10 +263,24 @@ end
|
||||
|
||||
local function loanList()
|
||||
local list = {}
|
||||
for _, loan in pairs(loans) do table.insert(list, {siloId = loan.siloId, fillType = loan.fillType, liters = loan.liters}) end
|
||||
for _, loan in pairs(loans) do table.insert(list, {siloId = loan.siloId, storeId = loan.storeId, fillType = loan.fillType, liters = loan.liters}) end
|
||||
return list
|
||||
end
|
||||
|
||||
-- Rute fra vognen til siloen og videre til lageret (samme opslag som Wait-punkterne); én advarsel pr. kombination.
|
||||
local warnedRoute = {}
|
||||
local function hasRoutes(adEnv, vehicle, order)
|
||||
if ADUnloadWait == nil or ADUnloadWait.hasRouteTo == nil then return true end
|
||||
local ok = ADUnloadWait.hasRouteTo(adEnv, vehicle, order.siloMarkerId) and ADUnloadWait.hasRouteTo(adEnv, vehicle, order.storeMarkerId)
|
||||
local warnKey = tostring(order.vehicleId) .. ">" .. tostring(order.siloMarkerId)
|
||||
if not ok and not warnedRoute[warnKey] then
|
||||
warnedRoute[warnKey] = true
|
||||
Logging.warning(ADFieldSilos.LOG_PREFIX .. "ingen AutoDrive-rute for '%s' til marksilo-markør %s eller gårdlager-markør %s",
|
||||
tostring(ADRuns.vehicleLabel(vehicle)), tostring(order.siloMarkerId), tostring(order.storeMarkerId))
|
||||
end
|
||||
return ok
|
||||
end
|
||||
|
||||
function ADFieldSilos.planNow(adEnv)
|
||||
local cfg = ADFieldSilos.config
|
||||
local silos, stores = ADFieldSilos.collectBuildings(adEnv)
|
||||
@@ -244,6 +294,9 @@ function ADFieldSilos.planNow(adEnv)
|
||||
for _, store in ipairs(stores) do storesById[store.id] = store end
|
||||
for _, order in ipairs(plan.dispatch) do
|
||||
local vehicle = vehiclesById[order.vehicleId]
|
||||
if vehicle ~= nil and not hasRoutes(adEnv, vehicle, order) then
|
||||
vehicle = nil
|
||||
end
|
||||
if vehicle ~= nil then
|
||||
local ok, err = pcall(dispatchOne, adEnv, order, vehicle, silosById, storesById)
|
||||
if not ok then
|
||||
|
||||
@@ -99,6 +99,7 @@ local function parkMarkerId(adEnv, vehicle)
|
||||
local marker = adEnv.ADGraphManager:getMapMarkerById(index)
|
||||
return marker ~= nil and marker.id or nil
|
||||
end
|
||||
ADFieldWork.parkMarkerId = parkMarkerId
|
||||
|
||||
local function restLoad(adEnv, vehicle)
|
||||
local ok, level = pcall(function()
|
||||
|
||||
@@ -911,6 +911,7 @@ local function setSetting(adEnv, vehicle, settingName, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
ADRunsController.setSetting = setSetting
|
||||
|
||||
-- Nærmeste markør med en læssestation: kun en gyldig start — moden vælger den reelle kilde pr. tur.
|
||||
local function findNearestLoadMarker(adEnv, vehicle, farmId)
|
||||
|
||||
@@ -21,14 +21,24 @@ local function indexOf(list, value)
|
||||
return 1
|
||||
end
|
||||
|
||||
-- Valg med flere værdier: productPrefab (MultiTextOption). ingredientPrefab er en BinaryOption med kun to sider.
|
||||
function SmartPickupFrame:addFieldSiloChoiceRow(kind, title, texts, state)
|
||||
local element = self:addRow(self.productPrefab, {kind = kind})
|
||||
local option = element:getDescendantByName("option")
|
||||
option:setTexts(texts)
|
||||
option:setState(state, false)
|
||||
element:getDescendantByName("title"):setText(title)
|
||||
local tooltip = option:getDescendantByName("ignore")
|
||||
if tooltip ~= nil then tooltip:setText("") end
|
||||
return option
|
||||
end
|
||||
|
||||
function SmartPickupFrame:fillFieldSiloRows(adEnv)
|
||||
local i18n, cfg = self.i18n, ADFieldSilos.config
|
||||
local onOff = {i18n:getText("ui_no"), i18n:getText("ui_yes")}
|
||||
self:addToggleRow("fsEnabled", i18n:getText("spu_fs_enabled"), onOff, cfg.enabled)
|
||||
local maxOption = self:addToggleRow("fsMaxVehicles", i18n:getText("spu_fs_maxVehicles"), numberTexts(1, ADFieldSiloConfig.MAX_VEHICLES), false)
|
||||
maxOption:setState(cfg.maxVehicles, false)
|
||||
local minOption = self:addToggleRow("fsMinLiters", i18n:getText("spu_fs_minLiters"), literTexts(), false)
|
||||
minOption:setState(indexOf(ADFieldSiloConfig.MIN_LITERS_CHOICES, cfg.minLiters), false)
|
||||
self:addFieldSiloChoiceRow("fsMaxVehicles", i18n:getText("spu_fs_maxVehicles"), numberTexts(1, ADFieldSiloConfig.MAX_VEHICLES), cfg.maxVehicles)
|
||||
self:addFieldSiloChoiceRow("fsMinLiters", i18n:getText("spu_fs_minLiters"), literTexts(), indexOf(ADFieldSiloConfig.MIN_LITERS_CHOICES, cfg.minLiters))
|
||||
|
||||
local plan = ADFieldSilos.lastPlan
|
||||
local waiting = 0
|
||||
|
||||
@@ -119,6 +119,9 @@ function SmartPickupFrame:onClickProduct(state, element)
|
||||
if clicked ~= nil and clicked.kind == "storageBuilding" then
|
||||
return self:safe(function(frame) frame:onClickStorageBuilding(state) end)
|
||||
end
|
||||
if clicked ~= nil and SmartPickupFrame.FIELDSILO_ROW_KINDS ~= nil and SmartPickupFrame.FIELDSILO_ROW_KINDS[clicked.kind] then
|
||||
return self:onClickFieldSiloRow(state, clicked)
|
||||
end
|
||||
if clicked ~= nil and SmartPickupFrame.FIELD_ROW_KINDS ~= nil and SmartPickupFrame.FIELD_ROW_KINDS[clicked.kind] then
|
||||
return self:onClickFieldRow(state, clicked)
|
||||
end
|
||||
|
||||
@@ -75,5 +75,14 @@ local input = base({silos = {silo("A", 500, {[WHEAT] = 90000})}, vehicles = {veh
|
||||
P.plan(input)
|
||||
check("input.stores urørt", input.stores[1].free[WHEAT], 1000000)
|
||||
|
||||
|
||||
-- I1: lån på vej til et lager reserverer pladsen på tværs af planlægningsrunder
|
||||
r = P.plan(base({stores = {store("s", 400, {[WHEAT] = 30000})}, silos = {silo("A", 500, {[WHEAT] = 90000})},
|
||||
loans = {{siloId = "A", fillType = WHEAT, liters = 30000, storeId = "s"}}, vehicles = {vehicle("v1", 400, 50000)}}))
|
||||
check("I1 lager fyldt af lån på vej -> ingen ny vogn dertil", #r.dispatch, 0)
|
||||
r = P.plan(base({stores = {store("s", 400, {[WHEAT] = 30000}), store("t", 900, {[WHEAT] = 500000})}, silos = {silo("A", 500, {[WHEAT] = 90000})},
|
||||
loans = {{siloId = "A", fillType = WHEAT, liters = 30000, storeId = "s"}}, vehicles = {vehicle("v1", 400, 50000)}}))
|
||||
check("I1 næste vogn til det andet lager", r.dispatch[1] ~= nil and r.dispatch[1].storeId, "t")
|
||||
|
||||
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
||||
os.exit(failures == 0 and 0 or 1)
|
||||
|
||||
@@ -12,13 +12,20 @@ local function check(name, actual, expected)
|
||||
end
|
||||
local loan = {startedMs = 0, lastProgressMs = 0, lastFill = 0}
|
||||
check("kører, tidligt -> behold", S.releaseReason(loan, {adActive = true, controlled = false, fill = 0, moving = true}, 5000), nil)
|
||||
check("AD slukket -> done", S.releaseReason(loan, {adActive = false, controlled = false, fill = 0}, 5000), "done")
|
||||
check("AD slukket efter 40 s -> done", S.releaseReason(loan, {adActive = false, controlled = false, fill = 0}, 40000), "done")
|
||||
check("spiller i vognen -> player", S.releaseReason(loan, {adActive = true, controlled = true, fill = 0}, 5000), "player")
|
||||
check("står stille uden fyld i 120 s -> stuck", S.releaseReason(loan, {adActive = true, controlled = false, fill = 0, moving = false}, 120001), "stuck")
|
||||
check("kører stadig efter 120 s -> behold", S.releaseReason(loan, {adActive = true, controlled = false, fill = 0, moving = true}, 120001), nil)
|
||||
local loading = {startedMs = 0, lastProgressMs = 110000, lastFill = 0}
|
||||
check("fyldning steg for nylig -> behold", S.releaseReason(loading, {adActive = true, controlled = false, fill = 20000, moving = false}, 125000), nil)
|
||||
|
||||
-- I2/I3: vagten gælder kun før turen er kommet i gang; AD der slukker straks uden fremdrift = fejl
|
||||
local going = {startedMs = 0, lastFill = 30000, hasProgressed = true}
|
||||
check("I2 i gang, står i kø 500 s -> behold", S.releaseReason(going, {adActive = true, controlled = false, fill = 30000, moving = false}, 500000), nil)
|
||||
check("I2 aflæsning (fyld falder) er fremdrift", S.releaseReason({startedMs = 0, lastFill = 30000}, {adActive = true, controlled = false, fill = 20000, moving = false}, 500000), nil)
|
||||
check("I3 AD slukket efter 10 s uden fremdrift -> failed", S.releaseReason({startedMs = 0, lastFill = 0}, {adActive = false, controlled = false, fill = 0}, 10000), "failed")
|
||||
check("I3 AD slukket efter 10 s med fremdrift -> done", S.releaseReason({startedMs = 0, lastFill = 0, hasProgressed = true}, {adActive = false, controlled = false, fill = 0}, 10000), "done")
|
||||
|
||||
-- Røgtest af spil-laget med mocks: planNow låner nærmeste tømmevogn, isLoaned = optaget,
|
||||
-- frakobling (setConfig enabled=false) stopper AD og frigiver (Review Focus).
|
||||
do
|
||||
@@ -34,7 +41,9 @@ do
|
||||
ADBuildings = {list = function() return {fieldSilo, farm} end,
|
||||
getMarkers = function(b, role) return {{id = b.id .. "-" .. role}} end}
|
||||
ADFields = {list = function() return {{id = 1}} end, fieldSilos = function() return {fieldSilo, farm} end}
|
||||
local started = {}
|
||||
local started, settingsSet, noPark, noRoute, residue = {}, {}, {}, {}, 0
|
||||
ADRunsController = {store = {runs = {}}, setSetting = function(_, v, name, value) settingsSet[v] = settingsSet[v] or {}; settingsSet[v][name] = value end}
|
||||
ADUnloadWait = {hasRouteTo = function(_, _, id) return not noRoute[id] end}
|
||||
local function makeVehicle(name, x)
|
||||
local module = {active = false}
|
||||
function module:setMode() end
|
||||
@@ -48,18 +57,23 @@ do
|
||||
stopAutoDrive = function(self) self.ad.stateModule.active = false; self.stopped = true end}
|
||||
end
|
||||
local near, far = makeVehicle("Nær", 900), makeVehicle("Fjern", 5000)
|
||||
local adEnv = {AutoDrive = {MODE_PICKUPANDDELIVER = 2,
|
||||
local adEnv = {AutoDrive = {MODE_PICKUPANDDELIVER = 2, RT_NONE = 0,
|
||||
getAllDischargeableUnits = function() return {{fillUnitIndex = 1, object = {
|
||||
getFillUnitCapacity = function() return 40000 end,
|
||||
getFillUnitSupportedFillTypes = function() return {[WHEAT] = true} end,
|
||||
getFillUnitFillLevel = function() return 0 end, getFillUnitFillType = function() return WHEAT end}}} end,
|
||||
getFillUnitFillLevel = function() return residue end, getFillUnitFillType = function() return WHEAT end}}} end,
|
||||
getAllUnits = function() return {} end, getAllFillLevels = function() return 0 end}}
|
||||
ADFieldWork = {
|
||||
getRigs = function() return {
|
||||
{id = "n", vehicle = near, role = "unloader", enabled = true, busy = S.isLoaned(near), controlled = false, x = 900, z = 0},
|
||||
{id = "f", vehicle = far, role = "unloader", enabled = true, busy = S.isLoaned(far), controlled = false, x = 5000, z = 0},
|
||||
{id = "h", vehicle = far, role = "harvester", enabled = true, busy = false, controlled = false, x = 1000, z = 0}} end,
|
||||
getRigs = function()
|
||||
local rigs = {}
|
||||
-- som spillets vehicleSystem: slettede køretøjer er ikke med
|
||||
if not near.isDeleted then table.insert(rigs, {id = "n", vehicle = near, role = "unloader", enabled = true, busy = S.isLoaned(near), controlled = false, x = 900, z = 0}) end
|
||||
if not far.isDeleted then table.insert(rigs, {id = "f", vehicle = far, role = "unloader", enabled = true, busy = S.isLoaned(far), controlled = false, x = 5000, z = 0}) end
|
||||
table.insert(rigs, {id = "h", vehicle = far, role = "harvester", enabled = true, busy = false, controlled = false, x = 1000, z = 0})
|
||||
return rigs
|
||||
end,
|
||||
enableParkAtJobFinished = function() end,
|
||||
parkMarkerId = function(_, v) if noPark[v] then return nil end return 777 end,
|
||||
startAd = function(_, v, _, first, second, fillType) v.ad.stateModule.active = true; table.insert(started, {v = v, first = first, second = second, fillType = fillType}) end,
|
||||
}
|
||||
S.setConfig(ADFieldSiloConfig.with(ADFieldSiloConfig.toggleStore(ADFieldSiloConfig.new(), "farm"), {enabled = true, maxVehicles = 1}))
|
||||
@@ -72,9 +86,52 @@ do
|
||||
check("RØG gårdlager er ikke marksilo", #plan.status, 1)
|
||||
check("RØG vognen er lånt", S.isLoaned(near), true)
|
||||
check("RØG x nået -> ingen flere", #S.planNow(adEnv).dispatch, 0)
|
||||
check("I4 rotation slået fra på lånt vogn", settingsSet[near] ~= nil and settingsSet[near].rotateTargets, 0)
|
||||
S.setConfig(ADFieldSiloConfig.with(S.config, {enabled = false}))
|
||||
check("RØG frakobling stopper AD", near.stopped, true)
|
||||
check("RØG frakobling frigiver", S.isLoaned(near), false)
|
||||
|
||||
-- I5: vogn uden parkeringspunkt lånes ikke (ville blive holdende på lagerets markør)
|
||||
started = {}
|
||||
noPark[near] = true
|
||||
near.stopped = nil
|
||||
S.setConfig(ADFieldSiloConfig.with(S.config, {enabled = true}))
|
||||
S.planNow(adEnv)
|
||||
check("I5 uden parkering -> fjern vogn med parkering", started[1] ~= nil and started[1].v.name, "Fjern")
|
||||
S.setConfig(ADFieldSiloConfig.with(S.config, {enabled = false}))
|
||||
noPark[near] = nil
|
||||
|
||||
-- I3: ingen rute til siloen -> ingen afsendelse
|
||||
started = {}
|
||||
noRoute["fs-load"] = true
|
||||
S.setConfig(ADFieldSiloConfig.with(S.config, {enabled = true}))
|
||||
S.planNow(adEnv)
|
||||
check("I3 ingen rute -> ingen afsendelse", #started, 0)
|
||||
noRoute["fs-load"] = nil
|
||||
S.setConfig(ADFieldSiloConfig.with(S.config, {enabled = false}))
|
||||
|
||||
-- I6: silo der er kilde/mål i et flow er ikke marksilo
|
||||
ADRunsController.store.runs = {{kind = "supply", sourceBuildingIds = {}, targetBuildingIds = {"fs"}, storeBuildingIds = {}}}
|
||||
local silos = S.collectBuildings(adEnv)
|
||||
check("I6 silo i et flow tømmes ikke", #silos, 0)
|
||||
ADRunsController.store.runs = {}
|
||||
|
||||
-- M5: rest under 100 l tæller ikke som last
|
||||
residue = 50
|
||||
local vehicles = S.collectVehicles(adEnv)
|
||||
check("M5 rest på 50 l er ikke last", vehicles[1].cargo, nil)
|
||||
residue = 0
|
||||
|
||||
-- M4: slettet lånt vogn fjernes uden at vælte tick
|
||||
S.setConfig(ADFieldSiloConfig.with(S.config, {enabled = true}))
|
||||
started = {}
|
||||
S.planNow(adEnv)
|
||||
local loaned = started[1] ~= nil and started[1].v or nil
|
||||
if loaned ~= nil then loaned.isDeleted = true end
|
||||
local okTick = pcall(S.tick, adEnv, 2000)
|
||||
check("M4 tick tåler slettet vogn", okTick, true)
|
||||
check("M4 slettet vogn frigivet", loaned ~= nil and S.isLoaned(loaned), false)
|
||||
S.setConfig(ADFieldSiloConfig.with(S.config, {enabled = false}))
|
||||
end
|
||||
|
||||
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
||||
|
||||
Reference in New Issue
Block a user