feat: fyldeste kilde først for mælk/gylle/digestat (v1.5.0.0)
Lagervarer tømmes stadig mindst-fyldte-først; varer hvis tanke løber fulde og stopper produktionen hentes fyldest-først (ADSupplyPlanner.FULLEST_FIRST_FILL_TYPES). Strategien vises i loggen. fix: en trigger foran næsen tæller aldrig som markørens egen (tolerance 2 -> 0). Markør-drift i ensilage-rækken lod næste tanks rør (1,9 m foran) vinde. Verificeret mod savegame: 40/40 siloer, 7/7 ensilage-tanke, 0 dropof.
This commit is contained in:
@@ -14,8 +14,9 @@ ADSmartPickup = {}
|
||||
-- vogntog bagved. Siloer tættere end dette regnes som "markørens silo".
|
||||
ADSmartPickup.MAX_MARKER_TO_TRIGGER_DISTANCE = 40
|
||||
-- I tætte silo-rækker ligger nabosiloens trigger FORAN næsen og er ofte nærmere
|
||||
-- end markørens egen. Triggere mere end dette foran næsen hører til naboen.
|
||||
ADSmartPickup.MAX_TRIGGER_AHEAD_OF_MARKER = 2
|
||||
-- end markørens egen. Vognen holder altid BAG næsen, så en trigger foran næsen
|
||||
-- hører til naboen (en ensom silo med markøren ved røret fanges af nødløsningen).
|
||||
ADSmartPickup.MAX_TRIGGER_AHEAD_OF_MARKER = 0
|
||||
-- Vognen følger trækkerens spor: en trigger længere til siden end dette er en
|
||||
-- anden bane (fx aflæsningssiden af samme tank), ikke markørens læsseplads.
|
||||
ADSmartPickup.MAX_TRIGGER_LATERAL_OFFSET = 6
|
||||
@@ -194,13 +195,26 @@ local function collectMarkerStations(adEnv, candidateMarkers, farmId, excludedPl
|
||||
return markerStations
|
||||
end
|
||||
|
||||
-- Mindst fyldte silo der har varen; siloer med varen i EGET lager går altid
|
||||
-- forud for dem der kun kan låne fra naboer. Returnerer et valg eller nil.
|
||||
local function findLeastFilled(markerStations, fillTypes, farmId)
|
||||
local best = {[true] = {level = math.huge}, [false] = {level = math.huge}}
|
||||
local function getFillTypeNames(fillTypes)
|
||||
local names = {}
|
||||
for _, fillType in ipairs(fillTypes) do
|
||||
local name = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(fillType) or nil
|
||||
if name ~= nil then
|
||||
table.insert(names, name)
|
||||
end
|
||||
end
|
||||
return names
|
||||
end
|
||||
|
||||
-- Bedste kilde der har varen: mindst fyldte først for lagervarer, fyldeste først for
|
||||
-- varer hvis tanke løber fulde (ADSupplyPlanner). Siloer med varen i EGET lager går
|
||||
-- altid forud for dem der kun kan låne fra naboer. Returnerer et valg eller nil.
|
||||
local function findBestSource(markerStations, fillTypes, farmId)
|
||||
local prefersFullest = ADSupplyPlanner.prefersFullestSource(getFillTypeNames(fillTypes))
|
||||
local best = {[true] = {}, [false] = {}}
|
||||
for _, entry in ipairs(markerStations) do
|
||||
local level, isOwn = getStationFillLevel(entry.station, fillTypes, farmId)
|
||||
if level >= ADSmartPickup.MIN_USEFUL_LITERS and level < best[isOwn].level then
|
||||
if level >= ADSmartPickup.MIN_USEFUL_LITERS and ADSupplyPlanner.isBetterSource(level, best[isOwn].level, prefersFullest) then
|
||||
best[isOwn] = {level = level, marker = entry.marker, station = entry.station, isOwn = isOwn}
|
||||
end
|
||||
end
|
||||
@@ -217,6 +231,7 @@ local function findLeastFilled(markerStations, fillTypes, farmId)
|
||||
station = choice.station,
|
||||
isOwn = choice.isOwn,
|
||||
fillTypes = fillTypes,
|
||||
prefersFullest = prefersFullest,
|
||||
}
|
||||
end
|
||||
|
||||
@@ -232,7 +247,7 @@ function ADSmartPickup.findLeastFilledPickup(adEnv, driver)
|
||||
return nil
|
||||
end
|
||||
local groupMarkers = adEnv.ADGraphManager:getMapMarkersInGroup(firstMarker.group)
|
||||
return findLeastFilled(collectMarkerStations(adEnv, groupMarkers, farmId, nil), fillTypes, farmId)
|
||||
return findBestSource(collectMarkerStations(adEnv, groupMarkers, farmId, nil), fillTypes, farmId)
|
||||
end
|
||||
|
||||
-- Lagrene bag aflæsningsstationen; produktionspunkter uden targetStorages læses direkte.
|
||||
@@ -285,7 +300,7 @@ 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))) do
|
||||
local choice = findLeastFilled(markerStations, {need.fillType}, farmId)
|
||||
local choice = findBestSource(markerStations, {need.fillType}, farmId)
|
||||
if choice ~= nil then
|
||||
return {
|
||||
markerIndex = choice.markerIndex,
|
||||
@@ -295,6 +310,7 @@ function ADSmartPickup.findSupplyPickup(adEnv, driver, ingredients)
|
||||
station = choice.station,
|
||||
isOwn = choice.isOwn,
|
||||
fillTypes = choice.fillTypes,
|
||||
prefersFullest = choice.prefersFullest,
|
||||
fillType = need.fillType,
|
||||
need = need,
|
||||
}
|
||||
@@ -330,6 +346,7 @@ end
|
||||
|
||||
local function describeChoice(choice)
|
||||
local source = choice.isOwn and "eget lager" or "nabo-lager"
|
||||
source = source .. (choice.prefersFullest and ", fyldeste først" or ", mindst fyldte først")
|
||||
if choice.fillType == nil then
|
||||
return string.format("%.0f l, %s", choice.level, source)
|
||||
end
|
||||
|
||||
@@ -7,6 +7,39 @@ ADSupplyPlanner = {}
|
||||
-- Mindre fri plads end dette i målet regnes som "fuldt" (undgår ture med læs der ikke kan komme af).
|
||||
ADSupplyPlanner.MIN_FREE_LITERS = 1000
|
||||
|
||||
-- Varer hvis kilder LØBER FULDE (dyr/produktion fylder tanken løbende og går i stå
|
||||
-- når den er fuld): her hentes den fyldeste kilde først. Alt andet er lagervarer,
|
||||
-- hvor den mindst fyldte silo tømmes først så rester ryddes og siloer frigives.
|
||||
ADSupplyPlanner.FULLEST_FIRST_FILL_TYPES = {
|
||||
MILK = true, GOATMILK = true, BUFFALOMILK = true, SHEEPMILK = true,
|
||||
LIQUIDMANURE = true, DIGESTATE = true,
|
||||
}
|
||||
|
||||
-- fillTypeNames: navnene på de varer der hentes på turen. Kun når ALLE er
|
||||
-- "løber fuld"-varer vendes strategien; blandet eller ukendt valg = mindst først.
|
||||
function ADSupplyPlanner.prefersFullestSource(fillTypeNames)
|
||||
if #fillTypeNames == 0 then
|
||||
return false
|
||||
end
|
||||
for _, name in ipairs(fillTypeNames) do
|
||||
if not ADSupplyPlanner.FULLEST_FIRST_FILL_TYPES[name] then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Er en kilde med dette niveau bedre end den hidtil bedste (nil = ingen endnu)?
|
||||
function ADSupplyPlanner.isBetterSource(level, bestLevel, prefersFullest)
|
||||
if bestLevel == nil then
|
||||
return true
|
||||
end
|
||||
if prefersFullest then
|
||||
return level > bestLevel
|
||||
end
|
||||
return level < bestLevel
|
||||
end
|
||||
|
||||
function ADSupplyPlanner.copyList(list)
|
||||
local copy = {}
|
||||
for index, value in ipairs(list) do
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<modDesc descVersion="107">
|
||||
<author>masterdraco</author>
|
||||
<version>1.4.0.0</version>
|
||||
<version>1.5.0.0</version>
|
||||
<title>
|
||||
<en>AD Smart Pickup</en>
|
||||
</title>
|
||||
|
||||
Reference in New Issue
Block a user