feat(foder): parallelt foder (høns: korn 80 %/roesnitter 20 %) — gruppeandele af truget, ingen 'bedste foder først'-spærring (v1.19.7.0)
This commit is contained in:
@@ -498,6 +498,27 @@ local function getHusbandryFoodFillTypes(husbandry)
|
||||
return fillTypes
|
||||
end
|
||||
|
||||
-- Parallelt foder (animalFood consumptionType PARALLEL, fx høns: korn + roesnitter): dyrene spiser fra alle
|
||||
-- grupper samtidig. Returnerer grupperne {fillTypes, eatWeight} eller nil (serielt = bedste foder først).
|
||||
local function getParallelFoodGroups(husbandry)
|
||||
local foodSpec = husbandry.spec_husbandryFood
|
||||
local foodSystem = g_currentMission ~= nil and g_currentMission.animalFoodSystem or nil
|
||||
if foodSpec == nil or foodSystem == nil or foodSpec.animalTypeIndex == nil or foodSystem.getAnimalFood == nil then
|
||||
return nil
|
||||
end
|
||||
local animalFood = foodSystem:getAnimalFood(foodSpec.animalTypeIndex)
|
||||
if animalFood == nil then return nil end
|
||||
local consumption = animalFood.consumptionType
|
||||
local parallelConstant = AnimalFoodSystem ~= nil and AnimalFoodSystem.FOOD_CONSUME_TYPE_PARALLEL or nil
|
||||
local isParallel = (parallelConstant ~= nil and consumption == parallelConstant) or string.upper(tostring(consumption)) == "PARALLEL"
|
||||
if not isParallel then return nil end
|
||||
local groups = {}
|
||||
for _, group in pairs(animalFood.groups or {}) do
|
||||
table.insert(groups, {fillTypes = group.fillTypes or {}, eatWeight = tonumber(group.eatWeight) or tonumber(group.productionWeight) or 1})
|
||||
end
|
||||
return groups
|
||||
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)
|
||||
@@ -505,6 +526,10 @@ local function getFoodPriority(station, fillType)
|
||||
if foodFillTypes == nil or foodFillTypes[fillType] == nil then
|
||||
return nil
|
||||
end
|
||||
-- parallelt foder: grupperne supplerer hinanden, så "bedste foder først" gælder ikke
|
||||
if getParallelFoodGroups(husbandry) ~= nil then
|
||||
return nil
|
||||
end
|
||||
local foodSpec = husbandry.spec_husbandryFood
|
||||
local total = 0
|
||||
for _, level in pairs(foodSpec.fillLevels or {}) do
|
||||
@@ -542,6 +567,17 @@ end
|
||||
-- Foder deler ét trug: varens eget niveau + trugets fri plads = den kapacitet varen kan nå.
|
||||
local function getHusbandryFoodLevelAndCapacity(husbandry, fillType)
|
||||
local foodSpec = husbandry.spec_husbandryFood
|
||||
local groups = getParallelFoodGroups(husbandry)
|
||||
if groups ~= nil then
|
||||
local level, capacity = ADSupplyPlanner.parallelFoodShare(groups, foodSpec.fillLevels, foodSpec.capacity, fillType)
|
||||
if level ~= nil then
|
||||
-- andelen kan ikke overstige den plads truget faktisk har fri (fuldt af korn = ingen plads til snitter)
|
||||
local total = 0
|
||||
for _, value in pairs(foodSpec.fillLevels or {}) do total = total + (value or 0) end
|
||||
local actualFree = math.max(0, (foodSpec.capacity or 0) - total)
|
||||
return level, math.max(level, math.min(capacity, level + actualFree))
|
||||
end
|
||||
end
|
||||
local total = 0
|
||||
for _, level in pairs(foodSpec.fillLevels or {}) do
|
||||
total = total + (level or 0)
|
||||
|
||||
@@ -323,3 +323,25 @@ function ADSupplyPlanner.findTriggerNodes(root, maxDepth)
|
||||
visit(root, 0)
|
||||
return nodes
|
||||
end
|
||||
|
||||
|
||||
-- Parallelt foder (animalFood consumptionType PARALLEL, fx høns): dyrene spiser fra alle grupper samtidig,
|
||||
-- så hver gruppe skal have sin andel af truget efter eatWeight. Returnerer gruppens niveau og kapacitet
|
||||
-- (trugets kapacitet × gruppens andel) for gruppen der indeholder fillType; nil hvis varen ikke er foder.
|
||||
function ADSupplyPlanner.parallelFoodShare(groups, fillLevels, capacity, fillType)
|
||||
local totalWeight = 0
|
||||
for _, group in ipairs(groups or {}) do totalWeight = totalWeight + (tonumber(group.eatWeight) or 0) end
|
||||
if totalWeight <= 0 then return nil end
|
||||
for _, group in ipairs(groups or {}) do
|
||||
local isMember = false
|
||||
for _, member in pairs(group.fillTypes or {}) do
|
||||
if member == fillType then isMember = true end
|
||||
end
|
||||
if isMember then
|
||||
local level = 0
|
||||
for _, member in pairs(group.fillTypes or {}) do level = level + ((fillLevels or {})[member] or 0) end
|
||||
return level, (capacity or 0) * (tonumber(group.eatWeight) or 0) / totalWeight
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<modDesc descVersion="107">
|
||||
<author>masterdraco</author>
|
||||
<version>1.19.6.0</version>
|
||||
<version>1.19.7.0</version>
|
||||
<title>
|
||||
<en>AD Smart Pickup</en>
|
||||
</title>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# AD Smart Pickup — brugermanual
|
||||
|
||||
Version 1.19.6 · Farming Simulator 25 · tillæg til AutoDrive
|
||||
Version 1.19.7 · Farming Simulator 25 · tillæg til AutoDrive
|
||||
|
||||
*English version: [USER_MANUAL.md](USER_MANUAL.md)*
|
||||
|
||||
@@ -238,6 +238,10 @@ Foder i et stald-trug deler plads. Står bedre foder som **TMR** på listen, hen
|
||||
ensilage og hø kun, når truget er **mindst 75 % tomt**. Så fylder silage ikke truget op, mens der er
|
||||
TMR at få.
|
||||
|
||||
Dyr, der spiser fra flere fodergrupper **samtidig**, fx høns med korn og roesnitter, følger ikke den regel.
|
||||
Hver gruppe får sin andel af krybben efter hvor meget dyrene spiser af den. For høns er det korn 80 % og
|
||||
roesnitter 20 %. Begge grupper skal være med under **Vælg**, for at hønsene når 100 %.
|
||||
|
||||
### Flere traktorer til samme stald
|
||||
|
||||
Moden husker, hvad der allerede er **på vej** til hver stald. Har du fire vogne på samme stald,
|
||||
|
||||
+6
-1
@@ -1,6 +1,6 @@
|
||||
# AD Smart Pickup — user manual
|
||||
|
||||
Version 1.19.6 · Farming Simulator 25 · add-on for AutoDrive
|
||||
Version 1.19.7 · Farming Simulator 25 · add-on for AutoDrive
|
||||
|
||||
*Dansk version: [BRUGERMANUAL.md](BRUGERMANUAL.md)*
|
||||
|
||||
@@ -240,6 +240,11 @@ Feed in a barn trough shares space. If better feed such as **TMR** is on the lis
|
||||
as silage and hay is only fetched when the trough is **at least 75 % empty**. That way silage does
|
||||
not fill the trough while TMR is available.
|
||||
|
||||
Animals that eat from several food groups **at the same time**, such as chickens with grain and root
|
||||
crops, do not follow that rule. Each group gets its share of the trough by how much the animals eat of
|
||||
it. For chickens that is grain 80 % and root crops 20 %. Both groups must be included under **Select**
|
||||
for the chickens to reach 100 %.
|
||||
|
||||
### Several tractors on the same barn
|
||||
|
||||
The mod remembers what is already **on the way** to each barn. With four trailers on the same barn
|
||||
|
||||
@@ -806,6 +806,20 @@ check("E6 nødlidende trug: hø direkte", manager:getNextPickup(e5Driver, false)
|
||||
ADOutbound = nil
|
||||
ADRunsController.store = ADRuns.newStore()
|
||||
testVehicles = {}
|
||||
-- E7 (parallelt foder, høns): korn og roesnitter spises SAMTIDIG (80 %/20 %) — truget har sin kornandel,
|
||||
-- mangler roesnitter -> de hentes, "bedste foder først" spærrer ikke (in-game 24/9: kun 70 % produktion)
|
||||
g_currentMission.animalFoodSystem = {
|
||||
getAnimalFood = function(_, animalTypeIndex) if animalTypeIndex == 7 then return {consumptionType = "PARALLEL", groups = {
|
||||
{fillTypes = {TMR}, productionWeight = 0.7, eatWeight = 0.8}, {fillTypes = {HAY}, productionWeight = 0.3, eatWeight = 0.2}}} end end,
|
||||
getMixturesByAnimalTypeIndex = function() return {} end,
|
||||
}
|
||||
e5Straw.level = 100000
|
||||
e5Food[TMR], e5Food[HAY], e5Food[GRASS] = 24000, 0, 0 -- kornandel (80 % af 30000) fuld, 20 % fri
|
||||
stations[1].getFillLevel = function(_, fillType) return fillType == TMR and 30000 or 0 end -- korn findes: serielt ville det vælges
|
||||
check("E7 parallelt: roesnitter hentes selv om truget kun er 20 % tomt", manager:getNextPickup(e5Driver, false), 23)
|
||||
e5Food[TMR] = 30000 -- truget helt fuldt af korn: ingen plads til snitter -> intet behov for dem
|
||||
local hayLevel, hayCapacity = ADSmartPickup.getStationLevelAndCapacity(unloadStations[1], HAY, 1)
|
||||
check("E7 fuldt trug: snitternes plads = 0", hayCapacity - hayLevel, 0)
|
||||
g_currentMission.animalFoodSystem = nil
|
||||
|
||||
-- W13: AD stopper vognen i triggeren FØR markøren (isTargetReached=false) — Wait udløses alligevel
|
||||
|
||||
@@ -232,5 +232,17 @@ check("AP intet på vej -> samme værdier", ADSupplyPlanner.applyPending(pending
|
||||
local ranked = ADSupplyPlanner.rankNeeds(adjusted, 8000)
|
||||
check("AP halm fuld (på vej) -> kun trug-varer tilbage", #ranked, 2)
|
||||
|
||||
-- PF: parallelt foder (høns: korn 80 % / roesnitter 20 % af det de spiser) — hver gruppe har sin andel af truget
|
||||
do
|
||||
local WHEAT, BARLEY, BEETCUT = 1, 2, 3
|
||||
local groups = {{fillTypes = {WHEAT, BARLEY}, eatWeight = 0.8}, {fillTypes = {BEETCUT}, eatWeight = 0.2}}
|
||||
local levels = {[WHEAT] = 60000, [BARLEY] = 20000, [BEETCUT] = 0}
|
||||
local lvl, cap = ADSupplyPlanner.parallelFoodShare(groups, levels, 100000, BEETCUT)
|
||||
check("PF roesnitter: andel 20k, har 0", lvl .. "/" .. cap, "0/20000")
|
||||
lvl, cap = ADSupplyPlanner.parallelFoodShare(groups, levels, 100000, BARLEY)
|
||||
check("PF korn-gruppen samlet: 80k af 80k", lvl .. "/" .. cap, "80000/80000")
|
||||
check("PF ukendt vare -> nil", ADSupplyPlanner.parallelFoodShare(groups, levels, 100000, 99), nil)
|
||||
end
|
||||
|
||||
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
||||
os.exit(failures == 0 and 0 or 1)
|
||||
|
||||
Reference in New Issue
Block a user