feat: AD Smart Pickup — vare-bevidst mappe-rotation (mindst fyldte silo først)
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
-- Kør: luajit tests/test_adSmartPickup.lua (fra repo-roden)
|
||||
-- Mock'er de få FS25-/AutoDrive-API'er moden rører og tester valg-logikken.
|
||||
|
||||
local SUGARBEET, WHEAT = 10, 11
|
||||
local logLines = {}
|
||||
|
||||
-- ---- FS25-mocks ----
|
||||
MathUtil = {vector2Length = function(x, z) return math.sqrt(x * x + z * z) end}
|
||||
Logging = {
|
||||
info = function(fmt, ...) table.insert(logLines, string.format(fmt, ...)) end,
|
||||
warning = function(fmt, ...) table.insert(logLines, "WARN " .. string.format(fmt, ...)) end,
|
||||
}
|
||||
local nodePositions = {}
|
||||
function entityExists(node) return nodePositions[node] ~= nil end
|
||||
function getWorldTranslation(node) local p = nodePositions[node]; return p.x, 0, p.z end
|
||||
local listener
|
||||
function addModEventListener(l) listener = l end
|
||||
|
||||
local function makeStation(node, x, z, levels, isBroken, ownLevels)
|
||||
nodePositions[node] = {x = x, z = z}
|
||||
local placeable = ownLevels ~= nil and {spec_silo = {storages = {
|
||||
{getFillLevel = function(_, fillType) return ownLevels[fillType] or 0 end},
|
||||
}}} or nil
|
||||
return {
|
||||
owningPlaceable = placeable,
|
||||
loadTriggers = {{triggerNode = node}},
|
||||
getFillLevel = function(_, fillType)
|
||||
if isBroken then error("boom") end
|
||||
return levels[fillType] or 0
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
local stations = {}
|
||||
g_currentMission = {
|
||||
storageSystem = {getLoadingStations = function() return stations end},
|
||||
accessHandler = {canFarmAccess = function() return true end},
|
||||
}
|
||||
|
||||
-- ---- AutoDrive-mocks ----
|
||||
local markers, wayPoints = {}, {}
|
||||
local function addMarker(index, name, group, x, z)
|
||||
wayPoints[index] = {x = x, z = z}
|
||||
table.insert(markers, {id = index, markerIndex = index, name = name, group = group})
|
||||
end
|
||||
|
||||
local function resetWorld()
|
||||
stations, markers, wayPoints, nodePositions, logLines = {}, {}, {}, {}, {}
|
||||
FS25_AutoDrive.ADMultipleTargetsManager.pickups = {}
|
||||
end
|
||||
|
||||
FS25_AutoDrive = {
|
||||
ADMultipleTargetsManager = {pickups = {}, getNextPickup = function() return "ORIGINAL" end},
|
||||
ADGraphManager = {
|
||||
getMapMarkersInGroup = function(_, group)
|
||||
local result = {}
|
||||
for _, m in ipairs(markers) do if m.group == group then table.insert(result, m) end end
|
||||
return result
|
||||
end,
|
||||
getWayPointById = function(_, id) return wayPoints[id] end,
|
||||
},
|
||||
}
|
||||
|
||||
local function makeDriver(firstMarker, fillTypes)
|
||||
return {
|
||||
getName = function() return "Testtraktor" end,
|
||||
getOwnerFarmId = function() return 1 end,
|
||||
ad = {stateModule = {
|
||||
getFirstMarker = function() return firstMarker end,
|
||||
getSelectedFillTypes = function() return fillTypes end,
|
||||
getFillType = function() return fillTypes[1] end,
|
||||
}},
|
||||
}
|
||||
end
|
||||
|
||||
dofile("FS25_ADSmartPickup/adSmartPickup.lua")
|
||||
listener:update(16) -- installerer hook'en
|
||||
local manager = FS25_AutoDrive.ADMultipleTargetsManager
|
||||
|
||||
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
|
||||
|
||||
-- 1: vælger mindst fyldte silo med varen; springer tomme og forkert vare over
|
||||
resetWorld()
|
||||
addMarker(1, "Silo 1", "Siloer", 0, 0); table.insert(stations, makeStation(101, 0, 15, {[WHEAT] = 900000}))
|
||||
addMarker(2, "Silo 2", "Siloer", 500, 0); table.insert(stations, makeStation(102, 500, 15, {[SUGARBEET] = 800000}))
|
||||
addMarker(3, "Silo 3", "Siloer", 1000, 0); table.insert(stations, makeStation(103, 1000, 15, {[SUGARBEET] = 12000}))
|
||||
addMarker(4, "Silo 4", "Siloer", 1500, 0); table.insert(stations, makeStation(104, 1500, 15, {[SUGARBEET] = 0}))
|
||||
addMarker(5, "Fabrik", "Andet", 1000, 5); -- anden mappe, skal ignoreres
|
||||
check("mindst fyldte med varen vælges", manager:getNextPickup(makeDriver(markers[1], {SUGARBEET}), false), 3)
|
||||
check("AD-rotationstilstand opdateret", manager.pickups["Siloer"].lastTarget, 3)
|
||||
|
||||
-- 2: ingen silo har varen -> AutoDrives originale rotation
|
||||
check("fallback når varen ikke findes", manager:getNextPickup(makeDriver(markers[1], {99}), false), "ORIGINAL")
|
||||
|
||||
-- 3: markør uden silo i nærheden ignoreres
|
||||
resetWorld()
|
||||
addMarker(1, "Langt væk", "Siloer", 0, 0); table.insert(stations, makeStation(101, 0, 200, {[SUGARBEET] = 5}))
|
||||
addMarker(2, "Silo 2", "Siloer", 500, 0); table.insert(stations, makeStation(102, 500, 15, {[SUGARBEET] = 700}))
|
||||
check("markør uden nær silo ignoreres", manager:getNextPickup(makeDriver(markers[1], {SUGARBEET}), false), 2)
|
||||
|
||||
-- 4: flere valgte varer lægges sammen
|
||||
resetWorld()
|
||||
addMarker(1, "Silo 1", "Siloer", 0, 0); table.insert(stations, makeStation(101, 0, 15, {[SUGARBEET] = 100, [WHEAT] = 5000}))
|
||||
addMarker(2, "Silo 2", "Siloer", 500, 0); table.insert(stations, makeStation(102, 500, 15, {[SUGARBEET] = 3000}))
|
||||
check("flere varetyper summeres", manager:getNextPickup(makeDriver(markers[1], {SUGARBEET, WHEAT}), false), 2)
|
||||
|
||||
-- 4b: klynge med delt lager — eget indhold slår nabo-sum, også når nabo-summen er mindre
|
||||
resetWorld()
|
||||
addMarker(1, "Nabo", "Siloer", 0, 0); table.insert(stations, makeStation(101, 0, 15, {[SUGARBEET] = 800}, false, {}))
|
||||
addMarker(2, "Ejer stor", "Siloer", 14, 0); table.insert(stations, makeStation(102, 14, 15, {[SUGARBEET] = 900000}, false, {[SUGARBEET] = 500000}))
|
||||
addMarker(3, "Ejer lille", "Siloer", 28, 0);table.insert(stations, makeStation(103, 28, 15, {[SUGARBEET] = 900000}, false, {[SUGARBEET] = 20000}))
|
||||
check("eget lager foran nabo-lån, mindst først", manager:getNextPickup(makeDriver(markers[1], {SUGARBEET}), false), 3)
|
||||
|
||||
-- 4c: kun nabo-lån muligt -> bruges stadig
|
||||
resetWorld()
|
||||
addMarker(1, "Nabo", "Siloer", 0, 0); table.insert(stations, makeStation(101, 0, 15, {[SUGARBEET] = 800}, false, {}))
|
||||
check("nabo-lån bruges når ingen ejer varen", manager:getNextPickup(makeDriver(markers[1], {SUGARBEET}), false), 1)
|
||||
|
||||
-- 5: fejl i spil-API -> fallback + advarsel, aldrig crash
|
||||
resetWorld()
|
||||
addMarker(1, "Silo 1", "Siloer", 0, 0); table.insert(stations, makeStation(101, 0, 15, {}, true))
|
||||
check("fejl giver fallback", manager:getNextPickup(makeDriver(markers[1], {SUGARBEET}), false), "ORIGINAL")
|
||||
check("fejl logges som advarsel", logLines[#logLines]:sub(1, 4), "WARN")
|
||||
|
||||
-- 6: gruppen "All" og manglende første markør røres ikke
|
||||
check("gruppe All -> fallback", manager:getNextPickup(makeDriver({group = "All", markerIndex = 1}, {SUGARBEET}), false), "ORIGINAL")
|
||||
check("ingen første markør -> fallback", manager:getNextPickup(makeDriver(nil, {SUGARBEET}), false), "ORIGINAL")
|
||||
|
||||
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