feat: Wait-punkter for rest-læs + læs der passer foretrækkes (v1.7.0.0)
Rest-læs ved fuldt mål: AutoDrive ventede ved aflæsningspunktet 'til tømt' og spærrede køen. Nu omdirigeres den aktuelle UnloadAtDestinationTask (destinationID + drivePathModule:setPathTo) til nærmeste ledige markør med 'Wait' i navnet / mappen Wait (fælles pulje, reservationer pr. køretøj); tilbage når målet har plads til hele resten. Ventende ser rotateTargets=RT_NONE så 'rotér aflæsning' ikke kører videre fra Wait-punktet. Ingen ledige punkter = som i dag + én advarsel. Rangering: varer hvor et fuldt læs (AutoDrive.getAllFillLevels-kapacitet) passer i målet går forud; passer intet, mest trængende. Nyt modul adUnloadWait.lua; ADSmartPickup.getTargetFreeCapacity delt hjælper.
This commit is contained in:
@@ -357,31 +357,70 @@ local function isFillTypeAccepted(station, husbandry, fillType)
|
||||
return station.getIsFillTypeSupported == nil or station:getIsFillTypeSupported(fillType)
|
||||
end
|
||||
|
||||
-- Niveau + kapacitet for én vare i aflæsningsmålet; nil hvis målet ikke tager varen.
|
||||
local function getTargetLevelAndCapacity(station, fillType, farmId)
|
||||
local husbandry = getHusbandry(station)
|
||||
if not isFillTypeAccepted(station, husbandry, fillType) then
|
||||
return nil
|
||||
end
|
||||
if husbandry ~= nil then
|
||||
local level = husbandry:getHusbandryFillLevel(fillType) or 0
|
||||
return level, husbandry:getHusbandryCapacity(fillType) or level
|
||||
end
|
||||
local level, freeSpace = 0, 0
|
||||
for _, storage in pairs(getTargetStorages(station)) do
|
||||
level = level + (storage:getFillLevel(fillType) or 0)
|
||||
freeSpace = freeSpace + (storage:getFreeCapacity(fillType) or 0)
|
||||
end
|
||||
if level + freeSpace <= 0 and station.getFreeCapacity ~= nil then
|
||||
-- ukendt lagertype: brug stationens egen opgørelse af fri plads
|
||||
level, freeSpace = 0, station:getFreeCapacity(fillType, farmId) or 0
|
||||
end
|
||||
return level, level + freeSpace
|
||||
end
|
||||
|
||||
-- Niveau + kapacitet pr. ingrediens i aflæsningsmålets lager; demand giver forbrug/min.
|
||||
local function getTargetNeeds(station, ingredients, farmId, demand)
|
||||
local needs = {}
|
||||
local storages = getTargetStorages(station)
|
||||
local husbandry = getHusbandry(station)
|
||||
for _, fillType in ipairs(ingredients) do
|
||||
if husbandry ~= nil and isFillTypeAccepted(station, husbandry, fillType) then
|
||||
local level = husbandry:getHusbandryFillLevel(fillType) or 0
|
||||
table.insert(needs, {fillType = fillType, level = level, capacity = husbandry:getHusbandryCapacity(fillType) or level, litersPerMinute = demand[fillType]})
|
||||
elseif isFillTypeAccepted(station, husbandry, fillType) then
|
||||
local level, freeSpace = 0, 0
|
||||
for _, storage in pairs(storages) do
|
||||
level = level + (storage:getFillLevel(fillType) or 0)
|
||||
freeSpace = freeSpace + (storage:getFreeCapacity(fillType) or 0)
|
||||
end
|
||||
if level + freeSpace <= 0 and station.getFreeCapacity ~= nil then
|
||||
-- ukendt lagertype: brug stationens egen opgørelse af fri plads
|
||||
level, freeSpace = 0, station:getFreeCapacity(fillType, farmId) or 0
|
||||
end
|
||||
table.insert(needs, {fillType = fillType, level = level, capacity = level + freeSpace, litersPerMinute = demand[fillType]})
|
||||
local level, capacity = getTargetLevelAndCapacity(station, fillType, farmId)
|
||||
if level ~= nil then
|
||||
table.insert(needs, {fillType = fillType, level = level, capacity = capacity, litersPerMinute = demand[fillType]})
|
||||
end
|
||||
end
|
||||
return needs
|
||||
end
|
||||
|
||||
-- Vognens samlede kapacitet (liter); nil hvis AutoDrive ikke kan opgøre den.
|
||||
local function getLoadCapacity(adEnv, driver)
|
||||
if adEnv.AutoDrive.getAllUnits == nil or adEnv.AutoDrive.getAllFillLevels == nil then
|
||||
return nil
|
||||
end
|
||||
local trailers = adEnv.AutoDrive.getAllUnits(driver)
|
||||
local _, capacity = adEnv.AutoDrive.getAllFillLevels(trailers)
|
||||
return capacity ~= nil and capacity > 0 and capacity or nil
|
||||
end
|
||||
|
||||
-- Fri plads til varen i køretøjets aflæsningsmål (bruges af Wait-punkt-logikken);
|
||||
-- nil hvis målet ikke kendes eller ikke tager varen.
|
||||
function ADSmartPickup.getTargetFreeCapacity(adEnv, driver, fillType)
|
||||
local secondMarker = driver.ad.stateModule:getSecondMarker()
|
||||
local farmId = getFarmId(driver)
|
||||
if secondMarker == nil or farmId == nil then
|
||||
return nil
|
||||
end
|
||||
local targetWayPoint = adEnv.ADGraphManager:getWayPointById(secondMarker.id)
|
||||
local target = targetWayPoint ~= nil and getUnloadStationAtMarker(adEnv, targetWayPoint, farmId) or nil
|
||||
if target == nil then
|
||||
return nil
|
||||
end
|
||||
local level, capacity = getTargetLevelAndCapacity(target, fillType, farmId)
|
||||
if level == nil then
|
||||
return nil
|
||||
end
|
||||
return capacity - level
|
||||
end
|
||||
|
||||
-- Behovsstyret: den ingrediens aflæsningsmålet mangler mest, som også findes i en silo.
|
||||
function ADSmartPickup.findSupplyPickup(adEnv, driver, ingredients)
|
||||
local secondMarker = driver.ad.stateModule:getSecondMarker()
|
||||
@@ -407,7 +446,8 @@ function ADSmartPickup.findSupplyPickup(adEnv, driver, ingredients)
|
||||
|
||||
local allMarkers = adEnv.ADGraphManager:getMapMarkers()
|
||||
local markerStations = collectMarkerStations(adEnv, allMarkers, farmId, target.owningPlaceable)
|
||||
for _, need in ipairs(ADSupplyPlanner.rankNeeds(getTargetNeeds(target, ingredients, farmId, demand))) do
|
||||
local loadCapacity = getLoadCapacity(adEnv, driver)
|
||||
for _, need in ipairs(ADSupplyPlanner.rankNeeds(getTargetNeeds(target, ingredients, farmId, demand), loadCapacity)) do
|
||||
local choice = findBestSource(markerStations, {need.fillType}, farmId)
|
||||
if choice ~= nil then
|
||||
return {
|
||||
@@ -463,6 +503,9 @@ local function describeChoice(choice)
|
||||
if choice.need.minutesToEmpty ~= nil then
|
||||
urgency = string.format(", fabrikken bruger %.0f l/min = %.0f min til tom", choice.need.litersPerMinute, choice.need.minutesToEmpty)
|
||||
end
|
||||
if choice.need.fits == false then
|
||||
urgency = urgency .. ", et fuldt læs passer IKKE (rest ventes ved Wait-punkt)"
|
||||
end
|
||||
return string.format("%s: kilde %.0f l, %s, målet har %.0f/%.0f l%s", tostring(fillTypeName), choice.level, source, choice.need.level, choice.need.capacity, urgency)
|
||||
end
|
||||
|
||||
@@ -571,8 +614,11 @@ local function installHook(adEnv)
|
||||
end
|
||||
|
||||
installLoadWaitHook(adEnv)
|
||||
if ADUnloadWait ~= nil then
|
||||
ADUnloadWait.install(adEnv)
|
||||
end
|
||||
|
||||
Logging.info(ADSmartPickup.LOG_PREFIX .. "aktiv (mindst fyldte silo med varen; flere valgte varer = behovsstyret forsyning)")
|
||||
Logging.info(ADSmartPickup.LOG_PREFIX .. "aktiv (mindst fyldte silo med varen; flere valgte varer = behovsstyret forsyning; Wait-punkter for rest-læs)")
|
||||
end
|
||||
|
||||
-- Når AutoDrive stopper, får køretøjet hele ingredienslisten tilbage i varevalget
|
||||
@@ -608,6 +654,9 @@ function ADSmartPickup:update(dt)
|
||||
return
|
||||
end
|
||||
|
||||
if ADUnloadWait ~= nil then
|
||||
pcall(ADUnloadWait.releaseInactive)
|
||||
end
|
||||
local ok, err = pcall(restoreStoppedVehicles)
|
||||
if not ok then
|
||||
Logging.warning(ADSmartPickup.LOG_PREFIX .. "kunne ikke gendanne varevalg: %s", tostring(err))
|
||||
|
||||
Reference in New Issue
Block a user