-- Kør: luajit tests/test_adFieldGuide.lua (fra repo-roden) dofile("FS25_ADSmartPickup/adGuide.lua") dofile("FS25_ADSmartPickup/adFieldModel.lua") dofile("FS25_ADSmartPickup/adFieldFleet.lua") dofile("FS25_ADSmartPickup/adFlowView.lua") dofile("FS25_ADSmartPickup/adFieldGuide.lua") local FG, G = ADFieldGuide, ADGuide 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 SOWABLE = {{name = "WHEAT", title = "Hvede"}, {name = "BARLEY", title = "Byg"}, {name = "GRASS", title = "Græs"}, {name = "MAIZE", title = "Majs"}} local RIGS = { {id = "v1", text = "Fendt 1 — slåmaskine", role = "mower"}, {id = "v2", text = "Claas 2 — mejetærsker", role = "harvester"}, {id = "v3", text = "Sprøjte 3 — sprøjte", role = "weeder"}, {id = "v4", text = "Vogn 4 — læssevogn", role = "collector"}, } local function ctx(info, extra) local context = { info = info, sowable = SOWABLE, mowable = {GRASS = true}, straw = {WHEAT = true, BARLEY = true}, rigs = RIGS, rigIdsByField = {[90] = {"v3"}}, fieldSilos = {}, storeHidden = 0, stores = info.kind ~= "bare" and {{id = "s1", text = "Silo A, 300 m"}, {id = "s2", text = "Silo B, 1,2 km"}} or nil, fields = {{id = 1, text = "F1 Græs"}, {id = 2, text = "F2 Hvede"}}, } for key, value in pairs(extra or {}) do context[key] = value end return context end local GRASS = {id = 1, kind = "mowable", fruitName = "GRASS", cropTitle = "Græs", markerId = 5} local WHEAT = {id = 2, kind = "harvest", fruitName = "WHEAT", cropTitle = "Hvede", markerId = 6} local MAIZE = {id = 3, kind = "harvest", fruitName = "MAIZE", cropTitle = "Majs", markerId = 7} local BARE = {id = 4, kind = "bare", markerId = 8} local function steps(guide) return table.concat(G.visibleSteps(guide), ",") end local function field(id, plan) local f = ADFieldModel.newField(id) return ADFieldModel.with(f, {plan = plan or {}}) end local function findRow(rows, id, item) for _, row in ipairs(rows) do if row.id == id and (item == nil or row.item == item) then return row end end return nil end local function countType(rows, rowType) local n = 0 for _, row in ipairs(rows) do if row.type == rowType then n = n + 1 end end return n end -- ---- synlige trin pr. marktype ---- check("FG1 græs", steps(FG.open(field(1), ctx(GRASS))), "crop,cropChoice,care,machines,store,summary") check("FG1 hvede m. halm", steps(FG.open(field(2), ctx(WHEAT))), "crop,cropChoice,prep,care,machines,store,summary") check("FG1 majs uden halm", steps(FG.open(field(3), ctx(MAIZE))), "crop,prep,care,machines,store,summary") check("FG1 bar mark", steps(FG.open(field(4), ctx(BARE))), "crop,prep,machines,summary") check("FG1 halm ukendt -> vis", steps(FG.open(field(3), ctx(MAIZE, {straw = {}}))), "crop,cropChoice,prep,care,machines,store,summary") check("FG1 hvede med mål græs", steps(FG.open(field(2, {targetFruit = "GRASS"}), ctx(WHEAT))), "crop,cropChoice,prep,care,machines,store,summary") check("FG1 bar med mål hvede", steps(FG.open(field(4, {targetFruit = "WHEAT"}), ctx(BARE))), "crop,cropChoice,prep,care,machines,summary") check("FG1 græs med mål græs: ingen klargøring", steps(FG.open(field(1, {targetFruit = "GRASS"}), ctx(GRASS))), "crop,cropChoice,care,machines,store,summary") check("FG1 græs med mål hvede: klargøring", steps(FG.open(field(1, {targetFruit = "WHEAT"}), ctx(GRASS))), "crop,cropChoice,prep,care,machines,store,summary") local picker = FG.openPicker(ctx(GRASS)) check("FG1 vælger: kun mark", steps(picker), "field") check("FG1 vælger: trin", picker.step, "field") check("FG1 vælger: position uden total", (G.position(picker)), 1) -- ---- standarder og udfyldning ---- local g = FG.open(field(2), ctx(WHEAT)) check("FG2 starter på afgrøde", g.step, "crop") check("FG2 klargøring auto", g.draft.prepAuto, true) check("FG2 ingen faste", g.draft.useDedicated, false) check("FG2 lager auto", g.draft.storeMode, "auto") check("FG2 kladde er kopi", g.draft.plan ~= nil and g.draft.fieldId, 2) local plowed = FG.open(field(2, {soil = "plow"}), ctx(WHEAT)) check("FG2 pløj -> vælg selv", plowed.draft.prepAuto, false) local withRigs = FG.open(field(2, {rigIds = {"v2"}}), ctx(WHEAT)) check("FG2 faste maskiner -> ja", withRigs.draft.useDedicated, true) local silo = FG.open(field(1, {storeBuildingIds = {"m1"}}), ctx(GRASS, {fieldSilos = {{id = "m1", text = "Marksilo"}}})) check("FG2 marksilo valgt", silo.draft.storeMode, "fieldSilo") local manual = FG.open(field(1, {storeBuildingIds = {"s2"}}), ctx(GRASS)) check("FG2 valgt silo -> vælg selv", manual.draft.storeMode, "manual") check("FG2 valgt silo i listen", manual.draft.storeIds[1], "s2") -- ---- choose er immutabel ---- local chosen = FG.choose(g, "targetFruit", "BARLEY") check("FG3 ny kladde", chosen.draft.plan.targetFruit, "BARLEY") check("FG3 gammel urørt", g.draft.plan.targetFruit, "") local toggled = FG.choose(withRigs, "rigIds", {item = "v1", on = true}) check("FG3 check tilføjer", table.concat(toggled.draft.plan.rigIds, ","), "v2,v1") check("FG3 gammel liste urørt", table.concat(withRigs.draft.plan.rigIds, ","), "v2") check("FG3 check fjerner", table.concat(FG.choose(toggled, "rigIds", {item = "v2", on = false}).draft.plan.rigIds, ","), "v1") check("FG3 produkt hø", FG.choose(FG.open(field(1), ctx(GRASS)), "product", true).draft.plan.product, "hay") check("FG3 produkt ensilage", FG.choose(FG.open(field(1), ctx(GRASS)), "product", false).draft.plan.product, "silage") -- ---- rækker ---- local cropRows = FG.rows(g) local target = findRow(cropRows, "targetFruit") check("FG4 afgrøde: valg", target.type, "choice") check("FG4 afgrøde: behold først", target.options[1].value, "") check("FG4 afgrøde: såbare", #target.options, 5) check("FG4 så igen for høstmark", findRow(cropRows, "sow") ~= nil, true) check("FG4 så igen skjult med mål", findRow(FG.rows(chosen), "sow"), nil) check("FG4 så igen skjult på græs", findRow(FG.rows(FG.open(field(1), ctx(GRASS))), "sow"), nil) local choiceGrass = FG.rows(G.jump(FG.open(field(1), ctx(GRASS)), "cropChoice", "close")) check("FG5 græs: ensilage/hø", findRow(choiceGrass, "product") ~= nil, true) check("FG5 græs: river", findRow(choiceGrass, "rake") ~= nil, true) check("FG5 græs: ingen halm", findRow(choiceGrass, "straw"), nil) local choiceWheat = FG.rows(G.jump(g, "cropChoice", "close")) check("FG5 hvede: halm", findRow(choiceWheat, "straw").type, "choice") check("FG5 hvede: ingen ensilage", findRow(choiceWheat, "product"), nil) local prepRows = FG.rows(G.jump(g, "prep", "close")) check("FG6 klargøring auto: kun valget + tekst", findRow(prepRows, "soil"), nil) check("FG6 klargøring valg", findRow(prepRows, "prepAuto").type, "choice") local prepManual = FG.rows(G.jump(FG.choose(g, "prepAuto", false), "prep", "close")) check("FG6 vælg selv: jord", findRow(prepManual, "soil") ~= nil, true) check("FG6 vælg selv: kalk", findRow(prepManual, "lime") ~= nil, true) check("FG6 vælg selv: mulch", findRow(prepManual, "mulch") ~= nil, true) check("FG6 vælg selv: ingen tromle uden såning", findRow(prepManual, "roll"), nil) local careGrass = FG.rows(G.jump(FG.open(field(1), ctx(GRASS)), "care", "close")) check("FG7 græs: ingen ukrudt", findRow(careGrass, "weed"), nil) check("FG7 græs: kalk i pleje", findRow(careGrass, "lime") ~= nil, true) local careWheat = FG.rows(G.jump(g, "care", "close")) check("FG7 hvede: ukrudt", findRow(careWheat, "weed") ~= nil, true) check("FG7 hvede: kalk ikke i pleje", findRow(careWheat, "lime"), nil) local machinesOff = FG.rows(G.jump(g, "machines", "close")) check("FG8 antal ad gangen", findRow(machinesOff, "rigs").type, "choice") check("FG8 aflæsningsvogne ved høst", findRow(machinesOff, "unloaders") ~= nil, true) check("FG8 ingen liste uden faste", countType(machinesOff, "check"), 0) check("FG8 ingen aflæsningsvogne på græs", findRow(FG.rows(G.jump(FG.open(field(1), ctx(GRASS)), "machines", "close")), "unloaders"), nil) local machinesOn = FG.rows(G.jump(FG.choose(g, "useDedicated", true), "machines", "close")) check("FG8 liste: v3 fast på F90 skjult", findRow(machinesOn, "rigIds", "v3"), nil) check("FG8 liste: tre synlige", countType(machinesOn, "check"), 3) local hiddenText = nil for _, row in ipairs(machinesOn) do if row.type == "text" and row.label.key == "spu_field_hiddenDedicated" then hiddenText = row end end check("FG8 tekst om skjulte", hiddenText ~= nil and hiddenText.label.args[1], 1) check("FG8 tekst marker", hiddenText ~= nil and hiddenText.label.args[2], "F90") local ownFirst = FG.rows(G.jump(withRigs, "machines", "close")) local firstCheck = nil for _, row in ipairs(ownFirst) do if row.type == "check" and firstCheck == nil then firstCheck = row end end check("FG8 egne først", firstCheck.item, "v2") check("FG8 egne sat", firstCheck.value, true) local storeAuto = FG.rows(G.jump(FG.open(field(1), ctx(GRASS)), "store", "close")) check("FG9 ingen marksilo-spørgsmål uden marksilo", findRow(storeAuto, "useFieldSilo"), nil) check("FG9 automatisk/vælg selv", findRow(storeAuto, "storeAuto").type, "choice") check("FG9 auto: ingen siloliste", countType(storeAuto, "check"), 0) local storeManual = FG.rows(G.jump(FG.choose(FG.open(field(1), ctx(GRASS)), "storeAuto", false), "store", "close")) check("FG9 vælg selv: siloer", countType(storeManual, "check"), 2) local siloCtx = ctx(GRASS, {fieldSilos = {{id = "m1", text = "Marksilo F1"}}}) local storeSilo = FG.rows(G.jump(FG.open(field(1), siloCtx), "store", "close")) check("FG9 marksilo-spørgsmål", findRow(storeSilo, "useFieldSilo").type, "toggle") local useSilo = FG.choose(FG.open(field(1), siloCtx), "useFieldSilo", true) check("FG9 marksilo ja -> skjul auto", findRow(FG.rows(G.jump(useSilo, "store", "close")), "storeAuto"), nil) local pickRows = FG.rows(picker) check("FG10 vælger: links", countType(pickRows, "link"), 2) check("FG10 vælger: id", findRow(pickRows, "field").value, 1) local picked = FG.pickField(picker, field(2), ctx(WHEAT)) check("FG10 valgt mark", picked.draft.fieldId, 2) check("FG10 videre til afgrøde", picked.step, "crop") check("FG10 mark-trin stadig talt", (G.position(picked)), 2) -- ---- resultat ---- local r = FG.result(g, true) check("FG11 auto ved start", r.plan.mode, "auto") check("FG11 manuel uden start", FG.result(g, false).plan.mode, "manual") local autoField = FG.open(field(2, {mode = "auto"}), ctx(WHEAT)) check("FG11 Ret bevarer auto", FG.result(autoField, nil).plan.mode, "auto") check("FG11 Ret bevarer manuel", FG.result(g, nil).plan.mode, "manual") check("FG11 mål tvinger auto", FG.result(chosen, false).plan.mode, "auto") check("FG11 mål ændret", FG.result(chosen, true).targetChanged, true) check("FG11 mål uændret", r.targetChanged, false) check("FG11 ingen rigIds i plan", r.plan.rigIds, nil) local soilPlan = FG.result(FG.open(field(2, {soil = "plow", mulch = true, lime = false, roll = true}), ctx(WHEAT)), true).plan check("FG12 vælg selv bevarer jord", soilPlan.soil, "plow") local autoPrep = FG.result(FG.choose(FG.open(field(2, {soil = "plow", mulch = true, lime = false, roll = true}), ctx(WHEAT)), "prepAuto", true), true).plan check("FG12 auto: jord", autoPrep.soil, "auto") check("FG12 auto: mulch", autoPrep.mulch, false) check("FG12 auto: kalk", autoPrep.lime, true) check("FG12 auto: tromle", autoPrep.roll, false) local grassNoPrep = FG.result(FG.choose(FG.open(field(1, {lime = false}), ctx(GRASS)), "prepAuto", true), true).plan check("FG12 græs: auto rører ikke kalk", grassNoPrep.lime, false) check("FG13 lager auto", #FG.result(FG.open(field(1, {storeBuildingIds = {"s1"}}), ctx(GRASS)) and FG.choose(FG.open(field(1, {storeBuildingIds = {"s1"}}), ctx(GRASS)), "storeAuto", true), true).plan.storeBuildingIds, 0) check("FG13 lager vælg selv", table.concat(FG.result(FG.choose(FG.choose(FG.open(field(1), ctx(GRASS)), "storeAuto", false), "storeBuildingIds", {item = "s2", on = true}), true).plan.storeBuildingIds, ","), "s2") check("FG13 lager marksilo", table.concat(FG.result(useSilo, true).plan.storeBuildingIds, ","), "m1") check("FG13 bar mark bevarer lager", table.concat(FG.result(FG.open(field(4, {storeBuildingIds = {"s9"}}), ctx(BARE)), true).plan.storeBuildingIds, ","), "s9") check("FG14 faste fra -> tom", #FG.result(FG.choose(withRigs, "useDedicated", false), true).rigIds, 0) check("FG14 faste til", table.concat(FG.result(toggled, true).rigIds, ","), "v2,v1") -- ---- faste maskiner på tværs af marker ---- local byField = FG.applyRigs({[90] = {"v3", "v5"}, [2] = {"v2"}}, 2, {"v2", "v3"}) check("FG15 fjernet fra anden mark", table.concat(byField[90], ","), "v5") check("FG15 sat på marken", table.concat(byField[2], ","), "v2,v3") check("FG15 ny mark", table.concat(FG.applyRigs({}, 7, {"v1"})[7], ","), "v1") -- ---- resumé ---- local function lineFor(lines, step) for _, line in ipairs(lines) do if line.step == step then return line end end return nil end local function partKeys(line) local keys = {} for _, part in ipairs(line.parts) do table.insert(keys, part.key or ("=" .. tostring(part.text))) end return table.concat(keys, ",") end local sum = FG.summary(g) check("FG16 linjer for synlige trin", #sum, 6) check("FG16 afgrøde behold", partKeys(lineFor(sum, "crop")), "spu_guide_crop_keep") check("FG16 halm", partKeys(lineFor(sum, "cropChoice")), "spu_guide_sum_straw_chop") check("FG16 klargøring auto", partKeys(lineFor(sum, "prep")), "spu_guide_sum_auto") check("FG16 pleje", partKeys(lineFor(sum, "care")), "spu_guide_sum_fert,spu_guide_sum_weed") check("FG16 maskiner", partKeys(lineFor(sum, "machines")), "spu_guide_sum_freeRigs,spu_guide_sum_rigs,spu_guide_sum_unloaders") check("FG16 lager auto", partKeys(lineFor(sum, "store")), "spu_guide_sum_auto") check("FG16 ingen mark/summary-linje", lineFor(sum, "summary"), nil) local sumTarget = FG.summary(chosen) check("FG17 mål", partKeys(lineFor(sumTarget, "crop")), "spu_guide_sum_target") check("FG17 mål titel", lineFor(sumTarget, "crop").parts[1].args[1], "Byg") local sumRigs = FG.summary(withRigs) check("FG17 faste", lineFor(sumRigs, "machines").parts[1].key, "spu_guide_sum_dedicated") check("FG17 faste antal", lineFor(sumRigs, "machines").parts[1].args[1], 1) local sumManual = FG.summary(FG.open(field(2, {soil = "plow", lime = true, mulch = true}), ctx(WHEAT))) check("FG17 klargøring vælg selv", partKeys(lineFor(sumManual, "prep")), "spu_field_soil_plow,spu_guide_sum_lime,spu_guide_sum_mulch") check("FG17 lager valgt silo", partKeys(lineFor(FG.summary(manual), "store")), "=Silo B, 1,2 km") check("FG17 lager marksilo", partKeys(lineFor(FG.summary(useSilo), "store")), "spu_guide_sum_fieldSilo") local sumHay = FG.summary(FG.choose(FG.choose(FG.open(field(1), ctx(GRASS)), "product", true), "rake", true)) check("FG17 hø + river", partKeys(lineFor(sumHay, "cropChoice")), "spu_field_plan_hay,spu_guide_sum_rake") local sumNoCare = FG.summary(FG.choose(FG.choose(g, "fertilize", false), "weed", false)) check("FG17 ingen pleje", partKeys(lineFor(sumNoCare, "care")), "spu_guide_sum_noCare") local sumSow = FG.summary(FG.choose(g, "sow", true)) check("FG17 så igen", partKeys(lineFor(sumSow, "crop")), "spu_guide_crop_keep,spu_guide_sum_sowAgain") -- ---- oversigts-trinnet: links pr. linje ---- local summaryRows = FG.rows(G.new(g.def, g.draft, g.context, {step = "summary"})) check("FG18 oversigt: link pr. linje", countType(summaryRows, "link"), 6) check("FG18 oversigt: link-id", findRow(summaryRows, "jump").value, "crop") print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL")) os.exit(failures == 0 and 0 or 1)