14 KiB
Guider til opsætning (marker + flows) — implementeringsplan
For agentic workers: REQUIRED SUB-SKILL: superpowers:executing-plans (native; brugeren har givet fuld autonomi). Trin bruger
- [ ].
Goal: Fields- og Flows-fanen får en oversigt med resumé (klik = ret ét trin) og en trin-for-trin-guide ("Opsæt mark" / "Opsæt flow") på én fælles guide-ramme.
Architecture: En ren guide-motor (adGuide.lua) styrer trin, synlighed, tælling, næste/tilbage/spring. Oven på den to rene trin-definitioner (adFieldGuide.lua, adFlowGuide.lua) der ud fra en kladde + et context (det spil-afhængige, hentet af GUI'et) giver rækker (som data), valg, standarder, resumé og gem-resultat. GUI-laget (gui/SmartPickupGuide.lua fælles trin-skærm, gui/SmartPickupFieldGuide.lua, gui/SmartPickupFlowGuide.lua) er tyndt: bygger context, tegner rækkerne, router klik og gemmer via de eksisterende ADFieldJobs/ADRunsController-funktioner.
Tech Stack: Lua 5.1 (FS25), luajit til tests, FS25 GUI (klonede prefabs).
Spec: docs/superpowers/specs/2026-09-26-guider-design.md
Global Constraints
- Lua 5.1: ingen goto, ingen coroutines, ingen
#på tabeller med huller; pcall om spil-API. - Gemt format (
ADSmartPickup_fields.xml,ADSmartPickup_runs.xml) ændres ikke. Guiderne skriver kun viaADFieldJobs.setTarget/setPlanogADRunsController.createRun/updateRun/assignVehicle/unassignVehicle. - Intet gemmes før [Gem]/[Kør automatisk]/[Start flow]. [Annullér], fanebyt og lukket menu kasserer kladden.
- Rene moduler returnerer nye tabeller (kladden kopieres ved hvert valg).
- Filer under ~800 linjer;
SmartPickupFrame.lua(971) får kun små routing-ændringer. - Nye .lua i modDesc (rene moduler) eller
source()i adSmartPickup.lua (GUI-filer), i rigtig rækkefølge. - Al ny tekst i både
l10n_da.xmlogl10n_en.xml. - Guide-rækker laves KUN med
ingredientPrefab(Ja/Nej, flueben) ogproductPrefab(valg) medkind = "guideRow", routet ionClickIngredient/onClickProduct; klikbare tekstlinjer viamakeRowClickable+ pendingClick. Ingen guide-rækker påvehiclePrefab(v1.30.4-fælden). - Bundknapper: kun MENU_ACTIVATE, MENU_EXTRA_1, MENU_EXTRA_2, MENU_CANCEL (+ MENU_BACK) — andre findes ikke sikkert i FS25.
- Tests:
for t in tests/test_*.lua; do luajit $t | tail -1; done— alle grønne.
Review Focus
- Klik på guide-rækker gemmes aldrig (forkert routing) → alle nye kinds routes via
guideRow; testplan-punkt in-game. - Kladde muteres ved valg (Annullér gemmer alligevel) → test:
chooseændrer ikke den gamle guide/kladde. - Trin forsvinder/dukker op efter et valg (fx mål-afgrøde græs på kornmark) → tælling og næste følger de synlige trin; test.
- [Ret] fra oversigten må kun gemme det ene trin og bevare Auto/Manuel → test
result(guide, nil)bevarer mode. - Faste maskiner: maskine fast på anden mark flyttes kun hvis brugeren vælger den (skjult i listen) → test
applyRigs.
Beslutninger (uklarheder i spec'en)
- [Opsæt mark] uden valgt mark vises også (åbner trin 1 "Mark"); ellers kunne trin 1 aldrig nås.
- "Så igen bagefter" (plan.sow uden mål-afgrøde) står i trin 2 under "Behold det der gror" for høst-/bare marker — ellers forsvinder muligheden.
- Kalk: i Klargøring ("Vælg selv"); når Klargøring ikke vises (ren græsmark) står Kalk i Pleje.
- Klargøring "Automatisk" = jord auto, kalk ja, mulch nej, tromle nej (anvendes kun når trinnet er synligt).
- Maskiner-trinnet: antal ad gangen + aflæsningsvogne først, så "Faste maskiner?" + listen (listen kan være lang). Aflæsningsvogne 1–3 (modellens
MAX_UNLOADERS), ikke 1–5. - Mark uden markør: gemmes med den valgte tilstand; job-løkken venter allerede på markøren (dagens regel). Oversigten viser "sæt markøren".
- Mål-afgrøde tvinger Auto (som i dag); på Oversigt-trinnet vises da kun [Kør automatisk].
- [Ret] fra trin 8 vender tilbage til Oversigt-trinnet (kladden bevares); [Tilbage] i et [Ret]-trin fortryder det ene trins ændringer.
- Flows: bundlinjen har plads til 4 knapper → [Start/Stop] [Opsæt flow] [Nyt flow] [Slet]; Omdøb ligger på resuméets Navn-linje; Start alle/Stop alle bliver på fanen Oversigt.
- Halm:
context.straw= afgrøder med halm (FS25fruitType.hasWindrow/windrowName); kan det ikke aflæses (tom), vises halm-valget for alle høstafgrøder som i dag.
Etape A — fælles ramme + Marker (v1.31.0.0)
Task A1: Guide-motoren adGuide.lua
Files: Create FS25_ADSmartPickup/adGuide.lua, tests/test_adGuide.lua; Modify modDesc.xml (før adFieldModel.lua).
Interfaces (Produces):
ADGuide.new(def, draft, context, options) -> guide
-- def = {order = {stepId...}, isVisible = function(stepId, guide) -> bool}
-- options = {step = id|nil, single = bool, returnTo = "close"|"summary"}
-- guide = {def, draft, context, step, single, returnTo, snapshot}
ADGuide.visibleSteps(guide) -> {stepId...}
ADGuide.position(guide) -> index|nil, total
ADGuide.isLast(guide) -> bool
ADGuide.next(guide) -> guide, event -- event nil | "done"
ADGuide.back(guide) -> guide, event -- event nil | "cancel"
ADGuide.jump(guide, stepId, returnTo) -> guide (single, snapshot = kopi af kladden)
ADGuide.withDraft(guide, draft) / ADGuide.withContext(guide, context) -> guide
ADGuide.deepCopy(value) ; ADGuide.toggleItem(list, item, on) -> ny liste
ADGuide.labelText(label, getText) -> string -- label = {key, args} | {text}
ADGuide.lineText(line, getText) -> "Titel: del, del" -- line = {step, title = label, parts = {label...}}
- Test (RED): næste/tilbage springer skjulte trin over; tælling "3 af 5" over synlige;
nextpå sidste = "done";backpå første = "cancel";jump(..., "summary")+nextlander påsummarymed single=false;jump(..., "close")+next= "done";backi spring gendanner snapshot;withDraftreturnerer ny guide (gammel urørt); trin der bliver usynligt efter et valg:nextgår til næste synlige iorder;toggleItemuden dubletter;labelTextmed args og manglende args (pcall). - Kør
luajit tests/test_adGuide.lua→ FAIL (fil mangler). - Implementér; kør → ALLE TESTS OK.
Task A2: Markguidens trin adFieldGuide.lua
Files: Create FS25_ADSmartPickup/adFieldGuide.lua, tests/test_adFieldGuide.lua; Modify modDesc.xml (efter adFieldView.lua).
Interfaces:
- Consumes:
ADGuide.*,ADFieldModel.product/MAX_RIGS/MAX_UNLOADERS,ADFieldFleet.visibleForField,ADFlowView.naturalLess. - Produces:
ADFieldGuide.ORDER = {"field","crop","cropChoice","prep","care","machines","store","summary"}
ADFieldGuide.open(field, context, options) -> guide -- context.info påkrævet
ADFieldGuide.openPicker(context) -> guide -- trin "field"
ADFieldGuide.pickField(guide, field, context) -> guide -- videre til trinnet efter "field"
ADFieldGuide.isVisible(stepId, guide) -> bool
ADFieldGuide.rows(guide) -> {row...}
-- row = {type="choice", id, title, options={{label, value}}, value}
-- | {type="toggle", id, title, off, on, value}
-- | {type="check", id, item, title, value}
-- | {type="text", label} | {type="link", id, value, label}
ADFieldGuide.choose(guide, id, value) -> guide
ADFieldGuide.summary(guide) -> {line...}
ADFieldGuide.result(guide, start) -> {fieldId, targetFruit, targetChanged, plan, rigIds}
ADFieldGuide.applyRigs(rigIdsByField, fieldId, rigIds) -> ny {[fieldId] = ids}
ADFieldGuide.stepKey(stepId) / hintKey(stepId) -> l10n-nøgler
-
context:
{info, sowable={{name,title}}, mowable={[name]=true}, straw={[name]=true}|nil, rigs={{id,text,role}}, rigIdsByField, fieldSilos={{id,text}}, stores={{id,text}}|nil, storeHidden, fields={{id,text}}}. -
kladde:
{fieldId, plan (kopi), originalTarget, prepAuto, useDedicated, storeMode ("auto"|"manual"|"fieldSilo"), storeIds, pickField}. -
Test (RED): synlige trin for (a) græs uden mål: crop, cropChoice, care, machines, store, summary (ingen prep); (b) høst m. halm: + prep, cropChoice (halm); (c) høst uden halm (
strawsat, afgrøden ikke med): ingen cropChoice; (d) bar mark uden mål: crop, prep, machines, summary (ingen care/store); (e) kornmark med mål græs: cropChoice (ensilage/hø) + prep; picker: kun "field". Standarder: ny mark → prepAuto, useDedicated=false, storeMode auto; plan med soil=plow → prepAuto=false; plan med rigIds → useDedicated; storeIds lig marksilo → fieldSilo.chooseændrer ikke gammel guide;rigIds-check toggler;result: prepAuto overskriver soil/mulch/lime/roll kun når prep er synlig; mode auto/manual efter start, uændret ved start=nil, auto ved mål; storeBuildingIds pr. storeMode; rigIds tom når useDedicated=false; targetChanged.applyRigsfjerner maskinen fra anden mark. Rækker: maskiner-trinnet skjuler maskiner faste på andre marker + tekst med antal; marksilo-spørgsmål kun når fieldSilos findes; "Vælg selv" viser siloerne. Resumé: linjer kun for synlige trin, med rigtige nøgler (fxspu_guide_sum_dedicatedargs {3}). -
Kør → FAIL; implementér; kør → OK. Hele suiten grøn.
Task A3: Fælles trin-skærm gui/SmartPickupGuide.lua
Files: Create gui/SmartPickupGuide.lua; Modify adSmartPickup.lua (source efter SmartPickupFlowTab.lua), gui/SmartPickupFrame.lua (initGuideButtons i new, routing guideRow i onClickIngredient, refreshButtons → getGuideButtons, switchTab/onFrameClose lukker guiden, rebuild for faner med åben guide), gui/SmartPickupOutboundTab.lua (onClickProduct → guideRow).
Interfaces (Produces):
SmartPickupFrame.GUIDE_HOOKS[kind] = {model, tab, context(frame, adEnv, guide) -> context, save(frame, guide, start), choose(frame, id, value) -> handled}
SmartPickupFrame:initGuideButtons(i18n)
SmartPickupFrame:openGuide(kind, guide) SmartPickupFrame:closeGuide()
SmartPickupFrame:fillGuideRows(adEnv) -- overskrift "Trin 3 af 7 — …", forklaring, rækker
SmartPickupFrame:guideText(label) -> string
SmartPickupFrame:addLinkRow(text, action)
SmartPickupFrame:onClickGuideRow(state, data)
SmartPickupFrame:getGuideButtons() -> knapliste
SmartPickupFrame:onClickGuideNext/Back/Cancel/SaveOnly()
- Skriv filen;
luajit -blsyntakstjek.
Task A4: Marker-fanen: oversigt, markflåde, guide
Files: Create gui/SmartPickupFieldGuide.lua (context, gem, knapper for fanen); Modify gui/SmartPickupFieldTab.lua (fillFieldRows → oversigt/markflåde/guide; fjern den lange detaljeliste), l10n da/en.
- Oversigt: hint, tabel, for valgt mark: overskrift, resumé-linjer (klik =
ADGuide.jump(step, "close")), fuld status, markør-linje, marksilo-advarsel. Knapper: [Opsæt mark] (EXTRA_1), [Start nu/Stop] (ACTIVATE), [Markflåde] (EXTRA_2). - Markflåde:
fillFleetRows(adEnv, nil)(alle maskiner). Knap [Til marker] (EXTRA_2). - Gem:
setTargethvis ændret →setPlan(plan)→applyRigs→setPlan(fid, {rigIds})for ændrede marker. - Skriv, syntakstjek, suiten grøn.
Task A5: Docs + ship v1.31.0.0
- TESTPLAN-markarbejde.md: afsnit "Guider (v1.31)"; BRUGERMANUAL/USER_MANUAL: Marker-afsnit kort.
- Ship-procedure (version 1.30.4.0 → 1.31.0.0), commit
feat(gui): guide "Opsæt mark" …, push gitea.
Etape B — Flows på samme ramme (v1.32.0.0)
Task B1: Flowguidens trin adFlowGuide.lua
Files: Create FS25_ADSmartPickup/adFlowGuide.lua, tests/test_adFlowGuide.lua; modDesc (efter adFlowView.lua).
Interfaces (Produces):
ADFlowGuide.ORDER = {"name","direction","buildings","goods","store","rules","wait","tractors","summary"}
ADFlowGuide.open(run, context, options) -> guide -- run = eksisterende run
ADFlowGuide.openNew(name, context) -> guide -- nyt flow (trin "name" synligt)
ADFlowGuide.isVisible(stepId, guide); ADFlowGuide.rows(guide); ADFlowGuide.choose(guide, id, value)
ADFlowGuide.summary(guide) -> {line...}
ADFlowGuide.result(guide) -> {isNew, runId, name, kind, changes, vehicleIds}
ADFlowGuide.vehicleChanges(oldIds, newIds) -> added, removed
ADFlowGuide.previewRun(draft) -> run-formet tabel til controllerens opslag
- context:
{buildings={{id,name,label,hasMarker,text}}, fillTypes={{name,title}}, products={{name,title}}, storeBuildings={{id,text}}, waitPools={{group,count}}, vehicles={{id,text,otherRunId,otherRunName,blocked}}, sellAtSteps, storeAboveSteps, returnBelowSteps, maxLoops}. - kladde: kopi af run-felterne +
isNew,showAllBuildings,storeAuto. - Test (RED): name-trin kun ved nyt flow; store-trin kun ved udkørsel med en vare på Lager/Salg-ellers-lager; retning skifter bygnings-rolle; varer: forsyning auto/vælg (ingredients toggles), udkørsel politik pr. vare (products); regler pr. retning; traktorer i andre flows/blokerede skjult + tekst; resumé pr. retning; result.changes; vehicleChanges; choose immutabelt.
- FAIL → implementér → OK.
Task B2: Flows-fanen i GUI'et
Files: Create gui/SmartPickupFlowGuide.lua; Modify gui/SmartPickupFrame.lua (rebuild for Flows-fanen: tavle + resumé, statiske rækker skjult; refreshLive/refreshButtons), l10n.
- Oversigt: tavlen (
fillOverviewRows), valgt flow: resumé (klik = ret ét trin; Navn-linjen = omdøb-dialog), status-linje (live). Knapper: [Start/Stop] (ACTIVATE), [Opsæt flow] (EXTRA_1), [Nyt flow] (EXTRA_2), [Slet] (CANCEL). - Gem: nyt →
createRun;updateRun(changes); traktorer viavehicleChanges+assignVehicle/unassignVehicle;resolveMarkers;save(); [Start flow] →startRun. - Skriv, syntakstjek, suiten grøn.
Task B3: Docs + ship v1.32.0.0; selv-review
- TESTPLAN + manualer (Flows-afsnit), ship 1.31.0.0 → 1.32.0.0.
- Code-review-agent på hele diffen; ret CRITICAL/HIGH; evt. v1.32.1.0.