feat(udkørsel): kilder hvis læssestationer deler lager (mælketanke som udvidelser) regnes som ét stop (v1.17.3.0)
This commit is contained in:
@@ -62,6 +62,30 @@ local function fillTypeName(fillType)
|
|||||||
return g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(fillType) or tostring(fillType)
|
return g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(fillType) or tostring(fillType)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Lagrene en kildes læssestation trækker fra (FS25: sourceStorages = {[storage] = storage}); nil = ukendt.
|
||||||
|
local function sourceStorages(source)
|
||||||
|
local station = source ~= nil and source.station or nil
|
||||||
|
if station == nil or type(station.sourceStorages) ~= "table" then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local list = {}
|
||||||
|
for key, value in pairs(station.sourceStorages) do
|
||||||
|
table.insert(list, type(key) == "table" and key or value)
|
||||||
|
end
|
||||||
|
return #list > 0 and list or nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local mergedLogged = {}
|
||||||
|
local function logMergedSources(vehicle, run, merged)
|
||||||
|
for keptId, ids in pairs(merged or {}) do
|
||||||
|
local key = tostring(run.id) .. ":" .. tostring(keptId) .. ":" .. table.concat(ids, ",")
|
||||||
|
if not mergedLogged[key] then
|
||||||
|
mergedLogged[key] = true
|
||||||
|
Logging.info(ADOutbound.LOG_PREFIX .. "run '%s': kilde %s deler lager med %s — regnes som ét stop", tostring(run.name), tostring(keptId), table.concat(ids, ", "))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local function getStatus(run)
|
local function getStatus(run)
|
||||||
status[run.id] = status[run.id] or {}
|
status[run.id] = status[run.id] or {}
|
||||||
return status[run.id]
|
return status[run.id]
|
||||||
@@ -199,6 +223,10 @@ function ADOutbound.buildPlanInput(adEnv, run, vehicle)
|
|||||||
sourcesById[wayPointId] = source
|
sourcesById[wayPointId] = source
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
-- kilder der deler lager (mælketanke som udvidelser) er ét stop — ellers kører runden mellem dem
|
||||||
|
local merged
|
||||||
|
sources, merged = ADOutboundPlanner.dedupeSharedSources(sources, sourceStorages)
|
||||||
|
logMergedSources(vehicle, run, merged)
|
||||||
local byName, products = {}, {}
|
local byName, products = {}, {}
|
||||||
local time = now()
|
local time = now()
|
||||||
for _, source in ipairs(sources) do
|
for _, source in ipairs(sources) do
|
||||||
|
|||||||
@@ -193,6 +193,39 @@ local function buildTrip(primary, candidates, input)
|
|||||||
return trip
|
return trip
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Kilder hvis læssestationer trækker fra samme lagre (fx mælketanke der er udvidelser inden for hinandens
|
||||||
|
-- storageRadius) er ét stop: læsser man ved én, tømmes de alle. Den første i rækkefølgen beholdes, de
|
||||||
|
-- øvrige lægges ind under den. storagesOf(source) -> liste af lager-objekter (nil = ukendt, beholdes).
|
||||||
|
-- Returnerer kept (rækkefølge bevaret) og merged {[beholdt wayPointId] = {sammenlagte wayPointIds}}.
|
||||||
|
function ADOutboundPlanner.dedupeSharedSources(sources, storagesOf)
|
||||||
|
local kept, merged, groups = {}, {}, {}
|
||||||
|
for _, source in ipairs(sources or {}) do
|
||||||
|
local storages = storagesOf(source)
|
||||||
|
local owner = nil
|
||||||
|
if storages ~= nil then
|
||||||
|
for _, group in ipairs(groups) do
|
||||||
|
for _, storage in ipairs(storages) do
|
||||||
|
if group.storages[storage] then owner = group break end
|
||||||
|
end
|
||||||
|
if owner ~= nil then break end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if owner ~= nil then
|
||||||
|
for _, storage in ipairs(storages) do owner.storages[storage] = true end
|
||||||
|
merged[owner.source.wayPointId] = merged[owner.source.wayPointId] or {}
|
||||||
|
table.insert(merged[owner.source.wayPointId], source.wayPointId)
|
||||||
|
else
|
||||||
|
table.insert(kept, source)
|
||||||
|
if storages ~= nil then
|
||||||
|
local set = {}
|
||||||
|
for _, storage in ipairs(storages) do set[storage] = true end
|
||||||
|
table.insert(groups, {source = source, storages = set})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return kept, merged
|
||||||
|
end
|
||||||
|
|
||||||
function ADOutboundPlanner.plan(input)
|
function ADOutboundPlanner.plan(input)
|
||||||
local sell, store, reasons = collectCandidates(input)
|
local sell, store, reasons = collectCandidates(input)
|
||||||
if sell[1] ~= nil then
|
if sell[1] ~= nil then
|
||||||
|
|||||||
@@ -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.2.0</version>
|
<version>1.17.3.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.2 · Farming Simulator 25 · tillæg til AutoDrive
|
Version 1.17.3 · Farming Simulator 25 · tillæg til AutoDrive
|
||||||
|
|
||||||
*English version: [USER_MANUAL.md](USER_MANUAL.md)*
|
*English version: [USER_MANUAL.md](USER_MANUAL.md)*
|
||||||
|
|
||||||
@@ -270,6 +270,11 @@ Under **Fra** kan du vælge:
|
|||||||
| **Stald** | Mælk, gylle og gødning fra staldens læssepunkter, inklusive tilknyttede udvidelsestanke som Milk Tank Extension |
|
| **Stald** | Mælk, gylle og gødning fra staldens læssepunkter, inklusive tilknyttede udvidelsestanke som Milk Tank Extension |
|
||||||
| **Objektlager** | Paller og baller. De tages ud én ad gangen |
|
| **Objektlager** | Paller og baller. De tages ud én ad gangen |
|
||||||
|
|
||||||
|
**Kilder med fælles lager:** nogle lagre er udvidelser, der deler beholdning med alle inden for en
|
||||||
|
vis afstand, fx mælketanke i en række. Læsser man ved én, tømmes de alle. Moden opdager det selv og
|
||||||
|
regner dem som ét stop, så traktoren ikke kører rundt mellem tankene. Den første i listen bruges, og
|
||||||
|
loggen skriver hvilke kilder der er slået sammen. Det er nok at vælge én tank som kilde.
|
||||||
|
|
||||||
### Politik pr. vare
|
### Politik pr. vare
|
||||||
|
|
||||||
Hver vare, kilderne har, står med sin mængde og nuværende pris. Vælg en politik:
|
Hver vare, kilderne har, står med sin mængde og nuværende pris. Vælg en politik:
|
||||||
|
|||||||
+7
-1
@@ -1,6 +1,6 @@
|
|||||||
# AD Smart Pickup — user manual
|
# AD Smart Pickup — user manual
|
||||||
|
|
||||||
Version 1.17.2 · Farming Simulator 25 · add-on for AutoDrive
|
Version 1.17.3 · Farming Simulator 25 · add-on for AutoDrive
|
||||||
|
|
||||||
*Dansk version: [BRUGERMANUAL.md](BRUGERMANUAL.md)*
|
*Dansk version: [BRUGERMANUAL.md](BRUGERMANUAL.md)*
|
||||||
|
|
||||||
@@ -273,6 +273,12 @@ Under **From** you can pick:
|
|||||||
| **Barn** | Milk, slurry and manure from the barn's loading points, including attached extension tanks such as Milk Tank Extension |
|
| **Barn** | Milk, slurry and manure from the barn's loading points, including attached extension tanks such as Milk Tank Extension |
|
||||||
| **Object storage** | Pallets and bales. They are taken out one at a time |
|
| **Object storage** | Pallets and bales. They are taken out one at a time |
|
||||||
|
|
||||||
|
**Sources with shared storage:** some storages are extensions that share their stock with everything
|
||||||
|
within a set distance, such as a row of milk tanks. Loading at one empties them all. The mod detects
|
||||||
|
this and treats them as one stop, so the tractor does not drive between the tanks. The first one in
|
||||||
|
the list is used, and the log says which sources were merged. Choosing a single tank as the source
|
||||||
|
is enough.
|
||||||
|
|
||||||
### Policy per good
|
### Policy per good
|
||||||
|
|
||||||
Every good in the sources is listed with its amount and current price. Pick a policy:
|
Every good in the sources is listed with its amount and current price. Pick a policy:
|
||||||
|
|||||||
@@ -543,5 +543,23 @@ v24b.trailers[1].setAllTensionBeltsActive = function(self, active) self.beltsAct
|
|||||||
adEnv.LoadAtDestinationTask.finished(newTask(v24b, 1))
|
adEnv.LoadAtDestinationTask.finished(newTask(v24b, 1))
|
||||||
check("O24 tipvogn uden tur: rører ikke stropper", v24b.trailers[1].beltsActive, nil)
|
check("O24 tipvogn uden tur: rører ikke stropper", v24b.trailers[1].beltsActive, nil)
|
||||||
|
|
||||||
|
-- O-pool: to kilder hvis stationer deler lager (mælketanke som udvidelser) = ét stop i runden
|
||||||
|
do
|
||||||
|
local pool = {}
|
||||||
|
local st1, st2 = sources[1].station, sources[2].station
|
||||||
|
sources[1].station = {name = "tankA", sourceStorages = {[pool] = pool}}
|
||||||
|
sources[2].station = {name = "tankB", sourceStorages = {[pool] = pool}}
|
||||||
|
local vPool = newVehicle("Tank", 0, 0, 10000)
|
||||||
|
runs[vPool] = outboundRun(77, {1, 2}, {{fillType = "SUGAR", policy = "sell"}}, {collectRound = true})
|
||||||
|
local inputPool = ADOutbound.buildPlanInput(adEnv, runs[vPool], vPool)
|
||||||
|
local ids = {}
|
||||||
|
for _, product in ipairs(inputPool.products) do
|
||||||
|
for _, source in ipairs(product.sources) do table.insert(ids, tostring(source.wayPointId)) end
|
||||||
|
end
|
||||||
|
check("O-pool kun første kilde", table.concat(ids, ","), "1")
|
||||||
|
check("O-pool logget", lastLog("deler lager") ~= nil, true)
|
||||||
|
sources[1].station, sources[2].station = st1, st2
|
||||||
|
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)
|
||||||
|
|||||||
@@ -144,5 +144,17 @@ local twoSources = product("STRAW_BASKET", BASKET, "store", {{wayPointId = 5, av
|
|||||||
check("P14 paller summeres over kilder", P.plan(palletInput({twoSources})).kind, "store")
|
check("P14 paller summeres over kilder", P.plan(palletInput({twoSources})).kind, "store")
|
||||||
check("P14 evaluate palletCount", P.evaluate(twoSources, palletInput({})).palletCount, 4)
|
check("P14 evaluate palletCount", P.evaluate(twoSources, palletInput({})).palletCount, 4)
|
||||||
|
|
||||||
|
-- P15: kilder der deler lager (mælketanke = udvidelser inden for storageRadius) regnes som ét stop;
|
||||||
|
-- den første i forløbets rækkefølge beholdes, rækkefølgen bevares
|
||||||
|
local storA, storB, storC = {}, {}, {}
|
||||||
|
local pools = {[1] = {storA, storB}, [2] = {storB}, [3] = {storC}, [4] = {storA}, [5] = nil}
|
||||||
|
local srcs = {{wayPointId = 1}, {wayPointId = 2}, {wayPointId = 3}, {wayPointId = 4}, {wayPointId = 5}}
|
||||||
|
local kept, merged = P.dedupeSharedSources(srcs, function(source) return pools[source.wayPointId] end)
|
||||||
|
check("P15 behold 1, 3, 5", join((function() local ids = {} for _, s in ipairs(kept) do table.insert(ids, s.wayPointId) end return ids end)()), "1,3,5")
|
||||||
|
check("P15 slået sammen: 2 og 4 ind i 1", join(merged[1]), "2,4")
|
||||||
|
check("P15 kilde uden lagre beholdes", kept[3].wayPointId, 5)
|
||||||
|
local none = P.dedupeSharedSources({}, function() return nil end)
|
||||||
|
check("P15 tom liste", #none, 0)
|
||||||
|
|
||||||
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