diff --git a/FS25_ADSmartPickup/adFieldFleet.lua b/FS25_ADSmartPickup/adFieldFleet.lua new file mode 100644 index 0000000..deb7e05 --- /dev/null +++ b/FS25_ADSmartPickup/adFieldFleet.lua @@ -0,0 +1,53 @@ +-- AD Field Fleet +-- Markflåden som ren logik: hvilken rolle et sæt har ud fra redskabernes specs, og hvilket ledigt sæt +-- der sendes til en mark. Kun sæt med flueben bruges; et sæt spilleren sidder i, røres aldrig. + +ADFieldFleet = {} + +-- Rækkefølge = prioritet når et køretøj har flere (læssevogn med egen pickup m.m.) +ADFieldFleet.ROLE_SPECS = { + {role = "collector", spec = "spec_forageWagon"}, + {role = "rake", spec = "spec_windrower"}, + {role = "tedder", spec = "spec_tedder"}, + {role = "mower", spec = "spec_mower"}, +} + +function ADFieldFleet.roleFromSpecs(specs) + for _, entry in ipairs(ADFieldFleet.ROLE_SPECS) do + if specs[entry.spec] then return entry.role end + end + return nil +end + +-- Nærmeste brugbare sæt til rollen. Grund når intet passer: noRig (ingen med flueben og rollen), +-- allBusy (alle optaget/i brug af spilleren), tooWide/tooNarrow (bredden, med tal fra den første). +function ADFieldFleet.pick(candidates, role, x, z, mowWidth) + local best, bestDistance = nil, math.huge + local sawRole, widthReason, widthArgs = false, nil, nil + for _, candidate in ipairs(candidates) do + if candidate.role == role and candidate.enabled then + sawRole = true + if not candidate.busy and not candidate.controlled then + local ok, reason, args = ADFieldModel.checkWidth(role, candidate.width or 0, mowWidth) + if ok then + local dx, dz = candidate.x - x, candidate.z - z + local distance = dx * dx + dz * dz + if distance < bestDistance then best, bestDistance = candidate, distance end + elseif widthReason == nil then + widthReason, widthArgs = reason, args + end + end + end + end + if best ~= nil then return best end + if not sawRole then return nil, "noRig" end + if widthReason ~= nil then return nil, widthReason, widthArgs end + return nil, "allBusy" +end + +function ADFieldFleet.toggle(enabledIds, id) + local copy = {} + for key, value in pairs(enabledIds or {}) do copy[key] = value end + copy[id] = (not copy[id]) or nil + return copy +end diff --git a/tests/test_adFieldFleet.lua b/tests/test_adFieldFleet.lua new file mode 100644 index 0000000..4c9093b --- /dev/null +++ b/tests/test_adFieldFleet.lua @@ -0,0 +1,53 @@ +-- Kør: luajit tests/test_adFieldFleet.lua (fra repo-roden) +dofile("FS25_ADSmartPickup/adFieldModel.lua") +dofile("FS25_ADSmartPickup/adFieldFleet.lua") +local F = ADFieldFleet +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 + +-- FL1: rolle ud fra redskabets spec (læssevogn vinder over andet på samme køretøj) +check("FL1 slåmaskine", F.roleFromSpecs({spec_mower = true}), "mower") +check("FL1 vender", F.roleFromSpecs({spec_tedder = true}), "tedder") +check("FL1 river", F.roleFromSpecs({spec_windrower = true}), "rake") +check("FL1 læssevogn", F.roleFromSpecs({spec_forageWagon = true, spec_mower = true}), "collector") +check("FL1 intet", F.roleFromSpecs({spec_plow = true}), nil) + +local function rig(id, role, x, extra) + local r = {id = id, role = role, enabled = true, busy = false, controlled = false, width = 40.8, x = x, z = 0, label = id} + for k, v in pairs(extra or {}) do r[k] = v end + return r +end + +-- FL2: nærmeste ledige med flueben og rigtig rolle +local picked = F.pick({rig("far", "mower", 500), rig("near", "mower", 50), rig("wagon", "collector", 10)}, "mower", 0, 0, nil) +check("FL2 nærmeste slåmaskine", picked.id, "near") + +-- FL3: uden flueben / optaget / spiller i sædet springes over +local _, why = F.pick({rig("a", "mower", 1, {enabled = false})}, "mower", 0, 0) +check("FL3 intet med flueben", why, "noRig") +local _, whyBusy = F.pick({rig("a", "mower", 1, {busy = true}), rig("b", "mower", 2, {controlled = true})}, "mower", 0, 0) +check("FL3 alle optaget", whyBusy, "allBusy") +check("FL3 ingen med rollen", select(2, F.pick({rig("a", "tedder", 1)}, "mower", 0, 0)), "noRig") + +-- FL4: læssevogn smallere end slåbredden springes over, bredere vælges +local wide = F.pick({rig("smal", "collector", 1, {width = 20}), rig("bred", "collector", 900, {width = 40.8})}, "collector", 0, 0, 40.8) +check("FL4 bred valgt selv om længere væk", wide.id, "bred") +-- FL5: kun for smalle -> grund tooNarrow med tal +local none, whyNarrow, args = F.pick({rig("smal", "collector", 1, {width = 20})}, "collector", 0, 0, 40.8) +check("FL5 ingen", none, nil); check("FL5 grund", whyNarrow, "tooNarrow"); check("FL5 bredde", args[1], 20) +-- FL6: over 50 m -> tooWide +check("FL6 for bred", select(2, F.pick({rig("x", "mower", 1, {width = 60})}, "mower", 0, 0)), "tooWide") + +-- FL7: toggle giver ny tabel +local enabled = {a = true} +local toggled = F.toggle(enabled, "b") +check("FL7 b til", toggled.b, true); check("FL7 original urørt", enabled.b, nil) +check("FL7 a fra", F.toggle(toggled, "a").a, nil) + +print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL")) +os.exit(failures == 0 and 0 or 1)