From e9272b8b8f6d42ebb3cf7a54320592333ffcd901 Mon Sep 17 00:00:00 2001 From: masterdraco Date: Sun, 27 Sep 2026 10:40:24 +0200 Subject: [PATCH] =?UTF-8?q?feat(marksilo):=20ops=C3=A6tningsmodel=20(til/f?= =?UTF-8?q?ra,=20g=C3=A5rdlagre,=20x=201-10,=20t=C3=A6rskel)=20+=20records?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FS25_ADSmartPickup/adFieldSiloConfig.lua | 76 ++++++++++++++++++++++++ tests/test_adFieldSiloConfig.lua | 33 ++++++++++ 2 files changed, 109 insertions(+) create mode 100644 FS25_ADSmartPickup/adFieldSiloConfig.lua create mode 100644 tests/test_adFieldSiloConfig.lua diff --git a/FS25_ADSmartPickup/adFieldSiloConfig.lua b/FS25_ADSmartPickup/adFieldSiloConfig.lua new file mode 100644 index 0000000..158dcf7 --- /dev/null +++ b/FS25_ADSmartPickup/adFieldSiloConfig.lua @@ -0,0 +1,76 @@ +-- AD Field Silo Config +-- Marksilo-flowets opsætning som ren model (ny tabel ud, input muteres ikke) + flade records til XML-laget. + +ADFieldSiloConfig = {} + +ADFieldSiloConfig.MAX_VEHICLES = 10 +ADFieldSiloConfig.DEFAULT_MAX_VEHICLES = 2 +ADFieldSiloConfig.MIN_LITERS_CHOICES = {5000, 10000, 25000, 50000} +ADFieldSiloConfig.DEFAULT_MIN_LITERS = 10000 + +local function copy(cfg) + local ids = {} + for index, id in ipairs(cfg.storeIds or {}) do ids[index] = id end + return {enabled = cfg.enabled == true, storeIds = ids, maxVehicles = cfg.maxVehicles, minLiters = cfg.minLiters} +end + +local function clampVehicles(value) + value = tonumber(value) or ADFieldSiloConfig.DEFAULT_MAX_VEHICLES + return math.max(1, math.min(ADFieldSiloConfig.MAX_VEHICLES, math.floor(value))) +end + +local function snapLiters(value) + value = tonumber(value) + if value == nil then return ADFieldSiloConfig.DEFAULT_MIN_LITERS end + local best, bestDiff = nil, nil + for _, choice in ipairs(ADFieldSiloConfig.MIN_LITERS_CHOICES) do + local diff = math.abs(choice - value) + if bestDiff == nil or diff < bestDiff then best, bestDiff = choice, diff end + end + return best +end + +function ADFieldSiloConfig.new() + return {enabled = false, storeIds = {}, maxVehicles = ADFieldSiloConfig.DEFAULT_MAX_VEHICLES, minLiters = ADFieldSiloConfig.DEFAULT_MIN_LITERS} +end + +function ADFieldSiloConfig.with(cfg, changes) + local new = copy(cfg) + if changes.enabled ~= nil then new.enabled = changes.enabled == true end + if changes.maxVehicles ~= nil then new.maxVehicles = clampVehicles(changes.maxVehicles) end + if changes.minLiters ~= nil then new.minLiters = snapLiters(changes.minLiters) end + return new +end + +function ADFieldSiloConfig.hasStore(cfg, id) + for _, storeId in ipairs(cfg.storeIds or {}) do + if storeId == id then return true end + end + return false +end + +function ADFieldSiloConfig.toggleStore(cfg, id) + local new = copy(cfg) + local kept, found = {}, false + for _, storeId in ipairs(new.storeIds) do + if storeId == id then found = true else table.insert(kept, storeId) end + end + if not found then table.insert(kept, id) end + new.storeIds = kept + return new +end + +function ADFieldSiloConfig.toRecord(cfg) + return {enabled = cfg.enabled and 1 or 0, stores = table.concat(cfg.storeIds or {}, " "), + maxVehicles = cfg.maxVehicles, minLiters = cfg.minLiters} +end + +function ADFieldSiloConfig.fromRecord(record) + local cfg = ADFieldSiloConfig.new() + if record == nil then return cfg end + for token in string.gmatch(tostring(record.stores or ""), "%S+") do table.insert(cfg.storeIds, token) end + cfg.enabled = tonumber(record.enabled) == 1 + cfg.maxVehicles = clampVehicles(record.maxVehicles) + cfg.minLiters = snapLiters(record.minLiters) + return cfg +end diff --git a/tests/test_adFieldSiloConfig.lua b/tests/test_adFieldSiloConfig.lua new file mode 100644 index 0000000..4958667 --- /dev/null +++ b/tests/test_adFieldSiloConfig.lua @@ -0,0 +1,33 @@ +-- Kør: luajit tests/test_adFieldSiloConfig.lua (fra repo-roden) +dofile("FS25_ADSmartPickup/adFieldSiloConfig.lua") +local C = ADFieldSiloConfig +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 +local cfg = C.new() +check("standard fra", cfg.enabled, false) +check("standard x=2", cfg.maxVehicles, 2) +check("standard tærskel 10000", cfg.minLiters, 10000) +check("x under 1 -> 1", C.with(cfg, {maxVehicles = 0}).maxVehicles, 1) +check("x over 10 -> 10", C.with(cfg, {maxVehicles = 99}).maxVehicles, 10) +check("tærskel snappes til nærmeste valg", C.with(cfg, {minLiters = 12000}).minLiters, 10000) +check("tærskel 40000 -> 50000", C.with(cfg, {minLiters = 40000}).minLiters, 50000) +check("with muterer ikke", cfg.maxVehicles, 2) +local on = C.toggleStore(cfg, "silo1") +check("toggle til", C.hasStore(on, "silo1"), true) +check("toggle muterer ikke", C.hasStore(cfg, "silo1"), false) +check("toggle fra", C.hasStore(C.toggleStore(on, "silo1"), "silo1"), false) +local full = C.with(C.toggleStore(C.toggleStore(cfg, "a"), "b"), {enabled = true, maxVehicles = 4, minLiters = 25000}) +local back = C.fromRecord(C.toRecord(full)) +check("record: enabled", back.enabled, true) +check("record: lagre", table.concat(back.storeIds, " "), "a b") +check("record: x", back.maxVehicles, 4) +check("record: tærskel", back.minLiters, 25000) +check("tom record -> standard", C.fromRecord(nil).maxVehicles, 2) +check("record uden tal -> standard tærskel", C.fromRecord({enabled = 1}).minLiters, 10000) +print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL")) +os.exit(failures == 0 and 0 or 1)