feat: flere mål pr. run (afkrydsning; den stald der mangler mest får turen, AD's mål skiftes ved turstart) + under-faner Overblik/Runs (v1.11.0.0)

This commit is contained in:
2026-09-23 01:56:47 +02:00
parent 69a98984bb
commit bcd7de8344
12 changed files with 376 additions and 113 deletions
+86 -44
View File
@@ -120,29 +120,51 @@ end
-- Auto-listen: det vognen kan bære, som målet også tager. Er målet en fabrik, indsnævrer
-- findSupplyPickup selv til de ønskede produktioners inputs bagefter.
-- Run'ets mål som liste (flere stalde pr. run); gamle runs har kun targetWayPointId.
function ADRunsController.getRunTargets(run)
if run.targetWayPointIds ~= nil and #run.targetWayPointIds > 0 then
return run.targetWayPointIds
end
return run.targetWayPointId ~= nil and {run.targetWayPointId} or {}
end
local function getTargetStations(adEnv, run, farmId)
local stations = {}
for _, wayPointId in ipairs(ADRunsController.getRunTargets(run)) do
local station = ADSmartPickup.getUnloadStationAtWayPointId(adEnv, wayPointId, farmId)
if station ~= nil then
table.insert(stations, {wayPointId = wayPointId, station = station})
end
end
return stations
end
function ADRunsController.getTargetFillTypes(adEnv, run, vehicle)
local farmId = ADSmartPickup.getFarmId(vehicle)
-- En kørende traktor følger AD's eget mål (stateModule:getSecondMarker(), det samme
-- choosePickup/findSupplyPickup bruger) indtil næste Start — IKKE run'ets gemte
-- targetWayPointId. Redigerer brugeren run'ets Mål mens tildelte traktorer kører,
-- skal Auto-listen derfor følge det LIVE mål, ellers kan den blive tom og fejlagtigt
-- smide traktoren over i mappe-logikken midt i turen.
local wayPointId = run.targetWayPointId
-- choosePickup/findSupplyPickup bruger) indtil næste tur — IKKE run'ets gemte mål.
-- Redigerer brugeren run'ets Mål mens tildelte traktorer kører, skal Auto-listen derfor
-- følge det LIVE mål, ellers kan den blive tom og fejlagtigt smide traktoren over i
-- mappe-logikken midt i turen. Inaktiv: union over alle run'ets mål.
local stations = {}
local stateModule = vehicle.ad ~= nil and vehicle.ad.stateModule or nil
if stateModule ~= nil and stateModule.isActive ~= nil and stateModule:isActive() and stateModule.getSecondMarker ~= nil then
local secondMarker = stateModule:getSecondMarker()
if secondMarker ~= nil and secondMarker.id ~= nil then
wayPointId = secondMarker.id
local station = secondMarker ~= nil and secondMarker.id ~= nil and ADSmartPickup.getUnloadStationAtWayPointId(adEnv, secondMarker.id, farmId) or nil
if station ~= nil then
stations = {{wayPointId = secondMarker.id, station = station}}
end
end
local target = wayPointId ~= nil and ADSmartPickup.getUnloadStationAtWayPointId(adEnv, wayPointId, farmId) or nil
if target == nil then
return {}
if #stations == 0 then
stations = getTargetStations(adEnv, run, farmId)
end
local result = {}
local result, seen = {}, {}
for _, fillType in ipairs(ADRunsController.getCarriableFillTypes(adEnv, vehicle)) do
if ADSmartPickup.getStationLevelAndCapacity(target, fillType, farmId) ~= nil then
table.insert(result, fillType)
for _, entry in ipairs(stations) do
if not seen[fillType] and ADSmartPickup.getStationLevelAndCapacity(entry.station, fillType, farmId) ~= nil then
seen[fillType] = true
table.insert(result, fillType)
end
end
end
table.sort(result)
@@ -165,25 +187,52 @@ end
-- Alle varer målet tager (uanset vogn) — afkrydsningslisten i GUI'et. {index, name, title}, sorteret på titel.
function ADRunsController.getTargetAcceptedFillTypes(adEnv, run)
if run.targetWayPointId == nil then
return {}
end
local farmId = g_currentMission:getFarmId()
local target = ADSmartPickup.getUnloadStationAtWayPointId(adEnv, run.targetWayPointId, farmId)
if target == nil then
local stations = getTargetStations(adEnv, run, farmId)
if #stations == 0 then
return {}
end
local fillTypes = g_fillTypeManager.getFillTypes ~= nil and g_fillTypeManager:getFillTypes() or g_fillTypeManager.fillTypes or {}
local result = {}
for _, fillType in ipairs(fillTypes) do
if fillType.index ~= nil and ADSmartPickup.getStationLevelAndCapacity(target, fillType.index, farmId) ~= nil then
table.insert(result, {index = fillType.index, name = fillType.name, title = fillType.title or fillType.name})
if fillType.index ~= nil then
for _, entry in ipairs(stations) do
if ADSmartPickup.getStationLevelAndCapacity(entry.station, fillType.index, farmId) ~= nil then
table.insert(result, {index = fillType.index, name = fillType.name, title = fillType.title or fillType.name})
break
end
end
end
end
table.sort(result, function(a, b) return tostring(a.title) < tostring(b.title) end)
return result
end
-- Flere mål: den stald der mangler mest lige nu (bedste rangerede behov pr. mål; et FULDT
-- læs der passer vinder). nil uden mål. Ét mål = det.
function ADRunsController.chooseTarget(adEnv, run, vehicle)
local targets = ADRunsController.getRunTargets(run)
if #targets <= 1 then
return targets[1]
end
local farmId = ADSmartPickup.getFarmId(vehicle)
local ingredients = ADRunsController.getRunIngredients(adEnv, run, vehicle)
local bestId, bestNeed = nil, nil
for _, entry in ipairs(getTargetStations(adEnv, run, farmId)) do
local ranked = ADSmartPickup.getTargetNeedsRanked(entry.station, ingredients, farmId)
local need = ranked[1]
if need ~= nil and need.freeSpace >= (ADSupplyPlanner.MIN_FREE_LITERS or 1000) then
local isBetter = bestNeed == nil
or (need.fits == true and bestNeed.fits ~= true)
or (need.fits == bestNeed.fits and need.score > bestNeed.score)
if isBetter then
bestId, bestNeed = entry.wayPointId, need
end
end
end
return bestId or targets[1]
end
-- Fire traktorer kan hedde det samme; løbenummeret er pladsen i farmens AD-køretøjsliste.
function ADRunsController.getVehicleLabel(adEnv, vehicle)
for index, candidate in ipairs(ADRunsController.getFarmVehicles(adEnv)) do
@@ -220,7 +269,13 @@ end
function ADRunsController.validateVehicle(adEnv, run, vehicle)
local carriable = ADRunsController.getCarriableFillTypes(adEnv, vehicle)
local result = {ok = false, carriable = carriable, capacity = getLoadCapacity(adEnv, vehicle)}
if run.targetWayPointId == nil or adEnv.ADGraphManager:getMapMarkerByWayPointId(run.targetWayPointId) == nil then
local hasTarget = false
for _, wayPointId in ipairs(ADRunsController.getRunTargets(run)) do
if adEnv.ADGraphManager:getMapMarkerByWayPointId(wayPointId) ~= nil then
hasTarget = true
end
end
if not hasTarget then
result.reason = "noTarget"
return result
end
@@ -298,7 +353,7 @@ local function applyRunToVehicle(adEnv, run, vehicle, ingredients)
local stateModule = vehicle.ad.stateModule
local farmId = ADSmartPickup.getFarmId(vehicle)
stateModule:setMode(adEnv.AutoDrive.MODE_PICKUPANDDELIVER)
stateModule:setSecondMarkerByWayPointId(run.targetWayPointId)
stateModule:setSecondMarkerByWayPointId(ADRunsController.chooseTarget(adEnv, run, vehicle) or run.targetWayPointId)
local loadMarker = findNearestLoadMarker(adEnv, vehicle, farmId)
if loadMarker ~= nil then
stateModule:setFirstMarkerByWayPointId(loadMarker.id)
@@ -432,13 +487,10 @@ function ADRunsController.getVehicleActivity(adEnv, vehicle)
return {kind = "empty", place = first ~= nil and first.name or nil}
end
-- Målets niveauer for run'ets varer: {{fillType, level, capacity}, ...} mest trængende først.
function ADRunsController.getTargetLevels(adEnv, run)
-- Niveauer pr. mål for run'ets varer: {{wayPointId, name, levels = {{fillType, level, capacity, free}}}}
-- i samme rangering som valget bruger (trug som én trang, fodervægt som prioritet); fulde sidst.
function ADRunsController.getTargetsLevels(adEnv, run)
local farmId = g_currentMission:getFarmId()
local target = run.targetWayPointId ~= nil and ADSmartPickup.getUnloadStationAtWayPointId(adEnv, run.targetWayPointId, farmId) or nil
if target == nil then
return {}
end
local fillTypes = {}
if run.ingredientMode == "manual" then
for _, name in ipairs(run.ingredients) do
@@ -450,26 +502,16 @@ function ADRunsController.getTargetLevels(adEnv, run)
table.insert(fillTypes, fillType.index)
end
end
-- samme rangering som valget bruger (trug som én trang, fodervægt som prioritet); fulde sidst
if ADSmartPickup.getTargetNeedsRanked ~= nil then
local result = {}
for _, entry in ipairs(getTargetStations(adEnv, run, farmId)) do
local marker = adEnv.ADGraphManager:getMapMarkerByWayPointId(entry.wayPointId)
local levels = {}
for _, need in ipairs(ADSmartPickup.getTargetNeedsRanked(target, fillTypes, farmId)) do
for _, need in ipairs(ADSmartPickup.getTargetNeedsRanked(entry.station, fillTypes, farmId)) do
table.insert(levels, {fillType = need.fillType, level = need.level, capacity = need.capacity, free = need.freeSpace})
end
return levels
table.insert(result, {wayPointId = entry.wayPointId, name = marker ~= nil and tostring(marker.name) or tostring(entry.wayPointId), levels = levels})
end
local levels = {}
for _, fillType in ipairs(fillTypes) do
local level, capacity = ADSmartPickup.getStationLevelAndCapacity(target, fillType, farmId)
if level ~= nil then
table.insert(levels, {fillType = fillType, level = level, capacity = capacity, free = capacity - level})
end
end
table.sort(levels, function(a, b)
if a.free ~= b.free then return a.free > b.free end
return a.fillType < b.fillType
end)
return levels
return result
end
-- ---- opslag til dropdowns ----