feat: foderprioritering — trug som én trang, spillets fodervægt (TMR 1,0 > hø/ensilage 0,8 > græs 0,4) afgør rækkefølgen i truget; fanen viser samme rangering (v1.10.3.0)

This commit is contained in:
2026-09-23 01:49:19 +02:00
parent 231d6a41d6
commit 69a98984bb
6 changed files with 108 additions and 7 deletions
+8
View File
@@ -450,6 +450,14 @@ 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 levels = {}
for _, need in ipairs(ADSmartPickup.getTargetNeedsRanked(target, fillTypes, farmId)) do
table.insert(levels, {fillType = need.fillType, level = need.level, capacity = need.capacity, free = need.freeSpace})
end
return levels
end
local levels = {}
for _, fillType in ipairs(fillTypes) do
local level, capacity = ADSmartPickup.getStationLevelAndCapacity(target, fillType, farmId)
+38 -3
View File
@@ -377,23 +377,43 @@ local function getHusbandryFoodFillTypes(husbandry)
if foodSpec == nil or foodSystem == nil or foodSpec.animalTypeIndex == nil then
return nil
end
-- værdien er foderets vægt (spillets productionWeight/eatWeight: TMR 1,0, hø/ensilage
-- 0,8, græs 0,4) — bruges som prioritet inden for truget; ukendt = 1
local fillTypes = {}
local animalFood = foodSystem.getAnimalFood ~= nil and foodSystem:getAnimalFood(foodSpec.animalTypeIndex) or nil
for _, group in pairs(animalFood ~= nil and animalFood.groups or {}) do
local weight = tonumber(group.productionWeight) or tonumber(group.eatWeight) or 1
for _, fillType in pairs(group.fillTypes or {}) do
fillTypes[fillType] = true
fillTypes[fillType] = math.max(fillTypes[fillType] or 0, weight)
end
end
local mixtures = foodSystem.getMixturesByAnimalTypeIndex ~= nil and foodSystem:getMixturesByAnimalTypeIndex(foodSpec.animalTypeIndex) or nil
for _, mixture in pairs(mixtures or {}) do
local fillType = type(mixture) == "table" and (mixture.fillType or mixture.fillTypeIndex) or mixture
if type(fillType) == "number" then
fillTypes[fillType] = true
fillTypes[fillType] = math.max(fillTypes[fillType] or 0, 1)
end
end
return fillTypes
end
-- Trugets fælles trang (fri/kapacitet) og foderets vægt for en vare; nil når varen ikke er foder.
local function getFoodPriority(station, fillType)
local husbandry = getHusbandry(station)
local foodFillTypes = husbandry ~= nil and getHusbandryFoodFillTypes(husbandry) or nil
if foodFillTypes == nil or foodFillTypes[fillType] == nil then
return nil
end
local foodSpec = husbandry.spec_husbandryFood
local total = 0
for _, level in pairs(foodSpec.fillLevels or {}) do
total = total + (level or 0)
end
local capacity = foodSpec.capacity or 0
local troughScore = capacity > 0 and math.max(0, capacity - total) / capacity or 0
return troughScore, foodFillTypes[fillType]
end
-- En stald kan MODTAGE foder, halm og vand — ikke sine egne outputs (mælk, gødning, gylle),
-- selv om placeable'n "understøtter" dem som lager. Uden foder-spec (ældre/mod-stalde)
-- spørges staldens egen understøttelse.
@@ -463,12 +483,27 @@ local function getTargetNeeds(station, ingredients, farmId, demand)
for _, fillType in ipairs(ingredients) do
local level, capacity = getTargetLevelAndCapacity(station, fillType, farmId)
if level ~= nil then
table.insert(needs, {fillType = fillType, level = level, capacity = capacity, litersPerMinute = demand[fillType]})
local troughScore, priority = getFoodPriority(station, fillType)
table.insert(needs, {fillType = fillType, level = level, capacity = capacity, litersPerMinute = demand[fillType], scoreOverride = troughScore, priority = priority})
end
end
return needs
end
-- Til fanen: samme rangering som valget bruger (uden vogn-størrelse). Fulde varer sidst.
function ADSmartPickup.getTargetNeedsRanked(station, fillTypes, farmId)
local needs = getTargetNeeds(station, fillTypes, farmId, {})
local ranked = ADSupplyPlanner.rankNeeds(needs)
local seen = {}
for _, need in ipairs(ranked) do seen[need.fillType] = true end
for _, need in ipairs(needs) do
if not seen[need.fillType] then
table.insert(ranked, {fillType = need.fillType, level = need.level, capacity = need.capacity, freeSpace = need.capacity - need.level, fits = false, score = 0, priority = need.priority or 0})
end
end
return ranked
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
+10 -3
View File
@@ -168,10 +168,13 @@ function ADSupplyPlanner.canUnloadRest(freeSpace, rest, capacity, freeFraction)
return freeSpace >= needed
end
-- needs: {{fillType, level, capacity[, litersPerMinute]}, ...}. Returnerer NY liste,
-- mest trængende først; ingredienser uden plads i målet er sorteret fra.
-- needs: {{fillType, level, capacity[, litersPerMinute][, scoreOverride][, priority]}, ...}.
-- Returnerer NY liste, mest trængende først; ingredienser uden plads i målet er sorteret fra.
-- loadCapacity (valgfri): vognens kapacitet — varer hvor et FULDT læs kan komme af
-- går forud (så vognen ikke ender med rest-læs); passer intet, gælder ren trang.
-- scoreOverride: varer der deler ét lager (staldens fodertrug) får trugets fælles score,
-- så truget konkurrerer som ÉN trang; priority (fx spillets fodervægt: TMR 1,0 > hø 0,8 >
-- græs 0,4) afgør så rækkefølgen inden for lageret.
function ADSupplyPlanner.rankNeeds(needs, loadCapacity)
local ranked = {}
for _, need in ipairs(needs) do
@@ -186,7 +189,8 @@ function ADSupplyPlanner.rankNeeds(needs, loadCapacity)
litersPerMinute = need.litersPerMinute,
minutesToEmpty = minutesToEmpty,
fits = ADSupplyPlanner.fullLoadFits(freeSpace, loadCapacity),
score = ADSupplyPlanner.scoreNeed(need.level, need.capacity, freeSpace, minutesToEmpty),
score = need.scoreOverride or ADSupplyPlanner.scoreNeed(need.level, need.capacity, freeSpace, minutesToEmpty),
priority = need.priority or 0,
})
end
end
@@ -197,6 +201,9 @@ function ADSupplyPlanner.rankNeeds(needs, loadCapacity)
if a.score ~= b.score then
return a.score > b.score
end
if a.priority ~= b.priority then
return a.priority > b.priority
end
return a.fillType < b.fillType
end)
return ranked
+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.10.2.0</version>
<version>1.10.3.0</version>
<title>
<en>AD Smart Pickup</en>
</title>