feat: køretøjer navngives efter deres flow (AD-førernavn 'Milk Collect 1'), bruges i log og menu; modelnavn tilbage ved udmeldelse (v1.17.0.0)

This commit is contained in:
2026-09-24 03:14:28 +02:00
parent d63f0fcd5e
commit 65dd202e1b
12 changed files with 176 additions and 47 deletions
+2 -2
View File
@@ -121,7 +121,7 @@ function ADLoadSwap.tryFromWait(adEnv, task, wait, dt, redirect, release, isReac
if marker == nil then
if not warnedNoSilo[vehicle] then
warnedNoSilo[vehicle] = true
Logging.warning(ADLoadSwap.LOG_PREFIX .. "'%s' venter med %.0f l %s (%s) — %s; den bliver ved Wait-punktet", tostring(vehicle:getName()), wait.rest, tostring(restName), missing ~= nil and ("målet mangler " .. tostring(missingName)) or "målet tager ikke varen", tostring(why))
Logging.warning(ADLoadSwap.LOG_PREFIX .. "'%s' venter med %.0f l %s (%s) — %s; den bliver ved Wait-punktet", tostring(ADRuns.vehicleLabel(vehicle)), wait.rest, tostring(restName), missing ~= nil and ("målet mangler " .. tostring(missingName)) or "målet tager ikke varen", tostring(why))
end
return false
end
@@ -129,7 +129,7 @@ function ADLoadSwap.tryFromWait(adEnv, task, wait, dt, redirect, release, isReac
release(vehicle)
redirect(task, marker.id)
local why = missing ~= nil and ("målet mangler " .. tostring(missingName)) or "målet tager ikke varen"
Logging.info(ADLoadSwap.LOG_PREFIX .. "'%s' bytter læs: %.0f l %s tilbage i %s (markør %s), %s", tostring(vehicle:getName()), wait.rest, tostring(restName), tostring(marker.name), tostring(marker.markerIndex or marker.id), why)
Logging.info(ADLoadSwap.LOG_PREFIX .. "'%s' bytter læs: %.0f l %s tilbage i %s (markør %s), %s", tostring(ADRuns.vehicleLabel(vehicle)), wait.rest, tostring(restName), tostring(marker.name), tostring(marker.markerIndex or marker.id), why)
return true
end
+16 -16
View File
@@ -245,7 +245,7 @@ function ADOutbound.buildPlanInput(adEnv, run, vehicle)
if warned[vehicle] == nil or warned[vehicle][key] ~= text then
warned[vehicle] = warned[vehicle] or {}
warned[vehicle][key] = text
Logging.info(ADOutbound.LOG_PREFIX .. "'%s': %s", tostring(vehicle:getName()), text)
Logging.info(ADOutbound.LOG_PREFIX .. "'%s': %s", tostring(ADRuns.vehicleLabel(vehicle)), text)
end
end
-- gårdens eget behov (fabrikker/stalde) sælges ikke; kilderne selv tæller ikke som forbrugere
@@ -254,7 +254,7 @@ function ADOutbound.buildPlanInput(adEnv, run, vehicle)
product.reserve, product.reservedFor = demand.liters, demand.consumers
end
if quote == nil and unreachableName ~= nil then
warnOnce(adEnv, vehicle, "sell:" .. product.name, string.format("'%s' kan ikke nå salgssted '%s' for %s – tjek vejnettet", tostring(vehicle:getName()), unreachableName, product.name))
warnOnce(adEnv, vehicle, "sell:" .. product.name, string.format("'%s' kan ikke nå salgssted '%s' for %s – tjek vejnettet", tostring(ADRuns.vehicleLabel(vehicle)), unreachableName, product.name))
else
clearWarning(vehicle, "sell:" .. product.name)
end
@@ -352,7 +352,7 @@ local function applyTrip(adEnv, vehicle, run, trip, sourcesById)
local sourceNames = {}
for _, id in ipairs(trip.sourceIds) do table.insert(sourceNames, sourcesById[id] ~= nil and sourcesById[id].name or tostring(id)) end
local why = trip.kind == "sell" and string.format("salg, %d %% af top", trip.percent or 0) or "lager"
Logging.info(ADOutbound.LOG_PREFIX .. "'%s' udkørsel: %s fra %s → %s (%s)", tostring(vehicle:getName()), table.concat(names, "+"), table.concat(sourceNames, ", "), tostring(trip.targetName), why)
Logging.info(ADOutbound.LOG_PREFIX .. "'%s' udkørsel: %s fra %s → %s (%s)", tostring(ADRuns.vehicleLabel(vehicle)), table.concat(names, "+"), table.concat(sourceNames, ", "), tostring(trip.targetName), why)
end
-- Lagermål i en tæt silorække: AutoDrive tipper ved den FØRSTE aflæsningstrigger inden for sin
@@ -378,7 +378,7 @@ local function warnDenseSilosOnce(adEnv, vehicle, trip)
local dx, dz = wayPoint ~= nil and (wayPoint.x - target.x) or math.huge, wayPoint ~= nil and (wayPoint.z - target.z) or math.huge
if dx * dx + dz * dz <= distance * distance and ADSmartPickup.getUnloadStationAtWayPointId(adEnv, marker.id, farmId) ~= nil then
warnedTriggerDistance[trip.targetWayPointId] = true
Logging.warning(ADOutbound.LOG_PREFIX .. "'%s': målet %s har en anden aflæsningsmarkør (%s) inden for AutoDrives 'Max trigger distance' (%d m) — AutoDrive kan tippe ved nabosiloen; sæt AD-indstillingen til 10 m", tostring(vehicle:getName()), tostring(trip.targetName), tostring(marker.name), distance)
Logging.warning(ADOutbound.LOG_PREFIX .. "'%s': målet %s har en anden aflæsningsmarkør (%s) inden for AutoDrives 'Max trigger distance' (%d m) — AutoDrive kan tippe ved nabosiloen; sæt AD-indstillingen til 10 m", tostring(ADRuns.vehicleLabel(vehicle)), tostring(trip.targetName), tostring(marker.name), distance)
return
end
end
@@ -409,11 +409,11 @@ local function startHold(adEnv, vehicle, run, reasons, sourcesById)
if marker == nil then
return nil
end
warnOnce(adEnv, vehicle, "noWait", string.format("'%s' har intet ledigt Wait-punkt med vejnet (run '%s'); holder ved kilden %s", tostring(vehicle:getName()), tostring(run.name), tostring(marker.name)))
warnOnce(adEnv, vehicle, "noWait", string.format("'%s' har intet ledigt Wait-punkt med vejnet (run '%s'); holder ved kilden %s", tostring(ADRuns.vehicleLabel(vehicle)), tostring(run.name), tostring(marker.name)))
end
local previous = holds[vehicle]
holds[vehicle] = {markerId = marker.id, markerName = tostring(marker.name), reasons = reasons, timerMs = 0}
local message = string.format("'%s' holder ved %s: %s", tostring(vehicle:getName()), tostring(marker.name), table.concat(reasons, "; "))
local message = string.format("'%s' holder ved %s: %s", tostring(ADRuns.vehicleLabel(vehicle)), tostring(marker.name), table.concat(reasons, "; "))
if previous == nil or previous.lastLogged ~= message then
Logging.info(ADOutbound.LOG_PREFIX .. "%s", message)
end
@@ -447,7 +447,7 @@ function ADOutbound.choosePickup(adEnv, vehicle)
runStatus.reasons = reasons
for _, reason in ipairs(reasons) do
if string.find(reason, ": ingen silo med plads", 1, true) then
warnOnce(adEnv, vehicle, "store:" .. reason, string.format("'%s' finder ingen silo med plads (%s)", tostring(vehicle:getName()), reason))
warnOnce(adEnv, vehicle, "store:" .. reason, string.format("'%s' finder ingen silo med plads (%s)", tostring(ADRuns.vehicleLabel(vehicle)), reason))
end
end
if trip == nil then
@@ -461,7 +461,7 @@ function ADOutbound.choosePickup(adEnv, vehicle)
if trip.kind == "sell" then
for _, product in ipairs(input.products) do
if product.fillType == trip.fillTypes[1] and product.quote ~= nil then
Logging.info(ADOutbound.LOG_PREFIX .. "'%s' pris %s: %.0f kr/1000 l ved %s, årets top %.0f -> %d %% (kræver %d)", tostring(vehicle:getName()), product.name, (product.quote.price or 0) * 1000, tostring(product.quote.stationName), (product.quote.top or 0) * 1000, product.quote.percent or 0, run.sellAtPercent or 90)
Logging.info(ADOutbound.LOG_PREFIX .. "'%s' pris %s: %.0f kr/1000 l ved %s, årets top %.0f -> %d %% (kræver %d)", tostring(ADRuns.vehicleLabel(vehicle)), product.name, (product.quote.price or 0) * 1000, tostring(product.quote.stationName), (product.quote.top or 0) * 1000, product.quote.percent or 0, run.sellAtPercent or 90)
end
end
end
@@ -511,7 +511,7 @@ local function updateHold(adEnv, task, hold, dt)
releaseHold(vehicle)
ADWaitPool.redirect(task, targetId)
task.activatedUALLoading = false
Logging.info(ADOutbound.LOG_PREFIX .. "'%s' kører fra Wait: der er noget at hente igen", tostring(vehicle:getName()))
Logging.info(ADOutbound.LOG_PREFIX .. "'%s' kører fra Wait: der er noget at hente igen", tostring(ADRuns.vehicleLabel(vehicle)))
end
return true
end
@@ -568,7 +568,7 @@ local function updateSpawn(adEnv, state, task, source, dt)
if stored < spawn.pending.stored and (loaded > spawn.pending.loaded or level > spawn.pending.level) then
spawn.pending = nil
elseif spawn.pending.ms > ADOutbound.SPAWN_STALL_MS then
warnOnce(adEnv, vehicle, "spawn", string.format("'%s': objektlageret %s spawner ikke %s (30 s uden fremdrift); kører med det der er", tostring(vehicle:getName()), tostring(source.name), fillTypeName(fillType)))
warnOnce(adEnv, vehicle, "spawn", string.format("'%s': objektlageret %s spawner ikke %s (30 s uden fremdrift); kører med det der er", tostring(ADRuns.vehicleLabel(vehicle)), tostring(source.name), fillTypeName(fillType)))
state.done = true
return
else
@@ -594,7 +594,7 @@ local function updateSpawn(adEnv, state, task, source, dt)
if ADSources.spawnOne(source, index) then
spawn.pending = {stored = ADSources.countStored(source, fillType), loaded = countLoaded(task.trailers), level = adEnv.AutoDrive.getAllFillLevels(task.trailers) or 0, ms = 0}
else
warnOnce(adEnv, vehicle, "spawn", string.format("'%s': kunne ikke tage %s ud af %s; kører med det der er", tostring(vehicle:getName()), fillTypeName(fillType), tostring(source.name)))
warnOnce(adEnv, vehicle, "spawn", string.format("'%s': kunne ikke tage %s ud af %s; kører med det der er", tostring(ADRuns.vehicleLabel(vehicle)), fillTypeName(fillType), tostring(source.name)))
state.done = true
end
end
@@ -669,13 +669,13 @@ function ADOutbound.beforeLoadUpdate(adEnv, task, dt)
emptyUntil[tostring(state.current) .. ":" .. tostring(fillType)] = expires
end
local okDiag, diagnosis = pcall(describeLoadFailure, adEnv, vehicle, task, state, source)
Logging.warning(ADOutbound.LOG_PREFIX .. "'%s': intet at læsse ved %s efter %d s; kilden springes over i %d min (%s)", tostring(vehicle:getName()), tostring(source ~= nil and source.name or state.current), math.floor(ADOutbound.EMPTY_SOURCE_MS / 1000), math.floor(ADOutbound.EMPTY_SOURCE_TTL_MS / 60000), okDiag and diagnosis or tostring(diagnosis))
Logging.warning(ADOutbound.LOG_PREFIX .. "'%s': intet at læsse ved %s efter %d s; kilden springes over i %d min (%s)", tostring(ADRuns.vehicleLabel(vehicle)), tostring(source ~= nil and source.name or state.current), math.floor(ADOutbound.EMPTY_SOURCE_MS / 1000), math.floor(ADOutbound.EMPTY_SOURCE_TTL_MS / 60000), okDiag and diagnosis or tostring(diagnosis))
state.noProgressMs, state.completed = 0, true
task:finished()
return true
end
if state.noProgressMs > ADOutbound.NO_PROGRESS_MS and level > 0 and not spawnPending then
Logging.info(ADOutbound.LOG_PREFIX .. "'%s': ingen mere last ved %s; kører med %.0f l", tostring(vehicle:getName()), tostring(source ~= nil and source.name or state.current), level)
Logging.info(ADOutbound.LOG_PREFIX .. "'%s': ingen mere last ved %s; kører med %.0f l", tostring(ADRuns.vehicleLabel(vehicle)), tostring(source ~= nil and source.name or state.current), level)
state.noProgressMs, state.completed = 0, true
task:finished()
return true
@@ -716,7 +716,7 @@ function ADOutbound.beforeUnloadUpdate(adEnv, task, dt)
pcall(unit.setAllTensionBeltsActive, unit, false, false)
end
end
Logging.info(ADOutbound.LOG_PREFIX .. "'%s': stropper løsnet %.0f m før %s", tostring(vehicle:getName()), distance, tostring(state.trip.targetName))
Logging.info(ADOutbound.LOG_PREFIX .. "'%s': stropper løsnet %.0f m før %s", tostring(ADRuns.vehicleLabel(vehicle)), distance, tostring(state.trip.targetName))
return false
end
@@ -741,7 +741,7 @@ function ADOutbound.strapAfterLoading(adEnv, task)
end
state.unstrapped = false
if strapped > 0 then
Logging.info(ADOutbound.LOG_PREFIX .. "'%s': stropper spændt efter pålæsning", tostring(vehicle:getName()))
Logging.info(ADOutbound.LOG_PREFIX .. "'%s': stropper spændt efter pålæsning", tostring(ADRuns.vehicleLabel(vehicle)))
end
end
@@ -759,7 +759,7 @@ function ADOutbound.beforeLoadFinished(adEnv, task)
end
for _, wayPointId in ipairs(state.queue) do
if not state.visited[wayPointId] and state.sources[wayPointId] ~= nil then
Logging.info(ADOutbound.LOG_PREFIX .. "'%s' runde: %.0f l på vognen, videre til %s", tostring(vehicle:getName()), level or 0, tostring(state.sources[wayPointId].name))
Logging.info(ADOutbound.LOG_PREFIX .. "'%s' runde: %.0f l på vognen, videre til %s", tostring(ADRuns.vehicleLabel(vehicle)), level or 0, tostring(state.sources[wayPointId].name))
goToSource(adEnv, state, task, wayPointId)
return true
end
+40
View File
@@ -410,3 +410,43 @@ function ADRuns.fromRecords(records)
end
return store
end
-- ---- køretøjsnavne ----
-- Navn pr. køretøj efter det forløb det kører: "Milk Collect 1", "Milk Collect 2" … i medlemsrækkefølge;
-- er køretøjet alene i forløbet, bare forløbets navn. {[vehicleId] = navn}.
function ADRuns.vehicleNames(store)
local names = {}
for _, run in ipairs(store ~= nil and store.runs or {}) do
local count = #(run.vehicleIds or {})
for index, vehicleId in ipairs(run.vehicleIds or {}) do
names[vehicleId] = count > 1 and string.format("%s %d", tostring(run.name), index) or tostring(run.name)
end
end
return names
end
-- true når navnet er et forløbsnavn vi selv har sat ("Navn" eller "Navn 3").
function ADRuns.isRunVehicleName(store, name)
if name == nil then return false end
for _, run in ipairs(store ~= nil and store.runs or {}) do
local runName = tostring(run.name)
if name == runName then return true end
local prefix, number = string.match(name, "^(.-) (%d+)$")
if prefix == runName and number ~= nil then return true end
end
return false
end
-- Navnet i log og menu: AutoDrives førernavn (sat efter forløbet), ellers køretøjets modelnavn.
function ADRuns.vehicleLabel(vehicle)
local stateModule = vehicle ~= nil and vehicle.ad ~= nil and vehicle.ad.stateModule or nil
if stateModule ~= nil and stateModule.getName ~= nil then
local ok, name = pcall(stateModule.getName, stateModule)
if ok and name ~= nil and name ~= "" then return tostring(name) end
end
if vehicle ~= nil and vehicle.getName ~= nil then
return tostring(vehicle:getName())
end
return "?"
end
+56 -12
View File
@@ -136,6 +136,45 @@ function ADRunsController.unassignVehicle(vehicle)
end
end
-- ---- køretøjsnavne ----
ADRunsController.NAME_INTERVAL_MS = 2000
local nameTimerMs = 0
local namedByUs = {}
-- Sætter AutoDrives førernavn efter forløbet ("Milk Collect 1"). Et køretøj der ikke længere er i et
-- forløb, får modelnavnet tilbage — men kun hvis navnet er et vi selv har sat (brugerens egne navne røres ikke).
function ADRunsController.applyVehicleNames(adEnv)
local store = ADRunsController.store
local names = ADRuns.vehicleNames(store)
for _, vehicle in ipairs(ADRunsController.getFarmVehicles(adEnv)) do
local stateModule = vehicle.ad ~= nil and vehicle.ad.stateModule or nil
if stateModule ~= nil and stateModule.setName ~= nil then
local id = ADRunsController.getVehicleId(vehicle)
local wanted = id ~= nil and names[id] or nil
local current = stateModule.getName ~= nil and stateModule:getName() or stateModule.driverName
if wanted ~= nil then
if current ~= wanted then
stateModule:setName(wanted)
if stateModule.raiseDirtyFlag ~= nil then stateModule:raiseDirtyFlag() end
end
namedByUs[vehicle] = wanted
elseif (namedByUs[vehicle] ~= nil and current == namedByUs[vehicle]) or ADRuns.isRunVehicleName(store, current) then
stateModule:setName(tostring(vehicle:getName()))
if stateModule.raiseDirtyFlag ~= nil then stateModule:raiseDirtyFlag() end
namedByUs[vehicle] = nil
end
end
end
end
function ADRunsController.applyVehicleNamesThrottled(adEnv, dt)
nameTimerMs = nameTimerMs + (dt or 0)
if nameTimerMs < ADRunsController.NAME_INTERVAL_MS then return end
nameTimerMs = 0
ADRunsController.applyVehicleNames(adEnv)
end
-- ---- varer ----
function ADRunsController.getCarriableFillTypes(adEnv, vehicle)
@@ -270,12 +309,17 @@ end
-- Fire traktorer kan hedde det samme; løbenummeret er pladsen i farmens AD-køretøjsliste.
function ADRunsController.getVehicleLabel(adEnv, vehicle)
local label, model = tostring(ADRuns.vehicleLabel(vehicle)), tostring(vehicle:getName())
-- førernavn efter forløbet: "Milk Collect 1 (Virtus 135 RVshift)"; ellers modelnavn + løbenummer
if label ~= model then
return string.format("%s (%s)", label, model)
end
for index, candidate in ipairs(ADRunsController.getFarmVehicles(adEnv)) do
if candidate == vehicle then
return string.format("%s (#%d)", tostring(vehicle:getName()), index)
return string.format("%s (#%d)", model, index)
end
end
return tostring(vehicle:getName())
return model
end
-- ---- bygninger (flow-tavlen): bygnings-id'er -> markører ----
@@ -428,7 +472,7 @@ function ADRunsController.getFlowRow(adEnv, run)
local vehiclesById = getFarmVehiclesById(adEnv)
for _, vehicleId in ipairs(run.vehicleIds) do
local vehicle = vehiclesById[vehicleId]
table.insert(row.vehicleNames, vehicle ~= nil and tostring(vehicle:getName()) or "?")
table.insert(row.vehicleNames, vehicle ~= nil and tostring(ADRuns.vehicleLabel(vehicle)) or "?")
end
local status = ADRunsController.getRunStatus(adEnv, run)
row.running, row.total, row.isRunning = status.running, status.total, status.isRunning
@@ -484,7 +528,7 @@ local function hasAutoload(adEnv, vehicle)
autoloadDiagnosed[vehicle] = true
local parts = {}
for _, unit in ipairs(trailers or {}) do table.insert(parts, describeAutoloadUnit(unit)) end
Logging.info(ADRunsController.LOG_PREFIX .. "'%s': ingen autoload fundet på enhederne: %s", tostring(vehicle:getName()), #parts > 0 and table.concat(parts, "; ") or "(ingen enheder)")
Logging.info(ADRunsController.LOG_PREFIX .. "'%s': ingen autoload fundet på enhederne: %s", tostring(ADRuns.vehicleLabel(vehicle)), #parts > 0 and table.concat(parts, "; ") or "(ingen enheder)")
end
return false
end
@@ -719,10 +763,10 @@ function ADRunsController.findWrongCargoDump(adEnv, run, vehicle, targetId)
local marker, why = ADLoadSwap.findDumpMarker(adEnv, vehicle, fillType, liters, targetId, isReachable)
local fillTypeName = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(fillType) or tostring(fillType)
if marker == nil then
Logging.warning(ADRunsController.LOG_PREFIX .. "run '%s': '%s' har %.0f l %s på vognen, som målet ikke tager — %s; AutoDrive starter som normalt", tostring(run.name), tostring(vehicle:getName()), liters, tostring(fillTypeName), tostring(why))
Logging.warning(ADRunsController.LOG_PREFIX .. "run '%s': '%s' har %.0f l %s på vognen, som målet ikke tager — %s; AutoDrive starter som normalt", tostring(run.name), tostring(ADRuns.vehicleLabel(vehicle)), liters, tostring(fillTypeName), tostring(why))
return nil
end
Logging.info(ADRunsController.LOG_PREFIX .. "run '%s': '%s' læsser først %.0f l %s af i %s (markør %s) — målet tager ikke varen", tostring(run.name), tostring(vehicle:getName()), liters, tostring(fillTypeName), tostring(marker.name), tostring(marker.markerIndex or marker.id))
Logging.info(ADRunsController.LOG_PREFIX .. "run '%s': '%s' læsser først %.0f l %s af i %s (markør %s) — målet tager ikke varen", tostring(run.name), tostring(ADRuns.vehicleLabel(vehicle)), liters, tostring(fillTypeName), tostring(marker.name), tostring(marker.markerIndex or marker.id))
return {marker = marker, fillType = fillType, liters = liters}
end
@@ -793,7 +837,7 @@ ADRunsController.AL_UNLOAD_CENTER = 1
local function ensureAutoloadUnload(adEnv, vehicle)
if getSettingValue(adEnv, vehicle, "ALUnload") == 0 then
setSetting(adEnv, vehicle, "ALUnload", ADRunsController.AL_UNLOAD_CENTER)
Logging.info(ADRunsController.LOG_PREFIX .. "'%s': AutoDrives 'AL unload' var fra — sat til 'center' (stropper løsnes i triggeren)", tostring(vehicle:getName()))
Logging.info(ADRunsController.LOG_PREFIX .. "'%s': AutoDrives 'AL unload' var fra — sat til 'center' (stropper løsnes i triggeren)", tostring(ADRuns.vehicleLabel(vehicle)))
end
end
@@ -914,7 +958,7 @@ function ADRunsController.startRun(adEnv, runId)
local validation = ADRunsController.validateVehicle(adEnv, run, vehicle)
local result = {vehicle = vehicle, ok = validation.ok, reason = validation.reason, missingBuilding = validation.missingBuilding}
if not validation.ok then
Logging.info(ADRunsController.LOG_PREFIX .. "run '%s': '%s' sprunget over (%s)", tostring(run.name), tostring(vehicle:getName()), tostring(validation.reason))
Logging.info(ADRunsController.LOG_PREFIX .. "run '%s': '%s' sprunget over (%s)", tostring(run.name), tostring(ADRuns.vehicleLabel(vehicle)), tostring(validation.reason))
end
if validation.ok then
local ingredients = ADRunsController.getRunIngredients(adEnv, run, vehicle)
@@ -922,10 +966,10 @@ function ADRunsController.startRun(adEnv, runId)
if ok then
started = started + 1
local target = run.kind == "outbound" and ("kilde " .. tostring(run.sourceWayPointIds[1])) or ("markør " .. tostring(run.targetWayPointId))
Logging.info(ADRunsController.LOG_PREFIX .. "run '%s': '%s' startet mod %s", tostring(run.name), tostring(vehicle:getName()), target)
Logging.info(ADRunsController.LOG_PREFIX .. "run '%s': '%s' startet mod %s", tostring(run.name), tostring(ADRuns.vehicleLabel(vehicle)), target)
else
result.ok, result.reason = false, "error"
Logging.warning(ADRunsController.LOG_PREFIX .. "run '%s': kunne ikke starte '%s': %s", tostring(run.name), tostring(vehicle:getName()), tostring(err))
Logging.warning(ADRunsController.LOG_PREFIX .. "run '%s': kunne ikke starte '%s': %s", tostring(run.name), tostring(ADRuns.vehicleLabel(vehicle)), tostring(err))
end
end
table.insert(results, result)
@@ -944,7 +988,7 @@ function ADRunsController.stopIfRunning(vehicle, reason)
return false
end
stopVehicle(vehicle)
Logging.info(ADRunsController.LOG_PREFIX .. "'%s' stoppet (%s)", tostring(vehicle:getName()), tostring(reason))
Logging.info(ADRunsController.LOG_PREFIX .. "'%s' stoppet (%s)", tostring(ADRuns.vehicleLabel(vehicle)), tostring(reason))
return true
end
@@ -960,7 +1004,7 @@ function ADRunsController.stopRun(adEnv, runId)
if vehicle ~= nil and isVehicleActive(vehicle) then
stopVehicle(vehicle)
stopped = stopped + 1
Logging.info(ADRunsController.LOG_PREFIX .. "run '%s': '%s' stoppet", tostring(run.name), tostring(vehicle:getName()))
Logging.info(ADRunsController.LOG_PREFIX .. "run '%s': '%s' stoppet", tostring(run.name), tostring(ADRuns.vehicleLabel(vehicle)))
end
end
ADRunsController.runningRuns[runId] = nil
+8 -5
View File
@@ -379,7 +379,7 @@ local factoryFallbackLogged = setmetatable({}, {__mode = "k"})
local function logFactoryFallbackOnce(driver, station)
local placeable = station.owningPlaceable
local name = placeable ~= nil and placeable.getName ~= nil and placeable:getName() or "fabrik"
local message = string.format("'%s': %s har ingen ønskede produktioner (tændte eller auto-slukkede pga. mangel) med varer vognen kan bære; bruger dit varevalg", tostring(driver:getName()), tostring(name))
local message = string.format("'%s': %s har ingen ønskede produktioner (tændte eller auto-slukkede pga. mangel) med varer vognen kan bære; bruger dit varevalg", tostring(ADRuns.vehicleLabel(driver)), tostring(name))
if factoryFallbackLogged[driver] ~= message then
factoryFallbackLogged[driver] = message
Logging.info(ADSmartPickup.LOG_PREFIX .. "%s", message)
@@ -723,7 +723,7 @@ local function chooseRunTarget(adEnv, driver)
stateModule:setSecondMarkerByWayPointId(targetId)
local marker = adEnv.ADGraphManager.getMapMarkerByWayPointId ~= nil and adEnv.ADGraphManager:getMapMarkerByWayPointId(targetId) or nil
local why = #ADRunsController.getRunTargets(run) > 1 and "mangler mest af run'ets mål" or "run'ets mål"
Logging.info(ADSmartPickup.LOG_PREFIX .. "'%s' kører til %s (%s)", tostring(driver:getName()), marker ~= nil and tostring(marker.name) or tostring(targetId), why)
Logging.info(ADSmartPickup.LOG_PREFIX .. "'%s' kører til %s (%s)", tostring(ADRuns.vehicleLabel(driver)), marker ~= nil and tostring(marker.name) or tostring(targetId), why)
end
-- Samlet valg: behovsstyret med ingrediensliste, ellers mappe-logik. nil = AutoDrives original.
@@ -781,7 +781,7 @@ local function describeChoice(choice)
end
local function logChoiceOnce(driver, choice)
local message = string.format("'%s' -> %s (%s)", tostring(driver:getName()), tostring(choice.markerName), describeChoice(choice))
local message = string.format("'%s' -> %s (%s)", tostring(ADRuns.vehicleLabel(driver)), tostring(choice.markerName), describeChoice(choice))
if lastLogged[driver] ~= message then
lastLogged[driver] = message
Logging.info(ADSmartPickup.LOG_PREFIX .. "%s", message)
@@ -856,7 +856,7 @@ local function installLoadWaitHook(adEnv)
end
local cargoName = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(fillType) or tostring(fillType)
local wantedName = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(pickup.fillType) or tostring(pickup.fillType)
Logging.info(ADSmartPickup.LOG_PREFIX .. "'%s' har %.0f l %s på vognen og skulle hente %s — leverer først det den har", tostring(loadTask.vehicle:getName()), liters, tostring(cargoName), tostring(wantedName))
Logging.info(ADSmartPickup.LOG_PREFIX .. "'%s' har %.0f l %s på vognen og skulle hente %s — leverer først det den har", tostring(ADRuns.vehicleLabel(loadTask.vehicle)), liters, tostring(cargoName), tostring(wantedName))
return true
end
@@ -874,7 +874,7 @@ local function installLoadWaitHook(adEnv)
if shouldWait then
local stalledOk, isStalled = pcall(hasLoadingStalled, self, dt)
if not stalledOk or isStalled then
Logging.warning(ADSmartPickup.LOG_PREFIX .. "'%s' læsser ikke ved markøren; slipper grebet så AutoDrive kører videre", tostring(self.vehicle:getName()))
Logging.warning(ADSmartPickup.LOG_PREFIX .. "'%s' læsser ikke ved markøren; slipper grebet så AutoDrive kører videre", tostring(ADRuns.vehicleLabel(self.vehicle)))
activePickups[self.vehicle] = nil
shouldWait = false
end
@@ -1052,6 +1052,9 @@ function ADSmartPickup:update(dt)
if ADOutbound ~= nil and ADOutbound.releaseInactive ~= nil then
pcall(ADOutbound.releaseInactive)
end
if ADRunsController ~= nil and ADRunsController.applyVehicleNamesThrottled ~= nil then
pcall(ADRunsController.applyVehicleNamesThrottled, getAutoDriveEnv(), dt)
end
local ok, err = pcall(restoreStoppedVehicles)
if not ok then
Logging.warning(ADSmartPickup.LOG_PREFIX .. "kunne ikke gendanne varevalg: %s", tostring(err))
+6 -6
View File
@@ -142,7 +142,7 @@ local function startWaiting(adEnv, task)
-- ("til den er tømt") og spærrer for de næste. Regn vognen som tom og kør videre.
local smallFree = ADSmartPickup.getTargetFreeCapacity(adEnv, vehicle, fillType)
if rest > 0 and (smallFree == nil or smallFree < rest) and task.finished ~= nil then
Logging.info(ADUnloadWait.LOG_PREFIX .. "'%s': %.0f l %s rest kan ikke komme af — regnes som tom, kører videre", tostring(vehicle:getName()), rest, g_fillTypeManager ~= nil and tostring(g_fillTypeManager:getFillTypeNameByIndex(fillType)) or tostring(fillType))
Logging.info(ADUnloadWait.LOG_PREFIX .. "'%s': %.0f l %s rest kan ikke komme af — regnes som tom, kører videre", tostring(ADRuns.vehicleLabel(vehicle)), rest, g_fillTypeManager ~= nil and tostring(g_fillTypeManager:getFillTypeNameByIndex(fillType)) or tostring(fillType))
task:finished()
end
return
@@ -166,7 +166,7 @@ local function startWaiting(adEnv, task)
if not warnedNoWaitPoint[vehicle] then
warnedNoWaitPoint[vehicle] = true
local poolText = pool ~= nil and pool ~= "" and (" i puljen '" .. pool .. "'") or ""
Logging.warning(ADUnloadWait.LOG_PREFIX .. "'%s' har %.0f l rest, og målet er fuldt — intet ledigt Wait-punkt%s med vejnet til OG fra målet (markør i en mappe med 'Wait' i navnet), så AutoDrive venter ved målet", tostring(vehicle:getName()), rest, poolText)
Logging.warning(ADUnloadWait.LOG_PREFIX .. "'%s' har %.0f l rest, og målet er fuldt — intet ledigt Wait-punkt%s med vejnet til OG fra målet (markør i en mappe med 'Wait' i navnet), så AutoDrive venter ved målet", tostring(ADRuns.vehicleLabel(vehicle)), rest, poolText)
end
return
end
@@ -177,7 +177,7 @@ local function startWaiting(adEnv, task)
-- portioner, når målet forbruger løbende. Derfor peger AD's mål på Wait-punktet imens.
redirectForUnload(task, candidate.marker.id)
local fillTypeName = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(fillType) or tostring(fillType)
Logging.info(ADUnloadWait.LOG_PREFIX .. "'%s' venter ved %s (markør %s): %.0f l %s rest, målet har kun %.0f l fri", tostring(vehicle:getName()), tostring(candidate.marker.name), tostring(candidate.marker.markerIndex or candidate.marker.id), rest, tostring(fillTypeName), free)
Logging.info(ADUnloadWait.LOG_PREFIX .. "'%s' venter ved %s (markør %s): %.0f l %s rest, målet har kun %.0f l fri", tostring(ADRuns.vehicleLabel(vehicle)), tostring(candidate.marker.name), tostring(candidate.marker.markerIndex or candidate.marker.id), rest, tostring(fillTypeName), free)
end
-- Ventende køretøj: er der nu plads til hele resten, køres tilbage til målet.
@@ -216,7 +216,7 @@ local function updateWaiting(adEnv, task, wait, dt)
release(vehicle)
restoreTarget(vehicle)
redirect(task, home)
Logging.info(ADUnloadWait.LOG_PREFIX .. "'%s' kører tilbage fra %s og læsser %.0f l af (målet har %.0f l fri)", tostring(vehicle:getName()), tostring(wait.waitMarker.name), rest, free)
Logging.info(ADUnloadWait.LOG_PREFIX .. "'%s' kører tilbage fra %s og læsser %.0f l af (målet har %.0f l fri)", tostring(ADRuns.vehicleLabel(vehicle)), tostring(wait.waitMarker.name), rest, free)
end
-- Diagnose (midlertidig): mens en traktor holder ved sit mål med last, logges hvert 15. s hvad
@@ -255,7 +255,7 @@ local function debugAtTarget(adEnv, task, dt)
local fillTypeName = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(fillType) or tostring(fillType)
local distance = adEnv.AutoDrive.getDistanceToUnloadPosition ~= nil and adEnv.AutoDrive.getDistanceToUnloadPosition(vehicle) or -1
local secondMarker = vehicle.ad.stateModule.getSecondMarker ~= nil and vehicle.ad.stateModule:getSecondMarker() or nil
Logging.info(ADUnloadWait.LOG_PREFIX .. "DEBUG '%s': targetReached=%s taskDest=%s adMål=%s; %.0f l %s på vognen; målet fri=%s/kap=%s; AD isUnloading=%s isLoading=%s afstandTilAflæsning=%.1f; venter=%s; %s", tostring(vehicle:getName()), tostring(targetReached), tostring(task.destinationID), tostring(secondMarker ~= nil and secondMarker.id or nil), rest, tostring(fillTypeName), tostring(free), tostring(capacity), tostring(trailerModule ~= nil and trailerModule.isUnloading), tostring(trailerModule ~= nil and trailerModule.isLoading), tonumber(distance) or -1, tostring(waits[vehicle] ~= nil), table.concat(states, " | "))
Logging.info(ADUnloadWait.LOG_PREFIX .. "DEBUG '%s': targetReached=%s taskDest=%s adMål=%s; %.0f l %s på vognen; målet fri=%s/kap=%s; AD isUnloading=%s isLoading=%s afstandTilAflæsning=%.1f; venter=%s; %s", tostring(ADRuns.vehicleLabel(vehicle)), tostring(targetReached), tostring(task.destinationID), tostring(secondMarker ~= nil and secondMarker.id or nil), rest, tostring(fillTypeName), tostring(free), tostring(capacity), tostring(trailerModule ~= nil and trailerModule.isUnloading), tostring(trailerModule ~= nil and trailerModule.isLoading), tonumber(distance) or -1, tostring(waits[vehicle] ~= nil), table.concat(states, " | "))
end
function ADUnloadWait.beforeUpdate(adEnv, task, dt)
@@ -299,7 +299,7 @@ function ADUnloadWait.adoptOrphans(adEnv)
pendingTargetRestore[vehicle] = homeId
waits[vehicle] = {task = task, homeDestinationID = homeId, waitMarker = marker, fillType = fillType, rest = rest}
local fillTypeName = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(fillType) or tostring(fillType)
Logging.info(ADUnloadWait.LOG_PREFIX .. "'%s' genoptager ventning ved %s efter genindlæsning: %.0f l %s rest, hjem = markør %s", tostring(vehicle:getName()), tostring(marker.name), rest, tostring(fillTypeName), tostring(homeId))
Logging.info(ADUnloadWait.LOG_PREFIX .. "'%s' genoptager ventning ved %s efter genindlæsning: %.0f l %s rest, hjem = markør %s", tostring(ADRuns.vehicleLabel(vehicle)), tostring(marker.name), rest, tostring(fillTypeName), tostring(homeId))
end
end
end
+1 -1
View File
@@ -741,7 +741,7 @@ function SmartPickupFrame:onClickStartStop()
if result.reason == "noMarker" and result.missingBuilding ~= nil then
reasonText = string.format(reasonText, tostring(result.missingBuilding))
end
table.insert(reasons, string.format("%s: %s", tostring(result.vehicle:getName()), reasonText))
table.insert(reasons, string.format("%s: %s", tostring(ADRuns.vehicleLabel(result.vehicle)), reasonText))
end
end
frame.statusOverride = string.format(frame.i18n:getText("spu_status_started"), started, skipped)
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<modDesc descVersion="107">
<author>masterdraco</author>
<version>1.16.3.0</version>
<version>1.17.0.0</version>
<title>
<en>AD Smart Pickup</en>
</title>
+7 -2
View File
@@ -1,6 +1,6 @@
# AD Smart Pickup — brugermanual
Version 1.16.1 · Farming Simulator 25 · tillæg til AutoDrive
Version 1.17.0 · Farming Simulator 25 · tillæg til AutoDrive
*English version: [USER_MANUAL.md](USER_MANUAL.md)*
@@ -267,7 +267,7 @@ Under **Fra** kan du vælge:
|---|---|
| **Fabrik** | Fabrikkens outputs, både bulk og paller fra pallespawneren |
| **Silo** | Siloens indhold |
| **Stald** | Mælk, gylle og gødning fra staldens læssepunkter |
| **Stald** | Mælk, gylle og gødning fra staldens læssepunkter, inklusive tilknyttede udvidelsestanke som Milk Tank Extension |
| **Objektlager** | Paller og baller. De tages ud én ad gangen |
### Politik pr. vare
@@ -357,6 +357,11 @@ Nederst i flowet står gårdens køretøjer med kapacitet. Sæt **Ja** ud for de
- **Køretøjer, der ikke kan bruges, er låst** og viser grunden. Grundene er beskrevet i tabellen.
- Et køretøj kan kun være med i ét flow. Flyttes det, står der *flyttet fra 'andet flow'*.
- Fjerner du en kørende traktor fra et flow, stoppes den.
- **Navne:** traktorerne får automatisk AutoDrive-førernavn efter deres flow, fx *Milk Collect 1* og
*Milk Collect 2*. Er traktoren alene i flowet, hedder den bare som flowet. Navnet bruges i
AutoDrive, i menuen og i loggen, og modelnavnet står i parentes i menuen. Tages traktoren ud af
flowet, får den sit modelnavn igen. Navne, du selv har givet i AutoDrive, røres kun, mens
traktoren er med i et flow.
| Grund | Betydning |
|---|---|
+7 -2
View File
@@ -1,6 +1,6 @@
# AD Smart Pickup — user manual
Version 1.16.1 · Farming Simulator 25 · add-on for AutoDrive
Version 1.17.0 · Farming Simulator 25 · add-on for AutoDrive
*Dansk version: [BRUGERMANUAL.md](BRUGERMANUAL.md)*
@@ -270,7 +270,7 @@ Under **From** you can pick:
|---|---|
| **Factory** | The factory's outputs, both bulk and pallets from the pallet spawner |
| **Silo** | The silo's contents |
| **Barn** | Milk, slurry and manure from the barn's loading points |
| **Barn** | Milk, slurry and manure from the barn's loading points, including attached extension tanks such as Milk Tank Extension |
| **Object storage** | Pallets and bales. They are taken out one at a time |
### Policy per good
@@ -361,6 +361,11 @@ ones that should drive.
- **Vehicles that cannot be used are locked** and show the reason. The reasons are in the table.
- A vehicle can only be in one flow. If it is moved, it shows *moved from 'other flow'*.
- If you remove a running tractor from a flow, it is stopped.
- **Names:** tractors automatically get an AutoDrive driver name after their flow, such as
*Milk Collect 1* and *Milk Collect 2*. A tractor that is alone in its flow gets the flow's name.
The name is used in AutoDrive, in the menu and in the log, and the menu shows the model name in
brackets. When a tractor leaves its flow, it gets its model name back. Names you set yourself in
AutoDrive are only changed while the tractor is in a flow.
| Reason | Meaning |
|---|---|
+15
View File
@@ -292,5 +292,20 @@ do
check("Rv3 xml læs kilder", table.concat(ADRuns.getRun(back, flow.id).sourceBuildingIds, ","), "barn1,barn2")
end
-- RN: køretøjsnavne efter forløbet — "Navn 1", "Navn 2" … i medlemsrækkefølge; ét køretøj = bare navnet
do
local store, runA = ADRuns.createRun(ADRuns.newStore(), "Milk Collect", "outbound")
store = ADRuns.assignVehicle(store, runA.id, "v1")
store = ADRuns.assignVehicle(store, runA.id, "v2")
local runB
store, runB = ADRuns.createRun(store, "Milk Salg", "outbound")
store = ADRuns.assignVehicle(store, runB.id, "v3")
local names = ADRuns.vehicleNames(store)
check("RN to i samme forløb: 1", names.v1, "Milk Collect 1")
check("RN to i samme forløb: 2", names.v2, "Milk Collect 2")
check("RN alene i forløb = navnet", names.v3, "Milk Salg")
check("RN ukendt køretøj", names.v9, nil)
end
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
os.exit(failures == 0 and 0 or 1)
+17
View File
@@ -702,5 +702,22 @@ check("CF5 forsyning til", table.concat(rowIn.toNames, ","), "Kostald 1,Sukkerfa
check("CF5 forsyning auto-varer", rowIn.productAuto, true)
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
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
os.exit(failures == 0 and 0 or 1)