feat(lager): lagerture undgår markører andre udkørsels-forløb henter fra (Milk Store læsser af ved 'unload', ikke ved 'Load') (v1.17.5.0)
This commit is contained in:
@@ -54,7 +54,23 @@ end
|
|||||||
-- Nærmeste silo med plads til resten og vejnet fra traktoren; siloer der allerede har varen
|
-- Nærmeste silo med plads til resten og vejnet fra traktoren; siloer der allerede har varen
|
||||||
-- foretrækkes. Returnerer marker — eller nil + en forklaring (til loggen).
|
-- foretrækkes. Returnerer marker — eller nil + en forklaring (til loggen).
|
||||||
-- excludedPlaceables (valgfri): {[placeable] = true} der aldrig må vælges (fx udkørslens kilder).
|
-- excludedPlaceables (valgfri): {[placeable] = true} der aldrig må vælges (fx udkørslens kilder).
|
||||||
function ADLoadSwap.findDumpMarker(adEnv, vehicle, fillType, rest, homeWayPointId, isReachable, excludedPlaceables)
|
-- Rækkefølge for aflæsnings-siloer: markører et forløb HENTER fra (avoidMarkers = {[id] = true}) sidst —
|
||||||
|
-- ellers læsser en lagertur af dér hvor en salgstur skal læsse (samme tank-række); dernæst siloer der
|
||||||
|
-- allerede har varen, så nærmeste. Returnerer en ny sorteret liste.
|
||||||
|
function ADLoadSwap.rankDumpCandidates(candidates, avoidMarkers)
|
||||||
|
local ranked = {}
|
||||||
|
for _, candidate in ipairs(candidates or {}) do table.insert(ranked, candidate) end
|
||||||
|
local function avoided(candidate) return avoidMarkers ~= nil and avoidMarkers[candidate.marker.id] == true end
|
||||||
|
table.sort(ranked, function(a, b)
|
||||||
|
if avoided(a) ~= avoided(b) then return not avoided(a) end
|
||||||
|
if a.hasFillType ~= b.hasFillType then return a.hasFillType end
|
||||||
|
if a.distance ~= b.distance then return a.distance < b.distance end
|
||||||
|
return a.marker.id < b.marker.id
|
||||||
|
end)
|
||||||
|
return ranked
|
||||||
|
end
|
||||||
|
|
||||||
|
function ADLoadSwap.findDumpMarker(adEnv, vehicle, fillType, rest, homeWayPointId, isReachable, excludedPlaceables, avoidMarkers)
|
||||||
if vehicle.rootNode == nil then
|
if vehicle.rootNode == nil then
|
||||||
return nil, "køretøjet har ingen position"
|
return nil, "køretøjet har ingen position"
|
||||||
end
|
end
|
||||||
@@ -82,12 +98,7 @@ function ADLoadSwap.findDumpMarker(adEnv, vehicle, fillType, rest, homeWayPointI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.sort(candidates, function(a, b)
|
candidates = ADLoadSwap.rankDumpCandidates(candidates, avoidMarkers)
|
||||||
if a.hasFillType ~= b.hasFillType then
|
|
||||||
return a.hasFillType
|
|
||||||
end
|
|
||||||
return a.distance < b.distance
|
|
||||||
end)
|
|
||||||
for _, candidate in ipairs(candidates) do
|
for _, candidate in ipairs(candidates) do
|
||||||
if isReachable(candidate.marker.id) then
|
if isReachable(candidate.marker.id) then
|
||||||
return candidate.marker
|
return candidate.marker
|
||||||
|
|||||||
@@ -200,7 +200,8 @@ local function findStoreMarker(adEnv, vehicle, product, capacity, sources, liter
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
local liters = math.max(1, math.min(available, capacity or available))
|
local liters = math.max(1, math.min(available, capacity or available))
|
||||||
local marker = ADLoadSwap.findDumpMarker(adEnv, vehicle, product.fillType, liters, nil, isReachable, ADSources.getSourcePlaceables(sources))
|
local avoid = ADRunsController ~= nil and ADRunsController.getPickupMarkers ~= nil and ADRunsController.getPickupMarkers() or nil
|
||||||
|
local marker = ADLoadSwap.findDumpMarker(adEnv, vehicle, product.fillType, liters, nil, isReachable, ADSources.getSourcePlaceables(sources), avoid)
|
||||||
if marker == nil then
|
if marker == nil then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -136,6 +136,17 @@ function ADRunsController.unassignVehicle(vehicle)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Markører udkørsels-forløb HENTER fra: {[wayPointId] = true}. Lagerture læsser helst ikke af dér.
|
||||||
|
function ADRunsController.getPickupMarkers()
|
||||||
|
local result = {}
|
||||||
|
for _, run in ipairs(ADRunsController.store ~= nil and ADRunsController.store.runs or {}) do
|
||||||
|
if run.kind == "outbound" then
|
||||||
|
for _, wayPointId in ipairs(run.sourceWayPointIds or {}) do result[wayPointId] = true end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
-- ---- køretøjsnavne ----
|
-- ---- køretøjsnavne ----
|
||||||
|
|
||||||
ADRunsController.NAME_INTERVAL_MS = 2000
|
ADRunsController.NAME_INTERVAL_MS = 2000
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
<modDesc descVersion="107">
|
<modDesc descVersion="107">
|
||||||
<author>masterdraco</author>
|
<author>masterdraco</author>
|
||||||
<version>1.17.4.0</version>
|
<version>1.17.5.0</version>
|
||||||
<title>
|
<title>
|
||||||
<en>AD Smart Pickup</en>
|
<en>AD Smart Pickup</en>
|
||||||
</title>
|
</title>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# AD Smart Pickup — brugermanual
|
# AD Smart Pickup — brugermanual
|
||||||
|
|
||||||
Version 1.17.4 · Farming Simulator 25 · tillæg til AutoDrive
|
Version 1.17.5 · Farming Simulator 25 · tillæg til AutoDrive
|
||||||
|
|
||||||
*English version: [USER_MANUAL.md](USER_MANUAL.md)*
|
*English version: [USER_MANUAL.md](USER_MANUAL.md)*
|
||||||
|
|
||||||
@@ -304,7 +304,9 @@ Før hver pålæsning, og hvert femte sekund mens traktoren holder, vurderer mod
|
|||||||
til salg **uanset mængde**. Det sikrer, at du får pengene, når prisen topper. Den højeste pris-%
|
til salg **uanset mængde**. Det sikrer, at du får pengene, når prisen topper. Den højeste pris-%
|
||||||
går først.
|
går først.
|
||||||
2. **Lager.** Findes en Lager-vare med et fuldt læs, eller en kilde over tærsklen, køres den til den
|
2. **Lager.** Findes en Lager-vare med et fuldt læs, eller en kilde over tærsklen, køres den til den
|
||||||
nærmeste silo med plads til hele læsset. Den mest fyldte kilde går først.
|
nærmeste silo med plads til hele læsset. Den mest fyldte kilde går først. Markører, som et andet
|
||||||
|
udkørselsflow henter fra, bruges kun som aflæsningssted, hvis intet andet passer. Så læsser en
|
||||||
|
lagertur ikke af, hvor en salgstur skal læsse.
|
||||||
3. **Ingen tur.** Traktoren holder ved et Wait-punkt og prøver igen. Status viser hvorfor, fx
|
3. **Ingen tur.** Traktoren holder ved et Wait-punkt og prøver igen. Status viser hvorfor, fx
|
||||||
`holder ved Wait 3: SUGAR 78 % af top (kræver 90), lager 41 %`.
|
`holder ved Wait 3: SUGAR 78 % af top (kræver 90), lager 41 %`.
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -1,6 +1,6 @@
|
|||||||
# AD Smart Pickup — user manual
|
# AD Smart Pickup — user manual
|
||||||
|
|
||||||
Version 1.17.4 · Farming Simulator 25 · add-on for AutoDrive
|
Version 1.17.5 · Farming Simulator 25 · add-on for AutoDrive
|
||||||
|
|
||||||
*Dansk version: [BRUGERMANUAL.md](BRUGERMANUAL.md)*
|
*Dansk version: [BRUGERMANUAL.md](BRUGERMANUAL.md)*
|
||||||
|
|
||||||
@@ -308,7 +308,9 @@ Before each loading, and every five seconds while the tractor waits, the mod che
|
|||||||
drives to sell **regardless of amount**. This makes sure you get the money when the price peaks.
|
drives to sell **regardless of amount**. This makes sure you get the money when the price peaks.
|
||||||
The highest price share goes first.
|
The highest price share goes first.
|
||||||
2. **Store.** If a Store good has a full load, or a source is above its threshold, it is taken to the
|
2. **Store.** If a Store good has a full load, or a source is above its threshold, it is taken to the
|
||||||
nearest silo with room for the whole load. The fullest source goes first.
|
nearest silo with room for the whole load. The fullest source goes first. Markers another delivery
|
||||||
|
flow loads from are only used for unloading when nothing else fits. That way a storage trip does
|
||||||
|
not unload where a sale trip needs to load.
|
||||||
3. **No trip.** The tractor parks at a Wait point and tries again. The status says why, such as
|
3. **No trip.** The tractor parks at a Wait point and tries again. The status says why, such as
|
||||||
`holding at Wait 3: SUGAR 78 % of top (needs 90), storage 41 %`.
|
`holding at Wait 3: SUGAR 78 % of top (needs 90), storage 41 %`.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
-- Kør: luajit tests/test_adLoadSwap.lua (fra repo-roden)
|
||||||
|
-- Ren rangering af aflæsnings-siloer (lagermål for udkørsel og læs-bytte).
|
||||||
|
|
||||||
|
dofile("FS25_ADSmartPickup/adLoadSwap.lua")
|
||||||
|
local L = ADLoadSwap
|
||||||
|
|
||||||
|
local failures = 0
|
||||||
|
local function check(name, actual, expected)
|
||||||
|
if actual == expected then
|
||||||
|
print("OK " .. name)
|
||||||
|
else
|
||||||
|
failures = failures + 1
|
||||||
|
print(string.format("FAIL %s: forventede %s, fik %s", name, tostring(expected), tostring(actual)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- LS1: markører et andet forløb HENTER fra (fx "Milk Storage Load") vælges sidst; ellers har-varen, så afstand
|
||||||
|
local candidates = {
|
||||||
|
{marker = {id = 1, name = "Milk Storage Load"}, hasFillType = true, distance = 100},
|
||||||
|
{marker = {id = 2, name = "Milk Storage unload"}, hasFillType = true, distance = 400},
|
||||||
|
{marker = {id = 3, name = "Silo tom"}, hasFillType = false, distance = 10},
|
||||||
|
}
|
||||||
|
local ranked = L.rankDumpCandidates(candidates, {[1] = true})
|
||||||
|
check("LS1 afhentningsmarkør undgås", ranked[1].marker.id, 2)
|
||||||
|
check("LS1 derefter tom silo før afhentning", ranked[2].marker.id, 3)
|
||||||
|
check("LS1 afhentning sidst (stadig mulig)", ranked[3].marker.id, 1)
|
||||||
|
local plain = L.rankDumpCandidates(candidates, nil)
|
||||||
|
check("LS1 uden undgå-liste: har varen + nærmest", plain[1].marker.id, 1)
|
||||||
|
|
||||||
|
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
||||||
|
os.exit(failures == 0 and 0 or 1)
|
||||||
@@ -719,5 +719,16 @@ do
|
|||||||
check("RC-navne label uden AD-navn", ADRuns.vehicleLabel({getName = function() return "Fendt" end}), "Fendt")
|
check("RC-navne label uden AD-navn", ADRuns.vehicleLabel({getName = function() return "Fendt" end}), "Fendt")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- PM: afhentningsmarkører fra udkørsels-forløb (lagerture undgår dem som aflæsningssted)
|
||||||
|
do
|
||||||
|
local sale = ADRunsController.createRun("Salg-test", "outbound")
|
||||||
|
ADRunsController.updateRun(sale.id, {sourceWayPointIds = {4711, 4712}})
|
||||||
|
local supply = ADRunsController.createRun("Forsyning-test", "supply")
|
||||||
|
ADRunsController.updateRun(supply.id, {sourceWayPointIds = {9999}})
|
||||||
|
local pickups = ADRunsController.getPickupMarkers()
|
||||||
|
check("PM udkørsels-kilde med", pickups[4711], true)
|
||||||
|
check("PM forsyning tæller ikke", pickups[9999], nil)
|
||||||
|
end
|
||||||
|
|
||||||
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
||||||
os.exit(failures == 0 and 0 or 1)
|
os.exit(failures == 0 and 0 or 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user